#!/bin/sh # $FreeBSD: head/multimedia/webcamd/files/webcamd.in 353901 2014-05-12 22:01:10Z nox $ # # PROVIDE: webcamd # REQUIRE: DAEMON LOGIN # KEYWORD: shutdown # # ================================================================ # Webcamd is enabled by adding the following line to /etc/rc.conf: # ================================================================ # # webcamd_enable="YES" # # ================================================================ # By default webcamd instances are invoked by the devd(8) system # daemon. You do not normally need to do any extra configuraion. # ================================================================ # # ================================================================ # Webcamd flags can be set in general using this variable: # ================================================================ # # webcamd_flags="-m v4l2-dev.hflip=1" # # ================================================================ # If devd is not working (devd_enable="NO"), then you must tell # webcamd which devices you have explicitly with "_device_N_name" # as printed out when running the command "usbconfig". # # Index "N" is a sequentially increasing number starting from "0". # e.g. 0,1,2,3 etc... You must not skip any index numbers. # ================================================================ # # webcamd_device_0_name="Acer Crystal Eye webcam SuYin" # # ================================================================ # If you have multiple identical devices, then they can also be # distinguished by serial number, as found with these commands: # $ usbconfig && usbconfig dump_string 0x03 # This setting is only needed when "device_0_name"="device_1_name" # AND you need to set *different* flags for each inividual device. # ================================================================ # # webcamd_device_0_serial="CN0314-SN30-OV03-VA-R02.03.02" # # ================================================================ # You may set individual flags on a per USB device basis with # "_device_N_flags", along with a matching "_device_N_name" and # "_device_N_serial" as above. This works for devd invokations too. # ================================================================ # # webcamd_device_0_flags="-L 127.0.0.1:5100:-1" # # ================================================================ # Or can specify manually, each seperate custom webcamd instances # with this index being seperate from the auto-name finding. # This is useful when you cannot specify by name and serial number # and wish to specify by hard-coded USB device number instead. # Or when you need to start a vtuner client instance ("-D" option). # ================================================================ # # webcamd_custom_flags_0="-D 127.0.0.1:5100:-1" # webcamd_custom_flags_1="-d ugen2.2 127.0.0.1:5100:-1" # # ================================================================ # Additional Webcamd flags: # ================================================================ # # webcamd_startup_delay= # webcamd_user= # webcamd_group= # . /etc/rc.subr name=webcamd rcvar=webcamd_enable load_rc_config $name : ${webcamd_enable:=NO} : ${hald_enable:=NO} : ${webcamd_user=webcamd} : ${webcamd_group=webcamd} : ${webcamd_startup_delay=1} : ${webcamd_devd_starts_custom=YES} # If invoked automatically by devd, we receive additional arguments devd_device=${2} devd_interface=${3-0} command=/usr/local/sbin/webcamd command_args="-B -U ${webcamd_user} -G ${webcamd_group}" start_cmd="${name}_start" stop_cmd="${name}_stop" status_cmd="${name}_status" webcamd_pids() { pids=$(pgrep -d ' ' $name) pids=${pids% } printf "${pids}" } webcamd_set_vars() { # Whether or not we will start all custom instances, or just the vtuner client ones ("-D") if checkyesno devd_enable && checkyesno webcamd_devd_starts_custom ; then devd_starts_custom="true" else unset devd_starts_custom fi # Whether or not we will use the 'hald' service if checkyesno hald_enable ; then command_args="$command_args -H" fi # Whether or not we start all of our USB devices from this script, and can report certain errors if checkyesno devd_enable && [ ! "$rc_force" ]; then unset not_devd else not_devd="true" fi } webcamd_start() { # Set configuration variables that we need for later on webcamd_set_vars; # If this rc.d script was invoked by devd if [ "$devd_device" ]; then # Then start the device ugenX.X, as provied in the argv $2, $3 webcamd_start_devd; else # Count the number of webcamd instances we will start webcamd_count_instances; if [ "$num_instances_remaining" -gt 0 ]; then echo "Starting ${name}." # If custom instance config lines were found if [ "$webcamd_custom_flags_0" ]; then if [ "$devd_starts_custom" ]; then # Start only the vtuner client custom instances (the others are started by devd) webcamd_start_by_vtuner_client_flags; else # Start each specified custom instances webcamd_start_by_custom_flags; fi fi if [ "$num_found_by_name_serial" -gt "0" ]; then # If we found any devices matching a specified USB name, USB serial number, we must start them webcamd_start_by_usb_name_serial; fi # Check that webcamd started up (didn't quit unexpectedly or error out) webcamd_check_started; # Skip this error message if we are starting our devices from devd elif [ "$not_devd" ]; then # Display an appropriate error message to explain why webcamd could not be started if [ "$device_names" ]; then warn "failed to start ${name}." echo "No connected devices found of type: ${device_names#, }." return 1 else warn "failed to start ${name}." echo "webcamd settings need to be configured in /etc/rc.conf." echo "See /usr/local/etc/rc.d/${name} for more info." return 1 fi fi fi } webcamd_find_devd_flags_by_custom_flags() { # Find matching flags in any custom instances n=0 while [ "$n" -lt "100" ] do custom_flags=$(eval "echo \$webcamd_custom_flags_${n}") if [ "$custom_flags" ]; then # GREP the devd USB device number against this line of custom instance flags d_flag_match=$(echo "$custom_flags" | grep -o "\-d *[[:alpha:]]*${devd_device#ugen}") if [ "$d_flag_match" ]; then if [ "$devd_starts_custom" ]; then # Remember / store these custom flags devd_custom_flags=$(echo "$custom_flags" | sed -e "s/$d_flag_match *//") else # This particular devd invokation will be ignored, and we exit this script immediately. # Because custom_flags_N are instead started during the normal webcamd rc.d startup. exit 0 fi break fi n=$(expr $n + 1) else break fi done } webcamd_find_devd_flags_by_usb_name_serial() { # Lookup the names and serial numbers of USB devices usbconfig_names=$(usbconfig) usbconfig_serials=$(usbconfig dump_string 0x03) usbconfig_line=$(echo "$usbconfig_names" | grep -n "^ugen${devd_device#ugen}") usbconfig_line_num="$(echo "$usbconfig_line" | cut -d ':' -f 1)" # Determine the USB device name and serial number devd_usb_name=$(echo "$usbconfig_line" | sed -e 's/.*: at .*//') devd_usb_serial=$(echo "$usbconfig_serials" | sed -n "${usbconfig_line_num}p" | sed -e 's/.* = .*//') # Find any flags matching the USB name / USB serial number n=0 while [ "$n" -lt "100" ] do device_name=$(eval "echo \$webcamd_device_${n}_name") if [ "$device_name" ]; then if [ "$device_name" = "$devd_usb_name" ]; then # If serial numbers are also specified in config name_serial=$(eval "echo \$webcamd_device_${n}_serial") if [ "$name_serial" ]; then # if matches a USB name AND by USB serial number if [ "$name_serial" = "$devd_usb_serial" ]; then # remember / store these custom flags devd_name_serial_flags=$(eval "echo \$webcamd_device_${n}_flags") break fi else # We have match by USB name only, no serial devd_name_serial_flags=$(eval "echo \$webcamd_device_${n}_flags") break fi fi n=$(expr $n + 1) else break fi done } webcamd_start_devd() { # Start a single USB device, as this rc.d script was invoked by devd with extra arguments # First check for any custom flags that if [ "$webcamd_custom_flags_0" ]; then # that were specified as custom instance flags webcamd_find_devd_flags_by_custom_flags; fi if [ "$webcamd_device_0_name" ]; then # that were specified by the USB device name, USB serial number webcamd_find_devd_flags_by_usb_name_serial; fi # Start the connected USB device, with any matching custom flags that were found echo "Starting ${name} -d ${devd_device} -i ${devd_interface} ${devd_custom_flags} ${devd_name_serial_flags} ${webcamd_flags} ${command_args}" | tr -s ' ' ${command} -d ${devd_device} -i ${devd_interface} ${devd_custom_flags} ${devd_name_serial_flags} ${webcamd_flags} ${command_args} } webcamd_count_instances() { # This variable keeps track of how many instances we will start num_instances_remaining=0 num_found_by_name_serial=0 if [ "$devd_starts_custom" ]; then # Count the number of vtuner client custom instances we will start webcamd_count_custom_instances_vtuner_client; else # Count the number of custom instances we will start webcamd_count_custom_instances_all; fi # Skip this part if we are starting our devices from devd if [ "$not_devd" ]; then # Error out if webcamd is already running pids=$(webcamd_pids) if [ "$pids" ]; then echo "${name} already running? (pid=${pids})." exit 1 fi if [ "$webcamd_device_0_name" ]; then # Find and count the number of devices that match specified USB names and USB serial numbers webcamd_find_count_by_usb_name_serial; fi fi } webcamd_find_count_by_usb_name_serial() { # Gather data about all connected USB devices from usbconfig usbconfig_devices=$(usbconfig) usbconfig_serials=$(usbconfig dump_string 0x03) # Find connected devices by USB name / USB serial number n=0 while [ "$n" -lt "100" ] do device_name=$(eval "echo \$webcamd_device_${n}_name") if [ "$device_name" ]; then # If the config line also has a USB serial number specified device_serial=$(eval "echo \$webcamd_device_${n}_serial") if [ "$device_serial" ]; then # find the first connected device that matches USB name AND USB serial number usbconfig_line_num="$(echo "$usbconfig_serials" | grep --max-count=1 -n "$device_serial" | cut -d ':' -f 1)" if [ "$usbconfig_line_num" ]; then found_usb_devices=$(echo "$usbconfig_devices" | sed -n "${usbconfig_line_num}p" | cut -d ':' -f 1) fi # Remember text string for possible error message later on device_names="$device_names, $device_name (with serial: $device_serial)" else # match by USB name only found_usb_devices=$(echo "$usbconfig_devices" | grep "$device_name" | cut -d ':' -f 1) # Remember text string for possible error message later on device_names="$device_names, $device_name" fi # Store for later eval "webcamd_device_${n}_devices=$found_usb_devices" num_found_this_loop=$(echo "$found_usb_devices" | wc -w | grep -o -E "[0-9]+") num_found_by_name_serial=$(expr $num_found_by_name_serial + $num_found_this_loop) n=$(expr $n + 1) else break fi done num_instances_remaining=$(expr $num_instances_remaining + $num_found_by_name_serial) } webcamd_start_by_usb_name_serial() { # Start any devices that were found by USB name / USB serial number n=0 while [ "$n" -lt "100" ] do device_name=$(eval "echo \$webcamd_device_${n}_name") if [ "$device_name" ]; then # Any connected USB devices that match the specified USB name, USB serial number ? devices=$(eval "echo \$webcamd_device_${n}_devices") if [ "$devices" ]; then for device in $devices do device_flags=$(eval "echo \$webcamd_device_${n}_flags") # Launch an instance of webcamd for this device ${command} -d ${device} ${device_flags} ${webcamd_flags} ${command_args} num_instances_remaining=$(expr $num_instances_remaining - 1) # Wait n seconds until launching the next instance for the next device if [ "$num_instances_remaining" -gt 0 ]; then sleep $webcamd_startup_delay fi done fi n=$(expr $n + 1) else break fi done } webcamd_count_custom_instances_vtuner_client() { # count the number of vtuner client instances to be launched n=0 # outer loop - all custom instances i=0 # inner loop - vclient instances ('-D') while [ "$n" -lt "100" ] do custom_flags=$(eval "echo \$webcamd_custom_flags_${n}") if [ "$custom_flags" ]; then # If this custom_flags line is for a virtual device ('-D') if [ "$(echo "$custom_flags" | grep "\-D *")" ]; then # Copy to the array webcamd_vtuner_client_${n}_flags eval "webcamd_vtuner_client_${i}_flags=\$custom_flags" i=$(expr $i + 1) fi n=$(expr $n + 1) else break fi done num_instances_remaining=$(expr $num_instances_remaining + $i) } webcamd_start_by_vtuner_client_flags() { # Start any vtuner client instances n=0 while [ "$n" -lt "100" ] do vtuner_client_flags=$(eval "echo \$webcamd_vtuner_client_${n}_flags") if [ "$vtuner_client_flags" ]; then # Launch an instance of webcamd with these specific vtuner client ('-D') flags ${command} ${vtuner_client_flags} ${webcamd_flags} ${command_args} # increment the counters num_instances_remaining=$(expr $num_instances_remaining - 1) n=$(expr $n + 1) # Wait n seconds until launching the next instance for the next device if [ "$num_instances_remaining" -gt 0 ]; then sleep $webcamd_startup_delay fi else break fi done } webcamd_count_custom_instances_all() { # count the number of instances to be launched n=0 while [ "$n" -lt "100" ] do if [ "$(eval "echo \$webcamd_custom_flags_${n}")" ]; then n=$(expr $n + 1) else break fi done num_instances_remaining=$(expr $num_instances_remaining + $n) } webcamd_start_by_custom_flags() { # Start any custom instances n=0 while [ "$n" -lt "100" ] do custom_flags=$(eval "echo \$webcamd_custom_flags_${n}") if [ "$custom_flags" ]; then # Launch a custom instance of webcamd with these specific custom flags ${command} ${custom_flags} ${webcamd_flags} ${command_args} # increment the counters num_instances_remaining=$(expr $num_instances_remaining - 1) n=$(expr $n + 1) # Wait n seconds until launching the next instance for the next device if [ "$num_instances_remaining" -gt 0 ]; then sleep $webcamd_startup_delay fi else break fi done } webcamd_check_started() { # Check that at least 1+ webcamd processes are persistent if [ "$webcamd_startup_delay" -gt 0 ]; then # but not if doing "fast-start". When webcamd_startup_delay = 0 seconds sleep 1 pids=$(webcamd_pids) if [ "${pids}" ]; then echo "${name} is running as pid ${pids}." else if [ "$webcamd_devices" ]; then warn "webcamd not started." warn "Invalid configuration or USB devices not recognized: ${webcamd_devices% }." else warn "webcamd not started. Invalid configuration?" fi return 1 fi fi } webcamd_stop() { pids=$(webcamd_pids) if [ "${pids}" ]; then echo "Stopping ${name}." echo "Waiting for PIDs: ${pids}" for signal in TERM INT QUIT KILL HUP do kill -s ${signal} ${pids} sleep 1; pids=$(webcamd_pids) [ "${pids}" ] || break; done else echo "${name} is not running." return 1 fi } webcamd_status() { pids=$(webcamd_pids) if [ "${pids}" ]; then echo "${name} is running as pid ${pids}." else echo "${name} is not running." return 1 fi } run_rc_command "$1"