Browse Source

Pause viewers in the background and keep visible playback awake

master
evgeny 1 week ago
parent
commit
039c0f71f5
  1. 47
      tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/StreamScreen.kt

47
tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/StreamScreen.kt

@ -19,10 +19,13 @@ import androidx.compose.runtime.*
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView import androidx.compose.ui.viewinterop.AndroidView
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import com.utun.chat.R import com.utun.chat.R
import com.utun.chat.data.LogManager import com.utun.chat.data.LogManager
import com.utun.chat.data.NativeLib import com.utun.chat.data.NativeLib
@ -131,6 +134,21 @@ fun StreamScreen(channelId: String, channelName: String, onBack: () -> Unit) {
@Composable @Composable
private fun LiveStreamView(group: Long, source: Long, localPreview: Boolean) { private fun LiveStreamView(group: Long, source: Long, localPreview: Boolean) {
val owner = LocalLifecycleOwner.current
var visible by remember(owner) { mutableStateOf(owner.lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) }
DisposableEffect(owner) {
val observer = LifecycleEventObserver { _, event ->
if (event == Lifecycle.Event.ON_START) visible = true
if (event == Lifecycle.Event.ON_STOP) visible = false
}
owner.lifecycle.addObserver(observer)
onDispose { owner.lifecycle.removeObserver(observer) }
}
if (visible) LiveStreamSurface(group, source, localPreview)
}
@Composable
private fun LiveStreamSurface(group: Long, source: Long, localPreview: Boolean) {
val engine = remember(group, source, localPreview) { StreamPlayerEngine(group, source, localPreview) } val engine = remember(group, source, localPreview) { StreamPlayerEngine(group, source, localPreview) }
val aspect by engine.aspect.collectAsState() val aspect by engine.aspect.collectAsState()
val status by engine.status.collectAsState() val status by engine.status.collectAsState()
@ -140,21 +158,22 @@ private fun LiveStreamView(group: Long, source: Long, localPreview: Boolean) {
Text(stringResource(status)) Text(stringResource(status))
Box(Modifier.weight(1f).fillMaxWidth(), contentAlignment = Alignment.Center) { Box(Modifier.weight(1f).fillMaxWidth(), contentAlignment = Alignment.Center) {
AndroidView(factory = { context -> AndroidView(factory = { context ->
TextureView(context).apply { TextureView(context).apply {
surfaceTextureListener = object : TextureView.SurfaceTextureListener { keepScreenOn = true
override fun onSurfaceTextureAvailable(texture: SurfaceTexture, width: Int, height: Int) { surfaceTextureListener = object : TextureView.SurfaceTextureListener {
surface = Surface(texture); engine.start(surface!!) override fun onSurfaceTextureAvailable(texture: SurfaceTexture, width: Int, height: Int) {
} surface = Surface(texture); engine.start(surface!!)
override fun onSurfaceTextureSizeChanged(texture: SurfaceTexture, width: Int, height: Int) {} }
override fun onSurfaceTextureDestroyed(texture: SurfaceTexture): Boolean { override fun onSurfaceTextureSizeChanged(texture: SurfaceTexture, width: Int, height: Int) {}
engine.stop(); surface?.release(); surface = null; return true override fun onSurfaceTextureDestroyed(texture: SurfaceTexture): Boolean {
engine.stop(); surface?.release(); surface = null; return true
}
override fun onSurfaceTextureUpdated(texture: SurfaceTexture) {}
}
} }
override fun onSurfaceTextureUpdated(texture: SurfaceTexture) {} }, modifier = Modifier.aspectRatio(aspect, matchHeightConstraintsFirst = true), onRelease = { view ->
} engine.stop(); view.surfaceTextureListener = null; surface?.release(); surface = null
} })
}, modifier = Modifier.aspectRatio(aspect, matchHeightConstraintsFirst = true), onRelease = { view ->
engine.stop(); view.surfaceTextureListener = null; surface?.release(); surface = null
})
} }
} }
} }

Loading…
Cancel
Save