Review (GPT-6 Astra, P2): the still-image loop stopped calling show() once
the screen took its first frame, so a surround refused during standby was
never retried and stayed missing for PNG and splat playback until restart.
hold() now keeps draining pending uploads after the screen is shown, until
both are up.
Also: stills and the surround wait out standby without counting as dropped
video frames or tripping the five-minute limit (video only); teardown
errors no longer overwrite a finished status; Stop is ignored once the
outcome is decided.
Tests: PNG and splat where the screen is accepted before the surround
recovers (fail on the old loop); fake-clock coverage of the five-minute
limit and its reset; status keeps filename/metadata layout sources and
explicit layouts stay explicit.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Real-Frame testing (2026-09-29) found an unworn headset enters standby
within seconds; SetOverlayRaw then returns RequestFailed (23) and the
movie died. The player now drops frames during standby, keeps audio
and pacing, re-sends stills and the theatre surround after waking, and
only errors after five minutes without an accepted frame.
A Stop arriving while the player is already shutting down is ignored,
so a finished video stays 'ended' instead of 'error: Stopped'. The
status now reports the layout's real source (filename/metadata).
Docs record the end-to-end device matrix (API, web UI, CLI).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Stop always calls systemctl and treats exit 5 (unit already collected)
as done, so there is no is-active/stop race. Cleanup never masks the
copy error, the play ssh timeout covers the remote worst case, and
tests cover stop exit codes and systemd-run stderr reporting.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Stop is a no-op when the collected player unit is already gone
(raw systemctl stop exits 5 on the Frame; verified 2026-09-29).
- Surface systemd-run stderr when the player can't start.
- Keep the copy error if the cleanup ssh also fails; reject upload
names that the play path can never accept.
- Allow 60 s for play (ffprobe 30 s + systemd-run 15 s remote).
- Docs: four-hour cap is unconditional; no delete action yet; fix a
garbled timing sentence.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>