fix(hyprlua): only offer real capture nodes; show howdy's enroll error

The Brio (and most UVC webcams) expose a second /dev/video* node that is
metadata-capture only. The chooser listed it, the existence-only guard
accepted it, and howdy aborted with a bare exit 1 because that node can
never deliver a frame.

- list_cameras: skip nodes with no capture pixel formats (is_capture_device)
- howdy_camera_ok: require an actual capture node, not just an existing path,
  so a stale metadata-node device_path triggers reconfiguration
- howdy_add: tee howdy's output and surface the real reason on failure
  instead of only the exit code

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
main
Amir Alexander Abdelbaki 2026-06-13 22:41:24 +02:00
parent 5f83f10f48
commit 204dd31958
1 changed files with 21 additions and 4 deletions

View File

@ -74,9 +74,18 @@ require_dialog() {
}
# ── Camera helpers ─────────────────────────────────────────────────────────────
# True only for nodes that actually deliver video frames. UVC webcams expose
# extra /dev/video* nodes for metadata capture (no pixel formats); pointing
# howdy at one of those makes it fail to read a frame and abort with exit 1.
is_capture_device() {
v4l2-ctl --device="$1" --list-formats 2>/dev/null \
| grep -qE '^[[:space:]]*\[[0-9]+\]:'
}
list_cameras() {
for dev in /dev/video*; do
[[ -c "$dev" ]] || continue
is_capture_device "$dev" || continue
local id="${dev#/dev/video}"
local name
name=$(v4l2-ctl --device="$dev" --info 2>/dev/null \
@ -277,10 +286,12 @@ howdy_set_cfg() {
howdy_set_device_path() { howdy_set_cfg device_path "$1"; }
# True when howdy points at a device node that actually exists.
# True when howdy points at a node that exists AND can actually capture video
# (not a metadata-only node, which would make enrollment fail with exit 1).
howdy_camera_ok() {
local dp; dp=$(howdy_get_device_path)
[[ -n "$dp" && "$dp" != none && -e "$dp" ]]
[[ -n "$dp" && "$dp" != none && -e "$dp" ]] || return 1
is_capture_device "$dp"
}
# howdy's stock tuning assumes a Windows-Hello IR sensor. A regular colour
@ -356,7 +367,10 @@ howdy_add() {
printf "\033[35m ─────────────────────────────────────────\033[0m\n\n"
printf " Look at the camera and hold still.\n\n"
# howdy has no label flag; the label is read from stdin during `add`.
printf '%s\n' "$name" | sudo howdy -U "$USER" add
# Tee the output so the actual reason (dark frames, no face, busy camera…)
# can be shown on failure instead of a bare exit code.
local log="$TMP_D/howdy_add.log"
printf '%s\n' "$name" | sudo howdy -U "$USER" add 2>&1 | tee "$log"
local rc=${PIPESTATUS[1]}
if [[ $rc -eq 0 ]]; then
@ -364,7 +378,10 @@ howdy_add() {
"Face model '$name' added.\n\nYou may need to relogin for PAM changes to take effect." \
9 58
else
msg "Failed" "Enrollment failed (code $rc).\n\nCheck camera and lighting." 8 52
local why; why=$(grep -vE '^\s*$' "$log" 2>/dev/null | tail -n 4)
msg "Failed" \
"Enrollment failed (code $rc).\n\nhowdy said:\n${why:-(no output captured)}\n\nIf it's a camera/frame error, re-run\n'configure camera' and pick another node." \
16 64
fi
}