-
v0.11.0
Stableci / web (push) Successful in 45sci / docs-site (push) Successful in 51sci / bench (push) Successful in 6m6swindows-host / package (push) Successful in 8m11sandroid-screenshots / screenshots (push) Successful in 4m13swindows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 3m9sdecky / build-publish (push) Successful in 17swindows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 4m7sci / rust (push) Successful in 18m6sandroid / android (push) Successful in 11m58sarch / build-publish (push) Successful in 12m2sdocker / deploy-docs (push) Successful in 9sdocker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 7sdocker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 9sdocker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 10sdocker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 9sdocker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 9sflatpak / build-publish (push) Failing after 8m14sapple / swift (push) Successful in 5m27slinux-client-screenshots / screenshots (push) Successful in 7m23sdeb / build-publish (push) Successful in 11m57sweb-screenshots / screenshots (push) Successful in 2m49srpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 16m49srpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 16m45srelease / apple (push) Successful in 28m50sapple / screenshots (push) Has started runningreleased this
2026-07-14 22:14:13 +00:00 | 9 commits to main since this releaseWire-compatible with 0.10.x — no protocol or ABI change (
WIRE_VERSIONstays 2, the native C ABI stays v6). This is a throughput + controllers release: the transport's measured ceiling moves from ~1.5 to ~4.8 Gbps wire, Automatic bitrate now finds the link's real capacity and rides it without keyframe spikes, four new controller identities land across the clients and both hosts, and the long-standing "rumble and adaptive triggers never work with a Linux host" is root-caused and fixed. The new gamepad kinds ride additiveGamepadPrefwire bytes an older host simply folds onto an existing pad type — nothing touches the handshake, so any 0.10.x host/client pair keeps working with no re-pairing.Multi-gigabit transport
The receive path was rebuilt for the new ceiling — ~1.5 → ~4.8 Gbps wire between capable endpoints:
- ARMv8 hardware AES-GCM — every aarch64 client (Apple Silicon, iPhone/iPad, Android, Steam Deck OLED…) was running software crypto; hardware AES was the single biggest wall. Large frames additionally seal on two AES-GCM lanes so encryption no longer serializes a big AU behind one core.
- Zero-copy pooled reassembly — shards land at their final access-unit offset on arrival; no per-frame reassembly copy, no per-block allocation.
- FEC encoder reuse — cached erasure codecs + pooled parity buffers; per-block engine setup drops out of steady-state frames (Moonlight wire parity pinned byte-exact).
- Pace-aware send chunking — pace chunks scale 16→64 packets with the rate so a ≥1 Gbps frame keeps honest inter-chunk sleeps (and ~4× fewer syscalls) instead of collapsing into an unpaced blast; the auto microburst cap scales to a quarter of the frame (
PUNKTFUNK_PACE_BURST_KBpins an absolute override). - Reordering no longer reads as packet loss — early-FEC-reconstructed shards that then arrive are netted out of the loss estimate, so plain reordering can't inflate LossReports, over-size adaptive FEC, or permanently end the bitrate controller's climb.
- Observability —
PUNKTFUNK_PERF=1prints receive-path stage timing + frame-jitter percentiles; athroughput-sweepscript and headless-accurate probe sweeps ship in-tree.
Automatic bitrate that finds your link
Automatic now probes the link's capacity and slow-starts up to a measured ceiling instead of sitting on a fixed default — and quality steps got dramatically cheaper: in-place encoder rate reconfigure (NVENC
nvEncReconfigureEncoderon Linux + Windows, AMF dynamic properties, Vulkan rate-control update) means an ABR adjustment retargets the encoder mid-stream with no IDR. Verified on hardware: 20→60→10 Mbps live with zero keyframes. Backends without in-place support keep the old rebuild-on-next-IDR path;punktfunk-probe --rebitrate KBPS:SECSvalidates a host headlessly.Four new controller identities
Clients now declare what's physically in your hands, and the host builds exactly that:
- DualSense Edge — Linux UHID + Windows UMDF; the four back paddles land on the Edge's native button slots instead of being folded away or dropped.
- Nintendo Switch Pro Controller — Linux UHID via
hid-nintendo; Android also maps the Switch 2 Pro Controller and a paired Joy-Con 2 onto it. - Classic Steam Controller — Linux UHID via
hid-steam, dual-trackpad layout intact. - Steam Deck on Windows hosts — a Steam-Input-promoted UMDF virtual Deck (the
&MI_02interface synthesis Steam's driver filters on), with a Steam-accepted unit serial so the controller name renders clean.
Under the hood all virtual-pad backends moved onto one shared, unit-tested slot/lifecycle/feedback skeleton (
PadSlots+UhidManager) — one place for arrival routing, unplug sweeps, heartbeats, and feedback dedup.Rumble + adaptive triggers on Linux hosts — root-caused and fixed
Game feedback (rumble, DualSense adaptive triggers, lightbar, player LEDs) worked from Windows hosts but effectively never from Linux ones. The capture code was proven correct on real hardware (new on-box tests drive every chain the way a game would); the real causes were access and identity:
- hidraw access — Steam/SDL drive a DualSense's triggers/lightbar exclusively over hidraw, and without it Steam demotes the pad to a generic evdev device, losing its rumble handling too. The host udev rules now grant the
inputgroup the virtual pads' hidraw nodes for every identity we create — no longer dependent on the distro's steam-devices rules plus seat-session ACLs that a headless/dedicated streaming session never gets. - Per-pad serials, both hosts — every virtual DualSense/DS4 presented one hardcoded pairing MAC (and on Windows, one USB serial string); SDL/Steam dedup controllers by serial, so a second pad could be merged into the first. Serials now carry the pad index on Linux (UHID pairing replies) and Windows (UMDF feature reports +
HidD_GetSerialNumberString). - No more 5 s stalls — the UHID PlayStation backends ack
SET_REPORTinstead of letting writers hang into the kernel timeout.
Three permanent on-hardware tests pin the whole surface: DualSense evdev-FF + raw hidraw output report (rumble, lightbar, LEDs, and both adaptive-trigger blocks verbatim), uinput X-Box FF upload→mix→stop-on-erase, and usbip Deck rumble via the controller interface.
Client quality-of-life
- On-screen keyboard mid-stream — a three-finger swipe up/down shows/hides the device keyboard on iOS and Android (trackpad/pointer modes); scrolling is now an exactly-two-finger gesture on mobile.
- "Rumble on this phone/iPhone" — opt-in: pad-0 rumble mirrors onto the device's own vibration motor, for motor-less clip-on pads.
- Linux client decoder order —
autois now device-aware: Vulkan Video first on NVIDIA and all AMD (it outperforms VAAPI on RADV, and the Deck's VanGogh chroma-fringes over VAAPI), VAAPI first on Intel; and a mid-session Vulkan failure streak now demotes to VAAPI instead of software, so a broken Mesa Vulkan path can never strand a box on CPU decode. The GTK settings gain the missing explicit "Vulkan Video" option. - Console (gamepad) UI — a touch-mode setting and request-access pairing: a new device can knock and be approved from the host side without typing a PIN.
- Decky plugin — native-touch controller layout, restructured shortcuts, and store artwork.
Host & platform fixes
- Dedicated gamescope session vs. desktop Steam — launching the dedicated session now frees a desktop-session Steam first (Steam is single-instance; the collision black-screened the game library).
- Headless gamescope env isolation — the managed session no longer inherits a desktop
DISPLAY/WAYLAND_DISPLAY. - NVIDIA hosts warn loudly when a CUDA session runs a build compiled without the direct-SDK NVENC path (which carries the real loss recovery).
- Android TV visibility on Google Play — microphone and Wi-Fi permissions no longer imply required hardware features, so TV devices (e.g. Philips OLED TVs) stop being filtered from the listing.
Downloads