onVideoSizeChanged is not cought anymore

This commit is contained in:
Christian Schabesberger 2024-07-22 20:13:27 +02:00
parent 4089de7272
commit 8bed5b701d
8 changed files with 120 additions and 105 deletions

View File

@ -18,7 +18,7 @@
# along with NewPlayer. If not, see <http://www.gnu.org/licenses/>.
[versions]
agp = "8.5.0"
agp = "8.5.1"
kotlin = "2.0.20-Beta2"
coreKtx = "1.13.1"
junit = "4.13.2"
@ -31,7 +31,7 @@ constraintlayout = "2.1.4"
material3 = "1.2.1"
uiTooling = "1.6.8"
materialIconsExtendedAndroid = "1.7.0-beta05"
media3Ui = "1.4.0-beta01"
media3 = "1.3.1"
hiltAndroid = "2.51.1"
hiltCompiler = "1.2.0"
hiltNavigationCompose = "1.2.0"
@ -39,7 +39,6 @@ lifecycleViewmodelCompose = "2.8.3"
kspVersion = "2.0.20-Beta2-1.0.23"
fragmentKtx = "1.8.1"
lifecycleRuntimeKtx = "2.8.3"
composeBom = "2024.06.01"
kotlinParcelize = "2.0.20-Beta2"
newplayer = "master-SNAPSHOT"
@ -56,8 +55,9 @@ androidx-activity-compose = { group = "androidx.activity", name = "activity-comp
androidx-material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "material3" }
androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling", version.ref = "uiTooling" }
androidx-material-icons-extended-android = { group = "androidx.compose.material", name = "material-icons-extended-android", version.ref = "materialIconsExtendedAndroid" }
androidx-media3-exoplayer = { group = "androidx.media3", name = "media3-exoplayer", version.ref = "media3Ui" }
androidx-media3-ui = { group = "androidx.media3", name = "media3-ui", version.ref = "media3Ui" }
androidx-media3-exoplayer = { group = "androidx.media3", name = "media3-exoplayer", version.ref = "media3" }
androidx-media3-ui = { group = "androidx.media3", name = "media3-ui", version.ref = "media3" }
androidx-media3-common = { group = "androidx.media3", name = "media3-common", version.ref = "media3" }
hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hiltAndroid" }
androidx-hilt-compiler = { group = "androidx.hilt", name = "hilt-compiler", version.ref = "hiltCompiler" }
androidx-hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "hiltNavigationCompose" }
@ -75,6 +75,7 @@ androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit
newplayer = { group = "com.github.theScrabi.NewPlayer", name = "new-player", version.ref = "newplayer" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }

View File

@ -65,6 +65,7 @@ dependencies {
implementation(libs.androidx.ui.graphics)
implementation(libs.androidx.ui.tooling.preview)
implementation(libs.androidx.hilt.navigation.compose)
implementation(libs.androidx.media3.common)
ksp(libs.hilt.android.compiler)
ksp(libs.androidx.hilt.compiler)

View File

@ -38,6 +38,7 @@ import kotlinx.coroutines.flow.update
import net.newpipe.newplayer.utils.VideoSize
import kotlinx.parcelize.Parcelize
import net.newpipe.newplayer.NewPlayer
import net.newpipe.newplayer.ui.ContentFitMode
val VIDEOPLAYER_UI_STATE = "video_player_ui_state"
@ -47,19 +48,19 @@ private const val TAG = "VideoPlayerViewModel"
data class VideoPlayerUIState(
val playing: Boolean,
var fullscreen: Boolean,
var uiVissible: Boolean,
var contentRatio: Float,
var minContentRatio: Float,
var maxContentRatio: Float
var uiVisible: Boolean,
val contentRatio: Float,
val uiRatio: Float,
val contentFitMode: ContentFitMode
) : Parcelable {
companion object {
val DEFAULT = VideoPlayerUIState(
playing = false,
fullscreen = false,
uiVissible = false,
uiVisible = false,
contentRatio = 0F,
minContentRatio = 4F / 3F,
maxContentRatio = 16F / 9F
uiRatio = 16F / 9F,
contentFitMode = ContentFitMode.FIT_INSIDE
)
}
}
@ -68,7 +69,6 @@ interface VideoPlayerViewModel {
var newPlayer: NewPlayer?
val player: Player?
val uiState: StateFlow<VideoPlayerUIState>
var listener: Listener?
var minContentRatio: Float
var maxContentRatio: Float
@ -79,15 +79,6 @@ interface VideoPlayerViewModel {
fun nextStream()
fun switchToFullscreen()
fun switchToEmbeddedView()
interface Listener {
fun requestUpdateLayoutRatio(ratio: Float)
}
sealed class Events {
object SwitchToFullscreen : Events()
object SwitchToEmbeddedView : Events()
}
}
@HiltViewModel
@ -98,7 +89,6 @@ class VideoPlayerViewModelImpl @Inject constructor(
// private
private val mutableUiState = MutableStateFlow(VideoPlayerUIState.DEFAULT)
private var current_video_size = VideoSize.DEFAULT
//interface
override var newPlayer: NewPlayer? = null
@ -108,75 +98,71 @@ class VideoPlayerViewModelImpl @Inject constructor(
}
override val uiState = mutableUiState.asStateFlow()
override var listener: VideoPlayerViewModel.Listener? = null
override val player: Player?
get() = newPlayer?.player
override var minContentRatio: Float
override var minContentRatio: Float = 4F / 3F
set(value) {
if (value <= 0 || mutableUiState.value.maxContentRatio < value)
if (value <= 0 || maxContentRatio < value)
Log.e(
TAG,
"Ignoring maxContentRatio: It must not be 0 or less and it may not be bigger then mmaxContentRatio. It was Set to: $value"
)
else
mutableUiState.update { it.copy(minContentRatio = value) }
else {
field = value
mutableUiState.update { it.copy(uiRatio = getUiRatio()) }
}
}
get() = mutableUiState.value.minContentRatio
override var maxContentRatio: Float
get() = mutableUiState.value.maxContentRatio
override var maxContentRatio: Float = 16F / 9F
set(value) {
if (value <= 0 || value < mutableUiState.value.minContentRatio)
if (value <= 0 || value < minContentRatio)
Log.e(
TAG,
"Ignoring maxContentRatio: It must not be 0 or less and it may not be smaller then minContentRatio. It was Set to: $value"
)
else
mutableUiState.update { it.copy(maxContentRatio = value) }
else {
field = value
mutableUiState.update { it.copy(uiRatio = getUiRatio()) }
}
}
private fun installExoPlayer() {
player?.let { player ->
Log.i(TAG, "Install player")
Log.d(TAG, "Install player: ${player.videoSize.width}")
player.addListener(object : Player.Listener {
override fun onIsPlayingChanged(isPlaying: Boolean) {
super.onIsPlayingChanged(isPlaying)
Log.d(TAG, "Playing state changed. Is Playing: $isPlaying")
Log.d(TAG, "Gurken: ${VideoSize.fromMedia3VideoSize(player.videoSize)}")
mutableUiState.update {
it.copy(playing = isPlaying)
}
}
// We need to updated the layout of our player view if the video ratio changes
// However, this should be done differently depending on weather we are in
// embedded or fullscreen view.
// If we are in embedded view, we tell the mother layout (only ConstraintLayout supported!)
// to change the ratio of the whole player view.
// If we are in fullscreen we only want to change the ratio of the SurfaceView
override fun onVideoSizeChanged(media3VideoSize: androidx.media3.common.VideoSize) {
super.onVideoSizeChanged(media3VideoSize)
val videoSize = VideoSize.fromMedia3VideoSize(media3VideoSize)
if (current_video_size != videoSize) {
val newRatio = videoSize.getRatio()
if (current_video_size.getRatio() != newRatio) {
mutableUiState.update {
it.copy(contentRatio = newRatio)
}
if (!mutableUiState.value.fullscreen) {
listener?.requestUpdateLayoutRatio(newRatio)
}
}
current_video_size = videoSize
}
override fun onVideoSizeChanged(videoSize: androidx.media3.common.VideoSize) {
super.onVideoSizeChanged(videoSize)
println("gurken aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
updateContentRatio(VideoSize.fromMedia3VideoSize(videoSize))
}
})
}
}
fun updateContentRatio(videoSize: VideoSize) {
val newRatio = videoSize.getRatio()
Log.d(TAG, "Update Content ratio: $newRatio")
mutableUiState.update {
it.copy(
contentRatio = newRatio,
uiRatio = getUiRatio()
)
}
}
override fun onCleared() {
super.onCleared()
Log.d(TAG, "viewmodel cleared")
@ -226,12 +212,21 @@ class VideoPlayerViewModelImpl @Inject constructor(
}
}
private fun getUiRatio() =
player?.let { player ->
val videoRatio = VideoSize.fromMedia3VideoSize(player.videoSize).getRatio()
return if (videoRatio.isNaN())
minContentRatio
else
videoRatio.coerceIn(minContentRatio, maxContentRatio)
} ?: minContentRatio
companion object {
val dummy = object : VideoPlayerViewModel {
override var newPlayer: NewPlayer? = null
override val player: Player? = null
override val uiState = MutableStateFlow(VideoPlayerUIState.DEFAULT)
override var listener: VideoPlayerViewModel.Listener? = null
override var minContentRatio = 4F / 3F
override var maxContentRatio = 16F / 9F

View File

@ -0,0 +1,8 @@
package net.newpipe.newplayer.ui
enum class ContentFitMode {
FILL,
FIT_INSIDE,
ZOOM
}

View File

@ -17,13 +17,17 @@ import androidx.compose.ui.unit.dp
import net.newpipe.newplayer.ui.theme.VideoPlayerTheme
@Composable
fun VideoPlayerLoadingPlaceholder(aspectRatio:Float = 3F/1F) {
fun VideoPlayerLoadingPlaceholder(aspectRatio: Float = 3F / 1F) {
Surface(
modifier = Modifier.fillMaxWidth().aspectRatio(aspectRatio),
modifier = Modifier
.fillMaxWidth()
.aspectRatio(aspectRatio),
color = Color.Black
) {
Box {
CircularProgressIndicator(modifier = Modifier.width(64.dp).align((Alignment.Center)))
Box(contentAlignment = Alignment.Center) {
CircularProgressIndicator(modifier = Modifier
.width(64.dp)
.align((Alignment.Center)))
}
}
}

View File

@ -23,9 +23,9 @@ package net.newpipe.newplayer.ui
import android.content.pm.ActivityInfo
import android.view.SurfaceView
import androidx.activity.compose.BackHandler
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material3.Surface
@ -37,9 +37,9 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.viewinterop.AndroidView
@ -49,7 +49,6 @@ import net.newpipe.newplayer.model.VideoPlayerViewModel
import net.newpipe.newplayer.model.VideoPlayerViewModelImpl
import net.newpipe.newplayer.ui.theme.VideoPlayerTheme
import net.newpipe.newplayer.utils.LockScreenOrientation
import net.newpipe.newplayer.utils.findActivity
@Composable
fun VideoPlayerUI(
@ -57,8 +56,8 @@ fun VideoPlayerUI(
) {
if (viewModel == null) {
VideoPlayerLoadingPlaceholder()
} else if (viewModel.player == null) {
VideoPlayerLoadingPlaceholder(viewModel.uiState.collectAsState().value.maxContentRatio)
} else if (viewModel.player == null || viewModel.uiState.collectAsState().value.contentRatio == 0.0F) {
VideoPlayerLoadingPlaceholder(viewModel.uiState.collectAsState().value.uiRatio)
} else {
val uiState by viewModel.uiState.collectAsState()
@ -88,14 +87,6 @@ fun VideoPlayerUI(
}
}
val fullscreenLauncher =
rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartActivityForResult()
) { result ->
println("gurken returned for result")
viewModel.initUIState(result.data?.extras!!)
}
LaunchedEffect(key1 = uiState.fullscreen) {
println("gurken launch fullscreen: ${uiState.fullscreen}")
}
@ -110,17 +101,29 @@ fun VideoPlayerUI(
}
// Set UI
val aspectRatio =
uiState.contentRatio.coerceIn(uiState.minContentRatio, uiState.maxContentRatio)
Surface(
modifier = Modifier
.fillMaxWidth()
.aspectRatio(aspectRatio),
.aspectRatio(uiState.uiRatio),
color = Color.Black
) {
Box(contentAlignment = Alignment.Center){
AndroidView(
modifier = Modifier.fillMaxSize(),
modifier = Modifier.also { modifier ->
when (uiState.contentFitMode) {
ContentFitMode.FILL -> modifier.fillMaxSize()
ContentFitMode.FIT_INSIDE -> if (uiState.contentRatio < uiState.uiRatio) {
modifier.fillMaxHeight().aspectRatio(uiState.contentRatio)
} else if (uiState.uiRatio < uiState.contentRatio) {
modifier.fillMaxWidth().aspectRatio(uiState.contentRatio)
}
ContentFitMode.ZOOM -> if(uiState.uiRatio < uiState.contentRatio) {
modifier.fillMaxHeight().aspectRatio(uiState.contentRatio)
} else if (uiState.contentRatio < uiState.uiRatio) {
modifier.fillMaxWidth().aspectRatio(uiState.contentRatio)
}
}
},
factory = { context ->
SurfaceView(context).also { view ->
viewModel.player?.setVideoSurfaceView(view)
@ -147,6 +150,7 @@ fun VideoPlayerUI(
)
}
}
}
}
@Preview(device = "spec:width=1080px,height=700px,dpi=440,orientation=landscape")

View File

@ -20,6 +20,9 @@ data class VideoSize(
fun getRatio() =
(width * pixelWidthHeightRatio) / height
override fun toString() =
"VideoSize(width = $width, height = $height, pixelRatio = $pixelWidthHeightRatio, ratio = ${getRatio()})"
companion object {
val DEFAULT = VideoSize(0, 0, 1F)

View File

@ -98,6 +98,5 @@ class MainActivity : AppCompatActivity() {
)
insets
}
}
}