Only offer video capture devices as webcams (#6732)
* Only offer video capture devices as webcams V4L2 exposes raw processing and output-only nodes beside usable cameras. The webcam picker and automatic recorder selection treated the first /dev/video node as a camera, so IPU6 laptops opened a black overlay instead of their loopback capture device.\n\nShare one device lister across detection, selection, and recording, and keep only groups whose first video node advertises Video Capture in Device Caps. Cover raw IPU nodes, ordinary capture devices, and capture-less systems. * Fall through to a later capture-capable node in a webcam group A group whose first video node is not capture-capable vanished entirely, even when a later node in the same group could capture. Probe each node until one qualifies, still emitting at most one device per group. Also exit zero explicitly: a trailing filtered device used to leak the failed capability check as the script's exit status. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: David Heinemeier Hansson <david@hey.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
David Heinemeier Hansson
parent
860503f56a
commit
8b9e43d3e5
@@ -64,7 +64,7 @@ start_webcam_overlay() {
|
|||||||
|
|
||||||
# Auto-detect first available webcam if none specified
|
# Auto-detect first available webcam if none specified
|
||||||
if [[ -z $WEBCAM_DEVICE ]]; then
|
if [[ -z $WEBCAM_DEVICE ]]; then
|
||||||
WEBCAM_DEVICE=$(v4l2-ctl --list-devices 2>/dev/null | grep -m1 "^[[:space:]]*/dev/video" | tr -d '\t')
|
WEBCAM_DEVICE=$(omarchy-capture-webcam-list | sed -n '1s/[[:space:]].*//p')
|
||||||
if [[ -z $WEBCAM_DEVICE ]]; then
|
if [[ -z $WEBCAM_DEVICE ]]; then
|
||||||
omarchy-notification-send -u critical -t 3000 "No webcam devices found"
|
omarchy-notification-send -u critical -t 3000 "No webcam devices found"
|
||||||
return 1
|
return 1
|
||||||
|
|||||||
@@ -3,21 +3,7 @@
|
|||||||
# omarchy:summary=Pick a webcam and start a screen recording with it
|
# omarchy:summary=Pick a webcam and start a screen recording with it
|
||||||
# omarchy:examples=omarchy capture screenrecording-with-webcam
|
# omarchy:examples=omarchy capture screenrecording-with-webcam
|
||||||
|
|
||||||
set -o pipefail
|
mapfile -t devices < <(omarchy-capture-webcam-list)
|
||||||
|
|
||||||
webcam_list() {
|
|
||||||
v4l2-ctl --list-devices 2>/dev/null | while IFS= read -r line; do
|
|
||||||
if [[ $line != $'\t'* && -n $line ]]; then
|
|
||||||
local name="$line"
|
|
||||||
local device
|
|
||||||
IFS= read -r device || break
|
|
||||||
device=$(tr -d '\t' <<<"$device" | head -1)
|
|
||||||
[[ -n $device ]] && echo "$device $name"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
mapfile -t devices < <(webcam_list)
|
|
||||||
if (( ${#devices[@]} == 0 )); then
|
if (( ${#devices[@]} == 0 )); then
|
||||||
omarchy-notification-send "No webcam devices found" -u critical -t 3000
|
omarchy-notification-send "No webcam devices found" -u critical -t 3000
|
||||||
exit 1
|
exit 1
|
||||||
|
|||||||
Executable
+33
@@ -0,0 +1,33 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# omarchy:summary=List webcam devices that support video capture
|
||||||
|
# omarchy:hidden=true
|
||||||
|
|
||||||
|
capture_capable() {
|
||||||
|
local device="$1"
|
||||||
|
|
||||||
|
v4l2-ctl --device "$device" --info 2>/dev/null | awk '
|
||||||
|
/^[[:space:]]*Device Caps[[:space:]]*:/ { inspect = 1; next }
|
||||||
|
inspect && /^[[:space:]]*Video Capture/ { found = 1 }
|
||||||
|
END { exit !found }
|
||||||
|
'
|
||||||
|
}
|
||||||
|
|
||||||
|
name=""
|
||||||
|
emitted=0
|
||||||
|
|
||||||
|
while IFS= read -r line; do
|
||||||
|
if [[ -n $line && $line != [[:space:]]* ]]; then
|
||||||
|
name="$line"
|
||||||
|
emitted=0
|
||||||
|
elif (( ! emitted )); then
|
||||||
|
device="${line#"${line%%[![:space:]]*}"}"
|
||||||
|
|
||||||
|
if [[ $device == /dev/video* ]] && capture_capable "$device"; then
|
||||||
|
emitted=1
|
||||||
|
printf '%s %s\n' "$device" "$name"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done < <(v4l2-ctl --list-devices 2>/dev/null)
|
||||||
|
|
||||||
|
exit 0
|
||||||
@@ -2,4 +2,4 @@
|
|||||||
|
|
||||||
# omarchy:summary=Check whether a webcam is available
|
# omarchy:summary=Check whether a webcam is available
|
||||||
|
|
||||||
v4l2-ctl --list-devices 2>/dev/null | grep -q '^[[:space:]]*/dev/video'
|
[[ -n $(omarchy-capture-webcam-list) ]]
|
||||||
|
|||||||
@@ -15,12 +15,44 @@ cat >"$stub_bin/v4l2-ctl" <<'SH'
|
|||||||
|
|
||||||
[[ ${OMARCHY_TEST_NO_WEBCAM:-false} == "true" ]] && exit 0
|
[[ ${OMARCHY_TEST_NO_WEBCAM:-false} == "true" ]] && exit 0
|
||||||
|
|
||||||
printf '%s\n' "Built-in Webcam: Integrated Camera"
|
case "$1" in
|
||||||
printf '\t%s\n' "/dev/video0"
|
--list-devices)
|
||||||
printf '\t%s\n' "/dev/video1"
|
printf '%s\n' "ipu6 (PCI:0000:00:05.0):"
|
||||||
printf '\n'
|
printf '\t%s\n' "/dev/video0"
|
||||||
printf '%s\n' "USB Capture Card: External Camera"
|
printf '\t%s\n' "/dev/video1"
|
||||||
printf '\t%s\n' "/dev/video2"
|
|
||||||
|
if [[ ${OMARCHY_TEST_RAW_WEBCAM:-false} != "true" ]]; then
|
||||||
|
printf '\n%s\n' "Built-in Webcam: Integrated Camera"
|
||||||
|
printf '\t%s\n' "/dev/video42"
|
||||||
|
printf '\t%s\n' "/dev/video43"
|
||||||
|
printf '\n%s\n' "USB Capture Card: External Camera"
|
||||||
|
printf '\t%s\n' "/dev/video2"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ${OMARCHY_TEST_DUAL_NODE_WEBCAM:-false} == "true" ]]; then
|
||||||
|
printf '\n%s\n' "Dual Node Camera: ISP Wrapper"
|
||||||
|
printf '\t%s\n' "/dev/video7"
|
||||||
|
printf '\t%s\n' "/dev/video8"
|
||||||
|
printf '\n%s\n' "Metadata Only: Sensor"
|
||||||
|
printf '\t%s\n' "/dev/video9"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
--device)
|
||||||
|
case "$2" in
|
||||||
|
/dev/video0) device_capability="Video Output" ;;
|
||||||
|
/dev/video1) device_capability="Metadata Capture" ;;
|
||||||
|
/dev/video7 | /dev/video9) device_capability="Video Output" ;;
|
||||||
|
*) device_capability="Video Capture" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
printf '%s\n' \
|
||||||
|
"Driver Info:" \
|
||||||
|
$'\tCapabilities : 0x84a00001' \
|
||||||
|
$'\t\tVideo Capture' \
|
||||||
|
$'\tDevice Caps : 0x04200001' \
|
||||||
|
$'\t\t'"$device_capability"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
SH
|
SH
|
||||||
|
|
||||||
cat >"$stub_bin/omarchy-menu-select" <<'SH'
|
cat >"$stub_bin/omarchy-menu-select" <<'SH'
|
||||||
@@ -51,10 +83,39 @@ export OMARCHY_TEST_MENU_ARGS="$tmp_dir/menu-args"
|
|||||||
export OMARCHY_TEST_RECORDER_ARGS="$tmp_dir/recorder-args"
|
export OMARCHY_TEST_RECORDER_ARGS="$tmp_dir/recorder-args"
|
||||||
export OMARCHY_TEST_NOTIFICATION_ARGS="$tmp_dir/notification-args"
|
export OMARCHY_TEST_NOTIFICATION_ARGS="$tmp_dir/notification-args"
|
||||||
|
|
||||||
|
mapfile -t capture_devices < <(omarchy-capture-webcam-list)
|
||||||
|
expected_capture_devices=(
|
||||||
|
"/dev/video42 Built-in Webcam: Integrated Camera"
|
||||||
|
"/dev/video2 USB Capture Card: External Camera"
|
||||||
|
)
|
||||||
|
|
||||||
|
if [[ ${capture_devices[*]} != "${expected_capture_devices[*]}" ]]; then
|
||||||
|
fail "webcam detection filters output-only devices and collapses each capture group" \
|
||||||
|
"expected: ${expected_capture_devices[*]}\nactual: ${capture_devices[*]}"
|
||||||
|
fi
|
||||||
|
pass "webcam detection filters output-only devices and collapses each capture group"
|
||||||
|
|
||||||
|
dual_node=$(OMARCHY_TEST_DUAL_NODE_WEBCAM=true omarchy-capture-webcam-list) ||
|
||||||
|
fail "webcam listing exits zero when the trailing device is filtered"
|
||||||
|
pass "webcam listing exits zero when the trailing device is filtered"
|
||||||
|
|
||||||
|
expected_dual_node="/dev/video42 Built-in Webcam: Integrated Camera
|
||||||
|
/dev/video2 USB Capture Card: External Camera
|
||||||
|
/dev/video8 Dual Node Camera: ISP Wrapper"
|
||||||
|
[[ $dual_node == "$expected_dual_node" ]] ||
|
||||||
|
fail "webcam detection falls through to a later capture-capable node in a group" "$dual_node"
|
||||||
|
pass "webcam detection falls through to a later capture-capable node in a group"
|
||||||
|
|
||||||
if "$ROOT/bin/omarchy-hw-webcam"; then
|
if "$ROOT/bin/omarchy-hw-webcam"; then
|
||||||
pass "webcam hardware detection succeeds when a video device is available"
|
pass "webcam hardware detection succeeds when a capture device is available"
|
||||||
else
|
else
|
||||||
fail "webcam hardware detection succeeds when a video device is available"
|
fail "webcam hardware detection succeeds when a capture device is available"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if OMARCHY_TEST_RAW_WEBCAM=true "$ROOT/bin/omarchy-hw-webcam"; then
|
||||||
|
fail "webcam hardware detection rejects output-only video devices"
|
||||||
|
else
|
||||||
|
pass "webcam hardware detection rejects output-only video devices"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if OMARCHY_TEST_NO_WEBCAM=true "$ROOT/bin/omarchy-hw-webcam"; then
|
if OMARCHY_TEST_NO_WEBCAM=true "$ROOT/bin/omarchy-hw-webcam"; then
|
||||||
@@ -63,12 +124,19 @@ else
|
|||||||
pass "webcam hardware detection fails when no video device is available"
|
pass "webcam hardware detection fails when no video device is available"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if OMARCHY_TEST_RAW_WEBCAM=true "$ROOT/bin/omarchy-capture-screenrecording-with-webcam"; then
|
||||||
|
fail "screenrecording webcam picker rejects output-only video devices"
|
||||||
|
fi
|
||||||
|
grep -Fx 'No webcam devices found' "$OMARCHY_TEST_NOTIFICATION_ARGS" >/dev/null || \
|
||||||
|
fail "screenrecording webcam picker reports no capture-capable device"
|
||||||
|
pass "screenrecording webcam picker rejects output-only video devices"
|
||||||
|
|
||||||
"$ROOT/bin/omarchy-capture-screenrecording-with-webcam"
|
"$ROOT/bin/omarchy-capture-screenrecording-with-webcam"
|
||||||
|
|
||||||
expected_menu_args="$tmp_dir/expected-menu-args"
|
expected_menu_args="$tmp_dir/expected-menu-args"
|
||||||
printf '%s\n' \
|
printf '%s\n' \
|
||||||
"Select Webcam" \
|
"Select Webcam" \
|
||||||
"/dev/video0 Built-in Webcam: Integrated Camera" \
|
"/dev/video42 Built-in Webcam: Integrated Camera" \
|
||||||
"/dev/video2 USB Capture Card: External Camera" \
|
"/dev/video2 USB Capture Card: External Camera" \
|
||||||
"--" \
|
"--" \
|
||||||
"--width" \
|
"--width" \
|
||||||
@@ -93,6 +161,12 @@ if ! cmp -s "$OMARCHY_TEST_RECORDER_ARGS" "$expected_recorder_args"; then
|
|||||||
fi
|
fi
|
||||||
pass "screenrecording webcam picker starts recording with selected device"
|
pass "screenrecording webcam picker starts recording with selected device"
|
||||||
|
|
||||||
|
first_webcam=$(omarchy-capture-webcam-list | sed -n '1s/[[:space:]].*//p')
|
||||||
|
[[ $first_webcam == "/dev/video42" ]] || fail "screenrecording auto-detection selects the first capture device"
|
||||||
|
grep -F 'WEBCAM_DEVICE=$(omarchy-capture-webcam-list' "$ROOT/bin/omarchy-capture-screenrecording" >/dev/null || \
|
||||||
|
fail "screenrecording auto-detection uses capture-capable webcams"
|
||||||
|
pass "screenrecording auto-detection uses the first capture-capable webcam"
|
||||||
|
|
||||||
cat >"$stub_bin/hyprctl" <<'SH'
|
cat >"$stub_bin/hyprctl" <<'SH'
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user