Preparations for supporting DVD+R[/DL]

This commit is contained in:
Thomas Schmitt 2007-03-01 12:07:29 +00:00
parent 0c4cfdd359
commit 3b5c80e867
6 changed files with 348 additions and 120 deletions

View File

@ -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 || } else if((profile_number==0x1a || profile_number==0x13 ||
profile_number==0x12 || profile_number==0x12 ||
profile_number==0x11 || profile_number==0x14 || profile_number==0x11 || profile_number==0x14 ||
profile_number==0x15) profile_number==0x15 ||
profile_number==0x1b || profile_number==0x2b)
&& might_do_tao) { && 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"); strcpy(skin->preskin->write_mode_name,"TAO");
} else { } else {
strcpy(skin->preskin->write_mode_name,"SAO"); strcpy(skin->preskin->write_mode_name,"SAO");

View File

@ -1 +1 @@
#define Cdrskin_timestamP "2007.02.25.112733" #define Cdrskin_timestamP "2007.03.01.120945"

View File

@ -5,7 +5,7 @@ Content:
- SAO CD Cookbook (CD-R, CD-RW, pure audio or pure data only) - SAO CD Cookbook (CD-R, CD-RW, pure audio or pure data only)
- Overwriteable DVD Cookbook (DVD-RAM, DVD+RW, DVD-RW) - Overwriteable DVD Cookbook (DVD-RAM, DVD+RW, DVD-RW)
- Sequential DVD-R[W] Cookbook - Sequential DVD-R[W] Cookbook
- >>> DVD+R Cookbook (emerging, totally untested yet)
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
TAO Multi-Session CD Cookbook 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 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 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 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". 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. 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 <scdbackup@gmx.net>
-------------------------------------------------------------------------------
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) :
>>>
-------------------------------------------------------------------------------

View File

@ -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; o->advised_write_mode = BURN_WRITE_TAO;
} else if (d->current_profile == 0x1b || d->current_profile == 0x2b) { } else if (d->current_profile == 0x1b || d->current_profile == 0x2b) {
/* DVD+R , DVD+R/DL */ /* DVD+R , DVD+R/DL */
o->multi_session = 1; o->multi_session = o->multi_track = 1;
o->multi_track = 1;
o->might_do_tao = 2; o->might_do_tao = 2;
o->might_do_sao = 1; o->might_do_sao = 1;
o->advised_write_mode = BURN_WRITE_TAO; o->advised_write_mode = BURN_WRITE_TAO;

View File

@ -89,8 +89,6 @@ extern struct libdax_msgs *libdax_messenger;
size prediction mandatory. size prediction mandatory.
ts A70208 : Finally made tests with DVD-R. Worked exactly as new DVD-RW. 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) int mmc_read_track_info(struct burn_drive *d, int trackno, struct buffer *buf)
{ {
struct command c; struct command c;
int i;
mmc_function_spy("mmc_read_track_info"); mmc_function_spy("mmc_read_track_info");
c.retry = 1; 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 */ else /* mmc5r03c.pdf: valid only for CD, DVD+R, DVD+R DL */
trackno = 0xFF; trackno = 0xFF;
} }
for (i = 0; i < 4; i++) mmc_int_to_four_char(c.opcode + 2, trackno);
c.opcode[2 + i] = (trackno >> (24 - 8 * i)) & 0xff;
c.page = buf; c.page = buf;
memset(buf->data, 0, BUFFER_SIZE); memset(buf->data, 0, BUFFER_SIZE);
c.dir = FROM_DRIVE; 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; unsigned char *data;
mmc_function_spy("mmc_get_nwa"); 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); ret = mmc_read_track_info(d, trackno, &buf);
if (ret <= 0) if (ret <= 0)
return ret; return ret;
data = buf.data; data = buf.data;
*lba = mmc_four_char_to_int(data + 8); *lba = mmc_four_char_to_int(data + 8);
*nwa = mmc_four_char_to_int(data + 12); *nwa = mmc_four_char_to_int(data + 12);
num = mmc_four_char_to_int(data + 16); 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); 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) void mmc_close(struct burn_drive *d, int session, int track)
{ {
struct command c; struct command c;
@ -385,8 +371,8 @@ void mmc_close(struct burn_drive *d, int session, int track)
c.oplen = sizeof(MMC_CLOSE); c.oplen = sizeof(MMC_CLOSE);
memcpy(c.opcode, MMC_CLOSE, sizeof(MMC_CLOSE)); memcpy(c.opcode, MMC_CLOSE, sizeof(MMC_CLOSE));
/* ts A61030 : shifted !!session rather than or-ing plain session */ /* (ts A61030 : shifted !!session rather than or-ing plain session ) */
c.opcode[2] = ((!!session)<<1) | !!track; c.opcode[2] = ((session & 3) << 1) | !!track;
c.opcode[4] = track >> 8; c.opcode[4] = track >> 8;
c.opcode[5] = track & 0xFF; c.opcode[5] = track & 0xFF;
c.page = NULL; 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)); memcpy(c.opcode, MMC_WRITE_12, sizeof(MMC_WRITE_12));
c.retry = 1; c.retry = 1;
c.oplen = sizeof(MMC_WRITE_12); c.oplen = sizeof(MMC_WRITE_12);
c.opcode[2] = start >> 24; mmc_int_to_four_char(c.opcode + 2, start);
c.opcode[3] = (start >> 16) & 0xFF; mmc_int_to_four_char(c.opcode + 6, len);
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;
c.page = buf; c.page = buf;
c.dir = TO_DRIVE; 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)); memcpy(c.opcode, MMC_WRITE_10, sizeof(MMC_WRITE_10));
c.retry = 1; c.retry = 1;
c.oplen = sizeof(MMC_WRITE_10); c.oplen = sizeof(MMC_WRITE_10);
c.opcode[2] = start >> 24; mmc_int_to_four_char(c.opcode + 2, start);
c.opcode[3] = (start >> 16) & 0xFF;
c.opcode[4] = (start >> 8) & 0xFF;
c.opcode[5] = start & 0xFF;
c.opcode[6] = 0; c.opcode[6] = 0;
c.opcode[7] = (len >> 8) & 0xFF; c.opcode[7] = (len >> 8) & 0xFF;
c.opcode[8] = len & 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 */ if (cp == 0x15 && burn_support_untested_profiles) /* DVD-R/DL */
d->current_is_supported_profile = 1; d->current_is_supported_profile = 1;
#endif #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 : /* Enable this to get loud and repeated reports about the feature set :
#define Libburn_print_feature_descriptorS 1 #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[1] = 0x02; /* Immed */
c.page->data[3] = 8; /* Format descriptor length */ c.page->data[3] = 8; /* Format descriptor length */
num_of_blocks = size / 2048; num_of_blocks = size / 2048;
for (i = 0; i < 4; i++) mmc_int_to_four_char(c.page->data + 4, num_of_blocks);
c.page->data[4 + i] = (num_of_blocks >> (24 - 8 * i)) & 0xff;
if (flag & 128) { /* explicitely chosen format descriptor */ if (flag & 128) { /* explicitely chosen format descriptor */
/* use case: the app knows what to do */ /* use case: the app knows what to do */
@ -1947,9 +1929,7 @@ selected_not_suitable:;
if (flag & 4) { if (flag & 4) {
num_of_blocks = num_of_blocks =
d->format_descriptors[index].size / 2048; d->format_descriptors[index].size / 2048;
for (i = 0; i < 4; i++) mmc_int_to_four_char(c.page->data + 4, num_of_blocks);
c.page->data[4 + i] =
(num_of_blocks >> (24 - 8 * i)) & 0xff;
} }
if (format_type != 0x26) if (format_type != 0x26)
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
@ -2024,9 +2004,8 @@ selected_not_suitable:;
num_of_blocks = diff; num_of_blocks = diff;
} }
if (num_of_blocks > 0) if (num_of_blocks > 0)
for (i = 0; i < 4; i++) mmc_int_to_four_char(c.page->data + 4,
c.page->data[4 + i] = num_of_blocks);
(num_of_blocks >> (24 - 8 * i)) & 0xff;
} }
/* 6.5.4.2.8 , DVD-RW Quick Grow Last Border */ /* 6.5.4.2.8 , DVD-RW Quick Grow Last Border */
format_type = 0x13; format_type = 0x13;
@ -2050,9 +2029,8 @@ selected_not_suitable:;
if ((flag & 4) if ((flag & 4)
|| d->best_format_type == full_format_type) { || d->best_format_type == full_format_type) {
num_of_blocks = d->best_format_size / 2048; num_of_blocks = d->best_format_size / 2048;
for (i = 0; i < 4; i++) mmc_int_to_four_char(c.page->data + 4,
c.page->data[4 + i] = num_of_blocks);
(num_of_blocks >> (24 - 8 * i)) & 0xff;
} }
} else { } else {
@ -2356,6 +2334,10 @@ int mmc_compose_mode_page_5(struct burn_drive *d,
/* Packet Size */ /* Packet Size */
pd[13] = 16; 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 { } else {
/* Traditional setup for CD */ /* Traditional setup for CD */

View File

@ -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 */ /* 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, int burn_disc_open_track_dvd_minus_r(struct burn_write_opts *o,
struct burn_session *s, int tnum) 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 */ /* ts A70129 */
int burn_disc_close_track_dvd_minus_r(struct burn_write_opts *o, int burn_disc_close_track_dvd_minus_r(struct burn_write_opts *o,
struct burn_session *s, int tnum) 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 */ /* ts A61218 - A70129 */
int burn_dvd_write_track(struct burn_write_opts *o, int burn_dvd_write_track(struct burn_write_opts *o,
struct burn_session *s, int tnum) 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); ret = burn_disc_open_track_dvd_minus_r(o, s, tnum);
if (ret <= 0) if (ret <= 0)
goto ex; 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); sectors = burn_track_get_sectors(t);
@ -1035,7 +1180,12 @@ int burn_dvd_write_track(struct burn_write_opts *o,
d->current_profile == 0x15) { d->current_profile == 0x15) {
/* DVD-R, DVD-RW Sequential, DVD-R/DL Sequential */ /* DVD-R, DVD-RW Sequential, DVD-R/DL Sequential */
ret = burn_disc_close_track_dvd_minus_r(o, s, tnum); 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; goto ex;
} }
ret = 1; ret = 1;
@ -1148,6 +1298,8 @@ int burn_dvd_write_session(struct burn_write_opts *o,
if (ret <= 0) if (ret <= 0)
return 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; return 1;
} }
@ -1258,76 +1410,30 @@ int burn_disc_setup_dvd_minus_r(struct burn_write_opts *o,
} }
/* ts A70219 : API */ /* ts A70226 : for DVD+R , DVD+R/DL */
int burn_precheck_write(struct burn_write_opts *o, struct burn_disc *disc, int burn_disc_setup_dvd_plus_r(struct burn_write_opts *o,
char reasons[BURN_REASONS_LEN], int silent) struct burn_disc *disc)
{ {
enum burn_write_types wt;
struct burn_drive *d = o->drive; struct burn_drive *d = o->drive;
char msg[160], *reason_pt;
int no_media = 0;
reason_pt= reasons; /* most setup is in burn_disc_setup_track_dvd_plus_r() */;
reasons[0] = 0;
/* check write mode against write job */ d->nwa = 0;
wt = burn_write_opts_auto_write_type(o, disc, reasons, 1); return 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); /* ts A70229 */
if (d->current_profile == 0x09 || d->current_profile == 0x0a) { int burn_disc_finalize_dvd_plus_r(struct burn_write_opts *o)
if (!burn_disc_write_is_ok(o, disc, (!!silent) << 1)) {
strcat(reasons, "unsuitable track mode found, "); struct burn_drive *d = o->drive;
if (o->start_byte >= 0)
strcat(reasons, "write start address not supported, "); if (o->multi)
} else if (d->current_profile == 0x1a || d->current_profile == 0x12) { return 2;
/* DVD+RW , DVD-RAM */ d->busy = BURN_DRIVE_CLOSING_SESSION;
if (o->start_byte >= 0 && (o->start_byte % 2048)) /* CLOSE SESSION, 101b, Finalize with minimal radius */
strcat(reasons, d->close_track_session(d, 2, 1); /* (2<<1)|1 = 5 */
"write start address not properly aligned to 2048, "); d->busy = BURN_DRIVE_WRITING;
} 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;
}
return 1; return 1;
} }
@ -1534,6 +1640,38 @@ int burn_dvd_write_sync(struct burn_write_opts *o,
/* ??? padding needed ??? cowardly doing it for now */ /* ??? padding needed ??? cowardly doing it for now */
o->obs_pad = 1; /* fill-up track's last 32k buffer */ 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 #ifndef Libburn_precheck_write_ruleS
/* <<< covered by burn_precheck_write() */ /* <<< covered by burn_precheck_write() */
} else { } else {
@ -1564,8 +1702,11 @@ int burn_dvd_write_sync(struct burn_write_opts *o,
d->progress.sectors = 0; 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; ret = 1;
ex:; ex:;