diff options
author | Nicolas Pennequin <nicolas.pennequin@free.fr> | 2008-03-28 20:18:53 +0000 |
---|---|---|
committer | Nicolas Pennequin <nicolas.pennequin@free.fr> | 2008-03-28 20:18:53 +0000 |
commit | f68147e5eb21157a9835195c0f0778cf515fe73a (patch) | |
tree | 55235baaa50d9b1317bd59b216aec89d324b641a /apps | |
parent | 5280395baa8a8f9c122940ac2ddbc6869377e527 (diff) | |
download | rockbox-f68147e5eb21157a9835195c0f0778cf515fe73a.tar.gz rockbox-f68147e5eb21157a9835195c0f0778cf515fe73a.zip |
Track playback filling state with a state-machine approach. There shouldn't be any change in behaviour but things are simpler.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16868 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r-- | apps/playback.c | 50 |
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 | ||
145 | enum 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 */ |
232 | static unsigned long prev_track_elapsed = 0; /* Previous track elapsed time (C/A-)*/ | 239 | static unsigned long prev_track_elapsed = 0; /* Previous track elapsed time (C/A-)*/ |
233 | 240 | ||
241 | static enum filling_state filling; | ||
242 | |||
234 | /* Track change controls */ | 243 | /* Track change controls */ |
235 | static bool automatic_skip = false; /* Who initiated in-progress skip? (C/A-) */ | 244 | static bool automatic_skip = false; /* Who initiated in-progress skip? (C/A-) */ |
236 | static bool playlist_end = false; /* Has the current playlist ended? (A) */ | 245 | static 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 | |||
1904 | buffer_full: | ||
1905 | logf("buffer is full for now"); | ||
1906 | filling = STATE_FULL; | ||
1907 | return false; | ||
1891 | } | 1908 | } |
1892 | 1909 | ||
1893 | static void audio_fill_file_buffer(bool start_play, size_t offset) | 1910 | static 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: |