playback: fully use di
Fully use DI in the playback module. Previously use was split among different components that could leverage injection, and components that could not. This fully unifies them.
This commit is contained in:
parent
9f74fe8a20
commit
63e5a7ee69
11 changed files with 75 additions and 82 deletions
|
@ -196,7 +196,7 @@ private abstract class BaseMediaStoreExtractor(
|
||||||
if (cache?.populate(rawSong) == true) {
|
if (cache?.populate(rawSong) == true) {
|
||||||
completeSongs.send(rawSong)
|
completeSongs.send(rawSong)
|
||||||
} else {
|
} else {
|
||||||
query.populateFileInfo(rawSong)
|
query.populateTags(rawSong)
|
||||||
incompleteSongs.send(rawSong)
|
incompleteSongs.send(rawSong)
|
||||||
}
|
}
|
||||||
yield()
|
yield()
|
||||||
|
|
|
@ -17,17 +17,19 @@
|
||||||
|
|
||||||
package org.oxycblt.auxio.playback
|
package org.oxycblt.auxio.playback
|
||||||
|
|
||||||
import android.content.Context
|
import dagger.Binds
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
|
||||||
import dagger.hilt.InstallIn
|
import dagger.hilt.InstallIn
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
|
||||||
import dagger.hilt.components.SingletonComponent
|
import dagger.hilt.components.SingletonComponent
|
||||||
|
import javax.inject.Singleton
|
||||||
import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
||||||
|
import org.oxycblt.auxio.playback.state.PlaybackStateManagerImpl
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
@InstallIn(SingletonComponent::class)
|
@InstallIn(SingletonComponent::class)
|
||||||
class PlaybackModule {
|
interface PlaybackModule {
|
||||||
@Provides fun stateManager() = PlaybackStateManager.get()
|
@Singleton
|
||||||
@Provides fun settings(@ApplicationContext context: Context) = PlaybackSettings.from(context)
|
@Binds
|
||||||
|
fun stateManager(playbackManager: PlaybackStateManagerImpl): PlaybackStateManager
|
||||||
|
@Binds fun settings(playbackSettings: PlaybackSettingsImpl): PlaybackSettings
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ package org.oxycblt.auxio.playback
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
|
import javax.inject.Inject
|
||||||
import org.oxycblt.auxio.IntegerTable
|
import org.oxycblt.auxio.IntegerTable
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.music.MusicMode
|
import org.oxycblt.auxio.music.MusicMode
|
||||||
|
@ -65,17 +67,9 @@ interface PlaybackSettings : Settings<PlaybackSettings.Listener> {
|
||||||
/** Called when [notificationAction] has changed. */
|
/** Called when [notificationAction] has changed. */
|
||||||
fun onNotificationActionChanged() {}
|
fun onNotificationActionChanged() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
|
||||||
/**
|
|
||||||
* Get a framework-backed implementation.
|
|
||||||
* @param context [Context] required.
|
|
||||||
*/
|
|
||||||
fun from(context: Context): PlaybackSettings = PlaybackSettingsImpl(context)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class PlaybackSettingsImpl(context: Context) :
|
class PlaybackSettingsImpl @Inject constructor(@ApplicationContext context: Context) :
|
||||||
Settings.Impl<PlaybackSettings.Listener>(context), PlaybackSettings {
|
Settings.Impl<PlaybackSettings.Listener>(context), PlaybackSettings {
|
||||||
override val inListPlaybackMode: MusicMode
|
override val inListPlaybackMode: MusicMode
|
||||||
get() =
|
get() =
|
||||||
|
|
|
@ -21,6 +21,8 @@ import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import javax.inject.Inject
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.databinding.DialogPreAmpBinding
|
import org.oxycblt.auxio.databinding.DialogPreAmpBinding
|
||||||
|
@ -31,7 +33,10 @@ import org.oxycblt.auxio.ui.ViewBindingDialogFragment
|
||||||
* aa [ViewBindingDialogFragment] that allows user configuration of the current [ReplayGainPreAmp].
|
* aa [ViewBindingDialogFragment] that allows user configuration of the current [ReplayGainPreAmp].
|
||||||
* @author Alexander Capehart (OxygenCobalt)
|
* @author Alexander Capehart (OxygenCobalt)
|
||||||
*/
|
*/
|
||||||
|
@AndroidEntryPoint
|
||||||
class PreAmpCustomizeDialog : ViewBindingDialogFragment<DialogPreAmpBinding>() {
|
class PreAmpCustomizeDialog : ViewBindingDialogFragment<DialogPreAmpBinding>() {
|
||||||
|
@Inject lateinit var playbackSettings: PlaybackSettings
|
||||||
|
|
||||||
override fun onCreateBinding(inflater: LayoutInflater) = DialogPreAmpBinding.inflate(inflater)
|
override fun onCreateBinding(inflater: LayoutInflater) = DialogPreAmpBinding.inflate(inflater)
|
||||||
|
|
||||||
override fun onConfigDialog(builder: AlertDialog.Builder) {
|
override fun onConfigDialog(builder: AlertDialog.Builder) {
|
||||||
|
@ -39,11 +44,11 @@ class PreAmpCustomizeDialog : ViewBindingDialogFragment<DialogPreAmpBinding>() {
|
||||||
.setTitle(R.string.set_pre_amp)
|
.setTitle(R.string.set_pre_amp)
|
||||||
.setPositiveButton(R.string.lbl_ok) { _, _ ->
|
.setPositiveButton(R.string.lbl_ok) { _, _ ->
|
||||||
val binding = requireBinding()
|
val binding = requireBinding()
|
||||||
PlaybackSettings.from(requireContext()).replayGainPreAmp =
|
playbackSettings.replayGainPreAmp =
|
||||||
ReplayGainPreAmp(binding.withTagsSlider.value, binding.withoutTagsSlider.value)
|
ReplayGainPreAmp(binding.withTagsSlider.value, binding.withoutTagsSlider.value)
|
||||||
}
|
}
|
||||||
.setNeutralButton(R.string.lbl_reset) { _, _ ->
|
.setNeutralButton(R.string.lbl_reset) { _, _ ->
|
||||||
PlaybackSettings.from(requireContext()).replayGainPreAmp = ReplayGainPreAmp(0f, 0f)
|
playbackSettings.replayGainPreAmp = ReplayGainPreAmp(0f, 0f)
|
||||||
}
|
}
|
||||||
.setNegativeButton(R.string.lbl_cancel, null)
|
.setNegativeButton(R.string.lbl_cancel, null)
|
||||||
}
|
}
|
||||||
|
@ -53,7 +58,7 @@ class PreAmpCustomizeDialog : ViewBindingDialogFragment<DialogPreAmpBinding>() {
|
||||||
// First initialization, we need to supply the sliders with the values from
|
// First initialization, we need to supply the sliders with the values from
|
||||||
// settings. After this, the sliders save their own state, so we do not need to
|
// settings. After this, the sliders save their own state, so we do not need to
|
||||||
// do any restore behavior.
|
// do any restore behavior.
|
||||||
val preAmp = PlaybackSettings.from(requireContext()).replayGainPreAmp
|
val preAmp = playbackSettings.replayGainPreAmp
|
||||||
binding.withTagsSlider.value = preAmp.with
|
binding.withTagsSlider.value = preAmp.with
|
||||||
binding.withoutTagsSlider.value = preAmp.without
|
binding.withoutTagsSlider.value = preAmp.without
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
|
|
||||||
package org.oxycblt.auxio.playback.replaygain
|
package org.oxycblt.auxio.playback.replaygain
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import com.google.android.exoplayer2.C
|
import com.google.android.exoplayer2.C
|
||||||
import com.google.android.exoplayer2.Format
|
import com.google.android.exoplayer2.Format
|
||||||
import com.google.android.exoplayer2.Player
|
import com.google.android.exoplayer2.Player
|
||||||
|
@ -26,6 +25,7 @@ import com.google.android.exoplayer2.audio.AudioProcessor
|
||||||
import com.google.android.exoplayer2.audio.BaseAudioProcessor
|
import com.google.android.exoplayer2.audio.BaseAudioProcessor
|
||||||
import com.google.android.exoplayer2.util.MimeTypes
|
import com.google.android.exoplayer2.util.MimeTypes
|
||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
|
import javax.inject.Inject
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
import org.oxycblt.auxio.music.Album
|
import org.oxycblt.auxio.music.Album
|
||||||
import org.oxycblt.auxio.music.metadata.TextTags
|
import org.oxycblt.auxio.music.metadata.TextTags
|
||||||
|
@ -43,10 +43,12 @@ import org.oxycblt.auxio.util.logD
|
||||||
*
|
*
|
||||||
* @author Alexander Capehart (OxygenCobalt)
|
* @author Alexander Capehart (OxygenCobalt)
|
||||||
*/
|
*/
|
||||||
class ReplayGainAudioProcessor(context: Context) :
|
class ReplayGainAudioProcessor
|
||||||
BaseAudioProcessor(), Player.Listener, PlaybackSettings.Listener {
|
@Inject
|
||||||
private val playbackManager = PlaybackStateManager.get()
|
constructor(
|
||||||
private val playbackSettings = PlaybackSettings.from(context)
|
private val playbackManager: PlaybackStateManager,
|
||||||
|
private val playbackSettings: PlaybackSettings
|
||||||
|
) : BaseAudioProcessor(), Player.Listener, PlaybackSettings.Listener {
|
||||||
private var lastFormat: Format? = null
|
private var lastFormat: Format? = null
|
||||||
|
|
||||||
private var volume = 1f
|
private var volume = 1f
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
package org.oxycblt.auxio.playback.state
|
package org.oxycblt.auxio.playback.state
|
||||||
|
|
||||||
|
import javax.inject.Inject
|
||||||
import org.oxycblt.auxio.BuildConfig
|
import org.oxycblt.auxio.BuildConfig
|
||||||
import org.oxycblt.auxio.music.MusicParent
|
import org.oxycblt.auxio.music.MusicParent
|
||||||
import org.oxycblt.auxio.music.Song
|
import org.oxycblt.auxio.music.Song
|
||||||
|
@ -40,8 +41,6 @@ import org.oxycblt.auxio.util.logW
|
||||||
* Internal consumers should usually use [Listener], however the component that manages the player
|
* Internal consumers should usually use [Listener], however the component that manages the player
|
||||||
* itself should instead use [InternalPlayer].
|
* itself should instead use [InternalPlayer].
|
||||||
*
|
*
|
||||||
* All access should be done with [get].
|
|
||||||
*
|
|
||||||
* @author Alexander Capehart (OxygenCobalt)
|
* @author Alexander Capehart (OxygenCobalt)
|
||||||
*/
|
*/
|
||||||
interface PlaybackStateManager {
|
interface PlaybackStateManager {
|
||||||
|
@ -270,32 +269,9 @@ interface PlaybackStateManager {
|
||||||
val positionMs: Long,
|
val positionMs: Long,
|
||||||
val repeatMode: RepeatMode,
|
val repeatMode: RepeatMode,
|
||||||
)
|
)
|
||||||
|
|
||||||
companion object {
|
|
||||||
@Volatile private var INSTANCE: PlaybackStateManager? = null
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a singleton instance.
|
|
||||||
* @return The (possibly newly-created) singleton instance.
|
|
||||||
*/
|
|
||||||
fun get(): PlaybackStateManager {
|
|
||||||
val currentInstance = INSTANCE
|
|
||||||
logD(currentInstance)
|
|
||||||
|
|
||||||
if (currentInstance != null) {
|
|
||||||
return currentInstance
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized(this) {
|
|
||||||
val newInstance = PlaybackStateManagerImpl()
|
|
||||||
INSTANCE = newInstance
|
|
||||||
return newInstance
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class PlaybackStateManagerImpl : PlaybackStateManager {
|
class PlaybackStateManagerImpl @Inject constructor() : PlaybackStateManager {
|
||||||
private val listeners = mutableListOf<PlaybackStateManager.Listener>()
|
private val listeners = mutableListOf<PlaybackStateManager.Listener>()
|
||||||
@Volatile private var internalPlayer: InternalPlayer? = null
|
@Volatile private var internalPlayer: InternalPlayer? = null
|
||||||
@Volatile private var pendingAction: InternalPlayer.Action? = null
|
@Volatile private var pendingAction: InternalPlayer.Action? = null
|
||||||
|
|
|
@ -22,15 +22,19 @@ import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import javax.inject.Inject
|
||||||
import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A [BroadcastReceiver] that forwards [Intent.ACTION_MEDIA_BUTTON] [Intent]s to [PlaybackService].
|
* A [BroadcastReceiver] that forwards [Intent.ACTION_MEDIA_BUTTON] [Intent]s to [PlaybackService].
|
||||||
* @author Alexander Capehart (OxygenCobalt)
|
* @author Alexander Capehart (OxygenCobalt)
|
||||||
*/
|
*/
|
||||||
|
@AndroidEntryPoint
|
||||||
class MediaButtonReceiver : BroadcastReceiver() {
|
class MediaButtonReceiver : BroadcastReceiver() {
|
||||||
|
@Inject lateinit var playbackManager: PlaybackStateManager
|
||||||
|
|
||||||
override fun onReceive(context: Context, intent: Intent) {
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
val playbackManager = PlaybackStateManager.get()
|
|
||||||
if (playbackManager.queue.currentSong != null) {
|
if (playbackManager.queue.currentSong != null) {
|
||||||
// We have a song, so we can assume that the service will start a foreground state.
|
// We have a song, so we can assume that the service will start a foreground state.
|
||||||
// At least, I hope. Again, *this is why we don't do this*. I cannot describe how
|
// At least, I hope. Again, *this is why we don't do this*. I cannot describe how
|
||||||
|
|
|
@ -27,6 +27,8 @@ import android.support.v4.media.MediaMetadataCompat
|
||||||
import android.support.v4.media.session.MediaSessionCompat
|
import android.support.v4.media.session.MediaSessionCompat
|
||||||
import android.support.v4.media.session.PlaybackStateCompat
|
import android.support.v4.media.session.PlaybackStateCompat
|
||||||
import androidx.media.session.MediaButtonReceiver
|
import androidx.media.session.MediaButtonReceiver
|
||||||
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
|
import javax.inject.Inject
|
||||||
import org.oxycblt.auxio.BuildConfig
|
import org.oxycblt.auxio.BuildConfig
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.image.BitmapProvider
|
import org.oxycblt.auxio.image.BitmapProvider
|
||||||
|
@ -44,11 +46,15 @@ import org.oxycblt.auxio.util.logD
|
||||||
/**
|
/**
|
||||||
* A component that mirrors the current playback state into the [MediaSessionCompat] and
|
* A component that mirrors the current playback state into the [MediaSessionCompat] and
|
||||||
* [NotificationComponent].
|
* [NotificationComponent].
|
||||||
* @param context [Context] required to initialize components.
|
|
||||||
* @param listener [Listener] to forward notification updates to.
|
|
||||||
* @author Alexander Capehart (OxygenCobalt)
|
* @author Alexander Capehart (OxygenCobalt)
|
||||||
*/
|
*/
|
||||||
class MediaSessionComponent(private val context: Context, private val listener: Listener) :
|
class MediaSessionComponent
|
||||||
|
@Inject
|
||||||
|
constructor(
|
||||||
|
@ApplicationContext private val context: Context,
|
||||||
|
private val playbackManager: PlaybackStateManager,
|
||||||
|
private val playbackSettings: PlaybackSettings
|
||||||
|
) :
|
||||||
MediaSessionCompat.Callback(),
|
MediaSessionCompat.Callback(),
|
||||||
PlaybackStateManager.Listener,
|
PlaybackStateManager.Listener,
|
||||||
ImageSettings.Listener,
|
ImageSettings.Listener,
|
||||||
|
@ -59,12 +65,11 @@ class MediaSessionComponent(private val context: Context, private val listener:
|
||||||
setQueueTitle(context.getString(R.string.lbl_queue))
|
setQueueTitle(context.getString(R.string.lbl_queue))
|
||||||
}
|
}
|
||||||
|
|
||||||
private val playbackManager = PlaybackStateManager.get()
|
|
||||||
private val playbackSettings = PlaybackSettings.from(context)
|
|
||||||
|
|
||||||
private val notification = NotificationComponent(context, mediaSession.sessionToken)
|
private val notification = NotificationComponent(context, mediaSession.sessionToken)
|
||||||
private val provider = BitmapProvider(context)
|
private val provider = BitmapProvider(context)
|
||||||
|
|
||||||
|
private var listener: Listener? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
playbackManager.addListener(this)
|
playbackManager.addListener(this)
|
||||||
playbackSettings.registerListener(this)
|
playbackSettings.registerListener(this)
|
||||||
|
@ -79,11 +84,20 @@ class MediaSessionComponent(private val context: Context, private val listener:
|
||||||
MediaButtonReceiver.handleIntent(mediaSession, intent)
|
MediaButtonReceiver.handleIntent(mediaSession, intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a [Listener] for notification updates to this service.
|
||||||
|
* @param listener The [Listener] to register.
|
||||||
|
*/
|
||||||
|
fun registerListener(listener: Listener) {
|
||||||
|
this.listener = listener
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Release this instance, closing the [MediaSessionCompat] and preventing any further updates to
|
* Release this instance, closing the [MediaSessionCompat] and preventing any further updates to
|
||||||
* the [NotificationComponent].
|
* the [NotificationComponent].
|
||||||
*/
|
*/
|
||||||
fun release() {
|
fun release() {
|
||||||
|
listener = null
|
||||||
provider.release()
|
provider.release()
|
||||||
playbackSettings.unregisterListener(this)
|
playbackSettings.unregisterListener(this)
|
||||||
playbackManager.removeListener(this)
|
playbackManager.removeListener(this)
|
||||||
|
@ -135,7 +149,7 @@ class MediaSessionComponent(private val context: Context, private val listener:
|
||||||
invalidateSessionState()
|
invalidateSessionState()
|
||||||
notification.updatePlaying(playbackManager.playerState.isPlaying)
|
notification.updatePlaying(playbackManager.playerState.isPlaying)
|
||||||
if (!provider.isBusy) {
|
if (!provider.isBusy) {
|
||||||
listener.onPostNotification(notification)
|
listener?.onPostNotification(notification)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,7 +330,7 @@ class MediaSessionComponent(private val context: Context, private val listener:
|
||||||
val metadata = builder.build()
|
val metadata = builder.build()
|
||||||
mediaSession.setMetadata(metadata)
|
mediaSession.setMetadata(metadata)
|
||||||
notification.updateMetadata(metadata)
|
notification.updateMetadata(metadata)
|
||||||
listener.onPostNotification(notification)
|
listener?.onPostNotification(notification)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -403,7 +417,7 @@ class MediaSessionComponent(private val context: Context, private val listener:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!provider.isBusy) {
|
if (!provider.isBusy) {
|
||||||
listener.onPostNotification(notification)
|
listener?.onPostNotification(notification)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,11 +86,11 @@ class PlaybackService :
|
||||||
MusicRepository.Listener {
|
MusicRepository.Listener {
|
||||||
// Player components
|
// Player components
|
||||||
private lateinit var player: ExoPlayer
|
private lateinit var player: ExoPlayer
|
||||||
private lateinit var replayGainProcessor: ReplayGainAudioProcessor
|
@Inject lateinit var replayGainProcessor: ReplayGainAudioProcessor
|
||||||
|
|
||||||
// System backend components
|
// System backend components
|
||||||
private lateinit var mediaSessionComponent: MediaSessionComponent
|
@Inject lateinit var mediaSessionComponent: MediaSessionComponent
|
||||||
private lateinit var widgetComponent: WidgetComponent
|
@Inject lateinit var widgetComponent: WidgetComponent
|
||||||
private val systemReceiver = PlaybackReceiver()
|
private val systemReceiver = PlaybackReceiver()
|
||||||
|
|
||||||
// Shared components
|
// Shared components
|
||||||
|
@ -115,8 +115,6 @@ class PlaybackService :
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
|
|
||||||
// Initialize the player component.
|
|
||||||
replayGainProcessor = ReplayGainAudioProcessor(this)
|
|
||||||
// Enable constant bitrate seeking so that certain MP3s/AACs are seekable
|
// Enable constant bitrate seeking so that certain MP3s/AACs are seekable
|
||||||
val extractorsFactory = DefaultExtractorsFactory().setConstantBitrateSeekingEnabled(true)
|
val extractorsFactory = DefaultExtractorsFactory().setConstantBitrateSeekingEnabled(true)
|
||||||
// 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
|
||||||
|
@ -155,8 +153,7 @@ class PlaybackService :
|
||||||
// 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)
|
||||||
musicRepository.addListener(this)
|
musicRepository.addListener(this)
|
||||||
widgetComponent = WidgetComponent(this)
|
mediaSessionComponent.registerListener(this)
|
||||||
mediaSessionComponent = MediaSessionComponent(this, this)
|
|
||||||
registerReceiver(
|
registerReceiver(
|
||||||
systemReceiver,
|
systemReceiver,
|
||||||
IntentFilter().apply {
|
IntentFilter().apply {
|
||||||
|
|
|
@ -22,6 +22,8 @@ import android.graphics.Bitmap
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import coil.request.ImageRequest
|
import coil.request.ImageRequest
|
||||||
import coil.transform.RoundedCornersTransformation
|
import coil.transform.RoundedCornersTransformation
|
||||||
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
|
import javax.inject.Inject
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.image.BitmapProvider
|
import org.oxycblt.auxio.image.BitmapProvider
|
||||||
import org.oxycblt.auxio.image.ImageSettings
|
import org.oxycblt.auxio.image.ImageSettings
|
||||||
|
@ -39,14 +41,16 @@ import org.oxycblt.auxio.util.logD
|
||||||
/**
|
/**
|
||||||
* A component that manages the "Now Playing" state. This is kept separate from the [WidgetProvider]
|
* A component that manages the "Now Playing" state. This is kept separate from the [WidgetProvider]
|
||||||
* itself to prevent possible memory leaks and enable extension to more widgets in the future.
|
* itself to prevent possible memory leaks and enable extension to more widgets in the future.
|
||||||
* @param context [Context] required to manage AppWidgetProviders.
|
|
||||||
* @author Alexander Capehart (OxygenCobalt)
|
* @author Alexander Capehart (OxygenCobalt)
|
||||||
*/
|
*/
|
||||||
class WidgetComponent(private val context: Context) :
|
class WidgetComponent
|
||||||
PlaybackStateManager.Listener, UISettings.Listener, ImageSettings.Listener {
|
@Inject
|
||||||
private val playbackManager = PlaybackStateManager.get()
|
constructor(
|
||||||
private val uiSettings = UISettings.from(context)
|
@ApplicationContext private val context: Context,
|
||||||
private val imageSettings = ImageSettings.from(context)
|
private val imageSettings: ImageSettings,
|
||||||
|
private val playbackManager: PlaybackStateManager,
|
||||||
|
private val uiSettings: UISettings
|
||||||
|
) : PlaybackStateManager.Listener, UISettings.Listener, ImageSettings.Listener {
|
||||||
private val widgetProvider = WidgetProvider()
|
private val widgetProvider = WidgetProvider()
|
||||||
private val provider = BitmapProvider(context)
|
private val provider = BitmapProvider(context)
|
||||||
|
|
||||||
|
@ -109,9 +113,10 @@ class WidgetComponent(private val context: Context) :
|
||||||
/** Release this instance, preventing any further events from updating the widget instances. */
|
/** Release this instance, preventing any further events from updating the widget instances. */
|
||||||
fun release() {
|
fun release() {
|
||||||
provider.release()
|
provider.release()
|
||||||
|
imageSettings.unregisterListener(this)
|
||||||
|
playbackManager.removeListener(this)
|
||||||
uiSettings.unregisterListener(this)
|
uiSettings.unregisterListener(this)
|
||||||
widgetProvider.reset(context)
|
widgetProvider.reset(context)
|
||||||
playbackManager.removeListener(this)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- CALLBACKS ---
|
// --- CALLBACKS ---
|
||||||
|
|
|
@ -15,19 +15,13 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.oxycblt.auxio.music.parsing
|
package org.oxycblt.auxio.music.metadata
|
||||||
|
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.oxycblt.auxio.music.FakeMusicSettings
|
import org.oxycblt.auxio.music.FakeMusicSettings
|
||||||
import org.oxycblt.auxio.music.metadata.correctWhitespace
|
|
||||||
import org.oxycblt.auxio.music.metadata.parseId3GenreNames
|
|
||||||
import org.oxycblt.auxio.music.metadata.parseId3v2PositionField
|
|
||||||
import org.oxycblt.auxio.music.metadata.parseMultiValue
|
|
||||||
import org.oxycblt.auxio.music.metadata.parseVorbisPositionField
|
|
||||||
import org.oxycblt.auxio.music.metadata.splitEscaped
|
|
||||||
|
|
||||||
class ParsingUtilTest {
|
class TagUtilTest {
|
||||||
@Test
|
@Test
|
||||||
fun parseMultiValue_single() {
|
fun parseMultiValue_single() {
|
||||||
assertEquals(
|
assertEquals(
|
Loading…
Reference in a new issue