Files
Nomarchy/modules/home/recording.nix
Bernardo Magri 0fe46221ea
All checks were successful
Check / eval (push) Successful in 2m56s
feat(capture): screen recording — menu start, bar-click stop (item 12)
nomarchy-record owns the lifecycle: start prefers wl-screenrec (VAAPI
hardware encode) and falls back to wf-recorder if it dies at startup
(the no-VAAPI case), stop SIGINTs so the file finalizes cleanly, and
status feeds a self-gating Waybar ⏺ REC (alert red) whose click is
the one stop surface — signal 8 pokes make it appear/vanish
instantly. Capture gains Record region/screen (+ audio variants) and
self-swaps to '■ Stop recording' while one runs. Parity: both summer
whole-swap bars carry the same module. Recordings land in
~/Videos/Recordings with the screenshot timestamp naming (deviation
from 'next to Screenshots': an .mp4 in Pictures felt wrong).

V1: rendered bar config + CSS asserted, summer jsonc parse, recorder
dry-run state machine correct (idle/active/usage exits), both
recorders in home-path. Real capture needs a session → V3 queued
(incl. the VAAPI-vs-fallback check on the AMD box).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 20:58:40 +01:00

100 lines
3.7 KiB
Nix
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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; }
poke_bar() { pkill -RTMIN+8 waybar 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
'')
];
}