diff options
-rw-r--r-- | apps/playback.c | 117 | ||||
-rw-r--r-- | apps/playback.h | 12 | ||||
-rw-r--r-- | apps/scrobbler.c | 4 | ||||
-rw-r--r-- | apps/tagtree.c | 6 |
4 files changed, 71 insertions, 68 deletions
diff --git a/apps/playback.c b/apps/playback.c index f757f4ae08..f66fd2954a 100644 --- a/apps/playback.c +++ b/apps/playback.c | |||
@@ -210,8 +210,6 @@ struct track_info { | |||
210 | size_t filesize; /* File total length */ | 210 | size_t filesize; /* File total length */ |
211 | 211 | ||
212 | bool taginfo_ready; /* Is metadata read */ | 212 | bool taginfo_ready; /* Is metadata read */ |
213 | |||
214 | bool event_sent; /* Was this track's buffered event sent */ | ||
215 | }; | 213 | }; |
216 | 214 | ||
217 | static struct track_info tracks[MAX_TRACK]; | 215 | 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 | |||
247 | */ | 245 | */ |
248 | static bool codec_requested_stop = false; | 246 | static bool codec_requested_stop = false; |
249 | 247 | ||
250 | /* Callbacks which applications or plugins may set */ | 248 | struct playback_event { |
251 | /* When the playing track has changed from the user's perspective */ | 249 | enum PLAYBACK_EVENT_TYPE type; |
252 | void (*track_changed_callback)(struct mp3entry *id3) = NULL; | 250 | void (*callback)(void *data); |
253 | /* When a track has been buffered */ | 251 | }; |
254 | void (*track_buffer_callback)(struct mp3entry *id3) = NULL; | 252 | |
255 | /* When a track's buffer has been overwritten or cleared */ | 253 | struct playback_event events[PLAYBACK_MAX_EVENTS]; |
256 | void (*track_unbuffer_callback)(struct mp3entry *id3) = NULL; | ||
257 | 254 | ||
258 | static size_t buffer_margin = 0; /* Buffer margin aka anti-skip buffer (A/C-) */ | 255 | static size_t buffer_margin = 0; /* Buffer margin aka anti-skip buffer (A/C-) */ |
259 | 256 | ||
@@ -352,11 +349,6 @@ static bool clear_track_info(struct track_info *track) | |||
352 | } | 349 | } |
353 | 350 | ||
354 | if (track->id3_hid >= 0) { | 351 | if (track->id3_hid >= 0) { |
355 | if (track->event_sent && track_unbuffer_callback) { | ||
356 | /* If there is an unbuffer callback, call it */ | ||
357 | track_unbuffer_callback(bufgetid3(track->id3_hid)); | ||
358 | } | ||
359 | |||
360 | if (bufclose(track->id3_hid)) | 352 | if (bufclose(track->id3_hid)) |
361 | track->id3_hid = -1; | 353 | track->id3_hid = -1; |
362 | else | 354 | else |
@@ -381,7 +373,6 @@ static bool clear_track_info(struct track_info *track) | |||
381 | 373 | ||
382 | track->filesize = 0; | 374 | track->filesize = 0; |
383 | track->taginfo_ready = false; | 375 | track->taginfo_ready = false; |
384 | track->event_sent = false; | ||
385 | 376 | ||
386 | return true; | 377 | return true; |
387 | } | 378 | } |
@@ -1456,6 +1447,51 @@ static void codec_thread(void) | |||
1456 | 1447 | ||
1457 | /* --- Audio thread --- */ | 1448 | /* --- Audio thread --- */ |
1458 | 1449 | ||
1450 | void playback_add_event(enum PLAYBACK_EVENT_TYPE type, void (*handler)) | ||
1451 | { | ||
1452 | int i; | ||
1453 | |||
1454 | /* Try to find a free slot. */ | ||
1455 | for (i = 0; i < PLAYBACK_MAX_EVENTS; i++) | ||
1456 | { | ||
1457 | if (events[i].callback == NULL) | ||
1458 | { | ||
1459 | events[i].type = type; | ||
1460 | events[i].callback = handler; | ||
1461 | return; | ||
1462 | } | ||
1463 | } | ||
1464 | |||
1465 | panicf("playback event line full"); | ||
1466 | } | ||
1467 | |||
1468 | void playback_remove_event(enum PLAYBACK_EVENT_TYPE type, void (*handler)) | ||
1469 | { | ||
1470 | int i; | ||
1471 | |||
1472 | for (i = 0; i < PLAYBACK_MAX_EVENTS; i++) | ||
1473 | { | ||
1474 | if (events[i].type == type && events[i].callback == handler) | ||
1475 | { | ||
1476 | events[i].callback = NULL; | ||
1477 | return; | ||
1478 | } | ||
1479 | } | ||
1480 | |||
1481 | panicf("playback event not found"); | ||
1482 | } | ||
1483 | |||
1484 | static void send_event(enum PLAYBACK_EVENT_TYPE type, void *data) | ||
1485 | { | ||
1486 | int i; | ||
1487 | |||
1488 | for (i = 0; i < PLAYBACK_MAX_EVENTS; i++) | ||
1489 | { | ||
1490 | if (events[i].type == type && events[i].callback != NULL) | ||
1491 | events[i].callback(data); | ||
1492 | } | ||
1493 | } | ||
1494 | |||
1459 | static bool audio_have_tracks(void) | 1495 | static bool audio_have_tracks(void) |
1460 | { | 1496 | { |
1461 | return (audio_track_count() != 0); | 1497 | return (audio_track_count() != 0); |
@@ -1546,7 +1582,7 @@ static void audio_clear_track_entries(bool clear_unbuffered) | |||
1546 | 1582 | ||
1547 | /* If the track is buffered, conditionally clear/notify, | 1583 | /* If the track is buffered, conditionally clear/notify, |
1548 | * otherwise clear the track if that option is selected */ | 1584 | * otherwise clear the track if that option is selected */ |
1549 | if (tracks[cur_idx].event_sent || clear_unbuffered) | 1585 | if (clear_unbuffered) |
1550 | clear_track_info(&tracks[cur_idx]); | 1586 | clear_track_info(&tracks[cur_idx]); |
1551 | } | 1587 | } |
1552 | } | 1588 | } |
@@ -1750,8 +1786,7 @@ static bool audio_load_track(int offset, bool start_play) | |||
1750 | { | 1786 | { |
1751 | if (get_metadata(&id3, fd, trackname)) | 1787 | if (get_metadata(&id3, fd, trackname)) |
1752 | { | 1788 | { |
1753 | if (track_buffer_callback) | 1789 | send_event(PLAYBACK_EVENT_TRACK_BUFFER, &id3); |
1754 | track_buffer_callback(&id3); | ||
1755 | 1790 | ||
1756 | tracks[track_widx].id3_hid = | 1791 | tracks[track_widx].id3_hid = |
1757 | bufalloc(&id3, sizeof(struct mp3entry), TYPE_ID3); | 1792 | bufalloc(&id3, sizeof(struct mp3entry), TYPE_ID3); |
@@ -1910,30 +1945,6 @@ static bool audio_load_track(int offset, bool start_play) | |||
1910 | return true; | 1945 | return true; |
1911 | } | 1946 | } |
1912 | 1947 | ||
1913 | /* Send callback events to notify about new tracks. */ | ||
1914 | static void audio_generate_postbuffer_events(void) | ||
1915 | { | ||
1916 | int cur_idx; | ||
1917 | |||
1918 | logf("Postbuffer:%d/%d",track_ridx,track_widx); | ||
1919 | |||
1920 | if (audio_have_tracks()) | ||
1921 | { | ||
1922 | cur_idx = track_ridx; | ||
1923 | |||
1924 | while (1) { | ||
1925 | if (!tracks[cur_idx].event_sent) | ||
1926 | { | ||
1927 | /* Mark the event 'sent' even if we don't really send one */ | ||
1928 | tracks[cur_idx].event_sent = true; | ||
1929 | } | ||
1930 | if (cur_idx == track_widx) | ||
1931 | break; | ||
1932 | cur_idx = (cur_idx + 1) & MAX_TRACK_MASK; | ||
1933 | } | ||
1934 | } | ||
1935 | } | ||
1936 | |||
1937 | static void audio_fill_file_buffer(bool start_play, size_t offset) | 1948 | static void audio_fill_file_buffer(bool start_play, size_t offset) |
1938 | { | 1949 | { |
1939 | struct queue_event ev; | 1950 | struct queue_event ev; |
@@ -1978,7 +1989,6 @@ static void audio_fill_file_buffer(bool start_play, size_t offset) | |||
1978 | if (!had_next_track && audio_next_track()) | 1989 | if (!had_next_track && audio_next_track()) |
1979 | track_changed = true; | 1990 | track_changed = true; |
1980 | 1991 | ||
1981 | audio_generate_postbuffer_events(); | ||
1982 | } | 1992 | } |
1983 | 1993 | ||
1984 | static void audio_rebuffer(void) | 1994 | static void audio_rebuffer(void) |
@@ -2012,6 +2022,9 @@ static int audio_check_new_track(void) | |||
2012 | bool forward; | 2022 | bool forward; |
2013 | bool end_of_playlist; /* Temporary flag, not the same as playlist_end */ | 2023 | bool end_of_playlist; /* Temporary flag, not the same as playlist_end */ |
2014 | 2024 | ||
2025 | /* Now it's good time to send track unbuffer events. */ | ||
2026 | send_event(PLAYBACK_EVENT_TRACK_FINISH, &curtrack_id3); | ||
2027 | |||
2015 | if (dir_skip) | 2028 | if (dir_skip) |
2016 | { | 2029 | { |
2017 | dir_skip = false; | 2030 | dir_skip = false; |
@@ -2173,21 +2186,6 @@ skip_done: | |||
2173 | return Q_CODEC_REQUEST_COMPLETE; | 2186 | return Q_CODEC_REQUEST_COMPLETE; |
2174 | } | 2187 | } |
2175 | 2188 | ||
2176 | void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3)) | ||
2177 | { | ||
2178 | track_buffer_callback = handler; | ||
2179 | } | ||
2180 | |||
2181 | void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3)) | ||
2182 | { | ||
2183 | track_unbuffer_callback = handler; | ||
2184 | } | ||
2185 | |||
2186 | void audio_set_track_changed_event(void (*handler)(struct mp3entry *id3)) | ||
2187 | { | ||
2188 | track_changed_callback = handler; | ||
2189 | } | ||
2190 | |||
2191 | unsigned long audio_prev_elapsed(void) | 2189 | unsigned long audio_prev_elapsed(void) |
2192 | { | 2190 | { |
2193 | return prev_track_elapsed; | 2191 | return prev_track_elapsed; |
@@ -2404,8 +2402,7 @@ static void audio_finalise_track_change(void) | |||
2404 | bufgetid3(prev_ti->id3_hid)->elapsed = 0; | 2402 | bufgetid3(prev_ti->id3_hid)->elapsed = 0; |
2405 | } | 2403 | } |
2406 | 2404 | ||
2407 | if (track_changed_callback) | 2405 | send_event(PLAYBACK_EVENT_TRACK_CHANGE, &curtrack_id3); |
2408 | track_changed_callback(&curtrack_id3); | ||
2409 | 2406 | ||
2410 | track_changed = true; | 2407 | track_changed = true; |
2411 | playlist_update_resume_info(audio_current_track()); | 2408 | playlist_update_resume_info(audio_current_track()); |
diff --git a/apps/playback.h b/apps/playback.h index b005e63b3c..13a959a0ca 100644 --- a/apps/playback.h +++ b/apps/playback.h | |||
@@ -39,11 +39,17 @@ | |||
39 | 39 | ||
40 | #define MAX_TRACK_MASK (MAX_TRACK-1) | 40 | #define MAX_TRACK_MASK (MAX_TRACK-1) |
41 | 41 | ||
42 | #define PLAYBACK_MAX_EVENTS 4 | ||
43 | enum PLAYBACK_EVENT_TYPE { | ||
44 | PLAYBACK_EVENT_TRACK_BUFFER, | ||
45 | PLAYBACK_EVENT_TRACK_FINISH, | ||
46 | PLAYBACK_EVENT_TRACK_CHANGE, | ||
47 | }; | ||
48 | |||
42 | /* Functions */ | 49 | /* Functions */ |
43 | const char * get_codec_filename(int cod_spec); | 50 | const char * get_codec_filename(int cod_spec); |
44 | void audio_set_track_changed_event(void (*handler)(struct mp3entry *id3)); | 51 | void playback_add_event(enum PLAYBACK_EVENT_TYPE type, void (*handler)); |
45 | void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3)); | 52 | void playback_remove_event(enum PLAYBACK_EVENT_TYPE type, void (*handler)); |
46 | void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3)); | ||
47 | void voice_wait(void); | 53 | void voice_wait(void); |
48 | 54 | ||
49 | #if CONFIG_CODEC == SWCODEC /* This #ifdef is better here than gui/gwps.c */ | 55 | #if CONFIG_CODEC == SWCODEC /* This #ifdef is better here than gui/gwps.c */ |
diff --git a/apps/scrobbler.c b/apps/scrobbler.c index 01c704afab..6398fd1741 100644 --- a/apps/scrobbler.c +++ b/apps/scrobbler.c | |||
@@ -224,7 +224,7 @@ int scrobbler_init(void) | |||
224 | 224 | ||
225 | scrobbler_cache = buffer_alloc(SCROBBLER_MAX_CACHE*SCROBBLER_CACHE_LEN); | 225 | scrobbler_cache = buffer_alloc(SCROBBLER_MAX_CACHE*SCROBBLER_CACHE_LEN); |
226 | 226 | ||
227 | audio_set_track_changed_event(&scrobbler_change_event); | 227 | playback_add_event(PLAYBACK_EVENT_TRACK_CHANGE, scrobbler_change_event); |
228 | cache_pos = 0; | 228 | cache_pos = 0; |
229 | pending = false; | 229 | pending = false; |
230 | scrobbler_initialised = true; | 230 | scrobbler_initialised = true; |
@@ -259,7 +259,7 @@ void scrobbler_shutdown(void) | |||
259 | 259 | ||
260 | if (scrobbler_initialised) | 260 | if (scrobbler_initialised) |
261 | { | 261 | { |
262 | audio_set_track_changed_event(NULL); | 262 | playback_remove_event(PLAYBACK_EVENT_TRACK_CHANGE, scrobbler_change_event); |
263 | scrobbler_initialised = false; | 263 | scrobbler_initialised = false; |
264 | } | 264 | } |
265 | } | 265 | } |
diff --git a/apps/tagtree.c b/apps/tagtree.c index 17401f3fbb..86aa8069c7 100644 --- a/apps/tagtree.c +++ b/apps/tagtree.c | |||
@@ -660,7 +660,7 @@ static void tagtree_buffer_event(struct mp3entry *id3) | |||
660 | tagcache_search_finish(&tcs); | 660 | tagcache_search_finish(&tcs); |
661 | } | 661 | } |
662 | 662 | ||
663 | static void tagtree_unbuffer_event(struct mp3entry *id3) | 663 | static void tagtree_track_finish_event(struct mp3entry *id3) |
664 | { | 664 | { |
665 | long playcount; | 665 | long playcount; |
666 | long playtime; | 666 | long playtime; |
@@ -924,8 +924,8 @@ void tagtree_init(void) | |||
924 | root_menu = 0; | 924 | root_menu = 0; |
925 | 925 | ||
926 | uniqbuf = buffer_alloc(UNIQBUF_SIZE); | 926 | uniqbuf = buffer_alloc(UNIQBUF_SIZE); |
927 | audio_set_track_buffer_event(tagtree_buffer_event); | 927 | playback_add_event(PLAYBACK_EVENT_TRACK_BUFFER, tagtree_buffer_event); |
928 | audio_set_track_unbuffer_event(tagtree_unbuffer_event); | 928 | playback_add_event(PLAYBACK_EVENT_TRACK_FINISH, tagtree_track_finish_event); |
929 | } | 929 | } |
930 | 930 | ||
931 | static bool show_search_progress(bool init, int count) | 931 | static bool show_search_progress(bool init, int count) |