summaryrefslogtreecommitdiff
path: root/apps/playback.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/playback.c')
-rw-r--r--apps/playback.c194
1 files changed, 91 insertions, 103 deletions
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 @@
70static volatile bool audio_codec_loaded; 70static volatile bool audio_codec_loaded;
71static volatile bool voice_codec_loaded; 71static volatile bool voice_codec_loaded;
72static volatile bool playing; 72static volatile bool playing;
73static volatile bool seeking; 73static 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
690bool codec_seek_buffer_callback(size_t newpos) 695bool codec_seek_buffer_callback(size_t newpos)
@@ -852,7 +857,6 @@ void strip_id3v1_tag(void)
852 857
853static void audio_fill_file_buffer(void) 858static 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
1343static void audio_stop_playback(bool resume) 1309static 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)
1467static void audio_check_buffer(void) 1434static 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
2255void audio_pre_ff_rewind(void) {
2256 logf("pre ff/rewind");
2257 pcmbuf_pause(true);
2258}
2259
2267void audio_ff_rewind(long newpos) 2260void 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
2279void audio_flush_and_reload_tracks(void) 2266void 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;