Commit Graph

4 Commits

Author SHA1 Message Date
Levi Woodard
ed9814ab4e Reconnect streams in-process; fix for_window IPC rules
Root cause of the periodic drops (found via the new logs): mpv was
exiting cleanly (err=nil, exit 0) with its status line at 100% — i.e.
end-of-stream. UniFi Protect closes some cameras' RTSP connections every
20-40s; with --keep-open=no --idle=no mpv treated that as the file
ending, exited, and the supervisor relaunched it ~3s later (the visible
drop).

- Add --loop-file=inf so mpv reopens the stream the instant it EOFs,
  in the same process and window: sub-second recovery, no teardown,
  no supervisor bounce. The supervisor now only fires for real crashes.
- Clean up the logged exit "reason": strip ANSI escapes and skip mpv's
  transient A/V status prints, so a genuine error surfaces instead of
  "\x1b[KV: 00:00:35 / 00:00:35 (100%)". Tests cover the parsing.

Also fold in the for_window IPC fix: sway's IPC parser splits comma-
joined command lists at the top level and does not fold the continuation
into for_window (unlike the config-file parser), so the map-time
placement rules errored with "Only views can have borders" and never
installed. Register each command separately; drop the redundant
border none (the kiosk config already sets default_border none).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 12:54:02 -05:00
Levi Woodard
9985a93851 Place windows at map time so stream restarts never flash
Diagnosis: individual tiles flickered when their stream died and mpv
relaunched (confirmed via status: a PID dropping to 0 and coming back).
The restarted window mapped at the video's native size wherever sway
dropped it, and the corrective loop only snapped it into its cell on the
next tick — up to 2s later on the relaxed cadence.

Fix, at the source instead of racing the map:
- Pre-install a per-slot for_window rule (matched on each mpv's unique
  window title, anchored so slot-1 never matches slot-10) so sway
  positions and sizes the window synchronously the moment it maps.
- Pass --geometry=WxH per tile so mpv opens at the tile size rather
  than resizing itself to the video's native size on load.

The placeLoop remains as a corrective backstop for mid-life drift.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 09:50:39 -05:00
Levi Woodard
98ddf1645c Smoother daemon: no-op reloads, batched placement, muted audio, graceful teardown
- Skip stream restarts when a reload resolves to the identical wall
  (same URLs, tile geometry, player settings) — saving an unrelated
  config edit no longer blanks the screen.
- Replace per-tile placement polling (a swaymsg fork per tile per second,
  plus 150ms get_tree polling per tile at startup) with one shared loop:
  a single get_tree snapshot per tick, re-placing only drifted windows,
  relaxing to a 2s tick once settled.
- Mute streams by default (--no-audio) to skip an audio decoder per
  stream; opt back in with player.audio: true.
- Graceful, parallel mpv teardown via cmd.Cancel/WaitDelay, fixing the
  double-Wait race between Stop and Supervise and cutting worst-case
  layout switches from ~2s x N streams to ~2s total.
- status: probe mpv IPC outside the daemon mutex so a slow probe can't
  block layout switches.
- View sync: reuse the Protect session across ticks (re-login only on
  expiry) and pick up view_refresh_seconds changes without a restart.
- Health strikes keyed by player, not slot, so they never carry across
  layout switches; prune stale entries.
- New `rtsp-streamer reload` CLI; fix dead sort in `layout ls`; back off
  on persistent control-socket accept errors; fsync config before the
  atomic rename (SD-card power-cut safety); bump IPC client deadline;
  gofmt stragglers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 07:38:01 -05:00
Levi Woodard
55a8ea4bee adding to git.i0t.app 2026-07-01 18:21:14 -05:00