From 1bb751245fd364a72f2004dec0d388dcd1ba693c Mon Sep 17 00:00:00 2001 From: nico Date: Wed, 18 Jul 2007 18:35:16 +0000 Subject: [PATCH] Add a new thread ("bufopen") that just adds files. Rename the playback thread codec thread. Fix bugs. The bufopen thread will try adding a new file to the buffer every 8 seconds. There can now be between 0 and all the files on the buffer at the same time, which is much more interesting than only one. The playback thread is now actually much closer to the real-life codec thread than the playback thread (though it's a very simple codec), so now is a good time to rename it. Bugfixes: * The part in bufgetdata() to copy a whole piece to the guard buffer if needed was totally wrong. It should be fine now. * When adding a handle fails, close the file descriptor that was opened to get the file's size. * When moving a handle, the alignment should be done backwards, or else we risk losing some data, and free_buffer() needs to check whether the movng succeeded. * Before aligning the buffer write position to add a new handle, it's better to check whether we have enough space to do that. * When we see we can't allocate enough space for the whole file, we need to make sure we take enough off the asked size, or else there might be a confusion between the empty and full states of the main buffer. git-svn-id: svn://jdgordon.mine.nu/mob@61 9862a28c-4e93-4879-ac26-10afcf840a8f --- testplugin.c | 125 +++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 78 insertions(+), 47 deletions(-) diff --git a/testplugin.c b/testplugin.c index 763be6c..c954b5e 100644 --- a/testplugin.c +++ b/testplugin.c @@ -116,7 +116,12 @@ static struct memory_handle *add_handle(size_t *data_size) /* this will give each handle a unique id */ static int cur_handle_id = 1; - /* make sure buf_widx is 32-bit aligned so that the handle struct is. */ + /* make sure buf_widx is 32-bit aligned so that the handle struct is, + but before that we check we can actually align. */ + if (RINGBUF_ADD_CROSS(buf_widx, 3, buf_ridx) >= 0) { + DEBUGF("no space to even align\n"); + return NULL; + } buf_widx = (RINGBUF_ADD(buf_widx, 3)) & ~3; size_t len = (data_size ? *data_size : 0) @@ -125,8 +130,8 @@ static struct memory_handle *add_handle(size_t *data_size) /* check that we actually can add the handle and its data */ int overlap = RINGBUF_ADD_CROSS(buf_widx, len, buf_ridx); if (overlap >= 0) { - *data_size -= overlap; - len -= overlap; + *data_size -= overlap + 1; + len -= overlap + 1; } if (len < sizeof(struct memory_handle)) { DEBUGF("no space to add the handle\n"); @@ -226,8 +231,14 @@ static struct memory_handle *find_handle(int handle_id) Return a pointer to the new location of the handle */ static struct memory_handle *move_handle(size_t *delta, struct memory_handle *h) { + if (*delta < 4) { + /* aligning backwards would yield a negative result, + and moving the handle of such a small amount is a waste + of time anyway. */ + return NULL; + } /* make sure delta is 32-bit aligned so that the handle struct is. */ - *delta = (RINGBUF_ADD(*delta, 3)) & ~3; + *delta = (*delta - 3) & ~3; size_t newpos = RINGBUF_ADD((void *)h - (void *)buffer, *delta); @@ -256,19 +267,9 @@ static struct memory_handle *move_handle(size_t *delta, struct memory_handle *h) return NULL; } } -/* - DEBUGF("h: %lx", (long)h); - DEBUGF("h->id: %d", h->id); - DEBUGF("dest: %lx", (long)dest); - DEBUGF("dest->id: %d", dest->id); - DEBUGF("memmove"); -*/ + rb->memmove(dest, h, sizeof(struct memory_handle)); -/* - DEBUGF("h: %lx", (long)h); - DEBUGF("dest: %lx", (long)dest); - DEBUGF("dest->id: %d", dest->id); -*/ + return dest; } /* Buffer data for the given handle. Return the amount of data buffered @@ -384,6 +385,7 @@ static void free_buffer(int handle_id) size_t delta = h->ridx; h = move_handle(&delta, h); + if (!h) return; /* The value of delta might change for alignment reasons */ h->data = RINGBUF_ADD(h->data, delta); h->data_len -= delta; @@ -463,19 +465,18 @@ int bufopen(char *file, size_t offset) if (fd < 0) return -1; - if (offset) - rb->lseek(fd, offset, SEEK_SET); - size_t size = rb->filesize(fd) - offset + 1; DEBUGF("we want to allocate %ld bytes\n", size); struct memory_handle *h = add_handle(&size); if (!h) { DEBUGF("failed to add handle\n"); + rb->close(fd); return -1; } DEBUGF("allocated %ld bytes\n", size); + if (offset) rb->lseek(fd, offset, SEEK_SET); rb->strncpy(h->path, file, MAX_PATH); h->fd = fd; h->filesize = rb->filesize(fd); @@ -597,6 +598,8 @@ ssize_t bufgetdata(int handle_id, size_t size, unsigned char **data) ssize_t ret; + *data = (unsigned char *)&buffer[RINGBUF_ADD(h->data, h->ridx)]; + if (buffer_len - (h->data + h->ridx) > 0 && buffer_len - (h->data + h->ridx) < size && h->available - h->ridx >= size) @@ -622,7 +625,14 @@ ssize_t bufgetdata(int handle_id, size_t size, unsigned char **data) h->available - h->ridx >= size && size <= GUARD_SIZE) { - rb->memcpy(guard_buffer, (unsigned char *)&buffer[h->data], size); + size_t copy_1 = h->data_len - h->ridx; + size_t copy_2 = size - copy_1; + rb->memcpy(guard_buffer, + (unsigned char *)&buffer[RINGBUF_ADD(h->data, h->ridx)], + copy_1); + rb->memcpy(guard_buffer + copy_1, + (unsigned char *)&buffer[h->data], copy_2); + *data = guard_buffer; ret = size; DEBUGF("used the guard buffer for a whole piece\n"); } @@ -633,8 +643,6 @@ ssize_t bufgetdata(int handle_id, size_t size, unsigned char **data) buffer_len - (h->data + h->ridx)); } - *data = (unsigned char *)&buffer[RINGBUF_ADD(h->data, h->ridx)]; - //DEBUGF("bufgetdata(%d): h->ridx=%ld, ret=%ld\n", handle_id, (long)h->ridx, ret); return ret; } @@ -809,17 +817,20 @@ bool disk_is_spinning(void) } -static long playback_stack[4*DEFAULT_STACK_SIZE/sizeof(long)]; -static struct thread_entry* playbackthread_id; +static long codec_stack[4*DEFAULT_STACK_SIZE/sizeof(long)]; +static struct thread_entry* codecthread_id; + +static long bufopen_stack[DEFAULT_STACK_SIZE/sizeof(long)]; +static struct thread_entry* bufopenthread_id; bool done_playing = false; #define MAX_HANDLES 16 -void playback_thread(void) -{ +int handles[MAX_HANDLES]; - int handles[MAX_HANDLES]; +void codec_thread(void) +{ int idx = 0; int fd = -1; /* used to write the files out as they are read */ unsigned char *data; @@ -830,10 +841,7 @@ void playback_thread(void) { if (!done_playing) { - if (handles[idx] <= 0) { - handles[idx] = bufopen(files[idx], 0); - total = 0; - } else { + if (handles[idx] > 0) { if (fd < 0) { rb->snprintf(outfile, MAX_PATH, "/file%d.mp3", idx); @@ -860,12 +868,6 @@ void playback_thread(void) DEBUGF("read %ld bytes from handle %d\n", total, handles[idx]); } -#if 0 - if (idx < num_files-1 && handles[idx+1] <= 0) { - handles[idx+1] = bufopen(files[idx+1], 0); - } -#endif - if (read == -2) { DEBUGF("data for handle %d isn't ready\n", handles[idx]); } else if (read == -1) { @@ -875,6 +877,7 @@ void playback_thread(void) bufclose(handles[idx]); rb->close(fd); fd = -1; + total = 0; idx++; if (idx >= num_files) { @@ -888,7 +891,23 @@ void playback_thread(void) rb->sleep(HZ/4); } - DEBUGF("removing the playback thread\n"); + DEBUGF("removing the codec thread\n"); + rb->remove_thread(NULL); +} + +void bufopen_thread(void) +{ + int idx = 0, ret; + while (idx < num_files) + { + ret = bufopen(files[idx], 0); + if (ret > 0) { + handles[idx++] = ret; + } + rb->sleep(HZ*8); + } + + DEBUGF("bufopen thread finished\n"); rb->remove_thread(NULL); } @@ -908,16 +927,28 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) return PLUGIN_ERROR; } - playbackthread_id = rb->create_thread(playback_thread, - playback_stack, - sizeof(playback_stack), - "playback" - IF_PRIO(,PRIORITY_PLAYBACK) - IF_COP(, CPU, false)); - - if (!playbackthread_id) + codecthread_id = rb->create_thread(codec_thread, + codec_stack, + sizeof(codec_stack), + "codec" + IF_PRIO(,PRIORITY_PLAYBACK) + IF_COP(, CPU, false)); + + bufopenthread_id = rb->create_thread(bufopen_thread, + bufopen_stack, + sizeof(bufopen_stack), + "bufopen" + IF_PRIO(,PRIORITY_BACKGROUND) + IF_COP(, CPU, false)); + + if (!codecthread_id) + { + rb->splash(HZ, "failed to create codec thread"); + return PLUGIN_ERROR; + } + else if (!bufopenthread_id) { - rb->splash(HZ, "failed to create playback thread"); + rb->splash(HZ, "failed to create bufopen thread"); return PLUGIN_ERROR; } else -- 2.11.4.GIT