9537efdcd54c546fb148c3fbd48b0d80da6cc756
52 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
0ce2e37faf |
refactor(host/windows): clean up DDA path + add a proper Windows service
Final cleanup after the DDA-parity work, plus an end-user service to replace the PsExec/VBS/scheduled-task launch chain. Cleanup (behavior-preserving): - sudovda.rs: drop the dead legacy GDI isolate_displays/restore_displays (CCD is the sole isolation path), the always-empty Monitor.isolated field, and the vestigial reassert_isolation + PUNKTFUNK_ISOLATE_DISPLAYS knob; fix stale comments. - dxgi.rs: downgrade leftover debug warns/infos (DuplicateOutput1 retry, FALLBACKS, hook-hits, AcquireNextFrame idle timeout) to debug!; remove the PUNKTFUNK_NO_CURSOR per-frame test knob. Windows service (src/service.rs, `punktfunk-host service`): - SCM supervisor (windows-service crate) that duplicates its LocalSystem token, retargets it to the active console session, and CreateProcessAsUserW's the host there (Sunshine/Apollo model) — relaunching on exit and console session switch, inside a kill-on-close job object so a service crash never orphans the host. - install/uninstall/start/stop/status subcommands: one elevated `service install` registers an auto-start LocalSystem service + firewall rules + a default host.env. - Config moves to %ProgramData%\punktfunk\host.env; config_dir() now resolves to %ProgramData%\punktfunk on Windows (replacing the APPDATA=C:\Users\Public hack), with a PUNKTFUNK_CONFIG_DIR override. Logs land in %ProgramData%\punktfunk\logs\. - merged_env_block (shared with the WGC helper) now also carries RUST_LOG. - docs/windows-service.md + scripts/windows/host.env.example; windows-host.md updated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
3e2888de26 |
docs(apollo): mark GSO #4 (GameStream Windows USO) done
apple / swift (push) Successful in 54s
windows-msix / package (push) Successful in 1m31s
android / android (push) Successful in 2m29s
windows / build (push) Successful in 1m3s
ci / web (push) Successful in 36s
ci / docs-site (push) Successful in 35s
ci / rust (push) Successful in 4m18s
deb / build-publish (push) Successful in 2m3s
decky / build-publish (push) Successful in 13s
ci / bench (push) Successful in 4m22s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 15s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 2m30s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 2m35s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 22s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 2m14s
flatpak / build-publish (push) Failing after 5m17s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 7m45s
docker / deploy-docs (push) Successful in 18s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 7m17s
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
ba4e9a8672 |
docs(apollo): mark cursor #13 done, reclassify #21 as already-handled
apple / swift (push) Successful in 54s
ci / rust (push) Failing after 1m21s
ci / web (push) Successful in 27s
ci / docs-site (push) Successful in 29s
android / android (push) Failing after 5m44s
ci / bench (push) Failing after 3m26s
decky / build-publish (push) Successful in 12s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 6s
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 3s
deb / build-publish (push) Successful in 2m5s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 8m3s
docker / deploy-docs (push) Successful in 21s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 7m50s
#13 (two-pass alpha+XOR cursor) implemented in capture/dxgi.rs. #21 (composite moved cursor without a new desktop frame) is already handled: DXGI returns S_OK for pointer-only updates so punktfunk recomposites in present_acquired; the original premise (stutter via timeout) was incorrect. Adds status banner + per-item resolution notes in Part 4 and Part 3. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
183ddd5fa1 |
docs: Apollo (Sunshine fork) vs punktfunk architecture map + transfer backlog
apple / swift (push) Successful in 54s
android / android (push) Failing after 36s
ci / web (push) Failing after 25s
ci / docs-site (push) Successful in 34s
ci / rust (push) Failing after 3m18s
ci / bench (push) Failing after 3m9s
decky / build-publish (push) Successful in 12s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Failing after 38s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 5s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 2m50s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 2m17s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 26s
docker / deploy-docs (push) Has been skipped
deb / build-publish (push) Successful in 7m46s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Failing after 5m2s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Failing after 6m39s
Map Apollo's architecture for future agents and compare against punktfunk, with a deep-dive on the Windows host (the focus area). Produced by the apollo-vs-punktfunk multi-agent workflow; every claim carries file:line into both codebases. Contents: Apollo architecture map + Apollo->punktfunk file index; subsystem parity; a reference-grade Windows-host deep-dive (DXGI/WGC capture, cursor compositing, HDR, NVENC-on-D3D11, SendInput/ViGEm, SudoVDA, SYSTEM/secure desktop); and a prioritized 96-item improvement backlog (89 Windows-host, 24 high-severity). Top confirmed Windows gaps: GameStream TLS accepts any client cert (verify_client_cert returns assertion()), no NVENC reference-frame invalidation, SudoVDA watchdog ignores its ioctl result, absolute-mouse mapping discards the virtual-desktop rect. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
ec2907fc32 |
perf(host/windows): SendInput retry-on-failure model (two-process step 2)
apple / swift (push) Successful in 54s
android / android (push) Failing after 0s
ci / rust (push) Failing after 0s
ci / docs-site (push) Failing after 0s
ci / bench (push) Failing after 0s
deb / build-publish (push) Failing after 0s
ci / web (push) Failing after 1s
decky / build-publish (push) Failing after 0s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Failing after 1s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Failing after 0s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Failing after 1s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Failing after 0s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Failing after 1s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Failing after 0s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Failing after 0s
docker / deploy-docs (push) Has been skipped
The injector reattached the input desktop (OpenInputDesktop + SetThreadDesktop, two syscalls) before EVERY event. Now it stays bound to its desktop and only reattaches on a SendInput short write (the input desktop switched into UAC/lock) + retries once — Sunshine's model. No steady-state per-event overhead; still follows the desktop across the secure boundary, serving both desktops. Validated on the RTX 4090 (host as SYSTEM): client-rs --input-test injected for ~6s with no "blocked desktop" errors. Completes all 6 steps of the two-process secure-desktop build; only a real-UAC user smoke test remains. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
1e8f210948 |
docs(windows-secure-desktop): steps 1/3/4/5/6 live-validated; soak results
apple / swift (push) Successful in 55s
android / android (push) Failing after 34s
ci / web (push) Failing after 5s
ci / docs-site (push) Failing after 1s
ci / bench (push) Failing after 0s
deb / build-publish (push) Failing after 0s
decky / build-publish (push) Failing after 1s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Failing after 0s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Failing after 1s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Failing after 0s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Failing after 0s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Failing after 1s
docker / deploy-docs (push) Has been skipped
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Failing after 0s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Failing after 0s
ci / rust (push) Failing after 2m50s
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
4edfcd4b43 |
feat(host/windows): two-process mux test toggle + live-validate step 5
PUNKTFUNK_SECURE_TEST_PERIOD_MS=N drives a square-wave secure/normal toggle in
virtual_stream_relay (instead of the real DesktopWatcher), to exercise the
mid-session helper↔DDA mux without a live UAC/lock. Gated behind the env var,
in the style of PUNKTFUNK_VIDEO_DROP / PUNKTFUNK_FEC_PCT.
Live-validated on the RTX 4090 (host as SYSTEM): with a 4s toggle the mux
switched secure(DDA)↔normal(WGC relay) cleanly 5× in one session and the client
decoded 308 HEVC Main-10 frames continuously across every switch — the
wait-for-IDR latch held with no decode break. The real Winlogon DDA capture is
pre-proven by the single-process secure path (
|
||
|
|
140209bbfc |
feat(host/windows): two-process secure-desktop step 5 — DDA mux on Winlogon
`virtual_stream_relay` now muxes the AU source by input desktop. A DesktopWatcher (SYSTEM-only Winlogon-name poll) drives it: the user-session WGC helper relay feeds the normal (Default) desktop; the host's OWN DDA capturer+encoder — opened lazily on the first secure transition, on the same SudoVDA target with a no-op keepalive (the host still holds the real isolation owner) — captures the secure (Winlogon: UAC/lock/login) desktop that WGC can't see. Every switch latches "wait for IDR" and forces the now-active source to emit a keyframe (the two encoders keep independent infinite-GOP state, so the client must resume on an IDR); returning to the helper also drains its stale buffered AUs first. Reconfigure drops the stale-target DDA; keyframe requests route to the live source. Send path (FEC/seal/paced-send) unchanged. Also: wgc_relay gains try_recv (drain on switch-back); open_dda takes dims as args (avoids a closure borrow of the reassigned cur_mode); the forward! macro returns bool with `break 'outer` at the call site (no in-macro label hygiene). cfg-gated windows-only. Live validation (UAC switch over a session) pending. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
5c2bcbc2a2 |
docs(windows): secure-desktop two-process design + WGC impersonation attempt (vestigial)
apple / swift (push) Successful in 55s
android / android (push) Has been cancelled
ci / rust (push) Has been cancelled
ci / web (push) Has been cancelled
ci / docs-site (push) Has been cancelled
ci / bench (push) Has been cancelled
deb / build-publish (push) Has been cancelled
decky / build-publish (push) Has been cancelled
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Has been cancelled
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Has been cancelled
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Has been cancelled
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Has been cancelled
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Has been cancelled
docker / deploy-docs (push) Has been cancelled
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
Validated design for adding secure-desktop (UAC/lock/login) coverage on top of the shipped WGC animation fix. Key verified constraint: WGC won't activate under SYSTEM (0x80070424) even with thread-level ImpersonateLoggedOnUser, and DDA+SendInput on Winlogon need LOCAL_SYSTEM — so one process can't do both. Architecture: SYSTEM host (QUIC + SudoVDA + DDA-secure + SendInput + AU mux) + a USER-session WGC helper (CreateProcessAsUser) that relays encoded Annex-B AUs over a named pipe; the host muxes helper-AUs (normal desktop) vs its own DDA encoder (secure desktop), switched by a desktop-name watcher. No shared GPU texture (rejected — MIC/keyed-mutex pain); just AU bytes. docs/windows-secure-desktop.md has the ordered, box-testable steps. The impersonate_active_user() in wgc.rs is kept as a harmless no-op (under a user-token process WTSQueryUserToken fails → no impersonation → WGC works natively); it does NOT make WGC work under SYSTEM (the two-process design uses a real user process for WGC instead). + Win32_System_RemoteDesktop. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
3b3940dc8c |
docs(windows-client): correct the WinUI 3 record — reactor IS used (PR #4499)
apple / swift (push) Successful in 54s
android / android (push) Failing after 1m41s
ci / rust (push) Failing after 56s
ci / web (push) Successful in 28s
ci / docs-site (push) Successful in 28s
deb / build-publish (push) Successful in 2m26s
decky / build-publish (push) Successful in 12s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 6s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 5s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 30s
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 20s
ci / bench (push) Successful in 4m37s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 8m33s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 8m24s
docker / deploy-docs (push) Successful in 6s
The winit-commit docs claimed "Reactor rejected, no SwapChainPanel hatch" — that was wrong. windows-rs PR #4499 added the SwapChainPanel widget; the client now uses WinUI 3 via windows-reactor. Update CLAUDE.md M4, the bootstrap-doc status banner (reactor integration: pinned git dep, CARGO_WORKSPACE_DIR, App-SDK build.rs, LL-hook stream input), and the docs-site clients page (WinUI 3, launch-and-pick-a-host). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
296b976b8f |
feat(windows-client): SDL3 gamepads + docs — full stage-1 parity, MSVC-green
apple / swift (push) Successful in 54s
audit / cargo-audit (push) Failing after 1m19s
android / android (push) Failing after 2m22s
ci / web (push) Successful in 41s
ci / docs-site (push) Successful in 33s
ci / bench (push) Successful in 1m56s
deb / build-publish (push) Successful in 3m28s
ci / rust (push) Successful in 7m23s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 6s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
decky / build-publish (push) Successful in 12s
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 18s
flatpak / build-publish (push) Successful in 3m59s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 5m21s
docker / deploy-docs (push) Successful in 7s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 4m43s
Adds the SDL3 gamepad service (near-verbatim port of the GTK client's — SDL3 is cross-platform) and wires it into the winit app: per-session capture (buttons/axes, DualSense touchpad + motion 0xCC), feedback (rumble, lightbar, raw DualSense effects), single-pad-forwarded model with auto pad-type from the physical controller. Built from source on Windows (no system SDL3). - gamepad.rs: GamepadService (app-lifetime SDL thread) attach/detach on session connect/end; auto_pref resolves "Automatic" to the attached pad's type. - app.rs: hold the service, attach on Connected, detach on Ended/Failed/close. Also simplify the keydown path (drop the identical if/else arms). - main.rs: start the service for the windowed path, resolve GamepadPref from settings + the physical pad. Build gotcha documented + fixed in the dev loop: SDL3's build-from-source MSVC precompiled-header chokes on the `ü` in the dev box's username embedded in the cargo registry path (MSB8084/C4828) — CARGO_HOME must be an ASCII path (C:\Users\Public\.cargo). Unrelated to our code. Docs: CLAUDE.md M4 + docs/windows-client-bootstrap.md status banner (winit-not-Reactor rationale, CARGO_HOME gotcha, what's pending) + docs-site clients.md "Windows desktop client (in development)". Crate is build + clippy + fmt + test green on x86_64-pc-windows-msvc. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
0a3b92d994 |
fix(host/windows): HDR cursor brightness (203-nit) + probe-before-adopt recovery; windows-client bootstrap doc
apple / swift (push) Successful in 55s
android / android (push) Successful in 2m43s
ci / web (push) Successful in 31s
ci / docs-site (push) Successful in 37s
ci / bench (push) Successful in 1m35s
ci / rust (push) Successful in 7m7s
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 4s
deb / build-publish (push) Successful in 2m18s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 5m33s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 5m33s
docker / deploy-docs (push) Successful in 18s
- HDR cursor: sRGB→linear decode + scale to HDR graphics white (PUNKTFUNK_HDR_CURSOR_NITS, default 203 per BT.2408) in the FP16 cursor composite, so it's no longer ~2.5x too dim. SDR path unchanged; the masked-color (I-beam) inversion blend left unscaled. Cursor cbuffer widened 16→32 + bound to PS. (Validated live: cursor now correct brightness in HDR.) - Secure-desktop recovery: recreate_dupl now PROBES the rebuilt duplication with a 50ms AcquireNextFrame and only adopts it when live (Ok/WAIT_TIMEOUT); a born-lost one (immediate ACCESS_LOST) is dropped so the caller repeats the last frame + retries. Plus reassert_isolation() re-detaches physical displays on every recovery (re-routing the secure/HDR desktop to the virtual output, the delta a fresh reconnect has). NOTE: the born-lost ACCESS_LOST storm in HDR is NOT yet resolved by these — still under investigation (animations/secure-UI/cursor-trail in HDR remain). - docs/windows-client-bootstrap.md: handoff for the native Windows Rust client (windows-rs Reactor + WinUI 3 SwapChainPanel, D3D11VA decode, WASAPI audio, SDL3 input; ports crates/punktfunk-client-linux; 10-bit/HDR present; dev boxes + gotchas). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
f4b4a6c1e4 |
feat(host/windows): native res, cursor, secure-desktop capture, windowless SYSTEM launch
apple / swift (push) Successful in 52s
ci / rust (push) Failing after 36s
ci / web (push) Successful in 31s
android / android (push) Successful in 1m52s
ci / docs-site (push) Successful in 29s
ci / bench (push) Successful in 1m39s
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 4s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 3s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
deb / build-publish (push) Successful in 3m19s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 5m15s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 4m57s
docker / deploy-docs (push) Successful in 17s
Live-validated Mac <-> RTX 4090 at the display's native 5120x1440@240: - Resolution: set_active_mode enumerates the IDD's advertised modes and sets the requested resolution at the best supported refresh (keeps 5120x1440@240; no more silent fallback to the 1080p OS default when an exact mode is briefly unavailable). - Bitrate auto-cap: NVENC init probes and steps the average bitrate down to the GPU's codec-level max so a high client bitrate connects (matches the Linux host; we do not split NVENC sessions). - Mouse cursor: DXGI duplication excludes the HW cursor; capture the pointer shape/position (GetFramePointerShape) and GPU-composite it before NVENC. Color cursors alpha-blend; masked-color (the text I-beam) uses an INV_DEST_COLOR inversion blend so the caret inverts the screen and shows on any background (no black box); monochrome handled too. - Secure desktop (lock / login / UAC): run as SYSTEM in the interactive session, follow the input desktop via SetThreadDesktop, and on the WinSta switch recreate the D3D11 device and re-resolve the virtual output's GDI name from the stable SudoVDA target id (the name changes across the topology rebuild; the old failure hunted the stale \\.\DISPLAYn and dropped). ACCESS_LOST / INVALID_CALL / device-removed are recoverable, and a mid-stream resolution change is followed (capturer + NVENC re-init at the new size). isolate_displays detaches other monitors so Winlogon renders to the virtual output. One real session recovered 1012 desktop switches and completed cleanly. Windows-only backends; Linux/macOS unaffected. Builds clean on x86_64-pc-windows-msvc. Deployment (windowless SYSTEM launch via PsExec + hidden VBScript) documented in docs/windows-host.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
5b3d5689bf |
docs(windows-host): SendInput mouse injection live-validated on RTX 4090
apple / swift (push) Successful in 53s
audit / cargo-audit (push) Failing after 1m13s
android / android (push) Failing after 1m44s
ci / web (push) Successful in 28s
ci / rust (push) Successful in 1m10s
ci / docs-site (push) Successful in 31s
ci / bench (push) Successful in 1m39s
decky / build-publish (push) Successful in 12s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 4s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 5s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
flatpak / build-publish (push) Failing after 2s
deb / build-publish (push) Failing after 2m36s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 5m21s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 5m20s
docker / deploy-docs (push) Successful in 6s
The Session-1 cursor tracked the client's absolute diagonal sweep across the virtual desktop (baseline (2560,720) → (0,0) → diagonal climb → (6359,719)) — SendInput mouse injection confirmed. Keyboard shares the same SendInput primitive (not separately asserted; needs a focused field). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
4b6eaa8cf3 |
docs(windows-host): native 4090 build loop + the gotchas that bit us
apple / swift (push) Successful in 53s
ci / rust (push) Failing after 1m13s
ci / web (push) Successful in 31s
android / android (push) Failing after 1m54s
ci / docs-site (push) Successful in 32s
ci / bench (push) Successful in 1m47s
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 4s
flatpak / build-publish (push) Failing after 2s
deb / build-publish (push) Failing after 2m53s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 5m16s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 4m58s
docker / deploy-docs (push) Successful in 18s
Record the on-box native build path (fast iteration vs build-on-VM): full MSVC C++ tools incl. CRT libs (a partial VS install → LNK1104; fix via the GUI, headless setup.exe fails), build from an ASCII path (non-ASCII username → LNK1201 PDB write fail), nasm/cmake/NVENC import lib + CMAKE_POLICY_VERSION_MINIMUM. Validated: native build → 720p60 NVENC, 174/174 frames, p50 2.5 ms. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
a7c5d4256c |
docs(windows-host): NVENC live-validated on RTX 4090 + real-GPU box notes
apple / swift (push) Successful in 54s
android / android (push) Failing after 1m51s
ci / rust (push) Successful in 1m22s
ci / web (push) Successful in 28s
ci / docs-site (push) Successful in 31s
ci / bench (push) Successful in 1m46s
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 3s
flatpak / build-publish (push) Failing after 2s
deb / build-publish (push) Failing after 2m56s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 5m5s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 4m49s
docker / deploy-docs (push) Successful in 6s
Mark DXGI capture + NVENC as live-validated (720p60/1080p60), record the real-GPU test box (192.168.1.174), the Session-0→Session-1 Interactive scheduled-task launch, the VM-built-exe-runs-with-driver-DLL trick, and the SudoVDA-output-under-the-rendering-GPU gotcha. Refresh remaining gaps (SendInput in-session, ViGEm input/rumble, Moonlight-on-GPU, static-frame pacing). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
2bca89c555 |
feat(host/windows): Steam library auto-discovery on Windows
apple / swift (push) Successful in 53s
android / android (push) Failing after 44s
ci / web (push) Successful in 40s
ci / docs-site (push) Successful in 32s
ci / rust (push) Failing after 2m28s
decky / build-publish (push) Successful in 44s
ci / bench (push) Failing after 1m22s
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 4s
flatpak / build-publish (push) Failing after 2s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Failing after 37s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Failing after 45s
deb / build-publish (push) Failing after 2m46s
docker / deploy-docs (push) Successful in 10s
The Steam `LibraryProvider` keyed off `$HOME` + Linux paths, so the game library was empty on Windows. Add Windows discovery: the default Steam install dirs under Program Files (`ProgramFiles(x86)`/`ProgramFiles`/ `ProgramW6432`), with games on other drives picked up via each root's `libraryfolders.vdf` — whose Windows values are backslash-escaped, so unescape `\\` → `\`. The existing root-scan/dedup logic is shared via a new `steam_roots_existing` helper. The custom store (mgmt JSON CRUD) was already cross-platform; only Steam auto-discovery was Linux-only. Not yet covered: a non-default Steam install dir (the registry `Valve\Steam\InstallPath`). Degrades gracefully — no Steam → empty list. clippy -D warnings + library tests green on Windows and Linux. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
66f579461f |
feat(host/windows): GameStream (Moonlight) audio on Windows — stereo
ci / web (push) Successful in 27s
ci / docs-site (push) Successful in 30s
android / android (push) Failing after 53s
apple / swift (push) Successful in 54s
ci / rust (push) Failing after 47s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
ci / bench (push) Successful in 1m48s
decky / build-publish (push) Successful in 12s
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 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
flatpak / build-publish (push) Failing after 2s
deb / build-publish (push) Failing after 3m12s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Failing after 1m17s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Failing after 1m18s
docker / deploy-docs (push) Failing after 17s
`serve` gave Moonlight clients no audio on Windows: the GameStream audio stream thread was Linux-only (a non-Linux stub errored). Widen the stereo path to Windows — the encode/RTP/AES-CBC/hand-rolled-RS(4,2)-FEC logic is platform-neutral and already live-validated byte-identical on Linux, and it now runs over the WASAPI capturer + the (already cross-platform) `opus` crate. The cfg gates go from `linux` to `any(linux, windows)`; only the surround path stays Linux-only because its libopus *multistream* encoder needs `audiopus_sys` (a Linux dep) — on Windows a surround request fails cleanly with a "use stereo" error. Linux stays byte-identical (the `SessionEncoder::Surround` variant and its match arm keep `#[cfg(linux)]`, so Linux compiles exactly as before). Verified: clippy -D warnings + host test suite green on both x86_64-pc-windows-msvc (73/73) and Linux (78/78). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
9c61b03101 |
feat(host/windows): ViGEm rumble back-channel + Windows clippy clean
android / android (push) Failing after 21s
ci / web (push) Failing after 10s
ci / docs-site (push) Failing after 1s
ci / bench (push) Failing after 0s
deb / build-publish (push) Failing after 0s
decky / build-publish (push) Failing after 1s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Failing after 0s
docker / deploy-docs (push) Has been skipped
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Failing after 1s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Failing after 0s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Failing after 1s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Failing after 0s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Failing after 0s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Failing after 1s
flatpak / build-publish (push) Failing after 0s
apple / swift (push) Successful in 53s
ci / rust (push) Failing after 2m35s
Wire the host→client rumble path on Windows, the analogue of the Linux uinput EV_FF read loop: a game's force-feedback on the virtual Xbox 360 pad is delivered by ViGEm's notification API (`request_notification` → `spawn_thread`, gated by the crate's `unstable_xtarget_notification` feature). A per-pad background thread stores the latest motor levels; `pump_rumble` relays changes to the client on the universal 0xCA plane (motors scaled 0..255 → 0..65535). Dropping the target aborts the notification, so the thread exits with the session. Live verification still needs a physical pad. Also fix the Windows backends' clippy debt — these modules are cfg- excluded from Linux CI, so `clippy -D warnings` never saw them, and the VM's rustc 1.96 clippy is stricter on shared code than the CI image: - dxgi: manual checked division → checked_div().map_or - sendinput: `x = x | y` → `x |= y` - sudovda: `.then(|| ptr)` → `.then_some(ptr)` - m3 pick_compositor: drop the needless early return (match form) - m3 resolve_compositor: Windows arm is a tail expr, not `return` All Windows backends now build + clippy clean (default and --features nvenc); Linux unaffected (fmt/clippy/check green). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
b8a1b7e469 |
feat(host/windows): host→client Opus audio — vendored libopus on MSVC
apple / swift (push) Successful in 53s
android / android (push) Failing after 35s
ci / docs-site (push) Successful in 29s
ci / bench (push) Failing after 26s
decky / build-publish (push) Failing after 3s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Failing after 0s
ci / rust (push) Failing after 30s
ci / web (push) Successful in 27s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Failing after 0s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Failing after 0s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Failing after 0s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Failing after 1s
docker / deploy-docs (push) Has been skipped
flatpak / build-publish (push) Failing after 0s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Failing after 0s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Failing after 0s
deb / build-publish (push) Failing after 47s
The `m3` audio_thread (desktop capture → Opus 48 kHz stereo 5 ms CBR → AUDIO_MAGIC datagrams) now runs on Windows, fed by the WASAPI loopback capturer. The `opus` crate vendors libopus via `audiopus_sys` + cmake (no system lib / vcpkg), so it builds on MSVC — moved into a `cfg(any(linux, windows))` deps table and widened the audio_thread cfg to match (the stub now only covers other targets, e.g. macOS). Build note: CMake 4 rejects libopus's old `cmake_minimum_required`; set `CMAKE_POLICY_VERSION_MINIMUM=3.5` when building the host on Windows. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
38cce754bd |
docs: mark session-aware follow-ups #2 (switch input) + #3 (vout primary) resolved
android / android (push) Failing after 21s
ci / web (push) Failing after 3s
ci / docs-site (push) Failing after 1s
ci / bench (push) Failing after 0s
deb / build-publish (push) Failing after 0s
decky / build-publish (push) Failing after 1s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Failing after 0s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Failing after 1s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Failing after 0s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Failing after 1s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Failing after 1s
apple / swift (push) Successful in 53s
ci / rust (push) Failing after 2m33s
docker / deploy-docs (push) Has been skipped
flatpak / build-publish (push) Failing after 0s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Failing after 1s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Failing after 0s
Both landed in
|
||
|
|
5cf7b561b5 |
docs(windows-host): gamepad done; audio/rumble/GPU-validation remaining
apple / swift (push) Successful in 53s
android / android (push) Failing after 36s
ci / rust (push) Failing after 46s
ci / web (push) Successful in 31s
ci / docs-site (push) Successful in 29s
ci / bench (push) Successful in 1m35s
decky / build-publish (push) Successful in 13s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 4s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 3s
flatpak / build-publish (push) Failing after 2s
deb / build-publish (push) Successful in 3m17s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Failing after 1m16s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Failing after 1m42s
docker / deploy-docs (push) Successful in 7s
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
1a9a733f02 |
docs(windows-host): all backends landed; NVENC build/run + dev-loop notes
apple / swift (push) Successful in 53s
android / android (push) Failing after 2m2s
ci / rust (push) Failing after 52s
ci / web (push) Successful in 27s
ci / docs-site (push) Successful in 30s
ci / bench (push) Successful in 1m35s
decky / build-publish (push) Successful in 10s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 4s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 5s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 3s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
flatpak / build-publish (push) Failing after 2s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Failing after 1m14s
deb / build-publish (push) Successful in 3m4s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Failing after 2m52s
docker / deploy-docs (push) Successful in 18s
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
26741feada |
feat(host/windows): SudoVDA virtual-display backend (control path)
Windows VirtualDisplay backend driving SudoVDA (the Apollo IDD) via its DeviceIoControl IOCTL protocol: open by interface GUID, ADD at the client's exact WxH@Hz (mode baked into the IOCTL, no EDID seeding), mandatory watchdog ping thread, QueryDisplayConfig name resolution, RAII Drop -> REMOVE. Wired behind the existing VirtualDisplay trait (open()/probe() Windows arms). Validated live on the GPU-less VM (standalone + via the trait, env-gated test): version 0.2.1, ADD 1920x1080@60 -> target, watchdog hold, REMOVE. Monitor activation into a WDDM path (-> capturable \\.\DisplayN) needs a real GPU and is deferred with capture/NVENC. docs/windows-host.md updated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
9775794ba5 |
docs: known limitations + follow-ups for the session-aware host
apple / swift (push) Successful in 53s
android / android (push) Successful in 1m48s
ci / rust (push) Failing after 55s
ci / web (push) Successful in 26s
ci / docs-site (push) Successful in 27s
ci / bench (push) Successful in 1m35s
decky / build-publish (push) Successful in 12s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 4s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
flatpak / build-publish (push) Failing after 2s
deb / build-publish (push) Successful in 2m12s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 5m19s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 5m23s
docker / deploy-docs (push) Successful in 9s
Capture the deliberately-parked items after live-validating the session-aware backend selector on the Bazzite F44 box (Desktop KDE + Gaming both at the client's resolution, warm reuse, Feature B mid-stream switch both directions). Top follow-ups: (1) F44 gamescope teardown corrupts the GPU context (try SIGKILL teardown, else keep the managed session warm); (2) mid-stream-switch input is flaky until a reconnect (portal opens before the systemd/D-Bus activation env settles — fix: import-environment on switch); (3) the KWin virtual output isn't set primary. Plus polish: input-loss window on switch, the recovered NVENC invalid-param log, the 4090 HEVC ~800Mbps cap, restore-guard/keep-warm interaction, and promoting Feature B from opt-in to default. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
c9e90d4a59 |
docs(windows-host): host-first plan + SudoVDA protocol + no-GPU strategy
ci / docs-site (push) Successful in 31s
apple / swift (push) Successful in 1m17s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 7s
ci / web (push) Successful in 27s
ci / rust (push) Successful in 2m11s
ci / bench (push) Successful in 1m36s
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 5s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 3s
deb / build-publish (push) Successful in 2m26s
docker / deploy-docs (push) Successful in 18s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 4m56s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 5m5s
Rewrite the scoping doc into a concrete implementation plan: locked decisions (host-first, SudoVDA virtual display, pure-Rust windows-rs+Reactor client linking core directly, FFmpeg/D3D11VA decode), the SudoVDA IOCTL control protocol, the no-GPU dev strategy, the Windows-specific structural issues (interactive session, clock epoch, no IDD audio), and the phased plan. Step 0 (compile on MSVC) marked done. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
6351d516e0 |
feat(host/library): game library API — Steam adapter + custom store
ci / web (push) Successful in 28s
ci / docs-site (push) Successful in 30s
apple / swift (push) Successful in 1m15s
ci / bench (push) Successful in 1m35s
ci / rust (push) Successful in 2m7s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 6s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 15s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 3s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 5s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
deb / build-publish (push) Successful in 2m19s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 4m53s
docker / deploy-docs (push) Successful in 18s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 4m31s
A new `library` module + four mgmt endpoints surface the host's games to clients
(plan: "surface the user's games"). An adapter layer (`LibraryProvider`) so future
stores (Heroic/Epic, GOG, Lutris) slot in behind one uniform `GameEntry`.
- SteamProvider: reads the LOCAL Steam install — no Steam Web API key, no network.
Installed titles from steamapps/appmanifest_<appid>.acf; extra library folders
(incl. paths with spaces) from libraryfolders.vdf; candidate roots cover classic,
Flatpak and Deck layouts, canonicalized + deduped (the .steam/{steam,root}
symlinks all fold to one). Runtimes/redistributables (Proton, Steam Linux Runtime,
Steamworks Common, SteamVR) filtered out. Artwork = the public Steam CDN by appid
(portrait/hero/logo/header), fetched directly by the client.
- Custom store: ~/.config/punktfunk/library.json, write-then-rename persisted,
CRUD'd via the API — the "create custom entries via the admin web UI" requirement.
- API (under /api/v1, OpenAPI-documented + checked in): GET /library (all stores
merged, sorted), POST /library/custom, PUT/DELETE /library/custom/{id}.
- `punktfunk-host library` subcommand dumps the resolved library as JSON (diagnostic,
mirrors `openapi`).
Validated live against the real Steam library on the Bazzite box: 89 appmanifests →
78 games (11 tools filtered), correct titles/sort, and the CDN art URLs return 200.
5 unit tests for the VDF/ACF parsing, tool filter, art URLs, custom mapping.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
99b4de32ee |
feat(pairing): delegated approval (§8b-1) — approve an unpaired device from the console
ci / web (push) Failing after 40s
ci / rust (push) Successful in 1m6s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 13s
apple / swift (push) Successful in 1m20s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
ci / docs-site (push) Failing after 46s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 18s
docker / deploy-docs (push) Successful in 16s
An identified-but-unpaired device that knocks on a pairing-required host is now
held as a pending request the operator approves from the web console — pairing it
with no PIN fetched out of band — instead of a flat reject.
- core: Hello gains an optional trailing device name (len u8 || UTF-8, ≤64,
same trailing-back-compat pattern as compositor/gamepad/bitrate). client-rs
--name sends it; the connector sends None (fingerprint-derived label).
- native_pairing: in-memory pending queue (note_pending dedups by fingerprint,
evicts the least-recently-active past a 32 cap, 10-min TTL); approve_pending
pins the fingerprint, deny drops it. Names are sanitized (strip control/ANSI/
bidi — untrusted wire input); add()/remove() roll back in-memory on a persist
failure; pairing clears any stale pending knock.
- m3: the require_pairing gate records the knock (sanitized label) before
rejecting; anonymous (certless) clients record nothing.
- mgmt: GET /native/pending, POST /native/pending/{id}/approve (optional {name})
and /deny; OpenAPI + tests; docs/api/openapi.json regenerated.
- web: a "Waiting for approval" section on the Pairing page (live-poll, Approve/
Deny, error-surfaced via QueryState); en+de strings.
- Also completes an in-progress NativeClient Sync refactor (receivers behind
per-plane mutexes) that was left half-applied in the tree.
Adversarially reviewed (4 lenses + 3-vote verify); the confirmed findings are
fixed here. Validated live on the GNOME box: knock (with a wire name, and a
malicious ANSI/bidi name that got neutralized) → pending → approve → the same
identity streams real video. Full workspace tests + clippy + fmt green; web tsc
clean. Roadmap §8b-1 marked done; §8b-2 (peer-push approval) is the client
follow-up. See docs-site pairing page.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
e586961e0b |
docs(site): make docs-site the knowledge base — status tracker + setup guides
ci / rust (push) Has been cancelled
Per the new docs workflow (docs-site = KB layer; repo docs/ keeps design notes): - Add a canonical Status & Progress tracker (status.md): milestones, per-box live state, and a dated progress log — the go-forward place to track progress. - Add setup guides: GNOME/Mutter host (gnome-box — Secure Boot MOK enroll, the libnvidia-gl EGL fix, autologin, screen-lock disable, appliance unit), headless KDE box, and Bazzite host (ujust input group, gamescope session, gotchas). - Roadmap is now canonical in docs-site (synced the skew-handshake section 12 update); removed the repo docs/roadmap.md copy and repointed README to docs-site. - Nav (meta.json) + landing cards updated; site builds (bun run build). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
05bc9ab22c |
feat(latency): wall-clock skew handshake for cross-machine latency measurement
ci / rust (push) Has been cancelled
ClockProbe/ClockEcho on the QUIC control stream — 8 NTP-style rounds right after Start; the min-RTT sample gives the host-client clock offset (clock_offset_ns estimator in punktfunk-core). The client adds the offset to its receive instant before differencing against the AU pts_ns, so the capture->reassembled latency percentiles are valid across machines (skew_corrected=true), not just same-host. Back-compat: an old host that doesn't answer the probe times out and the client falls back to a shared-clock assumption (skew_corrected=false). Host adds one ClockProbe dispatch arm in the control task; the client runs clock_sync after Start, before the --remode/--speed-test tasks take the stream. Validated cross-LAN (GNOME box -> dev box): offset ~ -1.57 ms (reproducible), rtt ~140 us, p50 1.30 ms skew-corrected capture->reassembled — the offset is exactly the systematic error the handshake removes. Unit tests for the message codecs and the min-RTT offset estimator. Roadmap §12: skew handshake done; remaining for true glass-to-glass is the Apple client present-stamp (decode->present) plus the host render->capture term. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
4fff4641bb |
feat(discovery): native-protocol LAN auto-discovery over mDNS
ci / rust (push) Has been cancelled
Both the unified host (serve --native) and standalone m3-host now advertise the native punktfunk/1 service over mDNS (_punktfunk._udp) — the analogue of the GameStream _nvstream._tcp advert. TXT records carry proto, the host cert fingerprint (fp, the value clients pin), the pairing requirement (pair=required|optional), and the host id. New crate::discovery module, wired into m3::serve so both host entry points get it; best-effort, never blocks streaming (--connect always works). Client gains `punktfunk-client-rs --discover [SECS]`: browses the LAN and prints each host (name, addr:port, pairing, fingerprint), then exits. Apple clients browse the same service natively via NWBrowser (service type + TXT keys are the contract). Validated cross-LAN: the dev box discovered the GNOME-box appliance (pair=required) and a standalone synthetic host (pair=optional); fingerprint and pairing state correct in both. Also refresh the now-stale sendmmsg caveat in the bitrate doc (batched/paced send landed + validated to 1 Gbps) and mark the encode|send thread split done in §12. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
761ccace25 |
docs(roadmap): §12 glass-to-glass latency — quick wins landed, bigger bets scoped
ci / rust (push) Has been cancelled
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
2557ce1ee5 |
docs(roadmap): §11 1 Gbps+ data plane — foundation landed, batched send next
ci / rust (push) Has been cancelled
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
d39ad478bb |
docs(roadmap): §9 speed test + bitrate — host/protocol/ABI done, client UI left
ci / rust (push) Has been cancelled
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
6425f9995f |
docs(roadmap): §10 HDR parked (upstream compositor blocker) + Bazzite dynamic-resolution landed
ci / rust (push) Has been cancelled
§10: HDR/10-bit is blocked at the capture source, not our stack — gamescope's PipeWire
node is hardcoded 8-bit (BGRx/NV12; confirmed in src/pipewire.cpp on the box's c31743d
build), issue #2126 open+unstarted; PipeWire >=1.6 needs Fedora 44 (Bazzite F44 is
testing-only with a confirmed NVIDIA Game-Mode crash, so a rebase clears only the
PipeWire wall). The realistic route is KWin MR !8293 (HDR PipeWire capture, draft),
i.e. the desktop path. Records the settled constraints (NVENC 10-bit max, HDR⟹HEVC
Main10, AV1 can't HDR on VideoToolbox) + the ready-to-build downstream design.
Also notes the landed Bazzite dynamic-resolution work (host-managed gamescope-session
at the client's exact res+refresh,
|
||
|
|
4781933507 |
docs(roadmap): §9 client→host network speed test (bitrate prerequisite)
ci / rust (push) Has been cancelled
A bandwidth probe over the punktfunk/1 data path so a user-settable bitrate can be informed by what the network actually sustains (throughput/loss/jitter), surfaced in the client UI + web console. Reuses the existing Session/FEC plumbing. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
57f7e32c24 |
docs(roadmap): §8a done (mandatory pairing); split §8b into host+web / peer layers
ci / rust (push) Has been cancelled
§8a (require native pairing by default, serve --open) shipped + deployed. §8b (delegated approval) refined into §8b-1 (host pending-requests + mgmt endpoints + web Approve/Deny — achievable now) and §8b-2 (peer push to a paired Device A — needs the native/Apple client UI). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
12cf2e4e16 |
docs: refresh README/CLAUDE status; roadmap pairing-hardening + SudoVDA Windows
ci / rust (push) Has been cancelled
- README: replace the stale M0/M2-in-flight status with reality — M1 hardened, M2 GameStream host live to stock Moonlight, M3 punktfunk/1 validated, M4 Apple first light, web console + unified host; FFmpeg 7/8; Bazzite-deployed. Layout adds web/, packaging/, native_pairing, dualsense. - CLAUDE: protocol-growth item now reflects the unified host + web-console native pairing (done) and flags the next steps; layout updated. - roadmap §7 Windows: de-risked via SudoVDA (the Sunshine Virtual Display Adapter) — no self-signed kernel IDD needed; the virtual-display backend drops XL→M. - roadmap §8 (new) Pairing & trust hardening: mandatory PIN pairing by default (TOFU-open is insecure on a LAN) + delegated pairing approval (an already-paired device approves a new one, no out-of-band PIN). - windows-host.md: SudoVDA path throughout (status, table, phasing, effort M not L). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
19666ba57e |
feat(host): unified host + native pairing over the management API
`serve --native` now runs the GameStream host AND the native punktfunk/1 (QUIC) host in ONE process, sharing a single NativePairing handle with the management API — so native pairing is operable from the web console instead of journalctl. - gamestream::serve gains a native_port: spawns crate::m3::serve in the same runtime and passes the shared NativePairing to mgmt::run. Validated live: one process binds both RTSP 48010 and QUIC 9777. - mgmt API: new `native` endpoints — GET /native/pair (status), POST /native/pair/arm (mint a fresh, time-limited PIN to DISPLAY), DELETE /native/pair (disarm), GET/DELETE /native/clients (list/unpair). GameStream-only hosts report enabled:false. OpenAPI regenerated (checked-in doc + drift test). - main.rs: serve --native / --native-port flags. The native host arms pairing on demand (the operator reads the PIN from the console; the SPAKE2 ceremony is host-shows-PIN). New mgmt + native_pairing tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
59edeedf07 |
feat(dualsense): Phase C/D/E — virtual DualSense routing + 0xCC/0xCD planes + C ABI
ci / rust (push) Has been cancelled
PUNKTFUNK_GAMEPAD=dualsense now routes a session's gamepad through a real virtual
DualSense (UHID + hid-playstation) end to end:
- host: a `PadBackend` enum (m3.rs) selects `GamepadManager` (uinput xpad, default)
or the new `DualSenseManager` (dualsense.rs) per session. The manager keeps each
pad's full DsState so touchpad + motion (rich-input plane) persist across
button/stick frames, and services the !Send /dev/uhid fd only on the input thread
(which cycles <=4ms, so the GET_REPORT init handshake completes).
- feedback: `service()` now returns `DsFeedback { hidout, rumble }`. Motor rumble
stays on the universal 0xCA plane (so non-DualSense clients still feel it; manager
dedups change); lightbar / player LEDs / adaptive-trigger effects ride the new
0xCD HID-output plane (host->client) as `HidOutput`.
- rich input: touchpad contacts + motion ride the 0xCC plane (client->host) as
`RichInput`, applied via `DualSenseManager::apply_rich` (merged with button state;
touch normalized 0..65535 -> the touchpad resolution).
- connector + C ABI: `NativeClient::next_hidout` / `send_rich_input`, exported as
`punktfunk_connection_next_hidout` (-> PunktfunkHidOutput) and
`punktfunk_connection_send_rich_input` (<- PunktfunkRichInput); header regenerated.
- reference client: `--rich-input-test` drives the DualSense touchpad + motion and
logs the 0xCD feedback that comes back.
Validated live on-box: a synthetic-source m3-host + client-rs created the real
kernel DualSense, drove 0xCC, and decoded 12 live 0xCD events (the kernel's actual
lightbar/trigger init reports) with the data plane unaffected (600/600 frames).
Adversarial review fixes folded in: the input loop no longer skips the rich drain +
feedback pump on a dropped gamepad event, and the touch contact id is clamped to its
slot. Remaining: the Apple client renders triggers/rumble on a real DualSense.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
e5b15353c7 |
docs: scope advanced (audio-driven) DualSense haptics — NO-GO for now
ci / rust (push) Has been cancelled
4-agent feasibility read converged on three independent walls, any one fatal:
- host capture needs a kernel rebuild (CONFIG_USB_DUMMY_HCD off → no UDC for an
f_uac2 composite gadget; everything else for the gadget IS present);
- near-zero Linux supply (only ~5-10 Proton titles via custom Wine patches emit
it; hid-playstation/Steam-Input/RPCS3 don't);
- Apple client can't faithfully replay PCM haptics (CoreHaptics is discrete
pattern-based; no public CoreAudio channel-3/4 routing).
Advanced haptics ride the DualSense USB *audio* interface, not HID, so the UHID
backend structurally can't carry them. Defer; the reachable 80% ("real DualSense
feel") is adaptive triggers over the HID 0x02 path we already parse + two-motor
rumble. New docs/dualsense-haptics.md records the walls + conditions for a future
go; roadmap §5 updated (HID DualSense backend built & live-validated).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
dc375668ee |
feat: touch input — TouchDown/Move/Up + host libei ei_touchscreen injection
ci / rust (push) Has been cancelled
Roadmap #5 (touch, ahead of the XL UHID DualSense work). Touch fits the existing 18-byte InputEvent: code = touch id, x/y = client pixels, flags = (w<<16)|h — the same absolute mapping as MouseMoveAbs. - core: InputKind::{TouchDown=9, TouchMove=10, TouchUp=11} + from_u8 + roundtrip test. - host inject/libei.rs: request the RemoteDesktop Touchscreen device type, bind the Touch capability, and inject ei_touchscreen down/motion/up (one event = one frame, per the protocol rule), mapping coordinates into the device region like the abs pointer. wlroots has no virtual-touch protocol wired — no-ops there. - client-rs --touch-test: drags a synthetic finger (touch id 0) in a circle. Validated live on headless KWin: the portal GRANTS the Touchscreen device type (Keyboard|Pointer|Touchscreen), proving the request path — but KWin's EIS server creates no touchscreen *device*, so touch currently no-ops on this KWin (now logged once, not silent). The injection code is correct and will land on a backend that exposes ei_touchscreen (gamescope / a newer compositor / the real touch-client path). Workspace green, clippy/fmt clean, +1 unit test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
e07e359b6d |
docs: scope Windows-as-host (deferred) + update roadmap status
ci / rust (push) Has been cancelled
A 4-agent read of the host crate: a Windows host is an "add a backend" job, not a parallel port — ~95% reuse (core/protocol/FEC/crypto/C-ABI, QUIC, GameStream, mgmt, m3/pipeline are all platform-agnostic and already cfg-isolated). New cfg(windows) backends behind the existing traits: DXGI Desktop Duplication (capture), Media Foundation / NVENC-SDK (encode), SendInput + ViGEm (input), WASAPI loopback + virtual mic (audio). The blocker is the virtual-display feature — no user-mode Windows API; it needs a signed kernel-mode IDD driver (XL). docs/windows-host.md records the per-subsystem effort + a phased plan (Phase 0 = a "basic Windows host" capturing an existing monitor, smallest surface). Deferred: large and unbuildable on the Linux dev box, per the request to only take it on if manageable. roadmap.md marks #1/#2/#4 done, #3 packaged, and adds #7 Windows. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
6fdf7d1511 |
feat: client-selectable compositor (protocol → host → client → C ABI → mgmt → web)
A client can now request which compositor backend the host drives its virtual
output on (gamescope/KWin/Mutter/wlroots). The host honors the request if that
backend is available, else falls back to auto-detect and reports the resolved
choice back — wire-compatible both directions (no ABI bump).
Protocol (punktfunk-core):
- New CompositorPref (config.rs): Auto|Kwin|Wlroots|Mutter|Gamescope with
u8/name mappings. Appended as one optional byte to Hello (client preference)
and Welcome (host's resolved choice). Both decoders already tolerate trailing
bytes, so old↔new interop is preserved — ABI_VERSION stays 2. Round-trip +
back-compat (truncated-message) tests.
- C ABI: punktfunk_connect_ex(compositor) + PUNKTFUNK_COMPOSITOR_* constants;
punktfunk_connect delegates with AUTO, so the existing symbol is unchanged.
NativeClient::connect / worker_main thread the preference through.
Host:
- vdisplay::available() enumerates usable backends via cheap, side-effect-free
probes (KWin zkde global, gamescope binary+version, GNOME/Sway env), plus
Compositor id/label/as_pref/from_pref/all helpers.
- m3 handshake resolves the preference to a concrete backend during the
handshake (pick_compositor pure + resolved logging), reports it in Welcome,
and threads it into virtual_stream (replacing the unconditional detect()).
- mgmt GET /v1/compositors lists every backend with availability + the
auto-detected default (OpenAPI regenerated).
Client:
- punktfunk-client-rs --compositor NAME; logs the host's resolved choice from
the Welcome ("session offer … compositor=…").
Web console:
- Host page gains a Compositors card (availability + default badges) via the
codegen'd useListCompositors hook; en/de strings added.
Also fixes a pre-existing, env-dependent test-isolation bug:
mgmt::tests::paired_clients_list_and_unpair seeded the real
~/.config/punktfunk/paired.json (AppState::new loads it), so a real
GameStream-paired client leaked into body[0] on a dev box — now cleared first.
Live-validated against headless KWin: --compositor kwin honored, --compositor
mutter falls back to kwin (available=[kwin, gamescope]), resolved choice
round-trips to the client. Tests: +6 (wire/back-compat, resolution precedence,
endpoint); workspace green, clippy/fmt clean, C ABI harness PASS at abi_version=2,
web typecheck + build clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
aa5cee57bd |
docs: next-goals roadmap (KDE reliability → options → mic → Bazzite → touch → UHID DualSense)
ci / rust (push) Has been cancelled
Research-grounded sequence + per-goal approach/effort. Decisions: start with KDE startup reliability; Bazzite via COPR RPM then bootc image; commit to full UHID DualSense. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
bfd64ce871 |
rename: lumen → punktfunk, everywhere
ci / rust (push) Has been cancelled
Full project rename, decided 2026-06-10: - Crates/binaries: punktfunk-core / punktfunk-host / punktfunk-client-rs. - C ABI: punktfunk_* symbols, Punktfunk* types, include/punktfunk_core.h, PUNKTFUNK_FEATURE_QUIC guard (header regenerated; cbindgen renames updated, incl. PUNKTFUNK_BTN_*/PUNKTFUNK_AXIS_* wire constants). - Protocol: punktfunk/1 — control-plane magic LMN1 → PKF1, nonce salt lmn1 → pkf1. WIRE BREAK: clients must be rebuilt from this revision. - Env knobs: PUNKTFUNK_VIDEO_SOURCE / PUNKTFUNK_COMPOSITOR / PUNKTFUNK_ZEROCOPY / …. - Host config dir: ~/.config/punktfunk (the box's dir was migrated in place — the persistent identity is unchanged, pinned fingerprints stay valid). - Swift package: PunktfunkKit + PunktfunkCore.xcframework + PunktfunkConnection (Sources/PunktfunkClient app + tests renamed with it); build-xcframework.sh updated. - scripts/: 60-punktfunk.rules, punktfunk-host.service; OpenAPI doc regenerated. Also: scripts/headless/run-headless-kde.sh — full headless Plasma bringup. Root cause of "desktop but no apps/settings" over the stream: plasmashell launched without XDG_MENU_PREFIX=plasma-, so the launcher resolved a nonexistent applications.menu and rendered an empty menu. The script sets the complete KDE session env (menu prefix, KDE_FULL_SESSION, session version) and rebuilds ksycoca before starting plasmashell. Gate: 97/97 tests, clippy -D warnings (both feature sets), fmt, C-ABI harness PASS, zero lumen references left outside .git. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
bd25f5e02f |
fix: M2 — harden the management API after adversarial review
ci / rust (push) Has been cancelled
Five confirmed findings from a 46-agent review panel:
- Empty --mgmt-token no longer satisfies the non-loopback token gate
(critical: 'Bearer ' with an empty token authenticated; parse_serve now
bails on blank tokens and mgmt::run treats blank as none)
- axum's built-in body rejections (400/415/422) now wear the documented
ApiError envelope via an ApiJson extractor, and the spec documents them
- GET /health carries security([{}]) in the spec, matching the server's
auth exemption
- unpairClient's description no longer claims revocation the TLS layer
doesn't enforce yet (gamestream/tls.rs accepts any cert — known gap)
- CLAUDE.md/README.md no longer reference the deleted web.rs
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
a339a0466e |
feat: M2 — management REST API with OpenAPI doc (control-pane groundwork)
A versioned control-plane REST API (/api/v1) on its own port (default 127.0.0.1:47990) serving host info, runtime status, paired-client management, the pairing PIN flow, and session control (stop / force-IDR). The OpenAPI 3.1 document is generated from the handlers by utoipa, served live at /api/v1/openapi.json (+ Scalar docs at /api/docs), printable via `lumen-host openapi`, and checked in at docs/api/openapi.json for client codegen — a test fails if it drifts, mirroring the cbindgen header rule. Auth: optional bearer token (--mgmt-token / LUMEN_MGMT_TOKEN), enforced on everything but /health, and mandatory for non-loopback binds. PinGate gains a waiter count so the API can report pin_pending; logs moved to stderr so stdout stays machine-readable. Supersedes the web.rs stub. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
669d40ae21 |
build: migrate to ffmpeg-next 8 (FFmpeg 8.x / libavcodec 62)
Ubuntu 26.04 ships FFmpeg 8.0 (libavcodec 62); bump ffmpeg-next 7.1 -> 8.1 to bind it as the intended pairing. No source changes needed — the encode API surface we use (avcodec_send_frame, hwframe contexts, AV_PIX_FMT_CUDA, av_log) is stable across 7->8. Workspace builds + all tests green; clippy/fmt clean. Refresh the 7.x doc references. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
ab6dda2e5f |
feat: M0 capture→encode pipeline + M2 GameStream host (pairing, RTSP, video)
M0 (lumen-host) — verified on NVIDIA RTX 5070 Ti / Ubuntu 25.10: headless wlroots → xdg ScreenCast portal → PipeWire → NVENC HEVC → playable file, with each access unit round-tripped through a lumen_core host↔client Session (FEC + packetize + reassemble), 0 mismatches. - capture.rs: SyntheticCapturer + portal capture (ashpd 0.13 + pipewire 0.9), format-aware - encode/linux.rs: NVENC via ffmpeg-next 7 (BGRx/RGB → rgb0, no host-side swscale) - m0.rs: capture→encode→file + lumen-core loopback verification M2 P1 (lumen-host gamestream/) — a stock Moonlight client pairs + launches, verified live: - mDNS _nvstream._tcp + nvhttp /serverinfo (HTTP 47989, mutual-TLS HTTPS 47984) - 4-phase pairing: PIN→AES-128-ECB / SHA-256 / RSA-PKCS1v15 / X.509, custom rustls ClientCertVerifier for the mutual-TLS pairchallenge - /applist, /launch (rikey/rikeyid/mode), hand-rolled RTSP (OPTIONS/DESCRIBE/SETUP×3/ ANNOUNCE/PLAY, one-request-per-TCP-connection per moonlight-common-c's read-to-EOF) - video.rs: GameStream RTP + NV_VIDEO_PACKET wire packetizer, data-shards-only (0% FEC, clean-LAN), unit-tested (single/multi-block) Docs: docs/m2-plan.md (phased plan) + docs/research/ (ground-truth protocol spec). Bootstrap/setup updated for the verified path (libnvidia-gl, render/video groups, GPU EGL, pipewire 0.9). Workspace clippy-clean, tests green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |