summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/playback.c50
1 files changed, 33 insertions, 17 deletions
diff --git a/apps/playback.c b/apps/playback.c
index 880c9acf7e..88f1bb5816 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -142,6 +142,13 @@ enum {
142#endif 142#endif
143}; 143};
144 144
145enum filling_state {
146 STATE_IDLE, /* audio is stopped: nothing to do */
147 STATE_FILLING, /* adding tracks to the buffer */
148 STATE_FULL, /* can't add any more tracks */
149 STATE_FINISHED, /* all remaining tracks have been added */
150};
151
145/* As defined in plugins/lib/xxx2wav.h */ 152/* As defined in plugins/lib/xxx2wav.h */
146#if MEM > 1 153#if MEM > 1
147#define MALLOC_BUFSIZE (512*1024) 154#define MALLOC_BUFSIZE (512*1024)
@@ -231,6 +238,8 @@ static int last_peek_offset = 0;
231/* Scrobbler support */ 238/* Scrobbler support */
232static unsigned long prev_track_elapsed = 0; /* Previous track elapsed time (C/A-)*/ 239static unsigned long prev_track_elapsed = 0; /* Previous track elapsed time (C/A-)*/
233 240
241static enum filling_state filling;
242
234/* Track change controls */ 243/* Track change controls */
235static bool automatic_skip = false; /* Who initiated in-progress skip? (C/A-) */ 244static bool automatic_skip = false; /* Who initiated in-progress skip? (C/A-) */
236static bool playlist_end = false; /* Has the current playlist ended? (A) */ 245static bool playlist_end = false; /* Has the current playlist ended? (A) */
@@ -1493,9 +1502,11 @@ static void buffering_audio_callback(enum callback_event ev, int value)
1493 switch (ev) 1502 switch (ev)
1494 { 1503 {
1495 case EVENT_BUFFER_LOW: 1504 case EVENT_BUFFER_LOW:
1496 LOGFQUEUE("buffering > audio Q_AUDIO_FILL_BUFFER"); 1505 if (filling == STATE_FULL) {
1497 queue_remove_from_head(&audio_queue, Q_AUDIO_FILL_BUFFER); 1506 /* force a refill */
1498 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0); 1507 LOGFQUEUE("buffering > audio Q_AUDIO_FILL_BUFFER");
1508 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1509 }
1499 break; 1510 break;
1500 1511
1501 case EVENT_HANDLE_REBUFFER: 1512 case EVENT_HANDLE_REBUFFER:
@@ -1709,6 +1720,7 @@ static bool audio_load_track(int offset, bool start_play)
1709 logf("End-of-playlist"); 1720 logf("End-of-playlist");
1710 playlist_end = true; 1721 playlist_end = true;
1711 memset(&lasttrack_id3, 0, sizeof(struct mp3entry)); 1722 memset(&lasttrack_id3, 0, sizeof(struct mp3entry));
1723 filling = STATE_FINISHED;
1712 return false; 1724 return false;
1713 } 1725 }
1714 1726
@@ -1741,7 +1753,7 @@ static bool audio_load_track(int offset, bool start_play)
1741 last_peek_offset--; 1753 last_peek_offset--;
1742 close(fd); 1754 close(fd);
1743 copy_mp3entry(&lasttrack_id3, &id3); 1755 copy_mp3entry(&lasttrack_id3, &id3);
1744 return false; 1756 goto buffer_full;
1745 } 1757 }
1746 1758
1747 if (track_widx == track_ridx) 1759 if (track_widx == track_ridx)
@@ -1806,7 +1818,7 @@ static bool audio_load_track(int offset, bool start_play)
1806 if (tracks[track_widx].codec_hid == ERR_BUFFER_FULL) 1818 if (tracks[track_widx].codec_hid == ERR_BUFFER_FULL)
1807 { 1819 {
1808 /* No space for codec on buffer, not an error */ 1820 /* No space for codec on buffer, not an error */
1809 return false; 1821 goto buffer_full;
1810 } 1822 }
1811 1823
1812 /* This is an error condition, either no codec was found, or reading 1824 /* This is an error condition, either no codec was found, or reading
@@ -1874,7 +1886,7 @@ static bool audio_load_track(int offset, bool start_play)
1874 tracks[track_widx].audio_hid = bufopen(trackname, file_offset, type); 1886 tracks[track_widx].audio_hid = bufopen(trackname, file_offset, type);
1875 1887
1876 if (tracks[track_widx].audio_hid < 0) 1888 if (tracks[track_widx].audio_hid < 0)
1877 return false; 1889 goto buffer_full;
1878 1890
1879 /* All required data is now available for the codec. */ 1891 /* All required data is now available for the codec. */
1880 tracks[track_widx].taginfo_ready = true; 1892 tracks[track_widx].taginfo_ready = true;
@@ -1888,6 +1900,11 @@ static bool audio_load_track(int offset, bool start_play)
1888 track_widx = (track_widx + 1) & MAX_TRACK_MASK; 1900 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
1889 1901
1890 return true; 1902 return true;
1903
1904buffer_full:
1905 logf("buffer is full for now");
1906 filling = STATE_FULL;
1907 return false;
1891} 1908}
1892 1909
1893static void audio_fill_file_buffer(bool start_play, size_t offset) 1910static void audio_fill_file_buffer(bool start_play, size_t offset)
@@ -1896,6 +1913,8 @@ static void audio_fill_file_buffer(bool start_play, size_t offset)
1896 bool had_next_track = audio_next_track() != NULL; 1913 bool had_next_track = audio_next_track() != NULL;
1897 bool continue_buffering; 1914 bool continue_buffering;
1898 1915
1916 filling = STATE_FILLING;
1917
1899 /* No need to rebuffer if there are track skips pending. */ 1918 /* No need to rebuffer if there are track skips pending. */
1900 if (ci.new_track != 0) 1919 if (ci.new_track != 0)
1901 return; 1920 return;
@@ -1917,16 +1936,9 @@ static void audio_fill_file_buffer(bool start_play, size_t offset)
1917 continue_buffering = audio_load_track(offset, start_play); 1936 continue_buffering = audio_load_track(offset, start_play);
1918 do { 1937 do {
1919 sleep(1); 1938 sleep(1);
1920 if (queue_peek(&audio_queue, &ev)) { 1939 if (queue_peek(&audio_queue, &ev))
1921 if (ev.id != Q_AUDIO_FILL_BUFFER) 1940 /* There's a message in the queue. break the loop to treat it */
1922 {
1923 /* There's a message in the queue. break the loop to treat it,
1924 and go back to filling after that. */
1925 LOGFQUEUE("buffering > audio Q_AUDIO_FILL_BUFFER");
1926 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1927 }
1928 break; 1941 break;
1929 }
1930 continue_buffering = audio_load_track(0, false); 1942 continue_buffering = audio_load_track(0, false);
1931 } while (continue_buffering); 1943 } while (continue_buffering);
1932 1944
@@ -2181,6 +2193,8 @@ static void audio_stop_playback(void)
2181 audio_stop_codec_flush(); 2193 audio_stop_codec_flush();
2182 playing = false; 2194 playing = false;
2183 2195
2196 filling = STATE_IDLE;
2197
2184 /* Mark all entries null. */ 2198 /* Mark all entries null. */
2185 audio_clear_track_entries(); 2199 audio_clear_track_entries();
2186 2200
@@ -2230,6 +2244,7 @@ static void audio_play_start(size_t offset)
2230#ifndef HAVE_FLASH_STORAGE 2244#ifndef HAVE_FLASH_STORAGE
2231 set_filebuf_watermark(buffer_margin, 0); 2245 set_filebuf_watermark(buffer_margin, 0);
2232#endif 2246#endif
2247
2233 audio_fill_file_buffer(true, offset); 2248 audio_fill_file_buffer(true, offset);
2234 register_buffering_callback(buffering_audio_callback); 2249 register_buffering_callback(buffering_audio_callback);
2235 2250
@@ -2413,10 +2428,9 @@ static void audio_thread(void)
2413 queue_wait_w_tmo(&audio_queue, &ev, HZ/2); 2428 queue_wait_w_tmo(&audio_queue, &ev, HZ/2);
2414 2429
2415 switch (ev.id) { 2430 switch (ev.id) {
2431
2416 case Q_AUDIO_FILL_BUFFER: 2432 case Q_AUDIO_FILL_BUFFER:
2417 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER"); 2433 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER");
2418 if (!playing || playlist_end || ci.stop_codec)
2419 break;
2420 audio_fill_file_buffer(false, 0); 2434 audio_fill_file_buffer(false, 0);
2421 break; 2435 break;
2422 2436
@@ -2519,6 +2533,8 @@ static void audio_thread(void)
2519 2533
2520 case SYS_TIMEOUT: 2534 case SYS_TIMEOUT:
2521 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT"); 2535 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
2536 if (filling == STATE_FILLING)
2537 audio_fill_file_buffer(false, 0);
2522 break; 2538 break;
2523 2539
2524 default: 2540 default: