diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..44ca2d9
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/new-player/src/main/java/net/newpipe/newplayer/model/VideoPlayerViewModel.kt b/new-player/src/main/java/net/newpipe/newplayer/model/VideoPlayerViewModel.kt
index 18175e7..eb828c5 100644
--- a/new-player/src/main/java/net/newpipe/newplayer/model/VideoPlayerViewModel.kt
+++ b/new-player/src/main/java/net/newpipe/newplayer/model/VideoPlayerViewModel.kt
@@ -24,6 +24,7 @@ import android.app.Application
import android.os.Build
import android.os.Bundle
import android.os.Parcelable
+import android.util.Log
import androidx.annotation.RequiresApi
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.SavedStateHandle
@@ -40,16 +41,25 @@ import net.newpipe.newplayer.NewPlayer
val VIDEOPLAYER_UI_STATE = "video_player_ui_state"
+private const val TAG = "VideoPlayerViewModel"
+
@Parcelize
data class VideoPlayerUIState(
val playing: Boolean,
var fullscreen: Boolean,
var uiVissible: Boolean,
- var contentRatio: Float
+ var contentRatio: Float,
+ var minContentRatio: Float,
+ var maxContentRatio: Float
) : Parcelable {
companion object {
val DEFAULT = VideoPlayerUIState(
- playing = false, fullscreen = false, uiVissible = false, 0F
+ playing = false,
+ fullscreen = false,
+ uiVissible = false,
+ contentRatio = 0F,
+ minContentRatio = 4F / 3F,
+ maxContentRatio = 16F / 9F
)
}
}
@@ -59,6 +69,8 @@ interface VideoPlayerViewModel {
val player: Player?
val uiState: StateFlow
var listener: Listener?
+ var minContentRatio: Float
+ var maxContentRatio: Float
fun initUIState(instanceState: Bundle)
fun play()
@@ -78,7 +90,6 @@ interface VideoPlayerViewModel {
}
}
-
@HiltViewModel
class VideoPlayerViewModelImpl @Inject constructor(
private val savedStateHandle: SavedStateHandle,
@@ -99,11 +110,36 @@ class VideoPlayerViewModelImpl @Inject constructor(
override val uiState = mutableUiState.asStateFlow()
override var listener: VideoPlayerViewModel.Listener? = null
- override val player:Player?
+ override val player: Player?
get() = newPlayer?.player
+ override var minContentRatio: Float
+ set(value) {
+ if (value <= 0 || mutableUiState.value.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) }
+ }
+ get() = mutableUiState.value.minContentRatio
+
+ override var maxContentRatio: Float
+ get() = mutableUiState.value.maxContentRatio
+ set(value) {
+ if (value <= 0 || value < mutableUiState.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) }
+ }
+
private fun installExoPlayer() {
player?.let { player ->
+ Log.i(TAG, "Install player")
player.addListener(object : Player.Listener {
override fun onIsPlayingChanged(isPlaying: Boolean) {
super.onIsPlayingChanged(isPlaying)
@@ -143,17 +179,17 @@ class VideoPlayerViewModelImpl @Inject constructor(
override fun onCleared() {
super.onCleared()
- println("gurken viewmodel cleared")
+ Log.d(TAG, "viewmodel cleared")
}
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
override fun initUIState(instanceState: Bundle) {
val uiState =
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
- instanceState.getParcelable(VIDEOPLAYER_UI_STATE, VideoPlayerUIState::class.java)
- else
- instanceState.getParcelable(VIDEOPLAYER_UI_STATE)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) instanceState.getParcelable(
+ VIDEOPLAYER_UI_STATE, VideoPlayerUIState::class.java
+ )
+ else instanceState.getParcelable(VIDEOPLAYER_UI_STATE)
uiState?.let { uiState ->
mutableUiState.update {
@@ -171,11 +207,11 @@ class VideoPlayerViewModelImpl @Inject constructor(
}
override fun prevStream() {
- println("imeplement prev stream")
+ Log.e(TAG, "imeplement prev stream")
}
override fun nextStream() {
- println("implement next stream")
+ Log.e(TAG, "implement next stream")
}
override fun switchToEmbeddedView() {
@@ -196,7 +232,8 @@ class VideoPlayerViewModelImpl @Inject constructor(
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
override fun initUIState(instanceState: Bundle) {
println("dummy impl")
diff --git a/new-player/src/main/java/net/newpipe/newplayer/ui/VideoPlayerLoadingPlaceholder.kt b/new-player/src/main/java/net/newpipe/newplayer/ui/VideoPlayerLoadingPlaceholder.kt
index f155f12..bd60582 100644
--- a/new-player/src/main/java/net/newpipe/newplayer/ui/VideoPlayerLoadingPlaceholder.kt
+++ b/new-player/src/main/java/net/newpipe/newplayer/ui/VideoPlayerLoadingPlaceholder.kt
@@ -1,6 +1,7 @@
package net.newpipe.newplayer.ui
import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Surface
@@ -16,9 +17,9 @@ import androidx.compose.ui.unit.dp
import net.newpipe.newplayer.ui.theme.VideoPlayerTheme
@Composable
-fun VideoPlayerLoadingPlaceholder() {
+fun VideoPlayerLoadingPlaceholder(aspectRatio:Float = 3F/1F) {
Surface(
- modifier = Modifier.fillMaxWidth().height(200.dp),
+ modifier = Modifier.fillMaxWidth().aspectRatio(aspectRatio),
color = Color.Black
) {
Box {
diff --git a/new-player/src/main/java/net/newpipe/newplayer/ui/VideoPlayerUI.kt b/new-player/src/main/java/net/newpipe/newplayer/ui/VideoPlayerUI.kt
index 595be65..aa29e91 100644
--- a/new-player/src/main/java/net/newpipe/newplayer/ui/VideoPlayerUI.kt
+++ b/new-player/src/main/java/net/newpipe/newplayer/ui/VideoPlayerUI.kt
@@ -25,7 +25,9 @@ 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.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
@@ -53,8 +55,10 @@ import net.newpipe.newplayer.utils.findActivity
fun VideoPlayerUI(
viewModel: VideoPlayerViewModel?,
) {
- if (viewModel?.player == null) {
+ if (viewModel == null) {
VideoPlayerLoadingPlaceholder()
+ } else if (viewModel.player == null) {
+ VideoPlayerLoadingPlaceholder(viewModel.uiState.collectAsState().value.maxContentRatio)
} else {
val uiState by viewModel.uiState.collectAsState()
@@ -106,8 +110,13 @@ fun VideoPlayerUI(
}
// Set UI
+ val aspectRatio =
+ uiState.contentRatio.coerceIn(uiState.minContentRatio, uiState.maxContentRatio)
+
Surface(
- modifier = Modifier.fillMaxSize(),
+ modifier = Modifier
+ .fillMaxWidth()
+ .aspectRatio(aspectRatio),
color = Color.Black
) {
AndroidView(
diff --git a/test-app/src/main/java/net/newpipe/newplayer/testapp/MainActivity.kt b/test-app/src/main/java/net/newpipe/newplayer/testapp/MainActivity.kt
index 9ca0fb3..a1487ff 100644
--- a/test-app/src/main/java/net/newpipe/newplayer/testapp/MainActivity.kt
+++ b/test-app/src/main/java/net/newpipe/newplayer/testapp/MainActivity.kt
@@ -51,6 +51,8 @@ class MainActivity : AppCompatActivity() {
video_view.viewModel = videoPlayerViewModel
videoPlayerViewModel.newPlayer = newPlayer
+ videoPlayerViewModel.maxContentRatio = 4F/3F
+
/*
video_view.fullScreenToggleListener = object : VideoPlayerView.FullScreenToggleListener {
override fun fullscreenToggle(turnOn: Boolean) {