summaryrefslogtreecommitdiff
path: root/apps/playback.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/playback.c')
-rw-r--r--apps/playback.c233
1 files changed, 123 insertions, 110 deletions
diff --git a/apps/playback.c b/apps/playback.c
index 1aa595b131..0a43d958b9 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -401,11 +401,17 @@ bool codec_pcmbuf_insert_callback(const char *buf, size_t length)
401 401
402void* get_codec_memory_callback(size_t *size) 402void* get_codec_memory_callback(size_t *size)
403{ 403{
404 if (current_codec == CODEC_IDX_VOICE)
405 {
406 *size = 0;
407 return NULL;
408 }
409
404 *size = MALLOC_BUFSIZE; 410 *size = MALLOC_BUFSIZE;
405 if (voice_codec_loaded) 411 if (voice_codec_loaded)
406 return &audiobuf[talk_get_bufsize()]; 412 return &audiobuf[talk_get_bufsize()];
407 413 else
408 return &audiobuf[0]; 414 return audiobuf;
409} 415}
410 416
411static void pcmbuf_position_callback(size_t size) ICODE_ATTR; 417static void pcmbuf_position_callback(size_t size) ICODE_ATTR;
@@ -662,24 +668,20 @@ size_t buffer_count_tracks(int from_track, int to_track) {
662 return amount; 668 return amount;
663} 669}
664 670
665static bool buffer_wind_forward(bool require_codec, 671static bool buffer_wind_forward(int new_track_ridx, int old_track_ridx)
666 int new_track_ridx, int old_track_ridx)
667{ 672{
668 size_t amount; 673 size_t amount;
669 674
670 if (require_codec && !tracks[new_track_ridx].has_codec)
671 return false;
672
673 /* Start with the remainder of the previously playing track */ 675 /* Start with the remainder of the previously playing track */
674 amount = tracks[old_track_ridx].filesize - ci.curpos; 676 amount = tracks[old_track_ridx].filesize - ci.curpos;
675 /* Then collect all data from tracks in between them */ 677 /* Then collect all data from tracks in between them */
676 amount += buffer_count_tracks(old_track_ridx, new_track_ridx); 678 amount += buffer_count_tracks(old_track_ridx, new_track_ridx);
677 679
678 logf("bwf:%ldB",amount);
679
680 if (amount > filebufused) 680 if (amount > filebufused)
681 return false; 681 return false;
682 682
683 logf("bwf:%ldB",amount);
684
683 /* Wind the buffer to the beginning of the target track or its codec */ 685 /* Wind the buffer to the beginning of the target track or its codec */
684 buf_ridx += amount; 686 buf_ridx += amount;
685 filebufused -= amount; 687 filebufused -= amount;
@@ -690,8 +692,7 @@ static bool buffer_wind_forward(bool require_codec,
690 return true; 692 return true;
691} 693}
692 694
693static bool buffer_wind_backward(bool require_codec, 695static bool buffer_wind_backward(int new_track_ridx, int old_track_ridx) {
694 int new_track_ridx, int old_track_ridx) {
695 /* Available buffer data */ 696 /* Available buffer data */
696 size_t buf_back = buf_ridx; 697 size_t buf_back = buf_ridx;
697 if (buf_ridx < buf_widx) 698 if (buf_ridx < buf_widx)
@@ -712,15 +713,9 @@ static bool buffer_wind_backward(bool require_codec,
712 tracks[old_track_ridx].filesize - tracks[old_track_ridx].filerem; 713 tracks[old_track_ridx].filesize - tracks[old_track_ridx].filerem;
713 } 714 }
714 715
715 /* If the track needs to load its codec from the buffer */ 716 /* If the codec was ever buffered */
716 if (require_codec || 717 if (tracks[new_track_ridx].codecsize)
717 get_codec_base_type(tracks[old_track_ridx].id3.codectype) !=
718 get_codec_base_type(tracks[new_track_ridx].id3.codectype))
719 { 718 {
720 /* If the codec was never buffered */
721 if (!tracks[new_track_ridx].codecsize)
722 return false;
723
724 /* Add the codec to the needed size */ 719 /* Add the codec to the needed size */
725 amount += tracks[new_track_ridx].codecsize; 720 amount += tracks[new_track_ridx].codecsize;
726 tracks[new_track_ridx].has_codec = true; 721 tracks[new_track_ridx].has_codec = true;
@@ -782,7 +777,7 @@ static void audio_rebuffer(void)
782 audio_fill_file_buffer(false, true, 0); 777 audio_fill_file_buffer(false, true, 0);
783} 778}
784 779
785static void audio_check_new_track(bool require_codec) 780static void audio_check_new_track(void)
786{ 781{
787 int track_count = audio_track_count(); 782 int track_count = audio_track_count();
788 int old_track_ridx = track_ridx; 783 int old_track_ridx = track_ridx;
@@ -836,7 +831,7 @@ static void audio_check_new_track(bool require_codec)
836 /* The track may be in memory, see if it really is */ 831 /* The track may be in memory, see if it really is */
837 else if (forward) 832 else if (forward)
838 { 833 {
839 if (!buffer_wind_forward(require_codec, track_ridx, old_track_ridx)) 834 if (!buffer_wind_forward(track_ridx, old_track_ridx))
840 audio_rebuffer(); 835 audio_rebuffer();
841 } 836 }
842 else 837 else
@@ -863,8 +858,7 @@ static void audio_check_new_track(bool require_codec)
863 } 858 }
864 if (taginfo_ready) 859 if (taginfo_ready)
865 { 860 {
866 if (!buffer_wind_backward( 861 if (!buffer_wind_backward(track_ridx, old_track_ridx))
867 require_codec, track_ridx, old_track_ridx))
868 audio_rebuffer(); 862 audio_rebuffer();
869 } 863 }
870 else 864 else
@@ -902,7 +896,10 @@ static void rebuffer_and_seek(size_t newpos)
902 896
903 /* Clear codec buffer. */ 897 /* Clear codec buffer. */
904 filebufused = 0; 898 filebufused = 0;
905 buf_ridx = buf_widx = cur_ti->buf_idx + newpos; 899 buf_widx = cur_ti->buf_idx + newpos;
900 while (buf_widx >= filebuflen)
901 buf_widx -= filebuflen;
902 buf_ridx = buf_widx;
906 903
907 /* Write to the now current track */ 904 /* Write to the now current track */
908 track_widx = track_ridx; 905 track_widx = track_ridx;
@@ -962,7 +959,6 @@ void codec_advance_buffer_callback(size_t amount)
962 codec_set_offset_callback(ci.curpos); 959 codec_set_offset_callback(ci.curpos);
963} 960}
964 961
965/* Unused as of today 2006, 04/14, will be removed for 3.0 */
966void codec_advance_buffer_loc_callback(void *ptr) 962void codec_advance_buffer_loc_callback(void *ptr)
967{ 963{
968 size_t amount; 964 size_t amount;
@@ -971,6 +967,7 @@ void codec_advance_buffer_loc_callback(void *ptr)
971 amount = (size_t)ptr - (size_t)voicebuf; 967 amount = (size_t)ptr - (size_t)voicebuf;
972 else 968 else
973 amount = (size_t)ptr - (size_t)&filebuf[buf_ridx]; 969 amount = (size_t)ptr - (size_t)&filebuf[buf_ridx];
970
974 codec_advance_buffer_callback(amount); 971 codec_advance_buffer_callback(amount);
975} 972}
976 973
@@ -1178,7 +1175,7 @@ static void audio_read_file(void)
1178 1175
1179 /* If we're called and no file is open, this is an error */ 1176 /* If we're called and no file is open, this is an error */
1180 if (current_fd < 0) { 1177 if (current_fd < 0) {
1181 logf("Zero fd in arf"); 1178 logf("Bad fd in arf");
1182 /* Stop this buffer cycle immediately */ 1179 /* Stop this buffer cycle immediately */
1183 fill_bytesleft = 0; 1180 fill_bytesleft = 0;
1184 /* Give some hope of miraculous recovery by forcing a track reload */ 1181 /* Give some hope of miraculous recovery by forcing a track reload */
@@ -1270,67 +1267,60 @@ static void codec_discard_codec_callback(void)
1270 } 1267 }
1271} 1268}
1272 1269
1270static const char *get_codec_path(int codectype) {
1271 switch (codectype) {
1272 case AFMT_OGG_VORBIS:
1273 logf("Codec: Vorbis");
1274 return CODEC_VORBIS;
1275 case AFMT_MPA_L1:
1276 case AFMT_MPA_L2:
1277 case AFMT_MPA_L3:
1278 logf("Codec: MPA L1/L2/L3");
1279 return CODEC_MPA_L3;
1280 case AFMT_PCM_WAV:
1281 logf("Codec: PCM WAV");
1282 return CODEC_WAV;
1283 case AFMT_FLAC:
1284 logf("Codec: FLAC");
1285 return CODEC_FLAC;
1286 case AFMT_A52:
1287 logf("Codec: A52");
1288 return CODEC_A52;
1289 case AFMT_MPC:
1290 logf("Codec: Musepack");
1291 return CODEC_MPC;
1292 case AFMT_WAVPACK:
1293 logf("Codec: WAVPACK");
1294 return CODEC_WAVPACK;
1295 case AFMT_ALAC:
1296 logf("Codec: ALAC");
1297 return CODEC_ALAC;
1298 case AFMT_AAC:
1299 logf("Codec: AAC");
1300 return CODEC_AAC;
1301 case AFMT_SHN:
1302 logf("Codec: SHN");
1303 return CODEC_SHN;
1304 case AFMT_AIFF:
1305 logf("Codec: PCM AIFF");
1306 return CODEC_AIFF;
1307 default:
1308 logf("Codec: Unsupported");
1309 return NULL;
1310 }
1311}
1312
1273static bool loadcodec(bool start_play) 1313static bool loadcodec(bool start_play)
1274{ 1314{
1275 size_t size; 1315 size_t size;
1276 int fd; 1316 int fd;
1277 int rc; 1317 int rc;
1278 const char *codec_path;
1279 size_t copy_n; 1318 size_t copy_n;
1280 int prev_track; 1319 int prev_track;
1281 1320
1282 switch (tracks[track_widx].id3.codectype) { 1321 const char *codec_path = get_codec_path(tracks[track_widx].id3.codectype);
1283 case AFMT_OGG_VORBIS: 1322 if (codec_path == NULL)
1284 logf("Codec: Vorbis");
1285 codec_path = CODEC_VORBIS;
1286 break;
1287 case AFMT_MPA_L1:
1288 case AFMT_MPA_L2:
1289 case AFMT_MPA_L3:
1290 logf("Codec: MPA L1/L2/L3");
1291 codec_path = CODEC_MPA_L3;
1292 break;
1293 case AFMT_PCM_WAV:
1294 logf("Codec: PCM WAV");
1295 codec_path = CODEC_WAV;
1296 break;
1297 case AFMT_FLAC:
1298 logf("Codec: FLAC");
1299 codec_path = CODEC_FLAC;
1300 break;
1301 case AFMT_A52:
1302 logf("Codec: A52");
1303 codec_path = CODEC_A52;
1304 break;
1305 case AFMT_MPC:
1306 logf("Codec: Musepack");
1307 codec_path = CODEC_MPC;
1308 break;
1309 case AFMT_WAVPACK:
1310 logf("Codec: WAVPACK");
1311 codec_path = CODEC_WAVPACK;
1312 break;
1313 case AFMT_ALAC:
1314 logf("Codec: ALAC");
1315 codec_path = CODEC_ALAC;
1316 break;
1317 case AFMT_AAC:
1318 logf("Codec: AAC");
1319 codec_path = CODEC_AAC;
1320 break;
1321 case AFMT_SHN:
1322 logf("Codec: SHN");
1323 codec_path = CODEC_SHN;
1324 break;
1325 case AFMT_AIFF:
1326 logf("Codec: PCM AIFF");
1327 codec_path = CODEC_AIFF;
1328 break;
1329 default:
1330 logf("Codec: Unsupported");
1331 codec_path = NULL;
1332 return false; 1323 return false;
1333 }
1334 1324
1335 tracks[track_widx].has_codec = false; 1325 tracks[track_widx].has_codec = false;
1336 tracks[track_widx].codecsize = 0; 1326 tracks[track_widx].codecsize = 0;
@@ -1345,7 +1335,6 @@ static bool loadcodec(bool start_play)
1345 ci.taginfo_ready = &cur_ti->taginfo_ready; 1335 ci.taginfo_ready = &cur_ti->taginfo_ready;
1346 ci.curpos = 0; 1336 ci.curpos = 0;
1347 playing = true; 1337 playing = true;
1348 logf("Starting codec");
1349 queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (void *)codec_path); 1338 queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (void *)codec_path);
1350 return true; 1339 return true;
1351 } 1340 }
@@ -1376,7 +1365,7 @@ static bool loadcodec(bool start_play)
1376 1365
1377 size = filesize(fd); 1366 size = filesize(fd);
1378 /* Never load a partial codec */ 1367 /* Never load a partial codec */
1379 if (filebuflen - filebufused < size) { 1368 if (fill_bytesleft < size) {
1380 logf("Not enough space"); 1369 logf("Not enough space");
1381 fill_bytesleft = 0; 1370 fill_bytesleft = 0;
1382 close(fd); 1371 close(fd);
@@ -1401,9 +1390,6 @@ static bool loadcodec(bool start_play)
1401 1390
1402 tracks[track_widx].codecsize += rc; 1391 tracks[track_widx].codecsize += rc;
1403 1392
1404 /* FIXME: This will spin around pretty quickly, but still requires
1405 * full read of the codec when an event is posted to the audio
1406 * queue during this loop */
1407 yield_codecs(); 1393 yield_codecs();
1408 } 1394 }
1409 1395
@@ -1833,7 +1819,7 @@ static void track_skip_done(bool was_manual)
1833 } 1819 }
1834} 1820}
1835 1821
1836static bool load_next_track(bool require_codec) { 1822static bool load_next_track(void) {
1837 struct event ev; 1823 struct event ev;
1838 1824
1839#ifdef AB_REPEAT_ENABLE 1825#ifdef AB_REPEAT_ENABLE
@@ -1848,10 +1834,13 @@ static bool load_next_track(bool require_codec) {
1848 manual_skip = false; 1834 manual_skip = false;
1849 } 1835 }
1850 else 1836 else
1837 {
1851 manual_skip = true; 1838 manual_skip = true;
1839 pcmbuf_play_stop();
1840 }
1852 1841
1853 cpu_boost(true); 1842 cpu_boost(true);
1854 queue_post(&audio_queue, Q_AUDIO_CHECK_NEW_TRACK, (void *)require_codec); 1843 queue_post(&audio_queue, Q_AUDIO_CHECK_NEW_TRACK, 0);
1855 queue_wait(&codec_callback_queue, &ev); 1844 queue_wait(&codec_callback_queue, &ev);
1856 cpu_boost(false); 1845 cpu_boost(false);
1857 switch (ev.id) 1846 switch (ev.id)
@@ -1871,6 +1860,8 @@ static bool load_next_track(bool require_codec) {
1871 1860
1872static bool codec_request_next_track_callback(void) 1861static bool codec_request_next_track_callback(void)
1873{ 1862{
1863 int prev_codectype;
1864
1874 if (current_codec == CODEC_IDX_VOICE) { 1865 if (current_codec == CODEC_IDX_VOICE) {
1875 voice_remaining = 0; 1866 voice_remaining = 0;
1876 /* Terminate the codec if there are messages waiting on the queue or 1867 /* Terminate the codec if there are messages waiting on the queue or
@@ -1881,12 +1872,13 @@ static bool codec_request_next_track_callback(void)
1881 if (ci.stop_codec || !playing) 1872 if (ci.stop_codec || !playing)
1882 return false; 1873 return false;
1883 1874
1884 if (!load_next_track(false)) 1875 prev_codectype = get_codec_base_type(cur_ti->id3.codectype);
1876
1877 if (!load_next_track())
1885 return false; 1878 return false;
1886 1879
1887 /* Check if the next codec is the same file. */ 1880 /* Check if the next codec is the same file. */
1888 if (get_codec_base_type(prev_ti->id3.codectype) == 1881 if (prev_codectype == get_codec_base_type(cur_ti->id3.codectype))
1889 get_codec_base_type(cur_ti->id3.codectype))
1890 { 1882 {
1891 logf("New track loaded"); 1883 logf("New track loaded");
1892 codec_discard_codec_callback(); 1884 codec_discard_codec_callback();
@@ -1894,7 +1886,7 @@ static bool codec_request_next_track_callback(void)
1894 } 1886 }
1895 else 1887 else
1896 { 1888 {
1897 logf("New codec:%d/%d", cur_ti->id3.codectype, prev_ti->id3.codectype); 1889 logf("New codec:%d/%d", cur_ti->id3.codectype, prev_codectype);
1898 return false; 1890 return false;
1899 } 1891 }
1900} 1892}
@@ -2006,7 +1998,7 @@ void audio_thread(void)
2006 1998
2007 case Q_AUDIO_CHECK_NEW_TRACK: 1999 case Q_AUDIO_CHECK_NEW_TRACK:
2008 logf("Check new track buffer"); 2000 logf("Check new track buffer");
2009 audio_check_new_track((bool)ev.data); 2001 audio_check_new_track();
2010 break; 2002 break;
2011 2003
2012 case Q_AUDIO_DIR_SKIP: 2004 case Q_AUDIO_DIR_SKIP:
@@ -2055,11 +2047,12 @@ void codec_thread(void)
2055 2047
2056 switch (ev.id) { 2048 switch (ev.id) {
2057 case Q_CODEC_LOAD_DISK: 2049 case Q_CODEC_LOAD_DISK:
2050 logf("Codec load disk");
2058 ci.stop_codec = false; 2051 ci.stop_codec = false;
2059 audio_codec_loaded = true; 2052 audio_codec_loaded = true;
2060 mutex_lock(&mutex_codecthread); 2053 mutex_lock(&mutex_codecthread);
2061 current_codec = CODEC_IDX_AUDIO; 2054 current_codec = CODEC_IDX_AUDIO;
2062 status = codec_load_file((char *)ev.data, &ci); 2055 status = codec_load_file((const char *)ev.data, &ci);
2063 mutex_unlock(&mutex_codecthread); 2056 mutex_unlock(&mutex_codecthread);
2064 break ; 2057 break ;
2065 2058
@@ -2115,21 +2108,32 @@ void codec_thread(void)
2115 case Q_CODEC_LOAD_DISK: 2108 case Q_CODEC_LOAD_DISK:
2116 case Q_CODEC_LOAD: 2109 case Q_CODEC_LOAD:
2117 if (playing) { 2110 if (playing) {
2118 if (ci.new_track || status == CODEC_OK) { 2111 const char *codec_path;
2119 logf("Codec finished"); 2112 if (ci.new_track || status != CODEC_OK) {
2120 if (ci.stop_codec) 2113 if (!ci.new_track) {
2121 queue_post(&audio_queue, Q_AUDIO_STOP, 0); 2114 logf("Codec failure");
2122 else 2115 gui_syncsplash(HZ*2, true, "Codec failure");
2123 queue_post(&codec_queue, Q_CODEC_LOAD, 0); 2116 }
2117 if (!load_next_track())
2118 {
2119 queue_post(&codec_queue, Q_AUDIO_STOP, 0);
2120 break;
2121 }
2124 } else { 2122 } else {
2125 logf("Codec failure"); 2123 logf("Codec finished");
2126 gui_syncsplash(HZ*2, true, "Codec failure");
2127 if (ci.stop_codec) 2124 if (ci.stop_codec)
2125 {
2128 queue_post(&audio_queue, Q_AUDIO_STOP, 0); 2126 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
2129 else if (load_next_track(true)) 2127 break;
2130 queue_post(&codec_queue, Q_CODEC_LOAD, 0); 2128 }
2131 else 2129 }
2132 queue_post(&audio_queue, Q_AUDIO_STOP, 0); 2130 if (cur_ti->has_codec)
2131 queue_post(&codec_queue, Q_CODEC_LOAD, 0);
2132 else
2133 {
2134 codec_path = get_codec_path(cur_ti->id3.codectype);
2135 queue_post(&codec_queue,
2136 Q_CODEC_LOAD_DISK, (void *)codec_path);
2133 } 2137 }
2134 } 2138 }
2135 } 2139 }
@@ -2138,17 +2142,24 @@ void codec_thread(void)
2138 2142
2139static void reset_buffer(void) 2143static void reset_buffer(void)
2140{ 2144{
2145 size_t offset;
2146
2141 filebuf = (char *)&audiobuf[MALLOC_BUFSIZE]; 2147 filebuf = (char *)&audiobuf[MALLOC_BUFSIZE];
2142 filebuflen = audiobufend - audiobuf - MALLOC_BUFSIZE - GUARD_BUFSIZE - 2148 filebuflen = audiobufend - audiobuf - MALLOC_BUFSIZE - GUARD_BUFSIZE -
2143 (pcmbuf_get_bufsize() + get_pcmbuf_descsize() + PCMBUF_FADE_CHUNK); 2149 (pcmbuf_get_bufsize() + get_pcmbuf_descsize() + PCMBUF_FADE_CHUNK);
2144 2150
2145
2146 if (talk_get_bufsize() && voice_codec_loaded) 2151 if (talk_get_bufsize() && voice_codec_loaded)
2147 { 2152 {
2148 filebuf = &filebuf[talk_get_bufsize()]; 2153 filebuf = &filebuf[talk_get_bufsize()];
2149 filebuflen -= 2*CODEC_IRAM_SIZE + 2*CODEC_SIZE + talk_get_bufsize(); 2154 filebuflen -= 2*CODEC_IRAM_SIZE + 2*CODEC_SIZE + talk_get_bufsize();
2150 } 2155 }
2151 2156
2157 /* Ensure that everything is aligned */
2158 offset = (-(size_t)filebuf) & 3;
2159 filebuf += offset;
2160 filebuflen -= offset;
2161 filebuflen &= ~3;
2162
2152#ifndef SIMULATOR 2163#ifndef SIMULATOR
2153 iram_buf[0] = &filebuf[filebuflen]; 2164 iram_buf[0] = &filebuf[filebuflen];
2154 iram_buf[1] = &filebuf[filebuflen+CODEC_IRAM_SIZE]; 2165 iram_buf[1] = &filebuf[filebuflen+CODEC_IRAM_SIZE];
@@ -2473,7 +2484,7 @@ int mp3_get_file_pos(void)
2473 remainder = (id3->elapsed*100)%id3->length; 2484 remainder = (id3->elapsed*100)%id3->length;
2474 remainder = (remainder*100)/id3->length; 2485 remainder = (remainder*100)/id3->length;
2475 plen = (nexttoc - curtoc)*(id3->filesize/256); 2486 plen = (nexttoc - curtoc)*(id3->filesize/256);
2476 pos += (plen/100)*remainder; 2487 pos += (plen/100)*remainder;
2477 } 2488 }
2478 else 2489 else
2479 { 2490 {
@@ -2528,7 +2539,7 @@ void audio_set_crossfade(int enable)
2528 return; /* Audio buffers not yet set up */ 2539 return; /* Audio buffers not yet set up */
2529 2540
2530 /* Store the track resume position */ 2541 /* Store the track resume position */
2531 if (playing) 2542 if (was_playing)
2532 offset = cur_ti->id3.offset; 2543 offset = cur_ti->id3.offset;
2533 2544
2534 if (enable) 2545 if (enable)
@@ -2542,12 +2553,14 @@ void audio_set_crossfade(int enable)
2542 if (pcmbuf_get_bufsize() == size) 2553 if (pcmbuf_get_bufsize() == size)
2543 return ; 2554 return ;
2544 2555
2545 /* Playback has to be stopped before changing the buffer size. */
2546 audio_stop_playback();
2547
2548 /* Re-initialize audio system. */
2549 if (was_playing) 2556 if (was_playing)
2557 {
2558 /* Playback has to be stopped before changing the buffer size. */
2559 audio_stop_playback();
2550 gui_syncsplash(0, true, (char *)str(LANG_RESTARTING_PLAYBACK)); 2560 gui_syncsplash(0, true, (char *)str(LANG_RESTARTING_PLAYBACK));
2561 }
2562
2563 /* Re-initialize audio system. */
2551 pcmbuf_init(size); 2564 pcmbuf_init(size);
2552 pcmbuf_crossfade_enable(enable); 2565 pcmbuf_crossfade_enable(enable);
2553 reset_buffer(); 2566 reset_buffer();