Migrated to Media3

This commit is contained in:
self-similarity 2023-07-14 20:16:23 +02:00
parent 927453d9fe
commit a14f23063d
23 changed files with 241 additions and 135 deletions

View file

@ -74,12 +74,18 @@ android {
isDebuggable = false isDebuggable = false
isMinifyEnabled = false isMinifyEnabled = false
isShrinkResources = false isShrinkResources = false
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
} }
debug { debug {
isDebuggable = true isDebuggable = true
applicationIdSuffix = ".debug" applicationIdSuffix = ".debug"
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
} }
} }
flavorDimensions.add("state") flavorDimensions.add("state")
@ -155,10 +161,16 @@ dependencies {
// implementation("androidx.leanback:leanback-paging:1.1.0-alpha09") // implementation("androidx.leanback:leanback-paging:1.1.0-alpha09")
// Exoplayer // Exoplayer
implementation("com.google.android.exoplayer:exoplayer:2.18.2") implementation("androidx.media3:media3-common:1.1.0")
implementation("com.google.android.exoplayer:extension-cast:2.18.2") implementation("androidx.media3:media3-exoplayer:1.1.0")
implementation("com.google.android.exoplayer:extension-mediasession:2.18.2") implementation("androidx.media3:media3-datasource-okhttp:1.1.0")
implementation("com.google.android.exoplayer:extension-okhttp:2.18.2") 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 // 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") // implementation("org.jellyfin.exoplayer:exoplayer-ffmpeg-extension:2.18.2+1")

View file

@ -222,6 +222,7 @@ object CommonActivity {
"AmoledLight" -> R.style.AmoledModeLight "AmoledLight" -> R.style.AmoledModeLight
"Monet" -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) "Monet" -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
R.style.MonetMode else R.style.AppTheme R.style.MonetMode else R.style.AppTheme
else -> R.style.AppTheme else -> R.style.AppTheme
} }
@ -244,8 +245,10 @@ object CommonActivity {
"Pink" -> R.style.OverlayPrimaryColorPink "Pink" -> R.style.OverlayPrimaryColorPink
"Monet" -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) "Monet" -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
R.style.OverlayPrimaryColorMonet else R.style.OverlayPrimaryColorNormal R.style.OverlayPrimaryColorMonet else R.style.OverlayPrimaryColorNormal
"Monet2" -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) "Monet2" -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
R.style.OverlayPrimaryColorMonetTwo else R.style.OverlayPrimaryColorNormal R.style.OverlayPrimaryColorMonetTwo else R.style.OverlayPrimaryColorNormal
else -> R.style.OverlayPrimaryColorNormal else -> R.style.OverlayPrimaryColorNormal
} }
act.theme.applyStyle(currentTheme, true) act.theme.applyStyle(currentTheme, true)
@ -271,12 +274,15 @@ object CommonActivity {
FocusDirection.Left -> { FocusDirection.Left -> {
view.nextFocusLeftId view.nextFocusLeftId
} }
FocusDirection.Up -> { FocusDirection.Up -> {
view.nextFocusUpId view.nextFocusUpId
} }
FocusDirection.Right -> { FocusDirection.Right -> {
view.nextFocusRightId view.nextFocusRightId
} }
FocusDirection.Down -> { FocusDirection.Down -> {
view.nextFocusDownId view.nextFocusDownId
} }
@ -328,30 +334,39 @@ object CommonActivity {
KeyEvent.KEYCODE_FORWARD, KeyEvent.KEYCODE_D, KeyEvent.KEYCODE_MEDIA_SKIP_FORWARD, KeyEvent.KEYCODE_MEDIA_FAST_FORWARD -> { KeyEvent.KEYCODE_FORWARD, KeyEvent.KEYCODE_D, KeyEvent.KEYCODE_MEDIA_SKIP_FORWARD, KeyEvent.KEYCODE_MEDIA_FAST_FORWARD -> {
PlayerEventType.SeekForward PlayerEventType.SeekForward
} }
KeyEvent.KEYCODE_A, KeyEvent.KEYCODE_MEDIA_SKIP_BACKWARD, KeyEvent.KEYCODE_MEDIA_REWIND -> { KeyEvent.KEYCODE_A, KeyEvent.KEYCODE_MEDIA_SKIP_BACKWARD, KeyEvent.KEYCODE_MEDIA_REWIND -> {
PlayerEventType.SeekBack PlayerEventType.SeekBack
} }
KeyEvent.KEYCODE_MEDIA_NEXT, KeyEvent.KEYCODE_BUTTON_R1, KeyEvent.KEYCODE_N -> { KeyEvent.KEYCODE_MEDIA_NEXT, KeyEvent.KEYCODE_BUTTON_R1, KeyEvent.KEYCODE_N -> {
PlayerEventType.NextEpisode PlayerEventType.NextEpisode
} }
KeyEvent.KEYCODE_MEDIA_PREVIOUS, KeyEvent.KEYCODE_BUTTON_L1, KeyEvent.KEYCODE_B -> { KeyEvent.KEYCODE_MEDIA_PREVIOUS, KeyEvent.KEYCODE_BUTTON_L1, KeyEvent.KEYCODE_B -> {
PlayerEventType.PrevEpisode PlayerEventType.PrevEpisode
} }
KeyEvent.KEYCODE_MEDIA_PAUSE -> { KeyEvent.KEYCODE_MEDIA_PAUSE -> {
PlayerEventType.Pause PlayerEventType.Pause
} }
KeyEvent.KEYCODE_MEDIA_PLAY, KeyEvent.KEYCODE_BUTTON_START -> { KeyEvent.KEYCODE_MEDIA_PLAY, KeyEvent.KEYCODE_BUTTON_START -> {
PlayerEventType.Play PlayerEventType.Play
} }
KeyEvent.KEYCODE_L, KeyEvent.KEYCODE_NUMPAD_7, KeyEvent.KEYCODE_7 -> { KeyEvent.KEYCODE_L, KeyEvent.KEYCODE_NUMPAD_7, KeyEvent.KEYCODE_7 -> {
PlayerEventType.Lock PlayerEventType.Lock
} }
KeyEvent.KEYCODE_H, KeyEvent.KEYCODE_MENU -> { KeyEvent.KEYCODE_H, KeyEvent.KEYCODE_MENU -> {
PlayerEventType.ToggleHide PlayerEventType.ToggleHide
} }
KeyEvent.KEYCODE_M, KeyEvent.KEYCODE_VOLUME_MUTE -> { KeyEvent.KEYCODE_M, KeyEvent.KEYCODE_VOLUME_MUTE -> {
PlayerEventType.ToggleMute PlayerEventType.ToggleMute
} }
KeyEvent.KEYCODE_S, KeyEvent.KEYCODE_NUMPAD_9, KeyEvent.KEYCODE_9 -> { KeyEvent.KEYCODE_S, KeyEvent.KEYCODE_NUMPAD_9, KeyEvent.KEYCODE_9 -> {
PlayerEventType.ShowMirrors PlayerEventType.ShowMirrors
} }
@ -359,21 +374,27 @@ object CommonActivity {
KeyEvent.KEYCODE_O, KeyEvent.KEYCODE_NUMPAD_8, KeyEvent.KEYCODE_8 -> { KeyEvent.KEYCODE_O, KeyEvent.KEYCODE_NUMPAD_8, KeyEvent.KEYCODE_8 -> {
PlayerEventType.SearchSubtitlesOnline PlayerEventType.SearchSubtitlesOnline
} }
KeyEvent.KEYCODE_E, KeyEvent.KEYCODE_NUMPAD_3, KeyEvent.KEYCODE_3 -> { KeyEvent.KEYCODE_E, KeyEvent.KEYCODE_NUMPAD_3, KeyEvent.KEYCODE_3 -> {
PlayerEventType.ShowSpeed PlayerEventType.ShowSpeed
} }
KeyEvent.KEYCODE_R, KeyEvent.KEYCODE_NUMPAD_0, KeyEvent.KEYCODE_0 -> { KeyEvent.KEYCODE_R, KeyEvent.KEYCODE_NUMPAD_0, KeyEvent.KEYCODE_0 -> {
PlayerEventType.Resize PlayerEventType.Resize
} }
KeyEvent.KEYCODE_C, KeyEvent.KEYCODE_NUMPAD_4, KeyEvent.KEYCODE_4 -> { KeyEvent.KEYCODE_C, KeyEvent.KEYCODE_NUMPAD_4, KeyEvent.KEYCODE_4 -> {
PlayerEventType.SkipOp PlayerEventType.SkipOp
} }
KeyEvent.KEYCODE_V, KeyEvent.KEYCODE_NUMPAD_5, KeyEvent.KEYCODE_5 -> { KeyEvent.KEYCODE_V, KeyEvent.KEYCODE_NUMPAD_5, KeyEvent.KEYCODE_5 -> {
PlayerEventType.SkipCurrentChapter PlayerEventType.SkipCurrentChapter
} }
KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, KeyEvent.KEYCODE_P, KeyEvent.KEYCODE_SPACE, KeyEvent.KEYCODE_NUMPAD_ENTER, KeyEvent.KEYCODE_ENTER -> { // space is not captured due to navigation KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, KeyEvent.KEYCODE_P, KeyEvent.KEYCODE_SPACE, KeyEvent.KEYCODE_NUMPAD_ENTER, KeyEvent.KEYCODE_ENTER -> { // space is not captured due to navigation
PlayerEventType.PlayPauseToggle PlayerEventType.PlayPauseToggle
} }
else -> null else -> null
}?.let { playerEvent -> }?.let { playerEvent ->
playerEventListener?.invoke(playerEvent) playerEventListener?.invoke(playerEvent)
@ -398,16 +419,19 @@ object CommonActivity {
act.currentFocus, act.currentFocus,
FocusDirection.Left FocusDirection.Left
) )
KeyEvent.KEYCODE_DPAD_RIGHT -> getNextFocus( KeyEvent.KEYCODE_DPAD_RIGHT -> getNextFocus(
act, act,
act.currentFocus, act.currentFocus,
FocusDirection.Right FocusDirection.Right
) )
KeyEvent.KEYCODE_DPAD_UP -> getNextFocus( KeyEvent.KEYCODE_DPAD_UP -> getNextFocus(
act, act,
act.currentFocus, act.currentFocus,
FocusDirection.Up FocusDirection.Up
) )
KeyEvent.KEYCODE_DPAD_DOWN -> getNextFocus( KeyEvent.KEYCODE_DPAD_DOWN -> getNextFocus(
act, act,
act.currentFocus, act.currentFocus,

View file

@ -10,7 +10,11 @@ import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.util.AttributeSet import android.util.AttributeSet
import android.util.Log import android.util.Log
import android.view.* import android.view.KeyEvent
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.WindowManager
import android.widget.Toast import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.ActivityResultLauncher
import androidx.annotation.IdRes import androidx.annotation.IdRes
@ -31,7 +35,11 @@ import androidx.preference.PreferenceManager
import com.fasterxml.jackson.databind.DeserializationFeature import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.google.android.gms.cast.framework.* 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
import com.google.android.gms.cast.framework.SessionManagerListener
import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.navigationrail.NavigationRailView import com.google.android.material.navigationrail.NavigationRailView
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
@ -49,7 +57,10 @@ import com.lagradost.cloudstream3.CommonActivity.onDialogDismissedEvent
import com.lagradost.cloudstream3.CommonActivity.onUserLeaveHint import com.lagradost.cloudstream3.CommonActivity.onUserLeaveHint
import com.lagradost.cloudstream3.CommonActivity.showToast import com.lagradost.cloudstream3.CommonActivity.showToast
import com.lagradost.cloudstream3.CommonActivity.updateLocale import com.lagradost.cloudstream3.CommonActivity.updateLocale
import com.lagradost.cloudstream3.mvvm.* import com.lagradost.cloudstream3.mvvm.Resource
import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
import com.lagradost.cloudstream3.mvvm.observeNullable
import com.lagradost.cloudstream3.network.initClient import com.lagradost.cloudstream3.network.initClient
import com.lagradost.cloudstream3.plugins.PluginManager import com.lagradost.cloudstream3.plugins.PluginManager
import com.lagradost.cloudstream3.plugins.PluginManager.loadAllOnlinePlugins import com.lagradost.cloudstream3.plugins.PluginManager.loadAllOnlinePlugins
@ -83,7 +94,7 @@ import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.updateT
import com.lagradost.cloudstream3.ui.settings.SettingsGeneral import com.lagradost.cloudstream3.ui.settings.SettingsGeneral
import com.lagradost.cloudstream3.ui.setup.HAS_DONE_SETUP_KEY import com.lagradost.cloudstream3.ui.setup.HAS_DONE_SETUP_KEY
import com.lagradost.cloudstream3.ui.setup.SetupFragmentExtensions import com.lagradost.cloudstream3.ui.setup.SetupFragmentExtensions
import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.ApkInstaller
import com.lagradost.cloudstream3.utils.AppUtils.html import com.lagradost.cloudstream3.utils.AppUtils.html
import com.lagradost.cloudstream3.utils.AppUtils.isCastApiAvailable import com.lagradost.cloudstream3.utils.AppUtils.isCastApiAvailable
import com.lagradost.cloudstream3.utils.AppUtils.isNetworkAvailable import com.lagradost.cloudstream3.utils.AppUtils.isNetworkAvailable
@ -98,6 +109,8 @@ import com.lagradost.cloudstream3.utils.Coroutines.main
import com.lagradost.cloudstream3.utils.DataStore.getKey import com.lagradost.cloudstream3.utils.DataStore.getKey
import com.lagradost.cloudstream3.utils.DataStore.setKey import com.lagradost.cloudstream3.utils.DataStore.setKey
import com.lagradost.cloudstream3.utils.DataStoreHelper.migrateResumeWatching import com.lagradost.cloudstream3.utils.DataStoreHelper.migrateResumeWatching
import com.lagradost.cloudstream3.utils.Event
import com.lagradost.cloudstream3.utils.IOnBackPressed
import com.lagradost.cloudstream3.utils.InAppUpdater.Companion.runAutoUpdate import com.lagradost.cloudstream3.utils.InAppUpdater.Companion.runAutoUpdate
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog
import com.lagradost.cloudstream3.utils.UIHelper.changeStatusBarState import com.lagradost.cloudstream3.utils.UIHelper.changeStatusBarState
@ -108,11 +121,26 @@ import com.lagradost.cloudstream3.utils.UIHelper.getResourceColor
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
import com.lagradost.cloudstream3.utils.UIHelper.navigate import com.lagradost.cloudstream3.utils.UIHelper.navigate
import com.lagradost.cloudstream3.utils.UIHelper.requestRW import com.lagradost.cloudstream3.utils.UIHelper.requestRW
import com.lagradost.cloudstream3.utils.USER_PROVIDER_API
import com.lagradost.cloudstream3.utils.USER_SELECTED_HOMEPAGE_API
import com.lagradost.nicehttp.Requests import com.lagradost.nicehttp.Requests
import com.lagradost.nicehttp.ResponseParser import com.lagradost.nicehttp.ResponseParser
import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.activity_main.cast_mini_controller_holder
import kotlinx.android.synthetic.main.bottom_resultview_preview.* import kotlinx.android.synthetic.main.activity_main.nav_host_fragment
import kotlinx.android.synthetic.main.fragment_result_swipe.* import kotlinx.android.synthetic.main.activity_main.nav_rail_view
import kotlinx.android.synthetic.main.activity_main.nav_view
import kotlinx.android.synthetic.main.bottom_resultview_preview.resultview_preview_description
import kotlinx.android.synthetic.main.bottom_resultview_preview.resultview_preview_loading
import kotlinx.android.synthetic.main.bottom_resultview_preview.resultview_preview_loading_shimmer
import kotlinx.android.synthetic.main.bottom_resultview_preview.resultview_preview_meta_duration
import kotlinx.android.synthetic.main.bottom_resultview_preview.resultview_preview_meta_rating
import kotlinx.android.synthetic.main.bottom_resultview_preview.resultview_preview_meta_type
import kotlinx.android.synthetic.main.bottom_resultview_preview.resultview_preview_meta_year
import kotlinx.android.synthetic.main.bottom_resultview_preview.resultview_preview_more_info
import kotlinx.android.synthetic.main.bottom_resultview_preview.resultview_preview_poster
import kotlinx.android.synthetic.main.bottom_resultview_preview.resultview_preview_result
import kotlinx.android.synthetic.main.bottom_resultview_preview.resultview_preview_title
import kotlinx.android.synthetic.main.fragment_result_swipe.media_route_button
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
import java.io.File import java.io.File
@ -464,9 +492,11 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
Configuration.ORIENTATION_LANDSCAPE -> { Configuration.ORIENTATION_LANDSCAPE -> {
true true
} }
Configuration.ORIENTATION_PORTRAIT -> { Configuration.ORIENTATION_PORTRAIT -> {
false false
} }
else -> { else -> {
false false
} }
@ -839,6 +869,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
showToast(this, R.string.error) showToast(this, R.string.error)
hidePreviewPopupDialog() hidePreviewPopupDialog()
} }
is Resource.Loading -> { is Resource.Loading -> {
showPreviewPopupDialog().apply { showPreviewPopupDialog().apply {
resultview_preview_loading?.isVisible = true resultview_preview_loading?.isVisible = true
@ -846,6 +877,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
resultview_preview_loading_shimmer?.startShimmer() resultview_preview_loading_shimmer?.startShimmer()
} }
} }
is Resource.Success -> { is Resource.Success -> {
val d = resource.value val d = resource.value
showPreviewPopupDialog().apply { showPreviewPopupDialog().apply {

View file

@ -7,7 +7,6 @@ import android.graphics.drawable.AnimatedVectorDrawable
import android.media.metrics.PlaybackErrorEvent import android.media.metrics.PlaybackErrorEvent
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.support.v4.media.session.MediaSessionCompat
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@ -17,14 +16,13 @@ import androidx.annotation.LayoutRes
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.media.session.MediaButtonReceiver
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat
import com.google.android.exoplayer2.ExoPlayer import androidx.media3.common.PlaybackException
import com.google.android.exoplayer2.PlaybackException import androidx.media3.exoplayer.ExoPlayer
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector import androidx.media3.session.MediaSession
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout import androidx.media3.ui.AspectRatioFrameLayout
import com.google.android.exoplayer2.ui.SubtitleView import androidx.media3.ui.SubtitleView
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
import com.lagradost.cloudstream3.AcraApplication.Companion.setKey import com.lagradost.cloudstream3.AcraApplication.Companion.setKey
import com.lagradost.cloudstream3.CommonActivity.canEnterPipMode import com.lagradost.cloudstream3.CommonActivity.canEnterPipMode
@ -34,6 +32,7 @@ import com.lagradost.cloudstream3.CommonActivity.playerEventListener
import com.lagradost.cloudstream3.CommonActivity.showToast import com.lagradost.cloudstream3.CommonActivity.showToast
import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.mvvm.logError 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.SaveCaptionStyle
import com.lagradost.cloudstream3.ui.subtitles.SubtitlesFragment import com.lagradost.cloudstream3.ui.subtitles.SubtitlesFragment
import com.lagradost.cloudstream3.utils.AppUtils import com.lagradost.cloudstream3.utils.AppUtils
@ -171,7 +170,7 @@ abstract class AbstractPlayerFragment(
} }
canEnterPipMode = isPlayingRightNow && hasPipModeSupport 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 -> activity?.let { act ->
PlayerPipHelper.updatePIPModeActions(act, isPlayingRightNow) PlayerPipHelper.updatePIPModeActions(act, isPlayingRightNow)
} }
@ -180,6 +179,7 @@ abstract class AbstractPlayerFragment(
private var pipReceiver: BroadcastReceiver? = null private var pipReceiver: BroadcastReceiver? = null
override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean) { override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean) {
super.onPictureInPictureModeChanged(isInPictureInPictureMode)
try { try {
isInPIPMode = isInPictureInPictureMode isInPIPMode = isInPictureInPictureMode
if (isInPictureInPictureMode) { if (isInPictureInPictureMode) {
@ -202,9 +202,7 @@ abstract class AbstractPlayerFragment(
} }
} }
val filter = IntentFilter() val filter = IntentFilter()
filter.addAction( filter.addAction(ACTION_MEDIA_CONTROL)
ACTION_MEDIA_CONTROL
)
activity?.registerReceiver(pipReceiver, filter) activity?.registerReceiver(pipReceiver, filter)
val isPlaying = player.getIsPlaying() val isPlaying = player.getIsPlaying()
val isPlayingValue = val isPlayingValue =
@ -215,8 +213,11 @@ abstract class AbstractPlayerFragment(
piphide?.isVisible = true piphide?.isVisible = true
exitedPipMode() exitedPipMode()
pipReceiver?.let { pipReceiver?.let {
// Prevents java.lang.IllegalArgumentException: Receiver not registered
normalSafeApiCall {
activity?.unregisterReceiver(it) activity?.unregisterReceiver(it)
} }
}
activity?.hideSystemUI() activity?.hideSystemUI()
this.view?.let { UIHelper.hideKeyboard(it) } this.view?.let { UIHelper.hideKeyboard(it) }
} }
@ -270,18 +271,21 @@ abstract class AbstractPlayerFragment(
gotoNext = true 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 -> { 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( showToast(
"${ctx.getString(R.string.remote_error)}\n$errorName ($code)\n$msg", "${ctx.getString(R.string.remote_error)}\n$errorName ($code)\n$msg",
gotoNext = true 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 -> { 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( showToast(
"${ctx.getString(R.string.render_error)}\n$errorName ($code)\n$msg", "${ctx.getString(R.string.render_error)}\n$errorName ($code)\n$msg",
gotoNext = true gotoNext = true
) )
} }
else -> { else -> {
showToast( showToast(
"${ctx.getString(R.string.unexpected_error)}\n$errorName ($code)\n$msg", "${ctx.getString(R.string.unexpected_error)}\n$errorName ($code)\n$msg",
@ -290,12 +294,14 @@ abstract class AbstractPlayerFragment(
} }
} }
} }
is InvalidFileException -> { is InvalidFileException -> {
showToast( showToast(
"${ctx.getString(R.string.source_error)}\n${exception.message}", "${ctx.getString(R.string.source_error)}\n${exception.message}",
gotoNext = true gotoNext = true
) )
} }
else -> { else -> {
exception.message?.let { exception.message?.let {
showToast( showToast(
@ -316,15 +322,8 @@ abstract class AbstractPlayerFragment(
private fun playerUpdated(player: Any?) { private fun playerUpdated(player: Any?) {
if (player is ExoPlayer) { if (player is ExoPlayer) {
context?.let { ctx -> context?.let { ctx ->
val mediaButtonReceiver = ComponentName(ctx, MediaButtonReceiver::class.java) mMediaSession?.release()
MediaSessionCompat(ctx, "Player", mediaButtonReceiver, null).let { media -> mMediaSession = MediaSession.Builder(ctx, player).build()
//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
}
} }
// Necessary for multiple combined videos // Necessary for multiple combined videos
@ -334,8 +333,7 @@ abstract class AbstractPlayerFragment(
} }
} }
private var mediaSessionConnector: MediaSessionConnector? = null private var mMediaSession: MediaSession? = null
private var mMediaSessionCompat: MediaSessionCompat? = null
// this can be used in the future for players other than exoplayer // this can be used in the future for players other than exoplayer
//private val mMediaSessionCallback: MediaSessionCompat.Callback = object : MediaSessionCompat.Callback() { //private val mMediaSessionCallback: MediaSessionCompat.Callback = object : MediaSessionCompat.Callback() {
@ -436,6 +434,7 @@ abstract class AbstractPlayerFragment(
playerEventListener = null playerEventListener = null
keyEventListener = null keyEventListener = null
canEnterPipMode = false canEnterPipMode = false
mMediaSession?.release()
SubtitlesFragment.applyStyleEvent -= ::onSubStyleChanged SubtitlesFragment.applyStyleEvent -= ::onSubStyleChanged
keepScreenOn(false) keepScreenOn(false)

View file

@ -6,29 +6,40 @@ import android.os.Handler
import android.os.Looper import android.os.Looper
import android.util.Log import android.util.Log
import android.widget.FrameLayout import android.widget.FrameLayout
import androidx.media3.common.C
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.google.android.exoplayer2.* import androidx.media3.common.C.*
import com.google.android.exoplayer2.C.* import androidx.media3.common.Format
import com.google.android.exoplayer2.DefaultRenderersFactory.EXTENSION_RENDERER_MODE_ON import androidx.media3.common.MediaItem
import com.google.android.exoplayer2.DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER import androidx.media3.common.TrackSelectionOverride
import com.google.android.exoplayer2.database.StandaloneDatabaseProvider import androidx.media3.common.MimeTypes
import com.google.android.exoplayer2.ext.okhttp.OkHttpDataSource import androidx.media3.common.PlaybackException
import com.google.android.exoplayer2.mediacodec.MediaCodecSelector import androidx.media3.common.Player
import com.google.android.exoplayer2.source.* import androidx.media3.common.TrackGroup
import com.google.android.exoplayer2.text.TextRenderer import androidx.media3.common.Tracks
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector import androidx.media3.common.VideoSize
import com.google.android.exoplayer2.trackselection.TrackSelectionOverride import androidx.media3.database.StandaloneDatabaseProvider
import com.google.android.exoplayer2.trackselection.TrackSelector import androidx.media3.datasource.DataSource
import com.google.android.exoplayer2.ui.SubtitleView import androidx.media3.datasource.DefaultDataSourceFactory
import com.google.android.exoplayer2.upstream.DataSource import androidx.media3.datasource.DefaultHttpDataSource
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory import androidx.media3.datasource.HttpDataSource
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource import androidx.media3.datasource.cache.CacheDataSource
import com.google.android.exoplayer2.upstream.HttpDataSource import androidx.media3.datasource.cache.LeastRecentlyUsedCacheEvictor
import com.google.android.exoplayer2.upstream.cache.CacheDataSource import androidx.media3.datasource.cache.SimpleCache
import com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvictor import androidx.media3.datasource.okhttp.OkHttpDataSource
import com.google.android.exoplayer2.upstream.cache.SimpleCache import androidx.media3.exoplayer.DefaultLoadControl
import com.google.android.exoplayer2.util.MimeTypes import androidx.media3.exoplayer.DefaultRenderersFactory
import com.google.android.exoplayer2.video.VideoSize 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.APIHolder.getApiFromNameNull
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
import com.lagradost.cloudstream3.AcraApplication.Companion.setKey import com.lagradost.cloudstream3.AcraApplication.Companion.setKey
@ -44,7 +55,6 @@ import com.lagradost.cloudstream3.utils.ExtractorLinkPlayList
import com.lagradost.cloudstream3.utils.ExtractorUri import com.lagradost.cloudstream3.utils.ExtractorUri
import com.lagradost.cloudstream3.utils.SubtitleHelper.fromTwoLettersToLanguage import com.lagradost.cloudstream3.utils.SubtitleHelper.fromTwoLettersToLanguage
import java.io.File import java.io.File
import java.time.Duration
import javax.net.ssl.HttpsURLConnection import javax.net.ssl.HttpsURLConnection
import javax.net.ssl.SSLContext import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSession import javax.net.ssl.SSLSession
@ -387,6 +397,7 @@ class CS3IPlayer : IPlayer {
Log.i(TAG, "setPreferredSubtitles REQUIRES_RELOAD") Log.i(TAG, "setPreferredSubtitles REQUIRES_RELOAD")
return@let true return@let true
} }
SubtitleStatus.IS_ACTIVE -> { SubtitleStatus.IS_ACTIVE -> {
Log.i(TAG, "setPreferredSubtitles IS_ACTIVE") Log.i(TAG, "setPreferredSubtitles IS_ACTIVE")
@ -412,6 +423,7 @@ class CS3IPlayer : IPlayer {
// }, 1) // }, 1)
//} //}
} }
SubtitleStatus.NOT_FOUND -> { SubtitleStatus.NOT_FOUND -> {
Log.i(TAG, "setPreferredSubtitles NOT_FOUND") Log.i(TAG, "setPreferredSubtitles NOT_FOUND")
return@let true return@let true
@ -810,9 +822,11 @@ class CS3IPlayer : IPlayer {
CSPlayerEvent.Play -> { CSPlayerEvent.Play -> {
play() play()
} }
CSPlayerEvent.Pause -> { CSPlayerEvent.Pause -> {
pause() pause()
} }
CSPlayerEvent.ToggleMute -> { CSPlayerEvent.ToggleMute -> {
if (volume <= 0) { if (volume <= 0) {
//is muted //is muted
@ -823,6 +837,7 @@ class CS3IPlayer : IPlayer {
volume = 0f volume = 0f
} }
} }
CSPlayerEvent.PlayPauseToggle -> { CSPlayerEvent.PlayPauseToggle -> {
if (isPlaying) { if (isPlaying) {
pause() pause()
@ -830,6 +845,7 @@ class CS3IPlayer : IPlayer {
play() play()
} }
} }
CSPlayerEvent.SeekForward -> seekTime(seekActionTime) CSPlayerEvent.SeekForward -> seekTime(seekActionTime)
CSPlayerEvent.SeekBack -> seekTime(-seekActionTime) CSPlayerEvent.SeekBack -> seekTime(-seekActionTime)
CSPlayerEvent.NextEpisode -> nextEpisode?.invoke() CSPlayerEvent.NextEpisode -> nextEpisode?.invoke()
@ -954,6 +970,7 @@ class CS3IPlayer : IPlayer {
Player.STATE_READY -> { Player.STATE_READY -> {
onRenderFirst() onRenderFirst()
} }
else -> {} else -> {}
} }
@ -963,6 +980,7 @@ class CS3IPlayer : IPlayer {
Player.STATE_READY -> { Player.STATE_READY -> {
} }
Player.STATE_ENDED -> { Player.STATE_ENDED -> {
// Only play next episode if autoplay is on (default) // Only play next episode if autoplay is on (default)
if (PreferenceManager.getDefaultSharedPreferences(context) if (PreferenceManager.getDefaultSharedPreferences(context)
@ -974,12 +992,15 @@ class CS3IPlayer : IPlayer {
handleEvent(CSPlayerEvent.NextEpisode) handleEvent(CSPlayerEvent.NextEpisode)
} }
} }
Player.STATE_BUFFERING -> { Player.STATE_BUFFERING -> {
updatedTime() updatedTime()
} }
Player.STATE_IDLE -> { Player.STATE_IDLE -> {
// IDLE // IDLE
} }
else -> Unit else -> Unit
} }
} }
@ -994,11 +1015,13 @@ class CS3IPlayer : IPlayer {
&& exoPlayer?.duration != TIME_UNSET -> { && exoPlayer?.duration != TIME_UNSET -> {
exoPlayer?.prepare() exoPlayer?.prepare()
} }
error.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW -> { error.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW -> {
// Re-initialize player at the current live window default position. // Re-initialize player at the current live window default position.
exoPlayer?.seekToDefaultPosition() exoPlayer?.seekToDefaultPosition()
exoPlayer?.prepare() exoPlayer?.prepare()
} }
else -> { else -> {
playerError?.invoke(error) playerError?.invoke(error)
} }
@ -1025,6 +1048,7 @@ class CS3IPlayer : IPlayer {
Player.STATE_READY -> { Player.STATE_READY -> {
} }
Player.STATE_ENDED -> { Player.STATE_ENDED -> {
// Only play next episode if autoplay is on (default) // Only play next episode if autoplay is on (default)
if (PreferenceManager.getDefaultSharedPreferences(context) if (PreferenceManager.getDefaultSharedPreferences(context)
@ -1036,12 +1060,15 @@ class CS3IPlayer : IPlayer {
handleEvent(CSPlayerEvent.NextEpisode) handleEvent(CSPlayerEvent.NextEpisode)
} }
} }
Player.STATE_BUFFERING -> { Player.STATE_BUFFERING -> {
updatedTime() updatedTime()
} }
Player.STATE_IDLE -> { Player.STATE_IDLE -> {
// IDLE // IDLE
} }
else -> Unit else -> Unit
} }
} }
@ -1169,6 +1196,7 @@ class CS3IPlayer : IPlayer {
null null
} }
} }
SubtitleOrigin.URL -> { SubtitleOrigin.URL -> {
if (onlineSourceFactory != null) { if (onlineSourceFactory != null) {
activeSubtitles.add(sub) activeSubtitles.add(sub)
@ -1181,6 +1209,7 @@ class CS3IPlayer : IPlayer {
null null
} }
} }
SubtitleOrigin.EMBEDDED_IN_VIDEO -> { SubtitleOrigin.EMBEDDED_IN_VIDEO -> {
if (offlineSourceFactory != null) { if (offlineSourceFactory != null) {
activeSubtitles.add(sub) activeSubtitles.add(sub)

View file

@ -3,19 +3,23 @@ package com.lagradost.cloudstream3.ui.player
import android.content.Context import android.content.Context
import android.util.Log import android.util.Log
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.google.android.exoplayer2.Format import androidx.media3.common.Format
import com.google.android.exoplayer2.text.* import androidx.media3.common.MimeTypes
import com.google.android.exoplayer2.text.cea.Cea608Decoder import androidx.media3.exoplayer.text.ExoplayerCuesDecoder
import com.google.android.exoplayer2.text.cea.Cea708Decoder import androidx.media3.exoplayer.text.SubtitleDecoderFactory
import com.google.android.exoplayer2.text.dvb.DvbDecoder import androidx.media3.extractor.text.SubtitleDecoder
import com.google.android.exoplayer2.text.pgs.PgsDecoder import androidx.media3.extractor.text.SubtitleInputBuffer
import com.google.android.exoplayer2.text.ssa.SsaDecoder import androidx.media3.extractor.text.SubtitleOutputBuffer
import com.google.android.exoplayer2.text.subrip.SubripDecoder import androidx.media3.extractor.text.cea.Cea608Decoder
import com.google.android.exoplayer2.text.ttml.TtmlDecoder import androidx.media3.extractor.text.cea.Cea708Decoder
import com.google.android.exoplayer2.text.tx3g.Tx3gDecoder import androidx.media3.extractor.text.dvb.DvbDecoder
import com.google.android.exoplayer2.text.webvtt.Mp4WebvttDecoder import androidx.media3.extractor.text.pgs.PgsDecoder
import com.google.android.exoplayer2.text.webvtt.WebvttDecoder import androidx.media3.extractor.text.ssa.SsaDecoder
import com.google.android.exoplayer2.util.MimeTypes 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.R
import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.mvvm.logError
import org.mozilla.universalchardet.UniversalDetector import org.mozilla.universalchardet.UniversalDetector

View file

@ -1,8 +1,8 @@
package com.lagradost.cloudstream3.ui.player package com.lagradost.cloudstream3.ui.player
import android.os.Looper import android.os.Looper
import com.google.android.exoplayer2.text.SubtitleDecoderFactory import androidx.media3.exoplayer.text.SubtitleDecoderFactory
import com.google.android.exoplayer2.text.TextOutput import androidx.media3.exoplayer.text.TextOutput
class CustomTextRenderer( class CustomTextRenderer(
offset: Long, offset: Long,

View file

@ -19,8 +19,8 @@ import androidx.core.view.isGone
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.google.android.exoplayer2.Format.NO_VALUE import androidx.media3.common.Format.NO_VALUE
import com.google.android.exoplayer2.util.MimeTypes import androidx.media3.common.MimeTypes
import com.hippo.unifile.UniFile import com.hippo.unifile.UniFile
import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull

View file

@ -15,10 +15,10 @@
*/ */
package com.lagradost.cloudstream3.ui.player; package com.lagradost.cloudstream3.ui.player;
import static com.google.android.exoplayer2.text.Cue.DIMEN_UNSET; import static androidx.media3.common.text.Cue.DIMEN_UNSET;
import static com.google.android.exoplayer2.text.Cue.LINE_TYPE_NUMBER; import static androidx.media3.common.text.Cue.LINE_TYPE_NUMBER;
import static com.google.android.exoplayer2.util.Assertions.checkNotNull; import static androidx.media3.common.util.Assertions.checkNotNull;
import static com.google.android.exoplayer2.util.Assertions.checkState; import static androidx.media3.common.util.Assertions.checkState;
import static java.lang.annotation.ElementType.TYPE_USE; import static java.lang.annotation.ElementType.TYPE_USE;
import android.os.Handler; import android.os.Handler;
@ -28,25 +28,24 @@ import android.os.Message;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.media3.common.C;
import com.google.android.exoplayer2.BaseRenderer; import androidx.media3.common.Format;
import com.google.android.exoplayer2.C; import androidx.media3.common.text.Cue;
import com.google.android.exoplayer2.Format; import androidx.media3.common.text.CueGroup;
import com.google.android.exoplayer2.FormatHolder; import androidx.media3.common.MimeTypes;
import com.google.android.exoplayer2.RendererCapabilities; import androidx.media3.common.util.Log;
import com.google.android.exoplayer2.source.SampleStream.ReadDataResult; import androidx.media3.common.util.Util;
import com.google.android.exoplayer2.text.Cue; import androidx.media3.exoplayer.BaseRenderer;
import com.google.android.exoplayer2.text.CueGroup; import androidx.media3.exoplayer.FormatHolder;
import com.google.android.exoplayer2.text.Subtitle; import androidx.media3.exoplayer.RendererCapabilities;
import com.google.android.exoplayer2.text.SubtitleDecoder; import androidx.media3.exoplayer.source.SampleStream;
import com.google.android.exoplayer2.text.SubtitleDecoderException; import androidx.media3.exoplayer.text.SubtitleDecoderFactory;
import com.google.android.exoplayer2.text.SubtitleDecoderFactory; import androidx.media3.exoplayer.text.TextOutput;
import com.google.android.exoplayer2.text.SubtitleInputBuffer; import androidx.media3.extractor.text.Subtitle;
import com.google.android.exoplayer2.text.SubtitleOutputBuffer; import androidx.media3.extractor.text.SubtitleDecoder;
import com.google.android.exoplayer2.text.TextOutput; import androidx.media3.extractor.text.SubtitleDecoderException;
import com.google.android.exoplayer2.util.Log; import androidx.media3.extractor.text.SubtitleInputBuffer;
import com.google.android.exoplayer2.util.MimeTypes; import androidx.media3.extractor.text.SubtitleOutputBuffer;
import com.google.android.exoplayer2.util.Util;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
@ -310,7 +309,7 @@ public class NonFinalTextRenderer extends BaseRenderer implements Callback {
return; return;
} }
// Try and read the next subtitle from the source. // 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 (result == C.RESULT_BUFFER_READ) {
if (nextInputBuffer.isEndOfStream()) { if (nextInputBuffer.isEndOfStream()) {
inputStreamEnded = true; inputStreamEnded = true;

View file

@ -26,7 +26,7 @@ class PlayerPipHelper {
activity, activity,
code, code,
Intent("media_control").putExtra("control_type", code), Intent("media_control").putExtra("control_type", code),
0 PendingIntent.FLAG_IMMUTABLE
) )
} }
} }
@ -88,7 +88,15 @@ class PlayerPipHelper {
) )
) )
activity.setPictureInPictureParams( activity.setPictureInPictureParams(
PictureInPictureParams.Builder().setActions(actions).build() PictureInPictureParams.Builder()
.apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
setSeamlessResizeEnabled(true)
setAutoEnterEnabled(isPlaying)
}
}
.setActions(actions)
.build()
) )
} }
} }

View file

@ -4,8 +4,8 @@ import android.util.Log
import android.util.TypedValue import android.util.TypedValue
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.FrameLayout import android.widget.FrameLayout
import com.google.android.exoplayer2.ui.SubtitleView import androidx.media3.common.MimeTypes
import com.google.android.exoplayer2.util.MimeTypes import androidx.media3.ui.SubtitleView
import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.SubtitleFile
import com.lagradost.cloudstream3.ui.player.CustomDecoder.Companion.regexSubtitlesToRemoveBloat import com.lagradost.cloudstream3.ui.player.CustomDecoder.Companion.regexSubtitlesToRemoveBloat
import com.lagradost.cloudstream3.ui.player.CustomDecoder.Companion.regexSubtitlesToRemoveCaptions import com.lagradost.cloudstream3.ui.player.CustomDecoder.Companion.regexSubtitlesToRemoveCaptions

View file

@ -14,7 +14,7 @@ import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import com.fasterxml.jackson.annotation.JsonProperty 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.google.android.gms.cast.TextTrackStyle.* import com.google.android.gms.cast.TextTrackStyle.*
import com.jaredrummler.android.colorpicker.ColorPickerDialog import com.jaredrummler.android.colorpicker.ColorPickerDialog

View file

@ -18,8 +18,8 @@ import androidx.core.content.res.ResourcesCompat
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.annotation.JsonProperty
import com.google.android.exoplayer2.text.Cue import androidx.media3.common.text.Cue
import com.google.android.exoplayer2.ui.CaptionStyleCompat import androidx.media3.ui.CaptionStyleCompat
import com.jaredrummler.android.colorpicker.ColorPickerDialog import com.jaredrummler.android.colorpicker.ColorPickerDialog
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
import com.lagradost.cloudstream3.AcraApplication.Companion.setKey import com.lagradost.cloudstream3.AcraApplication.Companion.setKey

View file

@ -1,7 +1,7 @@
package com.lagradost.cloudstream3.utils package com.lagradost.cloudstream3.utils
import android.net.Uri 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.*
import com.google.android.gms.cast.framework.CastSession import com.google.android.gms.cast.framework.CastSession
import com.google.android.gms.cast.framework.media.RemoteMediaClient import com.google.android.gms.cast.framework.media.RemoteMediaClient

View file

@ -35,7 +35,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/preview_background_img_des" /> android:contentDescription="@string/preview_background_img_des" />
<com.google.android.exoplayer2.ui.SubtitleView <androidx.media3.ui.SubtitleView
android:id="@+id/subtitle_text" android:id="@+id/subtitle_text"
android:layout_width="match_parent" android:layout_width="match_parent"

View file

@ -13,7 +13,7 @@
<!-- <!--
app:fastforward_increment="10000" app:fastforward_increment="10000"
app:rewind_increment="10000"--> app:rewind_increment="10000"-->
<com.google.android.exoplayer2.ui.PlayerView <androidx.media3.ui.PlayerView
android:id="@+id/player_view" android:id="@+id/player_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"

View file

@ -13,7 +13,7 @@
<!-- <!--
app:fastforward_increment="10000" app:fastforward_increment="10000"
app:rewind_increment="10000"--> app:rewind_increment="10000"-->
<com.google.android.exoplayer2.ui.PlayerView <androidx.media3.ui.PlayerView
android:id="@+id/player_view" android:id="@+id/player_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"

View file

@ -14,7 +14,7 @@
<!-- <!--
app:fastforward_increment="10000" app:fastforward_increment="10000"
app:rewind_increment="10000"--> app:rewind_increment="10000"-->
<com.google.android.exoplayer2.ui.PlayerView <androidx.media3.ui.PlayerView
android:id="@+id/player_view" android:id="@+id/player_view"
app:show_timeout="0" app:show_timeout="0"
app:hide_on_touch="false" app:hide_on_touch="false"

View file

@ -432,7 +432,7 @@
android:textStyle="normal" android:textStyle="normal"
tools:text="15:30" /> tools:text="15:30" />
<!--app:buffered_color="@color/videoCache"--> <!--app:buffered_color="@color/videoCache"-->
<com.google.android.exoplayer2.ui.DefaultTimeBar <androidx.media3.ui.DefaultTimeBar
android:id="@id/exo_progress" android:id="@id/exo_progress"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="30dp" android:layout_height="30dp"

View file

@ -260,7 +260,7 @@
android:textStyle="normal" android:textStyle="normal"
tools:text="15:30" /> tools:text="15:30" />
<!--app:buffered_color="@color/videoCache"--> <!--app:buffered_color="@color/videoCache"-->
<com.google.android.exoplayer2.ui.DefaultTimeBar <androidx.media3.ui.DefaultTimeBar
android:id="@id/exo_progress" android:id="@id/exo_progress"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="30dp" android:layout_height="30dp"

View file

@ -35,9 +35,8 @@
android:scaleType="centerCrop" android:scaleType="centerCrop"
android:src="@drawable/subtitles_preview_background" /> android:src="@drawable/subtitles_preview_background" />
<com.google.android.exoplayer2.ui.SubtitleView <androidx.media3.ui.SubtitleView
android:id="@+id/subtitle_text" android:id="@+id/subtitle_text"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_gravity="center" android:layout_gravity="center"

View file

@ -333,7 +333,7 @@
android:textStyle="normal" android:textStyle="normal"
tools:text="15:30" /> tools:text="15:30" />
<!--app:buffered_color="@color/videoCache"--> <!--app:buffered_color="@color/videoCache"-->
<com.google.android.exoplayer2.ui.DefaultTimeBar <androidx.media3.ui.DefaultTimeBar
android:id="@id/exo_progress" android:id="@id/exo_progress"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="30dp" android:layout_height="30dp"

View file

@ -16,6 +16,6 @@ org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# https://developer.android.com/topic/libraries/support-library/androidx-rn # https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX # 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 for this project: "official" or "obsolete":
kotlin.code.style=official kotlin.code.style=official