Keep video gesture callbacks current and forbid reads during cleanup

This commit is contained in:
evgeny committed 2026-10-29 13:34:25 +01:00
1 parent fdecfe1b78
commit 7ec46278af
3 files changed
+11 -8

No files matched your search

@@ -20,11 +20,13 @@ internal class VideoFileMetadata : AutoCloseable {
private val main = Handler(Looper.getMainLooper())
private var delay = 250L
private var scheduled = false
private var closing = false
private val retry = Runnable {
synchronized(this) { scheduled = false }
try { close() } catch (e: Exception) { LogManager.addLog("WARN", "VideoPlayer", "Metadata cleanup pending: $e") }
}
@Synchronized fun read(path: String): VideoInfo {
check(!closing) { "Metadata reader closing" }
val current = checkNotNull(retriever) { "Metadata reader closed" }
current.setDataSource(path)
val width = current.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)?.toIntOrNull() ?: 0
@@ -34,6 +36,7 @@ internal class VideoFileMetadata : AutoCloseable {
return VideoInfo(width, height, rotation)
}
@Synchronized override fun close() {
closing = true
val current = retriever ?: return
try {
current.release(); retriever = null
@@ -68,7 +68,7 @@ internal class VideoFilePlayer(onCompleted: () -> Unit) : AutoCloseable {
fun attach(texture: SurfaceTexture) {
check(Looper.myLooper() == Looper.getMainLooper())
if (uiTargets.containsKey(texture)) return
val target = StreamPreviewTarget(texture)
val target = try { StreamPreviewTarget(texture) } catch (e: Exception) { fail("create Surface", e); return }
uiTargets[texture] = target
if (disposed) { target.release(); return }
if (retiring) return // UI сохраняет собственную texture до destroy/close даже после ошибки player.
@@ -259,13 +259,13 @@ fun VideoPlayerScreen(filePath: String, onClose: () -> Unit) {
if (error == null) {
Box(
modifier = Modifier.fillMaxSize()
.pointerInput(Unit) {
.pointerInput(player) {
detectTapGestures {
hideTick++
if (isPlaying) controlsVisible = !controlsVisible
if (player.state.value.playing) controlsVisible = !controlsVisible
}
}
.pointerInput(screenW, screenH, videoW, videoH) {
.pointerInput(player, screenW, screenH, videoW, videoH) {
detectTransformGestures { centroid, pan, factor, _ ->
onInteraction()
zoom.transform(centroid, pan, factor, Size(videoW, videoH), Size(screenW, screenH))
@@ -377,7 +377,7 @@ fun VideoPlayerScreen(filePath: String, onClose: () -> Unit) {
modifier = Modifier
.weight(1f)
.height(32.dp)
.pointerInput(durationMs, playback.prepared, error) {
.pointerInput(player, durationMs, playback.prepared, error) {
detectTapGestures { offset ->
if (!playback.prepared || error != null) return@detectTapGestures
onInteraction()
@@ -385,11 +385,11 @@ fun VideoPlayerScreen(filePath: String, onClose: () -> Unit) {
player.seek(pos)
}
}
.pointerInput(durationMs, playback.prepared, error) {
.pointerInput(player, durationMs, playback.prepared, error) {
detectDragGestures(
onDragStart = { offset ->
wasPlayingBeforeDrag = isPlaying
if (playback.prepared && error == null && (!isPlaying || player.pause())) {
wasPlayingBeforeDrag = player.state.value.playing
if (playback.prepared && error == null && (!wasPlayingBeforeDrag || player.pause())) {
dragging = true
dragPosition = (offset.x / size.width * durationMs).toInt().coerceIn(0, durationMs)
player.seek(dragPosition)