New API calls for composing CD-TEXT
This commit is contained in:
parent
2063dc2ca7
commit
620871c91d
@ -1 +1 @@
|
||||
#define Cdrskin_timestamP "2011.12.09.092152"
|
||||
#define Cdrskin_timestamP "2011.12.12.092602"
|
||||
|
@ -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,
|
||||
|
@ -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).
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "drive.h"
|
||||
#include "transport.h"
|
||||
#include "init.h"
|
||||
#include "write.h"
|
||||
|
||||
/* ts A61007 */
|
||||
/* #include <a ssert.h> */
|
||||
@ -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;
|
||||
|
@ -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(). */
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 */
|
||||
|
493
libburn/write.c
493
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);
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user