package it.vfsfitvnm.vimusic.utils import androidx.compose.runtime.* import androidx.media3.common.MediaItem import androidx.media3.session.MediaController import com.google.common.util.concurrent.ListenableFuture import it.vfsfitvnm.youtubemusic.Outcome import it.vfsfitvnm.youtubemusic.YouTube import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.guava.await import kotlinx.coroutines.withContext class YoutubePlayer(mediaController: MediaController) : PlayerState(mediaController) { 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.Initial) suspend fun process(): List { val token = nextContinuation.valueOrNull nextContinuation = Outcome.Loading var mediaItems: List? = 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) nextResult.continuation?.takeUnless { token == nextResult.continuation } }.recoverWith(token) return mediaItems ?: emptyList() } } } val LocalYoutubePlayer = compositionLocalOf { null } @Composable fun rememberYoutubePlayer( mediaControllerFuture: ListenableFuture ): YoutubePlayer? { val mediaController by produceState(initialValue = null) { value = mediaControllerFuture.await() } val playerState = remember(mediaController) { YoutubePlayer(mediaController ?: return@remember null).also { // TODO: should we remove the listener later on? mediaController?.addListener(it) } } return playerState }