synchronize UI mode and playMode
This commit is contained in:
parent
47ad16c03d
commit
f3d3ce380f
|
@ -35,9 +35,9 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
|||
import kotlinx.coroutines.flow.SharedFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import net.newpipe.newplayer.model.UIModeState
|
||||
import net.newpipe.newplayer.utils.PlayList
|
||||
import kotlin.Exception
|
||||
|
||||
|
@ -63,13 +63,14 @@ interface NewPlayer {
|
|||
var currentPosition: Long
|
||||
var fastSeekAmountSec: Int
|
||||
var playBackMode: PlayMode
|
||||
var playMode : MutableStateFlow<PlayMode?>
|
||||
var playMode: StateFlow<PlayMode?>
|
||||
|
||||
var playlist: PlayList
|
||||
|
||||
// callbacks
|
||||
|
||||
val errorFlow: SharedFlow<Exception>
|
||||
val onExoPlayerEvent: SharedFlow<Pair<Player, Player.Events>>
|
||||
|
||||
// methods
|
||||
fun prepare()
|
||||
|
@ -78,6 +79,7 @@ interface NewPlayer {
|
|||
fun addToPlaylist(item: String)
|
||||
fun playStream(item: String, playMode: PlayMode)
|
||||
fun playStream(item: String, streamVariant: String, playMode: PlayMode)
|
||||
fun setPlayMode(playMode: PlayMode)
|
||||
|
||||
data class Builder(val app: Application, val repository: MediaRepository) {
|
||||
private var mediaSourceFactory: MediaSource.Factory? = null
|
||||
|
@ -130,7 +132,12 @@ class NewPlayerImpl(
|
|||
|
||||
private var playerScope = CoroutineScope(Dispatchers.Main + Job())
|
||||
|
||||
override var playMode = MutableStateFlow<PlayMode?>(null)
|
||||
var mutablePlayMode = MutableStateFlow<PlayMode?>(null)
|
||||
override var playMode = mutablePlayMode.asStateFlow()
|
||||
|
||||
var mutableOnEvent = MutableSharedFlow<Pair<Player, Player.Events>>()
|
||||
override val onExoPlayerEvent: SharedFlow<Pair<Player, Player.Events>> =
|
||||
mutableOnEvent.asSharedFlow()
|
||||
|
||||
override var playWhenReady: Boolean
|
||||
set(value) {
|
||||
|
@ -157,6 +164,13 @@ class NewPlayerImpl(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onEvents(player: Player, events: Player.Events) {
|
||||
super.onEvents(player, events)
|
||||
launchJobAndCollectError {
|
||||
mutableOnEvent.emit(Pair(player, events))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -197,11 +211,15 @@ class NewPlayerImpl(
|
|||
}
|
||||
}
|
||||
|
||||
override fun setPlayMode(playMode: PlayMode) {
|
||||
this.mutablePlayMode.update { playMode }
|
||||
}
|
||||
|
||||
private fun internalPlayStream(mediaItem: MediaItem, playMode: PlayMode) {
|
||||
if (internalPlayer.playbackState == Player.STATE_IDLE) {
|
||||
internalPlayer.prepare()
|
||||
}
|
||||
this.playMode.update { playMode }
|
||||
this.mutablePlayMode.update { playMode }
|
||||
this.internalPlayer.setMediaItem(mediaItem)
|
||||
this.internalPlayer.play()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package net.newpipe.newplayer
|
||||
|
||||
class NewPlayerException : Exception {
|
||||
constructor(message: String) : super(message)
|
||||
constructor(message: String, cause: Throwable) : super(message, cause)
|
||||
}
|
|
@ -96,6 +96,17 @@ enum class UIModeState {
|
|||
else -> this
|
||||
}
|
||||
|
||||
fun toPlayMode() = when(this) {
|
||||
PLACEHOLDER -> null
|
||||
EMBEDDED_VIDEO -> PlayMode.EMBEDDED_VIDEO
|
||||
EMBEDDED_VIDEO_CONTROLLER_UI -> PlayMode.EMBEDDED_VIDEO
|
||||
EMBEDDED_VIDEO_CHAPTER_SELECT -> PlayMode.EMBEDDED_VIDEO
|
||||
EMBEDDED_VIDEO_STREAM_SELECT -> PlayMode.EMBEDDED_VIDEO
|
||||
FULLSCREEN_VIDEO -> PlayMode.FULLSCREEN_VIDEO
|
||||
FULLSCREEN_VIDEO_CONTROLLER_UI -> PlayMode.FULLSCREEN_VIDEO
|
||||
FULLSCREEN_VIDEO_CHAPTER_SELECT -> PlayMode.FULLSCREEN_VIDEO
|
||||
FULLSCREEN_VIDEO_STREAM_SELECT -> PlayMode.FULLSCREEN_VIDEO
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun fromPlayMode(playMode: PlayMode?) =
|
||||
|
|
|
@ -46,7 +46,7 @@ data class VideoPlayerUIState(
|
|||
val DEFAULT = VideoPlayerUIState(
|
||||
// TODO: replace this with the placeholder state.
|
||||
// The actual initial state upon starting to play is dictated by the NewPlayer instance
|
||||
uiMode = UIModeState.EMBEDDED_VIDEO,
|
||||
uiMode = UIModeState.PLACEHOLDER,
|
||||
//uiMode = UIModeState.PLACEHOLDER,
|
||||
playing = false,
|
||||
contentRatio = 16 / 9f,
|
||||
|
|
|
@ -28,7 +28,6 @@ import android.util.Log
|
|||
import androidx.annotation.RequiresApi
|
||||
import androidx.core.content.ContextCompat.getSystemService
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.media3.common.Player
|
||||
|
@ -134,7 +133,6 @@ class VideoPlayerViewModelImpl @Inject constructor(
|
|||
|
||||
override fun onVideoSizeChanged(videoSize: androidx.media3.common.VideoSize) {
|
||||
super.onVideoSizeChanged(videoSize)
|
||||
|
||||
updateContentRatio(VideoSize.fromMedia3VideoSize(videoSize))
|
||||
}
|
||||
|
||||
|
@ -150,11 +148,11 @@ class VideoPlayerViewModelImpl @Inject constructor(
|
|||
}
|
||||
newPlayer?.let { newPlayer ->
|
||||
viewModelScope.launch {
|
||||
while(true) {
|
||||
newPlayer.playMode.collect { mode ->
|
||||
println("blub: $mode")
|
||||
newPlayer.playMode.collect { newMode ->
|
||||
val currentMode = mutableUiState.value.uiMode.toPlayMode()
|
||||
if (currentMode != newMode) {
|
||||
mutableUiState.update {
|
||||
it.copy(uiMode = UIModeState.fromPlayMode(mode))
|
||||
it.copy(uiMode = UIModeState.fromPlayMode(newMode))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -184,15 +182,15 @@ class VideoPlayerViewModelImpl @Inject constructor(
|
|||
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
||||
override fun initUIState(instanceState: Bundle) {
|
||||
|
||||
val uiState =
|
||||
val recoveredUiState =
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) instanceState.getParcelable(
|
||||
VIDEOPLAYER_UI_STATE, VideoPlayerUIState::class.java
|
||||
)
|
||||
else instanceState.getParcelable(VIDEOPLAYER_UI_STATE)
|
||||
|
||||
uiState?.let { uiState ->
|
||||
if(recoveredUiState != null) {
|
||||
mutableUiState.update {
|
||||
uiState
|
||||
recoveredUiState
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -349,17 +347,25 @@ class VideoPlayerViewModelImpl @Inject constructor(
|
|||
callbackListeners.forEach { it?.onFullscreenToggle(false) }
|
||||
uiVisibilityJob?.cancel()
|
||||
finishFastSeek()
|
||||
mutableUiState.update {
|
||||
it.copy(uiMode = UIModeState.EMBEDDED_VIDEO)
|
||||
}
|
||||
updateUiMode(UIModeState.EMBEDDED_VIDEO)
|
||||
}
|
||||
|
||||
override fun switchToFullscreen() {
|
||||
callbackListeners.forEach { it?.onFullscreenToggle(true) }
|
||||
uiVisibilityJob?.cancel()
|
||||
finishFastSeek()
|
||||
updateUiMode(UIModeState.FULLSCREEN_VIDEO)
|
||||
}
|
||||
|
||||
private fun updateUiMode(newState: UIModeState) {
|
||||
val newPlayMode = newState.toPlayMode()
|
||||
val currentPlayMode = mutableUiState.value.uiMode.toPlayMode()
|
||||
if(newPlayMode != currentPlayMode) {
|
||||
newPlayer?.setPlayMode(newPlayMode!!)
|
||||
} else {
|
||||
mutableUiState.update {
|
||||
it.copy(uiMode = UIModeState.FULLSCREEN_VIDEO)
|
||||
it.copy(uiMode = newState)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue