From 3495d189e15c25a578edb33a070c5d46dc1846b5 Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Fri, 17 Jul 2026 08:54:47 +0200 Subject: [PATCH] refactor(host/W6.1): extract the config() global into the pf-host-config leaf crate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Third de-coupling for the host crate carve (plan §W6.1 leaf). HostConfig + the config() OnceLock (config.rs, pure std, zero deps) move to a new pf-host-config leaf so every subsystem crate (pf-encode/pf-capture/pf-vdisplay/pf-gpu) can read process config WITHOUT depending on the orchestrator. 34 crate::config::config() call sites across 19 files repoint to pf_host_config::config(). thread_qos stays in the host for now (it calls session_tuning::on_hot_thread — its own leaf-ification rides the encode carve). Granular-crate decision (supersedes the plan's single pf-media): split capture/encode/ vdisplay into separate crates rather than one broad crate — the capture↔encode cycle is broken by a shared frame-types leaf, and vdisplay→encode (can_open_another_session) is a legal one-way edge since encode never references vdisplay. Verified: Linux (home-worker-5) clippy -p pf-host-config -p punktfunk-host --all-targets -D warnings; Windows (192.168.1.158) clippy --features nvenc,amf-qsv --all-targets green. Co-Authored-By: Claude Opus 4.8 (1M context) --- Cargo.lock | 5 +++++ Cargo.toml | 1 + crates/pf-host-config/Cargo.toml | 12 ++++++++++++ .../src/config.rs => pf-host-config/src/lib.rs} | 2 +- crates/punktfunk-host/Cargo.toml | 2 ++ crates/punktfunk-host/src/capture/linux/mod.rs | 2 +- .../punktfunk-host/src/capture/windows/idd_push.rs | 2 +- crates/punktfunk-host/src/encode.rs | 14 +++++++------- crates/punktfunk-host/src/encode/linux/vaapi.rs | 2 +- .../src/encode/windows/ffmpeg_win.rs | 2 +- crates/punktfunk-host/src/gamestream/mod.rs | 2 +- crates/punktfunk-host/src/gamestream/stream.rs | 6 +++--- crates/punktfunk-host/src/gpu.rs | 4 ++-- crates/punktfunk-host/src/hooks.rs | 4 ++-- crates/punktfunk-host/src/inject.rs | 4 ++-- crates/punktfunk-host/src/main.rs | 1 - crates/punktfunk-host/src/mgmt/gpu.rs | 2 +- crates/punktfunk-host/src/native/compositor.rs | 2 +- crates/punktfunk-host/src/native/gamepad.rs | 2 +- crates/punktfunk-host/src/native/handshake.rs | 4 ++-- crates/punktfunk-host/src/native/stream.rs | 6 +++--- crates/punktfunk-host/src/session_plan.rs | 2 +- crates/punktfunk-host/src/vdisplay.rs | 4 ++-- .../punktfunk-host/src/vdisplay/linux/gamescope.rs | 2 +- crates/punktfunk-host/src/vdisplay/session.rs | 2 +- 25 files changed, 55 insertions(+), 36 deletions(-) create mode 100644 crates/pf-host-config/Cargo.toml rename crates/{punktfunk-host/src/config.rs => pf-host-config/src/lib.rs} (99%) diff --git a/Cargo.lock b/Cargo.lock index 53b7f526..a2544b46 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2808,6 +2808,10 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "pf-host-config" +version = "0.12.0" + [[package]] name = "pf-paths" version = "0.12.0" @@ -3129,6 +3133,7 @@ dependencies = [ "opus", "parking_lot", "pf-driver-proto", + "pf-host-config", "pf-paths", "pipewire", "punktfunk-core", diff --git a/Cargo.toml b/Cargo.toml index 81e61161..461f813e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ members = [ "crates/pf-ffvk", "crates/pf-driver-proto", "crates/pf-paths", + "crates/pf-host-config", "crates/pyrowave-sys", "clients/probe", "clients/linux", diff --git a/crates/pf-host-config/Cargo.toml b/crates/pf-host-config/Cargo.toml new file mode 100644 index 00000000..c306713d --- /dev/null +++ b/crates/pf-host-config/Cargo.toml @@ -0,0 +1,12 @@ +# The process-wide host configuration global (HostConfig + the config() OnceLock), extracted into a +# leaf crate so every subsystem crate (pf-encode, pf-capture, pf-vdisplay, pf-gpu) can read config +# WITHOUT depending on the orchestrator (plan §W6 — config parked above its consumers). Pure std. +[package] +name = "pf-host-config" +version = "0.12.0" +edition = "2021" +license = "MIT OR Apache-2.0" +description = "Process-wide punktfunk host configuration (env-parsed HostConfig behind a OnceLock)." +publish = false + +[dependencies] diff --git a/crates/punktfunk-host/src/config.rs b/crates/pf-host-config/src/lib.rs similarity index 99% rename from crates/punktfunk-host/src/config.rs rename to crates/pf-host-config/src/lib.rs index 18705584..9867509d 100644 --- a/crates/punktfunk-host/src/config.rs +++ b/crates/pf-host-config/src/lib.rs @@ -12,7 +12,7 @@ //! capture/topology/encoder decision. //! //! **What is deliberately NOT here (and must stay a live `env::var` read):** -//! - **Runtime-mutated session vars.** On Linux, [`crate::vdisplay::apply_session_env`] rewrites the process +//! - **Runtime-mutated session vars.** On Linux, `crate::vdisplay::apply_session_env` rewrites the process //! env on *every connect* so one host follows a Bazzite box across Gaming↔Desktop: `WAYLAND_DISPLAY`, //! `XDG_CURRENT_DESKTOP`, `XDG_RUNTIME_DIR`, `DBUS_SESSION_BUS_ADDRESS`, and the *derived* `PUNKTFUNK_*` //! vars `INPUT_BACKEND`, `GAMESCOPE_SESSION`/`GAMESCOPE_NODE`, `KWIN_VIRTUAL_PRIMARY`, diff --git a/crates/punktfunk-host/Cargo.toml b/crates/punktfunk-host/Cargo.toml index 9dca068a..3b2001ee 100644 --- a/crates/punktfunk-host/Cargo.toml +++ b/crates/punktfunk-host/Cargo.toml @@ -12,6 +12,8 @@ repository.workspace = true punktfunk-core = { path = "../punktfunk-core", features = ["quic"] } # Config-dir + owner-private file helpers (moved out of the gamestream junk drawer, plan §W6). pf-paths = { path = "../pf-paths" } +# Process-wide host config global, extracted to a leaf crate (plan §W6). +pf-host-config = { path = "../pf-host-config" } # M3 native control plane (the `punktfunk/1` QUIC handshake; data plane stays native-thread UDP). quinn = "0.11" anyhow = "1" diff --git a/crates/punktfunk-host/src/capture/linux/mod.rs b/crates/punktfunk-host/src/capture/linux/mod.rs index 03042662..0c172f42 100644 --- a/crates/punktfunk-host/src/capture/linux/mod.rs +++ b/crates/punktfunk-host/src/capture/linux/mod.rs @@ -1626,7 +1626,7 @@ mod pipewire { // advertisement with every modifier its device samples from, so compositors that // never allocate LINEAR (Mutter+NVIDIA) still negotiate zero-copy dmabufs. #[cfg(feature = "pyrowave")] - if vaapi_passthrough && crate::config::config().encoder_pref.as_str() == "pyrowave" { + if vaapi_passthrough && pf_host_config::config().encoder_pref.as_str() == "pyrowave" { for m in crate::encode::pyrowave_capture_modifiers( crate::zerocopy::drm_fourcc(PixelFormat::Bgrx).unwrap(), ) { diff --git a/crates/punktfunk-host/src/capture/windows/idd_push.rs b/crates/punktfunk-host/src/capture/windows/idd_push.rs index a8bcf0ec..f81fcddc 100644 --- a/crates/punktfunk-host/src/capture/windows/idd_push.rs +++ b/crates/punktfunk-host/src/capture/windows/idd_push.rs @@ -1522,7 +1522,7 @@ impl Capturer for IddPushCapturer { // NVENC encodes N on the ASIC. We hand a rotating `OUT_RING` of output textures, so this is safe. // `PUNKTFUNK_IDD_DEPTH` overrides (1 disables pipelining; clamp to ≤ OUT_RING so a frame in flight // always has its own texture). - crate::config::config().idd_depth.clamp(1, OUT_RING) + pf_host_config::config().idd_depth.clamp(1, OUT_RING) } } diff --git a/crates/punktfunk-host/src/encode.rs b/crates/punktfunk-host/src/encode.rs index cbe4e4c0..c4eaddf9 100644 --- a/crates/punktfunk-host/src/encode.rs +++ b/crates/punktfunk-host/src/encode.rs @@ -35,7 +35,7 @@ impl Codec { // keeps the bit off (no Vulkan device to open). #[cfg(all(target_os = "linux", feature = "pyrowave"))] let pyro = if !matches!( - crate::config::config().encoder_pref.as_str(), + pf_host_config::config().encoder_pref.as_str(), "software" | "sw" | "openh264" ) { punktfunk_core::quic::CODEC_PYROWAVE @@ -53,7 +53,7 @@ impl Codec { #[cfg(target_os = "linux")] { if matches!( - crate::config::config().encoder_pref.as_str(), + pf_host_config::config().encoder_pref.as_str(), "software" | "sw" | "openh264" ) { return punktfunk_core::quic::CODEC_H264; @@ -83,7 +83,7 @@ impl Codec { #[cfg(not(any(target_os = "linux", target_os = "windows")))] { let _ = GPU_SUPERSET; - match crate::config::config().encoder_pref.as_str() { + match pf_host_config::config().encoder_pref.as_str() { "software" | "sw" | "openh264" => punktfunk_core::quic::CODEC_H264, _ => punktfunk_core::quic::CODEC_HEVC, } @@ -262,7 +262,7 @@ fn open_video_backend( // AMD/Intel → VAAPI (one libavcodec backend for both). Auto-detect by default so a single // Linux binary serves any GPU; `PUNKTFUNK_ENCODER` forces a specific backend (and surfaces // its errors crisply instead of silently trying the other). - let pref = crate::config::config().encoder_pref.as_str(); + let pref = pf_host_config::config().encoder_pref.as_str(); // AMD/Intel opener. Default = libav VAAPI. With `--features vulkan-encode` + // PUNKTFUNK_VULKAN_ENCODE, an HEVC session instead opens the raw Vulkan Video backend (real // RFI loss recovery the VAAPI path can't express); a failed open falls back to VAAPI so the @@ -708,7 +708,7 @@ pub(crate) fn pyrowave_capture_modifiers(fourcc: u32) -> Vec { /// passthrough for VAAPI vs the EGL→CUDA import for NVENC). #[cfg(target_os = "linux")] pub fn linux_zero_copy_is_vaapi() -> bool { - match crate::config::config().encoder_pref.as_str() { + match pf_host_config::config().encoder_pref.as_str() { "nvenc" | "nvidia" | "cuda" => false, "vaapi" | "amd" | "intel" => true, // PyroWave ingests the raw capture dmabuf itself (Vulkan import + compute CSC) on ANY @@ -945,7 +945,7 @@ enum GpuVendor { #[cfg(target_os = "windows")] pub(crate) fn windows_resolved_backend() -> WindowsBackend { // Resolved ONCE in HostConfig (Goal-1) — was re-read from PUNKTFUNK_ENCODER on every call. - match crate::config::config().encoder_pref.as_str() { + match pf_host_config::config().encoder_pref.as_str() { "nvenc" | "hw" | "nvidia" | "cuda" => WindowsBackend::Nvenc, "amf" | "amd" => WindowsBackend::Amf, "qsv" | "intel" => WindowsBackend::Qsv, @@ -974,7 +974,7 @@ pub(crate) fn resolved_backend_is_gpu() -> bool { #[cfg(not(target_os = "windows"))] pub(crate) fn resolved_backend_is_gpu() -> bool { !matches!( - crate::config::config().encoder_pref.as_str(), + pf_host_config::config().encoder_pref.as_str(), "software" | "sw" | "openh264" ) } diff --git a/crates/punktfunk-host/src/encode/linux/vaapi.rs b/crates/punktfunk-host/src/encode/linux/vaapi.rs index 19c7137e..09b1a1a5 100644 --- a/crates/punktfunk-host/src/encode/linux/vaapi.rs +++ b/crates/punktfunk-host/src/encode/linux/vaapi.rs @@ -809,7 +809,7 @@ impl DmabufInner { // Sampled breakdown of this synchronous submit under PUNKTFUNK_PERF: push = descriptor // build + buffersrc (the per-frame DRM→VA import happens inside hwmap on the pull path), // pull = buffersink (VPP CSC + any sync), send = avcodec_send_frame. One line per ~2 s. - let sample = crate::config::config().perf && self.frames % 120 == 0; + let sample = pf_host_config::config().perf && self.frames % 120 == 0; self.frames += 1; let t0 = std::time::Instant::now(); let t_push: std::time::Duration; diff --git a/crates/punktfunk-host/src/encode/windows/ffmpeg_win.rs b/crates/punktfunk-host/src/encode/windows/ffmpeg_win.rs index 265bb8c4..1402648d 100644 --- a/crates/punktfunk-host/src/encode/windows/ffmpeg_win.rs +++ b/crates/punktfunk-host/src/encode/windows/ffmpeg_win.rs @@ -122,7 +122,7 @@ impl WinVendor { /// open-failure fallback only catches *setup* errors; a derive that opens but maps wrong would /// corrupt silently, so it stays opt-in per the probe-never-assume rule). fn zerocopy_enabled(vendor: WinVendor) -> bool { - crate::config::config() + pf_host_config::config() .zerocopy .unwrap_or(matches!(vendor, WinVendor::Amf)) } diff --git a/crates/punktfunk-host/src/gamestream/mod.rs b/crates/punktfunk-host/src/gamestream/mod.rs index c929d892..4c03c687 100644 --- a/crates/punktfunk-host/src/gamestream/mod.rs +++ b/crates/punktfunk-host/src/gamestream/mod.rs @@ -64,7 +64,7 @@ pub const SERVER_CODEC_MODE_SUPPORT: u32 = SCM_H264 | SCM_HEVC | SCM_AV1_MAIN8; /// whenever the desktop is HDR, and a client HDR request makes the GameStream video path proactively /// enable advanced color on the per-session virtual display so PQ flows even from an SDR desktop. pub fn host_hdr_capable() -> bool { - cfg!(target_os = "windows") && crate::config::config().ten_bit + cfg!(target_os = "windows") && pf_host_config::config().ten_bit } /// Stable host identity + advertised capabilities, shared across control-plane handlers. diff --git a/crates/punktfunk-host/src/gamestream/stream.rs b/crates/punktfunk-host/src/gamestream/stream.rs index d5f34761..3731d2fa 100644 --- a/crates/punktfunk-host/src/gamestream/stream.rs +++ b/crates/punktfunk-host/src/gamestream/stream.rs @@ -162,7 +162,7 @@ fn run( // request and capture it (no scaling). Self-contained — deliberately NOT pooled in // `video_cap`, since a reconnect at a different resolution needs a freshly-sized output; the // output is released when this capturer drops at stream end (RAII via its keepalive). - if crate::config::config().video_source.as_deref() == Some("virtual") { + if pf_host_config::config().video_source.as_deref() == Some("virtual") { // Per-app prep steps (RFC §6): the entry's own `prep` plus a custom library title's, // run synchronously BEFORE the virtual output opens or anything launches (an HDR // toggle / sink switch must land first — and gamescope's nested launch happens inside @@ -249,7 +249,7 @@ fn run( tracing::info!("video source: reusing capturer"); c } - None if crate::config::config().video_source.as_deref() == Some("portal") => { + None if pf_host_config::config().video_source.as_deref() == Some("portal") => { tracing::info!("video source: portal desktop capture"); capture::open_portal_monitor().context("open portal capturer")? } @@ -676,7 +676,7 @@ fn stream_body( // Per-stage timing (PUNKTFUNK_PERF=1): max µs/stage per second + unique vs re-encoded frames, // to pinpoint stalls. `unique` counts genuinely-new captured frames (vs re-encoded holds). - let perf = crate::config::config().perf; + let perf = pf_host_config::config().perf; let (mut mx_cap, mut mx_enc, mut mx_pkt, mut mx_send, mut uniq) = (0u128, 0u128, 0u128, 0u128, 0u32); // Web-console stats accumulation (active when `perf` OR a capture is armed): per-stage vectors diff --git a/crates/punktfunk-host/src/gpu.rs b/crates/punktfunk-host/src/gpu.rs index 385fa496..683f4814 100644 --- a/crates/punktfunk-host/src/gpu.rs +++ b/crates/punktfunk-host/src/gpu.rs @@ -420,7 +420,7 @@ impl GpuPrefStore { } /// The process-wide preference store (config-dir file), loaded once on first access — the same -/// global-accessor shape as [`crate::config::config`], because selection happens deep inside +/// global-accessor shape as [`pf_host_config::config`], because selection happens deep inside /// capture/encode setup where no app state is threaded. pub(crate) fn prefs() -> &'static GpuPrefStore { static STORE: OnceLock = OnceLock::new(); @@ -535,7 +535,7 @@ pub(crate) fn pick( pub(crate) fn selected_gpu() -> Option { let gpus = enumerate(); let pref = prefs().get(); - let env = crate::config::config() + let env = pf_host_config::config() .render_adapter .clone() .filter(|s| !s.is_empty()); diff --git a/crates/punktfunk-host/src/hooks.rs b/crates/punktfunk-host/src/hooks.rs index a1646159..7de83416 100644 --- a/crates/punktfunk-host/src/hooks.rs +++ b/crates/punktfunk-host/src/hooks.rs @@ -298,8 +298,8 @@ fn dispatch( // The two env-var mirrors (`PUNKTFUNK_ON_CONNECT_CMD` / `PUNKTFUNK_ON_DISCONNECT_CMD`) — // the zero-config siblings of `PUNKTFUNK_RECOVER_SESSION_CMD` for the simplest cases. let mirror = match kind { - "client.connected" => crate::config::config().on_connect_cmd.clone(), - "client.disconnected" => crate::config::config().on_disconnect_cmd.clone(), + "client.connected" => pf_host_config::config().on_connect_cmd.clone(), + "client.disconnected" => pf_host_config::config().on_disconnect_cmd.clone(), _ => None, }; if let Some(cmd) = mirror { diff --git a/crates/punktfunk-host/src/inject.rs b/crates/punktfunk-host/src/inject.rs index 3fdc7638..81d07786 100644 --- a/crates/punktfunk-host/src/inject.rs +++ b/crates/punktfunk-host/src/inject.rs @@ -124,7 +124,7 @@ pub fn default_backend() -> Backend { } } // An explicit compositor pick (set per connect / mid-stream) is the strongest signal. - let compositor = crate::config::config().compositor.clone(); + let compositor = pf_host_config::config().compositor.clone(); if let Some(c) = compositor.as_deref() { let c = c.trim(); if c.eq_ignore_ascii_case("gamescope") { @@ -176,7 +176,7 @@ pub(crate) use service::InjectorService; /// (`org.gnome.Mutter.RemoteDesktop`), the same direct API the Mutter video backend uses. #[cfg(target_os = "linux")] fn libei_ei_source() -> libei::EiSource { - let gnome = crate::config::config() + let gnome = pf_host_config::config() .compositor .as_deref() .is_some_and(|v| v.trim().eq_ignore_ascii_case("mutter")) diff --git a/crates/punktfunk-host/src/main.rs b/crates/punktfunk-host/src/main.rs index fe8cf220..24869bf6 100644 --- a/crates/punktfunk-host/src/main.rs +++ b/crates/punktfunk-host/src/main.rs @@ -20,7 +20,6 @@ mod audio; mod capture; -mod config; mod detect; mod devtest; mod discovery; diff --git a/crates/punktfunk-host/src/mgmt/gpu.rs b/crates/punktfunk-host/src/mgmt/gpu.rs index 6fc920f1..972e4d6f 100644 --- a/crates/punktfunk-host/src/mgmt/gpu.rs +++ b/crates/punktfunk-host/src/mgmt/gpu.rs @@ -139,7 +139,7 @@ pub(crate) fn gpu_state() -> GpuState { preferred_id, preferred_name, preferred_available, - env_override: crate::config::config() + env_override: pf_host_config::config() .render_adapter .clone() .filter(|s| !s.is_empty()), diff --git a/crates/punktfunk-host/src/native/compositor.rs b/crates/punktfunk-host/src/native/compositor.rs index 885a1043..19e4bb03 100644 --- a/crates/punktfunk-host/src/native/compositor.rs +++ b/crates/punktfunk-host/src/native/compositor.rs @@ -57,7 +57,7 @@ pub(super) fn resolve_compositor( crate::vdisplay::cancel_pending_tv_restore(); // Explicit operator override (legacy / CI / forcing a backend for a test) wins and is assumed // to come with a hand-set env — don't retarget the process env in that case. - let overridden = crate::config::config().compositor.is_some(); + let overridden = pf_host_config::config().compositor.is_some(); let detected = if overridden { crate::vdisplay::detect().ok() } else { diff --git a/crates/punktfunk-host/src/native/gamepad.rs b/crates/punktfunk-host/src/native/gamepad.rs index bd9f6e89..c27eefc5 100644 --- a/crates/punktfunk-host/src/native/gamepad.rs +++ b/crates/punktfunk-host/src/native/gamepad.rs @@ -200,7 +200,7 @@ fn degrade_steam_on_conflict(chosen: GamepadPref) -> GamepadPref { /// Resolve the client's gamepad-backend preference (the env/logging shell around /// [`pick_gamepad`]). Always concrete — the `Welcome` reports what the session will drive. pub(super) fn resolve_gamepad(pref: GamepadPref) -> GamepadPref { - let env = crate::config::config().gamepad.clone(); + let env = pf_host_config::config().gamepad.clone(); let chosen = pick_gamepad( pref, env.as_deref(), diff --git a/crates/punktfunk-host/src/native/handshake.rs b/crates/punktfunk-host/src/native/handshake.rs index 539eaaaf..6ec1cd8a 100644 --- a/crates/punktfunk-host/src/native/handshake.rs +++ b/crates/punktfunk-host/src/native/handshake.rs @@ -207,7 +207,7 @@ pub(super) async fn negotiate( // Welcome, exactly like the 4:4:4 gate below, so `color` reflects what we'll really emit — // the honest-downgrade channel: a GPU/backend that can't 10-bit yields 8-bit AND an SDR // label that matches the stream. - let host_wants_10bit = crate::config::config().ten_bit; + let host_wants_10bit = pf_host_config::config().ten_bit; let client_supports_10bit = hello.video_caps & punktfunk_core::quic::VIDEO_CAP_10BIT != 0; // The GPU probe may open a tiny encoder on first use, so run it off the reactor like the // 4:4:4 probe below (blocking probes → spawn_blocking), short-circuited behind the cheap @@ -239,7 +239,7 @@ pub(super) async fn negotiate( // what we'll really emit — the honest-downgrade channel: if any gate fails the client is // told 4:2:0 before it builds its decoder. The probe opens a tiny encoder; it runs only // when the earlier gates pass and is cached after the first. - let host_wants_444 = crate::config::config().four_four_four; + let host_wants_444 = pf_host_config::config().four_four_four; let client_supports_444 = hello.video_caps & punktfunk_core::quic::VIDEO_CAP_444 != 0; // The active capturer must be able to deliver a full-chroma (RGB) source — the honest-downgrade // gate. Linux's portal capturer can; the Windows IDD-push path delivers subsampled NV12/P010 diff --git a/crates/punktfunk-host/src/native/stream.rs b/crates/punktfunk-host/src/native/stream.rs index eff57d85..1cb08db5 100644 --- a/crates/punktfunk-host/src/native/stream.rs +++ b/crates/punktfunk-host/src/native/stream.rs @@ -873,7 +873,7 @@ pub(super) fn virtual_stream(ctx: SessionContext) -> Result<()> { #[cfg(not(any(target_os = "windows", target_os = "linux")))] let _ = &launch; - let perf = crate::config::config().perf; + let perf = pf_host_config::config().perf; // Microburst cap (applied in send_loop/paced_submit): a frame ≤ the cap bursts out // immediately; only a bigger frame's overflow is spread. `None` = auto — max(128 KB, the // AU's wire bytes / 4), so the burst stays a bounded fraction of high-rate frames instead @@ -956,7 +956,7 @@ pub(super) fn virtual_stream(ctx: SessionContext) -> Result<()> { // place when the box flips Gaming↔Desktop. When not spawned, session_rx just stays empty. let mut compositor = compositor; let (session_tx, session_rx) = std::sync::mpsc::channel::(); - let watch = session_watch_enabled() && crate::config::config().compositor.is_none(); + let watch = session_watch_enabled() && pf_host_config::config().compositor.is_none(); let _watcher = if watch { tracing::info!("session watcher on — following a mid-stream Gaming↔Desktop switch"); let stop = stop.clone(); @@ -1461,7 +1461,7 @@ pub(super) fn virtual_stream(ctx: SessionContext) -> Result<()> { let (new_cap, new_enc, new_frame, new_interval, new_node_id, new_display_gen) = loop { // Follow the active session unless an explicit PUNKTFUNK_COMPOSITOR pin forbids // retargeting (then we stick to the pinned backend and just rebuild it). - if crate::config::config().compositor.is_none() { + if pf_host_config::config().compositor.is_none() { let active = crate::vdisplay::detect_active_session(); // A4: fold any compositor-instance change into the epoch/invalidation before we // rebuild, so the rebuild's acquire won't reuse a dead-instance node. diff --git a/crates/punktfunk-host/src/session_plan.rs b/crates/punktfunk-host/src/session_plan.rs index cf92f495..8d86d4ba 100644 --- a/crates/punktfunk-host/src/session_plan.rs +++ b/crates/punktfunk-host/src/session_plan.rs @@ -205,7 +205,7 @@ fn resolve_encoder() -> EncoderBackend { // capture (`EncoderBackend::Software.is_gpu() == false` → `output_format().gpu = false`), so the // portal capturer delivers CPU RGB. Everything else stays `PlatformAuto` (NVENC/VAAPI resolved // inside `encode::open_video`). - match crate::config::config().encoder_pref.as_str() { + match pf_host_config::config().encoder_pref.as_str() { "software" | "sw" | "openh264" => EncoderBackend::Software, _ => EncoderBackend::PlatformAuto, } diff --git a/crates/punktfunk-host/src/vdisplay.rs b/crates/punktfunk-host/src/vdisplay.rs index 2acf39ae..082bbada 100644 --- a/crates/punktfunk-host/src/vdisplay.rs +++ b/crates/punktfunk-host/src/vdisplay.rs @@ -186,7 +186,7 @@ pub fn with_env_lock(f: impl FnOnce() -> R) -> R { /// a backend for a test), else the **live session** ([`detect_active_session`] — so a Bazzite box /// follows Gaming↔Desktop switches), else a last-resort `XDG_CURRENT_DESKTOP` read. pub fn detect() -> Result { - if let Some(v) = crate::config::config().compositor.as_deref() { + if let Some(v) = pf_host_config::config().compositor.as_deref() { return match v.trim().to_ascii_lowercase().as_str() { "kwin" | "kde" | "plasma" => Ok(Compositor::Kwin), // `hyprland` names the distinct backend (D1); `wlroots`/`sway`/`wlr` stay wlroots-proper. @@ -317,7 +317,7 @@ pub(crate) mod layout; pub fn resolve_topology(t: policy::Topology) -> policy::Topology { match t { policy::Topology::Auto => { - if crate::config::config().compositor.is_some() { + if pf_host_config::config().compositor.is_some() { policy::Topology::Extend } else { policy::Topology::Exclusive diff --git a/crates/punktfunk-host/src/vdisplay/linux/gamescope.rs b/crates/punktfunk-host/src/vdisplay/linux/gamescope.rs index 4268604e..0d1e36ff 100644 --- a/crates/punktfunk-host/src/vdisplay/linux/gamescope.rs +++ b/crates/punktfunk-host/src/vdisplay/linux/gamescope.rs @@ -1408,7 +1408,7 @@ fn spawn(w: u32, h: u32, hz: u32, cmd: Option<&str>, log: &std::path::Path) -> R let app = shape_dedicated_command(&app); let relay = ei_socket_file(); let _ = std::fs::remove_file(&relay); // stale socket path from a previous session - let steam_mode = crate::config::config().gamescope_steam; + let steam_mode = pf_host_config::config().gamescope_steam; let mut cmd = Command::new("gamescope"); add_bare_gamescope_args(&mut cmd, w, h, hz, steam_mode); cmd.args([ diff --git a/crates/punktfunk-host/src/vdisplay/session.rs b/crates/punktfunk-host/src/vdisplay/session.rs index 8ded7d74..1253e63c 100644 --- a/crates/punktfunk-host/src/vdisplay/session.rs +++ b/crates/punktfunk-host/src/vdisplay/session.rs @@ -418,7 +418,7 @@ pub fn apply_session_env(_active: &ActiveSession) {} /// handshake error tell the client to simply retry. #[cfg(target_os = "linux")] pub fn try_recover_session() -> bool { - let Some(cmd) = crate::config::config().recover_session_cmd.clone() else { + let Some(cmd) = pf_host_config::config().recover_session_cmd.clone() else { return false; }; static LAST_LAUNCH: std::sync::Mutex> = std::sync::Mutex::new(None);