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/playlist.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/playlist.c')
-rwxr-xr-x | apps/playlist.c | 87 |
1 files changed, 63 insertions, 24 deletions
diff --git a/apps/playlist.c b/apps/playlist.c index 35b7e35baa..3d930cf3f9 100755 --- a/apps/playlist.c +++ b/apps/playlist.c | |||
@@ -104,6 +104,7 @@ | |||
104 | #include "rbunicode.h" | 104 | #include "rbunicode.h" |
105 | #include "root_menu.h" | 105 | #include "root_menu.h" |
106 | #include "plugin.h" /* To borrow a temp buffer to rewrite a .m3u8 file */ | 106 | #include "plugin.h" /* To borrow a temp buffer to rewrite a .m3u8 file */ |
107 | #include "panic.h" | ||
107 | 108 | ||
108 | #define PLAYLIST_CONTROL_FILE_VERSION 2 | 109 | #define PLAYLIST_CONTROL_FILE_VERSION 2 |
109 | 110 | ||
@@ -532,13 +533,6 @@ static int add_indices_to_playlist(struct playlist_info* playlist, | |||
532 | 533 | ||
533 | splash(0, ID2P(LANG_WAIT)); | 534 | splash(0, ID2P(LANG_WAIT)); |
534 | 535 | ||
535 | if (!buffer) | ||
536 | { | ||
537 | /* use mp3 buffer for maximum load speed */ | ||
538 | audio_stop(); | ||
539 | buffer = audio_get_buffer(false, &buflen); | ||
540 | } | ||
541 | |||
542 | store_index = true; | 536 | store_index = true; |
543 | 537 | ||
544 | while(1) | 538 | while(1) |
@@ -2077,8 +2071,26 @@ int playlist_create(const char *dir, const char *file) | |||
2077 | new_playlist(playlist, dir, file); | 2071 | new_playlist(playlist, dir, file); |
2078 | 2072 | ||
2079 | if (file) | 2073 | if (file) |
2080 | /* load the playlist file */ | 2074 | { |
2081 | add_indices_to_playlist(playlist, NULL, 0); | 2075 | /* dummy ops with no callbacks, needed because by |
2076 | * default buflib buffers can be moved around which must be avoided */ | ||
2077 | static struct buflib_callbacks dummy_ops; | ||
2078 | int handle; | ||
2079 | size_t buflen; | ||
2080 | /* use mp3 buffer for maximum load speed */ | ||
2081 | handle = core_alloc_maximum("temp", &buflen, &dummy_ops); | ||
2082 | if (handle > 0) | ||
2083 | { | ||
2084 | /* load the playlist file */ | ||
2085 | add_indices_to_playlist(playlist, core_get_data(handle), buflen); | ||
2086 | core_free(handle); | ||
2087 | } | ||
2088 | else | ||
2089 | { | ||
2090 | /* should not happen */ | ||
2091 | panicf("%s(): OOM", __func__); | ||
2092 | } | ||
2093 | } | ||
2082 | 2094 | ||
2083 | return 0; | 2095 | return 0; |
2084 | } | 2096 | } |
@@ -2094,14 +2106,22 @@ int playlist_resume(void) | |||
2094 | struct playlist_info* playlist = ¤t_playlist; | 2106 | struct playlist_info* playlist = ¤t_playlist; |
2095 | char *buffer; | 2107 | char *buffer; |
2096 | size_t buflen; | 2108 | size_t buflen; |
2109 | int handle; | ||
2097 | int nread; | 2110 | int nread; |
2098 | int total_read = 0; | 2111 | int total_read = 0; |
2099 | int control_file_size = 0; | 2112 | int control_file_size = 0; |
2100 | bool first = true; | 2113 | bool first = true; |
2101 | bool sorted = true; | 2114 | bool sorted = true; |
2115 | int result = -1; | ||
2102 | 2116 | ||
2117 | /* dummy ops with no callbacks, needed because by | ||
2118 | * default buflib buffers can be moved around which must be avoided */ | ||
2119 | static struct buflib_callbacks dummy_ops; | ||
2103 | /* use mp3 buffer for maximum load speed */ | 2120 | /* use mp3 buffer for maximum load speed */ |
2104 | buffer = (char *)audio_get_buffer(false, &buflen); | 2121 | handle = core_alloc_maximum("temp", &buflen, &dummy_ops); |
2122 | if (handle < 0) | ||
2123 | panicf("%s(): OOM", __func__); | ||
2124 | buffer = core_get_data(handle); | ||
2105 | 2125 | ||
2106 | empty_playlist(playlist, true); | 2126 | empty_playlist(playlist, true); |
2107 | 2127 | ||
@@ -2110,7 +2130,7 @@ int playlist_resume(void) | |||
2110 | if (playlist->control_fd < 0) | 2130 | if (playlist->control_fd < 0) |
2111 | { | 2131 | { |
2112 | splash(HZ*2, ID2P(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); | 2132 | splash(HZ*2, ID2P(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); |
2113 | return -1; | 2133 | goto out; |
2114 | } | 2134 | } |
2115 | playlist->control_created = true; | 2135 | playlist->control_created = true; |
2116 | 2136 | ||
@@ -2118,7 +2138,7 @@ int playlist_resume(void) | |||
2118 | if (control_file_size <= 0) | 2138 | if (control_file_size <= 0) |
2119 | { | 2139 | { |
2120 | splash(HZ*2, ID2P(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); | 2140 | splash(HZ*2, ID2P(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); |
2121 | return -1; | 2141 | goto out; |
2122 | } | 2142 | } |
2123 | 2143 | ||
2124 | /* read a small amount first to get the header */ | 2144 | /* read a small amount first to get the header */ |
@@ -2127,14 +2147,14 @@ int playlist_resume(void) | |||
2127 | if(nread <= 0) | 2147 | if(nread <= 0) |
2128 | { | 2148 | { |
2129 | splash(HZ*2, ID2P(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); | 2149 | splash(HZ*2, ID2P(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); |
2130 | return -1; | 2150 | goto out; |
2131 | } | 2151 | } |
2132 | 2152 | ||
2133 | playlist->started = true; | 2153 | playlist->started = true; |
2134 | 2154 | ||
2135 | while (1) | 2155 | while (1) |
2136 | { | 2156 | { |
2137 | int result = 0; | 2157 | result = 0; |
2138 | int count; | 2158 | int count; |
2139 | enum playlist_command current_command = PLAYLIST_COMMAND_COMMENT; | 2159 | enum playlist_command current_command = PLAYLIST_COMMAND_COMMENT; |
2140 | int last_newline = 0; | 2160 | int last_newline = 0; |
@@ -2195,7 +2215,10 @@ int playlist_resume(void) | |||
2195 | version = atoi(str1); | 2215 | version = atoi(str1); |
2196 | 2216 | ||
2197 | if (version != PLAYLIST_CONTROL_FILE_VERSION) | 2217 | if (version != PLAYLIST_CONTROL_FILE_VERSION) |
2198 | return -1; | 2218 | { |
2219 | result = -1; | ||
2220 | goto out; | ||
2221 | } | ||
2199 | 2222 | ||
2200 | update_playlist_filename(playlist, str2, str3); | 2223 | update_playlist_filename(playlist, str2, str3); |
2201 | 2224 | ||
@@ -2204,7 +2227,7 @@ int playlist_resume(void) | |||
2204 | /* NOTE: add_indices_to_playlist() overwrites the | 2227 | /* NOTE: add_indices_to_playlist() overwrites the |
2205 | audiobuf so we need to reload control file | 2228 | audiobuf so we need to reload control file |
2206 | data */ | 2229 | data */ |
2207 | add_indices_to_playlist(playlist, NULL, 0); | 2230 | add_indices_to_playlist(playlist, buffer, buflen); |
2208 | } | 2231 | } |
2209 | else if (str2[0] != '\0') | 2232 | else if (str2[0] != '\0') |
2210 | { | 2233 | { |
@@ -2242,7 +2265,10 @@ int playlist_resume(void) | |||
2242 | buffer */ | 2265 | buffer */ |
2243 | if (add_track_to_playlist(playlist, str3, position, | 2266 | if (add_track_to_playlist(playlist, str3, position, |
2244 | queue, total_read+(str3-buffer)) < 0) | 2267 | queue, total_read+(str3-buffer)) < 0) |
2245 | return -1; | 2268 | { |
2269 | result = -1; | ||
2270 | goto out; | ||
2271 | } | ||
2246 | 2272 | ||
2247 | playlist->last_insert_pos = last_position; | 2273 | playlist->last_insert_pos = last_position; |
2248 | 2274 | ||
@@ -2264,7 +2290,10 @@ int playlist_resume(void) | |||
2264 | 2290 | ||
2265 | if (remove_track_from_playlist(playlist, position, | 2291 | if (remove_track_from_playlist(playlist, position, |
2266 | false) < 0) | 2292 | false) < 0) |
2267 | return -1; | 2293 | { |
2294 | result = -1; | ||
2295 | goto out; | ||
2296 | } | ||
2268 | 2297 | ||
2269 | break; | 2298 | break; |
2270 | } | 2299 | } |
@@ -2291,7 +2320,10 @@ int playlist_resume(void) | |||
2291 | 2320 | ||
2292 | if (randomise_playlist(playlist, seed, false, | 2321 | if (randomise_playlist(playlist, seed, false, |
2293 | false) < 0) | 2322 | false) < 0) |
2294 | return -1; | 2323 | { |
2324 | result = -1; | ||
2325 | goto out; | ||
2326 | } | ||
2295 | sorted = false; | 2327 | sorted = false; |
2296 | break; | 2328 | break; |
2297 | } | 2329 | } |
@@ -2308,7 +2340,10 @@ int playlist_resume(void) | |||
2308 | playlist->first_index = atoi(str1); | 2340 | playlist->first_index = atoi(str1); |
2309 | 2341 | ||
2310 | if (sort_playlist(playlist, false, false) < 0) | 2342 | if (sort_playlist(playlist, false, false) < 0) |
2311 | return -1; | 2343 | { |
2344 | result = -1; | ||
2345 | goto out; | ||
2346 | } | ||
2312 | 2347 | ||
2313 | sorted = true; | 2348 | sorted = true; |
2314 | break; | 2349 | break; |
@@ -2421,13 +2456,14 @@ int playlist_resume(void) | |||
2421 | if (result < 0) | 2456 | if (result < 0) |
2422 | { | 2457 | { |
2423 | splash(HZ*2, ID2P(LANG_PLAYLIST_CONTROL_INVALID)); | 2458 | splash(HZ*2, ID2P(LANG_PLAYLIST_CONTROL_INVALID)); |
2424 | return result; | 2459 | goto out; |
2425 | } | 2460 | } |
2426 | 2461 | ||
2427 | if (useraborted) | 2462 | if (useraborted) |
2428 | { | 2463 | { |
2429 | splash(HZ*2, ID2P(LANG_CANCEL)); | 2464 | splash(HZ*2, ID2P(LANG_CANCEL)); |
2430 | return -1; | 2465 | result = -1; |
2466 | goto out; | ||
2431 | } | 2467 | } |
2432 | if (!newline || (exit_loop && count<nread)) | 2468 | if (!newline || (exit_loop && count<nread)) |
2433 | { | 2469 | { |
@@ -2435,7 +2471,8 @@ int playlist_resume(void) | |||
2435 | { | 2471 | { |
2436 | /* no newline at end of control file */ | 2472 | /* no newline at end of control file */ |
2437 | splash(HZ*2, ID2P(LANG_PLAYLIST_CONTROL_INVALID)); | 2473 | splash(HZ*2, ID2P(LANG_PLAYLIST_CONTROL_INVALID)); |
2438 | return -1; | 2474 | result = -1; |
2475 | goto out; | ||
2439 | } | 2476 | } |
2440 | 2477 | ||
2441 | /* We didn't end on a newline or we exited loop prematurely. | 2478 | /* We didn't end on a newline or we exited loop prematurely. |
@@ -2464,7 +2501,9 @@ int playlist_resume(void) | |||
2464 | queue_post(&playlist_queue, PLAYLIST_LOAD_POINTERS, 0); | 2501 | queue_post(&playlist_queue, PLAYLIST_LOAD_POINTERS, 0); |
2465 | #endif | 2502 | #endif |
2466 | 2503 | ||
2467 | return 0; | 2504 | out: |
2505 | core_free(handle); | ||
2506 | return result; | ||
2468 | } | 2507 | } |
2469 | 2508 | ||
2470 | /* | 2509 | /* |