Files
motion/src/conf.cpp
2021-03-21 16:23:51 -06:00

1294 lines
44 KiB
C++

/*
**
** conf.cpp
** Copyright 1999 Jeroen Vreeken (pe1rxq@chello.nl)
**
** This software is licensed under the terms of the GNU General
** Public License (GPL). Please see the file COPYING for details.
**
**
*/
#include <dirent.h>
#include <string.h>
#include "motion.hpp"
#include "util.hpp"
#include "logger.hpp"
#include "conf_edit.hpp"
/* Forward Declares */
void conf_process(struct ctx_motapp *motapp, FILE *fp, int threadnbr);
/*Configuration parameters */
struct ctx_parm config_parms[] = {
{
"daemon",
"############################################################\n"
"# System control configuration parameters\n"
"############################################################\n\n"
"# Start in daemon (background) mode and release terminal.",
1 ,PARM_TYP_BOOL,PARM_CAT_00,WEBUI_LEVEL_ADVANCED},
{
"setup_mode",
"# Start in Setup-Mode, daemon disabled.",
0 ,PARM_TYP_BOOL ,PARM_CAT_00,WEBUI_LEVEL_ADVANCED},
{
"conf_filename",
"# Configuration file name.",
1 ,PARM_TYP_STRING ,PARM_CAT_00,WEBUI_LEVEL_ADVANCED},
{
"pid_file",
"# File to store the process ID.",
1 ,PARM_TYP_STRING ,PARM_CAT_00,WEBUI_LEVEL_ADVANCED},
{
"log_file",
"# File to write logs messages into. If not defined stderr and syslog is used.",
1, PARM_TYP_STRING, PARM_CAT_00 , WEBUI_LEVEL_ADVANCED},
{
"log_level",
"# Level of log messages [1..9] (EMG, ALR, CRT, ERR, WRN, NTC, INF, DBG, ALL).",
1, PARM_TYP_INT, PARM_CAT_00, WEBUI_LEVEL_LIMITED},
{
"log_type",
"# Filter to log messages by type (COR, STR, ENC, NET, DBL, EVT, TRK, VID, ALL).",
1, PARM_TYP_STRING, PARM_CAT_00, WEBUI_LEVEL_LIMITED},
{
"quiet",
"# Do not sound beeps when detecting motion",
0, PARM_TYP_BOOL, PARM_CAT_01, WEBUI_LEVEL_LIMITED},
{
"native_language",
"# Native language support.",
1, PARM_TYP_STRING, PARM_CAT_00, WEBUI_LEVEL_LIMITED},
{
"camera_name",
"# User defined name for the camera.",
0, PARM_TYP_STRING,PARM_CAT_01, WEBUI_LEVEL_ADVANCED },
{
"camera_id",
"# Numeric identifier for the camera.",
0, PARM_TYP_INT,PARM_CAT_01,WEBUI_LEVEL_ADVANCED},
/* camera and camera_dir must be last in this list */
{
"target_dir",
"# Target directory for pictures, snapshots and movies",
0,PARM_TYP_STRING,PARM_CAT_01, WEBUI_LEVEL_LIMITED },
{
"videodevice",
"# Video device (e.g. /dev/video0) to be used for capturing.",
0,PARM_TYP_STRING,PARM_CAT_01,WEBUI_LEVEL_ADVANCED
},
{
"vid_control_params",
"# Parameters to control video device. See motion_guide.html",
0,PARM_TYP_STRING,PARM_CAT_01,WEBUI_LEVEL_LIMITED},
{
"v4l2_palette",
"# Preferred color palette to be used for the video device",
0, PARM_TYP_INT, PARM_CAT_01, WEBUI_LEVEL_ADVANCED},
{
"input",
"# The input number to be used on the video device.",
0, PARM_TYP_INT, PARM_CAT_01, WEBUI_LEVEL_ADVANCED },
{
"norm",
"# The video norm to use for video capture and TV tuner cards.",
0,PARM_TYP_INT, PARM_CAT_01, WEBUI_LEVEL_ADVANCED },
{
"frequency",
"# The frequency to set the tuner to (kHz) for TV tuner cards",
0,PARM_TYP_INT, PARM_CAT_01,WEBUI_LEVEL_ADVANCED },
{
"roundrobin_frames",
"# Number of frames to capture in each roundrobin step",
0,PARM_TYP_INT, PARM_CAT_01, WEBUI_LEVEL_LIMITED },
{
"roundrobin_skip",
"# Number of frames to skip before each roundrobin step",
0,PARM_TYP_INT, PARM_CAT_01, WEBUI_LEVEL_LIMITED },
{
"roundrobin_switchfilter",
"# Try to filter out noise generated by roundrobin",
0,PARM_TYP_BOOL, PARM_CAT_01, WEBUI_LEVEL_LIMITED},
{
"netcam_url",
"# The full URL of the network camera stream.",
0, PARM_TYP_STRING, PARM_CAT_01, WEBUI_LEVEL_ADVANCED},
{
"netcam_highres",
"# Optional high resolution URL for rtsp/rtmp cameras only.",
0, PARM_TYP_STRING, PARM_CAT_01, WEBUI_LEVEL_ADVANCED},
{
"netcam_userpass",
"# Username and password for network camera. Syntax username:password",
0, PARM_TYP_STRING, PARM_CAT_01, WEBUI_LEVEL_ADVANCED },
{
"netcam_use_tcp",
"# Use TCP transport for RTSP/RTMP connections to camera.",
1, PARM_TYP_STRING, PARM_CAT_01, WEBUI_LEVEL_ADVANCED },
{
"mmalcam_name",
"# Name of mmal camera (e.g. vc.ril.camera for pi camera).",
0, PARM_TYP_STRING, PARM_CAT_01, WEBUI_LEVEL_ADVANCED },
{
"mmalcam_control_params",
"# Camera control parameters (see raspivid/raspistill tool documentation)",
0, PARM_TYP_STRING, PARM_CAT_01, WEBUI_LEVEL_ADVANCED },
{
"width",
"############################################################\n"
"# Image Processing configuration parameters\n"
"############################################################\n\n"
"# Image width in pixels.",
0, PARM_TYP_INT, PARM_CAT_02, WEBUI_LEVEL_ADVANCED },
{
"height",
"# Image height in pixels.",
0, PARM_TYP_INT, PARM_CAT_02, WEBUI_LEVEL_ADVANCED},
{
"framerate",
"# Maximum number of frames to be captured per second.",
0, PARM_TYP_INT, PARM_CAT_02, WEBUI_LEVEL_LIMITED },
{
"rotate",
"# Number of degrees to rotate image.",
0, PARM_TYP_INT, PARM_CAT_02, WEBUI_LEVEL_LIMITED },
{
"flip_axis",
"# Flip image over a given axis",
0, PARM_TYP_STRING, PARM_CAT_02, WEBUI_LEVEL_LIMITED },
{
"locate_motion_mode",
"# Draw a locate box around the moving object.",
0, PARM_TYP_STRING, PARM_CAT_02, WEBUI_LEVEL_LIMITED },
{
"locate_motion_style",
"# Set the look and style of the locate box.",
0, PARM_TYP_STRING, PARM_CAT_02, WEBUI_LEVEL_LIMITED },
{
"text_left",
"# Text to be overlayed in the lower left corner of images",
0,PARM_TYP_STRING, PARM_CAT_02, WEBUI_LEVEL_LIMITED },
{
"text_right",
"# Text to be overlayed in the lower right corner of images.",
0,PARM_TYP_STRING, PARM_CAT_02, WEBUI_LEVEL_LIMITED },
{
"text_changes",
"# Overlay number of changed pixels in upper right corner of images.",
0,PARM_TYP_BOOL, PARM_CAT_02, WEBUI_LEVEL_LIMITED },
{
"text_scale",
"# Scale factor for text overlayed on images.",
0,PARM_TYP_INT, PARM_CAT_02, WEBUI_LEVEL_LIMITED },
{
"text_event",
"# The special event conversion specifier %C",
0,PARM_TYP_STRING, PARM_CAT_02, WEBUI_LEVEL_LIMITED },
{
"emulate_motion",
"############################################################\n"
"# Motion detection configuration parameters\n"
"############################################################\n\n"
"# Always save pictures and movies even if there was no motion.",
0,PARM_TYP_BOOL, PARM_CAT_02, WEBUI_LEVEL_LIMITED },
{
"threshold",
"# Threshold for number of changed pixels that triggers motion.",
0,PARM_TYP_INT, PARM_CAT_02, WEBUI_LEVEL_LIMITED },
{
"threshold_maximum",
"# The maximum threshold for number of changed pixels that triggers motion.",
0,PARM_TYP_INT, PARM_CAT_02, WEBUI_LEVEL_LIMITED },
{
"threshold_tune",
"# Enable tuning of the threshold down if possible.",
0,PARM_TYP_BOOL, PARM_CAT_02, WEBUI_LEVEL_LIMITED},
{
"noise_level",
"# Noise threshold for the motion detection.",
0,PARM_TYP_INT, PARM_CAT_02, WEBUI_LEVEL_LIMITED },
{
"noise_tune",
"# Automatically tune the noise threshold",
0,PARM_TYP_BOOL, PARM_CAT_02, WEBUI_LEVEL_LIMITED},
{
"despeckle_filter",
"# Despeckle the image using (E/e)rode or (D/d)ilate or (l)abel.",
0,PARM_TYP_STRING, PARM_CAT_02, WEBUI_LEVEL_LIMITED },
{
"area_detect",
"# Area number used to trigger the on_area_detected script.",
0,PARM_TYP_STRING, PARM_CAT_02, WEBUI_LEVEL_LIMITED },
{
"mask_file",
"# Full path and file name for motion detection mask PGM file.",
0,PARM_TYP_STRING, PARM_CAT_02, WEBUI_LEVEL_ADVANCED },
{
"mask_privacy",
"# Full path and file name for privacy mask PGM file.",
0,PARM_TYP_STRING, PARM_CAT_02, WEBUI_LEVEL_ADVANCED },
{
"smart_mask_speed",
"# The value defining how slow or fast the smart motion mask created and used.",
0, PARM_TYP_INT, PARM_CAT_02, WEBUI_LEVEL_LIMITED },
{
"lightswitch_percent",
"# Percentage of image that triggers a lightswitch detected.",
0, PARM_TYP_INT, PARM_CAT_02, WEBUI_LEVEL_LIMITED},
{
"lightswitch_frames",
"# When lightswitch is detected, ignore this many frames",
0, PARM_TYP_INT, PARM_CAT_02, WEBUI_LEVEL_LIMITED },
{
"minimum_motion_frames",
"# Number of images that must contain motion to trigger an event.",
0, PARM_TYP_INT, PARM_CAT_02, WEBUI_LEVEL_LIMITED
},
{
"event_gap",
"# Gap in seconds of no motion detected that triggers the end of an event.",
0, PARM_TYP_INT, PARM_CAT_02, WEBUI_LEVEL_LIMITED },
{
"pre_capture",
"# The number of pre-captured (buffered) pictures from before motion.",
0, PARM_TYP_INT, PARM_CAT_02, WEBUI_LEVEL_LIMITED },
{
"post_capture",
"# Number of frames to capture after motion is no longer detected.",
0, PARM_TYP_INT, PARM_CAT_02, WEBUI_LEVEL_LIMITED },
{
"on_event_start",
"############################################################\n"
"# Script execution configuration parameters\n"
"############################################################\n\n"
"# Command to be executed when an event starts.",
0, PARM_TYP_STRING, PARM_CAT_03, WEBUI_LEVEL_RESTRICTED },
{
"on_event_end",
"# Command to be executed when an event ends.",
0, PARM_TYP_STRING, PARM_CAT_03, WEBUI_LEVEL_RESTRICTED},
{
"on_picture_save",
"# Command to be executed when a picture is saved.",
0, PARM_TYP_STRING, PARM_CAT_03, WEBUI_LEVEL_RESTRICTED },
{
"on_area_detected",
"# Command to be executed when motion in a predefined area is detected",
0, PARM_TYP_STRING, PARM_CAT_03, WEBUI_LEVEL_RESTRICTED },
{
"on_motion_detected",
"# Command to be executed when motion is detected",
0, PARM_TYP_STRING, PARM_CAT_03, WEBUI_LEVEL_RESTRICTED },
{
"on_movie_start",
"# Command to be executed when a movie file is created.",
0, PARM_TYP_STRING, PARM_CAT_03, WEBUI_LEVEL_RESTRICTED},
{
"on_movie_end",
"# Command to be executed when a movie file is closed.",
0, PARM_TYP_STRING, PARM_CAT_03, WEBUI_LEVEL_RESTRICTED },
{
"on_camera_lost",
"# Command to be executed when a camera can't be opened or if it is lost",
0, PARM_TYP_STRING, PARM_CAT_03, WEBUI_LEVEL_RESTRICTED },
{
"on_camera_found",
"# Command to be executed when a camera that was lost has been found.",
0, PARM_TYP_STRING, PARM_CAT_03, WEBUI_LEVEL_RESTRICTED},
{
"picture_output",
"############################################################\n"
"# Picture output configuration parameters\n"
"############################################################\n\n"
"# Output pictures when motion is detected",
0, PARM_TYP_STRING, PARM_CAT_03, WEBUI_LEVEL_LIMITED },
{
"picture_output_motion",
"# Output pictures with only the pixels moving object (ghost images)",
0, PARM_TYP_BOOL, PARM_CAT_03, WEBUI_LEVEL_LIMITED },
{
"picture_type",
"# Format for the output pictures.",
0, PARM_TYP_STRING, PARM_CAT_03, WEBUI_LEVEL_LIMITED},
{
"picture_quality",
"# The quality (in percent) to be used in the picture compression",
0, PARM_TYP_INT, PARM_CAT_03, WEBUI_LEVEL_LIMITED },
{
"picture_exif",
"# Text to include in a JPEG EXIF comment",
0, PARM_TYP_STRING, PARM_CAT_03, WEBUI_LEVEL_LIMITED },
{
"picture_filename",
"# File name(without extension) for pictures relative to target directory",
0, PARM_TYP_STRING, PARM_CAT_03, WEBUI_LEVEL_LIMITED },
{
"snapshot_interval",
"############################################################\n"
"# Snapshot output configuration parameters\n"
"############################################################\n\n"
"# Make automated snapshot every N seconds",
0, PARM_TYP_INT, PARM_CAT_03, WEBUI_LEVEL_LIMITED },
{
"snapshot_filename",
"# File name(without extension) for snapshots relative to target directory",
0, PARM_TYP_STRING, PARM_CAT_03, WEBUI_LEVEL_LIMITED},
{
"movie_output",
"############################################################\n"
"# Movie output configuration parameters\n"
"############################################################\n\n"
"# Create movies of motion events.",
0, PARM_TYP_BOOL, PARM_CAT_03, WEBUI_LEVEL_LIMITED },
{
"movie_output_motion",
"# Create movies of moving pixels of motion events.",
0, PARM_TYP_BOOL, PARM_CAT_03, WEBUI_LEVEL_LIMITED },
{
"movie_max_time",
"# Maximum length of movie in seconds.",
0, PARM_TYP_INT, PARM_CAT_03, WEBUI_LEVEL_LIMITED },
{
"movie_bps",
"# The fixed bitrate to be used by the movie encoder. Ignore quality setting",
0, PARM_TYP_INT, PARM_CAT_03, WEBUI_LEVEL_LIMITED },
{
"movie_quality",
"# The encoding quality of the movie. (0=use bitrate. 1=worst quality, 100=best)",
0, PARM_TYP_INT, PARM_CAT_03, WEBUI_LEVEL_LIMITED },
{
"movie_codec",
"# Container/Codec to used for the movie. See motion_guide.html",
0, PARM_TYP_STRING, PARM_CAT_03, WEBUI_LEVEL_LIMITED },
{
"movie_passthrough",
"# Pass through from the camera to the movie without decode/encoding.",
0, PARM_TYP_BOOL, PARM_CAT_03, WEBUI_LEVEL_ADVANCED },
{
"movie_filename",
"# File name(without extension) for movies relative to target directory",
0, PARM_TYP_STRING, PARM_CAT_03, WEBUI_LEVEL_LIMITED },
{
"movie_extpipe_use",
"# Use pipe and external encoder for creating movies.",
0, PARM_TYP_BOOL, PARM_CAT_03, WEBUI_LEVEL_LIMITED },
{
"movie_extpipe",
"# Full path and options for external encoder of movies from raw images",
0, PARM_TYP_STRING, PARM_CAT_03, WEBUI_LEVEL_RESTRICTED },
{
"timelapse_interval",
"############################################################\n"
"# Timelapse output configuration parameters\n"
"############################################################\n\n"
"# Interval in seconds between timelapse captures.",
0, PARM_TYP_INT, PARM_CAT_03, WEBUI_LEVEL_LIMITED },
{
"timelapse_mode",
"# Timelapse file rollover mode. See motion_guide.html for options and uses.",
0, PARM_TYP_STRING, PARM_CAT_03, WEBUI_LEVEL_LIMITED},
{
"timelapse_fps",
"# Frame rate for timelapse playback",
0, PARM_TYP_INT, PARM_CAT_03, WEBUI_LEVEL_LIMITED },
{
"timelapse_codec",
"# Container/Codec for timelapse movie.",
0, PARM_TYP_STRING, PARM_CAT_03, WEBUI_LEVEL_LIMITED},
{
"timelapse_filename",
"# File name(without extension) for timelapse movies relative to target directory",
0, PARM_TYP_STRING, PARM_CAT_03, WEBUI_LEVEL_LIMITED},
{
"video_pipe",
"############################################################\n"
"# Loopback pipe configuration parameters\n"
"############################################################\n\n"
"# v4l2 loopback device to receive normal images",
0, PARM_TYP_STRING, PARM_CAT_03, WEBUI_LEVEL_LIMITED },
{
"video_pipe_motion",
"# v4l2 loopback device to receive motion images",
0, PARM_TYP_STRING, PARM_CAT_03, WEBUI_LEVEL_LIMITED},
{
"webcontrol_port",
"############################################################\n"
"# Webcontrol configuration parameters\n"
"############################################################\n\n"
"# Port number used for the webcontrol.",
1, PARM_TYP_STRING, PARM_CAT_04, WEBUI_LEVEL_ADVANCED},
{
"webcontrol_ipv6",
"# Enable IPv6 addresses.",
0, PARM_TYP_BOOL, PARM_CAT_04, WEBUI_LEVEL_ADVANCED},
{
"webcontrol_localhost",
"# Restrict webcontrol connections to the localhost.",
1, PARM_TYP_BOOL, PARM_CAT_04, WEBUI_LEVEL_ADVANCED },
{
"webcontrol_parms",
"# Type of configuration options to allow via the webcontrol.",
1, PARM_TYP_INT, PARM_CAT_04, WEBUI_LEVEL_NEVER},
{
"webcontrol_interface",
"# Method that webcontrol should use for interface with user.",
1, PARM_TYP_INT, PARM_CAT_04, WEBUI_LEVEL_LIMITED },
{
"webcontrol_auth_method",
"# The authentication method for the webcontrol",
0, PARM_TYP_INT, PARM_CAT_04, WEBUI_LEVEL_RESTRICTED},
{
"webcontrol_authentication",
"# Authentication string for the webcontrol. Syntax username:password",
1, PARM_TYP_STRING, PARM_CAT_04, WEBUI_LEVEL_RESTRICTED},
{
"webcontrol_tls",
"# Use ssl / tls for the webcontrol",
0, PARM_TYP_BOOL, PARM_CAT_04, WEBUI_LEVEL_RESTRICTED },
{
"webcontrol_cert",
"# Full path and file name of the certificate file for tls",
1, PARM_TYP_STRING, PARM_CAT_04, WEBUI_LEVEL_RESTRICTED},
{
"webcontrol_key",
"# Full path and file name of the key file for tls",
1, PARM_TYP_STRING, PARM_CAT_04, WEBUI_LEVEL_RESTRICTED},
{
"webcontrol_cors_header",
"# The cross-origin resource sharing (CORS) header for webcontrol",
0, PARM_TYP_STRING, PARM_CAT_04, WEBUI_LEVEL_RESTRICTED },
{
"stream_port",
"############################################################\n"
"# Live stream configuration parameters\n"
"############################################################\n\n"
"# The port number for the live stream.",
0, PARM_TYP_INT, PARM_CAT_04, WEBUI_LEVEL_ADVANCED },
{
"stream_localhost",
"# Restrict stream connections to the localhost.",
0, PARM_TYP_BOOL, PARM_CAT_04, WEBUI_LEVEL_ADVANCED },
{
"stream_auth_method",
"# Authentication method for live stream.",
0, PARM_TYP_INT, PARM_CAT_04, WEBUI_LEVEL_RESTRICTED},
{
"stream_authentication",
"# The authentication string for the stream. Syntax username:password",
1, PARM_TYP_STRING, PARM_CAT_04, WEBUI_LEVEL_RESTRICTED },
{
"stream_tls",
"# Use ssl / tls for stream.",
0, PARM_TYP_BOOL, PARM_CAT_04, WEBUI_LEVEL_RESTRICTED },
{
"stream_cors_header",
"# The cross-origin resource sharing (CORS) header for the stream",
0, PARM_TYP_STRING, PARM_CAT_04, WEBUI_LEVEL_RESTRICTED },
{
"stream_preview_scale",
"# Percentage to scale the stream image on the webcontrol.",
0, PARM_TYP_INT, PARM_CAT_04, WEBUI_LEVEL_LIMITED },
{
"stream_preview_newline",
"# Have the stream image start on a new line of the webcontrol",
0, PARM_TYP_BOOL, PARM_CAT_04, WEBUI_LEVEL_LIMITED },
{
"stream_preview_method",
"# Method for showing stream on webcontrol.",
0, PARM_TYP_INT, PARM_CAT_04, WEBUI_LEVEL_LIMITED },
{
"stream_quality",
"# Quality of the jpeg images produced for stream.",
0, PARM_TYP_INT, PARM_CAT_04, WEBUI_LEVEL_LIMITED },
{
"stream_grey",
"# Provide the stream images in black and white",
0, PARM_TYP_BOOL, PARM_CAT_04, WEBUI_LEVEL_LIMITED },
{
"stream_motion",
"# Output frames at 1 fps when no motion is detected.",
0, PARM_TYP_BOOL, PARM_CAT_04, WEBUI_LEVEL_LIMITED },
{
"stream_maxrate",
"# Maximum framerate of images provided for stream",
0, PARM_TYP_INT, PARM_CAT_04, WEBUI_LEVEL_LIMITED },
{
"database_type",
"############################################################\n"
"# Database and SQL Configuration parameters\n"
"############################################################\n\n"
"# The type of database being used if any.",
0, PARM_TYP_STRING, PARM_CAT_05, WEBUI_LEVEL_ADVANCED},
{
"database_dbname",
"# Database name to use. For sqlite3, the full path and name.",
0, PARM_TYP_STRING, PARM_CAT_05, WEBUI_LEVEL_ADVANCED },
{
"database_host",
"# The host on which the database is located",
0, PARM_TYP_STRING, PARM_CAT_05, WEBUI_LEVEL_ADVANCED },
{
"database_port",
"# Port used by the database.",
0, PARM_TYP_INT, PARM_CAT_05, WEBUI_LEVEL_ADVANCED },
{
"database_user",
"# User account name for database.",
0, PARM_TYP_STRING, PARM_CAT_05, WEBUI_LEVEL_RESTRICTED },
{
"database_password",
"# User password for database.",
0, PARM_TYP_STRING, PARM_CAT_05, WEBUI_LEVEL_RESTRICTED },
{
"database_busy_timeout",
"# Database wait for unlock time",
0, PARM_TYP_INT, PARM_CAT_05, WEBUI_LEVEL_ADVANCED },
{
"sql_log_picture",
"# Log to the database when creating motion triggered image file",
0,PARM_TYP_INT, PARM_CAT_05, WEBUI_LEVEL_LIMITED },
{
"sql_log_snapshot",
"# Log to the database when creating a snapshot image file",
0,PARM_TYP_INT, PARM_CAT_05, WEBUI_LEVEL_LIMITED},
{
"sql_log_movie",
"# Log to the database when creating motion triggered movie file",
0,PARM_TYP_INT, PARM_CAT_05, WEBUI_LEVEL_LIMITED },
{
"sql_log_timelapse",
"# Log to the database when creating timelapse movie file",
0,PARM_TYP_INT, PARM_CAT_05, WEBUI_LEVEL_LIMITED},
{
"sql_query_start",
"# SQL query at event start. See motion_guide.html",
0, PARM_TYP_STRING, PARM_CAT_05, WEBUI_LEVEL_ADVANCED },
{
"sql_query_stop",
"# SQL query at event stop. See motion_guide.html",
0, PARM_TYP_STRING, PARM_CAT_05, WEBUI_LEVEL_ADVANCED },
{
"sql_query",
"# SQL query string that is sent to the database. See motion_guide.html",
0, PARM_TYP_STRING, PARM_CAT_05, WEBUI_LEVEL_ADVANCED},
{
"track_type",
"############################################################\n"
"# Tracking configuration parameters\n"
"############################################################\n\n"
"# Method used by tracking camera. See motion_guide.html",
0, PARM_TYP_INT, PARM_CAT_05, WEBUI_LEVEL_LIMITED },
{
"track_auto",
"# Enable auto tracking",
0, PARM_TYP_BOOL, PARM_CAT_05, WEBUI_LEVEL_LIMITED },
{
"track_move_wait",
"# Delay to wait for after tracking movement as number of picture frames.",
0, PARM_TYP_INT, PARM_CAT_05, WEBUI_LEVEL_LIMITED },
{
"track_generic_move",
"# Command to execute to move a camera in generic tracking mode",
0, PARM_TYP_STRING, PARM_CAT_05, WEBUI_LEVEL_LIMITED },
{
"track_step_angle_x",
"# Angle in degrees the camera moves per step on the X-axis with auto-track",
0, PARM_TYP_INT, PARM_CAT_05, WEBUI_LEVEL_LIMITED },
{
"track_step_angle_y",
"# Angle in degrees the camera moves per step on the Y-axis with auto-track.",
0, PARM_TYP_INT, PARM_CAT_05, WEBUI_LEVEL_LIMITED },
{
"camera",
"##############################################################\n"
"# Camera config files - One for each camera.\n"
"##############################################################",
1, PARM_TYP_STRING, PARM_CAT_05, WEBUI_LEVEL_ADVANCED },
/* using a conf.d style camera addition */
{
"camera_dir",
"##############################################################\n"
"# Directory to read '.conf' files for cameras.\n"
"##############################################################",
1, PARM_TYP_STRING, PARM_CAT_05, WEBUI_LEVEL_ADVANCED },
{ NULL, NULL, 0, (enum PARM_TYP)0, (enum PARM_CAT)0, (enum WEBUI_LEVEL)0 }
};
/*
* Array of deprecated config options:
* When deprecating an option, remove it from above (config_parms array)
* and create an entry in this array of name, last version, info,
* and (if applicable) a replacement conf value and copy funcion.
* Upon reading a deprecated config option, a warning will be logged
* with the given information and last version it was used in.
* If set, the given value will be copied into the conf value
* for backwards compatibility.
*/
struct ctx_parm_depr config_parms_depr[] = {
{
"thread",
"3.4.1",
"The \"thread\" option has been replaced by the \"camera\"",
"camera"
},
{
"ffmpeg_timelapse",
"4.0.1",
"\"ffmpeg_timelapse\" replaced with \"timelapse_interval\"",
"timelapse_interval"
},
{
"ffmpeg_timelapse_mode",
"4.0.1",
"\"ffmpeg_timelapse_mode\" replaced with \"timelapse_mode\"",
"timelapse_mode"
},
{
"brightness",
"4.1.1",
"\"brightness\" replaced with \"vid_control_params\"",
"vid_control_params"
},
{
"contrast",
"4.1.1",
"\"contrast\" replaced with \"vid_control_params\"",
"vid_control_params"
},
{
"saturation",
"4.1.1",
"\"saturation\" replaced with \"vid_control_params\"",
"vid_control_params"
},
{
"hue",
"4.1.1",
"\"hue\" replaced with \"vid_control_params\"",
"vid_control_params"
},
{
"power_line_frequency",
"4.1.1",
"\"power_line_frequency\" replaced with \"vid_control_params\"",
"vid_control_params"
},
{
"text_double",
"4.1.1",
"\"text_double\" replaced with \"text_scale\"",
"text_scale"
},
{
"webcontrol_html_output",
"4.1.1",
"\"webcontrol_html_output\" replaced with \"webcontrol_interface\"",
"webcontrol_interface"
},
{
"lightswitch",
"4.1.1",
"\"lightswitch\" replaced with \"lightswitch_percent\"",
"lightswitch_percent"
},
{
"ffmpeg_output_movies",
"4.1.1",
"\"ffmpeg_output_movies\" replaced with \"movie_output\"",
"movie_output"
},
{
"ffmpeg_output_debug_movies",
"4.1.1",
"\"ffmpeg_output_debug_movies\" replaced with \"movie_output_motion\"",
"movie_output_motion"
},
{
"max_movie_time",
"4.1.1",
"\"max_movie_time\" replaced with \"movie_max_time\"",
"movie_max_time"
},
{
"ffmpeg_bps",
"4.1.1",
"\"ffmpeg_bps\" replaced with \"movie_bps\"",
"movie_bps"
},
{
"ffmpeg_variable_bitrate",
"4.1.1",
"\"ffmpeg_variable_bitrate\" replaced with \"movie_quality\"",
"movie_quality"
},
{
"ffmpeg_video_codec",
"4.1.1",
"\"ffmpeg_video_codec\" replaced with \"movie_codec\"",
"movie_codec"
},
{
"ffmpeg_passthrough",
"4.1.1",
"\"ffmpeg_passthrough\" replaced with \"movie_passthrough\"",
"movie_passthrough"
},
{
"use_extpipe",
"4.1.1",
"\"use_extpipe\" replaced with \"movie_extpipe_use\"",
"movie_extpipe_use"
},
{
"extpipe",
"4.1.1",
"\"extpipe\" replaced with \"movie_extpipe\"",
"movie_extpipe"
},
{
"output_pictures",
"4.1.1",
"\"output_pictures\" replaced with \"picture_output\"",
"picture_output"
},
{
"output_debug_pictures",
"4.1.1",
"\"output_debug_pictures\" replaced with \"picture_output_motion\"",
"picture_output_motion"
},
{
"quality",
"4.1.1",
"\"quality\" replaced with \"picture_quality\"",
"picture_quality"
},
{
"exif_text",
"4.1.1",
"\"exif_text\" replaced with \"picture_exif\"",
"picture_exif"
},
{
"motion_video_pipe",
"4.1.1",
"\"motion_video_pipe\" replaced with \"video_pipe_motion\"",
"video_pipe_motion"
},
{
"ipv6_enabled",
"4.1.1",
"\"ipv6_enabled\" replaced with \"webcontrol_ipv6\"",
"webcontrol_ipv6"
},
{
"rtsp_uses_tcp",
"4.1.1",
"\"rtsp_uses_tcp\" replaced with \"netcam_use_tcp\"",
"netcam_use_tcp"
},
{
"switchfilter",
"4.1.1",
"\"switchfilter\" replaced with \"roundrobin_switchfilter\"",
"roundrobin_switchfilter"
},
{
"logfile",
"4.1.1",
"\"logfile\" replaced with \"log_file\"",
"log_file"
},
{
"process_id_file",
"4.1.1",
"\"process_id_file\" replaced with \"pid_file\"",
"pid_file"
},
{ NULL, NULL, NULL, NULL}
};
/** Prints usage and options allowed from Command-line. */
static void usage(void) {
printf("motion Version %s, Copyright 2000-2019 Jeroen Vreeken/Folkert van Heusden/Kenneth Lavrsen/Motion-Project maintainers\n",PACKAGE_VERSION);
printf("\nHome page :\t https://motion-project.github.io/ \n");
printf("\nusage:\tmotion [options]\n");
printf("\n\n");
printf("Possible options:\n\n");
printf("-b\t\t\tRun in background (daemon) mode.\n");
printf("-n\t\t\tRun in non-daemon mode.\n");
printf("-s\t\t\tRun in setup mode.\n");
printf("-c config\t\tFull path and filename of config file.\n");
printf("-d level\t\tLog level (1-9) (EMG, ALR, CRT, ERR, WRN, NTC, INF, DBG, ALL). default: 6 / NTC.\n");
printf("-k type\t\t\tType of log (COR, STR, ENC, NET, DBL, EVT, TRK, VID, ALL). default: ALL.\n");
printf("-p process_id_file\tFull path and filename of process id file (pid file).\n");
printf("-l log file \t\tFull path and filename of log file.\n");
printf("-m\t\t\tDisable motion detection at startup.\n");
printf("-h\t\t\tShow this screen.\n");
printf("\n");
printf("Motion is configured using a config file only. If none is supplied,\n");
printf("it will read motion.conf from current directory, ~/.motion or %s.\n", sysconfdir);
printf("%s\n", sysconfdir);
printf("\n");
}
/** Process Command-line options specified */
static void conf_cmdline(struct ctx_motapp *motapp) {
int c;
while ((c = getopt(motapp->argc, motapp->argv, "bc:d:hmns?p:k:l:")) != EOF)
switch (c) {
case 'c':
conf_edit_set(motapp, -1, (char*)"conf_filename", optarg);
break;
case 'b':
conf_edit_set(motapp, -1, (char*)"daemon", (char*)"on");
break;
case 'n':
conf_edit_set(motapp, -1, (char*)"daemon", (char*)"off");
break;
case 's':
conf_edit_set(motapp, -1, (char*)"setup_mode", (char*)"on");
break;
case 'd':
conf_edit_set(motapp, -1, (char*)"log_level", optarg);
break;
case 'k':
conf_edit_set(motapp, -1, (char*)"log_type", optarg);
break;
case 'p':
conf_edit_set(motapp, -1, (char*)"pid_file", optarg);
break;
case 'l':
conf_edit_set(motapp, -1, (char*)"log_file", optarg);
break;
case 'm':
motapp->pause = TRUE;
break;
case 'h':
case '?':
default:
usage();
exit(1);
}
optind = 1;
}
static void conf_parm_camera(struct ctx_motapp *motapp, char *str) {
int indx_cams, indx;
char parm_val[PATH_MAX];
FILE *fp;
fp = fopen(str, "r");
if (!fp) {
MOTION_LOG(ALR, TYPE_ALL, SHOW_ERRNO
,_("Camera config file %s not found"), str);
return;
}
/* Find the current number of threads defined. */
indx_cams = 0;
while (motapp->cam_list[indx_cams] != NULL){
indx_cams++;
};
/* Index starts at zero (+1) plus another for our new camera(+2)*/
motapp->cam_list = (struct ctx_cam **)myrealloc(
motapp->cam_list, sizeof(struct ctx_cam *) * (indx_cams + 2), "config_camera");
motapp->cam_list[indx_cams] = (struct ctx_cam *)mymalloc(sizeof(struct ctx_cam));
motapp->cam_list[indx_cams + 1] = NULL;
conf_edit_dflt_cam(motapp->cam_list[indx_cams]);
indx = 0;
while (config_parms[indx].parm_name != NULL) {
conf_edit_get(motapp->cam_list[0],(char *)config_parms[indx].parm_name
,parm_val, config_parms[indx].parm_cat);
/* Once we adjust all the code to allow for "" being same as NULL we can remove this*/
if ((config_parms[indx].parm_type == PARM_TYP_STRING) && (mystreq(parm_val,""))) {
conf_edit_set(motapp,indx_cams, (char *)config_parms[indx].parm_name, NULL);
} else {
conf_edit_set(motapp,indx_cams, (char *)config_parms[indx].parm_name, parm_val);
}
indx++;
}
/* Process the camera's config file and notify user on console. */
MOTION_LOG(NTC, TYPE_ALL, NO_ERRNO
,_("Processing camera config file %s"), str);
snprintf(motapp->cam_list[indx_cams]->conf_filename
,sizeof(motapp->cam_list[indx_cams]->conf_filename),"%s", str);
conf_process(motapp, fp, indx_cams);
myfclose(fp);
/*Cascade new pointers to all cameras. */
indx_cams = 0;
while (motapp->cam_list[indx_cams] != NULL){
motapp->cam_list[indx_cams]->motapp = motapp;
motapp->cam_list[indx_cams]->cam_list = motapp->cam_list;
indx_cams++;
}
return;
}
/** Process camera_dir */
static void conf_parm_camera_dir(struct ctx_motapp *motapp, char *str) {
DIR *dp;
struct dirent *ep;
size_t name_len;
int i;
char conf_file[PATH_MAX];
dp = opendir(str);
if (dp != NULL) {
while( (ep = readdir(dp)) ) {
name_len = strlen(ep->d_name);
if ((name_len > strlen(".conf")) &&
(mystreq(".conf",ep->d_name + name_len - strlen(".conf")))) {
memset(conf_file, '\0', sizeof(conf_file));
snprintf(conf_file, sizeof(conf_file) - 1, "%s/%s",
str, ep->d_name);
MOTION_LOG(NTC, TYPE_ALL, NO_ERRNO
,_("Processing config file %s"), conf_file );
conf_parm_camera(motapp, conf_file);
/* The last ctx_cam thread would be ours,
* set it as created from conf directory.
*/
i = 0;
while (motapp->cam_list[++i]);
motapp->cam_list[i-1]->from_conf_dir = TRUE;
}
}
closedir(dp);
} else {
MOTION_LOG(ALR, TYPE_ALL, SHOW_ERRNO
,_("Camera directory config %s not found"), str);
}
/* Store the given config value to allow writing it out */
conf_edit_set(motapp,0, (char *)"camera_dir", str);
return;
}
/** Process each line from the config file. */
void conf_process(struct ctx_motapp *motapp, FILE *fp, int threadnbr) {
char line[PATH_MAX], *cmd = NULL, *arg1 = NULL;
char *beg = NULL, *end = NULL;
while (fgets(line, PATH_MAX-1, fp)) {
if (!(line[0] == '#' || line[0] == ';' || strlen(line) < 2)) {
arg1 = NULL;
/* Trim white space and any CR or LF at the end of the line. */
end = line + strlen(line) - 1; /* Point to the last non-null character in the string. */
while (end >= line && (*end == ' ' || *end == '\t' || *end == '\n' || *end == '\r')){
end--;
}
*(end+1) = '\0';
if (strlen(line) == 0) continue;
/* Trim leading whitespace from the line and find command. */
beg = line;
while (*beg == ' ' || *beg == '\t'){
beg++;
}
cmd = beg; /* Command starts here. */
while (*beg != ' ' && *beg != '\t' && *beg != '=' && *beg != '\0'){
beg++;
}
*beg = '\0'; /* Command string terminates here. */
/* Trim space between command and argument. */
beg++;
if (strlen(beg) > 0) {
while (*beg == ' ' || *beg == '\t' || *beg == '=' || *beg == '\n' || *beg == '\r'){
beg++;
}
/* Strip quotes from around arg */
if ((beg[0] == '"' && beg[strlen(beg)-1] == '"') ||
(beg[0] == '\'' && beg[strlen(beg)-1] == '\'')) {
beg[strlen(beg)-1] = '\0';
beg++;
}
arg1 = beg; /* Argument starts here */
}
/* Ignore camera/dir in sub files */
if (threadnbr == -1){
conf_edit_set(motapp, threadnbr, cmd, arg1);
} else {
if (mystreq(cmd,"camera_dir")) {
if (threadnbr == 0) conf_parm_camera_dir(motapp, arg1);
} else if (mystreq(cmd,"camera")) {
if (threadnbr == 0) conf_parm_camera(motapp, arg1);
} else {
conf_edit_set(motapp, threadnbr, cmd, arg1);
}
}
}
}
return;
}
/** Write the configuration(s) to the log */
void conf_parms_log(struct ctx_cam **cam_list) {
int i, threadnbr, diff_val;
char parm_val[PATH_MAX], parm_main[PATH_MAX];
MOTION_LOG(INF, TYPE_ALL, NO_ERRNO
,_("Writing configuration parameters from all files"));
threadnbr = 0;
while (cam_list[threadnbr]!= NULL){
motion_log(INF, TYPE_ALL, NO_ERRNO,0
,_("Camera %d - Config file: %s"), threadnbr, cam_list[threadnbr]->conf_filename);
i = 0;
while (config_parms[i].parm_name != NULL) {
diff_val = TRUE;
conf_edit_get(cam_list[threadnbr], config_parms[i].parm_name
, parm_val ,config_parms[i].parm_cat);
if (threadnbr > 0){
conf_edit_get(cam_list[0], config_parms[i].parm_name
, parm_main ,config_parms[i].parm_cat);
if (mystreq(parm_val, parm_main)) diff_val = FALSE;
}
if (diff_val) {
if (mystreq(config_parms[i].parm_name, "netcam_url") ||
mystreq(config_parms[i].parm_name, "netcam_userpass") ||
mystreq(config_parms[i].parm_name, "netcam_highres") ||
mystreq(config_parms[i].parm_name, "stream_cors_header") ||
mystreq(config_parms[i].parm_name, "stream_authentication") ||
mystreq(config_parms[i].parm_name, "webcontrol_authentication") ||
mystreq(config_parms[i].parm_name, "webcontrol_cors_header") ||
mystreq(config_parms[i].parm_name, "webcontrol_key") ||
mystreq(config_parms[i].parm_name, "webcontrol_cert") ||
mystreq(config_parms[i].parm_name, "database_user") ||
mystreq(config_parms[i].parm_name, "database_password"))
{
motion_log(INF, TYPE_ALL, NO_ERRNO,0
,_("%-25s <redacted>"), config_parms[i].parm_name);
} else {
if (strncmp(config_parms[i].parm_name, "text", 4) ||
strncmp(parm_val, " ", 1)){
motion_log(INF, TYPE_ALL, NO_ERRNO,0, "%-25s %s"
, config_parms[i].parm_name, parm_val);
} else {
motion_log(INF, TYPE_ALL, NO_ERRNO,0, "%-25s \"%s\""
, config_parms[i].parm_name, parm_val);
}
}
}
i++;
}
threadnbr++;
}
}
/** Write the configuration(s) to file */
void conf_parms_write(struct ctx_cam **cam_list) {
char parm_val[PATH_MAX];
int i, thread;
char timestamp[32];
FILE *conffile;
for (thread = 0; cam_list[thread]; thread++) {
MOTION_LOG(NTC, TYPE_ALL, NO_ERRNO
,_("Writing config file to %s")
,cam_list[thread]->conf_filename);
conffile = myfopen(cam_list[thread]->conf_filename, "w");
if (!conffile) continue;
time_t now = time(0);
strftime(timestamp, 32, "%Y-%m-%dT%H:%M:%S", localtime(&now));
fprintf(conffile, "# %s\n", cam_list[thread]->conf_filename);
fprintf(conffile, "#\n# This config file was generated by motion " VERSION "\n");
fprintf(conffile, "# at %s\n", timestamp);
fprintf(conffile, "\n\n");
for (i = 0; config_parms[i].parm_name; i++) {
conf_edit_get(cam_list[i], config_parms[i].parm_name
, parm_val, config_parms[i].parm_cat);
/* If config parameter has a value (not NULL) print it to the config file. */
if (strlen(parm_val) > 0) {
fprintf(conffile, "%s\n", config_parms[i].parm_help);
/*
* If the option is a text_* and first char is a space put
* quotation marks around to allow leading spaces.
*/
if (strncmp(config_parms[i].parm_name, "text", 4) || strncmp(parm_val, " ", 1)){
fprintf(conffile, "%s %s\n\n", config_parms[i].parm_name, parm_val);
} else {
fprintf(conffile, "%s \"%s\"\n\n", config_parms[i].parm_name, parm_val);
}
} else {
if (thread == 0) {
char value[PATH_MAX];
/* The 'camera_dir' option should keep the installed default value */
if (mystreq(config_parms[i].parm_name, "camera_dir")){
sprintf(value, "%s", sysconfdir "/conf.d");
} else {
sprintf(value, "%s", "value");
}
fprintf(conffile, "%s\n", config_parms[i].parm_help);
fprintf(conffile, "; %s %s\n\n", config_parms[i].parm_name, value);
}
}
}
fprintf(conffile, "\n");
myfclose(conffile);
conffile = NULL;
}
}
void conf_init_app(struct ctx_motapp *motapp, int argc, char *argv[]){
FILE *fp = NULL;
char filename[PATH_MAX];
char path[PATH_MAX];
int retcd;
motapp->argc = argc;
motapp->argv = argv;
conf_edit_dflt_app(motapp);
conf_cmdline(motapp); /* Get the filename if provided */
if (motapp->conf_filename != NULL) {
retcd = snprintf(filename, PATH_MAX, "%s", motapp->conf_filename);
if ((retcd < 0) || (retcd > PATH_MAX)){
MOTION_LOG(ERR, TYPE_ALL, SHOW_ERRNO, _("Error setting filename"));
exit(-1);
}
fp = fopen (filename, "r");
}
if (!fp) {
if (getcwd(path, sizeof(path)) == NULL) {
MOTION_LOG(ERR, TYPE_ALL, SHOW_ERRNO, _("Error getcwd"));
exit(-1);
}
retcd = snprintf(filename, PATH_MAX, "%s/motion.conf", path);
if ((retcd < 0) || (retcd > PATH_MAX)){
MOTION_LOG(ERR, TYPE_ALL, SHOW_ERRNO, _("Error setting filename"));
exit(-1);
}
fp = fopen (filename, "r");
}
if (!fp) {
retcd = snprintf(filename, PATH_MAX, "%s/.motion/motion.conf", getenv("HOME"));
if ((retcd < 0) || (retcd > PATH_MAX)){
MOTION_LOG(ERR, TYPE_ALL, SHOW_ERRNO, _("Error setting filename"));
exit(-1);
}
fp = fopen(filename, "r");
}
if (!fp) {
retcd = snprintf(filename, PATH_MAX, "%s/motion.conf", sysconfdir);
if ((retcd < 0) || (retcd > PATH_MAX)){
MOTION_LOG(ERR, TYPE_ALL, SHOW_ERRNO, _("Error setting filename"));
exit(-1);
}
fp = fopen(filename, "r");
}
if (!fp){
MOTION_LOG(ALR, TYPE_ALL, SHOW_ERRNO
,_("could not open configfile %s"), filename);
}
/* Now we process the motion.conf config file and close it. */
if (fp) {
MOTION_LOG(NTC, TYPE_ALL, NO_ERRNO,_("Processing config file %s"), filename);
conf_edit_set(motapp, -1, (char*)"conf_filename", (char*)filename);
conf_process(motapp, fp, -1);
myfclose(fp);
conf_cmdline(motapp);
} else {
MOTION_LOG(CRT, TYPE_ALL, NO_ERRNO
,_("No config file to process, using default values"));
}
return;
}
void conf_init_cams(struct ctx_motapp *motapp){
FILE *fp = NULL;
int retcd;
motapp->cam_list = (struct ctx_cam**)calloc(sizeof(struct ctx_cam *), 2);
motapp->cam_list[0] = (struct ctx_cam *)mymalloc(sizeof(struct ctx_cam));
memset(motapp->cam_list[0], 0, sizeof(struct ctx_cam));
motapp->cam_list[1] = NULL;
motapp->cam_list[0]->motapp = motapp;
motapp->cam_list[0]->cam_list = motapp->cam_list;
conf_edit_dflt_cam(motapp->cam_list[0]);
if (motapp->conf_filename != NULL) {
retcd = snprintf(motapp->cam_list[0]->conf_filename
,PATH_MAX,"%s",motapp->conf_filename);
if ((retcd < 0)|| (retcd > PATH_MAX)){
MOTION_LOG(NTC, TYPE_ALL, NO_ERRNO
,_("Error setting file name %s"), motapp->conf_filename);
exit(1);
}
fp = fopen (motapp->conf_filename, "r");
}
if (fp) {
MOTION_LOG(NTC, TYPE_ALL, NO_ERRNO
,_("Processing thread 0 - config file %s"), motapp->conf_filename);
conf_process(motapp, fp, 0);
myfclose(fp);
} else {
MOTION_LOG(CRT, TYPE_ALL, NO_ERRNO
,_("No config file to process, using default values"));
}
motapp->cam_list[0]->pause = motapp->pause;
return;
}
void conf_deinit(struct ctx_motapp *motapp) {
int indx;
indx = 0;
while (motapp->cam_list[indx] != NULL){
conf_edit_free(motapp->cam_list[indx]);
free(motapp->cam_list[indx]);
indx++;
}
free(motapp->cam_list);
motapp->cam_list = NULL;
}