-
v0.9.1
Stableaudit / bun-audit (push) Successful in 13sci / web (push) Successful in 53sci / docs-site (push) Successful in 55sapple / swift (push) Successful in 1m10saudit / cargo-audit (push) Successful in 2m41sci / bench (push) Successful in 5m39sandroid-screenshots / screenshots (push) Successful in 3m3swindows / build (aarch64-pc-windows-msvc) (push) Successful in 58swindows / build (x86_64-pc-windows-msvc) (push) Successful in 1m15sdecky / build-publish (push) Successful in 17sflatpak / build-publish (push) Failing after 2m17sandroid / android (push) Successful in 12m47sarch / build-publish (push) Successful in 11m58swindows-host / package (push) Successful in 8m53sdeb / build-publish (push) Successful in 12m37sci / rust (push) Successful in 24m59srelease / apple (push) Successful in 12m36swindows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 2m5sweb-screenshots / screenshots (push) Successful in 2m44swindows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 2m18slinux-client-screenshots / screenshots (push) Successful in 8m34sapple / screenshots (push) Successful in 5m41srpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 13m48srpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 21m19sdocker / deploy-docs (push) Successful in 22sdocker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 9sdocker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 7sdocker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 7sdocker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 8sdocker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 8sreleased this
2026-07-10 08:49:10 +00:00 | 3 commits to main since this releaseWire-compatible with 0.9.0 and 0.8.x — existing pairings and clients keep working. The new gamepad-state snapshots are negotiated (
HOST_CAP_GAMEPAD_STATE): if either end is older, the previous per-transition input path runs unchanged.Android — pre-13 devices work again (0.9.0 regression)
0.9.0's stats-HUD display stage hard-linked an NDK symbol that only exists on Android 13+, so the native library failed to load on every Android < 13 device — "Identity unavailable: …NativeBridge", a dead pair button, and no discovery. The callback is now resolved at runtime: Android 13+ keeps the HUD's display stage, older devices simply don't show that one row — and everything works again. A new CI guard fails the APK build if the native library ever imports a symbol beyond the app's API-28 floor, so this class of regression can't ship twice.
GNOME hosts — one Approve admits exactly one connection
A retrying unpaired client parks one connection per knock, and a single console Approve admitted all of them — observed in the field as three virtual monitors created within microseconds and a gnome-shell segfault that dropped the box to the GDM greeter until reboot. Fixed at every layer: per-knock generations admit exactly one connection (superseded knocks close cleanly), all Mutter monitor mutations are serialized process-wide (concurrent rebuilds are what crash the shell), a stale session environment no longer routes connects into a dead session, and an opt-in
PUNKTFUNK_RECOVER_SESSION_CMDhook (e.g.sudo -n systemctl restart gdm) can revive a crashed desktop on the next connect — debounced, with the client told to retry.Windows hosts — two identical GPUs stream again
On a twin-GPU box (twin RTX 4090s in the field report) the virtual-display frame ring could open on the other twin than the driver was pinned to — the max-VRAM tie followed DXGI enumeration order, which follows the primary display that the virtual-display flow itself moves mid-session. Every session then died in a texture-open retry loop. The host now reads the render adapter the driver actually reports and rebinds the ring onto it, and GPU inventory ordering is stable for the boot instead of tracking the primary display. Single-GPU streaming verified unchanged.
Input — held gamepad state is rock-solid
A held trigger could jitter mid-game. Two causes, both fixed: Android folded joystick events from every device into one pad state — a DualSense's motion-sensor sibling node reports all pad axes as 0, flapping a held trigger on every event interleave; the mapper now qualifies real gamepads and pins to one device. Underneath, pad state rode per-transition events over unreliable datagrams, so one dropped packet corrupted held state until the next change — gamepad input now travels as idempotent, sequence-gated snapshots (refreshed at 100 ms) on every client when both ends run 0.9.1.
Security
Findings from a repo security review, all addressed:
- A sliding-window anti-replay filter on the (already AEAD-authenticated) data-plane sequence — replayed input datagrams are now dropped instead of left to the LAN/VPN trust assumption.
- The mTLS client key is written 0600 and the config dir 0700 on Unix (was world-readable at the umask default); existing stores are re-locked on load.
- The web console's post-login redirect now enforces same-origin, closing an open redirect the old prefix check missed.
- Supply chain: the FFmpeg DLLs bundled into the signed Windows installer are SHA-256-pinned (were fetched from a rolling tag unverified), and PR build jobs that share runner labels with the signing jobs gained a fork guard.
Stats overlay — three tiers on every platform
The Android HUD's ladder ships everywhere: Off → Compact (one glass pill: fps · e2e ms · Mb/s) → Normal (mode, e2e p50/p95, loss counters) → Detailed (decoder path, HDR tag, per-stage latency equation). Cycle with the three-finger tap or ⌃⌥⇧S on Apple platforms, Ctrl+Alt+Shift+S on Linux/Windows/Deck; tier pickers in every settings UI. On Apple the overlay is now a single glass card that morphs between tiers and sits concentric with the physical display corner on iOS.
Apple — experimental stage-3 presenter
An opt-in present-pacing mode (Settings → Display) that keeps at most one presented-but-undisplayed frame in flight, eliminating a hidden display-queue latency measured at ~29–30 ms on 120 Hz ProMotion devices. Live-verified holding 120/120 fps. Stage 2 remains the default while stage 3 soaks;
PUNKTFUNK_PRESENTER=stage2|stage3for A/B runs.Housekeeping
- Repo-wide docs sync — READMEs and docs-site now describe the code as shipped (decode chains, shell/session split, new env knobs, GNOME per-client scaling ✅).
- The flatpak CI job now retries every network fetch and prefetches all sources before the long compile — release and canary flatpaks build reliably on a busy runner.
Downloads