0c261de636f5fc64502223aee07ee5861674fe01
3
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
f0e71e928a |
fix(gamestream): the resolved launch command is what the backend nests
plugin-kit-publish / publish (push) Failing after 34s
ci / web (push) Successful in 58s
ci / docs-site (push) Successful in 1m2s
apple / swift (push) Successful in 5m39s
ci / bench (push) Successful in 6m18s
deb / build-publish (push) Successful in 8m56s
decky / build-publish (push) Successful in 34s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 10s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 42s
android / android (push) Successful in 12m2s
deb / build-publish-client-arm64 (push) Successful in 7m35s
ci / rust-arm64 (push) Successful in 17m58s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 1m26s
windows-host / package (push) Successful in 19m41s
deb / build-publish-host (push) Successful in 18m45s
docker / build-push (ci, ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 8m49s
arch / build-publish (push) Successful in 22m17s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 9m4s
ci / rust (push) Failing after 23m6s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 12m7s
docker / deploy-docs (push) Successful in 28s
docker / build-push-arm64cross (push) Successful in 4m20s
apple / screenshots (push) Successful in 24m30s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 21m41s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 21m18s
A Windows/macOS build compiled the resolved-launch parameter out entirely and warned about it, because the two uses left were both Linux-gated. Both platforms want the same value: off Linux `set_launch_command` is a backend no-op and a library title resolves to no command at all (the interactive-session spawner launches it by id), so the cfg split was carrying an older distinction that no longer exists. Also covers the Windows half of `process_name` with a test — the pure name match plus a live scan for this test process, since `find`'s early return would otherwise skip the signal entirely and the test would pass vacuously. Gates: .133 check + clippy --all-targets clean with no warnings, 5/5 procscan (incl. live); .21 299 tests + fmt. |
||
|
|
110eabf281 |
feat(library/providers): let a provider say how to recognize its games
A plugin's titles launch through the provider's own client, which hands off and exits — so the host had nothing left to watch, and both lifetime behaviors went quiet for exactly the entries a provider contributes. A `ProviderEntry` (and a manual custom entry) may now carry an optional `detect` hint: install dir, exe, or process name. It is deliberately a subset of what the host tracks internally. A Steam appid or a launcher's environment marker are things the host discovers for itself and would be meaningless — or dangerous — to take on someone's word; where a title is installed is something only the provider knows. The host's own findings win where both exist, so a stale export can never redirect the matcher, and a blank field is treated as absent rather than as "match everything" — an empty install dir would otherwise prefix-match every process on the box, and this feature can end processes. `process_name` is the weakest of the three and the only one typed by hand, so it is matched case-insensitively against the image's file name and nothing else: `retroarch` finds RetroArch, not a helper whose name merely starts the same way, and not a script that happens to live in a `retroarch/` directory. The never-adopt-a-pre-existing-process rule still bounds it. Also: the tray summary gains the running-game row (with the closing-in countdown for a game whose client is gone — visible at the machine without opening the console), the SDK mirrors the `game.*` events, and its generated client catches up with the endpoints Phase 1 added. Gates on .21: check + clippy --all-targets clean, 299 tests, fmt CI-parity, openapi regenerated (GameEntry still carries no `detect` outbound); SDK tsc + 54 tests green. |
||
|
|
ed4e3d3ab6 |
feat(session): end-game/end-session lifetime on Windows
Phase 2. The lease, the settings, the events and the status surface were already platform-neutral; what Windows lacked was a way to see processes and a way to ask one to close. `procscan` splits per-OS behind one contract. The Windows matcher is a Toolhelp snapshot plus each process's full image path (`QueryFullProcessImageNameW`), with creation times from `GetProcessTimes` enforcing the two rules the module exists for: never adopt a process that predates the launch, never trust a bare pid. Both matter more here than on Linux — the host is SYSTEM, so it can see and signal everything, and Windows recycles pids briskly. Path matching is case-insensitive and separator-aware, and normalizes the `\\?\` prefix `canonicalize` adds, without which a store-derived path would never compare equal to a live image path. There is no reaper argv and no readable environment on Windows, so a spec carrying only a Steam appid or an env marker matches nothing rather than falling through to an empty predicate. Steam's appid instead feeds a **veto**: its per-app `Running` flag in the user's hive can't be trusted to say a game IS running (Steam sets it around updates too, and leaves it stale after a crash), but it is exactly right for refusing to declare one gone. If the matcher can't see a game whose exe sits outside its manifest's install dir, ending the session would be a false positive the player feels immediately; honoring the veto only ever leaves a stream up. Termination asks before it insists, which on Windows needs a detail that fails silently if missed: `EnumWindows` only sees the calling thread's desktop, and the host's is session 0, which holds none of the user's windows. So the terminating thread binds to the input desktop first (the pattern `pf-inject`'s `sendinput.rs` uses), posts `WM_CLOSE` to the game's visible top-level windows, waits, and only then calls `TerminateProcess` on freshly re-verified pids. Without the desktop bind the polite pass finds nothing and every game dies unsaved. Job Objects, planned as WP2.3, are deferred with the reasoning in the design doc: every Windows launch either hands off through a launcher or the shell — where a job would wrap a shim that exits immediately — or is a direct exe whose path we already know, and wiring one in would touch the `CreateProcessAsUserW` token path the UAC and secure-desktop work depends on. Also: the watcher's steady-state poll now re-verifies known pids and only re-scans the whole table once they all vanish (which still catches a game that re-execs). On Windows a full scan is an `OpenProcess` per process on the box, so this is the difference between a negligible and a noticeable poll. Gates: Linux .21 check/clippy/fmt/293 tests green; Windows .133 check + clippy --all-targets clean, and the 4 procscan tests pass — including the live one that finds the test process in the real process table and rejects a wrong creation time. On-glass Windows (Steam/Epic/GOG/Xbox titles, the unsaved-progress check) still owed; it needs a box with games on it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |