- "Automatic" gamepad type resolves to the virtual Steam Deck pad on Deck
hardware (env SteamDeck / DMI Jupiter|Galileo): the built-in 28DE:1205
identity is invisible at Hello time — the Valve HIDAPI drivers run
in-session only and Steam Input shadows the pad with its virtual X360 —
so auto always fell through to Xbox 360. "steamdeck" is now also
selectable in Settings.
- Chrome-less launches flatten the window CSS (border-radius/box-shadow)
and fullscreen at startup: gamescope never ACKs the xdg fullscreen
state, so adwaita kept the floating-CSD rounded corners + shadow
visible over the stream.
- Gaming-Mode --connect launches quit on session end, so Steam ends the
"game" and the Deck returns to Gaming Mode — previously the app popped
to its own hosts page, stranding the user fullscreen and making the
escape chord read as broken.
- The capture hint is controller-aware; the chromeless hint teaches the
hold-chord ("hold L1+R1+Start+Select to leave") and a quick chord press
re-flashes it.
- Colour bisect for the reported off-colours on the VAAPI dmabuf path:
graphics offload defaults OFF under gamescope (a subsurface hands the
NV12 CSC to the compositor), PUNKTFUNK_OFFLOAD=1|0 overrides, and each
colour-signaling change logs whether GDK accepted the BT.709-narrow
color state (fallback = GDK's BT.601 dmabuf default).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
punktfunk — Linux client
The native Linux app for streaming a punktfunk host to your desktop, laptop, or Steam Deck. It's a clean GTK4/libadwaita app that finds hosts on your network, pairs with a PIN, and puts a low-latency stream on glass at your display's own resolution and refresh rate.
Built in Rust, it links the shared punktfunk-core directly (no C ABI) and speaks the fast
punktfunk/1 protocol — QUIC control plane, GF(2¹⁶) FEC + AES-GCM data plane.
Features
- Zero-copy hardware decode — FFmpeg VAAPI decode → DRM-PRIME dmabuf →
GdkDmabufTexture(Tier-1 zero-copy on Intel and AMD), with an automatic software-HEVC fallback on NVIDIA or when VAAPI is unavailable. - Your display's native mode — the host builds a virtual output at exactly your WxH@Hz; no scaling, no letterboxing. Steady 60 fps at 1080p60, ~6 ms capture→decoded on the LAN.
- Audio both ways — PipeWire playback with a jitter ring, plus mic uplink to the host.
- Full controller support — SDL3 gamepads with rumble and DualSense fidelity (lightbar, player LEDs, touchpad, motion, adaptive-trigger replay). Click-to-capture keyboard and mouse, with a release chord (Ctrl+Alt+Shift+Q) and focus-loss release.
- Find hosts automatically — mDNS discovery lists hosts on your LAN; saved hosts persist. First connect does a one-time SPAKE2 PIN pairing (or TOFU on trusted LANs), then reconnects on a pinned identity.
- Per-host speed test to pick a bitrate, plus compositor and mode preferences in Settings.
- Game library browser (experimental, off by default) — "Browse library…" on a saved host shows its games (Steam + custom) as a poster grid; click one to launch it in the session. Fetched from the host's management API over mTLS — paired devices are authorized by their certificate, no extra host setup.
Get it
Most people should install a package rather than build from source:
| Distro | Install |
|---|---|
| Flatpak (any distro, Steam Deck) | io.unom.Punktfunk — see packaging/flatpak |
| Ubuntu / Debian (apt) | sudo apt install punktfunk-client (after adding the repo) |
| Fedora / Bazzite (rpm) | rpm-ostree install punktfunk-client |
| Arch (PKGBUILD) | see packaging/arch |
Per-device install steps and pairing walkthrough: docs.punktfunk.unom.io/docs/install-client.
Build & run from source
Requires GTK ≥ 4.16, libadwaita ≥ 1.5, FFmpeg 7 or 8 (with VAAPI for hardware decode), PipeWire, and SDL3 (with hidapi) development packages.
# from the repo root
cargo run -p punktfunk-client-linux # launch the app
cargo run -p punktfunk-client-linux -- --discover # list hosts on the LAN, then exit
cargo run -p punktfunk-client-linux -- --connect HOST[:PORT] # skip the host list and connect
The binary is named punktfunk-client. Handy flags: --connect host[:port] (start a session
immediately — for scripting and the Steam Deck launcher), --discover [secs], and
--pair <PIN> --connect host[:port] (run the pairing ceremony headlessly), and
--library host[:mgmt_port] (print a host's game library headlessly). Force a decoder with
PUNKTFUNK_DECODER=software|vaapi.
Layout
src/
main.rs · app.rs entry point, GTK application, primary menu, CSS
cli.rs CLI paths (--connect, headless --pair, screenshot scenes)
ui_hosts.rs host card grids (saved + discovered) · add-host dialog · banner
ui_library.rs game-library poster grid (per-host, launches titles)
ui_trust.rs TOFU / PIN-pairing / request-access dialogs
ui_settings.rs resolution · refresh · decoder · bitrate · compositor · mic
ui_stream.rs the stream window (GtkGraphicsOffload present) + input capture
launch.rs · session.rs session launch/UI glue; lifecycle over the NativeClient connector
video.rs FFmpeg VAAPI / software decode → dmabuf / texture
audio.rs PipeWire playback + mic uplink
gamepad.rs · keymap.rs SDL3 controllers + feedback; keyboard VK mapping
trust.rs · discovery.rs persistent identity, known hosts + settings, mDNS browse
library.rs mgmt-API library client (mTLS + pinned fingerprint, art proxy)
tools/screenshots.sh store screenshot capture (app self-capture; Xvfb fallback)
Related
- Documentation — quick start, pairing, troubleshooting
- Steam Deck plugin — launches this client fullscreen in Gaming Mode
- Project README — the host, the other clients, and how it all fits together