diff --git a/cdrskin/cdrskin_timestamp.h b/cdrskin/cdrskin_timestamp.h index ebce6fa..7a5c797 100644 --- a/cdrskin/cdrskin_timestamp.h +++ b/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2007.10.03.223851" +#define Cdrskin_timestamP "2007.10.04.200221" diff --git a/libburn/file.c b/libburn/file.c index a859998..bb1f6d3 100644 --- a/libburn/file.c +++ b/libburn/file.c @@ -14,6 +14,10 @@ #include "file.h" #include "async.h" +#include "libdax_msgs.h" +extern struct libdax_msgs *libdax_messenger; + + /* main channel data can be padded on read, but 0 padding the subs will make an unreadable disc */ @@ -123,6 +127,8 @@ failure:; return NULL; } + fs->magic[0] = 'f'; fs->magic[1] = 'i'; + fs->magic[2] = 'l'; fs->magic[3] = 'e'; fs->datafd = fd1; fs->subfd = fd2; @@ -161,6 +167,8 @@ struct burn_source *burn_fd_source_new(int datafd, int subfd, off_t size) fs = malloc(sizeof(struct burn_source_file)); if (fs == NULL) /* ts A70825 */ return NULL; + fs->magic[0] = 'f'; fs->magic[1] = 'i'; + fs->magic[2] = 'l'; fs->magic[3] = 'e'; fs->datafd = datafd; fs->subfd = subfd; fs->fixed_size = size; @@ -202,9 +210,9 @@ static int fifo_read(struct burn_source *source, if (fs->is_started == 0) { ret = burn_fifo_start(source, 0); if (ret <= 0) { - - /* >>> msg: cannot start fifo thread */; - + libdax_msgs_submit(libdax_messenger, -1, 0x00020152, + LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, + "Cannot start fifo thread", 0, 0); return -1; } fs->is_started = 1; @@ -261,7 +269,9 @@ int burn_fifo_source_shoveller_og(struct burn_source *source, int flag) else if (ret == 0) break; /* EOF */ else { - /* >>> read error */; + libdax_msgs_submit(libdax_messenger, -1, 0x00020153, + LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, + "Read error on fifo input", errno, 0); break; } ret = write(fs->outlet[1], fs->buf, ret); @@ -306,17 +316,15 @@ static int fifo_read_ng(struct burn_source *source, int ret, todo, rpos, bufsize, diff; if (fs->end_of_consumption) { - - /* >>> msg: reading has been ended already */; - + /* ??? msg: reading has been ended already */; return 0; } if (fs->is_started == 0) { ret = burn_fifo_start(source, 0); if (ret <= 0) { - - /* >>> msg: cannot start fifo thread */; - + libdax_msgs_submit(libdax_messenger, -1, 0x00020152, + LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, + "Cannot start fifo thread", 0, 0); fs->end_of_consumption = 1; return -1; } @@ -344,9 +352,10 @@ static int fifo_read_ng(struct burn_source *source, if (todo < size) /* deliver partial buffer */ break; fs->end_of_consumption = 1; - - /* >>> msg: report fs->input_error as errno */; - + libdax_msgs_submit(libdax_messenger, -1, + 0x00020154, + LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH, + "Forwarded input error ends output", 0, 0); return -1; } fifo_sleep(0); @@ -447,9 +456,10 @@ int burn_fifo_source_shoveller_ng(struct burn_source *source, int flag) if (trans_end) { bufpt = calloc(fs->chunksize, 1); if (bufpt == NULL) { - - /* >>> msg: out of memory */; - + libdax_msgs_submit(libdax_messenger, -1, + 0x00000003, + LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, + "Out of virtual memory", 0, 0); fs->input_error = ENOMEM; break; } @@ -463,6 +473,9 @@ int burn_fifo_source_shoveller_ng(struct burn_source *source, int flag) else if (ret == 0) break; /* EOF */ else { + libdax_msgs_submit(libdax_messenger, -1, 0x00020153, + LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, + "Read error on fifo input", errno, 0); fs->input_error = errno; if(errno == 0) fs->input_error = EIO; @@ -514,7 +527,7 @@ int burn_fifo_source_shoveller_ng(struct burn_source *source, int flag) So in both cases the consumer is aware that reading is futile or even fatal. */ - free(fs->buf); + free(fs->buf); /* Give up fifo buffer. Next fifo might start soon. */ fs->buf = NULL; return (fs->input_error == 0); @@ -543,11 +556,15 @@ struct burn_source *burn_fifo_source_new(struct burn_source *inp, #endif if (((double) chunksize) * ((double) chunks) > 1024.0*1024.0*1024.0) { - /* >>> buffer larger than 1 GB */; + libdax_msgs_submit(libdax_messenger, -1, 0x00020155, + LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, + "Desired fifo buffer too large (> 1GB)", 0, 0); return NULL; } if (chunksize < 1 || chunks < 2) { - /* >>> buffer too small */; + libdax_msgs_submit(libdax_messenger, -1, 0x00020156, + LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, + "Desired fifo buffer too small", 0, 0); return NULL; } @@ -614,17 +631,23 @@ struct burn_source *burn_fifo_source_new(struct burn_source *inp, /* ts A71003 : API */ -int burn_fifo_inquire_status(struct burn_source *source, int *size, - int *free_bytes) +int burn_fifo_inquire_status(struct burn_source *source, + int *size, int *free_bytes, char **status_text) { struct burn_source_fifo *fs = source->data; int ret = 0, diff, wpos, rpos; + static char *(states[8]) = { + "standby", "active", "ending", "failing", + "unused", "abandoned", "ended", "aborted"}; + + *status_text = NULL; + *size = 0; if (fs->magic[0] != 'f' || fs->magic[1] != 'i' || fs->magic[2] != 'f' || fs->magic[3] != 'o') { - - /* >>> not a fifo burn_source */; - + libdax_msgs_submit(libdax_messenger, -1, 0x00020157, + LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, + "burn_source is not a fifo object", 0, 0); return -1; } *size = fs->chunksize * fs->chunks; @@ -645,6 +668,7 @@ int burn_fifo_inquire_status(struct burn_source *source, int *size, ret |= 2; else ret |= 1; + *status_text = states[ret]; return ret; } diff --git a/libburn/file.h b/libburn/file.h index 1ca228c..7d99c64 100644 --- a/libburn/file.h +++ b/libburn/file.h @@ -5,6 +5,8 @@ struct burn_source_file { + char magic[4]; + int datafd; int subfd; off_t fixed_size; @@ -33,7 +35,7 @@ struct burn_source_fifo { /* the burn_source for which this fifo is acting as proxy */ struct burn_source *inp; - /* <<< currently it is only a pipe */ + /* <<< up to now it was only a pipe. This is on its way out. */ int outlet[2]; /* The ring buffer mechanism */ diff --git a/libburn/libburn.h b/libburn/libburn.h index 6f971c7..efab116 100644 --- a/libburn/libburn.h +++ b/libburn/libburn.h @@ -334,7 +334,11 @@ struct burn_toc_entry In general, burn_source objects can be freed as soon as they are attached to track objects. The track objects will keep them alive and dispose them - when they are no longer needed. + when they are no longer needed. With a fifo burn_source it makes sense to + keep the own reference for inquiring its state while burning is in + progress. + + --- The following description of burn_source applies only to application implemented burn_source objects. You need not to know it for API provided @@ -423,13 +427,31 @@ struct burn_source { /** Source specific data. Here the various source classes express their specific properties and the instance objects store their individual - management data. E.g. data may point to a struct like this: + management data. + You SHOULD implement two attributes in *data : + 1) The first member of the structure should be a 4 byte array + magic[] with the first byte being set to an uppercase letter + and the other 3 set to some value you deem unique for your + burn_source. + libburnia sets magic[0] to a lower case letter in its burn_source + objects. Established magic values are: + {'f','i','l','e'} , {'f','i','f','o'} , {'e','1','1','9'}. + 2) off_t fixed_size should store an eventual value from (*set_size) + and if set be used as reply of (*get_size). + + E.g. data could point to a struct like this: struct app_burn_source { + char magic[4]; + off_t fixed_size; struct my_app *app_handle; ... other individual source parameters ... - off_t fixed_size; }; + With .magic[] getting initialized as {'M','y','a','p'} + and .fixed_size initialized as 0 (= invalid). + + Function (*free_data) has to be prepared to clean up and free + the struct. */ void *data; @@ -1458,14 +1480,22 @@ struct burn_source *burn_file_source_new(const char *path, struct burn_source *burn_fd_source_new(int datafd, int subfd, off_t size); -/* ts A70930 : Provisory API call. Subject to changes ! */ +/* ts A70930 */ /** Creates a fifo which acts as proxy for an already existing data source. - NOTE: Incomplete function. Curently the ring buffer is not implemented. - The only purpose is to decouple the writer thread of libburn from an - eventually error prone burn_source. - In future this will implement a ring buffer which shall smoothen the - data stream between burn_source and writer thread. + The fifo is based on a ring buffer which shall smoothen the data stream + between burn_source and writer thread. Each fifo serves only for one + data source and gets attached to one track instead of its data source + by burn_track_set_source(). + 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 + and allocates its buffer. After input has ended and all buffer content is + consumed, the buffer space gets freedi and the worker thread ends. + This happens asynchronously. So expect two buffers and worker threads to + exist for a short time between tracks. Be modest in your size demands if + multiple tracks are to be expected. @param inp The burn_source for which the fifo shall act as proxy. + It can be disposed by burn_source_free() immediately + after this call. @param chunksize The size in bytes of a chunk. Use 2048 for sources suitable for BURN_BLOCK_MODE1 and 2352 for sources which deliver for BURN_BLOCK_AUDIO. @@ -1477,6 +1507,8 @@ struct burn_source *burn_fd_source_new(int datafd, int subfd, off_t size); @return A pointer to the newly created burn_source. Later both burn_sources, inp and the returned fifo, have to be disposed by calling burn_source_free() for each. + inp can be freed immediately, the returned fifo may be + kept as handle for burn_fifo_inquire_status(). */ struct burn_source *burn_fifo_source_new(struct burn_source *inp, int chunksize, int chunks, int flag); @@ -1487,16 +1519,20 @@ struct burn_source *burn_fifo_source_new(struct burn_source *inp, @param fifo The fifo object to inquire @param size The total size of the fifo @param free_bytes The current free capacity of the fifo - @return <=0 error, - 1=input and consumption are active - 2=input has ended without error - 3=input had error and ended, - 5=consumption has ended prematurely - 6=consumption has ended without input error - 7=consumption has ended after input error + @param status_text Returns a pointer to a constant text, see below + @return <0 reply invalid, >=0 fifo status code: + bit0+1=input status, bit2=consumption status, i.e: + 0="standby" : data processing not started yet + 1="active" : input and consumption are active + 2="ending" : input has ended without error + 3="failing" : input had error and ended, + 4="unused" : ( consumption has ended before processing start ) + 5="abandoned" : consumption has ended prematurely + 6="ended" : consumption has ended without input error + 7="aborted" : consumption has ended after input error */ int burn_fifo_inquire_status(struct burn_source *fifo, int *size, - int *free_bytes); + int *free_bytes, char **status_text); /* ts A70328 */ diff --git a/libburn/libdax_msgs.h b/libburn/libdax_msgs.h index 5d7205a..6c3aec5 100644 --- a/libburn/libdax_msgs.h +++ b/libburn/libdax_msgs.h @@ -433,6 +433,13 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff 0x0002014d (SORRY,HIGH) = Asynchromous SCSI error 0x0002014f (SORRY,HIGH) = Timeout with asynchromous SCSI command 0x00020150 (DEBUG,LOW) = Reporting asynchronous waiting time + 0x00020151 (FATAL,HIGH) = Read attempt on write-only drive + 0x00020152 (FATAL,HIGH) = Cannot start fifo thread + 0x00020153 (SORRY,HIGH) = Read error on fifo input + 0x00020154 (NOTE,HIGH) = Forwarded input error ends output + 0x00020155 (SORRY,HIGH) = Desired fifo buffer too large + 0x00020156 (SORRY,HIGH) = Desired fifo buffer too small + 0x00020157 (FATAL,HIGH) = burn_source is not a fifo object libdax_audioxtr: @@ -475,6 +482,18 @@ Range "vreixo" : 0x00030000 to 0x0003ffff 0x00030301 (NOTE,MEDIUM) = Unsupported file type for Joliet tree +------------------------------------------------------------------------------ +Range "application" : 0x00040000 to 0x0004ffff + + 0x00040000 (ABORT,HIGH) : Application supplied message + 0x00040001 (FATAL,HIGH) : Application supplied message + 0x00040002 (SORRY,HIGH) : Application supplied message + 0x00040003 (WARNING,HIGH) : Application supplied message + 0x00040004 (HINT,HIGH) : Application supplied message + 0x00040005 (NOTE,HIGH) : Application supplied message + 0x00040006 (UPDATE,HIGH) : Application supplied message + 0x00040007 (DEBUG,HIGH) : Application supplied message + ------------------------------------------------------------------------------