playback: re-add index correction

Re-add index correction, albeit with a new system that accomodates the
single queue mechanism.

The issue with using the previous queue mechanism for the single queue
was that it risked using the index of an incorrect duplicate song, as
the search would always start at index 0. Fix this by implementing a
sort of "wobbly" search that starts at the current index and moves back
and forth, checking the closest items first and the furthest items
last.
This commit is contained in:
OxygenCobalt 2022-02-05 11:36:55 -07:00
parent 685d3af12f
commit 4d22b99577
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
3 changed files with 49 additions and 8 deletions

View file

@ -566,6 +566,7 @@ class PlaybackStateManager private constructor() {
unpackFromPlaybackState(playbackState)
unpackQueue(queue)
doParentSanityCheck()
doIndexSanityCheck()
}
logD("Restore finished in ${System.currentTimeMillis() - start}ms")
@ -606,7 +607,7 @@ class PlaybackStateManager private constructor() {
}
/**
* Do the sanity check to make sure the parent was not lost in the restore process.
* Do a sanity check to make sure the parent was not lost in the restore process.
*/
private fun doParentSanityCheck() {
// Check if the parent was lost while in the DB.
@ -622,6 +623,52 @@ class PlaybackStateManager private constructor() {
}
}
/**
* Do a sanity check to make sure that the index lines up with the current song.
*/
private fun doIndexSanityCheck() {
if (mSong != null && mSong != mQueue[mIndex]) {
val correctedIndex = mQueue.wobblyIndexOfFirst(mIndex, mSong)
if (correctedIndex > -1) {
logD("Correcting malformed index to $correctedIndex")
mIndex = correctedIndex
}
}
}
/**
* Finds the index of an item through a sort-of "wobbly" search where it progressively searches
* for item away from the [start] index, instead of from position zero. This is useful, as it
* increases the likelihood that the correct index was found instead of the index of a
* duplicate.
*/
private fun <T> List<T>.wobblyIndexOfFirst(start: Int, item: T): Int {
if (start !in indices) {
return -1
}
var idx = start
var multiplier = -1
var delta = -1
while (true) {
idx += delta
if (idx !in indices) {
if (-idx !in indices) {
return -1
}
} else if (this.getOrNull(idx) == item) {
return idx
}
delta = -delta
multiplier = -multiplier
delta += multiplier
}
}
/**
* The interface for receiving updates from [PlaybackStateManager].
* Add the callback to [PlaybackStateManager] using [addCallback],

View file

@ -19,18 +19,12 @@
package org.oxycblt.auxio.settings
import android.content.SharedPreferences
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.content.edit
import org.oxycblt.auxio.accent.ACCENT_COUNT
import org.oxycblt.auxio.accent.Accent
import org.oxycblt.auxio.playback.state.PlaybackMode
// A couple of utils for migrating from old settings values to the new
// formats used in 1.3.2 & 1.4.0
// TODO: Slate these for removal eventually. There probably isn't that many left who have the
// old values but 2.0.0 will probably convince most of those to update too.
fun handleAccentCompat(prefs: SharedPreferences): Accent {
if (prefs.contains(OldKeys.KEY_ACCENT2)) {
var accent = prefs.getInt(OldKeys.KEY_ACCENT2, 5)

View file

@ -109,7 +109,7 @@ class SettingsManager private constructor(context: Context) :
/** What queue to create when a song is selected (ex. From All Songs or Search) */
val songPlaybackMode: PlaybackMode
get() = PlaybackMode.fromInt(sharedPrefs.getInt(KEY_SONG_PLAYBACK_MODE, Int.MIN_VALUE))
?: PlaybackMode.ALL_SONGS
?: PlaybackMode.ALL_SONGS
/** Whether shuffle should stay on when a new song is selected. */
val keepShuffle: Boolean