playback: tweak media3 command surface
This commit is contained in:
parent
fb15791c2f
commit
0ca928a477
1 changed files with 38 additions and 43 deletions
|
@ -44,10 +44,17 @@ import org.oxycblt.auxio.playback.state.PlaybackCommand
|
||||||
import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
||||||
import org.oxycblt.auxio.playback.state.RepeatMode
|
import org.oxycblt.auxio.playback.state.RepeatMode
|
||||||
import org.oxycblt.auxio.playback.state.ShuffleMode
|
import org.oxycblt.auxio.playback.state.ShuffleMode
|
||||||
|
import org.oxycblt.auxio.util.logD
|
||||||
|
import org.oxycblt.auxio.util.logE
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A thin wrapper around the player instance that takes all the events I know MediaSession will send
|
* A thin wrapper around the player instance that drastically reduces the command surface and
|
||||||
* and routes them to PlaybackStateManager so I know that they will work the way I want it to.
|
* forwards all commands to PlaybackStateManager so I can ensure that all the unhinged commands
|
||||||
|
* that Media3 will throw at me will be handled in a predictable way, rather than just clobbering
|
||||||
|
* the playback state. Largely limited to the legacy media APIs.
|
||||||
|
*
|
||||||
|
* I'll add more support as I go along when I can confirm that apps will use the Media3 API and
|
||||||
|
* send more advanced commands.
|
||||||
*
|
*
|
||||||
* @author Alexander Capehart
|
* @author Alexander Capehart
|
||||||
*/
|
*/
|
||||||
|
@ -70,45 +77,34 @@ class MediaSessionPlayer(
|
||||||
command in setOf(Player.COMMAND_SEEK_TO_NEXT, Player.COMMAND_SEEK_TO_PREVIOUS)
|
command in setOf(Player.COMMAND_SEEK_TO_NEXT, Player.COMMAND_SEEK_TO_PREVIOUS)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun setMediaItems(mediaItems: MutableList<MediaItem>, resetPosition: Boolean) {
|
||||||
|
if (!resetPosition) {
|
||||||
|
error("Playing MediaItems with custom position parameters is not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
setMediaItems(mediaItems, C.INDEX_UNSET, C.TIME_UNSET)
|
||||||
|
}
|
||||||
|
|
||||||
override fun setMediaItems(
|
override fun setMediaItems(
|
||||||
mediaItems: MutableList<MediaItem>,
|
mediaItems: MutableList<MediaItem>,
|
||||||
startIndex: Int,
|
startIndex: Int,
|
||||||
startPositionMs: Long
|
startPositionMs: Long
|
||||||
) {
|
) {
|
||||||
// We assume the only people calling this method are going to be the MediaSession callbacks,
|
// We assume the only people calling this method are going to be the MediaSession callbacks.
|
||||||
// since anything else (like newPlayback) will be calling directly on the player. As part
|
// As part of this, we expand the given MediaItems into the command that should be sent to
|
||||||
// of this, we expand the given MediaItems into the command that should be sent to the
|
// the player.
|
||||||
// player.
|
if (startIndex != C.INDEX_UNSET || startPositionMs != C.TIME_UNSET) {
|
||||||
val command =
|
error("Playing MediaItems with custom position parameters is not supported")
|
||||||
if (mediaItems.size > 1) {
|
|
||||||
this.playMediaItemSelection(mediaItems, startIndex)
|
|
||||||
} else {
|
|
||||||
this.playSingleMediaItem(mediaItems.first())
|
|
||||||
}
|
}
|
||||||
|
if (mediaItems.size != 1) {
|
||||||
|
error("Playing multiple MediaItems is not supported")
|
||||||
|
}
|
||||||
|
val command = expandMediaItemIntoCommand(mediaItems.first())
|
||||||
requireNotNull(command) { "Invalid playback configuration" }
|
requireNotNull(command) { "Invalid playback configuration" }
|
||||||
playbackManager.play(command)
|
playbackManager.play(command)
|
||||||
if (startPositionMs != C.TIME_UNSET) {
|
|
||||||
playbackManager.seekTo(startPositionMs)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun playMediaItemSelection(
|
private fun expandMediaItemIntoCommand(mediaItem: MediaItem): PlaybackCommand? {
|
||||||
mediaItems: List<MediaItem>,
|
|
||||||
startIndex: Int
|
|
||||||
): PlaybackCommand? {
|
|
||||||
val deviceLibrary = musicRepository.deviceLibrary ?: return null
|
|
||||||
val targetSong = mediaItems.getOrNull(startIndex)?.toSong(deviceLibrary)
|
|
||||||
val songs = mediaItems.mapNotNull { it.toSong(deviceLibrary) }
|
|
||||||
var index = startIndex
|
|
||||||
if (targetSong != null) {
|
|
||||||
while (songs.getOrNull(index)?.uid != targetSong.uid) {
|
|
||||||
index--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return commandFactory.songs(songs, ShuffleMode.OFF)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun playSingleMediaItem(mediaItem: MediaItem): PlaybackCommand? {
|
|
||||||
val uid = MediaSessionUID.fromString(mediaItem.mediaId) ?: return null
|
val uid = MediaSessionUID.fromString(mediaItem.mediaId) ?: return null
|
||||||
val music: Music
|
val music: Music
|
||||||
var parent: MusicParent? = null
|
var parent: MusicParent? = null
|
||||||
|
@ -143,9 +139,9 @@ class MediaSessionPlayer(
|
||||||
null -> commandFactory.songFromAll(music, ShuffleMode.IMPLICIT)
|
null -> commandFactory.songFromAll(music, ShuffleMode.IMPLICIT)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setPlayWhenReady(playWhenReady: Boolean) {
|
override fun play() = playbackManager.playing(true)
|
||||||
playbackManager.playing(playWhenReady)
|
|
||||||
}
|
override fun pause() = playbackManager.playing(false)
|
||||||
|
|
||||||
override fun setRepeatMode(repeatMode: Int) {
|
override fun setRepeatMode(repeatMode: Int) {
|
||||||
val appRepeatMode =
|
val appRepeatMode =
|
||||||
|
@ -243,9 +239,6 @@ class MediaSessionPlayer(
|
||||||
|
|
||||||
override fun setMediaItems(mediaItems: MutableList<MediaItem>) = notAllowed()
|
override fun setMediaItems(mediaItems: MutableList<MediaItem>) = notAllowed()
|
||||||
|
|
||||||
override fun setMediaItems(mediaItems: MutableList<MediaItem>, resetPosition: Boolean) =
|
|
||||||
notAllowed()
|
|
||||||
|
|
||||||
override fun addMediaItem(mediaItem: MediaItem) = notAllowed()
|
override fun addMediaItem(mediaItem: MediaItem) = notAllowed()
|
||||||
|
|
||||||
override fun addMediaItem(index: Int, mediaItem: MediaItem) = notAllowed()
|
override fun addMediaItem(index: Int, mediaItem: MediaItem) = notAllowed()
|
||||||
|
@ -280,14 +273,12 @@ class MediaSessionPlayer(
|
||||||
|
|
||||||
@Deprecated("Deprecated in Java") override fun seekToNextWindow() = notAllowed()
|
@Deprecated("Deprecated in Java") override fun seekToNextWindow() = notAllowed()
|
||||||
|
|
||||||
override fun play() = playbackManager.playing(true)
|
|
||||||
|
|
||||||
override fun pause() = playbackManager.playing(false)
|
|
||||||
|
|
||||||
override fun prepare() = notAllowed()
|
override fun prepare() = notAllowed()
|
||||||
|
|
||||||
override fun release() = notAllowed()
|
override fun release() = notAllowed()
|
||||||
|
|
||||||
|
override fun setPlayWhenReady(playWhenReady: Boolean) = notAllowed()
|
||||||
|
|
||||||
override fun stop() = notAllowed()
|
override fun stop() = notAllowed()
|
||||||
|
|
||||||
override fun hasNextMediaItem() = notAllowed()
|
override fun hasNextMediaItem() = notAllowed()
|
||||||
|
@ -337,7 +328,11 @@ class MediaSessionPlayer(
|
||||||
|
|
||||||
override fun clearVideoTextureView(textureView: TextureView?) = notAllowed()
|
override fun clearVideoTextureView(textureView: TextureView?) = notAllowed()
|
||||||
|
|
||||||
private fun notAllowed(): Nothing = error("MediaSession unexpectedly called this method")
|
private fun notAllowed(): Nothing {
|
||||||
|
logD("MediaSession unexpectedly called this method")
|
||||||
|
logE(Exception().stackTraceToString())
|
||||||
|
error("MediaSession unexpectedly called this method")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Player.unscrambleQueueIndices(): List<Int> {
|
fun Player.unscrambleQueueIndices(): List<Int> {
|
||||||
|
|
Loading…
Reference in a new issue