nixpkgs wraps waybar, so the running comm is `.waybar-wrapped`: `pkill -x waybar` (state-sync restart/SIGUSR2 branches, tz-watch, updates) matched nothing — a theme switch neither restarted nor reloaded the bar, which then kept the gtk.css of whatever theme it started under (the stale workspace-digit colors reported 2026-07-18; companion gtk fix in the next commit). The unanchored pokes (recording, airplane, theme-shot) had the opposite bug: `waybar` substring-matches the supervisor's `nomarchy-waybar` comm too, and an unhandled RTMIN terminates its bash — the pokes were killing the crash guard. All seven sites now use `pkill … -x 'waybar|\.waybar-wrapped'`. state-sync 0.5.1 → 0.5.2. Verified live on Newton (V3-grade): new pattern restarts the bar under the supervisor (fresh pid, supervisor alive); RTMIN+10 poke reaches the bar, supervisor survives. V0 `nix flake check --no-build` + py_compile; V1 HM generation + system toplevel build. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
103 lines
4.0 KiB
Nix
103 lines
4.0 KiB
Nix
# Screen recording (menu › Tools › Capture). One helper owns the whole
|
||
# lifecycle: `start` launches wl-screenrec (VAAPI hardware encode) and
|
||
# falls back to wf-recorder (software x264) if it dies on the spot —
|
||
# e.g. no usable VAAPI device; `status` feeds the self-gating Waybar
|
||
# indicator (waybar.nix, signal 8), whose click is the ONE stop surface
|
||
# (`stop` SIGINTs the recorder so it finalizes the file cleanly). State
|
||
# is a runtime pidfile — nothing persists across sessions.
|
||
{ config, lib, pkgs, ... }:
|
||
|
||
lib.mkIf config.nomarchy.rofi.enable {
|
||
home.packages = [
|
||
pkgs.wl-screenrec
|
||
pkgs.wf-recorder
|
||
|
||
(pkgs.writeShellScriptBin "nomarchy-record" ''
|
||
run="''${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"
|
||
pidfile="$run/nomarchy-record.pid"
|
||
filefile="$run/nomarchy-record.file"
|
||
|
||
alive() { [ -f "$pidfile" ] && kill -0 "$(cat "$pidfile")" 2>/dev/null; }
|
||
# -x, both comm names: nixpkgs wraps the binary as `.waybar-wrapped`,
|
||
# and an unanchored `waybar` also matches (and kills) the
|
||
# nomarchy-waybar supervisor, whose bash dies on an unhandled RTMIN.
|
||
poke_bar() { pkill -RTMIN+8 -x 'waybar|\.waybar-wrapped' 2>/dev/null || true; }
|
||
|
||
case "''${1:-}" in
|
||
start)
|
||
if alive; then
|
||
notify-send "Screen recording" "Already recording — stop it via the ⏺ in the bar."
|
||
exit 1
|
||
fi
|
||
target="''${2:-screen}"; audio="''${3:-}"
|
||
geo=""
|
||
if [ "$target" = region ]; then
|
||
geo=$(slurp) || exit 0 # Esc in slurp = cancel, silently
|
||
fi
|
||
dir="$HOME/Videos/Recordings"
|
||
mkdir -p "$dir"
|
||
file="$dir/$(date +%Y%m%d-%H%M%S).mp4"
|
||
|
||
launch() { # launch <recorder> -> 0 if it survived startup
|
||
case "$1" in
|
||
wl-screenrec)
|
||
setsid wl-screenrec ''${geo:+-g "$geo"} \
|
||
''${audio:+--audio} -f "$file" >/dev/null 2>&1 & ;;
|
||
wf-recorder)
|
||
setsid wf-recorder ''${geo:+-g "$geo"} \
|
||
''${audio:+-a} -f "$file" >/dev/null 2>&1 & ;;
|
||
esac
|
||
echo $! > "$pidfile"
|
||
sleep 0.7
|
||
alive
|
||
}
|
||
|
||
started=""
|
||
if command -v wl-screenrec >/dev/null 2>&1 && launch wl-screenrec; then
|
||
started=wl-screenrec
|
||
elif command -v wf-recorder >/dev/null 2>&1 && launch wf-recorder; then
|
||
started=wf-recorder # software fallback (no VAAPI device)
|
||
fi
|
||
if [ -z "$started" ]; then
|
||
rm -f "$pidfile"
|
||
notify-send "Screen recording" "Recorder failed to start (no wl-screenrec/wf-recorder able to run)."
|
||
exit 1
|
||
fi
|
||
printf '%s' "$file" > "$filefile"
|
||
poke_bar
|
||
notify-send "Screen recording" "Recording ($started)''${audio:+ with audio} — click the ⏺ in the bar to stop." ;;
|
||
|
||
stop)
|
||
if ! alive; then
|
||
rm -f "$pidfile" "$filefile"; poke_bar
|
||
notify-send "Screen recording" "No recording is running."
|
||
exit 0
|
||
fi
|
||
pid=$(cat "$pidfile")
|
||
kill -INT "$pid" 2>/dev/null # graceful: both recorders finalize on INT
|
||
for _ in $(seq 1 50); do kill -0 "$pid" 2>/dev/null || break; sleep 0.1; done
|
||
kill -0 "$pid" 2>/dev/null && kill "$pid" 2>/dev/null
|
||
file=$(cat "$filefile" 2>/dev/null || echo "?")
|
||
rm -f "$pidfile" "$filefile"
|
||
poke_bar
|
||
notify-send "Screen recording saved" "$file" ;;
|
||
|
||
active)
|
||
alive ;;
|
||
|
||
status)
|
||
# Waybar JSON while recording; nothing => module hidden.
|
||
if alive; then
|
||
file=$(cat "$filefile" 2>/dev/null || echo "")
|
||
printf '{"text":"⏺ REC","class":"recording","tooltip":"Recording to %s — click to stop"}\n' "''${file##*/}"
|
||
fi
|
||
exit 0 ;;
|
||
|
||
*)
|
||
echo "usage: nomarchy-record start [region|screen] [audio] | stop | active | status" >&2
|
||
exit 2 ;;
|
||
esac
|
||
'')
|
||
];
|
||
}
|