feat(host): script-facing stream-active runtime marker file
ci / web (push) Successful in 1m54s
ci / docs-site (push) Successful in 1m50s
decky / build-publish (push) Successful in 23s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 15s
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 17s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 12s
ci / rust (push) Failing after 7m8s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 1m12s
ci / bench (push) Successful in 6m10s
docker / deploy-docs (push) Successful in 27s
arch / build-publish (push) Successful in 11m11s
android / android (push) Successful in 14m47s
windows-host / package (push) Successful in 15m22s
deb / build-publish (push) Successful in 14m9s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 14m6s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 15m43s
apple / swift (push) Successful in 4m58s
apple / screenshots (push) Successful in 21m8s

Maintain $XDG_RUNTIME_DIR/punktfunk/stream while any client is streaming,
holding the primary session's negotiated mode. A per-title launch wrapper
can branch on it: present → session is already at the stream mode, run the
game as-is; absent → run the local (e.g. multi-head gamescope) path.

- New stream_marker module: RAII Guard registered per session, refcounted
  for concurrent clients, atomic (temp+rename) writes, injection-safe
  single-quoted client name. POSIX-sh-sourceable KEY=value, namespaced
  PF_STREAM_* keys, schema-versioned, additive-only.
- Hooked into serve_session so every exit path (disconnect, error,
  panic-unwind) retracts the marker. File exists iff a stream is live.

Unblocks the downstream triple-head gamescope launch-wrapper use case.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-15 18:40:05 +02:00
parent a7d4a93ff2
commit a93f5a71ce
3 changed files with 271 additions and 0 deletions
+11
View File
@@ -1582,6 +1582,17 @@ async fn serve_session(
let source = opts.source;
let (seconds, frames) = (opts.seconds, opts.frames);
let mode = hello.mode;
// Script-facing runtime marker: `$XDG_RUNTIME_DIR/punktfunk/stream` exists (with this session's
// negotiated mode) for exactly as long as this session streams. Held by RAII to session end, so
// every exit path — clean disconnect, error, panic-unwind — retracts it. Lets a launch wrapper
// branch "streaming → run the game as-is; not → my local multi-head gamescope" (see the module).
let _stream_marker = crate::stream_marker::announce(crate::stream_marker::StreamInfo {
width: mode.width,
height: mode.height,
refresh_hz: mode.refresh_hz,
hdr: welcome.color.is_hdr(),
client: hello.name.clone().unwrap_or_default(),
});
// The session's launch, threaded into the data plane. Windows carries the store-qualified id
// (spawned into the interactive user session once capture is live); other hosts resolve the id
// to its shell command HERE against the host's own library — a client can only ever pick an