Dispose PlayerState
This commit is contained in:
parent
8155294516
commit
c74a8f9f07
|
@ -77,7 +77,7 @@ class PlayerService : Service(), Player.Listener, PlaybackStatsListener.Callback
|
|||
private var lastArtworkUri: Uri? = null
|
||||
private var lastBitmap: Bitmap? = null
|
||||
|
||||
private var radio: YoutubePlayer.Radio? = null
|
||||
private var radio: YouTubeRadio? = null
|
||||
|
||||
private val coroutineScope = CoroutineScope(Dispatchers.IO) + Job()
|
||||
|
||||
|
@ -549,7 +549,7 @@ class PlayerService : Service(), Player.Listener, PlaybackStatsListener.Callback
|
|||
private fun startRadio(endpoint: NavigationEndpoint.Endpoint.Watch?, justAdd: Boolean) {
|
||||
radioJob?.cancel()
|
||||
radio = null
|
||||
YoutubePlayer.Radio(
|
||||
YouTubeRadio(
|
||||
endpoint?.videoId,
|
||||
endpoint?.playlistId,
|
||||
endpoint?.playlistSetVideoId,
|
||||
|
|
|
@ -73,7 +73,7 @@ fun PlayerView(
|
|||
val context = LocalContext.current
|
||||
|
||||
val player = binder?.player
|
||||
val playerState = rememberYoutubePlayer(player)
|
||||
val playerState = rememberPlayerState(player)
|
||||
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import androidx.media3.common.*
|
|||
import kotlin.math.absoluteValue
|
||||
|
||||
@Stable
|
||||
open class PlayerState(private val player: Player) : Player.Listener {
|
||||
class PlayerState(private val player: Player) : Player.Listener, Runnable {
|
||||
private val handler = Handler(Looper.getMainLooper())
|
||||
|
||||
var currentPosition by mutableStateOf(player.currentPosition)
|
||||
|
@ -30,9 +30,6 @@ open class PlayerState(private val player: Player) : Player.Listener {
|
|||
var mediaMetadata by mutableStateOf(player.mediaMetadata)
|
||||
private set
|
||||
|
||||
var isPlaying by mutableStateOf(player.isPlaying)
|
||||
private set
|
||||
|
||||
var playWhenReady by mutableStateOf(player.playWhenReady)
|
||||
private set
|
||||
|
||||
|
@ -47,16 +44,6 @@ open class PlayerState(private val player: Player) : Player.Listener {
|
|||
var volume by mutableStateOf(player.volume)
|
||||
private set
|
||||
|
||||
init {
|
||||
handler.post(object : Runnable {
|
||||
override fun run() {
|
||||
duration = player.duration
|
||||
currentPosition = player.currentPosition
|
||||
handler.postDelayed(this, 500)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onVolumeChanged(volume: Float) {
|
||||
this.volume = volume
|
||||
}
|
||||
|
@ -69,10 +56,6 @@ open class PlayerState(private val player: Player) : Player.Listener {
|
|||
this.mediaMetadata = mediaMetadata
|
||||
}
|
||||
|
||||
override fun onIsPlayingChanged(isPlaying: Boolean) {
|
||||
this.isPlaying = isPlaying
|
||||
}
|
||||
|
||||
override fun onPlayWhenReadyChanged(playWhenReady: Boolean, reason: Int) {
|
||||
this.playWhenReady = playWhenReady
|
||||
}
|
||||
|
@ -94,4 +77,38 @@ open class PlayerState(private val player: Player) : Player.Listener {
|
|||
mediaItems = timeline.mediaItems
|
||||
mediaItemIndex = player.currentMediaItemIndex
|
||||
}
|
||||
|
||||
override fun run() {
|
||||
duration = player.duration
|
||||
currentPosition = player.currentPosition
|
||||
handler.postDelayed(this, 500)
|
||||
}
|
||||
|
||||
fun init() {
|
||||
player.addListener(this)
|
||||
handler.post(this)
|
||||
}
|
||||
|
||||
fun dispose() {
|
||||
player.removeListener(this)
|
||||
handler.removeCallbacks(this)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun rememberPlayerState(
|
||||
player: Player?
|
||||
): PlayerState? {
|
||||
val playerState = remember(player) {
|
||||
player?.let(::PlayerState)
|
||||
}
|
||||
|
||||
playerState?.let {
|
||||
DisposableEffect(Unit) {
|
||||
playerState.init()
|
||||
onDispose(playerState::dispose)
|
||||
}
|
||||
}
|
||||
|
||||
return playerState
|
||||
}
|
||||
|
|
|
@ -2,54 +2,40 @@ package it.vfsfitvnm.vimusic.utils
|
|||
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.media3.common.MediaItem
|
||||
import androidx.media3.common.Player
|
||||
import it.vfsfitvnm.youtubemusic.Outcome
|
||||
import it.vfsfitvnm.youtubemusic.YouTube
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class YoutubePlayer(player: Player) : PlayerState(player) {
|
||||
data class Radio(
|
||||
private val videoId: String? = null,
|
||||
private val playlistId: String? = null,
|
||||
private val playlistSetVideoId: String? = null,
|
||||
private val parameters: String? = null
|
||||
) {
|
||||
var nextContinuation by mutableStateOf<Outcome<String?>>(Outcome.Initial)
|
||||
data class YouTubeRadio(
|
||||
private val videoId: String? = null,
|
||||
private val playlistId: String? = null,
|
||||
private val playlistSetVideoId: String? = null,
|
||||
private val parameters: String? = null
|
||||
) {
|
||||
var nextContinuation by mutableStateOf<Outcome<String?>>(Outcome.Initial)
|
||||
|
||||
suspend fun process(): List<MediaItem> {
|
||||
val token = nextContinuation.valueOrNull
|
||||
suspend fun process(): List<MediaItem> {
|
||||
val token = nextContinuation.valueOrNull
|
||||
|
||||
nextContinuation = Outcome.Loading
|
||||
nextContinuation = Outcome.Loading
|
||||
|
||||
var mediaItems: List<MediaItem>? = null
|
||||
var mediaItems: List<MediaItem>? = null
|
||||
|
||||
nextContinuation = withContext(Dispatchers.IO) {
|
||||
YouTube.next(
|
||||
videoId = videoId ?: error("This should not happen"),
|
||||
playlistId = playlistId,
|
||||
params = parameters,
|
||||
playlistSetVideoId = playlistSetVideoId,
|
||||
continuation = token
|
||||
)
|
||||
}.map { nextResult ->
|
||||
mediaItems = nextResult.items?.map(YouTube.Item.Song::asMediaItem)
|
||||
nextContinuation = withContext(Dispatchers.IO) {
|
||||
YouTube.next(
|
||||
videoId = videoId ?: error("This should not happen"),
|
||||
playlistId = playlistId,
|
||||
params = parameters,
|
||||
playlistSetVideoId = playlistSetVideoId,
|
||||
continuation = token
|
||||
)
|
||||
}.map { nextResult ->
|
||||
mediaItems = nextResult.items?.map(YouTube.Item.Song::asMediaItem)
|
||||
|
||||
nextResult.continuation?.takeUnless { token == nextResult.continuation }
|
||||
}.recoverWith(token)
|
||||
nextResult.continuation?.takeUnless { token == nextResult.continuation }
|
||||
}.recoverWith(token)
|
||||
|
||||
return mediaItems ?: emptyList()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun rememberYoutubePlayer(
|
||||
player: Player?
|
||||
): YoutubePlayer? {
|
||||
return remember(player) {
|
||||
YoutubePlayer(player ?: return@remember null).also {
|
||||
player.addListener(it)
|
||||
}
|
||||
return mediaItems ?: emptyList()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue