Skip to content

feat(cast): self-contained casting package skeleton - #73

Open
susamn wants to merge 1 commit into
feature/mpd-outputsfrom
feature/cast-skeleton
Open

feat(cast): self-contained casting package skeleton#73
susamn wants to merge 1 commit into
feature/mpd-outputsfrom
feature/cast-skeleton

Conversation

@susamn

@susamn susamn commented Aug 27, 2026

Copy link
Copy Markdown
Owner

Stacked on #72. Second slice of the casting feature.

What

Introduces internal/cast — the interface + lifecycle core, with provider stubs. Nothing imports it yet.

  • CastProvider interface; Target/Session/MediaMeta/NowCasting types; narrow MPD interface
  • Manager: concurrent discovery (fan-out, dedupe by (Kind,ID), one dead/slow provider can't block the rest), single-session lifecycle
  • StartCast: snapshot outputs → enable httpd (+ disable others when cast_exclusive) → persist session → device Play, with rollback on any failure
  • StopCast: from in-memory session, on-disk state file, or a discovery fallback (device found playing our stream) — so -cast-stop works with no TUI running
  • Reattach: adopt a persisted session iff the device is still playing our stream URL; discard stale (>24h) / mismatched / gone
  • state.go atomic JSON session file under $XDG_CACHE_HOME/mpdtui
  • stream.go stream-URL derivation (override → httpd port → config → 8000; reject loopback host with LAN-IP fallback)
  • config.go reads ~/.config/mpdtui/config directly (own keys, no internal/config change)
  • cli.go List/Start/Stop headless entrypoints
  • chromecast / homeassistant / dlna providers — interface-conformant stubs; real protocols land in follow-ups

Tests

12 internal tests: discovery, full lifecycle, rollback, re-attach match/mismatch/staleness, URL derivation, target matching.

Design constraint

All casting logic stays in this one package; existing files get only tiny hooks later.

🤖 Generated with Claude Code

Introduces internal/cast, which will send MPD's audio to external players
(Chromecast, Home Assistant media_player, DLNA/UPnP). Model is "sender
only": mpdtui enables MPD's httpd output, points the device at that stream
URL, then steps back -- MPD stays the source of truth and the device keeps
playing after mpdtui exits.

This commit is the interface + lifecycle core, with provider stubs:

- CastProvider interface; Target/Session/MediaMeta/NowCasting types
- Manager: concurrent discovery (fan-out, dedupe by (Kind,ID), one dead
  or slow provider can't block others), single-session lifecycle
- StartCast: snapshot outputs -> enable httpd (+ disable others when
  cast_exclusive) -> persist session -> device Play, with rollback on
  any failure
- StopCast: works from in-memory session, the on-disk state file, or a
  discovery fallback (device found playing our stream) -- so -cast-stop
  works with no TUI running
- Reattach: adopt a persisted session iff the device is still playing our
  stream URL; discard stale (>24h) / mismatched / gone
- state.go: atomic JSON session file under $XDG_CACHE_HOME/mpdtui
- stream.go: stream-URL derivation (override -> httpd port -> config ->
  8000; reject loopback host with a LAN-IP fallback)
- config.go: reads ~/.config/mpdtui/config directly (own keys, no
  internal/config change)
- cli.go: List / Start / Stop headless entrypoints + name/ID matching
- chromecast/homeassistant/dlna providers: interface-conformant stubs
  (errNotImplemented); real protocols land in follow-up commits

12 internal tests cover discovery, the full lifecycle, rollback,
re-attach match/mismatch/staleness, URL derivation and target matching.
Nothing imports internal/cast yet.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JBJdG8Qenand5i16WT6BHG
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant