Rewritten playback event handling. Should fix runtime statistics gathering.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16546 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Miika Pekkarinen 2008-03-07 22:56:51 +00:00
parent aafa321d31
commit 2ccdc48ee9
4 changed files with 71 additions and 68 deletions

View File

@ -210,8 +210,6 @@ struct track_info {
size_t filesize; /* File total length */
bool taginfo_ready; /* Is metadata read */
bool event_sent; /* Was this track's buffered event sent */
};
static struct track_info tracks[MAX_TRACK];
@ -247,13 +245,12 @@ static bool skipped_during_pause = false; /* Do we need to clear the PCM buffer
*/
static bool codec_requested_stop = false;
/* Callbacks which applications or plugins may set */
/* When the playing track has changed from the user's perspective */
void (*track_changed_callback)(struct mp3entry *id3) = NULL;
/* When a track has been buffered */
void (*track_buffer_callback)(struct mp3entry *id3) = NULL;
/* When a track's buffer has been overwritten or cleared */
void (*track_unbuffer_callback)(struct mp3entry *id3) = NULL;
struct playback_event {
enum PLAYBACK_EVENT_TYPE type;
void (*callback)(void *data);
};
struct playback_event events[PLAYBACK_MAX_EVENTS];
static size_t buffer_margin = 0; /* Buffer margin aka anti-skip buffer (A/C-) */
@ -352,11 +349,6 @@ static bool clear_track_info(struct track_info *track)
}
if (track->id3_hid >= 0) {
if (track->event_sent && track_unbuffer_callback) {
/* If there is an unbuffer callback, call it */
track_unbuffer_callback(bufgetid3(track->id3_hid));
}
if (bufclose(track->id3_hid))
track->id3_hid = -1;
else
@ -381,7 +373,6 @@ static bool clear_track_info(struct track_info *track)
track->filesize = 0;
track->taginfo_ready = false;
track->event_sent = false;
return true;
}
@ -1456,6 +1447,51 @@ static void codec_thread(void)
/* --- Audio thread --- */
void playback_add_event(enum PLAYBACK_EVENT_TYPE type, void (*handler))
{
int i;
/* Try to find a free slot. */
for (i = 0; i < PLAYBACK_MAX_EVENTS; i++)
{
if (events[i].callback == NULL)
{
events[i].type = type;
events[i].callback = handler;
return;
}
}
panicf("playback event line full");
}
void playback_remove_event(enum PLAYBACK_EVENT_TYPE type, void (*handler))
{
int i;
for (i = 0; i < PLAYBACK_MAX_EVENTS; i++)
{
if (events[i].type == type && events[i].callback == handler)
{
events[i].callback = NULL;
return;
}
}
panicf("playback event not found");
}
static void send_event(enum PLAYBACK_EVENT_TYPE type, void *data)
{
int i;
for (i = 0; i < PLAYBACK_MAX_EVENTS; i++)
{
if (events[i].type == type && events[i].callback != NULL)
events[i].callback(data);
}
}
static bool audio_have_tracks(void)
{
return (audio_track_count() != 0);
@ -1546,7 +1582,7 @@ static void audio_clear_track_entries(bool clear_unbuffered)
/* If the track is buffered, conditionally clear/notify,
* otherwise clear the track if that option is selected */
if (tracks[cur_idx].event_sent || clear_unbuffered)
if (clear_unbuffered)
clear_track_info(&tracks[cur_idx]);
}
}
@ -1750,8 +1786,7 @@ static bool audio_load_track(int offset, bool start_play)
{
if (get_metadata(&id3, fd, trackname))
{
if (track_buffer_callback)
track_buffer_callback(&id3);
send_event(PLAYBACK_EVENT_TRACK_BUFFER, &id3);
tracks[track_widx].id3_hid =
bufalloc(&id3, sizeof(struct mp3entry), TYPE_ID3);
@ -1910,30 +1945,6 @@ static bool audio_load_track(int offset, bool start_play)
return true;
}
/* Send callback events to notify about new tracks. */
static void audio_generate_postbuffer_events(void)
{
int cur_idx;
logf("Postbuffer:%d/%d",track_ridx,track_widx);
if (audio_have_tracks())
{
cur_idx = track_ridx;
while (1) {
if (!tracks[cur_idx].event_sent)
{
/* Mark the event 'sent' even if we don't really send one */
tracks[cur_idx].event_sent = true;
}
if (cur_idx == track_widx)
break;
cur_idx = (cur_idx + 1) & MAX_TRACK_MASK;
}
}
}
static void audio_fill_file_buffer(bool start_play, size_t offset)
{
struct queue_event ev;
@ -1978,7 +1989,6 @@ static void audio_fill_file_buffer(bool start_play, size_t offset)
if (!had_next_track && audio_next_track())
track_changed = true;
audio_generate_postbuffer_events();
}
static void audio_rebuffer(void)
@ -2012,6 +2022,9 @@ static int audio_check_new_track(void)
bool forward;
bool end_of_playlist; /* Temporary flag, not the same as playlist_end */
/* Now it's good time to send track unbuffer events. */
send_event(PLAYBACK_EVENT_TRACK_FINISH, &curtrack_id3);
if (dir_skip)
{
dir_skip = false;
@ -2173,21 +2186,6 @@ skip_done:
return Q_CODEC_REQUEST_COMPLETE;
}
void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3))
{
track_buffer_callback = handler;
}
void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3))
{
track_unbuffer_callback = handler;
}
void audio_set_track_changed_event(void (*handler)(struct mp3entry *id3))
{
track_changed_callback = handler;
}
unsigned long audio_prev_elapsed(void)
{
return prev_track_elapsed;
@ -2404,8 +2402,7 @@ static void audio_finalise_track_change(void)
bufgetid3(prev_ti->id3_hid)->elapsed = 0;
}
if (track_changed_callback)
track_changed_callback(&curtrack_id3);
send_event(PLAYBACK_EVENT_TRACK_CHANGE, &curtrack_id3);
track_changed = true;
playlist_update_resume_info(audio_current_track());

View File

@ -39,11 +39,17 @@
#define MAX_TRACK_MASK (MAX_TRACK-1)
#define PLAYBACK_MAX_EVENTS 4
enum PLAYBACK_EVENT_TYPE {
PLAYBACK_EVENT_TRACK_BUFFER,
PLAYBACK_EVENT_TRACK_FINISH,
PLAYBACK_EVENT_TRACK_CHANGE,
};
/* Functions */
const char * get_codec_filename(int cod_spec);
void audio_set_track_changed_event(void (*handler)(struct mp3entry *id3));
void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3));
void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3));
void playback_add_event(enum PLAYBACK_EVENT_TYPE type, void (*handler));
void playback_remove_event(enum PLAYBACK_EVENT_TYPE type, void (*handler));
void voice_wait(void);
#if CONFIG_CODEC == SWCODEC /* This #ifdef is better here than gui/gwps.c */

View File

@ -224,7 +224,7 @@ int scrobbler_init(void)
scrobbler_cache = buffer_alloc(SCROBBLER_MAX_CACHE*SCROBBLER_CACHE_LEN);
audio_set_track_changed_event(&scrobbler_change_event);
playback_add_event(PLAYBACK_EVENT_TRACK_CHANGE, scrobbler_change_event);
cache_pos = 0;
pending = false;
scrobbler_initialised = true;
@ -259,7 +259,7 @@ void scrobbler_shutdown(void)
if (scrobbler_initialised)
{
audio_set_track_changed_event(NULL);
playback_remove_event(PLAYBACK_EVENT_TRACK_CHANGE, scrobbler_change_event);
scrobbler_initialised = false;
}
}

View File

@ -660,7 +660,7 @@ static void tagtree_buffer_event(struct mp3entry *id3)
tagcache_search_finish(&tcs);
}
static void tagtree_unbuffer_event(struct mp3entry *id3)
static void tagtree_track_finish_event(struct mp3entry *id3)
{
long playcount;
long playtime;
@ -924,8 +924,8 @@ void tagtree_init(void)
root_menu = 0;
uniqbuf = buffer_alloc(UNIQBUF_SIZE);
audio_set_track_buffer_event(tagtree_buffer_event);
audio_set_track_unbuffer_event(tagtree_unbuffer_event);
playback_add_event(PLAYBACK_EVENT_TRACK_BUFFER, tagtree_buffer_event);
playback_add_event(PLAYBACK_EVENT_TRACK_FINISH, tagtree_track_finish_event);
}
static bool show_search_progress(bool init, int count)