New API calls burn_cdtext_from_packfile() and burn_session_by_cue_file()
This commit is contained in:
parent
117188f1e4
commit
f4db5fc855
@ -1 +1 @@
|
|||||||
#define Cdrskin_timestamP "2011.12.22.112138"
|
#define Cdrskin_timestamP "2011.12.25.103852"
|
||||||
|
@ -438,8 +438,11 @@ ex:;
|
|||||||
else if (flag & 1)
|
else if (flag & 1)
|
||||||
ret = -1;
|
ret = -1;
|
||||||
BURN_FREE_MEM(crs.packs);
|
BURN_FREE_MEM(crs.packs);
|
||||||
} else if (crs.num_packs > 0) {
|
} else {
|
||||||
|
if (crs.num_packs > 0)
|
||||||
*text_packs = crs.packs;
|
*text_packs = crs.packs;
|
||||||
|
else
|
||||||
|
BURN_FREE_MEM(crs.packs);
|
||||||
*num_packs = crs.num_packs;
|
*num_packs = crs.num_packs;
|
||||||
}
|
}
|
||||||
return(ret);
|
return(ret);
|
||||||
@ -616,6 +619,7 @@ static int v07t_cdtext_to_track(struct burn_track *track, int block,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ts B11215 API */
|
||||||
int burn_session_input_sheet_v07t(struct burn_session *session,
|
int burn_session_input_sheet_v07t(struct burn_session *session,
|
||||||
char *path, int block, int flag)
|
char *path, int block, int flag)
|
||||||
{
|
{
|
||||||
@ -1006,3 +1010,97 @@ ex:;
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ts B11221 API */
|
||||||
|
int burn_cdtext_from_packfile(char *path, unsigned char **text_packs,
|
||||||
|
int *num_packs, int flag)
|
||||||
|
{
|
||||||
|
int ret = 0, residue = 0;
|
||||||
|
struct stat stbuf;
|
||||||
|
FILE *fp = NULL;
|
||||||
|
unsigned char head[4], tail[1];
|
||||||
|
char *msg = NULL;
|
||||||
|
|
||||||
|
BURN_ALLOC_MEM(msg, char, 4096);
|
||||||
|
|
||||||
|
if (stat(path, &stbuf) == -1) {
|
||||||
|
cannot_open:;
|
||||||
|
sprintf(msg, "Cannot open CD-TEXT pack file '%.4000s'", path);
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020198,
|
||||||
|
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
burn_printify(msg), errno, 0);
|
||||||
|
ret = 0; goto ex;
|
||||||
|
}
|
||||||
|
if (!S_ISREG(stbuf.st_mode))
|
||||||
|
goto not_a_textfile;
|
||||||
|
residue = (stbuf.st_size % 18);
|
||||||
|
if(residue != 4 && residue != 0 && residue != 1) {
|
||||||
|
not_a_textfile:;
|
||||||
|
sprintf(msg,
|
||||||
|
"File is not of usable type or content for CD-TEXT packs: '%.4000s'",
|
||||||
|
path);
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020198,
|
||||||
|
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
burn_printify(msg), 0, 0);
|
||||||
|
ret = 0; goto ex;
|
||||||
|
}
|
||||||
|
if (stbuf.st_size < 18)
|
||||||
|
goto not_a_textfile;
|
||||||
|
|
||||||
|
fp = fopen(path, "rb");
|
||||||
|
if (fp == NULL)
|
||||||
|
goto cannot_open;
|
||||||
|
if (residue == 4) { /* This is for files from cdrecord -vv -toc */
|
||||||
|
ret = fread(head, 4, 1, fp);
|
||||||
|
if (ret != 1) {
|
||||||
|
cannot_read:;
|
||||||
|
sprintf(msg,
|
||||||
|
"Cannot read all bytes from CD-TEXT pack file '%.4000s'",
|
||||||
|
path);
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020198,
|
||||||
|
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
burn_printify(msg), errno, 0);
|
||||||
|
ret = 0; goto ex;
|
||||||
|
}
|
||||||
|
if (head[0] * 256 + head[1] != stbuf.st_size - 2)
|
||||||
|
goto not_a_textfile;
|
||||||
|
}
|
||||||
|
*num_packs = (stbuf.st_size - residue) / 18;
|
||||||
|
if (*num_packs > 2048) {
|
||||||
|
/* Each block can have 256 text packs.
|
||||||
|
There are 8 blocks at most. */
|
||||||
|
sprintf(msg,
|
||||||
|
"CD-Text pack file too large (max. 36864 bytes): '%.4000s'",
|
||||||
|
path);
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x0002018b,
|
||||||
|
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
burn_printify(msg), errno, 0);
|
||||||
|
ret = 0; goto ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
BURN_ALLOC_MEM(*text_packs, unsigned char, *num_packs * 18);
|
||||||
|
ret = fread(*text_packs, *num_packs * 18, 1, fp);
|
||||||
|
if (ret != 1)
|
||||||
|
goto cannot_read;
|
||||||
|
if (residue == 1) { /* This is for Sony CDTEXT files */
|
||||||
|
ret = fread(tail, 1, 1, fp);
|
||||||
|
if (ret != 1)
|
||||||
|
goto cannot_read;
|
||||||
|
if (tail[0] != 0)
|
||||||
|
goto not_a_textfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret= 1;
|
||||||
|
ex:;
|
||||||
|
if (ret <= 0) {
|
||||||
|
BURN_FREE_MEM(*text_packs);
|
||||||
|
*text_packs = NULL;
|
||||||
|
*num_packs = 0;
|
||||||
|
}
|
||||||
|
if (fp != NULL)
|
||||||
|
fclose(fp);
|
||||||
|
BURN_FREE_MEM(msg);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "libburn.h"
|
#include "libburn.h"
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "async.h"
|
#include "async.h"
|
||||||
|
#include "init.h"
|
||||||
|
|
||||||
#include "libdax_msgs.h"
|
#include "libdax_msgs.h"
|
||||||
extern struct libdax_msgs *libdax_messenger;
|
extern struct libdax_msgs *libdax_messenger;
|
||||||
@ -175,7 +176,7 @@ struct burn_source *burn_fd_source_new(int datafd, int subfd, off_t size)
|
|||||||
|
|
||||||
if (datafd == -1)
|
if (datafd == -1)
|
||||||
return NULL;
|
return NULL;
|
||||||
fs = calloc(1, sizeof(struct burn_source_file));
|
fs = burn_alloc_mem(sizeof(struct burn_source_file), 1, 0);
|
||||||
if (fs == NULL) /* ts A70825 */
|
if (fs == NULL) /* ts A70825 */
|
||||||
return NULL;
|
return NULL;
|
||||||
fs->datafd = datafd;
|
fs->datafd = datafd;
|
||||||
@ -510,7 +511,7 @@ struct burn_source *burn_fifo_source_new(struct burn_source *inp,
|
|||||||
"Desired fifo buffer too small", 0, 0);
|
"Desired fifo buffer too small", 0, 0);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
fs = calloc(1, sizeof(struct burn_source_fifo));
|
fs = burn_alloc_mem(sizeof(struct burn_source_fifo), 1, 0);
|
||||||
if (fs == NULL)
|
if (fs == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
fs->is_started = 0;
|
fs->is_started = 0;
|
||||||
@ -757,9 +758,12 @@ int burn_fifo_fill(struct burn_source *source, int bufsize, int flag)
|
|||||||
|
|
||||||
static void offst_free(struct burn_source *source);
|
static void offst_free(struct burn_source *source);
|
||||||
|
|
||||||
static struct burn_source_offst *offst_auth(struct burn_source *source)
|
/* @param flag bit0 = do not check for burn_source_offst, do not return NULL
|
||||||
|
*/
|
||||||
|
static struct burn_source_offst *offst_auth(struct burn_source *source,
|
||||||
|
int flag)
|
||||||
{
|
{
|
||||||
if (source->free_data != offst_free) {
|
if (source->free_data != offst_free && !(flag & 1)) {
|
||||||
libdax_msgs_submit(libdax_messenger, -1, 0x0002017a,
|
libdax_msgs_submit(libdax_messenger, -1, 0x0002017a,
|
||||||
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
"Expected offset source object as parameter",
|
"Expected offset source object as parameter",
|
||||||
@ -773,7 +777,7 @@ static off_t offst_get_size(struct burn_source *source)
|
|||||||
{
|
{
|
||||||
struct burn_source_offst *fs;
|
struct burn_source_offst *fs;
|
||||||
|
|
||||||
if ((fs = offst_auth(source)) == NULL)
|
if ((fs = offst_auth(source, 0)) == NULL)
|
||||||
return (off_t) 0;
|
return (off_t) 0;
|
||||||
return fs->size;
|
return fs->size;
|
||||||
}
|
}
|
||||||
@ -782,7 +786,7 @@ static int offst_set_size(struct burn_source *source, off_t size)
|
|||||||
{
|
{
|
||||||
struct burn_source_offst *fs;
|
struct burn_source_offst *fs;
|
||||||
|
|
||||||
if ((fs = offst_auth(source)) == NULL)
|
if ((fs = offst_auth(source, 0)) == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
fs->size = size;
|
fs->size = size;
|
||||||
return 1;
|
return 1;
|
||||||
@ -792,12 +796,12 @@ static void offst_free(struct burn_source *source)
|
|||||||
{
|
{
|
||||||
struct burn_source_offst *fs;
|
struct burn_source_offst *fs;
|
||||||
|
|
||||||
if ((fs = offst_auth(source)) == NULL)
|
if ((fs = offst_auth(source, 0)) == NULL)
|
||||||
return;
|
return;
|
||||||
if (fs->prev != NULL)
|
if (fs->prev != NULL)
|
||||||
offst_auth(fs->prev)->next = fs->next;
|
offst_auth(fs->prev, 1)->next = fs->next;
|
||||||
if (fs->next != NULL)
|
if (fs->next != NULL)
|
||||||
offst_auth(fs->next)->prev = fs->prev;
|
offst_auth(fs->next, 1)->prev = fs->prev;
|
||||||
if (fs->inp != NULL)
|
if (fs->inp != NULL)
|
||||||
burn_source_free(fs->inp); /* i.e. decrement refcount */
|
burn_source_free(fs->inp); /* i.e. decrement refcount */
|
||||||
free(source->data);
|
free(source->data);
|
||||||
@ -809,13 +813,13 @@ static int offst_read(struct burn_source *source, unsigned char *buffer,
|
|||||||
int ret, to_read, todo;
|
int ret, to_read, todo;
|
||||||
struct burn_source_offst *fs;
|
struct burn_source_offst *fs;
|
||||||
|
|
||||||
if ((fs = offst_auth(source)) == NULL)
|
if ((fs = offst_auth(source, 0)) == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Eventually skip bytes up to start position */;
|
/* Eventually skip bytes up to start position */;
|
||||||
if (!fs->running) {
|
if (!fs->running) {
|
||||||
if (fs->prev != NULL)
|
if (fs->prev != NULL)
|
||||||
fs->pos = offst_auth(fs->prev)->pos;
|
fs->pos = offst_auth(fs->prev, 1)->pos;
|
||||||
fs->running= 1;
|
fs->running= 1;
|
||||||
}
|
}
|
||||||
if(fs->pos < fs->start) {
|
if(fs->pos < fs->start) {
|
||||||
@ -850,7 +854,7 @@ static int offst_cancel(struct burn_source *source)
|
|||||||
int ret;
|
int ret;
|
||||||
struct burn_source_offst *fs;
|
struct burn_source_offst *fs;
|
||||||
|
|
||||||
if ((fs = offst_auth(source)) == NULL)
|
if ((fs = offst_auth(source, 0)) == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
ret = burn_source_cancel(fs->inp);
|
ret = burn_source_cancel(fs->inp);
|
||||||
return ret;
|
return ret;
|
||||||
@ -864,7 +868,7 @@ struct burn_source *burn_offst_source_new(
|
|||||||
struct burn_source_offst *fs, *prev_fs = NULL;
|
struct burn_source_offst *fs, *prev_fs = NULL;
|
||||||
|
|
||||||
if (prev != NULL)
|
if (prev != NULL)
|
||||||
if ((prev_fs = offst_auth(prev)) == NULL)
|
if ((prev_fs = offst_auth(prev, 0)) == NULL)
|
||||||
return NULL; /* Not type burn_source_offst */
|
return NULL; /* Not type burn_source_offst */
|
||||||
|
|
||||||
fs = calloc(1, sizeof(struct burn_source_offst));
|
fs = calloc(1, sizeof(struct burn_source_offst));
|
||||||
@ -889,7 +893,7 @@ struct burn_source *burn_offst_source_new(
|
|||||||
fs->next = NULL;
|
fs->next = NULL;
|
||||||
if (prev != NULL) {
|
if (prev != NULL) {
|
||||||
if (prev_fs->next != NULL) {
|
if (prev_fs->next != NULL) {
|
||||||
offst_auth(prev_fs->next)->prev = src;
|
offst_auth(prev_fs->next, 1)->prev = src;
|
||||||
fs->next = prev_fs->next;
|
fs->next = prev_fs->next;
|
||||||
}
|
}
|
||||||
prev_fs->next = src;
|
prev_fs->next = src;
|
||||||
|
@ -1850,7 +1850,56 @@ int burn_disc_add_session(struct burn_disc *d, struct burn_session *s,
|
|||||||
int burn_disc_remove_session(struct burn_disc *d, struct burn_session *s);
|
int burn_disc_remove_session(struct burn_disc *d, struct burn_session *s);
|
||||||
|
|
||||||
|
|
||||||
/** Create a track (for TAO recording, or to put in a session) */
|
/* ts B11219 */
|
||||||
|
/** Read a CDRWIN cue sheet file and equip the session object by tracks and
|
||||||
|
CD-TEXT according to the content of the file.
|
||||||
|
For a description of CDRWIN file format see
|
||||||
|
http://digitalx.org/cue-sheet/syntax/
|
||||||
|
>>> supported commands: CDTEXTFILE PERFORMER REM SONGWRITER TITLE
|
||||||
|
>>> partly supported commands: CATALOG FILE ISRC INDEX TRACK
|
||||||
|
>>> supported FILE types: BINARY MOTOROLA
|
||||||
|
>>> supported FLAGS:
|
||||||
|
>>> supported TRACK datatypes: AUDIO MODE1/2048
|
||||||
|
>>> ignored commands: POSTGAP PREGAP FLAGS
|
||||||
|
>>> ignored INDEX numbers: 00, 02 to 99
|
||||||
|
>>> ignored CUE SHEET features: CATALOG and ISRC (but supported as CD-TEXT)
|
||||||
|
>>> ignored FLAGS: DCP 4CH PRE SCMS
|
||||||
|
>>> not allowed: mixing of ADUIO and MODE1/2048
|
||||||
|
>>> not allowed: unsupported FILE types
|
||||||
|
>>> not allowed: unsupported TRACK datatypes
|
||||||
|
>>>
|
||||||
|
>>>
|
||||||
|
@param session Session where to attach tracks. It must not yet have
|
||||||
|
tracks or else this call will fail.
|
||||||
|
@param path Filesystem address of the CDRWIN cue sheet file.
|
||||||
|
Normally with suffix .cue
|
||||||
|
@param fifo_size Number of bytes in fifo. This will be rounded up by
|
||||||
|
the block size of the track mode. <= 0 means no fifo.
|
||||||
|
@param fifo Returns a reference to the burn_source object that
|
||||||
|
was installed as fifo between FILE and the track
|
||||||
|
burn sources. One may use this to inquire the fifo
|
||||||
|
state. Dispose it by burn_source_free() when no longer
|
||||||
|
needed. It is permissible to pass this parameter to
|
||||||
|
libburn as NULL, in order to immediately drop ownership
|
||||||
|
on the fifo.
|
||||||
|
@param text_packs Returns pre-formatted CD-TEXT packs resulting from
|
||||||
|
cue sheet command CDTEXTFILE. To be used with call
|
||||||
|
burn_write_opts_set_leadin_text().
|
||||||
|
It is permissible to pass this parameter to libburn
|
||||||
|
as NULL, in order to disable CDTEXTFILE.
|
||||||
|
@param num_packs Returns the number of 18 byte records in text_packs.
|
||||||
|
@param flag Bitfield for control purposes.
|
||||||
|
bit0= Do not attach CD-TEXT information to session and
|
||||||
|
tracks. Do not load text_packs.
|
||||||
|
@return > 0 indicates success, <= 0 indicates failure
|
||||||
|
@since 1.2.0
|
||||||
|
*/
|
||||||
|
int burn_session_by_cue_file(struct burn_session *session,
|
||||||
|
char *path, int fifo_size, struct burn_source **fifo,
|
||||||
|
unsigned char **text_packs, int *num_packs, int flag);
|
||||||
|
|
||||||
|
|
||||||
|
/** Create a track */
|
||||||
struct burn_track *burn_track_create(void);
|
struct burn_track *burn_track_create(void);
|
||||||
|
|
||||||
/** Free a track
|
/** Free a track
|
||||||
@ -2074,6 +2123,9 @@ int burn_session_set_cdtext(struct burn_session *s, int block,
|
|||||||
See above burn_session_set_cdtext().
|
See above burn_session_set_cdtext().
|
||||||
@param payload Will return a pointer to text or binary bytes.
|
@param payload Will return a pointer to text or binary bytes.
|
||||||
Not a copy of data. Do not free() this address.
|
Not a copy of data. Do not free() this address.
|
||||||
|
If no text attribute is attached for pack type and
|
||||||
|
block, then payload is returned as NULL. The return
|
||||||
|
value will not indicate error in this case.
|
||||||
@pram length Will return the number of bytes pointed to by payload.
|
@pram length Will return the number of bytes pointed to by payload.
|
||||||
Including terminating 0-bytes.
|
Including terminating 0-bytes.
|
||||||
@param flag Bitfield for control purposes. Unused yet. Submit 0.
|
@param flag Bitfield for control purposes. Unused yet. Submit 0.
|
||||||
@ -2145,6 +2197,26 @@ int burn_cdtext_from_session(struct burn_session *s,
|
|||||||
int burn_session_dispose_cdtext(struct burn_session *s, int block);
|
int burn_session_dispose_cdtext(struct burn_session *s, int block);
|
||||||
|
|
||||||
|
|
||||||
|
/* ts B11221*/
|
||||||
|
/** Read an array of CD-TEXT packs from a file. This array should be suitable
|
||||||
|
for burn_write_opts_set_leadin_text().
|
||||||
|
The function tolerates and removes 4-byte headers as produced by
|
||||||
|
cdrecord -vv -toc, if this header tells the correct number of bytes which
|
||||||
|
matches the file size. If no 4-byte header is present, then the function
|
||||||
|
tolerates and removes a trailing 0-byte as of Sony specs.
|
||||||
|
@param path Filesystem address of the CD-TEXT pack file.
|
||||||
|
Normally with suffix .cdt or .dat
|
||||||
|
@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. Unused yet.Submit 0.
|
||||||
|
@return 0 is success, <= 0 failure
|
||||||
|
@since 1.2.0
|
||||||
|
*/
|
||||||
|
int burn_cdtext_from_packfile(char *path, unsigned char **text_packs,
|
||||||
|
int *num_packs, int flag);
|
||||||
|
|
||||||
|
|
||||||
/** 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
|
||||||
@ -2214,6 +2286,9 @@ int burn_track_set_cdtext(struct burn_track *t, int block,
|
|||||||
See above burn_track_set_cdtext().
|
See above burn_track_set_cdtext().
|
||||||
@param payload Will return a pointer to text bytes.
|
@param payload Will return a pointer to text bytes.
|
||||||
Not a copy of data. Do not free() this address.
|
Not a copy of data. Do not free() this address.
|
||||||
|
If no text attribute is attached for pack type and
|
||||||
|
block, then payload is returned as NULL. The return
|
||||||
|
value will not indicate error in this case.
|
||||||
@pram length Will return the number of bytes pointed to by payload.
|
@pram length Will return the number of bytes pointed to by payload.
|
||||||
Including terminating 0-bytes.
|
Including terminating 0-bytes.
|
||||||
@param flag Bitfield for control purposes. Unused yet. Submit 0.
|
@param flag Bitfield for control purposes. Unused yet. Submit 0.
|
||||||
@ -2424,14 +2499,15 @@ struct burn_source *burn_offst_source_new(
|
|||||||
/** Creates a fifo which acts as proxy for an already existing data source.
|
/** Creates a fifo which acts as proxy for an already existing data source.
|
||||||
The fifo provides a ring buffer which shall smoothen the data stream
|
The fifo provides a ring buffer which shall smoothen the data stream
|
||||||
between burn_source and writer thread. Each fifo serves only for one
|
between burn_source and writer thread. Each fifo serves only for one
|
||||||
data source and gets attached to one track as its only data source
|
data source. It may be attached to one track as its only data source
|
||||||
by burn_track_set_source().
|
by burn_track_set_source(), or it may be used as input for other burn
|
||||||
|
sources.
|
||||||
A fifo starts its life in "standby" mode with no buffer space allocated.
|
A fifo starts its life in "standby" mode with no buffer space allocated.
|
||||||
As soon as its track requires bytes, the fifo establishes a worker thread
|
As soon as its consumer requires bytes, the fifo establishes a worker
|
||||||
and allocates its buffer. After input has ended and all buffer content is
|
thread and allocates its buffer. After input has ended and all buffer
|
||||||
consumed, the buffer space gets freed and the worker thread ends.
|
content is consumed, the buffer space gets freed and the worker thread
|
||||||
This happens asynchronously. So expect two buffers and worker threads to
|
ends. This happens asynchronously. So expect two buffers and worker threads
|
||||||
exist for a short time between tracks. Be modest in your size demands if
|
to exist for a short time between tracks. Be modest in your size demands if
|
||||||
multiple tracks are to be expected.
|
multiple tracks are to be expected.
|
||||||
@param inp The burn_source for which the fifo shall act as proxy.
|
@param inp The burn_source for which the fifo shall act as proxy.
|
||||||
It can be disposed by burn_source_free() immediately
|
It can be disposed by burn_source_free() immediately
|
||||||
@ -3699,7 +3775,6 @@ int libdax_audioxtr_detach_fd(struct libdax_audioxtr *o, int *fd, int flag);
|
|||||||
int libdax_audioxtr_destroy(struct libdax_audioxtr **xtr, int flag);
|
int libdax_audioxtr_destroy(struct libdax_audioxtr **xtr, int flag);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef DOXYGEN
|
#ifndef DOXYGEN
|
||||||
|
|
||||||
BURN_END_DECLS
|
BURN_END_DECLS
|
||||||
|
@ -5,6 +5,7 @@ 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_cdtext_from_session;
|
||||||
|
burn_cdtext_from_packfile;
|
||||||
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,6 +114,7 @@ burn_read_opts_transfer_damaged_blocks;
|
|||||||
burn_scsi_transport_id;
|
burn_scsi_transport_id;
|
||||||
burn_sectors_to_msf;
|
burn_sectors_to_msf;
|
||||||
burn_session_add_track;
|
burn_session_add_track;
|
||||||
|
burn_session_by_cue_file;
|
||||||
burn_session_create;
|
burn_session_create;
|
||||||
burn_session_dispose_cdtext;
|
burn_session_dispose_cdtext;
|
||||||
burn_session_free;
|
burn_session_free;
|
||||||
|
@ -583,11 +583,14 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
|
|||||||
0x0002018e (FAILURE,HIGH) = Too many CD-TEXT packs in block
|
0x0002018e (FAILURE,HIGH) = Too many CD-TEXT packs in block
|
||||||
0x0002018f (FAILURE,HIGH) = CD-TEXT pack CRC mismatch
|
0x0002018f (FAILURE,HIGH) = CD-TEXT pack CRC mismatch
|
||||||
0x00020190 (WARNING,HIGH) = CD-TEXT pack CRC mismatch had to be corrected
|
0x00020190 (WARNING,HIGH) = CD-TEXT pack CRC mismatch had to be corrected
|
||||||
0x00020191 (FAILURE,HIGH) = Unknown v07t parameter
|
0x00020191 (FAILURE,HIGH) = Unknown parameter in text input file
|
||||||
0x00020192 (FAILURE,HIGH) = Input sheet v07t sequence error
|
0x00020192 (FAILURE,HIGH) = Text input file sequence error
|
||||||
0x00020193 (FAILURE,HIGH) = Input sheet v07t readability problem
|
0x00020193 (FAILURE,HIGH) = Text input file readability problem
|
||||||
0x00020194 (FAILURE,HIGH) = Input sheet v07t syntax error
|
0x00020194 (FAILURE,HIGH) = Text input file syntax error or specs violation
|
||||||
0x00020195 (WARNING,HIGH) = Input sheet v07t warning
|
0x00020195 (WARNING,HIGH) = Text input file warning
|
||||||
|
0x00020196 (FAILURE,HIGH) = Session has already defined tracks
|
||||||
|
0x00020197 (FAILURE,HIGH) = Unsupported text input file feature
|
||||||
|
0x00020198 (FAILURE,HIGH) = CD-TEXT pack file readability problem
|
||||||
|
|
||||||
|
|
||||||
libdax_audioxtr:
|
libdax_audioxtr:
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "libburn.h"
|
#include "libburn.h"
|
||||||
#include "source.h"
|
#include "source.h"
|
||||||
#include "structure.h"
|
#include "structure.h"
|
||||||
|
#include "init.h"
|
||||||
|
|
||||||
void burn_source_free(struct burn_source *src)
|
void burn_source_free(struct burn_source *src)
|
||||||
{
|
{
|
||||||
@ -41,12 +42,10 @@ struct burn_source *burn_source_new(void)
|
|||||||
{
|
{
|
||||||
struct burn_source *out;
|
struct burn_source *out;
|
||||||
|
|
||||||
out = calloc(1, sizeof(struct burn_source));
|
/* ts A70825 , B11219 */
|
||||||
|
out = burn_alloc_mem(sizeof(struct burn_source), 1, 0);
|
||||||
/* ts A70825 */
|
|
||||||
if (out == NULL)
|
if (out == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
memset((char *) out, 0, sizeof(struct burn_source));
|
|
||||||
|
|
||||||
out->refcount = 1;
|
out->refcount = 1;
|
||||||
return out;
|
return out;
|
||||||
|
@ -15,11 +15,18 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#include "libburn.h"
|
#include "libburn.h"
|
||||||
#include "structure.h"
|
#include "structure.h"
|
||||||
#include "write.h"
|
#include "write.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "init.h"
|
#include "init.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
#include "libdax_msgs.h"
|
#include "libdax_msgs.h"
|
||||||
extern struct libdax_msgs *libdax_messenger;
|
extern struct libdax_msgs *libdax_messenger;
|
||||||
@ -849,6 +856,11 @@ int burn_track_get_cdtext(struct burn_track *t, int block,
|
|||||||
|
|
||||||
if (burn_cdtext_check_blockno(block) <= 0)
|
if (burn_cdtext_check_blockno(block) <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
if (t->cdtext[block] == NULL) {
|
||||||
|
*payload = NULL;
|
||||||
|
*length = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
ret = burn_cdtext_get(t->cdtext[block], pack_type, pack_type_name,
|
ret = burn_cdtext_get(t->cdtext[block], pack_type, pack_type_name,
|
||||||
payload, length, 0);
|
payload, length, 0);
|
||||||
return ret;
|
return ret;
|
||||||
@ -899,6 +911,12 @@ int burn_session_get_cdtext(struct burn_session *s, int block,
|
|||||||
|
|
||||||
if (burn_cdtext_check_blockno(block) <= 0)
|
if (burn_cdtext_check_blockno(block) <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (s->cdtext[block] == NULL) {
|
||||||
|
*payload = NULL;
|
||||||
|
*length = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
ret = burn_cdtext_get(s->cdtext[block], pack_type, pack_type_name,
|
ret = burn_cdtext_get(s->cdtext[block], pack_type, pack_type_name,
|
||||||
payload, length, 0);
|
payload, length, 0);
|
||||||
return ret;
|
return ret;
|
||||||
@ -962,3 +980,779 @@ int burn_session_dispose_cdtext(struct burn_session *s, int block)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* --------------------- Reading CDRWIN cue sheet files ----------------- */
|
||||||
|
|
||||||
|
|
||||||
|
struct burn_cue_file_cursor {
|
||||||
|
char *cdtextfile;
|
||||||
|
char *source_file;
|
||||||
|
off_t source_size;
|
||||||
|
struct burn_source *file_source;
|
||||||
|
int fifo_size;
|
||||||
|
struct burn_source *fifo;
|
||||||
|
int swap_audio_bytes;
|
||||||
|
int no_cdtext;
|
||||||
|
struct burn_source *offst_source;
|
||||||
|
int current_file_ba;
|
||||||
|
struct burn_track *prev_track;
|
||||||
|
int prev_file_ba;
|
||||||
|
int prev_block_size;
|
||||||
|
struct burn_track *track;
|
||||||
|
int track_no;
|
||||||
|
int track_has_index;
|
||||||
|
int track_has_source;
|
||||||
|
int block_size;
|
||||||
|
int block_size_locked;
|
||||||
|
int flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static int cue_crs_new(struct burn_cue_file_cursor **reply, int flag)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct burn_cue_file_cursor *crs;
|
||||||
|
|
||||||
|
BURN_ALLOC_MEM(crs, struct burn_cue_file_cursor, 1);
|
||||||
|
crs->cdtextfile = NULL;
|
||||||
|
crs->source_file = NULL;
|
||||||
|
crs->source_size = -1;
|
||||||
|
crs->file_source = NULL;
|
||||||
|
crs->fifo_size = 0;
|
||||||
|
crs->fifo = NULL;
|
||||||
|
crs->swap_audio_bytes = 0;
|
||||||
|
crs->no_cdtext = 0;
|
||||||
|
crs->offst_source = NULL;
|
||||||
|
crs->current_file_ba = -1000000000;
|
||||||
|
crs->prev_track = NULL;
|
||||||
|
crs->prev_file_ba = -1000000000;
|
||||||
|
crs->prev_block_size = 0;
|
||||||
|
crs->track = NULL;
|
||||||
|
crs->track_no = 0;
|
||||||
|
crs->track_has_index = 0;
|
||||||
|
crs->track_has_source = 0;
|
||||||
|
crs->block_size = 0;
|
||||||
|
crs->block_size_locked = 0;
|
||||||
|
crs->flags = 0;
|
||||||
|
|
||||||
|
*reply = crs;
|
||||||
|
ret = 1;
|
||||||
|
ex:;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int cue_crs_destroy(struct burn_cue_file_cursor **victim, int flag)
|
||||||
|
{
|
||||||
|
struct burn_cue_file_cursor *crs;
|
||||||
|
|
||||||
|
if (*victim == NULL)
|
||||||
|
return 2;
|
||||||
|
crs = *victim;
|
||||||
|
if (crs->cdtextfile != NULL)
|
||||||
|
free(crs->cdtextfile);
|
||||||
|
if (crs->source_file != NULL)
|
||||||
|
free(crs->source_file);
|
||||||
|
if (crs->file_source != NULL)
|
||||||
|
burn_source_free(crs->file_source);
|
||||||
|
if (crs->fifo != NULL)
|
||||||
|
burn_source_free(crs->fifo);
|
||||||
|
if (crs->offst_source != NULL)
|
||||||
|
burn_source_free(crs->offst_source);
|
||||||
|
if (crs->prev_track != NULL)
|
||||||
|
burn_track_free(crs->prev_track);
|
||||||
|
if (crs->track != NULL)
|
||||||
|
burn_track_free(crs->track);
|
||||||
|
BURN_FREE_MEM(crs);
|
||||||
|
*victim = NULL;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char *cue_unquote_text(char *text, int flag)
|
||||||
|
{
|
||||||
|
char *ept, *spt;
|
||||||
|
|
||||||
|
spt = text;
|
||||||
|
for (ept = text + strlen(text); ept > text; ept--)
|
||||||
|
if (*(ept - 1) != 32 && *(ept - 1) != 9)
|
||||||
|
break;
|
||||||
|
if (text[0] == '"') {
|
||||||
|
spt = text + 1;
|
||||||
|
if (ept > spt)
|
||||||
|
if (*(ept - 1) == '"')
|
||||||
|
ept--;
|
||||||
|
}
|
||||||
|
*ept = 0;
|
||||||
|
return spt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* @param flag bit0= insist in having a track object
|
||||||
|
bit1= remove quotation marks if present
|
||||||
|
*/
|
||||||
|
static int cue_set_cdtext(struct burn_session *session,
|
||||||
|
struct burn_track *track, int pack_type, char *text,
|
||||||
|
struct burn_cue_file_cursor *crs, int flag)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
char *payload;
|
||||||
|
|
||||||
|
if (crs->no_cdtext == 1) {
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020195,
|
||||||
|
LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
"In cue sheet file: Being set to ignore all CD-TEXT aspects",
|
||||||
|
0, 0);
|
||||||
|
crs->no_cdtext = 2;
|
||||||
|
}
|
||||||
|
if (crs->no_cdtext)
|
||||||
|
return 2;
|
||||||
|
if ((flag & 1) && track == NULL) {
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020192,
|
||||||
|
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
"Track attribute set before first track in cue sheet file",
|
||||||
|
0, 0);
|
||||||
|
ret = 0; goto ex;
|
||||||
|
}
|
||||||
|
if (flag & 2)
|
||||||
|
payload = cue_unquote_text(text, 0);
|
||||||
|
else
|
||||||
|
payload = text;
|
||||||
|
if (track != NULL) {
|
||||||
|
ret = burn_track_set_cdtext(track, 0, pack_type, "",
|
||||||
|
(unsigned char *) payload,
|
||||||
|
strlen(payload) + 1, 0);
|
||||||
|
} else {
|
||||||
|
ret = burn_session_set_cdtext(session, 0, pack_type, "",
|
||||||
|
(unsigned char *) payload,
|
||||||
|
strlen(payload) + 1, 0);
|
||||||
|
}
|
||||||
|
ex:;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int cue_attach_track(struct burn_session *session,
|
||||||
|
struct burn_cue_file_cursor *crs, int flag)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (crs->track == NULL)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
if (!crs->track_has_source) {
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020194,
|
||||||
|
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
"In cue sheet file: TRACK without INDEX 01", 0, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (crs->track_no > 1 && session->tracks == 0) {
|
||||||
|
|
||||||
|
/* >>> ??? implement ? */;
|
||||||
|
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020195,
|
||||||
|
LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
"In cue sheet file: TRACK numbering does not start with 01",
|
||||||
|
0, 0);
|
||||||
|
}
|
||||||
|
ret = burn_session_add_track(session, crs->track, BURN_POS_END);
|
||||||
|
if (ret <= 0)
|
||||||
|
return ret;
|
||||||
|
if (crs->prev_track != NULL)
|
||||||
|
burn_track_free(crs->prev_track); /* release reference */
|
||||||
|
crs->prev_track = crs->track;
|
||||||
|
crs->prev_file_ba = crs->current_file_ba;
|
||||||
|
crs->prev_block_size = crs->block_size;
|
||||||
|
crs->track = NULL;
|
||||||
|
crs->track_has_index = crs->track_has_source = 0;
|
||||||
|
crs->current_file_ba = -1;
|
||||||
|
if (!crs->block_size_locked)
|
||||||
|
crs->block_size = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* @param flag bit0= do not alter the content of *payload
|
||||||
|
do not change *payload
|
||||||
|
*/
|
||||||
|
static int cue_read_number(char **payload, int *number, int flag)
|
||||||
|
{
|
||||||
|
int ret, at_end = 0;
|
||||||
|
char *apt, *msg = NULL;
|
||||||
|
|
||||||
|
for(apt = *payload; *apt != 0 && *apt != 32 && *apt != 9; apt++);
|
||||||
|
if (*apt == 0)
|
||||||
|
at_end = 1;
|
||||||
|
else if (!(flag & 1))
|
||||||
|
*apt = 0;
|
||||||
|
ret = sscanf(*payload, "%d", number);
|
||||||
|
if (ret != 1) {
|
||||||
|
BURN_ALLOC_MEM(msg, char, 4096);
|
||||||
|
sprintf(msg,
|
||||||
|
"Unsuitable number in cue sheet file: '%.4000s'",
|
||||||
|
*payload);
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020194,
|
||||||
|
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
burn_printify(msg), 0, 0);
|
||||||
|
ret = 0; goto ex;
|
||||||
|
}
|
||||||
|
/* Find start of next argument */
|
||||||
|
if (!at_end)
|
||||||
|
for (apt++; *apt == 32 || *apt == 9; apt++);
|
||||||
|
if (!(flag & 1))
|
||||||
|
*payload = apt;
|
||||||
|
|
||||||
|
ret = 1;
|
||||||
|
ex:
|
||||||
|
BURN_FREE_MEM(msg);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int cue_create_file_source(char *path, struct burn_cue_file_cursor *crs,
|
||||||
|
int flag)
|
||||||
|
{
|
||||||
|
int fd, ret;
|
||||||
|
char *msg = NULL;
|
||||||
|
|
||||||
|
BURN_ALLOC_MEM(msg, char, 4096);
|
||||||
|
|
||||||
|
fd = open(path, O_RDONLY);
|
||||||
|
if (fd == -1) {
|
||||||
|
sprintf(msg, "In cue sheet: Cannot open FILE '%.4000s'", path);
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020193,
|
||||||
|
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
burn_printify(msg), errno, 0);
|
||||||
|
ret = 0; goto ex;
|
||||||
|
}
|
||||||
|
crs->file_source = burn_fd_source_new(fd, -1, crs->source_size);
|
||||||
|
if (crs->file_source == NULL) {
|
||||||
|
ret = -1; goto ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 1;
|
||||||
|
ex:;
|
||||||
|
BURN_FREE_MEM(msg);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int cue_interpret_line(struct burn_session *session, char *line,
|
||||||
|
struct burn_cue_file_cursor *crs, int flag)
|
||||||
|
{
|
||||||
|
int ret, mode, index_no, minute, second, frame, file_ba, chunks;
|
||||||
|
int block_size;
|
||||||
|
off_t size;
|
||||||
|
char *cmd, *apt, *msg = NULL, msf[3], *msf_pt, *cpt, *filetype;
|
||||||
|
struct burn_source *src, *inp_src;
|
||||||
|
enum burn_source_status source_status;
|
||||||
|
struct stat stbuf;
|
||||||
|
|
||||||
|
BURN_ALLOC_MEM(msg, char, 4096);
|
||||||
|
|
||||||
|
if (line[0] == 0 || line[0] == '#') {
|
||||||
|
ret = 1; goto ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (cmd = line; *cmd == 32 || *cmd == 9; cmd++);
|
||||||
|
for(apt = cmd; *apt != 0 && *apt != 32 && *apt != 9; apt++);
|
||||||
|
if (*apt != 0) {
|
||||||
|
*apt = 0;
|
||||||
|
for (apt++; *apt == 32 || *apt == 9; apt++);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(cmd, "CATALOG") == 0) {
|
||||||
|
ret = cue_set_cdtext(session, NULL, 0x8e, apt, crs, 0);
|
||||||
|
if (ret <= 0)
|
||||||
|
goto ex;
|
||||||
|
|
||||||
|
/* >>> ??? data for burn_write_opts_set_mediacatalog ?
|
||||||
|
(not implemented yet in SAO) */
|
||||||
|
|
||||||
|
|
||||||
|
} else if (strcmp(cmd, "CDTEXTFILE") == 0) {
|
||||||
|
if (crs->no_cdtext) {
|
||||||
|
ret = 1; goto ex;
|
||||||
|
}
|
||||||
|
apt = cue_unquote_text(apt, 0);
|
||||||
|
if (crs->cdtextfile != NULL)
|
||||||
|
free(crs->cdtextfile);
|
||||||
|
crs->cdtextfile = strdup(apt);
|
||||||
|
if (crs->cdtextfile == NULL) {
|
||||||
|
out_of_mem:;
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00000003,
|
||||||
|
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
"Out of virtual memory", 0, 0);
|
||||||
|
ret = -1; goto ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (strcmp(cmd, "FILE") == 0) {
|
||||||
|
if (crs->file_source != NULL) {
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020192,
|
||||||
|
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
"In cue sheet file: Multiple occurences of FILE",
|
||||||
|
0, 0);
|
||||||
|
ret = 0; goto ex;
|
||||||
|
}
|
||||||
|
/* Obtain type */
|
||||||
|
for (cpt = apt + (strlen(apt) - 1);
|
||||||
|
cpt > apt && (*cpt == 32 || *cpt == 9); cpt--);
|
||||||
|
cpt[1] = 0;
|
||||||
|
for (; cpt > apt && *cpt != 32 && *cpt != 9; cpt--);
|
||||||
|
if (cpt <= apt) {
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020194,
|
||||||
|
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
"In cue sheet file: FILE without type word",
|
||||||
|
0, 0);
|
||||||
|
ret = 0; goto ex;
|
||||||
|
}
|
||||||
|
*cpt = 0;
|
||||||
|
filetype = cpt + 1;
|
||||||
|
if (strcmp(filetype, "BINARY") == 0) {
|
||||||
|
crs->swap_audio_bytes = 0;
|
||||||
|
} else if (strcmp(filetype, "MOTOROLA") == 0) {
|
||||||
|
crs->swap_audio_bytes = 1;
|
||||||
|
} else if (strcmp(filetype, "WAVE") == 0 && 0 ) {
|
||||||
|
|
||||||
|
/* >>> Use libdax_audioxtr_* functions to extract */;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
sprintf(msg,
|
||||||
|
"In cue sheet file: Unsupported FILE type '%.4000s'",
|
||||||
|
filetype);
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020197,
|
||||||
|
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
burn_printify(msg), 0, 0);
|
||||||
|
ret = 0; goto ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
apt = cue_unquote_text(apt, 0);
|
||||||
|
if (*apt == 0)
|
||||||
|
ret = -1;
|
||||||
|
else
|
||||||
|
ret = stat(apt, &stbuf);
|
||||||
|
if (ret == -1) {
|
||||||
|
not_usable_file:;
|
||||||
|
sprintf(msg,
|
||||||
|
"In cue sheet file: Unusable FILE '%.4000s'",
|
||||||
|
apt);
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020194,
|
||||||
|
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
burn_printify(msg), 0, 0);
|
||||||
|
ret = 0; goto ex;
|
||||||
|
}
|
||||||
|
if (!S_ISREG(stbuf.st_mode))
|
||||||
|
goto not_usable_file;
|
||||||
|
crs->source_size = stbuf.st_size;
|
||||||
|
if (crs->source_file != NULL)
|
||||||
|
free(crs->source_file);
|
||||||
|
crs->source_file = strdup(apt);
|
||||||
|
if (crs->source_file == NULL)
|
||||||
|
goto out_of_mem;
|
||||||
|
ret = cue_create_file_source(apt, crs, 0);
|
||||||
|
if (ret <= 0)
|
||||||
|
goto ex;
|
||||||
|
|
||||||
|
} else if (strcmp(cmd, "FLAGS") == 0) {
|
||||||
|
|
||||||
|
/* >>> Interpret DCP 4CH PRE SCMS into crs->flags */;
|
||||||
|
|
||||||
|
} else if (strcmp(cmd, "INDEX") == 0) {
|
||||||
|
if (crs->track == NULL) {
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020192,
|
||||||
|
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
"In cue sheet file: INDEX found before TRACK",
|
||||||
|
0, 0);
|
||||||
|
ret = 0; goto ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = cue_read_number(&apt, &index_no, 0);
|
||||||
|
if (ret <= 0)
|
||||||
|
goto ex;
|
||||||
|
|
||||||
|
/* Obtain time point */
|
||||||
|
if (strlen(apt) < 8) {
|
||||||
|
no_time_point:;
|
||||||
|
sprintf(msg,
|
||||||
|
"Inappropriate cue sheet file index time point '%.4000s'",
|
||||||
|
apt);
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020194,
|
||||||
|
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
burn_printify(msg), 0, 0);
|
||||||
|
ret = 0; goto ex;
|
||||||
|
}
|
||||||
|
if (apt[2] != ':' || apt[5] != ':' ||
|
||||||
|
(apt[8] != 0 && apt[8] != 32 && apt[8] != 9))
|
||||||
|
goto no_time_point;
|
||||||
|
msf[2] = 0;
|
||||||
|
msf_pt = msf;
|
||||||
|
strncpy(msf, apt, 2);
|
||||||
|
ret = cue_read_number(&msf_pt, &minute, 1);
|
||||||
|
if (ret <= 0)
|
||||||
|
goto ex;
|
||||||
|
strncpy(msf, apt + 3, 2);
|
||||||
|
ret = cue_read_number(&msf_pt, &second, 1);
|
||||||
|
if (ret <= 0)
|
||||||
|
goto ex;
|
||||||
|
strncpy(msf, apt + 6, 2);
|
||||||
|
ret = cue_read_number(&msf_pt, &frame, 1);
|
||||||
|
if (ret <= 0)
|
||||||
|
goto ex;
|
||||||
|
|
||||||
|
file_ba = ((minute * 60) + second ) * 75 + frame;
|
||||||
|
if (file_ba <= crs->prev_file_ba) {
|
||||||
|
overlapping_ba:;
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020192,
|
||||||
|
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
"Overlapping INDEX addresses in cue sheet file",
|
||||||
|
0, 0);
|
||||||
|
ret = 0; goto ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (crs->prev_track != NULL && !crs->track_has_index) {
|
||||||
|
size = (file_ba - crs->prev_file_ba) *
|
||||||
|
crs->prev_block_size;
|
||||||
|
if (size <= 0)
|
||||||
|
goto overlapping_ba;
|
||||||
|
burn_track_set_size(crs->prev_track, size);
|
||||||
|
}
|
||||||
|
crs->track_has_index = 1;
|
||||||
|
|
||||||
|
if (index_no != 1) {
|
||||||
|
|
||||||
|
/* >>> what to do with index != 1 ? */;
|
||||||
|
/* >>> INDEX 00 defines start of a track pregap
|
||||||
|
Pregap and postgap still has to be properly
|
||||||
|
mapped onto track
|
||||||
|
*/;
|
||||||
|
|
||||||
|
|
||||||
|
ret = 1; goto ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (crs->block_size_locked && crs->fifo == NULL &&
|
||||||
|
crs->fifo_size > 0) {
|
||||||
|
/* Now that the block size is known from TRACK:
|
||||||
|
Create fifo and use it for creating the offset
|
||||||
|
sources. This will fixate the block size to one
|
||||||
|
common value.
|
||||||
|
*/
|
||||||
|
chunks = crs->fifo_size / crs->block_size +
|
||||||
|
!!(crs->fifo_size % crs->block_size);
|
||||||
|
if (chunks < 4)
|
||||||
|
chunks = 4;
|
||||||
|
crs->fifo = burn_fifo_source_new(crs->file_source,
|
||||||
|
crs->block_size, chunks, 0);
|
||||||
|
if (crs->fifo == NULL) {
|
||||||
|
ret = -1; goto ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (crs->fifo != NULL)
|
||||||
|
inp_src = crs->fifo;
|
||||||
|
else
|
||||||
|
inp_src = crs->file_source;
|
||||||
|
src = burn_offst_source_new(inp_src, crs->offst_source,
|
||||||
|
(off_t) (file_ba * crs->block_size), (off_t) 0, 0);
|
||||||
|
if (src == NULL)
|
||||||
|
goto out_of_mem;
|
||||||
|
|
||||||
|
/* >>> Alternative to above fifo creation:
|
||||||
|
Create a fifo for each track track.
|
||||||
|
This will be necessary if mixed-mode sessions get supporded.
|
||||||
|
*/;
|
||||||
|
|
||||||
|
source_status = burn_track_set_source(crs->track, src);
|
||||||
|
if (source_status != BURN_SOURCE_OK) {
|
||||||
|
ret = -1; goto ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Switch current source in crs */
|
||||||
|
if (crs->offst_source != NULL)
|
||||||
|
burn_source_free(crs->offst_source);
|
||||||
|
crs->offst_source = src;
|
||||||
|
crs->current_file_ba = file_ba;
|
||||||
|
crs->track_has_source = 1;
|
||||||
|
|
||||||
|
} else if (strcmp(cmd, "ISRC") == 0) {
|
||||||
|
ret = cue_set_cdtext(session, crs->track, 0x8e, apt, crs,
|
||||||
|
1 | 2);
|
||||||
|
if (ret <= 0)
|
||||||
|
goto ex;
|
||||||
|
|
||||||
|
/* >>> ??? burn_track_set_isrc ?
|
||||||
|
(not implemented yet in SAO) */
|
||||||
|
|
||||||
|
} else if (strcmp(cmd, "PERFORMER") == 0) {
|
||||||
|
ret = cue_set_cdtext(session, crs->track, 0x81, apt, crs, 2);
|
||||||
|
if (ret <= 0)
|
||||||
|
goto ex;
|
||||||
|
|
||||||
|
} else if (strcmp(cmd, "POSTGAP") == 0) {
|
||||||
|
|
||||||
|
/* >>> ??? implement ? */;
|
||||||
|
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020195,
|
||||||
|
LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
"In cue sheet file: POSTGAP command not supported",
|
||||||
|
0, 0);
|
||||||
|
|
||||||
|
} else if (strcmp(cmd, "PREGAP") == 0) {
|
||||||
|
|
||||||
|
/* >>> ??? implement ? */;
|
||||||
|
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020195,
|
||||||
|
LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
"In cue sheet file: PREGAP command not supported",
|
||||||
|
0, 0);
|
||||||
|
|
||||||
|
} else if (strcmp(cmd, "REM") == 0) {
|
||||||
|
;
|
||||||
|
|
||||||
|
} else if (strcmp(cmd, "SONGWRITER") == 0) {
|
||||||
|
ret = cue_set_cdtext(session, crs->track, 0x82, apt, crs, 2);
|
||||||
|
if (ret <= 0)
|
||||||
|
goto ex;
|
||||||
|
|
||||||
|
} else if (strcmp(cmd, "TITLE") == 0) {
|
||||||
|
ret = cue_set_cdtext(session, crs->track, 0x80, apt, crs, 2);
|
||||||
|
if (ret <= 0)
|
||||||
|
goto ex;
|
||||||
|
|
||||||
|
} else if (strcmp(cmd, "TRACK") == 0) {
|
||||||
|
if (crs->file_source == NULL) {
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020192,
|
||||||
|
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
"No FILE defined before TRACK in cue sheet file",
|
||||||
|
0, 0);
|
||||||
|
ret = 0; goto ex;
|
||||||
|
}
|
||||||
|
/* Attach previous track to session */
|
||||||
|
ret = cue_attach_track(session, crs, 0);
|
||||||
|
if (ret <= 0)
|
||||||
|
goto ex;
|
||||||
|
/* Create new track */;
|
||||||
|
ret = cue_read_number(&apt, &(crs->track_no), 0);
|
||||||
|
if (ret <= 0)
|
||||||
|
goto ex;
|
||||||
|
if (crs->track_no < 1 || crs->track_no > 99) {
|
||||||
|
sprintf(msg,
|
||||||
|
"Inappropriate cue sheet file track number %d",
|
||||||
|
crs->track_no);
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020194,
|
||||||
|
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
burn_printify(msg), 0, 0);
|
||||||
|
ret = 0; goto ex;
|
||||||
|
}
|
||||||
|
if (strcmp(apt, "AUDIO") == 0) {
|
||||||
|
mode = BURN_AUDIO;
|
||||||
|
block_size = 2352;
|
||||||
|
} else if (strcmp(apt, "MODE1/2048") == 0) {
|
||||||
|
mode = BURN_MODE1;
|
||||||
|
block_size = 2048;
|
||||||
|
} else {
|
||||||
|
sprintf(msg,
|
||||||
|
"Unsupported cue sheet file track datatype '%.4000s'",
|
||||||
|
apt);
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020197,
|
||||||
|
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
burn_printify(msg), 0, 0);
|
||||||
|
ret = 0; goto ex;
|
||||||
|
}
|
||||||
|
if (block_size != crs->block_size && crs->block_size > 0 &&
|
||||||
|
crs->block_size_locked) {
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020197,
|
||||||
|
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
"In cue sheet file: Unsupported mix track block sizes",
|
||||||
|
0, 0);
|
||||||
|
ret = 0; goto ex;
|
||||||
|
}
|
||||||
|
crs->block_size = block_size;
|
||||||
|
|
||||||
|
crs->track = burn_track_create();
|
||||||
|
if (crs->track == NULL)
|
||||||
|
goto out_of_mem;
|
||||||
|
crs->track_has_source = 0;
|
||||||
|
burn_track_define_data(crs->track, 0, 0, 1, mode);
|
||||||
|
if (mode == BURN_AUDIO)
|
||||||
|
burn_track_set_byte_swap(crs->track,
|
||||||
|
!!crs->swap_audio_bytes);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
sprintf(msg, "Unknown cue sheet file command '%.4000s'", line);
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020191,
|
||||||
|
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
burn_printify(msg), 0, 0);
|
||||||
|
ret = 0; goto ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 1;
|
||||||
|
ex:;
|
||||||
|
BURN_FREE_MEM(msg);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ts B11216 API */
|
||||||
|
/* @param flag bit0= do not attach CD-TEXT information to session and tracks
|
||||||
|
*/
|
||||||
|
int burn_session_by_cue_file(struct burn_session *session, char *path,
|
||||||
|
int fifo_size, struct burn_source **fifo,
|
||||||
|
unsigned char **text_packs, int *num_packs, int flag)
|
||||||
|
{
|
||||||
|
int ret, num_tracks, i, pack_type, length, double_byte = 0;
|
||||||
|
struct burn_track **tracks;
|
||||||
|
char *msg = NULL, *line = NULL;
|
||||||
|
unsigned char *payload;
|
||||||
|
struct stat stbuf;
|
||||||
|
FILE *fp = NULL;
|
||||||
|
struct burn_cue_file_cursor *crs;
|
||||||
|
|
||||||
|
static unsigned char dummy_cdtext[2] = {0, 0};
|
||||||
|
|
||||||
|
if (fifo != NULL)
|
||||||
|
*fifo = NULL;
|
||||||
|
if (text_packs != NULL)
|
||||||
|
*text_packs = NULL;
|
||||||
|
*num_packs = 0;
|
||||||
|
|
||||||
|
BURN_ALLOC_MEM(msg, char, 4096);
|
||||||
|
BURN_ALLOC_MEM(line, char, 4096);
|
||||||
|
ret = cue_crs_new(&crs, 0);
|
||||||
|
if (ret <= 0)
|
||||||
|
goto ex;
|
||||||
|
crs->no_cdtext = (flag & 1);
|
||||||
|
crs->fifo_size = fifo_size;
|
||||||
|
crs->block_size_locked = 1; /* No mixed sessions for now */
|
||||||
|
|
||||||
|
tracks = burn_session_get_tracks(session, &num_tracks);
|
||||||
|
if (num_tracks > 0) {
|
||||||
|
sprintf(msg,
|
||||||
|
"Cue sheet file reader called while session has already defined tracks");
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020196,
|
||||||
|
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
burn_printify(msg), 0, 0);
|
||||||
|
ret = 0; goto ex;
|
||||||
|
}
|
||||||
|
if (stat(path, &stbuf) == -1) {
|
||||||
|
cannot_open:;
|
||||||
|
sprintf(msg, "Cannot open cue sheet file '%.4000s'",
|
||||||
|
path);
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020193,
|
||||||
|
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
burn_printify(msg), errno, 0);
|
||||||
|
ret = 0; goto ex;
|
||||||
|
}
|
||||||
|
if (!S_ISREG(stbuf.st_mode)) {
|
||||||
|
sprintf(msg,
|
||||||
|
"File is not of usable type: Cue sheet file '%.4000s'",
|
||||||
|
path);
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020193,
|
||||||
|
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
burn_printify(msg), 0, 0);
|
||||||
|
ret = 0; goto ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
fp = fopen(path, "rb");
|
||||||
|
if (fp == NULL)
|
||||||
|
goto cannot_open;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (burn_sfile_fgets(line, 4095, fp) == NULL) {
|
||||||
|
if (!ferror(fp))
|
||||||
|
break;
|
||||||
|
sprintf(msg,
|
||||||
|
"Cannot read all bytes from cue sheet file '%.4000s'",
|
||||||
|
path);
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020193,
|
||||||
|
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
burn_printify(msg), 0, 0);
|
||||||
|
ret = 0; goto ex;
|
||||||
|
}
|
||||||
|
ret = cue_interpret_line(session, line, crs, 0);
|
||||||
|
if (ret <= 0)
|
||||||
|
goto ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attach last track to session */
|
||||||
|
if (crs->track != NULL) {
|
||||||
|
/* Set track size up to end of file */
|
||||||
|
if (crs->current_file_ba < 0) {
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020192,
|
||||||
|
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
"No INDEX 01 defined for last TRACK in cue sheet file",
|
||||||
|
0, 0);
|
||||||
|
ret = 0; goto ex;
|
||||||
|
}
|
||||||
|
if (crs->current_file_ba * crs->block_size >=
|
||||||
|
crs->source_size) {
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020194,
|
||||||
|
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
"INDEX 01 time point exceeds size of FILE from cue sheet file",
|
||||||
|
0, 0);
|
||||||
|
ret = 0; goto ex;
|
||||||
|
}
|
||||||
|
burn_track_set_size(crs->track, crs->source_size -
|
||||||
|
(off_t) (crs->current_file_ba * crs->block_size));
|
||||||
|
|
||||||
|
ret = cue_attach_track(session, crs, 0);
|
||||||
|
if (ret <= 0)
|
||||||
|
goto ex;
|
||||||
|
}
|
||||||
|
if (crs->cdtextfile != NULL) {
|
||||||
|
if (text_packs == NULL) {
|
||||||
|
|
||||||
|
/* >>> Warn of ignored text packs */;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ret = burn_cdtext_from_packfile(crs->cdtextfile,
|
||||||
|
text_packs, num_packs, 0);
|
||||||
|
if (ret <= 0)
|
||||||
|
goto ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check which tracks have data of pack types where session has not */
|
||||||
|
tracks = burn_session_get_tracks(session, &num_tracks);
|
||||||
|
for (pack_type = 0x80; pack_type < 0x8f; pack_type++) {
|
||||||
|
if (pack_type > 0x86 && pack_type != 0x8e)
|
||||||
|
continue;
|
||||||
|
ret = burn_session_get_cdtext(session, 0, pack_type, "",
|
||||||
|
&payload, &length, 0);
|
||||||
|
if (ret <= 0)
|
||||||
|
goto ex;
|
||||||
|
if (payload != NULL)
|
||||||
|
continue;
|
||||||
|
for (i = 0; i < num_tracks; i++) {
|
||||||
|
ret = burn_track_get_cdtext(tracks[i], 0, pack_type,
|
||||||
|
"", &payload, &length, 0);
|
||||||
|
if (ret <= 0)
|
||||||
|
goto ex;
|
||||||
|
double_byte = (ret > 1);
|
||||||
|
if (payload != NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i < num_tracks) {
|
||||||
|
ret = burn_session_set_cdtext(session, 0, pack_type,
|
||||||
|
"", dummy_cdtext, 1 + double_byte,
|
||||||
|
double_byte);
|
||||||
|
if (ret <= 0)
|
||||||
|
goto ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = 1;
|
||||||
|
ex:
|
||||||
|
if (ret <= 0) {
|
||||||
|
tracks = burn_session_get_tracks(session, &num_tracks);
|
||||||
|
for (i = 0; i < num_tracks; i++)
|
||||||
|
burn_track_free(tracks[i]);
|
||||||
|
} else {
|
||||||
|
if (fifo != NULL) {
|
||||||
|
*fifo = crs->fifo;
|
||||||
|
crs->fifo = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cue_crs_destroy(&crs, 0);
|
||||||
|
BURN_FREE_MEM(line);
|
||||||
|
BURN_FREE_MEM(msg);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user