51cdaea3f3236779e5c8bd85b98ac68bfc6e6b9c
1192 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
8a18e130a2 |
feat(client): freeze-until-reanchor loss recovery on Android + Apple via shared core gate
After unrecoverable loss the host keeps sending delta frames that reference a picture the client never received; hardware decoders conceal these as gray/ garbage with a success status. Linux already withheld them and held the last good frame until a proven clean re-anchor — this brings that behavior to the Android and Apple clients. Extract the Linux pump's freeze state machine into a shared `ReanchorGate` in punktfunk-core (reanchor.rs, 18 tests) exposed over the C ABI (ABI v6, additive — no wire change) for the Swift clients. Migrate the Linux/Deck pump (pf-client-core) onto it as the parity proof (no-op refactor). Then wire: - Android (decode.rs, both sync + async loops): arm on the frame-index gap, a pts-keyed flag map carries the wire flags to the output-buffer release, fold the gate per drained output, gate.poll replaces the dropped-climb block. - Apple Stage2Pipeline (default): arm on a gap (new noteFrameIndexGap), withhold at the ring-submit seam (CAMetalLayer holds its last drawable), poll framesDropped, fold VT decode errors through the no-output streak. - Apple StreamPump (stage-1): fold at enqueue, withhold via kCMSampleAttachmentKey_DoNotDisplay so the layer keeps decoding (reference chain intact) but holds the last displayed frame. - Apple VideoDecoder: thread the AU's wire flags to the async decode callback via a retained FrameContext refcon (replaces the receivedNs bit-pattern scalar). Lifts only on a proven re-anchor (IDR / RFI anchor / 2nd recovery mark) with a 500 ms backstop so a lost re-anchor can never freeze forever. Apple: swift build clean, 123/123 tests pass (incl. VideoToolboxRoundTripTests). On-glass loss-injection validation still owed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
cd701a9594 |
fix(vdisplay): preserve FramePublisher across swap-chain reassign (sibling-join freeze)
windows-drivers / probe-and-proto (push) Successful in 28s
ci / web (push) Successful in 54s
ci / docs-site (push) Successful in 1m0s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 8s
decky / build-publish (push) Successful in 19s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 8s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 9s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 7s
windows-drivers / driver-build (push) Successful in 1m35s
apple / swift (push) Successful in 4m34s
ci / bench (push) Successful in 5m39s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 6m50s
docker / deploy-docs (push) Successful in 33s
windows-host / package (push) Successful in 10m8s
android / android (push) Successful in 12m24s
arch / build-publish (push) Successful in 16m41s
deb / build-publish (push) Successful in 17m40s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 12m13s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 18m21s
ci / rust (push) Successful in 23m52s
apple / screenshots (push) Successful in 20m9s
When a second client got its own virtual display mid-stream, the FIRST client's IDD-push stream froze (video only; `new_fps=0 repeat_fps=240` forever). Adding/removing/resizing a sibling display re-commits the CCD topology, which makes the OS unassign+reassign the first monitor's IddCx swap chain. `unassign_swap_chain` dropped the SwapChainProcessor, dropping `run_core`'s local FramePublisher and closing the sealed-channel handles. The fresh worker then polled the frame-channel stash — but that stash is consumed once at session open, and the host only re-delivers on a ring recreate (a descriptor change). The first monitor's descriptor didn't change and WUDFHost stayed alive, so no watchdog fired: the driver drained the swap chain without publishing and the host repeated its last frame indefinitely. Confirmed twice on the .173 box (host.log 21:12 & 21:15). Preserve the live FramePublisher across the flap instead of dropping it: the host-owned ring (header/event/textures) it holds stays valid — only the swap chain died. - frame_transport.rs: FramePublisher records its render-adapter LUID + exposes render_adapter(). - monitor.rs: MonitorObject.preserved_publisher + preserve_publisher() (mirrors set_frame_channel) + take_preserved_publisher() (mirrors take_frame_channel). Monitor teardown drops the stashed publisher and closes its ring handles, so nothing leaks. - swap_chain_processor.rs run_core: after SetDevice OK, re-adopt a preserved publisher ONLY when the new swap chain renders on the same LUID (same pooled Direct3DDevice → its context + opened textures are valid); on loop exit, stash the publisher back on the monitor. Safe: the old worker is fully joined (drop-outside-lock discipline) before the new one runs, so no concurrent context use; a stale re-adopted publisher is superseded by the existing is_stale() + has_frame_channel() newest-wins checks at the loop top. Verified clippy -D warnings clean on rustc 1.96.0 via a faithful mock crate (the real crate needs the WDK to compile). Needs a driver rebuild + reinstall on the host to take effect; not yet hardware-validated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
05868ef634 |
fix(encode): Vulkan-HEVC full-RPS reference retention + AV1 feature gate (RFI review)
ci / web (push) Successful in 56s
ci / docs-site (push) Successful in 1m0s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 14s
decky / build-publish (push) Successful in 30s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 11s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 8s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 10s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 52s
apple / swift (push) Successful in 4m47s
ci / bench (push) Successful in 6m2s
docker / deploy-docs (push) Successful in 24s
windows-host / package (push) Successful in 8m6s
arch / build-publish (push) Successful in 11m4s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 13m19s
android / android (push) Successful in 16m58s
deb / build-publish (push) Successful in 17m45s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 18m38s
ci / rust (push) Successful in 24m8s
apple / screenshots (push) Successful in 20m38s
2026-07-12 review of the host encoders / client decoders / RFI plane. NVENC (both), AMF-LTR, the session glue, and the client RfiTracker came out clean; every fix lands in the Vulkan Video backend + dispatch: 1. HEVC: author each P-frame's short-term RPS to retain ALL resident DPB pictures (minus the setup slot), not just its one reference. HEVC 8.3.2 evicts unlisted pictures, and clients keep FEEDING the decoder while frozen — so with the old single-pic RPS, a conforming parser (FFmpeg = the Linux VAAPI/Vulkan and Windows D3D11VA clients) had already discarded the picture an RFI recovery anchor references whenever a fed post-loss frame preceded it: generate_missing_ref, and the "clean" anchor plus everything chained after it decodes as garbage. Pure builder (`build_h265_rps_s0`) + unit tests; AV1 needs nothing (slot-based retention). The smoke test now encodes a fed post-loss frame between loss@4 and anchor@6 so an ffmpeg decode of the dropped dump exercises exactly this (expect ONE POC-4 complaint, never POC 3) — revalidate on the AMD box; this NVIDIA dev box fails the backend earlier at HEVC header retrieval (pre-existing). 2. AV1: chain PhysicalDeviceVideoEncodeAV1FeaturesKHR (videoEncodeAV1 = TRUE, stype 1000513004) into device creation — spec-required for the ENCODE_AV1 codec op; RADV tolerated the omission, validation layers and stricter drivers do not. 3. RFI decline no longer self-arms force_kf — that bypassed the session glue's 750 ms IDR cooldown, turning a storm of hopeless RFI requests into one full IDR each. Decline like NVENC/AMF and let the caller's coalesced keyframe path own the fallback; add the missing first>last guard for parity. 4. open_video_backend now returns the label of the branch that ACTUALLY opened, so the mgmt API / web console reports "vulkan" instead of "vaapi" for the default-on Vulkan sessions (the old dispatch-mirror resolved_backend_label went stale when the backend gained its VAAPI fallback; deleted). Structure: the ~230-line inline HEVC coding block moves to record_coding_h265 (symmetric with record_coding_av1) and the duplicated pre-encode barriers dedupe into begin_encode_cmd. Follow-up plan (separate, punktfunk-planning): bring the post-loss freeze + RECOVERY_ANCHOR/POINT lift to the Android/Windows/Apple clients via a shared ReanchorGate (design/client-reanchor-freeze-parity.md). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
2d37835545 |
feat(encode): AV1 on the Linux Vulkan Video encoder (real RFI)
ci / web (push) Successful in 1m12s
ci / docs-site (push) Successful in 1m22s
decky / build-publish (push) Successful in 19s
ci / bench (push) Successful in 5m36s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 9s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 8s
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 8s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 8s
arch / build-publish (push) Successful in 12m32s
docker / deploy-docs (push) Successful in 21s
android / android (push) Successful in 13m27s
ci / rust (push) Successful in 17m43s
deb / build-publish (push) Successful in 13m40s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 15m19s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 15m36s
windows-host / package (push) Successful in 14m43s
apple / swift (push) Successful in 4m42s
apple / screenshots (push) Successful in 19m20s
Extend the raw Vulkan Video backend to AV1 (`VK_KHR_video_encode_av1`) alongside HEVC, so AMD/Intel Linux hosts get the same clean-P-frame loss recovery for AV1 that HEVC already has — no full IDR on packet loss. ash 0.38.0+1.3.281 predates the AV1-encode extension (finalized in Vulkan 1.3.290) and bumping ash breaks the SDL/Vulkan client (it drops the lifetime on AllocationCallbacks, which sdl3-sys still generates). So the AV1-encode structs/flags/enums are vendored host-only in `encode/linux/vk_av1_encode.rs`, copied verbatim from ash-master's generated code and chained into ash's generic video-encode calls via raw p_next — the common StdVideoAV1* types (from AV1 decode) are reused from ash 1.3.281. `vulkan_video.rs` gains a parallel AV1 path: AV1 Main profile/caps/session (+ max-level session-create), a bit-packed sequence-header OBU + per-frame temporal-delimiter framing (Vulkan AV1 encode, unlike H26x, emits only the frame OBU), and per-frame StdVideoEncodeAV1PictureInfo with the RFI reference model — a normal P inherits CDF context from its reference for compression, while an IDR or recovery anchor sets primary_ref_frame=NONE + error_resilient_mode so it decodes independent of the (possibly lost) frames since its reference. HEVC recording is unchanged; the shared CSC / ring / DPB-barrier pipeline is reused as-is. Codec routing in `open_video_backend` extends the HEVC arm to HEVC|AV1. The seq header enables only order-hint (+128px superblocks per caps), matching FFmpeg's proven Vulkan AV1 config — enabling CDEF/restoration made VCN emit frame-header sections our seq header didn't match, desyncing every inter frame. Headless-validated on real RADV (780M): open + 6-frame encode (I P P P P P) decodes 0-error on both dav1d and ffmpeg/cbs; the RFI recovery anchor at frame 4 is a clean P (not IDR), and dropping the "lost" frame 3 still decodes clean (re-anchored to frame 2). HEVC smoke unchanged (no regression). `cargo clippy --features vulkan-encode -- -D warnings` and the no-feature build both green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
9514a8c0e2 |
fix(client): correct Linux/Windows "Forwarded controller" copy for multi-controller
ci / web (push) Successful in 51s
ci / docs-site (push) Successful in 56s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 8s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 8s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 11s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 10s
decky / build-publish (push) Successful in 52s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 8s
apple / swift (push) Successful in 4m39s
ci / bench (push) Successful in 6m27s
windows-host / package (push) Successful in 8m34s
flatpak / build-publish (push) Successful in 7m15s
docker / deploy-docs (push) Successful in 24s
android / android (push) Successful in 12m49s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 4m16s
deb / build-publish (push) Successful in 12m50s
arch / build-publish (push) Successful in 16m32s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 3m53s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 19m44s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 5m14s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 17m53s
ci / rust (push) Successful in 25m18s
release / apple (push) Successful in 22m3s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 5m57s
apple / screenshots (push) Successful in 18m56s
The relm4 (Linux) and native (Windows) shells spawn punktfunk-session, which
since the native-plane rework forwards ALL controllers by default — but the
"Forwarded controller" settings dropdowns still described the pre-rework world
("Automatic (most recent)", "Exactly one controller is forwarded to the host").
The dropdown already lists every detected pad and wires set_pinned(None)=all /
set_pinned(key)=single-player; this fixes only the misleading labels, subtitle,
tooltip, and stale leading comments to match: Automatic forwards every real
controller (each its own player); pick one to force single-player.
cargo check -p punktfunk-client-linux green; Windows is windows-gated (pure
string edits, CI windows.yml).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
97c67b2692 |
feat(apple): multi-controller support
Roll the pf-client-core slot pattern to the Apple client (Swift): - GamepadManager tracks all connected GCControllers, assigning each a stable lowest-free wire pad index + concrete type, emitting GamepadArrival on connect and GamepadRemove on disconnect (index freed for reuse on re-plug). - GamepadCapture binds every controller with per-controller Slot state (buttons/axes/fingers/motion), threading the pad index into flags on every event; GamepadWire/InputEvents carry the pad + the two new events. - GamepadFeedback + RumbleRenderer go per-pad (rumbleByPad, slots[pad]), routing rumble/HID back to the correct controller by wire index. - ContentView/Settings surface every forwarded controller. pad 0 => flags 0, so single-controller wire is byte-identical. Cannot build on the Linux dev box (no Swift toolchain / Apple frameworks); wire bytes hand-checked against input.rs and GamepadWireTests extended for multi-pad. CI apple.yml (swift build/test on macOS) is the compile gate. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
0ad4e6eff7 |
feat(android): multi-controller support
Roll the pf-client-core slot pattern to the Android client (Kotlin + JNI): - New kit/GamepadRouter.kt: the Android analogue of the client-core Slot model — a deviceId→Slot map assigning each InputDevice a stable lowest-free wire pad index held for its lifetime, GamepadArrival(pref) before a pad's first input, GamepadRemove on onInputDeviceRemoved, per-slot AxisMapper + held-bitmask so two pads never clobber each other. The isForwardable gate (excludes DualSense/DS4 all-zero sensor sibling nodes) is centralized in slotFor so no entry point can open a phantom slot. - native/src/session/input.rs: JNI shims take a pad arg -> flags=pad (nativeSendGamepadButton/Axis, plus nativeSendGamepadArrival/Remove). - native/src/feedback.rs: pad carried in rumble bits 49..52 + a leading hidout pad byte; GamepadFeedback.kt routes rumble/lightbar/LED back to the originating device by pad via deviceForPad. - MainActivity.kt routes key/motion events by device; ControllersScreen.kt badges every forwarded pad (was hardcoded i==0), reading getControllerNumber. A lone controller lands on wire index 0, so its per-transition datagrams stay byte-identical to the old single-pad path. gradle :app:assembleDebug green (Rust cross-compiled via cargo-ndk); JNI signatures hand-verified 1:1. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
76be4c3e12 |
feat(gamepad): multi-controller support on the native plane
Host was already built for 16 pads; the blocker was every client hard-coding pad 0. This lands the host-side + reference-client contract: - input.rs: new wire kinds GamepadArrival=14 (declares a pad's type: code=GamepadPref byte, flags=pad) and GamepadRemove=13 (flags=seq<<24|pad, shares the snapshot seq space via encode/decode_gamepad_remove). - pf-client-core/gamepad.rs: reworked from a single `open` pad to a slots: Vec<Slot> model — every forwarded controller gets a stable lowest-free wire index held for its lifetime, per-slot held/axis/touch/ rumble state, GamepadArrival on open + GamepadRemove on close, and feedback routed back per wire index. Automatic forwards all real pads; a pin forces single-player. - punktfunk1.rs: replaced the single-session PadBackend enum with a Pads router — per-pad kinds[]/owner[] arrays, lazily-created per-kind managers, pure route_decision keeping a live device in its manager across a kind change (no ghost/dup). Input thread seq-gates GamepadRemove (clears the pad_mask bit, resets rumble) and applies GamepadArrival kinds. - inject linux/windows backends: add the two new no-op InputKind arms. Native/session + default-Windows clients (both spawn punktfunk-session) inherit this. 57 core + 33 client-core + 272 host tests green; clippy clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
84329205eb |
feat(encode): default-on the Linux Vulkan Video HEVC backend
ci / docs-site (push) Successful in 59s
ci / web (push) Successful in 1m7s
decky / build-publish (push) Successful in 18s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 8s
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 8s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 44s
apple / swift (push) Successful in 4m13s
ci / bench (push) Successful in 7m13s
windows-host / package (push) Successful in 9m43s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 9m26s
docker / deploy-docs (push) Successful in 28s
android / android (push) Successful in 12m35s
deb / build-publish (push) Successful in 12m46s
arch / build-publish (push) Successful in 16m31s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 19m32s
apple / screenshots (push) Successful in 18m49s
ci / rust (push) Successful in 25m10s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 18m0s
On-glass validated 2026-07-12 on an AMD RADV 780M with a real Deck-class client: the pipelined raw-Vulkan HEVC encoder ran a rock-solid 1080p@240 session and healed loss with clean P-frame recovery anchors (real RFI the libav VAAPI path can't express). Ship it on by default, mirroring the NVENC default-on. - vulkan_encode_enabled() defaults ON; PUNKTFUNK_VULKAN_ENCODE=0 is the libav VAAPI escape hatch. A failed open still falls back to VAAPI, so a device without h265 Vulkan encode (or an untested Intel/ANV that misbehaves at open) degrades gracefully instead of breaking the stream. - Ring depth defaults to 2 (one frame of overlap, lowest added latency — the on-glass-validated real-time setting); PUNKTFUNK_VULKAN_INFLIGHT still tunes it. - Compile --features punktfunk-host/vulkan-encode into the arch/deb/rpm host builds (pure-Rust ash, no new lib / no link-time dep), alongside nvenc. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
e9d8f2bc04 |
perf(encode): pipeline the Vulkan Video encoder (frames in flight)
The Linux raw-Vulkan HEVC backend blocked on two GPU fences per frame, so CPU readback and the next capture could not overlap the GPU encode. Refactor into a small ring of per-in-flight-frame resources (own command buffers, CSC descriptor set + Y/UV/NV12 scratch, bitstream buffer, feedback query and sync objects) so submit() records into a free slot and returns without waiting, and poll() reads back the oldest slot once its fence signals. The pump's non-blocking poll then overlaps a frame's CSC+encode with the next capture — the throughput win — with no capturer/pump change (VAAPI untouched). - New `Frame` struct + `make_frame`; encoder holds `frames`/`ring`/`in_flight`. - `record_submit` (non-blocking) + `read_slot` (fence-gated readback) replace the synchronous `encode_frame`; `enqueue` applies backpressure by draining the oldest slot when the ring is full. - DPB self-barrier between consecutive encodes: orders frame N's reconstruct write before N+1's reference read now that they can be in flight together. - flush() drains all in-flight slots in order; reset() waits idle + discards. - Ring depth defaults to 3, overridable via PUNKTFUNK_VULKAN_INFLIGHT (2..=6). - Smoke test drains via poll-loop + flush (async breaks one-AU-per-submit). Headless-validated on real RADV 780M: cargo check (feature on/off) + clippy -D warnings + rustfmt clean; smoke test at ring depth 2/3/6 all ffmpeg-decode clean (I P P P P P) and drop-heal (I P P P P) with 0 errors. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
bbbb7f5723 |
fix+perf(encode): clamp Vulkan CSC to source edge + cache dmabuf imports
Two refinements after the initial on-glass validation on RADV (780M): - Green padding bar at non-16-aligned heights (e.g. 1080 → coded 1088): the CSC compute shader read past the edge of the shorter source dmabuf for the 8 alignment-padding rows, producing undefined/green garbage that showed on a client rendering the coded frame. Clamp every source fetch to `textureSize-1` so padding rows duplicate the last real row (invisible, and the SPS conformance window still crops it for a compliant decoder). BT.709 conversion is byte-identical for in-bounds pixels. 5120x1440 (exactly aligned) was never affected. - Per-frame dmabuf import churn: the backend created + imported + destroyed a VkImage every frame (allocation jitter → stutter). PipeWire cycles a small fixed pool, so import each underlying buffer ONCE (keyed by st_dev/st_ino — each frame's fd is a fresh dup of the same buffer) and reuse it, matching the CUDA-path VkBridge. First import acquires from the foreign producer; cached re-reads keep queue ownership and use a plain visibility barrier. On-glass: ~3-6 imports per session then silent (was ~one per frame at 240 Hz), stutter gone at resolutions with headroom. Also adds a PF_SMOKE_W/H override to the headless smoke test to exercise the conformance-window crop path (ffprobe confirms coded 1088 → displayed 1080). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
5ab6daa694 |
feat(encode): raw Vulkan Video HEVC backend on Linux (AMD/Intel) with real RFI
Add `VulkanVideoEncoder` (`VK_KHR_video_encode_h265` via ash) — the open-stack twin of the direct-NVENC RFI path, giving AMD/Intel Linux hosts real reference-frame invalidation loss recovery: a clean P-frame recovery anchor that re-references a known-good older frame instead of a full IDR. The app owns the DPB, so recovery = pointing the P-frame's single L0 reference at a resident slot strictly older than the loss (never a concealed frame). The backend owns its own ash instance/device with encode + compute queues, authors VPS/SPS/PPS (Main, conformance-window crop for non-16-aligned heights like 1080->1088), runs a DPB-ring reference-slot state machine with monotonic POC and CBR rate control, and does an on-GPU RGB->NV12 BT.709 compute CSC (embedded rgb2yuv.spv) since capture delivers packed-RGB dmabufs — importing each frame's dmabuf (explicit DRM modifier) or uploading a CPU-RGB fallback, CSC on the compute queue, then encode on the encode queue, ordered by a semaphore. Wired into `open_video_backend`: an AMD/Intel HEVC session opens this instead of libav VAAPI when `PUNKTFUNK_VULKAN_ENCODE=1` (VAAPI fallback on any open error, so it can only improve recovery, never break a stream); `PUNKTFUNK_ ENCODER=vulkan` forces it. Gated behind the new `vulkan-encode` Cargo feature, which pulls no new dependency (reuses the `ash` bindings already carried for the dmabuf zero-copy bridge). Opt-in until on-glass validated, mirroring how the direct-NVENC path shipped. Headless-validated on real RADV (RDNA3 780M, Mesa 26): open + multi-frame encode + `invalidate_ref_frames` all run through the real struct and ffmpeg decodes the output `I P P P P P` with 0 errors; the recovery frame is a clean P-frame (not an IDR); and dropping the "lost" AU still decodes cleanly because the recovery re-anchored to an older frame — the RFI heal, proven on real hardware. `cargo check`/`clippy -D warnings` green with the feature on and off. Design: design/linux-vulkan-video-encode.md. Harness: design/vkenc-probe-harness/. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
76594f27c1 |
feat(nvenc): default-on the Linux direct-SDK NVENC path
ci / web (push) Successful in 45s
ci / docs-site (push) Successful in 1m5s
decky / build-publish (push) Successful in 20s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 9s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 7s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 7s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 8s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 8s
apple / swift (push) Successful in 4m49s
ci / bench (push) Successful in 6m13s
docker / deploy-docs (push) Successful in 20s
windows-host / package (push) Successful in 14m19s
arch / build-publish (push) Successful in 20m25s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 18m28s
android / android (push) Successful in 21m8s
deb / build-publish (push) Successful in 20m53s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 20m25s
ci / rust (push) Successful in 24m14s
apple / screenshots (push) Successful in 21m0s
On-glass validated 2026-07-12 on an RTX 5070 Ti host with a real Steam Deck client (NV12 4:2:0, 1280x800@90): real nvEncInvalidateRefFrames landed 73/73 as clean P-frame recovery anchors (never IDR), losses consistently ~2 frames deep — well inside the 5-frame DPB. That is the loss recovery the libav hevc_nvenc path cannot express, so make the direct path the default on NVIDIA. PUNKTFUNK_NVENC_DIRECT=0 (also false/no/off) is now the libav escape hatch. Still gated on a CUDA capture payload — the `cuda` check in open_nvenc_probed keeps AMD/Intel on VAAPI regardless, and the NVENC/CUDA entry points stay dlopen'd at runtime (no new DT_NEEDED), so non-NVIDIA hosts are unaffected. Packaging comments updated to match. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
e89b2f60eb |
build(linux): enable --features nvenc in the arch/deb/rpm host builds
ci / web (push) Successful in 53s
ci / docs-site (push) Successful in 1m3s
decky / build-publish (push) Successful in 20s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 8s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 8s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 7s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 6s
ci / bench (push) Successful in 6m36s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 6m7s
docker / deploy-docs (push) Successful in 20s
deb / build-publish (push) Successful in 12m12s
apple / swift (push) Successful in 5m5s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 12m55s
arch / build-publish (push) Successful in 15m6s
android / android (push) Successful in 20m8s
ci / rust (push) Successful in 23m44s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 18m36s
apple / screenshots (push) Successful in 20m26s
The Phase 5.2 direct-SDK NVENC Linux backend (encode/linux/nvenc_cuda.rs) is gated `#[cfg(all(target_os = "linux", feature = "nvenc"))]`, but no Linux packager passed `--features nvenc` (it was historically a Windows-only feature for the D3D11 NVENC path). So the module was compiled OUT of every arch/deb/rpm canary regardless of commit — PUNKTFUNK_NVENC_DIRECT was a silent no-op on the shipped Linux host. Add `--features punktfunk-host/nvenc` to all three package builds so the code actually ships. AMD/Intel-SAFE (verified): this is NOT the old Windows link-import crash. The NVENC/CUDA entry points are dlopen'd at RUNTIME (libloading) — `objdump -p` shows the feature build's DT_NEEDED is byte-identical to a plain build (no libcuda / libnvidia-encode), so the binary starts fine driver-less. We use only the crate's `sys::nvEncodeAPI` types (no code-running safe wrapper / lazy statics), cudarc stays on `ci-check`/dynamic-loading (no CUDA toolkit at build), and the encoder is only constructed for a CUDA capture frame + PUNKTFUNK_NVENC_DIRECT — never on a VAAPI (AMD/Intel) host. The sysext images repackage these outputs, so they inherit it; no other Linux host build compiles the binary. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
63bc2bb10f |
docs(web-console): fix stale http:// URLs — the console serves HTTPS on :47992
ci / docs-site (push) Successful in 48s
ci / web (push) Successful in 53s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 10s
decky / build-publish (push) Successful in 17s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 9s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 14s
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 52s
arch / build-publish (push) Has been cancelled
ci / bench (push) Has been cancelled
ci / rust (push) Has been cancelled
deb / build-publish (push) Has been cancelled
android / android (push) Has been cancelled
apple / swift (push) Has been cancelled
apple / screenshots (push) Has been cancelled
docker / deploy-docs (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-host / package (push) Has been cancelled
The punktfunk-web unit serves HTTP/1.1 over TLS with the host's own self-signed identity cert, but several guides still told users to open http://<host>:47992, which fails. Correct the scheme everywhere and note the one-time browser cert warning in the canonical + SteamOS docs. The RPM %post web hint was doubly wrong (http://<host-ip>:3000): wrong scheme and wrong port — the service listens on :47992, not the :3000 dev default. Also fixes scripts/web-init.sh, so the URL the SteamOS/Linux installer prints at the end of setup is correct too. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
ad532b08a0 |
style(encode): rustfmt the direct-SDK NVENC Linux backend
ci / web (push) Successful in 49s
ci / docs-site (push) Successful in 52s
decky / build-publish (push) Successful in 17s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 8s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 7s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 6s
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 6m1s
docker / deploy-docs (push) Successful in 20s
arch / build-publish (push) Successful in 12m23s
android / android (push) Successful in 13m26s
deb / build-publish (push) Successful in 14m27s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 15m22s
ci / rust (push) Successful in 18m25s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 15m14s
windows-host / package (push) Successful in 14m15s
apple / swift (push) Successful in 4m49s
apple / screenshots (push) Successful in 20m11s
`cargo fmt` was not run on the Phase 5.2 additions (nvenc_cuda.rs + the encode.rs dispatcher fork), failing the ci.yml rust fmt job. Whitespace/wrapping only — no behavior change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
93093f3cf9 |
feat(encode): direct-SDK NVENC on Linux (CUDA input) with real RFI
ci / rust (push) Failing after 1m1s
ci / web (push) Successful in 1m3s
ci / docs-site (push) Successful in 1m9s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 10s
decky / build-publish (push) Successful in 17s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 8s
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 8s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 57s
apple / swift (push) Successful in 4m42s
ci / bench (push) Successful in 7m37s
docker / deploy-docs (push) Successful in 22s
flatpak / build-publish (push) Successful in 6m51s
windows-host / package (push) Successful in 14m26s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 12m59s
arch / build-publish (push) Successful in 16m48s
deb / build-publish (push) Successful in 17m14s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 3m49s
android / android (push) Successful in 18m24s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 18m28s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 3m36s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 5m1s
release / apple (push) Successful in 22m56s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 5m40s
apple / screenshots (push) Successful in 18m53s
Phase 5.2 of design/encoder-recovery-hardening.md (design/linux-direct-nvenc.md). The Linux NVIDIA host encodes through libavcodec `hevc_nvenc`, which structurally cannot express `nvEncInvalidateRefFrames` — so every FEC-unrecoverable loss is a full IDR and, since the client freezes-until-reanchor, a per-loss freeze for RTT+IDR-encode. This ports the Windows raw-NVENC backend to NV_ENC_DEVICE_TYPE_CUDA over the shared CUcontext so Linux NVIDIA gets the same real RFI + F2 recovery-anchor + reset() stall lever + HDR-SEI/Main10 plumbing. New `encode/linux/nvenc_cuda.rs` (`NvencCudaEncoder`): - runtime-loaded entry table via `dlopen libnvidia-encode.so.1` (never link-time, mirroring the zerocopy::cuda libcuda loader) — one binary still starts on AMD/Intel Linux boxes and falls through to VAAPI/software; - session on the shared CUcontext (zerocopy::cuda::context()); - an encoder-owned ring of registered CUDADEVICEPTR input surfaces (zerocopy::cuda::InputSurface + a contiguous-NV12 allocator), each captured DeviceBuffer device→device copied in via the existing copy_* helpers — mirrors the libav recycled-hwframe-pool copy, so zero regression vs today; - config/RFI/anchor/reset ported from the Windows backend; sync-only (NVENC async is Windows-only, so that whole subsystem is dropped); - Main10/HDR-SEI wired but inert until a Linux P010 capture path (Phase 5.1). Wired behind PUNKTFUNK_NVENC_DIRECT (default OFF) in open_nvenc_probed; the Windows path is untouched (no shared extraction in v1). Two on-hardware `#[ignore]` smokes added. Validated on .21 (RTX 5070 Ti, driver 610.43.03): builds on Linux under ci-check, clippy-clean, full host suite 272/0, NV12 smoke (8 AUs, real invalidate_ref_frames + recovery_anchor on a P-frame) and YUV444 FREXT smoke (6 AUs, chroma_444) green; Windows compile unaffected. Owed: the client-in-the-loop matrix (RFI-survives-ABR, reset() heal, A/B vs libav) and the default flip. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
fdda7144ed |
fix(encode): harden loss-recovery correctness across host encoders (F1–F7)
Phases 1–4 of design/encoder-recovery-hardening.md — make the shipped RFI/ freeze-until-reanchor recovery honest and rebuild-safe across every backend. F1 — frame-index domain desync: the encode loop now owns a session-lifetime `au_seq`; `Encoder::submit_indexed(au_seq + inflight)` pins NVENC inputTimeStamp and AMF LTR slots to the WIRE frame index, so `invalidate_ref_frames` compares client frame numbers in the same domain and survives adaptive-bitrate rebuilds (an internal counter desynced on the first rebuild → RFI silently dead / an AMF force-ref onto a never-decoded frame). `FrameMsg.frame_index` → `Session::seal_frame_at`; GameStream gets the same via `VideoPacketizer:: packetize(.., Some(idx))`. F2 — Windows NVENC left the client frozen ~1s per loss: NVENC RFI was transparent (no anchor tag) while the session glue armed the 750ms IDR cooldown, so the freeze only lifted on the ~1s keyframe re-ask. NVENC now mirrors AMF — `pending_anchor` tags the first post-invalidate AU (the clean re-anchor P-frame) `recovery_anchor`, incl. the covering-range dedupe re-arm; the client lifts at ~RTT. F3 — speed-test probe filler burned video frame indexes: moved to its own index space (`Packetizer::alloc_probe_index` + `Session::submit_probe_frame`) with a second client reassembly window routed on FLAG_PROBE, gated on the new VIDEO_CAP_PROBE_SEQ Hello bit (mid-session probes declined for older clients). F4 — RFI range sanity cap: forward gaps wider than `packet::RFI_MAX_RANGE` (256) resync via keyframe instead of an out-of-range RFI, host- and client-side (client huge-gap → keyframe in `RfiRecovery::observe` + the pf-client-core pump). F5 — reset() parity: Windows NVENC (teardown + lazy re-init), Linux VAAPI (drop-inner), Linux NVENC (reopen from stored OpenArgs) now give the stall watchdog a heal lever instead of ending the session. F6 — sw.rs `pending: VecDeque` (was `Option`), killing the silent AU drop at capturer pipeline depth > 1. F7 — doc sweep on the RFI/anchor comments. Verified: punktfunk-core lib tests (macOS + Linux), full punktfunk-host suite on Linux (RTX 5070 Ti), Windows compile. Owed: the on-glass client matrix (F2 freeze A/B, AMF LTR spike across a bitrate rebuild). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
0dc414f197 |
docs: guide for embedding the C ABI (webOS, Xbox, Tizen examples)
ci / web (push) Successful in 1m4s
ci / docs-site (push) Successful in 1m19s
decky / build-publish (push) Successful in 33s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 40s
apple / swift (push) Successful in 3m38s
ci / bench (push) Successful in 7m5s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 9s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 9s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 9m21s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 8m25s
docker / deploy-docs (push) Successful in 35s
android / android (push) Successful in 12m34s
arch / build-publish (push) Successful in 15m3s
deb / build-publish (push) Successful in 16m18s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 15m7s
apple / screenshots (push) Successful in 19m20s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 12m17s
ci / rust (push) Successful in 23m12s
Developer integration guide for building a punktfunk client on any platform by linking punktfunk-core through its stable C ABI: what the core does vs. what the embedder supplies, build/link/cross-compile, the full client lifecycle (identity/pairing, connect ladder, video+recovery loop, audio, input, feedback planes, teardown), plus worked blueprints for webOS, Xbox (GDK), and Tizen. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
a95b518ef3 |
fix(windows): show app version on About screen + capitalize Punktfunk on licenses
ci / docs-site (push) Successful in 51s
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 9s
decky / build-publish (push) Successful in 19s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 7s
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 7s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 38s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 2m1s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 2m3s
apple / swift (push) Successful in 5m1s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 1m4s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 1m25s
ci / bench (push) Successful in 8m10s
docker / deploy-docs (push) Successful in 20s
arch / build-publish (push) Successful in 11m11s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 12m47s
android / android (push) Successful in 16m10s
deb / build-publish (push) Successful in 16m57s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 17m47s
ci / rust (push) Successful in 23m26s
apple / screenshots (push) Successful in 19m57s
The About settings card had no version at all — add an identity block (app name + "Version <CARGO_PKG_VERSION>", the workspace version) at the top, the WinUI Settings convention and matching the Apple client's "Version X" wording. Also capitalize the brand name on the licenses screen (was lowercase "punktfunk"). Verified against the pinned windows-reactor source + cargo fmt --check; full Windows link left to CI (Windows-only crate). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
f77fdee3e9 |
style(host): fix clippy doc_lazy_continuation in reconfig_allowed
ci / web (push) Successful in 49s
ci / docs-site (push) Successful in 55s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 9s
decky / build-publish (push) Successful in 17s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 7s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 7s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 8s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 7s
ci / bench (push) Successful in 5m57s
docker / deploy-docs (push) Successful in 21s
windows-host / package (push) Successful in 8m52s
android / android (push) Successful in 12m58s
arch / build-publish (push) Successful in 13m33s
deb / build-publish (push) Successful in 16m27s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 16m10s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 16m26s
apple / swift (push) Successful in 5m21s
ci / rust (push) Successful in 19m47s
apple / screenshots (push) Successful in 19m47s
New clippy (rust-1.96) flags the summary line after the 'Gated OFF for' bullet list as a lazy list-continuation under -D warnings. Add a blank /// line so it reads as its own paragraph (clippy's suggested fix), matching intent. Comment only; no behavior change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
a85be8e467 |
feat(displays): clearer virtual-display preset names + descriptions
ci / web (push) Successful in 1m0s
ci / docs-site (push) Successful in 1m15s
decky / build-publish (push) Successful in 18s
apple / swift (push) Successful in 4m55s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 31s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 7s
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 1m2s
ci / rust (push) Failing after 7m8s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 6m21s
docker / deploy-docs (push) Successful in 24s
windows-host / package (push) Failing after 8m23s
ci / bench (push) Successful in 8m44s
arch / build-publish (push) Successful in 12m26s
android / android (push) Successful in 13m37s
deb / build-publish (push) Successful in 14m23s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 12m34s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 13m17s
release / apple (push) Successful in 22m53s
apple / screenshots (push) Successful in 20m47s
"Gaming rig" actually meant a dedicated/headless box you only ever stream from, which confused users — rename it to "Headless box" and rewrite all five preset summaries to be scenario-first and shorter (the console cards already show the mechanics as badges). Updated across the host API summaries (mgmt.rs), the web console labels (en/de), and the docs table + prose. The internal preset id `gaming-rig` is unchanged (stable API / stored-policy / test contract). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
1dfcb0b2f6 |
feat(android): default-UI connect/wake modal (Material dialog)
Mirror the Apple client: the connect/wake overlay was showing the full-screen aurora takeover in the default touch UI too. Make ConnectOverlay mode-aware — gamepad/console keeps the aurora ConnectTakeover, the default UI now renders a Material 3 AlertDialog over the host grid (inert scrim; Back/buttons cancel), matching the app's other touch dialogs. Extract a shared connectCopy() so both presentations read identically; ConnectTakeover is now console-only. Screenshot scenes updated (touch phases -> modal over the host grid via shootScreen; console stays a root capture); record-mode tests green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
e87fd42cee |
feat(apple): default-UI connect/wake modal, auto-wake toggle, pixel-exact windowed streaming
Three client-UX changes that share the connect/present path (and settings files): - Connect/wake overlay is now mode-aware: the console/gamepad UI keeps the full-screen aurora takeover, while the default (touch/desktop) UI shows a Liquid Glass modal over the host grid — the takeover looked out of place there. - Add an auto-wake toggle (DefaultsKey.autoWake, default on) across macOS/iOS/tvOS Settings + the gamepad settings view; gate startSession/prepareWake and the gamepad "Wake & Connect" label on it. MAC-address learning stays always-on. - Windowed sessions now stream at the window's native pixels (Match-window default-on) so the picture is 1:1 pixel-exact instead of the presenter resampling a fixed-mode frame; fullscreen reports full-display px, also 1:1. Also lands the mid-resize aspect-fit tracking (decoded contentSize) that keeps the picture undistorted after a resize. swift build + swift test (121 tests) green; screenshot scenes verified. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
dd02e1f402 |
feat(clients): unified full-screen connect/wake takeover + iOS/tvOS Wake-on-LAN
ci / web (push) Successful in 54s
ci / docs-site (push) Successful in 1m8s
decky / build-publish (push) Successful in 20s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 7s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 11s
android / android (push) Successful in 12m23s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 8s
ci / bench (push) Successful in 6m3s
arch / build-publish (push) Successful in 12m57s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 9m40s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 7m4s
docker / deploy-docs (push) Successful in 11s
flatpak / build-publish (push) Successful in 5m57s
deb / build-publish (push) Successful in 13m26s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 3m50s
apple / swift (push) Successful in 4m31s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 14m8s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 13m44s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 4m7s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 5m9s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 5m45s
release / apple (push) Successful in 21m27s
ci / rust (push) Failing after 6m47s
apple / screenshots (push) Successful in 20m18s
Give instant feedback the moment a host is picked, and make the wake wait a full-screen takeover instead of a modal card — unified into one ConnectOverlay across every client: - android: new ConnectOverlay (aurora backdrop; Connecting / Waking / timed-out phases) replaces the tiny inline "Connecting…" row and the WakeOverlay card. The dial phase is now cancelable and hands off to the wake wait in one frame. - console (pf-console-ui): the connect/wake overlays become a full-screen aurora takeover (draw_takeover) instead of a centered card over a dim scrim; the Waking → Connecting handoff no longer blinks. - apple: new ConnectOverlay mirrors it (macOS / iOS / tvOS), replacing the per-tile connecting spinner + the WakeOverlay card; instant "Connecting…" from model.phase, and the carousel is gated inactive during the dial. Also enable Wake-on-LAN on iOS/tvOS now that the multicast entitlement is approved: enable com.apple.developer.networking.multicast and flip wakeOnLANAvailable to true on every platform (MACs were already learned from mDNS, so wake works immediately). Verified: Android compileDebugKotlin + screenshot renders; console clippy + 36 tests + rendered phases on Linux; Apple swift build + 121 tests + rendered phases. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
2271f67202 |
style: rustfmt the recovery + resize changes (Windows CI fmt check)
ci / web (push) Successful in 59s
ci / docs-site (push) Successful in 1m1s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 7s
decky / build-publish (push) Successful in 18s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 8s
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 59s
apple / swift (push) Successful in 4m26s
ci / bench (push) Successful in 5m53s
ci / rust (push) Failing after 7m35s
windows-host / package (push) Failing after 8m56s
flatpak / build-publish (push) Failing after 8m12s
arch / build-publish (push) Successful in 11m41s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 3m54s
android / android (push) Successful in 13m28s
deb / build-publish (push) Successful in 13m42s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 13m16s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 3m42s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 15m33s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 5m0s
docker / deploy-docs (push) Successful in 20s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 5m48s
release / apple (push) Successful in 25m4s
apple / screenshots (push) Successful in 19m32s
The `cargo fmt --check` step on the x86_64-pc-windows-msvc job was failing: the mid-stream loss-recovery and resize-overlay commits landed with unformatted wraps across pf-presenter, pf-client-core, punktfunk-core, pf-console-ui, and a few host files. Applied `cargo fmt`, and hand-relocated two trailing comments in session.rs (a decoded-frame note and the wrap-counter note) to their own lines so rustfmt no longer column-aligns the following comment block to a deep indent. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
89aa6767f9 |
feat(resize): scrim+spinner resize overlay in the shared presenter (Windows + GTK4)
ci / docs-site (push) Failing after 29s
ci / web (push) Successful in 43s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 9s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 8s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 9s
decky / build-publish (push) Successful in 33s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 9s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 7s
docker / deploy-docs (push) Successful in 20s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 3m52s
apple / swift (push) Successful in 4m55s
ci / bench (push) Successful in 6m37s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 4m2s
arch / build-publish (push) Successful in 12m42s
android / android (push) Successful in 12m51s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 5m7s
deb / build-publish (push) Successful in 13m4s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 13m24s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 13m56s
apple / screenshots (push) Successful in 19m31s
ci / rust (push) Failing after 39s
windows / build (x86_64-pc-windows-msvc) (push) Failing after 1m4s
flatpak / build-publish (push) Failing after 8m4s
The mid-stream Match-window trigger + Resolution tri-state already shipped on BOTH desktop clients via the session-always punktfunk-session binary (pf-presenter D1/D2, C1). This ports the last Apple-parity piece — the resize-in-progress indicator (clients/apple ResizeIndicator/ResizeIndicatorView) — into the SHARED pf-presenter overlay, so one implementation covers both the Windows and GTK4 session windows. - ResizeIndicator (run.rs): the Apple state machine in Rust — `steering` (a switch was requested) shows it, `decoded` (a frame reached the target size) clears it, `tick` times it out after 2.5 s for a switch the host rejected/capped. The live drag stays sharp; only the host's 0.3-2 s virtual-display + encoder rebuild gap is covered. A present-while-resizing path keeps the spinner animating through that frame-less gap. - DecodedImage::dimensions() (pf-client-core): the END signal — a decoded frame at the target size means the sharp new-mode picture is on glass (the accept ack alone lands ahead of the host's rebuild). Mirrors is_keyframe()'s cfg arms. - FrameCtx.resizing (pf-presenter/overlay.rs) + Skia draw (pf-console-ui): a full-screen 55% scrim + the shared rotating theme::spinner + "Resizing…" label. The overlay composites its own RGBA quad and can't sample the video to blur it as SwiftUI does, so a scrim stands in for the blur — same intent, one draw. resizing_since clocks the spinner; Drawn.resize_step defeats the damage gate so it redraws each frame. Verified on Linux: pf-presenter/pf-console-ui/session/linux-client build + clippy -D warnings clean; 8 pf-presenter tests green incl. 2 new ResizeIndicator tests. Windows session-binary compile (cfg-symmetric) + live on-glass both pending. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
7cea893db5 |
feat(recovery): wire LTR-RFI loss recovery into every client
ci / web (push) Successful in 48s
ci / rust (push) Failing after 48s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 7s
ci / docs-site (push) Successful in 1m0s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 7s
decky / build-publish (push) Successful in 17s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 9s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 11s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 11s
apple / swift (push) Successful in 4m51s
ci / bench (push) Successful in 6m13s
docker / deploy-docs (push) Successful in 20s
windows-host / package (push) Failing after 8m22s
flatpak / build-publish (push) Failing after 8m4s
arch / build-publish (push) Successful in 11m53s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 3m45s
android / android (push) Successful in 12m53s
deb / build-publish (push) Successful in 13m4s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 13m16s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 13m29s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 3m42s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 5m2s
windows / build (x86_64-pc-windows-msvc) (push) Failing after 5m29s
release / apple (push) Successful in 25m48s
apple / screenshots (push) Successful in 19m31s
Centralize the client-side loss-range detector in punktfunk-core so every embedder shares one implementation instead of re-deriving the wrapping frame-index arithmetic: - NativeClient::note_frame_index(frame_index) folds each received AU (in receive order) through RfiRecovery::observe, firing a throttled RFI request for the exact lost span [first_missing, frame_index-1] on a forward gap. A host that can RFI (AMD LTR / NVENC) re-references a known-good frame instead of paying a 20-40x IDR spike; the frames_dropped-driven keyframe path stays the backstop for when the recovery frame itself is lost. - Export request_rfi + note_frame_index over the C ABI (Apple client). - Call it from the Android (hw+sw pumps), Apple (StreamPump + Stage2Pipeline via PunktfunkConnection.noteFrameIndex), and Windows in-process pumps. Linux/Deck inherit it through pf-client-core's session pump. - Split the decision into a pure RfiRecovery::observe(frame_index, now) and add 8 unit tests: arming, contiguous runs, exact lost-range, single-frame drop, the 100ms throttle (burst-suppress then re-open), reorder stragglers, and u32 wraparound (contiguous + gap-range). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
e55ff1bb28 |
feat(recovery): clean mid-stream loss recovery — freeze-until-reanchor + AMD LTR-RFI
ci / rust (push) Failing after 53s
ci / docs-site (push) Successful in 54s
ci / web (push) Successful in 58s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 8s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 9s
decky / build-publish (push) Successful in 18s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 8s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 7s
apple / swift (push) Successful in 4m57s
ci / bench (push) Successful in 5m43s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 6m4s
docker / deploy-docs (push) Successful in 21s
windows-host / package (push) Failing after 8m42s
flatpak / build-publish (push) Failing after 8m6s
android / android (push) Successful in 11m59s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 3m59s
arch / build-publish (push) Successful in 13m20s
deb / build-publish (push) Successful in 14m36s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 14m45s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 3m44s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 13m21s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 5m1s
windows / build (x86_64-pc-windows-msvc) (push) Failing after 5m28s
release / apple (push) Successful in 25m54s
apple / screenshots (push) Successful in 19m35s
Removes the "gray frames with motion" artifact on Vulkan-Video clients and lets AMD/NVENC hosts re-anchor after loss WITHOUT a 20-40x IDR spike. Client (pf-client-core): after a reference loss the hardware decoder conceals the missing-reference deltas (on RADV, a gray plate with new motion painted over) and returns Ok. The pump now freezes on the last good picture until a clean re-anchor instead of showing the concealment — lifting on a real IDR, an intra-refresh recovery mark (2nd wave boundary), or an LTR-RFI recovery anchor (1st). The frame_index gap is the early, precise loss signal and drives an RFI request. Host recovery signals (inert unless the backend supports them): - USER_FLAG_RECOVERY_POINT — intra-refresh wave boundary (NVENC constrained GDR). - USER_FLAG_RECOVERY_ANCHOR — AMD LTR reference-frame-invalidation recovery frame. AMD LTR-RFI (encode/windows/amf.rs) — the AMD twin of NVENC RFI. AMF's AVC/HEVC API has no constrained-intra property (intra-refresh cannot heal; PSNR-proven), so the only clean-recovery lever is user LTR: mark frames as long-term references, and on loss force the next frame to re-reference the newest known-good one — a clean P-frame, not an IDR. Two rotating LTR slots, ~0.5s mark cadence, on by default for AVC/HEVC (PUNKTFUNK_NO_AMF_LTR disables). invalidate_ref_frames picks the newest LTR before the loss; a range older than the live slots falls back to a keyframe. Protocol (punktfunk-core): RfiRequest control message + NativeClient::request_rfi(). Host: RfiRequest dispatch -> invalidate_ref_frames (IDR fallback); an RFI success anchors the keyframe cooldown so the client's frames_dropped echo of the same loss is coalesced away rather than emitting a redundant IDR. Spike: synthetic NV12 GPU source for headless AMF encoder testing. Validated: core rfi_request_roundtrip; pf-client-core 31 unit tests (incl. an_rfi_anchor_lifts_immediately); punktfunk-host builds + 271 tests on Linux; punktfunk-host builds clean on Windows; real AMD iGPU spike (invalidate at frame 90 forced re-reference to LTR frame 60 — 180 frames, keyframes=1, no recovery IDR). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
890c7531d8 |
Merge branch 'midstream-resize': mid-stream resolution resize
apple / swift (push) Successful in 4m19s
ci / rust (push) Failing after 46s
ci / web (push) Successful in 51s
ci / docs-site (push) Successful in 1m2s
decky / build-publish (push) Successful in 20s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 9s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 9s
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 8s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 8s
ci / bench (push) Successful in 5m17s
arch / build-publish (push) Successful in 10m44s
docker / deploy-docs (push) Successful in 11s
android / android (push) Successful in 16m43s
windows-host / package (push) Failing after 8m29s
flatpak / build-publish (push) Failing after 8m13s
deb / build-publish (push) Successful in 11m24s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 3m51s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 4m1s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 12m24s
release / apple (push) Successful in 24m35s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 12m24s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 5m2s
windows / build (x86_64-pc-windows-msvc) (push) Failing after 5m25s
apple / screenshots (push) Successful in 19m55s
Lands the mid-stream resolution resize feature (client-driven Reconfigure so the host's virtual display + encoder follow a resized client window without a reconnect), all paths default OFF: - host hardening H1-H5 + session-binary Match window (C1) - Apple macOS/iPadOS Match-window trigger + settings (C3) and the resize overlay (blur + spinner) client UX - Windows on-glass fixes: corrective-ack actual resolution + pf-vdisplay monitor re-arrival for out-of-list mid-stream modes - Linux backend matrix + the live-reconfigure gate unit tests Validated on-glass: Windows IDD-push (.173), Linux Mutter + KWin. Android (C4) deferred; Apple full build pending on a Mac. |
||
|
|
e6fbcecdb9 |
fix(clients/windows): GUI text inputs read the live value, not a stale render snapshot
ci / web (push) Successful in 50s
ci / docs-site (push) Successful in 1m5s
decky / build-publish (push) Successful in 23s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 16s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 14s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 14s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 9s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 1m0s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 2m33s
apple / swift (push) Successful in 4m24s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 2m18s
ci / bench (push) Successful in 7m10s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 5m17s
arch / build-publish (push) Successful in 11m38s
deb / build-publish (push) Successful in 12m6s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 13m9s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 5m46s
android / android (push) Successful in 17m7s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 19m48s
docker / deploy-docs (push) Successful in 22s
ci / rust (push) Successful in 26m33s
apple / screenshots (push) Successful in 19m29s
A component() page re-renders reliably only when its props change: root wraps every screen in a stable animated border, so once the entrance tween settles the reconciler skips that unchanged-props subtree and a page's own use_state writes never force a re-render. Three text fields read their value at click time from that stranded local state: - PIN pairing sent an empty PIN, so pairing always failed with "wrong PIN, or not armed?" — the reported bug. The CLI --pair path bypasses the reactor and worked. - "Add host" Connect captured the empty mount-time address and silently did nothing (you open the modal precisely when the host isn't being discovered, so no discovery tick re-renders the page while you type). - Rename round-tripped the draft through an always-deferred AsyncSetState into a controlled text box, fighting the caret on fast typing and dropping the last character when Save was clicked before the write landed. Fix: hold each field's live value in a use_ref cell written on every keystroke and read at commit time (uncontrolled input), instead of a render-time snapshot. Rename is seeded when its target changes and no longer re-renders the whole page per keystroke. Reviewed the rest of the app (settings, speed test, library, stream, connect/request-access/waking, forget) — all driven by root-state props and wired correctly. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
f01c5e210c |
feat(resize/apple): resize overlay — blur + spinner during mid-stream resize
Make a Match-window resize deliberate instead of a stutter: blur the live stream and show a spinner while the host rebuilds its virtual display + encoder and VideoToolbox re-inits on the new-mode IDR. No new protocol — driven entirely by existing client signals. - ResizeIndicator (pure core, unit-tested): START = follower steering, END = a decoded frame at the target size, TIMEOUT = 2.5s safety net for a rejected/capped switch that never yields a new-size frame; re-arms only on a CHANGED target, not a repeated same-size drag. - MatchWindowFollower.onResizeTarget fires the instant the window differs from the live mode (deduped via lastSteered); a new onDecodedSize callback threads each new-mode IDR's coded dims through StreamPump/Stage2Pipeline → SessionPresenter → both stream views. - SessionModel gains @Published resizing (+ resizeTargeted/resizeDecoded, a tick on the 1 Hz stats timer, reset on disconnect); ContentView blurs the stream 16px and overlays ResizeIndicatorView while resizing (the 32px trust-prompt blur is unchanged and takes precedence). tvOS declares the props but never fires the follower (it drives modes via AVDisplayManager), so the overlay stays dormant there. Pure core verified on the Linux toolchain; full AppKit/UIKit build pending on a Mac. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
d294b3923c |
test(resize): extract + unit-test the live-reconfigure gate (H1 gamescope / H5 per-client-mode)
The Linux §6 on-glass matrix can validate the gamescope must-REJECT behavior only on native-gamescope hardware (the NVIDIA dev box fails headless GBM allocation — a nested Hyprland/sway/gamescope output comes up 0×0), so pin the gate down deterministically instead: extract the inline `live_reconfig_ok` decision into a pure `reconfig_allowed(compositor, per_client_mode)` and test it — gamescope rejects in every identity mode, a per-client-mode policy rejects on every backend, and all other compositors (plus the synthetic protocol-test source) with the default identity accept. Also fmt-normalizes the re_add block from the prior commit (whitespace only). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
4c18bb80ca |
feat(resize/win): mid-stream resize on-glass fixes — corrective-ack actual res + monitor re-arrival
On-glass validation on the .173 Windows IDD-push host confirmed the Reconfigure
protocol + host rebuild work end-to-end and genuinely change pixels for an
advertised mode (1920x1080 -> 1280x720: two SPS/IDR sets, ffprobe both res). It
also surfaced two gaps for out-of-EDID-list target modes, both fixed here.
Fix 2 (corrective ack carries the ACTUAL resolution): the H2/H3 corrective ack
recovered only the achieved REFRESH (interval_hz), taking width/height straight
from the request — so when a backend delivered a different RESOLUTION (Windows
pf-vdisplay falling back to its advertised mode) the client was told it got a
size it never received, and by the D2 discipline never re-asked. New
`delivered_mode(frame.{w,h}, interval)` derives the ack from the captured frame's
real dims (what the encoder opened at / the client decodes) in both the success
and rollback branches. Unit-tested.
Fix 1 (reach arbitrary mid-stream modes via monitor RE-ARRIVAL): the pf-vdisplay
driver freezes a monitor's advertised mode list at IOCTL_ADD, and IddCx exposes
no live update-modes DDI, so an in-place ChangeDisplaySettingsExW to a mode not
advertised at arrival returns DISP_CHANGE_BADMODE. The manager's mid-stream
reconfigure now REMOVEs + re-ADDs the driver monitor at the exact new mode,
reusing the slot's stable per-client id (EDID serial / ContainerId) so the OS
keeps identity + saved DPI. The rebuilt Monitor PRESERVES gen (lease/refcount
continuity) and the group restore snapshot; reisolate_after_swap re-isolates the
new target without recapturing it. Host-only — no driver change. One monitor
hotplug per switch (the design's accepted "re-arrival for everything").
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
89ff326ebf |
feat(resize/apple): Match-window mid-stream resize trigger + settings (C3)
design/midstream-resolution-resize.md Phase 2, Apple client. The stream mode follows the session window/scene: a windowed macOS window resize or an iPad Stage Manager / Split View scene change renegotiates the host's virtual display + encoder via the existing PunktfunkConnection.requestMode, so a windowed session streams native-resolution pixels instead of scaling. Decode/present need nothing — VideoToolbox recreates its session on the keyframe-derived format-description change (§1 table). - MatchWindowFollower (new): the shared D2 trigger discipline — physical pixels even-floored + clamped ≥320×200, debounce to resize-end, ≥1 s between requests, skip a size equal to the live mode, request each distinct size at most once (stops re-asking a rejected size / looping on a host rollback). Pure normalize/request core is unit-tested (MatchWindowTests). - macOS StreamLayerView: fed from layoutPresenter() (bounds → convertToBacking), guarded to once-in-a-window. - iOS StreamViewController: fed from viewDidLayoutSubviews (bounds × render scale); iOS-only (iPhone fullscreen no-ops, tvOS uses AVDisplayManager). - Settings: "Match window" toggle in the Stream mode section (iOS + macOS), DefaultsKey.matchWindow, read per session by the follower. Verified on a Linux Swift 6.1.2 toolchain (the app target needs AppKit/UIKit, unavailable here): the real MatchWindowFollower.swift type-checks in Swift 5 mode against a connection stub, and the pure discipline + the follower's decision path pass a standalone harness (drag-settle + grow → exactly two switches, refresh preserved, no re-request loop). A full build + on-device run (macOS window, iPad Stage Manager) remains for a Mac. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
d0d9bd5bfb |
feat(resize): mid-stream resolution resize — host hardening (H1–H5) + session-binary Match window (C1)
design/midstream-resolution-resize.md Phase 0 + Phase 1. Host (Phase 0): - H1/H5: per-backend Reconfigure acceptance gate — reject for gamescope (all sub-modes; a resize must never relaunch the title) and under the per-client-mode identity policy (a resize would resolve a different display slot). Synthetic stays reconfigurable on purpose (the protocol test source; the C-ABI roundtrip test rides it). Plus a 500 ms host-side min-interval backstop against Reconfigure spam. - H2: rollback/corrective ack — the data plane reports the mode actually live after a failed rebuild (or a refresh the backend capped) through a reconfig_result channel; the control task forwards it as a second accepted Reconfigured so the client's mode slot self-corrects. - H3: live stats mode — SendStats reads a packed AtomicU64 (w|h|hz) updated on every switch instead of latching the session-start mode. - H4: registry::retire(gen) — a mode-switch rebuild force-releases the superseded Linux display, so linger/forever keep-alive policies don't accumulate kept monitors at stale modes. VirtualOutput carries pool_gen (fresh AND reused) and the Pipeline tuple threads it to the switch arm. Client (Phase 1, default off): - Settings: match_window policy + persisted last window size; exposed as the Resolution tri-state (Native / Match window / explicit) in the Skia console, GTK and WinUI settings pages. - pf-presenter: window opens at the persisted size; Hello mode follows the window's pixel size; D2 trigger discipline (400 ms debounce to resize-end, ≥1 s spacing, even-floor + ≥320×200 clamp, each distinct size requested at most once — covers rejects and host rollbacks) as a pure, unit-tested decision; HUD line + title refresh on a switch. - Session binary wires both --connect and --browse paths; the WinUI shell is session-always, so this covers Windows too. Verified: workspace tests + clippy green; synthetic --remode end-to-end; live session-binary run (window at persisted 1000×600 → Hello 1000×600@60). On-glass per-backend matrix (Mutter/KWin/gamescope-reject, keep-alive accumulation) still pending before any default flip. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
64b9d11ee6 |
fix(ci/windows): reclaim runner disk before building
ci / web (push) Successful in 1m2s
ci / docs-site (push) Successful in 1m2s
apple / swift (push) Successful in 4m58s
ci / bench (push) Successful in 6m47s
android-screenshots / screenshots (push) Successful in 2m58s
windows-host / package (push) Successful in 14m30s
decky / build-publish (push) Successful in 16s
ci / rust (push) Successful in 18m31s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 4m6s
android / android (push) Successful in 12m26s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 3m58s
web-screenshots / screenshots (push) Successful in 2m45s
linux-client-screenshots / screenshots (push) Successful in 7m33s
docker / deploy-docs (push) Successful in 19s
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 6s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 7s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 7s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 5m35s
arch / build-publish (push) Successful in 12m58s
deb / build-publish (push) Successful in 14m8s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 12m35s
release / apple (push) Successful in 28m12s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 14m43s
apple / screenshots (push) Successful in 18m28s
flatpak / build-publish (push) Failing after 8m17s
A full Windows CI pass writes ~50 GB of cargo target output into the shared C:\t (x64) / C:\t-a64 (arm64) scratch dirs on the intentionally-small (100 GB) windows-amd64 runner. Left to accumulate across runs, that overflowed the disk and every build died with "no space on device" (os error 112) — bytemuck_derive, cc, bindgen, windows, tracing-subscriber, fs4 all failing mid-compile, taking down pf-vdisplay/host builds. ensure-windows-toolchain.ps1 already runs first in every Windows job, so reclaim disk there before provisioning/building: call the runner-baked reclaimer (unom/infra installs C:\Users\Public\act-runner\clean-runner-disk.ps1 + a scheduled task) in threshold mode so THIS job starts with headroom regardless of when that task last ran, and keep incremental caches warm when there's room. A small inline fallback covers a runner not yet re-baked with the reclaimer. The whole step is best-effort — a cleanup hiccup never fails the build. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>v0.9.2 |
||
|
|
ca61477c3c |
docs(roadmap): surround 5.1/7.1 is shipped, not planned
ci / web (push) Successful in 43s
ci / docs-site (push) Successful in 1m10s
decky / build-publish (push) Successful in 27s
apple / swift (push) Successful in 4m20s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 39s
ci / bench (push) Successful in 6m53s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 9s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 6m0s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 1m30s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 6m56s
android / android (push) Successful in 12m10s
docker / deploy-docs (push) Successful in 23s
arch / build-publish (push) Successful in 14m55s
deb / build-publish (push) Successful in 16m5s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 12m59s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 14m24s
ci / rust (push) Successful in 23m13s
apple / screenshots (push) Successful in 19m9s
5.1 and 7.1 surround now works end to end (host encodes multichannel via multistream Opus; native clients render >2 channels via AudioDec::Surround). Move it to Shipped + the at-a-glance table, and narrow the Planned entry to the genuinely-future object-based spatial audio work. Corrects the stale 'every path is stereo end to end / no client renders it yet' claim. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
68a1ec41c2 |
Merge pull request 'Rumble envelopes (0xCA v2) + 0.9.2' (#3) from rumble-envelopes into main
audit / bun-audit (push) Successful in 13s
ci / web (push) Successful in 43s
ci / docs-site (push) Successful in 1m10s
audit / cargo-audit (push) Successful in 2m16s
apple / swift (push) Successful in 4m51s
ci / bench (push) Successful in 6m19s
android-screenshots / screenshots (push) Successful in 2m51s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 1m4s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 1m22s
decky / build-publish (push) Successful in 21s
arch / build-publish (push) Successful in 10m40s
flatpak / build-publish (push) Successful in 5m58s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 2m29s
deb / build-publish (push) Successful in 11m47s
ci / rust (push) Successful in 23m27s
docker / deploy-docs (push) Successful in 9s
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 8s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 9s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 10s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 9s
linux-client-screenshots / screenshots (push) Successful in 8m30s
web-screenshots / screenshots (push) Successful in 2m40s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 2m58s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 13m51s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 12m19s
android / android (push) Successful in 11m50s
release / apple (push) Successful in 28m25s
apple / screenshots (push) Successful in 19m37s
windows-host / package (push) Successful in 8m29s
|
||
|
|
4873e8925d |
fix(apple/test): unwrap optional leaseSeconds in RumbleTuningTests
ci / web (pull_request) Successful in 51s
windows / build (aarch64-pc-windows-msvc) (pull_request) Successful in 59s
ci / docs-site (pull_request) Successful in 1m1s
windows / build (x86_64-pc-windows-msvc) (pull_request) Successful in 1m17s
apple / swift (pull_request) Successful in 4m50s
apple / screenshots (pull_request) Has been skipped
ci / bench (pull_request) Successful in 6m18s
android / android (pull_request) Successful in 9m4s
ci / rust (pull_request) Successful in 18m21s
RumbleTuning.leaseSeconds returns TimeInterval? (nil for the no-lease sentinel); XCTAssertEqual(_, _, accuracy:) needs a non-optional Double. Coalesce with .nan so a nil (which must not happen for a real ttl) still fails the assertion. Test-only — the production Swift built clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
01d10f46ea |
chore(release): bump workspace version to 0.9.2
ci / docs-site (pull_request) Successful in 53s
ci / web (pull_request) Successful in 57s
windows / build (aarch64-pc-windows-msvc) (pull_request) Successful in 1m1s
windows / build (x86_64-pc-windows-msvc) (pull_request) Successful in 1m17s
apple / swift (pull_request) Failing after 4m46s
apple / screenshots (pull_request) Has been skipped
ci / bench (pull_request) Successful in 5m26s
android / android (pull_request) Successful in 9m39s
ci / rust (pull_request) Successful in 18m50s
Release 0.9.2 — self-terminating rumble envelopes (0xCA v2) make "stuck rumble" inexpressible on the wire and retire the per-client staleness guesses, plus the Windows game-abandoned-residual stop and the Steam Deck Game-Mode HDR fix (bind gamescope's Wayland socket). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
73c911cae4 |
feat(rumble): host-authoritative self-terminating envelopes (0xCA v2)
Rumble was level-triggered, unbounded state on a lossy channel: a non-zero level meant "buzz until further notice", healed only by the host re-sending state every 500 ms, and every client guessed when the host had died with its own magic timeout (SDL 1.5 s, Apple 1.6 s, Android up to 60 s). A lost stop, a reordered start, or a dead host could drone the motor for seconds. Make "stuck rumble" inexpressible on the wire. The 0xCA datagram grows a length-tolerant tail — [u8 seq][u16 ttl_ms] — so it self-terminates: the host authorizes a level for at most ttl_ms and renews it (~120 ms) while it holds, letting an abandoned one lapse client-side. seq is a per-pad wrapping reorder gate (reusing GamepadSnapshot::seq_newer) so a reordered stale start can't re-light a stopped motor. Decoders read the first 7 bytes as a plain level and ignore the tail, so no wire-version bump: an old client renders a new host's levels, and a new client falls back to its prior staleness heuristic against an old host (ttl = None). All four generation pairings render correctly. - core: encode_rumble_datagram_v2 / decode_rumble_envelope (datagram.rs); the client demux applies the seq gate then forwards (pad, low, high, Option<ttl>); next_rumble is unchanged (drops ttl), next_rumble_ttl keeps it; ABI adds punktfunk_connection_next_rumble2 + PUNKTFUNK_RUMBLE_NO_TTL, ABI_VERSION 4->5 (WIRE_VERSION unchanged — the tail is backward-compatible). - host (punktfunk1.rs): the flat 500 ms refresh becomes a renewal loop that bumps seq + stamps a fresh TTL on active pads and drains a short post-stop zero burst, then goes quiet. Hatches: PUNKTFUNK_RUMBLE_ENVELOPE=0 (legacy v1 + flat refresh, a bisect switch), PUNKTFUNK_RUMBLE_TTL_MS (clamped [150, 5000]). - renderers honor the TTL as their playback duration/deadline and keep their old heuristic only for a legacy (ttl=None) update: pf-client-core (the Deck haptic keep-alive is now deadline-bounded so it can't sustain a host-stopped rumble), clients/windows (SDL duration), android (JNI packs the lease out-of-band in bit 48 so any u16 ttl is unambiguous; Kotlin createOneShot(ttl)), apple (RumbleRenderer.envelopeDeadline + nextRumble2; sessionStaleSeconds demoted to the legacy fallback). - tests: codec round-trip + tail tolerance + seq-gate reorder (Rust); the probe asserts the v2 tail arrived under PUNKTFUNK_TEST_FEEDBACK; the Apple loopback asserts ttlMs round-trips end to end; RumbleTuning lease-decision cases. The host-side idle-timeout from the previous commit is defense in depth on the game side; this is the guarantee on the client side. Design: punktfunk-planning/design/rumble-envelope-plan.md. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
19e9828e8d |
fix(host/windows): force off a stale rumble residual the game abandoned
XInput vibration is level-triggered — it persists until the game sets it to zero — so a game that latches a rumble and then stops calling XInputSetState (a residual left at a menu/loading screen, or a plain forgotten stop) drones to the client forever (measured: a stuck (0,512) resent every 500 ms for 5.5 minutes). A real controller stops when the app stops driving it; mirror that. Keyed on game ACTIVITY (any SET_STATE, even an unchanged one), so a rumble the game keeps asserting is never cut — only an abandoned residual is; kept above SDL's ~2 s resend so an SDL-driven host game refreshes the activity clock before it fires. This is the game-facing half of the rumble-stop story; the wire-facing half is the self-terminating envelope model in the following commit. They compose: this bounds a game-abandoned rumble at the host, envelopes bound a host-abandoned rumble at the client. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
a1e79a0d69 |
fix(flatpak): bind gamescope's Wayland socket for Deck Game-Mode HDR
The Vulkan-layer env vars alone left hdr10_format=None on a Deck OLED: the FROG gamescope WSI layer loads but must open a Wayland connection to gamescope's private socket ($GAMESCOPE_WAYLAND_DISPLAY = gamescope-0) to negotiate HDR10 via the gamescope_swapchain protocol. The Deck runs games as X11 clients, so --socket=wayland binds nothing and that socket never enters the sandbox → the layer silently can't reach the compositor → PQ tone-mapped to SDR, badge dark. Bind xdg-run/gamescope-0 (as chiaki-ng does); with the layer path + ENABLE_GAMESCOPE_WSI + the socket, the surface offers HDR10 and the presenter's existing HDR10 swapchain path engages — no client code change. Harmless off-Deck (the layer no-ops with no gamescope socket to bind). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
313f194c63 |
fix(ci/flatpak): the DNS failures are runner-load packet drops, not nsswitch — widen the retry budget
ci / web (push) Successful in 49s
ci / docs-site (push) Successful in 1m9s
decky / build-publish (push) Successful in 17s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 8s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 8s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 7s
ci / bench (push) Successful in 5m45s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 8s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 5m20s
arch / build-publish (push) Successful in 11m35s
docker / deploy-docs (push) Successful in 22s
android / android (push) Successful in 13m7s
deb / build-publish (push) Successful in 12m36s
flatpak / build-publish (push) Failing after 8m5s
ci / rust (push) Successful in 17m55s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 12m17s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 12m15s
apple / swift (push) Successful in 5m13s
apple / screenshots (push) Successful in 21m49s
Live-debugged on home-runner-1: confirmed the dnf install in Tooling does NOT actually rewrite /etc/nsswitch.conf (no authselect trigger fires), so the nss-resolve sed from 68b5376f/5f687a70 was never the actual fix. gitea-runner-fleet on this box is a shared, resource-capped fleet (3 replicas, --cpus 5/--memory 7g each, on 16c/24G) serving punktfunk AND several other orgs' repos concurrently. A push to main fans out ~8 punktfunk workflows at once on top of that other traffic, and the box's Docker embedded DNS resolver (127.0.0.11) drops UDP lookups under the combined load — exactly what retry.sh's own header already documented. Manually dispatching this job while the box was idle succeeded instantly, with or without the sed. retry.sh's 5-attempt (~100s) budget isn't always enough to outlast a synchronized multi-org burst; bumped the three flathub-facing calls (remote-add, install-deps-only, download-only) to 10 attempts (~9min). Verified end-to-end on a live re-run (run 8993) after this change: full success including publish + OSTree deploy. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
55472495a4 |
Merge pull request 'feat(ci): accept deploy_host input in deploy-services for target-agnostic deploys' (#2) from feat/deploy-host-input into main
ci / web (push) Successful in 1m4s
ci / docs-site (push) Successful in 1m19s
ci / bench (push) Successful in 6m38s
decky / build-publish (push) Successful in 16s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 7s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 8s
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 8s
arch / build-publish (push) Successful in 12m5s
android / android (push) Successful in 14m38s
docker / deploy-docs (push) Successful in 18s
ci / rust (push) Successful in 18m22s
deb / build-publish (push) Successful in 14m4s
apple / swift (push) Successful in 4m38s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 14m33s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 14m37s
apple / screenshots (push) Successful in 19m53s
|
||
|
|
9e6bd790a3 |
feat(ci): accept deploy_host input so deploy-all can target a fresh box
ci / web (pull_request) Successful in 52s
ci / docs-site (pull_request) Successful in 1m2s
ci / bench (pull_request) Successful in 7m44s
android / android (pull_request) Successful in 12m47s
apple / swift (pull_request) Successful in 4m42s
ci / rust (pull_request) Successful in 18m33s
apple / screenshots (pull_request) Has been skipped
When unom/infra deploy-all provisions a new unom-1, it dispatches this deploy with the just-created box IP. Falls back to the DEPLOY_HOST secret on push-triggered runs, so existing behavior is unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
68b5376fb8 |
fix(ci/flatpak): reapply nss-resolve DNS fix after dnf pulls systemd upgrade
ci / web (push) Successful in 49s
ci / docs-site (push) Successful in 55s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 10s
decky / build-publish (push) Successful in 18s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 7s
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 6s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 59s
flatpak / build-publish (push) Failing after 2m12s
ci / bench (push) Successful in 6m49s
docker / deploy-docs (push) Successful in 21s
apple / swift (push) Successful in 4m35s
android / android (push) Successful in 12m53s
arch / build-publish (push) Successful in 14m4s
deb / build-publish (push) Successful in 15m28s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 13m33s
ci / rust (push) Successful in 18m16s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 15m30s
apple / screenshots (push) Successful in 18m50s
The earlier fix (
|
||
|
|
35d97ae6ac |
feat(windows): parallel virtual displays — proto v3 ring binding, manager slot map, group topology (W0–W3)
windows-drivers / probe-and-proto (push) Successful in 41s
ci / web (push) Successful in 1m2s
ci / docs-site (push) Successful in 1m7s
apple / swift (push) Successful in 1m11s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 8s
decky / build-publish (push) Successful in 15s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 9s
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
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 38s
windows-drivers / driver-build (push) Successful in 1m46s
ci / bench (push) Successful in 6m35s
docker / deploy-docs (push) Successful in 20s
windows-host / package (push) Successful in 9m37s
deb / build-publish (push) Successful in 13m48s
arch / build-publish (push) Successful in 14m21s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 2m24s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 13m34s
android / android (push) Successful in 15m45s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 2m20s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 1m18s
ci / rust (push) Successful in 18m48s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 1m41s
release / apple (push) Successful in 19m30s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 16m49s
flatpak / build-publish (push) Failing after 2m9s
apple / screenshots (push) Successful in 19m3s
design/windows-parallel-virtual-displays.md (display-management Stage 7 / §6.6): N simultaneously-live pf-vdisplay monitors, one sealed ring each, every idd-push-security invariant preserved per-ring. - proto v3: SharedHeader._pad → target_id — the ring NAMES its monitor, host-stamped before the magic; the driver publisher refuses a cross-bound ring via the shared, unit-tested frame::check_attach (new DRV_STATUS_BIND_FAIL — the gamepad pad_index validation applied to frames, invariant #10); the host's wait_for_attach surfaces the refusal loudly and self-checks its own stamp. - manager: the one-monitor MgrState becomes a slot map keyed by the client's identity slot (0 = anonymous/GameStream); per-slot reconnect + dead-WUDFHost preempts, slot-scoped begin_idd_setup (a different identity is an admission question, never a preempt), ONE device-level watchdog pinger, per-slot /display/state + /display/release. - group topology: isolate_displays_ccd takes the managed target SET (a sibling slot is never deactivated); SavedConfig + the DDC/PnP axes move to the group record (first-in captures, last-out restores); desktop layout via CCD source origins from the pure layout::arrange (auto-row default, manual pins win), re-applied on create + reconfigure. - admission: the Windows separate→reject override now sits behind the PUNKTFUNK_WIN_SEPARATE=1 validation hatch (the wedge it guarded is structurally gone — a second identity gets its own monitor + ring; default flips in W5 after soak); max_displays and NVENC session-unit budgets decline an unaffordable display AT admission; kick_dwm_compose is process-globally throttled and per-display — cursor jump + 35 ms dwell (a sub-tick jump composes nothing; DWM reads dirties from current state at the next vsync tick). On-glass on the RTX box: V1/V2/V4/V5/V6/V9 green — two paired clients on two monitors streaming ~60 fps each with zero mismatches and zero bind failures, churn-hammer clean (no 0x80070490), per-ring mode-change recreate leaves the sibling untouched, typed budget rejection, fault-injected cross-bind refused loudly with the sibling undisturbed. V7: WUDFHost-kill shared fate is clean; in-process device recovery is a known follow-up (the retired-never-closed control handles block the adapter cycle — reset-pf-vdisplay.ps1 recovers). DWM composes two IDD monitors concurrently at 60 fps — the plan's load-bearing unknown, answered yes. Also carries the client-HDR EDID forwarding that shared this working tree (Hello::display_hdr → AddRequest luminance tail → the monitor's CTA-861.3 HDR block, PUNKTFUNK_CLIENT_PEAK_NITS hatch) and the Deck client fixes (40 ms rumble keep-alive with 1-LSB jitter, HDR self-diagnosing presenter warn, flatpak HDR env). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
979e38523b |
Merge pull request 'ci: build-free deploy-services.yml for docs + flatpak server' (#1) from deploy-services-workflow into main
ci / bench (push) Failing after 30s
ci / rust (push) Failing after 34s
ci / docs-site (push) Successful in 58s
decky / build-publish (push) Successful in 32s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 9s
ci / web (push) Successful in 1m13s
apple / swift (push) Successful in 1m16s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 8s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 8s
apple / screenshots (push) Successful in 13m22s
arch / build-publish (push) Successful in 15m18s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 16m3s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 15m34s
docker / deploy-docs (push) Successful in 21s
deb / build-publish (push) Successful in 21m49s
android / android (push) Successful in 25m21s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 24m8s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 24m16s
|