mirror of
https://github.com/gabehf/Fladder.git
synced 2026-03-07 13:38:13 -08:00
feat: Add fillScreen and videoFit to native player options
This commit is contained in:
parent
63203f39df
commit
318f32c7e6
8 changed files with 148 additions and 23 deletions
|
|
@ -55,6 +55,8 @@ class MainActivity : AudioServiceFragmentActivity(), NativeVideoActivity {
|
|||
}
|
||||
|
||||
callback?.invoke(Result.success(startResult))
|
||||
VideoPlayerObject.implementation.player?.stop()
|
||||
VideoPlayerObject.implementation.player?.release()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -72,6 +74,8 @@ class MainActivity : AudioServiceFragmentActivity(), NativeVideoActivity {
|
|||
}
|
||||
|
||||
override fun disposeActivity() {
|
||||
VideoPlayerObject.implementation.player?.stop()
|
||||
VideoPlayerObject.implementation.player?.release()
|
||||
VideoPlayerObject.currentActivity?.finish()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -65,6 +65,22 @@ private object PlayerSettingsHelperPigeonUtils {
|
|||
|
||||
}
|
||||
|
||||
enum class VideoPlayerFit(val raw: Int) {
|
||||
FILL(0),
|
||||
CONTAIN(1),
|
||||
COVER(2),
|
||||
FIT_WIDTH(3),
|
||||
FIT_HEIGHT(4),
|
||||
NONE(5),
|
||||
SCALE_DOWN(6);
|
||||
|
||||
companion object {
|
||||
fun ofRaw(raw: Int): VideoPlayerFit? {
|
||||
return values().firstOrNull { it.raw == raw }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class PlayerOrientations(val raw: Int) {
|
||||
PORTRAIT_UP(0),
|
||||
PORTRAIT_DOWN(1),
|
||||
|
|
@ -124,7 +140,9 @@ data class PlayerSettings (
|
|||
val skipForward: Long,
|
||||
val skipBackward: Long,
|
||||
val autoNextType: AutoNextType,
|
||||
val acceptedOrientations: List<PlayerOrientations>
|
||||
val acceptedOrientations: List<PlayerOrientations>,
|
||||
val fillScreen: Boolean,
|
||||
val videoFit: VideoPlayerFit
|
||||
)
|
||||
{
|
||||
companion object {
|
||||
|
|
@ -136,7 +154,9 @@ data class PlayerSettings (
|
|||
val skipBackward = pigeonVar_list[4] as Long
|
||||
val autoNextType = pigeonVar_list[5] as AutoNextType
|
||||
val acceptedOrientations = pigeonVar_list[6] as List<PlayerOrientations>
|
||||
return PlayerSettings(enableTunneling, skipTypes, themeColor, skipForward, skipBackward, autoNextType, acceptedOrientations)
|
||||
val fillScreen = pigeonVar_list[7] as Boolean
|
||||
val videoFit = pigeonVar_list[8] as VideoPlayerFit
|
||||
return PlayerSettings(enableTunneling, skipTypes, themeColor, skipForward, skipBackward, autoNextType, acceptedOrientations, fillScreen, videoFit)
|
||||
}
|
||||
}
|
||||
fun toList(): List<Any?> {
|
||||
|
|
@ -148,6 +168,8 @@ data class PlayerSettings (
|
|||
skipBackward,
|
||||
autoNextType,
|
||||
acceptedOrientations,
|
||||
fillScreen,
|
||||
videoFit,
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
|
|
@ -166,25 +188,30 @@ private open class PlayerSettingsHelperPigeonCodec : StandardMessageCodec() {
|
|||
return when (type) {
|
||||
129.toByte() -> {
|
||||
return (readValue(buffer) as Long?)?.let {
|
||||
PlayerOrientations.ofRaw(it.toInt())
|
||||
VideoPlayerFit.ofRaw(it.toInt())
|
||||
}
|
||||
}
|
||||
130.toByte() -> {
|
||||
return (readValue(buffer) as Long?)?.let {
|
||||
AutoNextType.ofRaw(it.toInt())
|
||||
PlayerOrientations.ofRaw(it.toInt())
|
||||
}
|
||||
}
|
||||
131.toByte() -> {
|
||||
return (readValue(buffer) as Long?)?.let {
|
||||
SegmentType.ofRaw(it.toInt())
|
||||
AutoNextType.ofRaw(it.toInt())
|
||||
}
|
||||
}
|
||||
132.toByte() -> {
|
||||
return (readValue(buffer) as Long?)?.let {
|
||||
SegmentSkip.ofRaw(it.toInt())
|
||||
SegmentType.ofRaw(it.toInt())
|
||||
}
|
||||
}
|
||||
133.toByte() -> {
|
||||
return (readValue(buffer) as Long?)?.let {
|
||||
SegmentSkip.ofRaw(it.toInt())
|
||||
}
|
||||
}
|
||||
134.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
PlayerSettings.fromList(it)
|
||||
}
|
||||
|
|
@ -194,24 +221,28 @@ private open class PlayerSettingsHelperPigeonCodec : StandardMessageCodec() {
|
|||
}
|
||||
override fun writeValue(stream: ByteArrayOutputStream, value: Any?) {
|
||||
when (value) {
|
||||
is PlayerOrientations -> {
|
||||
is VideoPlayerFit -> {
|
||||
stream.write(129)
|
||||
writeValue(stream, value.raw)
|
||||
}
|
||||
is AutoNextType -> {
|
||||
is PlayerOrientations -> {
|
||||
stream.write(130)
|
||||
writeValue(stream, value.raw)
|
||||
}
|
||||
is SegmentType -> {
|
||||
is AutoNextType -> {
|
||||
stream.write(131)
|
||||
writeValue(stream, value.raw)
|
||||
}
|
||||
is SegmentSkip -> {
|
||||
is SegmentType -> {
|
||||
stream.write(132)
|
||||
writeValue(stream, value.raw)
|
||||
}
|
||||
is PlayerSettings -> {
|
||||
is SegmentSkip -> {
|
||||
stream.write(133)
|
||||
writeValue(stream, value.raw)
|
||||
}
|
||||
is PlayerSettings -> {
|
||||
stream.write(134)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
else -> super.writeValue(stream, value)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import PlayerSettingsPigeon
|
|||
import androidx.compose.ui.graphics.Color
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import nl.jknaapen.fladder.utility.toExoPlayerFit
|
||||
import kotlin.time.DurationUnit
|
||||
import kotlin.time.toDuration
|
||||
|
||||
|
|
@ -33,6 +34,14 @@ object PlayerSettingsObject : PlayerSettingsPigeon {
|
|||
settings?.autoNextType ?: AutoNextType.OFF
|
||||
}
|
||||
|
||||
val acceptedOrientations = settings.map { settings ->
|
||||
settings?.acceptedOrientations ?: emptyList()
|
||||
}
|
||||
|
||||
val fillScreen = settings.map { settings -> settings?.fillScreen ?: false }
|
||||
|
||||
val videoFit = settings.map { settings -> settings?.videoFit.toExoPlayerFit }
|
||||
|
||||
override fun sendPlayerSettings(playerSettings: PlayerSettings) {
|
||||
settings.value = playerSettings
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,12 +7,15 @@ import android.view.WindowManager
|
|||
import androidx.activity.compose.LocalActivity
|
||||
import androidx.annotation.OptIn
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.displayCutoutPadding
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.compositionLocalOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
|
@ -33,6 +36,7 @@ import androidx.media3.exoplayer.source.DefaultMediaSourceFactory
|
|||
import androidx.media3.exoplayer.trackselection.DefaultTrackSelector
|
||||
import androidx.media3.extractor.DefaultExtractorsFactory
|
||||
import androidx.media3.extractor.ts.TsExtractor
|
||||
import androidx.media3.ui.AspectRatioFrameLayout
|
||||
import androidx.media3.ui.CaptionStyleCompat
|
||||
import androidx.media3.ui.PlayerView
|
||||
import io.github.peerless2012.ass.media.kt.buildWithAssSupport
|
||||
|
|
@ -43,6 +47,7 @@ import nl.jknaapen.fladder.messengers.properlySetSubAndAudioTracks
|
|||
import nl.jknaapen.fladder.objects.PlayerSettingsObject
|
||||
import nl.jknaapen.fladder.objects.VideoPlayerObject
|
||||
import nl.jknaapen.fladder.utility.AllowedOrientations
|
||||
import nl.jknaapen.fladder.utility.conditional
|
||||
import nl.jknaapen.fladder.utility.getAudioTracks
|
||||
import nl.jknaapen.fladder.utility.getSubtitleTracks
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
|
@ -139,7 +144,6 @@ internal fun ExoPlayer(
|
|||
val listener = object : Player.Listener {
|
||||
override fun onIsPlayingChanged(isPlaying: Boolean) {
|
||||
activity?.window?.let {
|
||||
println("Changing playback state")
|
||||
if (isPlaying) {
|
||||
it.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
} else {
|
||||
|
|
@ -200,8 +204,12 @@ internal fun ExoPlayer(
|
|||
}
|
||||
}
|
||||
|
||||
val acceptedOrientations by PlayerSettingsObject.acceptedOrientations.collectAsState(emptyList())
|
||||
val fillScreen by PlayerSettingsObject.fillScreen.collectAsState(false)
|
||||
val videoFit by PlayerSettingsObject.videoFit.collectAsState(AspectRatioFrameLayout.RESIZE_MODE_FIT)
|
||||
|
||||
AllowedOrientations(
|
||||
PlayerSettingsObject.settings.value?.acceptedOrientations ?: emptyList()
|
||||
acceptedOrientations
|
||||
) {
|
||||
NextUpOverlay(
|
||||
modifier = Modifier
|
||||
|
|
@ -210,11 +218,15 @@ internal fun ExoPlayer(
|
|||
AndroidView(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(color = Color.Black),
|
||||
.background(color = Color.Black)
|
||||
.conditional(!fillScreen) {
|
||||
displayCutoutPadding()
|
||||
},
|
||||
factory = {
|
||||
PlayerView(it).apply {
|
||||
player = exoPlayer
|
||||
useController = false
|
||||
resizeMode = videoFit
|
||||
layoutParams = ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
package nl.jknaapen.fladder.utility
|
||||
|
||||
import VideoPlayerFit
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.media3.ui.AspectRatioFrameLayout
|
||||
|
||||
val VideoPlayerFit?.toExoPlayerFit: Int
|
||||
@UnstableApi
|
||||
get() = when (this) {
|
||||
VideoPlayerFit.FILL -> AspectRatioFrameLayout.RESIZE_MODE_FILL
|
||||
VideoPlayerFit.CONTAIN -> AspectRatioFrameLayout.RESIZE_MODE_FIT
|
||||
VideoPlayerFit.COVER -> AspectRatioFrameLayout.RESIZE_MODE_ZOOM
|
||||
VideoPlayerFit.FIT_WIDTH -> AspectRatioFrameLayout.RESIZE_MODE_FIXED_WIDTH
|
||||
VideoPlayerFit.FIT_HEIGHT -> AspectRatioFrameLayout.RESIZE_MODE_FIXED_HEIGHT
|
||||
VideoPlayerFit.NONE -> AspectRatioFrameLayout.RESIZE_MODE_FIXED_WIDTH
|
||||
VideoPlayerFit.SCALE_DOWN -> AspectRatioFrameLayout.RESIZE_MODE_FIT
|
||||
null -> AspectRatioFrameLayout.RESIZE_MODE_FIT
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue