replace first callbacks with mutablestate/shareflow

This commit is contained in:
Christian Schabesberger 2024-08-24 14:06:23 +02:00
parent 32075dec73
commit ea099253a1
3 changed files with 43 additions and 38 deletions

View File

@ -30,7 +30,14 @@ import androidx.media3.exoplayer.source.MediaSource
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import net.newpipe.newplayer.model.UIModeState
import net.newpipe.newplayer.utils.PlayList
import kotlin.Exception
@ -56,16 +63,13 @@ interface NewPlayer {
var currentPosition: Long
var fastSeekAmountSec: Int
var playBackMode: PlayMode
var playMode: PlayMode?
var playMode : MutableStateFlow<PlayMode?>
var playlist: PlayList
// calbacks
// callbacks
interface Listener {
fun playModeChange(playMode: PlayMode) {}
fun onError(exception: Exception) {}
}
val errorFlow : SharedFlow<Exception>
// methods
fun prepare()
@ -74,7 +78,6 @@ interface NewPlayer {
fun addToPlaylist(item: String)
fun playStream(item: String, playMode: PlayMode)
fun playStream(item: String, streamVariant: String, playMode: PlayMode)
fun addCallbackListener(listener: Listener?)
data class Builder(val app: Application, val repository: MediaRepository) {
private var mediaSourceFactory: MediaSource.Factory? = null
@ -111,6 +114,9 @@ class NewPlayerImpl(
override val repository: MediaRepository,
) : NewPlayer {
var mutableErrorFlow = MutableSharedFlow<Exception>()
override val errorFlow = mutableErrorFlow.asSharedFlow()
override val bufferedPercentage: Int
get() = internalPlayer.bufferedPercentage
override var currentPosition: Long
@ -122,16 +128,9 @@ class NewPlayerImpl(
override var fastSeekAmountSec: Int = 10
override var playBackMode: PlayMode = PlayMode.EMBEDDED_VIDEO
private var callbackListener: ArrayList<NewPlayer.Listener?> = ArrayList()
private var playerScope = CoroutineScope(Dispatchers.Default + Job())
override var playMode: PlayMode? = null
set(value) {
field = value
if (field != null) {
callbackListener.forEach { it?.playModeChange(field!!) }
}
}
override var playMode = MutableStateFlow<PlayMode?>(null)
override var playWhenReady: Boolean
set(value) {
@ -154,9 +153,7 @@ class NewPlayerImpl(
if (newUri != null) {
TODO("Implement handing new uri on fixed error")
} else {
callbackListener.forEach {
it?.onError(error)
}
mutableErrorFlow.emit(error)
}
}
}
@ -204,7 +201,7 @@ class NewPlayerImpl(
if (internalPlayer.playbackState == Player.STATE_IDLE) {
internalPlayer.prepare()
}
this.playMode = playMode
this.playMode.update { playMode }
}
private suspend fun toMediaItem(item: String, streamVariant: String): MediaItem {
@ -232,13 +229,7 @@ class NewPlayerImpl(
try {
task()
} catch (e: Exception) {
callbackListener.forEach {
it?.onError(e)
mutableErrorFlow.emit(e)
}
}
}
override fun addCallbackListener(listener: NewPlayer.Listener?) {
callbackListener.add(listener)
}
}

View File

@ -21,7 +21,9 @@
package net.newpipe.newplayer.utils
import androidx.media3.common.MediaMetadata
import androidx.media3.common.Player
import androidx.media3.common.Player.Listener
// TODO: This is cool, but it might still contains all raceconditions since two actors are mutating the
@ -32,6 +34,8 @@ import androidx.media3.common.Player
// due to this reason some functions force the user to handle elements out of bounds exceptions.
class PlayListIterator(
val exoPlayer: Player,
val fromIndex: Int,
@ -83,6 +87,7 @@ class PlayList(val exoPlayer: Player, val fromIndex: Int = 0, val toIndex: Int =
override val size: Int
get() = minOf(exoPlayer.mediaItemCount, toIndex) - fromIndex
// TODO: This contains a race condition. When the player might change the playlist while this function runns
override fun contains(element: String): Boolean {
for (i in fromIndex..minOf(exoPlayer.mediaItemCount, toIndex)) {
try {
@ -95,6 +100,7 @@ class PlayList(val exoPlayer: Player, val fromIndex: Int = 0, val toIndex: Int =
return false
}
// TODO: This contains a race condition. When the player might change the playlist while this function runns
override fun containsAll(elements: Collection<String>): Boolean {
for (element in elements) {
if (!this.contains(element)) {
@ -106,10 +112,10 @@ class PlayList(val exoPlayer: Player, val fromIndex: Int = 0, val toIndex: Int =
@Throws(IndexOutOfBoundsException::class)
override fun get(index: Int) =
if (index < fromIndex || toIndex < index)
throw IndexOutOfBoundsException("Accessed playlist item outside of permitted Playlist ListWindow: $index")
if (index < 0 || toIndex < index + fromIndex)
throw IndexOutOfBoundsException("Accessed playlist item outside of permitted Playlist ListWindow: $index with [$fromIndex;$toIndex[")
else
exoPlayer.getMediaItemAt(index).mediaId
exoPlayer.getMediaItemAt(index + fromIndex).mediaId
override fun isEmpty() = exoPlayer.mediaItemCount == 0 || fromIndex == toIndex
@ -127,14 +133,21 @@ class PlayList(val exoPlayer: Player, val fromIndex: Int = 0, val toIndex: Int =
)
override fun lastIndexOf(element: String): Int {
var mediaItemCount = 0
var newMediaItemCount = minOf(toIndex, exoPlayer.mediaItemCount)
// this while loop is there to catch raceconditions
while(mediaItemCount != newMediaItemCount) {
mediaItemCount = newMediaItemCount
for (i in minOf(toIndex, exoPlayer.mediaItemCount) downTo fromIndex) {
try {
if (exoPlayer.getMediaItemAt(i).mediaId == element) {
return i - fromIndex
}
} catch (e: IndexOutOfBoundsException) {
return -1
} catch (_: IndexOutOfBoundsException) {}
}
newMediaItemCount = minOf(toIndex, exoPlayer.mediaItemCount)
}
return -1
}

View File

@ -34,6 +34,7 @@ import androidx.media3.common.MediaItem
import dagger.hilt.android.AndroidEntryPoint
import net.newpipe.newplayer.ActivityBrainSlug
import net.newpipe.newplayer.NewPlayer
import net.newpipe.newplayer.PlayMode
import net.newpipe.newplayer.VideoPlayerView
import net.newpipe.newplayer.model.VideoPlayerViewModel
import net.newpipe.newplayer.model.VideoPlayerViewModelImpl
@ -63,7 +64,7 @@ class MainActivity : AppCompatActivity() {
startStreamButton.setOnClickListener {
newPlayer.playWhenReady = true
newPlayer.setStream(MediaItem.fromUri(getString(R.string.ccc_6502_video)))
newPlayer.playStream(getString(R.string.ccc_6502_video), PlayMode.EMBEDDED_VIDEO)
}
videoPlayerViewModel.newPlayer = newPlayer