Fix song restore issue
Fix an issue where the playback restore process would only search the list of songs for the currently playing song, running the risk of picking the wrong song with the same name.
This commit is contained in:
parent
a55b42a3da
commit
72a7aa6744
8 changed files with 36 additions and 31 deletions
|
@ -29,18 +29,6 @@ fun SQLiteDatabase.execute(commands: SQLiteDatabase.() -> Unit): Boolean {
|
|||
return success
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut for running a query on this database and then running [block] with the cursor returned.
|
||||
* Will not run if the cursor is null.
|
||||
*/
|
||||
fun <R> SQLiteDatabase.queryUse(
|
||||
tableName: String,
|
||||
columns: Array<String>?,
|
||||
selection: String?,
|
||||
vararg args: String,
|
||||
block: (Cursor) -> R
|
||||
) = query(tableName, columns, selection, args, null, null, null, null)?.use(block)
|
||||
|
||||
/**
|
||||
* Shortcut for querying all items in a database and running [block] with the cursor returned.
|
||||
* Will not run if the cursor is null.
|
||||
|
|
|
@ -15,6 +15,7 @@ package org.oxycblt.auxio.database
|
|||
data class PlaybackState(
|
||||
val id: Long = 0L,
|
||||
val songName: String = "",
|
||||
val songAlbumName: String = "",
|
||||
val position: Long,
|
||||
val parentName: String = "",
|
||||
val index: Int,
|
||||
|
@ -25,7 +26,8 @@ data class PlaybackState(
|
|||
) {
|
||||
companion object {
|
||||
const val COLUMN_ID = "state_id"
|
||||
const val COLUMN_SONG_NAME = "song_name"
|
||||
const val COLUMN_SONG_NAME = "cur_song_name"
|
||||
const val COLUMN_SONG_ALBUM_NAME = "cur_song_album"
|
||||
const val COLUMN_POSITION = "position"
|
||||
const val COLUMN_PARENT_NAME = "parent_name"
|
||||
const val COLUMN_INDEX = "state_index"
|
||||
|
|
|
@ -53,6 +53,7 @@ class PlaybackStateDatabase(context: Context) :
|
|||
private fun constructStateTable(command: StringBuilder): StringBuilder {
|
||||
command.append("${PlaybackState.COLUMN_ID} LONG PRIMARY KEY,")
|
||||
.append("${PlaybackState.COLUMN_SONG_NAME} TEXT NOT NULL,")
|
||||
.append("${PlaybackState.COLUMN_SONG_ALBUM_NAME} TEXT NOT NULL,")
|
||||
.append("${PlaybackState.COLUMN_POSITION} LONG NOT NULL,")
|
||||
.append("${PlaybackState.COLUMN_PARENT_NAME} TEXT NOT NULL,")
|
||||
.append("${PlaybackState.COLUMN_INDEX} INTEGER NOT NULL,")
|
||||
|
@ -89,9 +90,10 @@ class PlaybackStateDatabase(context: Context) :
|
|||
|
||||
this@PlaybackStateDatabase.logD("Wiped state db.")
|
||||
|
||||
val stateData = ContentValues(9).apply {
|
||||
val stateData = ContentValues(10).apply {
|
||||
put(PlaybackState.COLUMN_ID, state.id)
|
||||
put(PlaybackState.COLUMN_SONG_NAME, state.songName)
|
||||
put(PlaybackState.COLUMN_SONG_ALBUM_NAME, state.songAlbumName)
|
||||
put(PlaybackState.COLUMN_POSITION, state.position)
|
||||
put(PlaybackState.COLUMN_PARENT_NAME, state.parentName)
|
||||
put(PlaybackState.COLUMN_INDEX, state.index)
|
||||
|
@ -120,6 +122,7 @@ class PlaybackStateDatabase(context: Context) :
|
|||
if (cursor.count == 0) return@queryAll
|
||||
|
||||
val songIndex = cursor.getColumnIndexOrThrow(PlaybackState.COLUMN_SONG_NAME)
|
||||
val albumIndex = cursor.getColumnIndexOrThrow(PlaybackState.COLUMN_SONG_ALBUM_NAME)
|
||||
val posIndex = cursor.getColumnIndexOrThrow(PlaybackState.COLUMN_POSITION)
|
||||
val parentIndex = cursor.getColumnIndexOrThrow(PlaybackState.COLUMN_PARENT_NAME)
|
||||
val indexIndex = cursor.getColumnIndexOrThrow(PlaybackState.COLUMN_INDEX)
|
||||
|
@ -134,6 +137,7 @@ class PlaybackStateDatabase(context: Context) :
|
|||
|
||||
state = PlaybackState(
|
||||
songName = cursor.getStringOrNull(songIndex) ?: "",
|
||||
songAlbumName = cursor.getStringOrNull(albumIndex) ?: "",
|
||||
position = cursor.getLong(posIndex),
|
||||
parentName = cursor.getStringOrNull(parentIndex) ?: "",
|
||||
index = cursor.getInt(indexIndex),
|
||||
|
|
|
@ -75,12 +75,25 @@ class MusicStore private constructor() {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the song for a file [uri].
|
||||
* Find a song from this instance in a safe manner.
|
||||
* Using a normal search of the songs list runs the risk of getting the *wrong* song with
|
||||
* the same name, so the album name is used to fix the above problem.
|
||||
* @param name The name of the song
|
||||
* @param albumName The name of the song's album.
|
||||
* @return The song requested, null if there isnt one.
|
||||
*/
|
||||
fun findSong(name: String, albumName: String): Song? {
|
||||
return albums.find { it.name == albumName }?.songs?.find { it.name == name }
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a song for a [uri], this is similar to [findSong], but with some kind of content uri.
|
||||
* @return The corresponding [Song] for this [uri], null if there isnt one.
|
||||
*/
|
||||
fun getSongForUri(uri: Uri, resolver: ContentResolver): Song? {
|
||||
resolver.query(uri, arrayOf(OpenableColumns.DISPLAY_NAME), null, null, null)
|
||||
?.use { cursor ->
|
||||
fun findSongForUri(uri: Uri, resolver: ContentResolver): Song? {
|
||||
val cur = resolver.query(uri, arrayOf(OpenableColumns.DISPLAY_NAME), null, null, null)
|
||||
|
||||
cur?.use { cursor ->
|
||||
cursor.moveToFirst()
|
||||
val fileName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME))
|
||||
|
||||
|
|
|
@ -183,7 +183,7 @@ class PlaybackViewModel : ViewModel(), PlaybackStateManager.Callback {
|
|||
private fun playWithUriInternal(uri: Uri, context: Context) {
|
||||
logD("Playing with uri $uri")
|
||||
|
||||
musicStore.getSongForUri(uri, context.contentResolver)?.let { song ->
|
||||
musicStore.findSongForUri(uri, context.contentResolver)?.let { song ->
|
||||
playSong(song)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -652,6 +652,7 @@ class PlaybackStateManager private constructor() {
|
|||
private fun packToPlaybackState(): PlaybackState {
|
||||
return PlaybackState(
|
||||
songName = mSong?.name ?: "",
|
||||
songAlbumName = mSong?.album?.name ?: "",
|
||||
position = mPosition,
|
||||
parentName = mParent?.name ?: "",
|
||||
index = mIndex,
|
||||
|
@ -674,7 +675,7 @@ class PlaybackStateManager private constructor() {
|
|||
mIndex = playbackState.index
|
||||
|
||||
// Then set up the current state
|
||||
mSong = musicStore.songs.find { it.name == playbackState.songName }
|
||||
mSong = musicStore.findSong(playbackState.songName, playbackState.songAlbumName)
|
||||
mLoopMode = LoopMode.fromInt(playbackState.loopMode) ?: LoopMode.NONE
|
||||
mIsShuffling = playbackState.isShuffling
|
||||
mIsInUserQueue = playbackState.inUserQueue
|
||||
|
@ -709,12 +710,8 @@ class PlaybackStateManager private constructor() {
|
|||
* @param queueItems The list of [QueueItem]s to unpack.
|
||||
*/
|
||||
private fun unpackQueue(queueItems: List<QueueItem>) {
|
||||
// When unpacking, first traverse albums and then traverse album songs to reduce
|
||||
// the amount of comparisons in large queues.
|
||||
queueItems.forEach { item ->
|
||||
val album = musicStore.albums.find { it.name == item.albumName }
|
||||
|
||||
album?.songs?.find { it.name == item.songName }?.let { song ->
|
||||
musicStore.findSong(item.songName, item.albumName)?.let { song ->
|
||||
if (item.isUserQueue) {
|
||||
mUserQueue.add(song)
|
||||
} else {
|
||||
|
|
|
@ -50,9 +50,10 @@ org.oxycblt.auxio # Main UI's and logging utilities
|
|||
│ └──.viewholders # Shared ViewHolders and ViewHolder utilities
|
||||
├──.search # Search UI
|
||||
├──.settings # Settings UI and systems
|
||||
│ ├──.blacklist # Excluded Directories/Systems
|
||||
│ └──.ui # Contains UI's related to the settings view, such as the about screen
|
||||
├──.songs # Songs UI
|
||||
├──.ui # Shared user interface utilities
|
||||
└──.ui # Shared user interface utilities
|
||||
```
|
||||
|
||||
#### `.coil`
|
||||
|
|
Loading…
Reference in a new issue