New API calls for composing CD-TEXT

This commit is contained in:
Thomas Schmitt 2011-12-12 09:26:41 +00:00
parent 7eb0360f16
commit c2674a3ea5
11 changed files with 1109 additions and 52 deletions

View File

@ -1 +1 @@
#define Cdrskin_timestamP "2011.12.09.092152" #define Cdrskin_timestamP "2011.12.12.092602"

View File

@ -589,7 +589,7 @@ void *burn_alloc_mem(size_t size, size_t count, int flag)
{ {
void *pt; void *pt;
pt = calloc(size, count); pt = calloc(count, size);
if(pt == NULL) if(pt == NULL)
libdax_msgs_submit(libdax_messenger, -1, 0x00000003, libdax_msgs_submit(libdax_messenger, -1, 0x00000003,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,

View File

@ -1291,45 +1291,17 @@ int burn_disc_get_cd_info(struct burn_drive *d, char disc_type[80],
int *valid); int *valid);
/* ts B11201 */ /* 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 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. of 0-terminated texts or binary data. 2 bytes hold a CRC.
See also MMC-3 Annex J. For a description of the format of the array, see file doc/cdtext.txt.
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."
@param d The drive to query. @param d The drive to query.
@param text_packs Will point to an allocated memory buffer with CD-TEXT. @param text_packs Will point to an allocated memory buffer with CD-TEXT.
It will only contain text packs, and not be prepended It will only contain text packs, and not be prepended
by the TOC header of four bytes, which gets stored with 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 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. Dispose this buffer by free(), when no longer needed.
@param num_packs Will tell the number of text packs, i.e. the number of @param num_packs Will tell the number of text packs, i.e. the number of
bytes in text_packs divided by 18. 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); 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 /** Define the data in a track
@param t the track to define @param t the track to define
@param offset The lib will write this many 0s before start of data @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); 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 */ /* ts A90910 */
/** Activates CD XA compatibility modes. /** Activates CD XA compatibility modes.
libburn currently writes data only in CD mode 1. Some programs insist in 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. of a SAO write run on CD.
@param opts The option object to be manipulated @param opts The option object to be manipulated
@param text_packs Array of bytes which form CD-TEXT packs of 18 bytes @param text_packs Array of bytes which form CD-TEXT packs of 18 bytes
each. See burn_disc_get_leadin_text() for a description each. For a description of the format of the array,
of the text pack format. see file doc/cdtext.txt.
No header of 4 bytes must be prepended which would No header of 4 bytes must be prepended which would
tell the number of pack bytes + 2. 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 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 @return 1 on success, <= 0 on failure
@since 1.2.0 @since 1.2.0
*/ */
@ -2450,6 +2661,7 @@ int burn_write_opts_set_leadin_text(struct burn_write_opts *opts,
unsigned char *text_packs, unsigned char *text_packs,
int num_packs, int flag); int num_packs, int flag);
/* ts A61222 */ /* ts A61222 */
/** Sets a start address for writing to media and write modes which allow to /** 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). choose this address at all (for now: DVD+RW, DVD-RAM, formatted DVD-RW).

View File

@ -4,6 +4,7 @@ burn_abort;
burn_abort_pacifier; burn_abort_pacifier;
burn_allow_drive_role_4; burn_allow_drive_role_4;
burn_allow_untested_profiles; burn_allow_untested_profiles;
burn_cdtext_from_session;
burn_disc_add_session; burn_disc_add_session;
burn_disc_available_space; burn_disc_available_space;
burn_disc_close_damaged; burn_disc_close_damaged;
@ -113,13 +114,18 @@ burn_scsi_transport_id;
burn_sectors_to_msf; burn_sectors_to_msf;
burn_session_add_track; burn_session_add_track;
burn_session_create; burn_session_create;
burn_session_dispose_cdtext;
burn_session_free; burn_session_free;
burn_session_get_cdtext;
burn_session_get_cdtext_par;
burn_session_get_hidefirst; burn_session_get_hidefirst;
burn_session_get_leadout_entry; burn_session_get_leadout_entry;
burn_session_get_sectors; burn_session_get_sectors;
burn_session_get_tracks; burn_session_get_tracks;
burn_session_hide_first_track; burn_session_hide_first_track;
burn_session_remove_track; burn_session_remove_track;
burn_session_set_cdtext;
burn_session_set_cdtext_par;
burn_set_messenger; burn_set_messenger;
burn_set_scsi_logging; burn_set_scsi_logging;
burn_set_signal_handling; burn_set_signal_handling;
@ -133,13 +139,16 @@ burn_text_to_sev;
burn_track_clear_isrc; burn_track_clear_isrc;
burn_track_create; burn_track_create;
burn_track_define_data; burn_track_define_data;
burn_track_dispose_cdtext;
burn_track_free; burn_track_free;
burn_track_get_cdtext;
burn_track_get_counters; burn_track_get_counters;
burn_track_get_entry; burn_track_get_entry;
burn_track_get_mode; burn_track_get_mode;
burn_track_get_sectors; burn_track_get_sectors;
burn_track_set_byte_swap; burn_track_set_byte_swap;
burn_track_set_cdxa_conv; burn_track_set_cdxa_conv;
burn_track_set_cdtext;
burn_track_set_default_size; burn_track_set_default_size;
burn_track_set_isrc; burn_track_set_isrc;
burn_track_set_size; burn_track_set_size;

View File

@ -578,6 +578,11 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
0x00020189 (FATAL,HIGH) = Drive is already grabbed by libburn 0x00020189 (FATAL,HIGH) = Drive is already grabbed by libburn
0x0002018a (SORRY,HIGH) = Timeout exceeded. Retry cancled. 0x0002018a (SORRY,HIGH) = Timeout exceeded. Retry cancled.
0x0002018b (FAILURE,HIGH) = Too many CD-TEXT packs 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: libdax_audioxtr:
0x00020200 (SORRY,HIGH) = Cannot open audio source file 0x00020200 (SORRY,HIGH) = Cannot open audio source file

View File

@ -13,6 +13,7 @@
#include "drive.h" #include "drive.h"
#include "transport.h" #include "transport.h"
#include "init.h" #include "init.h"
#include "write.h"
/* ts A61007 */ /* ts A61007 */
/* #include <a ssert.h> */ /* #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->stdio_fsync_size = Libburn_stdio_fsync_limiT;
opts->text_packs = NULL; opts->text_packs = NULL;
opts->num_text_packs = 0; opts->num_text_packs = 0;
opts->no_text_pack_crc_check = 0;
opts->has_mediacatalog = 0; opts->has_mediacatalog = 0;
opts->format = BURN_CDROM; opts->format = BURN_CDROM;
opts->multi = 0; opts->multi = 0;
@ -196,6 +198,10 @@ void burn_write_opts_set_multi(struct burn_write_opts *opts, int multi)
/* ts B11204 */ /* 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, int burn_write_opts_set_leadin_text(struct burn_write_opts *opts,
unsigned char *text_packs, unsigned char *text_packs,
int num_packs, int flag) int num_packs, int flag)
@ -203,12 +209,11 @@ int burn_write_opts_set_leadin_text(struct burn_write_opts *opts,
int ret; int ret;
unsigned char *pack_buffer = NULL; unsigned char *pack_buffer = NULL;
if (num_packs > 3640) { if (num_packs > Libburn_leadin_cdtext_packs_maX ) {
/* READ TOC/PMA/ATIP can at most return 3640.7 packs */
libdax_msgs_submit(libdax_messenger, opts->drive->global_index, libdax_msgs_submit(libdax_messenger, opts->drive->global_index,
0x0002018b, 0x0002018b,
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH, 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; ret= 0; goto ex;
} }
@ -219,6 +224,26 @@ int burn_write_opts_set_leadin_text(struct burn_write_opts *opts,
free(opts->text_packs); free(opts->text_packs);
opts->text_packs = NULL; 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) { if (num_packs > 0) {
memcpy(pack_buffer, text_packs, num_packs * 18); memcpy(pack_buffer, text_packs, num_packs * 18);
opts->text_packs = pack_buffer; opts->text_packs = pack_buffer;

View File

@ -72,6 +72,7 @@ struct burn_write_opts
/* ts B11203 : CD-TEXT */ /* ts B11203 : CD-TEXT */
unsigned char *text_packs; unsigned char *text_packs;
int num_text_packs; int num_text_packs;
int no_text_pack_crc_check;
/** A disc can have a media catalog number */ /** A disc can have a media catalog number */
int has_mediacatalog; int has_mediacatalog;
@ -87,6 +88,13 @@ struct burn_write_opts
*/ */
#define Libburn_stdio_fsync_limiT 8192 #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 /** Options for disc reading operations. This should be created with
burn_read_opts_new() and freed with burn_read_opts_free(). */ burn_read_opts_new() and freed with burn_read_opts_free(). */

View File

@ -14,6 +14,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <ctype.h>
#include "libburn.h" #include "libburn.h"
#include "structure.h" #include "structure.h"
#include "write.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 *burn_session_create(void)
{ {
struct burn_session *s; struct burn_session *s;
int i;
s = calloc(1, sizeof(struct burn_session)); s = calloc(1, sizeof(struct burn_session));
if (s == NULL) /* ts A70825 */ if (s == NULL) /* ts A70825 */
return NULL; return NULL;
@ -82,6 +85,13 @@ struct burn_session *burn_session_create(void)
s->tracks = 0; s->tracks = 0;
s->track = NULL; s->track = NULL;
s->hidefirst = 0; 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; 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) void burn_session_free(struct burn_session *s)
{ {
int i;
s->refcnt--; s->refcnt--;
if (s->refcnt == 0) { if (s->refcnt == 0) {
/* dec refs on all elements */ /* dec refs on all elements */
int i;
for (i = 0; i < s->tracks; i++) for (i = 0; i < s->tracks; i++)
burn_track_free(s->track[i]); burn_track_free(s->track[i]);
for (i = 0; i < 8; i++)
burn_cdtext_free(&(s->cdtext[i]));
free(s->track); free(s->track);
free(s); 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 *burn_track_create(void)
{ {
struct burn_track *t; struct burn_track *t;
int i;
t = calloc(1, sizeof(struct burn_track)); t = calloc(1, sizeof(struct burn_track));
if (t == NULL) /* ts A70825 */ if (t == NULL) /* ts A70825 */
return NULL; return NULL;
@ -180,16 +194,25 @@ struct burn_track *burn_track_create(void)
/* ts A61024 */ /* ts A61024 */
t->swap_source_bytes = 0; t->swap_source_bytes = 0;
/* ts B11206 */
for (i = 0; i < 8; i++)
t->cdtext[i] = NULL;
return t; return t;
} }
void burn_track_free(struct burn_track *t) void burn_track_free(struct burn_track *t)
{ {
int i;
t->refcnt--; t->refcnt--;
if (t->refcnt == 0) { if (t->refcnt == 0) {
/* dec refs on all elements */ /* dec refs on all elements */
if (t->source) if (t->source)
burn_source_free(t->source); burn_source_free(t->source);
for (i = 0; i < 8; i++)
burn_cdtext_free(&(t->cdtext[i]));
free(t); 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;
}

View File

@ -16,6 +16,22 @@ struct isrc
unsigned int serial; /* must be 0-99999 */ 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 struct burn_track
{ {
int refcnt; int refcnt;
@ -82,6 +98,9 @@ struct burn_track
/* ts A90910 : conversions from CD XA prepared input */ /* ts A90910 : conversions from CD XA prepared input */
int cdxa_conversion; /* 0=none, 1=remove -xa1 headers (first 8 bytes)*/ int cdxa_conversion; /* 0=none, 1=remove -xa1 headers (first 8 bytes)*/
/* ts B11206 */
struct burn_cdtext *cdtext[8];
}; };
struct burn_session struct burn_session
@ -97,6 +116,13 @@ struct burn_session
int tracks; int tracks;
struct burn_track **track; struct burn_track **track;
int refcnt; 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 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); 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 */ #endif /* BURN__STRUCTURE_H */

View File

@ -405,10 +405,23 @@ struct cue_sheet *burn_create_toc_entries(struct burn_write_opts *o,
"Track mode has unusable value", 0, 0); "Track mode has unusable value", 0, 0);
goto failed; goto failed;
} }
if (o->num_text_packs > 0) if (o->num_text_packs > 0) {
leadin_form = 0x41; leadin_form = 0x41;
else } else {
leadin_form = 0x01; 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); ret = add_cue(sheet, ctladr | 1, 0, 0, leadin_form, 0, runtime);
if (ret <= 0) if (ret <= 0)
goto failed; 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, 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 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 ret, i, j, si, lba, sub_cursor = 0, err, write_lba, sectors = 0;
int self_made_text_packs = 0;
unsigned char *subdata = NULL; unsigned char *subdata = NULL;
struct burn_drive *d = o->drive; struct burn_drive *d = o->drive;
struct buffer *buf = NULL; 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; unsigned char *packs;
#endif #endif
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) if (o->num_text_packs <= 0)
{ret = 1; goto ex;} {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; 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; ret = 1;
ex:; 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(subdata);
BURN_FREE_MEM(buf); BURN_FREE_MEM(buf);
d->busy = was_busy; 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", "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, tnum+1, nwa, ret, d->nwa, (double) burn_track_get_sectors(t) * 2048.0,
(double) d->media_capacity_remaining); (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, LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
msg, 0, 0); msg, 0, 0);
@ -1196,7 +1669,7 @@ int burn_disc_open_track_dvd_minus_r(struct burn_write_opts *o,
sprintf(msg, sprintf(msg,
"DVD pre-track %2.2d : get_nwa(%d), ret= %d , d->nwa= %d", "DVD pre-track %2.2d : get_nwa(%d), ret= %d , d->nwa= %d",
tnum+1, nwa, ret, d->nwa); 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); LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, msg,0,0);
if (nwa > d->nwa) if (nwa > d->nwa)
d->nwa = nwa; d->nwa = nwa;
@ -1256,7 +1729,7 @@ int burn_disc_open_track_dvd_plus_r(struct burn_write_opts *o,
sprintf(msg, sprintf(msg,
"DVD+R pre-track %2.2d : get_nwa(%d), ret= %d , d->nwa= %d", "DVD+R pre-track %2.2d : get_nwa(%d), ret= %d , d->nwa= %d",
tnum+1, nwa, ret, d->nwa); 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); LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, msg,0,0);
if (nwa > d->nwa) if (nwa > d->nwa)
d->nwa = nwa; d->nwa = nwa;
@ -2670,7 +3143,7 @@ return crap. so we send the command, then ignore the result.
sprintf(msg, sprintf(msg,
"SAO appendable d->nwa= %d\n", d->nwa); "SAO appendable d->nwa= %d\n", d->nwa);
libdax_msgs_submit( libdax_msgs_submit(
libdax_messenger, d->global_index, 0x000002, libdax_messenger, d->global_index, 0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
msg, 0, 0); msg, 0, 0);

View File

@ -39,6 +39,13 @@ int burn_write_close_track(struct burn_write_opts *o, struct burn_session *s,
int tnum); int tnum);
int burn_write_close_session(struct burn_write_opts *o); 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 /* mmc5r03c.pdf 6.3.3.3.3: DVD-R DL: Close Function 010b: Close Session