diff options
author | Brandon Low <lostlogic@rockbox.org> | 2006-04-09 02:15:35 +0000 |
---|---|---|
committer | Brandon Low <lostlogic@rockbox.org> | 2006-04-09 02:15:35 +0000 |
commit | 72232bdc663f6437d77e8495c8b8c0ec1245f808 (patch) | |
tree | d9f60d4da31ea67b624056283f1cba0609e292e9 /apps | |
parent | 2ee282396f8cf740db8b3d513f2826503ed2cb00 (diff) | |
download | rockbox-72232bdc663f6437d77e8495c8b8c0ec1245f808.tar.gz rockbox-72232bdc663f6437d77e8495c8b8c0ec1245f808.zip |
Fix bad rebuffering bug, and kill the track_count variable
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9571 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r-- | apps/debug_menu.c | 3 | ||||
-rw-r--r-- | apps/playback.c | 322 |
2 files changed, 168 insertions, 157 deletions
diff --git a/apps/debug_menu.c b/apps/debug_menu.c index 9ad1c5f94c..fff124f779 100644 --- a/apps/debug_menu.c +++ b/apps/debug_menu.c | |||
@@ -211,7 +211,6 @@ bool dbg_audio_thread(void) | |||
211 | extern size_t audiobuffer_free; | 211 | extern size_t audiobuffer_free; |
212 | extern int filebuflen; | 212 | extern int filebuflen; |
213 | extern int filebufused; | 213 | extern int filebufused; |
214 | extern int track_count; | ||
215 | 214 | ||
216 | static unsigned int ticks, boost_ticks; | 215 | static unsigned int ticks, boost_ticks; |
217 | 216 | ||
@@ -276,7 +275,7 @@ bool dbg_audio_thread(void) | |||
276 | filebufused, HORIZONTAL); | 275 | filebufused, HORIZONTAL); |
277 | line++; | 276 | line++; |
278 | 277 | ||
279 | snprintf(buf, sizeof(buf), "track count: %2d", track_count); | 278 | snprintf(buf, sizeof(buf), "track count: %2d", audio_track_count()); |
280 | lcd_puts(0, line++, buf); | 279 | lcd_puts(0, line++, buf); |
281 | 280 | ||
282 | snprintf(buf, sizeof(buf), "cpu freq: %3dMHz", | 281 | snprintf(buf, sizeof(buf), "cpu freq: %3dMHz", |
diff --git a/apps/playback.c b/apps/playback.c index 7889f120f7..ccdacedf85 100644 --- a/apps/playback.c +++ b/apps/playback.c | |||
@@ -88,6 +88,7 @@ static volatile bool paused; | |||
88 | #define AUDIO_DEFAULT_WATERMARK (1024*512) | 88 | #define AUDIO_DEFAULT_WATERMARK (1024*512) |
89 | #define AUDIO_DEFAULT_FILECHUNK (1024*32) | 89 | #define AUDIO_DEFAULT_FILECHUNK (1024*32) |
90 | #define AUDIO_FILEBUF_CRITICAL (1024*128) | 90 | #define AUDIO_FILEBUF_CRITICAL (1024*128) |
91 | #define AUDIO_REBUFFER_GUESS_SIZE (1024*128) | ||
91 | 92 | ||
92 | enum { | 93 | enum { |
93 | Q_AUDIO_PLAY = 1, | 94 | Q_AUDIO_PLAY = 1, |
@@ -96,6 +97,7 @@ enum { | |||
96 | Q_AUDIO_SKIP, | 97 | Q_AUDIO_SKIP, |
97 | Q_AUDIO_PRE_FF_REWIND, | 98 | Q_AUDIO_PRE_FF_REWIND, |
98 | Q_AUDIO_FF_REWIND, | 99 | Q_AUDIO_FF_REWIND, |
100 | Q_AUDIO_REBUFFER_SEEK, | ||
99 | Q_AUDIO_FLUSH_RELOAD, | 101 | Q_AUDIO_FLUSH_RELOAD, |
100 | Q_AUDIO_CODEC_DONE, | 102 | Q_AUDIO_CODEC_DONE, |
101 | Q_AUDIO_FLUSH, | 103 | Q_AUDIO_FLUSH, |
@@ -138,8 +140,8 @@ static struct event_queue voice_codec_queue; | |||
138 | static long voice_codec_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)] IBSS_ATTR; | 140 | static long voice_codec_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)] IBSS_ATTR; |
139 | static const char voice_codec_thread_name[] = "voice codec"; | 141 | static const char voice_codec_thread_name[] = "voice codec"; |
140 | 142 | ||
141 | static struct mutex mutex_bufferfill; | ||
142 | static struct mutex mutex_codecthread; | 143 | static struct mutex mutex_codecthread; |
144 | static struct mutex mutex_rebuffer; | ||
143 | 145 | ||
144 | static struct mp3entry id3_voice; | 146 | static struct mp3entry id3_voice; |
145 | 147 | ||
@@ -178,7 +180,6 @@ static int last_peek_offset; | |||
178 | 180 | ||
179 | /* Track information (count in file buffer, read/write indexes for | 181 | /* Track information (count in file buffer, read/write indexes for |
180 | track ring structure. */ | 182 | track ring structure. */ |
181 | int track_count; | ||
182 | static volatile int track_ridx; | 183 | static volatile int track_ridx; |
183 | static volatile int track_widx; | 184 | static volatile int track_widx; |
184 | static bool track_changed; | 185 | static bool track_changed; |
@@ -451,6 +452,38 @@ static bool filebuf_is_lowdata(void) | |||
451 | return filebufused < AUDIO_FILEBUF_CRITICAL; | 452 | return filebufused < AUDIO_FILEBUF_CRITICAL; |
452 | } | 453 | } |
453 | 454 | ||
455 | static bool have_tracks(void) | ||
456 | { | ||
457 | return track_ridx != track_widx || tracks[track_ridx].filesize; | ||
458 | } | ||
459 | |||
460 | static bool have_free_tracks(void) | ||
461 | { | ||
462 | if (track_widx < track_ridx) | ||
463 | return track_widx + 1 < track_ridx; | ||
464 | else if (track_ridx == 0) | ||
465 | return track_widx < MAX_TRACK - 1; | ||
466 | else | ||
467 | return true; | ||
468 | } | ||
469 | |||
470 | int audio_track_count(void) | ||
471 | { | ||
472 | int track_count = 0; | ||
473 | if (have_tracks()) | ||
474 | { | ||
475 | int cur_idx = track_ridx; | ||
476 | track_count++; | ||
477 | while (cur_idx != track_widx) | ||
478 | { | ||
479 | track_count++; | ||
480 | if (++cur_idx > MAX_TRACK) | ||
481 | cur_idx -= MAX_TRACK; | ||
482 | } | ||
483 | } | ||
484 | return track_count; | ||
485 | } | ||
486 | |||
454 | static void advance_buffer_counters(size_t amount) { | 487 | static void advance_buffer_counters(size_t amount) { |
455 | buf_ridx += amount; | 488 | buf_ridx += amount; |
456 | if (buf_ridx >= filebuflen) | 489 | if (buf_ridx >= filebuflen) |
@@ -597,19 +630,23 @@ void* codec_request_buffer_callback(size_t *realsize, size_t reqsize) | |||
597 | return (char *)&filebuf[buf_ridx]; | 630 | return (char *)&filebuf[buf_ridx]; |
598 | } | 631 | } |
599 | 632 | ||
600 | static bool rebuffer_and_seek(size_t newpos) | 633 | static void rebuffer_and_seek(size_t newpos) |
601 | { | 634 | { |
602 | int fd; | 635 | int fd; |
636 | size_t filepos; | ||
603 | 637 | ||
604 | logf("Re-buffering song"); | 638 | /* Prevent multiple rebuffer calls on codecs that 'hunt' when seeking */ |
605 | mutex_lock(&mutex_bufferfill); | 639 | if (newpos > AUDIO_REBUFFER_GUESS_SIZE) |
640 | filepos = newpos - AUDIO_REBUFFER_GUESS_SIZE; | ||
641 | else | ||
642 | filepos = 0; | ||
606 | 643 | ||
607 | /* (Re-)open current track's file handle. */ | 644 | /* (Re-)open current track's file handle. */ |
608 | fd = open(playlist_peek(0), O_RDONLY); | 645 | fd = open(playlist_peek(0), O_RDONLY); |
609 | if (fd < 0) { | 646 | if (fd < 0) { |
610 | logf("Open failed!"); | 647 | logf("Open failed!"); |
611 | mutex_unlock(&mutex_bufferfill); | 648 | mutex_unlock(&mutex_rebuffer); |
612 | return false; | 649 | return; |
613 | } | 650 | } |
614 | if (current_fd >= 0) | 651 | if (current_fd >= 0) |
615 | close(current_fd); | 652 | close(current_fd); |
@@ -620,18 +657,15 @@ static bool rebuffer_and_seek(size_t newpos) | |||
620 | filebufused = 0; | 657 | filebufused = 0; |
621 | playlist_end = false; | 658 | playlist_end = false; |
622 | buf_ridx = buf_widx = 0; | 659 | buf_ridx = buf_widx = 0; |
623 | cur_ti->filerem = cur_ti->filesize - newpos; | 660 | cur_ti->filerem = cur_ti->filesize - filepos; |
624 | cur_ti->filepos = newpos; | 661 | cur_ti->filepos = filepos; |
625 | cur_ti->start_pos = newpos; | 662 | cur_ti->start_pos = filepos; |
626 | ci.curpos = newpos; | 663 | ci.curpos = newpos; |
627 | cur_ti->available = 0; | 664 | cur_ti->available = 0; |
628 | lseek(current_fd, newpos, SEEK_SET); | 665 | lseek(current_fd, filepos, SEEK_SET); |
629 | |||
630 | mutex_unlock(&mutex_bufferfill); | ||
631 | 666 | ||
632 | queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0); | 667 | queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0); |
633 | 668 | mutex_unlock(&mutex_rebuffer); | |
634 | return true; | ||
635 | } | 669 | } |
636 | 670 | ||
637 | void codec_advance_buffer_callback(size_t amount) | 671 | void codec_advance_buffer_callback(size_t amount) |
@@ -653,8 +687,11 @@ void codec_advance_buffer_callback(size_t amount) | |||
653 | 687 | ||
654 | /* This should not happen */ | 688 | /* This should not happen */ |
655 | if (amount > cur_ti->available) { | 689 | if (amount > cur_ti->available) { |
656 | if (!rebuffer_and_seek(ci.curpos + amount)) | 690 | mutex_lock(&mutex_rebuffer); |
657 | ci.stop_codec = true; | 691 | queue_post(&audio_queue, |
692 | Q_AUDIO_REBUFFER_SEEK, (void *)(ci.curpos + amount)); | ||
693 | mutex_lock(&mutex_rebuffer); | ||
694 | mutex_unlock(&mutex_rebuffer); | ||
658 | return ; | 695 | return ; |
659 | } | 696 | } |
660 | 697 | ||
@@ -722,7 +759,10 @@ bool codec_seek_buffer_callback(size_t newpos) | |||
722 | 759 | ||
723 | /* We need to reload the song. */ | 760 | /* We need to reload the song. */ |
724 | if (newpos < cur_ti->start_pos) | 761 | if (newpos < cur_ti->start_pos) |
725 | return rebuffer_and_seek(newpos); | 762 | { |
763 | queue_post(&audio_queue, Q_AUDIO_REBUFFER_SEEK, (void *)newpos); | ||
764 | return true; | ||
765 | } | ||
726 | 766 | ||
727 | /* Seeking inside buffer space. */ | 767 | /* Seeking inside buffer space. */ |
728 | logf("seek: -%d", difference); | 768 | logf("seek: -%d", difference); |
@@ -878,8 +918,6 @@ static void audio_read_file(void) | |||
878 | return ; | 918 | return ; |
879 | } | 919 | } |
880 | 920 | ||
881 | mutex_lock(&mutex_bufferfill); | ||
882 | |||
883 | /* Throw away buffered codec. */ | 921 | /* Throw away buffered codec. */ |
884 | if (tracks[track_widx].start_pos != 0) | 922 | if (tracks[track_widx].start_pos != 0) |
885 | tracks[track_widx].codecsize = 0; | 923 | tracks[track_widx].codecsize = 0; |
@@ -931,8 +969,6 @@ static void audio_read_file(void) | |||
931 | } else { | 969 | } else { |
932 | logf("Partially buf:%d", tracks[track_widx].available); | 970 | logf("Partially buf:%d", tracks[track_widx].available); |
933 | } | 971 | } |
934 | |||
935 | mutex_unlock(&mutex_bufferfill); | ||
936 | } | 972 | } |
937 | 973 | ||
938 | static int get_codec_base_type(int type) | 974 | static int get_codec_base_type(int type) |
@@ -1032,7 +1068,7 @@ static bool loadcodec(bool start_play) | |||
1032 | prev_track = track_widx - 1; | 1068 | prev_track = track_widx - 1; |
1033 | if (prev_track < 0) | 1069 | if (prev_track < 0) |
1034 | prev_track = MAX_TRACK-1; | 1070 | prev_track = MAX_TRACK-1; |
1035 | if (track_count > 0 && | 1071 | if (have_tracks() && |
1036 | get_codec_base_type(tracks[track_widx].id3.codectype) == | 1072 | get_codec_base_type(tracks[track_widx].id3.codectype) == |
1037 | get_codec_base_type(tracks[prev_track].id3.codectype)) | 1073 | get_codec_base_type(tracks[prev_track].id3.codectype)) |
1038 | { | 1074 | { |
@@ -1059,7 +1095,6 @@ static bool loadcodec(bool start_play) | |||
1059 | return false; | 1095 | return false; |
1060 | } | 1096 | } |
1061 | 1097 | ||
1062 | mutex_lock(&mutex_bufferfill); | ||
1063 | i = 0; | 1098 | i = 0; |
1064 | while (i < size) { | 1099 | while (i < size) { |
1065 | copy_n = MIN(conf_filechunk, filebuflen - buf_widx); | 1100 | copy_n = MIN(conf_filechunk, filebuflen - buf_widx); |
@@ -1078,7 +1113,6 @@ static bool loadcodec(bool start_play) | |||
1078 | * queue during this loop */ | 1113 | * queue during this loop */ |
1079 | yield_codecs(); | 1114 | yield_codecs(); |
1080 | } | 1115 | } |
1081 | mutex_unlock(&mutex_bufferfill); | ||
1082 | 1116 | ||
1083 | close(fd); | 1117 | close(fd); |
1084 | logf("Done: %dB", i); | 1118 | logf("Done: %dB", i); |
@@ -1142,9 +1176,8 @@ static bool audio_load_track(int offset, bool start_play, int peek_offset) | |||
1142 | /* Stop buffer filling if there is no free track entries. | 1176 | /* Stop buffer filling if there is no free track entries. |
1143 | Don't fill up the last track entry (we wan't to store next track | 1177 | Don't fill up the last track entry (we wan't to store next track |
1144 | metadata there). */ | 1178 | metadata there). */ |
1145 | if (track_count >= MAX_TRACK - 1) { | 1179 | if (!have_free_tracks()) |
1146 | return false; | 1180 | return false; |
1147 | } | ||
1148 | 1181 | ||
1149 | if (current_fd >= 0) | 1182 | if (current_fd >= 0) |
1150 | { | 1183 | { |
@@ -1268,52 +1301,49 @@ static bool audio_load_track(int offset, bool start_play, int peek_offset) | |||
1268 | } | 1301 | } |
1269 | 1302 | ||
1270 | if (start_play) { | 1303 | if (start_play) { |
1271 | track_count++; | ||
1272 | codec_track_changed(); | 1304 | codec_track_changed(); |
1273 | } | 1305 | } |
1274 | 1306 | ||
1275 | audio_read_file(); | 1307 | audio_read_file(); |
1276 | 1308 | ||
1277 | if (!start_play) | ||
1278 | track_count++; | ||
1279 | |||
1280 | return true; | 1309 | return true; |
1281 | } | 1310 | } |
1282 | 1311 | ||
1283 | static void audio_clear_track_entries(bool buffered_only) | 1312 | static void audio_clear_track_entries(bool buffered_only) |
1284 | { | 1313 | { |
1285 | int cur_idx, event_count; | 1314 | int cur_idx; |
1286 | int i; | 1315 | int last_idx = 0; |
1287 | 1316 | ||
1317 | /* Loop over all tracks from write index to read index. */ | ||
1288 | cur_idx = track_widx; | 1318 | cur_idx = track_widx; |
1289 | event_count = 0; | 1319 | while (1) { |
1290 | for (i = 0; i < MAX_TRACK - track_count; i++) { | ||
1291 | if (++cur_idx >= MAX_TRACK) | 1320 | if (++cur_idx >= MAX_TRACK) |
1292 | cur_idx = 0; | 1321 | cur_idx = 0; |
1322 | if (cur_idx == track_ridx) | ||
1323 | break; | ||
1293 | 1324 | ||
1294 | if (tracks[cur_idx].event_sent) | 1325 | /* If the track is buffered, conditionally clear/notify, |
1295 | event_count++; | 1326 | * otherwise clear the track if that option is selected */ |
1296 | 1327 | if (tracks[cur_idx].event_sent) { | |
1297 | if (!track_unbuffer_callback) | 1328 | /* If there is an unbuffer callback, call it, otherwise, just |
1329 | * clear the track */ | ||
1330 | if (track_unbuffer_callback) | ||
1331 | track_unbuffer_callback(&tracks[last_idx].id3, false); | ||
1332 | |||
1333 | memset(&tracks[last_idx], 0, sizeof(struct track_info)); | ||
1334 | last_idx = cur_idx; | ||
1335 | } else if (!buffered_only) | ||
1298 | memset(&tracks[cur_idx], 0, sizeof(struct track_info)); | 1336 | memset(&tracks[cur_idx], 0, sizeof(struct track_info)); |
1299 | } | 1337 | } |
1300 | 1338 | ||
1301 | if (!track_unbuffer_callback) | 1339 | /* We clear the previous instance of a buffered track throughout |
1302 | return ; | 1340 | * the above loop to facilitate 'last' detection. Clear/notify |
1303 | 1341 | * the last track here */ | |
1304 | cur_idx = track_widx; | 1342 | if (last_idx) |
1305 | for (i = 0; i < MAX_TRACK - track_count; i++) { | 1343 | { |
1306 | if (++cur_idx >= MAX_TRACK) | 1344 | if (track_unbuffer_callback) |
1307 | cur_idx = 0; | 1345 | track_unbuffer_callback(&tracks[last_idx].id3, true); |
1308 | 1346 | memset(&tracks[last_idx], 0, sizeof(struct track_info)); | |
1309 | /* Send an event to notify that track has finished. */ | ||
1310 | if (tracks[cur_idx].event_sent) { | ||
1311 | event_count--; | ||
1312 | track_unbuffer_callback(&tracks[cur_idx].id3, event_count == 0); | ||
1313 | } | ||
1314 | |||
1315 | if (tracks[cur_idx].event_sent || !buffered_only) | ||
1316 | memset(&tracks[cur_idx], 0, sizeof(struct track_info)); | ||
1317 | } | 1347 | } |
1318 | } | 1348 | } |
1319 | 1349 | ||
@@ -1339,7 +1369,6 @@ static void audio_stop_playback(bool resume) | |||
1339 | current_fd = -1; | 1369 | current_fd = -1; |
1340 | } | 1370 | } |
1341 | 1371 | ||
1342 | track_count = 0; | ||
1343 | /* Mark all entries null. */ | 1372 | /* Mark all entries null. */ |
1344 | audio_clear_track_entries(false); | 1373 | audio_clear_track_entries(false); |
1345 | } | 1374 | } |
@@ -1353,14 +1382,12 @@ static void audio_play_start(size_t offset) | |||
1353 | current_fd = -1; | 1382 | current_fd = -1; |
1354 | } | 1383 | } |
1355 | 1384 | ||
1356 | memset(&tracks, 0, sizeof(struct track_info) * MAX_TRACK); | ||
1357 | sound_set_volume(global_settings.volume); | 1385 | sound_set_volume(global_settings.volume); |
1358 | track_count = 0; | 1386 | track_widx = track_ridx = 0; |
1359 | track_widx = 0; | 1387 | buf_ridx = buf_widx = 0; |
1360 | track_ridx = 0; | ||
1361 | buf_ridx = 0; | ||
1362 | buf_widx = 0; | ||
1363 | filebufused = 0; | 1388 | filebufused = 0; |
1389 | |||
1390 | memset(&tracks[0], 0, sizeof(struct track_info)); | ||
1364 | 1391 | ||
1365 | last_peek_offset = -1; | 1392 | last_peek_offset = -1; |
1366 | 1393 | ||
@@ -1373,81 +1400,69 @@ static void audio_play_start(size_t offset) | |||
1373 | /* Send callback events to notify about new tracks. */ | 1400 | /* Send callback events to notify about new tracks. */ |
1374 | static void generate_postbuffer_events(void) | 1401 | static void generate_postbuffer_events(void) |
1375 | { | 1402 | { |
1376 | int i; | 1403 | int cur_idx; |
1377 | int cur_ridx, event_count; | 1404 | int last_idx = 0; |
1378 | 1405 | ||
1379 | /* At first determine how many unsent events we have. */ | 1406 | if (have_tracks()) { |
1380 | cur_ridx = track_ridx; | 1407 | cur_idx = track_ridx; |
1381 | event_count = 0; | 1408 | while (1) { |
1382 | for (i = 0; i < track_count; i++) { | 1409 | if (!tracks[cur_idx].event_sent) { |
1383 | if (!tracks[cur_ridx].event_sent) | 1410 | if (last_idx) { |
1384 | event_count++; | 1411 | /* Mark the event 'sent' even if we don't really send one */ |
1385 | if (++cur_ridx >= MAX_TRACK) | 1412 | tracks[last_idx].event_sent = true; |
1386 | cur_ridx -= MAX_TRACK; | 1413 | if (track_buffer_callback) |
1387 | } | 1414 | track_buffer_callback(&tracks[last_idx].id3, false); |
1388 | 1415 | } | |
1389 | /* Now sent these events. */ | 1416 | last_idx = cur_idx; |
1390 | cur_ridx = track_ridx; | 1417 | } |
1391 | for (i = 0; i < track_count; i++) { | 1418 | if (cur_idx == track_widx) |
1392 | if (!tracks[cur_ridx].event_sent) { | 1419 | break; |
1393 | tracks[cur_ridx].event_sent = true; | 1420 | if (++cur_idx >= MAX_TRACK) |
1394 | event_count--; | 1421 | cur_idx -= MAX_TRACK; |
1395 | /* We still want to set event_sent flags even if not using | 1422 | } |
1396 | event callbacks. */ | 1423 | |
1424 | if (last_idx) { | ||
1425 | tracks[last_idx].event_sent = true; | ||
1397 | if (track_buffer_callback) | 1426 | if (track_buffer_callback) |
1398 | track_buffer_callback(&tracks[cur_ridx].id3, event_count == 0); | 1427 | track_buffer_callback(&tracks[last_idx].id3, true); |
1399 | } | 1428 | } |
1400 | if (++cur_ridx >= MAX_TRACK) | ||
1401 | cur_ridx -= MAX_TRACK; | ||
1402 | } | 1429 | } |
1403 | } | 1430 | } |
1404 | 1431 | ||
1405 | static void initialize_buffer_fill(bool start_play) | 1432 | static void initialize_buffer_fill(bool start_play) |
1406 | { | 1433 | { |
1407 | int cur_idx, i; | 1434 | if (start_play) { |
1408 | 1435 | filling_initial = true; | |
1409 | if (!filling_initial && !start_play) | 1436 | fill_bytesleft = filebuflen >> 2; |
1437 | } | ||
1438 | else if (!filling_initial) | ||
1410 | { | 1439 | { |
1411 | fill_bytesleft = filebuflen - filebufused; | 1440 | /* Recalculate remaining bytes to buffer, but always leave extra |
1412 | cur_ti->start_pos = ci.curpos; | 1441 | * data for the currently playing codec to seek back into */ |
1442 | size_t buf_bytesleft = filebuflen - filebufused; | ||
1443 | |||
1444 | if (buf_bytesleft > AUDIO_REBUFFER_GUESS_SIZE) | ||
1445 | fill_bytesleft = buf_bytesleft - AUDIO_REBUFFER_GUESS_SIZE; | ||
1446 | else | ||
1447 | fill_bytesleft = 0; | ||
1448 | |||
1449 | if (ci.curpos > AUDIO_REBUFFER_GUESS_SIZE) | ||
1450 | cur_ti->start_pos = ci.curpos - AUDIO_REBUFFER_GUESS_SIZE; | ||
1451 | else | ||
1452 | cur_ti->start_pos = 0; | ||
1413 | } | 1453 | } |
1414 | 1454 | ||
1415 | /* Initialize only once; do not truncate the tracks. */ | 1455 | /* Initialize only once; do not truncate the tracks. */ |
1416 | if (filling) | 1456 | if (filling) |
1417 | return ; | 1457 | return ; |
1418 | 1458 | ||
1419 | /* Save the current resume position once. */ | ||
1420 | playlist_update_resume_info(audio_current_track()); | ||
1421 | |||
1422 | pcmbuf_set_boost_mode(true); | 1459 | pcmbuf_set_boost_mode(true); |
1423 | 1460 | ||
1424 | if (!start_play) { | 1461 | /* Mark all buffered entries null (not metadata for next track). */ |
1425 | /* Calculate real track count after throwing away old tracks. */ | 1462 | audio_clear_track_entries(!start_play); |
1426 | cur_idx = track_ridx; | ||
1427 | for (i = 0; i < track_count; i++) { | ||
1428 | if (cur_idx == track_widx) | ||
1429 | break ; | ||
1430 | |||
1431 | if (++cur_idx >= MAX_TRACK) | ||
1432 | cur_idx = 0; | ||
1433 | } | ||
1434 | |||
1435 | track_count = i; | ||
1436 | if (tracks[track_widx].filesize == 0) { | ||
1437 | if (--track_widx < 0) | ||
1438 | track_widx = MAX_TRACK - 1; | ||
1439 | } else { | ||
1440 | track_count++; | ||
1441 | } | ||
1442 | 1463 | ||
1443 | /* Mark all buffered entries null (not metadata for next track). */ | 1464 | /* Save the current resume position once. */ |
1444 | audio_clear_track_entries(true); | 1465 | playlist_update_resume_info(audio_current_track()); |
1445 | } | ||
1446 | else | ||
1447 | { | ||
1448 | filling_initial = true; | ||
1449 | fill_bytesleft = filebuflen >> 2; | ||
1450 | } | ||
1451 | 1466 | ||
1452 | filling = true; | 1467 | filling = true; |
1453 | 1468 | ||
@@ -1459,9 +1474,7 @@ static void audio_fill_file_buffer(bool start_play, size_t offset) | |||
1459 | if (ci.stop_codec || ci.reload_codec || playlist_end) | 1474 | if (ci.stop_codec || ci.reload_codec || playlist_end) |
1460 | return; | 1475 | return; |
1461 | 1476 | ||
1462 | mutex_lock(&mutex_bufferfill); | ||
1463 | initialize_buffer_fill(start_play); | 1477 | initialize_buffer_fill(start_play); |
1464 | mutex_unlock(&mutex_bufferfill); | ||
1465 | 1478 | ||
1466 | /* If we have a partially buffered track, continue loading, otherwise | 1479 | /* If we have a partially buffered track, continue loading, otherwise |
1467 | * load a new track */ | 1480 | * load a new track */ |
@@ -1602,7 +1615,7 @@ static int skip_previous_track(bool inside_codec_thread) | |||
1602 | track_ridx += MAX_TRACK; | 1615 | track_ridx += MAX_TRACK; |
1603 | 1616 | ||
1604 | if (tracks[track_ridx].filesize == 0 || | 1617 | if (tracks[track_ridx].filesize == 0 || |
1605 | filebufused+ci.curpos + tracks[track_ridx].filesize > filebuflen) | 1618 | filebufused + ci.curpos + tracks[track_ridx].filesize > filebuflen) |
1606 | { | 1619 | { |
1607 | logf("Loading from disk..."); | 1620 | logf("Loading from disk..."); |
1608 | ci.reload_codec = true; | 1621 | ci.reload_codec = true; |
@@ -1729,24 +1742,27 @@ bool codec_request_next_track_callback(void) | |||
1729 | /* Invalidates all but currently playing track. */ | 1742 | /* Invalidates all but currently playing track. */ |
1730 | void audio_invalidate_tracks(void) | 1743 | void audio_invalidate_tracks(void) |
1731 | { | 1744 | { |
1732 | if (track_count == 0) { | 1745 | if (have_tracks()) { |
1733 | /* This call doesn't seem necessary anymore. Uncomment it | 1746 | playlist_end = false; |
1734 | if things break */ | 1747 | last_peek_offset = 0; |
1735 | /* queue_post(&audio_queue, Q_AUDIO_PLAY, 0); */ | ||
1736 | return ; | ||
1737 | } | ||
1738 | 1748 | ||
1739 | playlist_end = false; | 1749 | track_widx = track_ridx; |
1740 | track_count = 1; | 1750 | |
1741 | last_peek_offset = 0; | 1751 | audio_clear_track_entries(false); |
1742 | track_widx = track_ridx; | 1752 | |
1743 | /* Mark all other entries null (also buffered wrong metadata). */ | 1753 | /* If the current track is fully buffered, advance the write pointer */ |
1744 | audio_clear_track_entries(false); | 1754 | if (tracks[track_ridx].filerem == 0) |
1745 | filebufused = cur_ti->available; | 1755 | if (++track_widx >= MAX_TRACK) |
1746 | buf_widx = buf_ridx + cur_ti->available; | 1756 | track_widx -= MAX_TRACK; |
1747 | if (buf_widx >= filebuflen) | 1757 | |
1748 | buf_widx -= filebuflen; | 1758 | /* Mark all other entries null (also buffered wrong metadata). */ |
1749 | read_next_metadata(); | 1759 | filebufused = cur_ti->available; |
1760 | buf_widx = buf_ridx + cur_ti->available; | ||
1761 | if (buf_widx >= filebuflen) | ||
1762 | buf_widx -= filebuflen; | ||
1763 | |||
1764 | read_next_metadata(); | ||
1765 | } | ||
1750 | } | 1766 | } |
1751 | 1767 | ||
1752 | static void initiate_track_change(long peek_index) | 1768 | static void initiate_track_change(long peek_index) |
@@ -1816,7 +1832,6 @@ void audio_thread(void) | |||
1816 | case Q_AUDIO_PLAY: | 1832 | case Q_AUDIO_PLAY: |
1817 | /* Don't start playing immediately if user is skipping tracks | 1833 | /* Don't start playing immediately if user is skipping tracks |
1818 | * fast to prevent UI lag. */ | 1834 | * fast to prevent UI lag. */ |
1819 | track_count = 0; | ||
1820 | last_peek_offset = 0; | 1835 | last_peek_offset = 0; |
1821 | track_changed = true; | 1836 | track_changed = true; |
1822 | playlist_end = false; | 1837 | playlist_end = false; |
@@ -1881,6 +1896,11 @@ void audio_thread(void) | |||
1881 | ci.seek_time = (long)ev.data+1; | 1896 | ci.seek_time = (long)ev.data+1; |
1882 | break ; | 1897 | break ; |
1883 | 1898 | ||
1899 | case Q_AUDIO_REBUFFER_SEEK: | ||
1900 | logf("Re-buffering song"); | ||
1901 | rebuffer_and_seek((size_t)ev.data); | ||
1902 | break; | ||
1903 | |||
1884 | case Q_AUDIO_DIR_SKIP: | 1904 | case Q_AUDIO_DIR_SKIP: |
1885 | logf("audio_dir_skip"); | 1905 | logf("audio_dir_skip"); |
1886 | playlist_end = false; | 1906 | playlist_end = false; |
@@ -2095,7 +2115,7 @@ struct mp3entry* audio_current_track(void) | |||
2095 | const char *p; | 2115 | const char *p; |
2096 | static struct mp3entry temp_id3; | 2116 | static struct mp3entry temp_id3; |
2097 | 2117 | ||
2098 | if (track_count > 0 && cur_ti->taginfo_ready) | 2118 | if (have_tracks() && cur_ti->taginfo_ready) |
2099 | return (struct mp3entry *)&cur_ti->id3; | 2119 | return (struct mp3entry *)&cur_ti->id3; |
2100 | 2120 | ||
2101 | memset(&temp_id3, 0, sizeof(struct mp3entry)); | 2121 | memset(&temp_id3, 0, sizeof(struct mp3entry)); |
@@ -2125,7 +2145,7 @@ struct mp3entry* audio_next_track(void) | |||
2125 | { | 2145 | { |
2126 | int next_idx = track_ridx + 1; | 2146 | int next_idx = track_ridx + 1; |
2127 | 2147 | ||
2128 | if (track_count == 0) | 2148 | if (!have_tracks()) |
2129 | return NULL; | 2149 | return NULL; |
2130 | 2150 | ||
2131 | if (next_idx >= MAX_TRACK) | 2151 | if (next_idx >= MAX_TRACK) |
@@ -2198,10 +2218,6 @@ void audio_next(void) | |||
2198 | playlist_next(1); | 2218 | playlist_next(1); |
2199 | track_changed = true; | 2219 | track_changed = true; |
2200 | 2220 | ||
2201 | /* Force WPS to update even if audio thread is blocked spinning. */ | ||
2202 | if (mutex_bufferfill.locked) | ||
2203 | cur_ti->taginfo_ready = false; | ||
2204 | |||
2205 | queue_post(&audio_queue, Q_AUDIO_SKIP, (void *)1); | 2221 | queue_post(&audio_queue, Q_AUDIO_SKIP, (void *)1); |
2206 | } | 2222 | } |
2207 | 2223 | ||
@@ -2216,10 +2232,6 @@ void audio_prev(void) | |||
2216 | playlist_next(-1); | 2232 | playlist_next(-1); |
2217 | track_changed = true; | 2233 | track_changed = true; |
2218 | 2234 | ||
2219 | /* Force WPS to update even if audio thread is blocked spinning. */ | ||
2220 | if (mutex_bufferfill.locked) | ||
2221 | cur_ti->taginfo_ready = false; | ||
2222 | |||
2223 | queue_post(&audio_queue, Q_AUDIO_SKIP, (void *)-1); | 2235 | queue_post(&audio_queue, Q_AUDIO_SKIP, (void *)-1); |
2224 | } | 2236 | } |
2225 | 2237 | ||
@@ -2525,9 +2537,9 @@ static void playback_init(void) | |||
2525 | id3_voice.length = 1000000L; | 2537 | id3_voice.length = 1000000L; |
2526 | 2538 | ||
2527 | create_thread(codec_thread, codec_stack, sizeof(codec_stack), | 2539 | create_thread(codec_thread, codec_stack, sizeof(codec_stack), |
2528 | codec_thread_name); | 2540 | codec_thread_name); |
2529 | create_thread(voice_codec_thread, voice_codec_stack, | 2541 | create_thread(voice_codec_thread, voice_codec_stack, |
2530 | sizeof(voice_codec_stack), voice_codec_thread_name); | 2542 | sizeof(voice_codec_stack), voice_codec_thread_name); |
2531 | 2543 | ||
2532 | while (1) | 2544 | while (1) |
2533 | { | 2545 | { |
@@ -2573,8 +2585,8 @@ void audio_preinit(void) | |||
2573 | /* Just to prevent cur_ti never be anything random. */ | 2585 | /* Just to prevent cur_ti never be anything random. */ |
2574 | cur_ti = &tracks[0]; | 2586 | cur_ti = &tracks[0]; |
2575 | 2587 | ||
2576 | mutex_init(&mutex_bufferfill); | ||
2577 | mutex_init(&mutex_codecthread); | 2588 | mutex_init(&mutex_codecthread); |
2589 | mutex_init(&mutex_rebuffer); | ||
2578 | 2590 | ||
2579 | queue_init(&audio_queue); | 2591 | queue_init(&audio_queue); |
2580 | queue_init(&codec_queue); | 2592 | queue_init(&codec_queue); |