From 55a3b176e053bac87cf4614471cf7bcf55b1b4af Mon Sep 17 00:00:00 2001 From: Nicolas Pennequin Date: Fri, 3 Aug 2007 15:20:16 +0200 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: * 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. --- testplugin.c | 110 +++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 70 insertions(+), 40 deletions(-) diff --git a/testplugin.c b/testplugin.c index 6015ca3..508f5ae 100644 --- a/testplugin.c +++ b/testplugin.c @@ -96,11 +96,18 @@ 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, + but before that we check we can actually align. */ + if (RINGBUF_ADD_CROSS(buf_widx, 3, buf_ridx) >= 0) { + return NULL; + } + buf_widx = (RINGBUF_ADD(buf_widx, 3)) & ~3; + size_t len = (data_size ? *data_size : 0) + sizeof(struct memory_handle); /* check that we actually can add the handle and its data */ - int overlap = RINGBUF_ADD_CROSS(buf_widx, len + 3, buf_ridx); + int overlap = RINGBUF_ADD_CROSS(buf_widx, len, buf_ridx); if (overlap >= 0) { *data_size -= overlap; len -= overlap; @@ -109,9 +116,6 @@ static struct memory_handle *add_handle(size_t *data_size) return NULL; } - /* make sure buf_widx is 32-bit aligned so that the handle struct is. */ - buf_widx = (RINGBUF_ADD(buf_widx, 3)) & ~3; - struct memory_handle *new_handle = (struct memory_handle *)(&buffer[buf_widx]); /* only advance the buffer write index of the size of the struct */ @@ -205,12 +209,17 @@ 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); - DEBUGF("move_handle\n"); struct memory_handle *dest = (struct memory_handle *)(&buffer[newpos]); /* Invalidate the cache to prevent it from keeping the old location of h */ @@ -236,21 +245,12 @@ 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 or -1 if the handle wasn't found */ static ssize_t buffer_handle(int handle_id) @@ -336,6 +336,7 @@ static void free_buffer(int handle_id) size_t delta = RINGBUF_SUB(h->ridx, h->data); 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->ridx = h->data; @@ -397,17 +398,16 @@ 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; struct memory_handle *h = add_handle(&size); if (!h) { DEBUGF("failed to add handle\n"); + rb->close(fd); return -1; } + if (offset) rb->lseek(fd, offset, SEEK_SET); rb->strncpy(h->path, file, MAX_PATH); h->fd = fd; h->filesize = rb->filesize(fd); @@ -714,17 +714,21 @@ 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; @@ -735,10 +739,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); @@ -774,6 +775,7 @@ void playback_thread(void) bufclose(handles[idx]); rb->close(fd); fd = -1; + total = 0; idx++; if (idx >= num_files) { @@ -787,7 +789,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); } @@ -807,16 +825,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