forked from len0rd/rockbox
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
This commit is contained in:
parent
5280395baa
commit
f68147e5eb
1 changed files with 33 additions and 17 deletions
|
|
@ -142,6 +142,13 @@ enum {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum filling_state {
|
||||||
|
STATE_IDLE, /* audio is stopped: nothing to do */
|
||||||
|
STATE_FILLING, /* adding tracks to the buffer */
|
||||||
|
STATE_FULL, /* can't add any more tracks */
|
||||||
|
STATE_FINISHED, /* all remaining tracks have been added */
|
||||||
|
};
|
||||||
|
|
||||||
/* As defined in plugins/lib/xxx2wav.h */
|
/* As defined in plugins/lib/xxx2wav.h */
|
||||||
#if MEM > 1
|
#if MEM > 1
|
||||||
#define MALLOC_BUFSIZE (512*1024)
|
#define MALLOC_BUFSIZE (512*1024)
|
||||||
|
|
@ -231,6 +238,8 @@ static int last_peek_offset = 0;
|
||||||
/* Scrobbler support */
|
/* Scrobbler support */
|
||||||
static unsigned long prev_track_elapsed = 0; /* Previous track elapsed time (C/A-)*/
|
static unsigned long prev_track_elapsed = 0; /* Previous track elapsed time (C/A-)*/
|
||||||
|
|
||||||
|
static enum filling_state filling;
|
||||||
|
|
||||||
/* Track change controls */
|
/* Track change controls */
|
||||||
static bool automatic_skip = false; /* Who initiated in-progress skip? (C/A-) */
|
static bool automatic_skip = false; /* Who initiated in-progress skip? (C/A-) */
|
||||||
static bool playlist_end = false; /* Has the current playlist ended? (A) */
|
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)
|
||||||
switch (ev)
|
switch (ev)
|
||||||
{
|
{
|
||||||
case EVENT_BUFFER_LOW:
|
case EVENT_BUFFER_LOW:
|
||||||
LOGFQUEUE("buffering > audio Q_AUDIO_FILL_BUFFER");
|
if (filling == STATE_FULL) {
|
||||||
queue_remove_from_head(&audio_queue, Q_AUDIO_FILL_BUFFER);
|
/* force a refill */
|
||||||
queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
|
LOGFQUEUE("buffering > audio Q_AUDIO_FILL_BUFFER");
|
||||||
|
queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EVENT_HANDLE_REBUFFER:
|
case EVENT_HANDLE_REBUFFER:
|
||||||
|
|
@ -1709,6 +1720,7 @@ static bool audio_load_track(int offset, bool start_play)
|
||||||
logf("End-of-playlist");
|
logf("End-of-playlist");
|
||||||
playlist_end = true;
|
playlist_end = true;
|
||||||
memset(&lasttrack_id3, 0, sizeof(struct mp3entry));
|
memset(&lasttrack_id3, 0, sizeof(struct mp3entry));
|
||||||
|
filling = STATE_FINISHED;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1741,7 +1753,7 @@ static bool audio_load_track(int offset, bool start_play)
|
||||||
last_peek_offset--;
|
last_peek_offset--;
|
||||||
close(fd);
|
close(fd);
|
||||||
copy_mp3entry(&lasttrack_id3, &id3);
|
copy_mp3entry(&lasttrack_id3, &id3);
|
||||||
return false;
|
goto buffer_full;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (track_widx == track_ridx)
|
if (track_widx == track_ridx)
|
||||||
|
|
@ -1806,7 +1818,7 @@ static bool audio_load_track(int offset, bool start_play)
|
||||||
if (tracks[track_widx].codec_hid == ERR_BUFFER_FULL)
|
if (tracks[track_widx].codec_hid == ERR_BUFFER_FULL)
|
||||||
{
|
{
|
||||||
/* No space for codec on buffer, not an error */
|
/* No space for codec on buffer, not an error */
|
||||||
return false;
|
goto buffer_full;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is an error condition, either no codec was found, or reading
|
/* 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)
|
||||||
tracks[track_widx].audio_hid = bufopen(trackname, file_offset, type);
|
tracks[track_widx].audio_hid = bufopen(trackname, file_offset, type);
|
||||||
|
|
||||||
if (tracks[track_widx].audio_hid < 0)
|
if (tracks[track_widx].audio_hid < 0)
|
||||||
return false;
|
goto buffer_full;
|
||||||
|
|
||||||
/* All required data is now available for the codec. */
|
/* All required data is now available for the codec. */
|
||||||
tracks[track_widx].taginfo_ready = true;
|
tracks[track_widx].taginfo_ready = true;
|
||||||
|
|
@ -1888,6 +1900,11 @@ static bool audio_load_track(int offset, bool start_play)
|
||||||
track_widx = (track_widx + 1) & MAX_TRACK_MASK;
|
track_widx = (track_widx + 1) & MAX_TRACK_MASK;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
buffer_full:
|
||||||
|
logf("buffer is full for now");
|
||||||
|
filling = STATE_FULL;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void audio_fill_file_buffer(bool start_play, size_t offset)
|
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)
|
||||||
bool had_next_track = audio_next_track() != NULL;
|
bool had_next_track = audio_next_track() != NULL;
|
||||||
bool continue_buffering;
|
bool continue_buffering;
|
||||||
|
|
||||||
|
filling = STATE_FILLING;
|
||||||
|
|
||||||
/* No need to rebuffer if there are track skips pending. */
|
/* No need to rebuffer if there are track skips pending. */
|
||||||
if (ci.new_track != 0)
|
if (ci.new_track != 0)
|
||||||
return;
|
return;
|
||||||
|
|
@ -1917,16 +1936,9 @@ static void audio_fill_file_buffer(bool start_play, size_t offset)
|
||||||
continue_buffering = audio_load_track(offset, start_play);
|
continue_buffering = audio_load_track(offset, start_play);
|
||||||
do {
|
do {
|
||||||
sleep(1);
|
sleep(1);
|
||||||
if (queue_peek(&audio_queue, &ev)) {
|
if (queue_peek(&audio_queue, &ev))
|
||||||
if (ev.id != Q_AUDIO_FILL_BUFFER)
|
/* There's a message in the queue. break the loop to treat it */
|
||||||
{
|
|
||||||
/* There's a message in the queue. break the loop to treat it,
|
|
||||||
and go back to filling after that. */
|
|
||||||
LOGFQUEUE("buffering > audio Q_AUDIO_FILL_BUFFER");
|
|
||||||
queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
continue_buffering = audio_load_track(0, false);
|
continue_buffering = audio_load_track(0, false);
|
||||||
} while (continue_buffering);
|
} while (continue_buffering);
|
||||||
|
|
||||||
|
|
@ -2181,6 +2193,8 @@ static void audio_stop_playback(void)
|
||||||
audio_stop_codec_flush();
|
audio_stop_codec_flush();
|
||||||
playing = false;
|
playing = false;
|
||||||
|
|
||||||
|
filling = STATE_IDLE;
|
||||||
|
|
||||||
/* Mark all entries null. */
|
/* Mark all entries null. */
|
||||||
audio_clear_track_entries();
|
audio_clear_track_entries();
|
||||||
|
|
||||||
|
|
@ -2230,6 +2244,7 @@ static void audio_play_start(size_t offset)
|
||||||
#ifndef HAVE_FLASH_STORAGE
|
#ifndef HAVE_FLASH_STORAGE
|
||||||
set_filebuf_watermark(buffer_margin, 0);
|
set_filebuf_watermark(buffer_margin, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
audio_fill_file_buffer(true, offset);
|
audio_fill_file_buffer(true, offset);
|
||||||
register_buffering_callback(buffering_audio_callback);
|
register_buffering_callback(buffering_audio_callback);
|
||||||
|
|
||||||
|
|
@ -2413,10 +2428,9 @@ static void audio_thread(void)
|
||||||
queue_wait_w_tmo(&audio_queue, &ev, HZ/2);
|
queue_wait_w_tmo(&audio_queue, &ev, HZ/2);
|
||||||
|
|
||||||
switch (ev.id) {
|
switch (ev.id) {
|
||||||
|
|
||||||
case Q_AUDIO_FILL_BUFFER:
|
case Q_AUDIO_FILL_BUFFER:
|
||||||
LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER");
|
LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER");
|
||||||
if (!playing || playlist_end || ci.stop_codec)
|
|
||||||
break;
|
|
||||||
audio_fill_file_buffer(false, 0);
|
audio_fill_file_buffer(false, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -2519,6 +2533,8 @@ static void audio_thread(void)
|
||||||
|
|
||||||
case SYS_TIMEOUT:
|
case SYS_TIMEOUT:
|
||||||
LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
|
LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
|
||||||
|
if (filling == STATE_FILLING)
|
||||||
|
audio_fill_file_buffer(false, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue