refactor: drop milestone names + consolidate clients; loss-recovery & rumble fixes
apple / swift (push) Failing after 40s
audit / cargo-audit (push) Failing after 1m12s
windows-msix / package (push) Successful in 1m37s
windows / build (push) Successful in 1m14s
android / android (push) Successful in 4m48s
ci / web (push) Successful in 27s
ci / rust (push) Successful in 4m21s
ci / docs-site (push) Successful in 31s
ci / bench (push) Successful in 4m39s
decky / build-publish (push) Successful in 11s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 19s
deb / build-publish (push) Successful in 6m3s
flatpak / build-publish (push) Successful in 4m13s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 8m15s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 8m16s
docker / deploy-docs (push) Successful in 18s

Two bodies of work in one commit (the rename moved files the fixes also touched).

Naming/structure cleanup (pre-launch):
- Host modules m3.rs->punktfunk1.rs, m0.rs->spike.rs; CLI m3-host->punktfunk1-host,
  m0->spike; bare `punktfunk-host` now prints help. Types M3Options/M3Source->
  Punktfunk1Options/Punktfunk1Source.
- Clients consolidated out of crates/ into clients/: punktfunk-client-rs->
  clients/probe (crate punktfunk-probe), client-linux->clients/linux,
  client-windows->clients/windows, punktfunk-android->clients/android/native
  (crate punktfunk-client-android; kept [lib] name=punktfunk_android so the JNI
  contract is unchanged). crates/ now holds only core + host.
- Milestone codes M0-M4 purged from code/CLI/CLAUDE.md/README/docs/docs-site,
  kept only in docs/implementation-plan.md. docs/m2-plan.md->
  docs/gamestream-host-plan.md. CI/gradle/flatpak paths updated.

Client loss-recovery (video froze and never recovered after a brief drop):
- Export punktfunk_connection_frames_dropped through the C ABI (the core already
  tracked it for the client keyframe-recovery loop; it was never reachable from
  the ABI clients). Regenerated punktfunk_core.h.
- Apple (StreamPump + Stage2Pipeline) and Android (decode.rs) now poll
  frames_dropped and request a keyframe when it climbs -- the same loss-driven
  recovery Linux/Windows already had. Under infinite GOP the decoder silently
  conceals reference-missing frames, so the decode-error trigger rarely fires.

Apple rumble robustness (worked then went spotty -- DualSense + Xbox):
- Add CHHapticEngine stopped/reset handlers (rebuild on app background / audio
  interruption / server reset) and drop the permanent `broken` latch on a
  transient drive failure; latch only when the controller truly has no haptics.
- Surface swallowed SDL set_rumble errors on Linux/Windows + diagnostic logging.

Verified: cargo build/clippy/fmt --workspace, C-ABI harness, header drift.
Not runnable on this box (verify in CI): Gitea workflows, gradle/Android,
flatpak, Swift/decky.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-18 21:03:55 +00:00
parent 1faa6c6ad4
commit 9c8fa9340c
110 changed files with 534 additions and 341 deletions
+8 -8
View File
@@ -7,7 +7,7 @@ the gotchas. Read it top to bottom, then start at **Phase 1** (de-risk Reactor f
## Status — WinUI 3 client landed (2026-06-15)
The client is implemented in `crates/punktfunk-client-windows` (binary `punktfunk-client`) and is
The client is implemented in `clients/windows` (binary `punktfunk-client`) and is
**build + clippy + fmt green on `x86_64-pc-windows-msvc`** (built on the dev VM). It is the **WinUI 3**
client this doc planned: native chrome (host list, settings, in-app SPAKE2 PIN pairing) + the video on
a **`SwapChainPanel`**, all in pure Rust.
@@ -44,9 +44,9 @@ a **`SwapChainPanel`**, all in pure Rust.
## What we're building
A native Windows client that connects to a punktfunk/1 host (`serve --native` / `m3-host`), decodes
A native Windows client that connects to a punktfunk/1 host (`serve --native` / `punktfunk1-host`), decodes
HEVC, presents it low-latency, plays Opus audio, and captures local mouse/keyboard/gamepad to send
back — i.e. the Windows analogue of the **GTK4 Linux client** (`crates/punktfunk-client-linux`),
back — i.e. the Windows analogue of the **GTK4 Linux client** (`clients/linux`),
which is the architectural template. The Windows client is close to a 1:1 port of the Linux client
with the platform layers swapped.
@@ -73,7 +73,7 @@ with the platform layers swapped.
- **Trust = shared client identity + SPAKE2 PIN pairing + TOFU** (port `trust.rs`; same identity
files/logic as the other native clients).
## The reference: `crates/punktfunk-client-linux/src/`
## The reference: `clients/linux/src/`
Port these files (near 1:1; only the platform layers change):
@@ -144,11 +144,11 @@ Windows client should mirror it:
`SwapChainPanel` and presents a cleared D3D11 swapchain into it. Confirm the windows-rs Reactor
version/API (PR #4479) and `ISwapChainPanelNative::SetSwapChain` interop. If Reactor proves too
raw, the fallback is `winit` + a child HWND swapchain, but try Reactor first per the decision.
2. **Crate scaffold.** `crates/punktfunk-client-windows`, `[target.'cfg(windows)'.dependencies]`:
2. **Crate scaffold.** `clients/windows`, `[target.'cfg(windows)'.dependencies]`:
`punktfunk-core { path, features=["quic"] }`, `windows`, the Reactor crate, `ffmpeg-next`, `opus`,
`sdl3`, `mdns-sd`, `anyhow`, `tracing`. Mirror `crates/punktfunk-client-linux/Cargo.toml`.
`sdl3`, `mdns-sd`, `anyhow`, `tracing`. Mirror `clients/linux/Cargo.toml`.
3. **Connect + control plane.** Port `session.rs` + `trust.rs`; validate headless against the 4090
box (`m3-host`/`serve --native`) — handshake, PIN/TOFU, plane counters — before any UI/decode.
box (`punktfunk1-host`/`serve --native`) — handshake, PIN/TOFU, plane counters — before any UI/decode.
4. **Decode + present.** FFmpeg D3D11VA → `SwapChainPanel`. SDR (8-bit BGRA) first, then **P010 +
HDR colorspace** (see the HDR section).
5. **Audio.** WASAPI render + Opus decode (port `audio.rs`).
@@ -158,7 +158,7 @@ Windows client should mirror it:
## Key references
- **Template:** `crates/punktfunk-client-linux/src/*` (the client to port).
- **Template:** `clients/linux/src/*` (the client to port).
- **Apple HDR present** (the pattern to mirror): `clients/apple/Sources/PunktfunkKit/{VideoDecoder,
MetalVideoPresenter,Stage2Pipeline}.swift` — in-band PQ detection, P010 decode, EDR present.
- **Core client API:** `crates/punktfunk-core/src/client.rs` (`NativeClient`).