mirror of
				https://github.com/recloudstream/cloudstream.git
				synced 2024-08-15 01:53:11 +00:00 
			
		
		
		
	Self similarity/master (#525)
* Migrated to Media3 --------- Co-authored-by: self-similarity <137652432+self-similarity@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									6b87fb7831
								
							
						
					
					
						commit
						8dae4c2b0f
					
				
					 23 changed files with 189 additions and 130 deletions
				
			
		|  | @ -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") | ||||
| 
 | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
|  | @ -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) | ||||
|     } | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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, | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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) | ||||
| 
 | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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<RemoteAction> = 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() | ||||
|             ) | ||||
|         } | ||||
|     } | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -35,7 +35,7 @@ | |||
|                     android:layout_height="match_parent" | ||||
|                     android:contentDescription="@string/preview_background_img_des" /> | ||||
| 
 | ||||
|             <com.google.android.exoplayer2.ui.SubtitleView | ||||
|             <androidx.media3.ui.SubtitleView | ||||
|                     android:id="@+id/subtitle_text" | ||||
| 
 | ||||
|                     android:layout_width="match_parent" | ||||
|  |  | |||
|  | @ -13,7 +13,7 @@ | |||
|     <!-- | ||||
|           app:fastforward_increment="10000" | ||||
|             app:rewind_increment="10000"--> | ||||
|     <com.google.android.exoplayer2.ui.PlayerView | ||||
|     <androidx.media3.ui.PlayerView | ||||
|         android:id="@+id/player_view" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="match_parent" | ||||
|  |  | |||
|  | @ -13,7 +13,7 @@ | |||
|     <!-- | ||||
|           app:fastforward_increment="10000" | ||||
|             app:rewind_increment="10000"--> | ||||
|     <com.google.android.exoplayer2.ui.PlayerView | ||||
|     <androidx.media3.ui.PlayerView | ||||
|         android:id="@+id/player_view" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="match_parent" | ||||
|  |  | |||
|  | @ -14,7 +14,7 @@ | |||
|     <!-- | ||||
|           app:fastforward_increment="10000" | ||||
|             app:rewind_increment="10000"--> | ||||
|     <com.google.android.exoplayer2.ui.PlayerView | ||||
|     <androidx.media3.ui.PlayerView | ||||
|             android:id="@+id/player_view" | ||||
|             app:show_timeout="0" | ||||
|             app:hide_on_touch="false" | ||||
|  |  | |||
|  | @ -450,7 +450,7 @@ | |||
|                         android:textStyle="normal" | ||||
|                         tools:text="15:30" /> | ||||
|                     <!--app:buffered_color="@color/videoCache"--> | ||||
|                     <com.google.android.exoplayer2.ui.DefaultTimeBar | ||||
|                     <androidx.media3.ui.DefaultTimeBar | ||||
|                         android:id="@id/exo_progress" | ||||
|                         android:layout_width="0dp" | ||||
|                         android:layout_height="30dp" | ||||
|  |  | |||
|  | @ -543,7 +543,7 @@ | |||
|                         android:textStyle="normal" | ||||
|                         tools:text="15:30" /> | ||||
|                     <!--app:buffered_color="@color/videoCache"--> | ||||
|                     <com.google.android.exoplayer2.ui.DefaultTimeBar | ||||
|                     <androidx.media3.ui.DefaultTimeBar | ||||
|                         android:id="@id/exo_progress" | ||||
|                         android:layout_width="0dp" | ||||
|                         android:layout_height="30dp" | ||||
|  |  | |||
|  | @ -35,9 +35,8 @@ | |||
|                 android:scaleType="centerCrop" | ||||
|                 android:src="@drawable/subtitles_preview_background" /> | ||||
| 
 | ||||
|             <com.google.android.exoplayer2.ui.SubtitleView | ||||
|             <androidx.media3.ui.SubtitleView | ||||
|                 android:id="@+id/subtitle_text" | ||||
| 
 | ||||
|                 android:layout_width="match_parent" | ||||
|                 android:layout_height="match_parent" | ||||
|                 android:layout_gravity="center" | ||||
|  |  | |||
|  | @ -443,7 +443,7 @@ | |||
|                     android:textStyle="normal" | ||||
|                     tools:text="15:30" /> | ||||
|                 <!--app:buffered_color="@color/videoCache"--> | ||||
|                 <com.google.android.exoplayer2.ui.DefaultTimeBar | ||||
|                 <androidx.media3.ui.DefaultTimeBar | ||||
|                     android:id="@id/exo_progress" | ||||
|                     android:layout_width="0dp" | ||||
|                     android:layout_height="30dp" | ||||
|  |  | |||
|  | @ -16,7 +16,7 @@ org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 | |||
| # https://developer.android.com/topic/libraries/support-library/androidx-rn | ||||
| android.useAndroidX=true | ||||
| # Automatically convert third-party libraries to use AndroidX | ||||
| android.enableJetifier=true | ||||
| # android.enableJetifier=true | ||||
| # Kotlin code style for this project: "official" or "obsolete": | ||||
| kotlin.code.style=official | ||||
| android.defaults.buildfeatures.buildconfig=true | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue