Both host and viewer hardcoded presets::N0, pinning every session to the
bundled relays (which on iroh rc.0 are the canary-grade defaults). Add a
shared common::endpoint::bind() that keeps N0's DNS discovery + crypto but
swaps in a RelayMode::Custom single-relay map when --relay (or the
PIXELPASS_RELAY env var, so GUI children inherit it) is set.
Lets users point at a self-hosted relay or staging today; the production
relays (*.relay.iroh.network) speak a newer protocol that rc.0 rejects
("invalid iroh-relay version header"), so they only become usable — and
the default — after an iroh GA bump. Verified: override connects cleanly
through staging; bad URLs are rejected before any network work.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds common/output.rs: a process-global JSON-lines emitter for
non-interactive front-ends. With --output json, host and viewer emit one
JSON object per line on stdout (ticket, host_info, viewer_count, capture
start/stop, viewer_refused, connected), flushed per line; the human banner
and tracing logs stay on stderr so the two never interleave. No-op when the
flag is absent, so call sites emit unconditionally.
This is the shell-out counterpart to an in-process event channel: the
upcoming --gui front-end re-execs this binary as `pixelpass --host
--output json` and parses these lines to drive its window. serde_json was
already in the tree from the bandwidth pre-flight.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
First-run host launch now offers a one-time upstream measurement
against speed.cloudflare.com/__up via ureq (~5 MB POST, ~5s). The
result lives at ~/.config/pixelpass/config.toml under [bandwidth]
and feeds the default --max-viewers calculation on subsequent runs.
Sticky semantics for the dialog:
- Unmeasured: first-run prompt (Run / Skip)
- Measured / Skipped: silent — never re-prompts
- Failed: ask again on next launch (Retry / give up → Skipped)
`pixelpass --reconfigure` re-runs the test unconditionally for users
whose connection has changed (new ISP, moved house, etc.).
--max-viewers is now Option<u32>. When unset, host startup loads the
saved measurement, runs recommended_max_viewers(safe_mbps, bitrate),
and surfaces the source in the banner: "max viewers : N (auto: X.X
Mbps measured upstream)" — or user-specified / default fallback.
User verified end-to-end on 2026-05-21 16:54 EDT: first-run dialog,
skip path, run path, --reconfigure refresh, and banner integration
all work as expected.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Bare `pixelpass` now opens a dialoguer-driven Host/View menu instead of
going straight to host mode. Host path copies the ticket to the system
clipboard via arboard with silent print-only fallback. View path
prompts for the ticket, then after the local listener binds prompts
mpv-vs-VLC and spawns it detached (setsid + null stdio) so the player
survives pixelpass exiting.
Headless invocations (`pixelpass <ticket>`, `pixelpass --repair`)
unchanged. Per spec at ~/Documents/pixelpass-interactive-mode-spec.md.