summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorroman.artiukhin <bahusdrive@gmail.com>2023-10-02 19:19:09 +0300
committerAidan MacDonald <amachronic@protonmail.com>2023-10-28 15:11:07 -0400
commit831faa3b82a8c3bfb3241e60641bf783adba4d4a (patch)
tree622e87637e0ef3fab652e053b22b1f8fd7f20fa7
parent90e35716e312b9446515263f75e9e7cb66483c2c (diff)
downloadrockbox-831faa3b82.tar.gz
rockbox-831faa3b82.zip
Rework auto playback frequency switch
Moved logic outside playback events to be executed early. Stops buffering when frequency change is detected (additional STATE_STOPPED state is introduced) Removed no longer used AUDIO_START_REFRESH flag Change-Id: Icfae61725a4d8ffb47380f561a011bda4841457b
-rw-r--r--apps/playback.c102
-rw-r--r--firmware/pcm.c4
2 files changed, 54 insertions, 52 deletions
diff --git a/apps/playback.c b/apps/playback.c
index c61fd9d399..ad7075eaf9 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -202,6 +202,7 @@ static enum filling_state
STATE_FINISHED, /* all remaining tracks are fully buffered */
STATE_ENDING, /* audio playback is ending */
STATE_ENDED, /* audio playback is done */
+ STATE_STOPPED, /* buffering is stopped explicitly */
} filling = STATE_IDLE;
/* Track info - holds information about each track in the buffer */
@@ -349,7 +350,6 @@ enum audio_start_playback_flags
{
AUDIO_START_RESTART = 0x1, /* "Restart" playback (flush _all_ tracks) */
AUDIO_START_NEWBUF = 0x2, /* Mark the audiobuffer as invalid */
- AUDIO_START_REFRESH = 0x80
};
static void audio_start_playback(const struct audio_resume_info *resume_info,
@@ -2055,6 +2055,10 @@ static int audio_load_track(void)
return LOAD_TRACK_OK;
}
+#ifdef HAVE_PLAY_FREQ
+static bool audio_auto_change_frequency(struct mp3entry *id3, bool play);
+#endif
+
/* Second part of the track loading: We now have the metadata available, so we
can load the codec, the album art and finally the audio data.
This is called on the audio thread after the buffering thread calls the
@@ -2087,6 +2091,24 @@ static int audio_finish_load_track(struct track_info *infop)
goto audio_finish_load_track_exit;
}
+ struct track_info user_cur;
+
+#ifdef HAVE_PLAY_FREQ
+ track_list_user_current(0, &user_cur);
+ bool is_current_user = infop->self_hid == user_cur.self_hid;
+ if (audio_auto_change_frequency(track_id3, is_current_user))
+ {
+ // frequency switch requires full re-buffering, so stop buffering
+ filling = STATE_STOPPED;
+ logf("buffering stopped (current_track: %b, current_user: %b)", infop->self_hid == cur_info.self_hid, is_current_user);
+ if (is_current_user)
+ // audio_finish_load_track_exit not needed as playback restart is already initiated
+ return trackstat;
+
+ goto audio_finish_load_track_exit;
+ }
+#endif
+
/* Try to load a cuesheet for the track */
if (!audio_load_cuesheet(infop, track_id3))
{
@@ -2113,7 +2135,6 @@ static int audio_finish_load_track(struct track_info *infop)
/* All handles available to external routines are ready - audio and codec
information is private */
- struct track_info user_cur;
track_list_user_current(0, &user_cur);
if (infop->self_hid == user_cur.self_hid)
{
@@ -2241,7 +2262,7 @@ audio_finish_load_track_exit:
playlist_peek_offset--;
}
- if (filling != STATE_FULL)
+ if (filling != STATE_FULL && filling != STATE_STOPPED)
{
/* Load next track - error or not */
track_list.in_progress_hid = 0;
@@ -2566,6 +2587,11 @@ static void audio_finalise_track_change(void)
id3_mutex_unlock();
audio_playlist_track_change();
+
+#ifdef HAVE_PLAY_FREQ
+ if (filling == STATE_STOPPED)
+ audio_auto_change_frequency(track_id3, true);
+#endif
}
/* Actually begin a transition and take care of the codec change - may complete
@@ -2667,7 +2693,7 @@ static void audio_on_codec_complete(int status)
struct track_info info;
bool have_track = track_list_advance_current(1, &info);
- if (!have_track || info.audio_hid < 0)
+ if (!have_track || (info.audio_hid < 0 && filling != STATE_STOPPED))
{
bool end_of_playlist = false;
@@ -2764,18 +2790,15 @@ static void audio_start_playback(const struct audio_resume_info *resume_info,
static struct audio_resume_info resume = { 0, 0 };
enum play_status old_status = play_status;
- if (!(flags & AUDIO_START_REFRESH))
+ if (resume_info)
{
- if (resume_info)
- {
- resume.elapsed = resume_info->elapsed;
- resume.offset = resume_info->offset;
- }
- else
- {
- resume.elapsed = 0;
- resume.offset = 0;
- }
+ resume.elapsed = resume_info->elapsed;
+ resume.offset = resume_info->offset;
+ }
+ else
+ {
+ resume.elapsed = 0;
+ resume.offset = 0;
}
if (flags & AUDIO_START_NEWBUF)
@@ -2802,11 +2825,8 @@ static void audio_start_playback(const struct audio_resume_info *resume_info,
left off */
pcmbuf_play_stop();
- if (!(flags & AUDIO_START_REFRESH))
- {
- resume.elapsed = id3_get(PLAYING_ID3)->elapsed;
- resume.offset = id3_get(PLAYING_ID3)->offset;
- }
+ resume.elapsed = id3_get(PLAYING_ID3)->elapsed;
+ resume.offset = id3_get(PLAYING_ID3)->offset;
track_list_clear(TRACK_LIST_CLEAR_ALL);
pcmbuf_update_frequency();
@@ -3425,7 +3445,7 @@ void audio_playback_handler(struct queue_event *ev)
case Q_AUDIO_REMAKE_AUDIO_BUFFER:
/* buffer needs to be reinitialized */
LOGFQUEUE("playback < Q_AUDIO_REMAKE_AUDIO_BUFFER");
- audio_start_playback(NULL, AUDIO_START_RESTART | AUDIO_START_NEWBUF | (ev->data ? AUDIO_START_REFRESH : 0));
+ audio_start_playback(NULL, AUDIO_START_RESTART | AUDIO_START_NEWBUF);
if (play_status == PLAY_STOPPED)
return; /* just need to change buffer state */
break;
@@ -3465,6 +3485,7 @@ void audio_playback_handler(struct queue_event *ev)
}
/* Fall-through */
case STATE_FINISHED:
+ case STATE_STOPPED:
/* All data was buffered */
cancel_cpu_boost();
/* Fall-through */
@@ -4029,37 +4050,22 @@ static unsigned long audio_guess_frequency(struct mp3entry *id3)
}
}
-static void audio_change_frequency_callback(unsigned short id, void *data)
+static bool audio_auto_change_frequency(struct mp3entry *id3, bool play)
{
- static bool starting_playback = false;
- struct mp3entry *id3;
-
- switch (id)
+ unsigned long guessed_frequency = global_settings.play_frequency == 0 ? audio_guess_frequency(id3) : 0;
+ if (guessed_frequency && mixer_get_frequency() != guessed_frequency)
{
- case PLAYBACK_EVENT_START_PLAYBACK:
- starting_playback = true;
- break;
+ if (!play)
+ return true;
- case PLAYBACK_EVENT_TRACK_CHANGE:
- id3 = ((struct track_event *)data)->id3;
- if (id3 && !global_settings.play_frequency)
- {
- unsigned long guessed_frequency = audio_guess_frequency(id3);
- if (mixer_get_frequency() != guessed_frequency)
- {
#ifdef PLAYBACK_VOICE
- voice_stop();
+ voice_stop();
#endif
- mixer_set_frequency(guessed_frequency);
- audio_queue_post(Q_AUDIO_REMAKE_AUDIO_BUFFER, starting_playback);
- }
- }
- starting_playback = false;
- break;
-
- default:
- break;
+ mixer_set_frequency(guessed_frequency);
+ audio_queue_post(Q_AUDIO_REMAKE_AUDIO_BUFFER, 0);
+ return true;
}
+ return false;
}
void audio_set_playback_frequency(unsigned int sample_rate_hz)
@@ -4124,10 +4130,6 @@ void INIT_ATTR playback_init(void)
track_list_init();
buffering_init();
pcmbuf_update_frequency();
-#ifdef HAVE_PLAY_FREQ
- add_event(PLAYBACK_EVENT_TRACK_CHANGE, audio_change_frequency_callback);
- add_event(PLAYBACK_EVENT_START_PLAYBACK, audio_change_frequency_callback);
-#endif
#ifdef HAVE_CROSSFADE
/* Set crossfade setting for next buffer init which should be about... */
pcmbuf_request_crossfade_enable(global_settings.crossfade);
diff --git a/firmware/pcm.c b/firmware/pcm.c
index 6fc0b626f7..de01af484f 100644
--- a/firmware/pcm.c
+++ b/firmware/pcm.c
@@ -23,7 +23,7 @@
#include "kernel.h"
/* Define LOGF_ENABLE to enable logf output in this file */
-/*#define LOGF_ENABLE*/
+//#define LOGF_ENABLE
#include "logf.h"
#include "audio.h"
#include "sound.h"
@@ -314,7 +314,7 @@ void pcm_play_stop(void)
* what pcm_apply_settings will set */
void pcm_set_frequency(unsigned int samplerate)
{
- logf("pcm_set_frequency");
+ logf("pcm_set_frequency %u", samplerate);
int index;