fix: autoplay countdown continues although other video selected

This commit is contained in:
Bnyro 2024-12-02 20:44:32 +01:00
parent 9458b5597b
commit 40c885316d
5 changed files with 55 additions and 26 deletions

View File

@ -7,8 +7,10 @@ import android.os.Looper
import android.view.KeyEvent
import androidx.annotation.OptIn
import androidx.core.app.ServiceCompat
import androidx.core.os.bundleOf
import androidx.core.os.postDelayed
import androidx.media3.common.C
import androidx.media3.common.MediaMetadata
import androidx.media3.common.PlaybackException
import androidx.media3.common.Player
import androidx.media3.common.util.UnstableApi
@ -22,6 +24,7 @@ import androidx.media3.session.SessionCommand
import androidx.media3.session.SessionResult
import com.github.libretube.R
import com.github.libretube.api.obj.Subtitle
import com.github.libretube.constants.IntentData
import com.github.libretube.enums.PlayerCommand
import com.github.libretube.enums.PlayerEvent
import com.github.libretube.extensions.parcelable
@ -47,6 +50,8 @@ abstract class AbstractPlayerService : MediaLibraryService(), MediaLibrarySessio
var trackSelector: DefaultTrackSelector? = null
lateinit var videoId: String
private set
var isTransitioning = true
val handler = Handler(Looper.getMainLooper())
@ -170,7 +175,7 @@ abstract class AbstractPlayerService : MediaLibraryService(), MediaLibrarySessio
}
private fun navigateVideo(videoId: String) {
this.videoId = videoId
setVideoId(videoId)
CoroutineScope(Dispatchers.IO).launch {
startPlayback()
@ -185,6 +190,28 @@ abstract class AbstractPlayerService : MediaLibraryService(), MediaLibrarySessio
}
}
/**
* Update the [videoId] to the new videoId and change the playlist metadata
* to reflect that videoId change
*/
protected fun setVideoId(videoId: String) {
this.videoId = videoId
updatePlaylistMetadata {
setExtras(bundleOf(IntentData.videoId to videoId))
}
}
protected fun updatePlaylistMetadata(updateAction: MediaMetadata.Builder.() -> Unit) {
handler.post {
exoPlayer?.playlistMetadata = MediaMetadata.Builder()
.apply(updateAction)
// send a unique timestamp to notify that the metadata changed, even if playing the same video twice
.setTrackNumber(System.currentTimeMillis().mod(Int.MAX_VALUE))
.build()
}
}
private fun handlePlayerAction(event: PlayerEvent) {
if (PlayerHelper.handlePlayerAction(exoPlayer ?: return, event)) return
@ -303,7 +330,7 @@ abstract class AbstractPlayerService : MediaLibraryService(), MediaLibrarySessio
*/
abstract suspend fun startPlayback()
fun saveWatchPosition() {
private fun saveWatchPosition() {
if (isTransitioning || !PlayerHelper.watchPositionsVideo) return
exoPlayer?.let { PlayerHelper.saveWatchPosition(it, videoId) }

View File

@ -56,13 +56,14 @@ open class OfflinePlayerService : AbstractPlayerService() {
shuffle = args.getBoolean(IntentData.shuffle, false)
noInternetService = args.getBoolean(IntentData.noInternet, false)
videoId = if (shuffle) {
val videoId = if (shuffle) {
runBlocking(Dispatchers.IO) {
Database.downloadDao().getRandomVideoIdByFileType(FileType.AUDIO)
}
} else {
args.getString(IntentData.videoId)
} ?: return
setVideoId(videoId)
PlayingQueue.clear()
@ -131,9 +132,7 @@ open class OfflinePlayerService : AbstractPlayerService() {
}
private fun playNextVideo(videoId: String) {
saveWatchPosition()
this.videoId = videoId
setVideoId(videoId)
scope.launch {
startPlayback()

View File

@ -6,7 +6,6 @@ import androidx.core.net.toUri
import androidx.core.os.bundleOf
import androidx.media3.common.MediaItem
import androidx.media3.common.MediaItem.SubtitleConfiguration
import androidx.media3.common.MediaMetadata
import androidx.media3.common.MimeTypes
import androidx.media3.common.Player
import androidx.media3.datasource.cronet.CronetDataSource
@ -106,7 +105,7 @@ open class OnlinePlayerService : AbstractPlayerService() {
}
// get the intent arguments
videoId = playerData.videoId
setVideoId(playerData.videoId)
playlistId = playerData.playlistId
channelId = playerData.channelId
startTimestamp = playerData.timestamp
@ -178,8 +177,6 @@ open class OnlinePlayerService : AbstractPlayerService() {
* Plays the next video from the queue
*/
private fun playNextVideo(nextId: String? = null) {
saveWatchPosition()
if (nextId == null) {
if (PlayingQueue.repeatMode == Player.REPEAT_MODE_ONE) {
exoPlayer?.seekTo(0)
@ -192,7 +189,7 @@ open class OnlinePlayerService : AbstractPlayerService() {
val nextVideo = nextId ?: PlayingQueue.getNext() ?: return
// play new video on background
this.videoId = nextVideo
setVideoId(nextVideo)
this.streams = null
this.sponsorBlockSegments = emptyList()
@ -214,9 +211,9 @@ open class OnlinePlayerService : AbstractPlayerService() {
).segments
withContext(Dispatchers.Main) {
exoPlayer?.playlistMetadata = MediaMetadata.Builder()
.setExtras(bundleOf(IntentData.segments to ArrayList(sponsorBlockSegments)))
.build()
updatePlaylistMetadata {
setExtras(bundleOf(IntentData.segments to ArrayList(sponsorBlockSegments)))
}
checkForSegments()
}

View File

@ -305,16 +305,6 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
override fun onMediaMetadataChanged(mediaMetadata: MediaMetadata) {
super.onMediaMetadataChanged(mediaMetadata)
mediaMetadata.extras?.getString(IntentData.videoId)?.let {
videoId = it
// fix: if the fragment is recreated, play the current video, and not the initial one
arguments?.run {
val playerData =
parcelable<PlayerData>(IntentData.playerData)!!.copy(videoId = videoId)
putParcelable(IntentData.playerData, playerData)
}
}
val maybeStreams: Streams? = mediaMetadata.extras?.parcelable(IntentData.streams)
maybeStreams?.let { streams ->
this@PlayerFragment.streams = streams
@ -327,6 +317,18 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
override fun onPlaylistMetadataChanged(mediaMetadata: MediaMetadata) {
super.onPlaylistMetadataChanged(mediaMetadata)
mediaMetadata.extras?.getString(IntentData.videoId)?.let {
videoId = it
_binding?.autoplayCountdown?.cancelAndHideCountdown()
// fix: if the fragment is recreated, play the current video, and not the initial one
arguments?.run {
val playerData =
parcelable<PlayerData>(IntentData.playerData)!!.copy(videoId = videoId)
putParcelable(IntentData.playerData, playerData)
}
}
val segments: List<Segment>? = mediaMetadata.extras?.parcelableList(IntentData.segments)
viewModel.segments.postValue(segments.orEmpty())
}

View File

@ -34,8 +34,7 @@ class AutoplayCountdownView(
init {
binding.cancel.setOnClickListener {
handler.removeCallbacksAndMessages(TIMER_RUNNABLE_TOKEN)
hideSelf.invoke()
cancelAndHideCountdown()
}
}
@ -78,6 +77,11 @@ class AutoplayCountdownView(
handler.postDelayed(1000, TIMER_RUNNABLE_TOKEN, this::updateCountdown)
}
fun cancelAndHideCountdown() {
handler.removeCallbacksAndMessages(TIMER_RUNNABLE_TOKEN)
hideSelf.invoke()
}
companion object {
private const val COUNTDOWN_SECONDS = 5
private const val TIMER_RUNNABLE_TOKEN = "timer_runnable"