diff --git a/apps/buffering.c b/apps/buffering.c index 83ff0d5a31..6bde1f2ed5 100644 --- a/apps/buffering.c +++ b/apps/buffering.c @@ -658,10 +658,10 @@ static void rebuffer_handle(int handle_id, size_t newpos) h->offset = newpos; - LOGFQUEUE("? >| buffering Q_RESET_HANDLE"); + LOGFQUEUE("buffering >| buffering Q_RESET_HANDLE"); queue_send(&buffering_queue, Q_RESET_HANDLE, handle_id); - LOGFQUEUE("? >| buffering Q_BUFFER_HANDLE"); + LOGFQUEUE("buffering >| buffering Q_BUFFER_HANDLE"); queue_send(&buffering_queue, Q_BUFFER_HANDLE, handle_id); h->ridx = h->data; @@ -830,7 +830,7 @@ int bufopen(const char *file, size_t offset, enum data_type type) if (type == TYPE_CODEC || type == TYPE_CUESHEET || type == TYPE_IMAGE) { h->fd = fd; /* Immediately start buffering those */ - LOGFQUEUE("? >| buffering Q_BUFFER_HANDLE"); + LOGFQUEUE("buffering >| buffering Q_BUFFER_HANDLE"); queue_send(&buffering_queue, Q_BUFFER_HANDLE, h->id); } else { /* Other types will get buffered in the course of normal operations */ @@ -931,7 +931,9 @@ int bufadvance(int handle_id, off_t offset) } /* Copy data from the given handle to the dest buffer. - Return the number of bytes copied or < 0 for failure. */ + Return the number of bytes copied or < 0 for failure (handle not found). + The caller is blocked until the requested amount of data is available. +*/ ssize_t bufread(int handle_id, size_t size, void *dest) { const struct memory_handle *h = find_handle(handle_id); @@ -939,21 +941,26 @@ ssize_t bufread(int handle_id, size_t size, void *dest) return ERR_HANDLE_NOT_FOUND; size_t ret; - size_t copy_n = RINGBUF_SUB(h->widx, h->ridx); + size_t avail = RINGBUF_SUB(h->widx, h->ridx); - if (size == 0 && h->filerem > 0 && copy_n == 0) - /* Data isn't ready */ - return ERR_DATA_NOT_READY; - - if (copy_n < size && h->filerem > 0) - /* Data isn't ready */ - return ERR_DATA_NOT_READY; - - if (copy_n == 0 && h->filerem == 0) + if (avail == 0 && h->filerem == 0) /* File is finished reading */ return 0; - ret = MIN(size, copy_n); + if (h->filerem > 0 && (avail == 0 || avail < size)) + { + /* Data isn't ready. Request buffering */ + buf_request_buffer_handle(handle_id); + /* Wait for the data to be ready */ + do + { + sleep(1); + avail = RINGBUF_SUB(h->widx, h->ridx); + } + while (h->filerem > 0 && (avail == 0 || avail < size)); + } + + ret = MIN(size, avail); if (h->ridx + ret > buffer_len) { @@ -971,10 +978,14 @@ ssize_t bufread(int handle_id, size_t size, void *dest) } /* Update the "data" pointer to make the handle's data available to the caller. - Return the length of the available linear data or < 0 for failure. + Return the length of the available linear data or < 0 for failure (handle + not found). + The caller is blocked until the requested amount of data is available. size is the amount of linear data requested. it can be 0 to get as much as possible. - The guard buffer may be used to provide the requested size */ + The guard buffer may be used to provide the requested size. This means it's + unsafe to request more than the size of the guard buffer. +*/ ssize_t bufgetdata(int handle_id, size_t size, void **data) { const struct memory_handle *h = find_handle(handle_id); @@ -982,21 +993,26 @@ ssize_t bufgetdata(int handle_id, size_t size, void **data) return ERR_HANDLE_NOT_FOUND; ssize_t ret; - size_t copy_n = RINGBUF_SUB(h->widx, h->ridx); + size_t avail = RINGBUF_SUB(h->widx, h->ridx); - if (size == 0 && h->filerem > 0 && copy_n == 0) - /* Data isn't ready */ - return ERR_DATA_NOT_READY; - - if (copy_n < size && h->filerem > 0) - /* Data isn't ready */ - return ERR_DATA_NOT_READY; - - if (copy_n == 0 && h->filerem == 0) + if (avail == 0 && h->filerem == 0) /* File is finished reading */ return 0; - if (h->ridx + size > buffer_len && copy_n >= size) + if (h->filerem > 0 && (avail == 0 || avail < size)) + { + /* Data isn't ready. Request buffering */ + buf_request_buffer_handle(handle_id); + /* Wait for the data to be ready */ + do + { + sleep(1); + avail = RINGBUF_SUB(h->widx, h->ridx); + } + while (h->filerem > 0 && (avail == 0 || avail < size)); + } + + if (h->ridx + size > buffer_len && avail >= size) { /* the data wraps around the end of the buffer : use the guard buffer to provide the requested amount of data. */ @@ -1006,7 +1022,7 @@ ssize_t bufgetdata(int handle_id, size_t size, void **data) } else { - ret = MIN(copy_n, buffer_len - h->ridx); + ret = MIN(avail, buffer_len - h->ridx); } *data = &buffer[h->ridx]; diff --git a/apps/buffering.h b/apps/buffering.h index 46f2fadf47..799c18aa93 100644 --- a/apps/buffering.h +++ b/apps/buffering.h @@ -40,7 +40,6 @@ enum data_type { #define ERR_BUFFER_FULL -2 #define ERR_INVALID_VALUE -3 #define ERR_FILE_ERROR -4 -#define ERR_DATA_NOT_READY -5 /* Initialise the buffering subsystem */ @@ -61,6 +60,9 @@ bool buffering_reset(char *buf, size_t buflen); * bufadvance: Move handle reading index, relatively to current position * bufread : Copy data from a handle to a buffer * bufgetdata: Obtain a pointer for linear access to a "size" amount of data + * + * NOTE: bufread and bufgetdata will block the caller until the requested + * amount of data is ready (unless EOF is reached). ****************************************************************************/ int bufopen(const char *file, size_t offset, enum data_type type); diff --git a/apps/codecs.c b/apps/codecs.c index e0ba09618d..7d4d3892cf 100644 --- a/apps/codecs.c +++ b/apps/codecs.c @@ -227,17 +227,6 @@ static int codec_load_ram(int size, struct codec_api *api) int codec_load_buf(unsigned int hid, int size, struct codec_api *api) { int rc; rc = bufread(hid, size, codecbuf); - if (rc < 0) { - if (rc == ERR_DATA_NOT_READY) { - buf_request_buffer_handle(hid); - } else { - logf("error loading codec"); - return CODEC_ERROR; - } - do { - rc = bufread(hid, size, codecbuf); - } while (rc == ERR_DATA_NOT_READY); - } if (rc < 0) { logf("error loading codec"); return CODEC_ERROR; diff --git a/apps/playback.c b/apps/playback.c index d9f7fa97c2..805c930488 100644 --- a/apps/playback.c +++ b/apps/playback.c @@ -1495,23 +1495,6 @@ static size_t codec_filebuf_callback(void *ptr, size_t size) if (copy_n == 0) return 0; - - if (copy_n == ERR_DATA_NOT_READY) - { - buf_request_buffer_handle(CUR_TI->audio_hid); - } - - /* Let the disk buffer catch fill until enough data is available */ - while (copy_n == ERR_DATA_NOT_READY) - { - sleep(1); - - if (ci.stop_codec || ci.new_track) - return 0; - - copy_n = bufread(CUR_TI->audio_hid, size, ptr); - } - /* Update read and other position pointers */ codec_advance_buffer_counters(copy_n); @@ -1541,25 +1524,6 @@ static void* codec_request_buffer_callback(size_t *realsize, size_t reqsize) return NULL; } - if (ret == ERR_DATA_NOT_READY) - { - buf_request_buffer_handle(CUR_TI->audio_hid); - } - - /* Let the disk buffer catch fill until enough data is available */ - while (ret == ERR_DATA_NOT_READY) - { - sleep(1); - - if (ci.stop_codec || ci.new_track) - { - *realsize = 0; - return NULL; - } - ret = bufgetdata(CUR_TI->audio_hid, reqsize, &ptr); - } - copy_n = MIN((size_t)ret, reqsize); - *realsize = copy_n; return ptr;