diff --git a/cdrskin/cdrskin.1 b/cdrskin/cdrskin.1 index dafe279..03dfd24 100644 --- a/cdrskin/cdrskin.1 +++ b/cdrskin/cdrskin.1 @@ -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 "Jan 01, 2012" +.TH CDRSKIN 1 "Jan 03, 2012" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: @@ -508,8 +508,8 @@ To enable CD-TEXT from the cue sheet file, cdrskin option -text has to be present. .br cdrskin currently supports TRACK datatypes AUDIO and MODE1/2048 which may -not be mixed. It ignores commands POSTGAP and PREGAP. Only INDEX 01 -is interpreted yet. Data source may be of FILE type BINARY or MOTOROLA. +not be mixed. It ignores commands POSTGAP and PREGAP. +Data source may be of FILE type BINARY or MOTOROLA. .br Non-CDRWIN commands ARRANGER, COMPOSER, MESSAGE are supported. .br diff --git a/cdrskin/cdrskin_timestamp.h b/cdrskin/cdrskin_timestamp.h index 456fade..8fc6544 100644 --- a/cdrskin/cdrskin_timestamp.h +++ b/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2012.01.02.164110" +#define Cdrskin_timestamP "2012.01.03.194322" diff --git a/doc/cdtext.txt b/doc/cdtext.txt index b9c567f..516d753 100644 --- a/doc/cdtext.txt +++ b/doc/cdtext.txt @@ -632,7 +632,7 @@ CDRWIN cue sheet files: A CDRWIN cue sheet file defines the track data source (FILE), various text attributes (CATALOG, TITLE, PERFORMER, SONGWRITER, ISRC), track block types -(TRACK) and track start addresses (INDEX 01). +(TRACK), track start addresses (INDEX). The rules for CDRWIN cue sheet files are described at http://digitalx.org/cue-sheet/syntax/ There are three more text attributes mentioned in man cdrecord for defining @@ -647,7 +647,7 @@ CATALOG 1234567890123 FILE "cdtext.bin" BINARY TITLE "Joyful Nights" TRACK 01 AUDIO - FLAGS DCP 4CH PRE + FLAGS DCP TITLE "Song of Joy" PERFORMER "Felix and The Purrs" SONGWRITER "Friedrich Schiller" @@ -676,7 +676,6 @@ Commands POSTGAP, PREGAP are ignored. Only FILE types BINARY, MOTOROLA are allowed. Only TRACK datatypes AUDIO, MODE1/2048 are allowed. They may not be mixed in the same session. -INDEX numbers 00, 02 to 99 are ignored. On the other hand, ARRANGER, COMPOSER, MESSAGE are supported unconditionally. diff --git a/libburn/libburn.h b/libburn/libburn.h index 0ebfcf8..4ca4b97 100644 --- a/libburn/libburn.h +++ b/libburn/libburn.h @@ -1864,13 +1864,12 @@ int burn_disc_remove_session(struct burn_disc *d, struct burn_session *s); CD-TEXT according to the content of the file. For a description of CDRWIN file format see http://digitalx.org/cue-sheet/syntax/ ->>> fully supported commands: CATALOG CDTEXTFILE FLAGS ISRC PERFORMER REM +>>> fully supported commands: CATALOG CDTEXTFILE FLAGS INDEX ISRC PERFORMER REM >>> SONGWRITER TITLE ->>> partly supported commands: FILE INDEX TRACK +>>> partly supported commands: FILE TRACK >>> supported FILE types: BINARY MOTOROLA >>> supported TRACK datatypes: AUDIO MODE1/2048 >>> ignored commands: POSTGAP PREGAP ->>> ignored INDEX numbers: 00, 02 to 99 >>> not allowed: mixing of ADUIO and MODE1/2048 >>> not allowed: unsupported FILE types >>> not allowed: unsupported TRACK datatypes @@ -2373,6 +2372,39 @@ int burn_track_set_isrc_string(struct burn_track *t, char isrc[13], int flag); void burn_track_clear_isrc(struct burn_track *t); +/* ts B20103 */ +/** Define an index start address within a track. The index numbers inside a + track have to form sequence starting at 0 or 1 with no gaps up to the + highest number used. They affect only writing of CD SAO sessions. + The first index start address of a track must be 0. + Blocks between index 0 and index 1 are considered to be located before the + track start as of the table-of-content. + @param t The track to be manipulated + @param index_number A number between 0 and 99 + @param relative_lba The start address relative to the start of the + burn_source of the track. It will get mapped to the + appropriate absolute block address. + @param flag Bitfield for control purposes. Unused yet. Submit 0. + @return > 0 indicates success, <= 0 means failure + @since 1.2.0 +*/ +int burn_track_set_index(struct burn_track *t, int index_number, + unsigned int relative_lba, int flag); + +/* ts B20103 */ +/** Remove all index start addresses and reset to the default indexing of + CD SAO sessions. This means index 0 of track 1 reaches from LBA -150 + to LBA -1. Index 1 of track 1 reaches from LBA 0 to track end. Index 1 + of track 2 follows immediately. The same happens for all further tracks + after the end of their predecessor. + @param t The track to be manipulated + @param flag Bitfield for control purposes. Unused yet. Submit 0. + @return i > 0 indicates success, <= 0 means failure + @since 1.2.0 +*/ +int burn_track_clear_indice(struct burn_track *t, int flag); + + /** Hide the first track in the "pre gap" of the disc @param s session to change @param onoff 1 to enable hiding, 0 to disable diff --git a/libburn/libburn.ver b/libburn/libburn.ver index a486569..77821ae 100644 --- a/libburn/libburn.ver +++ b/libburn/libburn.ver @@ -139,6 +139,7 @@ burn_structure_print_disc; burn_structure_print_session; burn_structure_print_track; burn_text_to_sev; +burn_track_clear_indice; burn_track_clear_isrc; burn_track_create; burn_track_define_data; @@ -153,6 +154,7 @@ burn_track_set_byte_swap; burn_track_set_cdxa_conv; burn_track_set_cdtext; burn_track_set_default_size; +burn_track_set_index; burn_track_set_isrc; burn_track_set_isrc_string; burn_track_set_size; diff --git a/libburn/libdax_msgs.h b/libburn/libdax_msgs.h index f0627c6..590c394 100644 --- a/libburn/libdax_msgs.h +++ b/libburn/libdax_msgs.h @@ -592,6 +592,7 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff 0x00020197 (FAILURE,HIGH) = Unsupported text input file feature 0x00020198 (FAILURE,HIGH) = CD-TEXT pack file readability problem 0x00020199 (SORRY,HIGH) = Text input file reading aborted + 0x0002019a (SORRY,HIGH) = Bad track index number libdax_audioxtr: diff --git a/libburn/structure.c b/libburn/structure.c index 2bd9b14..315a5a2 100644 --- a/libburn/structure.c +++ b/libburn/structure.c @@ -168,6 +168,8 @@ struct burn_track *burn_track_create(void) return NULL; t->refcnt = 1; t->indices = 0; + for (i = 0; i < 100; i++) + t->index[i] = 0x7fffffff; t->offset = 0; t->offsetcount = 0; t->tail = 0; @@ -441,6 +443,37 @@ void burn_track_clear_isrc(struct burn_track *t) t->isrc.has_isrc = 0; } +/* ts B20103 API */ +int burn_track_set_index(struct burn_track *t, int index_number, + unsigned int relative_lba, int flag) +{ + if (index_number < 0 || index_number > 99) { + libdax_msgs_submit(libdax_messenger, -1, 0x0002019a, + LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, + "Bad track index number", 0, 0); + return 0; + } + + /* >>> if track size known : check index */; + + t->index[index_number] = relative_lba; + if (index_number >= t->indices) + t->indices = index_number + 1; + return 1; +} + +/* ts B20103 API */ +int burn_track_clear_indice(struct burn_track *t, int flag) +{ + int i; + + for (i = 0; i < 100; i++) + t->index[i] = 0x7fffffff; + t->indices = 0; + return 1; +} + + int burn_track_get_sectors(struct burn_track *t) { /* ts A70125 : was int */ @@ -1024,7 +1057,7 @@ struct burn_cue_file_cursor { int prev_block_size; struct burn_track *track; int track_no; - int track_has_index; + int track_current_index; int track_has_source; int block_size; int block_size_locked; @@ -1055,7 +1088,7 @@ static int cue_crs_new(struct burn_cue_file_cursor **reply, int flag) crs->prev_block_size = 0; crs->track = NULL; crs->track_no = 0; - crs->track_has_index = 0; + crs->track_current_index = -1; crs->track_has_source = 0; crs->block_size = 0; crs->block_size_locked = 0; @@ -1173,6 +1206,13 @@ static int cue_attach_track(struct burn_session *session, "In cue sheet file: TRACK without INDEX 01", 0, 0); return 0; } + if (crs->track_current_index < 1) { + libdax_msgs_submit(libdax_messenger, -1, 0x00020192, + LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH, + "No INDEX 01 defined for last TRACK in cue sheet file", + 0, 0); + return 0; + } if (crs->track_no > 1 && session->tracks == 0) { /* >>> ??? implement ? */; @@ -1191,7 +1231,8 @@ static int cue_attach_track(struct burn_session *session, crs->prev_file_ba = crs->current_file_ba; crs->prev_block_size = crs->block_size; crs->track = NULL; - crs->track_has_index = crs->track_has_source = 0; + crs->track_current_index = -1; + crs->track_has_source = 0; crs->current_file_ba = -1; if (!crs->block_size_locked) crs->block_size = 0; @@ -1487,33 +1528,42 @@ no_time_point:; goto ex; file_ba = ((minute * 60) + second ) * 75 + frame; - if (file_ba <= crs->prev_file_ba) { + if (file_ba < crs->prev_file_ba) { overlapping_ba:; libdax_msgs_submit(libdax_messenger, -1, 0x00020192, LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH, - "Overlapping INDEX addresses in cue sheet file", + "Backward INDEX address in cue sheet file", 0, 0); ret = 0; goto ex; } - if (crs->prev_track != NULL && !crs->track_has_index) { + if (crs->prev_track != NULL && crs->track_current_index < 0) { size = (file_ba - crs->prev_file_ba) * crs->prev_block_size; if (size <= 0) goto overlapping_ba; burn_track_set_size(crs->prev_track, size); } - crs->track_has_index = 1; + if (crs->track_current_index + 1 != index_no && + !(crs->track_current_index < 0 && index_no <= 1)) { + libdax_msgs_submit(libdax_messenger, -1, 0x00020192, + LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH, + "Backward INDEX number in cue sheet file", + 0, 0); + ret = 0; goto ex; + } + crs->track_current_index = index_no; - if (index_no != 1) { - - /* >>> what to do with index != 1 ? */; - /* >>> INDEX 00 defines start of a track pregap - Pregap and postgap still has to be properly - mapped onto track - */; + if (crs->current_file_ba < 0) + crs->current_file_ba = file_ba; + /* Set index address relative to track source start */ + ret = burn_track_set_index(crs->track, index_no, + file_ba - crs->current_file_ba, 0); + if (ret <= 0) + goto ex; + if (crs->track_has_source) { ret = 1; goto ex; } @@ -1557,7 +1607,6 @@ overlapping_ba:; if (crs->offst_source != NULL) burn_source_free(crs->offst_source); crs->offst_source = src; - crs->current_file_ba = file_ba; crs->track_has_source = 1; } else if (strcmp(cmd, "ISRC") == 0) { @@ -1783,7 +1832,7 @@ cannot_open:; /* Attach last track to session */ if (crs->track != NULL) { /* Set track size up to end of file */ - if (crs->current_file_ba < 0) { + if (crs->current_file_ba < 0 || crs->track_current_index < 1) { libdax_msgs_submit(libdax_messenger, -1, 0x00020192, LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH, "No INDEX 01 defined for last TRACK in cue sheet file", @@ -1794,7 +1843,7 @@ cannot_open:; crs->source_size) { libdax_msgs_submit(libdax_messenger, -1, 0x00020194, LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH, - "INDEX 01 time point exceeds size of FILE from cue sheet file", + "TRACK start time point exceeds size of FILE from cue sheet file", 0, 0); ret = 0; goto ex; } diff --git a/libburn/structure.h b/libburn/structure.h index b5dee22..d3ad151 100644 --- a/libburn/structure.h +++ b/libburn/structure.h @@ -37,8 +37,11 @@ struct burn_track int refcnt; struct burn_toc_entry *entry; unsigned char indices; - /* lba address of the index */ - unsigned int index[99]; + /* lba address of the index. CD only. 0x7fffffff means undefined index. + To be programmed relative to track source start before burning, + but to hold absolute addresses after burning or reading. + */ + int index[100]; /** number of 0 bytes to write before data */ int offset; /** how much offset has been used */ diff --git a/libburn/write.c b/libburn/write.c index 5519c41..2920558 100644 --- a/libburn/write.c +++ b/libburn/write.c @@ -301,6 +301,7 @@ int burn_write_close_session(struct burn_write_opts *o) This is useful only when changes about CD SAO get tested. # define Libburn_write_with_function_print_cuE yes */ +#define Libburn_write_with_function_print_cuE #ifdef Libburn_write_with_function_print_cuE @@ -450,7 +451,7 @@ struct cue_sheet *burn_create_toc_entries(struct burn_write_opts *o, int nwa) { int i, m, s, f, form, pform, runtime = -150, ret, track_length; - int leadin_form, leadin_start; + int leadin_form, leadin_start, pregap; unsigned char ctladr, scms; struct burn_drive *d; struct burn_toc_entry *e; @@ -459,6 +460,13 @@ struct cue_sheet *burn_create_toc_entries(struct burn_write_opts *o, int ntr = session->tracks; int rem = 0; +#define Libburn_track_multi_indeX yes + +#ifdef Libburn_track_multi_indeX + int j; +#endif + + d = o->drive; @@ -571,12 +579,14 @@ struct cue_sheet *burn_create_toc_entries(struct burn_write_opts *o, e[2].control = e[1].control; e[2].adr = 1; - /* ts A70121 : The pause before the first track is not a Pre-gap. + /* ts A70121 : The pause before the first track is not really Pre-gap. To count it as part 2 of a Pre-gap is a dirty hack. It also seems to have caused confusion in dealing with part 1 of an eventual real Pre-gap. mmc5r03c.pdf 6.33.3.2, 6.33.3.18 . + ts B20103 : It is not really Pre-gap with audio tracks. */ tar[0]->pregap2 = 1; + pregap = 150; pform = form; for (i = 0; i < ntr; i++) { @@ -593,20 +603,64 @@ struct cue_sheet *burn_create_toc_entries(struct burn_write_opts *o, goto failed; } + +#ifdef Libburn_track_multi_indeX + + for(j = 0; j < tar[i]->indices || j < 2; j++) { + if(tar[i]->index[j] == 0x7fffffff) { + if (j > 1) + break; + if (j == 0 && i > 0) + continue; + /* force existence of mandatory index */ + tar[i]->index[j] = 0; + } else if (j == 0) { + tar[i]->index[j] = 0; + } else if (j == 1 && tar[i]->index[0] == 0x7fffffff) { + tar[i]->index[j] = 0; + } + + if (j == 1) { + tar[i]->entry = &e[3 + i]; + e[3 + i].point = i + 1; + burn_lba_to_msf(runtime, &m, &s, &f); + e[3 + i].pmin = m; + e[3 + i].psec = s; + e[3 + i].pframe = f; + e[3 + i].adr = 1; + e[3 + i].control = type_to_ctrl(tar[i]->mode); + } + + /* >>> ??? else if j == 0 && mode change to -data : + Extended pregap */; + + /* >>> ??? user defined pregap ? */; + + /* >>> check index with track size */; + + tar[i]->index[j] += runtime; + ret = add_cue(sheet, ctladr | 1, i + 1, j, form, scms, + tar[i]->index[j]); + if (ret <= 0) + goto failed; + runtime += pregap; + pregap = 0; + } + +#else /* Libburn_track_multi_indeX */ + if (i == 0) { ret = add_cue(sheet, ctladr | 1, 1, 0, form, 0, runtime); if (ret <= 0) goto failed; runtime += 150; - } + } else if (pform != form) { /* ts A70121 : This seems to be thw wrong test. Correct would be to compare tar[]->mode or bit2 of ctladr. */ - if (pform != form) { - ret = add_cue(sheet, ctladr | 1, i + 1, 0, form, scms, runtime); if (ret <= 0) @@ -653,6 +707,9 @@ struct cue_sheet *burn_create_toc_entries(struct burn_write_opts *o, if (ret <= 0) goto failed; +#endif /* ! Libburn_track_multi_indeX */ + + /* ts A70125 : Still not understanding the sense behind linking tracks, i decided to at least enforce the MMC specs' minimum