From 8dae4c2b0f3ddc62414c5e7f8016093ca7b9fb45 Mon Sep 17 00:00:00 2001 From: Osten <11805592+LagradOst@users.noreply.github.com> Date: Tue, 1 Aug 2023 01:25:28 +0200 Subject: [PATCH] Self similarity/master (#525) * Migrated to Media3 --------- Co-authored-by: self-similarity <137652432+self-similarity@users.noreply.github.com> --- app/build.gradle.kts | 26 +++++--- .../lagradost/cloudstream3/MainActivity.kt | 3 +- .../ui/player/AbstractPlayerFragment.kt | 49 +++++++-------- .../cloudstream3/ui/player/CS3IPlayer.kt | 63 ++++++++++++------- .../ui/player/CustomSubtitleDecoderFactory.kt | 30 +++++---- .../ui/player/CustomTextRenderer.kt | 4 +- .../cloudstream3/ui/player/GeneratorPlayer.kt | 4 +- .../cloudstream3/ui/player/IPlayer.kt | 14 +++++ .../ui/player/NonFinalTextRenderer.java | 47 +++++++------- .../cloudstream3/ui/player/PlayerPipHelper.kt | 48 +++++++++----- .../ui/player/PlayerSubtitleHelper.kt | 4 +- .../subtitles/ChromecastSubtitlesFragment.kt | 2 +- .../ui/subtitles/SubtitlesFragment.kt | 4 +- .../cloudstream3/utils/CastHelper.kt | 2 +- .../layout/chromecast_subtitle_settings.xml | 2 +- app/src/main/res/layout/fragment_player.xml | 2 +- .../main/res/layout/fragment_player_tv.xml | 2 +- app/src/main/res/layout/fragment_trailer.xml | 2 +- .../main/res/layout/player_custom_layout.xml | 2 +- .../res/layout/player_custom_layout_tv.xml | 2 +- app/src/main/res/layout/subtitle_settings.xml | 3 +- .../main/res/layout/trailer_custom_layout.xml | 2 +- gradle.properties | 2 +- 23 files changed, 189 insertions(+), 130 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 27bd1e48..6fd4ae21 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -18,7 +18,7 @@ fun String.execute() = ByteArrayOutputStream().use { baot -> workingDir = projectDir commandLine = this@execute.split(Regex("\\s")) standardOutput = baot - }.exitValue == 0) + }.exitValue == 0) String(baot.toByteArray()).trim() else null } @@ -78,12 +78,18 @@ android { isDebuggable = false isMinifyEnabled = false isShrinkResources = false - proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) } debug { isDebuggable = true applicationIdSuffix = ".debug" - proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) } } flavorDimensions.add("state") @@ -160,10 +166,16 @@ dependencies { // implementation("androidx.leanback:leanback-paging:1.1.0-alpha09") // Exoplayer - implementation("com.google.android.exoplayer:exoplayer:2.18.2") - implementation("com.google.android.exoplayer:extension-cast:2.18.2") - implementation("com.google.android.exoplayer:extension-mediasession:2.18.2") - implementation("com.google.android.exoplayer:extension-okhttp:2.18.2") + implementation("androidx.media3:media3-common:1.1.0") + implementation("androidx.media3:media3-exoplayer:1.1.0") + implementation("androidx.media3:media3-datasource-okhttp:1.1.0") + implementation("androidx.media3:media3-ui:1.1.0") + implementation("androidx.media3:media3-session:1.1.0") + implementation("androidx.media3:media3-cast:1.1.0") + implementation("androidx.media3:media3-exoplayer-hls:1.1.0") + implementation("androidx.media3:media3-exoplayer-dash:1.1.0") + + // Use the Jellyfin ffmpeg extension for easy ffmpeg audio decoding in exoplayer. Thank you Jellyfin <3 // implementation("org.jellyfin.exoplayer:exoplayer-ffmpeg-extension:2.18.2+1") diff --git a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt index b7add6ff..0728fe61 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt @@ -40,6 +40,7 @@ import androidx.preference.PreferenceManager import com.fasterxml.jackson.databind.DeserializationFeature import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper +import com.google.android.gms.cast.framework.CastButtonFactory import com.google.android.gms.cast.framework.CastContext import com.google.android.gms.cast.framework.Session import com.google.android.gms.cast.framework.SessionManager @@ -62,10 +63,10 @@ import com.lagradost.cloudstream3.CommonActivity.onDialogDismissedEvent import com.lagradost.cloudstream3.CommonActivity.onUserLeaveHint import com.lagradost.cloudstream3.CommonActivity.showToast import com.lagradost.cloudstream3.CommonActivity.updateLocale +import com.lagradost.cloudstream3.mvvm.Resource import com.lagradost.cloudstream3.databinding.ActivityMainBinding import com.lagradost.cloudstream3.databinding.ActivityMainTvBinding import com.lagradost.cloudstream3.databinding.BottomResultviewPreviewBinding -import com.lagradost.cloudstream3.mvvm.Resource import com.lagradost.cloudstream3.mvvm.debugAssert import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.mvvm.normalSafeApiCall diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/AbstractPlayerFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/AbstractPlayerFragment.kt index a00127fd..e6f93377 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/AbstractPlayerFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/AbstractPlayerFragment.kt @@ -7,7 +7,6 @@ import android.graphics.drawable.AnimatedVectorDrawable import android.media.metrics.PlaybackErrorEvent import android.os.Build import android.os.Bundle -import android.support.v4.media.session.MediaSessionCompat import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -20,15 +19,14 @@ import androidx.annotation.LayoutRes import androidx.annotation.StringRes import androidx.core.view.isVisible import androidx.fragment.app.Fragment -import androidx.media.session.MediaButtonReceiver import androidx.preference.PreferenceManager import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat -import com.google.android.exoplayer2.ExoPlayer -import com.google.android.exoplayer2.PlaybackException -import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector -import com.google.android.exoplayer2.ui.AspectRatioFrameLayout -import com.google.android.exoplayer2.ui.PlayerView -import com.google.android.exoplayer2.ui.SubtitleView +import androidx.media3.common.PlaybackException +import androidx.media3.exoplayer.ExoPlayer +import androidx.media3.session.MediaSession +import androidx.media3.ui.AspectRatioFrameLayout +import androidx.media3.ui.PlayerView +import androidx.media3.ui.SubtitleView import com.lagradost.cloudstream3.AcraApplication.Companion.getKey import com.lagradost.cloudstream3.AcraApplication.Companion.setKey import com.lagradost.cloudstream3.CommonActivity.canEnterPipMode @@ -38,6 +36,7 @@ import com.lagradost.cloudstream3.CommonActivity.playerEventListener import com.lagradost.cloudstream3.CommonActivity.showToast import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.mvvm.logError +import com.lagradost.cloudstream3.mvvm.normalSafeApiCall import com.lagradost.cloudstream3.ui.subtitles.SaveCaptionStyle import com.lagradost.cloudstream3.ui.subtitles.SubtitlesFragment import com.lagradost.cloudstream3.utils.AppUtils @@ -179,15 +178,16 @@ abstract class AbstractPlayerFragment( } canEnterPipMode = isPlayingRightNow && hasPipModeSupport - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && isInPIPMode) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { activity?.let { act -> - PlayerPipHelper.updatePIPModeActions(act, isPlayingRightNow) + PlayerPipHelper.updatePIPModeActions(act, isPlayingRightNow, player.getAspectRatio()) } } } private var pipReceiver: BroadcastReceiver? = null override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean) { + super.onPictureInPictureModeChanged(isInPictureInPictureMode) try { isInPIPMode = isInPictureInPictureMode if (isInPictureInPictureMode) { @@ -210,9 +210,7 @@ abstract class AbstractPlayerFragment( } } val filter = IntentFilter() - filter.addAction( - ACTION_MEDIA_CONTROL - ) + filter.addAction(ACTION_MEDIA_CONTROL) activity?.registerReceiver(pipReceiver, filter) val isPlaying = player.getIsPlaying() val isPlayingValue = @@ -223,7 +221,10 @@ abstract class AbstractPlayerFragment( piphide?.isVisible = true exitedPipMode() pipReceiver?.let { - activity?.unregisterReceiver(it) + // Prevents java.lang.IllegalArgumentException: Receiver not registered + normalSafeApiCall { + activity?.unregisterReceiver(it) + } } activity?.hideSystemUI() this.view?.let { UIHelper.hideKeyboard(it) } @@ -276,18 +277,21 @@ abstract class AbstractPlayerFragment( gotoNext = true ) } + PlaybackException.ERROR_CODE_REMOTE_ERROR, PlaybackException.ERROR_CODE_IO_BAD_HTTP_STATUS, PlaybackException.ERROR_CODE_TIMEOUT, PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED, PlaybackException.ERROR_CODE_IO_INVALID_HTTP_CONTENT_TYPE -> { showToast( "${ctx.getString(R.string.remote_error)}\n$errorName ($code)\n$msg", gotoNext = true ) } + PlaybackException.ERROR_CODE_DECODING_FAILED, PlaybackErrorEvent.ERROR_AUDIO_TRACK_INIT_FAILED, PlaybackErrorEvent.ERROR_AUDIO_TRACK_OTHER, PlaybackException.ERROR_CODE_AUDIO_TRACK_WRITE_FAILED, PlaybackException.ERROR_CODE_DECODER_INIT_FAILED, PlaybackException.ERROR_CODE_DECODER_QUERY_FAILED -> { showToast( "${ctx.getString(R.string.render_error)}\n$errorName ($code)\n$msg", gotoNext = true ) } + else -> { showToast( "${ctx.getString(R.string.unexpected_error)}\n$errorName ($code)\n$msg", @@ -296,12 +300,14 @@ abstract class AbstractPlayerFragment( } } } + is InvalidFileException -> { showToast( "${ctx.getString(R.string.source_error)}\n${exception.message}", gotoNext = true ) } + else -> { exception.message?.let { showToast( @@ -322,15 +328,8 @@ abstract class AbstractPlayerFragment( private fun playerUpdated(player: Any?) { if (player is ExoPlayer) { context?.let { ctx -> - val mediaButtonReceiver = ComponentName(ctx, MediaButtonReceiver::class.java) - MediaSessionCompat(ctx, "Player", mediaButtonReceiver, null).let { media -> - //media.setCallback(mMediaSessionCallback) - //media.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS or MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS) - val mediaSessionConnector = MediaSessionConnector(media) - mediaSessionConnector.setPlayer(player) - media.isActive = true - mMediaSessionCompat = media - } + mMediaSession?.release() + mMediaSession = MediaSession.Builder(ctx, player).build() } // Necessary for multiple combined videos @@ -340,8 +339,7 @@ abstract class AbstractPlayerFragment( } } - private var mediaSessionConnector: MediaSessionConnector? = null - private var mMediaSessionCompat: MediaSessionCompat? = null + private var mMediaSession: MediaSession? = null // this can be used in the future for players other than exoplayer //private val mMediaSessionCallback: MediaSessionCompat.Callback = object : MediaSessionCompat.Callback() { @@ -442,6 +440,7 @@ abstract class AbstractPlayerFragment( playerEventListener = null keyEventListener = null canEnterPipMode = false + mMediaSession?.release() SubtitlesFragment.applyStyleEvent -= ::onSubStyleChanged keepScreenOn(false) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/CS3IPlayer.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/CS3IPlayer.kt index f491f995..70e12a47 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/CS3IPlayer.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/CS3IPlayer.kt @@ -5,30 +5,42 @@ import android.net.Uri import android.os.Handler import android.os.Looper import android.util.Log +import android.util.Rational import android.widget.FrameLayout +import androidx.media3.common.C import androidx.preference.PreferenceManager -import com.google.android.exoplayer2.* -import com.google.android.exoplayer2.C.* -import com.google.android.exoplayer2.DefaultRenderersFactory.EXTENSION_RENDERER_MODE_ON -import com.google.android.exoplayer2.DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER -import com.google.android.exoplayer2.database.StandaloneDatabaseProvider -import com.google.android.exoplayer2.ext.okhttp.OkHttpDataSource -import com.google.android.exoplayer2.mediacodec.MediaCodecSelector -import com.google.android.exoplayer2.source.* -import com.google.android.exoplayer2.text.TextRenderer -import com.google.android.exoplayer2.trackselection.DefaultTrackSelector -import com.google.android.exoplayer2.trackselection.TrackSelectionOverride -import com.google.android.exoplayer2.trackselection.TrackSelector -import com.google.android.exoplayer2.ui.SubtitleView -import com.google.android.exoplayer2.upstream.DataSource -import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory -import com.google.android.exoplayer2.upstream.DefaultHttpDataSource -import com.google.android.exoplayer2.upstream.HttpDataSource -import com.google.android.exoplayer2.upstream.cache.CacheDataSource -import com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvictor -import com.google.android.exoplayer2.upstream.cache.SimpleCache -import com.google.android.exoplayer2.util.MimeTypes -import com.google.android.exoplayer2.video.VideoSize +import androidx.media3.common.C.* +import androidx.media3.common.Format +import androidx.media3.common.MediaItem +import androidx.media3.common.TrackSelectionOverride +import androidx.media3.common.MimeTypes +import androidx.media3.common.PlaybackException +import androidx.media3.common.Player +import androidx.media3.common.TrackGroup +import androidx.media3.common.Tracks +import androidx.media3.common.VideoSize +import androidx.media3.database.StandaloneDatabaseProvider +import androidx.media3.datasource.DataSource +import androidx.media3.datasource.DefaultDataSourceFactory +import androidx.media3.datasource.DefaultHttpDataSource +import androidx.media3.datasource.HttpDataSource +import androidx.media3.datasource.cache.CacheDataSource +import androidx.media3.datasource.cache.LeastRecentlyUsedCacheEvictor +import androidx.media3.datasource.cache.SimpleCache +import androidx.media3.datasource.okhttp.OkHttpDataSource +import androidx.media3.exoplayer.DefaultLoadControl +import androidx.media3.exoplayer.DefaultRenderersFactory +import androidx.media3.exoplayer.ExoPlayer +import androidx.media3.exoplayer.SeekParameters +import androidx.media3.exoplayer.source.ClippingMediaSource +import androidx.media3.exoplayer.source.ConcatenatingMediaSource +import androidx.media3.exoplayer.source.DefaultMediaSourceFactory +import androidx.media3.exoplayer.source.MergingMediaSource +import androidx.media3.exoplayer.source.SingleSampleMediaSource +import androidx.media3.exoplayer.text.TextRenderer +import androidx.media3.exoplayer.trackselection.DefaultTrackSelector +import androidx.media3.exoplayer.trackselection.TrackSelector +import androidx.media3.ui.SubtitleView import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull import com.lagradost.cloudstream3.AcraApplication.Companion.getKey import com.lagradost.cloudstream3.AcraApplication.Companion.setKey @@ -44,7 +56,6 @@ import com.lagradost.cloudstream3.utils.ExtractorLinkPlayList import com.lagradost.cloudstream3.utils.ExtractorUri import com.lagradost.cloudstream3.utils.SubtitleHelper.fromTwoLettersToLanguage import java.io.File -import java.time.Duration import javax.net.ssl.HttpsURLConnection import javax.net.ssl.SSLContext import javax.net.ssl.SSLSession @@ -451,6 +462,12 @@ class CS3IPlayer : IPlayer { } } + override fun getAspectRatio(): Rational? { + return exoPlayer?.videoFormat?.let { format -> + Rational(format.width, format.height) + } + } + override fun updateSubtitleStyle(style: SaveCaptionStyle) { subtitleHelper.setSubStyle(style) } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/CustomSubtitleDecoderFactory.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/CustomSubtitleDecoderFactory.kt index 974a5d26..b830d4e0 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/CustomSubtitleDecoderFactory.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/CustomSubtitleDecoderFactory.kt @@ -3,19 +3,23 @@ package com.lagradost.cloudstream3.ui.player import android.content.Context import android.util.Log import androidx.preference.PreferenceManager -import com.google.android.exoplayer2.Format -import com.google.android.exoplayer2.text.* -import com.google.android.exoplayer2.text.cea.Cea608Decoder -import com.google.android.exoplayer2.text.cea.Cea708Decoder -import com.google.android.exoplayer2.text.dvb.DvbDecoder -import com.google.android.exoplayer2.text.pgs.PgsDecoder -import com.google.android.exoplayer2.text.ssa.SsaDecoder -import com.google.android.exoplayer2.text.subrip.SubripDecoder -import com.google.android.exoplayer2.text.ttml.TtmlDecoder -import com.google.android.exoplayer2.text.tx3g.Tx3gDecoder -import com.google.android.exoplayer2.text.webvtt.Mp4WebvttDecoder -import com.google.android.exoplayer2.text.webvtt.WebvttDecoder -import com.google.android.exoplayer2.util.MimeTypes +import androidx.media3.common.Format +import androidx.media3.common.MimeTypes +import androidx.media3.exoplayer.text.ExoplayerCuesDecoder +import androidx.media3.exoplayer.text.SubtitleDecoderFactory +import androidx.media3.extractor.text.SubtitleDecoder +import androidx.media3.extractor.text.SubtitleInputBuffer +import androidx.media3.extractor.text.SubtitleOutputBuffer +import androidx.media3.extractor.text.cea.Cea608Decoder +import androidx.media3.extractor.text.cea.Cea708Decoder +import androidx.media3.extractor.text.dvb.DvbDecoder +import androidx.media3.extractor.text.pgs.PgsDecoder +import androidx.media3.extractor.text.ssa.SsaDecoder +import androidx.media3.extractor.text.subrip.SubripDecoder +import androidx.media3.extractor.text.ttml.TtmlDecoder +import androidx.media3.extractor.text.tx3g.Tx3gDecoder +import androidx.media3.extractor.text.webvtt.Mp4WebvttDecoder +import androidx.media3.extractor.text.webvtt.WebvttDecoder import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.mvvm.logError import org.mozilla.universalchardet.UniversalDetector diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/CustomTextRenderer.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/CustomTextRenderer.kt index d3f4171a..514aaeab 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/CustomTextRenderer.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/CustomTextRenderer.kt @@ -1,8 +1,8 @@ package com.lagradost.cloudstream3.ui.player import android.os.Looper -import com.google.android.exoplayer2.text.SubtitleDecoderFactory -import com.google.android.exoplayer2.text.TextOutput +import androidx.media3.exoplayer.text.SubtitleDecoderFactory +import androidx.media3.exoplayer.text.TextOutput class CustomTextRenderer( offset: Long, diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt index 46bf8568..c280af59 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt @@ -19,8 +19,8 @@ import androidx.core.view.isGone import androidx.core.view.isVisible import androidx.lifecycle.ViewModelProvider import androidx.preference.PreferenceManager -import com.google.android.exoplayer2.Format.NO_VALUE -import com.google.android.exoplayer2.util.MimeTypes +import androidx.media3.common.Format.NO_VALUE +import androidx.media3.common.MimeTypes import com.hippo.unifile.UniFile import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/IPlayer.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/IPlayer.kt index ba5a4a85..3038cb8d 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/IPlayer.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/IPlayer.kt @@ -1,6 +1,7 @@ package com.lagradost.cloudstream3.ui.player import android.content.Context +import android.util.Rational import com.lagradost.cloudstream3.ui.subtitles.SaveCaptionStyle import com.lagradost.cloudstream3.utils.EpisodeSkip import com.lagradost.cloudstream3.utils.ExtractorLink @@ -167,6 +168,19 @@ interface IPlayer { fun getVideoTracks(): CurrentTracks + /** + * Original video aspect ratio used for PiP mode + * + * Set using: Width, Height. + * Example: Rational(16, 9) + * + * If null will default to set no aspect ratio. + * + * PiP functions calling this needs to coerce this value between 0.418410 and 2.390000 + * to prevent crashes. + */ + fun getAspectRatio(): Rational? + /** If no parameters are set it'll default to no set size, Specifying the id allows for track overrides to force the player to pick the quality. */ fun setMaxVideoSize(width: Int = Int.MAX_VALUE, height: Int = Int.MAX_VALUE, id: String? = null) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/NonFinalTextRenderer.java b/app/src/main/java/com/lagradost/cloudstream3/ui/player/NonFinalTextRenderer.java index 3b47b27a..b5ecfe8f 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/NonFinalTextRenderer.java +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/NonFinalTextRenderer.java @@ -15,10 +15,10 @@ */ package com.lagradost.cloudstream3.ui.player; -import static com.google.android.exoplayer2.text.Cue.DIMEN_UNSET; -import static com.google.android.exoplayer2.text.Cue.LINE_TYPE_NUMBER; -import static com.google.android.exoplayer2.util.Assertions.checkNotNull; -import static com.google.android.exoplayer2.util.Assertions.checkState; +import static androidx.media3.common.text.Cue.DIMEN_UNSET; +import static androidx.media3.common.text.Cue.LINE_TYPE_NUMBER; +import static androidx.media3.common.util.Assertions.checkNotNull; +import static androidx.media3.common.util.Assertions.checkState; import static java.lang.annotation.ElementType.TYPE_USE; import android.os.Handler; @@ -28,25 +28,24 @@ import android.os.Message; import androidx.annotation.IntDef; import androidx.annotation.Nullable; - -import com.google.android.exoplayer2.BaseRenderer; -import com.google.android.exoplayer2.C; -import com.google.android.exoplayer2.Format; -import com.google.android.exoplayer2.FormatHolder; -import com.google.android.exoplayer2.RendererCapabilities; -import com.google.android.exoplayer2.source.SampleStream.ReadDataResult; -import com.google.android.exoplayer2.text.Cue; -import com.google.android.exoplayer2.text.CueGroup; -import com.google.android.exoplayer2.text.Subtitle; -import com.google.android.exoplayer2.text.SubtitleDecoder; -import com.google.android.exoplayer2.text.SubtitleDecoderException; -import com.google.android.exoplayer2.text.SubtitleDecoderFactory; -import com.google.android.exoplayer2.text.SubtitleInputBuffer; -import com.google.android.exoplayer2.text.SubtitleOutputBuffer; -import com.google.android.exoplayer2.text.TextOutput; -import com.google.android.exoplayer2.util.Log; -import com.google.android.exoplayer2.util.MimeTypes; -import com.google.android.exoplayer2.util.Util; +import androidx.media3.common.C; +import androidx.media3.common.Format; +import androidx.media3.common.text.Cue; +import androidx.media3.common.text.CueGroup; +import androidx.media3.common.MimeTypes; +import androidx.media3.common.util.Log; +import androidx.media3.common.util.Util; +import androidx.media3.exoplayer.BaseRenderer; +import androidx.media3.exoplayer.FormatHolder; +import androidx.media3.exoplayer.RendererCapabilities; +import androidx.media3.exoplayer.source.SampleStream; +import androidx.media3.exoplayer.text.SubtitleDecoderFactory; +import androidx.media3.exoplayer.text.TextOutput; +import androidx.media3.extractor.text.Subtitle; +import androidx.media3.extractor.text.SubtitleDecoder; +import androidx.media3.extractor.text.SubtitleDecoderException; +import androidx.media3.extractor.text.SubtitleInputBuffer; +import androidx.media3.extractor.text.SubtitleOutputBuffer; import java.lang.annotation.Documented; import java.lang.annotation.Retention; @@ -310,7 +309,7 @@ public class NonFinalTextRenderer extends BaseRenderer implements Callback { return; } // Try and read the next subtitle from the source. - @ReadDataResult int result = readSource(formatHolder, nextInputBuffer, /* readFlags= */ 0); + @SampleStream.ReadDataResult int result = readSource(formatHolder, nextInputBuffer, /* readFlags= */ 0); if (result == C.RESULT_BUFFER_READ) { if (nextInputBuffer.isEndOfStream()) { inputStreamEnded = true; diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerPipHelper.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerPipHelper.kt index 0fbc22f6..4bed0c9d 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerPipHelper.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerPipHelper.kt @@ -7,28 +7,22 @@ import android.app.RemoteAction import android.content.Intent import android.graphics.drawable.Icon import android.os.Build +import android.util.Rational import androidx.annotation.RequiresApi import androidx.annotation.StringRes import com.lagradost.cloudstream3.R +import kotlin.math.roundToInt class PlayerPipHelper { companion object { + @RequiresApi(Build.VERSION_CODES.O) private fun getPen(activity: Activity, code: Int): PendingIntent { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - PendingIntent.getBroadcast( - activity, - code, - Intent("media_control").putExtra("control_type", code), - PendingIntent.FLAG_IMMUTABLE - ) - } else { - PendingIntent.getBroadcast( - activity, - code, - Intent("media_control").putExtra("control_type", code), - 0 - ) - } + return PendingIntent.getBroadcast( + activity, + code, + Intent(ACTION_MEDIA_CONTROL).putExtra(EXTRA_CONTROL_TYPE, code), + PendingIntent.FLAG_IMMUTABLE + ) } @RequiresApi(Build.VERSION_CODES.O) @@ -48,7 +42,7 @@ class PlayerPipHelper { } @RequiresApi(Build.VERSION_CODES.O) - fun updatePIPModeActions(activity: Activity, isPlaying: Boolean) { + fun updatePIPModeActions(activity: Activity, isPlaying: Boolean, aspectRatio: Rational?) { val actions: ArrayList = ArrayList() actions.add( getRemoteAction( @@ -87,8 +81,28 @@ class PlayerPipHelper { CSPlayerEvent.SeekForward ) ) + + // Nessecary to prevent crashing. + val mixAspectRatio = 0.41841f // ~1/2.39 + val maxAspectRatio = 2.39f // widescreen standard + val ratioAccuracy = 100000 // To convert the float to int + + // java.lang.IllegalArgumentException: setPictureInPictureParams: Aspect ratio is too extreme (must be between 0.418410 and 2.390000) + val fixedRational = aspectRatio?.toFloat()?.coerceIn(mixAspectRatio, maxAspectRatio)?.let { + Rational((it * ratioAccuracy).roundToInt(), ratioAccuracy) + } + activity.setPictureInPictureParams( - PictureInPictureParams.Builder().setActions(actions).build() + PictureInPictureParams.Builder() + .apply { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + setSeamlessResizeEnabled(true) + setAutoEnterEnabled(isPlaying) + } + } + .setAspectRatio(fixedRational) + .setActions(actions) + .build() ) } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerSubtitleHelper.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerSubtitleHelper.kt index 8d85f176..e532d1a3 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerSubtitleHelper.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerSubtitleHelper.kt @@ -4,8 +4,8 @@ import android.util.Log import android.util.TypedValue import android.view.ViewGroup import android.widget.FrameLayout -import com.google.android.exoplayer2.ui.SubtitleView -import com.google.android.exoplayer2.util.MimeTypes +import androidx.media3.common.MimeTypes +import androidx.media3.ui.SubtitleView import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.ui.player.CustomDecoder.Companion.regexSubtitlesToRemoveBloat import com.lagradost.cloudstream3.ui.player.CustomDecoder.Companion.regexSubtitlesToRemoveCaptions diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/subtitles/ChromecastSubtitlesFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/subtitles/ChromecastSubtitlesFragment.kt index 07d00b07..ffb593a0 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/subtitles/ChromecastSubtitlesFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/subtitles/ChromecastSubtitlesFragment.kt @@ -14,7 +14,7 @@ import android.widget.TextView import android.widget.Toast import androidx.fragment.app.Fragment import com.fasterxml.jackson.annotation.JsonProperty -import com.google.android.exoplayer2.text.Cue +import androidx.media3.common.text.Cue import com.google.android.gms.cast.TextTrackStyle import com.google.android.gms.cast.TextTrackStyle.* import com.jaredrummler.android.colorpicker.ColorPickerDialog diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/subtitles/SubtitlesFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/subtitles/SubtitlesFragment.kt index ea8524e3..f053023d 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/subtitles/SubtitlesFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/subtitles/SubtitlesFragment.kt @@ -18,8 +18,8 @@ import androidx.core.content.res.ResourcesCompat import androidx.fragment.app.Fragment import androidx.preference.PreferenceManager import com.fasterxml.jackson.annotation.JsonProperty -import com.google.android.exoplayer2.text.Cue -import com.google.android.exoplayer2.ui.CaptionStyleCompat +import androidx.media3.common.text.Cue +import androidx.media3.ui.CaptionStyleCompat import com.jaredrummler.android.colorpicker.ColorPickerDialog import com.lagradost.cloudstream3.AcraApplication.Companion.getKey import com.lagradost.cloudstream3.AcraApplication.Companion.setKey diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/CastHelper.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/CastHelper.kt index 9e8cc1d4..6b5e9ec2 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/CastHelper.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/CastHelper.kt @@ -1,7 +1,7 @@ package com.lagradost.cloudstream3.utils import android.net.Uri -import com.google.android.exoplayer2.util.MimeTypes +import androidx.media3.common.MimeTypes import com.google.android.gms.cast.* import com.google.android.gms.cast.framework.CastSession import com.google.android.gms.cast.framework.media.RemoteMediaClient diff --git a/app/src/main/res/layout/chromecast_subtitle_settings.xml b/app/src/main/res/layout/chromecast_subtitle_settings.xml index 624c2201..4d3b50df 100644 --- a/app/src/main/res/layout/chromecast_subtitle_settings.xml +++ b/app/src/main/res/layout/chromecast_subtitle_settings.xml @@ -35,7 +35,7 @@ android:layout_height="match_parent" android:contentDescription="@string/preview_background_img_des" /> - - - - - - - -