forked from len0rd/rockbox
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
This commit is contained in:
parent
90e35716e3
commit
831faa3b82
2 changed files with 54 additions and 52 deletions
102
apps/playback.c
102
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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue