diff options
-rw-r--r-- | apps/abrepeat.c | 6 | ||||
-rw-r--r-- | apps/pcmbuf.c | 13 | ||||
-rw-r--r-- | apps/playback.c | 52 | ||||
-rw-r--r-- | firmware/export/audio.h | 1 | ||||
-rw-r--r-- | firmware/pcm_playback.c | 2 |
5 files changed, 29 insertions, 45 deletions
diff --git a/apps/abrepeat.c b/apps/abrepeat.c index b83a7b6aa3..fc1913d37b 100644 --- a/apps/abrepeat.c +++ b/apps/abrepeat.c | |||
@@ -111,13 +111,13 @@ reasonable amount of time for the typical user to react */ | |||
111 | 111 | ||
112 | void ab_jump_to_A_marker(void) | 112 | void ab_jump_to_A_marker(void) |
113 | { | 113 | { |
114 | #if (CONFIG_CODEC == SWCODEC) | 114 | #if (CONFIG_CODEC != SWCODEC) |
115 | audio_seamless_seek(ab_A_marker); | ||
116 | #else | ||
117 | bool paused = (audio_status() & AUDIO_STATUS_PAUSE) != 0; | 115 | bool paused = (audio_status() & AUDIO_STATUS_PAUSE) != 0; |
118 | if ( ! paused ) | 116 | if ( ! paused ) |
119 | audio_pause(); | 117 | audio_pause(); |
118 | #endif | ||
120 | audio_ff_rewind(ab_A_marker); | 119 | audio_ff_rewind(ab_A_marker); |
120 | #if (CONFIG_CODEC != SWCODEC) | ||
121 | if ( ! paused ) | 121 | if ( ! paused ) |
122 | audio_resume(); | 122 | audio_resume(); |
123 | #endif | 123 | #endif |
diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c index c0791987ce..7a261fecbe 100644 --- a/apps/pcmbuf.c +++ b/apps/pcmbuf.c | |||
@@ -61,8 +61,6 @@ static bool crossfade_init IDATA_ATTR; | |||
61 | static size_t crossfade_pos IDATA_ATTR; | 61 | static size_t crossfade_pos IDATA_ATTR; |
62 | static size_t crossfade_rem IDATA_ATTR; | 62 | static size_t crossfade_rem IDATA_ATTR; |
63 | 63 | ||
64 | static struct mutex pcmbuf_mutex IDATA_ATTR; | ||
65 | |||
66 | /* Crossfade modes. If CFM_CROSSFADE is selected, normal | 64 | /* Crossfade modes. If CFM_CROSSFADE is selected, normal |
67 | * crossfader will activate. Selecting CFM_FLUSH is a special | 65 | * crossfader will activate. Selecting CFM_FLUSH is a special |
68 | * operation that only overwrites the pcm buffer without crossfading. | 66 | * operation that only overwrites the pcm buffer without crossfading. |
@@ -297,7 +295,6 @@ bool pcmbuf_crossfade_init(bool manual_skip) | |||
297 | 295 | ||
298 | void pcmbuf_play_stop(void) | 296 | void pcmbuf_play_stop(void) |
299 | { | 297 | { |
300 | mutex_lock(&pcmbuf_mutex); | ||
301 | /** Prevent a very tiny pop from happening by muting audio | 298 | /** Prevent a very tiny pop from happening by muting audio |
302 | * until dma has been initialized. */ | 299 | * until dma has been initialized. */ |
303 | pcm_mute(true); | 300 | pcm_mute(true); |
@@ -320,7 +317,6 @@ void pcmbuf_play_stop(void) | |||
320 | pcmbuf_set_boost_mode(false); | 317 | pcmbuf_set_boost_mode(false); |
321 | pcmbuf_boost(false); | 318 | pcmbuf_boost(false); |
322 | 319 | ||
323 | mutex_unlock(&pcmbuf_mutex); | ||
324 | } | 320 | } |
325 | 321 | ||
326 | int pcmbuf_used_descs(void) { | 322 | int pcmbuf_used_descs(void) { |
@@ -356,7 +352,6 @@ static void pcmbuf_init_pcmbuffers(void) { | |||
356 | * ...CODECBUFFER|---------PCMBUF---------|GUARDBUF|DESCS| */ | 352 | * ...CODECBUFFER|---------PCMBUF---------|GUARDBUF|DESCS| */ |
357 | void pcmbuf_init(size_t bufsize) | 353 | void pcmbuf_init(size_t bufsize) |
358 | { | 354 | { |
359 | mutex_init(&pcmbuf_mutex); | ||
360 | pcmbuf_size = bufsize; | 355 | pcmbuf_size = bufsize; |
361 | pcmbuf_descsize = pcmbuf_descs()*sizeof(struct pcmbufdesc); | 356 | pcmbuf_descsize = pcmbuf_descs()*sizeof(struct pcmbufdesc); |
362 | audiobuffer = (char *)&audiobuf[(audiobufend - audiobuf) - | 357 | audiobuffer = (char *)&audiobuf[(audiobufend - audiobuf) - |
@@ -401,8 +396,6 @@ void pcmbuf_pause(bool pause) { | |||
401 | /* Force playback. */ | 396 | /* Force playback. */ |
402 | void pcmbuf_play_start(void) | 397 | void pcmbuf_play_start(void) |
403 | { | 398 | { |
404 | mutex_lock(&pcmbuf_mutex); | ||
405 | |||
406 | if (!pcm_is_playing() && pcmbuf_unplayed_bytes) | 399 | if (!pcm_is_playing() && pcmbuf_unplayed_bytes) |
407 | { | 400 | { |
408 | /** Prevent a very tiny pop from happening by muting audio | 401 | /** Prevent a very tiny pop from happening by muting audio |
@@ -417,8 +410,6 @@ void pcmbuf_play_start(void) | |||
417 | /* Now unmute the audio. */ | 410 | /* Now unmute the audio. */ |
418 | pcm_mute(false); | 411 | pcm_mute(false); |
419 | } | 412 | } |
420 | |||
421 | mutex_unlock(&pcmbuf_mutex); | ||
422 | } | 413 | } |
423 | 414 | ||
424 | /** | 415 | /** |
@@ -426,8 +417,6 @@ void pcmbuf_play_start(void) | |||
426 | */ | 417 | */ |
427 | static void pcmbuf_flush_fillpos(void) | 418 | static void pcmbuf_flush_fillpos(void) |
428 | { | 419 | { |
429 | mutex_lock(&pcmbuf_mutex); | ||
430 | |||
431 | if (audiobuffer_fillpos) { | 420 | if (audiobuffer_fillpos) { |
432 | /* Never use the last buffer descriptor */ | 421 | /* Never use the last buffer descriptor */ |
433 | while (pcmbuf_write == pcmbuf_write_end) { | 422 | while (pcmbuf_write == pcmbuf_write_end) { |
@@ -444,8 +433,6 @@ static void pcmbuf_flush_fillpos(void) | |||
444 | } | 433 | } |
445 | pcmbuf_add_chunk(); | 434 | pcmbuf_add_chunk(); |
446 | } | 435 | } |
447 | |||
448 | mutex_unlock(&pcmbuf_mutex); | ||
449 | } | 436 | } |
450 | 437 | ||
451 | /** | 438 | /** |
diff --git a/apps/playback.c b/apps/playback.c index 9f8fc5a71b..aa48dd9bae 100644 --- a/apps/playback.c +++ b/apps/playback.c | |||
@@ -70,6 +70,7 @@ | |||
70 | static volatile bool audio_codec_loaded; | 70 | static volatile bool audio_codec_loaded; |
71 | static volatile bool voice_codec_loaded; | 71 | static volatile bool voice_codec_loaded; |
72 | static volatile bool playing; | 72 | static volatile bool playing; |
73 | static volatile bool seeking; | ||
73 | 74 | ||
74 | #define CODEC_VORBIS "/.rockbox/codecs/vorbis.codec" | 75 | #define CODEC_VORBIS "/.rockbox/codecs/vorbis.codec" |
75 | #define CODEC_MPA_L3 "/.rockbox/codecs/mpa.codec" | 76 | #define CODEC_MPA_L3 "/.rockbox/codecs/mpa.codec" |
@@ -102,7 +103,6 @@ enum { | |||
102 | Q_AUDIO_TRACK_CHANGED, | 103 | Q_AUDIO_TRACK_CHANGED, |
103 | Q_AUDIO_DIR_NEXT, | 104 | Q_AUDIO_DIR_NEXT, |
104 | Q_AUDIO_DIR_PREV, | 105 | Q_AUDIO_DIR_PREV, |
105 | Q_AUDIO_SEAMLESS_SEEK, | ||
106 | Q_AUDIO_POSTINIT, | 106 | Q_AUDIO_POSTINIT, |
107 | 107 | ||
108 | Q_CODEC_LOAD, | 108 | Q_CODEC_LOAD, |
@@ -679,7 +679,12 @@ off_t codec_mp3_get_filepos_callback(int newtime) | |||
679 | void codec_seek_complete_callback(void) | 679 | void codec_seek_complete_callback(void) |
680 | { | 680 | { |
681 | /* assume we're called from non-voice codec, as they shouldn't seek */ | 681 | /* assume we're called from non-voice codec, as they shouldn't seek */ |
682 | if (pcm_is_paused()) { | ||
683 | /* If this is not a seamless seek, clear the buffer */ | ||
684 | pcmbuf_play_stop(); | ||
685 | } | ||
682 | ci.seek_time = 0; | 686 | ci.seek_time = 0; |
687 | seeking = false; | ||
683 | } | 688 | } |
684 | 689 | ||
685 | bool codec_seek_buffer_callback(size_t newpos) | 690 | bool codec_seek_buffer_callback(size_t newpos) |
@@ -1329,10 +1334,10 @@ static void audio_clear_track_entries(bool buffered_only) | |||
1329 | static void stop_codec_flush(void) | 1334 | static void stop_codec_flush(void) |
1330 | { | 1335 | { |
1331 | ci.stop_codec = true; | 1336 | ci.stop_codec = true; |
1332 | pcmbuf_play_stop(); | 1337 | pcmbuf_pause(true); |
1333 | while (audio_codec_loaded) | 1338 | while (audio_codec_loaded) |
1334 | yield(); | 1339 | yield(); |
1335 | pcmbuf_play_stop(); | 1340 | pcmbuf_pause(false); |
1336 | } | 1341 | } |
1337 | 1342 | ||
1338 | static void audio_stop_playback(bool resume) | 1343 | static void audio_stop_playback(bool resume) |
@@ -1343,7 +1348,6 @@ static void audio_stop_playback(bool resume) | |||
1343 | playing = false; | 1348 | playing = false; |
1344 | filling = false; | 1349 | filling = false; |
1345 | stop_codec_flush(); | 1350 | stop_codec_flush(); |
1346 | pcmbuf_pause(false); | ||
1347 | if (current_fd >= 0) { | 1351 | if (current_fd >= 0) { |
1348 | close(current_fd); | 1352 | close(current_fd); |
1349 | current_fd = -1; | 1353 | current_fd = -1; |
@@ -1768,11 +1772,11 @@ static void initiate_track_change(int peek_index) | |||
1768 | { | 1772 | { |
1769 | /* Detect if disk is spinning or already loading. */ | 1773 | /* Detect if disk is spinning or already loading. */ |
1770 | if (filling || ci.reload_codec || !audio_codec_loaded) { | 1774 | if (filling || ci.reload_codec || !audio_codec_loaded) { |
1771 | if (pcmbuf_is_crossfade_enabled()) | 1775 | if (pcmbuf_is_crossfade_enabled()) { |
1772 | pcmbuf_crossfade_init(true); | 1776 | pcmbuf_crossfade_init(true); |
1773 | else | 1777 | ci.stop_codec = true; |
1774 | pcmbuf_play_stop(); | 1778 | } else |
1775 | ci.stop_codec = true; | 1779 | stop_codec_flush(); |
1776 | queue_post(&audio_queue, Q_AUDIO_PLAY, 0); | 1780 | queue_post(&audio_queue, Q_AUDIO_PLAY, 0); |
1777 | } else { | 1781 | } else { |
1778 | new_track = peek_index; | 1782 | new_track = peek_index; |
@@ -1836,10 +1840,6 @@ void audio_thread(void) | |||
1836 | play_pending = false; | 1840 | play_pending = false; |
1837 | last_tick = current_tick; | 1841 | last_tick = current_tick; |
1838 | 1842 | ||
1839 | /* Do not start crossfading if audio is paused. */ | ||
1840 | if (pcm_is_paused()) | ||
1841 | pcmbuf_play_stop(); | ||
1842 | |||
1843 | #ifdef CONFIG_TUNER | 1843 | #ifdef CONFIG_TUNER |
1844 | /* check if radio is playing */ | 1844 | /* check if radio is playing */ |
1845 | if (get_radio_status() != FMRADIO_OFF) { | 1845 | if (get_radio_status() != FMRADIO_OFF) { |
@@ -1848,6 +1848,7 @@ void audio_thread(void) | |||
1848 | #endif | 1848 | #endif |
1849 | 1849 | ||
1850 | logf("starting..."); | 1850 | logf("starting..."); |
1851 | |||
1851 | playing = true; | 1852 | playing = true; |
1852 | ci.stop_codec = true; | 1853 | ci.stop_codec = true; |
1853 | ci.reload_codec = false; | 1854 | ci.reload_codec = false; |
@@ -1898,19 +1899,13 @@ void audio_thread(void) | |||
1898 | case Q_AUDIO_FF_REWIND: | 1899 | case Q_AUDIO_FF_REWIND: |
1899 | if (!playing) | 1900 | if (!playing) |
1900 | break ; | 1901 | break ; |
1901 | pcmbuf_play_stop(); | ||
1902 | ci.seek_time = (long)ev.data+1; | ||
1903 | break ; | ||
1904 | |||
1905 | case Q_AUDIO_SEAMLESS_SEEK: | ||
1906 | if (!playing) | ||
1907 | break ; | ||
1908 | ci.seek_time = (long)ev.data+1; | 1902 | ci.seek_time = (long)ev.data+1; |
1909 | break ; | 1903 | break ; |
1910 | 1904 | ||
1911 | case Q_AUDIO_DIR_NEXT: | 1905 | case Q_AUDIO_DIR_NEXT: |
1912 | logf("audio_dir_next"); | 1906 | logf("audio_dir_next"); |
1913 | playlist_end = false; | 1907 | playlist_end = false; |
1908 | /* pcmbuf_beep may or may not be safe on audio thread */ | ||
1914 | if (global_settings.beep) | 1909 | if (global_settings.beep) |
1915 | pcmbuf_beep(5000, 100, 2500*global_settings.beep); | 1910 | pcmbuf_beep(5000, 100, 2500*global_settings.beep); |
1916 | initiate_dir_change(1); | 1911 | initiate_dir_change(1); |
@@ -1919,6 +1914,7 @@ void audio_thread(void) | |||
1919 | case Q_AUDIO_DIR_PREV: | 1914 | case Q_AUDIO_DIR_PREV: |
1920 | logf("audio_dir_prev"); | 1915 | logf("audio_dir_prev"); |
1921 | playlist_end = false; | 1916 | playlist_end = false; |
1917 | /* pcmbuf_beep may or may not be safe on audio thread */ | ||
1922 | if (global_settings.beep) | 1918 | if (global_settings.beep) |
1923 | pcmbuf_beep(5000, 100, 2500*global_settings.beep); | 1919 | pcmbuf_beep(5000, 100, 2500*global_settings.beep); |
1924 | initiate_dir_change(-1); | 1920 | initiate_dir_change(-1); |
@@ -2010,6 +2006,9 @@ void codec_thread(void) | |||
2010 | #endif | 2006 | #endif |
2011 | } | 2007 | } |
2012 | 2008 | ||
2009 | if (ci.stop_codec && pcm_is_paused()) | ||
2010 | pcmbuf_play_stop(); | ||
2011 | |||
2013 | audio_codec_loaded = false; | 2012 | audio_codec_loaded = false; |
2014 | 2013 | ||
2015 | switch (ev.id) { | 2014 | switch (ev.id) { |
@@ -2191,7 +2190,6 @@ void audio_play(long offset) | |||
2191 | else | 2190 | else |
2192 | { | 2191 | { |
2193 | stop_codec_flush(); | 2192 | stop_codec_flush(); |
2194 | pcmbuf_play_stop(); | ||
2195 | } | 2193 | } |
2196 | 2194 | ||
2197 | queue_post(&audio_queue, Q_AUDIO_PLAY, (void *)offset); | 2195 | queue_post(&audio_queue, Q_AUDIO_PLAY, (void *)offset); |
@@ -2268,14 +2266,14 @@ void audio_prev_dir(void) | |||
2268 | 2266 | ||
2269 | void audio_ff_rewind(long newpos) | 2267 | void audio_ff_rewind(long newpos) |
2270 | { | 2268 | { |
2271 | logf("rewind: %d", newpos); | 2269 | logf("ff/rewind: %d", newpos); |
2270 | seeking = true; | ||
2272 | queue_post(&audio_queue, Q_AUDIO_FF_REWIND, (int *)newpos); | 2271 | queue_post(&audio_queue, Q_AUDIO_FF_REWIND, (int *)newpos); |
2273 | } | 2272 | /* This is a hack, the correct solution is to report back to |
2274 | 2273 | * the caller when the seek is complete. */ | |
2275 | void audio_seamless_seek(long newpos) | 2274 | while (seeking) { |
2276 | { | 2275 | yield(); |
2277 | logf("seamless_seek: %d", newpos); | 2276 | } |
2278 | queue_post(&audio_queue, Q_AUDIO_SEAMLESS_SEEK, (int *)newpos); | ||
2279 | } | 2277 | } |
2280 | 2278 | ||
2281 | void audio_flush_and_reload_tracks(void) | 2279 | void audio_flush_and_reload_tracks(void) |
diff --git a/firmware/export/audio.h b/firmware/export/audio.h index 62dec73078..d1421ce9a3 100644 --- a/firmware/export/audio.h +++ b/firmware/export/audio.h | |||
@@ -71,7 +71,6 @@ void audio_next(void); | |||
71 | void audio_prev(void); | 71 | void audio_prev(void); |
72 | int audio_status(void); | 72 | int audio_status(void); |
73 | void audio_ff_rewind(long newtime); | 73 | void audio_ff_rewind(long newtime); |
74 | void audio_seamless_seek(long newtime); | ||
75 | void audio_flush_and_reload_tracks(void); | 74 | void audio_flush_and_reload_tracks(void); |
76 | struct mp3entry* audio_current_track(void); | 75 | struct mp3entry* audio_current_track(void); |
77 | struct mp3entry* audio_next_track(void); | 76 | struct mp3entry* audio_next_track(void); |
diff --git a/firmware/pcm_playback.c b/firmware/pcm_playback.c index d6dc41cdde..8210276c48 100644 --- a/firmware/pcm_playback.c +++ b/firmware/pcm_playback.c | |||
@@ -638,7 +638,7 @@ void pcm_play_pause(bool play) | |||
638 | /* nothing yet */ | 638 | /* nothing yet */ |
639 | #endif | 639 | #endif |
640 | } | 640 | } |
641 | } | 641 | } /* pcm_playing && needs_change */ |
642 | } | 642 | } |
643 | 643 | ||
644 | bool pcm_is_playing(void) { | 644 | bool pcm_is_playing(void) { |