diff options
author | Brandon Low <lostlogic@rockbox.org> | 2006-10-17 12:56:22 +0000 |
---|---|---|
committer | Brandon Low <lostlogic@rockbox.org> | 2006-10-17 12:56:22 +0000 |
commit | 08a4ceaae7ac756b8815b230d12ba7992a0cb120 (patch) | |
tree | 064f3648a81b8dc3c4293becc5f77bf9a8ab9a27 /apps/playback.c | |
parent | f8e2f3e08d779092cf7d3f26f369c0941edf9349 (diff) | |
download | rockbox-08a4ceaae7ac756b8815b230d12ba7992a0cb120.tar.gz rockbox-08a4ceaae7ac756b8815b230d12ba7992a0cb120.zip |
Remove fill_bytesleft, simplify some buffering code, fix bug 5906
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11247 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/playback.c')
-rw-r--r-- | apps/playback.c | 220 |
1 files changed, 99 insertions, 121 deletions
diff --git a/apps/playback.c b/apps/playback.c index feba1d1c6c..5cf059f3c6 100644 --- a/apps/playback.c +++ b/apps/playback.c | |||
@@ -194,6 +194,7 @@ static volatile size_t buf_widx IDATA_ATTR; | |||
194 | /* Ring buffer arithmetic */ | 194 | /* Ring buffer arithmetic */ |
195 | #define RINGBUF_ADD(p,v) ((p+v)<filebuflen ? p+v : p+v-filebuflen) | 195 | #define RINGBUF_ADD(p,v) ((p+v)<filebuflen ? p+v : p+v-filebuflen) |
196 | #define RINGBUF_SUB(p,v) ((p>=v) ? p-v : p+filebuflen-v) | 196 | #define RINGBUF_SUB(p,v) ((p>=v) ? p-v : p+filebuflen-v) |
197 | #define RINGBUF_ADD_CROSS(p1,v,p2) ((p1<p2)?(int)(p1+v)-(int)p2:(int)(p1+v-p2)-(int)filebuflen) | ||
197 | 198 | ||
198 | /* Bytes available in the buffer. */ | 199 | /* Bytes available in the buffer. */ |
199 | #define FILEBUFUSED RINGBUF_SUB(buf_widx, buf_ridx) | 200 | #define FILEBUFUSED RINGBUF_SUB(buf_widx, buf_ridx) |
@@ -214,9 +215,6 @@ static bool track_changed; /* Audio and codec threads */ | |||
214 | /* Partially loaded song's file handle to continue buffering later. */ | 215 | /* Partially loaded song's file handle to continue buffering later. */ |
215 | static int current_fd; | 216 | static int current_fd; |
216 | 217 | ||
217 | /* Information about how many bytes left on the buffer re-fill run. */ | ||
218 | static size_t fill_bytesleft; | ||
219 | |||
220 | /* Track info structure about songs in the file buffer. */ | 218 | /* Track info structure about songs in the file buffer. */ |
221 | static struct track_info tracks[MAX_TRACK]; /* Audio thread */ | 219 | static struct track_info tracks[MAX_TRACK]; /* Audio thread */ |
222 | 220 | ||
@@ -1236,7 +1234,7 @@ static void codec_advance_buffer_counters(size_t amount) | |||
1236 | /* Start buffer filling as necessary. */ | 1234 | /* Start buffer filling as necessary. */ |
1237 | if (!pcmbuf_is_lowdata() && !filling) | 1235 | if (!pcmbuf_is_lowdata() && !filling) |
1238 | { | 1236 | { |
1239 | if (conf_watermark && FILEBUFUSED <= conf_watermark && playing) | 1237 | if (FILEBUFUSED < conf_watermark && playing) |
1240 | { | 1238 | { |
1241 | LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER"); | 1239 | LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER"); |
1242 | queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0); | 1240 | queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0); |
@@ -2034,9 +2032,7 @@ static bool audio_yield_codecs(void) | |||
2034 | } | 2032 | } |
2035 | 2033 | ||
2036 | /* Note that this function might yield(). */ | 2034 | /* Note that this function might yield(). */ |
2037 | static void audio_clear_track_entries( | 2035 | static void audio_clear_track_entries(bool clear_unbuffered) |
2038 | bool clear_buffered, bool clear_unbuffered, | ||
2039 | bool may_yield) | ||
2040 | { | 2036 | { |
2041 | int cur_idx = track_widx; | 2037 | int cur_idx = track_widx; |
2042 | int last_idx = -1; | 2038 | int last_idx = -1; |
@@ -2056,23 +2052,16 @@ static void audio_clear_track_entries( | |||
2056 | * otherwise clear the track if that option is selected */ | 2052 | * otherwise clear the track if that option is selected */ |
2057 | if (tracks[cur_idx].event_sent) | 2053 | if (tracks[cur_idx].event_sent) |
2058 | { | 2054 | { |
2059 | if (clear_buffered) | 2055 | if (last_idx >= 0) |
2060 | { | 2056 | { |
2061 | if (last_idx >= 0) | 2057 | /* If there is an unbuffer callback, call it, otherwise, |
2062 | { | 2058 | * just clear the track */ |
2063 | /* If there is an unbuffer callback, call it, otherwise, | 2059 | if (track_unbuffer_callback) |
2064 | * just clear the track */ | 2060 | track_unbuffer_callback(&tracks[last_idx].id3, false); |
2065 | if (track_unbuffer_callback) | 2061 | |
2066 | { | 2062 | memset(&tracks[last_idx], 0, sizeof(struct track_info)); |
2067 | if (may_yield) | ||
2068 | audio_yield_codecs(); | ||
2069 | track_unbuffer_callback(&tracks[last_idx].id3, false); | ||
2070 | } | ||
2071 | |||
2072 | memset(&tracks[last_idx], 0, sizeof(struct track_info)); | ||
2073 | } | ||
2074 | last_idx = cur_idx; | ||
2075 | } | 2063 | } |
2064 | last_idx = cur_idx; | ||
2076 | } | 2065 | } |
2077 | else if (clear_unbuffered) | 2066 | else if (clear_unbuffered) |
2078 | memset(&tracks[cur_idx], 0, sizeof(struct track_info)); | 2067 | memset(&tracks[cur_idx], 0, sizeof(struct track_info)); |
@@ -2118,68 +2107,71 @@ static void audio_strip_id3v1_tag(void) | |||
2118 | } | 2107 | } |
2119 | } | 2108 | } |
2120 | 2109 | ||
2121 | static void audio_read_file(bool quick) | 2110 | /* Returns true if a whole file is read, false otherwise */ |
2111 | static bool audio_read_file(size_t minimum) | ||
2122 | { | 2112 | { |
2123 | size_t copy_n; | 2113 | bool ret_val = false; |
2124 | int rc; | ||
2125 | 2114 | ||
2126 | /* If we're called and no file is open, this is an error */ | 2115 | /* If we're called and no file is open, this is an error */ |
2127 | if (current_fd < 0) | 2116 | if (current_fd < 0) |
2128 | { | 2117 | { |
2129 | logf("Bad fd in arf"); | 2118 | logf("Bad fd in arf"); |
2130 | /* Stop this buffer cycle immediately */ | ||
2131 | fill_bytesleft = 0; | ||
2132 | /* Give some hope of miraculous recovery by forcing a track reload */ | 2119 | /* Give some hope of miraculous recovery by forcing a track reload */ |
2133 | tracks[track_widx].filesize = 0; | 2120 | tracks[track_widx].filesize = 0; |
2134 | return ; | 2121 | /* Stop this buffering run */ |
2122 | return ret_val; | ||
2135 | } | 2123 | } |
2136 | 2124 | ||
2137 | trigger_cpu_boost(); | 2125 | trigger_cpu_boost(); |
2138 | while (tracks[track_widx].filerem > 0) | 2126 | while (tracks[track_widx].filerem > 0) |
2139 | { | 2127 | { |
2128 | size_t copy_n; | ||
2140 | int overlap; | 2129 | int overlap; |
2141 | 2130 | int rc; | |
2142 | if (fill_bytesleft == 0) | ||
2143 | break ; | ||
2144 | 2131 | ||
2145 | /* copy_n is the largest chunk that is safe to read */ | 2132 | /* copy_n is the largest chunk that is safe to read */ |
2146 | copy_n = MIN(conf_filechunk, filebuflen - buf_widx); | 2133 | copy_n = MIN(conf_filechunk, filebuflen - buf_widx); |
2147 | copy_n = MIN(copy_n, fill_bytesleft); | 2134 | |
2135 | if (RINGBUF_ADD_CROSS(buf_widx,copy_n,buf_ridx) >= 0) | ||
2136 | break; | ||
2148 | 2137 | ||
2149 | /* rc is the actual amount read */ | 2138 | /* rc is the actual amount read */ |
2150 | rc = read(current_fd, &filebuf[buf_widx], copy_n); | 2139 | rc = read(current_fd, &filebuf[buf_widx], copy_n); |
2151 | 2140 | ||
2152 | if (rc <= 0) | 2141 | if (rc < 0) |
2153 | { | 2142 | { |
2154 | /* Reached the end of the file */ | 2143 | logf("File ended %dB early", tracks[track_widx].filerem); |
2144 | tracks[track_widx].filesize -= tracks[track_widx].filerem; | ||
2155 | tracks[track_widx].filerem = 0; | 2145 | tracks[track_widx].filerem = 0; |
2156 | break ; | 2146 | break; |
2157 | } | 2147 | } |
2158 | 2148 | ||
2159 | overlap = buf_widx + rc - CUR_TI->buf_idx; | ||
2160 | buf_widx = RINGBUF_ADD(buf_widx, rc); | ||
2161 | |||
2162 | if (overlap > 0 && (unsigned) overlap >= filebuflen) | ||
2163 | overlap -= filebuflen; | ||
2164 | |||
2165 | if (overlap > 0 && overlap <= rc && CUR_TI->available != 0) { | ||
2166 | CUR_TI->buf_idx = buf_widx; | ||
2167 | CUR_TI->start_pos += overlap; | ||
2168 | } | ||
2169 | |||
2170 | tracks[track_widx].available += rc; | 2149 | tracks[track_widx].available += rc; |
2171 | tracks[track_widx].filerem -= rc; | 2150 | tracks[track_widx].filerem -= rc; |
2172 | 2151 | ||
2173 | if (fill_bytesleft > (unsigned)rc) | 2152 | /* How much of the playing track did we overwrite */ |
2174 | fill_bytesleft -= rc; | 2153 | overlap = RINGBUF_ADD_CROSS(buf_widx,rc,CUR_TI->buf_idx); |
2175 | else | 2154 | |
2176 | fill_bytesleft = 0; | 2155 | /* Advance buffer */ |
2156 | buf_widx = RINGBUF_ADD(buf_widx, rc); | ||
2177 | 2157 | ||
2178 | /* Let the codec process until it is out of the danger zone, or there | 2158 | /* If we write into the playing track, adjust it's buffer info */ |
2179 | * is an event to handle. In the latter case, break this fill cycle | 2159 | if (overlap > 0 && CUR_TI->available != 0) { |
2180 | * immediately */ | 2160 | CUR_TI->buf_idx += overlap; |
2181 | if (quick || audio_yield_codecs()) | 2161 | CUR_TI->start_pos += overlap; |
2162 | } | ||
2163 | |||
2164 | /* For a rebuffer, fill at least this minimum */ | ||
2165 | if (minimum > (unsigned)rc) | ||
2166 | minimum -= rc; | ||
2167 | /* Let the codec process up to the watermark */ | ||
2168 | /* Break immediately if this is a quick buffer, or there is an event */ | ||
2169 | else if (minimum || audio_yield_codecs()) | ||
2170 | { | ||
2171 | /* Exit quickly, but don't stop the overall buffering process */ | ||
2172 | ret_val = true; | ||
2182 | break; | 2173 | break; |
2174 | } | ||
2183 | } | 2175 | } |
2184 | 2176 | ||
2185 | if (tracks[track_widx].filerem == 0) | 2177 | if (tracks[track_widx].filerem == 0) |
@@ -2193,17 +2185,19 @@ static void audio_read_file(bool quick) | |||
2193 | track_widx &= MAX_TRACK_MASK; | 2185 | track_widx &= MAX_TRACK_MASK; |
2194 | 2186 | ||
2195 | tracks[track_widx].filesize = 0; | 2187 | tracks[track_widx].filesize = 0; |
2188 | return true; | ||
2196 | } | 2189 | } |
2197 | else | 2190 | else |
2198 | { | 2191 | { |
2199 | logf("Partially buf:%dB", | 2192 | logf("%s buf:%dB", ret_val?"Quick":"Partially", |
2200 | tracks[track_widx].filesize - tracks[track_widx].filerem); | 2193 | tracks[track_widx].filesize - tracks[track_widx].filerem); |
2194 | return ret_val; | ||
2201 | } | 2195 | } |
2202 | } | 2196 | } |
2203 | 2197 | ||
2204 | static bool audio_loadcodec(bool start_play) | 2198 | static bool audio_loadcodec(bool start_play) |
2205 | { | 2199 | { |
2206 | size_t size; | 2200 | size_t size = 0; |
2207 | int fd; | 2201 | int fd; |
2208 | int rc; | 2202 | int rc; |
2209 | size_t copy_n; | 2203 | size_t copy_n; |
@@ -2215,7 +2209,6 @@ static bool audio_loadcodec(bool start_play) | |||
2215 | return false; | 2209 | return false; |
2216 | 2210 | ||
2217 | tracks[track_widx].has_codec = false; | 2211 | tracks[track_widx].has_codec = false; |
2218 | tracks[track_widx].codecsize = 0; | ||
2219 | 2212 | ||
2220 | if (start_play) | 2213 | if (start_play) |
2221 | { | 2214 | { |
@@ -2257,35 +2250,34 @@ static bool audio_loadcodec(bool start_play) | |||
2257 | return false; | 2250 | return false; |
2258 | } | 2251 | } |
2259 | 2252 | ||
2260 | size = filesize(fd); | 2253 | tracks[track_widx].codecsize = filesize(fd); |
2261 | 2254 | ||
2262 | /* Never load a partial codec */ | 2255 | /* Never load a partial codec */ |
2263 | if (fill_bytesleft < size) | 2256 | if (RINGBUF_ADD_CROSS(buf_widx,tracks[track_widx].codecsize,buf_ridx) >= 0) |
2264 | { | 2257 | { |
2265 | logf("Not enough space"); | 2258 | logf("Not enough space"); |
2266 | fill_bytesleft = 0; | ||
2267 | close(fd); | 2259 | close(fd); |
2268 | return false; | 2260 | return false; |
2269 | } | 2261 | } |
2270 | 2262 | ||
2271 | while (tracks[track_widx].codecsize < size) | 2263 | while (size < tracks[track_widx].codecsize) |
2272 | { | 2264 | { |
2273 | copy_n = MIN(conf_filechunk, filebuflen - buf_widx); | 2265 | copy_n = MIN(conf_filechunk, filebuflen - buf_widx); |
2274 | rc = read(fd, &filebuf[buf_widx], copy_n); | 2266 | rc = read(fd, &filebuf[buf_widx], copy_n); |
2275 | if (rc < 0) | 2267 | if (rc < 0) |
2276 | { | 2268 | { |
2277 | close(fd); | 2269 | close(fd); |
2270 | /* This is an error condition, likely the codec file is corrupt */ | ||
2271 | logf("Partial codec loaded"); | ||
2272 | /* Must undo the buffer write of the partial codec */ | ||
2273 | buf_widx = RINGBUF_SUB(buf_widx, size); | ||
2274 | tracks[track_widx].codecsize = 0; | ||
2278 | return false; | 2275 | return false; |
2279 | } | 2276 | } |
2280 | 2277 | ||
2281 | if (fill_bytesleft > (unsigned)rc) | ||
2282 | fill_bytesleft -= rc; | ||
2283 | else | ||
2284 | fill_bytesleft = 0; | ||
2285 | |||
2286 | buf_widx = RINGBUF_ADD(buf_widx, rc); | 2278 | buf_widx = RINGBUF_ADD(buf_widx, rc); |
2287 | 2279 | ||
2288 | tracks[track_widx].codecsize += rc; | 2280 | size += rc; |
2289 | } | 2281 | } |
2290 | 2282 | ||
2291 | tracks[track_widx].has_codec = true; | 2283 | tracks[track_widx].has_codec = true; |
@@ -2446,35 +2438,28 @@ static bool audio_load_track(int offset, bool start_play, bool rebuffer) | |||
2446 | tracks[track_widx].codecbuf = &filebuf[buf_widx]; | 2438 | tracks[track_widx].codecbuf = &filebuf[buf_widx]; |
2447 | if (!audio_loadcodec(start_play)) | 2439 | if (!audio_loadcodec(start_play)) |
2448 | { | 2440 | { |
2449 | if (tracks[track_widx].codecsize) | ||
2450 | { | ||
2451 | /* Must undo the buffer write of the partial codec */ | ||
2452 | logf("Partial codec loaded"); | ||
2453 | fill_bytesleft += tracks[track_widx].codecsize; | ||
2454 | buf_widx = RINGBUF_SUB(buf_widx, tracks[track_widx].codecsize); | ||
2455 | tracks[track_widx].codecsize = 0; | ||
2456 | } | ||
2457 | |||
2458 | /* Set filesize to zero to indicate no file was loaded. */ | 2441 | /* Set filesize to zero to indicate no file was loaded. */ |
2459 | tracks[track_widx].filesize = 0; | 2442 | tracks[track_widx].filesize = 0; |
2460 | tracks[track_widx].filerem = 0; | 2443 | tracks[track_widx].filerem = 0; |
2461 | close(current_fd); | 2444 | close(current_fd); |
2462 | current_fd = -1; | 2445 | current_fd = -1; |
2463 | 2446 | ||
2464 | /* Try skipping to next track if there is space. */ | 2447 | if (tracks[track_widx].codecsize) |
2465 | if (fill_bytesleft > 0) | ||
2466 | { | 2448 | { |
2467 | /* This is an error condition unless the fill_bytesleft is 0 */ | 2449 | /* No space for codec on buffer, not an error */ |
2468 | snprintf(msgbuf, sizeof(msgbuf)-1, "No codec for: %s", trackname); | 2450 | tracks[track_widx].codecsize = 0; |
2469 | /* We should not use gui_syncplash from audio thread! */ | 2451 | return false; |
2470 | gui_syncsplash(HZ*2, true, msgbuf); | ||
2471 | /* Skip invalid entry from playlist. */ | ||
2472 | playlist_skip_entry(NULL, last_peek_offset); | ||
2473 | tracks[track_widx].taginfo_ready = false; | ||
2474 | goto peek_again; | ||
2475 | } | 2452 | } |
2476 | 2453 | ||
2477 | return false; | 2454 | /* This is an error condition, either no codec was found, or reading |
2455 | * the codec file failed part way through, either way, skip the track */ | ||
2456 | snprintf(msgbuf, sizeof(msgbuf)-1, "No codec for: %s", trackname); | ||
2457 | /* We should not use gui_syncplash from audio thread! */ | ||
2458 | gui_syncsplash(HZ*2, true, msgbuf); | ||
2459 | /* Skip invalid entry from playlist. */ | ||
2460 | playlist_skip_entry(NULL, last_peek_offset); | ||
2461 | tracks[track_widx].taginfo_ready = false; | ||
2462 | goto peek_again; | ||
2478 | } | 2463 | } |
2479 | 2464 | ||
2480 | tracks[track_widx].start_pos = 0; | 2465 | tracks[track_widx].start_pos = 0; |
@@ -2518,9 +2503,7 @@ static bool audio_load_track(int offset, bool start_play, bool rebuffer) | |||
2518 | logf("alt:%s", trackname); | 2503 | logf("alt:%s", trackname); |
2519 | tracks[track_widx].buf_idx = buf_widx; | 2504 | tracks[track_widx].buf_idx = buf_widx; |
2520 | 2505 | ||
2521 | audio_read_file(rebuffer); | 2506 | return audio_read_file(rebuffer); |
2522 | |||
2523 | return true; | ||
2524 | } | 2507 | } |
2525 | 2508 | ||
2526 | static bool audio_read_next_metadata(void) | 2509 | static bool audio_read_next_metadata(void) |
@@ -2612,28 +2595,14 @@ static bool audio_initialize_buffer_fill(bool clear_tracks) | |||
2612 | if (filling) | 2595 | if (filling) |
2613 | return true; | 2596 | return true; |
2614 | 2597 | ||
2615 | /* Don't start buffer fill if buffer is already full. */ | ||
2616 | if (FILEBUFUSED > conf_watermark && !filling) | ||
2617 | return false; | ||
2618 | |||
2619 | logf("Starting buffer fill"); | 2598 | logf("Starting buffer fill"); |
2620 | 2599 | ||
2621 | fill_bytesleft = filebuflen - FILEBUFUSED; | ||
2622 | /* TODO: This doesn't look right, and might explain some problems with | ||
2623 | * seeking in large files (to offsets larger than filebuflen). | ||
2624 | * And what about buffer wraps? | ||
2625 | * | ||
2626 | * This really doesn't look right, so don't use it. | ||
2627 | */ | ||
2628 | // if (buf_ridx > CUR_TI->buf_idx) | ||
2629 | // CUR_TI->start_pos = buf_ridx - CUR_TI->buf_idx; | ||
2630 | |||
2631 | /* Set the filling flag true before calling audio_clear_tracks as that | 2600 | /* Set the filling flag true before calling audio_clear_tracks as that |
2632 | * function can yield and we start looping. */ | 2601 | * function can yield and we start looping. */ |
2633 | filling = true; | 2602 | filling = true; |
2634 | 2603 | ||
2635 | if (clear_tracks) | 2604 | if (clear_tracks) |
2636 | audio_clear_track_entries(true, false, true); | 2605 | audio_clear_track_entries(false); |
2637 | 2606 | ||
2638 | /* Save the current resume position once. */ | 2607 | /* Save the current resume position once. */ |
2639 | playlist_update_resume_info(audio_current_track()); | 2608 | playlist_update_resume_info(audio_current_track()); |
@@ -2645,6 +2614,7 @@ static void audio_fill_file_buffer( | |||
2645 | bool start_play, bool rebuffer, size_t offset) | 2614 | bool start_play, bool rebuffer, size_t offset) |
2646 | { | 2615 | { |
2647 | bool had_next_track = audio_next_track() != NULL; | 2616 | bool had_next_track = audio_next_track() != NULL; |
2617 | bool continue_buffering; | ||
2648 | 2618 | ||
2649 | if (!audio_initialize_buffer_fill(!start_play)) | 2619 | if (!audio_initialize_buffer_fill(!start_play)) |
2650 | return ; | 2620 | return ; |
@@ -2652,15 +2622,15 @@ static void audio_fill_file_buffer( | |||
2652 | /* If we have a partially buffered track, continue loading, | 2622 | /* If we have a partially buffered track, continue loading, |
2653 | * otherwise load a new track */ | 2623 | * otherwise load a new track */ |
2654 | if (tracks[track_widx].filesize > 0) | 2624 | if (tracks[track_widx].filesize > 0) |
2655 | audio_read_file(false); | 2625 | continue_buffering = audio_read_file(rebuffer); |
2656 | else if (!audio_load_track(offset, start_play, rebuffer)) | 2626 | else |
2657 | fill_bytesleft = 0; | 2627 | continue_buffering = audio_load_track(offset, start_play, rebuffer); |
2658 | 2628 | ||
2659 | if (!had_next_track && audio_next_track()) | 2629 | if (!had_next_track && audio_next_track()) |
2660 | track_changed = true; | 2630 | track_changed = true; |
2661 | 2631 | ||
2662 | /* If we're done buffering */ | 2632 | /* If we're done buffering */ |
2663 | if (fill_bytesleft == 0) | 2633 | if (!continue_buffering) |
2664 | { | 2634 | { |
2665 | audio_read_next_metadata(); | 2635 | audio_read_next_metadata(); |
2666 | 2636 | ||
@@ -2672,6 +2642,7 @@ static void audio_fill_file_buffer( | |||
2672 | ata_sleep(); | 2642 | ata_sleep(); |
2673 | #endif | 2643 | #endif |
2674 | } | 2644 | } |
2645 | |||
2675 | } | 2646 | } |
2676 | 2647 | ||
2677 | static void audio_rebuffer(void) | 2648 | static void audio_rebuffer(void) |
@@ -2708,7 +2679,7 @@ static void audio_rebuffer(void) | |||
2708 | /* Reset buffer and track pointers */ | 2679 | /* Reset buffer and track pointers */ |
2709 | CUR_TI->buf_idx = buf_ridx = buf_widx = 0; | 2680 | CUR_TI->buf_idx = buf_ridx = buf_widx = 0; |
2710 | track_widx = track_ridx; | 2681 | track_widx = track_ridx; |
2711 | audio_clear_track_entries(true, true, false); | 2682 | audio_clear_track_entries(true); |
2712 | CUR_TI->available = 0; | 2683 | CUR_TI->available = 0; |
2713 | 2684 | ||
2714 | /* Fill the buffer */ | 2685 | /* Fill the buffer */ |
@@ -2893,23 +2864,30 @@ static void audio_rebuffer_and_seek(size_t newpos) | |||
2893 | last_peek_offset = 0; | 2864 | last_peek_offset = 0; |
2894 | filling = false; | 2865 | filling = false; |
2895 | audio_initialize_buffer_fill(true); | 2866 | audio_initialize_buffer_fill(true); |
2896 | filling = true; | ||
2897 | 2867 | ||
2898 | if (newpos > conf_preseek) { | 2868 | if (newpos > conf_preseek) |
2899 | buf_ridx = RINGBUF_ADD(buf_ridx, conf_preseek); | 2869 | { |
2900 | CUR_TI->start_pos = newpos - conf_preseek; | 2870 | CUR_TI->start_pos = newpos - conf_preseek; |
2871 | CUR_TI->filerem = CUR_TI->filesize - CUR_TI->start_pos; | ||
2872 | newpos = conf_preseek; | ||
2901 | } | 2873 | } |
2902 | else | 2874 | else |
2903 | { | 2875 | { |
2904 | buf_ridx = RINGBUF_ADD(buf_ridx, newpos); | ||
2905 | CUR_TI->start_pos = 0; | 2876 | CUR_TI->start_pos = 0; |
2877 | CUR_TI->filerem = CUR_TI->filesize; | ||
2906 | } | 2878 | } |
2907 | 2879 | ||
2908 | CUR_TI->filerem = CUR_TI->filesize - CUR_TI->start_pos; | ||
2909 | CUR_TI->available = 0; | 2880 | CUR_TI->available = 0; |
2910 | 2881 | ||
2911 | lseek(current_fd, CUR_TI->start_pos, SEEK_SET); | 2882 | lseek(current_fd, CUR_TI->start_pos, SEEK_SET); |
2912 | 2883 | ||
2884 | audio_read_file(newpos); | ||
2885 | |||
2886 | /* Account for the data we just read that is 'behind' us now */ | ||
2887 | CUR_TI->available -= newpos; | ||
2888 | |||
2889 | buf_ridx = RINGBUF_ADD(buf_ridx, newpos); | ||
2890 | |||
2913 | LOGFQUEUE("audio > codec Q_CODEC_REQUEST_COMPLETE"); | 2891 | LOGFQUEUE("audio > codec Q_CODEC_REQUEST_COMPLETE"); |
2914 | queue_post(&codec_callback_queue, Q_CODEC_REQUEST_COMPLETE, 0); | 2892 | queue_post(&codec_callback_queue, Q_CODEC_REQUEST_COMPLETE, 0); |
2915 | } | 2893 | } |
@@ -2967,7 +2945,7 @@ static void audio_stop_playback(void) | |||
2967 | } | 2945 | } |
2968 | 2946 | ||
2969 | /* Mark all entries null. */ | 2947 | /* Mark all entries null. */ |
2970 | audio_clear_track_entries(true, false, false); | 2948 | audio_clear_track_entries(false); |
2971 | memset(tracks, 0, sizeof(struct track_info) * MAX_TRACK); | 2949 | memset(tracks, 0, sizeof(struct track_info) * MAX_TRACK); |
2972 | } | 2950 | } |
2973 | 2951 | ||
@@ -3015,13 +2993,13 @@ void audio_invalidate_tracks(void) | |||
3015 | 2993 | ||
3016 | playlist_end = false; | 2994 | playlist_end = false; |
3017 | track_widx = track_ridx; | 2995 | track_widx = track_ridx; |
3018 | audio_clear_track_entries(true, true, true); | 2996 | /* Mark all other entries null (also buffered wrong metadata). */ |
2997 | audio_clear_track_entries(true); | ||
3019 | 2998 | ||
3020 | /* If the current track is fully buffered, advance the write pointer */ | 2999 | /* If the current track is fully buffered, advance the write pointer */ |
3021 | if (tracks[track_widx].filerem == 0) | 3000 | if (tracks[track_widx].filerem == 0) |
3022 | track_widx = (track_widx + 1) & MAX_TRACK_MASK; | 3001 | track_widx = (track_widx + 1) & MAX_TRACK_MASK; |
3023 | 3002 | ||
3024 | /* Mark all other entries null (also buffered wrong metadata). */ | ||
3025 | buf_widx = RINGBUF_ADD(buf_ridx, CUR_TI->available); | 3003 | buf_widx = RINGBUF_ADD(buf_ridx, CUR_TI->available); |
3026 | 3004 | ||
3027 | audio_read_next_metadata(); | 3005 | audio_read_next_metadata(); |
@@ -3035,7 +3013,7 @@ static void audio_new_playlist(void) | |||
3035 | if (audio_have_tracks()) { | 3013 | if (audio_have_tracks()) { |
3036 | playlist_end = false; | 3014 | playlist_end = false; |
3037 | track_widx = track_ridx; | 3015 | track_widx = track_ridx; |
3038 | audio_clear_track_entries(true, true, true); | 3016 | audio_clear_track_entries(true); |
3039 | 3017 | ||
3040 | track_widx++; | 3018 | track_widx++; |
3041 | track_widx &= MAX_TRACK_MASK; | 3019 | track_widx &= MAX_TRACK_MASK; |
@@ -3239,7 +3217,7 @@ static void audio_thread(void) | |||
3239 | 3217 | ||
3240 | case Q_AUDIO_PLAY: | 3218 | case Q_AUDIO_PLAY: |
3241 | LOGFQUEUE("audio < Q_AUDIO_PLAY"); | 3219 | LOGFQUEUE("audio < Q_AUDIO_PLAY"); |
3242 | audio_clear_track_entries(true, false, true); | 3220 | audio_clear_track_entries(false); |
3243 | audio_play_start((size_t)ev.data); | 3221 | audio_play_start((size_t)ev.data); |
3244 | break ; | 3222 | break ; |
3245 | 3223 | ||