diff --git a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt index 06af21820..775f620b2 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt @@ -131,7 +131,7 @@ class AlbumDetailFragment : check(item is Song) { "Unexpected datatype: ${item::class.simpleName}" } when (settings.detailPlaybackMode) { null, MusicMode.ALBUMS -> playbackModel.playFromAlbum(item) - MusicMode.SONGS -> playbackModel.play(item) + MusicMode.SONGS -> playbackModel.playFromAll(item) MusicMode.ARTISTS -> playbackModel.playFromArtist(item) MusicMode.GENRES -> if (item.genres.size > 1) { navModel.mainNavigateTo( @@ -151,11 +151,11 @@ class AlbumDetailFragment : } override fun onPlayParent() { - playbackModel.play(unlikelyToBeNull(detailModel.currentAlbum.value), false) + playbackModel.play(unlikelyToBeNull(detailModel.currentAlbum.value)) } override fun onShuffleParent() { - playbackModel.play(unlikelyToBeNull(detailModel.currentAlbum.value), true) + playbackModel.shuffle(unlikelyToBeNull(detailModel.currentAlbum.value)) } override fun onShowSortMenu(anchor: View) { diff --git a/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt index 5f9e920cb..0e913baca 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt @@ -123,7 +123,7 @@ class ArtistDetailFragment : is Song -> { when (settings.detailPlaybackMode) { null, MusicMode.ARTISTS -> playbackModel.playFromArtist(item) - MusicMode.SONGS -> playbackModel.play(item) + MusicMode.SONGS -> playbackModel.playFromAll(item) MusicMode.ALBUMS -> playbackModel.playFromAlbum(item) MusicMode.GENRES -> if (item.genres.size > 1) { navModel.mainNavigateTo( @@ -150,11 +150,11 @@ class ArtistDetailFragment : } override fun onPlayParent() { - playbackModel.play(unlikelyToBeNull(detailModel.currentArtist.value), false) + playbackModel.play(unlikelyToBeNull(detailModel.currentArtist.value)) } override fun onShuffleParent() { - playbackModel.play(unlikelyToBeNull(detailModel.currentArtist.value), true) + playbackModel.shuffle(unlikelyToBeNull(detailModel.currentArtist.value)) } override fun onShowSortMenu(anchor: View) { diff --git a/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt index e2f11d58d..bdf32be36 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt @@ -123,7 +123,7 @@ class GenreDetailFragment : check(item is Song) { "Unexpected datatype: ${item::class.simpleName}" } when (settings.detailPlaybackMode) { null -> playbackModel.playFromGenre(item, unlikelyToBeNull(detailModel.currentGenre.value)) - MusicMode.SONGS -> playbackModel.play(item) + MusicMode.SONGS -> playbackModel.playFromAll(item) MusicMode.ALBUMS -> playbackModel.playFromAlbum(item) MusicMode.ARTISTS -> playbackModel.playFromArtist(item) MusicMode.GENRES -> if (item.genres.size > 1) { @@ -144,11 +144,11 @@ class GenreDetailFragment : } override fun onPlayParent() { - playbackModel.play(unlikelyToBeNull(detailModel.currentGenre.value), false) + playbackModel.play(unlikelyToBeNull(detailModel.currentGenre.value)) } override fun onShuffleParent() { - playbackModel.play(unlikelyToBeNull(detailModel.currentGenre.value), true) + playbackModel.shuffle(unlikelyToBeNull(detailModel.currentGenre.value)) } override fun onShowSortMenu(anchor: View) { diff --git a/app/src/main/java/org/oxycblt/auxio/home/list/SongListFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/list/SongListFragment.kt index 986c6a70d..b58fa0d2f 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/list/SongListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/list/SongListFragment.kt @@ -113,7 +113,7 @@ class SongListFragment : HomeListFragment() { override fun onItemClick(item: Item) { check(item is Song) { "Unexpected datatype: ${item::class.java}" } when (settings.libPlaybackMode) { - MusicMode.SONGS -> playbackModel.play(item) + MusicMode.SONGS -> playbackModel.playFromAll(item) MusicMode.ALBUMS -> playbackModel.playFromAlbum(item) MusicMode.ARTISTS -> playbackModel.playFromArtist(item) MusicMode.GENRES -> if (item.genres.size > 1) { diff --git a/app/src/main/java/org/oxycblt/auxio/music/Music.kt b/app/src/main/java/org/oxycblt/auxio/music/Music.kt index aa47ddddc..47ed7a980 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/Music.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/Music.kt @@ -26,6 +26,7 @@ import kotlinx.parcelize.Parcelize import org.oxycblt.auxio.BuildConfig import org.oxycblt.auxio.R import org.oxycblt.auxio.music.Date.Companion.from +import org.oxycblt.auxio.music.extractor.parseId3GenreNames import org.oxycblt.auxio.music.extractor.parseMultiValue import org.oxycblt.auxio.music.extractor.parseReleaseType import org.oxycblt.auxio.settings.Settings @@ -40,6 +41,8 @@ import java.util.UUID import kotlin.math.max import kotlin.math.min +// TODO: Make empty parents a hard error + // --- MUSIC MODELS --- /** [Item] variant that represents a music item. */ @@ -204,11 +207,11 @@ class Song constructor(raw: Raw, settings: Settings) : Music() { update(raw.albumName) update(raw.date) - update(raw.artistNames) - update(raw.albumArtistNames) - update(raw.track) update(raw.disc) + + update(raw.artistNames) + update(raw.albumArtistNames) } override val rawName = requireNotNull(raw.name) { "Invalid raw: No title" } @@ -317,7 +320,8 @@ class Song constructor(raw: Raw, settings: Settings) : Music() { } ) - val _rawGenres = raw.genreNames.map { Genre.Raw(it) }.ifEmpty { listOf(Genre.Raw(null)) } + val _rawGenres = raw.genreNames.parseId3GenreNames(settings) + .map { Genre.Raw(it) }.ifEmpty { listOf(Genre.Raw(null)) } fun _link(album: Album) { _album = album @@ -379,7 +383,7 @@ class Album constructor(raw: Raw, override val songs: List) : MusicParent( override fun resolveName(context: Context) = rawName - /** The latest date this album was released. */ + /** The earliest date this album was released. */ val date: Date? /** The release type of this album, such as "EP". Defaults to "Album". */ @@ -435,7 +439,6 @@ class Album constructor(raw: Raw, override val songs: List) : MusicParent( } totalDuration += song.durationMs - } date = earliestDate @@ -528,11 +531,11 @@ class Genre constructor(raw: Raw, override val songs: List) : MusicParent( val durationMs: Long init { - val totalDuration = 0L + var totalDuration = 0L for (song in songs) { song._link(this) - durationMs += song.durationMs + totalDuration += song.durationMs } durationMs = totalDuration diff --git a/app/src/main/java/org/oxycblt/auxio/music/extractor/CacheLayer.kt b/app/src/main/java/org/oxycblt/auxio/music/extractor/CacheDatabase.kt similarity index 98% rename from app/src/main/java/org/oxycblt/auxio/music/extractor/CacheLayer.kt rename to app/src/main/java/org/oxycblt/auxio/music/extractor/CacheDatabase.kt index 5102b74e8..dd973a9e0 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/extractor/CacheLayer.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/extractor/CacheDatabase.kt @@ -20,7 +20,7 @@ package org.oxycblt.auxio.music.extractor import org.oxycblt.auxio.music.Song /** TODO: Stub class, not implemented yet */ -class CacheLayer { +class CacheDatabase { fun init() { } diff --git a/app/src/main/java/org/oxycblt/auxio/music/extractor/MediaStoreLayer.kt b/app/src/main/java/org/oxycblt/auxio/music/extractor/MediaStoreExtractor.kt similarity index 95% rename from app/src/main/java/org/oxycblt/auxio/music/extractor/MediaStoreLayer.kt rename to app/src/main/java/org/oxycblt/auxio/music/extractor/MediaStoreExtractor.kt index 0fc3814cb..36d79f38b 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/extractor/MediaStoreLayer.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/extractor/MediaStoreExtractor.kt @@ -68,9 +68,7 @@ import java.io.File * to something that actually works, not even in Android 12. ID3v2.4 has been around for *21 * years.* *It can drink now.* * - * Not to mention all the other infuriating quirks. Album artists can't be accessed from the albums - * table, so we have to go for the less efficient "make a big query on all the songs lol" method so - * that songs don't end up fragmented across artists. Pretty much every OEM has added some extension + * Not to mention all the other infuriating quirks. Pretty much every OEM has added some extension * or quirk to MediaStore that I cannot reproduce, with some OEMs (COUGHSAMSUNGCOUGH) crippling the * normal tables so that you're railroaded into their music app. I have to use a semi-deprecated * field to work with file paths, and the supposedly "modern" method is SLOWER and causes even more @@ -82,12 +80,12 @@ import java.io.File * Is there anything we can do about it? No. Google has routinely shut down issues that begged * google to fix glaring issues with MediaStore or to just take the API behind the woodshed and * shoot it. Largely because they have zero incentive to improve it given how "obscure" local music - * listening is. As a result, Auxio exposes an option to use an internal parser based on ExoPlayer - * that at least tries to correct the insane metadata that this API returns, but not only is that - * system horrifically slow and bug-prone, it also faces the even larger issue of how google keeps - * trying to kill the filesystem and force you into their ContentResolver API. In the future - * MediaStore could be the only system we have, which is also the day that greenland melts and - * birthdays stop happening forever. + * listening is. As a result, I am forced to write my own extractor (Which is the contents of the + * rest of this module) based on ExoPlayer that at least tries to correct the insane metadata that + * this API returns, but not only is that system horrifically slow and bug-prone, it also faces the + * even larger issue of how google keeps trying to kill the filesystem and force you into their + * ContentResolver API. In the future MediaStore could be the only system we have, which is also + * the day that greenland melts and birthdays stop happening forever. * * I'm pretty sure nothing is going to happen and MediaStore will continue to be neglected and * probably deprecated eventually for a "new" API that just coincidentally excludes music indexing. @@ -102,7 +100,7 @@ import java.io.File * music loading process. * @author OxygenCobalt */ -abstract class MediaStoreLayer(private val context: Context, private val cacheLayer: CacheLayer) { +abstract class MediaStoreLayer(private val context: Context, private val cacheLayer: CacheDatabase) { private var cursor: Cursor? = null private var idIndex = -1 @@ -249,7 +247,7 @@ abstract class MediaStoreLayer(private val context: Context, private val cacheLa * This returns true if the song could be restored from cache, false if metadata had to be * re-extracted, and null if the cursor is exhausted. */ - fun populateRaw(raw: Song.Raw): Boolean? { + fun populateRawSong(raw: Song.Raw): Boolean? { val cursor = requireNotNull(cursor) { "MediaStoreLayer is not properly initialized" } if (!cursor.moveToNext()) { logD("Cursor is exhausted") @@ -374,7 +372,7 @@ abstract class MediaStoreLayer(private val context: Context, private val cacheLa * API 21 onwards to API 29. * @author OxygenCobalt */ -class Api21MediaStoreLayer(context: Context, cacheLayer: CacheLayer) : +class Api21MediaStoreLayer(context: Context, cacheLayer: CacheDatabase) : MediaStoreLayer(context, cacheLayer) { private var trackIndex = -1 private var dataIndex = -1 @@ -440,7 +438,7 @@ class Api21MediaStoreLayer(context: Context, cacheLayer: CacheLayer) : * @author OxygenCobalt */ @RequiresApi(Build.VERSION_CODES.Q) -open class BaseApi29MediaStoreLayer(context: Context, cacheLayer: CacheLayer) : +open class BaseApi29MediaStoreLayer(context: Context, cacheLayer: CacheDatabase) : MediaStoreLayer(context, cacheLayer) { private var volumeIndex = -1 private var relativePathIndex = -1 @@ -496,7 +494,7 @@ open class BaseApi29MediaStoreLayer(context: Context, cacheLayer: CacheLayer) : * @author OxygenCobalt */ @RequiresApi(Build.VERSION_CODES.Q) -open class Api29MediaStoreLayer(context: Context, cacheLayer: CacheLayer) : +open class Api29MediaStoreLayer(context: Context, cacheLayer: CacheDatabase) : BaseApi29MediaStoreLayer(context, cacheLayer) { private var trackIndex = -1 @@ -528,7 +526,7 @@ open class Api29MediaStoreLayer(context: Context, cacheLayer: CacheLayer) : * @author OxygenCobalt */ @RequiresApi(Build.VERSION_CODES.R) -class Api30MediaStoreLayer(context: Context, cacheLayer: CacheLayer) : +class Api30MediaStoreLayer(context: Context, cacheLayer: CacheDatabase) : BaseApi29MediaStoreLayer(context, cacheLayer) { private var trackIndex: Int = -1 private var discIndex: Int = -1 diff --git a/app/src/main/java/org/oxycblt/auxio/music/extractor/MetadataLayer.kt b/app/src/main/java/org/oxycblt/auxio/music/extractor/MetadataExtractor.kt similarity index 99% rename from app/src/main/java/org/oxycblt/auxio/music/extractor/MetadataLayer.kt rename to app/src/main/java/org/oxycblt/auxio/music/extractor/MetadataExtractor.kt index 399f93eca..b95fcc0fc 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/extractor/MetadataLayer.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/extractor/MetadataExtractor.kt @@ -55,7 +55,7 @@ class MetadataLayer(private val context: Context, private val mediaStoreLayer: M suspend fun parse(emit: suspend (Song.Raw) -> Unit) { while (true) { val raw = Song.Raw() - if (mediaStoreLayer.populateRaw(raw) ?: break) { + if (mediaStoreLayer.populateRawSong(raw) ?: break) { // No need to extract metadata that was successfully restored from the cache emit(raw) continue diff --git a/app/src/main/java/org/oxycblt/auxio/music/dirs/MusicDirAdapter.kt b/app/src/main/java/org/oxycblt/auxio/music/settings/MusicDirAdapter.kt similarity index 98% rename from app/src/main/java/org/oxycblt/auxio/music/dirs/MusicDirAdapter.kt rename to app/src/main/java/org/oxycblt/auxio/music/settings/MusicDirAdapter.kt index 8b3156dab..f39b64fad 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/dirs/MusicDirAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/settings/MusicDirAdapter.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package org.oxycblt.auxio.music.dirs +package org.oxycblt.auxio.music.settings import android.view.View import android.view.ViewGroup diff --git a/app/src/main/java/org/oxycblt/auxio/music/dirs/MusicDirs.kt b/app/src/main/java/org/oxycblt/auxio/music/settings/MusicDirs.kt similarity index 95% rename from app/src/main/java/org/oxycblt/auxio/music/dirs/MusicDirs.kt rename to app/src/main/java/org/oxycblt/auxio/music/settings/MusicDirs.kt index 748bd43c1..61db8e10c 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/dirs/MusicDirs.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/settings/MusicDirs.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package org.oxycblt.auxio.music.dirs +package org.oxycblt.auxio.music.settings import org.oxycblt.auxio.music.Directory diff --git a/app/src/main/java/org/oxycblt/auxio/music/dirs/MusicDirsDialog.kt b/app/src/main/java/org/oxycblt/auxio/music/settings/MusicDirsDialog.kt similarity index 99% rename from app/src/main/java/org/oxycblt/auxio/music/dirs/MusicDirsDialog.kt rename to app/src/main/java/org/oxycblt/auxio/music/settings/MusicDirsDialog.kt index 582183487..74ac2c280 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/dirs/MusicDirsDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/settings/MusicDirsDialog.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package org.oxycblt.auxio.music.dirs +package org.oxycblt.auxio.music.settings import android.net.Uri import android.os.Bundle diff --git a/app/src/main/java/org/oxycblt/auxio/music/separators/SeparatorsDialog.kt b/app/src/main/java/org/oxycblt/auxio/music/settings/SeparatorsDialog.kt similarity index 98% rename from app/src/main/java/org/oxycblt/auxio/music/separators/SeparatorsDialog.kt rename to app/src/main/java/org/oxycblt/auxio/music/settings/SeparatorsDialog.kt index 28a706352..fcce67eae 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/separators/SeparatorsDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/settings/SeparatorsDialog.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package org.oxycblt.auxio.music.separators +package org.oxycblt.auxio.music.settings import android.os.Bundle import android.view.LayoutInflater diff --git a/app/src/main/java/org/oxycblt/auxio/music/system/Indexer.kt b/app/src/main/java/org/oxycblt/auxio/music/system/Indexer.kt index 6676ae09f..0e3b82edc 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/system/Indexer.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/system/Indexer.kt @@ -36,7 +36,7 @@ import org.oxycblt.auxio.music.Sort import org.oxycblt.auxio.music.extractor.Api21MediaStoreLayer import org.oxycblt.auxio.music.extractor.Api29MediaStoreLayer import org.oxycblt.auxio.music.extractor.Api30MediaStoreLayer -import org.oxycblt.auxio.music.extractor.CacheLayer +import org.oxycblt.auxio.music.extractor.CacheDatabase import org.oxycblt.auxio.music.extractor.MetadataLayer import org.oxycblt.auxio.settings.Settings import org.oxycblt.auxio.util.logD @@ -202,7 +202,7 @@ class Indexer { // experience. This is technically dependency injection. Except it doesn't increase // your compile times by 3x. Isn't that nice. - val cacheLayer = CacheLayer() + val cacheLayer = CacheDatabase() val mediaStoreLayer = when { diff --git a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackViewModel.kt b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackViewModel.kt index d31f28152..2d18bb8f8 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackViewModel.kt @@ -38,7 +38,6 @@ import org.oxycblt.auxio.playback.state.PlaybackStateManager import org.oxycblt.auxio.playback.state.RepeatMode import org.oxycblt.auxio.settings.Settings import org.oxycblt.auxio.util.application -import org.oxycblt.auxio.util.logE /** * The ViewModel that provides a UI frontend for [PlaybackStateManager]. @@ -92,72 +91,70 @@ class PlaybackViewModel(application: Application) : // --- PLAYING FUNCTIONS --- /** Play a [song] from all songs. */ - fun play(song: Song) { + fun playFromAll(song: Song) { playbackManager.play(song, null, settings) } - /** Play a song from it's album. */ - fun playFromAlbum(song: Song) { - playbackManager.play(song, song.album, settings) - } - - /** Play a song from it's artist. */ - fun playFromArtist(song: Song) { - playbackManager.play(song, song.album.artist, settings) - } - - /** Play a song from the specific genre that contains the song. */ - fun playFromGenre(song: Song, genre: Genre) { - if (!genre.songs.contains(song)) { - logE("Genre does not contain song, not playing") - return - } - - playbackManager.play(song, genre, settings) - } - - /** - * Play an [album]. - * @param shuffled Whether to shuffle the new queue - */ - fun play(album: Album, shuffled: Boolean) { - if (album.songs.isEmpty()) { - logE("Album is empty, Not playing") - return - } - - playbackManager.play(album, shuffled, settings) - } - - /** - * Play an [artist]. - * @param shuffled Whether to shuffle the new queue - */ - fun play(artist: Artist, shuffled: Boolean) { - if (artist.songs.isEmpty()) { - logE("Artist is empty, Not playing") - return - } - - playbackManager.play(artist, shuffled, settings) - } - - /** - * Play a [genre]. - * @param shuffled Whether to shuffle the new queue - */ - fun play(genre: Genre, shuffled: Boolean) { - if (genre.songs.isEmpty()) { - logE("Genre is empty, Not playing") - return - } - - playbackManager.play(genre, shuffled, settings) - } - /** Shuffle all songs */ fun shuffleAll() { - playbackManager.shuffleAll(settings) + playbackManager.play(null, null, settings, true) + } + + /** Play a song from it's album. */ + fun playFromAlbum(song: Song) { + playbackManager.play(song, song.album, settings, false) + } + + /** Play a song from it's artist. */ + fun playFromArtist(song: Song) { + playbackManager.play(song, song.album.artist, settings, false) + } + + /** Play a song from the specific genre that contains the song. */ + fun playFromGenre(song: Song, genre: Genre) { + playbackManager.play(song, genre, settings, false) + } + + /** + * Play an [album]. + */ + fun play(album: Album) { + playbackManager.play(null, album, settings, false) + } + + /** + * Play an [artist]. + */ + fun play(artist: Artist) { + playbackManager.play(null, artist, settings, false) + } + + /** + * Play a [genre]. + */ + fun play(genre: Genre) { + playbackManager.play(null, genre, settings, false) + } + + /** + * Shuffle an [album]. + */ + fun shuffle(album: Album) { + playbackManager.play(null, album, settings, true) + } + + /** + * Shuffle an [artist]. + */ + fun shuffle(artist: Artist) { + playbackManager.play(null, artist, settings, true) + } + + /** + * Shuffle a [genre]. + */ + fun shuffle(genre: Genre) { + playbackManager.play(null, genre, settings, true) } /** diff --git a/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt b/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt index 16107810c..8eb0f202a 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt @@ -151,54 +151,27 @@ class PlaybackStateManager private constructor() { /** Play a song from a parent that contains the song. */ @Synchronized - fun play(song: Song, parent: MusicParent?, settings: Settings) { + fun play( + song: Song?, + parent: MusicParent?, + settings: Settings, + shuffled: Boolean = settings.keepShuffle && isShuffled + ) { val internalPlayer = internalPlayer ?: return val library = musicStore.library ?: return this.parent = parent - - applyNewQueue(library, settings, settings.keepShuffle && isShuffled, song) + _queue = (parent?.songs ?: library.songs).toMutableList() + orderQueue(settings, shuffled, song) notifyNewPlayback() notifyShuffledChanged() - internalPlayer.loadSong(song, true) + internalPlayer.loadSong(this.song, true) isInitialized = true } - /** Play a [parent], such as an artist or album. */ - @Synchronized - fun play(parent: MusicParent, shuffled: Boolean, settings: Settings) { - val internalPlayer = internalPlayer ?: return - val library = musicStore.library ?: return - - this.parent = parent - applyNewQueue(library, settings, shuffled, null) - - notifyNewPlayback() - notifyShuffledChanged() - - internalPlayer.loadSong(song, true) - isInitialized = true - } - - /** Shuffle all songs. */ - @Synchronized - fun shuffleAll(settings: Settings) { - val internalPlayer = internalPlayer ?: return - val library = musicStore.library ?: return - - parent = null - applyNewQueue(library, settings, true, null) - - notifyNewPlayback() - notifyShuffledChanged() - - internalPlayer.loadSong(song, true) - isInitialized = true - } - // --- QUEUE FUNCTIONS --- /** Go to the next song, along with doing all the checks that entails. */ @@ -288,27 +261,24 @@ class PlaybackStateManager private constructor() { /** Set whether this instance is [shuffled]. Updates the queue accordingly. */ @Synchronized fun reshuffle(shuffled: Boolean, settings: Settings) { - val library = musicStore.library ?: return val song = song ?: return - applyNewQueue(library, settings, shuffled, song) + orderQueue(settings, shuffled, song) notifyQueueReworked() notifyShuffledChanged() } - private fun applyNewQueue( - library: MusicStore.Library, + private fun orderQueue( settings: Settings, shuffled: Boolean, keep: Song? ) { - val newQueue = (parent?.songs ?: library.songs).toMutableList() val newIndex: Int if (shuffled) { - newQueue.shuffle() + _queue.shuffle() if (keep != null) { - newQueue.add(0, newQueue.removeAt(newQueue.indexOf(keep))) + _queue.add(0, _queue.removeAt(_queue.indexOf(keep))) } newIndex = 0 @@ -323,12 +293,11 @@ class PlaybackStateManager private constructor() { } } - sort.songsInPlace(newQueue) - - newIndex = keep?.let(newQueue::indexOf) ?: 0 + sort.songsInPlace(_queue) + newIndex = keep?.let(_queue::indexOf) ?: 0 } - _queue = newQueue + _queue = queue index = newIndex isShuffled = shuffled } diff --git a/app/src/main/java/org/oxycblt/auxio/playback/system/MediaSessionComponent.kt b/app/src/main/java/org/oxycblt/auxio/playback/system/MediaSessionComponent.kt index c4a9b0275..c0f557c91 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/system/MediaSessionComponent.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/system/MediaSessionComponent.kt @@ -163,7 +163,7 @@ class MediaSessionComponent(private val context: Context, private val callback: builder.putLong(MediaMetadataCompat.METADATA_KEY_DISC_NUMBER, it.toLong()) } - song.album.date?.let { + song.date?.let { builder.putString(MediaMetadataCompat.METADATA_KEY_DATE, it.toString()) } diff --git a/app/src/main/java/org/oxycblt/auxio/playback/system/PlaybackService.kt b/app/src/main/java/org/oxycblt/auxio/playback/system/PlaybackService.kt index 8a137b032..b1d902482 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/system/PlaybackService.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/system/PlaybackService.kt @@ -382,7 +382,7 @@ class PlaybackService : } } is InternalPlayer.Action.ShuffleAll -> { - playbackManager.shuffleAll(settings) + playbackManager.play(null, null, settings, true) } is InternalPlayer.Action.Open -> { library.findSongForUri(application, action.uri)?.let { song -> diff --git a/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt b/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt index ddf26ddc7..a205b37b5 100644 --- a/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt @@ -151,7 +151,7 @@ class SearchFragment : override fun onItemClick(item: Item) { when (item) { is Song -> when (settings.libPlaybackMode) { - MusicMode.SONGS -> playbackModel.play(item) + MusicMode.SONGS -> playbackModel.playFromAll(item) MusicMode.ALBUMS -> playbackModel.playFromAlbum(item) MusicMode.ARTISTS -> playbackModel.playFromArtist(item) MusicMode.GENRES -> if (item.genres.size > 1) { diff --git a/app/src/main/java/org/oxycblt/auxio/settings/Settings.kt b/app/src/main/java/org/oxycblt/auxio/settings/Settings.kt index da5ee7ee8..34fbc024b 100644 --- a/app/src/main/java/org/oxycblt/auxio/settings/Settings.kt +++ b/app/src/main/java/org/oxycblt/auxio/settings/Settings.kt @@ -30,7 +30,7 @@ import org.oxycblt.auxio.home.tabs.Tab import org.oxycblt.auxio.music.Directory import org.oxycblt.auxio.music.MusicMode import org.oxycblt.auxio.music.Sort -import org.oxycblt.auxio.music.dirs.MusicDirs +import org.oxycblt.auxio.music.settings.MusicDirs import org.oxycblt.auxio.playback.BarAction import org.oxycblt.auxio.playback.replaygain.ReplayGainMode import org.oxycblt.auxio.playback.replaygain.ReplayGainPreAmp diff --git a/app/src/main/java/org/oxycblt/auxio/ui/fragment/MenuFragment.kt b/app/src/main/java/org/oxycblt/auxio/ui/fragment/MenuFragment.kt index d6c02d848..271638417 100644 --- a/app/src/main/java/org/oxycblt/auxio/ui/fragment/MenuFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/fragment/MenuFragment.kt @@ -96,10 +96,10 @@ abstract class MenuFragment : ViewBindingFragment() { musicMenuImpl(anchor, menuRes) { id -> when (id) { R.id.action_play -> { - playbackModel.play(album, false) + playbackModel.play(album) } R.id.action_shuffle -> { - playbackModel.play(album, true) + playbackModel.shuffle(album) } R.id.action_play_next -> { playbackModel.playNext(album) @@ -131,10 +131,10 @@ abstract class MenuFragment : ViewBindingFragment() { musicMenuImpl(anchor, menuRes) { id -> when (id) { R.id.action_play -> { - playbackModel.play(artist, false) + playbackModel.play(artist) } R.id.action_shuffle -> { - playbackModel.play(artist, true) + playbackModel.shuffle(artist) } R.id.action_play_next -> { playbackModel.playNext(artist) @@ -163,10 +163,10 @@ abstract class MenuFragment : ViewBindingFragment() { musicMenuImpl(anchor, menuRes) { id -> when (id) { R.id.action_play -> { - playbackModel.play(genre, false) + playbackModel.play(genre) } R.id.action_shuffle -> { - playbackModel.play(genre, true) + playbackModel.shuffle(genre) } R.id.action_play_next -> { playbackModel.playNext(genre) diff --git a/app/src/main/res/navigation/nav_main.xml b/app/src/main/res/navigation/nav_main.xml index 56b22133e..a7132ca06 100644 --- a/app/src/main/res/navigation/nav_main.xml +++ b/app/src/main/res/navigation/nav_main.xml @@ -83,12 +83,12 @@ tools:layout="@layout/dialog_pre_amp" />