make shuffle and repeatmode work

This commit is contained in:
Christian Schabesberger 2024-09-03 13:54:33 +02:00
parent c0a006f238
commit 9a71e8f0b5
6 changed files with 75 additions and 39 deletions

View File

@ -53,6 +53,12 @@ enum class PlayMode {
AUDIO_FOREGROUND,
}
enum class RepeatMode {
DONT_REPEAT,
REPEAT_ALL,
REPEAT_ONE
}
private val TAG = "NewPlayer"
interface NewPlayer {
@ -68,6 +74,8 @@ interface NewPlayer {
var fastSeekAmountSec: Int
var playBackMode: PlayMode
var playMode: StateFlow<PlayMode?>
var shuffle: Boolean
var repeatMode: RepeatMode
val playlist: StateFlow<List<PlaylistItem>>
@ -154,6 +162,27 @@ class NewPlayerImpl(
var mutablePlayMode = MutableStateFlow<PlayMode?>(null)
override var playMode = mutablePlayMode.asStateFlow()
override var shuffle: Boolean
get() = internalPlayer.shuffleModeEnabled
set(value) {
internalPlayer.shuffleModeEnabled = value
}
override var repeatMode: RepeatMode
get() = when(internalPlayer.repeatMode) {
Player.REPEAT_MODE_OFF -> RepeatMode.DONT_REPEAT
Player.REPEAT_MODE_ALL -> RepeatMode.REPEAT_ALL
Player.REPEAT_MODE_ONE -> RepeatMode.REPEAT_ONE
else -> throw NewPlayerException("Unknown Repeatmode option returned by ExoPlayer: ${internalPlayer.repeatMode}")
}
set(value) {
when(value) {
RepeatMode.DONT_REPEAT -> internalPlayer.repeatMode = Player.REPEAT_MODE_OFF
RepeatMode.REPEAT_ALL -> internalPlayer.repeatMode = Player.REPEAT_MODE_ALL
RepeatMode.REPEAT_ONE -> internalPlayer.repeatMode = Player.REPEAT_MODE_ONE
}
}
var mutableOnEvent = MutableSharedFlow<Pair<Player, Player.Events>>()
override val onExoPlayerEvent: SharedFlow<Pair<Player, Player.Events>> =
mutableOnEvent.asSharedFlow()

View File

@ -22,6 +22,7 @@ package net.newpipe.newplayer.model
import androidx.media3.common.Player
import net.newpipe.newplayer.Chapter
import net.newpipe.newplayer.RepeatMode
import net.newpipe.newplayer.playerInternals.PlaylistItem
import net.newpipe.newplayer.ui.ContentScale
@ -43,7 +44,7 @@ data class VideoPlayerUIState(
val playList: List<PlaylistItem>,
val chapters: List<Chapter>,
val shuffleEnabled: Boolean,
val repeatMode: Int,
val repeatMode: RepeatMode,
val playListDurationInS: Int
) {
companion object {
@ -68,7 +69,7 @@ data class VideoPlayerUIState(
playList = emptyList(),
chapters = emptyList(),
shuffleEnabled = false,
repeatMode = Player.REPEAT_MODE_OFF,
repeatMode = RepeatMode.DONT_REPEAT,
playListDurationInS = 0
)
}

View File

@ -26,6 +26,7 @@ import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow
import net.newpipe.newplayer.Chapter
import net.newpipe.newplayer.NewPlayer
import net.newpipe.newplayer.RepeatMode
import net.newpipe.newplayer.ui.ContentScale
import net.newpipe.newplayer.utils.Thumbnail
@ -60,8 +61,8 @@ interface VideoPlayerViewModel {
fun closeStreamSelection()
fun chapterSelected(chapter: Chapter)
fun streamSelected(streamId: Int)
fun setRepeatmode(repeatMode: Int)
fun setSuffleEnabled(enabled: Boolean)
fun cycleRepeatmode()
fun toggleShuffle()
fun onStorePlaylist()
fun movePlaylistItem(from: Int, to: Int)
fun removePlaylistItem(index: Int)

View File

@ -45,6 +45,7 @@ import kotlinx.coroutines.launch
import net.newpipe.newplayer.Chapter
import net.newpipe.newplayer.utils.VideoSize
import net.newpipe.newplayer.NewPlayer
import net.newpipe.newplayer.RepeatMode
import net.newpipe.newplayer.ui.ContentScale
import java.util.LinkedList
@ -132,7 +133,8 @@ class VideoPlayerViewModelImpl @Inject constructor(
override val onBackPressed: SharedFlow<Unit> = mutableOnBackPressed.asSharedFlow()
private fun installNewPlayer() {
newPlayer?.internalPlayer?.let { player ->
newPlayer?.let { newPlayer ->
val player = newPlayer.internalPlayer
Log.d(TAG, "Install player: ${player.videoSize.width}")
player.addListener(object : Player.Listener {
@ -157,6 +159,20 @@ class VideoPlayerViewModelImpl @Inject constructor(
it.copy(isLoading = isLoading)
}
}
override fun onRepeatModeChanged(repeatMode: Int) {
super.onRepeatModeChanged(repeatMode)
mutableUiState.update {
it.copy(repeatMode = newPlayer.repeatMode)
}
}
override fun onShuffleModeEnabledChanged(shuffleModeEnabled: Boolean) {
super.onShuffleModeEnabledChanged(shuffleModeEnabled)
mutableUiState.update {
it.copy(shuffleEnabled = newPlayer.shuffle)
}
}
})
}
newPlayer?.let { newPlayer ->
@ -406,19 +422,20 @@ class VideoPlayerViewModelImpl @Inject constructor(
println("stream selected: $streamId")
}
override fun setRepeatmode(repeatMode: Int) {
assert(
repeatMode == Player.REPEAT_MODE_ALL
|| repeatMode == Player.REPEAT_MODE_OFF
|| repeatMode == Player.REPEAT_MODE_ONE
) {
"Illegal repeat mode: $repeatMode"
override fun cycleRepeatmode() {
newPlayer?.let {
it.repeatMode = when (it.repeatMode) {
RepeatMode.DONT_REPEAT -> RepeatMode.REPEAT_ALL
RepeatMode.REPEAT_ALL -> RepeatMode.REPEAT_ONE
RepeatMode.REPEAT_ONE -> RepeatMode.DONT_REPEAT
}
}
TODO("Not yet implemented")
}
override fun setSuffleEnabled(enabled: Boolean) {
TODO("Not yet implemented")
override fun toggleShuffle() {
newPlayer?.let {
it.shuffle = !it.shuffle
}
}
override fun onStorePlaylist() {
@ -453,7 +470,6 @@ class VideoPlayerViewModelImpl @Inject constructor(
}
private fun updateUiMode(newState: UIModeState) {
val newPlayMode = newState.toPlayMode()
val currentPlayMode = mutableUiState.value.uiMode.toPlayMode()

View File

@ -8,6 +8,7 @@ import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import net.newpipe.newplayer.Chapter
import net.newpipe.newplayer.NewPlayer
import net.newpipe.newplayer.RepeatMode
import net.newpipe.newplayer.ui.ContentScale
open class VideoPlayerViewModelDummy : VideoPlayerViewModel {
@ -91,12 +92,12 @@ open class VideoPlayerViewModelDummy : VideoPlayerViewModel {
println("dummy impl stream selected: $streamId")
}
override fun setRepeatmode(repeatMode: Int) {
println("dummy impl repeat mode: $repeatMode")
override fun cycleRepeatmode() {
println("dummy impl")
}
override fun setSuffleEnabled(enabled: Boolean) {
println("dummy impl shuffle enabled: $enabled")
override fun toggleShuffle() {
println("dummy impl")
}
override fun onStorePlaylist() {

View File

@ -46,6 +46,7 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.media3.common.Player
import net.newpipe.newplayer.NewPlayerException
import net.newpipe.newplayer.R
import net.newpipe.newplayer.RepeatMode
import net.newpipe.newplayer.model.VideoPlayerUIState
import net.newpipe.newplayer.model.VideoPlayerViewModel
import net.newpipe.newplayer.model.VideoPlayerViewModelDummy
@ -75,41 +76,28 @@ fun StreamSelectTopBar(
)
}, actions = {
IconButton(
onClick = {
viewModel.setRepeatmode(
when (uiState.repeatMode) {
Player.REPEAT_MODE_OFF -> Player.REPEAT_MODE_ALL
Player.REPEAT_MODE_ALL -> Player.REPEAT_MODE_ONE
Player.REPEAT_MODE_ONE -> Player.REPEAT_MODE_OFF
else -> throw NewPlayerException("Unknown repeat mode: ${uiState.repeatMode}")
}
)
}
onClick = viewModel::cycleRepeatmode
) {
when (uiState.repeatMode) {
Player.REPEAT_MODE_OFF -> Icon(
RepeatMode.DONT_REPEAT -> Icon(
imageVector = Icons.Filled.Repeat,
contentDescription = stringResource(R.string.repeat_mode_no_repeat)
)
Player.REPEAT_MODE_ALL -> Icon(
RepeatMode.REPEAT_ALL -> Icon(
imageVector = Icons.Filled.RepeatOn,
contentDescription = stringResource(R.string.repeat_mode_repeat_all)
)
Player.REPEAT_MODE_ONE -> Icon(
RepeatMode.REPEAT_ONE -> Icon(
imageVector = Icons.Filled.RepeatOneOn,
contentDescription = stringResource(R.string.repeat_mode_repeat_all)
)
else -> throw NewPlayerException("Unknown repeat mode: ${uiState.repeatMode}")
}
}
IconButton(
onClick = {
viewModel.setSuffleEnabled(!uiState.shuffleEnabled)
}
onClick = viewModel::toggleShuffle
) {
if (uiState.shuffleEnabled) {
Icon(