summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoman Artiukhin <bahusdrive@gmail.com>2024-01-24 10:57:17 +0200
committerChristian Soffke <christian.soffke@gmail.com>2024-07-21 11:51:02 -0400
commitfe5375a6cb8761e6af33ac1c2cddbe0c76200d91 (patch)
tree7cf27ac9b179addf0ddb57c8d49376d4d8590f8c
parent9f366b1b8a00acdec6b0161293a404d4237a2557 (diff)
downloadrockbox-fe5375a6cb.tar.gz
rockbox-fe5375a6cb.zip
Improve Crossfade handling in Single Mode
Crossfade (see Playback Settings -> Crossfade) now works between songs in Single Mode (see Playback Settings -> Single Mode) unless it’s the last song to be played. Change-Id: Icfe3d48459bb35bbc050f237a68b27e793ab9152
-rw-r--r--apps/pcmbuf.c3
-rw-r--r--apps/playback.c160
2 files changed, 86 insertions, 77 deletions
diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c
index 8718d730fb..773e97cce0 100644
--- a/apps/pcmbuf.c
+++ b/apps/pcmbuf.c
@@ -741,9 +741,6 @@ void pcmbuf_start_track_change(enum pcm_track_change_type type)
}
}
- if (auto_skip && global_settings.single_mode != SINGLE_MODE_OFF && !global_settings.party_mode)
- crossfade = false;
-
if (crossfade)
{
logf("crossfade track change");
diff --git a/apps/playback.c b/apps/playback.c
index 8a30af5199..a284a1858d 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -2494,6 +2494,23 @@ static inline char* single_mode_get_id3_tag(struct mp3entry *id3)
return NULL;
}
+static bool single_mode_do_pause(int id3_hid)
+{
+ if (global_settings.single_mode != SINGLE_MODE_OFF && global_settings.party_mode == 0 &&
+ ((skip_pending == TRACK_SKIP_AUTO) || (skip_pending == TRACK_SKIP_AUTO_NEW_PLAYLIST))) {
+
+ if (global_settings.single_mode == SINGLE_MODE_TRACK)
+ return true;
+
+ char *previous_tag = single_mode_get_id3_tag(id3_get(PLAYING_ID3));
+ char *new_tag = single_mode_get_id3_tag(bufgetid3(id3_hid));
+ return previous_tag == NULL ||
+ new_tag == NULL ||
+ strcmp(previous_tag, new_tag) != 0;
+ }
+ return false;
+}
+
/* Called to make an outstanding track skip the current track and to send the
transition events */
static void audio_finalise_track_change(void)
@@ -2540,43 +2557,28 @@ static void audio_finalise_track_change(void)
bool have_info = track_list_current(0, &info);
struct mp3entry *track_id3 = NULL;
- id3_mutex_lock();
-
/* Update the current cuesheet if any and enabled */
if (have_info)
{
buf_read_cuesheet(info.cuesheet_hid);
track_id3 = bufgetid3(info.id3_hid);
- }
-
- if (SINGLE_MODE_OFF != global_settings.single_mode && global_settings.party_mode == 0 &&
- ((skip_pending == TRACK_SKIP_AUTO) || (skip_pending == TRACK_SKIP_AUTO_NEW_PLAYLIST)))
- {
- bool single_mode_do_pause = true;
- if (SINGLE_MODE_TRACK != global_settings.single_mode)
- {
- char *previous_tag = single_mode_get_id3_tag(id3_get(PLAYING_ID3));
- char *new_tag = single_mode_get_id3_tag(track_id3);
- single_mode_do_pause = previous_tag == NULL ||
- new_tag == NULL ||
- strcmp(previous_tag, new_tag) != 0;
- }
- if (single_mode_do_pause)
+ if (single_mode_do_pause(info.id3_hid))
{
play_status = PLAY_PAUSED;
pcmbuf_pause(true);
}
}
+ /* Sync the next track information */
+ have_info = track_list_current(1, &info);
+
+ id3_mutex_lock();
id3_write(PLAYING_ID3, track_id3);
/* The skip is technically over */
skip_pending = TRACK_SKIP_NONE;
- /* Sync the next track information */
- have_info = track_list_current(1, &info);
-
id3_write(NEXTTRACK_ID3, have_info ? bufgetid3(info.id3_hid) :
id3_get(UNBUFFERED_ID3));
@@ -2641,54 +2643,12 @@ static void audio_monitor_end_of_playlist(void)
pcmbuf_start_track_change(TRACK_CHANGE_END_OF_DATA);
}
-/* Codec has completed decoding the track
- (usually Q_AUDIO_CODEC_COMPLETE) */
-static void audio_on_codec_complete(int status)
+/* Does this track have an entry allocated? */
+static bool audio_can_change_track(int *trackstat, int *id3_hid)
{
- logf("%s(%d)", __func__, status);
-
- if (play_status == PLAY_STOPPED)
- return;
-
- /* If it didn't notify us first, don't expect "seek complete" message
- since the codec can't post it now - do things like it would have
- done */
- audio_complete_codec_seek();
-
- if (play_status == PLAY_PAUSED || skip_pending != TRACK_SKIP_NONE)
- {
- /* Old-hay on the ip-skay - codec has completed decoding
-
- Paused: We're not sounding it, so just remember that it happened
- and the resume will begin the transition
-
- Skipping: There was already a skip in progress, remember it and
- allow no further progress until the PCM from the previous
- song has finished
-
- This function will be reentered upon completing the existing
- transition in order to do the one that was just tried (below)
- */
- codec_skip_pending = true;
- codec_skip_status = status;
-
- /* PCM buffer must know; audio could still be filling and hasn't
- yet reached the play watermark */
- pcmbuf_start_track_change(TRACK_CHANGE_AUTO_PILEUP);
- return;
- }
-
- codec_skip_pending = false;
-
- int trackstat = LOAD_TRACK_OK;
-
- track_event_flags = TEF_AUTO_SKIP;
- skip_pending = TRACK_SKIP_AUTO;
-
- /* Does this track have an entry allocated? */
struct track_info info;
bool have_track = track_list_advance_current(1, &info);
-
+ *id3_hid = info.id3_hid;
if (!have_track || info.audio_hid < 0)
{
bool end_of_playlist = false;
@@ -2697,8 +2657,8 @@ static void audio_on_codec_complete(int status)
{
if (filling == STATE_STOPPED)
{
- audio_begin_track_change(TRACK_CHANGE_END_OF_DATA, trackstat);
- return;
+ audio_begin_track_change(TRACK_CHANGE_END_OF_DATA, *trackstat);
+ return false;
}
/* Track load is not complete - it might have stopped on a
@@ -2719,8 +2679,7 @@ static void audio_on_codec_complete(int status)
{
/* Continue filling after this track */
audio_reset_and_rebuffer(TRACK_LIST_KEEP_CURRENT, 1);
- audio_begin_track_change(TRACK_CHANGE_AUTO, trackstat);
- return;
+ return true;
}
/* else rebuffer at this track; status applies to the track we
want */
@@ -2736,10 +2695,10 @@ static void audio_on_codec_complete(int status)
if (!end_of_playlist)
{
- trackstat = audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL,
- skip_pending == TRACK_SKIP_AUTO ? 0 : -1);
+ *trackstat = audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL,
+ skip_pending == TRACK_SKIP_AUTO ? 0 : -1);
- if (trackstat == LOAD_TRACK_ERR_NO_MORE)
+ if (*trackstat == LOAD_TRACK_ERR_NO_MORE)
{
/* Failed to find anything after all - do playlist switchover
instead */
@@ -2751,11 +2710,64 @@ static void audio_on_codec_complete(int status)
if (end_of_playlist)
{
audio_monitor_end_of_playlist();
- return;
+ return false;
}
}
+ return true;
+}
+
+/* Codec has completed decoding the track
+ (usually Q_AUDIO_CODEC_COMPLETE) */
+static void audio_on_codec_complete(int status)
+{
+ logf("%s(%d)", __func__, status);
- audio_begin_track_change(TRACK_CHANGE_AUTO, trackstat);
+ if (play_status == PLAY_STOPPED)
+ return;
+
+ /* If it didn't notify us first, don't expect "seek complete" message
+ since the codec can't post it now - do things like it would have
+ done */
+ audio_complete_codec_seek();
+
+ if (play_status == PLAY_PAUSED || skip_pending != TRACK_SKIP_NONE)
+ {
+ /* Old-hay on the ip-skay - codec has completed decoding
+
+ Paused: We're not sounding it, so just remember that it happened
+ and the resume will begin the transition
+
+ Skipping: There was already a skip in progress, remember it and
+ allow no further progress until the PCM from the previous
+ song has finished
+
+ This function will be reentered upon completing the existing
+ transition in order to do the one that was just tried (below)
+ */
+ codec_skip_pending = true;
+ codec_skip_status = status;
+
+ /* PCM buffer must know; audio could still be filling and hasn't
+ yet reached the play watermark */
+ pcmbuf_start_track_change(TRACK_CHANGE_AUTO_PILEUP);
+ return;
+ }
+
+ codec_skip_pending = false;
+
+ int trackstat = LOAD_TRACK_OK;
+
+ track_event_flags = TEF_AUTO_SKIP;
+ skip_pending = TRACK_SKIP_AUTO;
+
+ int id3_hid = 0;
+ if (audio_can_change_track(&trackstat, &id3_hid))
+ {
+ audio_begin_track_change(
+ single_mode_do_pause(id3_hid)
+ ? TRACK_CHANGE_END_OF_DATA
+ : TRACK_CHANGE_AUTO, trackstat);
+ }
}
/* Called when codec completes seek operation