mirror of
https://github.com/libre-tube/LibreTube.git
synced 2025-04-27 23:40:33 +05:30
refactor: merge OfflinePlayerService with VideoOfflinePlayerService
This commit is contained in:
parent
caaa095faf
commit
09660cd5d6
@ -17,7 +17,6 @@ import com.github.libretube.parcelable.PlayerData
|
||||
import com.github.libretube.services.AbstractPlayerService
|
||||
import com.github.libretube.services.OfflinePlayerService
|
||||
import com.github.libretube.services.OnlinePlayerService
|
||||
import com.github.libretube.services.VideoOfflinePlayerService
|
||||
import com.github.libretube.ui.activities.MainActivity
|
||||
import com.github.libretube.ui.activities.NoInternetActivity
|
||||
import com.github.libretube.ui.fragments.DownloadTab
|
||||
@ -65,8 +64,7 @@ object BackgroundHelper {
|
||||
fun stopBackgroundPlay(context: Context) {
|
||||
arrayOf(
|
||||
OnlinePlayerService::class.java,
|
||||
OfflinePlayerService::class.java,
|
||||
VideoOfflinePlayerService::class.java
|
||||
OfflinePlayerService::class.java
|
||||
).forEach {
|
||||
val intent = Intent(context, it)
|
||||
context.stopService(intent)
|
||||
@ -104,7 +102,8 @@ object BackgroundHelper {
|
||||
IntentData.videoId to videoId,
|
||||
IntentData.shuffle to shuffle,
|
||||
IntentData.downloadTab to downloadTab,
|
||||
IntentData.noInternet to noInternet
|
||||
IntentData.noInternet to noInternet,
|
||||
IntentData.audioOnly to true
|
||||
)
|
||||
|
||||
startMediaService(context, OfflinePlayerService::class.java, arguments)
|
||||
|
@ -15,7 +15,6 @@ import androidx.media3.common.ForwardingPlayer
|
||||
import androidx.media3.common.MediaMetadata
|
||||
import androidx.media3.common.PlaybackException
|
||||
import androidx.media3.common.Player
|
||||
import androidx.media3.common.util.Log
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.media3.exoplayer.ExoPlayer
|
||||
import androidx.media3.exoplayer.trackselection.DefaultTrackSelector
|
||||
@ -119,13 +118,6 @@ abstract class AbstractPlayerService : MediaLibraryService(), MediaLibrarySessio
|
||||
onServiceCreated(args)
|
||||
notificationProvider?.intentActivity = getIntentActivity()
|
||||
|
||||
if (isAudioOnlyPlayer) {
|
||||
trackSelector?.updateParameters {
|
||||
setTrackTypeDisabled(C.TRACK_TYPE_VIDEO, true)
|
||||
}
|
||||
}
|
||||
|
||||
Log.e("custom start", "custom start")
|
||||
if (::videoId.isInitialized) startPlayback()
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,16 @@ package com.github.libretube.services
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.annotation.OptIn
|
||||
import androidx.media3.common.C
|
||||
import androidx.media3.common.MediaItem
|
||||
import androidx.media3.common.MediaItem.SubtitleConfiguration
|
||||
import androidx.media3.common.MimeTypes
|
||||
import androidx.media3.common.Player
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.media3.datasource.FileDataSource
|
||||
import androidx.media3.exoplayer.source.MergingMediaSource
|
||||
import androidx.media3.exoplayer.source.ProgressiveMediaSource
|
||||
import androidx.media3.exoplayer.source.SingleSampleMediaSource
|
||||
import com.github.libretube.constants.IntentData
|
||||
import com.github.libretube.db.DatabaseHelper
|
||||
import com.github.libretube.db.DatabaseHolder.Database
|
||||
@ -15,6 +22,7 @@ import com.github.libretube.enums.FileType
|
||||
import com.github.libretube.extensions.serializable
|
||||
import com.github.libretube.extensions.setMetadata
|
||||
import com.github.libretube.extensions.toAndroidUri
|
||||
import com.github.libretube.extensions.updateParameters
|
||||
import com.github.libretube.helpers.PlayerHelper
|
||||
import com.github.libretube.ui.activities.MainActivity
|
||||
import com.github.libretube.ui.activities.NoInternetActivity
|
||||
@ -65,6 +73,7 @@ open class OfflinePlayerService : AbstractPlayerService() {
|
||||
downloadTab = args.serializable(IntentData.downloadTab)!!
|
||||
shuffle = args.getBoolean(IntentData.shuffle, false)
|
||||
noInternetService = args.getBoolean(IntentData.noInternet, false)
|
||||
isAudioOnlyPlayer = args.getBoolean(IntentData.audioOnly, false)
|
||||
|
||||
val videoId = if (shuffle) {
|
||||
runBlocking(Dispatchers.IO) {
|
||||
@ -75,10 +84,12 @@ open class OfflinePlayerService : AbstractPlayerService() {
|
||||
} ?: return
|
||||
setVideoId(videoId)
|
||||
|
||||
PlayingQueue.clear()
|
||||
|
||||
exoPlayer?.addListener(playerListener)
|
||||
trackSelector?.updateParameters {
|
||||
setTrackTypeDisabled(C.TRACK_TYPE_VIDEO, isAudioOnlyPlayer)
|
||||
}
|
||||
|
||||
PlayingQueue.clear()
|
||||
fillQueue()
|
||||
}
|
||||
|
||||
@ -116,23 +127,71 @@ open class OfflinePlayerService : AbstractPlayerService() {
|
||||
}
|
||||
}
|
||||
|
||||
open fun setMediaItem(downloadWithItems: DownloadWithItems) {
|
||||
val audioItem = downloadWithItems.downloadItems.filter { it.path.exists() }
|
||||
.firstOrNull { it.type == FileType.AUDIO }
|
||||
?: // in some rare cases, video files can contain audio
|
||||
downloadWithItems.downloadItems.firstOrNull { it.type == FileType.VIDEO }
|
||||
private fun setMediaItem(downloadWithItems: DownloadWithItems) {
|
||||
val downloadFiles = downloadWithItems.downloadItems.filter { it.path.exists() }
|
||||
|
||||
if (audioItem == null) {
|
||||
val videoUri = downloadFiles.firstOrNull { it.type == FileType.VIDEO }?.path?.toAndroidUri()
|
||||
val audioUri = downloadFiles.firstOrNull { it.type == FileType.AUDIO }?.path?.toAndroidUri()
|
||||
if (isAudioOnlyPlayer && audioUri == null) {
|
||||
stopSelf()
|
||||
return
|
||||
}
|
||||
|
||||
val mediaItem = MediaItem.Builder()
|
||||
.setUri(audioItem.path.toAndroidUri())
|
||||
.setMetadata(downloadWithItems)
|
||||
.build()
|
||||
val subtitleInfo = downloadFiles.firstOrNull { it.type == FileType.SUBTITLE }
|
||||
|
||||
exoPlayer?.setMediaItem(mediaItem)
|
||||
val subtitle = subtitleInfo?.let {
|
||||
SubtitleConfiguration.Builder(it.path.toAndroidUri())
|
||||
.setMimeType(MimeTypes.APPLICATION_TTML)
|
||||
.setLanguage(it.language ?: "en")
|
||||
.build()
|
||||
}
|
||||
|
||||
when {
|
||||
videoUri != null && audioUri != null -> {
|
||||
val videoItem = MediaItem.Builder()
|
||||
.setUri(videoUri)
|
||||
.setMetadata(downloadWithItems)
|
||||
.setSubtitleConfigurations(listOfNotNull(subtitle))
|
||||
.build()
|
||||
|
||||
val videoSource = ProgressiveMediaSource.Factory(FileDataSource.Factory())
|
||||
.createMediaSource(videoItem)
|
||||
|
||||
val audioSource = ProgressiveMediaSource.Factory(FileDataSource.Factory())
|
||||
.createMediaSource(MediaItem.fromUri(audioUri))
|
||||
|
||||
var mediaSource = MergingMediaSource(audioSource, videoSource)
|
||||
if (subtitle != null) {
|
||||
val subtitleSource = SingleSampleMediaSource.Factory(FileDataSource.Factory())
|
||||
.createMediaSource(subtitle, C.TIME_UNSET)
|
||||
|
||||
mediaSource = MergingMediaSource(mediaSource, subtitleSource)
|
||||
}
|
||||
|
||||
exoPlayer?.setMediaSource(mediaSource)
|
||||
}
|
||||
|
||||
videoUri != null -> exoPlayer?.setMediaItem(
|
||||
MediaItem.Builder()
|
||||
.setUri(videoUri)
|
||||
.setMetadata(downloadWithItems)
|
||||
.setSubtitleConfigurations(listOfNotNull(subtitle))
|
||||
.build()
|
||||
)
|
||||
|
||||
audioUri != null -> exoPlayer?.setMediaItem(
|
||||
MediaItem.Builder()
|
||||
.setUri(audioUri)
|
||||
.setMetadata(downloadWithItems)
|
||||
.setSubtitleConfigurations(listOfNotNull(subtitle))
|
||||
.build()
|
||||
)
|
||||
}
|
||||
|
||||
trackSelector?.updateParameters {
|
||||
setPreferredTextRoleFlags(C.ROLE_FLAG_CAPTION)
|
||||
setPreferredTextLanguage(subtitle?.language)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun fillQueue() {
|
||||
|
@ -4,6 +4,7 @@ import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import androidx.core.net.toUri
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.media3.common.C
|
||||
import androidx.media3.common.MediaItem
|
||||
import androidx.media3.common.MediaItem.SubtitleConfiguration
|
||||
import androidx.media3.common.MimeTypes
|
||||
@ -25,6 +26,7 @@ import com.github.libretube.extensions.parcelable
|
||||
import com.github.libretube.extensions.setMetadata
|
||||
import com.github.libretube.extensions.toastFromMainDispatcher
|
||||
import com.github.libretube.extensions.toastFromMainThread
|
||||
import com.github.libretube.extensions.updateParameters
|
||||
import com.github.libretube.helpers.PlayerHelper
|
||||
import com.github.libretube.helpers.PlayerHelper.checkForSegments
|
||||
import com.github.libretube.helpers.PlayerHelper.getSubtitleRoleFlags
|
||||
@ -112,13 +114,14 @@ open class OnlinePlayerService : AbstractPlayerService() {
|
||||
if (!playerData.keepQueue) PlayingQueue.clear()
|
||||
|
||||
exoPlayer?.addListener(playerListener)
|
||||
trackSelector?.updateParameters {
|
||||
setTrackTypeDisabled(C.TRACK_TYPE_VIDEO, isAudioOnlyPlayer)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun startPlayback() {
|
||||
super.startPlayback()
|
||||
|
||||
Log.e("start", "playback")
|
||||
|
||||
val timestampMs = startTimestampSeconds?.times(1000) ?: 0L
|
||||
startTimestampSeconds = null
|
||||
|
||||
|
@ -1,85 +0,0 @@
|
||||
package com.github.libretube.services
|
||||
|
||||
import androidx.annotation.OptIn
|
||||
import androidx.media3.common.C
|
||||
import androidx.media3.common.MediaItem
|
||||
import androidx.media3.common.MediaItem.SubtitleConfiguration
|
||||
import androidx.media3.common.MimeTypes
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.media3.datasource.FileDataSource
|
||||
import androidx.media3.exoplayer.source.MergingMediaSource
|
||||
import androidx.media3.exoplayer.source.ProgressiveMediaSource
|
||||
import androidx.media3.exoplayer.source.SingleSampleMediaSource
|
||||
import com.github.libretube.db.obj.DownloadWithItems
|
||||
import com.github.libretube.enums.FileType
|
||||
import com.github.libretube.extensions.setMetadata
|
||||
import com.github.libretube.extensions.toAndroidUri
|
||||
import com.github.libretube.extensions.updateParameters
|
||||
import kotlin.io.path.exists
|
||||
|
||||
@OptIn(UnstableApi::class)
|
||||
class VideoOfflinePlayerService: OfflinePlayerService() {
|
||||
override var isAudioOnlyPlayer = false
|
||||
|
||||
override fun setMediaItem(downloadWithItems: DownloadWithItems) {
|
||||
val downloadFiles = downloadWithItems.downloadItems.filter { it.path.exists() }
|
||||
|
||||
val videoUri = downloadFiles.firstOrNull { it.type == FileType.VIDEO }?.path?.toAndroidUri()
|
||||
val audioUri = downloadFiles.firstOrNull { it.type == FileType.AUDIO }?.path?.toAndroidUri()
|
||||
val subtitleInfo = downloadFiles.firstOrNull { it.type == FileType.SUBTITLE }
|
||||
|
||||
val subtitle = subtitleInfo?.let {
|
||||
SubtitleConfiguration.Builder(it.path.toAndroidUri())
|
||||
.setMimeType(MimeTypes.APPLICATION_TTML)
|
||||
.setLanguage(it.language ?: "en")
|
||||
.build()
|
||||
}
|
||||
|
||||
when {
|
||||
videoUri != null && audioUri != null -> {
|
||||
val videoItem = MediaItem.Builder()
|
||||
.setUri(videoUri)
|
||||
.setMetadata(downloadWithItems)
|
||||
.setSubtitleConfigurations(listOfNotNull(subtitle))
|
||||
.build()
|
||||
|
||||
val videoSource = ProgressiveMediaSource.Factory(FileDataSource.Factory())
|
||||
.createMediaSource(videoItem)
|
||||
|
||||
val audioSource = ProgressiveMediaSource.Factory(FileDataSource.Factory())
|
||||
.createMediaSource(MediaItem.fromUri(audioUri))
|
||||
|
||||
var mediaSource = MergingMediaSource(audioSource, videoSource)
|
||||
if (subtitle != null) {
|
||||
val subtitleSource = SingleSampleMediaSource.Factory(FileDataSource.Factory())
|
||||
.createMediaSource(subtitle, C.TIME_UNSET)
|
||||
|
||||
mediaSource = MergingMediaSource(mediaSource, subtitleSource)
|
||||
}
|
||||
|
||||
exoPlayer?.setMediaSource(mediaSource)
|
||||
}
|
||||
|
||||
videoUri != null -> exoPlayer?.setMediaItem(
|
||||
MediaItem.Builder()
|
||||
.setUri(videoUri)
|
||||
.setMetadata(downloadWithItems)
|
||||
.setSubtitleConfigurations(listOfNotNull(subtitle))
|
||||
.build()
|
||||
)
|
||||
|
||||
audioUri != null -> exoPlayer?.setMediaItem(
|
||||
MediaItem.Builder()
|
||||
.setUri(audioUri)
|
||||
.setMetadata(downloadWithItems)
|
||||
.setSubtitleConfigurations(listOfNotNull(subtitle))
|
||||
.build()
|
||||
)
|
||||
}
|
||||
|
||||
trackSelector?.updateParameters {
|
||||
setPreferredTextRoleFlags(C.ROLE_FLAG_CAPTION)
|
||||
setPreferredTextLanguage(subtitle?.language)
|
||||
}
|
||||
}
|
||||
}
|
@ -32,7 +32,7 @@ import com.github.libretube.helpers.BackgroundHelper
|
||||
import com.github.libretube.helpers.PlayerHelper
|
||||
import com.github.libretube.helpers.WindowHelper
|
||||
import com.github.libretube.services.AbstractPlayerService
|
||||
import com.github.libretube.services.VideoOfflinePlayerService
|
||||
import com.github.libretube.services.OfflinePlayerService
|
||||
import com.github.libretube.ui.base.BaseActivity
|
||||
import com.github.libretube.ui.fragments.DownloadTab
|
||||
import com.github.libretube.ui.interfaces.TimeFrameReceiver
|
||||
@ -139,9 +139,10 @@ class OfflinePlayerActivity : BaseActivity() {
|
||||
|
||||
val arguments = bundleOf(
|
||||
IntentData.downloadTab to DownloadTab.VIDEO,
|
||||
IntentData.videoId to videoId
|
||||
IntentData.videoId to videoId,
|
||||
IntentData.audioOnly to false
|
||||
)
|
||||
BackgroundHelper.startMediaService(this, VideoOfflinePlayerService::class.java, arguments) {
|
||||
BackgroundHelper.startMediaService(this, OfflinePlayerService::class.java, arguments) {
|
||||
playerController = it
|
||||
playerController.addListener(playerListener)
|
||||
initializePlayerView()
|
||||
|
@ -95,7 +95,6 @@ class AudioPlayerFragment : Fragment(R.layout.fragment_audio_player), AudioPlaye
|
||||
BackgroundHelper.startMediaService(
|
||||
requireContext(),
|
||||
if (isOffline) OfflinePlayerService::class.java else OnlinePlayerService::class.java,
|
||||
bundleOf()
|
||||
) {
|
||||
if (_binding == null) {
|
||||
it.sendCustomCommand(AbstractPlayerService.stopServiceCommand, Bundle.EMPTY)
|
||||
|
Loading…
x
Reference in New Issue
Block a user