service: re-add attach pattern

Turns out I can't actually couple creation/attach without creating a
huge amount of variable issues.
This commit is contained in:
Alexander Capehart 2024-09-18 14:50:29 -06:00
parent 09588b3f38
commit 4917330633
14 changed files with 77 additions and 68 deletions

View file

@ -49,8 +49,9 @@ class AuxioService :
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
playbackFragment = playbackFragmentFactory.create(this, this) playbackFragment = playbackFragmentFactory.create(this, this)
sessionToken = playbackFragment.token sessionToken = playbackFragment.attach()
musicFragment = musicFragmentFactory.create(this, this, this) musicFragment = musicFragmentFactory.create(this, this, this)
musicFragment.attach()
} }
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {

View file

@ -47,6 +47,8 @@ interface DetailGenerator {
fun playlist(uid: Music.UID): Detail<Playlist>? fun playlist(uid: Music.UID): Detail<Playlist>?
fun attach()
fun release() fun release()
interface Factory { interface Factory {
@ -71,7 +73,7 @@ private class DetailGeneratorImpl(
private val listSettings: ListSettings, private val listSettings: ListSettings,
private val musicRepository: MusicRepository private val musicRepository: MusicRepository
) : DetailGenerator, MusicRepository.UpdateListener, ListSettings.Listener { ) : DetailGenerator, MusicRepository.UpdateListener, ListSettings.Listener {
init { override fun attach() {
listSettings.registerListener(this) listSettings.registerListener(this)
musicRepository.addUpdateListener(this) musicRepository.addUpdateListener(this)
} }

View file

@ -72,8 +72,6 @@ constructor(
private val playbackSettings: PlaybackSettings, private val playbackSettings: PlaybackSettings,
detailGeneratorFactory: DetailGenerator.Factory detailGeneratorFactory: DetailGenerator.Factory
) : ViewModel(), DetailGenerator.Invalidator { ) : ViewModel(), DetailGenerator.Invalidator {
private val detailGenerator = detailGeneratorFactory.create(this)
private val _toShow = MutableEvent<Show>() private val _toShow = MutableEvent<Show>()
/** /**
* A [Show] command that is awaiting a view capable of responding to it. Null if none currently. * A [Show] command that is awaiting a view capable of responding to it. Null if none currently.
@ -197,6 +195,8 @@ constructor(
playbackSettings.inParentPlaybackMode playbackSettings.inParentPlaybackMode
?: PlaySong.FromPlaylist(unlikelyToBeNull(currentPlaylist.value)) ?: PlaySong.FromPlaylist(unlikelyToBeNull(currentPlaylist.value))
private val detailGenerator = detailGeneratorFactory.create(this)
override fun onCleared() { override fun onCleared() {
detailGenerator.release() detailGenerator.release()
} }

View file

@ -32,6 +32,10 @@ import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.logD
interface HomeGenerator { interface HomeGenerator {
fun attach()
fun release()
fun songs(): List<Song> fun songs(): List<Song>
fun albums(): List<Album> fun albums(): List<Album>
@ -44,8 +48,6 @@ interface HomeGenerator {
fun tabs(): List<MusicType> fun tabs(): List<MusicType>
fun release()
interface Invalidator { interface Invalidator {
fun invalidateMusic(type: MusicType, instructions: UpdateInstructions) fun invalidateMusic(type: MusicType, instructions: UpdateInstructions)
@ -74,41 +76,14 @@ private class HomeGeneratorImpl(
private val listSettings: ListSettings, private val listSettings: ListSettings,
private val musicRepository: MusicRepository, private val musicRepository: MusicRepository,
) : HomeGenerator, HomeSettings.Listener, ListSettings.Listener, MusicRepository.UpdateListener { ) : HomeGenerator, HomeSettings.Listener, ListSettings.Listener, MusicRepository.UpdateListener {
override fun songs() = override fun attach() {
musicRepository.deviceLibrary?.let { listSettings.songSort.songs(it.songs) } ?: emptyList()
override fun albums() =
musicRepository.deviceLibrary?.let { listSettings.albumSort.albums(it.albums) }
?: emptyList()
override fun artists() =
musicRepository.deviceLibrary?.let { listSettings.artistSort.artists(it.artists) }
?: emptyList()
override fun genres() =
musicRepository.deviceLibrary?.let { listSettings.genreSort.genres(it.genres) }
?: emptyList()
override fun playlists() =
musicRepository.userLibrary?.let { listSettings.playlistSort.playlists(it.playlists) }
?: emptyList()
override fun tabs() = homeSettings.homeTabs.filterIsInstance<Tab.Visible>().map { it.type }
override fun onTabsChanged() {
invalidator.invalidateTabs()
}
init {
homeSettings.registerListener(this) homeSettings.registerListener(this)
listSettings.registerListener(this) listSettings.registerListener(this)
musicRepository.addUpdateListener(this) musicRepository.addUpdateListener(this)
} }
override fun release() { override fun onTabsChanged() {
musicRepository.removeUpdateListener(this) invalidator.invalidateTabs()
listSettings.unregisterListener(this)
homeSettings.unregisterListener(this)
} }
override fun onHideCollaboratorsChanged() { override fun onHideCollaboratorsChanged() {
@ -161,4 +136,29 @@ private class HomeGeneratorImpl(
invalidator.invalidateMusic(MusicType.PLAYLISTS, UpdateInstructions.Diff) invalidator.invalidateMusic(MusicType.PLAYLISTS, UpdateInstructions.Diff)
} }
} }
override fun release() {
musicRepository.removeUpdateListener(this)
listSettings.unregisterListener(this)
homeSettings.unregisterListener(this)
}
override fun songs() =
musicRepository.deviceLibrary?.let { listSettings.songSort.songs(it.songs) } ?: emptyList()
override fun albums() =
musicRepository.deviceLibrary?.let { listSettings.albumSort.albums(it.albums) }
?: emptyList()
override fun artists() =
musicRepository.deviceLibrary?.let { listSettings.artistSort.artists(it.artists) }
?: emptyList()
override fun genres() =
musicRepository.deviceLibrary?.let { listSettings.genreSort.genres(it.genres) }
?: emptyList()
override fun playlists() =
musicRepository.userLibrary?.let { listSettings.playlistSort.playlists(it.playlists) }
?: emptyList()
override fun tabs() = homeSettings.homeTabs.filterIsInstance<Tab.Visible>().map { it.type }
} }

View file

@ -52,8 +52,6 @@ constructor(
private val playbackSettings: PlaybackSettings, private val playbackSettings: PlaybackSettings,
homeGeneratorFactory: HomeGenerator.Factory homeGeneratorFactory: HomeGenerator.Factory
) : ViewModel(), HomeGenerator.Invalidator { ) : ViewModel(), HomeGenerator.Invalidator {
private val homeGenerator = homeGeneratorFactory.create(this)
private val _songList = MutableStateFlow(listOf<Song>()) private val _songList = MutableStateFlow(listOf<Song>())
/** A list of [Song]s, sorted by the preferred [Sort], to be shown in the home view. */ /** A list of [Song]s, sorted by the preferred [Sort], to be shown in the home view. */
val songList: StateFlow<List<Song>> val songList: StateFlow<List<Song>>
@ -131,6 +129,8 @@ constructor(
val playlistSort: Sort val playlistSort: Sort
get() = listSettings.playlistSort get() = listSettings.playlistSort
private val homeGenerator = homeGeneratorFactory.create(this)
/** /**
* A list of [MusicType] corresponding to the current [Tab] configuration, excluding invisible * A list of [MusicType] corresponding to the current [Tab] configuration, excluding invisible
* [Tab]s. * [Tab]s.

View file

@ -80,7 +80,7 @@ private constructor(
.newWakeLock( .newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK, BuildConfig.APPLICATION_ID + ":IndexingComponent") PowerManager.PARTIAL_WAKE_LOCK, BuildConfig.APPLICATION_ID + ":IndexingComponent")
init { fun attach() {
musicSettings.registerListener(this) musicSettings.registerListener(this)
musicRepository.addUpdateListener(this) musicRepository.addUpdateListener(this)
musicRepository.addIndexingListener(this) musicRepository.addIndexingListener(this)

View file

@ -71,6 +71,11 @@ private constructor(
private val homeGenerator = homeGeneratorFactory.create(this) private val homeGenerator = homeGeneratorFactory.create(this)
private val detailGenerator = detailGeneratorFactory.create(this) private val detailGenerator = detailGeneratorFactory.create(this)
fun attach() {
homeGenerator.attach()
detailGenerator.attach()
}
fun release() { fun release() {
homeGenerator.release() homeGenerator.release()
detailGenerator.release() detailGenerator.release()

View file

@ -74,6 +74,11 @@ constructor(
fun invalidateMusic(mediaId: String) fun invalidateMusic(mediaId: String)
} }
fun attach() {
indexer.attach()
musicBrowser.attach()
}
fun release() { fun release() {
dispatchJob.cancel() dispatchJob.cancel()
musicBrowser.release() musicBrowser.release()

View file

@ -44,20 +44,10 @@ import org.oxycblt.auxio.util.logD
* *
* @author Alexander Capehart (OxygenCobalt) * @author Alexander Capehart (OxygenCobalt)
*/ */
class ReplayGainAudioProcessor class ReplayGainAudioProcessor @Inject constructor(
private constructor(
private val playbackManager: PlaybackStateManager, private val playbackManager: PlaybackStateManager,
private val playbackSettings: PlaybackSettings private val playbackSettings: PlaybackSettings
) : BaseAudioProcessor(), PlaybackStateManager.Listener, PlaybackSettings.Listener { ) : BaseAudioProcessor(), PlaybackStateManager.Listener, PlaybackSettings.Listener {
class Factory
@Inject
constructor(
private val playbackManager: PlaybackStateManager,
private val playbackSettings: PlaybackSettings
) {
fun create() = ReplayGainAudioProcessor(playbackManager, playbackSettings)
}
private var volume = 1f private var volume = 1f
set(value) { set(value) {
field = value field = value
@ -65,7 +55,7 @@ private constructor(
flush() flush()
} }
init { fun attach() {
playbackManager.addListener(this) playbackManager.addListener(this)
playbackSettings.registerListener(this) playbackSettings.registerListener(this)
} }

View file

@ -86,7 +86,7 @@ class ExoPlaybackStateHolder(
var sessionOngoing = false var sessionOngoing = false
private set private set
init { fun attach() {
imageSettings.registerListener(this) imageSettings.registerListener(this)
player.addListener(this) player.addListener(this)
playbackManager.registerStateHolder(this) playbackManager.registerStateHolder(this)
@ -581,14 +581,13 @@ class ExoPlaybackStateHolder(
private val playbackSettings: PlaybackSettings, private val playbackSettings: PlaybackSettings,
private val commandFactory: PlaybackCommand.Factory, private val commandFactory: PlaybackCommand.Factory,
private val mediaSourceFactory: MediaSource.Factory, private val mediaSourceFactory: MediaSource.Factory,
private val replayGainProcessorFactory: ReplayGainAudioProcessor.Factory, private val replayGainProcessor: ReplayGainAudioProcessor,
private val musicRepository: MusicRepository, private val musicRepository: MusicRepository,
private val imageSettings: ImageSettings, private val imageSettings: ImageSettings,
) { ) {
fun create(): ExoPlaybackStateHolder { fun create(): ExoPlaybackStateHolder {
// Since Auxio is a music player, only specify an audio renderer to save // Since Auxio is a music player, only specify an audio renderer to save
// battery/apk size/cache size // battery/apk size/cache size]
val replayGainProcessor = replayGainProcessorFactory.create()
val audioRenderer = RenderersFactory { handler, _, audioListener, _, _ -> val audioRenderer = RenderersFactory { handler, _, audioListener, _, _ ->
arrayOf( arrayOf(
FfmpegAudioRenderer(handler, audioListener, replayGainProcessor), FfmpegAudioRenderer(handler, audioListener, replayGainProcessor),

View file

@ -96,7 +96,7 @@ private constructor(
val notification: ForegroundServiceNotification val notification: ForegroundServiceNotification
get() = _notification get() = _notification
init { fun attach() {
playbackManager.addListener(this) playbackManager.addListener(this)
playbackSettings.registerListener(this) playbackSettings.registerListener(this)
imageSettings.registerListener(this) imageSettings.registerListener(this)

View file

@ -66,13 +66,15 @@ private constructor(
private val widgetComponent = widgetComponentFactory.create(context) private val widgetComponent = widgetComponentFactory.create(context)
private val systemReceiver = systemReceiverFactory.create(context, widgetComponent) private val systemReceiver = systemReceiverFactory.create(context, widgetComponent)
val token: MediaSessionCompat.Token
get() = sessionHolder.token
// --- MEDIASESSION CALLBACKS --- // --- MEDIASESSION CALLBACKS ---
init { fun attach(): MediaSessionCompat.Token {
exoHolder.attach()
sessionHolder.attach()
widgetComponent.attach()
systemReceiver.attach()
playbackManager.addListener(this) playbackManager.addListener(this)
return sessionHolder.token
} }
fun handleTaskRemoved() { fun handleTaskRemoved() {

View file

@ -37,6 +37,7 @@ import org.oxycblt.auxio.widgets.WidgetProvider
*/ */
class SystemPlaybackReceiver class SystemPlaybackReceiver
private constructor( private constructor(
private val context: Context,
private val playbackManager: PlaybackStateManager, private val playbackManager: PlaybackStateManager,
private val playbackSettings: PlaybackSettings, private val playbackSettings: PlaybackSettings,
private val widgetComponent: WidgetComponent private val widgetComponent: WidgetComponent
@ -49,13 +50,17 @@ private constructor(
private val playbackManager: PlaybackStateManager, private val playbackManager: PlaybackStateManager,
private val playbackSettings: PlaybackSettings private val playbackSettings: PlaybackSettings
) { ) {
fun create(context: Context, widgetComponent: WidgetComponent): SystemPlaybackReceiver { fun create(context: Context, widgetComponent: WidgetComponent) =
val receiver = SystemPlaybackReceiver(context, playbackManager, playbackSettings, widgetComponent)
SystemPlaybackReceiver(playbackManager, playbackSettings, widgetComponent) }
ContextCompat.registerReceiver(
context, receiver, INTENT_FILTER, ContextCompat.RECEIVER_EXPORTED) fun attach() {
return receiver ContextCompat.registerReceiver(
} context, this, INTENT_FILTER, ContextCompat.RECEIVER_EXPORTED)
}
fun release() {
context.unregisterReceiver(this)
} }
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {

View file

@ -67,7 +67,7 @@ private constructor(
private val widgetProvider = WidgetProvider() private val widgetProvider = WidgetProvider()
init { fun attach() {
playbackManager.addListener(this) playbackManager.addListener(this)
uiSettings.registerListener(this) uiSettings.registerListener(this)
imageSettings.registerListener(this) imageSettings.registerListener(this)