From c49995b11a1b1476415146af68612d1cae2dfe4f Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Wed, 22 Sep 2010 17:51:26 +0000 Subject: [PATCH] New API call burn_offst_source_new() --- cdrskin/cdrskin_timestamp.h | 2 +- libburn/file.c | 164 +++++++++++++++++++++++++++++++++++- libburn/file.h | 18 ++++ libburn/libburn.h | 38 ++++++++- libburn/libburn.ver | 1 + libburn/libdax_msgs.h | 2 + libburn/source.c | 12 +++ libburn/source.h | 2 + 8 files changed, 234 insertions(+), 5 deletions(-) diff --git a/cdrskin/cdrskin_timestamp.h b/cdrskin/cdrskin_timestamp.h index f76722f..75bbd82 100644 --- a/cdrskin/cdrskin_timestamp.h +++ b/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2010.09.22.105426" +#define Cdrskin_timestamP "2010.09.22.175054" diff --git a/libburn/file.c b/libburn/file.c index b831560..f8f2b6b 100644 --- a/libburn/file.c +++ b/libburn/file.c @@ -481,10 +481,11 @@ int burn_fifo_source_shoveller(struct burn_source *source, int flag) int burn_fifo_cancel(struct burn_source *source) { + int ret; struct burn_source_fifo *fs = source->data; - burn_source_cancel(fs->inp); - return(1); + ret = burn_source_cancel(fs->inp); + return ret; } /* @@ -747,3 +748,162 @@ int burn_fifo_fill(struct burn_source *source, int bufsize, int flag) 1 | ((flag & 1) << 1)); } + +/* ----------------------------- Offset source ----------------------------- */ +/* ts B00922 */ + +static void offst_free(struct burn_source *source); + +static struct burn_source_offst *offst_auth(struct burn_source *source) +{ + if (source->free_data != offst_free) { + libdax_msgs_submit(libdax_messenger, -1, 0x0002017a, + LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH, + "Expected offset source object as parameter", + 0, 0); + return NULL; + } + return (struct burn_source_offst *) source->data; +} + +static off_t offst_get_size(struct burn_source *source) +{ + struct burn_source_offst *fs; + + if ((fs = offst_auth(source)) == NULL) + return (off_t) 0; + return fs->size; +} + +static int offst_set_size(struct burn_source *source, off_t size) +{ + struct burn_source_offst *fs; + + if ((fs = offst_auth(source)) == NULL) + return 0; + fs->size = size; + return 1; +} + +static void offst_free(struct burn_source *source) +{ + struct burn_source_offst *fs; + + if ((fs = offst_auth(source)) == NULL) + return; + if (fs->prev != NULL) + offst_auth(fs->prev)->next = fs->next; + if (fs->next != NULL) + offst_auth(fs->next)->prev = fs->prev; + if (fs->inp != NULL) + burn_source_free(fs->inp); /* i.e. decrement refcount */ + free(source->data); +} + +static int offst_read(struct burn_source *source, unsigned char *buffer, + int size) +{ + int ret, to_read, todo; + struct burn_source_offst *fs; + + if ((fs = offst_auth(source)) == NULL) + return -1; + + /* Eventually skip bytes up to start position */; + if (!fs->running) { + if (fs->prev != NULL) + fs->pos = offst_auth(fs->prev)->pos; + fs->running= 1; + } + if(fs->pos < fs->start) { + todo = fs->start - fs->pos; + while (todo > 0) { + to_read = todo; + if (to_read > size) + to_read = size; + ret = burn_source_read(fs->inp, buffer, to_read); + if (ret <= 0) + return ret; + todo -= ret; + fs->pos += ret; + } + } + + /* Produce EOF if source size is exhausted. + burn_source delivers no incomplete sector buffers. + */ + if (fs->pos + size > fs->start + fs->size) + return 0; + + /* Read payload */ + ret = burn_source_read(fs->inp, buffer, size); + if (ret > 0) + fs->pos += ret; + return ret; +} + +static int offst_cancel(struct burn_source *source) +{ + int ret; + struct burn_source_offst *fs; + + if ((fs = offst_auth(source)) == NULL) + return -1; + ret = burn_source_cancel(fs->inp); + return ret; +} + +struct burn_source *burn_offst_source_new( + struct burn_source *inp, struct burn_source *prev, + off_t start, off_t size, int flag) +{ + struct burn_source *src; + struct burn_source_offst *fs, *prev_fs = NULL; + + if (prev != NULL) + if ((prev_fs = offst_auth(prev)) == NULL) + return NULL; /* Not type burn_source_offst */ + + fs = calloc(1, sizeof(struct burn_source_offst)); + if (fs == NULL) + return NULL; + src = burn_source_new(); + if (src == NULL) { + free((char *) fs); + return NULL; + } + src->read = NULL; + src->read_sub = NULL; + src->get_size = offst_get_size; + src->set_size = offst_set_size; + src->free_data = offst_free; + src->data = fs; + src->version= 1; + src->read_xt = offst_read; + src->cancel= offst_cancel; + fs->inp = inp; + fs->prev = prev; + fs->next = NULL; + if (prev != NULL) { + if (prev_fs->next != NULL) { + offst_auth(prev_fs->next)->prev = src; + fs->next = prev_fs->next; + } + prev_fs->next = src; + if (prev_fs->start + prev_fs->size > start) { + libdax_msgs_submit(libdax_messenger, -1, 0x00020179, + LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH, + "Offset source start address is before end of previous source", + 0, 0); + return NULL; + } + } + fs->start = start; + fs->size = size; + fs->running = 0; + fs->pos = 0; + inp->refcount++; /* make sure inp lives longer than src */ + + return src; +} + diff --git a/libburn/file.h b/libburn/file.h index 8d76648..49268e1 100644 --- a/libburn/file.h +++ b/libburn/file.h @@ -74,4 +74,22 @@ struct burn_source_fifo { int burn_fifo_source_shoveller(struct burn_source *source, int flag); +/* ts B00922 */ +struct burn_source_offst { + + /* See burn_offst_source_new() */ + struct burn_source *inp; + struct burn_source *prev; + off_t start; + off_t size; + + /* To help offst_free() */ + struct burn_source *next; + + /* The current reading position */ + int running; + off_t pos; + +}; + #endif /* LIBBURN__FILE_H */ diff --git a/libburn/libburn.h b/libburn/libburn.h index ff1f82a..974a3ea 100644 --- a/libburn/libburn.h +++ b/libburn/libburn.h @@ -1311,9 +1311,10 @@ off_t burn_disc_available_space(struct burn_drive *d, 0xffff "stdio file" Note: 0xffff is not a MMC profile but a libburn invention. Read-only are the profiles - 0x08 "CD-ROM", 0x10 "DVD-ROM", + 0x08 "CD-ROM", + 0x10 "DVD-ROM", 0x40 "BD-ROM", - For now read-only is BD-R profile (testers wanted) + Read-only for now is this BD-R profile (testers wanted) 0x42 "BD-R random recording" @param d The drive where the media is inserted. @param pno Profile Number. See also mmc5r03c.pdf, table 89 @@ -1889,6 +1890,39 @@ int burn_os_free_buffer(void *buffer, size_t amount, int flag); struct burn_source *burn_fd_source_new(int datafd, int subfd, off_t size); +/* ts B00922 */ +/** Creates an offset source which shall provide a byte interval of a stream + to its consumer. It is supposed to be chain-linked with other offset + sources which serve neighboring consumers. The chronological sequence + of consumers and the sequence of offset sources must match. The intervals + of the sources must not overlap. + + A chain of these burn_source objects may be used to feed multiple tracks + from one single stream of input bytes. + Each of the offset sources will skip the bytes up to its start address and + provide the prescribed number of bytes to the track. Skipping takes into + respect the bytes which have been processed by eventual predecessors in the + chain. + Important: It is not allowed to free an offset source before its successor + has ended its work. Best is to keep them all until all tracks + are done. + + @param inp The burn_source object from which to read stream data + @param prev The eventual offset source object which shall read data from + inp before the new offset source will begin its own work. + This must either be a result of burn_offst_source_new() or + it must be NULL. + @param start The byte address where to start reading bytes for the + consumer. inp bytes may get skipped to reach this address. + @param size The number of bytes to be delivered to the consumer. + @param flag Bitfield for control purposes (unused yet, submit 0). + @return Pointer to a burn_source object, NULL indicates failure + @since 0.8.8 +*/ +struct burn_source *burn_offst_source_new( + struct burn_source *inp, struct burn_source *prev, + off_t start, off_t size, int flag); + /* ts A70930 */ /** 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 diff --git a/libburn/libburn.ver b/libburn/libburn.ver index 4f52630..eddfd5e 100644 --- a/libburn/libburn.ver +++ b/libburn/libburn.ver @@ -83,6 +83,7 @@ burn_msgs_obtain; burn_msgs_set_severities; burn_msgs_submit; burn_obtain_profile_name; +burn_offst_source_new; burn_os_alloc_buffer; burn_os_free_buffer; burn_os_open_track_src; diff --git a/libburn/libdax_msgs.h b/libburn/libdax_msgs.h index 4fb9eaf..e34b1fd 100644 --- a/libburn/libdax_msgs.h +++ b/libburn/libdax_msgs.h @@ -558,6 +558,8 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff 0x00020176 (NOTE,HIGH) = Stream recording disabled because of small OS buffer 0x00020177 (ABORT,HIGH) = Urged drive worker threads to do emergency halt 0x00020178 (DEBUG,HIGH) = Write thread ended + 0x00020179 (FAILURE,HIGH) = Offset source start address is before end of previous source + 0x0002017a (FAILURE,HIGH) = Expected offset source object as parameter libdax_audioxtr: diff --git a/libburn/source.c b/libburn/source.c index e0566f7..a9e04a3 100644 --- a/libburn/source.c +++ b/libburn/source.c @@ -63,3 +63,15 @@ int burn_source_cancel(struct burn_source *src) return 1; } + +/* ts B00922 */ +int burn_source_read(struct burn_source *src, unsigned char *buffer, int size) +{ + int ret; + + if (src->read != NULL) + ret = src->read(src, buffer, size); + else + ret = src->read_xt(src, buffer, size); + return ret; +} diff --git a/libburn/source.h b/libburn/source.h index 1f31527..90a96b5 100644 --- a/libburn/source.h +++ b/libburn/source.h @@ -7,4 +7,6 @@ struct burn_source *burn_source_new(void); int burn_source_cancel(struct burn_source *src); +int burn_source_read(struct burn_source *src, unsigned char *buffer, int size); + #endif /*__SOURCE*/