From 3f5a2a2aa60ce25cc3e2d4d7662a4d79cb58696d Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 7 Jan 2019 15:56:23 -0500 Subject: [PATCH 01/12] disable delete button when event is archived. --- web/skins/classic/views/event.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/event.php b/web/skins/classic/views/event.php index ce27dfcf8..07181b268 100644 --- a/web/skins/classic/views/event.php +++ b/web/skins/classic/views/event.php @@ -128,7 +128,7 @@ if ( ! $Event->Id() ) { -
+
Archived == 1 ? ' class="hidden"' : '' ?>>
Archived == 0 ? ' class="hidden"' : '' ?>>
From ae1f00f2a1f1b479b61b4e3b533f09db43a88a97 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 8 Jan 2019 13:06:19 -0500 Subject: [PATCH 02/12] add a logging callback to the libvlc camera --- src/zm_libvlc_camera.cpp | 27 +++++++++++++++++++++++++++ src/zm_libvlc_camera.h | 8 +++++--- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/zm_libvlc_camera.cpp b/src/zm_libvlc_camera.cpp index 833666144..1998d1854 100644 --- a/src/zm_libvlc_camera.cpp +++ b/src/zm_libvlc_camera.cpp @@ -186,6 +186,8 @@ int LibvlcCamera::PrimeCapture() { Error("Unable to create libvlc instance due to: %s", libvlc_errmsg()); return -1; } + libvlc_log_set(mLibvlcInstance, LibvlcCamera::log_callback, NULL); + mLibvlcMedia = libvlc_media_new_location(mLibvlcInstance, mPath.c_str()); if ( mLibvlcMedia == NULL ) { @@ -214,6 +216,7 @@ int LibvlcCamera::PrimeCapture() { return 0; } + int LibvlcCamera::PreCapture() { return 0; } @@ -244,4 +247,28 @@ int LibvlcCamera::PostCapture() { return 0; } +void LibvlcCamera::log_callback(void *ptr, int level, const libvlc_log_t *ctx, const char *fmt, va_list vargs) { + Logger *log = Logger::fetch(); + int log_level = Logger::NOLOG; + if ( level == LIBVLC_ERROR ) { + log_level = Logger::WARNING; // ffmpeg outputs a lot of errors that don't really affect anything. + //log_level = Logger::ERROR; + } else if ( level == LIBVLC_WARNING ) { + log_level = Logger::INFO; + //log_level = Logger::WARNING; + } else if ( level == LIBVLC_NOTICE ) { + log_level = Logger::DEBUG1; + //log_level = Logger::INFO; + } else if ( level == LIBVLC_DEBUG ) { + log_level = Logger::DEBUG3; + } else { + Error("Unknown log level %d", level); + } + + if ( log ) { + char logString[8192]; + vsnprintf(logString, sizeof(logString)-1, fmt, vargs); + log->logPrint(false, __FILE__, __LINE__, log_level, logString); + } +} #endif // HAVE_LIBVLC diff --git a/src/zm_libvlc_camera.h b/src/zm_libvlc_camera.h index f5c659e72..038d30f05 100644 --- a/src/zm_libvlc_camera.h +++ b/src/zm_libvlc_camera.h @@ -42,6 +42,8 @@ struct LibvlcPrivateData }; class LibvlcCamera : public Camera { + private: + static void log_callback( void *ptr, int level, const libvlc_log_t *ctx, const char *format, va_list vargs ); protected: std::string mPath; std::string mMethod; @@ -59,9 +61,9 @@ public: LibvlcCamera( int p_id, const std::string &path, const std::string &p_method, const std::string &p_options, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio ); ~LibvlcCamera(); - const std::string &Path() const { return( mPath ); } - const std::string &Options() const { return( mOptions ); } - const std::string &Method() const { return( mMethod ); } + const std::string &Path() const { return mPath; } + const std::string &Options() const { return mOptions; } + const std::string &Method() const { return mMethod; } void Initialise(); void Terminate(); From a5de51478eed44a777c8f2df44c748b9567e9d83 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 8 Jan 2019 13:12:22 -0500 Subject: [PATCH 03/12] The termination callback should be private --- src/zm_ffmpeg_camera.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/zm_ffmpeg_camera.h b/src/zm_ffmpeg_camera.h index 21eeb328f..4d316eb60 100644 --- a/src/zm_ffmpeg_camera.h +++ b/src/zm_ffmpeg_camera.h @@ -99,12 +99,13 @@ class FfmpegCamera : public Camera { void Initialise(); void Terminate(); - static int FfmpegInterruptCallback(void*ctx); int PrimeCapture(); int PreCapture(); int Capture( Image &image ); int CaptureAndRecord( Image &image, timeval recording, char* event_directory ); int PostCapture(); + private: + static int FfmpegInterruptCallback(void*ctx); }; #endif // ZM_FFMPEG_CAMERA_H From ffa37d8c10e8ca3fa8bccb03e24afc708c6f7bb5 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 8 Jan 2019 13:12:35 -0500 Subject: [PATCH 04/12] Fix margins on replayControl --- web/skins/classic/css/base/views/event.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/css/base/views/event.css b/web/skins/classic/css/base/views/event.css index 4696215b7..f392cb99c 100644 --- a/web/skins/classic/css/base/views/event.css +++ b/web/skins/classic/css/base/views/event.css @@ -61,7 +61,7 @@ span.noneCue { } #menuBar1 #replayControl { - margin: 0 4px 0 auto; + margin: auto 5px auto auto; } #menuBar1 div { From c1e4fbac6a548944642e28c39e63c1d1104f919d Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 9 Jan 2019 12:37:42 -0500 Subject: [PATCH 05/12] extend input path and options to the full width of the popup --- web/skins/classic/css/base/views/monitor.css | 5 +++++ web/skins/classic/views/monitor.php | 7 +++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/web/skins/classic/css/base/views/monitor.css b/web/skins/classic/css/base/views/monitor.css index 7cac28fe1..aa9ce1c26 100644 --- a/web/skins/classic/css/base/views/monitor.css +++ b/web/skins/classic/css/base/views/monitor.css @@ -3,3 +3,8 @@ margin-left: 3px; padding: 0px; } + +.SourceOptions input, +.SourcePath input { + width: 100%; +} diff --git a/web/skins/classic/views/monitor.php b/web/skins/classic/views/monitor.php index dfc96b547..8d7e518eb 100644 --- a/web/skins/classic/views/monitor.php +++ b/web/skins/classic/views/monitor.php @@ -879,9 +879,12 @@ include('_monitor_source_nvsocket.php'); Type() == 'Ffmpeg' || $monitor->Type() == 'Libvlc' ) { ?> - +  ()Method() ); ?> -  (Type()), 'zmOptionHelp', 'optionhelp', '?' ) ?>) + +  (Type()), 'zmOptionHelp', 'optionhelp', '?' ) ?>) + + Type() != 'NVSocket' && $monitor->Type() != 'WebSite' ) { From 1d54216e801b11e9b4447edb9fc3c70ce0454766 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 9 Jan 2019 16:23:58 -0500 Subject: [PATCH 06/12] spacing --- web/skins/classic/views/filter.php | 83 +++++++++++++++--------------- 1 file changed, 41 insertions(+), 42 deletions(-) diff --git a/web/skins/classic/views/filter.php b/web/skins/classic/views/filter.php index 2be6c264c..516c5d0f4 100644 --- a/web/skins/classic/views/filter.php +++ b/web/skins/classic/views/filter.php @@ -18,7 +18,7 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // -if ( !canView( 'Events' ) ) { +if ( !canView('Events') ) { $view = 'error'; return; } @@ -28,7 +28,7 @@ parseSort(); $filterNames = array( ''=>translate('ChooseFilter') ); $filter = NULL; -foreach ( dbFetchAll( 'SELECT * FROM Filters ORDER BY Name' ) as $row ) { +foreach ( dbFetchAll('SELECT * FROM Filters ORDER BY Name') as $row ) { $filterNames[$row['Id']] = $row['Id'] . ' ' . $row['Name']; if ( $row['Background'] ) $filterNames[$row['Id']] .= '*'; @@ -36,7 +36,7 @@ foreach ( dbFetchAll( 'SELECT * FROM Filters ORDER BY Name' ) as $row ) { $filterNames[$row['Id']] .= '&'; if ( isset($_REQUEST['Id']) && $_REQUEST['Id'] == $row['Id'] ) { - $filter = new Filter( $row ); + $filter = new Filter($row); } } if ( ! $filter ) { @@ -69,8 +69,8 @@ if (count($filter->terms()) > 0) { if ( count($terms) ) { for ( $i = 0; $i <= count($terms)-2; $i++ ) { - $obracketTypes[$i] = str_repeat( '(', $i ); - $cbracketTypes[$i] = str_repeat( ')', $i ); + $obracketTypes[$i] = str_repeat('(', $i); + $cbracketTypes[$i] = str_repeat(')', $i); } } @@ -130,28 +130,28 @@ $archiveTypes = array( $focusWindow = true; -$storageareas = array( '' => 'All' ); +$storageareas = array('' => 'All'); //$storageareas[0] = 'Default ' . ZM_DIR_EVENTS; -foreach ( dbFetchAll( 'SELECT Id,Name FROM Storage ORDER BY lower(Name) ASC' ) as $storage ) { +foreach ( dbFetchAll('SELECT Id,Name FROM Storage ORDER BY lower(Name) ASC') as $storage ) { $storageareas[$storage['Id']] = $storage['Name']; } $weekdays = array(); for ( $i = 0; $i < 7; $i++ ) { - $weekdays[$i] = strftime( '%A', mktime( 12, 0, 0, 1, $i+1, 2001 ) ); + $weekdays[$i] = strftime('%A', mktime(12, 0, 0, 1, $i+1, 2001)); } $states = array(); -foreach ( dbFetchAll( 'SELECT Id,Name FROM States ORDER BY lower(Name) ASC' ) as $state_row ) { +foreach ( dbFetchAll('SELECT Id,Name FROM States ORDER BY lower(Name) ASC') as $state_row ) { $states[$state_row['Id']] = $state_row['Name']; } $servers = array(); $servers['ZM_SERVER_ID'] = 'Current Server'; $servers['NULL'] = 'No Server'; -foreach ( dbFetchAll( 'SELECT Id,Name FROM Servers ORDER BY lower(Name) ASC' ) as $server ) { +foreach ( dbFetchAll('SELECT Id,Name FROM Servers ORDER BY lower(Name) ASC') as $server ) { $servers[$server['Id']] = $server['Name']; } $monitors = array(); -foreach ( dbFetchAll( 'select Id,Name from Monitors order by Name asc' ) as $monitor ) { - if ( visibleMonitor( $monitor['Id'] ) ) { +foreach ( dbFetchAll('SELECT Id,Name FROM Monitors ORDER BY Name ASC') as $monitor ) { + if ( visibleMonitor($monitor['Id']) ) { $monitors[$monitor['Name']] = $monitor['Name']; } } @@ -168,7 +168,7 @@ xhtmlHeaders(__FILE__, translate('EventFilter') );
1 ) { - echo htmlSelect( 'Id', $filterNames, $filter->Id(), 'this.form.submit();' ); + echo htmlSelect('Id', $filterNames, $filter->Id(), 'this.form.submit();'); } else { ?> - + - 2 ) { echo htmlSelect( "filter[Query][terms][$i][obr]", $obracketTypes, $term['obr'] ); } else { ?>  - + 2 ) { echo htmlSelect("filter[Query][terms][$i][obr]", $obracketTypes, $term['obr']); } else { ?>  + - + - + - + - + @@ -258,46 +258,46 @@ for ( $i=0; $i < count($terms); $i++ ) { - - + + - - + + - - + + - - + + - - + + - + - + - 2 ) { echo htmlSelect( "filter[Query][terms][$i][cbr]", $cbracketTypes, $term['cbr'] ); } else { ?>  + 2 ) { echo htmlSelect("filter[Query][terms][$i][cbr]", $cbracketTypes, $term['cbr']); } else { ?>  - - /> + + />

- - AutoExecute() ) { ?> checked="checked"/> - + AutoExecute() ) { ?> checked="checked"/> +

@@ -413,14 +412,14 @@ if ( ZM_OPT_MESSAGE ) { Id() ) { ?> - + Date: Wed, 9 Jan 2019 16:39:53 -0500 Subject: [PATCH 07/12] add some parenthesis to make logic at more clear if not more correct. Potentially fix #2405 --- src/zm_local_camera.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zm_local_camera.cpp b/src/zm_local_camera.cpp index 635861d4c..c9e1eca6b 100644 --- a/src/zm_local_camera.cpp +++ b/src/zm_local_camera.cpp @@ -952,7 +952,7 @@ void LocalCamera::Initialise() { } stdId = standard; - if ( (input.std != V4L2_STD_UNKNOWN) && vidioctl( vid_fd, VIDIOC_S_STD, &stdId ) < 0 ) { + if ( (input.std != V4L2_STD_UNKNOWN) && (vidioctl(vid_fd, VIDIOC_S_STD, &stdId) < 0) ) { Fatal("Failed to set video standard %d: %s", standard, strerror(errno)); } From b373577589427aeec7f46971ee6d48b762d2b358 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 10 Jan 2019 12:08:25 -0500 Subject: [PATCH 08/12] fix function view after actions cleanup --- web/includes/actions/function.php | 1 + web/skins/classic/views/function.php | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/web/includes/actions/function.php b/web/includes/actions/function.php index 8fcd411b6..489040d53 100644 --- a/web/includes/actions/function.php +++ b/web/includes/actions/function.php @@ -45,5 +45,6 @@ if ( !empty($_REQUEST['mid']) && canEdit('Monitors', $_REQUEST['mid']) ) { $refreshParent = true; } } // end if action + $view = 'none'; } // end if $mid and canEdit($mid) ?> diff --git a/web/skins/classic/views/function.php b/web/skins/classic/views/function.php index 45355ec4e..8864fb07e 100644 --- a/web/skins/classic/views/function.php +++ b/web/skins/classic/views/function.php @@ -18,42 +18,43 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // -if ( !canEdit( 'Monitors' ) ) { +if ( !canEdit('Monitors') ) { $view = 'error'; return; } -$monitor = dbFetchMonitor( $_REQUEST['mid'] ); +$monitor = dbFetchMonitor($_REQUEST['mid']); $focusWindow = true; -xhtmlHeaders(__FILE__, translate('Function')." - ".validHtmlStr($monitor['Name']) ); +xhtmlHeaders(__FILE__, translate('Function').' - '.validHtmlStr($monitor['Name'])); ?>

- +

- checked="checked"/> + + checked="checked"/>

- - + +
From 730ced60d86e7027f56489df1d674c36b4c3eb6e Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 10 Jan 2019 12:08:51 -0500 Subject: [PATCH 09/12] specify which input we are setting standard on. Not sure it is required, but the api docs do it --- src/zm_local_camera.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/zm_local_camera.cpp b/src/zm_local_camera.cpp index c9e1eca6b..c6030f08a 100644 --- a/src/zm_local_camera.cpp +++ b/src/zm_local_camera.cpp @@ -942,6 +942,7 @@ void LocalCamera::Initialise() { v4l2_std_id stdId; memset(&input, 0, sizeof(input)); + input.index = channel; if ( vidioctl(vid_fd, VIDIOC_ENUMINPUT, &input) < 0 ) { Fatal("Failed to enumerate input %d: %s", channel, strerror(errno)); @@ -953,7 +954,7 @@ void LocalCamera::Initialise() { stdId = standard; if ( (input.std != V4L2_STD_UNKNOWN) && (vidioctl(vid_fd, VIDIOC_S_STD, &stdId) < 0) ) { - Fatal("Failed to set video standard %d: %s", standard, strerror(errno)); + Fatal("Failed to set video standard %d: %d %s", standard, errno, strerror(errno)); } Contrast(contrast); From 208d8f28de369d49a74e162a569d1ffa10ab0e85 Mon Sep 17 00:00:00 2001 From: kobold81 <41242871+kobold81@users.noreply.github.com> Date: Fri, 11 Jan 2019 18:14:42 +0100 Subject: [PATCH 10/12] update debian to 1.32.x (#2407) Hello, the ZM_PATH config has cost me several hours to fix. I would like to add this little snipped to help others avoid this pitfall. Best regards Marc --- docs/installationguide/debian.rst | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/docs/installationguide/debian.rst b/docs/installationguide/debian.rst index 0b926435f..0d4167b8f 100644 --- a/docs/installationguide/debian.rst +++ b/docs/installationguide/debian.rst @@ -91,7 +91,7 @@ Adjust permissions to the zm.conf file to allow web account to access it. **Step 9:** Setup ZoneMinder service -:: + :: systemctl enable zoneminder.service @@ -127,7 +127,23 @@ CTRL+o then [Enter] to save CTRL+x to exit -**Step 12:** Start ZoneMinder + +**Step 12:** Please check the configuration +Zoneminder 1.32.x + 1. Check path of ZM_PATH in '/etc/zm/conf.d/zmcuston.conf' is ZM_PATH_ZMS=/zm/cgi-bin/nph-zms + :: + cat /etc/zm/conf.d/zmcuston.conf + + 2. Check config of /etc/apache2/conf-enabled/zoneminder.conf has the same ScriptAlias /zm/cgi-bin that is configured + in ZM_PATH. The part /nph-zms has to be left out of the ScriptAlias + + ScriptAlias /zm/cgi-bin "/usr/lib/zoneminder/cgi-bin" + + + :: + cat /etc/apache2/conf-enabled/zoneminder.conf + +**Step 13:** Start ZoneMinder Reload Apache to enable your changes and then start ZoneMinder. @@ -136,7 +152,7 @@ Reload Apache to enable your changes and then start ZoneMinder. systemctl reload apache2 systemctl start zoneminder -**Step 13:** Making sure ZoneMinder works +**Step 14:** Making sure ZoneMinder works 1. Open up a browser and go to ``http://hostname_or_ip/zm`` - should bring up ZoneMinder Console From a282b487d1783b748bff3caa7bbe9af26a614862 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 11 Jan 2019 13:55:03 -0500 Subject: [PATCH 11/12] load Help from Config as it is not longer always loaded into ram. --- web/skins/classic/views/optionhelp.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/web/skins/classic/views/optionhelp.php b/web/skins/classic/views/optionhelp.php index fe466ea62..573da2f0d 100644 --- a/web/skins/classic/views/optionhelp.php +++ b/web/skins/classic/views/optionhelp.php @@ -19,7 +19,11 @@ // $optionHelpIndex = preg_replace( '/^ZM_/', '', $_REQUEST['option'] ); -$optionHelpText = !empty($OLANG[$optionHelpIndex])?$OLANG[$optionHelpIndex]['Help']:$config[$_REQUEST['option']]['Help']; +if ( !empty($OLANG[$optionHelpIndex]) ) { + $optionHelpText = $OLANG[$optionHelpIndex]['Help']; +} else { + $optionHelpText = dbFetchOne('SELECT Help FROM Config WHERE Name=?', 'Help', array($_REQUEST['option']) ); +} $optionHelpText = validHtmlStr($optionHelpText); $optionHelpText = preg_replace( "/~~/", "
", $optionHelpText ); $optionHelpText = preg_replace( "/\[(.+)\]\((.+)\)/", "$1", $optionHelpText ); From c834fbe4624bea57c2a73a991aae757de43d2298 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sun, 13 Jan 2019 14:52:39 -0500 Subject: [PATCH 12/12] the filter action should singular filter, not filters --- web/includes/actions/{filters.php => filter.php} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename web/includes/actions/{filters.php => filter.php} (100%) diff --git a/web/includes/actions/filters.php b/web/includes/actions/filter.php similarity index 100% rename from web/includes/actions/filters.php rename to web/includes/actions/filter.php