playback: fix queue moves
Fix moving items with the new queue system. This took a bit of thinking, but I think this is the correct way to implement this in a future-proof manner.
This commit is contained in:
parent
5adc87550e
commit
bef4dca0ce
8 changed files with 96 additions and 47 deletions
|
@ -23,10 +23,10 @@ import android.database.sqlite.SQLiteDatabase
|
|||
import android.database.sqlite.SQLiteOpenHelper
|
||||
import androidx.core.database.getIntOrNull
|
||||
import androidx.core.database.getStringOrNull
|
||||
import org.oxycblt.auxio.music.tags.Date
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.music.parsing.correctWhitespace
|
||||
import org.oxycblt.auxio.music.parsing.splitEscaped
|
||||
import org.oxycblt.auxio.music.tags.Date
|
||||
import org.oxycblt.auxio.util.*
|
||||
|
||||
/**
|
||||
|
|
|
@ -27,7 +27,6 @@ import androidx.annotation.RequiresApi
|
|||
import androidx.core.database.getIntOrNull
|
||||
import androidx.core.database.getStringOrNull
|
||||
import java.io.File
|
||||
import org.oxycblt.auxio.music.tags.Date
|
||||
import org.oxycblt.auxio.music.MusicSettings
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.music.parsing.parseId3v2Position
|
||||
|
@ -38,6 +37,7 @@ import org.oxycblt.auxio.music.storage.mediaStoreVolumeNameCompat
|
|||
import org.oxycblt.auxio.music.storage.safeQuery
|
||||
import org.oxycblt.auxio.music.storage.storageVolumesCompat
|
||||
import org.oxycblt.auxio.music.storage.useQuery
|
||||
import org.oxycblt.auxio.music.tags.Date
|
||||
import org.oxycblt.auxio.util.getSystemServiceCompat
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.nonZeroOrNull
|
||||
|
|
|
@ -22,10 +22,10 @@ import androidx.core.text.isDigitsOnly
|
|||
import com.google.android.exoplayer2.MediaItem
|
||||
import com.google.android.exoplayer2.MetadataRetriever
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import org.oxycblt.auxio.music.tags.Date
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.music.parsing.parseId3v2Position
|
||||
import org.oxycblt.auxio.music.storage.toAudioUri
|
||||
import org.oxycblt.auxio.music.tags.Date
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.logW
|
||||
|
||||
|
|
|
@ -235,7 +235,8 @@ class Date private constructor(private val tokens: List<Int>) : Comparable<Date>
|
|||
val tokens =
|
||||
// Match the input with the timestamp regex. If there is no match, see if we can
|
||||
// fall back to some kind of year value.
|
||||
(ISO8601_REGEX.matchEntire(timestamp) ?: return timestamp.toIntOrNull()?.let(Companion::from))
|
||||
(ISO8601_REGEX.matchEntire(timestamp)
|
||||
?: return timestamp.toIntOrNull()?.let(Companion::from))
|
||||
.groupValues
|
||||
// Filter to the specific tokens we want and convert them to integer tokens.
|
||||
.mapIndexedNotNull { index, s -> if (index % 2 != 0) s.toIntOrNull() else null }
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Auxio Project
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.auxio.music.tags
|
||||
|
||||
import org.oxycblt.auxio.R
|
||||
|
@ -5,8 +22,8 @@ import org.oxycblt.auxio.R
|
|||
/**
|
||||
* The type of release an [Album] is considered. This includes EPs, Singles, Compilations, etc.
|
||||
*
|
||||
* This class is derived from the MusicBrainz Release Group Type specification. It can be found
|
||||
* at: https://musicbrainz.org/doc/Release_Group/Type
|
||||
* This class is derived from the MusicBrainz Release Group Type specification. It can be found at:
|
||||
* https://musicbrainz.org/doc/Release_Group/Type
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
sealed class ReleaseType {
|
||||
|
@ -21,8 +38,8 @@ sealed class ReleaseType {
|
|||
|
||||
/**
|
||||
* A plain album.
|
||||
* @param refinement A specification of what kind of performance this release is. If null,
|
||||
* the release is considered "Plain".
|
||||
* @param refinement A specification of what kind of performance this release is. If null, the
|
||||
* release is considered "Plain".
|
||||
*/
|
||||
data class Album(override val refinement: Refinement?) : ReleaseType() {
|
||||
override val stringRes: Int
|
||||
|
@ -37,8 +54,8 @@ sealed class ReleaseType {
|
|||
|
||||
/**
|
||||
* A "Extended Play", or EP. Usually a smaller release consisting of 4-5 songs.
|
||||
* @param refinement A specification of what kind of performance this release is. If null,
|
||||
* the release is considered "Plain".
|
||||
* @param refinement A specification of what kind of performance this release is. If null, the
|
||||
* release is considered "Plain".
|
||||
*/
|
||||
data class EP(override val refinement: Refinement?) : ReleaseType() {
|
||||
override val stringRes: Int
|
||||
|
@ -53,8 +70,8 @@ sealed class ReleaseType {
|
|||
|
||||
/**
|
||||
* A single. Usually a release consisting of 1-2 songs.
|
||||
* @param refinement A specification of what kind of performance this release is. If null,
|
||||
* the release is considered "Plain".
|
||||
* @param refinement A specification of what kind of performance this release is. If null, the
|
||||
* release is considered "Plain".
|
||||
*/
|
||||
data class Single(override val refinement: Refinement?) : ReleaseType() {
|
||||
override val stringRes: Int
|
||||
|
@ -69,8 +86,8 @@ sealed class ReleaseType {
|
|||
|
||||
/**
|
||||
* A compilation. Usually consists of many songs from a variety of artists.
|
||||
* @param refinement A specification of what kind of performance this release is. If null,
|
||||
* the release is considered "Plain".
|
||||
* @param refinement A specification of what kind of performance this release is. If null, the
|
||||
* release is considered "Plain".
|
||||
*/
|
||||
data class Compilation(override val refinement: Refinement?) : ReleaseType() {
|
||||
override val stringRes: Int
|
||||
|
@ -108,8 +125,8 @@ sealed class ReleaseType {
|
|||
}
|
||||
|
||||
/**
|
||||
* A Mix-tape. These are usually [EP]-sized releases of music made to promote an [Artist] or
|
||||
* a future release.
|
||||
* A Mix-tape. These are usually [EP]-sized releases of music made to promote an [Artist] or a
|
||||
* future release.
|
||||
*/
|
||||
object Mixtape : ReleaseType() {
|
||||
override val refinement: Refinement?
|
||||
|
@ -133,7 +150,8 @@ sealed class ReleaseType {
|
|||
* Parse a [ReleaseType] from a string formatted with the MusicBrainz Release Group Type
|
||||
* specification.
|
||||
* @param types A list of values consisting of valid release type values.
|
||||
* @return A [ReleaseType] consisting of the given types, or null if the types were not valid.
|
||||
* @return A [ReleaseType] consisting of the given types, or null if the types were not
|
||||
* valid.
|
||||
*/
|
||||
fun parse(types: List<String>): ReleaseType? {
|
||||
val primary = types.getOrNull(0) ?: return null
|
||||
|
@ -150,12 +168,12 @@ sealed class ReleaseType {
|
|||
}
|
||||
|
||||
/**
|
||||
* Parse "secondary" types (i.e not [Album], [EP], or [Single]) from a string formatted
|
||||
* with the MusicBrainz Release Group Type specification.
|
||||
* Parse "secondary" types (i.e not [Album], [EP], or [Single]) from a string formatted with
|
||||
* the MusicBrainz Release Group Type specification.
|
||||
* @param index The index of the release type to parse.
|
||||
* @param convertRefinement Code to convert a [Refinement] into a [ReleaseType] corresponding
|
||||
* to the callee's context. This is used in order to handle secondary times that are
|
||||
* actually [Refinement]s.
|
||||
* @param convertRefinement Code to convert a [Refinement] into a [ReleaseType]
|
||||
* corresponding to the callee's context. This is used in order to handle secondary times
|
||||
* that are actually [Refinement]s.
|
||||
* @return A [ReleaseType] corresponding to the secondary type found at that index.
|
||||
*/
|
||||
private inline fun List<String>.parseSecondaryTypes(
|
||||
|
@ -174,12 +192,12 @@ sealed class ReleaseType {
|
|||
}
|
||||
|
||||
/**
|
||||
* Parse "secondary" types (i.e not [Album], [EP], [Single]) that do not correspond to
|
||||
* any child values.
|
||||
* Parse "secondary" types (i.e not [Album], [EP], [Single]) that do not correspond to any
|
||||
* child values.
|
||||
* @param type The release type value to parse.
|
||||
* @param convertRefinement Code to convert a [Refinement] into a [ReleaseType] corresponding
|
||||
* to the callee's context. This is used in order to handle secondary times that are
|
||||
* actually [Refinement]s.
|
||||
* @param convertRefinement Code to convert a [Refinement] into a [ReleaseType]
|
||||
* corresponding to the callee's context. This is used in order to handle secondary times
|
||||
* that are actually [Refinement]s.
|
||||
*/
|
||||
private inline fun parseSecondaryTypeImpl(
|
||||
type: String?,
|
||||
|
|
|
@ -112,6 +112,21 @@ class Queue {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reformat the queue's internal representation to align with the given values. This is not
|
||||
* useful in most circumstances.
|
||||
* @param
|
||||
*/
|
||||
fun rework(heap: List<Song?>, orderedMapping: IntArray, shuffledMapping: IntArray) {
|
||||
// val instructions = mutableListOf<Int?>()
|
||||
// val currentBackshift = 0
|
||||
// for (song in heap) {
|
||||
// if (song == null) {
|
||||
// instructions.add(0, )
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Add [Song]s to the top of the queue. Will start playback if nothing is playing.
|
||||
* @param songs The [Song]s to add.
|
||||
|
@ -179,18 +194,17 @@ class Queue {
|
|||
orderedMapping.add(dst, orderedMapping.removeAt(src))
|
||||
}
|
||||
|
||||
// TODO: I really need to figure out how to get non-swap moves working.
|
||||
return when (index) {
|
||||
src -> {
|
||||
index = dst
|
||||
ChangeResult.INDEX
|
||||
}
|
||||
dst -> {
|
||||
index = src
|
||||
ChangeResult.INDEX
|
||||
}
|
||||
when (index) {
|
||||
// We are moving the currently playing song, correct the index to it's new position.
|
||||
src -> index = dst
|
||||
// We have moved an song from behind the playing song to in front, shift back.
|
||||
in (src + 1)..dst -> index -= 1
|
||||
// We have moved an song from in front of the playing song to behind, shift forward.
|
||||
in dst until src -> index += 1
|
||||
else -> ChangeResult.MAPPING
|
||||
}
|
||||
|
||||
return ChangeResult.INDEX
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Auxio Project
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.auxio.music.library
|
||||
|
||||
import org.oxycblt.auxio.music.Song
|
||||
|
@ -5,10 +22,6 @@ import org.oxycblt.auxio.music.Song
|
|||
class LibraryTest {
|
||||
|
||||
companion object {
|
||||
val LIBRARY = listOf(
|
||||
Song.Raw(
|
||||
|
||||
)
|
||||
)
|
||||
val LIBRARY = listOf(Song.Raw())
|
||||
}
|
||||
}
|
|
@ -30,7 +30,8 @@ class ReleaseTypeTest {
|
|||
|
||||
@Test
|
||||
fun releaseType_parse_secondary() {
|
||||
assertEquals(ReleaseType.Compilation(null), ReleaseType.parse(listOf("album", "compilation")))
|
||||
assertEquals(
|
||||
ReleaseType.Compilation(null), ReleaseType.parse(listOf("album", "compilation")))
|
||||
assertEquals(ReleaseType.Soundtrack, ReleaseType.parse(listOf("album", "soundtrack")))
|
||||
assertEquals(ReleaseType.Mix, ReleaseType.parse(listOf("album", "dj-mix")))
|
||||
assertEquals(ReleaseType.Mixtape, ReleaseType.parse(listOf("album", "mixtape/street")))
|
||||
|
@ -39,7 +40,8 @@ class ReleaseTypeTest {
|
|||
@Test
|
||||
fun releaseType_parse_modifiers() {
|
||||
assertEquals(
|
||||
ReleaseType.Album(ReleaseType.Refinement.LIVE), ReleaseType.parse(listOf("album", "live")))
|
||||
ReleaseType.Album(ReleaseType.Refinement.LIVE),
|
||||
ReleaseType.parse(listOf("album", "live")))
|
||||
assertEquals(
|
||||
ReleaseType.Album(ReleaseType.Refinement.REMIX),
|
||||
ReleaseType.parse(listOf("album", "remix")))
|
||||
|
@ -75,7 +77,8 @@ class ReleaseTypeTest {
|
|||
|
||||
@Test
|
||||
fun releaseType_parse_orphanedModifier() {
|
||||
assertEquals(ReleaseType.Album(ReleaseType.Refinement.LIVE), ReleaseType.parse(listOf("live")))
|
||||
assertEquals(
|
||||
ReleaseType.Album(ReleaseType.Refinement.LIVE), ReleaseType.parse(listOf("live")))
|
||||
assertEquals(
|
||||
ReleaseType.Album(ReleaseType.Refinement.REMIX), ReleaseType.parse(listOf("remix")))
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue