summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiika Pekkarinen <miipekk@ihme.org>2008-03-07 22:56:51 +0000
committerMiika Pekkarinen <miipekk@ihme.org>2008-03-07 22:56:51 +0000
commit2ccdc48ee943f1506809e94df990873cb937bd1a (patch)
tree1b365168ad24fc74c935a4eeaefcdf30f793c854
parentaafa321d31c0dab631a5e0a70a0d8798368169f4 (diff)
downloadrockbox-2ccdc48ee943f1506809e94df990873cb937bd1a.zip
rockbox-2ccdc48ee943f1506809e94df990873cb937bd1a.tar.gz
rockbox-2ccdc48ee943f1506809e94df990873cb937bd1a.tar.bz2
rockbox-2ccdc48ee943f1506809e94df990873cb937bd1a.tar.xz
Rewritten playback event handling. Should fix runtime statistics gathering.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16546 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/playback.c117
-rw-r--r--apps/playback.h12
-rw-r--r--apps/scrobbler.c4
-rw-r--r--apps/tagtree.c6
4 files changed, 71 insertions, 68 deletions
diff --git a/apps/playback.c b/apps/playback.c
index f757f4a..f66fd29 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -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());
diff --git a/apps/playback.h b/apps/playback.h
index b005e63..13a959a 100644
--- a/apps/playback.h
+++ b/apps/playback.h
@@ -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 */
diff --git a/apps/scrobbler.c b/apps/scrobbler.c
index 01c704a..6398fd1 100644
--- a/apps/scrobbler.c
+++ b/apps/scrobbler.c
@@ -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;
}
}
diff --git a/apps/tagtree.c b/apps/tagtree.c
index 17401f3..86aa806 100644
--- a/apps/tagtree.c
+++ b/apps/tagtree.c
@@ -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)