forked from unom/punktfunk
The ring layer moves out of the session binary into pf_client_core::logring (desktop-gated beside the ring it feeds) — it started as punktfunk-session's private module, and the moment both desktop shells wanted the row, a copy per bin was exactly the drift the crate exists to prevent. The session keeps the same layer under its new name; tracing-log and log fall out of its manifest. Both shells install it beside their visible layer with its own DEBUG filter — the env filter keeps scoping only what's printed, because the ring exists for the diagnostics nobody enabled before the bug happened. The row itself lands on each shell's saved-host menu on the console's own gate (paired + online), wired to logring::send_to_host on a worker thread, outcome as a toast (GTK) / the status line (WinUI), in the console's wording verbatim. And the bundle is worth sending: orchestrate now pipes the session child's stderr through logring::forward_child_stderr — every line still lands on our stderr exactly as inherit interleaved it, and lands in the ring too. Without that, the one surface a GUI-only user can export held everything EXCEPT the stream it was exported about — the same hole the WinUI logfile module was built to close for the file; its child forwarder now feeds the ring on the same pass.
252 lines
15 KiB
TOML
252 lines
15 KiB
TOML
[package]
|
|
name = "pf-client-core"
|
|
description = "Shared client plumbing (Linux + Windows) — session pump, native video decode, PipeWire/WASAPI audio, SDL3 gamepads, trust store, discovery — extracted from the GTK client so the shells and the Vulkan session binary build on one implementation"
|
|
version.workspace = true
|
|
edition.workspace = true
|
|
rust-version.workspace = true
|
|
license.workspace = true
|
|
authors.workspace = true
|
|
repository.workspace = true
|
|
|
|
# Linux + Windows: the Vulkan session client builds on both; `cargo build --workspace`
|
|
# stays green on macOS (the Mac client lives in clients/apple) — there this crate is
|
|
# `wol` plus stubs-free emptiness. `wol` is pure std and stays cross-platform, matching
|
|
# the old main.rs. Audio is the one per-OS swap: PipeWire on Linux, WASAPI on Windows
|
|
# (same public surface — see lib.rs).
|
|
#
|
|
# Android (design/android-skia-console-port.md, WP1): the Skia console shell
|
|
# (`pf-console-ui`) now runs inside the Android client too, and everything IT needs from
|
|
# this crate is data — `trust::Settings`, the menu-event vocabulary + synthesizer, the
|
|
# library model, the deep-link grammar, the overlay action/session-phase types. Those
|
|
# modules are gated `any(linux, windows, android)` in lib.rs; the session pump, decoders,
|
|
# audio, SDL gamepad service and the ureq fetches stay desktop-only, so this block carries
|
|
# only what the portable modules touch. `quic` (not `ureq-tls`): `trust` names
|
|
# `NativeClient`/`endpoint` for identity + pairing; nothing here fetches over HTTPS.
|
|
[target.'cfg(target_os = "android")'.dependencies]
|
|
punktfunk-core = { path = "../punktfunk-core", features = ["quic"] }
|
|
serde = { version = "1", features = ["derive"] }
|
|
serde_json = "1"
|
|
anyhow = "1"
|
|
tracing = "0.1"
|
|
# `profiles` mints profile ids.
|
|
rand = "0.9"
|
|
|
|
[target.'cfg(any(target_os = "linux", windows))'.dependencies]
|
|
punktfunk-core = { path = "../punktfunk-core", features = ["quic", "ureq-tls"] }
|
|
# Native Vulkan Video decode (WP-C of the native-decode program, HEVC added by M3
|
|
# WP-2, AV1 by M7): auto's TOP rung on both desktop OSes since M9 — for every codec it
|
|
# speaks, AV1 included — also pinnable via `PUNKTFUNK_DECODER=native-vulkan` —
|
|
# video_vk_native.rs, running pf-vkdecode's VkH264Decoder/VkH265Decoder/VkAv1Decoder on
|
|
# the presenter's shared device.
|
|
pf-vkdecode = { path = "../pf-vkdecode" }
|
|
# The one bitstream parser (M1): the SOFTWARE rung reads its per-picture colour
|
|
# signalling, IDR flag and recovery-point SEI from the same `AuPlan` every hardware rung
|
|
# already submits from (`video_software.rs`). That is what makes the swscale BT.601
|
|
# default unrepresentable rather than merely fixed — there is no second colour source
|
|
# left to disagree with.
|
|
pf-bitstream = { path = "../pf-bitstream" }
|
|
async-channel = "2"
|
|
|
|
# M8's software rung, the ladder's last one — no FFmpeg in either half.
|
|
#
|
|
# H.264: openh264 (BSD-2), already a workspace dependency (the HOST's GPU-less encoder,
|
|
# `pf-encode/src/enc/sw.rs`), so the licence posture and the bundled-source build are
|
|
# both already settled and already compiled by every `--workspace` leg.
|
|
#
|
|
# AV1: rav1d (BSD-2) — dav1d itself, ported to Rust by the ISRG/Prossimo memory-safety
|
|
# project. The plan of record names "dav1d"; the `dav1d` crate reaches it through
|
|
# `dav1d-sys`, which is `system-deps`-only (no vendored build): it needs `dav1d.pc` +
|
|
# headers at build time and `libdav1d.so`/`dav1d.dll` at run time on EVERY client
|
|
# package. That is a new system codec dependency added by the milestone family whose
|
|
# §6 excision checklist exists to delete exactly those. rav1d is the same decoder with
|
|
# none of that: pure Rust, no linker, nothing new in any package.
|
|
#
|
|
# ⚠ Both of these are NEW COMPILE COST on the client packaging legs, which is easy to
|
|
# miss because the workspace already built openh264: every client leg is `-p`-scoped and
|
|
# excludes pf-encode (flatpak's `cargo build -p punktfunk-client-linux -p
|
|
# punktfunk-client-session -p punktfunk-cli`, windows.yml/windows-msix.yml's
|
|
# `-p punktfunk-client-windows …`, deb.yml's client job, packaging/nix's
|
|
# `punktfunk-client`), so all of them compile the bundled OpenH264 tree for the FIRST
|
|
# time here. Only the `--workspace` CI legs and the host packages built it before.
|
|
#
|
|
# `default-features = false` drops two things deliberately:
|
|
# * `asm` — rav1d's hand-written assembly needs `nasm` at build time, and it is NOT the
|
|
# same trade openh264 makes next to it: openh264-sys2's `try_compile_nasm` returns
|
|
# quietly when nasm is missing ("Failed to compile NASM files, not using any
|
|
# assembly") and the C build still succeeds, whereas rav1d's build.rs PANICS ("NASM
|
|
# build failed. Make sure you have nasm installed or disable the \"asm\" feature").
|
|
# So turning `asm` on makes nasm a hard build requirement of every client package,
|
|
# and `ci/rust-ci.Dockerfile` — the container the client .deb and the workspace CI
|
|
# build in — does not have it (arch, rpm, nix and the FFmpeg-building noble image
|
|
# all do; the flatpak GNOME SDK and the Windows runner are not provisioned by
|
|
# anything in this tree). Making the rung that only ever runs BECAUSE the GPU
|
|
# already failed a build-breaker for the legs that ship it is the wrong way round.
|
|
# Turn it back on the day every client leg provisions nasm — and expect a large
|
|
# speedup when you do; this is dav1d's asm, and the Rust fallbacks are much slower.
|
|
# * `bitdepth_16` — the CPU rung is 8-bit by contract (`video_software.rs` refuses
|
|
# anything else rather than mis-scaling it), so building the 10/12-bit half would be
|
|
# compiling a path the code refuses to take.
|
|
#
|
|
# One packaging risk this DOESN'T carry: rav1d exports dav1d's C ABI as `#[no_mangle]`
|
|
# symbols (`dav1d_open`, `dav1d_send_data`, …), which could in principle interpose on a
|
|
# real libdav1d loaded into the same process. It cannot here — these are Rust `staticlib`
|
|
# symbols in an executable with no `-rdynamic` and no dynamic export table entry, so the
|
|
# loader never offers them to anyone. That changes if pf-client-core ever becomes a
|
|
# `cdylib` or a leg adds `-rdynamic`/`--export-dynamic`; re-check it then.
|
|
openh264 = "0.9"
|
|
rav1d = { version = "1", default-features = false, features = ["bitdepth_8"] }
|
|
# errno names for rav1d's negated-`c_int` returns (`video_software.rs`): `ENOPROTOOPT` —
|
|
# the code a `bitdepth_8`-only build answers a 10-bit stream with — is 92 on Linux and
|
|
# 123 on Windows, and rav1d re-exports only `Dav1dResult`, so the typed enum that would
|
|
# otherwise name it is out of reach. Already in the tree (rav1d's own dependency).
|
|
libc = "0.2"
|
|
|
|
# Opus for the audio planes. The VIDEO side has no FFmpeg at all since M10: every decode
|
|
# rung is native (pf-vkdecode / pf-dxvadec / pf-vaadec / openh264+rav1d) and the codec
|
|
# vocabulary is `punktfunk_core::quic`'s own `CODEC_*` wire bits. The HOST still encodes
|
|
# with libavcodec (`pf-encode`); nothing in this crate does.
|
|
opus = "0.3"
|
|
|
|
mdns-sd = "0.21"
|
|
|
|
# PyroWave decode (the opt-in wired-LAN wavelet codec, design/pyrowave-codec-plan.md
|
|
# §4.5) — pure Vulkan compute on the presenter's shared device, so it builds wherever the
|
|
# spawned Vulkan session presenter runs: Linux AND Windows (pyrowave-sys covers both; it
|
|
# is an empty stub elsewhere). `ash` only wraps the presenter's existing raw handles
|
|
# (same pinned version as pf-presenter).
|
|
pyrowave-sys = { path = "../pyrowave-sys", optional = true }
|
|
ash = { version = "0.38", optional = true }
|
|
# Game-library fetch from the host's management API over mTLS + fingerprint pinning.
|
|
# `ureq` is small + sync (the host uses it too) and its rustls unifies with the
|
|
# workspace's (quinn's) 0.23; the pinning verifier mirrors core's private `PinVerify`.
|
|
# ⚠ `rustls-no-provider`, NEVER the default `rustls` feature: that one pulls `_ring`, which would
|
|
# put the ring backend back into a tree that has moved to aws-lc-rs. Same spelling everywhere.
|
|
ureq = { version = "3", default-features = false, features = [
|
|
"rustls-no-provider",
|
|
"rustls-webpki-roots",
|
|
"gzip",
|
|
] }
|
|
# Signed update-manifest fetch/verify + the install-kind ladder, shared with the host so one
|
|
# trust rule serves both (crates/pf-update-check).
|
|
pf-update-check = { path = "../pf-update-check" }
|
|
# aws-lc-rs backend + PQ hybrid key exchange, matching punktfunk-core (see its Cargo.toml for
|
|
# why every crate that names a rustls backend has to name the same one).
|
|
rustls = { version = "0.23", default-features = false, features = ["aws_lc_rs", "prefer-post-quantum", "logging", "std", "tls12"] }
|
|
serde = { version = "1", features = ["derive"] }
|
|
serde_json = "1"
|
|
anyhow = "1"
|
|
tracing = "0.1"
|
|
# `logring::RingLayer` — the ONE tracing layer feeding the ring, shared by the session binary
|
|
# and both desktop shells (it lived in clients/session, which left the GTK and WinUI shells
|
|
# with no ring and so no "Send logs to host"). Minimal features: the layer only needs the
|
|
# `Layer` trait; the bins bring their own full-featured tracing-subscriber, and cargo's
|
|
# feature union means this adds nothing they didn't already compile. `tracing-log` is the
|
|
# bridge-normalization half (see the layer's docs) and rides tracing-subscriber's default
|
|
# `tracing-log` feature in every bin anyway. Android/Apple builds are untouched — this is
|
|
# the desktop target block.
|
|
tracing-subscriber = { version = "0.3", default-features = false, features = ["std", "registry"] }
|
|
tracing-log = "0.2"
|
|
# Stable ids for profiles and host records (profiles.rs) — the OS RNG only, same version the
|
|
# workspace already resolves for punktfunk-core. No uuid crate: the v4 layout is four lines.
|
|
rand = "0.9"
|
|
|
|
# Gamepads: capture + feedback (full DualSense fidelity — touchpad/motion/triggers/LEDs
|
|
# need the hidapi driver). Linux links the system SDL3; Windows builds it from source
|
|
# (no system SDL3 there — same choice as clients/windows).
|
|
[target.'cfg(target_os = "linux")'.dependencies]
|
|
# `v0_3_49` for `Buffer::requested` — the graph's per-cycle frame ask, without which the
|
|
# playback callback can only size writes from the buffer CEILING (quantum-limit, ~170 ms).
|
|
# Pure cfg gate; needs libpipewire ≥ 0.3.49 (2022-03) at runtime, which every ship target
|
|
# (SteamOS, flatpak runtimes, Arch, Ubuntu ≥ 22.10) clears.
|
|
pipewire = { version = "0.9", features = ["v0_3_49"] }
|
|
sdl3 = { version = "0.18", features = ["hidapi"] }
|
|
# Audio-thread priority (`audio_rt`): one blocking D-Bus call per boosted thread — the Realtime
|
|
# PORTAL (session bus) inside a flatpak, where the sandbox's PID namespace makes a direct rtkit
|
|
# call unresolvable, and rtkit (system bus) outside one. The same zbus, features and backend
|
|
# choice as `pf-frame`'s `thread_qos` (which the host uses for the same purpose): `tokio` because
|
|
# core's `quic` already resolves tokio for this crate, `blocking-api` because the callers are
|
|
# plain worker threads, no default `async-io`.
|
|
zbus = { version = "5", default-features = false, features = ["tokio", "blocking-api"] }
|
|
# Native VAAPI decode (M6 of the native-decode program): the hand-declared libva buffer
|
|
# layouts, the profile/format/surface decisions, the AuPlan → picparams/IQ/slice
|
|
# conversion and the DRM-PRIME export descriptor that `video_vaapi_native` marshals.
|
|
# Cross-platform on purpose — everything decidable without a device is tested by the
|
|
# ordinary macOS and container gates, exactly as pf-dxvadec does for Windows.
|
|
pf-vaadec = { path = "../pf-vaadec" }
|
|
# libva itself is dlopen'd, never linked (see `video_vaapi_native`'s module docs): the
|
|
# container can then compile and clippy the whole rung without `libva-dev`, and a machine
|
|
# without a VAAPI runtime gets a clean refusal instead of a packaging dependency.
|
|
libloading = "0.9"
|
|
# The gamescope overlay watcher (`overlay_focus`): read two CARDINAL properties off a
|
|
# gamescope root window and block on PropertyNotify. `default-features = false` keeps the
|
|
# pure-Rust `RustConnection` — no libxcb link, so no new C dependency on any client package
|
|
# — the same stance pf-capture and pf-vdisplay already take on this crate. No extension
|
|
# features: root-window properties and an event mask are core X11.
|
|
x11rb = { version = "0.14", default-features = false }
|
|
|
|
[target.'cfg(windows)'.dependencies]
|
|
wasapi = "0.24"
|
|
# Native D3D11VA decode (M5 of the native-decode program): the hand-declared DXVA buffer
|
|
# layouts and the AuPlan → picparams/qmatrix/slice-control conversion that video_d3d11_native
|
|
# submits. Windows-only because the rung is; the crate itself is cross-platform CPU code so
|
|
# its tests run on every CI leg (which is the point — `cfg(windows)` code cannot be tested by
|
|
# the Linux or macOS gates at all).
|
|
pf-dxvadec = { path = "../pf-dxvadec" }
|
|
# Pad-audio correlation (pad_audio.rs): the HID devnode's ContainerID and a render endpoint's
|
|
# stamped PKEY_Device_ContainerId both live in the registry — read-only, which sidesteps COM
|
|
# property stores entirely (the same version the host pins).
|
|
winreg = "0.56"
|
|
sdl3 = { version = "0.18", features = ["hidapi", "build-from-source"] }
|
|
# D3D11 decode-device plumbing (video_d3d11.rs): device/adapter selection, DXVA probes, and
|
|
# the shared NT-handle hand-off ring `video_d3d11_native` fills. Same pinned rev as
|
|
# clients/windows so the workspace builds ONE windows-rs.
|
|
windows = { git = "https://github.com/microsoft/windows-rs", rev = "acb5a1a7441033d9312b16842af02eb0c2b403dc", features = [
|
|
# Features are header-named since windows-rs generates from the SDK headers directly
|
|
# (#4689) — one feature per header, replacing the old `Win32_*` namespace features.
|
|
"d3d11",
|
|
"d3dcommon",
|
|
"dxgi",
|
|
"handleapi",
|
|
# RECT/HMONITOR for DXGI_OUTPUT_DESC1 (the display-HDR volume query).
|
|
"windef",
|
|
# HGLOBAL (clipboard.rs) + HINSTANCE (video_d3d11.rs), and the NT `HANDLE` the shared-surface
|
|
# hand-off uses. Both headers were used without being declared — they resolved only because
|
|
# clients/windows enables them on the same pinned rev, so this crate did not build standalone.
|
|
"minwindef",
|
|
"winnt",
|
|
# IDXGIResource1::CreateSharedHandle takes an optional SECURITY_ATTRIBUTES.
|
|
"minwinbase",
|
|
# The GlobalAlloc block the clipboard takes ownership of (clipboard.rs).
|
|
"winbase",
|
|
# The OS-clipboard bridge (clipboard.rs): Open/Get/SetClipboardData + the sequence
|
|
# number — all in winuser now.
|
|
"winuser",
|
|
] }
|
|
|
|
[target.'cfg(any(target_os = "linux", windows))'.dev-dependencies]
|
|
# The two platform native rungs' frame-hash parity tests compare decoded surfaces against
|
|
# the libavcodec goldens M5 captured — the same SHA-256 list, and the same crate,
|
|
# pf-vkdecode's Vulkan parity legs use (already in the workspace lock). The goldens are
|
|
# checked-in hashes; nothing links FFmpeg to read them.
|
|
#
|
|
# Windows was the only platform here until the VAAPI rung grew a readback: `cfg(windows)`
|
|
# for `video_d3d11_native::parity`, now `cfg(linux)` as well for
|
|
# `video_vaapi_native::parity`. A DEV dependency, so no shipped binary gains anything —
|
|
# which is also part of why the VAAPI readback cannot reach the production video path.
|
|
sha2 = "0.11"
|
|
# `logring`'s bridged-decoder test plants `log`-crate records through the tracing-log
|
|
# bridge and installs a registry subscriber — the full-featured halves the shipping layer
|
|
# deliberately doesn't need.
|
|
log = "0.4"
|
|
tracing-subscriber = { version = "0.3" }
|
|
|
|
[features]
|
|
# PyroWave client decode ships in every default build (flatpak included; pyrowave-sys is a
|
|
# vendored in-repo tree, offline-safe, and an empty stub off Linux/Windows). The codec is
|
|
# still strictly per-session opt-in (Settings codec pick / PUNKTFUNK_PREFER_PYROWAVE=1).
|
|
default = ["pyrowave"]
|
|
pyrowave = ["dep:pyrowave-sys", "dep:ash"]
|
|
|
|
[lints]
|
|
workspace = true
|