Files
punktfunk/clients/session
enricobuehler d0d9bd5bfb feat(resize): mid-stream resolution resize — host hardening (H1–H5) + session-binary Match window (C1)
design/midstream-resolution-resize.md Phase 0 + Phase 1.

Host (Phase 0):
- H1/H5: per-backend Reconfigure acceptance gate — reject for gamescope
  (all sub-modes; a resize must never relaunch the title) and under the
  per-client-mode identity policy (a resize would resolve a different
  display slot). Synthetic stays reconfigurable on purpose (the protocol
  test source; the C-ABI roundtrip test rides it). Plus a 500 ms host-side
  min-interval backstop against Reconfigure spam.
- H2: rollback/corrective ack — the data plane reports the mode actually
  live after a failed rebuild (or a refresh the backend capped) through a
  reconfig_result channel; the control task forwards it as a second
  accepted Reconfigured so the client's mode slot self-corrects.
- H3: live stats mode — SendStats reads a packed AtomicU64 (w|h|hz)
  updated on every switch instead of latching the session-start mode.
- H4: registry::retire(gen) — a mode-switch rebuild force-releases the
  superseded Linux display, so linger/forever keep-alive policies don't
  accumulate kept monitors at stale modes. VirtualOutput carries pool_gen
  (fresh AND reused) and the Pipeline tuple threads it to the switch arm.

Client (Phase 1, default off):
- Settings: match_window policy + persisted last window size; exposed as
  the Resolution tri-state (Native / Match window / explicit) in the Skia
  console, GTK and WinUI settings pages.
- pf-presenter: window opens at the persisted size; Hello mode follows the
  window's pixel size; D2 trigger discipline (400 ms debounce to
  resize-end, ≥1 s spacing, even-floor + ≥320×200 clamp, each distinct
  size requested at most once — covers rejects and host rollbacks) as a
  pure, unit-tested decision; HUD line + title refresh on a switch.
- Session binary wires both --connect and --browse paths; the WinUI shell
  is session-always, so this covers Windows too.

Verified: workspace tests + clippy green; synthetic --remode end-to-end;
live session-binary run (window at persisted 1000×600 → Hello 1000×600@60).
On-glass per-backend matrix (Mutter/KWin/gamescope-reject, keep-alive
accumulation) still pending before any default flip.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 12:53:47 +02:00
..

punktfunk-session

The Vulkan session binary: one stream per invocation in an SDL3 window — no UI toolkit, no widgets, terminal stats. The power-user / gamescope stream client, and the stage-2 presenter of the Linux client re-architecture (punktfunk-planning: linux-client-rearchitecture.md).

punktfunk-session --connect host[:port] [--fp HEX] [--launch id] [--fullscreen] [--stats]
punktfunk-session --browse host[:port] [--mgmt PORT] [--fullscreen]

--browse opens the console game library (the Skia coverflow over the animated aurora) instead of connecting: A launches the focused title as a stream in the same window, session end returns to the library, B quits (Gaming Mode returns). Paired hosts only — pairing is the desktop client / Decky plugin's job. PUNKTFUNK_FAKE_LIBRARY=<file.json> feeds canned entries with no host (portrait paths starting with / load from disk).

Reads the same identity / known-hosts / settings stores as the desktop client (punktfunk-client) — pair there (or via its headless --pair) first; this binary never connects to a host it has no pinned fingerprint for (--fp HEX overrides the store).

Stdout is the machine interface: {"ready":true} after the first presented frame, stats: … once per second while the overlay tier isn't Off (always the full detailed text, whatever the OSD shows; --stats forces the overlay on), one {"error"|"ended": …} JSON line on the way out. Logs go to stderr. Exit codes: 0 clean end, 2 connect failed, 3 trust rejected / pairing required, 4 presenter init failed.

In-stream keys match the desktop client: click captures input (Ctrl+Alt+Shift+Q releases), Ctrl+Alt+Shift+D disconnects, F11 toggles fullscreen; the controller escape chord (L1+R1+Start+Select, hold to disconnect) works the same.

The default build carries the Skia console UI (ui feature): the stats OSD and capture hint render in-window. Ctrl+Alt+Shift+S cycles the OSD tier live — Off → Compact (one line: fps · latency · Mb/s) → Normal (mode + end-to-end percentiles) → Detailed (decoder path + per-stage latency equation); any tier but Off also emits the stdout mirror. --no-default-features is the ~5 MB power-user build — same streaming, stats on stdout only, no Skia anywhere in the dependency tree.

Decode follows the Settings preference (auto: Vulkan Video → VAAPI → software on Linux, Vulkan Video → D3D11VA → software on Windows): FFmpeg's Vulkan Video decoder runs on the presenter's own device where the stack supports it (every vendor, zero copy); VAAPI dmabufs import per-plane elsewhere (D3D11VA textures on Windows); software is the universal fallback. 10-bit Main10 and HDR10 are advertised (VIDEO_CAP_10BIT|HDR): P010 decodes through all three paths, and PQ streams present on an HDR10/ST.2084 swapchain when the desktop offers one (KDE HDR, gamescope) or tone-map in-shader to SDR when it doesn't (PUNKTFUNK_TONEMAP_PEAK tunes the rolloff, default ≈1000 nits). The host still gates the upgrade behind its PUNKTFUNK_10BIT policy.

Debug/bisect knobs: PUNKTFUNK_DECODER=vulkan|vaapi|d3d11va|software, PUNKTFUNK_PRESENT_MODE= mailbox|immediate (default FIFO), PUNKTFUNK_VK_DEVICE=<index> (multi-GPU), and PUNKTFUNK_HW_FAULT=import (fault every VAAPI dmabuf import — proves the three-strike demotion to software on healthy hardware).