47d22b608200fe7028b2100c113fd0b5dff1f0c6
1055 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
47d22b6082 |
fix(host): admit exactly ONE parked knock per Approve — stop crashing gnome-shell, and self-heal dead sessions
ci / docs-site (push) Successful in 55s
ci / web (push) Successful in 1m11s
apple / swift (push) Successful in 1m12s
decky / build-publish (push) Successful in 17s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 13s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 8s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 7s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 6s
ci / bench (push) Successful in 7m3s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 6m57s
windows-host / package (push) Successful in 8m20s
arch / build-publish (push) Successful in 11m48s
deb / build-publish (push) Successful in 12m57s
apple / screenshots (push) Successful in 5m42s
android / android (push) Successful in 17m23s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 19m32s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 17m28s
ci / rust (push) Successful in 25m57s
docker / deploy-docs (push) Failing after 5m44s
A retrying unpaired client parks one QUIC connection per knock, but the delegated-approval waiters were keyed on fingerprint alone — one console Approve resolved ALL of them. Observed live (2026-07-10): an iPad knocked 3x, one Approve admitted three full sessions, three Mutter virtual monitors were created within ~200us plus an ApplyMonitorsConfig, and gnome-shell SIGSEGV'd inside meta_monitor_manager_rebuild — dropping the box to the GDM greeter, unreachable until reboot (GDM auto-login runs once per boot) while the lingering host spammed "RemoteDesktop ... not activatable" libei errors. Four fixes, outermost symptom inward: - Knock generations (native_pairing): note_pending returns a per-knock generation; a re-knock bumps it and wakes the previous waiter, which resolves the new PairingDecision::Superseded (connection closes; the console list is unchanged). An approval records WHICH generation it admitted, so a stale waiter polling only after the pending entry is cleared still loses the tie — exactly one admission, no matter the interleaving. - TOPOLOGY_LOCK (vdisplay/mutter): every Mutter monitor mutation (pre-snapshot -> RecordVirtual -> ApplyMonitorsConfig, and the teardown Stop) is serialized process-wide. Concurrent rebuilds are what segfault the shell (second on-glass crash of this class — the teardown race is already documented in-file), and serialization also keeps wait_virtual_connector's snapshot diff from attributing a sibling's connector. Create timeout 20s -> 45s for lock queueing. - Session-env hygiene (vdisplay): when detection finds NOTHING live, clear the previous connect's XDG_CURRENT_DESKTOP/WAYLAND_DISPLAY retarget. A stale GNOME value kept mutter::is_available() true after the crash, routing explicit-backend connects into the dead session (create timeouts + libei error loops) instead of the crisp "no live graphical session" handshake error. - Opt-in recovery hook (config + punktfunk1): PUNKTFUNK_RECOVER_SESSION_CMD fires (detached via sh -c, debounced to one launch/min) when a client connects while no graphical session is live — e.g. `sudo -n systemctl restart gdm` re-runs auto-login and the client's retry lands in the recovered desktop. The handshake error tells the client to retry. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
c86da1a1ff |
chore(android): silence the two vendored-ndk warnings on every native build
apple / swift (push) Successful in 1m14s
apple / screenshots (push) Successful in 5m38s
ci / web (push) Successful in 45s
ci / docs-site (push) Successful in 50s
windows-host / package (push) Successful in 8m30s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 2m16s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 2m17s
decky / build-publish (push) Successful in 16s
ci / bench (push) Successful in 6m46s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 11s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 17s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 12s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 1m5s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 11s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 11s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 1m21s
android / android (push) Successful in 12m38s
arch / build-publish (push) Successful in 14m7s
deb / build-publish (push) Successful in 15m11s
docker / deploy-docs (push) Successful in 9s
ci / rust (push) Successful in 22m50s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 13m7s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 15m7s
The vendored ndk 0.9.0 warned twice per Android build: an unnecessary `std::ptr::` qualification in input_queue.rs (the crate opts into unused_qualifications) and an unused `Result` import in media_format.rs — unused only because its sole consumers are #[cfg(feature = "api-level-29")] methods our default-feature build compiles out, so the import is now gated the same way (both feature configurations stay warning-free). Vendor-patch inventory in the workspace Cargo.toml updated to stay honest. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
d0faebf582 |
chore(release): bump workspace version to 0.9.0
audit / bun-audit (push) Successful in 11s
ci / web (push) Successful in 51s
apple / swift (push) Successful in 1m10s
ci / docs-site (push) Successful in 1m9s
audit / cargo-audit (push) Successful in 2m36s
ci / bench (push) Successful in 5m53s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 3m8s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m2s
android-screenshots / screenshots (push) Successful in 2m58s
decky / build-publish (push) Successful in 18s
ci / rust (push) Successful in 17m43s
release / apple (push) Successful in 9m55s
apple / screenshots (push) Successful in 5m56s
arch / build-publish (push) Successful in 14m2s
android / android (push) Successful in 15m44s
deb / build-publish (push) Successful in 15m15s
web-screenshots / screenshots (push) Successful in 2m45s
linux-client-screenshots / screenshots (push) Successful in 8m20s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 13m58s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 13m57s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 42s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 9m30s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 9s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 11m34s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 13s
flatpak / build-publish (push) Successful in 7m14s
windows-host / package (push) Successful in 8m1s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 54s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 1m17s
docker / deploy-docs (push) Successful in 14s
Release 0.9.0 — the Windows client grows up, bitrate goes adaptive, and the console shell arrives. The headline: Windows now runs the same Vulkan session client as Linux (session-always), with a single-window handoff from the shell, a shared settings store, a game library page, and D3D11VA hardware decode slotted into the chain (vulkan → d3d11va → software) — plus polish like hiding the local cursor while captured and a Shortcuts help screen. Alongside it, adaptive bitrate lands end to end: set to Automatic, the client's controller re-targets the host encoder mid-stream (rebuild-in-place, the fresh encoder opens on an IDR) instead of riding a fixed rate into congestion. And the console UI grows into a full gamepad shell — host list, PIN pairing, settings, on-screen keyboard, screen transitions. Apple clients gain AV1 decode (hardware-gated advertisement), user-configurable VRR, Game Mode across platforms, cross-client shortcuts, an opt-in V-Sync, and a presenter rework; a stream error now returns to windowed like a disconnect does. Codec selection is real everywhere: clients advertise what their GPU actually decodes and the host picks accordingly — and AV1 encode on Windows NVENC actually opens now: the init stamped HEVC HIGH tier and (on 10-bit sessions) the HEVC Main10 profile GUID onto the AV1 config, so every AV1 session died at the encoder with INVALID_PARAM. AV1 now rides its preset defaults where they are the only accepted values (Main tier, autoselect level — 0 means Level 2.0 on AV1, not autoselect), sets its bit depths on its own config, and a rejected split-encode mode falls back cleanly from AUTO too. Verified live: 10-bit AV1 macOS → RTX 4090. Android's stats HUD headline becomes true capture→displayed via OnFrameRendered, custom resolutions land in both Android UIs (typed W×H in touch settings, kept selectable on the pad — the Apple pattern), and the 3-finger stats tap actually fires now (the two-finger scroll centroid read the third finger's landing as a scroll notch and disqualified the tap). The console shell gates input the instant A starts a Wake-on-LAN connect — the "Waking…" card shows immediately instead of the cursor drifting ungated until the stream abruptly appeared. The web console gets a favicon, Punktfunk-cased branding, a save toast for the auto-saved display policy, and a stop-session button that only goes red when there is a session to stop. Reliability work on the host closes out a long field investigation into periodic virtual-display stutter: the IDD capture path no longer runs CCD display queries on the capture thread (a dedicated poller samples them, measures them, and warns when something is holding the Windows display-config lock), transient descriptor blips can no longer tear the ring down (last- known-good + a two-strikes debounce), and a metronomic keyframe-recovery cycle now names itself in the host log instead of hiding in "nothing in the logs". The GPU inventory filters out IddCx ghost adapters — every host used to list its render GPU twice (pf-vdisplay's adapter mirrors the GPU's whole DXGI identity), with the picker offering a dead twin. Also: per-client display scaling on GNOME hosts (Mutter virtual monitors), the shared-VkQueue race + swapchain recreate-in-use fix behind the intermittent device-lost stream killer, per-family MTU shard sizing (1388 over IPv6 — the v6 blackhole gate), mDNS discovery pinned to IPv4 on every client, reachability-probed presence with shareable Decky host management, --no-mdns/--pairing-pin for headless testing, and an offline-flatpak build fix. The [workspace.package] version (inherited by every crate via version.workspace) is the release being cut; the 14 workspace entries in Cargo.lock and the api/openapi.json info.version are refreshed to match (CI builds --locked). Canary derives from the tag as minor+1 of the latest stable (scripts/ci/pf-version.sh), so cutting 0.9.0 advances canary to 0.10.0. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>v0.9.0 |
||
|
|
968a9c66c1 |
fix(host): NVENC AV1 sessions actually open — stop stamping HEVC config onto the AV1 union
Every AV1 session died at initialize_encoder with NV_ENC_ERR_INVALID_PARAM
("rejected even at the floor bitrate") while negotiation and the session plan
looked healthy. Live-bisected on the RTX 4090 box against a 10-bit macOS AV1
session; three independent poisons, all HEVC-isms applied across the codec
union:
- Unconditional `hevcConfig.tier = 1`: NVENC's AV1 encoder is Main-tier only,
and the same write scribbled HEVC offsets into h264Config too. Tier/level
are now per-codec; AV1 deliberately writes NEITHER — its preset defaults are
the only accepted values, and `level = 0` is NOT autoselect on AV1 (that's
Level 2.0 in the AV1 enum — it pins the stream to the smallest level and
rejects any real mode). Explicit `idrPeriod = INFINITE` is likewise rejected;
with PTD enabled the driver follows the infinite gopLength, matching the
proven HEVC pattern of never touching idrPeriod.
- The 10-bit branch was gated on bit depth only, never codec: it stamped
NV_ENC_HEVC_PROFILE_MAIN10_GUID + hevcConfig bitfields onto AV1 (the killer
for HDR/10-bit clients). AV1's Main profile covers 10-bit natively; it now
sets output/input depth on its own config.
- The split-encode fallback only retried FORCED modes, so an AUTO-mode
rejection masqueraded as a bitrate cap and failed the whole clamp search.
Any non-disabled mode now retries once with split disabled. (Also corrects
the split-mode log legend: NV_ENC_SPLIT_DISABLE_MODE is 15, not 0.)
The AV1 RFI DPB write (maxNumRefFramesInDPB = 5) survives the bisect and
stays. Verified end to end: 10-bit AV1, macOS client → RTX 4090 host.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
8743f63406 |
polish(web): favicon, Punktfunk casing, display-save toast, idle stop button
- Favicon: the brand-mark lens SVG at /favicon.svg, linked from the root head. - Branding: user-facing "punktfunk" → "Punktfunk" (tab title, app_name, pairing prose, the logo aria-labels/SVG titles) — protocol identifiers (punktfunk/1, _punktfunk._udp, binary/module names) stay lowercase. - The display policy auto-saves on every preset pick / field edit with no signal; mount @unom/ui's sonner Toaster in the root and fire a success toast from the save funnel's onSuccess (new i18n key, en + de). First toast usage in the console — errors stay inline as before. - The stop-session button rendered destructive-red even with nothing to stop: variant switches to the muted `secondary` while no session is active. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
f470858110 |
fix(console-ui): gate input the instant A starts a wake — optimistic Waking card
Pressing A on an offline-but-wakeable host only queued ConsoleCmd::Wake; the service thread round-trips its first WakeStatus ~100 ms–1 s later, and until then the shell had no modal state — navigation kept flowing, the cursor drifted (e.g. onto Add Host), the arriving status then froze the UI wherever it sat, and for a fast wake the "Waking…" card was never rendered before the stream abruptly appeared. Every other input-initiated async path already gates synchronously (connect via `connecting`, pair via `busy`, screen pushes via `Motion`); the wake branch was the unique offender. `apply` now raises an optimistic WakeStatus placeholder in the same call that forwards the command — the Waking card shows immediately and the wake modal gate engages on the very next event. `sync` keeps the placeholder alive until the service's first real status supersedes it (tracked via `wake_optimistic`), and B-cancel clears both. Regression test replays the exact A-then-navigate sequence. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
03a2fabff1 |
feat(clients/android): custom resolutions in both settings UIs
The Settings model always carried arbitrary width/height (0 = native) end to end — only the two UIs' preset lists gated it. Mirror the Apple client's pattern: the touch Resolution dropdown gains a "Custom…" row revealing numeric W×H fields (seeded from the current effective size, coerced even on commit, capped at 8192 — the host's encode.rs stays the validation authority), and the gamepad screen surfaces a stored custom size as a leading "Custom · W × H" choice instead of silently snapping it to Native — a pad can keep a custom size, it just can't type one. Custom-ness is detected from the stored size itself (no persisted flag), so it can never disagree with what's saved. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
3952672873 |
fix(clients/android): 3-finger stats tap — re-anchor the scroll centroid on pointer-count changes
The two-or-more-finger scroll path measured its centroid across a VARYING pointer count: real fingers never land (or lift) in the same input frame, so the 2→3 transition moved the centroid far past SCROLL_DIV, emitted a phantom wheel tick to the host, and set `moved` — which disqualified the not-moved tap classification and made the advertised 3-finger stats-cycle tap unreachable on real hardware (two-finger right-click survived only because its anchor never crossed a count change). Re-anchor whenever the finger count changes; genuine two-finger scrolling is measured between same-count frames exactly as before. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
a1285dfa13 |
fix(host): IDD capture immune to display-config stalls/flaps + metronomic-recovery self-diagnosis
ci / docs-site (push) Successful in 1m7s
ci / web (push) Successful in 1m8s
decky / build-publish (push) Successful in 32s
android / android (push) Failing after 2m38s
windows-host / package (push) Failing after 11m13s
ci / rust (push) Successful in 22m2s
ci / bench (push) Successful in 5m36s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 10m9s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 12m15s
deb / build-publish (push) Successful in 15m40s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 12m41s
apple / swift (push) Successful in 1m12s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 21s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 12s
arch / build-publish (push) Successful in 14m26s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 12m11s
apple / screenshots (push) Successful in 5m30s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 12m52s
docker / deploy-docs (push) Failing after 6m14s
Field report (0.8.2→0.8.4): metronomic stutter every ~3.7-4 s, each event a double-jolt, on ALL clients — and the same box stuttered on Apollo (virtual display) but not Sunshine (physical). The disturbance class is host-side display-topology events / display-poller software (SteelSeries-GG class, Apollo #480/#358/#368) hitting the virtual-display path. Three changes make the IDD path resilient to it and self-diagnosing: - DescriptorPoller: the display-descriptor CCD queries (QueryDisplayConfig twice per sample) serialize on the session-global display-config lock, which topology churn and display-poller software can hold for tens-to- hundreds of ms. Polled inline, that stall landed ON the capture/encode thread 4x/s — a periodic frame hitch, invisible in any log. A dedicated thread now samples every 250 ms and publishes a snapshot; the capture loop pays one uncontended mutex read, and a sample slower than 50 ms logs a rate-limited warn — the stall is measured instead of streamed. - Flap immunity: advanced_color_enabled returns Option (None on a failed query or the target briefly missing from the active paths during a re-probe) and the poller keeps last-known-good per field — a transient no longer reads as "HDR off", which used to cost an HDR session TWO spurious ring recreates (false, then true again a poll later). On top, a two-strikes debounce: only two consecutive samples agreeing on the same new descriptor trigger the recreate; a real "Use HDR" flip or game mode-set still lands in ~1/2 s. - RecoveryCadence: served recovery IDRs within 1.5 s coalesce into one event (a double-jolt's paired IDRs count once); four consecutive events evenly spaced (±20%) warn "client keyframe recoveries are METRONOMIC — a periodic host/display disturbance, not random network loss" with the measured period (re-warn ≤ every 30 s) — so an affected host self-diagnoses in its own log / web console instead of reporting "nothing in the logs". Unit tests include the field report's exact double-jolt-pair schedule. Verified: host tests + clippy clean on Linux and on the RTX box (211/211, --features nvenc). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
c19c87c435 |
fix(host): filter IddCx ghost adapters out of the Windows GPU inventory
pf-vdisplay's IddCx adapter enumerates as a perfect DXGI twin of the GPU it renders on — same Description, VendorId/DeviceId/SubSysId, even DedicatedVideoMemory; only the LUID differs (verified on the RTX box: the twins were byte-identical in DXGI). Every host with the driver installed therefore listed each render GPU twice: the console picker offered a dead twin (display-only — D3D11 device creation on it fails), and auto-select's max-VRAM tie between the twins was settled by enumeration order — the real GPU won by luck, not construction. The kernel adapter type is the only field that separates the twins, so enumerate() now queries KMTQAITYPE_ADAPTERTYPE per adapter (raw gdi32 FFI — the windows crate's Wdk bindings aren't enabled, and one 3-call query doesn't justify them) and drops indirect-display, display-only, and software adapters. Fail-open: a failed query keeps the adapter — better a listed twin than a hidden real GPU. Incidentally also filters other vendors' virtual displays (Parsec-VDD class) from user machines' pickers. Existing manual preferences heal via find_preferred's same-model fallback when occurrence indices shift — a ghost accidentally pinned as -0 now resolves to the real GPU. The regression test pins the adapter-type words captured from real hardware; a Windows-gated smoke test runs enumerate() against the live machine (on the RTX box it actively exercises ghost exclusion: the inventory went from twin 4090s to exactly one). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
5d9f1ccb6d |
feat(host): --no-mdns/PUNKTFUNK_MDNS gate + punktfunk1-host --pairing-pin — docker-testing enablers
ci / docs-site (push) Successful in 54s
ci / web (push) Successful in 57s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 6s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
apple / swift (push) Successful in 1m6s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 5s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
decky / build-publish (push) Successful in 24s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 46s
ci / bench (push) Successful in 6m13s
apple / screenshots (push) Successful in 5m33s
windows-host / package (push) Successful in 9m42s
docker / deploy-docs (push) Successful in 5m59s
android / android (push) Successful in 13m48s
arch / build-publish (push) Successful in 13m59s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 12m52s
deb / build-publish (push) Successful in 15m5s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 15m7s
ci / rust (push) Successful in 18m35s
mDNS advertisement (native _punktfunk._udp AND GameStream _nvstream) can now be disabled with --no-mdns on serve/punktfunk1-host or PUNKTFUNK_MDNS=0 (the PUNKTFUNK_ZEROCOPY off-grammar) — for multicast-dead environments (bridged Docker, CI netns) where the advert reaches nobody or fails outright and aborts the GameStream plane; clients dial a manually-added host instead (mDNS-blind host-add works since the 0.8.4 dial-first fix). Unit tests no longer advertise on the LAN (mdns: false). punktfunk1-host gains --pairing-pin <PIN> (the already-plumbed fixed-PIN test seam, now CLI-exposed; empty refused like --mgmt-token) so a CI harness runs a deterministic SPAKE2 ceremony instead of scraping the logged PIN. Verified live: --no-mdns + PUNKTFUNK_MDNS=0 skip the advert, --pairing-pin arms with the fixed PIN, and a punktfunk1-host --source synthetic + punktfunk-probe loopback run passes verification (60/60 frames, 0 mismatch). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
c8fdef8bd1 |
fix(host): per-client display scaling on GNOME — host-persisted scale for Mutter virtual monitors
ci / web (push) Successful in 53s
decky / build-publish (push) Successful in 12s
apple / swift (push) Successful in 1m7s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 4s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 5s
ci / docs-site (push) Successful in 1m24s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 5s
ci / bench (push) Successful in 6m15s
apple / screenshots (push) Successful in 5m29s
windows-host / package (push) Successful in 8m43s
arch / build-publish (push) Successful in 11m29s
android / android (push) Successful in 13m14s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 12m47s
deb / build-publish (push) Successful in 16m13s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 16m12s
ci / rust (push) Successful in 22m39s
docker / deploy-docs (push) Successful in 17s
The identity policy promised per-client scaling, but on GNOME it could never work through the DE: Mutter mints a fresh EDID serial (0x%.6x, a per-shell counter) for every RecordVirtual monitor and offers no way to pass a stable identity, so the monitors.xml entry GNOME writes when the user sets a scale never rematches on reconnect — and our own topology ApplyMonitorsConfig then clobbered whatever was left back to a hardcoded scale 1.0. The host now remembers the scale itself (<config>/display-scale.json, keyed by the identity key — fp / fp@WxH / "shared" per the policy): reapplied at connect via the RecordVirtual mode's preferred-scale (Mutter pre-validates it; older Mutter ignores the key) and preserved — not forced — by the topology apply, with an integral-logical-size snap + retry-at-derived fallback (GetCurrentState reports no supported-scales for virtual monitors to snap to). The user's mid-session changes are polled from DisplayConfig every 5 s and written back, so a host crash loses at most a few seconds; an unconfirmed "Keep Changes" revert is tracked faithfully too. Mutter also now resolves the identity slot (set_client_identity/last_identity_slot) like KWin, keying the registry's group arrangement and /display/state. Verified live on the GNOME 50 box: set 1.5 mid-stream → persisted under the client fp; full teardown (fresh serial 0x000018); reconnect → monitor up at 1.5, "reapplying the client's saved display scale" logged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
4c99b78366 |
fix(flatpak): prune pf-client-core's windows-rs git dep from the sandbox manifest — offline build broken since a69a83b5
apple / swift (push) Successful in 1m8s
apple / screenshots (push) Successful in 5m26s
android / android (push) Successful in 9m51s
arch / build-publish (push) Successful in 9m53s
deb / build-publish (push) Successful in 51s
decky / build-publish (push) Successful in 26s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 34s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 55s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 2m42s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 2m34s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 2m43s
flatpak / build-publish (push) Successful in 6m59s
docker / deploy-docs (push) Successful in 26s
ci / web (push) Successful in 52s
ci / docs-site (push) Successful in 1m2s
ci / bench (push) Successful in 5m16s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 12m21s
ci / rust (push) Successful in 16m57s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 12m59s
The flatpak's offline cargo build has failed on every run since the D3D11VA push: pf-client-core now declares the same git-pinned `windows` dependency as the Windows client (cfg(windows)-gated, never compiled on Linux), and `cargo --offline` needs every DECLARED dependency's source just to build the unit graph — but windows-rs is deliberately not vendored into cargo-sources.json (flatpak-builder would full-clone the multi-GB repo; the reason prune-windows-lock.py exists). Removing the workspace member alone no longer covers it. New packaging/flatpak/prune-windows-toml.py (dependency-free, like its lock sibling) strips windows-rs git entries from a manifest in place — single- or multi-line — and the flatpak manifest runs it on crates/pf-client-core/Cargo.toml right after the existing clients/windows member sed. Registry deps in the same cfg(windows) table (wasapi, sdl3) are kept; they vendor normally. Verified in a scratch worktree with both prunes applied: the TOML stays valid and `cargo metadata` resolves ZERO windows-rs packages and zero git-source declarations — nothing left for --offline to fetch. End-to-end proof is the flatpak CI run on this push. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
f4c3a5d0c3 |
fix(clients): shared-VkQueue race + swapchain recreate destroy-in-use — the intermittent device-lost stream killer
apple / swift (push) Successful in 1m7s
ci / web (push) Successful in 1m9s
ci / docs-site (push) Successful in 1m18s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m41s
decky / build-publish (push) Successful in 21s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 5s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 9s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 5s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 6s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m43s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 1m11s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 1m34s
ci / bench (push) Successful in 6m12s
apple / screenshots (push) Successful in 5m18s
docker / deploy-docs (push) Successful in 27s
flatpak / build-publish (push) Failing after 5m25s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 13m50s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 17m35s
arch / build-publish (push) Successful in 19m55s
deb / build-publish (push) Successful in 18m59s
ci / rust (push) Successful in 20m9s
android / android (push) Successful in 20m11s
Live-diagnosed on the RTX box during the adaptive-bitrate A/B: 2 of 3 streams died with VK_ERROR_DEVICE_LOST at stream start or at a mid-stream encoder rebuild, then zombied — the demote-to-software path rebuilt the decoder against the same dead device, FFmpeg wedged inside the rebuild, and the pump flushed a never-draining backlog every 2 s forever. No OS TDR: the client's own Vulkan misuse. Two causes: 1. The presenter creates ONE graphics-family queue and hands FFmpeg's AVVulkanDeviceContext the same family (nb_graphics_queues=1 ⇒ queue 0) for its transfer/compute prep — so the pump thread and the presenter thread submitted to the SAME VkQueue with no shared lock, violating vkQueueSubmit's external-sync rule exactly when FFmpeg puts work on the graphics queue (decoder open / frames-context rebuild = stream start and every ABR encoder re-target). New guard-less QueueLock (FFmpeg's lock_queue/unlock_queue callbacks are a raw pair) shared by all four queue users: FFmpeg (callbacks installed via user_opaque), the presenter's submit/present/wait-idle, and the Skia overlay's flushes. 2. Swapchain recreation destroyed the old swapchain + render semaphores after ONE fence cycle — the fence proves our submit, not the presentation engine's semaphore consumption (VUID-vkDestroySemaphore-05149 + VUID-vkDestroySwapchainKHR-01282 on every recreate). Recreate now drains the queue (vkQueueWaitIdle under the shared lock — safe now that FFmpeg honours it) and destroys immediately; the deferred DisplayGarbage machinery is gone. Resilience: VK_ERROR_DEVICE_LOST anywhere in a present error chain is now fatal — the run loop fails the session loudly instead of demoting to software on a dead device (the zombie path). Verified on the RTX box (RTX 4090 → host .21) under VK_LAYER_KHRONOS_validation: 3/3 stream start/stop cycles clean, then 8 mid-stream encoder rebuilds in one session (4 ABR down-steps under 10% induced loss + 4 clean-link recovery up-steps — the exact scenarios that previously killed the device): 0 device losses, 0 wedges, both recreate VUIDs gone (previously fired on every path). Remaining validation messages are FFmpeg's own video-session VUIDs, untouched by this change. Linux: clippy -D warnings + tests green (home-worker-2). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
4839c0e6f6 |
fix(ci): windows clippy + rustfmt debt from the D3D11VA push
apple / swift (push) Successful in 1m16s
windows-host / package (push) Successful in 8m34s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m49s
release / apple (push) Successful in 9m12s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m45s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 1m22s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 1m49s
apple / screenshots (push) Successful in 5m42s
android / android (push) Successful in 4m53s
arch / build-publish (push) Successful in 7m9s
ci / web (push) Successful in 1m9s
ci / docs-site (push) Successful in 1m12s
ci / rust (push) Successful in 5m28s
deb / build-publish (push) Successful in 4m9s
decky / build-publish (push) Successful in 15s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 6s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 6s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 6s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
ci / bench (push) Successful in 6m13s
flatpak / build-publish (push) Failing after 5m1s
docker / deploy-docs (push) Successful in 16s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 12m30s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 12m36s
The windows workflow has been red since
|
||
|
|
d0f68cbbcd |
feat(core,host): per-family MTU shard sizing — the IPv6 gating item
apple / swift (push) Successful in 1m10s
windows-host / package (push) Successful in 8m41s
release / apple (push) Successful in 8m47s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m52s
arch / build-publish (push) Successful in 10m51s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m46s
android / android (push) Successful in 12m52s
audit / cargo-audit (push) Successful in 2m3s
audit / bun-audit (push) Successful in 15s
ci / rust (push) Failing after 25s
windows / build (aarch64-pc-windows-msvc) (push) Failing after 1m11s
ci / web (push) Successful in 55s
ci / docs-site (push) Successful in 1m12s
windows / build (x86_64-pc-windows-msvc) (push) Failing after 1m24s
apple / screenshots (push) Successful in 5m37s
ci / bench (push) Successful in 7m12s
decky / build-publish (push) Successful in 14s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 5s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 5s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 48s
deb / build-publish (push) Successful in 11m48s
flatpak / build-publish (push) Failing after 4m13s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 12m48s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 14m6s
docker / deploy-docs (push) Successful in 29s
Phase 1 of the dual-stack plan (design/client-parity-and-network-resilience.md, plan 5):
the host sizes each session's shard_payload from the QUIC remote's address family instead
of assuming IPv4 — 1408 over v4 (unchanged), 1388 over v6 (40-byte header). Rides the
existing Welcome::shard_payload negotiation, so there is zero wire change and old clients
simply follow.
This has to land before any v6 data path exists: the v4-maximal 1408 makes every sealed
video datagram overshoot a 1500-MTU IPv6 hop, and v6 routers never fragment — that's a
blackhole (every datagram dropped), not the graceful-ish degradation of the
|
||
|
|
13d1aa5738 |
feat(clients/android): OnFrameRendered display stage — HUD headline becomes capture→displayed
The long-deferred Android display stage (design/stats-unification.md; plan 4.1 of design/client-parity-and-network-resilience.md): AMediaCodec_setOnFrameRenderedCallback (API 26, under the minSdk-28 floor ⇒ hard-linked via ndk-sys) reports SurfaceFlinger's per-frame render timestamp, giving the HUD the spec's `display` = decoded→displayed term and the directly-measured capture→displayed end-to-end headline on both decode loops. Falls back per spec to the v1 capture→decoded endpoint on any window without render callbacks (the platform may drop them under load), and to it permanently if registration is refused. - The render timestamp arrives on CLOCK_MONOTONIC; it's re-based onto CLOCK_REALTIME against monotonic-now at callback time, which also cancels the (batchable) callback delivery lag. - The `ndk` crate exposes neither the callback nor the codec pointer needed to bind it raw, so the workspace pins `ndk` 0.9.0 to a vendored copy (clients/android/native/ vendor/ndk) whose ONLY change makes MediaCodec::as_ptr public — the "as_ptr patch". Workspace-excluded so host builds never compile it; drop when upstream exposes either. - nativeVideoStats grows to 26 doubles (22–25: dispValid, displayP50, e2eDispP50/P95; 0–21 unchanged for older readers); StatsOverlay moves headline endpoint + equation together so the equation always tiles the headline interval. Verified: host cargo check/test/clippy, aarch64-linux-android check/clippy, Kotlin app+kit+tests compile, roborazzi HUD render shows the full 4-term equation. Device verification rides plan 4.2's phone A/B. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
f508d3213f |
polish(clients/windows): name the session exe "Punktfunk Session" in its version info
apple / swift (push) Successful in 1m5s
android / android (push) Successful in 4m23s
audit / cargo-audit (push) Successful in 42s
audit / bun-audit (push) Successful in 19s
arch / build-publish (push) Successful in 5m38s
ci / rust (push) Failing after 44s
ci / web (push) Successful in 51s
ci / docs-site (push) Successful in 1m3s
windows-host / package (push) Successful in 8m41s
release / apple (push) Successful in 8m45s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m49s
ci / bench (push) Successful in 4m51s
decky / build-publish (push) Successful in 13s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m44s
deb / build-publish (push) Successful in 5m31s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 34s
windows / build (aarch64-pc-windows-msvc) (push) Failing after 1m16s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 2m36s
windows / build (x86_64-pc-windows-msvc) (push) Failing after 1m23s
apple / screenshots (push) Successful in 5m44s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 2m23s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 52s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4m39s
flatpak / build-publish (push) Failing after 3m13s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 11m24s
docker / deploy-docs (push) Successful in 29s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 11m27s
UAC prompts, Task Manager and Properties→Details show FileDescription; without one the exe appeared as its raw filename. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
a69a83b545 |
feat(clients/windows): D3D11VA hardware decode in the session client — Vulkan chain becomes vulkan → d3d11va → software
The vendor-agnostic DXVA path for GPUs without Vulkan Video (Intel's Windows driver foremost, which previously landed on CPU decode). Ported from the retired WinUI presenter's decoder with its Intel-safe discipline intact (decode pool stays libavcodec-derived — a hand-built pool broke Intel at the first SubmitDecoderBuffers), on a decode device LUID-matched to the presenter's adapter. Hand-off is a ring of shareable BGRA8 textures (SHARED_NTHANDLE | SHARED_KEYEDMUTEX) filled by the fixed-function ID3D11VideoProcessor (NV12/P010 → BGRA8, colour spaces from the per-frame CICP; PQ is tone-mapped to SDR by the processor — HDR-first boxes take Vulkan Video). BGRA is deliberate: importing a multiplanar NV12 D3D11 texture device-losts on NVIDIA however it is consumed (plane-view sampling and DMA copy both validation-clean, both TDR — bisected), while single-plane RGBA D3D11↔Vulkan interop is the path Chromium/ANGLE exercise on every driver. The presenter imports a slot's NT handle per frame (VK_KHR_external_memory_win32, gated on the spec-required external-format probe) and blits it into the video image — no CSC pass; the DXGI keyed mutex (key 0 both sides, drop-tolerant) is the cross-API lock and visibility barrier. Verified live vs a real host at 5120x1440@240 HEVC on an RTX 4090: 240 fps, e2e 2.7/3.0 ms p50/p95 under the Khronos validation layer — parity with Vulkan Video (2.6 ms); auto still resolves vulkan on NVIDIA. PUNKTFUNK_DECODER=d3d11va forces it; import/present failures demote to software on the existing streak contract. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
d0fa8bd3ee |
fix(clients): pin mDNS discovery to IPv4 on every client
Host machines' OS mDNS responders answer AAAA for hostname.local even though the punktfunk stack binds IPv4 sockets exclusively, so a v6-resolved address rendered a host card whose connect always failed. Apple's Network.framework prefers IPv6 (RFC 6724) — force the resolve connection to v4; pf-client-core (Linux/Windows/Deck shells) now picks get_addresses_v4() instead of an arbitrary first address. Android already did exactly this, for the same reason. Lift all three when the stack actually speaks IPv6 (per-family shard sizing is the gating item — the IPv6 header costs 20 bytes of the MTU budget shard_payload is maximal against). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
8e6e8bb25c |
feat(core,host): adaptive bitrate — mid-stream encoder re-targeting when set to Automatic
New SetBitrate (0x05) / BitrateChanged (0x06) control messages: the host clamps like the Hello request, acks the resolved rate, and rebuilds the ENCODER ONLY in place (same mode, first new-rate frame is an IDR — the proven mode-switch resync, minus the pipeline churn). The client side is an AIMD controller (core abr.rs) in the data-plane pump, armed only when the user's bitrate is Automatic (Hello bitrate_kbps == 0): ×0.7 after two bad 750 ms windows (FEC-unrecoverable frames, ≥2% loss, one-way-delay rise above its rolling baseline — the pre-loss bufferbloat signal off the clock-skew handshake — or a jump-to-live flush), ~+6% after ~10 s clean, ceiling = the session's starting rate, 3 s cooldown, self-disables against a host that never acks (older build). Division of labour: adaptive FEC keeps answering fast random loss; bitrate now answers persistent congestion, closing the FEC death-spiral gap. The web-console sample reports the live rate. Also: join_host_port() brackets bare IPv6 literals before SocketAddr parsing (parse-side IPv6 groundwork, pairs with the next commit). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
180ac3aa61 |
feat(console): full gamepad shell — hosts, PIN pairing, settings, OSK, screen transitions
apple / swift (push) Successful in 1m6s
android / android (push) Has been cancelled
apple / screenshots (push) Has been cancelled
arch / build-publish (push) Has been cancelled
audit / bun-audit (push) Has been cancelled
audit / cargo-audit (push) Has been cancelled
ci / rust (push) Has been cancelled
ci / web (push) Has been cancelled
ci / docs-site (push) Has been cancelled
ci / bench (push) Has been cancelled
deb / build-publish (push) Has been cancelled
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Has been cancelled
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Has been cancelled
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Has been cancelled
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Has been cancelled
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Has been cancelled
docker / deploy-docs (push) Has been cancelled
release / apple (push) Has been cancelled
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
windows / build (aarch64-pc-windows-msvc) (push) Has been cancelled
windows / build (x86_64-pc-windows-msvc) (push) Has been cancelled
windows-host / package (push) Has been cancelled
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Has been cancelled
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Has been cancelled
decky / build-publish (push) Successful in 25s
flatpak / build-publish (push) Successful in 4m31s
The Skia console UI grows from the single library coverflow into a complete couch shell (Apple gamepad-UI parity), so a Deck/gamescope session is self-sufficient end to end: - Home: host carousel (saved + discovered + Add Host tile) with presence pips, paired locks, wake & connect; A/Y/X/B per the Apple launcher. - In-console SPAKE2 PIN pairing (previously needed the Decky plugin or a desktop), add-host with a controller keyboard, couch settings over the shared Settings store, wake-on-LAN overlay with retry, cancelable dials. - Shell chrome: screen stack with push/pop entrance/exit choreography (slide + fade + recede; aurora↔form backdrop crossfade), per-pad button glyphs (PS shapes vs ABXY, keycaps with no pad), menu haptics, toasts, embedded Geist typography, in-stream start banner. - Steam Deck: our OSK never draws — fields start SDL text input (the new Overlay::text_input_active hook) and Steam's keyboard types; a hint chip points at STEAM + X. Other Linux gets the full gamepad keyboard tray. - punktfunk-session: bare --browse opens Home; --browse host opens that host's library with Home behind it (Decky launches keep working, B now pops instead of quitting). Service threads run discovery, 10 s probes, pairing, wake loops, fetches, and known-hosts persistence. - Presenter contract: Launch actions carry the host, CancelConnect never engages a won race, pad kind/list ride FrameCtx, menu events flow while dialing so B can cancel. Every screen renders to PNG on CPU raster for review (PF_CONSOLE_DUMP=<dir> cargo test -p pf-console-ui -- --ignored dump). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
c3fa6c1514 |
feat(clients/apple): AV1 decode support — OBU plumbing, hardware-gated advertisement
apple / swift (push) Successful in 1m15s
release / apple (push) Successful in 15m35s
apple / screenshots (push) Successful in 4m35s
android / android (push) Successful in 4m17s
arch / build-publish (push) Successful in 5m51s
ci / web (push) Successful in 1m5s
ci / docs-site (push) Successful in 1m22s
ci / rust (push) Successful in 5m14s
deb / build-publish (push) Successful in 3m31s
decky / build-publish (push) Successful in 12s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
ci / bench (push) Successful in 5m0s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 11m12s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 11m20s
docker / deploy-docs (push) Successful in 6s
The Apple client was HEVC/H.264-only: the receive path spoke Annex-B NALs exclusively, so AV1 was never advertised and the codec picker hid it. Add the OBU flavor of the same plumbing (AV1.swift, sibling of AnnexB.swift): a zero-copy OBU walker, a full spec-5.5.1 sequence-header parser, an av1C CMVideoFormatDescription with colorimetry extensions (so isHDRFormat and the presenter stay codec-agnostic), and an ISOBMFF 'av01' sample repack (temporal delimiter stripped, everything size-fielded, one copy per AU). VideoCodec gains .av1 (wire 0x04); both pumps and VideoDecoder route through dispatching formatDescription(fromKeyframe:)/sampleBuffer(au:) — keyframe gating keys on the in-band sequence header exactly as the NAL codecs key on in-band parameter sets, so loss recovery and mid-session reconfigure work unchanged. AV1 sessions require a hardware decoder (VideoToolbox has no software AV1; same fail-fast policy as 4:4:4), and both the Hello advertisement and the Settings picker are gated on VTIsHardwareDecodeSupported — AV1 only appears on devices that can actually decode it (M3-class Macs, A17 Pro-class iPhones; no Apple TV). Tests: real SVT-AV1 blobs (generation recipe in the file) cover the walk, the parse against an independent reference, av1C bytes, delta-TU gating, repack byte-exactness, and — on AV1 hardware — a real VTDecompressionSession decode through VideoDecoder. Host precedence stays HEVC > AV1 > H.264, so AV1 engages only when explicitly picked. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
bf9be59f0b |
feat(clients/windows): rename the Help button to Shortcuts
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m39s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m37s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 1m15s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 1m30s
apple / swift (push) Successful in 1m12s
apple / screenshots (push) Successful in 5m48s
android / android (push) Successful in 4m30s
arch / build-publish (push) Successful in 5m47s
ci / web (push) Successful in 1m0s
ci / docs-site (push) Successful in 1m19s
ci / rust (push) Successful in 5m10s
deb / build-publish (push) Successful in 3m30s
ci / bench (push) Successful in 5m5s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
decky / build-publish (push) Successful in 13s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 6s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 5s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 6s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 5s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 11m25s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 11m33s
docker / deploy-docs (push) Successful in 12s
"Shortcuts" says what the page actually is — the in-stream keyboard/controller reference — and the keyboard glyph reads better than the generic help icon (user feedback from the live-test round). Page title follows. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
a3332aedae |
fix(clients/apple): return to windowed after a stream error, not just an active disconnect
apple / swift (push) Successful in 1m12s
release / apple (push) Successful in 8m48s
apple / screenshots (push) Successful in 5m48s
android / android (push) Successful in 4m6s
arch / build-publish (push) Successful in 7m3s
ci / rust (push) Successful in 7m1s
ci / web (push) Successful in 51s
ci / docs-site (push) Successful in 1m0s
deb / build-publish (push) Successful in 3m40s
decky / build-publish (push) Successful in 12s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 4s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 5s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 5s
ci / bench (push) Successful in 5m4s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 11m5s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 10m51s
docker / deploy-docs (push) Failing after 18s
A session error tears down the same as a deliberate disconnect (connection → nil flips FullscreenController's `active` off), but ALSO sets `errorMessage`, raising the "Connection failed" alert. On macOS that alert is a window sheet, and AppKit drops `-toggleFullScreen:` while a sheet is attached — so the exit was swallowed and the window stayed fullscreen on the home screen (an active disconnect sets no error, so it never stuck). Defer the alert while a forced-fullscreen exit is pending: no sheet attaches during the exit, the window returns to windowed, then the alert presents over it. Not gated when fullscreen is the user's own manual choice (opt-out setting), where nothing is auto-exiting. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
069fcdfca6 |
feat(clients/apple): user-configurable Allow VRR (macOS + iOS)
Add an "Allow VRR" toggle (Settings → Display; default on, non-tvOS) that hands the presenter's display link a wide frame-rate RANGE — preferred = the stream rate — so a ProMotion / adaptive-sync display can vary its physical refresh to match the stream. `SessionPresenter.syncFrameRate` now runs on macOS too: on it requests min 24 / max display / preferred stream Hz; off restores the prior behavior (macOS free-runs at the native rate, iOS keeps its 30 Hz floor). A no-op on fixed-refresh displays. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
f58d91ba19 |
polish(clients/apple): tighten settings copy, fix stale ⌃⌥⇧S shortcut
The Statistics footer still advertised the old ⌘⇧S toggle after the cross-client shortcut migration — corrected to ⌃⌥⇧S (StreamCommands). Split the Audio footer into a platform-aware string (the "System default follows device changes" note only applies to macOS, where the device pickers live). Trim the overloaded Video-quality, Controllers, gamepad-UI, touch/pointer, presenter and library footers to the load-bearing facts. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
f4850625bd |
feat(clients/windows): game library page + session window placement + help polish
apple / swift (push) Successful in 1m10s
android / android (push) Successful in 4m56s
arch / build-publish (push) Successful in 5m56s
audit / bun-audit (push) Successful in 13s
audit / cargo-audit (push) Successful in 1m34s
ci / web (push) Successful in 1m11s
windows-host / package (push) Successful in 7m57s
ci / docs-site (push) Successful in 1m27s
release / apple (push) Successful in 8m39s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 3m26s
ci / bench (push) Successful in 5m0s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 3m16s
apple / screenshots (push) Successful in 5m35s
ci / rust (push) Successful in 10m32s
decky / build-publish (push) Successful in 13s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 5s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 7s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 4m47s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 2m36s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 5s
deb / build-publish (push) Successful in 6m38s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 5m39s
flatpak / build-publish (push) Successful in 5m32s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 11m0s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 10m33s
docker / deploy-docs (push) Successful in 18s
UX polish batch 2 (plan workstreams D/E5/E6): - D: a mouse/keyboard game library page over pf-client-core::library (the GTK ui_library.rs counterpart): responsive 2-6 column poster grid (2:3 portraits, store badge, monogram placeholder while art streams in), loading / error+retry / empty / grid states, tap-to-play via a normal spawn carrying --launch id. Poster bytes land in a disk cache (%LOCALAPPDATA%\punktfunk\art-cache) so the Image widget loads file:/// URIs (reactor has no from-bytes source) and revisits render instantly. Reached from a paired host's "Browse library..." menu item behind the new "Show game library (experimental)" Settings toggle (the shared library_enabled field, Apple/GTK parity). A Shared::library_gen generation guard keeps a superseded fetch from publishing (speed-test pattern). - E5: the session window opens at the shell's own top-left (--window-pos, new SessionOpts::window_pos) instead of centered on the primary display - streams land on the monitor the shell is on, and the hide/restore handoff reads as one window changing content. Fullscreen follows that display. - E6: the Help shortcuts add Alt+Enter and the controller escape chord (LB+RB+Start+Back, hold to disconnect). Also: rustfmt normalization of the merged probe helper. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
f5f186b691 |
Merge remote-tracking branch 'origin/main'
# Conflicts: # clients/windows/src/app/mod.rs |
||
|
|
573b2af334 |
feat(clients/windows): single-window handoff, shared settings store, console-UI surfacing
UX polish batch 1 (clients/windows/ui-polish-plan.md, workstreams W0/A1/B/C/E):
- W0: the shell's duplicated trust/settings structs are gone — src/trust.rs
re-exports pf-client-core's, so the shell and the spawned session binary share
ONE Settings shape over client-windows-settings.json. Fixes real bugs: the
shell's saves no longer drop session-side fields; the stats-overlay toggle
(show_hud -> show_stats, serde alias migrates old files) and the forwarded-
controller pick now actually reach the spawned session. The "Streaming engine"
Settings combo is gone (PUNKTFUNK_BUILTIN_STREAM=1 stays as the dev A/B knob).
- Forwarded-controller pinning by stable key (vid:pid:name, pf-client-core's
format): persisted as forward_pad, applied by the shell's own service at
startup AND by the session binary in session_params (both OSes — the session
never applied the pin before).
- A1 single window: the shell hides itself when the spawned session window
presents its first frame ({"ready":true}) and restores + foregrounds on the
child's exit — exactly one visible Punktfunk window at any time. Restore runs
before the request-access cancel gate so a Ready/Cancel race can't strand the
shell hidden.
- C console UI: punktfunk-session --browse gains --json-status (ready when the
library window presents; error line on a failed start), and the shell
surfaces it — "Open console UI" on paired hosts' menus, plus a controller-
detected hint card targeting the most recent paired host (x64 only; aarch64
ships no skia ui feature). Browse spawns hide/restore the shell like streams.
- B responsive: minimum window size (420x360); the hosts header collapses to
icon-only buttons below 700 px; the session status card shrinks instead of
clipping (max_width); busy pages, help actions, licenses and long labels wrap.
- E polish: session exe gets the app icon (winresource + WM_SETICON via the new
pf-presenter win32.rs); both exes share an explicit AppUserModelID on
unpackaged runs (packaged identity wins) so the windows group as one taskbar
app across the visibility handoff; "Start streams fullscreen" toggle passes
--fullscreen (GTK parity); connects stamp KnownHost::last_used; the connect
target is stashed for every route so "Connecting to X" always names the host.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
01428ced58 |
feat(clients): reachability-probed presence + shareable Decky host management
apple / swift (push) Failing after 27s
release / apple (push) Failing after 26s
apple / screenshots (push) Has been skipped
windows-host / package (push) Has been cancelled
arch / build-publish (push) Has been cancelled
android / android (push) Has been cancelled
ci / rust (push) Has been cancelled
ci / web (push) Has been cancelled
ci / docs-site (push) Has been cancelled
ci / bench (push) Has been cancelled
deb / build-publish (push) Has been cancelled
decky / build-publish (push) Has been cancelled
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Has been cancelled
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Has been cancelled
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Has been cancelled
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Has been cancelled
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Has been cancelled
docker / deploy-docs (push) Has been cancelled
flatpak / build-publish (push) Has been cancelled
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Has been cancelled
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Has been cancelled
windows / build (aarch64-pc-windows-msvc) (push) Has been cancelled
windows / build (x86_64-pc-windows-msvc) (push) Has been cancelled
Add a bounded, trust-agnostic, mDNS-INDEPENDENT QUIC reachability probe and surface it everywhere saved-host presence is shown, so a host reached over a routed network (Tailscale/VPN/multicast-filtering LAN) no longer reads Offline just because it isn't advertising — the display-side companion to the 0.8.4 dial-first connect fix. Core: - punktfunk-core: NativeClient::probe (bounded handshake; a real host answers even on trust mismatch, a wrong/closed/TCP-only port fails) + punktfunk_probe C ABI (ABI_VERSION 3->4, header regenerated). - pf-client-core: trust::probe_reachable_many (parallel per-host sweep). Presence pips now read `advertising OR probed-reachable`, refreshed by a ~10-12s background sweep off the UI thread: - Linux (relm4): ui_hosts probed map + HostsMsg::Probed sweep. - Windows (windows-reactor): pf-probe worker -> HostsProps.probed. - Apple (SwiftUI): HostStore.refreshReachability, driven by HomeView + GamepadHomeView .task. - Android (Compose): nativeProbe JNI seam + periodic LaunchedEffect (LNP-gated), online dot added to the touch HostCard. - Decky already probes via --list-hosts --probe. Decky client: make the flatpak client's known-hosts store the single source of truth via new headless CLI modes (--list-hosts / --add-host / --set-host / --forget-host / --reset / --reachable). The plugin can now add a host by address, edit/forget hosts, reset all state (keeping the client identity), and shows probe-backed online pips — state is shared with the desktop client, not duplicated. Also lands in-progress Android 17 LNP groundwork (targetSdk 37 + ACCESS_LOCAL_NETWORK runtime flow, permission dialogs) that was already present in the working tree. Verified: cargo check + clippy clean (punktfunk-core, pf-client-core, linux, android native); android assembleDebug BUILD SUCCESSFUL; decky typecheck + rollup build clean; probe true/false-positive behaviour exercised against a live host. Windows and Apple were not compiled locally (no MSVC/Xcode on this Linux box). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
6198da3daf |
feat(clients/apple): cross-client shortcuts + start banner, opt-in V-Sync, presenter rework
apple / swift (push) Failing after 28s
release / apple (push) Failing after 22s
apple / screenshots (push) Has been skipped
android / android (push) Has been cancelled
arch / build-publish (push) Has been cancelled
ci / rust (push) Has been cancelled
ci / web (push) Has been cancelled
ci / docs-site (push) Has been cancelled
ci / bench (push) Has been cancelled
deb / build-publish (push) Has been cancelled
decky / build-publish (push) Has been cancelled
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Has been cancelled
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Has been cancelled
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Has been cancelled
docker / deploy-docs (push) Has been cancelled
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Has been cancelled
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Has been cancelled
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
Align the macOS/iPad Stream menu on the cross-client Ctrl+Alt+Shift set the Windows and Linux clients reserve — Release Mouse (⌃⌥⇧Q), Disconnect (⌃⌥⇧D), HUD toggle (⌃⌥⇧S) — with ⌘⎋ kept as the macOS/iPad capture toggle, and surface them on a 6-second banner at stream start. Add an opt-in V-Sync present mode (punktfunk.vsync, default OFF = lowest-latency immediate present; PUNKTFUNK_PRESENT_MODE overrides for A/B), with the presenter reworked to a frame-arrival-triggered render thread across Stage2Pipeline / MetalVideoPresenter / SessionPresenter, plus the windowed title-bar safe-area handling. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
c511462536 |
feat(clients/apple): enable Game Mode across Apple platforms
Opt macOS and iOS into system Game Mode (GCSupportsGameMode=YES) and unify the App Store category to Games across macOS/iOS/tvOS (tvOS omits the key — no Game Mode there). Game Mode engages automatically when the stream is native-fullscreen (already the default), giving GPU/CPU priority and doubling controller/AirPods Bluetooth polling for lower input/audio latency — parity with the Android client's appCategory=game. Verified: macOS/iOS/tvOS Debug builds succeed and the produced bundle Info.plists carry the expected keys. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
d6647b9183 |
feat(clients/windows): port the Vulkan session client to Windows — session-always
The punktfunk-session Vulkan client (clients/linux-session, now clients/session) builds and runs on Windows; the WinUI shell spawns it for every stream. Verified live: 10-bit HEVC via Vulkan Video on both AMD (iGPU) and NVIDIA, 5120x1440 at 130 fps / 8 ms end-to-end on the RTX 4090. - pf-ffvk: Windows bindgen branch (FFMPEG_DIR + PF_FFVK_VULKAN_INCLUDE, no pkg-config); provisioning fetches Vulkan-Headers (pinned v1.4.309). - pf-client-core: builds on Windows — WASAPI audio (audio_wasapi.rs, cfg-swapped via #[path], same surface as the PipeWire twin), VAAPI/dmabuf gated inline (chain = vulkan -> software), trust reads the WinUI shell's %APPDATA% stores (parity tests pin both serialized shapes), Settings gains adapter/hdr_enabled (serde-defaulted; Linux stores unaffected). - pf-presenter: builds on Windows — dmabuf module Linux-gated; SDL keyboard grab while captured (Alt+Tab/Win reach the host); pick_device ranks discrete over integrated (device 0 was the iGPU on hybrid boxes — the silent footgun) and honors PUNKTFUNK_VK_ADAPTER (the Settings GPU pick, exported by the session). - run loop: block in one SDL wait woken by input AND decoded frames (a per- session forwarder pushes a FrameWake user event) instead of a 1 ms poll — measured 111%% -> 5%% of a core (NVIDIA), 86%% -> 3.5%% (AMD), stats unchanged. The pump's decode-fence wait became once-per-window sampling (no per-frame pipeline stall; the stat now shows true backlog). - pf-console-ui: builds on Windows (skia-safe msvc prebuilts); font lookup falls through fontconfig aliases to concrete DirectWrite families (Consolas/Segoe UI) — browse/coverflow works, verified against a live host. - WinUI shell: session-always via new src/spawn.rs (GTK spawn.rs port — CREATE_NO_WINDOW, stdout contract, kill handle); the Stream screen is a status card (chips + stage lines from the child's stats). The legacy in-process D3D11VA path stays behind Settings "Streaming engine" / PUNKTFUNK_BUILTIN_ STREAM=1 as the A/B baseline until Phase 8 deletes it. SessionParams.video_caps makes the HDR toggle real. - clients/linux-session renamed to clients/session (builds for both OSes). - CI/MSIX: both workflows build/test both bins with widened path filters; the MSIX ships punktfunk-session.exe. ARM64 session builds --no-default-features (rust-skia has no aarch64-pc-windows-msvc prebuilts; flip when it does). A/B on this box (5120x1440 HEVC vs home-worker-5): NVIDIA Vulkan 130 fps / 8 ms e2e / 1.6 ms decode — clearly better than the built-in path. The AMD iGPU VCN saturates at ~52 fps where its own D3D11VA does ~70 — Adrenalin Vulkan decode is slower on APU silicon; discrete RDNA validation gates Phase 8. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
2003d8a75c |
style(host): rustfmt the bit_depth ternary in serve_session
apple / swift (push) Successful in 1m13s
apple / screenshots (push) Successful in 3m26s
android / android (push) Successful in 4m58s
arch / build-publish (push) Successful in 5m53s
ci / web (push) Successful in 1m4s
windows-host / package (push) Successful in 7m46s
ci / docs-site (push) Successful in 1m22s
ci / rust (push) Successful in 4m59s
ci / bench (push) Successful in 5m7s
decky / build-publish (push) Successful in 25s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 5s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
deb / build-publish (push) Successful in 4m41s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 2m18s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 10m57s
docker / deploy-docs (push) Successful in 20s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 10m24s
Collapse the manually-wrapped if/else to rustfmt's canonical form; fixes the cargo fmt --all --check CI failure at punktfunk1.rs:895. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
838a1239cf |
feat(codec): make client codec selection real — GPU-aware native advertisement
apple / swift (push) Successful in 1m7s
release / apple (push) Successful in 8m27s
windows-host / package (push) Successful in 7m59s
apple / screenshots (push) Failing after 2m38s
android / android (push) Successful in 4m44s
ci / rust (push) Failing after 46s
arch / build-publish (push) Successful in 5m32s
ci / web (push) Successful in 50s
ci / docs-site (push) Successful in 1m2s
deb / build-publish (push) Successful in 4m44s
ci / bench (push) Successful in 5m7s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
decky / build-publish (push) Successful in 13s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 3s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 3s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 11m9s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 11m14s
docker / deploy-docs (push) Successful in 13s
The clients' codec pickers sent a preference the host threw away: host_wire_caps() hardcoded HEVC for every GPU backend, so the native path never emitted H.264/AV1 regardless of what the user chose. Host: advertise what the backend actually encodes, mirroring the GameStream serverinfo logic — software openh264 emits H.264; probed backends (Linux VAAPI, Windows AMF/QSV) advertise their per-GPU CodecSupport via the new wire_mask(); NVENC keeps the Moonlight-validated H.264|HEVC|AV1 static superset; an empty probe falls back to the superset so auto clients still resolve HEVC. Gate 10-bit to HEVC (like the 4:4:4 gate) now that a client can steer the codec — Main10 is the only 10-bit encode path. Fix the web-console stats label hardcoded to "hevc" (new Codec::label(), shared with the GameStream register_session mapping). Android: replace the hardcoded H264|HEVC Hello advertisement with a videoCodecs param fed by VideoDecoders.decodableCodecBits() (AV1 bit only when a real hardware video/av01 decoder exists — the decode loop was already mime-driven); offer AV1 in the codec picker on capable devices. Decky: add the missing "Video codec" dropdown (auto/hevc/h264/av1) to the plugin settings, round-tripping the same codec key the flatpak client reads. Apple: unchanged by design (AnnexB.swift is NAL-only, AV1 is never advertised); refresh the stale "hosts don't emit AV1 on the native path yet" comments here and host-side. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
0290bf7285 |
fix(clients/windows): hide the local cursor while captured
apple / swift (push) Successful in 1m11s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m42s
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m25s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 58s
android / android (push) Successful in 4m21s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 1m4s
arch / build-publish (push) Successful in 5m57s
ci / web (push) Successful in 1m14s
ci / docs-site (push) Successful in 1m19s
ci / rust (push) Successful in 5m4s
ci / bench (push) Successful in 5m4s
decky / build-publish (push) Successful in 13s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 5s
deb / build-publish (push) Successful in 4m45s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 5s
apple / screenshots (push) Successful in 6m26s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 11m29s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 11m32s
docker / deploy-docs (push) Failing after 18s
set_locked() hid the OS cursor with a one-shot ShowCursor(false), but the WinUI content island answers WM_SETCURSOR and re-asserts the arrow on every pointer move, so the cursor reappeared the instant the mouse moved while the pointer lock was engaged. A low-level mouse hook never sees WM_SETCURSOR, so it couldn't suppress it. Subclass the WinUI window and all its descendants (the video is a composition SwapChainPanel, so the pointer actually sits over WinUI's internal input-site child, which is the window that receives WM_SETCURSOR) and, while the lock wants the cursor hidden, answer WM_SETCURSOR ourselves with SetCursor(None) and return TRUE — halting WinUI's arrow re-assertion. ShowCursor(false) stays as the coarse first-frame hide. The subclass is removed on teardown so the reused app window (host list) is left pristine. Adds the Win32_UI_Shell feature for the subclassing APIs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
e28160ebb3 |
chore(release): bump workspace version to 0.8.4
apple / swift (push) Successful in 1m12s
audit / cargo-audit (push) Successful in 27s
audit / bun-audit (push) Successful in 15s
ci / web (push) Successful in 52s
ci / docs-site (push) Successful in 1m16s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 49s
ci / bench (push) Successful in 4m45s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 55s
apple / screenshots (push) Successful in 5m55s
ci / rust (push) Successful in 11m23s
android-screenshots / screenshots (push) Successful in 2m37s
windows-host / package (push) Successful in 7m37s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m15s
release / apple (push) Successful in 9m2s
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m12s
android / android (push) Successful in 10m53s
arch / build-publish (push) Successful in 9m4s
decky / build-publish (push) Successful in 26s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 5s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 2m26s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
flatpak / build-publish (push) Successful in 4m42s
deb / build-publish (push) Successful in 10m29s
linux-client-screenshots / screenshots (push) Successful in 6m36s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 10m41s
web-screenshots / screenshots (push) Successful in 2m44s
docker / deploy-docs (push) Successful in 20s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 10m2s
Release 0.8.4 — reconnect reliability and streaming polish over 0.8.3. The headline fix: a reconnect to a saved host that had stopped advertising on mDNS (but still had a learned Wake-on-LAN MAC) was routed into a wait-for-mDNS wake flow instead of being dialed — so a host reached over a routed network (Tailscale/VPN/another subnet) could never be reconnected, reading as "Offline" with no connection attempt in the host log. All four full clients now dial first and only fall into the visible "Waking…" wait when the dial actually fails. On the host side, the same investigation surfaced Windows-only gaps: a deliberate quit (⌘D) now tears the pf-vdisplay virtual monitor down immediately (no 10 s linger churning the reconnect's REMOVE→ADD), while keep_alive=forever (the gaming-rig preset) correctly outranks the quit on both platforms so a pinned screen stays alive. Silent deaths are no longer invisible: a panic hook tees panics into the web console's Logs, a Windows SEH filter names the faulting module on a native GPU-driver crash, and a watchdog flags a wedged monitor teardown. Also in this release: the presenter switches to MAILBOX present, pushes HDR10 mastering metadata, and tags HDR honestly; DualSense rumble accepts the v2 vibration valid-flag and bounds a stale buzz; the core caps the QUIC datagram send buffer so audio/rumble go latest-wins; the host folds a Steam Deck to a DualSense on Windows (split-pad touch + pad clicks) and applies input motion on arrival rather than after the 4 ms tick; Android gains a tiered stats HUD with windowed lost/skipped/FEC counters; and Windows surfaces a Help/shortcuts screen and exits fullscreen when the stream stops. The [workspace.package] version (inherited by every crate via version.workspace) is the release being cut; the 14 workspace entries in Cargo.lock and the api/openapi.json info.version are refreshed to match (CI builds --locked). Canary derives from the tag as minor+1 of the latest stable (scripts/ci/pf-version.sh), so cutting 0.8.4 keeps canary at 0.9.0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>v0.8.4 |
||
|
|
0b7e4a00ee |
fix(host): crash visibility + Windows deliberate-quit teardown; pin outranks quit
Two strands from the "Windows host went Offline after reconnect, zero errors in the logs" investigation. Crash visibility — the field reports kept arriving with nothing in the Logs tab because every way the host can die silently was unlogged: - A panic hook tees each panic (thread, location, backtrace) through `tracing` into the in-memory ring + host.log before the default hook runs — a panicking thread otherwise only hit stderr, absent from the web console and gone when stderr is detached. - A last-resort Windows SEH filter (windows/crash.rs) logs an unhandled native exception with its code, faulting address, and faulting MODULE — the smoking gun that separates our bug from a GPU runtime/driver DLL (amfrt64, the UMD, d3d11) crashing under us. - A 10 s watchdog around the vdisplay monitor teardown logs an ERROR when the driver REMOVE/CCD-restore looks wedged (it runs under the manager state lock, so a hang there silently blocks every future acquire). Deliberate-quit teardown (Windows pf-vdisplay) — the Windows manager never wired the linger skip the Linux registry has: on ⌘D (the QUIT close code) the monitor lingered 10 s, so a quick reconnect hit the Lingering-preempt's back-to-back REMOVE→ADD churn. A per-lease quit flag (VirtualDisplay:: set_quit_flag) now tears the monitor down immediately on a deliberate quit, so the reconnect finds the manager Idle and does a clean fresh ADD. Pin outranks quit (both platforms) — keep_alive=forever (the gaming-rig preset) promises "the screen stays alive", so a deliberate quit must skip only the linger WINDOW, never the pin. Windows release() checks keep_alive_forever() before the quit; the Linux registry had the inverse bug (force_immediate tore down even a pinned display) — fixed via effective_linger() with a unit test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
ab6790ef6c |
fix(clients): dial-first reconnect — don't gate the connect on mDNS presence
A saved host that stopped advertising on mDNS but has a learned Wake-on-LAN MAC was routed into a wake-and-WAIT-for-mDNS flow instead of being dialed. For a host reached over a routed network (Tailscale/VPN/another subnet) mDNS never sees it, so the wait could never succeed and reconnects were impossible — the host log showed no connection attempt at all. The tile's Offline pip and this connect gate shared the same LAN-only `advertises`/`liveAdvert` predicate, so a perfectly reachable host read as unreachable. The first connect worked only because the MAC hadn't been learned yet (a direct dial); once learned, every reconnect wedged in the waker. All four full clients carried this pattern (deliberate mirrors of the Apple `HostWaker`). Each now DIALS FIRST: fire the magic packet up front (fire-and-forget — harmless if the host is awake, and a genuinely-asleep box is booting while the dial times out) and attempt the connection unconditionally. Only a FAILED dial falls into the visible "Waking…" wait, whose redial carries no fallback so it can't loop. A fingerprint-mismatch/trust-rejection failure means the host ANSWERED, so it never takes the wake path. - apple: SessionModel.connect gains `onUnreachable`; startSession dials first. - linux (relm4): AppMsg::WakeConnect wakes+dials; a per-request wake_fallback is armed and consumed in SessionExited, matched by fingerprint/address. - windows: initiate_waking + ConnectOpts.wake_on_fail; the worker's Failed arm escalates to wake_and_connect only on a non-trust failure. - android: doConnectDirect gains onFailure; doConnect wakes+dials first. Decky was already correct (always launches `--connect`; WoL fire-and-forget). Explicit "Wake host" menu actions are unchanged — waiting on mDNS is right when the user explicitly asked to wake a box. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
52856d4b6b |
chore(web): refresh bun.lock
android / android (push) Successful in 4m34s
arch / build-publish (push) Successful in 5m39s
audit / bun-audit (push) Successful in 12s
audit / cargo-audit (push) Successful in 1m21s
ci / web (push) Successful in 49s
apple / screenshots (push) Successful in 5m49s
apple / swift (push) Successful in 1m12s
windows-host / package (push) Successful in 7m39s
ci / docs-site (push) Successful in 1m14s
ci / rust (push) Successful in 3m31s
ci / bench (push) Successful in 4m54s
decky / build-publish (push) Successful in 14s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
deb / build-publish (push) Successful in 4m0s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 5s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 3s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 34s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 11m17s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 11m12s
docker / deploy-docs (push) Successful in 18s
Dependency bumps within the existing package.json semver ranges; no manifest changes. |
||
|
|
6bbd2a9ed6 |
feat(windows): add deploy-all.ps1 wrapper; fix web console health check
deploy-all.ps1 chains deploy-host.ps1 + build-web.ps1 so a full redeploy is one command; stops before the web step if the host build/start fails. build-web.ps1's post-restart check was probing http:// while web-run.cmd serves HTTPS-only, so it always reported a false failure - probe https via curl.exe (no -SkipCertificateCheck on the Windows PowerShell 5.1 this runs under) with a short retry loop for the task's cold start instead. |
||
|
|
ade4266336 |
fix(presenter): MAILBOX present; push HDR10 metadata; honest HDR tag
apple / swift (push) Successful in 1m10s
android / android (push) Successful in 4m43s
arch / build-publish (push) Successful in 5m33s
ci / web (push) Successful in 59s
ci / docs-site (push) Successful in 1m9s
windows-host / package (push) Successful in 7m54s
ci / rust (push) Successful in 3m33s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m12s
release / apple (push) Successful in 8m28s
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m10s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 45s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 51s
deb / build-publish (push) Successful in 3m59s
decky / build-publish (push) Successful in 14s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
ci / bench (push) Successful in 5m1s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 5s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 5s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 5s
apple / screenshots (push) Successful in 5m52s
flatpak / build-publish (push) Successful in 4m55s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 10m52s
docker / deploy-docs (push) Successful in 18s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 9m50s
Three Deck-test findings in the Vulkan presenter: MAILBOX over FIFO when the surface offers it (PUNKTFUNK_PRESENT_MODE= fifo restores the old default): both are tear-free, but an arrival- paced presenter blocking in FIFO's present queue eats most of a vblank whenever gamescope holds images for its composite pass or cadence drifts against refresh — the display stat flipping 1 ms → 11-13 ms. VK_EXT_hdr_metadata wired up: the host's 0xCE mastering metadata (or the Windows presenter's generic HDR10 baseline until it arrives) is pushed via vkSetHdrMetadataEXT whenever an HDR10 swapchain is (re)- created. Compositors key their HDR-app signaling on this — colorspace alone leaves gamescope treating the app as SDR (no SteamOS badge). And the OSD's HDR tag now reports the display path, not the stream: a PQ stream tone-mapped onto an SDR surface shows HDR→SDR, so the next test distinguishes "badge missing" from "HDR never engaged". Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
dc834ea478 |
fix(rumble): accept the v2 vibration valid-flag; bound stale buzz to 1.5 s
Two hardenings against runaway vibration (one Deck session buzzed on a ~2 s cadence): the DualSense output-report parse now also treats valid_flag2 COMPATIBLE_VIBRATION2 (data[39] BIT2) as rumble-carrying — a writer hardcoding the ≥2.24-firmware convention previously had its rumble INCLUDING stops silently ignored, and a missed stop re-sends stale nonzero state forever via the host's 500 ms refresh. And the client's SDL rumble duration drops 5 s → 1.5 s: long enough that a couple of lost 500 ms refreshes don't gap genuine rumble, short enough that stale state dies on its own. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
4516bd48e1 |
perf(core): cap the QUIC datagram send buffer — audio/rumble go latest-wins
quinn's default 1 MiB datagram FIFO holds tens of seconds of Opus; on a congested link the audio/rumble/input planes built a standing delay that never drained while video (own latest-wins UDP path) stayed live — observed on the Deck as audio and rumble lagging together by the same experience-destroying amount. quinn sheds oldest-first at the cap, so a 4 KiB bound makes the plane latest-wins at the source: ~200 ms of stereo Opus worst case, and sustained congestion costs concealable drops instead of lag. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
4c9c7e606e |
feat(android): tiered stats HUD + windowed lost/skipped/FEC counters
Stats overlay verbosity tiers (Off/Compact/Normal/Detailed, 3-finger tap cycles live, old Boolean pref migrated) and the unified-spec line-4 reliability counters: lost/FEC windowed from the connector's cumulative totals, skipped from the client's own newest-wins drops. Adds the fec_recovered_shards accessor to NativeClient, mirrored from the data-plane pump like frames_dropped. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
b12c7d3deb |
style(windows): satisfy rustfmt on the uninstall() teardown comments
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m7s
apple / swift (push) Successful in 1m18s
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m9s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 39s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 1m0s
android / android (push) Successful in 5m34s
apple / screenshots (push) Successful in 6m8s
arch / build-publish (push) Successful in 6m57s
ci / web (push) Successful in 1m36s
ci / rust (push) Successful in 3m58s
ci / docs-site (push) Successful in 1m4s
deb / build-publish (push) Successful in 3m57s
decky / build-publish (push) Successful in 13s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 6s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
ci / bench (push) Successful in 5m3s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 11m35s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 11m24s
docker / deploy-docs (push) Successful in 29s
rustfmt 1.9.0 aligns standalone // lines out to the column of a preceding trailing comment, so the two-line fullscreen note placed right after `set_captured(...); // ...` failed `cargo fmt --check`. Make the first note a leading comment so no standalone comment follows a trailing one. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
8a4b0c7bae |
feat(windows): surface shortcuts on a Help screen; exit fullscreen when the stream stops
apple / swift (push) Successful in 1m10s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m13s
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m13s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 44s
windows / build (x86_64-pc-windows-msvc) (push) Failing after 41s
android / android (push) Successful in 4m11s
ci / rust (push) Failing after 1m21s
ci / web (push) Successful in 55s
apple / screenshots (push) Successful in 5m52s
ci / docs-site (push) Successful in 1m2s
arch / build-publish (push) Has been cancelled
ci / bench (push) Has been cancelled
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
deb / build-publish (push) Has been cancelled
decky / build-publish (push) Has been cancelled
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Has been cancelled
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Has been cancelled
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Has been cancelled
docker / deploy-docs (push) Has been cancelled
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Has been cancelled
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Has been cancelled
The in-stream keyboard shortcuts were only reachable deep in Settings > Input. Move them to a dedicated Help screen reached from a Help button on the host list (mirrors the Licenses screen — a hook-free page routed from root), and drop the reference card out of Settings so there's one home for it. Fullscreen (F11) was a window-style toggle that stream stop never undid, so disconnecting while fullscreen left the GUI borderless-fullscreen. Split toggle_fullscreen into is_fullscreen/enter_fullscreen/exit_fullscreen sharing a module-level SAVED_PLACEMENT, and have input::uninstall() call exit_fullscreen() on teardown. exit_fullscreen is a no-op when nothing was saved, so it's safe on every stream stop and idempotent with F11 — fullscreen is now streaming-only. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
d490397908 |
chore: gitignore the local flatpak-builder repo/build dirs
apple / swift (push) Successful in 1m12s
android / android (push) Successful in 4m29s
arch / build-publish (push) Successful in 5m23s
ci / web (push) Successful in 1m0s
ci / docs-site (push) Successful in 1m8s
ci / rust (push) Successful in 3m35s
windows-host / package (push) Successful in 8m53s
release / apple (push) Successful in 8m52s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m15s
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m16s
deb / build-publish (push) Successful in 4m1s
decky / build-publish (push) Successful in 12s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
ci / bench (push) Successful in 4m58s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 1m1s
apple / screenshots (push) Successful in 5m55s
flatpak / build-publish (push) Successful in 4m31s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 4m48s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 11m4s
docker / deploy-docs (push) Successful in 19s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 10m18s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
a41f679516 |
perf(host): one input channel — motion applies on arrival, not after the 4 ms tick
Rich input (gyro at the pad's report rate, trackpad contacts) rode a second mpsc channel that the input thread only drained after its main channel's 4 ms recv timeout — so during pure-gyro aiming (no button/pointer traffic, the common case) every motion sample ate up to 4 ms of added latency and quantization before reaching the virtual pad. At the Deck's 250 Hz sensor cadence that is a full sample period of jitter. Both planes now share one ClientInput channel: the thread wakes the moment either arrives and applies rich input immediately. The 4 ms timeout stays as the feedback-pump tick. Also adds a debug-level motion-cadence metric (inter-arrival p50/p95/max per 5 s window) so gyro delivery is measurable end-to-end instead of 'feels floaty'. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |