Moved burn_cdtext_from_session() from write.c to cdtext.c
This commit is contained in:
parent
7640970ccc
commit
08f0c6c588
@ -1 +1 @@
|
|||||||
#define Cdrskin_timestamP "2011.12.15.161349"
|
#define Cdrskin_timestamP "2011.12.15.174914"
|
||||||
|
@ -19,11 +19,432 @@
|
|||||||
|
|
||||||
#include "libburn.h"
|
#include "libburn.h"
|
||||||
#include "init.h"
|
#include "init.h"
|
||||||
|
#include "structure.h"
|
||||||
|
#include "options.h"
|
||||||
|
|
||||||
#include "libdax_msgs.h"
|
#include "libdax_msgs.h"
|
||||||
extern struct libdax_msgs *libdax_messenger;
|
extern struct libdax_msgs *libdax_messenger;
|
||||||
|
|
||||||
|
|
||||||
|
/* --------------------- Production of CD-TEXT packs -------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
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) {
|
||||||
|
dummy[0]= 0;
|
||||||
|
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 <= 1 + ((cdt_curr->flags >> idx) & 1))
|
||||||
|
return 0;
|
||||||
|
for (j = 0; j < length; j++)
|
||||||
|
if (cdt_curr->payload[idx][j] != cdt_prev->payload[idx][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;
|
||||||
|
else if (flag & 1)
|
||||||
|
ret = -1;
|
||||||
|
BURN_FREE_MEM(crs.packs);
|
||||||
|
} else if (crs.num_packs > 0) {
|
||||||
|
*text_packs = crs.packs;
|
||||||
|
*num_packs = crs.num_packs;
|
||||||
|
}
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ---------------- Reader of Sony Input Sheet Version 0.7T ------------- */
|
/* ---------------- Reader of Sony Input Sheet Version 0.7T ------------- */
|
||||||
|
|
||||||
|
|
||||||
|
@ -669,422 +669,6 @@ int burn_write_leadout(struct burn_write_opts *o,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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) {
|
|
||||||
dummy[0]= 0;
|
|
||||||
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 <= 1 + ((cdt_curr->flags >> idx) & 1))
|
|
||||||
return 0;
|
|
||||||
for (j = 0; j < length; j++)
|
|
||||||
if (cdt_curr->payload[idx][j] != cdt_prev->payload[idx][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;
|
|
||||||
else if (flag & 1)
|
|
||||||
ret = -1;
|
|
||||||
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,
|
static int burn_create_text_packs(struct burn_write_opts *o,
|
||||||
struct burn_session *s,
|
struct burn_session *s,
|
||||||
int flag)
|
int flag)
|
||||||
|
Loading…
Reference in New Issue
Block a user