mirror of
https://github.com/Motion-Project/motion.git
synced 2026-03-04 22:36:18 -05:00
1294 lines
44 KiB
C++
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;
|
|
|
|
}
|
|
|