diff --git a/.travis.yml b/.travis.yml
index 8ab86bf7d..7cfe96854 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -33,24 +33,23 @@ install:
env:
- SMPFLAGS=-j4 OS=el DIST=7
- - SMPFLAGS=-j4 OS=el DIST=8
- - SMPFLAGS=-j4 OS=fedora DIST=29 DOCKER_REPO=knnniggett/packpack
+ - SMPFLAGS=-j4 OS=el DIST=8 DOCKER_REPO=knnniggett/packpack
- SMPFLAGS=-j4 OS=fedora DIST=30
- - SMPFLAGS=-j4 OS=ubuntu DIST=trusty DOCKER_REPO=iconzm/packpack USE_SFTP=yes
- - SMPFLAGS=-j4 OS=ubuntu DIST=xenial DOCKER_REPO=iconzm/packpack USE_SFTP=yes
- - SMPFLAGS=-j4 OS=ubuntu DIST=bionic DOCKER_REPO=iconzm/packpack USE_SFTP=yes
- - SMPFLAGS=-j4 OS=ubuntu DIST=disco DOCKER_REPO=iconzm/packpack USE_SFTP=yes
- - SMPFLAGS=-j4 OS=ubuntu DIST=eoan DOCKER_REPO=iconzm/packpack USE_SFTP=yes
- - SMPFLAGS=-j4 OS=debian DIST=jessie DOCKER_REPO=iconzm/packpack USE_SFTP=yes
- - SMPFLAGS=-j4 OS=debian DIST=stretch DOCKER_REPO=iconzm/packpack USE_SFTP=yes
- - SMPFLAGS=-j4 OS=debian DIST=buster DOCKER_REPO=iconzm/packpack USE_SFTP=yes
+ - SMPFLAGS=-j4 OS=fedora DIST=31
+ - SMPFLAGS=-j4 OS=ubuntu DIST=trusty DOCKER_REPO=iconzm/packpack
+ - SMPFLAGS=-j4 OS=ubuntu DIST=xenial DOCKER_REPO=iconzm/packpack
+ - SMPFLAGS=-j4 OS=ubuntu DIST=bionic DOCKER_REPO=iconzm/packpack
+ - SMPFLAGS=-j4 OS=ubuntu DIST=disco DOCKER_REPO=iconzm/packpack
+ - SMPFLAGS=-j4 OS=ubuntu DIST=eoan DOCKER_REPO=iconzm/packpack
+ - SMPFLAGS=-j4 OS=debian DIST=jessie DOCKER_REPO=iconzm/packpack
+ - SMPFLAGS=-j4 OS=debian DIST=stretch DOCKER_REPO=iconzm/packpack
+ - SMPFLAGS=-j4 OS=debian DIST=buster DOCKER_REPO=iconzm/packpack
- SMPFLAGS=-j4 OS=ubuntu DIST=trusty ARCH=i386
- SMPFLAGS=-j4 OS=ubuntu DIST=xenial ARCH=i386
- - SMPFLAGS=-j4 OS=ubuntu DIST=bionic ARCH=i386
- SMPFLAGS=-j4 OS=ubuntu DIST=disco ARCH=i386
- SMPFLAGS=-j4 OS=debian DIST=buster ARCH=i386
- SMPFLAGS=-j4 OS=debian DIST=stretch ARCH=i386
- - SMPFLAGS=-j4 OS=raspbian DIST=stretch ARCH=armhf DOCKER_REPO=knnniggett/packpack
+ - SMPFLAGS=-j4 OS=eslint DIST=eslint
compiler:
- gcc
@@ -58,12 +57,6 @@ services:
- mysql
- docker
-jobs:
- include:
- - name: eslint
- install: npm install -g eslint@5.12.0 eslint-config-google@0.11.0 eslint-plugin-html@5.0.0 eslint-plugin-php-markup@0.2.5
- script: eslint --ext .php,.js .
-
script:
- utils/packpack/startpackpack.sh
diff --git a/distros/redhat/readme/README b/distros/redhat/readme/README
index 0b3e4bb9c..f0fff828f 100644
--- a/distros/redhat/readme/README
+++ b/distros/redhat/readme/README
@@ -22,14 +22,10 @@ What's New
switching between httpd <-> nginx requires manaully changing ownership of
all event folders and the php session folder after the change.
-4. If you have installed ZoneMinder from the FedBerry repositories, this build
- of ZoneMinder has support for Raspberry Pi hardware acceleration when using
- ffmpeg. Unforunately, there is a problem with the same hardware acceleration
- when using libvlc. Consequently, libvlc support in this build of ZoneMinder
- has been disabled until the problem is resolved. See the following bug
- report for details: https://trac.videolan.org/vlc/ticket/18594
+4. The timezone must now be set from the ZoneMinder web console. See the
+ appropriate README, mentioned in the next step, for details.
-5. Continue on to the next README that corresponds to the chosen webserver:
+6. Continue on to the next README that corresponds to your chosen webserver:
README.httpd - Follow these steps when using Apache
README.nginx - Follow these steps when using Nginx
diff --git a/distros/redhat/readme/README.httpd b/distros/redhat/readme/README.httpd
index 5301850df..1ba0ee688 100644
--- a/distros/redhat/readme/README.httpd
+++ b/distros/redhat/readme/README.httpd
@@ -36,20 +36,17 @@ NOTE: EL7 users should replace "dnf" with "yum" in the instructions below.
sudo chown root:apache *.conf
sudo chmod 640 *.conf
-4. Edit /etc/php.ini, uncomment the date.timezone line, and add your local
- timezone. PHP will complain loudly if this is not set, or if it is set
- incorrectly, and these complaints will show up in the zoneminder logging
- system as errors.
+4. Manually setting the timezone in /etc/php.ini is deprecated.
- If you are not sure of the proper timezone specification to use, look at
- http://php.net/date.timezone
+ Instead, navigate to Options -> System from the ZoneMinder web console.
+ Do this after completing step 10, below.
+
+ Note that timezone errors will appear in the ZoneMinder log until this
+ has been completed.
5. Disable SELinux
- We currently do not have the resources to create and maintain an accurate
- SELinux policy for ZoneMinder on Fedora. We will gladly accept pull
- reqeusts from anyone who wishes to do the work. In the meantime, SELinux
- will need to be disabled or put into permissive mode.
+ SELinux must be disabled or put into permissive mode. This is not optional!
To immediately disbale SELinux for the current seesion, issue the following
from the command line:
@@ -166,3 +163,11 @@ Upgrades
sudo systemctl restart httpd
sudo systemctl start zoneminder
+6. Manually setting the timezone in /etc/php.ini is deprecated.
+
+ Instead, navigate to Options -> System from the ZoneMinder web console.
+ Do this now.
+
+ Note that timezone errors will appear in the ZoneMinder log until this
+ has been completed.
+
diff --git a/distros/redhat/readme/README.nginx b/distros/redhat/readme/README.nginx
index cca4e72c2..8bc3bbdc1 100644
--- a/distros/redhat/readme/README.nginx
+++ b/distros/redhat/readme/README.nginx
@@ -34,13 +34,13 @@ New installs
sudo chown root:nginx *.conf
sudo chmod 640 *.conf
-4. Edit /etc/php.ini, uncomment the date.timezone line, and add your local
- timezone. PHP will complain loudly if this is not set, or if it is set
- incorrectly, and these complaints will show up in the zoneminder logging
- system as errors.
+4. Manually setting the timezone in /etc/php.ini is deprecated.
- If you are not sure of the proper timezone specification to use, look at
- http://php.net/date.timezone
+ Instead, navigate to Options -> System from the ZoneMinder web console.
+ Do this after completing step 10, below.
+
+ Note that timezone errors will appear in the ZoneMinder log until this
+ has been completed.
5. Disable SELinux
@@ -169,3 +169,11 @@ Upgrades
sudo systemctl restart php-fpm
sudo systemctl start zoneminder
+6. Manually setting the timezone in /etc/php.ini is deprecated.
+
+ Instead, navigate to Options -> System from the ZoneMinder web console.
+ Do this now.
+
+ Note that timezone errors will appear in the ZoneMinder log until this
+ has been completed.
+
diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec
index ffaa075a3..6715f7b26 100644
--- a/distros/redhat/zoneminder.spec
+++ b/distros/redhat/zoneminder.spec
@@ -14,11 +14,16 @@
# This will tell zoneminder's cmake process we are building against a known distro
%global zmtargetdistro %{?rhel:el%{rhel}}%{!?rhel:fc%{fedora}}
-# Fedora >= 25 needs apcu backwards compatibility module
-%if 0%{?fedora} >= 25
+# Fedora needs apcu backwards compatibility module
+%if 0%{?fedora}
%global with_apcu_bc 1
%endif
+# Newer php's keep json functions in a subpackage
+%if 0%{?fedora} || 0%{?rhel} >= 8
+%global with_php_json 1
+%endif
+
# The default for everything but el7 these days
%global _hardened_build 1
@@ -105,7 +110,7 @@ Summary: Common files for ZoneMinder, not tied to a specific web server
Requires: php-mysqli
Requires: php-common
Requires: php-gd
-%{?fedora:Requires: php-json}
+%{?with_php_json:Requires: php-json}
Requires: php-pecl-apcu
%{?with_apcu_bc:Requires: php-pecl-apcu-bc}
Requires: cambozola
diff --git a/distros/ubuntu1604/control b/distros/ubuntu1604/control
index 7e57c98a8..ef138a3ba 100644
--- a/distros/ubuntu1604/control
+++ b/distros/ubuntu1604/control
@@ -74,7 +74,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
,libfile-slurp-perl
,mysql-client | mariadb-client | virtual-mysql-client
,perl-modules
- ,php5-mysql | php-mysql, php5-gd | php-gd , php5-apcu | php-apcu , php-apc | php-apcu-bc
+ ,php5-mysql | php-mysql, php5-gd | php-gd , php5-apcu | php-apcu , php-apc | php-apcu-bc, php-json | php5-json
,policykit-1
,rsyslog | system-log-daemon
,zip
diff --git a/misc/logcheck b/misc/logcheck
index e59948e86..820108a66 100644
--- a/misc/logcheck
+++ b/misc/logcheck
@@ -28,3 +28,4 @@ zmtelemetry\[[[:digit:]]+\]: INF \[Telemetry data uploaded successfully.\]$
zmtelemetry\[[[:digit:]]+\]: INF \[Sending data to ZoneMinder Telemetry server.\]$
zmtelemetry\[[[:digit:]]+\]: INF \[Collec?ting data to send to ZoneMinder Telemetry server.\]$
web_php\[[[:digit:]]+\]: INF \[Login successful for user "[[:alnum:]]+"\]$
+zmeventnotification\[[[:digit:]]+\]: INF
diff --git a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in
index 31fafc1bc..cd93dfe15 100644
--- a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in
+++ b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in
@@ -1127,7 +1127,7 @@ our @options = (
},
{
name => 'ZM_LOG_LEVEL_FILE',
- default => '-5',
+ default => '1',
description => 'Save logging output to component files',
help => q`
ZoneMinder logging is now more integrated between
@@ -1312,7 +1312,7 @@ our @options = (
},
{
name => 'ZM_LOG_DEBUG_FILE',
- default => '@ZM_LOGDIR@/zm_debug.log+',
+ default => '',
description => 'Where extra debug is output to',
help => q`
This option allows you to specify a different target for debug
@@ -2468,7 +2468,7 @@ our @options = (
},
{
name => 'ZM_WATCH_MAX_DELAY',
- default => '5',
+ default => '45',
description => 'The maximum delay allowed since the last captured image',
help => q`
The zmwatch daemon checks the image capture performance of the
diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/Amcrest_HTTP.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/Amcrest_HTTP.pm
index e95f86cba..3fd36a0c4 100644
--- a/scripts/ZoneMinder/lib/ZoneMinder/Control/Amcrest_HTTP.pm
+++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/Amcrest_HTTP.pm
@@ -1,6 +1,6 @@
# ==========================================================================
#
-# ZoneMinder Acrest HTTP API Control Protocol Module, 20180214, Rev 3.0
+# ZoneMinder Amcrest HTTP API Control Protocol Module, 20180214, Rev 3.0
#
# Change Log
#
@@ -8,7 +8,7 @@
# - Fixes incorrect method names
# - Updates control sequences to Amcrest HTTP Protocol API v 2.12
# - Extends control features
-#
+#
# Rev 2.0:
# - Fixed installation instructions text, no changes to functionality.
#
@@ -38,6 +38,7 @@ use Time::HiRes qw( usleep );
require ZoneMinder::Base;
require ZoneMinder::Control;
+require LWP::UserAgent;
our @ISA = qw(ZoneMinder::Control);
@@ -50,130 +51,109 @@ our @ISA = qw(ZoneMinder::Control);
use ZoneMinder::Logger qw(:all);
use ZoneMinder::Config qw(:all);
-sub new
-{
- my $class = shift;
- my $id = shift;
- my $self = ZoneMinder::Control->new( $id );
- bless( $self, $class );
- srand( time() );
- return $self;
+sub new {
+ my $class = shift;
+ my $id = shift;
+ my $self = ZoneMinder::Control->new($id);
+ bless($self, $class);
+ return $self;
}
-our $AUTOLOAD;
+sub open {
+ my $self = shift;
-sub AUTOLOAD
-{
- my $self = shift;
- my $class = ref($self) || croak( "$self not object" );
- my $name = $AUTOLOAD;
- $name =~ s/.*://;
- Debug( "Received command: $name" );
- if ( exists($self->{$name}) )
- {
- return( $self->{$name} );
- }
- Fatal( "Can't access $name member of object of class $class" );
-}
+ $self->loadMonitor();
+ my $username;
+ my $password;
+ my $realm = 'Login to ' . $self->{Monitor}->{ControlDevice};
-sub open
-{
- my $self = shift;
+ if ( $self->{Monitor}->{ControlAddress} =~ /(.*):(.*)@(.*)/ ) {
+ $username = $1;
+ $password = $2;
+ $$self{address} = $3;
+ }
- $self->loadMonitor();
+ $self->{ua} = LWP::UserAgent->new;
+ $self->{ua}->credentials($$self{address}, $realm, $username, $password);
+ $self->{ua}->agent('ZoneMinder Control Agent/'.ZoneMinder::Base::ZM_VERSION);
+
+ # Detect REALM
+ my $res = $self->{ua}->get($$self{address}.'/cgi-bin/ptz.cgi');
+
+ if ( $res->is_success ) {
$self->{state} = 'open';
-}
+ return;
+ }
-sub initUA
-{
- my $self = shift;
- my $user = undef;
- my $password = undef;
- my $address = undef;
+ if ( $res->status_line() eq '401 Unauthorized' ) {
- if ( $self->{Monitor}->{ControlAddress} =~ /(.*):(.*)@(.*)/ )
- {
- $user = $1;
- $password = $2;
- $address = $3;
+ my $headers = $res->headers();
+ foreach my $k ( keys %$headers ) {
+ Debug("Initial Header $k => $$headers{$k}");
}
- use LWP::UserAgent;
- $self->{ua} = LWP::UserAgent->new;
- $self->{ua}->credentials("$address", "Login to " . $self->{Monitor}->{ControlDevice}, "$user", "$password");
- $self->{ua}->agent( "ZoneMinder Control Agent/".ZoneMinder::Base::ZM_VERSION );
+ if ( $$headers{'www-authenticate'} ) {
+ my ( $auth, $tokens ) = $$headers{'www-authenticate'} =~ /^(\w+)\s+(.*)$/;
+ if ( $tokens =~ /\w+="([^"]+)"/i ) {
+ if ( $realm ne $1 ) {
+ $realm = $1;
+ Debug("Changing REALM to $realm");
+ $self->{ua}->credentials($$self{address}, $realm, $username, $password);
+ $res = $self->{ua}->get($$self{address}.'/cgi-bin/ptz.cgi');
+ if ( $res->is_success() ) {
+ $self->{state} = 'open';
+ return;
+ }
+ Error('Authentication still failed after updating REALM' . $res->status_line);
+ $headers = $res->headers();
+ foreach my $k ( keys %$headers ) {
+ Debug("Initial Header $k => $$headers{$k}");
+ } # end foreach
+ } else {
+ Error('Authentication failed, not a REALM problem');
+ }
+ } else {
+ Error('Failed to match realm in tokens');
+ } # end if
+ } else {
+ Debug('No headers line');
+ } # end if headers
+ } # end if $res->status_line() eq '401 Unauthorized'
+
+ $self->{state} = 'open';
}
-sub destroyUA
-{
- my $self = shift;
-
- $self->{ua} = undef;
+sub close {
+ my $self = shift;
+ $self->{state} = 'closed';
}
-sub close
-{
- my $self = shift;
- $self->{state} = 'closed';
+sub sendCmd {
+ my $self = shift;
+ my $cmd = shift;
+ my $result = undef;
+
+ $self->printMsg($cmd, 'Tx');
+
+ my $req = HTTP::Request->new( GET=>"http://$$self{address}/$cmd" );
+ my $res = $self->{ua}->request($req);
+
+ if ( $res->is_success ) {
+ $result = !undef;
+ # Command to camera appears successful, write Info item to log
+ Info('Camera control: \''.$res->status_line().'\' for URL '.$self->{Monitor}->{ControlAddress}.'/'.$cmd);
+ # TODO: Add code to retrieve $res->message_decode or some such. Then we could do things like check the camera status.
+ } else {
+ Error('Camera control command FAILED: \''.$res->status_line().'\' for URL '.$self->{Monitor}->{ControlAddress}.'/'.$cmd);
+ }
+
+ return $result;
}
-sub printMsg
-{
- my $self = shift;
- my $msg = shift;
- my $msg_len = length($msg);
-
- Debug( $msg."[".$msg_len."]" );
-}
-
-sub sendCmd
-{
- my $self = shift;
- my $cmd = shift;
- my $result = undef;
-
- destroyUA($self);
- initUA($self);
-
- my $user = undef;
- my $password = undef;
- my $address = undef;
-
- if ( $self->{Monitor}->{ControlAddress} =~ /(.*):(.*)@(.*)/ )
- {
- $user = $1;
- $password = $2;
- $address = $3;
- }
-
- printMsg( $cmd, "Tx" );
-
- my $req = HTTP::Request->new( GET=>"http://$address/$cmd" );
- my $res = $self->{ua}->request($req);
-
- if ( $res->is_success )
- {
- $result = !undef;
- # Command to camera appears successful, write Info item to log
- Info( "Camera control: '".$res->status_line()."' for URL ".$self->{Monitor}->{ControlAddress}."/$cmd" );
- # TODO: Add code to retrieve $res->message_decode or some such. Then we could do things like check the camera status.
- }
- else
- {
- Error( "Camera control command FAILED: '".$res->status_line()."' for URL ".$self->{Monitor}->{ControlAddress}."/$cmd" );
- }
-
- return( $result );
-}
-
-sub reset
-{
- my $self = shift;
- # This reboots the camera effectively resetting it
- Debug( "Camera Reset" );
- $self->sendCmd( 'cgi-bin/magicBox.cgi?action=reboot' );
- ##FIXME: Exit is a bad idea as it appears to cause zmc to run away.
- #Exit (0);
+sub reset {
+ my $self = shift;
+ # This reboots the camera effectively resetting it
+ $self->sendCmd('cgi-bin/magicBox.cgi?action=reboot');
}
# NOTE: I'm putting this in, but absolute camera movement does not seem to be well supported in the classic skin ATM.
@@ -184,163 +164,148 @@ sub reset
sub moveAbs ## Up, Down, Left, Right, etc. ??? Doesn't make sense here...
{
- my $self = shift;
- my $pan_degrees = shift || 0;
- my $tilt_degrees = shift || 0;
- my $speed = shift || 1;
- Debug( "Move ABS" );
- $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=PositionABS&channel=0&arg1='.$pan_degrees.'&arg2='.$tilt_degrees.'&arg3=0&arg4='.$speed );
+ my $self = shift;
+ my $pan_degrees = shift || 0;
+ my $tilt_degrees = shift || 0;
+ my $speed = shift || 1;
+ Debug('Move ABS');
+ $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=PositionABS&channel=0&arg1='.$pan_degrees.'&arg2='.$tilt_degrees.'&arg3=0&arg4='.$speed);
}
-sub moveConUp
-{
- my $self = shift;
- Debug( "Move Up" );
- $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=Up&channel=0&arg1=0&arg2=1&arg3=0' );
- usleep (500); ##XXX Should this be passed in as a "speed" parameter?
- $self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=Up&channel=0&arg1=0&arg2=1&arg3=0' );
+sub moveConUp {
+ my $self = shift;
+ Debug('Move Up');
+ $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=Up&channel=0&arg1=0&arg2=1&arg3=0');
+ usleep(500); ##XXX Should this be passed in as a "speed" parameter?
+ $self->sendCmd('cgi-bin/ptz.cgi?action=stop&code=Up&channel=0&arg1=0&arg2=1&arg3=0');
}
-sub moveConDown
-{
- my $self = shift;
- Debug( "Move Down" );
- $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=Down&channel=0&arg1=0&arg2=1&arg3=0' );
- usleep (500);
- $self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=Down&channel=0&arg1=0&arg2=1&arg3=0' );
+sub moveConDown {
+ my $self = shift;
+ Debug('Move Down');
+ $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=Down&channel=0&arg1=0&arg2=1&arg3=0');
+ usleep(500);
+ $self->sendCmd('cgi-bin/ptz.cgi?action=stop&code=Down&channel=0&arg1=0&arg2=1&arg3=0');
}
-sub moveConLeft
-{
- my $self = shift;
- Debug( "Move Left" );
- $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=Left&channel=0&arg1=0&arg2=1&arg3=0' );
- usleep (500);
- $self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=Left&channel=0&arg1=0&arg2=1&arg3=0' );
+sub moveConLeft {
+ my $self = shift;
+ Debug('Move Left');
+ $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=Left&channel=0&arg1=0&arg2=1&arg3=0');
+ usleep(500);
+ $self->sendCmd('cgi-bin/ptz.cgi?action=stop&code=Left&channel=0&arg1=0&arg2=1&arg3=0');
}
-sub moveConRight
-{
- my $self = shift;
- Debug( "Move Right" );
-# $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=PositionABS&channel=0&arg1=270&arg2=5&arg3=0' );
- $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=Right&channel=0&arg1=0&arg2=1&arg3=0' );
- usleep (500);
- Debug( "Move Right Stop" );
- $self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=Right&channel=0&arg1=0&arg2=1&arg3=0' );
+sub moveConRight {
+ my $self = shift;
+ Debug('Move Right');
+ # $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=PositionABS&channel=0&arg1=270&arg2=5&arg3=0' );
+ $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=Right&channel=0&arg1=0&arg2=1&arg3=0');
+ usleep(500);
+ Debug('Move Right Stop');
+ $self->sendCmd('cgi-bin/ptz.cgi?action=stop&code=Right&channel=0&arg1=0&arg2=1&arg3=0');
}
-sub moveConUpRight
-{
- my $self = shift;
- Debug( "Move Diagonally Up Right" );
- $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=RightUp&channel=0&arg1=1&arg2=1&arg3=0' );
- usleep (500);
- $self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=RightUp&channel=0&arg1=0&arg2=1&arg3=0' );
+sub moveConUpRight {
+ my $self = shift;
+ Debug('Move Diagonally Up Right');
+ $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=RightUp&channel=0&arg1=1&arg2=1&arg3=0');
+ usleep(500);
+ $self->sendCmd('cgi-bin/ptz.cgi?action=stop&code=RightUp&channel=0&arg1=0&arg2=1&arg3=0');
}
-sub moveConDownRight
-{
- my $self = shift;
- Debug( "Move Diagonally Down Right" );
- $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=RightDown&channel=0&arg1=1&arg2=1&arg3=0' );
- usleep (500);
- $self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=RightDown&channel=0&arg1=0&arg2=1&arg3=0' );
+sub moveConDownRight {
+ my $self = shift;
+ Debug('Move Diagonally Down Right');
+ $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=RightDown&channel=0&arg1=1&arg2=1&arg3=0');
+ usleep(500);
+ $self->sendCmd('cgi-bin/ptz.cgi?action=stop&code=RightDown&channel=0&arg1=0&arg2=1&arg3=0');
}
-sub moveConUpLeft
-{
- my $self = shift;
- Debug( "Move Diagonally Up Left" );
- $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=LeftUp&channel=0&arg1=1&arg2=1&arg3=0' );
- usleep (500);
- $self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=LeftUp&channel=0&arg1=0&arg2=1&arg3=0' );
+sub moveConUpLeft {
+ my $self = shift;
+ Debug('Move Diagonally Up Left');
+ $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=LeftUp&channel=0&arg1=1&arg2=1&arg3=0');
+ usleep(500);
+ $self->sendCmd('cgi-bin/ptz.cgi?action=stop&code=LeftUp&channel=0&arg1=0&arg2=1&arg3=0');
}
-sub moveConDownLeft
-{
- my $self = shift;
- Debug( "Move Diagonally Down Left" );
- $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=LeftDown&channel=0&arg1=1&arg2=1&arg3=0' );
- usleep (500);
- $self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=LeftDown&channel=0&arg1=0&arg2=1&arg3=0' );
+sub moveConDownLeft {
+ my $self = shift;
+ Debug('Move Diagonally Down Left');
+ $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=LeftDown&channel=0&arg1=1&arg2=1&arg3=0');
+ usleep (500);
+ $self->sendCmd('cgi-bin/ptz.cgi?action=stop&code=LeftDown&channel=0&arg1=0&arg2=1&arg3=0');
}
# Stop is not "correctly" implemented as control_functions.php translates this to "Center"
# So we'll just send the camera to 0* Horz, 0* Vert, zoom out; Also, Amcrest does not seem to
# support a generic stop-all-current-action command.
-sub moveStop
-{
- my $self = shift;
- Debug( "Move Stop/Center" );
- $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=PositionABS&channel=0&arg1=0&arg2=0&arg3=0&arg4=1' );
+sub moveStop {
+ my $self = shift;
+ Debug('Move Stop/Center');
+ $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=PositionABS&channel=0&arg1=0&arg2=0&arg3=0&arg4=1');
}
# Move Camera to Home Position
# The current API does not support a Home per se, so we'll just send the camera to preset #1
# NOTE: It goes without saying that the user must have set up preset #1 for this to work.
-sub presetHome
-{
- my $self = shift;
- Debug( "Home Preset" );
- $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&channel=0&code=GotoPreset&&arg1=0&arg2=1&arg3=0&arg4=0' );
+sub presetHome {
+ my $self = shift;
+ Debug('Home Preset');
+ $self->sendCmd('cgi-bin/ptz.cgi?action=start&channel=0&code=GotoPreset&&arg1=0&arg2=1&arg3=0&arg4=0');
}
-sub presetGoto
-{
- my $self = shift;
- my $params = shift;
- my $preset = $self->getParam( $params, 'preset' );
- Debug( "Go To Preset $preset" );
- $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&channel=0&code=GotoPreset&&arg1=0&arg2='.$preset.'&arg3=0&arg4=0' );
+sub presetGoto {
+ my $self = shift;
+ my $params = shift;
+ my $preset = $self->getParam($params, 'preset');
+ Debug("Go To Preset $preset");
+ $self->sendCmd('cgi-bin/ptz.cgi?action=start&channel=0&code=GotoPreset&&arg1=0&arg2='.$preset.'&arg3=0&arg4=0');
}
-sub presetSet
-{
- my $self = shift;
- my $params = shift;
- my $preset = $self->getParam( $params, 'preset' );
- Debug( "Set Preset" );
- $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&channel=0&code=SetPreset&arg1=0&arg2='.$preset.'&arg3=0&arg4=0' );
+sub presetSet {
+ my $self = shift;
+ my $params = shift;
+ my $preset = $self->getParam($params, 'preset');
+ Debug('Set Preset');
+ $self->sendCmd('cgi-bin/ptz.cgi?action=start&channel=0&code=SetPreset&arg1=0&arg2='.$preset.'&arg3=0&arg4=0');
}
# NOTE: This does not appear to be implemented in the classic skin. But we'll leave it here for later.
-sub moveMap
-{
- my $self = shift;
- my $params = shift;
+sub moveMap {
+ my $self = shift;
+ my $params = shift;
- my $xcoord = $self->getParam( $params, 'xcoord', $self->{Monitor}{Width}/2 );
- my $ycoord = $self->getParam( $params, 'ycoord', $self->{Monitor}{Height}/2 );
- # if the camera is mounted upside down, you may have to inverse these coordinates
- # just use 360 minus pan instead of pan, 90 minus tilt instead of tilt
- # Convert xcoord into pan position 0 to 359
- my $pan = int(360 * $xcoord / $self->{Monitor}{Width});
- # Convert ycoord into tilt position 0 to 89
- my $tilt = 90 - int(90 * $ycoord / $self->{Monitor}{Height});
- # Now get the following url:
- $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=PositionABS&channel=0&arg1='.$pan.'&arg2='.$tilt.'&arg3=1&arg4=1');
+ my $xcoord = $self->getParam( $params, 'xcoord', $self->{Monitor}{Width}/2 );
+ my $ycoord = $self->getParam( $params, 'ycoord', $self->{Monitor}{Height}/2 );
+ # if the camera is mounted upside down, you may have to inverse these coordinates
+ # just use 360 minus pan instead of pan, 90 minus tilt instead of tilt
+ # Convert xcoord into pan position 0 to 359
+ my $pan = int(360 * $xcoord / $self->{Monitor}{Width});
+ # Convert ycoord into tilt position 0 to 89
+ my $tilt = 90 - int(90 * $ycoord / $self->{Monitor}{Height});
+ # Now get the following url:
+ $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=PositionABS&channel=0&arg1='.$pan.'&arg2='.$tilt.'&arg3=1&arg4=1');
}
-sub zoomConTele
-{
- my $self = shift;
- Debug( "Zoom continuous tele" );
- $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&channel=0&code=ZoomTele&arg1=0&arg2=0&arg3=0&arg4=0' );
- usleep (100000);
- $self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&channel=0&code=ZoomTele&arg1=0&arg2=0&arg3=0&arg4=0' );
+sub zoomConTele {
+ my $self = shift;
+ Debug('Zoom continuous tele');
+ $self->sendCmd('cgi-bin/ptz.cgi?action=start&channel=0&code=ZoomTele&arg1=0&arg2=0&arg3=0&arg4=0');
+ usleep(100000);
+ $self->sendCmd('cgi-bin/ptz.cgi?action=stop&channel=0&code=ZoomTele&arg1=0&arg2=0&arg3=0&arg4=0');
}
-sub zoomConWide
-{
- my $self = shift;
- Debug( "Zoom continuous wide" );
- $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&channel=0&code=ZoomWide&arg1=0&arg2=0&arg3=0&arg4=0' );
- usleep (100000);
- $self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&channel=0&code=ZoomWide&arg1=0&arg2=0&arg3=0&arg4=0' );
+sub zoomConWide {
+ my $self = shift;
+ Debug('Zoom continuous wide');
+ $self->sendCmd('cgi-bin/ptz.cgi?action=start&channel=0&code=ZoomWide&arg1=0&arg2=0&arg3=0&arg4=0');
+ usleep (100000);
+ $self->sendCmd('cgi-bin/ptz.cgi?action=stop&channel=0&code=ZoomWide&arg1=0&arg2=0&arg3=0&arg4=0');
}
1;
@@ -355,7 +320,7 @@ ZoneMinder::Control::Amcrest_HTTP - Amcrest camera control
=head1 DESCRIPTION
-This module contains the implementation of the Amcrest Camera
+This module contains the implementation of the Amcrest Camera
controllable SDK API.
NOTE: This module implements interaction with the camera in clear text.
diff --git a/scripts/zmtelemetry.pl.in b/scripts/zmtelemetry.pl.in
index efd5e735e..9b5e7c89d 100644
--- a/scripts/zmtelemetry.pl.in
+++ b/scripts/zmtelemetry.pl.in
@@ -23,6 +23,7 @@
use strict;
use bytes;
+use utf8;
@EXTRA_PERL_LIB@
use ZoneMinder;
@@ -34,6 +35,7 @@ use Sys::MemInfo qw(totalmem);
use Sys::CPU qw(cpu_count);
use POSIX qw(strftime uname);
use JSON::MaybeXS;
+use Encode;
$ENV{PATH} = '/bin:/usr/bin:/usr/local/bin';
$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL};
@@ -166,7 +168,7 @@ sub sendData {
$req->header('content-length' => length($msg));
$req->header('connection' => 'Close');
- $req->content($msg);
+ $req->content(encode('UTF-8',$msg));
my $resp = $ua->request($req);
my $resp_msg = $resp->decoded_content;
diff --git a/src/zm_eventstream.cpp b/src/zm_eventstream.cpp
index 2ca12972d..e2f1862ab 100644
--- a/src/zm_eventstream.cpp
+++ b/src/zm_eventstream.cpp
@@ -100,6 +100,7 @@ bool EventStream::loadInitialEventData(uint64_t init_event_id, unsigned int init
if ( init_frame_id >= event_data->frame_count ) {
Error("Invalid frame id specified. %d > %d", init_frame_id, event_data->frame_count);
curr_stream_time = event_data->start_time;
+ curr_frame_id = 1;
} else {
curr_stream_time = event_data->frames[init_frame_id-1].timestamp;
curr_frame_id = init_frame_id;
diff --git a/src/zm_ffmpeg.cpp b/src/zm_ffmpeg.cpp
index 6b6036db5..f0b3dc76e 100644
--- a/src/zm_ffmpeg.cpp
+++ b/src/zm_ffmpeg.cpp
@@ -81,7 +81,7 @@ void FFMPEGInit() {
av_log_set_callback(log_libav_callback);
Info("Enabling ffmpeg logs, as LOG_DEBUG+LOG_FFMPEG are enabled in options");
} else {
- Info("Not enabling ffmpeg logs, as LOG_FFMPEG and/or LOG_DEBUG is disabled in options, or this monitor not part of your debug targets");
+ Info("Not enabling ffmpeg logs, as LOG_FFMPEG and/or LOG_DEBUG is disabled in options, or this monitor is not part of your debug targets");
av_log_set_level(AV_LOG_QUIET);
}
#if !LIBAVFORMAT_VERSION_CHECK(58, 9, 0, 64, 0)
@@ -291,17 +291,18 @@ static void zm_log_fps(double d, const char *postfix) {
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
void zm_dump_codecpar ( const AVCodecParameters *par ) {
- Debug(1, "Dumping codecpar codec_type(%d) codec_id(%d %s) codec_tag(%d) width(%d) height(%d) bit_rate(%d) format(%d = %s)",
- par->codec_type,
- par->codec_id,
- avcodec_get_name(par->codec_id),
- par->codec_tag,
- par->width,
- par->height,
- par->bit_rate,
- par->format,
- ((AVPixelFormat)par->format == AV_PIX_FMT_NONE ? "none" : av_get_pix_fmt_name((AVPixelFormat)par->format))
-);
+ Debug(1, "Dumping codecpar codec_type(%d %s) codec_id(%d %s) codec_tag(%" PRIu32 ") width(%d) height(%d) bit_rate(%" PRIu64 ") format(%d %s)",
+ par->codec_type,
+ av_get_media_type_string(par->codec_type),
+ par->codec_id,
+ avcodec_get_name(par->codec_id),
+ par->codec_tag,
+ par->width,
+ par->height,
+ par->bit_rate,
+ par->format,
+ (((AVPixelFormat)par->format == AV_PIX_FMT_NONE) ? "none" : av_get_pix_fmt_name((AVPixelFormat)par->format))
+ );
}
#endif
diff --git a/src/zm_ffmpeg_camera.cpp b/src/zm_ffmpeg_camera.cpp
index ef4dfc057..3cc634e7d 100644
--- a/src/zm_ffmpeg_camera.cpp
+++ b/src/zm_ffmpeg_camera.cpp
@@ -517,19 +517,19 @@ int FfmpegCamera::OpenFfmpeg() {
Debug(1, "Selected hw_pix_fmt %d %s",
hw_pix_fmt, av_get_pix_fmt_name(hw_pix_fmt));
- mVideoCodecContext->get_format = get_hw_format;
-
ret = av_hwdevice_ctx_create(&hw_device_ctx, type,
(hwaccel_device != "" ? hwaccel_device.c_str(): NULL), NULL, 0);
if ( ret < 0 ) {
- Error("Failed to create hwaccel device.");
- return -1;
+ Error("Failed to create hwaccel device. %s",av_make_error_string(ret).c_str());
+ hw_pix_fmt = AV_PIX_FMT_NONE;
+ } else {
+ Debug(1, "Created hwdevice for %s", hwaccel_device.c_str());
+ mVideoCodecContext->get_format = get_hw_format;
+ mVideoCodecContext->hw_device_ctx = av_buffer_ref(hw_device_ctx);
+ hwFrame = zm_av_frame_alloc();
}
- Debug(1, "Created hwdevice for %s", hwaccel_device.c_str());
- mVideoCodecContext->hw_device_ctx = av_buffer_ref(hw_device_ctx);
- hwFrame = zm_av_frame_alloc();
} else {
- Debug(1, "Failed to setup hwaccel.");
+ Debug(1, "Failed to find suitable hw_pix_fmt.");
}
#else
Debug(1, "AVCodec not new enough for hwaccel");
@@ -537,7 +537,7 @@ int FfmpegCamera::OpenFfmpeg() {
#else
Warning("HWAccel support not compiled in.");
#endif
- } // end if hwacel_name
+ } // end if hwaccel_name
// Open the codec
#if !LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 8, 0)
@@ -1087,6 +1087,7 @@ int FfmpegCamera::transfer_to_image(
return -1;
}
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
+ // From what I've read, we should align the linesizes to 32bit so that ffmpeg can use SIMD instructions too.
int size = av_image_fill_arrays(
output_frame->data, output_frame->linesize,
directbuffer, imagePixFormat, width, height, 32);
@@ -1128,8 +1129,8 @@ int FfmpegCamera::transfer_to_image(
mConvertContext, input_frame->data, input_frame->linesize,
0, mVideoCodecContext->height,
output_frame->data, output_frame->linesize);
- if ( ret <= 0 ) {
- Error("Unable to convert format %u %s linesize %d height %d to format %u %s linesize %d at frame %d codec %u %s : code: %d",
+ if ( ret < 0 ) {
+ Error("Unable to convert format %u %s linesize %d height %d to format %u %s linesize %d at frame %d codec %u %s lines %d: code: %d",
input_frame->format, av_get_pix_fmt_name((AVPixelFormat)input_frame->format),
input_frame->linesize, mVideoCodecContext->height,
imagePixFormat,
@@ -1137,6 +1138,7 @@ int FfmpegCamera::transfer_to_image(
output_frame->linesize,
frameCount,
mVideoCodecContext->pix_fmt, av_get_pix_fmt_name(mVideoCodecContext->pix_fmt),
+ mVideoCodecContext->height,
ret
);
return -1;
diff --git a/src/zm_ffmpeg_input.cpp b/src/zm_ffmpeg_input.cpp
index 352de347c..45128645c 100644
--- a/src/zm_ffmpeg_input.cpp
+++ b/src/zm_ffmpeg_input.cpp
@@ -145,7 +145,11 @@ AVFrame *FFmpeg_Input::get_frame(int stream_id) {
av_frame_free(&frame);
continue;
} else {
- zm_dump_frame(frame, "resulting frame");
+ if ( is_video_stream(input_format_context->streams[packet.stream_index]) ) {
+ zm_dump_video_frame(frame, "resulting video frame");
+ } else {
+ zm_dump_frame(frame, "resulting frame");
+ }
}
frameComplete = 1;
diff --git a/src/zm_monitorstream.cpp b/src/zm_monitorstream.cpp
index 0c71b5c61..49d617f7d 100644
--- a/src/zm_monitorstream.cpp
+++ b/src/zm_monitorstream.cpp
@@ -1,21 +1,21 @@
//
// ZoneMinder Monitor Class Implementation, $Date$, $Revision$
// Copyright (C) 2001-2008 Philip Coombes
-//
+//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
-//
+//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
-//
+//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-//
+//
#include "zm.h"
#include "zm_db.h"
@@ -73,7 +73,7 @@ bool MonitorStream::checkSwapPath(const char *path, bool create_path) {
return false;
}
return true;
-} // end bool MonitorStream::checkSwapPath( const char *path, bool create_path )
+} // end bool MonitorStream::checkSwapPath( const char *path, bool create_path )
void MonitorStream::processCommand(const CmdMsg *msg) {
Debug( 2, "Got message, type %d, msg %d", msg->msg_type, msg->msg_data[0] );
@@ -265,7 +265,7 @@ void MonitorStream::processCommand(const CmdMsg *msg) {
//status_data.enabled = monitor->shared_data->active;
status_data.enabled = monitor->trigger_data->trigger_state!=Monitor::TRIGGER_OFF;
status_data.forced = monitor->trigger_data->trigger_state==Monitor::TRIGGER_ON;
- Debug(2, "Buffer Level:%d, Delayed:%d, Paused:%d, Rate:%d, delay:%.3f, Zoom:%d, Enabled:%d Forced:%d",
+ Debug(2, "Buffer Level:%d, Delayed:%d, Paused:%d, Rate:%d, delay:%.3f, Zoom:%d, Enabled:%d Forced:%d",
status_data.buffer_level,
status_data.delayed,
status_data.paused,
@@ -327,7 +327,7 @@ bool MonitorStream::sendFrame(const char *filepath, struct timeval *timestamp) {
// Calculate how long it takes to actually send the frame
struct timeval frameStartTime;
gettimeofday(&frameStartTime, NULL);
-
+
fputs("--ZoneMinderFrame\r\nContent-Type: image/jpeg\r\n", stdout);
fprintf(stdout, "Content-Length: %d\r\n\r\n", img_buffer_size);
if ( fwrite(img_buffer, img_buffer_size, 1, stdout) != 1 ) {
@@ -383,7 +383,7 @@ bool MonitorStream::sendFrame(Image *image, struct timeval *timestamp) {
// Calculate how long it takes to actually send the frame
struct timeval frameStartTime;
gettimeofday(&frameStartTime, NULL);
-
+
fputs("--ZoneMinderFrame\r\n", stdout);
switch( type ) {
case STREAM_JPEG :
@@ -412,7 +412,7 @@ bool MonitorStream::sendFrame(Image *image, struct timeval *timestamp) {
}
fprintf(stdout, "Content-Length: %d\r\n\r\n", img_buffer_size);
if ( fwrite(img_buffer, img_buffer_size, 1, stdout) != 1 ) {
- if ( !zm_terminate ) {
+ if ( !zm_terminate ) {
// If the pipe was closed, we will get signalled SIGPIPE to exit, which will set zm_terminate
Warning("Unable to send stream frame: %s", strerror(errno));
}
@@ -430,7 +430,7 @@ bool MonitorStream::sendFrame(Image *image, struct timeval *timestamp) {
Warning("Frame send time %d msec too slow, throttling maxfps to %.2f",
frameSendTime, maxfps);
}
- }
+ } // Not mpeg
last_frame_sent = TV_2_FLOAT(now);
return true;
} // end bool MonitorStream::sendFrame( Image *image, struct timeval *timestamp )
@@ -455,7 +455,7 @@ void MonitorStream::runStream() {
fputs("Content-Type: multipart/x-mixed-replace;boundary=ZoneMinderFrame\r\n\r\n", stdout);
// point to end which is theoretically not a valid value because all indexes are % image_buffer_count
- unsigned int last_read_index = monitor->image_buffer_count;
+ unsigned int last_read_index = monitor->image_buffer_count;
time_t stream_start_time;
time(&stream_start_time);
@@ -474,22 +474,21 @@ void MonitorStream::runStream() {
Image *paused_image = NULL;
struct timeval paused_timestamp;
- // 15 is the max length for the swap path suffix, /zmswap-whatever, assuming max 6 digits for monitor id
- const int max_swap_len_suffix = 15;
-
- int swap_path_length = staticConfig.PATH_SWAP.length() + 1; // +1 for NULL terminator
- int subfolder1_length = snprintf(NULL, 0, "/zmswap-m%d", monitor->Id()) + 1;
- int subfolder2_length = snprintf(NULL, 0, "/zmswap-q%06d", connkey) + 1;
- int total_swap_path_length = swap_path_length + subfolder1_length + subfolder2_length;
-
if ( connkey && ( playback_buffer > 0 ) ) {
+ // 15 is the max length for the swap path suffix, /zmswap-whatever, assuming max 6 digits for monitor id
+ const int max_swap_len_suffix = 15;
+
+ int swap_path_length = staticConfig.PATH_SWAP.length() + 1; // +1 for NULL terminator
+ int subfolder1_length = snprintf(NULL, 0, "/zmswap-m%d", monitor->Id()) + 1;
+ int subfolder2_length = snprintf(NULL, 0, "/zmswap-q%06d", connkey) + 1;
+ int total_swap_path_length = swap_path_length + subfolder1_length + subfolder2_length;
if ( total_swap_path_length + max_swap_len_suffix > PATH_MAX ) {
Error("Swap Path is too long. %d > %d ", total_swap_path_length+max_swap_len_suffix, PATH_MAX);
} else {
swap_path = staticConfig.PATH_SWAP;
- Debug( 3, "Checking swap path folder: %s", swap_path.c_str() );
+ Debug(3, "Checking swap path folder: %s", swap_path.c_str());
if ( checkSwapPath(swap_path.c_str(), true) ) {
swap_path += stringtf("/zmswap-m%d", monitor->Id());
@@ -509,8 +508,8 @@ void MonitorStream::runStream() {
} else {
Debug(2, "Assigning temporary buffer");
temp_image_buffer = new SwapImage[temp_image_buffer_count];
- memset( temp_image_buffer, 0, sizeof(*temp_image_buffer)*temp_image_buffer_count );
- Debug( 2, "Assigned temporary buffer" );
+ memset(temp_image_buffer, 0, sizeof(*temp_image_buffer)*temp_image_buffer_count);
+ Debug(2, "Assigned temporary buffer");
}
}
} else {
@@ -525,7 +524,7 @@ void MonitorStream::runStream() {
Debug(1, "Using %.3f for fps instead of current fps %.3f", capture_max_fps, capture_fps);
capture_fps = capture_max_fps;
}
-
+
if ( capture_fps < 1 ) {
max_secs_since_last_sent_frame = 10/capture_fps;
Debug(1, "Adjusting max_secs_since_last_sent_frame to %.2f from current fps %.2f",
@@ -562,7 +561,7 @@ void MonitorStream::runStream() {
touch(sock_path_lock);
last_comm_update = now;
}
- } // end if connkey
+ } // end if connkey
if ( paused ) {
if ( !was_paused ) {
@@ -589,7 +588,7 @@ void MonitorStream::runStream() {
} else {
if ( !paused ) {
int temp_index = MOD_ADD(temp_read_index, 0, temp_image_buffer_count);
- //Debug( 3, "tri: %d, ti: %d", temp_read_index, temp_index );
+ // Debug( 3, "tri: %d, ti: %d", temp_read_index, temp_index );
SwapImage *swap_image = &temp_image_buffer[temp_index];
if ( !swap_image->valid ) {
@@ -597,51 +596,61 @@ void MonitorStream::runStream() {
delayed = true;
temp_read_index = MOD_ADD(temp_read_index, (replay_rate>=0?-1:1), temp_image_buffer_count);
} else {
- //Debug( 3, "siT: %f, lfT: %f", TV_2_FLOAT( swap_image->timestamp ), TV_2_FLOAT( last_frame_timestamp ) );
- double expected_delta_time = ((TV_2_FLOAT( swap_image->timestamp ) - TV_2_FLOAT( last_frame_timestamp )) * ZM_RATE_BASE)/replay_rate;
- double actual_delta_time = TV_2_FLOAT( now ) - last_frame_sent;
+ // Debug( 3, "siT: %f, lfT: %f", TV_2_FLOAT( swap_image->timestamp ), TV_2_FLOAT( last_frame_timestamp ) );
+ double expected_delta_time = ((TV_2_FLOAT(swap_image->timestamp) - TV_2_FLOAT(last_frame_timestamp)) * ZM_RATE_BASE)/replay_rate;
+ double actual_delta_time = TV_2_FLOAT(now) - last_frame_sent;
- //Debug( 3, "eDT: %.3lf, aDT: %.3f, lFS:%.3f, NOW:%.3f", expected_delta_time, actual_delta_time, last_frame_sent, TV_2_FLOAT( now ) );
+ // Debug( 3, "eDT: %.3lf, aDT: %.3f, lFS:%.3f, NOW:%.3f", expected_delta_time, actual_delta_time, last_frame_sent, TV_2_FLOAT( now ) );
// If the next frame is due
if ( actual_delta_time > expected_delta_time ) {
- //Debug( 2, "eDT: %.3lf, aDT: %.3f", expected_delta_time, actual_delta_time );
+ // Debug( 2, "eDT: %.3lf, aDT: %.3f", expected_delta_time, actual_delta_time );
if ( temp_index%frame_mod == 0 ) {
- Debug( 2, "Sending delayed frame %d", temp_index );
+ Debug(2, "Sending delayed frame %d", temp_index);
// Send the next frame
- if ( ! sendFrame(temp_image_buffer[temp_index].file_name, &temp_image_buffer[temp_index].timestamp) )
+ if ( ! sendFrame(temp_image_buffer[temp_index].file_name, &temp_image_buffer[temp_index].timestamp) ) {
zm_terminate = true;
+ }
memcpy(&last_frame_timestamp, &(swap_image->timestamp), sizeof(last_frame_timestamp));
- //frame_sent = true;
+ // frame_sent = true;
}
temp_read_index = MOD_ADD(temp_read_index, (replay_rate>0?1:-1), temp_image_buffer_count);
}
}
} else if ( step != 0 ) {
- temp_read_index = MOD_ADD( temp_read_index, (step>0?1:-1), temp_image_buffer_count );
+ temp_read_index = MOD_ADD(temp_read_index, (step>0?1:-1), temp_image_buffer_count);
SwapImage *swap_image = &temp_image_buffer[temp_read_index];
// Send the next frame
- if ( !sendFrame( temp_image_buffer[temp_read_index].file_name, &temp_image_buffer[temp_read_index].timestamp ) )
+ if ( !sendFrame(
+ temp_image_buffer[temp_read_index].file_name,
+ &temp_image_buffer[temp_read_index].timestamp
+ ) ) {
zm_terminate = true;
- memcpy( &last_frame_timestamp, &(swap_image->timestamp), sizeof(last_frame_timestamp) );
- //frame_sent = true;
+ }
+ memcpy(
+ &last_frame_timestamp,
+ &(swap_image->timestamp),
+ sizeof(last_frame_timestamp)
+ );
+ // frame_sent = true;
step = 0;
} else {
//paused?
int temp_index = MOD_ADD(temp_read_index, 0, temp_image_buffer_count);
- double actual_delta_time = TV_2_FLOAT( now ) - last_frame_sent;
- if ( got_command || actual_delta_time > 5 ) {
+ double actual_delta_time = TV_2_FLOAT(now) - last_frame_sent;
+ if ( got_command || (actual_delta_time > 5) ) {
// Send keepalive
Debug(2, "Sending keepalive frame %d", temp_index);
// Send the next frame
- if ( !sendFrame( temp_image_buffer[temp_index].file_name, &temp_image_buffer[temp_index].timestamp ) )
+ if ( !sendFrame(temp_image_buffer[temp_index].file_name, &temp_image_buffer[temp_index].timestamp) ) {
zm_terminate = true;
- //frame_sent = true;
+ }
+ // frame_sent = true;
}
- } // end if (!paused) or step or paused
- } // end if have exceeded buffer or not
+ } // end if (!paused) or step or paused
+ } // end if have exceeded buffer or not
if ( temp_read_index == temp_write_index ) {
// Go back to live viewing
@@ -652,16 +661,16 @@ void MonitorStream::runStream() {
delayed = false;
replay_rate = ZM_RATE_BASE;
}
- } // end if ( buffered_playback && delayed )
+ } // end if ( buffered_playback && delayed )
if ( last_read_index != monitor->shared_data->last_write_index ) {
// have a new image to send
- int index = monitor->shared_data->last_write_index % monitor->image_buffer_count; // % shouldn't be neccessary
+ int index = monitor->shared_data->last_write_index % monitor->image_buffer_count; // % shouldn't be neccessary
if ( (frame_mod == 1) || ((frame_count%frame_mod) == 0) ) {
if ( !paused && !delayed ) {
last_read_index = monitor->shared_data->last_write_index;
Debug(2, "index: %d: frame_mod: %d frame count: %d paused(%d) delayed(%d)",
- index, frame_mod, frame_count, paused, delayed );
+ index, frame_mod, frame_count, paused, delayed);
// Send the next frame
Monitor::Snapshot *snap = &monitor->image_buffer[index];
@@ -670,9 +679,13 @@ void MonitorStream::runStream() {
Debug(2, "sendFrame failed, quiting.");
zm_terminate = true;
}
- // Perhaps we should use NOW instead.
- memcpy(&last_frame_timestamp, snap->timestamp, sizeof(last_frame_timestamp));
- //frame_sent = true;
+ // Perhaps we should use NOW instead.
+ memcpy(
+ &last_frame_timestamp,
+ snap->timestamp,
+ sizeof(last_frame_timestamp)
+ );
+ // frame_sent = true;
temp_read_index = temp_write_index;
} else {
@@ -697,7 +710,7 @@ void MonitorStream::runStream() {
if ( !sendFrame(paused_image, &paused_timestamp) )
zm_terminate = true;
} else {
- Debug(2, "Would have sent keepalive frame, but had no paused_image ");
+ Debug(2, "Would have sent keepalive frame, but had no paused_image");
}
} // end if actual_delta_time > 5
} // end if change in zoom
@@ -718,27 +731,27 @@ void MonitorStream::runStream() {
temp_index);
temp_image_buffer[temp_index].valid = true;
}
- memcpy( &(temp_image_buffer[temp_index].timestamp), monitor->image_buffer[index].timestamp, sizeof(temp_image_buffer[0].timestamp) );
- monitor->image_buffer[index].image->WriteJpeg( temp_image_buffer[temp_index].file_name, config.jpeg_file_quality );
- temp_write_index = MOD_ADD( temp_write_index, 1, temp_image_buffer_count );
+ memcpy(&(temp_image_buffer[temp_index].timestamp), monitor->image_buffer[index].timestamp, sizeof(temp_image_buffer[0].timestamp));
+ monitor->image_buffer[index].image->WriteJpeg(temp_image_buffer[temp_index].file_name, config.jpeg_file_quality);
+ temp_write_index = MOD_ADD(temp_write_index, 1, temp_image_buffer_count);
if ( temp_write_index == temp_read_index ) {
// Go back to live viewing
- Warning( "Exceeded temporary buffer, resuming live play" );
+ Warning("Exceeded temporary buffer, resuming live play");
paused = false;
delayed = false;
replay_rate = ZM_RATE_BASE;
}
} else {
- Warning( "Unable to store frame as timestamp invalid" );
+ Warning("Unable to store frame as timestamp invalid");
}
} else {
- Warning( "Unable to store frame as shared memory invalid" );
+ Warning("Unable to store frame as shared memory invalid");
}
} // end if buffered playback
frame_count++;
} else {
Debug(3, "Waiting for capture last_write_index=%u", monitor->shared_data->last_write_index);
- } // end if ( (unsigned int)last_read_index != monitor->shared_data->last_write_index )
+ } // end if ( (unsigned int)last_read_index != monitor->shared_data->last_write_index )
unsigned long sleep_time = (unsigned long)((1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2)));
Debug(3, "Sleeping for (%d)", sleep_time);
@@ -755,10 +768,10 @@ void MonitorStream::runStream() {
break;
}
}
- if ( ! last_frame_sent ) {
+ if ( !last_frame_sent ) {
// If we didn't capture above, because frame_mod was bad? Then last_frame_sent will not have a value.
last_frame_sent = now.tv_sec;
- Warning("no last_frame_sent. Shouldn't happen. frame_mod was (%d) frame_count (%d) ",
+ Warning("no last_frame_sent. Shouldn't happen. frame_mod was (%d) frame_count (%d)",
frame_mod, frame_count);
} else if (
(!paused)
@@ -799,9 +812,9 @@ void MonitorStream::runStream() {
}
}
}
- globfree( &pglob );
+ globfree(&pglob);
if ( rmdir(swap_path.c_str()) < 0 ) {
- Error( "Can't rmdir '%s': %s", swap_path.c_str(), strerror(errno) );
+ Error("Can't rmdir '%s': %s", swap_path.c_str(), strerror(errno));
}
} // end if checking for swap_path
} // end if buffered_playback
@@ -809,7 +822,7 @@ void MonitorStream::runStream() {
closeComms();
} // end MonitorStream::runStream
-void MonitorStream::SingleImage( int scale ) {
+void MonitorStream::SingleImage(int scale) {
int img_buffer_size = 0;
static JOCTET img_buffer[ZM_MAX_IMAGE_SIZE];
Image scaled_image;
@@ -817,42 +830,45 @@ void MonitorStream::SingleImage( int scale ) {
Image *snap_image = snap->image;
if ( scale != ZM_SCALE_BASE ) {
- scaled_image.Assign( *snap_image );
- scaled_image.Scale( scale );
+ scaled_image.Assign(*snap_image);
+ scaled_image.Scale(scale);
snap_image = &scaled_image;
}
if ( !config.timestamp_on_capture ) {
- monitor->TimestampImage( snap_image, snap->timestamp );
+ monitor->TimestampImage(snap_image, snap->timestamp);
}
- snap_image->EncodeJpeg( img_buffer, &img_buffer_size );
-
- fprintf( stdout, "Content-Length: %d\r\n", img_buffer_size );
- fprintf( stdout, "Content-Type: image/jpeg\r\n\r\n" );
- fwrite( img_buffer, img_buffer_size, 1, stdout );
+ snap_image->EncodeJpeg(img_buffer, &img_buffer_size);
+
+ fprintf(stdout,
+ "Content-Length: %d\r\n"
+ "Content-Type: image/jpeg\r\n\r\n",
+ img_buffer_size);
+ fwrite(img_buffer, img_buffer_size, 1, stdout);
}
-void MonitorStream::SingleImageRaw( int scale ) {
+void MonitorStream::SingleImageRaw(int scale) {
Image scaled_image;
Monitor::Snapshot *snap = monitor->getSnapshot();
Image *snap_image = snap->image;
if ( scale != ZM_SCALE_BASE ) {
- scaled_image.Assign( *snap_image );
- scaled_image.Scale( scale );
+ scaled_image.Assign(*snap_image);
+ scaled_image.Scale(scale);
snap_image = &scaled_image;
}
if ( !config.timestamp_on_capture ) {
- monitor->TimestampImage( snap_image, snap->timestamp );
+ monitor->TimestampImage(snap_image, snap->timestamp);
}
-
- fprintf( stdout, "Content-Length: %d\r\n", snap_image->Size() );
- fprintf( stdout, "Content-Type: image/x-rgb\r\n\r\n" );
- fwrite( snap_image->Buffer(), snap_image->Size(), 1, stdout );
+
+ fprintf(stdout,
+ "Content-Length: %d\r\n"
+ "Content-Type: image/x-rgb\r\n\r\n",
+ snap_image->Size());
+ fwrite(snap_image->Buffer(), snap_image->Size(), 1, stdout);
}
-
#ifdef HAVE_ZLIB_H
-void MonitorStream::SingleImageZip( int scale ) {
+void MonitorStream::SingleImageZip(int scale) {
unsigned long img_buffer_size = 0;
static Bytef img_buffer[ZM_MAX_IMAGE_SIZE];
Image scaled_image;
@@ -861,17 +877,19 @@ void MonitorStream::SingleImageZip( int scale ) {
Image *snap_image = snap->image;
if ( scale != ZM_SCALE_BASE ) {
- scaled_image.Assign( *snap_image );
- scaled_image.Scale( scale );
+ scaled_image.Assign(*snap_image);
+ scaled_image.Scale(scale);
snap_image = &scaled_image;
}
if ( !config.timestamp_on_capture ) {
- monitor->TimestampImage( snap_image, snap->timestamp );
+ monitor->TimestampImage(snap_image, snap->timestamp);
}
- snap_image->Zip( img_buffer, &img_buffer_size );
-
- fprintf( stdout, "Content-Length: %ld\r\n", img_buffer_size );
- fprintf( stdout, "Content-Type: image/x-rgbz\r\n\r\n" );
- fwrite( img_buffer, img_buffer_size, 1, stdout );
+ snap_image->Zip(img_buffer, &img_buffer_size);
+
+ fprintf(stdout,
+ "Content-Length: %ld\r\n"
+ "Content-Type: image/x-rgbz\r\n\r\n",
+ img_buffer_size);
+ fwrite(img_buffer, img_buffer_size, 1, stdout);
}
#endif // HAVE_ZLIB_H
diff --git a/utils/do_debian_package.sh b/utils/do_debian_package.sh
index 3e20b303a..b60996a78 100755
--- a/utils/do_debian_package.sh
+++ b/utils/do_debian_package.sh
@@ -175,7 +175,7 @@ cd ../
VERSION=`cat ${GITHUB_FORK}_zoneminder_release/version`
-if [ $VERSION == "" ]; then
+if [ -z "$VERSION" ]; then
exit 1;
fi;
if [ "$SNAPSHOT" != "stable" ] && [ "$SNAPSHOT" != "" ]; then
diff --git a/utils/packpack/rsync_xfer.sh b/utils/packpack/rsync_xfer.sh
index 40f5235be..9f273ca96 100755
--- a/utils/packpack/rsync_xfer.sh
+++ b/utils/packpack/rsync_xfer.sh
@@ -1,5 +1,10 @@
#!/bin/bash
+# We don't deploy during eslint checks, so exit immediately
+if [ "${DIST}" == "eslint" ]; then
+ exit 0
+fi
+
# Check to see if this script has access to all the commands it needs
for CMD in sshfs rsync find fusermount mkdir; do
type $CMD 2>&1 > /dev/null
@@ -12,53 +17,26 @@ for CMD in sshfs rsync find fusermount mkdir; do
fi
done
-# We only want to deploy packages during cron events
-# See https://docs.travis-ci.com/user/cron-jobs/
-if [ "${TRAVIS_EVENT_TYPE}" == "cron" ] || [ "${OS}" == "debian" ] || [ "${OS}" == "ubuntu" ]; then
-
- if [ "${OS}" == "debian" ] || [ "${OS}" == "ubuntu" ]; then
- targetfolder="debian/master/mini-dinstall/incoming"
- else
- targetfolder="travis"
- fi
-
- echo
- echo "Target subfolder set to $targetfolder"
- echo
- if [ "${USE_SFTP}" == "yes" ]; then
- echo "Running \$(rsync -v -e 'ssh -vvv' build/* zmrepo@zmrepo.zoneminder.com:${targetfolder}/ 2>&1)"
- rsync -v -e 'ssh -vvv' build/* zmrepo@zmrepo.zoneminder.com:${targetfolder}/ 2>&1
- if [ $? -eq 0 ]; then
- echo
- echo "Files copied successfully."
- echo
- else
- echo
- echo "ERROR: Attempt to rsync to zmrepo.zoneminder.com failed!"
- echo
- exit 99
- fi
- else
- mkdir -p ./zmrepo
- ssh_mntchk="$(sshfs zmrepo@zmrepo.zoneminder.com:./ ./zmrepo -o workaround=rename,reconnect 2>&1)"
-
- if [ -z "$ssh_mntchk" ]; then
- echo
- echo "Remote filesystem mounted successfully."
- echo "Begin transfering files..."
- echo
-
- # Don't keep packages older than 5 days
- find ./zmrepo/$targetfolder/ -maxdepth 1 -type f,l -mtime +5 -delete
- rsync -vzlh --ignore-errors build/* zmrepo/$targetfolder/
- fusermount -zu zmrepo
- else
- echo
- echo "ERROR: Attempt to mount zmrepo.zoneminder.com failed!"
- echo "sshfs gave the following error message:"
- echo \"$ssh_mntchk\"
- echo
- exit 99
- fi
- fi
+if [ "${OS}" == "debian" ] || [ "${OS}" == "ubuntu" ] || [ "${OS}" == "raspbian" ]; then
+ targetfolder="debian/master/mini-dinstall/incoming"
+else
+ targetfolder="travis"
+fi
+
+echo
+echo "Target subfolder set to $targetfolder"
+echo
+
+echo "Running \$(rsync -v -e 'ssh -vvv' build/*.{rpm,deb,dsc,tar.xz,buildinfo,changes} zmrepo@zmrepo.zoneminder.com:${targetfolder}/ 2>&1)"
+rsync -v --ignore-missing-args --exclude 'external-repo.noarch.rpm' -e 'ssh -vvv' build/*.{rpm,deb,dsc,tar.xz,changes} zmrepo@zmrepo.zoneminder.com:${targetfolder}/ 2>&1
+if [ "$?" -eq 0 ]; then
+ echo
+ echo "Files copied successfully."
+ echo
+else
+ echo
+ echo "ERROR: Attempt to rsync to zmrepo.zoneminder.com failed!"
+ echo "See log output for details."
+ echo
+ exit 99
fi
diff --git a/utils/packpack/startpackpack.sh b/utils/packpack/startpackpack.sh
index 35a6aeab4..6a51e2995 100755
--- a/utils/packpack/startpackpack.sh
+++ b/utils/packpack/startpackpack.sh
@@ -9,7 +9,7 @@
# General sanity checks
checksanity () {
# Check to see if this script has access to all the commands it needs
- for CMD in set echo curl git ln mkdir rmdir cat patch; do
+ for CMD in set echo curl git ln mkdir rmdir cat patch sed; do
type $CMD 2>&1 > /dev/null
if [ $? -ne 0 ]; then
@@ -30,7 +30,7 @@ checksanity () {
ARCH="x86_64"
fi
- if [[ "${ARCH}" != "x86_64" && "${ARCH}" != "i386" && "${ARCH}" != "armhf" ]]; then
+ if [[ "${ARCH}" != "x86_64" && "${ARCH}" != "i386" && "${ARCH}" != "armhf" && "${ARCH}" != "aarch64" ]]; then
echo
echo "ERROR: Unsupported architecture specified \"${ARCH}\"."
echo
@@ -150,7 +150,7 @@ install_deb () {
exit 1
fi
- # Install and test the zoneminder package (only) for Ubuntu Trusty
+ # Install and test the zoneminder package (only) for Ubuntu Xenial
pkgname="build/zoneminder_${VERSION}-${RELEASE}_amd64.deb"
if [ -e $pkgname ]; then
@@ -275,6 +275,8 @@ checkdeploytarget () {
echo "*** TRACEROUTE ***"
echo
traceroute -w 2 -m 15 ${DEPLOYTARGET}
+
+ exit 97
fi
}
@@ -291,43 +293,43 @@ if [ "${TRAVIS}" == "true" ]; then
fi
checksanity
-# We don't want to build packages for all supported distros after every commit
-# Only build all packages when executed via cron
-# See https://docs.travis-ci.com/user/cron-jobs/
-
# Steps common to Redhat distros
if [ "${OS}" == "el" ] || [ "${OS}" == "fedora" ]; then
- if [ "${TRAVIS_EVENT_TYPE}" == "cron" ] || [ "${TRAVIS}" != "true" ]; then
- commonprep
- echo "Begin Redhat build..."
+ commonprep
+ echo "Begin Redhat build..."
- setrpmpkgname
+ # Newer Redhat distros use dnf package manager rather than yum
+ if [ "${DIST}" -gt "7" ]; then
+ sed -i 's\yum\dnf\' utils/packpack/redhat_package.mk
+ fi
- ln -sfT distros/redhat rpm
+ setrpmpkgname
- # The rpm specfile requires the Crud submodule folder to be empty
- rm -rf web/api/app/Plugin/Crud
- mkdir web/api/app/Plugin/Crud
+ ln -sfT distros/redhat rpm
- reporpm="rpmfusion-free-release"
- dlurl="https://download1.rpmfusion.org/free/${OS}/${reporpm}-${DIST}.noarch.rpm"
+ # The rpm specfile requires the Crud submodule folder to be empty
+ rm -rf web/api/app/Plugin/Crud
+ mkdir web/api/app/Plugin/Crud
- # Give our downloaded repo rpm a common name so redhat_package.mk can find it
- if [ -n "$dlurl" ] && [ $? -eq 0 ]; then
- echo "Retrieving ${reporpm} repo rpm..."
- curl $dlurl > build/external-repo.noarch.rpm
- else
- echo "ERROR: Failed to retrieve ${reporpm} repo rpm..."
- echo "Download url was: $dlurl"
- exit 1
- fi
+ reporpm="rpmfusion-free-release"
+ dlurl="https://download1.rpmfusion.org/free/${OS}/${reporpm}-${DIST}.noarch.rpm"
- setrpmchangelog
+ # Give our downloaded repo rpm a common name so redhat_package.mk can find it
+ if [ -n "$dlurl" ] && [ $? -eq 0 ]; then
+ echo "Retrieving ${reporpm} repo rpm..."
+ curl $dlurl > build/external-repo.noarch.rpm
+ else
+ echo "ERROR: Failed to retrieve ${reporpm} repo rpm..."
+ echo "Download url was: $dlurl"
+ exit 1
+ fi
- echo "Starting packpack..."
- execpackpack
- fi;
- # Steps common to Debian based distros
+ setrpmchangelog
+
+ echo "Starting packpack..."
+ execpackpack
+
+# Steps common to Debian based distros
elif [ "${OS}" == "debian" ] || [ "${OS}" == "ubuntu" ] || [ "${OS}" == "raspbian" ]; then
commonprep
echo "Begin ${OS} ${DIST} build..."
@@ -348,14 +350,27 @@ elif [ "${OS}" == "debian" ] || [ "${OS}" == "ubuntu" ] || [ "${OS}" == "raspbia
echo "Starting packpack..."
execpackpack
- # We were not triggered via cron so just build and test trusty
- if [ "${OS}" == "ubuntu" ] && [ "${DIST}" == "xenial" ] && [ "${ARCH}" == "x86_64" ]; then
- # If we are running inside Travis then attempt to install the deb we just built
- if [ "${TRAVIS}" == "true" ]; then
+ # Try to install and run the newly built zoneminder package
+ if [ "${OS}" == "ubuntu" ] && [ "${DIST}" == "xenial" ] && [ "${ARCH}" == "x86_64" ] && [ "${TRAVIS}" == "true" ]; then
+ echo "Begin Deb package installation..."
install_deb
- fi
fi
+
+# Steps common to eslint checks
+elif [ "${OS}" == "eslint" ] || [ "${DIST}" == "eslint" ]; then
+
+ # Check we've got npm installed
+ type npm 2>&1 > /dev/null
+
+ if [ $? -ne 0 ]; then
+ echo
+ echo "ERROR: The script cannot find the required command \"npm\"."
+ echo
+ exit 1
+ fi
+
+ npm install -g eslint@5.12.0 eslint-config-google@0.11.0 eslint-plugin-html@5.0.0 eslint-plugin-php-markup@0.2.5
+ echo "Begin eslint checks..."
+ eslint --ext .php,.js .
fi
-exit 0
-
diff --git a/web/ajax/log.php b/web/ajax/log.php
index ef2e450f2..36a29adc3 100644
--- a/web/ajax/log.php
+++ b/web/ajax/log.php
@@ -41,7 +41,7 @@ function buildLogQuery($action) {
}
foreach ( $filter as $field=>$value ) {
- if ( ! in_array($field, $filterFields) ) {
+ if ( !in_array($field, $filterFields) ) {
ZM\Error("'$field' is not in valid filter fields " . print_r($filterField,true));
continue;
}
@@ -58,7 +58,7 @@ function buildLogQuery($action) {
$sql .= ' ORDER BY '.$sortField.' '.$sortOrder.' LIMIT '.$limit;
return array('sql'=>$sql, 'values'=>$values);
-}
+} # function buildLogQuery($action)
switch ( $_REQUEST['task'] ) {
case 'create' :
@@ -70,14 +70,16 @@ switch ( $_REQUEST['task'] ) {
$string = $_POST['message'];
$file = !empty($_POST['file']) ? preg_replace( '/\w+:\/\/[\w.:]+\//', '', $_POST['file'] ) : '';
- if ( !empty( $_POST['line'] ) )
+ if ( !empty( $_POST['line'] ) ) {
$line = validInt($_POST['line']);
- else
+ } else {
$line = NULL;
+ }
$levels = array_flip(ZM\Logger::$codes);
- if ( !isset($levels[$_POST['level']]) )
+ if ( !isset($levels[$_POST['level']]) ) {
ZM\Panic('Unexpected logger level '.$_POST['level']);
+ }
$level = $levels[$_POST['level']];
ZM\Logger::fetch()->logPrint($level, $string, $file, $line);
}
@@ -141,6 +143,10 @@ switch ( $_REQUEST['task'] ) {
$logs[] = $log;
}
+ foreach ( $options as $field => $values ) {
+ asort($options[$field]);
+ }
+
$available = count($logs);
ajaxResponse( array(
'updated' => preg_match('/%/', DATE_FMT_CONSOLE_LONG)?strftime(DATE_FMT_CONSOLE_LONG):date(DATE_FMT_CONSOLE_LONG),
diff --git a/web/api/app/Controller/HostController.php b/web/api/app/Controller/HostController.php
index 300352949..7ddba57df 100644
--- a/web/api/app/Controller/HostController.php
+++ b/web/api/app/Controller/HostController.php
@@ -136,7 +136,7 @@ class HostController extends AppController {
}*/
$access_issued_at = time();
- $access_ttl = (ZM_AUTH_HASH_TTL || 2) * 3600;
+ $access_ttl = max(ZM_AUTH_HASH_TTL,1) * 3600;
// by default access token will expire in 2 hrs
// you can change it by changing the value of ZM_AUTH_HASH_TLL
diff --git a/web/api/app/Controller/MonitorsController.php b/web/api/app/Controller/MonitorsController.php
index 3be9166b8..789307795 100644
--- a/web/api/app/Controller/MonitorsController.php
+++ b/web/api/app/Controller/MonitorsController.php
@@ -44,33 +44,25 @@ class MonitorsController extends AppController {
} else {
$conditions = array();
}
-
global $user;
$allowedMonitors = $user ? preg_split('@,@', $user['MonitorIds'], NULL, PREG_SPLIT_NO_EMPTY) : null;
if ( $allowedMonitors ) {
$conditions['Monitor.Id' ] = $allowedMonitors;
}
- $find_array = array('conditions'=>$conditions,'contain'=>array('Group'));
- if ( isset($conditions['GroupId']) ) {
- $find_array['joins'] = array(
+ $find_array = array(
+ 'conditions' => &$conditions,
+ 'contain' => array('Group'),
+ 'joins' => array(
array(
'table' => 'Groups_Monitors',
- 'type' => 'inner',
+ 'type' => 'left',
'conditions' => array(
- 'Groups_Monitors.MonitorId = Monitor.Id'
+ 'Groups_Monitors.MonitorId = Monitor.Id',
),
),
- //array(
- //'table' => 'Groups',
- //'type' => 'inner',
- //'conditions' => array(
- //'Groups.Id = Groups_Monitors.GroupId',
- //'Groups.Id' => $this->request->params['GroupId'],
- //),
- //)
- );
- }
+ )
+ );
$monitors = $this->Monitor->find('all',$find_array);
$this->set(array(
'monitors' => $monitors,
diff --git a/web/api/app/Model/Group.php b/web/api/app/Model/Group.php
index 8d8f533ca..04d783b14 100644
--- a/web/api/app/Model/Group.php
+++ b/web/api/app/Model/Group.php
@@ -77,4 +77,5 @@ class Group extends AppModel {
'counterQuery' => ''
),
);
+ var $actsAs = array( 'Containable' );
}
diff --git a/web/includes/Control.php b/web/includes/Control.php
index 39c259092..2121061b1 100644
--- a/web/includes/Control.php
+++ b/web/includes/Control.php
@@ -128,12 +128,16 @@ class Control extends ZM_Object {
$cmds['PresetHome'] = 'presetHome';
if ( $this->CanZoom() ) {
- if ( $this->CanZoomCon() )
+ if ( $this->CanZoomCon() ) {
$cmds['ZoomRoot'] = 'zoomCon';
- elseif ( $this->CanZoomRel() )
+ } else if ( $this->CanZoomRel() ) {
$cmds['ZoomRoot'] = 'zoomRel';
- elseif ( $this->CanZoomAbs() )
+ } else if ( $this->CanZoomAbs() ) {
$cmds['ZoomRoot'] = 'zoomAbs';
+ } else {
+ $cmds['ZoomRoot'] = '';
+ Error('No zoom type selected. Please select Continuous, Relative, Absolute');
+ }
$cmds['ZoomTele'] = $cmds['ZoomRoot'].'Tele';
$cmds['ZoomWide'] = $cmds['ZoomRoot'].'Wide';
$cmds['ZoomStop'] = 'zoomStop';
@@ -142,12 +146,16 @@ class Control extends ZM_Object {
}
if ( $this->CanFocus() ) {
- if ( $this->CanFocusCon() )
+ if ( $this->CanFocusCon() ) {
$cmds['FocusRoot'] = 'focusCon';
- elseif ( $this->CanFocusRel() )
+ } else if ( $this->CanFocusRel() ) {
$cmds['FocusRoot'] = 'focusRel';
- elseif ( $this->CanFocusAbs() )
+ } else if ( $this->CanFocusAbs() ) {
$cmds['FocusRoot'] = 'focusAbs';
+ } else {
+ $cmds['FocusRoot'] = '';
+ Error('No focus type selected. Please select Continuous, Relative, Absolute');
+ }
$cmds['FocusFar'] = $cmds['FocusRoot'].'Far';
$cmds['FocusNear'] = $cmds['FocusRoot'].'Near';
$cmds['FocusStop'] = 'focusStop';
@@ -156,12 +164,16 @@ class Control extends ZM_Object {
}
if ( $this->CanIris() ) {
- if ( $this->CanIrisCon() )
+ if ( $this->CanIrisCon() ) {
$cmds['IrisRoot'] = 'irisCon';
- elseif ( $this->CanIrisRel() )
+ } else if ( $this->CanIrisRel() ) {
$cmds['IrisRoot'] = 'irisRel';
- elseif ( $this->CanIrisAbs() )
+ } else if ( $this->CanIrisAbs() ) {
$cmds['IrisRoot'] = 'irisAbs';
+ } else {
+ $cmds['IrisRoot'] = '';
+ Error('No iris type selected. Please select Continuous, Relative, Absolute');
+ }
$cmds['IrisOpen'] = $cmds['IrisRoot'].'Open';
$cmds['IrisClose'] = $cmds['IrisRoot'].'Close';
$cmds['IrisStop'] = 'irisStop';
@@ -170,12 +182,16 @@ class Control extends ZM_Object {
}
if ( $this->CanWhite() ) {
- if ( $this->CanWhiteCon() )
+ if ( $this->CanWhiteCon() ) {
$cmds['WhiteRoot'] = 'whiteCon';
- elseif ( $this->CanWhiteRel() )
+ } else if ( $this->CanWhiteRel() ) {
$cmds['WhiteRoot'] = 'whiteRel';
- elseif ( $this->CanWhiteAbs() )
+ } else if ( $this->CanWhiteAbs() ) {
$cmds['WhiteRoot'] = 'whiteAbs';
+ } else {
+ Error('No White type selected. Please select Continuous, Relative, Absolute');
+ $cmds['WhiteRoot'] = '';
+ }
$cmds['WhiteIn'] = $cmds['WhiteRoot'].'In';
$cmds['WhiteOut'] = $cmds['WhiteRoot'].'Out';
$cmds['WhiteAuto'] = 'whiteAuto';
@@ -183,12 +199,16 @@ class Control extends ZM_Object {
}
if ( $this->CanGain() ) {
- if ( $this->CanGainCon() )
+ if ( $this->CanGainCon() ) {
$cmds['GainRoot'] = 'gainCon';
- elseif ( $this->CanGainRel() )
+ } else if ( $this->CanGainRel() ) {
$cmds['GainRoot'] = 'gainRel';
- elseif ( $this->CanGainAbs() )
+ } else if ( $this->CanGainAbs() ) {
$cmds['GainRoot'] = 'gainAbs';
+ } else {
+ Error('No Gain type selected');
+ $cmds['GainRoot'] = '';
+ }
$cmds['GainUp'] = $cmds['GainRoot'].'Up';
$cmds['GainDown'] = $cmds['GainRoot'].'Down';
$cmds['GainAuto'] = 'gainAuto';
@@ -207,6 +227,7 @@ class Control extends ZM_Object {
$cmds['Center'] = $cmds['PresetHome'];
} else {
$cmds['MoveRoot'] = '';
+ Error('No move type selected. Please select Continuous, Relative, Absolute');
}
$cmds['MoveUp'] = $cmds['MoveRoot'].'Up';
diff --git a/web/includes/Monitor.php b/web/includes/Monitor.php
index cc51926fd..b725963f2 100644
--- a/web/includes/Monitor.php
+++ b/web/includes/Monitor.php
@@ -59,10 +59,10 @@ class Monitor extends ZM_Object {
'LabelX' => 0,
'LabelY' => 0,
'LabelSize' => 1,
- 'ImageBufferCount' => 100,
+ 'ImageBufferCount' => 20,
'WarmupCount' => 0,
- 'PreEventCount' => 0,
- 'PostEventCount' => 0,
+ 'PreEventCount' => 5,
+ 'PostEventCount' => 5,
'StreamReplayBuffer' => 0,
'AlarmFrameCount' => 1,
'SectionLength' => 600,
@@ -89,7 +89,7 @@ class Monitor extends ZM_Object {
'DefaultScale' => 100,
'SignalCheckPoints' => 0,
'SignalCheckColour' => '#0000BE',
- 'WebColour' => 'red',
+ 'WebColour' => '#ff0000',
'Exif' => array('type'=>'boolean','default'=>0),
'Sequence' => null,
'TotalEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
@@ -473,53 +473,53 @@ class Monitor extends ZM_Object {
//ZM_MIN_STREAMING_PORT ? (ZM_MIN_STREAMING_PORT+$this->Id()) : null);
}
-public function sendControlCommand($command) {
- // command is generally a command option list like --command=blah but might be just the word quit
+ public function sendControlCommand($command) {
+ // command is generally a command option list like --command=blah but might be just the word quit
- $options = array();
- # Convert from a command line params to an option array
- foreach ( explode(' ', $command) as $option ) {
- if ( preg_match('/--([^=]+)(?:=(.+))?/', $option, $matches) ) {
- $options[$matches[1]] = $matches[2]?$matches[2]:1;
- } else if ( $option != '' and $option != 'quit' ) {
- Warning("Ignored command for zmcontrol $option in $command");
- }
- }
- if ( !count($options) ) {
- if ( $command == 'quit' ) {
- $options['command'] = 'quit';
- } else {
- Warning("No commands to send to zmcontrol from $command");
- return false;
- }
- }
-
- if ( (!defined('ZM_SERVER_ID')) or ( property_exists($this, 'ServerId') and (ZM_SERVER_ID==$this->{'ServerId'}) ) ) {
- # Local
- Logger::Debug('Trying to send options ' . print_r($options, true));
-
- $optionString = jsonEncode($options);
- Logger::Debug("Trying to send options $optionString");
- // Either connects to running zmcontrol.pl or runs zmcontrol.pl to send the command.
- $socket = socket_create(AF_UNIX, SOCK_STREAM, 0);
- if ( $socket < 0 ) {
- Error('socket_create() failed: '.socket_strerror($socket));
- return false;
- }
- $sockFile = ZM_PATH_SOCKS.'/zmcontrol-'.$this->{'Id'}.'.sock';
- if ( @socket_connect($socket, $sockFile) ) {
- if ( !socket_write($socket, $optionString) ) {
- Error('Can\'t write to control socket: '.socket_strerror(socket_last_error($socket)));
- return false;
+ $options = array();
+ # Convert from a command line params to an option array
+ foreach ( explode(' ', $command) as $option ) {
+ if ( preg_match('/--([^=]+)(?:=(.+))?/', $option, $matches) ) {
+ $options[$matches[1]] = $matches[2]?$matches[2]:1;
+ } else if ( $option != '' and $option != 'quit' ) {
+ Warning("Ignored command for zmcontrol $option in $command");
}
- } else if ( $command != 'quit' ) {
- $command = ZM_PATH_BIN.'/zmcontrol.pl '.$command.' --id='.$this->{'Id'};
-
- // Can't connect so use script
- $ctrlOutput = exec(escapeshellcmd($command));
}
- socket_close($socket);
- } else if ( $this->ServerId() ) {
+ if ( !count($options) ) {
+ if ( $command == 'quit' ) {
+ $options['command'] = 'quit';
+ } else {
+ Warning("No commands to send to zmcontrol from $command");
+ return false;
+ }
+ }
+
+ if ( (!defined('ZM_SERVER_ID')) or ( property_exists($this, 'ServerId') and (ZM_SERVER_ID==$this->{'ServerId'}) ) ) {
+ # Local
+ Logger::Debug('Trying to send options ' . print_r($options, true));
+
+ $optionString = jsonEncode($options);
+ Logger::Debug("Trying to send options $optionString");
+ // Either connects to running zmcontrol.pl or runs zmcontrol.pl to send the command.
+ $socket = socket_create(AF_UNIX, SOCK_STREAM, 0);
+ if ( $socket < 0 ) {
+ Error('socket_create() failed: '.socket_strerror($socket));
+ return false;
+ }
+ $sockFile = ZM_PATH_SOCKS.'/zmcontrol-'.$this->{'Id'}.'.sock';
+ if ( @socket_connect($socket, $sockFile) ) {
+ if ( !socket_write($socket, $optionString) ) {
+ Error('Can\'t write to control socket: '.socket_strerror(socket_last_error($socket)));
+ return false;
+ }
+ } else if ( $command != 'quit' ) {
+ $command = ZM_PATH_BIN.'/zmcontrol.pl '.$command.' --id='.$this->{'Id'};
+
+ // Can't connect so use script
+ $ctrlOutput = exec(escapeshellcmd($command));
+ }
+ socket_close($socket);
+ } else if ( $this->ServerId() ) {
$Server = $this->Server();
$url = ZM_BASE_PROTOCOL . '://'.$Server->Hostname().'/zm/api/monitors/daemonControl/'.$this->{'Id'}.'/'.$mode.'/zmcontrol.json';
@@ -544,7 +544,7 @@ public function sendControlCommand($command) {
}
} catch ( Exception $e ) {
Error("Except $e thrown trying to restart zma");
- return false;
+ return false;
}
} else {
Error('Server not assigned to Monitor in a multi-server setup. Please assign a server to the Monitor.');
diff --git a/web/includes/actions/controlcap.php b/web/includes/actions/controlcap.php
index eec3ffd8b..ad4985f11 100644
--- a/web/includes/actions/controlcap.php
+++ b/web/includes/actions/controlcap.php
@@ -28,6 +28,65 @@ if ( $action == 'controlcap' ) {
require_once('includes/Control.php');
$Control = new ZM\Control( !empty($_REQUEST['cid']) ? $_REQUEST['cid'] : null );
+ $field_defaults = array(
+ 'CanWake' => 0,
+ 'CanSleep' => 0,
+ 'CanReset' => 0,
+ 'CanReboot' => 0,
+ 'CanMove' => 0,
+ 'CanMoveDiag' => 0,
+ 'CanMoveMap' => 0,
+ 'CanMoveRel' => 0,
+ 'CanMoveAbs' => 0,
+ 'CanMoveCon' => 0,
+ 'CanPan' => 0,
+ 'HasPanSpeed' => 0,
+ 'HasTurboPan' => 0,
+ 'CanTilt' => 0,
+ 'HasTiltSpeed' => 0,
+ 'HasTurboTilt' => 0,
+ 'CanZoom' => 0,
+ 'CanZoomRel' => 0,
+ 'CanZoomAbs' => 0,
+ 'CanZoomCon' => 0,
+ 'HasZoomSpeed' => 0,
+ 'CanFocus' => 0,
+ 'CanAutoFocus' => 0,
+ 'CanFocusRel' => 0,
+ 'CanFocusAbs' => 0,
+ 'CanFocusCon' => 0,
+ 'HasFocusSpeed' => 0,
+ 'CanGain' => 0,
+ 'CanAutoGain' => 0,
+ 'CanGainRel' => 0,
+ 'CanGainAbs' => 0,
+ 'CanGainCon' => 0,
+ 'HasGainSpeed' => 0,
+ 'CanWhite' => 0,
+ 'CanAutoWhite' => 0,
+ 'CanWhiteRel' => 0,
+ 'CanWhiteAbs' => 0,
+ 'CanWhiteCon' => 0,
+ 'HasWhiteSpeed' => 0,
+ 'CanIris' => 0,
+ 'CanAutoIris' => 0,
+ 'CanIrisRel' => 0,
+ 'CanIrisAbs' => 0,
+ 'CanIrisCon' => 0,
+ 'HasIrisSpeed' => 0,
+ 'HasPresets' => 0,
+ 'HasHomePreset' => 0,
+ 'CanSetPresets' => 0,
+ );
+
+ # Checkboxes don't return an element in the POST data, so won't be present in newControl.
+ # So force a value for these fields
+ foreach ( $field_defaults as $field => $value ) {
+ if ( ! (isset($_REQUEST['newControl'][$field]) and $_REQUEST['newControl'][$field]) ) {
+ $_REQUEST['newControl'][$field] = $value;
+ }
+ } # end foreach type
+
//$changes = getFormChanges( $control, $_REQUEST['newControl'], $types, $columns );
$Control->save($_REQUEST['newControl']);
$refreshParent = true;
diff --git a/web/includes/config.php.in b/web/includes/config.php.in
index ef1bf4a16..909a10e15 100644
--- a/web/includes/config.php.in
+++ b/web/includes/config.php.in
@@ -179,14 +179,14 @@ if ( ! defined('ZM_SERVER_ID') ) {
# Use Server lookup so that it caches
$Server = ZM\Server::find_one(array('Name'=>ZM_SERVER_NAME));
if ( !$Server ) {
- Error('Invalid Multi-Server configration detected. ZM_SERVER_NAME set to ' . ZM_SERVER_NAME . ' in zm.conf, but no corresponding entry found in Servers table.');
+ ZM\Error('Invalid Multi-Server configration detected. ZM_SERVER_NAME set to ' . ZM_SERVER_NAME . ' in zm.conf, but no corresponding entry found in Servers table.');
} else {
define('ZM_SERVER_ID', $Server->Id());
}
} else if ( defined('ZM_SERVER_HOST') and ZM_SERVER_HOST ) {
$Server = ZM\Server::find_one(array('Name'=>ZM_SERVER_HOST));
if ( ! $Server ) {
- Error('Invalid Multi-Server configration detected. ZM_SERVER_HOST set to ' . ZM_SERVER_HOST . ' in zm.conf, but no corresponding entry found in Servers table.');
+ ZM\Error('Invalid Multi-Server configration detected. ZM_SERVER_HOST set to ' . ZM_SERVER_HOST . ' in zm.conf, but no corresponding entry found in Servers table.');
} else {
define('ZM_SERVER_ID', $Server->Id());
}
@@ -199,7 +199,7 @@ function process_configfile($configFile) {
if ( is_readable( $configFile ) ) {
$configvals = array();
- $cfg = fopen($configFile, 'r') or Error("Could not open config file: $configFile.");
+ $cfg = fopen($configFile, 'r') or ZM\Error("Could not open config file: $configFile.");
while ( !feof($cfg) ) {
$str = fgets($cfg, 256);
if ( preg_match('/^\s*(#.*)?$/', $str) ) {
@@ -207,7 +207,7 @@ function process_configfile($configFile) {
} else if ( preg_match( '/^\s*([^=\s]+)\s*=\s*[\'"]*(.*?)[\'"]*\s*$/', $str, $matches )) {
$configvals[$matches[1]] = $matches[2];
} else {
- Error("Malformed line in config $configFile\n$str");
+ ZM\Error("Malformed line in config $configFile\n$str");
}
}
fclose($cfg);
diff --git a/web/includes/functions.php b/web/includes/functions.php
index 93e30fb85..42dc56c30 100644
--- a/web/includes/functions.php
+++ b/web/includes/functions.php
@@ -1090,9 +1090,8 @@ function parseFilter(&$filter, $saveToSession=false, $querySep='&') {
$terms = isset($filter['Query']) ? $filter['Query']['terms'] : NULL;
if ( !isset($terms) ) {
$backTrace = debug_backtrace();
- $file = $backTrace[1]['file'];
- $line = $backTrace[1]['line'];
- ZM\Warning("No terms in filter from $file:$line");
+ ZM\Warning('No terms in filter');
+ ZM\Warning(print_r($backTrace, true));
ZM\Warning(print_r($filter, true));
}
if ( isset($terms) && count($terms) ) {
@@ -1329,7 +1328,7 @@ function parseFilter(&$filter, $saveToSession=false, $querySep='&') {
$filter['query'] .= $querySep.urlencode("filter[Query][terms][$i][val]").'='.urlencode($term['val']);
$filter['fields'] .= "\n";
}
- } // end if ( isset($term['attr']) )
+ } // end if isset($term['attr'])
if ( isset($term['cbr']) && (string)(int)$term['cbr'] == $term['cbr'] ) {
$filter['query'] .= $querySep.urlencode("filter[Query][terms][$i][cbr]").'='.urlencode($term['cbr']);
$filter['sql'] .= ' '.str_repeat(')', $term['cbr']).' ';
@@ -1341,6 +1340,8 @@ function parseFilter(&$filter, $saveToSession=false, $querySep='&') {
if ( $saveToSession ) {
$_SESSION['filter'] = $filter;
}
+ } else {
+ $filter['query'] = $querySep.urlencode('filter[Query][terms]=[]');
} // end if terms
#if ( 0 ) {
@@ -2609,4 +2610,12 @@ function html_radio($name, $values, $selected=null, $options=array(), $attrs=arr
return $html;
} # end sub html_radio
+
+function random_colour() {
+ return '#'.
+ str_pad( dechex( mt_rand( 0, 255 ) ), 2, '0', STR_PAD_LEFT).
+ str_pad( dechex( mt_rand( 0, 255 ) ), 2, '0', STR_PAD_LEFT).
+ str_pad( dechex( mt_rand( 0, 255 ) ), 2, '0', STR_PAD_LEFT);
+}
+
?>
diff --git a/web/skins/classic/css/base/views/controlcap.css b/web/skins/classic/css/base/views/controlcap.css
new file mode 100644
index 000000000..ed9a664e7
--- /dev/null
+++ b/web/skins/classic/css/base/views/controlcap.css
@@ -0,0 +1,4 @@
+
+input[type="number"] {
+ width: 70px;
+}
diff --git a/web/skins/classic/css/base/views/controlcaps.css b/web/skins/classic/css/base/views/controlcaps.css
index 1a2783fd7..d860d88ae 100644
--- a/web/skins/classic/css/base/views/controlcaps.css
+++ b/web/skins/classic/css/base/views/controlcaps.css
@@ -1,3 +1,9 @@
-#content table.major .colCanMove, #content table.major .colCanZoom, #content table.major .colCanFocus, #content table.major .colCanIris, #content table.major .colCanWhiteBal, #content table.major .colHasPresets {
+#content table.major .colCanMove,
+#content table.major .colCanZoom,
+#content table.major .colCanFocus,
+#content table.major .colCanIris,
+#content table.major .colCanWhiteBal,
+#content table.major .colHasPresets {
text-align: center;
}
+
diff --git a/web/skins/classic/includes/export_functions.php b/web/skins/classic/includes/export_functions.php
index 02d0d86dd..8ce0fba5a 100644
--- a/web/skins/classic/includes/export_functions.php
+++ b/web/skins/classic/includes/export_functions.php
@@ -113,17 +113,17 @@ function exportEventDetail($event, $exportFrames, $exportImages) {
| Id() ?> |
| Name()) ?> |
- | MonitorName()) ?> (MonitorId() ?>) |
+ | Monitor()->Name()) ?> (MonitorId() ?>) |
| Cause()) ?> |
| Notes()) ?> |
- | StartTime()) ) ?> |
+ | StartTime())) ?> |
| Length() ?> |
| Frames() ?> |
| AlarmFrames() ?> |
| TotScore() ?> |
| AvgScore() ?> |
| MaxScore() ?> |
- | Archived()?translate('Yes'):translate('No') ?> |
+ | Archived()?'Yes':'No') ?> |
@@ -226,13 +226,13 @@ function exportEventImages($event, $exportDetail, $exportFrames, $myfilelist) {
?>
@@ -247,7 +247,7 @@ function exportEventImages($event, $exportDetail, $exportFrames, $myfilelist) {
if ( $Monitor->VideoWriter() == '2' ) {
# Passthrough
$Rotation = $event->Orientation();
- if ( in_array($event->Orientation(),array('90','270')) )
+ if ( in_array($event->Orientation(),array('ROTATE_90','ROTATE_270')) )
$Zoom = $event->Height()/$event->Width();
}
?>
@@ -280,7 +280,7 @@ function exportEventImages($event, $exportDetail, $exportFrames, $myfilelist) {
+ onmousedown="slide(event,'horizontal', Width()-20)?>, 1, , ,0, 'imageslider_display_id');">
@@ -618,10 +618,10 @@ function exportEventImagesMaster($eids) {
Master
$eids));
+
+ foreach ($events as $event) {
//get monitor id and event id
- $event = new ZM\Event($eid);
$eventMonitorId[$eid] = $event->MonitorId();
$eventPath[$eid] = $event->Relative_Path();
}
@@ -653,20 +653,18 @@ function exportEventImagesMaster($eids) {
All
";
echo 'Monitor: ' . $monitorNames[$monitor_id] . '
';
- foreach ( $eids as $eid ) {
- $Event = new ZM\Event($eid);
- if ( $Event->MonitorId() == $monitor_id ) {
- eventlist_html($Event);
+ foreach ( $events as $event ) {
+ if ( $event->MonitorId() == $monitor_id ) {
+ eventlist_html($event);
} # end if its the right monitor
} # end foreach event
echo '';
@@ -780,7 +778,7 @@ function exportFileList($event, $exportDetail, $exportFrames, $exportImages, $ex
}
fwrite($fp, exportEventDetail($event, $exportFrames, $exportImages));
fclose($fp);
- $exportFileList[$file] = $event->Id().'/'.$file;
+ $exportFileList[$file] = $file;
}
if ( $exportFrames ) {
$file = 'zmEventFrames.html';
@@ -789,7 +787,7 @@ function exportFileList($event, $exportDetail, $exportFrames, $exportImages, $ex
}
fwrite($fp, exportEventFrames($event, $exportDetail, $exportImages));
fclose($fp);
- $exportFileList[$file] = $event->Id().'/'.$file;
+ $exportFileList[$file] = $file;
}
if ( $exportImages ) {
@@ -797,7 +795,7 @@ function exportFileList($event, $exportDetail, $exportFrames, $exportImages, $ex
$myfilelist = array();
foreach ( $files as $file ) {
if ( preg_match('/-(?:capture|analyse).jpg$/', $file ) ) {
- $myfilelist[$file] = $exportFileList[$file] = $event->Id().'/'.$file;
+ $myfilelist[$file] = $exportFileList[$file] = $file;
} else {
$filesLeft[$file] = $file;
}
@@ -806,12 +804,12 @@ function exportFileList($event, $exportDetail, $exportFrames, $exportImages, $ex
// create an image slider
if ( !empty($myfilelist) ) {
- $file = $event->Id().'/zmEventImages.html';
+ $file = 'zmEventImages.html';
if ( !($fp = fopen($file, 'w')) )
ZM\Fatal("Can't open event images export file '$file'");
fwrite($fp, exportEventImages($event, $exportDetail, $exportFrames, $myfilelist));
fclose($fp);
- $exportFileList[$file] = $event->Id().'/'.$file;
+ $exportFileList[$file] = $file;
}
} # end if exportImages
@@ -819,7 +817,7 @@ function exportFileList($event, $exportDetail, $exportFrames, $exportImages, $ex
$filesLeft = array();
foreach ( $files as $file ) {
if ( preg_match('/\.(?:mpg|mpeg|mov|swf|mp4|mkv|avi|asf|3gp)$/', $file) ) {
- $exportFileList[$file] = $event->Id().'/'.$file;
+ $exportFileList[$file] = $file;
} else {
$filesLeft[$file] = $file;
}
@@ -829,7 +827,7 @@ function exportFileList($event, $exportDetail, $exportFrames, $exportImages, $ex
if ( $exportMisc ) {
foreach ( $files as $file ) {
- $exportFileList[$file] = $event->Id().'/'.$file;
+ $exportFileList[$file] = $file;
}
$files = array();
}
@@ -850,10 +848,10 @@ function exportEvents(
) {
if ( !canView('Events') ) {
- ZM\Error("You do not have permission to view events.");
+ ZM\Error('You do not have permission to view events.');
return false;
} else if ( empty($eids) ) {
- ZM\Error("Attempt to export an empty list of events.");
+ ZM\Error('Attempt to export an empty list of events.');
return false;
}
@@ -863,23 +861,22 @@ function exportEvents(
}
# Ensure that we are going to be able to do this.
- if ( ! file_exists(ZM_DIR_EXPORTS) ) {
- if ( ! mkdir(ZM_DIR_EXPORTS) ) {
- ZM\Fatal("Can't create exports dir at '".ZM_DIR_EXPORTS."'");
- }
+ if ( ! ( mkdir(ZM_DIR_EXPORTS) or file_exists(ZM_DIR_EXPORTS) ) ) {
+ ZM\Fatal('Can\'t create exports dir at \''.ZM_DIR_EXPORTS.'\'');
}
+ chmod(ZM_DIR_EXPORTS, 0700);
$export_dir = ZM_DIR_EXPORTS.'/zmExport_'.$connkey;
# Ensure that we are going to be able to do this.
- if ( ! file_exists($export_dir) ) {
- if ( ! mkdir($export_dir) ) {
- ZM\Fatal("Can't create exports dir at '$export_dir'");
- } else {
- ZM\Logger::Debug("Successfully created dir '$export_dir'");
- }
+ if ( ! ( mkdir($export_dir) or file_exists($export_dir) ) ) {
+ ZM\Fatal("Can't create exports dir at '$export_dir'");
+ } else {
+ ZM\Logger::Debug("Successfully created dir '$export_dir'");
}
- if ( !chdir($export_dir) )
+ chmod($export_dir, 0700);
+ if ( !chdir($export_dir) ) {
ZM\Fatal("Can't chdir to $export_dir");
+ }
$export_root = 'zmExport';
$export_listFile = 'zmFileList.txt';
@@ -889,27 +886,30 @@ function exportEvents(
if ( !is_array($eids) ) {
$eids = array($eids);
}
- ZM\Logger::Debug("Eids: " . print_r($eids,true));
+ ZM\Logger::Debug('Eids: ' . print_r($eids,true));
foreach ( $eids as $eid ) {
$event = new ZM\Event($eid);
$event_dir = $export_dir.'/'.$event->Id();
- if ( !mkdir($event_dir) )
+ if ( !(mkdir($event_dir) or file_exists($event_dir) ) ) {
ZM\Error("Can't mkdir $event_dir");
+ }
$event_exportFileList = exportFileList($event, $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc);
ZM\Logger::Debug("File list for event $eid " . print_r($event_exportFileList, true));
$exportFileList = array_merge($exportFileList,$event_exportFileList);
foreach ( $event_exportFileList as $file ) {
- if ( preg_match('/\.html$/', $file ) )
+ if ( preg_match('/\.html$/', $file) )
continue;
- ZM\Logger::Debug('cp -as '.$event->Path().'/../'.$file.' '.$export_dir.'/'.$file);
- exec('cp -as '.$event->Path().'/../'.$file.' '.$export_dir.'/'.$file);
+ #exec('cp -as '.$event->Path().'/../'.$file.' '.$export_dir.'/'.$file, $output, $return);
+ $cmd = 'cp -as '.$event->Path().'/'.$file.' '.$export_dir.'/'.$event->Id().'/'.$file. ' 2>&1';
+ exec($cmd, $output, $return);
+ ZM\Logger::Debug($cmd.' return code: '.$return.' output: '.print_r($output,true));
}
- }
+ } # end foreach event
// create an master image
if ( $exportImages ) {
if ( !symlink(ZM_PATH_WEB.'/'.ZM_SKIN_PATH.'/js/jquery.js', $export_dir.'/jquery.js') )
- ZM\Error("Failed linking jquery.js");
+ ZM\Error('Failed linking jquery.js');
//if ( !symlink(ZM_PATH_WEB.'/'.ZM_SKIN_PATH.'/js/video.js', $export_dir.'/video.js') )
//Error("Failed linking video.js");
@@ -960,12 +960,12 @@ function exportEvents(
@unlink($archive);
$command .= ' zmExport_' . $connkey.'/';
- ZM\Logger::Debug("Command is $command");
exec($command, $output, $status);
if ( $status ) {
ZM\Error("Command '$command' returned with status $status");
- if ( isset($output[0]) )
- ZM\Error("First line of output is '".$output[0]."'");
+ if ( isset($output[0]) ) {
+ ZM\Error('First line of output is \''.$output[0].'\'');
+ }
return false;
}
diff --git a/web/skins/classic/includes/functions.php b/web/skins/classic/includes/functions.php
index 60558f8e8..328b63833 100644
--- a/web/skins/classic/includes/functions.php
+++ b/web/skins/classic/includes/functions.php
@@ -290,12 +290,12 @@ if ( $user and $user['Username'] ) {
# zmaudit can clean the logs, but if we aren't running it, then we should clean them regularly
if ( preg_match('/^\d+$/', ZM_LOG_DATABASE_LIMIT) ) {
# Number of lines, instead of an interval
- $rows = dbFetchOne('SELECT Count(*) AS Rows FROM Logs', 'Rows');
+ $rows = dbFetchOne('SELECT Count(*) AS `Rows` FROM `Logs`', 'Rows');
if ( $rows > ZM_LOG_DATABASE_LIMIT ) {
- dbQuery('DELETE low_priority FROM Logs ORDER BY TimeKey ASC LIMIT ?', array($rows - ZM_LOG_DATABASE_LIMIT));
+ dbQuery('DELETE low_priority FROM `Logs` ORDER BY `TimeKey` ASC LIMIT ?', array($rows - ZM_LOG_DATABASE_LIMIT));
}
} else if ( preg_match('/^\d\s*(hour|minute|day|week|month|year)$/', ZM_LOG_DATABASE_LIMIT, $matches) ) {
- dbQuery('DELETE FROM Logs WHERE TimeKey < unix_timestamp( NOW() - interval '.ZM_LOG_DATABASE_LIMIT.') LIMIT 100');
+ dbQuery('DELETE FROM `Logs` WHERE `TimeKey` < unix_timestamp( NOW() - interval '.ZM_LOG_DATABASE_LIMIT.') LIMIT 100');
} else {
ZM\Error('Potentially invalid value for ZM_LOG_DATABASE_LIMIT: ' . ZM_LOG_DATABASE_LIMIT);
}
diff --git a/web/skins/classic/js/base.js b/web/skins/classic/js/base.js
index 4ecc4c234..48747b98d 100644
--- a/web/skins/classic/js/base.js
+++ b/web/skins/classic/js/base.js
@@ -29,7 +29,7 @@ var popupSizes = {
'console': {'width': 750, 'height': 312},
'control': {'width': 480, 'height': 480},
'controlcaps': {'width': 780, 'height': 320},
- 'controlcap': {'width': 400, 'height': 400},
+ 'controlcap': {'width': 600, 'height': 500},
'cycle': {'addWidth': 32, 'minWidth': 384, 'addHeight': 62},
'device': {'width': 260, 'height': 150},
'devices': {'width': 400, 'height': 240},
diff --git a/web/skins/classic/js/skin.js b/web/skins/classic/js/skin.js
index 5ccddf96b..9e705bbc3 100644
--- a/web/skins/classic/js/skin.js
+++ b/web/skins/classic/js/skin.js
@@ -175,12 +175,13 @@ window.addEventListener("DOMContentLoaded", function onSkinDCL() {
});
// 'data-on-click' calls the global function in the attribute value with no arguments when a click happens.
- document.querySelectorAll("a[data-on-click], button[data-on-click], input[data-on-click]").forEach(function attachOnClick(el) {
+ document.querySelectorAll("i[data-on-click], a[data-on-click], button[data-on-click], input[data-on-click]").forEach(function attachOnClick(el) {
var fnName = el.getAttribute("data-on-click");
if ( !window[fnName] ) {
console.error("Nothing found to bind to " + fnName + " on element " + el.name);
return;
}
+
el.onclick = function() {
window[fnName]();
};
diff --git a/web/skins/classic/views/console.php b/web/skins/classic/views/console.php
index 8d8b08ff6..b910b11fa 100644
--- a/web/skins/classic/views/console.php
+++ b/web/skins/classic/views/console.php
@@ -187,7 +187,8 @@ getBodyTopHTML();
translate('New'),
'Type' => "Local",
@@ -166,16 +157,12 @@ xhtmlHeaders(__FILE__, translate('ControlCap')." - ".$newControl['Name'] );