Files
punktfunk/clients/session
enricobuehler 5be494f490 merge: bring main into the pad-audio branch
Main had moved 34 commits past the merge-base and 13 files had diverged.
Resolving now rather than later, since the force-feedback sweep work is landing
in the same files.

Five conflicts needed hand resolution. Four were "each side added something
different" and keep both: the Forwarding and PadAudioPrefs control variants with
their handlers and setters (pf-client-core/gamepad.rs), both of the session's
pre-attach declarations (forwarding first, so slots still declare their
pad-audio caps at open time), main's WiredPlan/fingerprint alongside the
branch's pad_render_ids (audio_control.rs), and main's judge_default signature
(wasapi_cap.rs).

wiring_plan.rs was not mechanical. Main's 652abeb3 added a flagged last-resort
loopback tier; the branch had added a fifth `plan` parameter excluding pad
endpoints from every role. Taking either side alone loses the other, and
combining them carelessly is worse than both: the new last-resort tier would
happily select the pad's own speaker endpoint, which is stamped "DualSense
Wireless Controller" with no virtual marker precisely so games read it as the
pad's speaker — routing the entire desktop mix into the controller's voice
coils. The branch's exclusion shadows `renders` before any tier runs, so the
last resort inherits it; `a_pad_is_never_the_last_resort` pins that, including
that a pad-only candidate set stays honestly unsatisfiable rather than falling
back onto the coils.

Verified: clippy -p punktfunk-host -p pf-client-core --all-targets --locked
-D warnings = 0; pf-client-core 93/93; punktfunk-host 387 passed with only the
known-environmental gamestream sender_delivers_batches UDP-loopback flake;
wiring_plan 21/21; fmt clean.

NOT verified: audio_control.rs and wasapi_cap.rs are cfg(windows), so neither
the Linux container nor xcheck.sh compiles them. Those two resolutions have had
review only and need the Windows runner before this merges.
2026-08-03 19:11:26 +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).

This binary is deliberately dumb: a renderer the front-ends call INTO — the GTK shell (punktfunk-client), the WinUI shell, and the punktfunk CLI all spawn it through the same brain (pf_client_core::orchestrate), which resolves policy (profiles, settings, wake) and hands the result down, normally as a --resolved-spec file. It reads the shared stores only as the compat fallback for a bare hand-launched invocation.

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), so enrolling on either side makes the other work; this binary never connects to a host it has no pinned fingerprint for (--fp HEX overrides the store).

Pairing is punktfunk pair <host> — the CLI, which ships alongside this binary in every package and needs no window and no toolkit either. punktfunk-session --pair still works for one release (someone's provisioning script calls it today) but prints a deprecation notice: pairing is a trust ceremony and belongs to the brain, not a renderer.

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|fifo|immediate|fifo_relaxed (default MAILBOX, FIFO where the surface offers no MAILBOX — AMD on Windows), 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).