summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorNicolas Pennequin <nicolas.pennequin@free.fr>2007-11-02 19:13:03 +0000
committerNicolas Pennequin <nicolas.pennequin@free.fr>2007-11-02 19:13:03 +0000
commitb838a62adf4a6e05d657bed5867ab9f47ba5ddfe (patch)
treed5198282eba3bc59cb52b92606649e8f26ba924c /apps
parentc70671b6527d8be1905d0d3f5c104c3f1d768ef0 (diff)
downloadrockbox-b838a62adf4a6e05d657bed5867ab9f47ba5ddfe.tar.gz
rockbox-b838a62adf4a6e05d657bed5867ab9f47ba5ddfe.zip
Make bufread and bufgetdata blocking. They now return when enough data is available or when EOF is reached. This improves the API and removes the need for several duplicate waiting loops.
Also fix a few logfqueue messages. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15412 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r--apps/buffering.c74
-rw-r--r--apps/buffering.h4
-rw-r--r--apps/codecs.c11
-rw-r--r--apps/playback.c36
4 files changed, 48 insertions, 77 deletions
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);
-
- if (size == 0 && h->filerem > 0 && copy_n == 0)
- /* Data isn't ready */
- return ERR_DATA_NOT_READY;
+ size_t avail = RINGBUF_SUB(h->widx, h->ridx);
- 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);
-
- if (size == 0 && h->filerem > 0 && copy_n == 0)
- /* Data isn't ready */
- return ERR_DATA_NOT_READY;
+ size_t avail = RINGBUF_SUB(h->widx, h->ridx);
- 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
@@ -228,17 +228,6 @@ 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;