playback: reattach settings to player
It's mostly identical to prior, albiet pausing on repeat now leaves the player position at the end of the song rather than the beginning. That's the only regression I couldn't figure out how to resolve.
This commit is contained in:
parent
bd240f967e
commit
b2d71f8903
5 changed files with 54 additions and 29 deletions
|
@ -66,6 +66,8 @@ interface PlaybackSettings : Settings<PlaybackSettings.Listener> {
|
||||||
fun onNotificationActionChanged() {}
|
fun onNotificationActionChanged() {}
|
||||||
/** Called when [barAction] has changed. */
|
/** Called when [barAction] has changed. */
|
||||||
fun onBarActionChanged() {}
|
fun onBarActionChanged() {}
|
||||||
|
/** Called when [pauseOnRepeat] has changed. */
|
||||||
|
fun onPauseOnRepeatChanged() {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,6 +189,10 @@ class PlaybackSettingsImpl @Inject constructor(@ApplicationContext context: Cont
|
||||||
logD("Dispatching bar action change")
|
logD("Dispatching bar action change")
|
||||||
listener.onBarActionChanged()
|
listener.onBarActionChanged()
|
||||||
}
|
}
|
||||||
|
getString(R.string.set_key_repeat_pause) -> {
|
||||||
|
logD("Dispatching pause on repeat change")
|
||||||
|
listener.onPauseOnRepeatChanged()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,8 +34,6 @@ interface PlaybackStateHolder {
|
||||||
|
|
||||||
fun resolveQueue(): RawQueue
|
fun resolveQueue(): RawQueue
|
||||||
|
|
||||||
val isShuffled: Boolean
|
|
||||||
|
|
||||||
val audioSessionId: Int
|
val audioSessionId: Int
|
||||||
|
|
||||||
fun newPlayback(queue: List<Song>, start: Song?, parent: MusicParent?, shuffled: Boolean)
|
fun newPlayback(queue: List<Song>, start: Song?, parent: MusicParent?, shuffled: Boolean)
|
||||||
|
|
|
@ -187,9 +187,9 @@ interface PlaybackStateManager {
|
||||||
* [PlaybackStateHolder].
|
* [PlaybackStateHolder].
|
||||||
*
|
*
|
||||||
* @param stateHolder The [PlaybackStateHolder] to synchronize with. Must be the current
|
* @param stateHolder The [PlaybackStateHolder] to synchronize with. Must be the current
|
||||||
* [PlaybackStateHolder]. Does nothing if invoked by another [PlaybackStateHolder]
|
* [PlaybackStateHolder]. Does nothing if invoked by another [PlaybackStateHolder]
|
||||||
* implementation.
|
* implementation.
|
||||||
* @param ack The [StateAck] to acknowledge.
|
* @param ack The [StateAck] to acknowledge.
|
||||||
*/
|
*/
|
||||||
fun ack(stateHolder: PlaybackStateHolder, ack: StateAck)
|
fun ack(stateHolder: PlaybackStateHolder, ack: StateAck)
|
||||||
|
|
||||||
|
@ -269,8 +269,8 @@ interface PlaybackStateManager {
|
||||||
fun onQueueChanged(queue: List<Song>, index: Int, change: QueueChange) {}
|
fun onQueueChanged(queue: List<Song>, index: Int, change: QueueChange) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the queue has changed in a non-trivial manner (such as re-shuffling), but
|
* Called when the queue has changed in a non-trivial manner (such as re-shuffling), but the
|
||||||
* the currently playing [Song] has not.
|
* currently playing [Song] has not.
|
||||||
*
|
*
|
||||||
* @param queue The songs of the new queue.
|
* @param queue The songs of the new queue.
|
||||||
* @param index The new index of the currently playing [Song].
|
* @param index The new index of the currently playing [Song].
|
||||||
|
@ -407,6 +407,8 @@ class PlaybackStateManagerImpl @Inject constructor() : PlaybackStateManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.stateHolder = stateHolder
|
this.stateHolder = stateHolder
|
||||||
|
|
||||||
|
// TODO: Re-init player
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
|
@ -627,7 +629,7 @@ class PlaybackStateManagerImpl @Inject constructor() : PlaybackStateManager {
|
||||||
)
|
)
|
||||||
|
|
||||||
if (change.type == QueueChange.Type.SONG) {
|
if (change.type == QueueChange.Type.SONG) {
|
||||||
playing(true)
|
stateHolder.playing(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
listeners.forEach {
|
listeners.forEach {
|
||||||
|
@ -640,7 +642,7 @@ class PlaybackStateManagerImpl @Inject constructor() : PlaybackStateManager {
|
||||||
stateMirror.copy(
|
stateMirror.copy(
|
||||||
queue = rawQueue.resolveSongs(),
|
queue = rawQueue.resolveSongs(),
|
||||||
index = rawQueue.resolveIndex(),
|
index = rawQueue.resolveIndex(),
|
||||||
isShuffled = stateHolder.isShuffled,
|
isShuffled = rawQueue.isShuffled,
|
||||||
rawQueue = rawQueue)
|
rawQueue = rawQueue)
|
||||||
listeners.forEach {
|
listeners.forEach {
|
||||||
it.onQueueReordered(
|
it.onQueueReordered(
|
||||||
|
@ -654,7 +656,7 @@ class PlaybackStateManagerImpl @Inject constructor() : PlaybackStateManager {
|
||||||
parent = stateHolder.parent,
|
parent = stateHolder.parent,
|
||||||
queue = rawQueue.resolveSongs(),
|
queue = rawQueue.resolveSongs(),
|
||||||
index = rawQueue.resolveIndex(),
|
index = rawQueue.resolveIndex(),
|
||||||
isShuffled = stateHolder.isShuffled,
|
isShuffled = rawQueue.isShuffled,
|
||||||
rawQueue = rawQueue)
|
rawQueue = rawQueue)
|
||||||
listeners.forEach {
|
listeners.forEach {
|
||||||
it.onNewPlayback(
|
it.onNewPlayback(
|
||||||
|
|
|
@ -24,7 +24,6 @@ import androidx.media3.common.Player
|
||||||
import androidx.media3.exoplayer.ExoPlayer
|
import androidx.media3.exoplayer.ExoPlayer
|
||||||
import org.oxycblt.auxio.music.Song
|
import org.oxycblt.auxio.music.Song
|
||||||
import org.oxycblt.auxio.playback.state.RawQueue
|
import org.oxycblt.auxio.playback.state.RawQueue
|
||||||
import org.oxycblt.auxio.playback.state.RepeatMode
|
|
||||||
import org.oxycblt.auxio.util.logD
|
import org.oxycblt.auxio.util.logD
|
||||||
|
|
||||||
val ExoPlayer.song
|
val ExoPlayer.song
|
||||||
|
@ -33,19 +32,9 @@ val ExoPlayer.song
|
||||||
fun ExoPlayer.resolveQueue(): RawQueue {
|
fun ExoPlayer.resolveQueue(): RawQueue {
|
||||||
val heap = (0 until mediaItemCount).map { getMediaItemAt(it).song }
|
val heap = (0 until mediaItemCount).map { getMediaItemAt(it).song }
|
||||||
val shuffledMapping = if (shuffleModeEnabled) unscrambleQueueIndices() else emptyList()
|
val shuffledMapping = if (shuffleModeEnabled) unscrambleQueueIndices() else emptyList()
|
||||||
logD(shuffledMapping)
|
|
||||||
return RawQueue(heap, shuffledMapping, currentMediaItemIndex)
|
return RawQueue(heap, shuffledMapping, currentMediaItemIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
val ExoPlayer.repeat: RepeatMode
|
|
||||||
get() =
|
|
||||||
when (repeatMode) {
|
|
||||||
Player.REPEAT_MODE_OFF -> RepeatMode.NONE
|
|
||||||
Player.REPEAT_MODE_ONE -> RepeatMode.TRACK
|
|
||||||
Player.REPEAT_MODE_ALL -> RepeatMode.ALL
|
|
||||||
else -> throw IllegalStateException("Unknown repeat mode: $repeatMode")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun ExoPlayer.orderedQueue(queue: Collection<Song>, start: Song?) {
|
fun ExoPlayer.orderedQueue(queue: Collection<Song>, start: Song?) {
|
||||||
clearMediaItems()
|
clearMediaItems()
|
||||||
shuffleModeEnabled = false
|
shuffleModeEnabled = false
|
||||||
|
|
|
@ -88,6 +88,7 @@ class PlaybackService :
|
||||||
Service(),
|
Service(),
|
||||||
Player.Listener,
|
Player.Listener,
|
||||||
PlaybackStateHolder,
|
PlaybackStateHolder,
|
||||||
|
PlaybackSettings.Listener,
|
||||||
MediaSessionComponent.Listener,
|
MediaSessionComponent.Listener,
|
||||||
MusicRepository.UpdateListener {
|
MusicRepository.UpdateListener {
|
||||||
// Player components
|
// Player components
|
||||||
|
@ -156,6 +157,7 @@ class PlaybackService :
|
||||||
playbackManager.registerStateHolder(this)
|
playbackManager.registerStateHolder(this)
|
||||||
musicRepository.addUpdateListener(this)
|
musicRepository.addUpdateListener(this)
|
||||||
mediaSessionComponent.registerListener(this)
|
mediaSessionComponent.registerListener(this)
|
||||||
|
playbackSettings.registerListener(this)
|
||||||
|
|
||||||
val intentFilter =
|
val intentFilter =
|
||||||
IntentFilter().apply {
|
IntentFilter().apply {
|
||||||
|
@ -197,6 +199,7 @@ class PlaybackService :
|
||||||
playbackManager.playing(false)
|
playbackManager.playing(false)
|
||||||
playbackManager.unregisterStateHolder(this)
|
playbackManager.unregisterStateHolder(this)
|
||||||
musicRepository.removeUpdateListener(this)
|
musicRepository.removeUpdateListener(this)
|
||||||
|
playbackSettings.unregisterListener(this)
|
||||||
|
|
||||||
unregisterReceiver(systemReceiver)
|
unregisterReceiver(systemReceiver)
|
||||||
serviceJob.cancel()
|
serviceJob.cancel()
|
||||||
|
@ -217,9 +220,6 @@ class PlaybackService :
|
||||||
|
|
||||||
// --- PLAYBACKSTATEHOLDER OVERRIDES ---
|
// --- PLAYBACKSTATEHOLDER OVERRIDES ---
|
||||||
|
|
||||||
override val repeatMode
|
|
||||||
get() = player.repeat
|
|
||||||
|
|
||||||
override val progression: Progression
|
override val progression: Progression
|
||||||
get() =
|
get() =
|
||||||
player.song?.let {
|
player.song?.let {
|
||||||
|
@ -232,10 +232,16 @@ class PlaybackService :
|
||||||
}
|
}
|
||||||
?: Progression.nil()
|
?: Progression.nil()
|
||||||
|
|
||||||
override var parent: MusicParent? = null
|
override val repeatMode
|
||||||
|
get() =
|
||||||
|
when (val repeatMode = player.repeatMode) {
|
||||||
|
Player.REPEAT_MODE_OFF -> RepeatMode.NONE
|
||||||
|
Player.REPEAT_MODE_ONE -> RepeatMode.TRACK
|
||||||
|
Player.REPEAT_MODE_ALL -> RepeatMode.ALL
|
||||||
|
else -> throw IllegalStateException("Unknown repeat mode: $repeatMode")
|
||||||
|
}
|
||||||
|
|
||||||
override val isShuffled
|
override var parent: MusicParent? = null
|
||||||
get() = player.shuffleModeEnabled
|
|
||||||
|
|
||||||
override fun resolveQueue() = player.resolveQueue()
|
override fun resolveQueue() = player.resolveQueue()
|
||||||
|
|
||||||
|
@ -272,6 +278,7 @@ class PlaybackService :
|
||||||
RepeatMode.TRACK -> Player.REPEAT_MODE_ONE
|
RepeatMode.TRACK -> Player.REPEAT_MODE_ONE
|
||||||
}
|
}
|
||||||
playbackManager.ack(this, StateAck.RepeatModeChanged)
|
playbackManager.ack(this, StateAck.RepeatModeChanged)
|
||||||
|
updatePauseOnRepeat()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun seekTo(positionMs: Long) {
|
override fun seekTo(positionMs: Long) {
|
||||||
|
@ -284,7 +291,11 @@ class PlaybackService :
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun prev() {
|
override fun prev() {
|
||||||
player.seekToPrevious()
|
if (playbackSettings.rewindWithPrev) {
|
||||||
|
player.seekToPrevious()
|
||||||
|
} else {
|
||||||
|
player.seekToPreviousMediaItem()
|
||||||
|
}
|
||||||
playbackManager.ack(this, StateAck.IndexMoved)
|
playbackManager.ack(this, StateAck.IndexMoved)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,6 +409,15 @@ class PlaybackService :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onPlaybackStateChanged(playbackState: Int) {
|
||||||
|
super.onPlaybackStateChanged(playbackState)
|
||||||
|
|
||||||
|
if (playbackState == Player.STATE_ENDED && player.repeatMode == Player.REPEAT_MODE_OFF) {
|
||||||
|
goto(0)
|
||||||
|
player.pause()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onEvents(player: Player, events: Player.Events) {
|
override fun onEvents(player: Player, events: Player.Events) {
|
||||||
super.onEvents(player, events)
|
super.onEvents(player, events)
|
||||||
|
|
||||||
|
@ -418,6 +438,12 @@ class PlaybackService :
|
||||||
playbackManager.next()
|
playbackManager.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- OTHER OVERRIDES ---
|
||||||
|
|
||||||
|
override fun onPauseOnRepeatChanged() {
|
||||||
|
updatePauseOnRepeat()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onMusicChanges(changes: MusicRepository.Changes) {
|
override fun onMusicChanges(changes: MusicRepository.Changes) {
|
||||||
if (changes.deviceLibrary && musicRepository.deviceLibrary != null) {
|
if (changes.deviceLibrary && musicRepository.deviceLibrary != null) {
|
||||||
// We now have a library, see if we have anything we need to do.
|
// We now have a library, see if we have anything we need to do.
|
||||||
|
@ -428,6 +454,11 @@ class PlaybackService :
|
||||||
|
|
||||||
// --- OTHER FUNCTIONS ---
|
// --- OTHER FUNCTIONS ---
|
||||||
|
|
||||||
|
private fun updatePauseOnRepeat() {
|
||||||
|
player.pauseAtEndOfMediaItems =
|
||||||
|
playbackManager.repeatMode == RepeatMode.TRACK && playbackSettings.pauseOnRepeat
|
||||||
|
}
|
||||||
|
|
||||||
private fun broadcastAudioEffectAction(event: String) {
|
private fun broadcastAudioEffectAction(event: String) {
|
||||||
logD("Broadcasting AudioEffect event: $event")
|
logD("Broadcasting AudioEffect event: $event")
|
||||||
sendBroadcast(
|
sendBroadcast(
|
||||||
|
@ -556,6 +587,5 @@ class PlaybackService :
|
||||||
const val ACTION_PLAY_PAUSE = BuildConfig.APPLICATION_ID + ".action.PLAY_PAUSE"
|
const val ACTION_PLAY_PAUSE = BuildConfig.APPLICATION_ID + ".action.PLAY_PAUSE"
|
||||||
const val ACTION_SKIP_NEXT = BuildConfig.APPLICATION_ID + ".action.NEXT"
|
const val ACTION_SKIP_NEXT = BuildConfig.APPLICATION_ID + ".action.NEXT"
|
||||||
const val ACTION_EXIT = BuildConfig.APPLICATION_ID + ".action.EXIT"
|
const val ACTION_EXIT = BuildConfig.APPLICATION_ID + ".action.EXIT"
|
||||||
private const val REWIND_THRESHOLD = 3000L
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue