pod: fully explicit activation (--profile) + RIOJoy.Tray.Ready signal

No detection anywhere in the pod chain (Cyd: foreground detection is too
slow - the pad appears after the game already enumerated controllers).
--profile <name> activates immediately at startup, never runs the
auto-switch watcher, and on success signals the named manual-reset event
RIOJoy.Tray.Ready (process-lifetime, never stale) so a launcher waits on
the signal instead of counting winmm devices. Legible failures for the
launcher: exit 4 unknown profile, exit 5 activation failed with the reason
on stderr - both verified live against the built exe. Editor close
re-activates the explicit profile. build-pod start scripts now pass
--profile <Name> --exit-with <exe>; docs updated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-31 23:01:44 -05:00
co-authored by Claude Fable 5
parent 5befd1d511
commit bdd30678e3
5 changed files with 164 additions and 28 deletions
+28 -8
View File
@@ -218,16 +218,36 @@ entry points the game's package wires up:
game:
```
start "" "...\riojoy\app\RioJoy.Tray.exe" --exit-with <game exe>
start "" "...\riojoy\app\RioJoy.Tray.exe" --profile "<Name>" --exit-with <game exe>
```
`--exit-with` makes RIOJoy self-managing: it activates when the game's window
comes foreground, and once the game process has run and then exited it tears
itself down completely (ports released, wallpaper restored, plasma blanked)
and quits. If the game never appears within 60 s it also quits, so a failed
launch can't strand it. Back-to-back launches hand over cleanly: a starting
`--exit-with` instance waits up to 15 s for the previous game's copy to
release the single-instance lock.
In pod mode **everything is explicit — there is no detection on either
side**. `--profile` activates the named profile immediately at startup, so
the virtual controller and the ports exist *before* the game launches and
enumerates input devices (foreground detection activates ~1 s after the
window appears — too late for startup enumeration, and the auto-switch
watcher never runs in this mode). On success RIOJoy signals the named event
**`RIOJoy.Tray.Ready`** — a launcher waits on that (with a timeout) instead
of guessing from device enumeration, and the failure modes stay legible:
| Launcher observes | Meaning |
|---|---|
| `RIOJoy.Tray.Ready` signaled | profile active; pad + ports exist — start the game |
| RIOJoy exited, code 4 | profile name not in the config (script typo) |
| RIOJoy exited, code 5 | activation failed — reason on stderr (port busy, bad endpoint) |
| no signal, still running | genuinely stuck — timeout and report |
The event is process-lifetime (it can never go stale); either side may create
it first — same name, manual-reset, both converge on one object. Batch-only
integrations without a launcher can simply order the script: `start`
RIOJoy, then the game — but a real launcher should wait on the event.
`--exit-with` handles the other end: once the game process has run and then
exited, RIOJoy tears itself down completely (ports released, wallpaper
restored, plasma blanked) and quits. If the game never appears within 60 s it
also quits, so a failed launch can't strand it. Back-to-back launches hand
over cleanly: a starting pod instance waits up to 15 s for the previous
game's copy to release the single-instance lock.
Properties that matter on a cabinet: each game pins the RIOJoy build it was
verified with (updating RIOJoy for a new game can't regress an old one);