diff options
Diffstat (limited to 'apps/playback.c')
-rw-r--r-- | apps/playback.c | 117 |
1 files changed, 57 insertions, 60 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()); |