diff --git a/app/src/main/java/org/oxycblt/auxio/list/selection/SelectionFragment.kt b/app/src/main/java/org/oxycblt/auxio/list/selection/SelectionFragment.kt index a5d762c42..32edb8f7a 100644 --- a/app/src/main/java/org/oxycblt/auxio/list/selection/SelectionFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/list/selection/SelectionFragment.kt @@ -71,6 +71,14 @@ abstract class SelectionFragment : requireContext().showToast(R.string.lng_queue_added) true } + R.id.action_selection_play -> { + playbackModel.play(selectionModel.consume()) + true + } + R.id.action_selection_shuffle -> { + playbackModel.shuffle(selectionModel.consume()) + true + } else -> false } } diff --git a/app/src/main/java/org/oxycblt/auxio/music/MusicStore.kt b/app/src/main/java/org/oxycblt/auxio/music/MusicStore.kt index cb04ef3e4..2e9bbab2d 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/MusicStore.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/MusicStore.kt @@ -58,7 +58,7 @@ class MusicStore private constructor() { } /** - * Remove a [Listener] from this instance, preventing it from recieving any further updates. + * Remove a [Listener] from this instance, preventing it from receiving any further updates. * @param listener The [Listener] to remove. Does nothing if the [Listener] was never added in * the first place. * @see Listener diff --git a/app/src/main/java/org/oxycblt/auxio/music/storage/Filesystem.kt b/app/src/main/java/org/oxycblt/auxio/music/storage/Filesystem.kt index 00a22deaf..5536e46df 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/storage/Filesystem.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/storage/Filesystem.kt @@ -129,7 +129,6 @@ class Directory private constructor(val volume: StorageVolume, val relativePath: * @author Alexander Capehart (OxygenCobalt) */ data class MusicDirectories(val dirs: List, val shouldInclude: Boolean) -// TODO: Unify include + exclude /** * A mime type of a file. Only intended for display. diff --git a/app/src/main/java/org/oxycblt/auxio/music/storage/StorageUtil.kt b/app/src/main/java/org/oxycblt/auxio/music/storage/StorageUtil.kt index 60bc797e9..6de6c4b3f 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/storage/StorageUtil.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/storage/StorageUtil.kt @@ -196,7 +196,7 @@ val StorageVolume.isInternalCompat: Boolean get() = isPrimaryCompat && isEmulatedCompat /** - * The unique identifier for this [StorageVolume], obtained in a version compatible manner Can be + * The unique identifier for this [StorageVolume], obtained in a version compatible manner. Can be * null. * @see StorageVolume.getUuid */ 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 e44651763..c46f6ad94 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackViewModel.kt @@ -38,6 +38,7 @@ class PlaybackViewModel(application: Application) : private val musicSettings = MusicSettings.from(application) private val playbackSettings = PlaybackSettings.from(application) private val playbackManager = PlaybackStateManager.getInstance() + private val musicStore = MusicStore.getInstance() private var lastPositionJob: Job? = null private val _song = MutableStateFlow(null) @@ -161,27 +162,13 @@ class PlaybackViewModel(application: Application) : */ fun playFrom(song: Song, playbackMode: MusicMode) { when (playbackMode) { - MusicMode.SONGS -> playFromAll(song) - MusicMode.ALBUMS -> playFromAlbum(song) + MusicMode.SONGS -> playImpl(song, null) + MusicMode.ALBUMS -> playImpl(song, song.album) MusicMode.ARTISTS -> playFromArtist(song) MusicMode.GENRES -> playFromGenre(song) } } - /** - * Play the given [Song] from all songs in the music library. - * @param song The [Song] to play. - */ - fun playFromAll(song: Song) { - playImpl(song, null) - } - - /** - * Play a [Song] from it's [Album]. - * @param song The [Song] to play. - */ - fun playFromAlbum(song: Song) = playImpl(song, song.album) - /** * Play a [Song] from one of it's [Artist]s. * @param song The [Song] to play. @@ -250,6 +237,13 @@ class PlaybackViewModel(application: Application) : */ fun play(genre: Genre) = playImpl(null, genre, false) + /** + * Play a [Music] selection. + * @param selection The selection to play. + */ + fun play(selection: List) = + playbackManager.play(null, selectionToSongs(selection), false) + /** * Shuffle an [Album]. * @param album The [Album] to shuffle. @@ -269,13 +263,11 @@ class PlaybackViewModel(application: Application) : fun shuffle(genre: Genre) = playImpl(null, genre, true) /** - * Start the given [InternalPlayer.Action] to be completed eventually. This can be used to - * enqueue a playback action at startup to then occur when the music library is fully loaded. - * @param action The [InternalPlayer.Action] to perform eventually. + * Shuffle a [Music] selection. + * @param selection The selection to shuffle. */ - fun startAction(action: InternalPlayer.Action) { - playbackManager.startAction(action) - } + fun shuffle(selection: List) = + playbackManager.play(null, selectionToSongs(selection), true) private fun playImpl( song: Song?, @@ -285,6 +277,7 @@ class PlaybackViewModel(application: Application) : check(song == null || parent == null || parent.songs.contains(song)) { "Song to play not in parent" } + val library = musicStore.library ?: return val sort = when (parent) { is Genre -> musicSettings.genreSongSort @@ -292,7 +285,17 @@ class PlaybackViewModel(application: Application) : is Album -> musicSettings.albumSongSort null -> musicSettings.songSort } - playbackManager.play(song, parent, sort, shuffled) + val queue = sort.songs(parent?.songs ?: library.songs) + playbackManager.play(song, queue, shuffled) + } + + /** + * Start the given [InternalPlayer.Action] to be completed eventually. This can be used to + * enqueue a playback action at startup to then occur when the music library is fully loaded. + * @param action The [InternalPlayer.Action] to perform eventually. + */ + fun startAction(action: InternalPlayer.Action) { + playbackManager.startAction(action) } // --- PLAYER FUNCTIONS --- 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 4f0bcf641..2cc2cf99d 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 @@ -155,20 +155,21 @@ class PlaybackStateManager private constructor() { /** * Start new playback. * @param song A particular [Song] to play, or null to play the first [Song] in the new queue. + * @param queue The queue of [Song]s to play from. * @param parent The [MusicParent] to play from, or null if to play from the entire [Library]. * @param sort [Sort] to initially sort an ordered queue with. * @param shuffled Whether to shuffle or not. */ @Synchronized - fun play(song: Song?, parent: MusicParent?, sort: Sort, shuffled: Boolean) { + fun play(song: Song?, queue: List, shuffled: Boolean) { val internalPlayer = internalPlayer ?: return val library = musicStore.library ?: return // Set up parent and queue this.parent = parent - queue.start(song, sort.songs(parent?.songs ?: library.songs), shuffled) + this.queue.start(song, queue, shuffled) // Notify components of changes notifyNewPlayback() - internalPlayer.loadSong(queue.currentSong, true) + internalPlayer.loadSong(this.queue.currentSong, true) // Played something, so we are initialized now isInitialized = true } 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 df7da5c53..aa2d254d0 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 @@ -355,15 +355,14 @@ class PlaybackService : } // Shuffle all -> Start new playback from all songs is InternalPlayer.Action.ShuffleAll -> { - playbackManager.play(null, null, musicSettings.songSort, true) + playbackManager.play(null, musicSettings.songSort.songs(library.songs), true) } // Open -> Try to find the Song for the given file and then play it from all songs is InternalPlayer.Action.Open -> { library.findSongForUri(application, action.uri)?.let { song -> playbackManager.play( song, - null, - musicSettings.songSort, + musicSettings.songSort.songs(library.songs), playbackManager.queue.isShuffled && playbackSettings.keepShuffle) } } diff --git a/app/src/main/res/menu/menu_selection_actions.xml b/app/src/main/res/menu/menu_selection_actions.xml index 841bbcd8d..ad023050c 100644 --- a/app/src/main/res/menu/menu_selection_actions.xml +++ b/app/src/main/res/menu/menu_selection_actions.xml @@ -8,16 +8,14 @@ app:showAsAction="ifRoom"/> - - - - - - - - - + + \ No newline at end of file