diff --git a/app/src/main/java/org/oxycblt/auxio/AuxioService.kt b/app/src/main/java/org/oxycblt/auxio/AuxioService.kt index 1b6a1a4c5..fb0f2aaac 100644 --- a/app/src/main/java/org/oxycblt/auxio/AuxioService.kt +++ b/app/src/main/java/org/oxycblt/auxio/AuxioService.kt @@ -38,16 +38,18 @@ import org.oxycblt.auxio.playback.service.PlaybackServiceFragment @AndroidEntryPoint class AuxioService : - MediaBrowserServiceCompat(), ForegroundListener, MusicServiceFragment.Invalidator { - @Inject lateinit var playbackFragment: PlaybackServiceFragment + MediaBrowserServiceCompat(), ForegroundListener, MusicServiceFragment.Invalidator { + @Inject lateinit var playbackFragmentFactory: PlaybackServiceFragment.Factory + private lateinit var playbackFragment: PlaybackServiceFragment @Inject lateinit var musicFragmentFactory: MusicServiceFragment.Factory - lateinit var musicFragment: MusicServiceFragment + private lateinit var musicFragment: MusicServiceFragment @SuppressLint("WrongConstant") override fun onCreate() { super.onCreate() - sessionToken = playbackFragment.attach(this) + playbackFragment = playbackFragmentFactory.create(this, this) + sessionToken = playbackFragment.token musicFragment = musicFragmentFactory.create(this, this, this) } diff --git a/app/src/main/java/org/oxycblt/auxio/playback/replaygain/ReplayGainAudioProcessor.kt b/app/src/main/java/org/oxycblt/auxio/playback/replaygain/ReplayGainAudioProcessor.kt index 1152ef4e3..9c9b8e695 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/replaygain/ReplayGainAudioProcessor.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/replaygain/ReplayGainAudioProcessor.kt @@ -44,12 +44,17 @@ import org.oxycblt.auxio.util.logD * * @author Alexander Capehart (OxygenCobalt) */ -class ReplayGainAudioProcessor -@Inject -constructor( +class ReplayGainAudioProcessor private 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 @@ -57,7 +62,7 @@ constructor( flush() } - fun attach() { + init { playbackManager.addListener(this) playbackSettings.registerListener(this) } diff --git a/app/src/main/java/org/oxycblt/auxio/playback/service/ExoPlaybackStateHolder.kt b/app/src/main/java/org/oxycblt/auxio/playback/service/ExoPlaybackStateHolder.kt index 203176ebd..b705cf1ab 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/service/ExoPlaybackStateHolder.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/service/ExoPlaybackStateHolder.kt @@ -86,10 +86,9 @@ class ExoPlaybackStateHolder( var sessionOngoing = false private set - fun attach() { + init { imageSettings.registerListener(this) player.addListener(this) - replayGainProcessor.attach() playbackManager.registerStateHolder(this) playbackSettings.registerListener(this) musicRepository.addUpdateListener(this) @@ -582,13 +581,14 @@ class ExoPlaybackStateHolder( private val playbackSettings: PlaybackSettings, private val commandFactory: PlaybackCommand.Factory, private val mediaSourceFactory: MediaSource.Factory, - private val replayGainProcessor: ReplayGainAudioProcessor, + private val replayGainProcessorFactory: ReplayGainAudioProcessor.Factory, 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() val audioRenderer = RenderersFactory { handler, _, audioListener, _, _ -> arrayOf( FfmpegAudioRenderer(handler, audioListener, replayGainProcessor), diff --git a/app/src/main/java/org/oxycblt/auxio/playback/service/PlaybackServiceFragment.kt b/app/src/main/java/org/oxycblt/auxio/playback/service/PlaybackServiceFragment.kt index 0bb5b9fda..399aefa55 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/service/PlaybackServiceFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/service/PlaybackServiceFragment.kt @@ -34,36 +34,38 @@ import org.oxycblt.auxio.playback.state.PlaybackStateManager import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.widgets.WidgetComponent -class PlaybackServiceFragment -@Inject -constructor( - @ApplicationContext private val context: Context, +class PlaybackServiceFragment private constructor( + private val context: Context, + private val foregroundListener: ForegroundListener, private val playbackManager: PlaybackStateManager, - private val playbackSettings: PlaybackSettings, - private val sessionHolderFactory: MediaSessionHolder.Factory, - private val widgetComponent: WidgetComponent, - exoHolderFactory: ExoPlaybackStateHolder.Factory + exoHolderFactory: ExoPlaybackStateHolder.Factory, + sessionHolderFactory: MediaSessionHolder.Factory, + widgetComponentFactory: WidgetComponent.Factory, + systemReceiverFactory: SystemPlaybackReceiver.Factory, ) : MediaSessionCompat.Callback(), PlaybackStateManager.Listener { + class Factory @Inject constructor( + private val playbackManager: PlaybackStateManager, + private val exoHolderFactory: ExoPlaybackStateHolder.Factory, + private val sessionHolderFactory: MediaSessionHolder.Factory, + private val widgetComponentFactory: WidgetComponent.Factory, + private val systemReceiverFactory: SystemPlaybackReceiver.Factory, + ) { + fun create(context: Context, foregroundListener: ForegroundListener) = + PlaybackServiceFragment(context, foregroundListener, playbackManager, exoHolderFactory, sessionHolderFactory, widgetComponentFactory, systemReceiverFactory) + } + private val waitJob = Job() private val exoHolder = exoHolderFactory.create() - private var foregroundListener: ForegroundListener? = null + private val sessionHolder = sessionHolderFactory.create(context, foregroundListener) + private val widgetComponent = widgetComponentFactory.create(context) + private val systemReceiver = systemReceiverFactory.create(context) - private lateinit var sessionHolder: MediaSessionHolder - private lateinit var systemReceiver: SystemPlaybackReceiver + val token: MediaSessionCompat.Token get() = sessionHolder.token // --- MEDIASESSION CALLBACKS --- - @SuppressLint("WrongConstant") - fun attach(listener: ForegroundListener): MediaSessionCompat.Token { - foregroundListener = listener + init { playbackManager.addListener(this) - exoHolder.attach() - sessionHolder = sessionHolderFactory.create(context, listener) - systemReceiver = SystemPlaybackReceiver(playbackManager, playbackSettings, widgetComponent) - ContextCompat.registerReceiver( - context, systemReceiver, systemReceiver.intentFilter, ContextCompat.RECEIVER_EXPORTED) - widgetComponent.attach() - return sessionHolder.token } fun handleTaskRemoved() { @@ -101,10 +103,9 @@ constructor( sessionHolder.release() exoHolder.release() playbackManager.removeListener(this) - foregroundListener = null } override fun onSessionEnded() { - foregroundListener?.updateForeground(ForegroundListener.Change.MEDIA_SESSION) + foregroundListener.updateForeground(ForegroundListener.Change.MEDIA_SESSION) } } diff --git a/app/src/main/java/org/oxycblt/auxio/playback/service/SystemPlaybackReceiver.kt b/app/src/main/java/org/oxycblt/auxio/playback/service/SystemPlaybackReceiver.kt index d671219a1..f7c7110f0 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/service/SystemPlaybackReceiver.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/service/SystemPlaybackReceiver.kt @@ -23,34 +23,36 @@ import android.content.Context import android.content.Intent import android.content.IntentFilter import android.media.AudioManager +import androidx.core.content.ContextCompat import org.oxycblt.auxio.playback.PlaybackSettings import org.oxycblt.auxio.playback.state.PlaybackStateManager import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.widgets.WidgetComponent import org.oxycblt.auxio.widgets.WidgetProvider +import javax.inject.Inject /** * A [BroadcastReceiver] for receiving playback-specific [Intent]s from the system that require an * active [IntentFilter] to be registered. */ -class SystemPlaybackReceiver( +class SystemPlaybackReceiver private constructor( private val playbackManager: PlaybackStateManager, private val playbackSettings: PlaybackSettings, private val widgetComponent: WidgetComponent ) : BroadcastReceiver() { private var initialHeadsetPlugEventHandled = false - val intentFilter = - IntentFilter().apply { - addAction(AudioManager.ACTION_AUDIO_BECOMING_NOISY) - addAction(AudioManager.ACTION_HEADSET_PLUG) - addAction(PlaybackActions.ACTION_INC_REPEAT_MODE) - addAction(PlaybackActions.ACTION_INVERT_SHUFFLE) - addAction(PlaybackActions.ACTION_SKIP_PREV) - addAction(PlaybackActions.ACTION_PLAY_PAUSE) - addAction(PlaybackActions.ACTION_SKIP_NEXT) - addAction(WidgetProvider.ACTION_WIDGET_UPDATE) + class Factory @Inject constructor( + private val playbackManager: PlaybackStateManager, + private val playbackSettings: PlaybackSettings, + private val widgetComponent: WidgetComponent + ) { + fun create(context: Context): SystemPlaybackReceiver { + val receiver = SystemPlaybackReceiver(playbackManager, playbackSettings, widgetComponent) + ContextCompat.registerReceiver(context, receiver, INTENT_FILTER, ContextCompat.RECEIVER_EXPORTED) + return receiver } + } override fun onReceive(context: Context, intent: Intent) { when (intent.action) { @@ -127,4 +129,18 @@ class SystemPlaybackReceiver( playbackManager.playing(false) } } + + private companion object { + val INTENT_FILTER = + IntentFilter().apply { + addAction(AudioManager.ACTION_AUDIO_BECOMING_NOISY) + addAction(AudioManager.ACTION_HEADSET_PLUG) + addAction(PlaybackActions.ACTION_INC_REPEAT_MODE) + addAction(PlaybackActions.ACTION_INVERT_SHUFFLE) + addAction(PlaybackActions.ACTION_SKIP_PREV) + addAction(PlaybackActions.ACTION_PLAY_PAUSE) + addAction(PlaybackActions.ACTION_SKIP_NEXT) + addAction(WidgetProvider.ACTION_WIDGET_UPDATE) + } + } } diff --git a/app/src/main/java/org/oxycblt/auxio/widgets/WidgetComponent.kt b/app/src/main/java/org/oxycblt/auxio/widgets/WidgetComponent.kt index bb8caf693..2afa5b177 100644 --- a/app/src/main/java/org/oxycblt/auxio/widgets/WidgetComponent.kt +++ b/app/src/main/java/org/oxycblt/auxio/widgets/WidgetComponent.kt @@ -46,18 +46,25 @@ import org.oxycblt.auxio.util.logD * * @author Alexander Capehart (OxygenCobalt) */ -class WidgetComponent -@Inject -constructor( - @ApplicationContext private val context: Context, +class WidgetComponent private constructor( + private val context: Context, private val imageSettings: ImageSettings, private val bitmapProvider: BitmapProvider, private val playbackManager: PlaybackStateManager, private val uiSettings: UISettings ) : PlaybackStateManager.Listener, UISettings.Listener, ImageSettings.Listener { + class Factory @Inject constructor( + private val imageSettings: ImageSettings, + private val bitmapProvider: BitmapProvider, + private val playbackManager: PlaybackStateManager, + private val uiSettings: UISettings + ) { + fun create(context: Context) = WidgetComponent(context, imageSettings, bitmapProvider, playbackManager, uiSettings) + } + private val widgetProvider = WidgetProvider() - fun attach() { + init { playbackManager.addListener(this) uiSettings.registerListener(this) imageSettings.registerListener(this)