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/plugin.c | |
parent | 64b9e1fa7b645daa36ca0018dc168d4f871fd538 (diff) | |
download | rockbox-22e802e80048defd401462e062afcb10093ac793.tar.gz rockbox-22e802e80048defd401462e062afcb10093ac793.zip |
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/plugin.c')
-rw-r--r-- | apps/plugin.c | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/apps/plugin.c b/apps/plugin.c index 18c49f4c27..d80e6a1e0e 100644 --- a/apps/plugin.c +++ b/apps/plugin.c | |||
@@ -801,6 +801,8 @@ static const struct plugin_api rockbox_api = { | |||
801 | the API gets incompatible */ | 801 | the API gets incompatible */ |
802 | }; | 802 | }; |
803 | 803 | ||
804 | static int plugin_buffer_handle; | ||
805 | |||
804 | int plugin_load(const char* plugin, const void* parameter) | 806 | int plugin_load(const char* plugin, const void* parameter) |
805 | { | 807 | { |
806 | struct plugin_header *p_hdr; | 808 | struct plugin_header *p_hdr; |
@@ -815,6 +817,8 @@ int plugin_load(const char* plugin, const void* parameter) | |||
815 | } | 817 | } |
816 | lc_close(current_plugin_handle); | 818 | lc_close(current_plugin_handle); |
817 | current_plugin_handle = pfn_tsr_exit = NULL; | 819 | current_plugin_handle = pfn_tsr_exit = NULL; |
820 | if (plugin_buffer_handle > 0) | ||
821 | plugin_buffer_handle = core_free(plugin_buffer_handle); | ||
818 | } | 822 | } |
819 | 823 | ||
820 | splash(0, ID2P(LANG_WAIT)); | 824 | splash(0, ID2P(LANG_WAIT)); |
@@ -878,6 +882,9 @@ int plugin_load(const char* plugin, const void* parameter) | |||
878 | touchscreen_set_mode(TOUCHSCREEN_BUTTON); | 882 | touchscreen_set_mode(TOUCHSCREEN_BUTTON); |
879 | #endif | 883 | #endif |
880 | 884 | ||
885 | /* allow voice to back off if the plugin needs lots of memory */ | ||
886 | talk_buffer_set_policy(TALK_BUFFER_LOOSE); | ||
887 | |||
881 | #ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE | 888 | #ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE |
882 | open_files = 0; | 889 | open_files = 0; |
883 | #endif | 890 | #endif |
@@ -891,8 +898,12 @@ int plugin_load(const char* plugin, const void* parameter) | |||
891 | { /* close handle if plugin is no tsr one */ | 898 | { /* close handle if plugin is no tsr one */ |
892 | lc_close(current_plugin_handle); | 899 | lc_close(current_plugin_handle); |
893 | current_plugin_handle = NULL; | 900 | current_plugin_handle = NULL; |
901 | if (plugin_buffer_handle > 0) | ||
902 | plugin_buffer_handle = core_free(plugin_buffer_handle); | ||
894 | } | 903 | } |
895 | 904 | ||
905 | talk_buffer_set_policy(TALK_BUFFER_DEFAULT); | ||
906 | |||
896 | /* Go back to the global setting in case the plugin changed it */ | 907 | /* Go back to the global setting in case the plugin changed it */ |
897 | #ifdef HAVE_TOUCHSCREEN | 908 | #ifdef HAVE_TOUCHSCREEN |
898 | touchscreen_set_mode(global_settings.touch_mode); | 909 | touchscreen_set_mode(global_settings.touch_mode); |
@@ -984,8 +995,12 @@ void* plugin_get_buffer(size_t *buffer_size) | |||
984 | */ | 995 | */ |
985 | void* plugin_get_audio_buffer(size_t *buffer_size) | 996 | void* plugin_get_audio_buffer(size_t *buffer_size) |
986 | { | 997 | { |
987 | audio_stop(); | 998 | /* dummy ops with no callbacks, needed because by |
988 | return audio_get_buffer(true, buffer_size); | 999 | * default buflib buffers can be moved around which must be avoided */ |
1000 | static struct buflib_callbacks dummy_ops; | ||
1001 | plugin_buffer_handle = core_alloc_maximum("plugin audio buf", buffer_size, | ||
1002 | &dummy_ops); | ||
1003 | return core_get_data(plugin_buffer_handle); | ||
989 | } | 1004 | } |
990 | 1005 | ||
991 | /* The plugin wants to stay resident after leaving its main function, e.g. | 1006 | /* The plugin wants to stay resident after leaving its main function, e.g. |