playback: use factory pattern
This commit is contained in:
parent
8418dccdc6
commit
a3af24688a
6 changed files with 81 additions and 50 deletions
|
@ -39,15 +39,17 @@ import org.oxycblt.auxio.playback.service.PlaybackServiceFragment
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class AuxioService :
|
class AuxioService :
|
||||||
MediaBrowserServiceCompat(), ForegroundListener, MusicServiceFragment.Invalidator {
|
MediaBrowserServiceCompat(), ForegroundListener, MusicServiceFragment.Invalidator {
|
||||||
@Inject lateinit var playbackFragment: PlaybackServiceFragment
|
@Inject lateinit var playbackFragmentFactory: PlaybackServiceFragment.Factory
|
||||||
|
private lateinit var playbackFragment: PlaybackServiceFragment
|
||||||
|
|
||||||
@Inject lateinit var musicFragmentFactory: MusicServiceFragment.Factory
|
@Inject lateinit var musicFragmentFactory: MusicServiceFragment.Factory
|
||||||
lateinit var musicFragment: MusicServiceFragment
|
private lateinit var musicFragment: MusicServiceFragment
|
||||||
|
|
||||||
@SuppressLint("WrongConstant")
|
@SuppressLint("WrongConstant")
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
sessionToken = playbackFragment.attach(this)
|
playbackFragment = playbackFragmentFactory.create(this, this)
|
||||||
|
sessionToken = playbackFragment.token
|
||||||
musicFragment = musicFragmentFactory.create(this, this, this)
|
musicFragment = musicFragmentFactory.create(this, this, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,12 +44,17 @@ import org.oxycblt.auxio.util.logD
|
||||||
*
|
*
|
||||||
* @author Alexander Capehart (OxygenCobalt)
|
* @author Alexander Capehart (OxygenCobalt)
|
||||||
*/
|
*/
|
||||||
class ReplayGainAudioProcessor
|
class ReplayGainAudioProcessor private constructor(
|
||||||
@Inject
|
|
||||||
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
|
||||||
|
@ -57,7 +62,7 @@ constructor(
|
||||||
flush()
|
flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun attach() {
|
init {
|
||||||
playbackManager.addListener(this)
|
playbackManager.addListener(this)
|
||||||
playbackSettings.registerListener(this)
|
playbackSettings.registerListener(this)
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,10 +86,9 @@ class ExoPlaybackStateHolder(
|
||||||
var sessionOngoing = false
|
var sessionOngoing = false
|
||||||
private set
|
private set
|
||||||
|
|
||||||
fun attach() {
|
init {
|
||||||
imageSettings.registerListener(this)
|
imageSettings.registerListener(this)
|
||||||
player.addListener(this)
|
player.addListener(this)
|
||||||
replayGainProcessor.attach()
|
|
||||||
playbackManager.registerStateHolder(this)
|
playbackManager.registerStateHolder(this)
|
||||||
playbackSettings.registerListener(this)
|
playbackSettings.registerListener(this)
|
||||||
musicRepository.addUpdateListener(this)
|
musicRepository.addUpdateListener(this)
|
||||||
|
@ -582,13 +581,14 @@ 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 replayGainProcessor: ReplayGainAudioProcessor,
|
private val replayGainProcessorFactory: ReplayGainAudioProcessor.Factory,
|
||||||
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),
|
||||||
|
|
|
@ -34,36 +34,38 @@ import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
||||||
import org.oxycblt.auxio.util.logD
|
import org.oxycblt.auxio.util.logD
|
||||||
import org.oxycblt.auxio.widgets.WidgetComponent
|
import org.oxycblt.auxio.widgets.WidgetComponent
|
||||||
|
|
||||||
class PlaybackServiceFragment
|
class PlaybackServiceFragment private constructor(
|
||||||
@Inject
|
private val context: Context,
|
||||||
constructor(
|
private val foregroundListener: ForegroundListener,
|
||||||
@ApplicationContext private val context: Context,
|
|
||||||
private val playbackManager: PlaybackStateManager,
|
private val playbackManager: PlaybackStateManager,
|
||||||
private val playbackSettings: PlaybackSettings,
|
exoHolderFactory: ExoPlaybackStateHolder.Factory,
|
||||||
private val sessionHolderFactory: MediaSessionHolder.Factory,
|
sessionHolderFactory: MediaSessionHolder.Factory,
|
||||||
private val widgetComponent: WidgetComponent,
|
widgetComponentFactory: WidgetComponent.Factory,
|
||||||
exoHolderFactory: ExoPlaybackStateHolder.Factory
|
systemReceiverFactory: SystemPlaybackReceiver.Factory,
|
||||||
) : MediaSessionCompat.Callback(), PlaybackStateManager.Listener {
|
) : 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 waitJob = Job()
|
||||||
private val exoHolder = exoHolderFactory.create()
|
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
|
val token: MediaSessionCompat.Token get() = sessionHolder.token
|
||||||
private lateinit var systemReceiver: SystemPlaybackReceiver
|
|
||||||
|
|
||||||
// --- MEDIASESSION CALLBACKS ---
|
// --- MEDIASESSION CALLBACKS ---
|
||||||
|
|
||||||
@SuppressLint("WrongConstant")
|
init {
|
||||||
fun attach(listener: ForegroundListener): MediaSessionCompat.Token {
|
|
||||||
foregroundListener = listener
|
|
||||||
playbackManager.addListener(this)
|
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() {
|
fun handleTaskRemoved() {
|
||||||
|
@ -101,10 +103,9 @@ constructor(
|
||||||
sessionHolder.release()
|
sessionHolder.release()
|
||||||
exoHolder.release()
|
exoHolder.release()
|
||||||
playbackManager.removeListener(this)
|
playbackManager.removeListener(this)
|
||||||
foregroundListener = null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSessionEnded() {
|
override fun onSessionEnded() {
|
||||||
foregroundListener?.updateForeground(ForegroundListener.Change.MEDIA_SESSION)
|
foregroundListener.updateForeground(ForegroundListener.Change.MEDIA_SESSION)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,33 +23,35 @@ import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
import android.media.AudioManager
|
import android.media.AudioManager
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import org.oxycblt.auxio.playback.PlaybackSettings
|
import org.oxycblt.auxio.playback.PlaybackSettings
|
||||||
import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
||||||
import org.oxycblt.auxio.util.logD
|
import org.oxycblt.auxio.util.logD
|
||||||
import org.oxycblt.auxio.widgets.WidgetComponent
|
import org.oxycblt.auxio.widgets.WidgetComponent
|
||||||
import org.oxycblt.auxio.widgets.WidgetProvider
|
import org.oxycblt.auxio.widgets.WidgetProvider
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A [BroadcastReceiver] for receiving playback-specific [Intent]s from the system that require an
|
* A [BroadcastReceiver] for receiving playback-specific [Intent]s from the system that require an
|
||||||
* active [IntentFilter] to be registered.
|
* active [IntentFilter] to be registered.
|
||||||
*/
|
*/
|
||||||
class SystemPlaybackReceiver(
|
class SystemPlaybackReceiver private constructor(
|
||||||
private val playbackManager: PlaybackStateManager,
|
private val playbackManager: PlaybackStateManager,
|
||||||
private val playbackSettings: PlaybackSettings,
|
private val playbackSettings: PlaybackSettings,
|
||||||
private val widgetComponent: WidgetComponent
|
private val widgetComponent: WidgetComponent
|
||||||
) : BroadcastReceiver() {
|
) : BroadcastReceiver() {
|
||||||
private var initialHeadsetPlugEventHandled = false
|
private var initialHeadsetPlugEventHandled = false
|
||||||
|
|
||||||
val intentFilter =
|
class Factory @Inject constructor(
|
||||||
IntentFilter().apply {
|
private val playbackManager: PlaybackStateManager,
|
||||||
addAction(AudioManager.ACTION_AUDIO_BECOMING_NOISY)
|
private val playbackSettings: PlaybackSettings,
|
||||||
addAction(AudioManager.ACTION_HEADSET_PLUG)
|
private val widgetComponent: WidgetComponent
|
||||||
addAction(PlaybackActions.ACTION_INC_REPEAT_MODE)
|
) {
|
||||||
addAction(PlaybackActions.ACTION_INVERT_SHUFFLE)
|
fun create(context: Context): SystemPlaybackReceiver {
|
||||||
addAction(PlaybackActions.ACTION_SKIP_PREV)
|
val receiver = SystemPlaybackReceiver(playbackManager, playbackSettings, widgetComponent)
|
||||||
addAction(PlaybackActions.ACTION_PLAY_PAUSE)
|
ContextCompat.registerReceiver(context, receiver, INTENT_FILTER, ContextCompat.RECEIVER_EXPORTED)
|
||||||
addAction(PlaybackActions.ACTION_SKIP_NEXT)
|
return receiver
|
||||||
addAction(WidgetProvider.ACTION_WIDGET_UPDATE)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onReceive(context: Context, intent: Intent) {
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
|
@ -127,4 +129,18 @@ class SystemPlaybackReceiver(
|
||||||
playbackManager.playing(false)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,18 +46,25 @@ import org.oxycblt.auxio.util.logD
|
||||||
*
|
*
|
||||||
* @author Alexander Capehart (OxygenCobalt)
|
* @author Alexander Capehart (OxygenCobalt)
|
||||||
*/
|
*/
|
||||||
class WidgetComponent
|
class WidgetComponent private constructor(
|
||||||
@Inject
|
private val context: Context,
|
||||||
constructor(
|
|
||||||
@ApplicationContext private val context: Context,
|
|
||||||
private val imageSettings: ImageSettings,
|
private val imageSettings: ImageSettings,
|
||||||
private val bitmapProvider: BitmapProvider,
|
private val bitmapProvider: BitmapProvider,
|
||||||
private val playbackManager: PlaybackStateManager,
|
private val playbackManager: PlaybackStateManager,
|
||||||
private val uiSettings: UISettings
|
private val uiSettings: UISettings
|
||||||
) : PlaybackStateManager.Listener, UISettings.Listener, ImageSettings.Listener {
|
) : 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()
|
private val widgetProvider = WidgetProvider()
|
||||||
|
|
||||||
fun attach() {
|
init {
|
||||||
playbackManager.addListener(this)
|
playbackManager.addListener(this)
|
||||||
uiSettings.registerListener(this)
|
uiSettings.registerListener(this)
|
||||||
imageSettings.registerListener(this)
|
imageSettings.registerListener(this)
|
||||||
|
|
Loading…
Reference in a new issue