diff options
author | Thomas Martitz <kugel@rockbox.org> | 2013-05-30 11:24:16 +0200 |
---|---|---|
committer | Thomas Martitz <kugel@rockbox.org> | 2013-12-23 12:17:38 +0100 |
commit | 22e802e80048defd401462e062afcb10093ac793 (patch) | |
tree | 09d24f7eb2a3b18e6563e838398b2715394f7c4c /apps/radio | |
parent | 64b9e1fa7b645daa36ca0018dc168d4f871fd538 (diff) |
playback,talk: Share audiobuffer via core_alloc_maximum().
This fixes the radioart crash that was the result of buffering.c working
on a freed buffer at the same time as buflib (radioart uses buffering.c for the
images). With this change the buffer is owned by buflib exclusively so this
cannot happen.
As a result, audio_get_buffer() doesn't exist anymore. Callers should call
core_alloc_maximum() directly. This buffer needs to be protected as usual
against movement if necessary (previously it was not protected at all which
cased the radioart crash), To get most of it they can adjust the willingness of
the talk engine to give its buffer away (at the expense of disabling voice
interface) with the new talk_buffer_set_policy() function.
Change-Id: I52123012208d04967876a304451d634e2bef3a33
Diffstat (limited to 'apps/radio')
-rw-r--r-- | apps/radio/radioart.c | 40 |
1 files changed, 38 insertions, 2 deletions
diff --git a/apps/radio/radioart.c b/apps/radio/radioart.c index 76697c6017..cab6aa29ce 100644 --- a/apps/radio/radioart.c +++ b/apps/radio/radioart.c @@ -32,6 +32,7 @@ #include "kernel.h" #include "string-extra.h" #include "filefuncs.h" +#include "core_alloc.h" #define MAX_RADIOART_IMAGES 10 struct radioart { @@ -158,14 +159,49 @@ static void buffer_reset_handler(void *data) (void)data; } +static int shrink_callback(int handle, unsigned hints, void* start, size_t old_size) +{ + (void)start; + (void)old_size; + + ssize_t old_size_s = old_size; + size_t size_hint = (hints & BUFLIB_SHRINK_SIZE_MASK); + ssize_t wanted_size = old_size_s - size_hint; + + if (wanted_size <= 0) + { + core_free(handle); + buffering_reset(NULL, 0); + } + else + { + if (hints & BUFLIB_SHRINK_POS_FRONT) + start += size_hint; + + buffering_reset(start, wanted_size); + core_shrink(handle, start, wanted_size); + buf = start; + + /* one-shot */ + add_event(BUFFER_EVENT_BUFFER_RESET, true, buffer_reset_handler); + } + + return BUFLIB_CB_OK; +} + +static struct buflib_callbacks radioart_ops = { + .shrink_callback = shrink_callback, +}; + void radioart_init(bool entering_screen) { if (entering_screen) { /* grab control over buffering */ size_t bufsize; - buf = audio_get_buffer(false, &bufsize); - buffering_reset(buf, bufsize); + int handle = core_alloc_maximum("radioart", &bufsize, &radioart_ops); + buffering_reset(core_get_data(handle), bufsize); + buf = core_get_data(handle); /* one-shot */ add_event(BUFFER_EVENT_BUFFER_RESET, true, buffer_reset_handler); } |