61 lines
3.2 KiB
Bash
Executable File
61 lines
3.2 KiB
Bash
Executable File
#!/bin/sh
|
|
# Watches sway for the user leaving Big Picture. Installed to /usr/local/bin/session-watcher.
|
|
#
|
|
# THIS IS THE "MEDIA APPS ONLY START WHEN YOU LEAVE BIG PICTURE" MECHANISM, HALF TWO.
|
|
# Read steam-session's header first — it explains why there are two halves.
|
|
#
|
|
# The case this one covers: Steam is *still running*, but the user is no longer looking
|
|
# at it. "Exit Big Picture mode" (which drops to Steam's desktop client), the remote's
|
|
# channel keys, $mod+3, or Home Assistant's Screen select — all of those change the
|
|
# focused sway workspace and none of them make the Steam process exit, so steam-session
|
|
# never resumes and something else has to notice.
|
|
#
|
|
# WHY WORKSPACE EVENTS AND NOT WINDOW TITLES
|
|
# ------------------------------------------
|
|
# The obvious implementation is to poll for a window titled "Steam Big Picture Mode"
|
|
# and react when it goes away. That was rejected: the title, the window class and the
|
|
# very existence of a separate Big Picture window have all changed across Steam client
|
|
# rewrites, and a media session that silently stops appearing after a Steam update is a
|
|
# bad failure — it looks like the image is broken, not like a string moved. A sway
|
|
# workspace name is a contract this repo owns and can only change by editing the sway
|
|
# config and steamtv_agent/sway_control.py together.
|
|
#
|
|
# Cost: one blocked read on a socket, and a jq per workspace switch. It publishes
|
|
# nothing and listens on nothing — the session-mode sensor in Home Assistant is
|
|
# steamtv-agent asking sway, not this script pushing anywhere. (Adding an inbound
|
|
# listener here would breach the MQTT-is-the-only-control-surface rule; see
|
|
# steamtv_agent/mqtt_discovery.py.)
|
|
set -eu
|
|
|
|
WS_STEAM="1:steam"
|
|
|
|
if ! command -v jq >/dev/null 2>&1; then
|
|
echo "session-watcher: jq is missing; the media session will only start when Steam" >&2
|
|
echo " itself exits (steam-session's path). Install jq and reload sway." >&2
|
|
exit 1
|
|
fi
|
|
|
|
# `swaymsg -m` streams one JSON object per event line and blocks forever. If sway goes
|
|
# away the pipe closes and this exits — which is correct, since sway restarting means
|
|
# `exec_always` starts a fresh watcher.
|
|
swaymsg -t subscribe -m '["workspace"]' 2>/dev/null | while read -r event; do
|
|
# "focus" is the only change that means the user went somewhere; "init", "empty" and
|
|
# "rename" fire during ordinary window churn and must not trigger a launch.
|
|
change=$(printf '%s' "$event" | jq -r '.change // empty' 2>/dev/null) || continue
|
|
[ "$change" = "focus" ] || continue
|
|
|
|
current=$(printf '%s' "$event" | jq -r '.current.name // empty' 2>/dev/null) || continue
|
|
[ -n "$current" ] || continue
|
|
# An `if` rather than `[ … ] && continue`: the && form returns non-zero when the test
|
|
# is false, which under `set -e` would kill the watcher the first time somebody moved
|
|
# to a non-Steam workspace — i.e. exactly once, silently, on the first use.
|
|
if [ "$current" = "$WS_STEAM" ]; then
|
|
continue
|
|
fi
|
|
|
|
# No --focus: the user has already chosen where they want to be, and yanking them to
|
|
# the browser workspace because they pressed the channel key would be worse than
|
|
# doing nothing. This only makes sure the apps exist.
|
|
/usr/local/bin/media-session start >/dev/null 2>&1 || true
|
|
done
|