summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/abrepeat.c6
-rw-r--r--apps/pcmbuf.c13
-rw-r--r--apps/playback.c52
-rw-r--r--firmware/export/audio.h1
-rw-r--r--firmware/pcm_playback.c2
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 */
void ab_jump_to_A_marker(void)
{
-#if (CONFIG_CODEC == SWCODEC)
- audio_seamless_seek(ab_A_marker);
-#else
+#if (CONFIG_CODEC != SWCODEC)
bool paused = (audio_status() & AUDIO_STATUS_PAUSE) != 0;
if ( ! paused )
audio_pause();
+#endif
audio_ff_rewind(ab_A_marker);
+#if (CONFIG_CODEC != SWCODEC)
if ( ! paused )
audio_resume();
#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;
static size_t crossfade_pos IDATA_ATTR;
static size_t crossfade_rem IDATA_ATTR;
-static struct mutex pcmbuf_mutex IDATA_ATTR;
-
/* Crossfade modes. If CFM_CROSSFADE is selected, normal
* crossfader will activate. Selecting CFM_FLUSH is a special
* operation that only overwrites the pcm buffer without crossfading.
@@ -297,7 +295,6 @@ bool pcmbuf_crossfade_init(bool manual_skip)
void pcmbuf_play_stop(void)
{
- mutex_lock(&pcmbuf_mutex);
/** Prevent a very tiny pop from happening by muting audio
* until dma has been initialized. */
pcm_mute(true);
@@ -320,7 +317,6 @@ void pcmbuf_play_stop(void)
pcmbuf_set_boost_mode(false);
pcmbuf_boost(false);
- mutex_unlock(&pcmbuf_mutex);
}
int pcmbuf_used_descs(void) {
@@ -356,7 +352,6 @@ static void pcmbuf_init_pcmbuffers(void) {
* ...CODECBUFFER|---------PCMBUF---------|GUARDBUF|DESCS| */
void pcmbuf_init(size_t bufsize)
{
- mutex_init(&pcmbuf_mutex);
pcmbuf_size = bufsize;
pcmbuf_descsize = pcmbuf_descs()*sizeof(struct pcmbufdesc);
audiobuffer = (char *)&audiobuf[(audiobufend - audiobuf) -
@@ -401,8 +396,6 @@ void pcmbuf_pause(bool pause) {
/* Force playback. */
void pcmbuf_play_start(void)
{
- mutex_lock(&pcmbuf_mutex);
-
if (!pcm_is_playing() && pcmbuf_unplayed_bytes)
{
/** Prevent a very tiny pop from happening by muting audio
@@ -417,8 +410,6 @@ void pcmbuf_play_start(void)
/* Now unmute the audio. */
pcm_mute(false);
}
-
- mutex_unlock(&pcmbuf_mutex);
}
/**
@@ -426,8 +417,6 @@ void pcmbuf_play_start(void)
*/
static void pcmbuf_flush_fillpos(void)
{
- mutex_lock(&pcmbuf_mutex);
-
if (audiobuffer_fillpos) {
/* Never use the last buffer descriptor */
while (pcmbuf_write == pcmbuf_write_end) {
@@ -444,8 +433,6 @@ static void pcmbuf_flush_fillpos(void)
}
pcmbuf_add_chunk();
}
-
- mutex_unlock(&pcmbuf_mutex);
}
/**
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 @@
static volatile bool audio_codec_loaded;
static volatile bool voice_codec_loaded;
static volatile bool playing;
+static volatile bool seeking;
#define CODEC_VORBIS "/.rockbox/codecs/vorbis.codec"
#define CODEC_MPA_L3 "/.rockbox/codecs/mpa.codec"
@@ -102,7 +103,6 @@ enum {
Q_AUDIO_TRACK_CHANGED,
Q_AUDIO_DIR_NEXT,
Q_AUDIO_DIR_PREV,
- Q_AUDIO_SEAMLESS_SEEK,
Q_AUDIO_POSTINIT,
Q_CODEC_LOAD,
@@ -679,7 +679,12 @@ off_t codec_mp3_get_filepos_callback(int newtime)
void codec_seek_complete_callback(void)
{
/* assume we're called from non-voice codec, as they shouldn't seek */
+ if (pcm_is_paused()) {
+ /* If this is not a seamless seek, clear the buffer */
+ pcmbuf_play_stop();
+ }
ci.seek_time = 0;
+ seeking = false;
}
bool codec_seek_buffer_callback(size_t newpos)
@@ -1329,10 +1334,10 @@ static void audio_clear_track_entries(bool buffered_only)
static void stop_codec_flush(void)
{
ci.stop_codec = true;
- pcmbuf_play_stop();
+ pcmbuf_pause(true);
while (audio_codec_loaded)
yield();
- pcmbuf_play_stop();
+ pcmbuf_pause(false);
}
static void audio_stop_playback(bool resume)
@@ -1343,7 +1348,6 @@ static void audio_stop_playback(bool resume)
playing = false;
filling = false;
stop_codec_flush();
- pcmbuf_pause(false);
if (current_fd >= 0) {
close(current_fd);
current_fd = -1;
@@ -1768,11 +1772,11 @@ static void initiate_track_change(int peek_index)
{
/* Detect if disk is spinning or already loading. */
if (filling || ci.reload_codec || !audio_codec_loaded) {
- if (pcmbuf_is_crossfade_enabled())
+ if (pcmbuf_is_crossfade_enabled()) {
pcmbuf_crossfade_init(true);
- else
- pcmbuf_play_stop();
- ci.stop_codec = true;
+ ci.stop_codec = true;
+ } else
+ stop_codec_flush();
queue_post(&audio_queue, Q_AUDIO_PLAY, 0);
} else {
new_track = peek_index;
@@ -1836,10 +1840,6 @@ void audio_thread(void)
play_pending = false;
last_tick = current_tick;
- /* Do not start crossfading if audio is paused. */
- if (pcm_is_paused())
- pcmbuf_play_stop();
-
#ifdef CONFIG_TUNER
/* check if radio is playing */
if (get_radio_status() != FMRADIO_OFF) {
@@ -1848,6 +1848,7 @@ void audio_thread(void)
#endif
logf("starting...");
+
playing = true;
ci.stop_codec = true;
ci.reload_codec = false;
@@ -1898,19 +1899,13 @@ void audio_thread(void)
case Q_AUDIO_FF_REWIND:
if (!playing)
break ;
- pcmbuf_play_stop();
- ci.seek_time = (long)ev.data+1;
- break ;
-
- case Q_AUDIO_SEAMLESS_SEEK:
- if (!playing)
- break ;
ci.seek_time = (long)ev.data+1;
break ;
case Q_AUDIO_DIR_NEXT:
logf("audio_dir_next");
playlist_end = false;
+ /* pcmbuf_beep may or may not be safe on audio thread */
if (global_settings.beep)
pcmbuf_beep(5000, 100, 2500*global_settings.beep);
initiate_dir_change(1);
@@ -1919,6 +1914,7 @@ void audio_thread(void)
case Q_AUDIO_DIR_PREV:
logf("audio_dir_prev");
playlist_end = false;
+ /* pcmbuf_beep may or may not be safe on audio thread */
if (global_settings.beep)
pcmbuf_beep(5000, 100, 2500*global_settings.beep);
initiate_dir_change(-1);
@@ -2010,6 +2006,9 @@ void codec_thread(void)
#endif
}
+ if (ci.stop_codec && pcm_is_paused())
+ pcmbuf_play_stop();
+
audio_codec_loaded = false;
switch (ev.id) {
@@ -2191,7 +2190,6 @@ void audio_play(long offset)
else
{
stop_codec_flush();
- pcmbuf_play_stop();
}
queue_post(&audio_queue, Q_AUDIO_PLAY, (void *)offset);
@@ -2268,14 +2266,14 @@ void audio_prev_dir(void)
void audio_ff_rewind(long newpos)
{
- logf("rewind: %d", newpos);
+ logf("ff/rewind: %d", newpos);
+ seeking = true;
queue_post(&audio_queue, Q_AUDIO_FF_REWIND, (int *)newpos);
-}
-
-void audio_seamless_seek(long newpos)
-{
- logf("seamless_seek: %d", newpos);
- queue_post(&audio_queue, Q_AUDIO_SEAMLESS_SEEK, (int *)newpos);
+ /* This is a hack, the correct solution is to report back to
+ * the caller when the seek is complete. */
+ while (seeking) {
+ yield();
+ }
}
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);
void audio_prev(void);
int audio_status(void);
void audio_ff_rewind(long newtime);
-void audio_seamless_seek(long newtime);
void audio_flush_and_reload_tracks(void);
struct mp3entry* audio_current_track(void);
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)
/* nothing yet */
#endif
}
- }
+ } /* pcm_playing && needs_change */
}
bool pcm_is_playing(void) {