From 620871c91d6b47526e374ef54c2d99bc3e430388 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Mon, 12 Dec 2011 09:26:41 +0000 Subject: [PATCH] New API calls for composing CD-TEXT --- cdrskin/cdrskin_timestamp.h | 2 +- libburn/init.c | 2 +- libburn/libburn.h | 282 ++++++++++++++++++--- libburn/libburn.ver | 9 + libburn/libdax_msgs.h | 5 + libburn/options.c | 31 ++- libburn/options.h | 8 + libburn/structure.c | 291 ++++++++++++++++++++- libburn/structure.h | 31 +++ libburn/write.c | 493 +++++++++++++++++++++++++++++++++++- libburn/write.h | 7 + 11 files changed, 1109 insertions(+), 52 deletions(-) diff --git a/cdrskin/cdrskin_timestamp.h b/cdrskin/cdrskin_timestamp.h index 0d0917c..f7ccdbb 100644 --- a/cdrskin/cdrskin_timestamp.h +++ b/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2011.12.09.092152" +#define Cdrskin_timestamP "2011.12.12.092602" diff --git a/libburn/init.c b/libburn/init.c index 3df3f2b..8a4c2c6 100644 --- a/libburn/init.c +++ b/libburn/init.c @@ -589,7 +589,7 @@ void *burn_alloc_mem(size_t size, size_t count, int flag) { void *pt; - pt = calloc(size, count); + pt = calloc(count, size); if(pt == NULL) libdax_msgs_submit(libdax_messenger, -1, 0x00000003, LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, diff --git a/libburn/libburn.h b/libburn/libburn.h index cb9ff50..cac7e2f 100644 --- a/libburn/libburn.h +++ b/libburn/libburn.h @@ -1291,45 +1291,17 @@ int burn_disc_get_cd_info(struct burn_drive *d, char disc_type[80], int *valid); /* ts B11201 */ -/** Read CD-TEXT packs from the Lead-in of an audio CD. +/** Read the array of CD-TEXT packs from the Lead-in of an audio CD. Each pack consists of 18 bytes, of which 4 are header. 12 bytes are pieces of 0-terminated texts or binary data. 2 bytes hold a CRC. - See also MMC-3 Annex J. - The first byte of each pack tells the pack type (text meaning): - 0x80 = Title - 0x81 = Names of performers - 0x82 = Songwriters - 0x83 = Composers, - 0x84 = Arrangers - 0x85 = Messages - 0x86 = text-and-binary: Disc Identification - 0x87 = text-and-binary: Genre Identification - 0x88 = binary: Table of Content information - 0x89 = binary: Second Table of Content information - 0x8e = UPC/EAN code of the album and ISRC code of each track - 0x8f = binary: Size Information of the Block - The second byte tells the track number to which the first text piece in - a pack is associated. Number 0 means the whole album. Higher numbers are - valid for types 0x80 to 0x85, and 0x8e. With these types, there should be - one text for the disc and one for each track. - The third byte is a sequential counter. - The fourth byte is the Block Number and Character Position Indicator. - It consists of three bit fields: - bit7 = Double Bytes Character Code (0= single byte characters) - bit4-6 = Block Number (groups text packs in language blocks) - bit0-3 = Character position. Either the number of characters which - the current text inherited from the previous pack, or - 15 if the current text started before the previous pack. - The two CRC bytes are optional. Polynomial is x^16 + x^12 + x^5 + 1. - "All bits shall be inverted." - + For a description of the format of the array, see file doc/cdtext.txt. @param d The drive to query. @param text_packs Will point to an allocated memory buffer with CD-TEXT. It will only contain text packs, and not be prepended by the TOC header of four bytes, which gets stored with - file cdtext.dat by cdrecord -vv -toc. The first two of + file cdtext.dat by cdrecord -vv -toc. (The first two of these bytes are supposed to hold the number of CD-TEXT - bytes + 2. The other two bytes are supposed to be 0. + bytes + 2. The other two bytes are supposed to be 0.) Dispose this buffer by free(), when no longer needed. @param num_packs Will tell the number of text packs, i.e. the number of bytes in text_packs divided by 18. @@ -1903,6 +1875,172 @@ int burn_session_add_track(struct burn_session *s, struct burn_track *t, int burn_session_remove_track(struct burn_session *s, struct burn_track *t); +/* ts B11206 */ +/** Set the Character Codes, the Copyright bytes, and the Language Codes + for CD-TEXT blocks 0 to 7. They will be used in the block summaries + of text packs which get generated from text or binary data submitted + by burn_session_set_cdtext() and burn_track_set_cdtext(). + Character Code value can be + 0x00 = ISO-8859-1 + 0x01 = 7 bit ASCII + 0x80 = MS-JIS (japanesei Kanji, double byte characters) + Copyright byte value can be + 0x00 = not copyrighted + 0x03 = copyrighted + Language Code value can be + 0x00 = Unknown 0x04 = Croatian 0x08 = German 0x09 = English + 0x0a = Spanish 0x0f = French 0x15 = Italian 0x27 = Finnish + 0x29 = Turkish 0x69 = Japanese + or other latin alphabet codes from EBU Tech 3264, appendix 3, like + 0x06 = Czech 0x07 = Danish 0x11 = Irish 0x17 = Latin + 0x1b = Hungarian 0x1d = Dutch 0x20 = Polish 0x21 = Portuguese + as well as such where character representation is unclear + 0x56 = Russian 0x6b = Hindi 0x6c = Hebrew 0x70 = Greek + 0x75 = Chinese 0x77 = Bulgarian 0x7e = Arabic 0x7f = Amharic + Default is 0x09 = English for block 0 and 0x00 = Unknown for block 1 to 7. + Copyright and Character Code are 0x00 for all blocks by default. + For a detailed description of these parameters see file + doc/cdtext.txt, "Format of a CD-TEXT packs array", "Pack type 0x8f". + + Parameter value -1 leaves the current setting of the session parameter + unchanged. + @param s Session where to change settings + @param char_codes Character Codes for block 0 to 7 + @param copyrights Copyright bytes for block 0 to 7 + @param languages Language Codes for block 0 to 7 + @param flag Bitfiled for control purposes. Unused yet. Submit 0. + @return <=0 failure, > 0 success + @since 1.2.0 +*/ +int burn_session_set_cdtext_par(struct burn_session *s, + int char_codes[8], int copyrights[8], + int languages[8], int flag); + +/* ts B11206 */ +/** Obtain the current settings as of burn_session_set_cdtext_par() resp. + by default. + @param s Session which to inquire + @param char_codes Will return Character Codes for block 0 to 7 + @param copyrights Will return Copyright bytes for block 0 to 7 + @param languages Will return Language Codes for block 0 to 7 + @param flag Bitfiled for control purposes. Unused yet. Submit 0. + @return <=0 failure, reply invalid, > 0 success, reply valid + @since 1.2.0 +*/ +int burn_session_get_cdtext_par(struct burn_session *s, + int char_codes[8], int copyrights[8], + int block_languages[8], int flag); + + +/* ts B11206 */ +/** Attach text or binary data as CD-TEXT attributes to a session. + They can be used to generate CD-TEXT packs by burn_cdtext_from_session() + or to write CD-TEXT packs into the lead-in of a CD SAO session. + The latter happens only if no array of CD-TEXT packs is attached to + the write options by burn_write_opts_set_leadin_text(). + For details of the CD-TEXT format and of the payload content, see file + doc/cdtext.txt . + @param s Session where to attach CD-TEXT attribute + @param block Number of the language block in which the attribute + shall appear. Possible values: 0 to 7. + @param pack_type Pack type number. 0x80 to 0x8e. Used if pack_type_name + is NULL or empty text. Else submit 0 and a name. + Pack type 0x8f is generated automatically and may not + be set by applications. + @param pack_type_name The pack type by name. Defined names are: + 0x80 = "TITLE" 0x81 = "PERFORMER" + 0x82 = "SONGWRITER" 0x83 = "COMPOSER" + 0x84 = "ARRANGER" 0x85 = "MESSAGE" + 0x86 = "DISCID" 0x87 = "GENRE" + 0x88 = "TOC" 0x89 = "TOC2" + 0x8d = "CLOSED" 0x8e = "UPC_ISRC" + Names are recognized uppercase and lowercase. + @param payload Text or binary bytes. The data will be copied to + session-internal memory. + Pack types 0x80 to 0x85 and 0x8e contain 0-terminated + cleartext. If double byte characters are used, then + two 0-bytes terminate the cleartext. + Pack type 0x86 is 0-terminated ASCII cleartext. + Pack type 0x87 consists of two byte big-endian + Genre code, and 0-terminated genre cleartext. + Pack type 0x88 mirrors the session table-of-content. + Pack type 0x89 is not understood yet. + Pack types 0x8a to 0x8c are reserved. + Pack type 0x8e contains cleartext which is not to be + shown by commercial audio CD players. + @pram length Number of bytes in payload. Including terminating + 0-bytes. + @param flag Bitfield for control purposes. + bit0= payload contains double byte characters + (with character code 0x80 MS-JIS japanese Kanji) + @return > 0 indicates success , <= 0 is failure + @since 1.2.0 +*/ +int burn_session_set_cdtext(struct burn_session *s, int block, + int pack_type, char *pack_type_name, + unsigned char *payload, int length, int flag); + +/* ts B11206 */ +/** Obtain a CD-TEXT attribute that was set by burn_session_set_cdtext() + @param s Session to inquire + @param block Number of the language block to inquire. + @param pack_type Pack type number to inquire. Used if pack_type_name + is NULL or empty text. Else submit 0 and a name. + Pack type 0x8f is generated automatically and may not + be inquire in advance. Use burn_cdtext_from_session() + to generate all packs including type 0x8f packs. + @param pack_type_name The pack type by name. + See above burn_session_set_cdtext(). + @param payload Will return a pointer to text or binary bytes. + Not a copy of data. Do not free() this address. + @pram length Will return the number of bytes pointed to by payload. + Including terminating 0-bytes. + @param flag Bitfield for control purposes. Unused yet. Submit 0. + @return 1 single byte char, 2 double byte char, <=0 error + @since 1.2.0 +*/ +int burn_session_get_cdtext(struct burn_session *s, int block, + int pack_type, char *pack_type_name, + unsigned char **payload, int *length, int flag); + +/* ts B11210 */ +/** Produce an array of CD-TEXT packs that could be submitted to + burn_write_opts_set_leadin_text() or stored as *.cdt file. + For a description of the format of the array, see file doc/cdtext.txt. + The input data stem from burn_session_set_cdtext_par(), + burn_session_set_cdtext(), and burn_track_set_cdtext(). + @param s Session from which to produce CD-TEXT packs. + @param text_packs Will return the buffer with the CD-TEXT packs. + Dispose by free() when no longer needed. + @param num_packs Will return the number of 18 byte text packs. + @param flag Bitfield for control purposes. + bit0= do not produce CD-TEXT packs, but return number + of packs. This happens also if + (text_packs == NULL || num_packs == NULL). + @return Without flag bit0: > 0 is success, <= 0 failure + With flag bit0: > 0 is number of packs, + 0 means no packs will be generated, + < 0 means failure + @since 1.2.0 +*/ +int burn_cdtext_from_session(struct burn_session *s, + unsigned char **text_packs, int *num_packs, + int flag); + + +/* ts B11206 */ +/** Remove all CD-TEXT attributes of the given block from the session. + They were attached by burn_session_set_cdtext(). + @param s Session where to remove the CD-TEXT attribute + @param block Number of the language block in which the attribute + shall appear. Possible values: 0 to 7. + -1 causes text packs of all blocks to be removed. + @return > 0 is success, <= 0 failure + @since 1.2.0 +*/ +int burn_session_dispose_cdtext(struct burn_session *s, int block); + + /** Define the data in a track @param t the track to define @param offset The lib will write this many 0s before start of data @@ -1926,6 +2064,72 @@ void burn_track_define_data(struct burn_track *t, int offset, int tail, int burn_track_set_byte_swap(struct burn_track *t, int swap_source_bytes); +/* ts B11206 */ +/** Attach text or binary data as CD-TEXT attributes to a track. + The payload will be used to generate CD-TEXT packs by + burn_cdtext_from_session() or to write CD-TEXT packs into the lead-in + of a CD SAO session. This happens if the CD-TEXT attribute of the session + gets generated, which has the same block number and pack type. In this + case, each track should have such a CD-TEXT attribute, too. + See burn_session_set_cdtext(). + @param t Track where to attach CD-TEXT attribute. + @param block Number of the language block in which the attribute + shall appear. Possible values: 0 to 7. + @param pack_type Pack type number. 0x80 to 0x85 or 0x8e. Used if + pack_type_name is NULL or empty text. Else submit 0 + and a name. + @param pack_type_name The pack type by name. Applicable names are: + 0x80 = "TITLE" 0x81 = "PERFORMER" + 0x82 = "SONGWRITER" 0x83 = "COMPOSER" + 0x84 = "ARRANGER" 0x85 = "MESSAGE" + 0x8e = "UPC_ISRC" + @param payload 0-terminated cleartext. If double byte characters + are used, then two 0-bytes terminate the cleartext. + @pram length Number of bytes in payload. Including terminating + 0-bytes. + @param flag Bitfield for control purposes. + bit0= payload contains double byte characters + (with character code 0x80 MS-JIS japanese Kanji) + @return > 0 indicates success , <= 0 is failure + @since 1.2.0 +*/ +int burn_track_set_cdtext(struct burn_track *t, int block, + int pack_type, char *pack_type_name, + unsigned char *payload, int length, int flag); + +/* ts B11206 */ +/** Obtain a CD-TEXT attribute that was set by burn_track_set_cdtext(). + @param t Track to inquire + @param block Number of the language block to inquire. + @param pack_type Pack type number to inquire. Used if pack_type_name + is NULL or empty text. Else submit 0 and a name. + @param pack_type_name The pack type by name. + See above burn_track_set_cdtext(). + @param payload Will return a pointer to text bytes. + Not a copy of data. Do not free() this address. + @pram length Will return the number of bytes pointed to by payload. + Including terminating 0-bytes. + @param flag Bitfield for control purposes. Unused yet. Submit 0. + @return 1=single byte char , 2= double byte char , <=0 error + @since 1.2.0 +*/ +int burn_track_get_cdtext(struct burn_track *t, int block, + int pack_type, char *pack_type_name, + unsigned char **payload, int *length, int flag); + +/* ts B11206 */ +/** Remove all CD-TEXT attributes of the given block from the track. + They were attached by burn_track_set_cdtext(). + @param t Track where to remove the CD-TEXT attribute. + @param block Number of the language block in which the attribute + shall appear. Possible values: 0 to 7. + -1 causes text packs of all blocks to be removed. + @return > 0 is success, <= 0 failure + @since 1.2.0 +*/ +int burn_track_dispose_cdtext(struct burn_track *t, int block); + + /* ts A90910 */ /** Activates CD XA compatibility modes. libburn currently writes data only in CD mode 1. Some programs insist in @@ -2437,12 +2641,19 @@ void burn_write_opts_set_multi(struct burn_write_opts *opts, int multi); of a SAO write run on CD. @param opts The option object to be manipulated @param text_packs Array of bytes which form CD-TEXT packs of 18 bytes - each. See burn_disc_get_leadin_text() for a description - of the text pack format. + each. For a description of the format of the array, + see file doc/cdtext.txt. No header of 4 bytes must be prepended which would tell the number of pack bytes + 2. + This parameter may be NULL if the currently attached + array of packs shall be removed. @param num_packs The number of 18 byte packs in text_packs. - @param flag Bitfield for control purposes. Unused yet. Submit 0. + This parameter may be 0 if the currently attached + array of packs shall be removed. + @param flag Bitfield for control purposes. + bit0= do not verify checksums + bit1= repair mismatching checksums + bit2= repair checksums if they are 00 00 with each pack @return 1 on success, <= 0 on failure @since 1.2.0 */ @@ -2450,6 +2661,7 @@ int burn_write_opts_set_leadin_text(struct burn_write_opts *opts, unsigned char *text_packs, int num_packs, int flag); + /* ts A61222 */ /** Sets a start address for writing to media and write modes which allow to choose this address at all (for now: DVD+RW, DVD-RAM, formatted DVD-RW). diff --git a/libburn/libburn.ver b/libburn/libburn.ver index d697723..3ea8ac8 100644 --- a/libburn/libburn.ver +++ b/libburn/libburn.ver @@ -4,6 +4,7 @@ burn_abort; burn_abort_pacifier; burn_allow_drive_role_4; burn_allow_untested_profiles; +burn_cdtext_from_session; burn_disc_add_session; burn_disc_available_space; burn_disc_close_damaged; @@ -113,13 +114,18 @@ burn_scsi_transport_id; burn_sectors_to_msf; burn_session_add_track; burn_session_create; +burn_session_dispose_cdtext; burn_session_free; +burn_session_get_cdtext; +burn_session_get_cdtext_par; burn_session_get_hidefirst; burn_session_get_leadout_entry; burn_session_get_sectors; burn_session_get_tracks; burn_session_hide_first_track; burn_session_remove_track; +burn_session_set_cdtext; +burn_session_set_cdtext_par; burn_set_messenger; burn_set_scsi_logging; burn_set_signal_handling; @@ -133,13 +139,16 @@ burn_text_to_sev; burn_track_clear_isrc; burn_track_create; burn_track_define_data; +burn_track_dispose_cdtext; burn_track_free; +burn_track_get_cdtext; burn_track_get_counters; burn_track_get_entry; burn_track_get_mode; burn_track_get_sectors; burn_track_set_byte_swap; burn_track_set_cdxa_conv; +burn_track_set_cdtext; burn_track_set_default_size; burn_track_set_isrc; burn_track_set_size; diff --git a/libburn/libdax_msgs.h b/libburn/libdax_msgs.h index 9e04a43..cbe392c 100644 --- a/libburn/libdax_msgs.h +++ b/libburn/libdax_msgs.h @@ -578,6 +578,11 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff 0x00020189 (FATAL,HIGH) = Drive is already grabbed by libburn 0x0002018a (SORRY,HIGH) = Timeout exceeded. Retry cancled. 0x0002018b (FAILURE,HIGH) = Too many CD-TEXT packs + 0x0002018c (FAILURE,HIGH) = CD-TEXT pack type out of range + 0x0002018d (FAILURE,HIGH) = CD-TEXT block number out of range + 0x0002018e (FAILURE,HIGH) = Too many CD-TEXT packs in block + 0x0002018f (FAILURE,HIGH) = CD-TEXT pack CRC mismatch + 0x00020190 (WARNING,HIGH) = CD-TEXT pack CRC mismatch had to be corrected libdax_audioxtr: 0x00020200 (SORRY,HIGH) = Cannot open audio source file diff --git a/libburn/options.c b/libburn/options.c index bbd307b..61f832f 100644 --- a/libburn/options.c +++ b/libburn/options.c @@ -13,6 +13,7 @@ #include "drive.h" #include "transport.h" #include "init.h" +#include "write.h" /* ts A61007 */ /* #include */ @@ -54,6 +55,7 @@ struct burn_write_opts *burn_write_opts_new(struct burn_drive *drive) opts->stdio_fsync_size = Libburn_stdio_fsync_limiT; opts->text_packs = NULL; opts->num_text_packs = 0; + opts->no_text_pack_crc_check = 0; opts->has_mediacatalog = 0; opts->format = BURN_CDROM; opts->multi = 0; @@ -196,6 +198,10 @@ void burn_write_opts_set_multi(struct burn_write_opts *opts, int multi) /* ts B11204 */ +/* @param flag bit0=do not verify checksums + bit1= repair mismatching checksums + bit2= repair checksums if they are 00 00 with each pack +*/ int burn_write_opts_set_leadin_text(struct burn_write_opts *opts, unsigned char *text_packs, int num_packs, int flag) @@ -203,12 +209,11 @@ int burn_write_opts_set_leadin_text(struct burn_write_opts *opts, int ret; unsigned char *pack_buffer = NULL; - if (num_packs > 3640) { - /* READ TOC/PMA/ATIP can at most return 3640.7 packs */ + if (num_packs > Libburn_leadin_cdtext_packs_maX ) { libdax_msgs_submit(libdax_messenger, opts->drive->global_index, 0x0002018b, LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH, - "Too many CD-TEXT packs (> 3640)", 0, 0); + "Too many CD-TEXT packs", 0, 0); ret= 0; goto ex; } @@ -219,6 +224,26 @@ int burn_write_opts_set_leadin_text(struct burn_write_opts *opts, free(opts->text_packs); opts->text_packs = NULL; } + + if (flag & 1) { + opts->no_text_pack_crc_check = 1; + } else { + opts->no_text_pack_crc_check = 0; + ret = burn_cdtext_crc_mismatches(text_packs, num_packs, + (flag >> 1) & 3); + if (ret > 0) { + libdax_msgs_submit(libdax_messenger, -1, 0x0002018f, + LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH, + "CD-TEXT pack CRC mismatch", 0, 0); + ret = 0; goto ex; + } else if (ret < 0) { + libdax_msgs_submit(libdax_messenger, -1, 0x00020190, + LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH, + "CD-TEXT pack CRC mismatch had to be corrected", + 0, 0); + } + } + if (num_packs > 0) { memcpy(pack_buffer, text_packs, num_packs * 18); opts->text_packs = pack_buffer; diff --git a/libburn/options.h b/libburn/options.h index 34d2fef..a8f1f53 100644 --- a/libburn/options.h +++ b/libburn/options.h @@ -72,6 +72,7 @@ struct burn_write_opts /* ts B11203 : CD-TEXT */ unsigned char *text_packs; int num_text_packs; + int no_text_pack_crc_check; /** A disc can have a media catalog number */ int has_mediacatalog; @@ -87,6 +88,13 @@ struct burn_write_opts */ #define Libburn_stdio_fsync_limiT 8192 +/* Maximum number of Lead-in text packs. + READ TOC/PMA/ATIP can at most return 3640.7 packs. + The sequence counters of the packs have 8 bits. There are 8 blocks at most. + Thus max 2048 packs. + */ +#define Libburn_leadin_cdtext_packs_maX 2048 + /** Options for disc reading operations. This should be created with burn_read_opts_new() and freed with burn_read_opts_free(). */ diff --git a/libburn/structure.c b/libburn/structure.c index 55b014f..07dc427 100644 --- a/libburn/structure.c +++ b/libburn/structure.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "libburn.h" #include "structure.h" #include "write.h" @@ -75,6 +76,8 @@ void burn_disc_free(struct burn_disc *d) struct burn_session *burn_session_create(void) { struct burn_session *s; + int i; + s = calloc(1, sizeof(struct burn_session)); if (s == NULL) /* ts A70825 */ return NULL; @@ -82,6 +85,13 @@ struct burn_session *burn_session_create(void) s->tracks = 0; s->track = NULL; s->hidefirst = 0; + for (i = 0; i < 8; i++) { + s->cdtext[i] = NULL; + s->cdtext_language[i] = 0x00; /* Unknown */ + s->cdtext_char_code[i] = 0x00; /* ISO-8859-1 */ + s->cdtext_copyright[i] = 0x00; + } + s->cdtext_language[0] = 0x09; /* Single-block default is English */ return s; } @@ -92,13 +102,15 @@ void burn_session_hide_first_track(struct burn_session *s, int onoff) void burn_session_free(struct burn_session *s) { + int i; + s->refcnt--; if (s->refcnt == 0) { /* dec refs on all elements */ - int i; - for (i = 0; i < s->tracks; i++) burn_track_free(s->track[i]); + for (i = 0; i < 8; i++) + burn_cdtext_free(&(s->cdtext[i])); free(s->track); free(s); } @@ -141,6 +153,8 @@ int burn_disc_remove_session(struct burn_disc *d, struct burn_session *s) struct burn_track *burn_track_create(void) { struct burn_track *t; + int i; + t = calloc(1, sizeof(struct burn_track)); if (t == NULL) /* ts A70825 */ return NULL; @@ -180,16 +194,25 @@ struct burn_track *burn_track_create(void) /* ts A61024 */ t->swap_source_bytes = 0; + + /* ts B11206 */ + for (i = 0; i < 8; i++) + t->cdtext[i] = NULL; + return t; } void burn_track_free(struct burn_track *t) { + int i; + t->refcnt--; if (t->refcnt == 0) { /* dec refs on all elements */ if (t->source) burn_source_free(t->source); + for (i = 0; i < 8; i++) + burn_cdtext_free(&(t->cdtext[i])); free(t); } } @@ -675,3 +698,267 @@ ex:; } +struct burn_cdtext *burn_cdtext_create(void) +{ + struct burn_cdtext *t; + int i; + + t = burn_alloc_mem(sizeof(struct burn_cdtext), 1, 0); + if (t == NULL) + return NULL; + for(i = 0; i < Libburn_pack_num_typeS; i ++) { + t->payload[i] = NULL; + t->length[i] = 0; + } + return t; +} + + +void burn_cdtext_free(struct burn_cdtext **cdtext) +{ + struct burn_cdtext *t; + int i; + + t = *cdtext; + if (t == NULL) + return; + for (i = 0; i < Libburn_pack_num_typeS; i++) + if (t->payload[i] != NULL) + free(t->payload[i]); + free(t); +} + + +static int burn_cdtext_name_to_type(char *pack_type_name) +{ + int i, j; + static char *pack_type_names[] = { + Libburn_pack_type_nameS + }; + + for (i = 0; i < Libburn_pack_num_typeS; i++) { + if (pack_type_names[i][0] == 0) + continue; + for (j = 0; pack_type_names[i][j]; j++) + if (pack_type_names[i][j] != pack_type_name[j] && + tolower(pack_type_names[i][j]) != + pack_type_name[j]) + break; + if (pack_type_names[i][j] == 0) + return Libburn_pack_type_basE + i; + } + return -1; +} + + +/* @param flag bit0= double byte characters +*/ +static int burn_cdtext_set(struct burn_cdtext **cdtext, + int pack_type, char *pack_type_name, + unsigned char *payload, int length, int flag) +{ + int i; + struct burn_cdtext *t; + + if (pack_type_name != NULL) + if (pack_type_name[0]) + pack_type = burn_cdtext_name_to_type(pack_type_name); + if (pack_type < Libburn_pack_type_basE || + pack_type >= Libburn_pack_type_basE + Libburn_pack_num_typeS) { + libdax_msgs_submit(libdax_messenger, -1, 0x0002018c, + LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH, + "CD-TEXT pack type out of range", 0, 0); + return 0; + } + t = *cdtext; + if (t == NULL) { + *cdtext = t = burn_cdtext_create(); + if (t == NULL) + return -1; + } + i = pack_type - Libburn_pack_type_basE; + if (t->payload[i] != NULL) + free(t->payload[i]); + t->payload[i] = burn_alloc_mem((size_t) length, 1, 0); + if (t->payload[i] == NULL) + return -1; + memcpy(t->payload[i], payload, length); + t->length[i] = length; + t->flags = (t->flags & ~(1 << i)) | (flag & (1 << i)); + return 1; +} + + +/* @return 1=single byte char , 2= double byte char , <=0 error */ +static int burn_cdtext_get(struct burn_cdtext *t, int pack_type, + char *pack_type_name, + unsigned char **payload, int *length, int flag) +{ + if (pack_type_name != NULL) + if (pack_type_name[0]) + pack_type = burn_cdtext_name_to_type(pack_type_name); + if (pack_type < Libburn_pack_type_basE || + pack_type >= Libburn_pack_type_basE + Libburn_pack_num_typeS) { + libdax_msgs_submit(libdax_messenger, -1, 0x0002018c, + LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH, + "CD-TEXT pack type out of range", 0, 0); + return 0; + } + *payload = t->payload[pack_type - Libburn_pack_type_basE]; + *length = t->length[pack_type - Libburn_pack_type_basE]; + return 1 + ((t->flags >> (pack_type - Libburn_pack_type_basE)) & 1); +} + + +static int burn_cdtext_check_blockno(int block) +{ + if (block < 0 || block > 7) { + libdax_msgs_submit(libdax_messenger, -1, 0x0002018d, + LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH, + "CD-TEXT block number out of range", 0, 0); + return 0; + } + return 1; +} + + +/* ts B11206 API */ +/* @param flag bit0= double byte characters +*/ +int burn_track_set_cdtext(struct burn_track *t, int block, + int pack_type, char *pack_type_name, + unsigned char *payload, int length, int flag) +{ + int ret; + + if (burn_cdtext_check_blockno(block) <= 0) + return 0; + ret = burn_cdtext_set(&(t->cdtext[block]), pack_type, pack_type_name, + payload, length, flag & 1); + return ret; +} + + +/* ts B11206 API */ +/* @return 1=single byte char , 2= double byte char , <=0 error */ +int burn_track_get_cdtext(struct burn_track *t, int block, + int pack_type, char *pack_type_name, + unsigned char **payload, int *length, int flag) +{ + int ret; + + if (burn_cdtext_check_blockno(block) <= 0) + return 0; + ret = burn_cdtext_get(t->cdtext[block], pack_type, pack_type_name, + payload, length, 0); + return ret; +} + + +/* ts B11206 API */ +int burn_track_dispose_cdtext(struct burn_track *t, int block) +{ + int i; + + if (block == -1) { + for (i= 0; i < 8; i++) + burn_cdtext_free(&(t->cdtext[i])); + return 1; + } + if (burn_cdtext_check_blockno(block) <= 0) + return 0; + burn_cdtext_free(&(t->cdtext[0])); + return 1; +} + + +/* ts B11206 API */ +/* @param flag bit0= double byte characters +*/ +int burn_session_set_cdtext(struct burn_session *s, int block, + int pack_type, char *pack_type_name, + unsigned char *payload, int length, int flag) +{ + int ret; + + if (burn_cdtext_check_blockno(block) <= 0) + return 0; + ret = burn_cdtext_set(&(s->cdtext[block]), pack_type, pack_type_name, + payload, length, flag & 1); + return ret; +} + + +/* ts B11206 API */ +/* @return 1=single byte char , 2= double byte char , <=0 error */ +int burn_session_get_cdtext(struct burn_session *s, int block, + int pack_type, char *pack_type_name, + unsigned char **payload, int *length, int flag) +{ + int ret; + + if (burn_cdtext_check_blockno(block) <= 0) + return 0; + ret = burn_cdtext_get(s->cdtext[block], pack_type, pack_type_name, + payload, length, 0); + return ret; +} + + +/* ts B11206 API */ +int burn_session_set_cdtext_par(struct burn_session *s, + int char_codes[8], int copyrights[8], + int block_languages[8], int flag) +{ + int i; + + for (i = 0; i < 8; i++) { + if (char_codes[i] >= 0 && char_codes[i] <= 255) + s->cdtext_char_code[i] = char_codes[i]; + if (copyrights[i] >= 0 && copyrights[i] <= 255) + s->cdtext_copyright[i] = copyrights[i]; + if (block_languages[i] >= 0 && block_languages[i] <= 255) + s->cdtext_language[i] = block_languages[i]; + } + return 1; +} + + +/* ts B11206 API */ +int burn_session_get_cdtext_par(struct burn_session *s, + int char_codes[8], int copyrights[8], + int block_languages[8], int flag) +{ + int i; + + for (i = 0; i < 8; i++) { + char_codes[i] = s->cdtext_char_code[i]; + copyrights[i] = s->cdtext_copyright[i]; + block_languages[i]= s->cdtext_language[i]; + } + return 1; +} + + +/* ts B11206 API */ +int burn_session_dispose_cdtext(struct burn_session *s, int block) +{ + int i; + + if (block == -1) { + for (i= 0; i < 8; i++) { + burn_session_dispose_cdtext(s, i); + s->cdtext_char_code[i] = 0x01; /* 7 bit ASCII */ + s->cdtext_copyright[i] = 0; + s->cdtext_language[i] = 0; + } + return 1; + } + if (burn_cdtext_check_blockno(block) <= 0) + return 0; + burn_cdtext_free(&(s->cdtext[block])); + s->cdtext_language[block] = 0x09; /* english */ + return 1; +} + + diff --git a/libburn/structure.h b/libburn/structure.h index 7c093f4..95a1a11 100644 --- a/libburn/structure.h +++ b/libburn/structure.h @@ -16,6 +16,22 @@ struct isrc unsigned int serial; /* must be 0-99999 */ }; +/* ts B11206 */ +#define Libburn_pack_type_basE 0x80 +#define Libburn_pack_num_typeS 0x10 +#define Libburn_pack_type_nameS \ + "TITLE", "PERFORMER", "SONGWRITER", "COMPOSER", \ + "ARRANGER", "MESSAGE", "DISCID", "GENRE", \ + "TOC", "TOC2", "", "", \ + "", "CLOSED", "UPC_ISRC", "BLOCKSIZE" + +struct burn_cdtext +{ + unsigned char *(payload[Libburn_pack_num_typeS]); + int length[Libburn_pack_num_typeS]; + int flags; /* bit0 - bit15= double byte characters */ +}; + struct burn_track { int refcnt; @@ -82,6 +98,9 @@ struct burn_track /* ts A90910 : conversions from CD XA prepared input */ int cdxa_conversion; /* 0=none, 1=remove -xa1 headers (first 8 bytes)*/ + /* ts B11206 */ + struct burn_cdtext *cdtext[8]; + }; struct burn_session @@ -97,6 +116,13 @@ struct burn_session int tracks; struct burn_track **track; int refcnt; + + /* ts B11206 */ + struct burn_cdtext *cdtext[8]; + unsigned char cdtext_char_code[8]; + unsigned char cdtext_copyright[8]; + unsigned char cdtext_language[8]; + }; struct burn_disc @@ -131,4 +157,9 @@ off_t burn_track_get_default_size(struct burn_track *t); int burn_disc_cd_toc_extensions(struct burn_disc *d, int flag); +/* ts B11206 */ +struct burn_cdtext *burn_cdtext_create(void); +void burn_cdtext_free(struct burn_cdtext **cdtext); + + #endif /* BURN__STRUCTURE_H */ diff --git a/libburn/write.c b/libburn/write.c index 93762b2..957b42c 100644 --- a/libburn/write.c +++ b/libburn/write.c @@ -405,10 +405,23 @@ struct cue_sheet *burn_create_toc_entries(struct burn_write_opts *o, "Track mode has unusable value", 0, 0); goto failed; } - if (o->num_text_packs > 0) + if (o->num_text_packs > 0) { leadin_form = 0x41; - else + } else { leadin_form = 0x01; + + /* Check for CD-TEXT in session. Not the final creation, + because the cue sheet content might be needed for CD-TEXT + pack type 0x88 "TOC". + */ + if (o->text_packs == NULL) { + ret = burn_cdtext_from_session(session, NULL, NULL, 1); + if (ret < 0) + goto failed; + else if (ret > 0) + leadin_form = 0x41; + } + } ret = add_cue(sheet, ctladr | 1, 0, 0, leadin_form, 0, runtime); if (ret <= 0) goto failed; @@ -656,10 +669,442 @@ int burn_write_leadout(struct burn_write_opts *o, } -int burn_write_leadin_cdtext(struct burn_write_opts *o, struct burn_session *s, - int flag) +struct burn_pack_cursor { + unsigned char *packs; + int num_packs; + int td_used; + int hiseq[8]; + int pack_count[16]; +}; + + +/* @param flag bit0= double_byte characters +*/ +int burn_create_new_pack(int pack_type, int track_no, int double_byte, + int block, int char_pos, + struct burn_pack_cursor *crs, int flag) +{ + int idx; + + if (crs->num_packs >= Libburn_leadin_cdtext_packs_maX) { + libdax_msgs_submit(libdax_messenger, -1, 0x0002018b, + LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH, + "Too many CD-TEXT packs", 0, 0); + return 0; + } + if (crs->hiseq[block] >= 255) { + libdax_msgs_submit(libdax_messenger, -1, 0x0002018e, + LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH, + "Too many CD-TEXT packs in block", 0, 0); + return 0; + } + if (char_pos > 15) + char_pos = 15; + else if (char_pos < 0) + char_pos = 0; + idx = crs->num_packs * 18; + crs->packs[idx++] = pack_type; + crs->packs[idx++] = track_no; + crs->packs[idx++] = crs->hiseq[block]; + crs->packs[idx++] = ((flag & 1) << 7) | (block << 4) | char_pos; + crs->hiseq[block]++; + crs->td_used = 0; + crs->pack_count[pack_type - Libburn_pack_type_basE]++; + return 1; +} + + +/* Plain implementation of polynomial division on a Galois field, where + addition and subtraction both are binary exor. Euclidian algorithm. + Divisor is x^16 + x^12 + x^5 + 1 = 0x11021. +*/ +static int crc_11021(unsigned char *data, int count, int flag) +{ + int acc = 0, i; + + for (i = 0; i < count * 8 + 16; i++) { + acc = (acc << 1); + if (i < count * 8) + acc |= ((data[i / 8] >> (7 - (i % 8))) & 1); + if (acc & 0x10000) + acc ^= 0x11021; + } + return acc; +} + + +/* @param flag bit0= repair mismatching checksums + bit1= repair checksums if all pack CRCs are 0 + @return 0= no mismatch , >0 number of unrepaired mismatches + <0 number of repaired mismatches that were not 0 +*/ +int burn_cdtext_crc_mismatches(unsigned char *packs, int num_packs, int flag) +{ + int i, residue, count = 0, repair; + unsigned char crc[2]; + + repair = flag & 1; + if (flag & 2) { + for (i = 0; i < num_packs * 18; i += 18) + if (packs[i + 16] || packs[i + 17]) + break; + if (i == num_packs * 18) + repair = 1; + } + for (i = 0; i < num_packs * 18; i += 18) { + residue = crc_11021(packs + i, 16, 0); + crc[0] = ((residue >> 8) & 0xff) ^ 0xff; + crc[1] = ((residue ) & 0xff) ^ 0xff; + if(crc[0] != packs[i + 16] || crc[1] != packs[i + 17]) { + if (repair) { + if (packs[i + 16] || packs[i + 17]) + count--; + packs[i + 16] = crc[0]; + packs[i + 17] = crc[1]; + } else + count++; + } + + } + return count; +} + + +static int burn_finalize_text_pack(struct burn_pack_cursor *crs, int flag) +{ + int residue = 0, i, idx; + + idx = 18 * crs->num_packs; + for(i = 4 + crs->td_used; i < 16; i++) + crs->packs[idx + i] = 0; + crs->td_used = 12; + + /* MMC-3 Annex J : CRC Field consists of 2 bytes. + The polynomial is X16 + X12 + X5 + 1. All bits shall be inverted. + */ + residue = crc_11021(crs->packs + idx, 16, 0) ^ 0xffff; + + crs->packs[idx + 16] = (residue >> 8) & 0xff; + crs->packs[idx + 17] = residue & 0xff; + crs->num_packs++; + crs->td_used = 0; + return 1; +} + + +/* @param flag bit0= double_byte characters +*/ +static int burn_create_tybl_packs(unsigned char *payload, int length, + int track_no, int pack_type, int block, + struct burn_pack_cursor *crs, int flag) +{ + int i, ret, binary_part = 0, char_pos; + + if (pack_type == 0x87) + binary_part = 2; + else if ((pack_type >= 0x88 && pack_type <= 0x8c) || pack_type == 0x8f) + binary_part = length; + for(i = 0; i < length; i++) { + if (crs->td_used == 0 || crs->td_used >= 12) { + if (crs->td_used > 0) { + ret = burn_finalize_text_pack(crs, 0); + if (ret <= 0) + return ret; + } + char_pos = (i - binary_part) / (1 + (flag & 1)); + ret = burn_create_new_pack(pack_type, track_no, + (flag & 1), block, char_pos, + crs, flag & 1); + if (ret <= 0) + return ret; + } + crs->packs[crs->num_packs * 18 + 4 + crs->td_used] = + payload[i]; + crs->td_used++; + } + return 1; +} + + +/* Finalize block by 0x8f. Set bytes 20 to 27 to 0 for now. */ +static int burn_create_bl_size_packs(int block, unsigned char *char_codes, + unsigned char *copyrights, + unsigned char *languages, + int num_tracks, + struct burn_pack_cursor *crs, int flag) +{ + int i, ret; + unsigned char payload[12]; + /* Normal is track_offset = 0. + But if the CUE sheet supports offset, then it is needed here too */ + int track_offset = 0; + + payload[0] = char_codes[block]; + payload[1] = 1 + track_offset; + payload[2] = num_tracks + track_offset; + payload[3] = copyrights[block]; + for (i = 0; i < 8; i++) + payload[i + 4] = crs->pack_count[i]; + ret = burn_create_tybl_packs(payload, 12, 0, 0x8f, block, crs, 0); + if (ret <= 0) + return ret; + + for (i = 0; i < 7; i++) + payload[i] = crs->pack_count[i + 8]; + payload[7] = 3; /* always 3 packs of type 0x8f */ + for (i = 0; i < 4; i++) { + /* Will be set when all blocks are done */ + payload[i + 8] = 0; + } + ret = burn_create_tybl_packs(payload, 12, 1, 0x8f, block, crs, 0); + if (ret <= 0) + return ret; + + for (i = 0; i < 4; i++) { + /* Will be set when all blocks are done */ + payload[i] = 0; + } + for (i = 0; i < 8; i++) { + payload[i + 4] = languages[i]; + } + ret = burn_create_tybl_packs(payload, 12, 2, 0x8f, block, crs, 0); + if (ret <= 0) + return ret; + ret = burn_finalize_text_pack(crs, 0); + if (ret <= 0) + return ret; + + for (i = 0; i < 16; i++) + crs->pack_count[i] = 0; + return 1; +} + + +/* Text packs of track for type and block + @param flag bit0= write TAB, because content is identical to previous track +*/ +static int burn_create_tybl_t_packs(struct burn_track *t, int track_no, + int pack_type, int block, + struct burn_pack_cursor *crs, int flag) +{ + int ret, length = 0, idx, double_byte, flags= 0; + unsigned char *payload = NULL, dummy[8]; + struct burn_cdtext *cdt; + + cdt = t->cdtext[block]; + idx = pack_type - Libburn_pack_type_basE; + if (cdt != NULL) { + if (cdt->length[idx] > 0) { + payload = cdt->payload[idx]; + length = cdt->length[idx]; + } + flags = cdt->flags; + } + if (payload == NULL) { + sprintf((char *) dummy, "%d", track_no); + payload = dummy; + length = strlen((char *) dummy) + 1; + } + double_byte = !!(flags & (1 <<(pack_type - Libburn_pack_type_basE))); + if (flag & 1) { + length = 0; + dummy[length++] = 9; + if (double_byte) + dummy[length++] = 9; + dummy[length++] = 0; + if (double_byte) + dummy[length++] = 0; + payload = dummy; + } + ret = burn_create_tybl_packs(payload, length, track_no, + pack_type, block, crs, double_byte); + return ret; +} + + +/* Check whether the content is the same as in the previous pack. If so, + advise to use the TAB abbreviation. +*/ +static int burn_decide_cdtext_tab(int block, int pack_type, + struct burn_cdtext *cdt_curr, + struct burn_cdtext *cdt_prev, int flag) +{ + int length, j, idx; + + idx = pack_type - Libburn_pack_type_basE; + if (cdt_curr == NULL || cdt_prev == NULL) + return 0; + if (((cdt_curr->flags >> idx) & 1) != ((cdt_prev->flags >> idx) & 1)) + return 0; + length = cdt_curr->length[idx]; + if (length != cdt_prev->length[idx] || length == 0) + return 0; + for (j = 0; j < length; j++) + if (cdt_curr->payload[j] != cdt_prev->payload[j]) + break; + if (j < length) + return 0; + return 1; +} + + +/* Text packs of session and of tracks (if applicable), for type and block +*/ +static int burn_create_tybl_s_packs(struct burn_session *s, + int pack_type, int block, + struct burn_pack_cursor *crs, int flag) +{ + int i, ret, idx, double_byte, use_tab; + struct burn_cdtext *cdt; + /* Normal is track_offset = 0. + But if the CUE sheet supports offset, then it is needed here too */ + int track_offset = 0; + + cdt = s->cdtext[block]; + idx = pack_type - Libburn_pack_type_basE; + if (cdt->length[idx] == 0 || cdt->payload[idx] == NULL) + return 1; + + double_byte = !!(cdt->flags & + (1 <<(pack_type - Libburn_pack_type_basE))); + ret = burn_create_tybl_packs(cdt->payload[idx], cdt->length[idx], 0, + pack_type, block, crs, double_byte); + if (ret <= 0) + return ret; + + if ((pack_type < 0x80 || pack_type > 0x85) && pack_type != 0x8e) { + ret = burn_finalize_text_pack(crs, 0); + return ret; + } + + for (i = 0; i < s->tracks; i++) { + if (i > 0) + use_tab = burn_decide_cdtext_tab(block, pack_type, + s->track[i]->cdtext[block], + s->track[i - 1]->cdtext[block], 0); + else + use_tab = 0; + ret = burn_create_tybl_t_packs(s->track[i], + i + 1 + track_offset, pack_type, + block, crs, use_tab); + if (ret <= 0) + return ret; + } + /* Fill up last pack with 0s */ + ret = burn_finalize_text_pack(crs, 0); + return ret; +} + + +/* ts B11210 : API */ +/* @param flag bit0= do not return CD-TEXT packs, but return number of packs +*/ +int burn_cdtext_from_session(struct burn_session *s, + unsigned char **text_packs, int *num_packs, + int flag) +{ + int pack_type, block, ret, i, idx, j, residue; + struct burn_pack_cursor crs; + + if (text_packs == NULL || num_packs == NULL) { + flag |= 1; + } else if (!(flag & 1)) { + *text_packs = NULL; + *num_packs = 0; + } + memset(&crs, 0, sizeof(struct burn_pack_cursor)); + BURN_ALLOC_MEM(crs.packs, unsigned char, + Libburn_leadin_cdtext_packs_maX * 18); + + for (block = 0; block < 8; block++) + if (s->cdtext[block] != NULL) + break; + if (block == 8) + {ret = 1; goto ex;} + + for (block= 0; block < 8; block++) { + if (s->cdtext[block] == NULL) + continue; + for (pack_type = 0x80; + pack_type < 0x80 + Libburn_pack_num_typeS; pack_type++) { + if (pack_type == 0x8f) + continue; + ret = burn_create_tybl_s_packs(s, + pack_type, block, &crs, 0); + if (ret <= 0) + goto ex; + } + ret = burn_create_bl_size_packs(block, + s->cdtext_char_code, s->cdtext_copyright, + s->cdtext_language, s->tracks, &crs, 0); + if (ret <= 0) + goto ex; + } + + /* Insert the highest sequence numbers of each block into + the 0x8f packs 2 and 3 (bytes 20 to 27) + */ + for (i = 0; i < crs.num_packs; i++) { + idx = i * 18; + if (crs.packs[idx] == 0x8f && crs.packs[idx + 1] == 1) { + for (j = 0; j < 4; j++) + if (crs.hiseq[j] > 0) + crs.packs[idx + 4 + 8 + j] = + crs.hiseq[j] - 1; + else + crs.packs[idx + 4 + 8 + j] = 0; + } else if (crs.packs[idx] == 0x8f && crs.packs[idx + 1] == 2) { + for (j = 0; j < 4; j++) + if (crs.hiseq[j + 4] > 0) + crs.packs[idx + 4 + j] = + crs.hiseq[j + 4] - 1; + else + crs.packs[idx + 4 + j] = 0; + } else + continue; + /* Re-compute checksum */ + residue = crc_11021(crs.packs + idx, 16, 0) ^ 0xffff; + crs.packs[idx + 16] = (residue >> 8) & 0xff; + crs.packs[idx + 17] = residue & 0xff; + } + + ret = 1; +ex:; + if (ret <= 0 || (flag & 1)) { + if (ret > 0) + ret = crs.num_packs; + BURN_FREE_MEM(crs.packs); + } else if (crs.num_packs > 0) { + *text_packs = crs.packs; + *num_packs = crs.num_packs; + } + return(ret); +} + + +static int burn_create_text_packs(struct burn_write_opts *o, + struct burn_session *s, + int flag) +{ + int ret, num_packs = 0; + unsigned char *text_packs = NULL; + + ret = burn_cdtext_from_session(s, &text_packs, &num_packs, 0); + if (ret > 0) { + if (o->text_packs != NULL) + free(o->text_packs); + o->text_packs = text_packs; + o->num_text_packs = num_packs; + } + return(ret); +} + + +static int burn_write_leadin_cdtext(struct burn_write_opts *o, + struct burn_session *s, int flag) { int ret, i, j, si, lba, sub_cursor = 0, err, write_lba, sectors = 0; + int self_made_text_packs = 0; unsigned char *subdata = NULL; struct burn_drive *d = o->drive; struct buffer *buf = NULL; @@ -668,8 +1113,29 @@ int burn_write_leadin_cdtext(struct burn_write_opts *o, struct burn_session *s, unsigned char *packs; #endif - if (o->num_text_packs <= 0) - {ret = 1; goto ex;} + if (o->num_text_packs <= 0) { + if (o->text_packs != NULL) + {ret = 1; goto ex;} + /* Try to create CD-TEXT from .cdtext_* of session and track */ + ret = burn_create_text_packs(o, s, 0); + if (ret <= 0) + goto ex; + self_made_text_packs = 1; + if (o->num_text_packs <= 0) + {ret = 1; goto ex;} + } + + if (!o->no_text_pack_crc_check) { + ret = burn_cdtext_crc_mismatches(o->text_packs, + o->num_text_packs, 0); + if (ret != 0) { + libdax_msgs_submit(libdax_messenger, -1, 0x0002018f, + LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH, + "Program error: CD-TEXT pack CRC mismatch", + 0, 0); + { ret = 0; goto ex; } + } + } d->busy = BURN_DRIVE_WRITING_LEADIN; @@ -741,6 +1207,12 @@ int burn_write_leadin_cdtext(struct burn_write_opts *o, struct burn_session *s, } ret = 1; ex:; + if (self_made_text_packs) { + if (o->text_packs != NULL) + free(o->text_packs); + o->text_packs = NULL; + o->num_text_packs = 0; + } BURN_FREE_MEM(subdata); BURN_FREE_MEM(buf); d->busy = was_busy; @@ -864,7 +1336,8 @@ int burn_write_track(struct burn_write_opts *o, struct burn_session *s, "TAO pre-track %2.2d : get_nwa(%d)=%d, d=%d , demand=%.f , cap=%.f\n", tnum+1, nwa, ret, d->nwa, (double) burn_track_get_sectors(t) * 2048.0, (double) d->media_capacity_remaining); - libdax_msgs_submit(libdax_messenger, d->global_index, 0x000002, + libdax_msgs_submit(libdax_messenger, d->global_index, + 0x00000002, LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, msg, 0, 0); @@ -1196,7 +1669,7 @@ int burn_disc_open_track_dvd_minus_r(struct burn_write_opts *o, sprintf(msg, "DVD 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_submit(libdax_messenger, d->global_index, 0x00000002, LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, msg,0,0); if (nwa > d->nwa) d->nwa = nwa; @@ -1256,7 +1729,7 @@ int burn_disc_open_track_dvd_plus_r(struct burn_write_opts *o, 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_submit(libdax_messenger, d->global_index, 0x00000002, LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, msg,0,0); if (nwa > d->nwa) d->nwa = nwa; @@ -2670,7 +3143,7 @@ return crap. so we send the command, then ignore the result. sprintf(msg, "SAO appendable d->nwa= %d\n", d->nwa); libdax_msgs_submit( - libdax_messenger, d->global_index, 0x000002, + libdax_messenger, d->global_index, 0x00000002, LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, msg, 0, 0); diff --git a/libburn/write.h b/libburn/write.h index 1e5ecce..75ffc53 100644 --- a/libburn/write.h +++ b/libburn/write.h @@ -39,6 +39,13 @@ int burn_write_close_track(struct burn_write_opts *o, struct burn_session *s, int tnum); int burn_write_close_session(struct burn_write_opts *o); +/* @param flag bit0= repair checksum + bit1= repair checksum if all pack CRCs are 0 + @return 0= no mismatch , >0 number of unrepaired mismatches + <0 number of repaired mismatches +*/ +int burn_cdtext_crc_mismatches(unsigned char *packs, int num_packs, int flag); + /* mmc5r03c.pdf 6.3.3.3.3: DVD-R DL: Close Function 010b: Close Session