music: hide musicstore impl
Hide the MusicStore implementation behind an interface, transforming it into a new MusicRepository class. This is in preparation for dependency injection.
This commit is contained in:
parent
bb2ea9df27
commit
b34e6fdc8a
11 changed files with 79 additions and 75 deletions
|
@ -32,7 +32,6 @@ import org.oxycblt.auxio.detail.recycler.SortHeader
|
||||||
import org.oxycblt.auxio.list.BasicHeader
|
import org.oxycblt.auxio.list.BasicHeader
|
||||||
import org.oxycblt.auxio.list.Item
|
import org.oxycblt.auxio.list.Item
|
||||||
import org.oxycblt.auxio.music.*
|
import org.oxycblt.auxio.music.*
|
||||||
import org.oxycblt.auxio.music.MusicStore
|
|
||||||
import org.oxycblt.auxio.music.format.AudioInfo
|
import org.oxycblt.auxio.music.format.AudioInfo
|
||||||
import org.oxycblt.auxio.music.format.Disc
|
import org.oxycblt.auxio.music.format.Disc
|
||||||
import org.oxycblt.auxio.music.format.ReleaseType
|
import org.oxycblt.auxio.music.format.ReleaseType
|
||||||
|
@ -49,8 +48,8 @@ import org.oxycblt.auxio.util.*
|
||||||
* @author Alexander Capehart (OxygenCobalt)
|
* @author Alexander Capehart (OxygenCobalt)
|
||||||
*/
|
*/
|
||||||
class DetailViewModel(application: Application) :
|
class DetailViewModel(application: Application) :
|
||||||
AndroidViewModel(application), MusicStore.Listener {
|
AndroidViewModel(application), MusicRepository.Listener {
|
||||||
private val musicStore = MusicStore.getInstance()
|
private val musicRepository = MusicRepository.get()
|
||||||
private val musicSettings = MusicSettings.from(application)
|
private val musicSettings = MusicSettings.from(application)
|
||||||
private val playbackSettings = PlaybackSettings.from(application)
|
private val playbackSettings = PlaybackSettings.from(application)
|
||||||
private val audioInfoProvider = AudioInfo.Provider.from(application)
|
private val audioInfoProvider = AudioInfo.Provider.from(application)
|
||||||
|
@ -137,11 +136,11 @@ class DetailViewModel(application: Application) :
|
||||||
get() = playbackSettings.inParentPlaybackMode
|
get() = playbackSettings.inParentPlaybackMode
|
||||||
|
|
||||||
init {
|
init {
|
||||||
musicStore.addListener(this)
|
musicRepository.addListener(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCleared() {
|
override fun onCleared() {
|
||||||
musicStore.removeListener(this)
|
musicRepository.removeListener(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onLibraryChanged(library: Library?) {
|
override fun onLibraryChanged(library: Library?) {
|
||||||
|
@ -235,7 +234,7 @@ class DetailViewModel(application: Application) :
|
||||||
_currentGenre.value = requireMusic<Genre>(uid)?.also(::refreshGenreList)
|
_currentGenre.value = requireMusic<Genre>(uid)?.also(::refreshGenreList)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <T : Music> requireMusic(uid: Music.UID) = musicStore.library?.find<T>(uid)
|
private fun <T : Music> requireMusic(uid: Music.UID) = musicRepository.library?.find<T>(uid)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start a new job to load a given [Song]'s [AudioInfo]. Result is pushed to [songAudioInfo].
|
* Start a new job to load a given [Song]'s [AudioInfo]. Result is pushed to [songAudioInfo].
|
||||||
|
|
|
@ -23,7 +23,6 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import org.oxycblt.auxio.home.tabs.Tab
|
import org.oxycblt.auxio.home.tabs.Tab
|
||||||
import org.oxycblt.auxio.music.*
|
import org.oxycblt.auxio.music.*
|
||||||
import org.oxycblt.auxio.music.MusicStore
|
|
||||||
import org.oxycblt.auxio.music.library.Library
|
import org.oxycblt.auxio.music.library.Library
|
||||||
import org.oxycblt.auxio.music.library.Sort
|
import org.oxycblt.auxio.music.library.Sort
|
||||||
import org.oxycblt.auxio.playback.PlaybackSettings
|
import org.oxycblt.auxio.playback.PlaybackSettings
|
||||||
|
@ -34,8 +33,8 @@ import org.oxycblt.auxio.util.logD
|
||||||
* @author Alexander Capehart (OxygenCobalt)
|
* @author Alexander Capehart (OxygenCobalt)
|
||||||
*/
|
*/
|
||||||
class HomeViewModel(application: Application) :
|
class HomeViewModel(application: Application) :
|
||||||
AndroidViewModel(application), MusicStore.Listener, HomeSettings.Listener {
|
AndroidViewModel(application), MusicRepository.Listener, HomeSettings.Listener {
|
||||||
private val musicStore = MusicStore.getInstance()
|
private val musicRepository = MusicRepository.get()
|
||||||
private val homeSettings = HomeSettings.from(application)
|
private val homeSettings = HomeSettings.from(application)
|
||||||
private val musicSettings = MusicSettings.from(application)
|
private val musicSettings = MusicSettings.from(application)
|
||||||
private val playbackSettings = PlaybackSettings.from(application)
|
private val playbackSettings = PlaybackSettings.from(application)
|
||||||
|
@ -92,13 +91,13 @@ class HomeViewModel(application: Application) :
|
||||||
val isFastScrolling: StateFlow<Boolean> = _isFastScrolling
|
val isFastScrolling: StateFlow<Boolean> = _isFastScrolling
|
||||||
|
|
||||||
init {
|
init {
|
||||||
musicStore.addListener(this)
|
musicRepository.addListener(this)
|
||||||
homeSettings.registerListener(this)
|
homeSettings.registerListener(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCleared() {
|
override fun onCleared() {
|
||||||
super.onCleared()
|
super.onCleared()
|
||||||
musicStore.removeListener(this)
|
musicRepository.removeListener(this)
|
||||||
homeSettings.unregisterListener(this)
|
homeSettings.unregisterListener(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,7 +129,7 @@ class HomeViewModel(application: Application) :
|
||||||
override fun onHideCollaboratorsChanged() {
|
override fun onHideCollaboratorsChanged() {
|
||||||
// Changes in the hide collaborator setting will change the artist contents
|
// Changes in the hide collaborator setting will change the artist contents
|
||||||
// of the library, consider it a library update.
|
// of the library, consider it a library update.
|
||||||
onLibraryChanged(musicStore.library)
|
onLibraryChanged(musicRepository.library)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -21,15 +21,14 @@ import androidx.lifecycle.ViewModel
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import org.oxycblt.auxio.music.*
|
import org.oxycblt.auxio.music.*
|
||||||
import org.oxycblt.auxio.music.MusicStore
|
|
||||||
import org.oxycblt.auxio.music.library.Library
|
import org.oxycblt.auxio.music.library.Library
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A [ViewModel] that manages the current selection.
|
* A [ViewModel] that manages the current selection.
|
||||||
* @author Alexander Capehart (OxygenCobalt)
|
* @author Alexander Capehart (OxygenCobalt)
|
||||||
*/
|
*/
|
||||||
class SelectionViewModel : ViewModel(), MusicStore.Listener {
|
class SelectionViewModel : ViewModel(), MusicRepository.Listener {
|
||||||
private val musicStore = MusicStore.getInstance()
|
private val musicRepository = MusicRepository.get()
|
||||||
|
|
||||||
private val _selected = MutableStateFlow(listOf<Music>())
|
private val _selected = MutableStateFlow(listOf<Music>())
|
||||||
/** the currently selected items. These are ordered in earliest selected and latest selected. */
|
/** the currently selected items. These are ordered in earliest selected and latest selected. */
|
||||||
|
@ -37,7 +36,7 @@ class SelectionViewModel : ViewModel(), MusicStore.Listener {
|
||||||
get() = _selected
|
get() = _selected
|
||||||
|
|
||||||
init {
|
init {
|
||||||
musicStore.addListener(this)
|
musicRepository.addListener(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onLibraryChanged(library: Library?) {
|
override fun onLibraryChanged(library: Library?) {
|
||||||
|
@ -60,7 +59,7 @@ class SelectionViewModel : ViewModel(), MusicStore.Listener {
|
||||||
|
|
||||||
override fun onCleared() {
|
override fun onCleared() {
|
||||||
super.onCleared()
|
super.onCleared()
|
||||||
musicStore.removeListener(this)
|
musicRepository.removeListener(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021 Auxio Project
|
* Copyright (c) 2023 Auxio Project
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -28,22 +28,13 @@ import org.oxycblt.auxio.music.library.Library
|
||||||
*
|
*
|
||||||
* @author Alexander Capehart (OxygenCobalt)
|
* @author Alexander Capehart (OxygenCobalt)
|
||||||
*/
|
*/
|
||||||
class MusicStore private constructor() {
|
interface MusicRepository {
|
||||||
private val listeners = mutableListOf<Listener>()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current [Library]. May be null if a [Library] has not been successfully loaded yet. This
|
* The current [Library]. May be null if a [Library] has not been successfully loaded yet. This
|
||||||
* can change, so it's highly recommended to not access this directly and instead rely on
|
* can change, so it's highly recommended to not access this directly and instead rely on
|
||||||
* [Listener].
|
* [Listener].
|
||||||
*/
|
*/
|
||||||
@Volatile
|
var library: Library?
|
||||||
var library: Library? = null
|
|
||||||
set(value) {
|
|
||||||
field = value
|
|
||||||
for (callback in listeners) {
|
|
||||||
callback.onLibraryChanged(library)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a [Listener] to this instance. This can be used to receive changes in the music library.
|
* Add a [Listener] to this instance. This can be used to receive changes in the music library.
|
||||||
|
@ -51,11 +42,7 @@ class MusicStore private constructor() {
|
||||||
* @param listener The [Listener] to add.
|
* @param listener The [Listener] to add.
|
||||||
* @see Listener
|
* @see Listener
|
||||||
*/
|
*/
|
||||||
@Synchronized
|
fun addListener(listener: Listener)
|
||||||
fun addListener(listener: Listener) {
|
|
||||||
listener.onLibraryChanged(library)
|
|
||||||
listeners.add(listener)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a [Listener] from this instance, preventing it from receiving any further updates.
|
* Remove a [Listener] from this instance, preventing it from receiving any further updates.
|
||||||
|
@ -63,12 +50,9 @@ class MusicStore private constructor() {
|
||||||
* the first place.
|
* the first place.
|
||||||
* @see Listener
|
* @see Listener
|
||||||
*/
|
*/
|
||||||
@Synchronized
|
fun removeListener(listener: Listener)
|
||||||
fun removeListener(listener: Listener) {
|
|
||||||
listeners.remove(listener)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A listener for changes in the music library. */
|
/** A listener for changes in [MusicRepository] */
|
||||||
interface Listener {
|
interface Listener {
|
||||||
/**
|
/**
|
||||||
* Called when the current [Library] has changed.
|
* Called when the current [Library] has changed.
|
||||||
|
@ -78,23 +62,47 @@ class MusicStore private constructor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@Volatile private var INSTANCE: MusicStore? = null
|
@Volatile private var INSTANCE: MusicRepository? = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a singleton instance.
|
* Get a singleton instance.
|
||||||
* @return The (possibly newly-created) singleton instance.
|
* @return The (possibly newly-created) singleton instance.
|
||||||
*/
|
*/
|
||||||
fun getInstance(): MusicStore {
|
fun get(): MusicRepository {
|
||||||
val currentInstance = INSTANCE
|
val currentInstance = INSTANCE
|
||||||
if (currentInstance != null) {
|
if (currentInstance != null) {
|
||||||
return currentInstance
|
return currentInstance
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
val newInstance = MusicStore()
|
val newInstance = RealMusicRepository()
|
||||||
INSTANCE = newInstance
|
INSTANCE = newInstance
|
||||||
return newInstance
|
return newInstance
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class RealMusicRepository : MusicRepository {
|
||||||
|
private val listeners = mutableListOf<MusicRepository.Listener>()
|
||||||
|
|
||||||
|
@Volatile
|
||||||
|
override var library: Library? = null
|
||||||
|
set(value) {
|
||||||
|
field = value
|
||||||
|
for (callback in listeners) {
|
||||||
|
callback.onLibraryChanged(library)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
override fun addListener(listener: MusicRepository.Listener) {
|
||||||
|
listener.onLibraryChanged(library)
|
||||||
|
listeners.add(listener)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
override fun removeListener(listener: MusicRepository.Listener) {
|
||||||
|
listeners.remove(listener)
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,7 +29,8 @@ import org.oxycblt.auxio.util.logD
|
||||||
* Organized music library information.
|
* Organized music library information.
|
||||||
*
|
*
|
||||||
* This class allows for the creation of a well-formed music library graph from raw song
|
* This class allows for the creation of a well-formed music library graph from raw song
|
||||||
* information. It's generally not expected to create this yourself and instead use [MusicStore].
|
* information. It's generally not expected to create this yourself and instead use
|
||||||
|
* [MusicRepository].
|
||||||
*
|
*
|
||||||
* @author Alexander Capehart
|
* @author Alexander Capehart
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -21,7 +21,6 @@ import androidx.lifecycle.ViewModel
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import org.oxycblt.auxio.music.*
|
import org.oxycblt.auxio.music.*
|
||||||
import org.oxycblt.auxio.music.MusicStore
|
|
||||||
import org.oxycblt.auxio.music.library.Library
|
import org.oxycblt.auxio.music.library.Library
|
||||||
import org.oxycblt.auxio.util.unlikelyToBeNull
|
import org.oxycblt.auxio.util.unlikelyToBeNull
|
||||||
|
|
||||||
|
@ -30,8 +29,8 @@ import org.oxycblt.auxio.util.unlikelyToBeNull
|
||||||
* contain the music themselves and then exit if the library changes.
|
* contain the music themselves and then exit if the library changes.
|
||||||
* @author Alexander Capehart (OxygenCobalt)
|
* @author Alexander Capehart (OxygenCobalt)
|
||||||
*/
|
*/
|
||||||
class PickerViewModel : ViewModel(), MusicStore.Listener {
|
class PickerViewModel : ViewModel(), MusicRepository.Listener {
|
||||||
private val musicStore = MusicStore.getInstance()
|
private val musicRepository = MusicRepository.get()
|
||||||
|
|
||||||
private val _currentItem = MutableStateFlow<Music?>(null)
|
private val _currentItem = MutableStateFlow<Music?>(null)
|
||||||
/** The current item whose artists should be shown in the picker. Null if there is no item. */
|
/** The current item whose artists should be shown in the picker. Null if there is no item. */
|
||||||
|
@ -49,7 +48,7 @@ class PickerViewModel : ViewModel(), MusicStore.Listener {
|
||||||
get() = _genreChoices
|
get() = _genreChoices
|
||||||
|
|
||||||
override fun onCleared() {
|
override fun onCleared() {
|
||||||
musicStore.removeListener(this)
|
musicRepository.removeListener(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onLibraryChanged(library: Library?) {
|
override fun onLibraryChanged(library: Library?) {
|
||||||
|
@ -63,7 +62,7 @@ class PickerViewModel : ViewModel(), MusicStore.Listener {
|
||||||
* @param uid The [Music.UID] of the [Song] to update to.
|
* @param uid The [Music.UID] of the [Song] to update to.
|
||||||
*/
|
*/
|
||||||
fun setItemUid(uid: Music.UID) {
|
fun setItemUid(uid: Music.UID) {
|
||||||
val library = unlikelyToBeNull(musicStore.library)
|
val library = unlikelyToBeNull(musicRepository.library)
|
||||||
_currentItem.value = library.find(uid)
|
_currentItem.value = library.find(uid)
|
||||||
refreshChoices()
|
refreshChoices()
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,8 +39,8 @@ import org.oxycblt.auxio.util.logW
|
||||||
*
|
*
|
||||||
* This class provides low-level access into the exact state of the music loading process. **This
|
* This class provides low-level access into the exact state of the music loading process. **This
|
||||||
* class should not be used in most cases.** It is highly volatile and provides far more information
|
* class should not be used in most cases.** It is highly volatile and provides far more information
|
||||||
* than is usually needed. Use [MusicStore] instead if you do not need to work with the exact music
|
* than is usually needed. Use [MusicRepository] instead if you do not need to work with the exact
|
||||||
* loading state.
|
* music loading state.
|
||||||
*
|
*
|
||||||
* @author Alexander Capehart (OxygenCobalt)
|
* @author Alexander Capehart (OxygenCobalt)
|
||||||
*/
|
*/
|
||||||
|
@ -345,8 +345,8 @@ class Indexer private constructor() {
|
||||||
* A listener for rapid-fire changes in the music loading state.
|
* A listener for rapid-fire changes in the music loading state.
|
||||||
*
|
*
|
||||||
* This is only useful for code that absolutely must show the current loading process.
|
* This is only useful for code that absolutely must show the current loading process.
|
||||||
* Otherwise, [MusicStore.Listener] is highly recommended due to it's updates only consisting of
|
* Otherwise, [MusicRepository.Listener] is highly recommended due to it's updates only
|
||||||
* the [Library].
|
* consisting of the [Library].
|
||||||
*/
|
*/
|
||||||
interface Listener {
|
interface Listener {
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -31,8 +31,8 @@ import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.oxycblt.auxio.BuildConfig
|
import org.oxycblt.auxio.BuildConfig
|
||||||
|
import org.oxycblt.auxio.music.MusicRepository
|
||||||
import org.oxycblt.auxio.music.MusicSettings
|
import org.oxycblt.auxio.music.MusicSettings
|
||||||
import org.oxycblt.auxio.music.MusicStore
|
|
||||||
import org.oxycblt.auxio.music.storage.contentResolverSafe
|
import org.oxycblt.auxio.music.storage.contentResolverSafe
|
||||||
import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
||||||
import org.oxycblt.auxio.service.ForegroundManager
|
import org.oxycblt.auxio.service.ForegroundManager
|
||||||
|
@ -55,7 +55,7 @@ import org.oxycblt.auxio.util.logD
|
||||||
*/
|
*/
|
||||||
class IndexerService : Service(), Indexer.Controller, MusicSettings.Listener {
|
class IndexerService : Service(), Indexer.Controller, MusicSettings.Listener {
|
||||||
private val indexer = Indexer.getInstance()
|
private val indexer = Indexer.getInstance()
|
||||||
private val musicStore = MusicStore.getInstance()
|
private val musicRepository = MusicRepository.get()
|
||||||
private val playbackManager = PlaybackStateManager.get()
|
private val playbackManager = PlaybackStateManager.get()
|
||||||
private val serviceJob = Job()
|
private val serviceJob = Job()
|
||||||
private val indexScope = CoroutineScope(serviceJob + Dispatchers.IO)
|
private val indexScope = CoroutineScope(serviceJob + Dispatchers.IO)
|
||||||
|
@ -85,7 +85,7 @@ class IndexerService : Service(), Indexer.Controller, MusicSettings.Listener {
|
||||||
indexer.registerController(this)
|
indexer.registerController(this)
|
||||||
// An indeterminate indexer and a missing library implies we are extremely early
|
// An indeterminate indexer and a missing library implies we are extremely early
|
||||||
// in app initialization so start loading music.
|
// in app initialization so start loading music.
|
||||||
if (musicStore.library == null && indexer.isIndeterminate) {
|
if (musicRepository.library == null && indexer.isIndeterminate) {
|
||||||
logD("No library present and no previous response, indexing music now")
|
logD("No library present and no previous response, indexing music now")
|
||||||
onStartIndexing(true)
|
onStartIndexing(true)
|
||||||
}
|
}
|
||||||
|
@ -129,11 +129,11 @@ class IndexerService : Service(), Indexer.Controller, MusicSettings.Listener {
|
||||||
is Indexer.State.Indexing -> updateActiveSession(state.indexing)
|
is Indexer.State.Indexing -> updateActiveSession(state.indexing)
|
||||||
is Indexer.State.Complete -> {
|
is Indexer.State.Complete -> {
|
||||||
val newLibrary = state.result.getOrNull()
|
val newLibrary = state.result.getOrNull()
|
||||||
if (newLibrary != null && newLibrary != musicStore.library) {
|
if (newLibrary != null && newLibrary != musicRepository.library) {
|
||||||
logD("Applying new library")
|
logD("Applying new library")
|
||||||
// We only care if the newly-loaded library is going to replace a previously
|
// We only care if the newly-loaded library is going to replace a previously
|
||||||
// loaded library.
|
// loaded library.
|
||||||
if (musicStore.library != null) {
|
if (musicRepository.library != null) {
|
||||||
// Wipe possibly-invalidated outdated covers
|
// Wipe possibly-invalidated outdated covers
|
||||||
imageLoader.memoryCache?.clear()
|
imageLoader.memoryCache?.clear()
|
||||||
// Clear invalid models from PlaybackStateManager. This is not connected
|
// Clear invalid models from PlaybackStateManager. This is not connected
|
||||||
|
@ -153,7 +153,7 @@ class IndexerService : Service(), Indexer.Controller, MusicSettings.Listener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Forward the new library to MusicStore to continue the update process.
|
// Forward the new library to MusicStore to continue the update process.
|
||||||
musicStore.library = newLibrary
|
musicRepository.library = newLibrary
|
||||||
}
|
}
|
||||||
// On errors, while we would want to show a notification that displays the
|
// On errors, while we would want to show a notification that displays the
|
||||||
// error, that requires the Android 13 notification permission, which is not
|
// error, that requires the Android 13 notification permission, which is not
|
||||||
|
|
|
@ -40,7 +40,7 @@ class PlaybackViewModel(application: Application) :
|
||||||
private val playbackSettings = PlaybackSettings.from(application)
|
private val playbackSettings = PlaybackSettings.from(application)
|
||||||
private val playbackManager = PlaybackStateManager.get()
|
private val playbackManager = PlaybackStateManager.get()
|
||||||
private val persistenceRepository = PersistenceRepository.from(application)
|
private val persistenceRepository = PersistenceRepository.from(application)
|
||||||
private val musicStore = MusicStore.getInstance()
|
private val musicRepository = MusicRepository.get()
|
||||||
private var lastPositionJob: Job? = null
|
private var lastPositionJob: Job? = null
|
||||||
|
|
||||||
private val _song = MutableStateFlow<Song?>(null)
|
private val _song = MutableStateFlow<Song?>(null)
|
||||||
|
@ -279,7 +279,7 @@ class PlaybackViewModel(application: Application) :
|
||||||
check(song == null || parent == null || parent.songs.contains(song)) {
|
check(song == null || parent == null || parent.songs.contains(song)) {
|
||||||
"Song to play not in parent"
|
"Song to play not in parent"
|
||||||
}
|
}
|
||||||
val library = musicStore.library ?: return
|
val library = musicRepository.library ?: return
|
||||||
val sort =
|
val sort =
|
||||||
when (parent) {
|
when (parent) {
|
||||||
is Genre -> musicSettings.genreSongSort
|
is Genre -> musicSettings.genreSongSort
|
||||||
|
@ -449,7 +449,7 @@ class PlaybackViewModel(application: Application) :
|
||||||
*/
|
*/
|
||||||
fun tryRestorePlaybackState(onDone: (Boolean) -> Unit) {
|
fun tryRestorePlaybackState(onDone: (Boolean) -> Unit) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
val library = musicStore.library
|
val library = musicRepository.library
|
||||||
if (library != null) {
|
if (library != null) {
|
||||||
val savedState = persistenceRepository.readState(library)
|
val savedState = persistenceRepository.readState(library)
|
||||||
if (savedState != null) {
|
if (savedState != null) {
|
||||||
|
|
|
@ -43,8 +43,8 @@ import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.oxycblt.auxio.BuildConfig
|
import org.oxycblt.auxio.BuildConfig
|
||||||
|
import org.oxycblt.auxio.music.MusicRepository
|
||||||
import org.oxycblt.auxio.music.MusicSettings
|
import org.oxycblt.auxio.music.MusicSettings
|
||||||
import org.oxycblt.auxio.music.MusicStore
|
|
||||||
import org.oxycblt.auxio.music.Song
|
import org.oxycblt.auxio.music.Song
|
||||||
import org.oxycblt.auxio.music.library.Library
|
import org.oxycblt.auxio.music.library.Library
|
||||||
import org.oxycblt.auxio.playback.PlaybackSettings
|
import org.oxycblt.auxio.playback.PlaybackSettings
|
||||||
|
@ -80,7 +80,7 @@ class PlaybackService :
|
||||||
Player.Listener,
|
Player.Listener,
|
||||||
InternalPlayer,
|
InternalPlayer,
|
||||||
MediaSessionComponent.Listener,
|
MediaSessionComponent.Listener,
|
||||||
MusicStore.Listener {
|
MusicRepository.Listener {
|
||||||
// Player components
|
// Player components
|
||||||
private lateinit var player: ExoPlayer
|
private lateinit var player: ExoPlayer
|
||||||
private lateinit var replayGainProcessor: ReplayGainAudioProcessor
|
private lateinit var replayGainProcessor: ReplayGainAudioProcessor
|
||||||
|
@ -90,12 +90,12 @@ class PlaybackService :
|
||||||
private lateinit var widgetComponent: WidgetComponent
|
private lateinit var widgetComponent: WidgetComponent
|
||||||
private val systemReceiver = PlaybackReceiver()
|
private val systemReceiver = PlaybackReceiver()
|
||||||
|
|
||||||
// Managers
|
// Shared components
|
||||||
private val playbackManager = PlaybackStateManager.get()
|
private val playbackManager = PlaybackStateManager.get()
|
||||||
private val musicStore = MusicStore.getInstance()
|
|
||||||
private lateinit var musicSettings: MusicSettings
|
|
||||||
private lateinit var playbackSettings: PlaybackSettings
|
private lateinit var playbackSettings: PlaybackSettings
|
||||||
private lateinit var persistenceRepository: PersistenceRepository
|
private lateinit var persistenceRepository: PersistenceRepository
|
||||||
|
private val musicRepository = MusicRepository.get()
|
||||||
|
private lateinit var musicSettings: MusicSettings
|
||||||
|
|
||||||
// State
|
// State
|
||||||
private lateinit var foregroundManager: ForegroundManager
|
private lateinit var foregroundManager: ForegroundManager
|
||||||
|
@ -153,7 +153,7 @@ class PlaybackService :
|
||||||
// Initialize any listener-dependent components last as we wouldn't want a listener race
|
// Initialize any listener-dependent components last as we wouldn't want a listener race
|
||||||
// condition to cause us to load music before we were fully initialize.
|
// condition to cause us to load music before we were fully initialize.
|
||||||
playbackManager.registerInternalPlayer(this)
|
playbackManager.registerInternalPlayer(this)
|
||||||
musicStore.addListener(this)
|
musicRepository.addListener(this)
|
||||||
widgetComponent = WidgetComponent(this)
|
widgetComponent = WidgetComponent(this)
|
||||||
mediaSessionComponent = MediaSessionComponent(this, this)
|
mediaSessionComponent = MediaSessionComponent(this, this)
|
||||||
registerReceiver(
|
registerReceiver(
|
||||||
|
@ -193,7 +193,7 @@ class PlaybackService :
|
||||||
// Pause just in case this destruction was unexpected.
|
// Pause just in case this destruction was unexpected.
|
||||||
playbackManager.setPlaying(false)
|
playbackManager.setPlaying(false)
|
||||||
playbackManager.unregisterInternalPlayer(this)
|
playbackManager.unregisterInternalPlayer(this)
|
||||||
musicStore.removeListener(this)
|
musicRepository.removeListener(this)
|
||||||
|
|
||||||
unregisterReceiver(systemReceiver)
|
unregisterReceiver(systemReceiver)
|
||||||
serviceJob.cancel()
|
serviceJob.cancel()
|
||||||
|
@ -339,7 +339,7 @@ class PlaybackService :
|
||||||
|
|
||||||
override fun performAction(action: InternalPlayer.Action): Boolean {
|
override fun performAction(action: InternalPlayer.Action): Boolean {
|
||||||
val library =
|
val library =
|
||||||
musicStore.library
|
musicRepository.library
|
||||||
// No library, cannot do anything.
|
// No library, cannot do anything.
|
||||||
?: return false
|
?: return false
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,6 @@ import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.list.BasicHeader
|
import org.oxycblt.auxio.list.BasicHeader
|
||||||
import org.oxycblt.auxio.list.Item
|
import org.oxycblt.auxio.list.Item
|
||||||
import org.oxycblt.auxio.music.*
|
import org.oxycblt.auxio.music.*
|
||||||
import org.oxycblt.auxio.music.MusicStore
|
|
||||||
import org.oxycblt.auxio.music.library.Library
|
import org.oxycblt.auxio.music.library.Library
|
||||||
import org.oxycblt.auxio.music.library.Sort
|
import org.oxycblt.auxio.music.library.Sort
|
||||||
import org.oxycblt.auxio.playback.PlaybackSettings
|
import org.oxycblt.auxio.playback.PlaybackSettings
|
||||||
|
@ -41,8 +40,8 @@ import org.oxycblt.auxio.util.logD
|
||||||
* @author Alexander Capehart (OxygenCobalt)
|
* @author Alexander Capehart (OxygenCobalt)
|
||||||
*/
|
*/
|
||||||
class SearchViewModel(application: Application) :
|
class SearchViewModel(application: Application) :
|
||||||
AndroidViewModel(application), MusicStore.Listener {
|
AndroidViewModel(application), MusicRepository.Listener {
|
||||||
private val musicStore = MusicStore.getInstance()
|
private val musicRepository = MusicRepository.get()
|
||||||
private val searchSettings = SearchSettings.from(application)
|
private val searchSettings = SearchSettings.from(application)
|
||||||
private val playbackSettings = PlaybackSettings.from(application)
|
private val playbackSettings = PlaybackSettings.from(application)
|
||||||
private var searchEngine = SearchEngine.from(application)
|
private var searchEngine = SearchEngine.from(application)
|
||||||
|
@ -59,12 +58,12 @@ class SearchViewModel(application: Application) :
|
||||||
get() = playbackSettings.inListPlaybackMode
|
get() = playbackSettings.inListPlaybackMode
|
||||||
|
|
||||||
init {
|
init {
|
||||||
musicStore.addListener(this)
|
musicRepository.addListener(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCleared() {
|
override fun onCleared() {
|
||||||
super.onCleared()
|
super.onCleared()
|
||||||
musicStore.removeListener(this)
|
musicRepository.removeListener(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onLibraryChanged(library: Library?) {
|
override fun onLibraryChanged(library: Library?) {
|
||||||
|
@ -84,7 +83,7 @@ class SearchViewModel(application: Application) :
|
||||||
currentSearchJob?.cancel()
|
currentSearchJob?.cancel()
|
||||||
lastQuery = query
|
lastQuery = query
|
||||||
|
|
||||||
val library = musicStore.library
|
val library = musicRepository.library
|
||||||
if (query.isNullOrEmpty() || library == null) {
|
if (query.isNullOrEmpty() || library == null) {
|
||||||
logD("Search query is not applicable.")
|
logD("Search query is not applicable.")
|
||||||
_searchResults.value = listOf()
|
_searchResults.value = listOf()
|
||||||
|
|
Loading…
Reference in a new issue