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() {
super.onCreate()
playbackFragment = playbackFragmentFactory.create(this, this)
sessionToken = playbackFragment.token
sessionToken = playbackFragment.attach()
musicFragment = musicFragmentFactory.create(this, this, this)
musicFragment.attach()
}
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 attach()
fun release()
interface Factory {
@ -71,7 +73,7 @@ private class DetailGeneratorImpl(
private val listSettings: ListSettings,
private val musicRepository: MusicRepository
) : DetailGenerator, MusicRepository.UpdateListener, ListSettings.Listener {
init {
override fun attach() {
listSettings.registerListener(this)
musicRepository.addUpdateListener(this)
}

View file

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

View file

@ -32,6 +32,10 @@ import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.util.logD
interface HomeGenerator {
fun attach()
fun release()
fun songs(): List<Song>
fun albums(): List<Album>
@ -44,8 +48,6 @@ interface HomeGenerator {
fun tabs(): List<MusicType>
fun release()
interface Invalidator {
fun invalidateMusic(type: MusicType, instructions: UpdateInstructions)
@ -74,41 +76,14 @@ private class HomeGeneratorImpl(
private val listSettings: ListSettings,
private val musicRepository: MusicRepository,
) : HomeGenerator, HomeSettings.Listener, ListSettings.Listener, MusicRepository.UpdateListener {
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 }
override fun onTabsChanged() {
invalidator.invalidateTabs()
}
init {
override fun attach() {
homeSettings.registerListener(this)
listSettings.registerListener(this)
musicRepository.addUpdateListener(this)
}
override fun release() {
musicRepository.removeUpdateListener(this)
listSettings.unregisterListener(this)
homeSettings.unregisterListener(this)
override fun onTabsChanged() {
invalidator.invalidateTabs()
}
override fun onHideCollaboratorsChanged() {
@ -161,4 +136,29 @@ private class HomeGeneratorImpl(
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,
homeGeneratorFactory: HomeGenerator.Factory
) : ViewModel(), HomeGenerator.Invalidator {
private val homeGenerator = homeGeneratorFactory.create(this)
private val _songList = MutableStateFlow(listOf<Song>())
/** A list of [Song]s, sorted by the preferred [Sort], to be shown in the home view. */
val songList: StateFlow<List<Song>>
@ -131,6 +129,8 @@ constructor(
val playlistSort: Sort
get() = listSettings.playlistSort
private val homeGenerator = homeGeneratorFactory.create(this)
/**
* A list of [MusicType] corresponding to the current [Tab] configuration, excluding invisible
* [Tab]s.

View file

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

View file

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

View file

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

View file

@ -44,20 +44,10 @@ import org.oxycblt.auxio.util.logD
*
* @author Alexander Capehart (OxygenCobalt)
*/
class ReplayGainAudioProcessor
private constructor(
class ReplayGainAudioProcessor @Inject constructor(
private val playbackManager: PlaybackStateManager,
private val playbackSettings: PlaybackSettings
) : 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
set(value) {
field = value
@ -65,7 +55,7 @@ private constructor(
flush()
}
init {
fun attach() {
playbackManager.addListener(this)
playbackSettings.registerListener(this)
}

View file

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

View file

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

View file

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

View file

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

View file

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