diff options
-rw-r--r-- | apps/gui/gwps-common.c | 6 | ||||
-rw-r--r-- | apps/playback.c | 194 | ||||
-rw-r--r-- | firmware/export/audio.h | 1 |
3 files changed, 98 insertions, 103 deletions
diff --git a/apps/gui/gwps-common.c b/apps/gui/gwps-common.c index 231aa28162..41e20ecadd 100644 --- a/apps/gui/gwps-common.c +++ b/apps/gui/gwps-common.c | |||
@@ -2347,7 +2347,11 @@ bool ffwd_rew(int button) | |||
2347 | wps_state.id3 && wps_state.id3->length ) | 2347 | wps_state.id3 && wps_state.id3->length ) |
2348 | { | 2348 | { |
2349 | if (!wps_state.paused) | 2349 | if (!wps_state.paused) |
2350 | #if (CONFIG_CODEC == SWCODEC) | ||
2351 | audio_pre_ff_rewind(); | ||
2352 | #else | ||
2350 | audio_pause(); | 2353 | audio_pause(); |
2354 | #endif | ||
2351 | #if CONFIG_KEYPAD == PLAYER_PAD | 2355 | #if CONFIG_KEYPAD == PLAYER_PAD |
2352 | FOR_NB_SCREENS(i) | 2356 | FOR_NB_SCREENS(i) |
2353 | gui_wps[i].display->stop_scroll(); | 2357 | gui_wps[i].display->stop_scroll(); |
@@ -2399,8 +2403,10 @@ bool ffwd_rew(int button) | |||
2399 | ff_rewind_count = 0; | 2403 | ff_rewind_count = 0; |
2400 | wps_state.ff_rewind = false; | 2404 | wps_state.ff_rewind = false; |
2401 | status_set_ffmode(0); | 2405 | status_set_ffmode(0); |
2406 | #if (CONFIG_CODEC != SWCODEC) | ||
2402 | if (!wps_state.paused) | 2407 | if (!wps_state.paused) |
2403 | audio_resume(); | 2408 | audio_resume(); |
2409 | #endif | ||
2404 | #ifdef HAVE_LCD_CHARCELLS | 2410 | #ifdef HAVE_LCD_CHARCELLS |
2405 | gui_wps_display(); | 2411 | gui_wps_display(); |
2406 | #endif | 2412 | #endif |
diff --git a/apps/playback.c b/apps/playback.c index aa48dd9bae..6baf683342 100644 --- a/apps/playback.c +++ b/apps/playback.c | |||
@@ -70,7 +70,7 @@ | |||
70 | static volatile bool audio_codec_loaded; | 70 | static volatile bool audio_codec_loaded; |
71 | static volatile bool voice_codec_loaded; | 71 | static volatile bool voice_codec_loaded; |
72 | static volatile bool playing; | 72 | static volatile bool playing; |
73 | static volatile bool seeking; | 73 | static volatile bool paused; |
74 | 74 | ||
75 | #define CODEC_VORBIS "/.rockbox/codecs/vorbis.codec" | 75 | #define CODEC_VORBIS "/.rockbox/codecs/vorbis.codec" |
76 | #define CODEC_MPA_L3 "/.rockbox/codecs/mpa.codec" | 76 | #define CODEC_MPA_L3 "/.rockbox/codecs/mpa.codec" |
@@ -104,6 +104,7 @@ enum { | |||
104 | Q_AUDIO_DIR_NEXT, | 104 | Q_AUDIO_DIR_NEXT, |
105 | Q_AUDIO_DIR_PREV, | 105 | Q_AUDIO_DIR_PREV, |
106 | Q_AUDIO_POSTINIT, | 106 | Q_AUDIO_POSTINIT, |
107 | Q_AUDIO_CHECK_BUFFER, | ||
107 | 108 | ||
108 | Q_CODEC_LOAD, | 109 | Q_CODEC_LOAD, |
109 | Q_CODEC_LOAD_DISK, | 110 | Q_CODEC_LOAD_DISK, |
@@ -454,6 +455,9 @@ static void advance_buffer_counters(size_t amount) { | |||
454 | ci.curpos += amount; | 455 | ci.curpos += amount; |
455 | cur_ti->available -= amount; | 456 | cur_ti->available -= amount; |
456 | filebufused -= amount; | 457 | filebufused -= amount; |
458 | |||
459 | if (!pcmbuf_is_lowdata() && !mutex_bufferfill.locked) | ||
460 | queue_post(&audio_queue, Q_AUDIO_CHECK_BUFFER, 0); | ||
457 | } | 461 | } |
458 | 462 | ||
459 | /* copy up-to size bytes into ptr and return the actual size copied */ | 463 | /* copy up-to size bytes into ptr and return the actual size copied */ |
@@ -476,6 +480,7 @@ size_t codec_filebuf_callback(void *ptr, size_t size) | |||
476 | 480 | ||
477 | /* Let the disk buffer catch fill until enough data is available */ | 481 | /* Let the disk buffer catch fill until enough data is available */ |
478 | while (copy_n > cur_ti->available) { | 482 | while (copy_n > cur_ti->available) { |
483 | queue_post(&audio_queue, Q_AUDIO_CHECK_BUFFER, 0); | ||
479 | yield(); | 484 | yield(); |
480 | if (ci.stop_codec || ci.reload_codec) | 485 | if (ci.stop_codec || ci.reload_codec) |
481 | return 0; | 486 | return 0; |
@@ -550,7 +555,7 @@ void* codec_request_buffer_callback(size_t *realsize, size_t reqsize) | |||
550 | return voice_request_data(realsize, reqsize); | 555 | return voice_request_data(realsize, reqsize); |
551 | } | 556 | } |
552 | 557 | ||
553 | if (ci.stop_codec || !playing) { | 558 | if (!playing) { |
554 | *realsize = 0; | 559 | *realsize = 0; |
555 | return NULL; | 560 | return NULL; |
556 | } | 561 | } |
@@ -562,6 +567,7 @@ void* codec_request_buffer_callback(size_t *realsize, size_t reqsize) | |||
562 | } | 567 | } |
563 | 568 | ||
564 | while (copy_n > cur_ti->available) { | 569 | while (copy_n > cur_ti->available) { |
570 | queue_post(&audio_queue, Q_AUDIO_CHECK_BUFFER, 0); | ||
565 | yield(); | 571 | yield(); |
566 | if (ci.stop_codec || ci.reload_codec) { | 572 | if (ci.stop_codec || ci.reload_codec) { |
567 | *realsize = 0; | 573 | *realsize = 0; |
@@ -618,11 +624,7 @@ static bool rebuffer_and_seek(size_t newpos) | |||
618 | 624 | ||
619 | mutex_unlock(&mutex_bufferfill); | 625 | mutex_unlock(&mutex_bufferfill); |
620 | 626 | ||
621 | while (cur_ti->available == 0 && cur_ti->filerem > 0) { | 627 | queue_post(&audio_queue, Q_AUDIO_CHECK_BUFFER, 0); |
622 | sleep(1); | ||
623 | if (ci.stop_codec || ci.reload_codec || !queue_empty(&audio_queue)) | ||
624 | return false; | ||
625 | } | ||
626 | 628 | ||
627 | return true; | 629 | return true; |
628 | } | 630 | } |
@@ -644,6 +646,7 @@ void codec_advance_buffer_callback(size_t amount) | |||
644 | while (amount > cur_ti->available && filling) | 646 | while (amount > cur_ti->available && filling) |
645 | sleep(1); | 647 | sleep(1); |
646 | 648 | ||
649 | /* This should not happen */ | ||
647 | if (amount > cur_ti->available) { | 650 | if (amount > cur_ti->available) { |
648 | if (!rebuffer_and_seek(ci.curpos + amount)) | 651 | if (!rebuffer_and_seek(ci.curpos + amount)) |
649 | ci.stop_codec = true; | 652 | ci.stop_codec = true; |
@@ -682,9 +685,11 @@ void codec_seek_complete_callback(void) | |||
682 | if (pcm_is_paused()) { | 685 | if (pcm_is_paused()) { |
683 | /* If this is not a seamless seek, clear the buffer */ | 686 | /* If this is not a seamless seek, clear the buffer */ |
684 | pcmbuf_play_stop(); | 687 | pcmbuf_play_stop(); |
688 | /* If playback was not 'deliberately' paused, unpause now */ | ||
689 | if (!paused) | ||
690 | pcmbuf_pause(false); | ||
685 | } | 691 | } |
686 | ci.seek_time = 0; | 692 | ci.seek_time = 0; |
687 | seeking = false; | ||
688 | } | 693 | } |
689 | 694 | ||
690 | bool codec_seek_buffer_callback(size_t newpos) | 695 | bool codec_seek_buffer_callback(size_t newpos) |
@@ -852,7 +857,6 @@ void strip_id3v1_tag(void) | |||
852 | 857 | ||
853 | static void audio_fill_file_buffer(void) | 858 | static void audio_fill_file_buffer(void) |
854 | { | 859 | { |
855 | unsigned long i; | ||
856 | size_t size; | 860 | size_t size; |
857 | size_t copy_n; | 861 | size_t copy_n; |
858 | int rc; | 862 | int rc; |
@@ -865,9 +869,8 @@ static void audio_fill_file_buffer(void) | |||
865 | tracks[track_widx].codecsize = 0; | 869 | tracks[track_widx].codecsize = 0; |
866 | 870 | ||
867 | mutex_lock(&mutex_bufferfill); | 871 | mutex_lock(&mutex_bufferfill); |
868 | i = 0; | ||
869 | size = MIN(tracks[track_widx].filerem, AUDIO_FILL_CYCLE); | 872 | size = MIN(tracks[track_widx].filerem, AUDIO_FILL_CYCLE); |
870 | while (i < size) { | 873 | while (size > 0) { |
871 | /* Give codecs some processing time. */ | 874 | /* Give codecs some processing time. */ |
872 | yield_codecs(); | 875 | yield_codecs(); |
873 | 876 | ||
@@ -884,12 +887,16 @@ static void audio_fill_file_buffer(void) | |||
884 | buf_widx += rc; | 887 | buf_widx += rc; |
885 | if (buf_widx >= filebuflen) | 888 | if (buf_widx >= filebuflen) |
886 | buf_widx -= filebuflen; | 889 | buf_widx -= filebuflen; |
887 | i += rc; | ||
888 | tracks[track_widx].available += rc; | 890 | tracks[track_widx].available += rc; |
889 | tracks[track_widx].filerem -= rc; | 891 | tracks[track_widx].filerem -= rc; |
890 | tracks[track_widx].filepos += rc; | 892 | tracks[track_widx].filepos += rc; |
891 | filebufused += rc; | 893 | filebufused += rc; |
892 | fill_bytesleft -= rc; | 894 | fill_bytesleft -= rc; |
895 | if ((unsigned)rc > size) { | ||
896 | rc = size; | ||
897 | logf("audio_fill_file_buffer read past end of file\n"); | ||
898 | } | ||
899 | size -= rc; | ||
893 | } | 900 | } |
894 | 901 | ||
895 | if (tracks[track_widx].filerem == 0) { | 902 | if (tracks[track_widx].filerem == 0) { |
@@ -1092,15 +1099,12 @@ static bool audio_load_track(int offset, bool start_play, int peek_offset) | |||
1092 | char *trackname; | 1099 | char *trackname; |
1093 | int fd = -1; | 1100 | int fd = -1; |
1094 | off_t size; | 1101 | off_t size; |
1095 | int rc, i; | ||
1096 | int copy_n; | ||
1097 | char msgbuf[80]; | 1102 | char msgbuf[80]; |
1098 | 1103 | ||
1099 | /* Stop buffer filling if there is no free track entries. | 1104 | /* Stop buffer filling if there is no free track entries. |
1100 | Don't fill up the last track entry (we wan't to store next track | 1105 | Don't fill up the last track entry (we wan't to store next track |
1101 | metadata there). */ | 1106 | metadata there). */ |
1102 | if (track_count >= MAX_TRACK - 1) { | 1107 | if (track_count >= MAX_TRACK - 1) { |
1103 | fill_bytesleft = 0; | ||
1104 | return false; | 1108 | return false; |
1105 | } | 1109 | } |
1106 | 1110 | ||
@@ -1196,7 +1200,6 @@ static bool audio_load_track(int offset, bool start_play, int peek_offset) | |||
1196 | set_filebuf_watermark(buffer_margin); | 1200 | set_filebuf_watermark(buffer_margin); |
1197 | tracks[track_widx].id3.elapsed = 0; | 1201 | tracks[track_widx].id3.elapsed = 0; |
1198 | 1202 | ||
1199 | /* Starting playback from an offset is only support in MPA at the moment */ | ||
1200 | if (offset > 0) { | 1203 | if (offset > 0) { |
1201 | switch (tracks[track_widx].id3.codectype) { | 1204 | switch (tracks[track_widx].id3.codectype) { |
1202 | case AFMT_MPA_L2: | 1205 | case AFMT_MPA_L2: |
@@ -1231,64 +1234,27 @@ static bool audio_load_track(int offset, bool start_play, int peek_offset) | |||
1231 | codec_track_changed(); | 1234 | codec_track_changed(); |
1232 | } | 1235 | } |
1233 | 1236 | ||
1234 | /* Do some initial file buffering. */ | 1237 | if (current_fd >= 0) { |
1235 | mutex_lock(&mutex_bufferfill); | 1238 | close(current_fd); |
1236 | i = tracks[track_widx].start_pos; | ||
1237 | size = MIN(size, AUDIO_FILL_CYCLE); | ||
1238 | while (i < size) { | ||
1239 | /* Give codecs some processing time to prevent glitches. */ | ||
1240 | yield_codecs(); | ||
1241 | |||
1242 | if (fill_bytesleft == 0) | ||
1243 | break ; | ||
1244 | |||
1245 | copy_n = MIN(conf_filechunk, filebuflen - buf_widx); | ||
1246 | copy_n = MIN(size - i, copy_n); | ||
1247 | copy_n = MIN((int)fill_bytesleft, copy_n); | ||
1248 | rc = read(fd, &filebuf[buf_widx], copy_n); | ||
1249 | if (rc < copy_n) { | ||
1250 | logf("File error!"); | ||
1251 | tracks[track_widx].filesize = 0; | ||
1252 | tracks[track_widx].filerem = 0; | ||
1253 | close(fd); | ||
1254 | mutex_unlock(&mutex_bufferfill); | ||
1255 | return false; | ||
1256 | } | ||
1257 | buf_widx += rc; | ||
1258 | if (buf_widx >= filebuflen) | ||
1259 | buf_widx -= filebuflen; | ||
1260 | i += rc; | ||
1261 | tracks[track_widx].available += rc; | ||
1262 | tracks[track_widx].filerem -= rc; | ||
1263 | filebufused += rc; | ||
1264 | fill_bytesleft -= rc; | ||
1265 | } | 1239 | } |
1266 | mutex_unlock(&mutex_bufferfill); | 1240 | current_fd = fd; |
1241 | |||
1242 | audio_fill_file_buffer(); | ||
1267 | 1243 | ||
1268 | if (!start_play) | 1244 | if (!start_play) |
1269 | track_count++; | 1245 | track_count++; |
1270 | 1246 | ||
1271 | tracks[track_widx].filepos = i; | ||
1272 | |||
1273 | if (current_fd >= 0) { | ||
1274 | close(current_fd); | ||
1275 | current_fd = -1; | ||
1276 | } | ||
1277 | |||
1278 | /* Leave the file handle open for faster buffer refill. */ | 1247 | /* Leave the file handle open for faster buffer refill. */ |
1279 | if (tracks[track_widx].filerem != 0) { | 1248 | if (tracks[track_widx].filerem != 0) { |
1280 | current_fd = fd; | ||
1281 | logf("Partially buf:%d", tracks[track_widx].available); | 1249 | logf("Partially buf:%d", tracks[track_widx].available); |
1282 | } else { | 1250 | } else { |
1283 | logf("Completely buf."); | 1251 | logf("Completely buf."); |
1284 | close(fd); | 1252 | close(fd); |
1285 | 1253 | ||
1286 | strip_id3v1_tag(); | ||
1287 | |||
1288 | if (++track_widx >= MAX_TRACK) { | 1254 | if (++track_widx >= MAX_TRACK) { |
1289 | track_widx = 0; | 1255 | track_widx = 0; |
1290 | } | 1256 | } |
1291 | tracks[track_widx].filerem = 0; | 1257 | tracks[track_widx].filesize = 0; |
1292 | } | 1258 | } |
1293 | 1259 | ||
1294 | return true; | 1260 | return true; |
@@ -1337,7 +1303,7 @@ static void stop_codec_flush(void) | |||
1337 | pcmbuf_pause(true); | 1303 | pcmbuf_pause(true); |
1338 | while (audio_codec_loaded) | 1304 | while (audio_codec_loaded) |
1339 | yield(); | 1305 | yield(); |
1340 | pcmbuf_pause(false); | 1306 | pcmbuf_pause(paused); |
1341 | } | 1307 | } |
1342 | 1308 | ||
1343 | static void audio_stop_playback(bool resume) | 1309 | static void audio_stop_playback(bool resume) |
@@ -1348,6 +1314,7 @@ static void audio_stop_playback(bool resume) | |||
1348 | playing = false; | 1314 | playing = false; |
1349 | filling = false; | 1315 | filling = false; |
1350 | stop_codec_flush(); | 1316 | stop_codec_flush(); |
1317 | paused = false; | ||
1351 | if (current_fd >= 0) { | 1318 | if (current_fd >= 0) { |
1352 | close(current_fd); | 1319 | close(current_fd); |
1353 | current_fd = -1; | 1320 | current_fd = -1; |
@@ -1467,10 +1434,10 @@ static void initialize_buffer_fill(void) | |||
1467 | static void audio_check_buffer(void) | 1434 | static void audio_check_buffer(void) |
1468 | { | 1435 | { |
1469 | /* Start buffer filling as necessary. */ | 1436 | /* Start buffer filling as necessary. */ |
1470 | if ((!conf_watermark || filebufused > conf_watermark | 1437 | if ((!conf_watermark || filebufused > conf_watermark || !playing |
1471 | || !queue_empty(&audio_queue) || !playing || ci.stop_codec | 1438 | || ci.stop_codec || ci.reload_codec || playlist_end) |
1472 | || ci.reload_codec || playlist_end) && !filling) | 1439 | && !filling) |
1473 | return ; | 1440 | return; |
1474 | 1441 | ||
1475 | mutex_lock(&mutex_bufferfill); | 1442 | mutex_lock(&mutex_bufferfill); |
1476 | initialize_buffer_fill(); | 1443 | initialize_buffer_fill(); |
@@ -1485,23 +1452,33 @@ static void audio_check_buffer(void) | |||
1485 | fill_bytesleft = 0; | 1452 | fill_bytesleft = 0; |
1486 | } | 1453 | } |
1487 | 1454 | ||
1488 | /* Try to load remainings of the file. */ | 1455 | /* If the current track has been started */ |
1489 | if (tracks[track_widx].filerem > 0) | 1456 | if (tracks[track_widx].filesize > 0) |
1490 | audio_fill_file_buffer(); | 1457 | { |
1491 | 1458 | /* Try to load remainings of the file. */ | |
1492 | /* Increase track write index as necessary. */ | 1459 | if (tracks[track_widx].filerem > 0) |
1493 | if (tracks[track_widx].filerem == 0 && tracks[track_widx].filesize != 0) { | 1460 | { |
1494 | if (++track_widx == MAX_TRACK) | 1461 | audio_fill_file_buffer(); |
1495 | track_widx = 0; | 1462 | } |
1463 | if (tracks[track_widx].filerem == 0) { | ||
1464 | if (++track_widx == MAX_TRACK) | ||
1465 | track_widx = 0; | ||
1466 | tracks[track_widx].filesize = 0; | ||
1467 | } | ||
1468 | else | ||
1469 | { | ||
1470 | /* Done filling, couldn't read that whole file */ | ||
1471 | fill_bytesleft = 0; | ||
1472 | } | ||
1496 | } | 1473 | } |
1497 | 1474 | /* Otherwise, load a new track */ | |
1498 | /* Load new files to fill the entire buffer. */ | 1475 | else if (audio_load_track(0, false, last_peek_offset + 1)) |
1499 | if (audio_load_track(0, false, last_peek_offset + 1)) { | 1476 | { |
1500 | if (conf_bufferlimit) | 1477 | if (conf_bufferlimit) |
1501 | fill_bytesleft = 0; | 1478 | fill_bytesleft = 0; |
1502 | } | 1479 | } else { |
1503 | else if (tracks[track_widx].filerem == 0) | ||
1504 | fill_bytesleft = 0; | 1480 | fill_bytesleft = 0; |
1481 | } | ||
1505 | 1482 | ||
1506 | if (fill_bytesleft <= 0) | 1483 | if (fill_bytesleft <= 0) |
1507 | { | 1484 | { |
@@ -1581,9 +1558,12 @@ static int skip_next_track(bool inside_codec_thread) | |||
1581 | track_ridx = 0; | 1558 | track_ridx = 0; |
1582 | 1559 | ||
1583 | /* Wait for new track data. */ | 1560 | /* Wait for new track data. */ |
1584 | while (tracks[track_ridx].filesize == 0 && filling | 1561 | while (tracks[track_ridx].filesize == 0 && filling) |
1585 | && !ci.stop_codec) | 1562 | { |
1586 | yield(); | 1563 | yield(); |
1564 | if (ci.stop_codec) | ||
1565 | return SKIP_FAIL; | ||
1566 | } | ||
1587 | 1567 | ||
1588 | if (tracks[track_ridx].filesize <= 0) | 1568 | if (tracks[track_ridx].filesize <= 0) |
1589 | { | 1569 | { |
@@ -1604,18 +1584,21 @@ static int skip_next_track(bool inside_codec_thread) | |||
1604 | return SKIP_OK_DISK; | 1584 | return SKIP_OK_DISK; |
1605 | } | 1585 | } |
1606 | 1586 | ||
1587 | /* Wind the buffer forward to the end of the current track */ | ||
1607 | buf_ridx += cur_ti->available; | 1588 | buf_ridx += cur_ti->available; |
1608 | filebufused -= cur_ti->available; | 1589 | filebufused -= cur_ti->available; |
1609 | 1590 | ||
1591 | /* Move to the new track */ | ||
1610 | cur_ti = &tracks[track_ridx]; | 1592 | cur_ti = &tracks[track_ridx]; |
1593 | /* Wind past the new track's codec */ | ||
1611 | buf_ridx += cur_ti->codecsize; | 1594 | buf_ridx += cur_ti->codecsize; |
1612 | filebufused -= cur_ti->codecsize; | 1595 | filebufused -= cur_ti->codecsize; |
1596 | |||
1597 | /* Check and handle buffer wrapping */ | ||
1613 | if (buf_ridx >= filebuflen) | 1598 | if (buf_ridx >= filebuflen) |
1614 | buf_ridx -= filebuflen; | 1599 | buf_ridx -= filebuflen; |
1615 | audio_update_trackinfo(); | ||
1616 | 1600 | ||
1617 | if (!filling) | 1601 | audio_update_trackinfo(); |
1618 | pcmbuf_set_boost_mode(false); | ||
1619 | 1602 | ||
1620 | return SKIP_OK_RAM; | 1603 | return SKIP_OK_RAM; |
1621 | } | 1604 | } |
@@ -1628,8 +1611,8 @@ static int skip_previous_track(bool inside_codec_thread) | |||
1628 | track_ridx += MAX_TRACK; | 1611 | track_ridx += MAX_TRACK; |
1629 | 1612 | ||
1630 | if (tracks[track_ridx].filesize == 0 || | 1613 | if (tracks[track_ridx].filesize == 0 || |
1631 | filebufused+ci.curpos+tracks[track_ridx].filesize | 1614 | filebufused+ci.curpos + tracks[track_ridx].filesize > filebuflen) |
1632 | /*+ (off_t)tracks[track_ridx].codecsize*/ > filebuflen) { | 1615 | { |
1633 | logf("Loading from disk..."); | 1616 | logf("Loading from disk..."); |
1634 | ci.reload_codec = true; | 1617 | ci.reload_codec = true; |
1635 | /* Stop playback. */ | 1618 | /* Stop playback. */ |
@@ -1645,16 +1628,23 @@ static int skip_previous_track(bool inside_codec_thread) | |||
1645 | return SKIP_OK_DISK; | 1628 | return SKIP_OK_DISK; |
1646 | } | 1629 | } |
1647 | 1630 | ||
1631 | /* Rewind the buffer to the beginning of the playing track */ | ||
1648 | buf_ridx -= ci.curpos + cur_ti->codecsize; | 1632 | buf_ridx -= ci.curpos + cur_ti->codecsize; |
1649 | filebufused += ci.curpos + cur_ti->codecsize; | 1633 | filebufused += ci.curpos + cur_ti->codecsize; |
1634 | /* Rewind the track to its beginning */ | ||
1650 | cur_ti->available = cur_ti->filesize - cur_ti->filerem; | 1635 | cur_ti->available = cur_ti->filesize - cur_ti->filerem; |
1651 | 1636 | ||
1637 | /* Move to the new track */ | ||
1652 | cur_ti = &tracks[track_ridx]; | 1638 | cur_ti = &tracks[track_ridx]; |
1639 | /* Rewind the buffer to the beginning of the new track */ | ||
1640 | buf_ridx -= cur_ti->filesize; | ||
1653 | filebufused += cur_ti->filesize; | 1641 | filebufused += cur_ti->filesize; |
1642 | /* Reset to the beginning of the new track */ | ||
1654 | cur_ti->available = cur_ti->filesize; | 1643 | cur_ti->available = cur_ti->filesize; |
1655 | if (buf_ridx < cur_ti->filesize) | 1644 | |
1645 | /* Check and handle buffer wrapping */ | ||
1646 | if (buf_ridx <= 0) | ||
1656 | buf_ridx += filebuflen; | 1647 | buf_ridx += filebuflen; |
1657 | buf_ridx -= cur_ti->filesize; | ||
1658 | 1648 | ||
1659 | audio_update_trackinfo(); | 1649 | audio_update_trackinfo(); |
1660 | 1650 | ||
@@ -1806,18 +1796,11 @@ void audio_thread(void) | |||
1806 | playback_init(); | 1796 | playback_init(); |
1807 | 1797 | ||
1808 | while (1) { | 1798 | while (1) { |
1809 | if (!play_pending && queue_empty(&audio_queue)) | 1799 | if (play_pending) |
1810 | { | 1800 | queue_wait_w_tmo(&audio_queue, &ev, 0); |
1811 | yield_codecs(); | ||
1812 | audio_check_buffer(); | ||
1813 | } | ||
1814 | else | 1801 | else |
1815 | { | 1802 | queue_wait(&audio_queue, &ev); |
1816 | // ata_spin(); | ||
1817 | sleep(1); | ||
1818 | } | ||
1819 | 1803 | ||
1820 | queue_wait_w_tmo(&audio_queue, &ev, 0); | ||
1821 | if (ev.id == SYS_TIMEOUT && play_pending) | 1804 | if (ev.id == SYS_TIMEOUT && play_pending) |
1822 | { | 1805 | { |
1823 | ev.id = Q_AUDIO_PLAY; | 1806 | ev.id = Q_AUDIO_PLAY; |
@@ -1825,6 +1808,9 @@ void audio_thread(void) | |||
1825 | } | 1808 | } |
1826 | 1809 | ||
1827 | switch (ev.id) { | 1810 | switch (ev.id) { |
1811 | case Q_AUDIO_CHECK_BUFFER: | ||
1812 | audio_check_buffer(); | ||
1813 | break; | ||
1828 | case Q_AUDIO_PLAY: | 1814 | case Q_AUDIO_PLAY: |
1829 | /* Don't start playing immediately if user is skipping tracks | 1815 | /* Don't start playing immediately if user is skipping tracks |
1830 | * fast to prevent UI lag. */ | 1816 | * fast to prevent UI lag. */ |
@@ -1875,11 +1861,13 @@ void audio_thread(void) | |||
1875 | case Q_AUDIO_PAUSE: | 1861 | case Q_AUDIO_PAUSE: |
1876 | logf("audio_pause"); | 1862 | logf("audio_pause"); |
1877 | pcmbuf_pause(true); | 1863 | pcmbuf_pause(true); |
1864 | paused = true; | ||
1878 | break ; | 1865 | break ; |
1879 | 1866 | ||
1880 | case Q_AUDIO_RESUME: | 1867 | case Q_AUDIO_RESUME: |
1881 | logf("audio_resume"); | 1868 | logf("audio_resume"); |
1882 | pcmbuf_pause(false); | 1869 | pcmbuf_pause(false); |
1870 | paused = false; | ||
1883 | break ; | 1871 | break ; |
1884 | 1872 | ||
1885 | case Q_AUDIO_NEXT: | 1873 | case Q_AUDIO_NEXT: |
@@ -2264,16 +2252,15 @@ void audio_prev_dir(void) | |||
2264 | queue_post(&audio_queue, Q_AUDIO_DIR_PREV, 0); | 2252 | queue_post(&audio_queue, Q_AUDIO_DIR_PREV, 0); |
2265 | } | 2253 | } |
2266 | 2254 | ||
2255 | void audio_pre_ff_rewind(void) { | ||
2256 | logf("pre ff/rewind"); | ||
2257 | pcmbuf_pause(true); | ||
2258 | } | ||
2259 | |||
2267 | void audio_ff_rewind(long newpos) | 2260 | void audio_ff_rewind(long newpos) |
2268 | { | 2261 | { |
2269 | logf("ff/rewind: %d", newpos); | 2262 | logf("ff/rewind: %d", newpos); |
2270 | seeking = true; | ||
2271 | queue_post(&audio_queue, Q_AUDIO_FF_REWIND, (int *)newpos); | 2263 | queue_post(&audio_queue, Q_AUDIO_FF_REWIND, (int *)newpos); |
2272 | /* This is a hack, the correct solution is to report back to | ||
2273 | * the caller when the seek is complete. */ | ||
2274 | while (seeking) { | ||
2275 | yield(); | ||
2276 | } | ||
2277 | } | 2264 | } |
2278 | 2265 | ||
2279 | void audio_flush_and_reload_tracks(void) | 2266 | void audio_flush_and_reload_tracks(void) |
@@ -2293,7 +2280,7 @@ int audio_status(void) | |||
2293 | if (playing) | 2280 | if (playing) |
2294 | ret |= AUDIO_STATUS_PLAY; | 2281 | ret |= AUDIO_STATUS_PLAY; |
2295 | 2282 | ||
2296 | if (pcm_is_paused()) | 2283 | if (paused) |
2297 | ret |= AUDIO_STATUS_PAUSE; | 2284 | ret |= AUDIO_STATUS_PAUSE; |
2298 | 2285 | ||
2299 | return ret; | 2286 | return ret; |
@@ -2596,6 +2583,7 @@ void audio_preinit(void) | |||
2596 | filling = false; | 2583 | filling = false; |
2597 | current_codec = CODEC_IDX_AUDIO; | 2584 | current_codec = CODEC_IDX_AUDIO; |
2598 | playing = false; | 2585 | playing = false; |
2586 | paused = false; | ||
2599 | audio_codec_loaded = false; | 2587 | audio_codec_loaded = false; |
2600 | voice_is_playing = false; | 2588 | voice_is_playing = false; |
2601 | track_changed = false; | 2589 | track_changed = false; |
diff --git a/firmware/export/audio.h b/firmware/export/audio.h index d1421ce9a3..0bc47c51f8 100644 --- a/firmware/export/audio.h +++ b/firmware/export/audio.h | |||
@@ -70,6 +70,7 @@ void audio_resume(void); | |||
70 | void audio_next(void); | 70 | void audio_next(void); |
71 | void audio_prev(void); | 71 | void audio_prev(void); |
72 | int audio_status(void); | 72 | int audio_status(void); |
73 | void audio_pre_ff_rewind(void); /* SWCODEC only */ | ||
73 | void audio_ff_rewind(long newtime); | 74 | void audio_ff_rewind(long newtime); |
74 | void audio_flush_and_reload_tracks(void); | 75 | void audio_flush_and_reload_tracks(void); |
75 | struct mp3entry* audio_current_track(void); | 76 | struct mp3entry* audio_current_track(void); |