Writing CATALOG and ISRC into Q sub-channel of CD SAO sessions
This commit is contained in:
parent
67ae1413e3
commit
cdaa2971db
@ -2,7 +2,7 @@
|
||||
.\" First parameter, NAME, should be all caps
|
||||
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
||||
.\" other parameters are allowed: see man(7), man(1)
|
||||
.TH CDRSKIN 1 "Dec 25, 2011"
|
||||
.TH CDRSKIN 1 "Dec 27, 2011"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
.\"
|
||||
.\" Some roff macros, for reference:
|
||||
@ -506,9 +506,7 @@ present.
|
||||
.br
|
||||
cdrskin currently supports TRACK datatypes AUDIO and MODE1/2048 which may
|
||||
not be mixed. It ignores commands POSTGAP, PREGAP, and FLAGS. Only INDEX 01
|
||||
is interpreted yet. Commands CATALOG and ISRC only affect CD-TEXT but not
|
||||
the Q sub-channel of the program area. Data source may be of FILE type BINARY
|
||||
or MOTOROLA.
|
||||
is interpreted yet. Data source may be of FILE type BINARY or MOTOROLA.
|
||||
.TP
|
||||
.BI \-dao
|
||||
Alias for option -sao. Write CD in Session at Once mode
|
||||
|
@ -1 +1 @@
|
||||
#define Cdrskin_timestamP "2011.12.27.115645"
|
||||
#define Cdrskin_timestamP "2011.12.27.133733"
|
||||
|
@ -225,7 +225,7 @@ sync. libburn uses the info provided by 52h READ TRACK INFORMATION.
|
||||
Guided by reading libburn/* from http://icculus.org/burn
|
||||
backed by reading mmc5r03c.pdf from http://www.t10.org/ftp/t10/drafts/mmc5/
|
||||
and by experiments with drives NEC ND-4570A, LG GSA-4082B, LITE-ON LTR48125S,
|
||||
Optiarc BD RW BD-5300S,
|
||||
Optiarc BD RW BD-5300S, LG BDDVDRW GGC-H20L
|
||||
|
||||
For libburnia-project.org by Thomas Schmitt <scdbackup@gmx.net>
|
||||
|
||||
@ -264,7 +264,8 @@ CTL|ADR, TNO, INDEX, DATA FORM, SCMS, MIN, SEC, FRAME .
|
||||
|
||||
CTL is 40h for data and 00h for audio.
|
||||
(mmc5r03c.pdf 6.33.3.4)
|
||||
ADR is always 01h.
|
||||
ADR is 01h for entries which define time points. It is 02h for media catalog
|
||||
entries and it is 03h for track ISRC entries.
|
||||
TNO is the track number (1 to 99).
|
||||
INDEX is a subaddress within tracks. This recipe uses only INDEX 01h within
|
||||
tracks.
|
||||
@ -277,18 +278,33 @@ MIN, SEC, FRAME give the MSF address where the described data entity starts.
|
||||
LBA = frames - 150, 75 frames = 1 sec , 60 sec = 1 min.
|
||||
This address must increase from entry to entry (or at least stay equal).
|
||||
|
||||
The first two entries describe the Media Catalog Number, a string of 13
|
||||
characters, also known with CD-TEXT as "UPC/EAN".
|
||||
(02h, catalog characters 1 to 7)
|
||||
(02h, catalog characters 8 to 13, 00h)
|
||||
These two entries shall be omitted if no catalog number is given.
|
||||
|
||||
The first entry describes the Lead-in. Its content is
|
||||
The next entry (eventually being the first one) describes the Lead-in.
|
||||
Its content is
|
||||
(CTL|ADR ,00h,00h, DATA FORM ,00h,00h,00h,00h)
|
||||
With the CTL|ADR for the first track: 41h for data, 01h for audio.
|
||||
DATA FORM is 41h if CD-TEXT shall be stored in Lean-in. Else it is 01h.
|
||||
|
||||
The LBA for the first write is negative: -150. This corresponds to MSF address
|
||||
00h:00h:00h. All addresses are to be given in MSF format.
|
||||
|
||||
Each track may be preceded by two entries describing an ISRC string of 12
|
||||
characters.
|
||||
(CTL | 03h, TNO, characters 1 to 6)
|
||||
(CTL | 03h, TNO, characters 7 to 12)
|
||||
These entries shall be omitted if no ISRC is given for the track.
|
||||
CTL shall be the same as with the track.
|
||||
|
||||
The first information track on disc is preceded by a pause encoding of 2 sec:
|
||||
(CTL|ADR,01h,00h, DATA FORM ,00h,00h,00h,00h)
|
||||
with DATA FORM = 00h for audio and 10h for data. By those 2 seconds the MSF
|
||||
address increases to 00h:02h:00h = LBA 0.
|
||||
address increases to 00h:02h:00h = LBA 0. This entry has to come after ISRC,
|
||||
if ISRC is given for the track.
|
||||
|
||||
Each track is represented by an entry
|
||||
(CTL|ADR, TNO ,01h,DATA FORM,00h, MIN , SEC , FRAME)
|
||||
@ -331,6 +347,10 @@ A Write Parameters mode page 05h has to be composed and transmitted via
|
||||
Track Mode Describes frame type 0 (is ignored)
|
||||
Data Block Type Layout of payload blocks 0 (is ignored)
|
||||
Audio Pause Length 150 = 2 seconds (ignored ?)
|
||||
|
||||
>>> CATALOG
|
||||
>>> no ISRC with SAO
|
||||
|
||||
Any other parameters may be set to 0.
|
||||
Mode page data as of MMC-5 table 644 are preceded by a Mode Parameter Header
|
||||
as of SPC-3 table 240. This 8-byte header may be filled with zeros.
|
||||
|
@ -620,6 +620,9 @@ static int v07t_cdtext_to_track(struct burn_track *track, int block,
|
||||
|
||||
|
||||
/* ts B11215 API */
|
||||
/* @param flag bit1= do not attach CATALOG to session or ISRC to track for
|
||||
writing to Q sub-channel
|
||||
*/
|
||||
int burn_session_input_sheet_v07t(struct burn_session *session,
|
||||
char *path, int block, int flag)
|
||||
{
|
||||
@ -802,6 +805,10 @@ cannot_open:;
|
||||
&int0x01, 0, "UPC_ISRC", 0);
|
||||
if (ret <= 0)
|
||||
goto ex;
|
||||
if (!(flag & 2)) {
|
||||
memcpy(session->mediacatalog, payload, 13);
|
||||
session->mediacatalog[13] = 0;
|
||||
}
|
||||
session_attr_seen[0xe] = 1;
|
||||
|
||||
} else if (strncmp(line, "Disc Information ", 17) == 0) {
|
||||
@ -928,9 +935,15 @@ bad_track_no:;
|
||||
strcmp(line + 9, "Message") == 0)
|
||||
pack_type = 0x85;
|
||||
else if (strcmp(line + 9, "0x8e") == 0 ||
|
||||
strcmp(line + 9, "ISRC") == 0)
|
||||
strcmp(line + 9, "ISRC") == 0) {
|
||||
pack_type = 0x8e;
|
||||
else {
|
||||
if (!(flag & 2)) {
|
||||
ret = burn_track_set_isrc_string(
|
||||
tracks[tno], payload, 0);
|
||||
if (ret <= 0)
|
||||
goto ex;
|
||||
}
|
||||
} else {
|
||||
sprintf(msg,
|
||||
"Unknown v07t Track purpose specifier '%s'",
|
||||
line + 9);
|
||||
@ -958,6 +971,12 @@ bad_track_no:;
|
||||
goto bad_track_no;
|
||||
}
|
||||
tno -= track_offset;
|
||||
if (!(flag & 2)) {
|
||||
ret = burn_track_set_isrc_string(
|
||||
tracks[tno], payload, 0);
|
||||
if (ret <= 0)
|
||||
goto ex;
|
||||
}
|
||||
ret = v07t_cdtext_to_track(tracks[tno], block, payload,
|
||||
&int0x00, 0x8e, "", 0);
|
||||
if (ret <= 0)
|
||||
|
172
libburn/write.c
172
libburn/write.c
@ -272,7 +272,6 @@ int burn_write_close_track(struct burn_write_opts *o, struct burn_session *s,
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ts A61030 */
|
||||
int burn_write_close_session(struct burn_write_opts *o)
|
||||
{
|
||||
@ -301,46 +300,66 @@ int burn_write_close_session(struct burn_write_opts *o)
|
||||
/* ts A60819:
|
||||
This is unused since about Feb 2006, icculus.org/burn CVS.
|
||||
The compiler complains. We shall please our compiler.
|
||||
# define Libburn_write_with_function_print_cuE
|
||||
*/
|
||||
|
||||
#ifdef Libburn_write_with_function_print_cuE
|
||||
|
||||
|
||||
static char cue_printify(char c)
|
||||
{
|
||||
if (c >= 32 && c < 127)
|
||||
return c;
|
||||
return '#';
|
||||
}
|
||||
|
||||
|
||||
static void print_cue(struct cue_sheet *sheet)
|
||||
{
|
||||
int i;
|
||||
unsigned char *unit;
|
||||
|
||||
printf("\n");
|
||||
printf("ctladr|trno|indx|form|scms| msf\n");
|
||||
printf("------+----+----+----+----+--------\n");
|
||||
printf("ctladr|trno|indx|form|scms| msf | text\n");
|
||||
printf("------+----+----+----+----+----------+--------\n");
|
||||
for (i = 0; i < sheet->count; i++) {
|
||||
unit = sheet->data + 8 * i;
|
||||
if ((unit[0] & 0xf) == 2) {
|
||||
printf(
|
||||
" %1X %1X | | | | | | %c%c%c%c%c%c%c\n",
|
||||
(unit[0] & 0xf0) >> 4, unit[0] & 0xf,
|
||||
cue_printify(unit[1]), cue_printify(unit[2]),
|
||||
cue_printify(unit[3]), cue_printify(unit[4]),
|
||||
cue_printify(unit[5]), cue_printify(unit[6]),
|
||||
unit[7] == 0 ? ' ' : cue_printify(unit[7]));
|
||||
} else if ((unit[0] & 0xf) == 3) {
|
||||
printf(
|
||||
" %1X %1X | %02X | | | | | %c%c%c%c%c%c\n",
|
||||
(unit[0] & 0xf0) >> 4, unit[0] & 0xf,
|
||||
unit[1], cue_printify(unit[2]),
|
||||
cue_printify(unit[3]), cue_printify(unit[4]),
|
||||
cue_printify(unit[5]), cue_printify(unit[6]),
|
||||
cue_printify(unit[7]));
|
||||
} else {
|
||||
printf(" %1X %1X | %02X | %02X | %02X | %02X |",
|
||||
(unit[0] & 0xf0) >> 4, unit[0] & 0xf, unit[1], unit[2],
|
||||
unit[3], unit[4]);
|
||||
printf("%02X:%02X:%02X\n", unit[5], unit[6], unit[7]);
|
||||
(unit[0] & 0xf0) >> 4, unit[0] & 0xf,
|
||||
unit[1], unit[2], unit[3], unit[4]);
|
||||
printf(" %02X:%02X:%02X |\n",
|
||||
unit[5], unit[6], unit[7]);
|
||||
}
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
#endif /* Libburn_write_with_print_cuE */
|
||||
|
||||
|
||||
/* ts A61009 : changed type from void to int */
|
||||
/** @return 1 = success , <=0 failure */
|
||||
static int add_cue(struct cue_sheet *sheet, unsigned char ctladr,
|
||||
unsigned char tno, unsigned char indx,
|
||||
unsigned char form, unsigned char scms, int lba)
|
||||
/* ts B11226 */
|
||||
static int new_cue(struct cue_sheet *sheet, int number, int flag)
|
||||
{
|
||||
unsigned char *unit;
|
||||
unsigned char *ptr;
|
||||
int m, s, f;
|
||||
|
||||
burn_lba_to_msf(lba, &m, &s, &f);
|
||||
|
||||
sheet->count++;
|
||||
ptr = realloc(sheet->data, sheet->count * 8);
|
||||
|
||||
/* ts A61009 */
|
||||
/* a ssert(ptr); */
|
||||
ptr = realloc(sheet->data, (sheet->count + number) * 8);
|
||||
if (ptr == NULL) {
|
||||
libdax_msgs_submit(libdax_messenger, -1, 0x00020111,
|
||||
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
||||
@ -348,8 +367,26 @@ static int add_cue(struct cue_sheet *sheet, unsigned char ctladr,
|
||||
0, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sheet->data = ptr;
|
||||
sheet->count += number;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* ts B11226 : outsourced new_cue() */
|
||||
/** @return 1 = success , <=0 failure */
|
||||
static int add_cue(struct cue_sheet *sheet, unsigned char ctladr,
|
||||
unsigned char tno, unsigned char indx,
|
||||
unsigned char form, unsigned char scms, int lba)
|
||||
{
|
||||
unsigned char *unit;
|
||||
int m, s, f, ret;
|
||||
|
||||
burn_lba_to_msf(lba, &m, &s, &f);
|
||||
|
||||
ret = new_cue(sheet, 1, 0);
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
unit = sheet->data + (sheet->count - 1) * 8;
|
||||
unit[0] = ctladr;
|
||||
unit[1] = tno;
|
||||
@ -362,13 +399,59 @@ static int add_cue(struct cue_sheet *sheet, unsigned char ctladr,
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* ts B11226 */
|
||||
static int add_catalog_cue(struct cue_sheet *sheet, unsigned char catalog[13])
|
||||
{
|
||||
unsigned char *unit;
|
||||
int i, ret;
|
||||
|
||||
ret = new_cue(sheet, 2, 0);
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
unit = sheet->data + (sheet->count - 2) * 8;
|
||||
unit[0] = unit[8] = 0x02;
|
||||
for (i = 0; i < 13; i++)
|
||||
unit[1 + (i >= 7) * 8 + (i % 7)] = catalog[i];
|
||||
unit[15] = 0x00;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* ts B11226 */
|
||||
static int add_isrc_cue(struct cue_sheet *sheet, unsigned char ctladr, int tno,
|
||||
struct isrc *isrc)
|
||||
{
|
||||
unsigned char *unit;
|
||||
int i, ret;
|
||||
char text[8];
|
||||
|
||||
ret = new_cue(sheet, 2, 0);
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
unit = sheet->data + (sheet->count - 2) * 8;
|
||||
unit[0] = unit[8] = (ctladr & 0xf0) | 0x03;
|
||||
unit[1] = unit[9] = tno;
|
||||
unit[2] = isrc->country[0];
|
||||
unit[3] = isrc->country[1];
|
||||
unit[4] = isrc->owner[0];
|
||||
unit[5] = isrc->owner[1];
|
||||
unit[6] = isrc->owner[2];
|
||||
sprintf(text, "%-2.2u%-5.5u", (unsigned int) isrc->year, isrc->serial);
|
||||
unit[7] = text[0];
|
||||
for (i = 1; i < 7; i++)
|
||||
unit[9 + i] = text[i];
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* ts A61114: added parameter nwa */
|
||||
struct cue_sheet *burn_create_toc_entries(struct burn_write_opts *o,
|
||||
struct burn_session *session,
|
||||
int nwa)
|
||||
{
|
||||
int i, m, s, f, form, pform, runtime = -150, ret, track_length;
|
||||
int leadin_form;
|
||||
int leadin_form, leadin_start;
|
||||
unsigned char ctladr;
|
||||
struct burn_drive *d;
|
||||
struct burn_toc_entry *e;
|
||||
@ -377,6 +460,7 @@ struct cue_sheet *burn_create_toc_entries(struct burn_write_opts *o,
|
||||
int ntr = session->tracks;
|
||||
int rem = 0;
|
||||
|
||||
|
||||
d = o->drive;
|
||||
|
||||
#ifdef Libburn_sao_can_appenD
|
||||
@ -422,13 +506,28 @@ struct cue_sheet *burn_create_toc_entries(struct burn_write_opts *o,
|
||||
leadin_form = 0x41;
|
||||
}
|
||||
}
|
||||
ret = add_cue(sheet, ctladr | 1, 0, 0, leadin_form, 0, runtime);
|
||||
|
||||
if (o->has_mediacatalog)
|
||||
ret = add_catalog_cue(sheet, o->mediacatalog);
|
||||
else if (session->mediacatalog[0])
|
||||
ret = add_catalog_cue(sheet, session->mediacatalog);
|
||||
else
|
||||
ret = 1;
|
||||
if (ret <= 0)
|
||||
goto failed;
|
||||
ret = add_cue(sheet, ctladr | 1, 1, 0, form, 0, runtime);
|
||||
|
||||
/* ts B11225
|
||||
MMC-5 6.33.3.15 Data Form of Sub-channel
|
||||
seems to indicate that for leadin_form 0x41 one should announce
|
||||
d->start_lba as start of the leadin (e.g. -12490) and that data
|
||||
block type should 2 or 3 with mode page 05h. But my drives refuse
|
||||
on that.
|
||||
It works with LBA -150 and data block type 0. Shrug.
|
||||
*/
|
||||
leadin_start = runtime;
|
||||
ret = add_cue(sheet, ctladr | 1, 0, 0, leadin_form, 0, leadin_start);
|
||||
if (ret <= 0)
|
||||
goto failed;
|
||||
runtime += 150;
|
||||
|
||||
d->toc_entries = ntr + 3;
|
||||
|
||||
@ -483,6 +582,20 @@ struct cue_sheet *burn_create_toc_entries(struct burn_write_opts *o,
|
||||
for (i = 0; i < ntr; i++) {
|
||||
type_to_form(tar[i]->mode, &ctladr, &form);
|
||||
|
||||
if (tar[i]->isrc.has_isrc) {
|
||||
ret = add_isrc_cue(sheet, ctladr, i + 1,
|
||||
&(tar[i]->isrc));
|
||||
if (ret <= 0)
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
ret = add_cue(sheet, ctladr | 1, 1, 0, form, 0,
|
||||
runtime);
|
||||
if (ret <= 0)
|
||||
goto failed;
|
||||
runtime += 150;
|
||||
}
|
||||
|
||||
/* ts A70121 : This seems to be thw wrong test. Correct would
|
||||
be to compare tar[]->mode or bit2 of ctladr.
|
||||
@ -705,9 +818,9 @@ static int burn_write_leadin_cdtext(struct burn_write_opts *o,
|
||||
{ret = 1; goto ex;}
|
||||
/* Try to create CD-TEXT from .cdtext_* of session and track */
|
||||
ret = burn_create_text_packs(o, s, 0);
|
||||
self_made_text_packs = 1;
|
||||
if (ret <= 0)
|
||||
goto ex;
|
||||
self_made_text_packs = 1;
|
||||
if (o->num_text_packs <= 0)
|
||||
{ret = 1; goto ex;}
|
||||
}
|
||||
@ -2673,7 +2786,6 @@ return crap. so we send the command, then ignore the result.
|
||||
if (o->write_type == BURN_WRITE_TAO) {
|
||||
nwa = 0; /* get_nwa() will be called in burn_track() */
|
||||
} else {
|
||||
|
||||
d->send_write_parameters(d, o);
|
||||
|
||||
ret = d->get_nwa(d, -1, &lba, &nwa);
|
||||
@ -2701,7 +2813,11 @@ return crap. so we send the command, then ignore the result.
|
||||
if (sheet == NULL)
|
||||
goto fail;
|
||||
|
||||
/* print_cue(sheet);*/
|
||||
#ifdef Libburn_write_with_function_print_cuE
|
||||
print_cue(sheet);
|
||||
/* goto fail_wo_sync; */
|
||||
#endif /* Libburn_write_with_function_print_cuE */
|
||||
|
||||
if (o->write_type == BURN_WRITE_SAO)
|
||||
d->send_cue_sheet(d, sheet);
|
||||
if (sheet->data != NULL)
|
||||
|
Loading…
Reference in New Issue
Block a user