From 09660cd5d6a7e2bfaa5bbb1e41f6cb674c9b090a Mon Sep 17 00:00:00 2001 From: Bnyro Date: Mon, 31 Mar 2025 18:58:38 +0200 Subject: [PATCH] refactor: merge OfflinePlayerService with VideoOfflinePlayerService --- .../libretube/helpers/BackgroundHelper.kt | 7 +- .../services/AbstractPlayerService.kt | 8 -- .../services/OfflinePlayerService.kt | 85 ++++++++++++++++--- .../libretube/services/OnlinePlayerService.kt | 7 +- .../services/VideoOfflinePlayerService.kt | 85 ------------------- .../ui/activities/OfflinePlayerActivity.kt | 7 +- .../ui/fragments/AudioPlayerFragment.kt | 1 - 7 files changed, 84 insertions(+), 116 deletions(-) delete mode 100644 app/src/main/java/com/github/libretube/services/VideoOfflinePlayerService.kt diff --git a/app/src/main/java/com/github/libretube/helpers/BackgroundHelper.kt b/app/src/main/java/com/github/libretube/helpers/BackgroundHelper.kt index 2e1467191..bcc575d57 100644 --- a/app/src/main/java/com/github/libretube/helpers/BackgroundHelper.kt +++ b/app/src/main/java/com/github/libretube/helpers/BackgroundHelper.kt @@ -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) diff --git a/app/src/main/java/com/github/libretube/services/AbstractPlayerService.kt b/app/src/main/java/com/github/libretube/services/AbstractPlayerService.kt index 4f9af2947..e3c4e9f64 100644 --- a/app/src/main/java/com/github/libretube/services/AbstractPlayerService.kt +++ b/app/src/main/java/com/github/libretube/services/AbstractPlayerService.kt @@ -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() } } diff --git a/app/src/main/java/com/github/libretube/services/OfflinePlayerService.kt b/app/src/main/java/com/github/libretube/services/OfflinePlayerService.kt index 78601d775..f4d4f2c4b 100644 --- a/app/src/main/java/com/github/libretube/services/OfflinePlayerService.kt +++ b/app/src/main/java/com/github/libretube/services/OfflinePlayerService.kt @@ -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() { diff --git a/app/src/main/java/com/github/libretube/services/OnlinePlayerService.kt b/app/src/main/java/com/github/libretube/services/OnlinePlayerService.kt index e5c78c8a8..a4e1d971a 100644 --- a/app/src/main/java/com/github/libretube/services/OnlinePlayerService.kt +++ b/app/src/main/java/com/github/libretube/services/OnlinePlayerService.kt @@ -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 diff --git a/app/src/main/java/com/github/libretube/services/VideoOfflinePlayerService.kt b/app/src/main/java/com/github/libretube/services/VideoOfflinePlayerService.kt deleted file mode 100644 index deae198e6..000000000 --- a/app/src/main/java/com/github/libretube/services/VideoOfflinePlayerService.kt +++ /dev/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) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/github/libretube/ui/activities/OfflinePlayerActivity.kt b/app/src/main/java/com/github/libretube/ui/activities/OfflinePlayerActivity.kt index 58923c9c1..1daaa8840 100644 --- a/app/src/main/java/com/github/libretube/ui/activities/OfflinePlayerActivity.kt +++ b/app/src/main/java/com/github/libretube/ui/activities/OfflinePlayerActivity.kt @@ -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() diff --git a/app/src/main/java/com/github/libretube/ui/fragments/AudioPlayerFragment.kt b/app/src/main/java/com/github/libretube/ui/fragments/AudioPlayerFragment.kt index e0fe53883..8a3064202 100644 --- a/app/src/main/java/com/github/libretube/ui/fragments/AudioPlayerFragment.kt +++ b/app/src/main/java/com/github/libretube/ui/fragments/AudioPlayerFragment.kt @@ -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)