188 lines
4.4 KiB
Bash
Executable File
188 lines
4.4 KiB
Bash
Executable File
#!/bin/sh
|
|
# Bananarchy rear camera photo capture utility and Sxmo menu wrapper
|
|
# Captures 800x600 24-bit RGB frames from /dev/video0 (msm8905-cam / GC2395)
|
|
# via v4l2-ctl and encodes JPEG/PNG images via ffmpeg -f rawvideo.
|
|
|
|
set -eu
|
|
|
|
DEV="/dev/video0"
|
|
USE_FLASH=0
|
|
VIEW_AFTER=0
|
|
MENU_MODE=0
|
|
OUT_FILE=""
|
|
|
|
usage() {
|
|
cat <<'EOF'
|
|
Usage: bananarchy-photo [options] [output_file]
|
|
|
|
Options:
|
|
-d, --device <dev> V4L2 video device (default: /dev/video0)
|
|
-f, --flash Enable rear flashlight (white:torch) during capture
|
|
-v, --view Open captured photo in imv after saving
|
|
-m, --menu Open interactive Sxmo camera menu
|
|
-h, --help Show this help message
|
|
|
|
If output_file is omitted, saves to ~/Pictures/photo-YYYYMMDD-HHMMSS.jpg.
|
|
EOF
|
|
}
|
|
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
-d|--device)
|
|
DEV="$2"
|
|
shift 2
|
|
;;
|
|
-f|--flash)
|
|
USE_FLASH=1
|
|
shift
|
|
;;
|
|
-v|--view)
|
|
VIEW_AFTER=1
|
|
shift
|
|
;;
|
|
-m|--menu)
|
|
MENU_MODE=1
|
|
shift
|
|
;;
|
|
-h|--help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
--)
|
|
shift
|
|
break
|
|
;;
|
|
-*)
|
|
echo "bananarchy-photo: unknown option: $1" >&2
|
|
usage >&2
|
|
exit 1
|
|
;;
|
|
*)
|
|
OUT_FILE="$1"
|
|
shift
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [ $# -gt 0 ] && [ -z "$OUT_FILE" ]; then
|
|
OUT_FILE="$1"
|
|
fi
|
|
|
|
get_pictures_dir() {
|
|
pic_dir="${XDG_PICTURES_DIR:-$HOME/Pictures}"
|
|
mkdir -p "$pic_dir"
|
|
printf "%s\n" "$pic_dir"
|
|
}
|
|
|
|
notify_msg() {
|
|
if command -v sxmo_notify_user.sh >/dev/null 2>&1 && [ -n "${WAYLAND_DISPLAY:-}" ]; then
|
|
sxmo_notify_user.sh -t 2000 "$1" >/dev/null 2>&1 || true
|
|
fi
|
|
}
|
|
|
|
take_photo() {
|
|
flash_flag="$1"
|
|
target_path="$2"
|
|
|
|
if [ -z "$target_path" ]; then
|
|
pic_dir="$(get_pictures_dir)"
|
|
target_path="$pic_dir/photo-$(date +%Y%m%d-%H%M%S).jpg"
|
|
else
|
|
mkdir -p "$(dirname "$target_path")"
|
|
fi
|
|
|
|
if [ ! -e "$DEV" ]; then
|
|
echo "bananarchy-photo: camera device $DEV not found" >&2
|
|
notify_msg "Camera $DEV not found"
|
|
return 1
|
|
fi
|
|
|
|
prev_torch=""
|
|
if [ "$flash_flag" -eq 1 ] && [ -w /sys/class/leds/white:torch/brightness ]; then
|
|
prev_torch="$(cat /sys/class/leds/white:torch/brightness 2>/dev/null || echo 0)"
|
|
echo 1 > /sys/class/leds/white:torch/brightness 2>/dev/null || true
|
|
sleep 0.15
|
|
fi
|
|
|
|
frame_tmp="/tmp/bananarchy-frame-$$.rgb"
|
|
rc=0
|
|
|
|
v4l2-ctl -d "$DEV" \
|
|
--set-fmt-video=width=800,height=600,pixelformat=RGB3 \
|
|
--stream-mmap --stream-count=1 --stream-to="$frame_tmp" >/dev/null 2>&1 || rc=$?
|
|
|
|
if [ "$flash_flag" -eq 1 ] && [ -n "$prev_torch" ] && [ -w /sys/class/leds/white:torch/brightness ]; then
|
|
echo "$prev_torch" > /sys/class/leds/white:torch/brightness 2>/dev/null || true
|
|
fi
|
|
|
|
if [ "$rc" -ne 0 ] || [ ! -s "$frame_tmp" ]; then
|
|
rm -f "$frame_tmp"
|
|
echo "bananarchy-photo: failed to capture frame from $DEV" >&2
|
|
notify_msg "Photo capture failed"
|
|
return 1
|
|
fi
|
|
|
|
if ! ffmpeg -hide_banner -loglevel error \
|
|
-f rawvideo -pixel_format rgb24 -video_size 800x600 \
|
|
-i "$frame_tmp" -frames:v 1 -y "$target_path"; then
|
|
rm -f "$frame_tmp"
|
|
echo "bananarchy-photo: ffmpeg failed to encode $target_path" >&2
|
|
notify_msg "Photo encoding failed"
|
|
return 1
|
|
fi
|
|
|
|
rm -f "$frame_tmp"
|
|
printf "%s\n" "$target_path"
|
|
notify_msg "Saved $(basename "$target_path")"
|
|
|
|
if [ "$VIEW_AFTER" -eq 1 ] && [ -n "${WAYLAND_DISPLAY:-}" ] && command -v imv >/dev/null 2>&1; then
|
|
imv "$target_path" >/dev/null 2>&1 &
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
run_menu() {
|
|
if [ -f /usr/share/sxmo/default_hooks/sxmo_hook_icons.sh ]; then
|
|
# shellcheck disable=SC1091
|
|
. /usr/share/sxmo/default_hooks/sxmo_hook_icons.sh
|
|
fi
|
|
ic_cam="${icon_cam:-*}"
|
|
ic_fll="${icon_fll:-*}"
|
|
ic_img="${icon_img:-*}"
|
|
ic_cls="${icon_cls:-x}"
|
|
|
|
choice="$(printf "%s\n" \
|
|
"$ic_cam Take photo" \
|
|
"$ic_fll Take photo (flash)" \
|
|
"$ic_img View photos" \
|
|
"$ic_cls Close" | sxmo_dmenu.sh -p "Camera" || true)"
|
|
|
|
case "$choice" in
|
|
*"Take photo (flash)"*)
|
|
VIEW_AFTER=1
|
|
take_photo 1 ""
|
|
;;
|
|
*"Take photo"*)
|
|
VIEW_AFTER=1
|
|
take_photo 0 ""
|
|
;;
|
|
*"View photos"*)
|
|
pic_dir="$(get_pictures_dir)"
|
|
if ls "$pic_dir"/*.jpg "$pic_dir"/*.png >/dev/null 2>&1; then
|
|
imv "$pic_dir" >/dev/null 2>&1 &
|
|
else
|
|
notify_msg "No photos in $pic_dir"
|
|
fi
|
|
;;
|
|
*)
|
|
exit 0
|
|
;;
|
|
esac
|
|
}
|
|
|
|
if [ "$MENU_MODE" -eq 1 ]; then
|
|
run_menu
|
|
else
|
|
take_photo "$USE_FLASH" "$OUT_FILE"
|
|
fi
|