diff --git a/cdrskin/cdrskin_timestamp.h b/cdrskin/cdrskin_timestamp.h index 3cda464..3e38919 100644 --- a/cdrskin/cdrskin_timestamp.h +++ b/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2013.10.10.161931" +#define Cdrskin_timestamP "2013.10.28.104957" diff --git a/libburn/drive.c b/libburn/drive.c index 8bcaa70..e69270a 100644 --- a/libburn/drive.c +++ b/libburn/drive.c @@ -570,6 +570,7 @@ struct burn_drive *burn_drive_register(struct burn_drive *d) d->toc_entry = NULL; d->disc = NULL; d->erasable = 0; + d->write_opts = NULL; #ifdef Libburn_ticket_62_re_register_is_possiblE /* ts A60904 : ticket 62, contribution by elmom */ @@ -675,6 +676,10 @@ int burn_drive_mark_unready(struct burn_drive *d, int flag) free(d->toc_entry); d->toc_entry = NULL; d->toc_entries = 0; + if (d->write_opts != NULL) { + burn_write_opts_free(d->write_opts); + d->write_opts = NULL; + } if (d->disc != NULL) { burn_disc_free(d->disc); d->disc = NULL; @@ -3402,3 +3407,13 @@ int burn_disc_get_leadin_text(struct burn_drive *d, return ret; } + +/* ts B31023 API */ +/* Inquire for DVD-RW failure of TAO +*/ +int burn_drive_was_feat21_failure(struct burn_drive *d) +{ + return !!d->was_feat21h_failure; +} + + diff --git a/libburn/libburn.h b/libburn/libburn.h index 56787cc..6128e6c 100644 --- a/libburn/libburn.h +++ b/libburn/libburn.h @@ -1814,6 +1814,18 @@ void burn_drive_cancel(struct burn_drive *drive); int burn_drive_wrote_well(struct burn_drive *d); +/* ts B31023 */ +/** Inquire whether a write error occured which is suspected to have happened + due to a false report about DVD-RW capability to be written in write type + BURN_WRITE_TAO. + @param d The drive to inquire. + @return 1= it seems that BURN_WRITE_TAO on DVD-RW caused error, + 0= it does not seem so + @since 1.3.4 +*/ +int burn_drive_was_feat21_failure(struct burn_drive *d); + + /** Convert a minute-second-frame (MSF) value to sector count @param m Minute component @param s Second component @@ -3055,6 +3067,29 @@ void burn_write_opts_set_has_mediacatalog(struct burn_write_opts *opts, */ void burn_write_opts_set_multi(struct burn_write_opts *opts, int multi); + +/* ts B31024 */ +/** Set the severity to be used with write error messages which are potentially + caused by not using write type BURN_WRITE_SAO on fast blanked DVD-RW. + + Normally the call burn_write_opts_auto_write_type() can prevent such + errors by looking for MMC feature 21h "Incremental Streaming Writable" + which anounnces the capability for BURN_WRITE_TAO and multi session. + Regrettable many drives announce feature 21h even if they only can do + BURN_WRITE_SAO. This mistake becomes obvious by an early write error. + + If you plan to call burn_drive_was_feat21_failure() and to repeat the + burn attempt with BURN_WRITE_SAO, then set the severity of the error + message low enough, so that the application does not see reason to abort. + + @param opts The option object to be manipulated + @param severity Severity as with burn_msgs_set_severities(). + "ALL" or empty text means the default severity that + is attributed to other kinds of write errors. +*/ +void burn_write_opts_set_fail21h_sev(struct burn_write_opts *opts, + char *severity); + /* ts B11204 */ /** Submit an array of CD-TEXT packs which shall be written to the Lead-in of a SAO write run on CD. diff --git a/libburn/libburn.ver b/libburn/libburn.ver index e7d2370..465ae59 100644 --- a/libburn/libburn.ver +++ b/libburn/libburn.ver @@ -73,6 +73,7 @@ burn_drive_set_buffer_waiting; burn_drive_set_speed; burn_drive_set_stream_recording; burn_drive_snooze; +burn_drive_was_feat21_failure; burn_drive_wrote_well; burn_fd_source_new; burn_fifo_fill; @@ -175,6 +176,7 @@ burn_write_opts_free; burn_write_opts_get_drive; burn_write_opts_new; burn_write_opts_set_dvd_obs; +burn_write_opts_set_fail21h_sev; burn_write_opts_set_fillup; burn_write_opts_set_force; burn_write_opts_set_format; diff --git a/libburn/mmc.c b/libburn/mmc.c index d64a156..26b8d57 100644 --- a/libburn/mmc.c +++ b/libburn/mmc.c @@ -1007,9 +1007,8 @@ fprintf(stderr, "libburn_DEBUG: buffer sectors= %d bytes= %d\n", /* ts A61112 : react on eventual error condition */ spc_decode_sense(c->sense, 0, &key, &asc, &ascq); if (c->error && key != 0) { - - /* >>> make this scsi_notify_error() when liberated */ int key, asc, ascq; + int err_sev = LIBDAX_MSGS_SEV_FATAL; msg = calloc(1, 256); if (msg != NULL) { @@ -1017,13 +1016,33 @@ fprintf(stderr, "libburn_DEBUG: buffer sectors= %d bytes= %d\n", start, len); scsi_error_msg(d, c->sense, 14, msg + strlen(msg), &key, &asc, &ascq); + } + + /* ts B31023 */ + /* Memorize if on DVD-RW write mode is TAO/Incremental and + error [5 64 00] occurs within the first drive buffer fill. + */ + if (d->current_profile == 0x14 && d->write_opts != NULL && + (d->progress.buffer_capacity == 0 || + start < (int) d->progress.buffer_capacity / 2048) && + key == 5 && asc == 0x64 && ascq == 0) { + if (d->write_opts->write_type == BURN_WRITE_TAO) { + d->was_feat21h_failure = 1 + (start == 0); + if (d->write_opts->feat21h_fail_sev != 0) + err_sev = + d->write_opts->feat21h_fail_sev; + } + } + + if (msg != NULL) { libdax_msgs_submit(libdax_messenger, d->global_index, 0x0002011d, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, + err_sev, LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0); free(msg); } d->cancel = 1; + return BE_CANCELLED; } diff --git a/libburn/options.c b/libburn/options.c index 5964a93..8ca8ce8 100644 --- a/libburn/options.c +++ b/libburn/options.c @@ -78,6 +78,24 @@ void burn_write_opts_free(struct burn_write_opts *opts) free(opts); } +int burn_write_opts_clone(struct burn_write_opts *from, + struct burn_write_opts **to, int flag) +{ + if (*to != NULL) + burn_write_opts_free(*to); + if (from == NULL) + return 1; + *to = calloc(1, sizeof(struct burn_write_opts)); + if (*to == NULL) { + libdax_msgs_submit(libdax_messenger, -1, 0x00000003, + LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, + "Out of virtual memory", 0, 0); + return -1; + } + memcpy(*to, from, sizeof(struct burn_write_opts)); + return 1; +} + struct burn_read_opts *burn_read_opts_new(struct burn_drive *drive) { struct burn_read_opts *opts; @@ -204,6 +222,21 @@ void burn_write_opts_set_multi(struct burn_write_opts *opts, int multi) } +/* ts B31024 */ +/* API */ +void burn_write_opts_set_fail21h_sev(struct burn_write_opts *opts, + char *severity) +{ + int ret, sevno; + + ret = libdax_msgs__text_to_sev(severity, &sevno, 0); + if (ret <= 0) + opts->feat21h_fail_sev = 0; + else + opts->feat21h_fail_sev = sevno; +} + + /* ts B11204 */ /* @param flag bit0=do not verify checksums bit1= repair mismatching checksums diff --git a/libburn/options.h b/libburn/options.h index 53fe49f..1512079 100644 --- a/libburn/options.h +++ b/libburn/options.h @@ -1,6 +1,6 @@ /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens - Copyright (c) 2006 - 2012 Thomas Schmitt + Copyright (c) 2006 - 2013 Thomas Schmitt Provided under GPL version 2 or later. */ @@ -81,9 +81,19 @@ struct burn_write_opts unsigned char mediacatalog[13]; /** Session format */ int format; + /* internal use only */ unsigned char control; + + /* Whether to keep medium appendable */ unsigned char multi; + + /* ts B31024 */ + /* The severity to be attributed to error messages about failed + write attempt with blank DVD-RW, possibly due to falsely reported + feature 21h Incremental Streaming Writable + */ + int feat21h_fail_sev; }; /* Default value for burn_write_opts.stdio_flush_size @@ -139,4 +149,9 @@ struct burn_read_opts }; + +int burn_write_opts_clone(struct burn_write_opts *from, + struct burn_write_opts **to, int flag); + + #endif /* BURN__OPTIONS_H */ diff --git a/libburn/transport.h b/libburn/transport.h index ff635f5..a98f5c0 100644 --- a/libburn/transport.h +++ b/libburn/transport.h @@ -188,6 +188,15 @@ struct burn_drive /* 1 = incremental recording available, 0 = not available */ int current_has_feat21h; + /* Some drives announce feature 21h on fast-blanked DVD-RW + although they cannot write them in Incremental mode. + 0= does not look like the recent write run failed due to + Incremental on fast blanked DVD-RW + 1= it seems to have happened + 2= it seems to have happened with write address 0 + */ + int was_feat21h_failure; + /* Link Size item number 0 from feature 0021h descriptor */ int current_feat21h_link_size; @@ -356,6 +365,13 @@ struct burn_drive volatile int cancel; volatile enum burn_drive_status busy; + /* During write runs, this points to a copy of the applied + struct burn_write_opts. Only read this underneath + burn_disc_write_sync() which removes the copy when done. + Especially do not read it from outside the write thread. + */ + struct burn_write_opts *write_opts; + /* ts A70929 */ pid_t thread_pid; int thread_pid_valid; diff --git a/libburn/write.c b/libburn/write.c index d0b27f4..e8d69c4 100644 --- a/libburn/write.c +++ b/libburn/write.c @@ -1318,7 +1318,7 @@ int burn_disc_init_write_status(struct burn_write_opts *o, { struct burn_drive *d = o->drive; struct burn_track *t = NULL; - int sx, tx; + int sx, tx, ret; d->cancel = 0; @@ -1363,6 +1363,11 @@ int burn_disc_init_write_status(struct burn_write_opts *o, if (o->fill_up_media && t != NULL) burn_track_set_fillup(t, 1); + d->was_feat21h_failure = 0; + ret = burn_write_opts_clone(o, &(d->write_opts), 0); + if (ret <= 0) + return ret; + d->busy = BURN_DRIVE_WRITING; return 1; @@ -2124,13 +2129,16 @@ int burn_dvd_write_session(struct burn_write_opts *o, if (d->current_profile == 0x11 || d->current_profile == 0x14 || d->current_profile == 0x15) { /* DVD-R , DVD-RW Sequential, DVD-R/DL Sequential */ - multi_mem = o->multi; - if (!is_last_session) - o->multi = 1; - ret = burn_disc_close_session_dvd_minus_r(o); - o->multi = multi_mem; - if (ret <= 0) - return 0; + /* If feature 21h failed on write 0: do not close session */ + if (d->was_feat21h_failure != 2) { + multi_mem = o->multi; + if (!is_last_session) + o->multi = 1; + ret = burn_disc_close_session_dvd_minus_r(o); + o->multi = multi_mem; + if (ret <= 0) + return 0; + } } else if (d->current_profile == 0x12 || d->current_profile == 0x43) { /* DVD-RAM , BD-RE */ /* ??? any finalization needed ? */; @@ -3129,6 +3137,10 @@ ex:; burn_os_free_buffer((char *) d->buffer, sizeof(struct buffer), 0); d->buffer = buffer_mem; + if (d->write_opts != NULL) { + burn_write_opts_free(d->write_opts); + d->write_opts = NULL; + } return; }