From 3b5c80e8671307f1ca2716a06f1e4a03903b88c2 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Thu, 1 Mar 2007 12:07:29 +0000 Subject: [PATCH] Preparations for supporting DVD+R[/DL] --- cdrskin/cdrskin.c | 6 +- cdrskin/cdrskin_timestamp.h | 2 +- doc/cookbook.txt | 108 +++++++++++++- libburn/drive.c | 3 +- libburn/mmc.c | 72 ++++------ libburn/write.c | 277 +++++++++++++++++++++++++++--------- 6 files changed, 348 insertions(+), 120 deletions(-) diff --git a/cdrskin/cdrskin.c b/cdrskin/cdrskin.c index 739be62..8336c35 100644 --- a/cdrskin/cdrskin.c +++ b/cdrskin/cdrskin.c @@ -4524,9 +4524,11 @@ int Cdrskin_activate_write_mode(struct CdrskiN *skin, enum burn_disc_status s, } else if((profile_number==0x1a || profile_number==0x13 || profile_number==0x12 || profile_number==0x11 || profile_number==0x14 || - profile_number==0x15) + profile_number==0x15 || + profile_number==0x1b || profile_number==0x2b) && might_do_tao) { - /* DVD+RW, DVD-RW Restr. Overwrite, DVD-RAM, DVD-R[W][/DL] Sequential */ + /* DVD+RW, DVD-RW Restricted Overwrite, DVD-RAM, + DVD-R[W][/DL] Sequential Recording, DVD+R[/DL] */ strcpy(skin->preskin->write_mode_name,"TAO"); } else { strcpy(skin->preskin->write_mode_name,"SAO"); diff --git a/cdrskin/cdrskin_timestamp.h b/cdrskin/cdrskin_timestamp.h index 6226065..712c419 100644 --- a/cdrskin/cdrskin_timestamp.h +++ b/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2007.02.25.112733" +#define Cdrskin_timestamP "2007.03.01.120945" diff --git a/doc/cookbook.txt b/doc/cookbook.txt index 64ace8f..807c4a9 100644 --- a/doc/cookbook.txt +++ b/doc/cookbook.txt @@ -5,7 +5,7 @@ Content: - SAO CD Cookbook (CD-R, CD-RW, pure audio or pure data only) - Overwriteable DVD Cookbook (DVD-RAM, DVD+RW, DVD-RW) - Sequential DVD-R[W] Cookbook - +- >>> DVD+R Cookbook (emerging, totally untested yet) ------------------------------------------------------------------------------- TAO Multi-Session CD Cookbook @@ -973,7 +973,7 @@ with DVD-R. A half-sentence in mmc5r03c.pdf 6.3.3.3.3 might indicate that closing a session by 5Bh CLOSE TRACK SESSION Close Function 010b overrides the multi-session bits -in mode page 5. +in mode page 05h. growisofs applies this function in case of not DAO, though. A comment in growisofs_mmc.cpp states: "// DVD-R DL Seq has no notion of multi-session". I am not reading this from the specs - but not explicitely the contrary either. @@ -985,3 +985,107 @@ close session if multi-session is demanded. ------------------------------------------------------------------------------- +------------------------------------------------------------------------------- + + INCOMPLETE, YET TOTALLY UNTESTED + + DVD+R Cookbook +------------------------------------------------------------------------------- +Inspired by reading mmc5r03c.pdf from http://www.t10.org/ftp/t10/drafts/mmc5/ +backed by Andy Polyakov's http://fy.chalmers.se/~appro/linux/DVD+RW/tools , + +For libburnia.pykix.org by Thomas Schmitt + +------------------------------------------------------------------------------- + +Media type can be recognized by Current Profile from 46h GET CONFIGURATION. +(mmc5r03c.pdf 6.6.2.1) +DVD+R 001bh +DVD+R/DL 002bh + +- About empty, appendable and finalized DVD+R +- Writing a Pseudo Session to DVD+R +- >>> Obtaining multi-session info for extending ISO-9660 filesystems +- >>> Obtaining a Table Of Content from CD +- >>> Hearsay about DVD+R/DL (Dual Layer) : + +------------------------------------------------------------------------------- +About blank, appendable and finalized DVD+R : + +In the beginning a DVD+R holds an empty session and the Incomplete Fragment. +From these one may spawn reserved fragments or one may write directly to +the incomplete fragment. As soon as this is done the empty session becomes the +open session which finally needs to get closed. By closing fragments and +session a new empty session with empty Incomplete Fragment gets spawned. +So the disc stays appendable. + +A DVD+R may hold 153 closed sessions with a single track each. +The open session may hold up to 15 open fragments. But on closure of the +session those fragments together form a single logical track. So one will +usually only use a single fragment for sequential writing. +(mmc5r03c.pdf 4.3.6.2) + +The disc may get finalized by another close command so that no more data can +be written. +(mmc5r03c.pdf 6.3.3.4.4) + + +------------------------------------------------------------------------------- +Writing a Pseudo Session to DVD+R : + +Session writing has to be pseudo because only one logical track per session +can be distinguished. So actually there have to be written multiple sessions +to mark multiple tracks. The pseudo session cannot get marked on disc and thus +the tracks of a pseudo session cannot be grouped accordingly in a TOC. + +Speed can be influenced by B6h SET STREAMING , speed capabilities can be +inquired by ACh GET PERFORMANCE. It is advised to set only speeds and sizes +which are returned by ACh. +(mmc5r03c.pdf 6.39 SET STREAMING, 6.8 GET PERFORMANCE) + +No mode page 05h is to be sent. +growisofs sends a page but the specs clearly state that one shall not do. +(mmc5r03c.pdf 7.5.3) + +It is optional wether a track size is reserved in advance or not. Eventually +this is done by 53h RESERVE TRACK, RMZ=ARSV=0. Reservation size should better +already be aligned to 32 KiB. +(mmc5r03c.pdf 6.31) +The specs promise to pad up the track if not enough data get written. +(mmc5r03c.pdf 6.3.3.4.2) + +Next Writeable Address is fetched from the reply of 52h READ TRACK INFORMATION +with track number FFh. +(mmc5r03c.pdf 6.27) +Since the fixely set write type is 16-block packet, full 32 kB buffers have +to be transmitted via 2Ah WRITE. +(mmc5r03c.pdf 4.3.6.2.2) + +When writing is done, it is mandatory to force the drive's buffer to media by +35h SYNCHRONIZE CACHE. +(mmc5r03c.pdf 6.41) + +The written fragment (i.e. track-to-be) has to be closed by 5Bh CLOSE TRACK +SESSION Close Function 001b. +(mmc5r03c.pdf 6.3.3.4.2) +libburn obtains the necessary logical track number from Last Track Number in +Last Session from the reply of 51h READ DISC INFORMATION requesting +Data Type 000b. +(mmc5r03c.pdf 6.22) +After each track 5Bh CLOSE TRACK SESSION Close Function 010b with Logical Track +Number 0 closes the DVD+R session but keeps the media appendable. +(mmc5r03c.pdf 6.3.3.4.3) + + +Eventually 5Bh CLOSE TRACK SESSION Close Function 101b is used to finalize +the media with minimal radius. After that the disc is not appendable any more ! +(mmc5r03c.pdf 6.3.3.4.4) + + +------------------------------------------------------------------------------- +Hearsay about DVD+R/DL (Dual Layer) : + +>>> + +------------------------------------------------------------------------------- + diff --git a/libburn/drive.c b/libburn/drive.c index fc1d95a..ce8ddc7 100644 --- a/libburn/drive.c +++ b/libburn/drive.c @@ -1696,8 +1696,7 @@ int burn_disc_get_multi_caps(struct burn_drive *d, enum burn_write_types wt, o->advised_write_mode = BURN_WRITE_TAO; } else if (d->current_profile == 0x1b || d->current_profile == 0x2b) { /* DVD+R , DVD+R/DL */ - o->multi_session = 1; - o->multi_track = 1; + o->multi_session = o->multi_track = 1; o->might_do_tao = 2; o->might_do_sao = 1; o->advised_write_mode = BURN_WRITE_TAO; diff --git a/libburn/mmc.c b/libburn/mmc.c index 8a05eca..86ffc83 100644 --- a/libburn/mmc.c +++ b/libburn/mmc.c @@ -89,8 +89,6 @@ extern struct libdax_msgs *libdax_messenger; size prediction mandatory. ts A70208 : Finally made tests with DVD-R. Worked exactly as new DVD-RW. -Todo: - Determine first free lba for appending data on overwriteables. */ @@ -242,7 +240,6 @@ int mmc_reserve_track(struct burn_drive *d, off_t size) int mmc_read_track_info(struct burn_drive *d, int trackno, struct buffer *buf) { struct command c; - int i; mmc_function_spy("mmc_read_track_info"); c.retry = 1; @@ -263,8 +260,7 @@ int mmc_read_track_info(struct burn_drive *d, int trackno, struct buffer *buf) else /* mmc5r03c.pdf: valid only for CD, DVD+R, DVD+R DL */ trackno = 0xFF; } - for (i = 0; i < 4; i++) - c.opcode[2 + i] = (trackno >> (24 - 8 * i)) & 0xff; + mmc_int_to_four_char(c.opcode + 2, trackno); c.page = buf; memset(buf->data, 0, BUFFER_SIZE); c.dir = FROM_DRIVE; @@ -285,26 +281,11 @@ int mmc_get_nwa(struct burn_drive *d, int trackno, int *lba, int *nwa) unsigned char *data; mmc_function_spy("mmc_get_nwa"); - if(trackno<=0) { - if (d->current_profile == 0x1a || d->current_profile == 0x13 || - d->current_profile == 0x12 ) - /* DVD+RW , DVD-RW restricted overwrite , DVD-RAM */ - trackno = 1; - else if (d->current_profile == 0x10 || - d->current_profile == 0x11 || - d->current_profile == 0x14 || - d->current_profile == 0x15) - /* DVD-ROM, DVD-R[W] Sequential */ - trackno = d->last_track_no; - else /* mmc5r03c.pdf: valid only for CD, DVD+R, DVD+R DL */ - trackno = 0xFF; - } ret = mmc_read_track_info(d, trackno, &buf); if (ret <= 0) return ret; data = buf.data; - *lba = mmc_four_char_to_int(data + 8); *nwa = mmc_four_char_to_int(data + 12); num = mmc_four_char_to_int(data + 16); @@ -375,6 +356,11 @@ void mmc_close_session(struct burn_write_opts *o) mmc_close(d, 1, 0); } +/* ts A70227 : extended meaning of session to address all possible values + of 5Bh CLOSE TRACK SESSION to address any Close Function. + @param session contains the two high bits of Close Function + @param track if not 0: sets the lowest bit of Close Function +*/ void mmc_close(struct burn_drive *d, int session, int track) { struct command c; @@ -385,8 +371,8 @@ void mmc_close(struct burn_drive *d, int session, int track) c.oplen = sizeof(MMC_CLOSE); memcpy(c.opcode, MMC_CLOSE, sizeof(MMC_CLOSE)); - /* ts A61030 : shifted !!session rather than or-ing plain session */ - c.opcode[2] = ((!!session)<<1) | !!track; + /* (ts A61030 : shifted !!session rather than or-ing plain session ) */ + c.opcode[2] = ((session & 3) << 1) | !!track; c.opcode[4] = track >> 8; c.opcode[5] = track & 0xFF; c.page = NULL; @@ -431,14 +417,8 @@ void mmc_write_12(struct burn_drive *d, int start, struct buffer *buf) memcpy(c.opcode, MMC_WRITE_12, sizeof(MMC_WRITE_12)); c.retry = 1; c.oplen = sizeof(MMC_WRITE_12); - c.opcode[2] = start >> 24; - c.opcode[3] = (start >> 16) & 0xFF; - c.opcode[4] = (start >> 8) & 0xFF; - c.opcode[5] = start & 0xFF; - c.opcode[6] = len >> 24; - c.opcode[7] = (len >> 16) & 0xFF; - c.opcode[8] = (len >> 8) & 0xFF; - c.opcode[9] = len & 0xFF; + mmc_int_to_four_char(c.opcode + 2, start); + mmc_int_to_four_char(c.opcode + 6, len); c.page = buf; c.dir = TO_DRIVE; @@ -491,10 +471,7 @@ int mmc_write(struct burn_drive *d, int start, struct buffer *buf) memcpy(c.opcode, MMC_WRITE_10, sizeof(MMC_WRITE_10)); c.retry = 1; c.oplen = sizeof(MMC_WRITE_10); - c.opcode[2] = start >> 24; - c.opcode[3] = (start >> 16) & 0xFF; - c.opcode[4] = (start >> 8) & 0xFF; - c.opcode[5] = start & 0xFF; + mmc_int_to_four_char(c.opcode + 2, start); c.opcode[6] = 0; c.opcode[7] = (len >> 8) & 0xFF; c.opcode[8] = len & 0xFF; @@ -1561,6 +1538,11 @@ void mmc_get_configuration(struct burn_drive *d) if (cp == 0x15 && burn_support_untested_profiles) /* DVD-R/DL */ d->current_is_supported_profile = 1; #endif +#ifdef Libburn_support_dvd_plusR + if ((cp == 0x1b || cp == 0x2b) && + burn_support_untested_profiles) /* DVD+R , DVD+R/DL */ + d->current_is_supported_profile = 1; +#endif /* Enable this to get loud and repeated reports about the feature set : #define Libburn_print_feature_descriptorS 1 @@ -1916,8 +1898,8 @@ int mmc_format_unit(struct burn_drive *d, off_t size, int flag) c.page->data[1] = 0x02; /* Immed */ c.page->data[3] = 8; /* Format descriptor length */ num_of_blocks = size / 2048; - for (i = 0; i < 4; i++) - c.page->data[4 + i] = (num_of_blocks >> (24 - 8 * i)) & 0xff; + mmc_int_to_four_char(c.page->data + 4, num_of_blocks); + if (flag & 128) { /* explicitely chosen format descriptor */ /* use case: the app knows what to do */ @@ -1947,9 +1929,7 @@ selected_not_suitable:; if (flag & 4) { num_of_blocks = d->format_descriptors[index].size / 2048; - for (i = 0; i < 4; i++) - c.page->data[4 + i] = - (num_of_blocks >> (24 - 8 * i)) & 0xff; + mmc_int_to_four_char(c.page->data + 4, num_of_blocks); } if (format_type != 0x26) for (i = 0; i < 3; i++) @@ -2024,9 +2004,8 @@ selected_not_suitable:; num_of_blocks = diff; } if (num_of_blocks > 0) - for (i = 0; i < 4; i++) - c.page->data[4 + i] = - (num_of_blocks >> (24 - 8 * i)) & 0xff; + mmc_int_to_four_char(c.page->data + 4, + num_of_blocks); } /* 6.5.4.2.8 , DVD-RW Quick Grow Last Border */ format_type = 0x13; @@ -2050,9 +2029,8 @@ selected_not_suitable:; if ((flag & 4) || d->best_format_type == full_format_type) { num_of_blocks = d->best_format_size / 2048; - for (i = 0; i < 4; i++) - c.page->data[4 + i] = - (num_of_blocks >> (24 - 8 * i)) & 0xff; + mmc_int_to_four_char(c.page->data + 4, + num_of_blocks); } } else { @@ -2356,6 +2334,10 @@ int mmc_compose_mode_page_5(struct burn_drive *d, /* Packet Size */ pd[13] = 16; + } else if (d->current_profile == 0x1a || d->current_profile == 0x1b || + d->current_profile == 0x2b || d->current_profile == 0x12) { + /* not with DVD+R[W][/DL] or DVD-RAM */; + return 0; } else { /* Traditional setup for CD */ diff --git a/libburn/write.c b/libburn/write.c index 8adf556..6531455 100644 --- a/libburn/write.c +++ b/libburn/write.c @@ -890,6 +890,84 @@ int burn_disc_init_write_status(struct burn_write_opts *o, } +/* ts A70219 : API */ +int burn_precheck_write(struct burn_write_opts *o, struct burn_disc *disc, + char reasons[BURN_REASONS_LEN], int silent) +{ + enum burn_write_types wt; + struct burn_drive *d = o->drive; + char msg[160], *reason_pt; + int no_media = 0; + + reason_pt= reasons; + reasons[0] = 0; + + /* check write mode against write job */ + wt = burn_write_opts_auto_write_type(o, disc, reasons, 1); + if (wt == BURN_WRITE_NONE) { + if (strncmp(reasons, "MEDIA: ", 7)==0) + no_media = 1; + goto ex; + } + + sprintf(reasons, "%s: ", d->current_profile_text); + reason_pt= reasons + strlen(reasons); + if (d->status == BURN_DISC_UNSUITABLE) + goto unsuitable_profile; + if (d->current_profile == 0x09 || d->current_profile == 0x0a) { + if (!burn_disc_write_is_ok(o, disc, (!!silent) << 1)) + strcat(reasons, "unsuitable track mode found, "); + if (o->start_byte >= 0) + strcat(reasons, "write start address not supported, "); + } else if (d->current_profile == 0x1a || d->current_profile == 0x12) { + /* DVD+RW , DVD-RAM */ + if (o->start_byte >= 0 && (o->start_byte % 2048)) + strcat(reasons, + "write start address not properly aligned to 2048, "); + } else if (d->current_profile == 0x13) { + /* DVD-RW Restricted Overwrite */ + if (o->start_byte >= 0 && (o->start_byte % 32768)) + strcat(reasons, + "write start address not properly aligned to 32k, "); + } else if (d->current_profile == 0x11 || d->current_profile == 0x14 || + d->current_profile == 0x15 || + d->current_profile == 0x1b || d->current_profile == 0x2b ) { + /* DVD-R* Sequential , DVD+R[/DL] */ + if (o->start_byte >= 0) + strcat(reasons, "write start address not supported, "); + } else { +unsuitable_profile:; + sprintf(msg, "Unsuitable media detected. Profile %4.4Xh %s", + d->current_profile, d->current_profile_text); + if (!silent) + libdax_msgs_submit(libdax_messenger, d->global_index, + 0x0002011e, + LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, + msg, 0, 0); + strcat(reasons, "no suitable media profile detected, "); + return 0; + } +ex:; + if (reason_pt[0]) { + if (no_media) { + if (!silent) + libdax_msgs_submit(libdax_messenger, + d->global_index, 0x0002013a, + LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, + "No suitable media detected", 0, 0); + return -1; + } + if (!silent) + libdax_msgs_submit(libdax_messenger, + d->global_index, 0x00020139, + LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, + "Write job parameters are unsuitable", 0, 0); + return 0; + } + return 1; +} + + /* ts A70129 : learned much from dvd+rw-tools-7.0/growisofs_mmc.cpp */ int burn_disc_open_track_dvd_minus_r(struct burn_write_opts *o, struct burn_session *s, int tnum) @@ -931,6 +1009,46 @@ int burn_disc_open_track_dvd_minus_r(struct burn_write_opts *o, } +/* ts A70226 */ +int burn_disc_open_track_dvd_plus_r(struct burn_write_opts *o, + struct burn_session *s, int tnum) +{ + struct burn_drive *d = o->drive; + char msg[160]; + int ret, lba, nwa; + off_t size; + + ret = d->get_nwa(d, -1, &lba, &nwa); + sprintf(msg, + "DVD+R pre-track %2.2d : get_nwa(%d), ret= %d , d->nwa= %d", + tnum+1, nwa, ret, d->nwa); + libdax_msgs_submit(libdax_messenger, d->global_index, 0x000002, + LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, msg,0,0); + if (nwa > d->nwa) + d->nwa = nwa; + /* ts A70214 : eventually adjust already expanded size of track */ + burn_track_apply_fillup(s->track[tnum], d->media_capacity_remaining,1); + + if (o->write_type == BURN_WRITE_SAO) { + /* Round track size up to 32 KiB and reserve track */ + size = ((off_t) burn_track_get_sectors(s->track[tnum])) + * (off_t) 2048; + size = (size + (off_t) 0x7fff) & ~((off_t) 0x7fff); + ret = d->reserve_track(d, size); + if (ret <= 0) { + sprintf(msg, "Cannot reserve track of %.f bytes", + (double) size); + libdax_msgs_submit(libdax_messenger, d->global_index, + 0x00020138, + LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, + msg, 0, 0); + return 0; + } + } + return 1; +} + + /* ts A70129 */ int burn_disc_close_track_dvd_minus_r(struct burn_write_opts *o, struct burn_session *s, int tnum) @@ -956,6 +1074,28 @@ int burn_disc_close_track_dvd_minus_r(struct burn_write_opts *o, } +/* ts A70226 */ +int burn_disc_close_track_dvd_plus_r(struct burn_write_opts *o, + struct burn_session *s, int tnum) +{ + struct burn_drive *d = o->drive; + char msg[80]; + + sprintf(msg, + "Closing track %2.2d (absolute track and session number %d)", + tnum + 1, d->last_track_no); + libdax_msgs_submit(libdax_messenger, o->drive->global_index,0x00020119, + LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, msg,0,0); + + d->busy = BURN_DRIVE_CLOSING_SESSION; + d->close_track_session(d, 0, d->last_track_no); /* CLOSE TRACK, 001b */ + d->close_track_session(d, 1, 0); /* CLOSE SESSION, 010b */ + d->busy = BURN_DRIVE_WRITING; + d->last_track_no++; + return 1; +} + + /* ts A61218 - A70129 */ int burn_dvd_write_track(struct burn_write_opts *o, struct burn_session *s, int tnum) @@ -975,6 +1115,11 @@ int burn_dvd_write_track(struct burn_write_opts *o, ret = burn_disc_open_track_dvd_minus_r(o, s, tnum); if (ret <= 0) goto ex; + } else if (d->current_profile == 0x1b || d->current_profile == 0x2b) { + /* DVD+R , DVD+R/DL */ + ret = burn_disc_open_track_dvd_plus_r(o, s, tnum); + if (ret <= 0) + goto ex; } sectors = burn_track_get_sectors(t); @@ -1035,7 +1180,12 @@ int burn_dvd_write_track(struct burn_write_opts *o, d->current_profile == 0x15) { /* DVD-R, DVD-RW Sequential, DVD-R/DL Sequential */ ret = burn_disc_close_track_dvd_minus_r(o, s, tnum); - if (ret != 2) + if (ret <= 0) + goto ex; + } else if (d->current_profile == 0x1b || d->current_profile == 0x2b) { + /* DVD+R , DVD+R/DL */ + ret = burn_disc_close_track_dvd_plus_r(o, s, tnum); + if (ret <= 0) goto ex; } ret = 1; @@ -1148,6 +1298,8 @@ int burn_dvd_write_session(struct burn_write_opts *o, if (ret <= 0) return 0; } + } else if (d->current_profile == 0x1b || d->current_profile == 0x2b) { + /* DVD+R , DVD+R/DL do each track as an own session */; } return 1; } @@ -1258,76 +1410,30 @@ int burn_disc_setup_dvd_minus_r(struct burn_write_opts *o, } -/* ts A70219 : API */ -int burn_precheck_write(struct burn_write_opts *o, struct burn_disc *disc, - char reasons[BURN_REASONS_LEN], int silent) +/* ts A70226 : for DVD+R , DVD+R/DL */ +int burn_disc_setup_dvd_plus_r(struct burn_write_opts *o, + struct burn_disc *disc) { - enum burn_write_types wt; struct burn_drive *d = o->drive; - char msg[160], *reason_pt; - int no_media = 0; - reason_pt= reasons; - reasons[0] = 0; + /* most setup is in burn_disc_setup_track_dvd_plus_r() */; - /* check write mode against write job */ - wt = burn_write_opts_auto_write_type(o, disc, reasons, 1); - if (wt == BURN_WRITE_NONE) { - if (strncmp(reasons, "MEDIA: ", 7)==0) - no_media = 1; - goto ex; - } + d->nwa = 0; + return 1; +} - sprintf(reasons, "%s: ", d->current_profile_text); - reason_pt= reasons + strlen(reasons); - if (d->current_profile == 0x09 || d->current_profile == 0x0a) { - if (!burn_disc_write_is_ok(o, disc, (!!silent) << 1)) - strcat(reasons, "unsuitable track mode found, "); - if (o->start_byte >= 0) - strcat(reasons, "write start address not supported, "); - } else if (d->current_profile == 0x1a || d->current_profile == 0x12) { - /* DVD+RW , DVD-RAM */ - if (o->start_byte >= 0 && (o->start_byte % 2048)) - strcat(reasons, - "write start address not properly aligned to 2048, "); - } else if (d->current_profile == 0x13) { - /* DVD-RW Restricted Overwrite */ - if (o->start_byte >= 0 && (o->start_byte % 32768)) - strcat(reasons, - "write start address not properly aligned to 32k, "); - } else if (d->current_profile == 0x11 || d->current_profile == 0x14 || - d->current_profile == 0x15) { - /* DVD-R* Sequential */ - if (o->start_byte >= 0) - strcat(reasons, "write start address not supported, "); - } else { - sprintf(msg, "Unsuitable media detected. Profile %4.4Xh %s", - d->current_profile, d->current_profile_text); - if (!silent) - libdax_msgs_submit(libdax_messenger, d->global_index, - 0x0002011e, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - msg, 0, 0); - strcat(reasons, "no suitable media profile detected, "); - return 0; - } -ex:; - if (reason_pt[0]) { - if (no_media) { - if (!silent) - libdax_msgs_submit(libdax_messenger, - d->global_index, 0x0002013a, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, - "No suitable media detected", 0, 0); - return -1; - } - if (!silent) - libdax_msgs_submit(libdax_messenger, - d->global_index, 0x00020139, - LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, - "Write job parameters are unsuitable", 0, 0); - return 0; - } + +/* ts A70229 */ +int burn_disc_finalize_dvd_plus_r(struct burn_write_opts *o) +{ + struct burn_drive *d = o->drive; + + if (o->multi) + return 2; + d->busy = BURN_DRIVE_CLOSING_SESSION; + /* CLOSE SESSION, 101b, Finalize with minimal radius */ + d->close_track_session(d, 2, 1); /* (2<<1)|1 = 5 */ + d->busy = BURN_DRIVE_WRITING; return 1; } @@ -1534,6 +1640,38 @@ int burn_dvd_write_sync(struct burn_write_opts *o, /* ??? padding needed ??? cowardly doing it for now */ o->obs_pad = 1; /* fill-up track's last 32k buffer */ + } else if (d->current_profile == 0x1b || d->current_profile == 0x2b) { + /* DVD+R , DVD+R/DL */ + t = disc->session[0]->track[0]; + o_end = ( burn_track_is_open_ended(t) && !o->fill_up_media ); + default_size = burn_track_get_default_size(t); + +#ifndef Libburn_precheck_write_ruleS + /* >>> oldfashioned checks hopefully never re-enabled */ +#endif /* ! Libburn_precheck_write_ruleS */ + + if (o->write_type == BURN_WRITE_SAO && o_end) { + sprintf(msg, "Activated track default size %.f", + (double) default_size); + libdax_msgs_submit(libdax_messenger, + d->global_index, 0x0002012e, + LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH, + msg, 0, 0); + burn_track_set_size(t, default_size); + } + ret = burn_disc_setup_dvd_plus_r(o, disc); + if (ret <= 0) { + sprintf(msg, + "Write preparation setup failed for DVD+R"); + libdax_msgs_submit(libdax_messenger, d->global_index, + 0x00020121, + LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, + msg, 0, 0); + goto early_failure; + } + /* ??? padding needed ??? cowardly doing it for now */ + o->obs_pad = 1; /* fill-up track's last 32k buffer */ + #ifndef Libburn_precheck_write_ruleS /* <<< covered by burn_precheck_write() */ } else { @@ -1564,8 +1702,11 @@ int burn_dvd_write_sync(struct burn_write_opts *o, d->progress.sectors = 0; } - /* >>> eventual normal finalization measures */ - + if (d->current_profile == 0x1b || d->current_profile == 0x2b) { + ret = burn_disc_finalize_dvd_plus_r(o); + if (ret <= 0) + goto ex; + } ret = 1; ex:;