diff --git a/android/app/src/main/java/com/remotedisplay/player/player/ZoneManager.kt b/android/app/src/main/java/com/remotedisplay/player/player/ZoneManager.kt index a1c5e05..7b9c1e1 100644 --- a/android/app/src/main/java/com/remotedisplay/player/player/ZoneManager.kt +++ b/android/app/src/main/java/com/remotedisplay/player/player/ZoneManager.kt @@ -252,6 +252,14 @@ class ZoneManager( override fun onPlaybackStateChanged(state: Int) { if (state == Player.STATE_ENDED) handler.post { advance() } } + // Same reason MediaPlayerManager treats a playback error as a completion + // ("Root-2: a corrupt/undecodable video used to freeze the playlist + // forever"): an error lands in STATE_IDLE, never STATE_ENDED, so without + // this the zone stops rotating and goes black until the layout changes or + // the app restarts — while every other zone keeps going. + override fun onPlayerError(error: androidx.media3.common.PlaybackException) { + handler.post { advance() } + } }) prepare() playWhenReady = true diff --git a/server/player/index.html b/server/player/index.html index 896f888..54ef27a 100644 --- a/server/player/index.html +++ b/server/player/index.html @@ -3091,7 +3091,16 @@ video.loop = !multi; // single-item zone loops; multi advances on end video.playsInline = true; video.style.cssText = `width:100%;height:100%;object-fit:${zone.fit_mode || 'cover'}`; - if (multi) video.onended = advance; + if (multi) { + video.onended = advance; + // A zone video advanced ONLY on `ended`, with no error handler and — alone among the zone + // branches — no timer either. A 404, an unreachable remote_url, an undecodable clip, or an + // `ended` that simply never fires left that region black for days while the other zones + // kept rotating: the screen looks half broken and nothing self-heals. The fullscreen web + // path and Tizen's ZoneRenderer both already carry these two guards. + video.onerror = advance; + zoneTimers[zone.id] = setTimeout(advance, dur + 5000); + } div.appendChild(video); } else { const img = document.createElement('img');