Add PlayerData class.

This commit is contained in:
Isira Seneviratne 2023-06-17 07:57:56 +05:30
parent 829ec7eb57
commit 5bb4f303b0
9 changed files with 81 additions and 76 deletions

View File

@ -2,14 +2,12 @@ package com.github.libretube.constants
object IntentData {
const val downloadData = "downloadData"
const val playerData = "playerData"
const val videoId = "videoId"
const val channelId = "channelId"
const val channelName = "channelName"
const val playlistId = "playlistId"
const val timeStamp = "timeStamp"
const val position = "position"
const val fileName = "fileName"
const val keepQueue = "keepQueue"
const val playlistType = "playlistType"
const val downloading = "downloading"
const val openAudioPlayer = "openAudioPlayer"

View File

@ -0,0 +1,9 @@
package com.github.libretube.extensions
import android.os.Bundle
import android.os.Parcelable
import androidx.core.os.BundleCompat
inline fun <reified T : Parcelable> Bundle.parcelable(key: String?): T? {
return BundleCompat.getParcelable(this, key, T::class.java)
}

View File

@ -7,8 +7,8 @@ import androidx.core.content.ContextCompat
import androidx.core.content.getSystemService
import androidx.fragment.app.commit
import com.github.libretube.constants.IntentData
import com.github.libretube.parcelable.PlayerData
import com.github.libretube.services.OnlinePlayerService
import com.github.libretube.ui.activities.MainActivity
import com.github.libretube.ui.fragments.PlayerFragment
/**
@ -23,10 +23,10 @@ object BackgroundHelper {
fun playOnBackground(
context: Context,
videoId: String,
position: Long? = null,
position: Long = 0,
playlistId: String? = null,
channelId: String? = null,
keepQueue: Boolean? = null,
keepQueue: Boolean = false,
keepVideoPlayerAlive: Boolean = false,
) {
// close the previous video player if open
@ -38,12 +38,9 @@ object BackgroundHelper {
}
// create an intent for the background mode service
val playerData = PlayerData(videoId, playlistId, channelId, keepQueue, position)
val intent = Intent(context, OnlinePlayerService::class.java)
.putExtra(IntentData.videoId, videoId)
.putExtra(IntentData.playlistId, playlistId)
.putExtra(IntentData.channelId, channelId)
.putExtra(IntentData.position, position)
.putExtra(IntentData.keepQueue, keepQueue)
.putExtra(IntentData.playerData, playerData)
// start the background mode as foreground service
ContextCompat.startForegroundService(context, intent)

View File

@ -16,6 +16,7 @@ import com.github.libretube.constants.IntentData
import com.github.libretube.constants.PreferenceKeys
import com.github.libretube.enums.PlaylistType
import com.github.libretube.extensions.toID
import com.github.libretube.parcelable.PlayerData
import com.github.libretube.ui.fragments.AudioPlayerFragment
import com.github.libretube.ui.fragments.PlayerFragment
import com.github.libretube.ui.views.SingleViewTouchableMotionLayout
@ -53,7 +54,7 @@ object NavigationHelper {
playlistId: String? = null,
channelId: String? = null,
keepQueue: Boolean = false,
timeStamp: Long? = null,
timestamp: Long = 0,
forceVideo: Boolean = false,
) {
if (videoId == null) return
@ -63,7 +64,7 @@ object NavigationHelper {
BackgroundHelper.playOnBackground(
context,
videoId.toID(),
timeStamp,
timestamp,
playlistId,
channelId,
keepQueue,
@ -74,13 +75,8 @@ object NavigationHelper {
return
}
val bundle = bundleOf(
IntentData.videoId to videoId.toID(),
IntentData.playlistId to playlistId,
IntentData.channelId to channelId,
IntentData.keepQueue to keepQueue,
IntentData.timeStamp to timeStamp,
)
val playerData = PlayerData(videoId.toID(), playlistId, channelId, keepQueue, timestamp)
val bundle = bundleOf(IntentData.playerData to playerData)
val activity = ContextHelper.unwrapActivity(context)
activity.supportFragmentManager.commitNow {

View File

@ -0,0 +1,13 @@
package com.github.libretube.parcelable
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
@Parcelize
data class PlayerData(
val videoId: String,
val playlistId: String? = null,
val channelId: String? = null,
val keepQueue: Boolean = false,
val timestamp: Long = 0
) : Parcelable

View File

@ -6,7 +6,6 @@ import android.os.Binder
import android.os.Handler
import android.os.IBinder
import android.os.Looper
import android.util.Log
import android.widget.Toast
import androidx.core.app.NotificationCompat
import androidx.core.app.ServiceCompat
@ -28,7 +27,7 @@ import com.github.libretube.constants.IntentData
import com.github.libretube.constants.PLAYER_NOTIFICATION_ID
import com.github.libretube.db.DatabaseHolder.Database
import com.github.libretube.db.obj.WatchPosition
import com.github.libretube.extensions.TAG
import com.github.libretube.extensions.parcelableExtra
import com.github.libretube.extensions.setMetadata
import com.github.libretube.extensions.toID
import com.github.libretube.helpers.PlayerHelper
@ -36,6 +35,7 @@ import com.github.libretube.helpers.PlayerHelper.checkForSegments
import com.github.libretube.helpers.PlayerHelper.loadPlaybackParams
import com.github.libretube.helpers.ProxyHelper
import com.github.libretube.obj.PlayerNotificationData
import com.github.libretube.parcelable.PlayerData
import com.github.libretube.util.NowPlayingNotification
import com.github.libretube.util.PlayingQueue
import kotlinx.coroutines.CoroutineScope
@ -117,27 +117,24 @@ class OnlinePlayerService : LifecycleService() {
* Initializes the [player] with the [MediaItem].
*/
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
try {
// reset the playing queue listeners
PlayingQueue.resetToDefaults()
// reset the playing queue listeners
PlayingQueue.resetToDefaults()
intent?.parcelableExtra<PlayerData>(IntentData.playerData)?.let { playerData ->
// get the intent arguments
videoId = intent?.getStringExtra(IntentData.videoId)!!
playlistId = intent.getStringExtra(IntentData.playlistId)
val position = intent.getLongExtra(IntentData.position, 0L)
val keepQueue = intent.getBooleanExtra(IntentData.keepQueue, false)
videoId = playerData.videoId
playlistId = playerData.playlistId
// play the audio in the background
loadAudio(videoId, position, keepQueue)
loadAudio(playerData)
PlayingQueue.setOnQueueTapListener { streamItem ->
streamItem.url?.toID()?.let { playNextVideo(it) }
}
if (PlayerHelper.watchPositionsAudio) updateWatchPosition()
} catch (e: Exception) {
Log.e(TAG(), e.toString())
onDestroy()
if (PlayerHelper.watchPositionsAudio) {
updateWatchPosition()
}
}
return super.onStartCommand(intent, flags, startId)
}
@ -158,15 +155,10 @@ class OnlinePlayerService : LifecycleService() {
/**
* Gets the video data and prepares the [player].
* @param videoId The id of the video to play
* @param seekToPosition The position of the video to seek to
* @param keepQueue Whether to keep the queue or clear it instead
*/
private fun loadAudio(
videoId: String,
seekToPosition: Long = 0,
keepQueue: Boolean = false,
) {
private fun loadAudio(playerData: PlayerData) {
val (videoId, _, _, keepQueue, timestamp) = playerData
lifecycleScope.launch(Dispatchers.IO) {
streams = runCatching {
RetrofitInstance.api.getStreams(videoId)
@ -183,7 +175,7 @@ class OnlinePlayerService : LifecycleService() {
}
withContext(Dispatchers.Main) {
playAudio(seekToPosition)
playAudio(timestamp)
}
}
}
@ -292,7 +284,7 @@ class OnlinePlayerService : LifecycleService() {
this.videoId = nextVideo
this.streams = null
this.segments = emptyList()
loadAudio(videoId, keepQueue = true)
loadAudio(PlayerData(videoId, keepQueue = true))
}
/**

View File

@ -28,7 +28,6 @@ import com.github.libretube.constants.IntentData
import com.github.libretube.constants.PreferenceKeys
import com.github.libretube.databinding.ActivityMainBinding
import com.github.libretube.extensions.toID
import com.github.libretube.helpers.BackgroundHelper
import com.github.libretube.helpers.NavBarHelper
import com.github.libretube.helpers.NavigationHelper
import com.github.libretube.helpers.NetworkHelper
@ -440,7 +439,7 @@ class MainActivity : BaseActivity() {
NavigationHelper.navigateVideo(
context = this,
videoId = it,
timeStamp = intent?.getLongExtra(IntentData.timeStamp, 0L),
timestamp = intent.getLongExtra(IntentData.timeStamp, 0L),
)
}

View File

@ -138,7 +138,7 @@ class AudioPlayerFragment : Fragment(), AudioPlayerOptions {
NavigationHelper.navigateVideo(
context = requireContext(),
videoId = PlayingQueue.getCurrent()?.url?.toID(),
timeStamp = playerService?.player?.currentPosition?.div(1000),
timestamp = playerService?.player?.currentPosition?.div(1000) ?: 0,
keepQueue = true,
forceVideo = true,
)

View File

@ -70,6 +70,7 @@ import com.github.libretube.enums.PlayerEvent
import com.github.libretube.enums.ShareObjectType
import com.github.libretube.extensions.formatShort
import com.github.libretube.extensions.hideKeyboard
import com.github.libretube.extensions.parcelable
import com.github.libretube.extensions.setMetadata
import com.github.libretube.extensions.toID
import com.github.libretube.extensions.toastFromMainDispatcher
@ -86,6 +87,7 @@ import com.github.libretube.helpers.ProxyHelper
import com.github.libretube.obj.PlayerNotificationData
import com.github.libretube.obj.ShareData
import com.github.libretube.obj.VideoResolution
import com.github.libretube.parcelable.PlayerData
import com.github.libretube.services.DownloadService
import com.github.libretube.ui.activities.MainActivity
import com.github.libretube.ui.adapters.ChaptersAdapter
@ -137,11 +139,12 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
/**
* Video information passed by the intent
*/
private var videoId: String? = null
private lateinit var playerData: PlayerData
private lateinit var videoId: String
private var playlistId: String? = null
private var channelId: String? = null
private var keepQueue: Boolean = false
private var timeStamp: Long? = null
private var timeStamp: Long = 0
/**
* Video information fetched at runtime
@ -234,13 +237,12 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
videoId = it.getString(IntentData.videoId)!!.toID()
playlistId = it.getString(IntentData.playlistId)
channelId = it.getString(IntentData.channelId)
keepQueue = it.getBoolean(IntentData.keepQueue, false)
timeStamp = it.getLong(IntentData.timeStamp, 0L)
}
val playerData = requireArguments().parcelable<PlayerData>(IntentData.playerData)!!
videoId = playerData.videoId
playlistId = playerData.playlistId
channelId = playerData.channelId
keepQueue = playerData.keepQueue
timeStamp = playerData.timestamp
// broadcast receiver for PiP actions
context?.registerReceiver(
@ -390,11 +392,10 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
}
binding.commentsToggle.setOnClickListener {
videoId ?: return@setOnClickListener
// set the max height to not cover the currently playing video
commentsViewModel.handleLink = this::handleLink
commentsViewModel.maxHeight = binding.root.height - binding.player.height
commentsViewModel.videoId = videoId
commentsViewModel.videoId = playerData.videoId
CommentsSheet().show(childFragmentManager)
}
@ -434,7 +435,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
if (!this::streams.isInitialized) return@setOnClickListener
val shareDialog =
ShareDialog(
videoId!!,
videoId,
ShareObjectType.VIDEO,
ShareData(
currentVideo = streams.title,
@ -487,7 +488,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
BackgroundHelper.stopBackgroundPlay(requireContext())
BackgroundHelper.playOnBackground(
requireContext(),
videoId!!,
videoId,
exoPlayer.currentPosition,
playlistId,
channelId,
@ -648,7 +649,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
C.TIME_UNSET
)
) return
val watchPosition = WatchPosition(videoId!!, exoPlayer.currentPosition)
val watchPosition = WatchPosition(videoId, exoPlayer.currentPosition)
CoroutineScope(Dispatchers.IO).launch {
Database.watchPositionDao().insert(watchPosition)
}
@ -685,7 +686,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
lifecycleScope.launch(Dispatchers.IO) {
streams = try {
RetrofitInstance.api.getStreams(videoId!!)
RetrofitInstance.api.getStreams(videoId)
} catch (e: IOException) {
context?.toastFromMainDispatcher(R.string.unknown_error, Toast.LENGTH_LONG)
return@launch
@ -700,18 +701,18 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
if (PlayingQueue.isEmpty()) {
lifecycleScope.launch(Dispatchers.IO) {
if (playlistId != null) {
PlayingQueue.insertPlaylist(playlistId!!, streams.toStreamItem(videoId!!))
PlayingQueue.insertPlaylist(playlistId!!, streams.toStreamItem(videoId))
} else if (channelId != null) {
PlayingQueue.insertChannel(channelId!!, streams.toStreamItem(videoId!!))
PlayingQueue.insertChannel(channelId!!, streams.toStreamItem(videoId))
} else {
PlayingQueue.updateCurrent(streams.toStreamItem(videoId!!))
PlayingQueue.updateCurrent(streams.toStreamItem(videoId))
if (PlayerHelper.autoInsertRelatedVideos) {
PlayingQueue.add(*streams.relatedStreams.toTypedArray())
}
}
}
} else {
PlayingQueue.updateCurrent(streams.toStreamItem(videoId!!))
PlayingQueue.updateCurrent(streams.toStreamItem(videoId))
}
if (PreferenceHelper.getBoolean(PreferenceKeys.AUTO_FULLSCREEN_SHORTS, false)) {
@ -761,7 +762,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
// add the video to the watch history
if (PlayerHelper.watchHistoryEnabled) {
DatabaseHelper.addToWatchHistory(videoId!!, streams)
DatabaseHelper.addToWatchHistory(videoId, streams)
}
}
}
@ -777,7 +778,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
if (categories.isEmpty()) return@runCatching
segments =
RetrofitInstance.api.getSegments(
videoId!!,
videoId,
JsonHelper.json.encodeToString(categories),
).segments
if (segments.isEmpty()) return@runCatching
@ -816,7 +817,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
// browse the watch positions
val position = try {
runBlocking {
Database.watchPositionDao().findById(videoId!!)?.position
Database.watchPositionDao().findById(videoId)?.position
}
} catch (e: Exception) {
return
@ -832,11 +833,11 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
*/
private fun trySeekToTimeStamp() {
// support for time stamped links
timeStamp?.let {
if (it != 0L) exoPlayer.seekTo(it * 1000)
if (timeStamp != 0L) {
exoPlayer.seekTo(timeStamp * 1000)
}
// delete the time stamp because it already got consumed
timeStamp = null
timeStamp = 0
}
// used for autoplay and skipping to next video
@ -1001,7 +1002,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
if (streams.duration <= 0) {
Toast.makeText(context, R.string.cannotDownload, Toast.LENGTH_SHORT).show()
} else if (!DownloadService.IS_DOWNLOAD_RUNNING) {
val newFragment = DownloadDialog(videoId!!)
val newFragment = DownloadDialog(videoId)
newFragment.show(childFragmentManager, DownloadDialog::class.java.name)
} else {
Toast.makeText(context, R.string.dlisinprogress, Toast.LENGTH_SHORT)
@ -1034,7 +1035,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
)
binding.relPlayerSave.setOnClickListener {
AddToPlaylistDialog(videoId!!).show(
AddToPlaylistDialog(videoId).show(
childFragmentManager,
AddToPlaylistDialog::class.java.name,
)
@ -1379,7 +1380,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
streams.uploader,
streams.thumbnailUrl,
)
nowPlayingNotification.updatePlayerNotification(videoId!!, playerNotificationData)
nowPlayingNotification.updatePlayerNotification(videoId, playerNotificationData)
}
/**
@ -1458,7 +1459,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
override fun onStatsClicked() {
if (!this::streams.isInitialized) return
StatsDialog(exoPlayer, videoId ?: return)
StatsDialog(exoPlayer, videoId)
.show(childFragmentManager, null)
}