Merge branch 'master' of github.com:zoneminder/ZoneMinder

This commit is contained in:
Isaac Connor 2020-01-05 17:28:50 -05:00
commit fd633a2175
62 changed files with 1335 additions and 1170 deletions

View File

@ -33,24 +33,23 @@ install:
env: env:
- SMPFLAGS=-j4 OS=el DIST=7 - SMPFLAGS=-j4 OS=el DIST=7
- SMPFLAGS=-j4 OS=el DIST=8 - SMPFLAGS=-j4 OS=el DIST=8 DOCKER_REPO=knnniggett/packpack
- SMPFLAGS=-j4 OS=fedora DIST=29 DOCKER_REPO=knnniggett/packpack
- SMPFLAGS=-j4 OS=fedora DIST=30 - SMPFLAGS=-j4 OS=fedora DIST=30
- SMPFLAGS=-j4 OS=ubuntu DIST=trusty DOCKER_REPO=iconzm/packpack USE_SFTP=yes - SMPFLAGS=-j4 OS=fedora DIST=31
- SMPFLAGS=-j4 OS=ubuntu DIST=xenial DOCKER_REPO=iconzm/packpack USE_SFTP=yes - SMPFLAGS=-j4 OS=ubuntu DIST=trusty DOCKER_REPO=iconzm/packpack
- SMPFLAGS=-j4 OS=ubuntu DIST=bionic DOCKER_REPO=iconzm/packpack USE_SFTP=yes - SMPFLAGS=-j4 OS=ubuntu DIST=xenial DOCKER_REPO=iconzm/packpack
- SMPFLAGS=-j4 OS=ubuntu DIST=disco DOCKER_REPO=iconzm/packpack USE_SFTP=yes - SMPFLAGS=-j4 OS=ubuntu DIST=bionic DOCKER_REPO=iconzm/packpack
- SMPFLAGS=-j4 OS=ubuntu DIST=eoan DOCKER_REPO=iconzm/packpack USE_SFTP=yes - SMPFLAGS=-j4 OS=ubuntu DIST=disco DOCKER_REPO=iconzm/packpack
- SMPFLAGS=-j4 OS=debian DIST=jessie DOCKER_REPO=iconzm/packpack USE_SFTP=yes - SMPFLAGS=-j4 OS=ubuntu DIST=eoan DOCKER_REPO=iconzm/packpack
- SMPFLAGS=-j4 OS=debian DIST=stretch DOCKER_REPO=iconzm/packpack USE_SFTP=yes - SMPFLAGS=-j4 OS=debian DIST=jessie DOCKER_REPO=iconzm/packpack
- SMPFLAGS=-j4 OS=debian DIST=buster DOCKER_REPO=iconzm/packpack USE_SFTP=yes - 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=trusty ARCH=i386
- SMPFLAGS=-j4 OS=ubuntu DIST=xenial 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=ubuntu DIST=disco ARCH=i386
- SMPFLAGS=-j4 OS=debian DIST=buster ARCH=i386 - SMPFLAGS=-j4 OS=debian DIST=buster ARCH=i386
- SMPFLAGS=-j4 OS=debian DIST=stretch 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: compiler:
- gcc - gcc
@ -58,12 +57,6 @@ services:
- mysql - mysql
- docker - 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: script:
- utils/packpack/startpackpack.sh - utils/packpack/startpackpack.sh

View File

@ -434,6 +434,7 @@ DROP TABLE IF EXISTS `Monitors`;
CREATE TABLE `Monitors` ( CREATE TABLE `Monitors` (
`Id` int(10) unsigned NOT NULL auto_increment, `Id` int(10) unsigned NOT NULL auto_increment,
`Name` varchar(64) NOT NULL default '', `Name` varchar(64) NOT NULL default '',
`Notes` TEXT,
`ServerId` int(10) unsigned, `ServerId` int(10) unsigned,
`StorageId` smallint(5) unsigned default 0, `StorageId` smallint(5) unsigned default 0,
`Type` enum('Local','Remote','File','Ffmpeg','Libvlc','cURL','WebSite','NVSocket') NOT NULL default 'Local', `Type` enum('Local','Remote','File','Ffmpeg','Libvlc','cURL','WebSite','NVSocket') NOT NULL default 'Local',

12
db/zm_update-1.33.16.sql Normal file
View File

@ -0,0 +1,12 @@
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Monitors'
AND column_name = 'Notes'
) > 0,
"SELECT 'Column Notes already exists in Monitors'",
"ALTER TABLE `Monitors` ADD `Notes` TEXT AFTER `Name`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;

View File

@ -22,14 +22,10 @@ What's New
switching between httpd <-> nginx requires manaully changing ownership of switching between httpd <-> nginx requires manaully changing ownership of
all event folders and the php session folder after the change. all event folders and the php session folder after the change.
4. If you have installed ZoneMinder from the FedBerry repositories, this build 4. The timezone must now be set from the ZoneMinder web console. See the
of ZoneMinder has support for Raspberry Pi hardware acceleration when using appropriate README, mentioned in the next step, for details.
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
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.httpd - Follow these steps when using Apache
README.nginx - Follow these steps when using Nginx README.nginx - Follow these steps when using Nginx

View File

@ -36,20 +36,17 @@ NOTE: EL7 users should replace "dnf" with "yum" in the instructions below.
sudo chown root:apache *.conf sudo chown root:apache *.conf
sudo chmod 640 *.conf sudo chmod 640 *.conf
4. Edit /etc/php.ini, uncomment the date.timezone line, and add your local 4. Manually setting the timezone in /etc/php.ini is deprecated.
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.
If you are not sure of the proper timezone specification to use, look at Instead, navigate to Options -> System from the ZoneMinder web console.
http://php.net/date.timezone 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 5. Disable SELinux
We currently do not have the resources to create and maintain an accurate SELinux must be disabled or put into permissive mode. This is not optional!
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.
To immediately disbale SELinux for the current seesion, issue the following To immediately disbale SELinux for the current seesion, issue the following
from the command line: from the command line:
@ -166,3 +163,11 @@ Upgrades
sudo systemctl restart httpd sudo systemctl restart httpd
sudo systemctl start zoneminder 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.

View File

@ -34,13 +34,13 @@ New installs
sudo chown root:nginx *.conf sudo chown root:nginx *.conf
sudo chmod 640 *.conf sudo chmod 640 *.conf
4. Edit /etc/php.ini, uncomment the date.timezone line, and add your local 4. Manually setting the timezone in /etc/php.ini is deprecated.
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.
If you are not sure of the proper timezone specification to use, look at Instead, navigate to Options -> System from the ZoneMinder web console.
http://php.net/date.timezone 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 5. Disable SELinux
@ -169,3 +169,11 @@ Upgrades
sudo systemctl restart php-fpm sudo systemctl restart php-fpm
sudo systemctl start zoneminder 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.

View File

@ -14,16 +14,21 @@
# This will tell zoneminder's cmake process we are building against a known distro # This will tell zoneminder's cmake process we are building against a known distro
%global zmtargetdistro %{?rhel:el%{rhel}}%{!?rhel:fc%{fedora}} %global zmtargetdistro %{?rhel:el%{rhel}}%{!?rhel:fc%{fedora}}
# Fedora >= 25 needs apcu backwards compatibility module # Fedora needs apcu backwards compatibility module
%if 0%{?fedora} >= 25 %if 0%{?fedora}
%global with_apcu_bc 1 %global with_apcu_bc 1
%endif %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 # The default for everything but el7 these days
%global _hardened_build 1 %global _hardened_build 1
Name: zoneminder Name: zoneminder
Version: 1.33.14 Version: 1.33.16
Release: 1%{?dist} Release: 1%{?dist}
Summary: A camera monitoring and analysis tool Summary: A camera monitoring and analysis tool
Group: System Environment/Daemons Group: System Environment/Daemons
@ -105,7 +110,7 @@ Summary: Common files for ZoneMinder, not tied to a specific web server
Requires: php-mysqli Requires: php-mysqli
Requires: php-common Requires: php-common
Requires: php-gd Requires: php-gd
%{?fedora:Requires: php-json} %{?with_php_json:Requires: php-json}
Requires: php-pecl-apcu Requires: php-pecl-apcu
%{?with_apcu_bc:Requires: php-pecl-apcu-bc} %{?with_apcu_bc:Requires: php-pecl-apcu-bc}
Requires: cambozola Requires: cambozola
@ -411,6 +416,9 @@ EOF
%dir %attr(755,nginx,nginx) %{_localstatedir}/spool/zoneminder-upload %dir %attr(755,nginx,nginx) %{_localstatedir}/spool/zoneminder-upload
%changelog %changelog
* Sun Dec 08 2019 Isaac Connor <isaac@zoneminder.com> - 1.33.15-1
- Bump to 1.33.15 Development
* Sun Aug 11 2019 Andrew Bauer <zonexpertconsulting@outlook.com> - 1.33.14-1 * Sun Aug 11 2019 Andrew Bauer <zonexpertconsulting@outlook.com> - 1.33.14-1
- Bump to 1.33.13 Development - Bump to 1.33.13 Development

View File

@ -74,7 +74,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
,libfile-slurp-perl ,libfile-slurp-perl
,mysql-client | mariadb-client | virtual-mysql-client ,mysql-client | mariadb-client | virtual-mysql-client
,perl-modules ,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
,policykit-1 ,policykit-1
,rsyslog | system-log-daemon ,rsyslog | system-log-daemon
,zip ,zip

View File

@ -28,3 +28,4 @@ zmtelemetry\[[[:digit:]]+\]: INF \[Telemetry data uploaded successfully.\]$
zmtelemetry\[[[:digit:]]+\]: INF \[Sending data to ZoneMinder Telemetry server.\]$ zmtelemetry\[[[:digit:]]+\]: INF \[Sending data to ZoneMinder Telemetry server.\]$
zmtelemetry\[[[:digit:]]+\]: INF \[Collec?ting data to send 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:]]+"\]$ web_php\[[[:digit:]]+\]: INF \[Login successful for user "[[:alnum:]]+"\]$
zmeventnotification\[[[:digit:]]+\]: INF

View File

@ -1127,7 +1127,7 @@ our @options = (
}, },
{ {
name => 'ZM_LOG_LEVEL_FILE', name => 'ZM_LOG_LEVEL_FILE',
default => '-5', default => '1',
description => 'Save logging output to component files', description => 'Save logging output to component files',
help => q` help => q`
ZoneMinder logging is now more integrated between ZoneMinder logging is now more integrated between
@ -1312,7 +1312,7 @@ our @options = (
}, },
{ {
name => 'ZM_LOG_DEBUG_FILE', name => 'ZM_LOG_DEBUG_FILE',
default => '@ZM_LOGDIR@/zm_debug.log+', default => '',
description => 'Where extra debug is output to', description => 'Where extra debug is output to',
help => q` help => q`
This option allows you to specify a different target for debug This option allows you to specify a different target for debug
@ -2468,7 +2468,7 @@ our @options = (
}, },
{ {
name => 'ZM_WATCH_MAX_DELAY', name => 'ZM_WATCH_MAX_DELAY',
default => '5', default => '45',
description => 'The maximum delay allowed since the last captured image', description => 'The maximum delay allowed since the last captured image',
help => q` help => q`
The zmwatch daemon checks the image capture performance of the The zmwatch daemon checks the image capture performance of the

View File

@ -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 # Change Log
# #
@ -38,6 +38,7 @@ use Time::HiRes qw( usleep );
require ZoneMinder::Base; require ZoneMinder::Base;
require ZoneMinder::Control; require ZoneMinder::Control;
require LWP::UserAgent;
our @ISA = qw(ZoneMinder::Control); our @ISA = qw(ZoneMinder::Control);
@ -50,130 +51,109 @@ our @ISA = qw(ZoneMinder::Control);
use ZoneMinder::Logger qw(:all); use ZoneMinder::Logger qw(:all);
use ZoneMinder::Config qw(:all); use ZoneMinder::Config qw(:all);
sub new sub new {
{ my $class = shift;
my $class = shift; my $id = shift;
my $id = shift; my $self = ZoneMinder::Control->new($id);
my $self = ZoneMinder::Control->new( $id ); bless($self, $class);
bless( $self, $class ); return $self;
srand( time() );
return $self;
} }
our $AUTOLOAD; sub open {
my $self = shift;
sub AUTOLOAD $self->loadMonitor();
{ my $username;
my $self = shift; my $password;
my $class = ref($self) || croak( "$self not object" ); my $realm = 'Login to ' . $self->{Monitor}->{ControlDevice};
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" );
}
sub open if ( $self->{Monitor}->{ControlAddress} =~ /(.*):(.*)@(.*)/ ) {
{ $username = $1;
my $self = shift; $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'; $self->{state} = 'open';
} return;
}
sub initUA if ( $res->status_line() eq '401 Unauthorized' ) {
{
my $self = shift;
my $user = undef;
my $password = undef;
my $address = undef;
if ( $self->{Monitor}->{ControlAddress} =~ /(.*):(.*)@(.*)/ ) my $headers = $res->headers();
{ foreach my $k ( keys %$headers ) {
$user = $1; Debug("Initial Header $k => $$headers{$k}");
$password = $2;
$address = $3;
} }
use LWP::UserAgent; if ( $$headers{'www-authenticate'} ) {
$self->{ua} = LWP::UserAgent->new; my ( $auth, $tokens ) = $$headers{'www-authenticate'} =~ /^(\w+)\s+(.*)$/;
$self->{ua}->credentials("$address", "Login to " . $self->{Monitor}->{ControlDevice}, "$user", "$password"); if ( $tokens =~ /\w+="([^"]+)"/i ) {
$self->{ua}->agent( "ZoneMinder Control Agent/".ZoneMinder::Base::ZM_VERSION ); 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 sub close {
{ my $self = shift;
my $self = shift; $self->{state} = 'closed';
$self->{ua} = undef;
} }
sub close sub sendCmd {
{ my $self = shift;
my $self = shift; my $cmd = shift;
$self->{state} = 'closed'; 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 sub reset {
{ my $self = shift;
my $self = shift; # This reboots the camera effectively resetting it
my $msg = shift; $self->sendCmd('cgi-bin/magicBox.cgi?action=reboot');
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);
} }
# NOTE: I'm putting this in, but absolute camera movement does not seem to be well supported in the classic skin ATM. # 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... sub moveAbs ## Up, Down, Left, Right, etc. ??? Doesn't make sense here...
{ {
my $self = shift; my $self = shift;
my $pan_degrees = shift || 0; my $pan_degrees = shift || 0;
my $tilt_degrees = shift || 0; my $tilt_degrees = shift || 0;
my $speed = shift || 1; my $speed = shift || 1;
Debug( "Move ABS" ); 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 ); $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=PositionABS&channel=0&arg1='.$pan_degrees.'&arg2='.$tilt_degrees.'&arg3=0&arg4='.$speed);
} }
sub moveConUp sub moveConUp {
{ my $self = shift;
my $self = shift; Debug('Move Up');
Debug( "Move Up" ); $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=Up&channel=0&arg1=0&arg2=1&arg3=0');
$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?
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');
$self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=Up&channel=0&arg1=0&arg2=1&arg3=0' );
} }
sub moveConDown sub moveConDown {
{ my $self = shift;
my $self = shift; Debug('Move Down');
Debug( "Move Down" ); $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=Down&channel=0&arg1=0&arg2=1&arg3=0');
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=Down&channel=0&arg1=0&arg2=1&arg3=0' ); usleep(500);
usleep (500); $self->sendCmd('cgi-bin/ptz.cgi?action=stop&code=Down&channel=0&arg1=0&arg2=1&arg3=0');
$self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=Down&channel=0&arg1=0&arg2=1&arg3=0' );
} }
sub moveConLeft sub moveConLeft {
{ my $self = shift;
my $self = shift; Debug('Move Left');
Debug( "Move Left" ); $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=Left&channel=0&arg1=0&arg2=1&arg3=0');
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=Left&channel=0&arg1=0&arg2=1&arg3=0' ); usleep(500);
usleep (500); $self->sendCmd('cgi-bin/ptz.cgi?action=stop&code=Left&channel=0&arg1=0&arg2=1&arg3=0');
$self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=Left&channel=0&arg1=0&arg2=1&arg3=0' );
} }
sub moveConRight sub moveConRight {
{ my $self = shift;
my $self = shift; Debug('Move Right');
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=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');
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=Right&channel=0&arg1=0&arg2=1&arg3=0' ); usleep(500);
usleep (500); Debug('Move Right Stop');
Debug( "Move Right Stop" ); $self->sendCmd('cgi-bin/ptz.cgi?action=stop&code=Right&channel=0&arg1=0&arg2=1&arg3=0');
$self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=Right&channel=0&arg1=0&arg2=1&arg3=0' );
} }
sub moveConUpRight sub moveConUpRight {
{ my $self = shift;
my $self = shift; Debug('Move Diagonally Up Right');
Debug( "Move Diagonally Up Right" ); $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=RightUp&channel=0&arg1=1&arg2=1&arg3=0');
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=RightUp&channel=0&arg1=1&arg2=1&arg3=0' ); usleep(500);
usleep (500); $self->sendCmd('cgi-bin/ptz.cgi?action=stop&code=RightUp&channel=0&arg1=0&arg2=1&arg3=0');
$self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=RightUp&channel=0&arg1=0&arg2=1&arg3=0' );
} }
sub moveConDownRight sub moveConDownRight {
{ my $self = shift;
my $self = shift; Debug('Move Diagonally Down Right');
Debug( "Move Diagonally Down Right" ); $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=RightDown&channel=0&arg1=1&arg2=1&arg3=0');
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=RightDown&channel=0&arg1=1&arg2=1&arg3=0' ); usleep(500);
usleep (500); $self->sendCmd('cgi-bin/ptz.cgi?action=stop&code=RightDown&channel=0&arg1=0&arg2=1&arg3=0');
$self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=RightDown&channel=0&arg1=0&arg2=1&arg3=0' );
} }
sub moveConUpLeft sub moveConUpLeft {
{ my $self = shift;
my $self = shift; Debug('Move Diagonally Up Left');
Debug( "Move Diagonally Up Left" ); $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=LeftUp&channel=0&arg1=1&arg2=1&arg3=0');
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=LeftUp&channel=0&arg1=1&arg2=1&arg3=0' ); usleep(500);
usleep (500); $self->sendCmd('cgi-bin/ptz.cgi?action=stop&code=LeftUp&channel=0&arg1=0&arg2=1&arg3=0');
$self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=LeftUp&channel=0&arg1=0&arg2=1&arg3=0' );
} }
sub moveConDownLeft sub moveConDownLeft {
{ my $self = shift;
my $self = shift; Debug('Move Diagonally Down Left');
Debug( "Move Diagonally Down Left" ); $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=LeftDown&channel=0&arg1=1&arg2=1&arg3=0');
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=LeftDown&channel=0&arg1=1&arg2=1&arg3=0' ); usleep (500);
usleep (500); $self->sendCmd('cgi-bin/ptz.cgi?action=stop&code=LeftDown&channel=0&arg1=0&arg2=1&arg3=0');
$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" # 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 # 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. # support a generic stop-all-current-action command.
sub moveStop sub moveStop {
{ my $self = shift;
my $self = shift; Debug('Move Stop/Center');
Debug( "Move Stop/Center" ); $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=PositionABS&channel=0&arg1=0&arg2=0&arg3=0&arg4=1');
$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 # 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 # 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. # NOTE: It goes without saying that the user must have set up preset #1 for this to work.
sub presetHome sub presetHome {
{ my $self = shift;
my $self = shift; Debug('Home Preset');
Debug( "Home Preset" ); $self->sendCmd('cgi-bin/ptz.cgi?action=start&channel=0&code=GotoPreset&&arg1=0&arg2=1&arg3=0&arg4=0');
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&channel=0&code=GotoPreset&&arg1=0&arg2=1&arg3=0&arg4=0' );
} }
sub presetGoto sub presetGoto {
{ my $self = shift;
my $self = shift; my $params = shift;
my $params = shift; my $preset = $self->getParam($params, 'preset');
my $preset = $self->getParam( $params, 'preset' ); Debug("Go To Preset $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');
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&channel=0&code=GotoPreset&&arg1=0&arg2='.$preset.'&arg3=0&arg4=0' );
} }
sub presetSet sub presetSet {
{ my $self = shift;
my $self = shift; my $params = shift;
my $params = shift; my $preset = $self->getParam($params, 'preset');
my $preset = $self->getParam( $params, 'preset' ); Debug('Set Preset');
Debug( "Set Preset" ); $self->sendCmd('cgi-bin/ptz.cgi?action=start&channel=0&code=SetPreset&arg1=0&arg2='.$preset.'&arg3=0&arg4=0');
$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. # NOTE: This does not appear to be implemented in the classic skin. But we'll leave it here for later.
sub moveMap sub moveMap {
{ my $self = shift;
my $self = shift; my $params = shift;
my $params = shift;
my $xcoord = $self->getParam( $params, 'xcoord', $self->{Monitor}{Width}/2 ); my $xcoord = $self->getParam( $params, 'xcoord', $self->{Monitor}{Width}/2 );
my $ycoord = $self->getParam( $params, 'ycoord', $self->{Monitor}{Height}/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 # 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 # just use 360 minus pan instead of pan, 90 minus tilt instead of tilt
# Convert xcoord into pan position 0 to 359 # Convert xcoord into pan position 0 to 359
my $pan = int(360 * $xcoord / $self->{Monitor}{Width}); my $pan = int(360 * $xcoord / $self->{Monitor}{Width});
# Convert ycoord into tilt position 0 to 89 # Convert ycoord into tilt position 0 to 89
my $tilt = 90 - int(90 * $ycoord / $self->{Monitor}{Height}); my $tilt = 90 - int(90 * $ycoord / $self->{Monitor}{Height});
# Now get the following url: # 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'); $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=PositionABS&channel=0&arg1='.$pan.'&arg2='.$tilt.'&arg3=1&arg4=1');
} }
sub zoomConTele sub zoomConTele {
{ my $self = shift;
my $self = shift; Debug('Zoom continuous tele');
Debug( "Zoom continuous tele" ); $self->sendCmd('cgi-bin/ptz.cgi?action=start&channel=0&code=ZoomTele&arg1=0&arg2=0&arg3=0&arg4=0');
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&channel=0&code=ZoomTele&arg1=0&arg2=0&arg3=0&arg4=0' ); usleep(100000);
usleep (100000); $self->sendCmd('cgi-bin/ptz.cgi?action=stop&channel=0&code=ZoomTele&arg1=0&arg2=0&arg3=0&arg4=0');
$self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&channel=0&code=ZoomTele&arg1=0&arg2=0&arg3=0&arg4=0' );
} }
sub zoomConWide sub zoomConWide {
{ my $self = shift;
my $self = shift; Debug('Zoom continuous wide');
Debug( "Zoom continuous wide" ); $self->sendCmd('cgi-bin/ptz.cgi?action=start&channel=0&code=ZoomWide&arg1=0&arg2=0&arg3=0&arg4=0');
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&channel=0&code=ZoomWide&arg1=0&arg2=0&arg3=0&arg4=0' ); usleep (100000);
usleep (100000); $self->sendCmd('cgi-bin/ptz.cgi?action=stop&channel=0&code=ZoomWide&arg1=0&arg2=0&arg3=0&arg4=0');
$self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&channel=0&code=ZoomWide&arg1=0&arg2=0&arg3=0&arg4=0' );
} }
1; 1;

View File

@ -1,6 +1,6 @@
# ========================================================================== # ==========================================================================
# #
# ZoneMinder Airlink SkyIPCam AICN747/AICN747W Control Protocol Module, $Date: 2008-09-13 17:30:29 +0000 (Sat, 13 Sept 2008) $, $Revision: 2229 $ # ZoneMinder Airlink SkyIPCam AICN747/AICN747W Control Protocol Module
# Copyright (C) 2008 Brian Rudy (brudyNO@SPAMpraecogito.com) # Copyright (C) 2008 Brian Rudy (brudyNO@SPAMpraecogito.com)
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
@ -43,8 +43,6 @@ our @ISA = qw(ZoneMinder::Control);
use ZoneMinder::Logger qw(:all); use ZoneMinder::Logger qw(:all);
use ZoneMinder::Config qw(:all); use ZoneMinder::Config qw(:all);
use Time::HiRes qw( usleep );
sub open { sub open {
my $self = shift; my $self = shift;
@ -52,58 +50,50 @@ sub open {
use LWP::UserAgent; use LWP::UserAgent;
$self->{ua} = LWP::UserAgent->new; $self->{ua} = LWP::UserAgent->new;
$self->{ua}->agent( "ZoneMinder Control Agent/".ZoneMinder::Base::ZM_VERSION ); $self->{ua}->agent('ZoneMinder Control Agent/'.ZoneMinder::Base::ZM_VERSION);
$self->{state} = 'open'; $self->{state} = 'open';
} }
sub printMsg {
my $self = shift;
my $msg = shift;
my $msg_len = length($msg);
Debug( $msg."[".$msg_len."]" );
}
sub sendCmd { sub sendCmd {
my $self = shift; my $self = shift;
my $cmd = shift; my $cmd = shift;
my $result = undef; my $result = undef;
printMsg( $cmd, "Tx" ); $self->printMsg($cmd, 'Tx');
my $url; my $url;
if ( $self->{Monitor}->{ControlAddress} =~ /^http/ ) { if ( $self->{Monitor}->{ControlAddress} =~ /^http/i ) {
$url = $self->{Monitor}->{ControlAddress}.$cmd; $url = $self->{Monitor}->{ControlAddress}.$cmd;
} else { } else {
$url = 'http://'.$self->{Monitor}->{ControlAddress}.$cmd; $url = 'http://'.$self->{Monitor}->{ControlAddress}.$cmd;
} # en dif } # end if
my $req = HTTP::Request->new( GET=>$url ); my $req = HTTP::Request->new(GET=>$url);
my $res = $self->{ua}->request($req); my $res = $self->{ua}->request($req);
if ( $res->is_success ) { if ( $res->is_success ) {
$result = !undef; $result = !undef;
} else { } else {
Error( "Error check failed: '".$res->status_line()."'" ); Error('Error check failed: \''.$res->status_line().'\'');
} }
return( $result ); return $result;
} }
sub reset { sub reset {
my $self = shift; my $self = shift;
Debug( "Camera Reset" ); Debug('Camera Reset');
my $cmd = "/admin/ptctl.cgi?move=reset"; my $cmd = '/admin/ptctl.cgi?move=reset';
$self->sendCmd( $cmd ); $self->sendCmd($cmd);
} }
sub moveMap { sub moveMap {
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
my $xcoord = $self->getParam( $params, 'xcoord' ); my $xcoord = $self->getParam($params, 'xcoord');
my $ycoord = $self->getParam( $params, 'ycoord' ); my $ycoord = $self->getParam($params, 'ycoord');
my $hor = $xcoord * 100 / $self->{Monitor}->{Width}; my $hor = $xcoord * 100 / $self->{Monitor}->{Width};
my $ver = $ycoord * 100 / $self->{Monitor}->{Height}; my $ver = $ycoord * 100 / $self->{Monitor}->{Height};
@ -125,81 +115,81 @@ sub moveMap {
elsif ( $hor > 50 ) { elsif ( $hor > 50 ) {
# right # right
$horSteps = (($hor - 50) / 50) * $maxhor; $horSteps = (($hor - 50) / 50) * $maxhor;
$horDir = "right"; $horDir = 'right';
} }
# Vertical movement # Vertical movement
if ( $ver < 50 ) { if ( $ver < 50 ) {
# up # up
$verSteps = ((50 - $ver) / 50) * $maxver; $verSteps = ((50 - $ver) / 50) * $maxver;
$verDir = "up"; $verDir = 'up';
} }
elsif ( $ver > 50 ) { elsif ( $ver > 50 ) {
# down # down
$verSteps = (($ver - 50) / 50) * $maxver; $verSteps = (($ver - 50) / 50) * $maxver;
$verDir = "down"; $verDir = 'down';
} }
my $v = int($verSteps); my $v = int($verSteps);
my $h = int($horSteps); my $h = int($horSteps);
Debug( "Move Map to $xcoord,$ycoord, hor=$h $horDir, ver=$v $verDir"); Debug("Move Map to $xcoord,$ycoord, hor=$h $horDir, ver=$v $verDir");
my $cmd = "/cgi/admin/ptctrl.cgi?action=movedegree&Cmd=$horDir&Degree=$h"; my $cmd = "/cgi/admin/ptctrl.cgi?action=movedegree&Cmd=$horDir&Degree=$h";
$self->sendCmd( $cmd ); $self->sendCmd($cmd);
$cmd = "/cgi/admin/ptctrl.cgi?action=movedegree&Cmd=$verDir&Degree=$v"; $cmd = "/cgi/admin/ptctrl.cgi?action=movedegree&Cmd=$verDir&Degree=$v";
$self->sendCmd( $cmd ); $self->sendCmd($cmd);
} }
sub moveRelUp { sub moveRelUp {
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
my $step = $self->getParam( $params, 'tiltstep' ); my $step = $self->getParam($params, 'tiltstep');
Debug( "Step Up $step" ); Debug("Step Up $step");
my $cmd = "/admin/ptctl.cgi?move=up"; my $cmd = '/admin/ptctl.cgi?move=up';
$self->sendCmd( $cmd ); $self->sendCmd($cmd);
} }
sub moveRelDown { sub moveRelDown {
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
my $step = $self->getParam( $params, 'tiltstep' ); my $step = $self->getParam($params, 'tiltstep');
Debug( "Step Down $step" ); Debug("Step Down $step");
my $cmd = "/admin/ptctl.cgi?move=down"; my $cmd = '/admin/ptctl.cgi?move=down';
$self->sendCmd( $cmd ); $self->sendCmd($cmd);
} }
sub moveRelLeft { sub moveRelLeft {
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
my $step = $self->getParam( $params, 'panstep' ); my $step = $self->getParam($params, 'panstep');
if ( $self->{Monitor}->{Orientation} eq "hori" ) { if ( $self->{Monitor}->{Orientation} eq 'FLIP_HORI' ) {
Debug( "Stepping Right because flipped horizontally " ); Debug('Stepping Right because flipped horizontally');
$self->sendCmd( "/admin/ptctl.cgi?move=right" ); $self->sendCmd('/admin/ptctl.cgi?move=right');
} else { } else {
Debug( "Step Left" ); Debug('Step Left');
$self->sendCmd( "/admin/ptctl.cgi?move=left" ); $self->sendCmd('/admin/ptctl.cgi?move=left');
} }
} }
sub moveRelRight { sub moveRelRight {
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
my $step = $self->getParam( $params, 'panstep' ); my $step = $self->getParam($params, 'panstep');
if ( $self->{Monitor}->{Orientation} eq "hori" ) { if ( $self->{Monitor}->{Orientation} eq 'FLIP_HORI' ) {
Debug( "Stepping Left because flipped horizontally " ); Debug('Stepping Left because flipped horizontally');
$self->sendCmd( "/admin/ptctl.cgi?move=left" ); $self->sendCmd('/admin/ptctl.cgi?move=left');
} else { } else {
Debug( "Step Right" ); Debug('Step Right');
$self->sendCmd( "/admin/ptctl.cgi?move=right" ); $self->sendCmd('/admin/ptctl.cgi?move=right');
} }
} }
sub presetClear { sub presetClear {
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
my $preset = $self->getParam( $params, 'preset' ); my $preset = $self->getParam($params, 'preset');
Debug( "Clear Preset $preset" ); Debug("Clear Preset $preset");
#my $cmd = "/axis-cgi/com/ptz.cgi?removeserverpresetno=$preset"; #my $cmd = "/axis-cgi/com/ptz.cgi?removeserverpresetno=$preset";
#$self->sendCmd( $cmd ); #$self->sendCmd( $cmd );
} }
@ -207,26 +197,26 @@ sub presetClear {
sub presetSet { sub presetSet {
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
my $preset = $self->getParam( $params, 'preset' ); my $preset = $self->getParam($params, 'preset');
Debug( "Set Preset $preset" ); Debug("Set Preset $preset");
my $cmd = "/admin/ptctl.cgi?position=" . ($preset - 1) . "&positionname=zm$preset"; my $cmd = '/admin/ptctl.cgi?position=' . ($preset - 1) . "&positionname=zm$preset";
$self->sendCmd( $cmd ); $self->sendCmd( $cmd );
} }
sub presetGoto { sub presetGoto {
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
my $preset = $self->getParam( $params, 'preset' ); my $preset = $self->getParam($params, 'preset');
Debug( "Goto Preset $preset" ); Debug("Goto Preset $preset");
my $cmd = "/admin/ptctl.cgi?move=p" . ($preset - 1); my $cmd = '/admin/ptctl.cgi?move=p'.($preset - 1);
$self->sendCmd( $cmd ); $self->sendCmd($cmd);
} }
sub presetHome { sub presetHome {
my $self = shift; my $self = shift;
Debug( "Home Preset" ); Debug('Home Preset');
my $cmd = "/admin/ptctl.cgi?move=h"; my $cmd = '/admin/ptctl.cgi?move=h';
$self->sendCmd( $cmd ); $self->sendCmd($cmd);
} }
1; 1;

View File

@ -81,7 +81,7 @@ void FFMPEGInit() {
av_log_set_callback(log_libav_callback); av_log_set_callback(log_libav_callback);
Info("Enabling ffmpeg logs, as LOG_DEBUG+LOG_FFMPEG are enabled in options"); Info("Enabling ffmpeg logs, as LOG_DEBUG+LOG_FFMPEG are enabled in options");
} else { } 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); av_log_set_level(AV_LOG_QUIET);
} }
#if !LIBAVFORMAT_VERSION_CHECK(58, 9, 0, 64, 0) #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) #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
void zm_dump_codecpar ( const AVCodecParameters *par ) { 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)", 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, par->codec_type,
par->codec_id, av_get_media_type_string(par->codec_type),
avcodec_get_name(par->codec_id), par->codec_id,
par->codec_tag, avcodec_get_name(par->codec_id),
par->width, par->codec_tag,
par->height, par->width,
par->bit_rate, par->height,
par->format, par->bit_rate,
((AVPixelFormat)par->format == AV_PIX_FMT_NONE ? "none" : av_get_pix_fmt_name((AVPixelFormat)par->format)) par->format,
); (((AVPixelFormat)par->format == AV_PIX_FMT_NONE) ? "none" : av_get_pix_fmt_name((AVPixelFormat)par->format))
);
} }
#endif #endif

View File

@ -1087,6 +1087,7 @@ int FfmpegCamera::transfer_to_image(
return -1; return -1;
} }
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0) #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( int size = av_image_fill_arrays(
output_frame->data, output_frame->linesize, output_frame->data, output_frame->linesize,
directbuffer, imagePixFormat, width, height, 32); directbuffer, imagePixFormat, width, height, 32);
@ -1128,8 +1129,8 @@ int FfmpegCamera::transfer_to_image(
mConvertContext, input_frame->data, input_frame->linesize, mConvertContext, input_frame->data, input_frame->linesize,
0, mVideoCodecContext->height, 0, mVideoCodecContext->height,
output_frame->data, output_frame->linesize); output_frame->data, output_frame->linesize);
if ( ret <= 0 ) { 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", 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->format, av_get_pix_fmt_name((AVPixelFormat)input_frame->format),
input_frame->linesize, mVideoCodecContext->height, input_frame->linesize, mVideoCodecContext->height,
imagePixFormat, imagePixFormat,
@ -1137,6 +1138,7 @@ int FfmpegCamera::transfer_to_image(
output_frame->linesize, output_frame->linesize,
frameCount, frameCount,
mVideoCodecContext->pix_fmt, av_get_pix_fmt_name(mVideoCodecContext->pix_fmt), mVideoCodecContext->pix_fmt, av_get_pix_fmt_name(mVideoCodecContext->pix_fmt),
mVideoCodecContext->height,
ret ret
); );
return -1; return -1;

View File

@ -10,6 +10,7 @@ FFmpeg_Input::FFmpeg_Input() {
FFMPEGInit(); FFMPEGInit();
streams = NULL; streams = NULL;
frame = NULL; frame = NULL;
last_seek_request = -1;
} }
FFmpeg_Input::~FFmpeg_Input() { FFmpeg_Input::~FFmpeg_Input() {
@ -102,7 +103,6 @@ int FFmpeg_Input::Open(const char *filepath) {
} // end int FFmpeg_Input::Open( const char * filepath ) } // end int FFmpeg_Input::Open( const char * filepath )
AVFrame *FFmpeg_Input::get_frame(int stream_id) { AVFrame *FFmpeg_Input::get_frame(int stream_id) {
Debug(1, "Getting frame from stream %d", stream_id);
int frameComplete = false; int frameComplete = false;
AVPacket packet; AVPacket packet;
@ -138,12 +138,14 @@ AVFrame *FFmpeg_Input::get_frame(int stream_id) {
frame = zm_av_frame_alloc(); frame = zm_av_frame_alloc();
} }
ret = zm_send_packet_receive_frame(context, frame, packet); ret = zm_send_packet_receive_frame(context, frame, packet);
if ( ret <= 0 ) { if ( ret < 0 ) {
Error("Unable to decode frame at frame %d: %s, continuing", Error("Unable to decode frame at frame %d: %s, continuing",
streams[packet.stream_index].frame_count, av_make_error_string(ret).c_str()); streams[packet.stream_index].frame_count, av_make_error_string(ret).c_str());
zm_av_packet_unref(&packet); zm_av_packet_unref(&packet);
av_frame_free(&frame); av_frame_free(&frame);
continue; continue;
} else {
zm_dump_frame(frame, "resulting frame");
} }
frameComplete = 1; frameComplete = 1;
@ -175,9 +177,20 @@ AVFrame *FFmpeg_Input::get_frame(int stream_id, double at) {
} }
// Have to grab a frame to update our current frame to know where we are // Have to grab a frame to update our current frame to know where we are
get_frame(stream_id); get_frame(stream_id);
} // end if ! frame } // end if ! frame
if ( frame->pts > seek_target ) { if ( !frame ) {
Warning("Unable to get frame.");
return NULL;
}
if (
(last_seek_request >= 0)
&&
(last_seek_request > seek_target )
&&
(frame->pts > seek_target)
) {
zm_dump_frame(frame, "frame->pts > seek_target, seek backwards"); zm_dump_frame(frame, "frame->pts > seek_target, seek backwards");
// our frame must be beyond our seek target. so go backwards to before it // our frame must be beyond our seek target. so go backwards to before it
if ( ( ret = av_seek_frame(input_format_context, stream_id, seek_target, if ( ( ret = av_seek_frame(input_format_context, stream_id, seek_target,
@ -191,6 +204,8 @@ AVFrame *FFmpeg_Input::get_frame(int stream_id, double at) {
zm_dump_frame(frame, "frame->pts > seek_target, got"); zm_dump_frame(frame, "frame->pts > seek_target, got");
} // end if frame->pts > seek_target } // end if frame->pts > seek_target
last_seek_request = seek_target;
// Seeking seems to typically seek to a keyframe, so then we have to decode until we get the frame we want. // Seeking seems to typically seek to a keyframe, so then we have to decode until we get the frame we want.
if ( frame->pts <= seek_target ) { if ( frame->pts <= seek_target ) {
zm_dump_frame(frame, "pts <= seek_target"); zm_dump_frame(frame, "pts <= seek_target");

View File

@ -42,6 +42,7 @@ class FFmpeg_Input {
int audio_stream_id; int audio_stream_id;
AVFormatContext *input_format_context; AVFormatContext *input_format_context;
AVFrame *frame; AVFrame *frame;
int64_t last_seek_request;
}; };
#endif #endif

View File

@ -430,7 +430,7 @@ bool MonitorStream::sendFrame(Image *image, struct timeval *timestamp) {
Warning("Frame send time %d msec too slow, throttling maxfps to %.2f", Warning("Frame send time %d msec too slow, throttling maxfps to %.2f",
frameSendTime, maxfps); frameSendTime, maxfps);
} }
} } // Not mpeg
last_frame_sent = TV_2_FLOAT(now); last_frame_sent = TV_2_FLOAT(now);
return true; return true;
} // end bool MonitorStream::sendFrame( Image *image, struct timeval *timestamp ) } // end bool MonitorStream::sendFrame( Image *image, struct timeval *timestamp )
@ -474,22 +474,21 @@ void MonitorStream::runStream() {
Image *paused_image = NULL; Image *paused_image = NULL;
struct timeval paused_timestamp; 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 ) ) { 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 ) { 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); Error("Swap Path is too long. %d > %d ", total_swap_path_length+max_swap_len_suffix, PATH_MAX);
} else { } else {
swap_path = staticConfig.PATH_SWAP; 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) ) { if ( checkSwapPath(swap_path.c_str(), true) ) {
swap_path += stringtf("/zmswap-m%d", monitor->Id()); swap_path += stringtf("/zmswap-m%d", monitor->Id());
@ -509,8 +508,8 @@ void MonitorStream::runStream() {
} else { } else {
Debug(2, "Assigning temporary buffer"); Debug(2, "Assigning temporary buffer");
temp_image_buffer = new SwapImage[temp_image_buffer_count]; temp_image_buffer = new SwapImage[temp_image_buffer_count];
memset( temp_image_buffer, 0, sizeof(*temp_image_buffer)*temp_image_buffer_count ); memset(temp_image_buffer, 0, sizeof(*temp_image_buffer)*temp_image_buffer_count);
Debug( 2, "Assigned temporary buffer" ); Debug(2, "Assigned temporary buffer");
} }
} }
} else { } else {
@ -562,7 +561,7 @@ void MonitorStream::runStream() {
touch(sock_path_lock); touch(sock_path_lock);
last_comm_update = now; last_comm_update = now;
} }
} // end if connkey } // end if connkey
if ( paused ) { if ( paused ) {
if ( !was_paused ) { if ( !was_paused ) {
@ -589,7 +588,7 @@ void MonitorStream::runStream() {
} else { } else {
if ( !paused ) { if ( !paused ) {
int temp_index = MOD_ADD(temp_read_index, 0, temp_image_buffer_count); 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]; SwapImage *swap_image = &temp_image_buffer[temp_index];
if ( !swap_image->valid ) { if ( !swap_image->valid ) {
@ -597,51 +596,61 @@ void MonitorStream::runStream() {
delayed = true; delayed = true;
temp_read_index = MOD_ADD(temp_read_index, (replay_rate>=0?-1:1), temp_image_buffer_count); temp_read_index = MOD_ADD(temp_read_index, (replay_rate>=0?-1:1), temp_image_buffer_count);
} else { } else {
//Debug( 3, "siT: %f, lfT: %f", TV_2_FLOAT( swap_image->timestamp ), TV_2_FLOAT( last_frame_timestamp ) ); // 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 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; 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 the next frame is due
if ( actual_delta_time > expected_delta_time ) { 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 ) { 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 // 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; zm_terminate = true;
}
memcpy(&last_frame_timestamp, &(swap_image->timestamp), sizeof(last_frame_timestamp)); 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); temp_read_index = MOD_ADD(temp_read_index, (replay_rate>0?1:-1), temp_image_buffer_count);
} }
} }
} else if ( step != 0 ) { } 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]; SwapImage *swap_image = &temp_image_buffer[temp_read_index];
// Send the next frame // 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; 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; step = 0;
} else { } else {
//paused? //paused?
int temp_index = MOD_ADD(temp_read_index, 0, temp_image_buffer_count); int temp_index = MOD_ADD(temp_read_index, 0, temp_image_buffer_count);
double actual_delta_time = TV_2_FLOAT( now ) - last_frame_sent; double actual_delta_time = TV_2_FLOAT(now) - last_frame_sent;
if ( got_command || actual_delta_time > 5 ) { if ( got_command || (actual_delta_time > 5) ) {
// Send keepalive // Send keepalive
Debug(2, "Sending keepalive frame %d", temp_index); Debug(2, "Sending keepalive frame %d", temp_index);
// Send the next frame // 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; zm_terminate = true;
//frame_sent = true; }
// frame_sent = true;
} }
} // end if (!paused) or step or paused } // end if (!paused) or step or paused
} // end if have exceeded buffer or not } // end if have exceeded buffer or not
if ( temp_read_index == temp_write_index ) { if ( temp_read_index == temp_write_index ) {
// Go back to live viewing // Go back to live viewing
@ -652,16 +661,16 @@ void MonitorStream::runStream() {
delayed = false; delayed = false;
replay_rate = ZM_RATE_BASE; 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 ) { if ( last_read_index != monitor->shared_data->last_write_index ) {
// have a new image to send // 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 ( (frame_mod == 1) || ((frame_count%frame_mod) == 0) ) {
if ( !paused && !delayed ) { if ( !paused && !delayed ) {
last_read_index = monitor->shared_data->last_write_index; last_read_index = monitor->shared_data->last_write_index;
Debug(2, "index: %d: frame_mod: %d frame count: %d paused(%d) delayed(%d)", 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 // Send the next frame
Monitor::Snapshot *snap = &monitor->image_buffer[index]; Monitor::Snapshot *snap = &monitor->image_buffer[index];
@ -671,8 +680,12 @@ void MonitorStream::runStream() {
zm_terminate = true; zm_terminate = true;
} }
// Perhaps we should use NOW instead. // Perhaps we should use NOW instead.
memcpy(&last_frame_timestamp, snap->timestamp, sizeof(last_frame_timestamp)); memcpy(
//frame_sent = true; &last_frame_timestamp,
snap->timestamp,
sizeof(last_frame_timestamp)
);
// frame_sent = true;
temp_read_index = temp_write_index; temp_read_index = temp_write_index;
} else { } else {
@ -697,7 +710,7 @@ void MonitorStream::runStream() {
if ( !sendFrame(paused_image, &paused_timestamp) ) if ( !sendFrame(paused_image, &paused_timestamp) )
zm_terminate = true; zm_terminate = true;
} else { } 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 actual_delta_time > 5
} // end if change in zoom } // end if change in zoom
@ -718,21 +731,21 @@ void MonitorStream::runStream() {
temp_index); temp_index);
temp_image_buffer[temp_index].valid = true; 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) ); 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 ); 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 ); temp_write_index = MOD_ADD(temp_write_index, 1, temp_image_buffer_count);
if ( temp_write_index == temp_read_index ) { if ( temp_write_index == temp_read_index ) {
// Go back to live viewing // Go back to live viewing
Warning( "Exceeded temporary buffer, resuming live play" ); Warning("Exceeded temporary buffer, resuming live play");
paused = false; paused = false;
delayed = false; delayed = false;
replay_rate = ZM_RATE_BASE; replay_rate = ZM_RATE_BASE;
} }
} else { } else {
Warning( "Unable to store frame as timestamp invalid" ); Warning("Unable to store frame as timestamp invalid");
} }
} else { } else {
Warning( "Unable to store frame as shared memory invalid" ); Warning("Unable to store frame as shared memory invalid");
} }
} // end if buffered playback } // end if buffered playback
frame_count++; frame_count++;
@ -755,10 +768,10 @@ void MonitorStream::runStream() {
break; 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. // 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; 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); frame_mod, frame_count);
} else if ( } else if (
(!paused) (!paused)
@ -799,9 +812,9 @@ void MonitorStream::runStream() {
} }
} }
} }
globfree( &pglob ); globfree(&pglob);
if ( rmdir(swap_path.c_str()) < 0 ) { 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 checking for swap_path
} // end if buffered_playback } // end if buffered_playback
@ -809,7 +822,7 @@ void MonitorStream::runStream() {
closeComms(); closeComms();
} // end MonitorStream::runStream } // end MonitorStream::runStream
void MonitorStream::SingleImage( int scale ) { void MonitorStream::SingleImage(int scale) {
int img_buffer_size = 0; int img_buffer_size = 0;
static JOCTET img_buffer[ZM_MAX_IMAGE_SIZE]; static JOCTET img_buffer[ZM_MAX_IMAGE_SIZE];
Image scaled_image; Image scaled_image;
@ -817,42 +830,45 @@ void MonitorStream::SingleImage( int scale ) {
Image *snap_image = snap->image; Image *snap_image = snap->image;
if ( scale != ZM_SCALE_BASE ) { if ( scale != ZM_SCALE_BASE ) {
scaled_image.Assign( *snap_image ); scaled_image.Assign(*snap_image);
scaled_image.Scale( scale ); scaled_image.Scale(scale);
snap_image = &scaled_image; snap_image = &scaled_image;
} }
if ( !config.timestamp_on_capture ) { 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 ); snap_image->EncodeJpeg(img_buffer, &img_buffer_size);
fprintf( stdout, "Content-Length: %d\r\n", img_buffer_size ); fprintf(stdout,
fprintf( stdout, "Content-Type: image/jpeg\r\n\r\n" ); "Content-Length: %d\r\n"
fwrite( img_buffer, img_buffer_size, 1, stdout ); "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; Image scaled_image;
Monitor::Snapshot *snap = monitor->getSnapshot(); Monitor::Snapshot *snap = monitor->getSnapshot();
Image *snap_image = snap->image; Image *snap_image = snap->image;
if ( scale != ZM_SCALE_BASE ) { if ( scale != ZM_SCALE_BASE ) {
scaled_image.Assign( *snap_image ); scaled_image.Assign(*snap_image);
scaled_image.Scale( scale ); scaled_image.Scale(scale);
snap_image = &scaled_image; snap_image = &scaled_image;
} }
if ( !config.timestamp_on_capture ) { 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,
fprintf( stdout, "Content-Type: image/x-rgb\r\n\r\n" ); "Content-Length: %d\r\n"
fwrite( snap_image->Buffer(), snap_image->Size(), 1, stdout ); "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 #ifdef HAVE_ZLIB_H
void MonitorStream::SingleImageZip( int scale ) { void MonitorStream::SingleImageZip(int scale) {
unsigned long img_buffer_size = 0; unsigned long img_buffer_size = 0;
static Bytef img_buffer[ZM_MAX_IMAGE_SIZE]; static Bytef img_buffer[ZM_MAX_IMAGE_SIZE];
Image scaled_image; Image scaled_image;
@ -861,17 +877,19 @@ void MonitorStream::SingleImageZip( int scale ) {
Image *snap_image = snap->image; Image *snap_image = snap->image;
if ( scale != ZM_SCALE_BASE ) { if ( scale != ZM_SCALE_BASE ) {
scaled_image.Assign( *snap_image ); scaled_image.Assign(*snap_image);
scaled_image.Scale( scale ); scaled_image.Scale(scale);
snap_image = &scaled_image; snap_image = &scaled_image;
} }
if ( !config.timestamp_on_capture ) { 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 ); snap_image->Zip(img_buffer, &img_buffer_size);
fprintf( stdout, "Content-Length: %ld\r\n", img_buffer_size ); fprintf(stdout,
fprintf( stdout, "Content-Type: image/x-rgbz\r\n\r\n" ); "Content-Length: %ld\r\n"
fwrite( img_buffer, img_buffer_size, 1, stdout ); "Content-Type: image/x-rgbz\r\n\r\n",
img_buffer_size);
fwrite(img_buffer, img_buffer_size, 1, stdout);
} }
#endif // HAVE_ZLIB_H #endif // HAVE_ZLIB_H

View File

@ -175,7 +175,7 @@ cd ../
VERSION=`cat ${GITHUB_FORK}_zoneminder_release/version` VERSION=`cat ${GITHUB_FORK}_zoneminder_release/version`
if [ $VERSION == "" ]; then if [ -z "$VERSION" ]; then
exit 1; exit 1;
fi; fi;
if [ "$SNAPSHOT" != "stable" ] && [ "$SNAPSHOT" != "" ]; then if [ "$SNAPSHOT" != "stable" ] && [ "$SNAPSHOT" != "" ]; then

View File

@ -1,5 +1,10 @@
#!/bin/bash #!/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 # Check to see if this script has access to all the commands it needs
for CMD in sshfs rsync find fusermount mkdir; do for CMD in sshfs rsync find fusermount mkdir; do
type $CMD 2>&1 > /dev/null type $CMD 2>&1 > /dev/null
@ -12,53 +17,26 @@ for CMD in sshfs rsync find fusermount mkdir; do
fi fi
done done
# We only want to deploy packages during cron events if [ "${OS}" == "debian" ] || [ "${OS}" == "ubuntu" ] || [ "${OS}" == "raspbian" ]; then
# See https://docs.travis-ci.com/user/cron-jobs/ targetfolder="debian/master/mini-dinstall/incoming"
if [ "${TRAVIS_EVENT_TYPE}" == "cron" ] || [ "${OS}" == "debian" ] || [ "${OS}" == "ubuntu" ]; then else
targetfolder="travis"
if [ "${OS}" == "debian" ] || [ "${OS}" == "ubuntu" ]; then fi
targetfolder="debian/master/mini-dinstall/incoming"
else echo
targetfolder="travis" echo "Target subfolder set to $targetfolder"
fi echo
echo echo "Running \$(rsync -v -e 'ssh -vvv' build/*.{rpm,deb,dsc,tar.xz,changes} zmrepo@zmrepo.zoneminder.com:${targetfolder}/ 2>&1)"
echo "Target subfolder set to $targetfolder" 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
echo if [ "$?" -eq 0 ]; then
if [ "${USE_SFTP}" == "yes" ]; then echo
echo "Running \$(rsync -v -e 'ssh -vvv' build/* zmrepo@zmrepo.zoneminder.com:${targetfolder}/ 2>&1)" echo "Files copied successfully."
rsync -v -e 'ssh -vvv' build/* zmrepo@zmrepo.zoneminder.com:${targetfolder}/ 2>&1 echo
if [ $? -eq 0 ]; then else
echo echo
echo "Files copied successfully." echo "ERROR: Attempt to rsync to zmrepo.zoneminder.com failed!"
echo echo "See log output for details."
else echo
echo exit 99
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
fi fi

View File

@ -9,7 +9,7 @@
# General sanity checks # General sanity checks
checksanity () { checksanity () {
# Check to see if this script has access to all the commands it needs # 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 type $CMD 2>&1 > /dev/null
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
@ -30,7 +30,7 @@ checksanity () {
ARCH="x86_64" ARCH="x86_64"
fi fi
if [[ "${ARCH}" != "x86_64" && "${ARCH}" != "i386" && "${ARCH}" != "armhf" ]]; then if [[ "${ARCH}" != "x86_64" && "${ARCH}" != "i386" && "${ARCH}" != "armhf" && "${ARCH}" != "aarch64" ]]; then
echo echo
echo "ERROR: Unsupported architecture specified \"${ARCH}\"." echo "ERROR: Unsupported architecture specified \"${ARCH}\"."
echo echo
@ -150,7 +150,7 @@ install_deb () {
exit 1 exit 1
fi 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" pkgname="build/zoneminder_${VERSION}-${RELEASE}_amd64.deb"
if [ -e $pkgname ]; then if [ -e $pkgname ]; then
@ -275,6 +275,8 @@ checkdeploytarget () {
echo "*** TRACEROUTE ***" echo "*** TRACEROUTE ***"
echo echo
traceroute -w 2 -m 15 ${DEPLOYTARGET} traceroute -w 2 -m 15 ${DEPLOYTARGET}
exit 97
fi fi
} }
@ -291,43 +293,43 @@ if [ "${TRAVIS}" == "true" ]; then
fi fi
checksanity 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 # Steps common to Redhat distros
if [ "${OS}" == "el" ] || [ "${OS}" == "fedora" ]; then if [ "${OS}" == "el" ] || [ "${OS}" == "fedora" ]; then
if [ "${TRAVIS_EVENT_TYPE}" == "cron" ] || [ "${TRAVIS}" != "true" ]; then commonprep
commonprep echo "Begin Redhat build..."
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 ln -sfT distros/redhat rpm
rm -rf web/api/app/Plugin/Crud
mkdir web/api/app/Plugin/Crud
reporpm="rpmfusion-free-release" # The rpm specfile requires the Crud submodule folder to be empty
dlurl="https://download1.rpmfusion.org/free/${OS}/${reporpm}-${DIST}.noarch.rpm" 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 reporpm="rpmfusion-free-release"
if [ -n "$dlurl" ] && [ $? -eq 0 ]; then dlurl="https://download1.rpmfusion.org/free/${OS}/${reporpm}-${DIST}.noarch.rpm"
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
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..." setrpmchangelog
execpackpack
fi; echo "Starting packpack..."
# Steps common to Debian based distros execpackpack
# Steps common to Debian based distros
elif [ "${OS}" == "debian" ] || [ "${OS}" == "ubuntu" ] || [ "${OS}" == "raspbian" ]; then elif [ "${OS}" == "debian" ] || [ "${OS}" == "ubuntu" ] || [ "${OS}" == "raspbian" ]; then
commonprep commonprep
echo "Begin ${OS} ${DIST} build..." echo "Begin ${OS} ${DIST} build..."
@ -348,14 +350,27 @@ elif [ "${OS}" == "debian" ] || [ "${OS}" == "ubuntu" ] || [ "${OS}" == "raspbia
echo "Starting packpack..." echo "Starting packpack..."
execpackpack execpackpack
# We were not triggered via cron so just build and test trusty # Try to install and run the newly built zoneminder package
if [ "${OS}" == "ubuntu" ] && [ "${DIST}" == "xenial" ] && [ "${ARCH}" == "x86_64" ]; then if [ "${OS}" == "ubuntu" ] && [ "${DIST}" == "xenial" ] && [ "${ARCH}" == "x86_64" ] && [ "${TRAVIS}" == "true" ]; then
# If we are running inside Travis then attempt to install the deb we just built echo "Begin Deb package installation..."
if [ "${TRAVIS}" == "true" ]; then
install_deb install_deb
fi
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 fi
exit 0

View File

@ -1 +1 @@
1.33.15 1.33.16

View File

@ -41,7 +41,7 @@ function buildLogQuery($action) {
} }
foreach ( $filter as $field=>$value ) { 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)); ZM\Error("'$field' is not in valid filter fields " . print_r($filterField,true));
continue; continue;
} }
@ -58,7 +58,7 @@ function buildLogQuery($action) {
$sql .= ' ORDER BY '.$sortField.' '.$sortOrder.' LIMIT '.$limit; $sql .= ' ORDER BY '.$sortField.' '.$sortOrder.' LIMIT '.$limit;
return array('sql'=>$sql, 'values'=>$values); return array('sql'=>$sql, 'values'=>$values);
} } # function buildLogQuery($action)
switch ( $_REQUEST['task'] ) { switch ( $_REQUEST['task'] ) {
case 'create' : case 'create' :
@ -70,14 +70,16 @@ switch ( $_REQUEST['task'] ) {
$string = $_POST['message']; $string = $_POST['message'];
$file = !empty($_POST['file']) ? preg_replace( '/\w+:\/\/[\w.:]+\//', '', $_POST['file'] ) : ''; $file = !empty($_POST['file']) ? preg_replace( '/\w+:\/\/[\w.:]+\//', '', $_POST['file'] ) : '';
if ( !empty( $_POST['line'] ) ) if ( !empty( $_POST['line'] ) ) {
$line = validInt($_POST['line']); $line = validInt($_POST['line']);
else } else {
$line = NULL; $line = NULL;
}
$levels = array_flip(ZM\Logger::$codes); $levels = array_flip(ZM\Logger::$codes);
if ( !isset($levels[$_POST['level']]) ) if ( !isset($levels[$_POST['level']]) ) {
ZM\Panic('Unexpected logger level '.$_POST['level']); ZM\Panic('Unexpected logger level '.$_POST['level']);
}
$level = $levels[$_POST['level']]; $level = $levels[$_POST['level']];
ZM\Logger::fetch()->logPrint($level, $string, $file, $line); ZM\Logger::fetch()->logPrint($level, $string, $file, $line);
} }
@ -141,6 +143,10 @@ switch ( $_REQUEST['task'] ) {
$logs[] = $log; $logs[] = $log;
} }
foreach ( $options as $field => $values ) {
asort($options[$field]);
}
$available = count($logs); $available = count($logs);
ajaxResponse( array( ajaxResponse( array(
'updated' => preg_match('/%/', DATE_FMT_CONSOLE_LONG)?strftime(DATE_FMT_CONSOLE_LONG):date(DATE_FMT_CONSOLE_LONG), 'updated' => preg_match('/%/', DATE_FMT_CONSOLE_LONG)?strftime(DATE_FMT_CONSOLE_LONG):date(DATE_FMT_CONSOLE_LONG),

View File

@ -77,16 +77,24 @@ class GroupsController extends AppController {
} }
$this->Group->create(); $this->Group->create();
if ( $this->Group->save($this->request->data) ) {
if ( $this->request->data['Group']['MonitorIds'] and ! isset($this->request->data['Monitor']) ) {
$this->request->data['Monitor'] = explode(',', $this->request->data['Group']['MonitorIds']);
unset($this->request->data['Group']['MonitorIds']);
}
if ( $this->Group->saveAssociated($this->request->data, array('atomic'=>true)) ) {
return $this->flash( return $this->flash(
__('The group has been saved.'), __('The group has been saved.'),
array('action' => 'index') array('action' => 'index')
); );
} } else {
} ZM\Error("Failed to save Group");
$monitors = $this->Group->Monitor->find('list'); debug($this->Group->invalidFields());
}
} # end if post
$monitors = $this->Group->Monitor->find('list');
$this->set(compact('monitors')); $this->set(compact('monitors'));
} } # end add
/** /**
* edit method * edit method

View File

@ -136,7 +136,7 @@ class HostController extends AppController {
}*/ }*/
$access_issued_at = time(); $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 // by default access token will expire in 2 hrs
// you can change it by changing the value of ZM_AUTH_HASH_TLL // you can change it by changing the value of ZM_AUTH_HASH_TLL

View File

@ -44,33 +44,25 @@ class MonitorsController extends AppController {
} else { } else {
$conditions = array(); $conditions = array();
} }
global $user; global $user;
$allowedMonitors = $user ? preg_split('@,@', $user['MonitorIds'], NULL, PREG_SPLIT_NO_EMPTY) : null; $allowedMonitors = $user ? preg_split('@,@', $user['MonitorIds'], NULL, PREG_SPLIT_NO_EMPTY) : null;
if ( $allowedMonitors ) { if ( $allowedMonitors ) {
$conditions['Monitor.Id' ] = $allowedMonitors; $conditions['Monitor.Id' ] = $allowedMonitors;
} }
$find_array = array('conditions'=>$conditions,'contain'=>array('Group'));
if ( isset($conditions['GroupId']) ) { $find_array = array(
$find_array['joins'] = array( 'conditions' => &$conditions,
'contain' => array('Group'),
'joins' => array(
array( array(
'table' => 'Groups_Monitors', 'table' => 'Groups_Monitors',
'type' => 'inner', 'type' => 'left',
'conditions' => array( '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); $monitors = $this->Monitor->find('all',$find_array);
$this->set(array( $this->set(array(
'monitors' => $monitors, 'monitors' => $monitors,

View File

@ -59,7 +59,7 @@ class Group extends AppModel {
* *
* @var array * @var array
*/ */
public $hasMany = array( public $hasAndBelongsToMany = array(
'Monitor' => array( 'Monitor' => array(
'className' => 'Monitor', 'className' => 'Monitor',
'joinTable' => 'Groups_Monitors', 'joinTable' => 'Groups_Monitors',
@ -77,4 +77,5 @@ class Group extends AppModel {
'counterQuery' => '' 'counterQuery' => ''
), ),
); );
var $actsAs = array( 'Containable' );
} }

View File

@ -128,12 +128,16 @@ class Control extends ZM_Object {
$cmds['PresetHome'] = 'presetHome'; $cmds['PresetHome'] = 'presetHome';
if ( $this->CanZoom() ) { if ( $this->CanZoom() ) {
if ( $this->CanZoomCon() ) if ( $this->CanZoomCon() ) {
$cmds['ZoomRoot'] = 'zoomCon'; $cmds['ZoomRoot'] = 'zoomCon';
elseif ( $this->CanZoomRel() ) } else if ( $this->CanZoomRel() ) {
$cmds['ZoomRoot'] = 'zoomRel'; $cmds['ZoomRoot'] = 'zoomRel';
elseif ( $this->CanZoomAbs() ) } else if ( $this->CanZoomAbs() ) {
$cmds['ZoomRoot'] = 'zoomAbs'; $cmds['ZoomRoot'] = 'zoomAbs';
} else {
$cmds['ZoomRoot'] = '';
Error('No zoom type selected. Please select Continuous, Relative, Absolute');
}
$cmds['ZoomTele'] = $cmds['ZoomRoot'].'Tele'; $cmds['ZoomTele'] = $cmds['ZoomRoot'].'Tele';
$cmds['ZoomWide'] = $cmds['ZoomRoot'].'Wide'; $cmds['ZoomWide'] = $cmds['ZoomRoot'].'Wide';
$cmds['ZoomStop'] = 'zoomStop'; $cmds['ZoomStop'] = 'zoomStop';
@ -142,12 +146,16 @@ class Control extends ZM_Object {
} }
if ( $this->CanFocus() ) { if ( $this->CanFocus() ) {
if ( $this->CanFocusCon() ) if ( $this->CanFocusCon() ) {
$cmds['FocusRoot'] = 'focusCon'; $cmds['FocusRoot'] = 'focusCon';
elseif ( $this->CanFocusRel() ) } else if ( $this->CanFocusRel() ) {
$cmds['FocusRoot'] = 'focusRel'; $cmds['FocusRoot'] = 'focusRel';
elseif ( $this->CanFocusAbs() ) } else if ( $this->CanFocusAbs() ) {
$cmds['FocusRoot'] = 'focusAbs'; $cmds['FocusRoot'] = 'focusAbs';
} else {
$cmds['FocusRoot'] = '';
Error('No focus type selected. Please select Continuous, Relative, Absolute');
}
$cmds['FocusFar'] = $cmds['FocusRoot'].'Far'; $cmds['FocusFar'] = $cmds['FocusRoot'].'Far';
$cmds['FocusNear'] = $cmds['FocusRoot'].'Near'; $cmds['FocusNear'] = $cmds['FocusRoot'].'Near';
$cmds['FocusStop'] = 'focusStop'; $cmds['FocusStop'] = 'focusStop';
@ -156,12 +164,16 @@ class Control extends ZM_Object {
} }
if ( $this->CanIris() ) { if ( $this->CanIris() ) {
if ( $this->CanIrisCon() ) if ( $this->CanIrisCon() ) {
$cmds['IrisRoot'] = 'irisCon'; $cmds['IrisRoot'] = 'irisCon';
elseif ( $this->CanIrisRel() ) } else if ( $this->CanIrisRel() ) {
$cmds['IrisRoot'] = 'irisRel'; $cmds['IrisRoot'] = 'irisRel';
elseif ( $this->CanIrisAbs() ) } else if ( $this->CanIrisAbs() ) {
$cmds['IrisRoot'] = 'irisAbs'; $cmds['IrisRoot'] = 'irisAbs';
} else {
$cmds['IrisRoot'] = '';
Error('No iris type selected. Please select Continuous, Relative, Absolute');
}
$cmds['IrisOpen'] = $cmds['IrisRoot'].'Open'; $cmds['IrisOpen'] = $cmds['IrisRoot'].'Open';
$cmds['IrisClose'] = $cmds['IrisRoot'].'Close'; $cmds['IrisClose'] = $cmds['IrisRoot'].'Close';
$cmds['IrisStop'] = 'irisStop'; $cmds['IrisStop'] = 'irisStop';
@ -170,12 +182,16 @@ class Control extends ZM_Object {
} }
if ( $this->CanWhite() ) { if ( $this->CanWhite() ) {
if ( $this->CanWhiteCon() ) if ( $this->CanWhiteCon() ) {
$cmds['WhiteRoot'] = 'whiteCon'; $cmds['WhiteRoot'] = 'whiteCon';
elseif ( $this->CanWhiteRel() ) } else if ( $this->CanWhiteRel() ) {
$cmds['WhiteRoot'] = 'whiteRel'; $cmds['WhiteRoot'] = 'whiteRel';
elseif ( $this->CanWhiteAbs() ) } else if ( $this->CanWhiteAbs() ) {
$cmds['WhiteRoot'] = 'whiteAbs'; $cmds['WhiteRoot'] = 'whiteAbs';
} else {
Error('No White type selected. Please select Continuous, Relative, Absolute');
$cmds['WhiteRoot'] = '';
}
$cmds['WhiteIn'] = $cmds['WhiteRoot'].'In'; $cmds['WhiteIn'] = $cmds['WhiteRoot'].'In';
$cmds['WhiteOut'] = $cmds['WhiteRoot'].'Out'; $cmds['WhiteOut'] = $cmds['WhiteRoot'].'Out';
$cmds['WhiteAuto'] = 'whiteAuto'; $cmds['WhiteAuto'] = 'whiteAuto';
@ -183,12 +199,16 @@ class Control extends ZM_Object {
} }
if ( $this->CanGain() ) { if ( $this->CanGain() ) {
if ( $this->CanGainCon() ) if ( $this->CanGainCon() ) {
$cmds['GainRoot'] = 'gainCon'; $cmds['GainRoot'] = 'gainCon';
elseif ( $this->CanGainRel() ) } else if ( $this->CanGainRel() ) {
$cmds['GainRoot'] = 'gainRel'; $cmds['GainRoot'] = 'gainRel';
elseif ( $this->CanGainAbs() ) } else if ( $this->CanGainAbs() ) {
$cmds['GainRoot'] = 'gainAbs'; $cmds['GainRoot'] = 'gainAbs';
} else {
Error('No Gain type selected');
$cmds['GainRoot'] = '';
}
$cmds['GainUp'] = $cmds['GainRoot'].'Up'; $cmds['GainUp'] = $cmds['GainRoot'].'Up';
$cmds['GainDown'] = $cmds['GainRoot'].'Down'; $cmds['GainDown'] = $cmds['GainRoot'].'Down';
$cmds['GainAuto'] = 'gainAuto'; $cmds['GainAuto'] = 'gainAuto';
@ -207,6 +227,7 @@ class Control extends ZM_Object {
$cmds['Center'] = $cmds['PresetHome']; $cmds['Center'] = $cmds['PresetHome'];
} else { } else {
$cmds['MoveRoot'] = ''; $cmds['MoveRoot'] = '';
Error('No move type selected. Please select Continuous, Relative, Absolute');
} }
$cmds['MoveUp'] = $cmds['MoveRoot'].'Up'; $cmds['MoveUp'] = $cmds['MoveRoot'].'Up';

View File

@ -51,10 +51,10 @@ class Event extends ZM_Object {
if ( $new ) { if ( $new ) {
$this->{'Storage'} = $new; $this->{'Storage'} = $new;
} }
if ( ! ( array_key_exists('Storage', $this) and $this->{'Storage'} ) ) { if ( ! ( property_exists($this, 'Storage') and $this->{'Storage'} ) ) {
if ( isset($this->{'StorageId'}) and $this->{'StorageId'} ) if ( isset($this->{'StorageId'}) and $this->{'StorageId'} )
$this->{'Storage'} = Storage::find_one(array('Id'=>$this->{'StorageId'})); $this->{'Storage'} = Storage::find_one(array('Id'=>$this->{'StorageId'}));
if ( ! ( array_key_exists('Storage', $this) and $this->{'Storage'} ) ) if ( ! ( property_exists($this, 'Storage') and $this->{'Storage'} ) )
$this->{'Storage'} = new Storage(NULL); $this->{'Storage'} = new Storage(NULL);
} }
return $this->{'Storage'}; return $this->{'Storage'};
@ -64,10 +64,10 @@ class Event extends ZM_Object {
if ( $new ) { if ( $new ) {
$this->{'SecondaryStorage'} = $new; $this->{'SecondaryStorage'} = $new;
} }
if ( ! ( array_key_exists('SecondaryStorage', $this) and $this->{'SecondaryStorage'} ) ) { if ( ! ( property_exists($this, 'SecondaryStorage') and $this->{'SecondaryStorage'} ) ) {
if ( isset($this->{'SecondaryStorageId'}) and $this->{'SecondaryStorageId'} ) if ( isset($this->{'SecondaryStorageId'}) and $this->{'SecondaryStorageId'} )
$this->{'SecondaryStorage'} = Storage::find_one(array('Id'=>$this->{'SecondaryStorageId'})); $this->{'SecondaryStorage'} = Storage::find_one(array('Id'=>$this->{'SecondaryStorageId'}));
if ( ! ( array_key_exists('SecondaryStorage', $this) and $this->{'SecondaryStorage'} ) ) if ( ! ( property_exists($this, 'SecondaryStorage') and $this->{'SecondaryStorage'} ) )
$this->{'SecondaryStorage'} = new Storage(NULL); $this->{'SecondaryStorage'} = new Storage(NULL);
} }
return $this->{'SecondaryStorage'}; return $this->{'SecondaryStorage'};
@ -262,7 +262,7 @@ class Event extends ZM_Object {
if ( is_null($new) or ( $new != '' ) ) { if ( is_null($new) or ( $new != '' ) ) {
$this->{'DiskSpace'} = $new; $this->{'DiskSpace'} = $new;
} }
if ( (!array_key_exists('DiskSpace',$this)) or (null === $this->{'DiskSpace'}) ) { if ( (!property_exists($this, 'DiskSpace')) or (null === $this->{'DiskSpace'}) ) {
$this->{'DiskSpace'} = folder_size($this->Path()); $this->{'DiskSpace'} = folder_size($this->Path());
dbQuery('UPDATE Events SET DiskSpace=? WHERE Id=?', array($this->{'DiskSpace'}, $this->{'Id'})); dbQuery('UPDATE Events SET DiskSpace=? WHERE Id=?', array($this->{'DiskSpace'}, $this->{'Id'}));
} }
@ -298,7 +298,7 @@ class Event extends ZM_Object {
} // end function createListThumbnail } // end function createListThumbnail
function ThumbnailWidth( ) { function ThumbnailWidth( ) {
if ( ! ( array_key_exists('ThumbnailWidth', $this) ) ) { if ( ! ( property_exists($this, 'ThumbnailWidth') ) ) {
if ( ZM_WEB_LIST_THUMB_WIDTH ) { if ( ZM_WEB_LIST_THUMB_WIDTH ) {
$this->{'ThumbnailWidth'} = ZM_WEB_LIST_THUMB_WIDTH; $this->{'ThumbnailWidth'} = ZM_WEB_LIST_THUMB_WIDTH;
$scale = (SCALE_BASE*ZM_WEB_LIST_THUMB_WIDTH)/$this->{'Width'}; $scale = (SCALE_BASE*ZM_WEB_LIST_THUMB_WIDTH)/$this->{'Width'};
@ -315,7 +315,7 @@ class Event extends ZM_Object {
} // end function ThumbnailWidth } // end function ThumbnailWidth
function ThumbnailHeight( ) { function ThumbnailHeight( ) {
if ( ! ( array_key_exists('ThumbnailHeight', $this) ) ) { if ( ! ( property_exists($this, 'ThumbnailHeight') ) ) {
if ( ZM_WEB_LIST_THUMB_WIDTH ) { if ( ZM_WEB_LIST_THUMB_WIDTH ) {
$this->{'ThumbnailWidth'} = ZM_WEB_LIST_THUMB_WIDTH; $this->{'ThumbnailWidth'} = ZM_WEB_LIST_THUMB_WIDTH;
$scale = (SCALE_BASE*ZM_WEB_LIST_THUMB_WIDTH)/$this->{'Width'}; $scale = (SCALE_BASE*ZM_WEB_LIST_THUMB_WIDTH)/$this->{'Width'};

View File

@ -39,8 +39,8 @@ class Filter extends ZM_Object {
$this->{'Query'} = func_get_arg(0);; $this->{'Query'} = func_get_arg(0);;
$this->{'Query_json'} = jsonEncode($this->{'Query'}); $this->{'Query_json'} = jsonEncode($this->{'Query'});
} }
if ( !array_key_exists('Query', $this) ) { if ( !property_exists($this, 'Query') ) {
if ( array_key_exists('Query_json', $this) and $this->{'Query_json'} ) { if ( property_exists($this, 'Query_json') and $this->{'Query_json'} ) {
$this->{'Query'} = jsonDecode($this->{'Query_json'}); $this->{'Query'} = jsonDecode($this->{'Query_json'});
} else { } else {
$this->{'Query'} = array(); $this->{'Query'} = array();

View File

@ -18,7 +18,7 @@ class Group extends ZM_Object {
} }
public function delete() { public function delete() {
if ( array_key_exists('Id', $this) ) { if ( property_exists($this, 'Id') ) {
dbQuery('DELETE FROM Groups_Monitors WHERE GroupId=?', array($this->{'Id'})); dbQuery('DELETE FROM Groups_Monitors WHERE GroupId=?', array($this->{'Id'}));
dbQuery('UPDATE Groups SET ParentId=NULL WHERE ParentId=?', array($this->{'Id'})); dbQuery('UPDATE Groups SET ParentId=NULL WHERE ParentId=?', array($this->{'Id'}));
dbQuery('DELETE FROM Groups WHERE Id=?', array($this->{'Id'})); dbQuery('DELETE FROM Groups WHERE Id=?', array($this->{'Id'}));
@ -35,7 +35,7 @@ class Group extends ZM_Object {
if ( isset($new) ) { if ( isset($new) ) {
$this->{'depth'} = $new; $this->{'depth'} = $new;
} }
if ( !array_key_exists('depth', $this) or ($this->{'depth'} === null) ) { if ( !property_exists($this, 'depth') or ($this->{'depth'} === null) ) {
$this->{'depth'} = 0; $this->{'depth'} = 0;
if ( $this->{'ParentId'} != null ) { if ( $this->{'ParentId'} != null ) {
$Parent = Group::find_one(array('Id'=>$this->{'ParentId'})); $Parent = Group::find_one(array('Id'=>$this->{'ParentId'}));
@ -46,7 +46,7 @@ class Group extends ZM_Object {
} // end public function depth } // end public function depth
public function MonitorIds( ) { public function MonitorIds( ) {
if ( ! array_key_exists('MonitorIds', $this) ) { if ( ! property_exists($this, 'MonitorIds') ) {
$this->{'MonitorIds'} = dbFetchAll('SELECT MonitorId FROM Groups_Monitors WHERE GroupId=?', 'MonitorId', array($this->{'Id'})); $this->{'MonitorIds'} = dbFetchAll('SELECT MonitorId FROM Groups_Monitors WHERE GroupId=?', 'MonitorId', array($this->{'Id'}));
} }
return $this->{'MonitorIds'}; return $this->{'MonitorIds'};

View File

@ -9,118 +9,119 @@ require_once('Storage.php');
class Monitor extends ZM_Object { class Monitor extends ZM_Object {
protected static $table = 'Monitors'; protected static $table = 'Monitors';
protected $defaults = array( protected $defaults = array(
'Id' => null, 'Id' => null,
'Name' => '', 'Name' => '',
'ServerId' => 0, 'Notes' => '',
'StorageId' => 0, 'ServerId' => 0,
'Type' => 'Ffmpeg', 'StorageId' => 0,
'Function' => 'Mocord', 'Type' => 'Ffmpeg',
'Enabled' => array('type'=>'boolean','default'=>1), 'Function' => 'Mocord',
'LinkedMonitors' => array('type'=>'set', 'default'=>null), 'Enabled' => array('type'=>'boolean','default'=>1),
'Triggers' => array('type'=>'set','default'=>''), 'LinkedMonitors' => array('type'=>'set', 'default'=>null),
'Device' => '', 'Triggers' => array('type'=>'set','default'=>''),
'Channel' => 0, 'Device' => '',
'Format' => '0', 'Channel' => 0,
'V4LMultiBuffer' => null, 'Format' => '0',
'V4LCapturesPerFrame' => 1, 'V4LMultiBuffer' => null,
'Protocol' => null, 'V4LCapturesPerFrame' => 1,
'Method' => '', 'Protocol' => null,
'Host' => null, 'Method' => '',
'Port' => '', 'Host' => null,
'SubPath' => '', 'Port' => '',
'Path' => null, 'SubPath' => '',
'Options' => null, 'Path' => null,
'User' => null, 'Options' => null,
'Pass' => null, 'User' => null,
// These are NOT NULL default 0 in the db, but 0 is not a valid value. FIXME 'Pass' => null,
'Width' => null, // These are NOT NULL default 0 in the db, but 0 is not a valid value. FIXME
'Height' => null, 'Width' => null,
'Colours' => 4, 'Height' => null,
'Palette' => '0', 'Colours' => 4,
'Orientation' => null, 'Palette' => '0',
'Deinterlacing' => 0, 'Orientation' => null,
'DecoderHWAccelName' => null, 'Deinterlacing' => 0,
'DecoderHWAccelDevice' => null, 'DecoderHWAccelName' => null,
'SaveJPEGs' => 3, 'DecoderHWAccelDevice' => null,
'VideoWriter' => '0', 'SaveJPEGs' => 3,
'OutputCodec' => null, 'VideoWriter' => '0',
'OutputContainer' => null, 'OutputCodec' => null,
'EncoderParameters' => "# Lines beginning with # are a comment \n# For changing quality, use the crf option\n# 1 is best, 51 is worst quality\n#crf=23\n", 'OutputContainer' => null,
'RecordAudio' => array('type'=>'boolean', 'default'=>0), 'EncoderParameters' => "# Lines beginning with # are a comment \n# For changing quality, use the crf option\n# 1 is best, 51 is worst quality\n#crf=23\n",
'RTSPDescribe' => array('type'=>'boolean','default'=>0), 'RecordAudio' => array('type'=>'boolean', 'default'=>0),
'Brightness' => -1, 'RTSPDescribe' => array('type'=>'boolean','default'=>0),
'Contrast' => -1, 'Brightness' => -1,
'Hue' => -1, 'Contrast' => -1,
'Colour' => -1, 'Hue' => -1,
'EventPrefix' => 'Event-', 'Colour' => -1,
'LabelFormat' => '%N - %d/%m/%y %H:%M:%S', 'EventPrefix' => 'Event-',
'LabelX' => 0, 'LabelFormat' => '%N - %d/%m/%y %H:%M:%S',
'LabelY' => 0, 'LabelX' => 0,
'LabelSize' => 1, 'LabelY' => 0,
'ImageBufferCount' => 100, 'LabelSize' => 1,
'WarmupCount' => 0, 'ImageBufferCount' => 20,
'PreEventCount' => 0, 'WarmupCount' => 0,
'PostEventCount' => 0, 'PreEventCount' => 5,
'StreamReplayBuffer' => 0, 'PostEventCount' => 5,
'AlarmFrameCount' => 1, 'StreamReplayBuffer' => 0,
'SectionLength' => 600, 'AlarmFrameCount' => 1,
'MinSectionLength' => 10, 'SectionLength' => 600,
'FrameSkip' => 0, 'MinSectionLength' => 10,
'MotionFrameSkip' => 0, 'FrameSkip' => 0,
'AnalysisFPSLimit' => null, 'MotionFrameSkip' => 0,
'AnalysisUpdateDelay' => 0, 'AnalysisFPSLimit' => null,
'MaxFPS' => null, 'AnalysisUpdateDelay' => 0,
'AlarmMaxFPS' => null, 'MaxFPS' => null,
'FPSReportInterval' => 100, 'AlarmMaxFPS' => null,
'RefBlendPerc' => 6, 'FPSReportInterval' => 100,
'AlarmRefBlendPerc' => 6, 'RefBlendPerc' => 6,
'Controllable' => array('type'=>'boolean','default'=>0), 'AlarmRefBlendPerc' => 6,
'ControlId' => null, 'Controllable' => array('type'=>'boolean','default'=>0),
'ControlDevice' => null, 'ControlId' => null,
'ControlAddress' => null, 'ControlDevice' => null,
'AutoStopTimeout' => null, 'ControlAddress' => null,
'TrackMotion' => array('type'=>'boolean','default'=>0), 'AutoStopTimeout' => null,
'TrackDelay' => null, 'TrackMotion' => array('type'=>'boolean','default'=>0),
'ReturnLocation' => -1, 'TrackDelay' => null,
'ReturnDelay' => null, 'ReturnLocation' => -1,
'DefaultRate' => 100, 'ReturnDelay' => null,
'DefaultScale' => 100, 'DefaultRate' => 100,
'SignalCheckPoints' => 0, 'DefaultScale' => 100,
'SignalCheckColour' => '#0000BE', 'SignalCheckPoints' => 0,
'WebColour' => 'red', 'SignalCheckColour' => '#0000BE',
'Exif' => array('type'=>'boolean','default'=>0), 'WebColour' => '#ff0000',
'Sequence' => null, 'Exif' => array('type'=>'boolean','default'=>0),
'TotalEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), 'Sequence' => null,
'TotalEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), 'TotalEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'HourEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), 'TotalEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'HourEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), 'HourEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'DayEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), 'HourEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'DayEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), 'DayEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'WeekEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), 'DayEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'WeekEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), 'WeekEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'MonthEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), 'WeekEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'MonthEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), 'MonthEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'ArchivedEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), 'MonthEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'ArchivedEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), 'ArchivedEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'ZoneCount' => 0, 'ArchivedEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'Refresh' => null, 'ZoneCount' => 0,
'DefaultCodec' => 'auto', 'Refresh' => null,
'GroupIds' => array('default'=>array(), 'do_not_update'=>1), 'DefaultCodec' => 'auto',
); 'GroupIds' => array('default'=>array(), 'do_not_update'=>1),
private $status_fields = array( );
'Status' => null, private $status_fields = array(
'AnalysisFPS' => null, 'Status' => null,
'CaptureFPS' => null, 'AnalysisFPS' => null,
'CaptureBandwidth' => null, 'CaptureFPS' => null,
); 'CaptureBandwidth' => null,
);
public function Control() { public function Control() {
if ( !array_key_exists('Control', $this) ) { if ( !property_exists($this, 'Control') ) {
if ( $this->ControlId() ) if ( $this->ControlId() )
$this->{'Control'} = Control::find_one(array('Id'=>$this->{'ControlId'})); $this->{'Control'} = Control::find_one(array('Id'=>$this->{'ControlId'}));
if ( !(array_key_exists('Control', $this) and $this->{'Control'}) ) if ( !(property_exists($this, 'Control') and $this->{'Control'}) )
$this->{'Control'} = new Control(); $this->{'Control'} = new Control();
} }
return $this->{'Control'}; return $this->{'Control'};
@ -138,7 +139,7 @@ private $status_fields = array(
$this->{$fn} = $args[0]; $this->{$fn} = $args[0];
} }
} }
if ( array_key_exists($fn, $this) ) { if ( property_exists($this, $fn) ) {
return $this->{$fn}; return $this->{$fn};
} else if ( array_key_exists($fn, $this->defaults) ) { } else if ( array_key_exists($fn, $this->defaults) ) {
if ( is_array($this->defaults[$fn]) ) { if ( is_array($this->defaults[$fn]) ) {
@ -211,9 +212,9 @@ private $status_fields = array(
$this->{'Width'} = $new; $this->{'Width'} = $new;
$field = ( $this->Orientation() == 'ROTATE_90' or $this->Orientation() == 'ROTATE_270' ) ? 'Height' : 'Width'; $field = ( $this->Orientation() == 'ROTATE_90' or $this->Orientation() == 'ROTATE_270' ) ? 'Height' : 'Width';
if ( array_key_exists($field, $this) ) if ( property_exists($this, $field) )
return $this->{$field}; return $this->{$field};
return $this->defaults{$field}; return $this->defaults[$field];
} // end function Width } // end function Width
public function ViewHeight($new=null) { public function ViewHeight($new=null) {
@ -221,9 +222,9 @@ private $status_fields = array(
$this->{'Height'} = $new; $this->{'Height'} = $new;
$field = ( $this->Orientation() == 'ROTATE_90' or $this->Orientation() == 'ROTATE_270' ) ? 'Width' : 'Height'; $field = ( $this->Orientation() == 'ROTATE_90' or $this->Orientation() == 'ROTATE_270' ) ? 'Width' : 'Height';
if ( array_key_exists($field, $this) ) if ( property_exists($this, $field) )
return $this->{$field}; return $this->{$field};
return $this->defaults{$field}; return $this->defaults[$field];
} // end function Height } // end function Height
public function SignalCheckColour($new=null) { public function SignalCheckColour($new=null) {
@ -234,10 +235,10 @@ private $status_fields = array(
// Validate that it's a valid colour (we seem to allow color names, not just hex). // Validate that it's a valid colour (we seem to allow color names, not just hex).
// This also helps prevent XSS. // This also helps prevent XSS.
if (array_key_exists($field, $this) && preg_match('/^[#0-9a-zA-Z]+$/', $this->{$field})) { if ( property_exists($this, $field) && preg_match('/^[#0-9a-zA-Z]+$/', $this->{$field})) {
return $this->{$field}; return $this->{$field};
} }
return $this->defaults{$field}; return $this->defaults[$field];
} // end function SignalCheckColour } // end function SignalCheckColour
public static function find( $parameters = array(), $options = array() ) { public static function find( $parameters = array(), $options = array() ) {
@ -253,7 +254,7 @@ private $status_fields = array(
Warning('Attempt to control a monitor with no Id'); Warning('Attempt to control a monitor with no Id');
return; return;
} }
if ( (!defined('ZM_SERVER_ID')) or ( array_key_exists('ServerId', $this) and (ZM_SERVER_ID==$this->{'ServerId'}) ) ) { if ( (!defined('ZM_SERVER_ID')) or ( property_exists($this, 'ServerId') and (ZM_SERVER_ID==$this->{'ServerId'}) ) ) {
if ( $this->Type() == 'Local' ) { if ( $this->Type() == 'Local' ) {
$zmcArgs = '-d '.$this->{'Device'}; $zmcArgs = '-d '.$this->{'Device'};
} else { } else {
@ -306,7 +307,7 @@ private $status_fields = array(
return; return;
} }
if ( (!defined('ZM_SERVER_ID')) or ( array_key_exists('ServerId', $this) and (ZM_SERVER_ID==$this->{'ServerId'}) ) ) { if ( (!defined('ZM_SERVER_ID')) or ( property_exists($this, 'ServerId') and (ZM_SERVER_ID==$this->{'ServerId'}) ) ) {
if ( $this->{'Function'} == 'None' || $this->{'Function'} == 'Monitor' || $mode == 'stop' ) { if ( $this->{'Function'} == 'None' || $this->{'Function'} == 'Monitor' || $mode == 'stop' ) {
if ( ZM_OPT_CONTROL ) { if ( ZM_OPT_CONTROL ) {
daemonControl('stop', 'zmtrack.pl', '-m '.$this->{'Id'}); daemonControl('stop', 'zmtrack.pl', '-m '.$this->{'Id'});
@ -367,8 +368,8 @@ private $status_fields = array(
} }
} }
if ( !array_key_exists('GroupIds', $this) ) { if ( !property_exists($this, 'GroupIds') ) {
if ( array_key_exists('Id', $this) and $this->{'Id'} ) { if ( property_exists($this, 'Id') and $this->{'Id'} ) {
$this->{'GroupIds'} = dbFetchAll('SELECT `GroupId` FROM `Groups_Monitors` WHERE `MonitorId`=?', 'GroupId', array($this->{'Id'}) ); $this->{'GroupIds'} = dbFetchAll('SELECT `GroupId` FROM `Groups_Monitors` WHERE `MonitorId`=?', 'GroupId', array($this->{'Id'}) );
if ( ! $this->{'GroupIds'} ) if ( ! $this->{'GroupIds'} )
$this->{'GroupIds'} = array(); $this->{'GroupIds'} = array();
@ -417,7 +418,7 @@ private $status_fields = array(
if ( $new ) { if ( $new ) {
$this->{'Storage'} = $new; $this->{'Storage'} = $new;
} }
if ( ! ( array_key_exists('Storage', $this) and $this->{'Storage'} ) ) { if ( ! ( property_exists($this, 'Storage') and $this->{'Storage'} ) ) {
$this->{'Storage'} = isset($this->{'StorageId'}) ? $this->{'Storage'} = isset($this->{'StorageId'}) ?
Storage::find_one(array('Id'=>$this->{'StorageId'})) : Storage::find_one(array('Id'=>$this->{'StorageId'})) :
new Storage(NULL); new Storage(NULL);
@ -467,58 +468,58 @@ private $status_fields = array(
return $source; return $source;
} // end function Source } // end function Source
public function UrlToIndex() { public function UrlToIndex($port=null) {
return $this->Server()->UrlToIndex(); return $this->Server()->UrlToIndex($port);
//ZM_MIN_STREAMING_PORT ? (ZM_MIN_STREAMING_PORT+$this->Id()) : null); //ZM_MIN_STREAMING_PORT ? (ZM_MIN_STREAMING_PORT+$this->Id()) : null);
} }
public function sendControlCommand($command) { public function sendControlCommand($command) {
// command is generally a command option list like --command=blah but might be just the word quit // command is generally a command option list like --command=blah but might be just the word quit
$options = array(); $options = array();
# Convert from a command line params to an option array # Convert from a command line params to an option array
foreach ( explode(' ', $command) as $option ) { foreach ( explode(' ', $command) as $option ) {
if ( preg_match('/--([^=]+)(?:=(.+))?/', $option, $matches) ) { if ( preg_match('/--([^=]+)(?:=(.+))?/', $option, $matches) ) {
$options[$matches[1]] = $matches[2]?$matches[2]:1; $options[$matches[1]] = $matches[2]?$matches[2]:1;
} else if ( $option != '' and $option != 'quit' ) { } else if ( $option != '' and $option != 'quit' ) {
Warning("Ignored command for zmcontrol $option in $command"); 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 ( array_key_exists('ServerId', $this) 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); if ( !count($options) ) {
} else if ( $this->ServerId() ) { 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(); $Server = $this->Server();
$url = ZM_BASE_PROTOCOL . '://'.$Server->Hostname().'/zm/api/monitors/daemonControl/'.$this->{'Id'}.'/'.$mode.'/zmcontrol.json'; $url = ZM_BASE_PROTOCOL . '://'.$Server->Hostname().'/zm/api/monitors/daemonControl/'.$this->{'Id'}.'/'.$mode.'/zmcontrol.json';

View File

@ -1,133 +1,22 @@
<?php <?php
namespace ZM; namespace ZM;
require_once('Object.php');
require_once('database.php'); class MontageLayout extends ZM_Object {
protected static $table = 'MontageLayouts';
class MontageLayout { protected $defaults = array(
private $defaults = array(
'Id' => null, 'Id' => null,
'Name' => '', 'Name' => '',
'Positions' => 0, 'Positions' => 0,
); );
public function __construct( $IdOrRow = NULL ) { public static function find( $parameters = array(), $options = array() ) {
if ( $IdOrRow ) { return ZM_Object::_find(get_class(), $parameters, $options);
$row = NULL;
if ( is_integer( $IdOrRow ) or is_numeric( $IdOrRow ) ) {
$row = dbFetchOne( 'SELECT * FROM MontageLayouts WHERE Id=?', NULL, array( $IdOrRow ) );
if ( ! $row ) {
Error("Unable to load MontageLayout record for Id=" . $IdOrRow );
}
} else if ( is_array( $IdOrRow ) ) {
$row = $IdOrRow;
} else {
Error("Unknown argument passed to MontageLayout Constructor ($IdOrRow)");
return;
}
if ( $row ) {
foreach ($row as $k => $v) {
$this->{$k} = $v;
}
} else {
Error('No row for MontageLayout ' . $IdOrRow );
}
} # end if isset($IdOrRow)
} // end function __construct
public function __call($fn, array $args){
if ( count($args) ) {
$this->{$fn} = $args[0];
}
if ( array_key_exists($fn, $this) ) {
return $this->{$fn};
} else {
if ( array_key_exists( $fn, $this->defaults ) ) {
return $this->defaults{$fn};
} else {
$backTrace = debug_backtrace();
$file = $backTrace[1]['file'];
$line = $backTrace[1]['line'];
Warning( "Unknown function call MontageLayout->$fn from $file:$line" );
}
}
} }
public function set( $data ) { public static function find_one( $parameters = array(), $options = array() ) {
foreach ($data as $k => $v) { return ZM_Object::_find_one(get_class(), $parameters, $options);
if ( is_array( $v ) ) {
# perhaps should turn into a comma-separated string
$this->{$k} = implode(',',$v);
} else if ( is_string( $v ) ) {
$this->{$k} = trim( $v );
} else if ( is_integer( $v ) ) {
$this->{$k} = $v;
} else if ( is_bool( $v ) ) {
$this->{$k} = $v;
} else {
Error( "Unknown type $k => $v of var " . gettype( $v ) );
$this->{$k} = $v;
}
}
} }
public static function find( $parameters = null, $options = null ) {
$filters = array();
$sql = 'SELECT * FROM MontageLayouts ';
$values = array();
if ( $parameters ) {
$fields = array();
$sql .= 'WHERE ';
foreach ( $parameters as $field => $value ) {
if ( $value == null ) {
$fields[] = $field.' IS NULL';
} else if ( is_array( $value ) ) {
$func = function(){return '?';};
$fields[] = $field.' IN ('.implode(',', array_map( $func, $value ) ). ')';
$values += $value;
} else {
$fields[] = $field.'=?';
$values[] = $value;
}
}
$sql .= implode(' AND ', $fields );
}
if ( $options and isset($options['order']) ) {
$sql .= ' ORDER BY ' . $options['order'];
}
$result = dbQuery($sql, $values);
if ( $result ) {
$results = $result->fetchALL();
foreach ( $results as $row ) {
$filters[] = new MontageLayout($row);
}
}
return $filters;
}
public function save( $new_values = null ) {
if ( $new_values ) {
foreach ( $new_values as $k=>$v ) {
$this->{$k} = $v;
}
}
$fields = array_values( array_filter( array_keys($this->defaults), function($field){return $field != 'Id';} ) );
$values = null;
if ( isset($this->{'Id'}) ) {
$sql = 'UPDATE MontageLayouts SET '.implode(', ', array_map( function($field) {return $field.'=?';}, $fields ) ) . ' WHERE Id=?';
$values = array_map( function($field){return $this->{$field};}, $fields );
$values[] = $this->{'Id'};
dbQuery($sql, $values);
} else {
$sql = 'INSERT INTO MontageLayouts ('.implode( ',', $fields ).') VALUES ('.implode(',',array_map( function(){return '?';}, $fields ) ).')';
$values = array_map( function($field){return $this->{$field};}, $fields );
dbQuery($sql, $values);
global $dbConn;
$this->{'Id'} = $dbConn->lastInsertId();
}
} // end function save
} // end class MontageLayout } // end class MontageLayout
?> ?>

View File

@ -45,7 +45,7 @@ class ZM_Object {
$this->{$fn} = $args[0]; $this->{$fn} = $args[0];
} }
if ( array_key_exists($fn, $this) ) { if ( property_exists($this, $fn) ) {
return $this->{$fn}; return $this->{$fn};
} else { } else {
if ( array_key_exists($fn, $this->defaults) ) { if ( array_key_exists($fn, $this->defaults) ) {
@ -140,10 +140,10 @@ class ZM_Object {
foreach ($this->defaults as $key => $value) { foreach ($this->defaults as $key => $value) {
if ( is_callable(array($this, $key)) ) { if ( is_callable(array($this, $key)) ) {
$json[$key] = $this->$key(); $json[$key] = $this->$key();
} else if ( array_key_exists($key, $this) ) { } else if ( property_exists($this, $key) ) {
$json[$key] = $this->{$key}; $json[$key] = $this->{$key};
} else { } else {
$json[$key] = $this->defaults{$key}; $json[$key] = $this->defaults[$key];
} }
} }
return json_encode($json); return json_encode($json);
@ -158,14 +158,24 @@ class ZM_Object {
# perhaps should turn into a comma-separated string # perhaps should turn into a comma-separated string
$this->{$k} = implode(',', $v); $this->{$k} = implode(',', $v);
} else if ( is_string($v) ) { } else if ( is_string($v) ) {
if ( $v == '' and array_key_exists($k, $this->defaults) ) { if ( 0 ) {
if ( is_array($this->defaults[$k]) ) # Remarking this out. We are setting a value, not asking for a default to be set.
# So don't do defaults here, do them somewhere else
if ( ($v == null) and array_key_exists($k, $this->defaults) ) {
Logger::Debug("$k => Have default for $v: ");
if ( is_array($this->defaults[$k]) ) {
$this->{$k} = $this->defaults[$k]['default']; $this->{$k} = $this->defaults[$k]['default'];
else } else {
$this->{$k} = $this->defaults[$k]; $this->{$k} = $this->defaults[$k];
} else { Logger::Debug("$k => Have default for $v: " . $this->{$k});
$this->{$k} = trim($v); }
} else {
$this->{$k} = trim($v);
} }
} else {
$this->{$k} = trim($v);
}
} else if ( is_integer($v) ) { } else if ( is_integer($v) ) {
$this->{$k} = $v; $this->{$k} = $v;
} else if ( is_bool($v) ) { } else if ( is_bool($v) ) {
@ -215,7 +225,7 @@ class ZM_Object {
} else if ( $this->$field() != $value ) { } else if ( $this->$field() != $value ) {
$changes[$field] = $value; $changes[$field] = $value;
} }
} else if ( array_key_exists($field, $this) ) { } else if ( property_exists($this, $field) ) {
$type = (array_key_exists($field, $this->defaults) && is_array($this->defaults[$field])) ? $this->defaults[$field]['type'] : 'scalar'; $type = (array_key_exists($field, $this->defaults) && is_array($this->defaults[$field])) ? $this->defaults[$field]['type'] : 'scalar';
Logger::Debug("Checking field $field => current ". Logger::Debug("Checking field $field => current ".
(is_array($this->{$field}) ? implode(',',$this->{$field}) : $this->{$field}) . ' ?= ' . (is_array($this->{$field}) ? implode(',',$this->{$field}) : $this->{$field}) . ' ?= ' .

View File

@ -80,7 +80,7 @@ class Storage extends ZM_Object {
} }
public function disk_total_space() { public function disk_total_space() {
if ( !array_key_exists('disk_total_space', $this) ) { if ( !property_exists($this, 'disk_total_space') ) {
$path = $this->Path(); $path = $this->Path();
if ( file_exists($path) ) { if ( file_exists($path) ) {
$this->{'disk_total_space'} = disk_total_space($path); $this->{'disk_total_space'} = disk_total_space($path);
@ -94,7 +94,7 @@ class Storage extends ZM_Object {
public function disk_used_space() { public function disk_used_space() {
# This isn't a function like this in php, so we have to add up the space used in each event. # This isn't a function like this in php, so we have to add up the space used in each event.
if ( ( !array_key_exists('disk_used_space', $this)) or !$this->{'disk_used_space'} ) { if ( ( !property_exists($this, 'disk_used_space')) or !$this->{'disk_used_space'} ) {
if ( $this->{'Type'} == 's3fs' ) { if ( $this->{'Type'} == 's3fs' ) {
$this->{'disk_used_space'} = $this->event_disk_space(); $this->{'disk_used_space'} = $this->event_disk_space();
} else { } else {
@ -112,7 +112,7 @@ class Storage extends ZM_Object {
public function event_disk_space() { public function event_disk_space() {
# This isn't a function like this in php, so we have to add up the space used in each event. # This isn't a function like this in php, so we have to add up the space used in each event.
if ( (! array_key_exists('DiskSpace', $this)) or (!$this->{'DiskSpace'}) ) { if ( (! property_exists($this, 'DiskSpace')) or (!$this->{'DiskSpace'}) ) {
$used = dbFetchOne('SELECT SUM(DiskSpace) AS DiskSpace FROM Events WHERE StorageId=? AND DiskSpace IS NOT NULL', 'DiskSpace', array($this->Id())); $used = dbFetchOne('SELECT SUM(DiskSpace) AS DiskSpace FROM Events WHERE StorageId=? AND DiskSpace IS NOT NULL', 'DiskSpace', array($this->Id()));
do { do {
@ -130,8 +130,8 @@ class Storage extends ZM_Object {
} // end function event_disk_space } // end function event_disk_space
public function Server() { public function Server() {
if ( ! array_key_exists('Server',$this) ) { if ( ! property_exists($this, 'Server') ) {
if ( array_key_exists('ServerId', $this) ) { if ( property_exists($this, 'ServerId') ) {
$this->{'Server'} = Server::find_one(array('Id'=>$this->{'ServerId'})); $this->{'Server'} = Server::find_one(array('Id'=>$this->{'ServerId'}));
if ( !$this->{'Server'} ) { if ( !$this->{'Server'} ) {

View File

@ -28,6 +28,65 @@ if ( $action == 'controlcap' ) {
require_once('includes/Control.php'); require_once('includes/Control.php');
$Control = new ZM\Control( !empty($_REQUEST['cid']) ? $_REQUEST['cid'] : null ); $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 ); //$changes = getFormChanges( $control, $_REQUEST['newControl'], $types, $columns );
$Control->save($_REQUEST['newControl']); $Control->save($_REQUEST['newControl']);
$refreshParent = true; $refreshParent = true;

View File

@ -39,7 +39,7 @@ if ( $action == 'function' ) {
$oldFunction = $monitor['Function']; $oldFunction = $monitor['Function'];
$oldEnabled = $monitor['Enabled']; $oldEnabled = $monitor['Enabled'];
if ( $newFunction != $oldFunction || $newEnabled != $oldEnabled ) { if ( $newFunction != $oldFunction || $newEnabled != $oldEnabled ) {
dbQuery('UPDATE Monitors SET Function=?, Enabled=? WHERE Id=?', dbQuery('UPDATE Monitors SET `Function`=?, `Enabled`=? WHERE `Id`=?',
array($newFunction, $newEnabled, $mid)); array($newFunction, $newEnabled, $mid));
$monitor['Function'] = $newFunction; $monitor['Function'] = $newFunction;

View File

@ -31,19 +31,19 @@ if ( $action == 'state' ) {
} }
} else if ( $action == 'save' ) { } else if ( $action == 'save' ) {
if ( !empty($_REQUEST['runState']) || !empty($_REQUEST['newState']) ) { if ( !empty($_REQUEST['runState']) || !empty($_REQUEST['newState']) ) {
$sql = 'SELECT Id,Function,Enabled FROM Monitors ORDER BY Id'; $sql = 'SELECT `Id`,`Function`,`Enabled` FROM Monitors ORDER BY Id';
$definitions = array(); $definitions = array();
foreach( dbFetchAll($sql) as $monitor ) { foreach ( dbFetchAll($sql) as $monitor ) {
$definitions[] = $monitor['Id'].':'.$monitor['Function'].':'.$monitor['Enabled']; $definitions[] = $monitor['Id'].':'.$monitor['Function'].':'.$monitor['Enabled'];
} }
$definition = join(',', $definitions); $definition = join(',', $definitions);
if ( $_REQUEST['newState'] ) if ( $_REQUEST['newState'] )
$_REQUEST['runState'] = $_REQUEST['newState']; $_REQUEST['runState'] = $_REQUEST['newState'];
dbQuery('REPLACE INTO States SET Name=?, Definition=?', array($_REQUEST['runState'],$definition)); dbQuery('REPLACE INTO `States` SET `Name`=?, `Definition`=?', array($_REQUEST['runState'],$definition));
} }
} else if ( $action == 'delete' ) { } else if ( $action == 'delete' ) {
if ( isset($_REQUEST['runState']) ) if ( isset($_REQUEST['runState']) )
dbQuery('DELETE FROM States WHERE Name=?', array($_REQUEST['runState'])); dbQuery('DELETE FROM `States` WHERE `Name`=?', array($_REQUEST['runState']));
} }
$view = 'console'; $view = 'console';
?> ?>

View File

@ -220,19 +220,19 @@ function generateAuthHash($useRemoteAddr, $force=false) {
function visibleMonitor($mid) { function visibleMonitor($mid) {
global $user; global $user;
return ( empty($user['MonitorIds']) || in_array($mid, explode(',', $user['MonitorIds'])) ); return ( $user && empty($user['MonitorIds']) || in_array($mid, explode(',', $user['MonitorIds'])) );
} }
function canView($area, $mid=false) { function canView($area, $mid=false) {
global $user; global $user;
return ( ($user[$area] == 'View' || $user[$area] == 'Edit') && ( !$mid || visibleMonitor($mid) ) ); return ( $user && ($user[$area] == 'View' || $user[$area] == 'Edit') && ( !$mid || visibleMonitor($mid) ) );
} }
function canEdit($area, $mid=false) { function canEdit($area, $mid=false) {
global $user; global $user;
return ( $user[$area] == 'Edit' && ( !$mid || visibleMonitor($mid) )); return ( $user && ($user[$area] == 'Edit') && ( !$mid || visibleMonitor($mid) ));
} }
function userFromSession() { function userFromSession() {

View File

@ -33,9 +33,9 @@ $configFile = ZM_CONFIG;
$localConfigFile = basename($configFile); $localConfigFile = basename($configFile);
if ( file_exists( $localConfigFile ) && filesize( $localConfigFile ) > 0 ) { if ( file_exists( $localConfigFile ) && filesize( $localConfigFile ) > 0 ) {
if ( php_sapi_name() == 'cli' && empty($_SERVER['REMOTE_ADDR']) ) if ( php_sapi_name() == 'cli' && empty($_SERVER['REMOTE_ADDR']) )
print( "Warning, overriding installed $localConfigFile file with local copy\n" ); print("Warning, overriding installed $localConfigFile file with local copy\n");
else else
error_log( "Warning, overriding installed $localConfigFile file with local copy" ); error_log("Warning, overriding installed $localConfigFile file with local copy");
$configFile = $localConfigFile; $configFile = $localConfigFile;
} }
@ -49,19 +49,19 @@ if ( is_dir($configSubFolder) ) {
if ( is_readable($configSubFolder) ) { if ( is_readable($configSubFolder) ) {
foreach ( glob("$configSubFolder/*.conf") as $filename ) { foreach ( glob("$configSubFolder/*.conf") as $filename ) {
//error_log("processing $filename"); //error_log("processing $filename");
$configvals = array_replace($configvals, process_configfile($filename) ); $configvals = array_replace($configvals, process_configfile($filename));
} }
} else { } else {
error_log( "WARNING: ZoneMinder configuration subfolder found but is not readable. Check folder permissions on $configSubFolder." ); error_log("WARNING: ZoneMinder configuration subfolder found but is not readable. Check folder permissions on $configSubFolder.");
} }
} else { } else {
error_log( "WARNING: ZoneMinder configuration subfolder found but is not a directory. Check $configSubFolder." ); error_log("WARNING: ZoneMinder configuration subfolder found but is not a directory. Check $configSubFolder.");
} }
# Now that our array our finalized, define each key => value # Now that our array our finalized, define each key => value
# pair in the array as a constant # pair in the array as a constant
foreach( $configvals as $key => $value) { foreach ( $configvals as $key => $value ) {
define( $key, $value ); define($key, $value);
} }
// //
@ -135,8 +135,8 @@ define( 'SCALE_BASE', 100 ); // The additional scalin
define( 'STRF_FMT_DATETIME_DB', '%Y-%m-%d %H:%M:%S' ); // Strftime format for database queries, don't change define( 'STRF_FMT_DATETIME_DB', '%Y-%m-%d %H:%M:%S' ); // Strftime format for database queries, don't change
define( 'MYSQL_FMT_DATETIME_SHORT', '%y/%m/%d %H:%i:%S' ); // MySQL date_format shorter format for dates with time define( 'MYSQL_FMT_DATETIME_SHORT', '%y/%m/%d %H:%i:%S' ); // MySQL date_format shorter format for dates with time
require_once( 'database.php' ); require_once('database.php');
require_once( 'logger.php' ); require_once('logger.php');
loadConfig(); loadConfig();
ZM\Logger::fetch()->initialise(); ZM\Logger::fetch()->initialise();
@ -165,28 +165,30 @@ function loadConfig( $defineConsts=true ) {
$result = $dbConn->query('SELECT Name,Value FROM Config'); $result = $dbConn->query('SELECT Name,Value FROM Config');
if ( !$result ) if ( !$result )
echo mysql_error(); echo mysql_error();
while( $row = dbFetchNext( $result ) ) { while( $row = dbFetchNext($result) ) {
if ( $defineConsts ) if ( $defineConsts )
define( $row['Name'], $row['Value'] ); define($row['Name'], $row['Value']);
$config[$row['Name']] = $row; $config[$row['Name']] = $row;
} }
} # end function loadConfig } # end function loadConfig
// For Human-readability, use ZM_SERVER_HOST or ZM_SERVER_NAME in zm.conf, and convert it here to a ZM_SERVER_ID // For Human-readability, use ZM_SERVER_HOST or ZM_SERVER_NAME in zm.conf, and convert it here to a ZM_SERVER_ID
if ( ! defined('ZM_SERVER_ID') ) { if ( ! defined('ZM_SERVER_ID') ) {
require_once('Server.php');
if ( defined('ZM_SERVER_NAME') and ZM_SERVER_NAME ) { if ( defined('ZM_SERVER_NAME') and ZM_SERVER_NAME ) {
$server_id = dbFetchOne('SELECT Id FROM Servers WHERE Name=?', 'Id', array(ZM_SERVER_NAME)); # Use Server lookup so that it caches
if ( ! $server_id ) { $Server = ZM\Server::find_one(array('Name'=>ZM_SERVER_NAME));
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.'); if ( !$Server ) {
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 { } else {
define( 'ZM_SERVER_ID', $server_id ); define('ZM_SERVER_ID', $Server->Id());
} }
} else if ( defined('ZM_SERVER_HOST') and ZM_SERVER_HOST ) { } else if ( defined('ZM_SERVER_HOST') and ZM_SERVER_HOST ) {
$server_id = dbFetchOne('SELECT Id FROM Servers WHERE Name=?', 'Id', array(ZM_SERVER_HOST)); $Server = ZM\Server::find_one(array('Name'=>ZM_SERVER_HOST));
if ( ! $server_id ) { 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 { } else {
define( 'ZM_SERVER_ID', $server_id ); define('ZM_SERVER_ID', $Server->Id());
} }
} }
} }
@ -197,21 +199,22 @@ function process_configfile($configFile) {
if ( is_readable( $configFile ) ) { if ( is_readable( $configFile ) ) {
$configvals = array(); $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) ) { while ( !feof($cfg) ) {
$str = fgets( $cfg, 256 ); $str = fgets($cfg, 256);
if ( preg_match( '/^\s*$/', $str )) if ( preg_match('/^\s*(#.*)?$/', $str) ) {
continue; continue;
elseif ( preg_match( '/^\s*#/', $str )) } else if ( preg_match( '/^\s*([^=\s]+)\s*=\s*[\'"]*(.*?)[\'"]*\s*$/', $str, $matches )) {
continue;
elseif ( preg_match( '/^\s*([^=\s]+)\s*=\s*[\'"]*(.*?)[\'"]*\s*$/', $str, $matches ))
$configvals[$matches[1]] = $matches[2]; $configvals[$matches[1]] = $matches[2];
} else {
ZM\Error("Malformed line in config $configFile\n$str");
}
} }
fclose( $cfg ); fclose($cfg);
return( $configvals ); return $configvals;
} else { } else {
error_log( "WARNING: ZoneMinder configuration file found but is not readable. Check file permissions on $configFile." ); error_log("WARNING: ZoneMinder configuration file found but is not readable. Check file permissions on $configFile.");
return( false ); return false;
} }
} }

View File

@ -110,16 +110,10 @@ function dbError($sql) {
function dbEscape( $string ) { function dbEscape( $string ) {
global $dbConn; global $dbConn;
if ( version_compare(phpversion(), '4.3.0', '<')) if ( version_compare(phpversion(), '5.4', '<=') and get_magic_quotes_gpc() )
if ( get_magic_quotes_gpc() ) return $dbConn->quote(stripslashes($string));
return $dbConn->quote(stripslashes($string));
else
return $dbConn->quote($string);
else else
if ( get_magic_quotes_gpc() ) return $dbConn->quote($string);
return $dbConn->quote(stripslashes($string));
else
return $dbConn->quote($string);
} }
function dbQuery($sql, $params=NULL) { function dbQuery($sql, $params=NULL) {
@ -212,6 +206,10 @@ function dbFetch($sql, $col=false) {
} }
function dbFetchNext($result, $col=false) { function dbFetchNext($result, $col=false) {
if ( !$result ) {
ZM\Error("dbFetchNext called on null result.");
return false;
}
if ( $dbRow = $result->fetch(PDO::FETCH_ASSOC) ) if ( $dbRow = $result->fetch(PDO::FETCH_ASSOC) )
return $col ? $dbRow[$col] : $dbRow; return $col ? $dbRow[$col] : $dbRow;
return false; return false;

View File

@ -409,6 +409,11 @@ ZM\Logger::Debug("Event type: " . gettype($event));
global $user; global $user;
if ( $event->Archived() ) {
ZM\Info('Cannot delete Archived event.');
return;
} # end if Archived
if ( $user['Events'] == 'Edit' ) { if ( $user['Events'] == 'Edit' ) {
$event->delete(); $event->delete();
} # CAN EDIT } # CAN EDIT
@ -1085,9 +1090,8 @@ function parseFilter(&$filter, $saveToSession=false, $querySep='&amp;') {
$terms = isset($filter['Query']) ? $filter['Query']['terms'] : NULL; $terms = isset($filter['Query']) ? $filter['Query']['terms'] : NULL;
if ( !isset($terms) ) { if ( !isset($terms) ) {
$backTrace = debug_backtrace(); $backTrace = debug_backtrace();
$file = $backTrace[1]['file']; ZM\Warning('No terms in filter');
$line = $backTrace[1]['line']; ZM\Warning(print_r($backTrace, true));
ZM\Warning("No terms in filter from $file:$line");
ZM\Warning(print_r($filter, true)); ZM\Warning(print_r($filter, true));
} }
if ( isset($terms) && count($terms) ) { if ( isset($terms) && count($terms) ) {
@ -1324,7 +1328,7 @@ function parseFilter(&$filter, $saveToSession=false, $querySep='&amp;') {
$filter['query'] .= $querySep.urlencode("filter[Query][terms][$i][val]").'='.urlencode($term['val']); $filter['query'] .= $querySep.urlencode("filter[Query][terms][$i][val]").'='.urlencode($term['val']);
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[Query][terms][$i][val]\" value=\"".htmlspecialchars($term['val'])."\"/>\n"; $filter['fields'] .= "<input type=\"hidden\" name=\"filter[Query][terms][$i][val]\" value=\"".htmlspecialchars($term['val'])."\"/>\n";
} }
} // end if ( isset($term['attr']) ) } // end if isset($term['attr'])
if ( isset($term['cbr']) && (string)(int)$term['cbr'] == $term['cbr'] ) { if ( isset($term['cbr']) && (string)(int)$term['cbr'] == $term['cbr'] ) {
$filter['query'] .= $querySep.urlencode("filter[Query][terms][$i][cbr]").'='.urlencode($term['cbr']); $filter['query'] .= $querySep.urlencode("filter[Query][terms][$i][cbr]").'='.urlencode($term['cbr']);
$filter['sql'] .= ' '.str_repeat(')', $term['cbr']).' '; $filter['sql'] .= ' '.str_repeat(')', $term['cbr']).' ';
@ -1336,6 +1340,8 @@ function parseFilter(&$filter, $saveToSession=false, $querySep='&amp;') {
if ( $saveToSession ) { if ( $saveToSession ) {
$_SESSION['filter'] = $filter; $_SESSION['filter'] = $filter;
} }
} else {
$filter['query'] = $querySep.urlencode('filter[Query][terms]=[]');
} // end if terms } // end if terms
#if ( 0 ) { #if ( 0 ) {
@ -2604,4 +2610,12 @@ function html_radio($name, $values, $selected=null, $options=array(), $attrs=arr
return $html; return $html;
} # end sub html_radio } # 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);
}
?> ?>

View File

@ -0,0 +1,4 @@
input[type="number"] {
width: 70px;
}

View File

@ -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; text-align: center;
} }

View File

@ -9,6 +9,10 @@
width: 100%; width: 100%;
} }
textarea,
input[name="newMonitor[Name]"] {
width: 100%;
}
input[name="newMonitor[Width]"], input[name="newMonitor[Width]"],
input[name="newMonitor[Height]"] { input[name="newMonitor[Height]"] {
width: 80px; width: 80px;

View File

@ -113,17 +113,17 @@ function exportEventDetail($event, $exportFrames, $exportImages) {
<table id="eventDetail"> <table id="eventDetail">
<tr><th scope="row"><?php echo translate('Id') ?></th><td><?php echo $event->Id() ?></td></tr> <tr><th scope="row"><?php echo translate('Id') ?></th><td><?php echo $event->Id() ?></td></tr>
<tr><th scope="row"><?php echo translate('Name') ?></th><td><?php echo validHtmlStr($event->Name()) ?></td></tr> <tr><th scope="row"><?php echo translate('Name') ?></th><td><?php echo validHtmlStr($event->Name()) ?></td></tr>
<tr><th scope="row"><?php echo translate('Monitor') ?></th><td><?php echo validHtmlStr($event->MonitorName()) ?> (<?php echo $event->MonitorId() ?>)</td></tr> <tr><th scope="row"><?php echo translate('Monitor') ?></th><td><?php echo validHtmlStr($event->Monitor()->Name()) ?> (<?php echo $event->MonitorId() ?>)</td></tr>
<tr><th scope="row"><?php echo translate('Cause') ?></th><td><?php echo validHtmlStr($event->Cause()) ?></td></tr> <tr><th scope="row"><?php echo translate('Cause') ?></th><td><?php echo validHtmlStr($event->Cause()) ?></td></tr>
<tr><th scope="row"><?php echo translate('Notes') ?></th><td><?php echo validHtmlStr($event->Notes()) ?></td></tr> <tr><th scope="row"><?php echo translate('Notes') ?></th><td><?php echo validHtmlStr($event->Notes()) ?></td></tr>
<tr><th scope="row"><?php echo translate('Time') ?></th><td><?php echo strftime( STRF_FMT_DATETIME_SHORTER, strtotime($event->StartTime()) ) ?></td></tr> <tr><th scope="row"><?php echo translate('Time') ?></th><td><?php echo strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->StartTime())) ?></td></tr>
<tr><th scope="row"><?php echo translate('Duration') ?></th><td><?php echo $event->Length() ?></td></tr> <tr><th scope="row"><?php echo translate('Duration') ?></th><td><?php echo $event->Length() ?></td></tr>
<tr><th scope="row"><?php echo translate('Frames') ?></th><td><?php echo $event->Frames() ?></td></tr> <tr><th scope="row"><?php echo translate('Frames') ?></th><td><?php echo $event->Frames() ?></td></tr>
<tr><th scope="row"><?php echo translate('AttrAlarmFrames') ?></th><td><?php echo $event->AlarmFrames() ?></td></tr> <tr><th scope="row"><?php echo translate('AttrAlarmFrames') ?></th><td><?php echo $event->AlarmFrames() ?></td></tr>
<tr><th scope="row"><?php echo translate('AttrTotalScore') ?></th><td><?php echo $event->TotScore() ?></td></tr> <tr><th scope="row"><?php echo translate('AttrTotalScore') ?></th><td><?php echo $event->TotScore() ?></td></tr>
<tr><th scope="row"><?php echo translate('AttrAvgScore') ?></th><td><?php echo $event->AvgScore() ?></td></tr> <tr><th scope="row"><?php echo translate('AttrAvgScore') ?></th><td><?php echo $event->AvgScore() ?></td></tr>
<tr><th scope="row"><?php echo translate('AttrMaxScore') ?></th><td><?php echo $event->MaxScore() ?></td></tr> <tr><th scope="row"><?php echo translate('AttrMaxScore') ?></th><td><?php echo $event->MaxScore() ?></td></tr>
<tr><th scope="row"><?php echo translate('Archived') ?></th><td><?php echo $event->Archived()?translate('Yes'):translate('No') ?></td></tr> <tr><th scope="row"><?php echo translate('Archived') ?></th><td><?php echo translate($event->Archived()?'Yes':'No') ?></td></tr>
</table> </table>
</div> </div>
</div> </div>
@ -226,13 +226,13 @@ function exportEventImages($event, $exportDetail, $exportFrames, $myfilelist) {
?> ?>
<body> <body>
<style> <style>
*.horizontal_track {background-color: #bbb;width: <?php echo$event->Width()?>px;line-height: 0px;font-size: 0px;text-align: left;padding: 4px;border: 1px solid;border-color: #ddd #999 #999 #ddd;} .horizontal_track {background-color: #bbb;width: <?php echo $event->Width()?>px;line-height: 0px;font-size: 0px;text-align: left;padding: 4px;border: 1px solid;border-color: #ddd #999 #999 #ddd;}
*.horizontal_slider {background-color: #666;width: 16px;height: 8px;position: relative;z-index: 2;line-height: 0;margin: 0;border: 2px solid;border-color: #999 #333 #333 #999;} .horizontal_slider {background-color: #666;width: 16px;height: 8px;position: relative;z-index: 2;line-height: 0;margin: 0;border: 2px solid;border-color: #999 #333 #333 #999;}
*.horizontal_slit {background-color: #333;width: <?php echo($event->Width()-10)?>px;height: 2px;margin: 4px 4px 2px 4px;line-height: 0;position: absolute;z-index: 1;border: 1px solid;border-color: #999 #ddd #ddd #999;} .horizontal_slit {background-color: #333;width: <?php echo($event->Width()-10)?>px;height: 2px;margin: 4px 4px 2px 4px;line-height: 0;position: absolute;z-index: 1;border: 1px solid;border-color: #999 #ddd #ddd #999;}
*.vertical_track {background-color: #bbb;padding: 3px 5px 15px 5px;border: 1px solid;border-color: #ddd #999 #999 #ddd;} .vertical_track {background-color: #bbb;padding: 3px 5px 15px 5px;border: 1px solid;border-color: #ddd #999 #999 #ddd;}
*.vertical_slider {background-color: #666;width: 18px;height: 8px;font: 0px;text-align: left;line-height: 0px;position: relative;z-index: 1;border: 2px solid;border-color: #999 #333 #333 #999;} .vertical_slider {background-color: #666;width: 18px;height: 8px;font: 0px;text-align: left;line-height: 0px;position: relative;z-index: 1;border: 2px solid;border-color: #999 #333 #333 #999;}
*.vertical_slit {background-color: #000;width: 2px;height: 100px;position: absolute;margin: 4px 10px 4px 10px;padding: 4px 0 1px 0;line-height: 0;font-size: 0;border: 1px solid;border-color: #666 #ccc #ccc #666;} .vertical_slit {background-color: #000;width: 2px;height: 100px;position: absolute;margin: 4px 10px 4px 10px;padding: 4px 0 1px 0;line-height: 0;font-size: 0;border: 1px solid;border-color: #666 #ccc #ccc #666;}
*.display_holder {background-color: #bbb;color: #fff;width: 34px;height: 20px;text-align: right;padding: 0;border: 1px solid;border-color: #ddd #999 #999 #ddd;} .display_holder {background-color: #bbb;color: #fff;width: 34px;height: 20px;text-align: right;padding: 0;border: 1px solid;border-color: #ddd #999 #999 #ddd;}
.value_display {background-color: #bbb;color: #333;width: 30px;margin: 0 2px;text-align: right;font-size: 8pt;font-face: verdana, arial, helvetica, sans-serif;font-weight: bold;line-height: 12px;border: 0;cursor: default;} .value_display {background-color: #bbb;color: #333;width: 30px;margin: 0 2px;text-align: right;font-size: 8pt;font-face: verdana, arial, helvetica, sans-serif;font-weight: bold;line-height: 12px;border: 0;cursor: default;}
</style> </style>
@ -247,7 +247,7 @@ function exportEventImages($event, $exportDetail, $exportFrames, $myfilelist) {
if ( $Monitor->VideoWriter() == '2' ) { if ( $Monitor->VideoWriter() == '2' ) {
# Passthrough # Passthrough
$Rotation = $event->Orientation(); $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(); $Zoom = $event->Height()/$event->Width();
} }
?> ?>
@ -280,7 +280,7 @@ function exportEventImages($event, $exportDetail, $exportFrames, $myfilelist) {
<div align="center"><div class="horizontal_track"> <div align="center"><div class="horizontal_track">
<div class="horizontal_slit">&nbsp;</div> <div class="horizontal_slit">&nbsp;</div>
<div class="horizontal_slider" id="imageslider_id" style="left: 0px;" <div class="horizontal_slider" id="imageslider_id" style="left: 0px;"
onmousedown="slide(event,'horizontal', <?php echo($event->Width()-20)?>, 1, <?php echo$listcount?>, <?php echo$listcount?>,0, 'imageslider_display_id');">&nbsp;</div> onmousedown="slide(event,'horizontal', <?php echo($event->Width()-20)?>, 1, <?php echo $listcount?>, <?php echo $listcount?>,0, 'imageslider_display_id');">&nbsp;</div>
</div> </div>
</div> </div>
<div align="center"><div class="display_holder"><input id="imageslider_display_id" class="value_display" type="text" value="0" onfocus="blur(this);"/></div></div> <div align="center"><div class="display_holder"><input id="imageslider_display_id" class="value_display" type="text" value="0" onfocus="blur(this);"/></div></div>
@ -618,10 +618,10 @@ function exportEventImagesMaster($eids) {
<body> <body>
<h2><?php echo translate('Images') ?> Master</h2> <h2><?php echo translate('Images') ?> Master</h2>
<?php <?php
// TODO: Should use find to make this 1 db query $events = ZM\Event::find(array('Id'=>$eids));
foreach ($eids as $eid) {
foreach ($events as $event) {
//get monitor id and event id //get monitor id and event id
$event = new ZM\Event($eid);
$eventMonitorId[$eid] = $event->MonitorId(); $eventMonitorId[$eid] = $event->MonitorId();
$eventPath[$eid] = $event->Relative_Path(); $eventPath[$eid] = $event->Relative_Path();
} }
@ -653,20 +653,18 @@ function exportEventImagesMaster($eids) {
<div class="tab_content" id="all"> <div class="tab_content" id="all">
<h2> All </h2> <h2> All </h2>
<?php <?php
foreach($eids as $eid) { foreach($events as $event) {
$Event = new ZM\Event($eid); eventlist_html($event);
eventlist_html($Event); } # end foreach event
} # end foreach event id
?> ?>
</div> </div>
<?php <?php
foreach ($monitors as $monitor_id) { foreach ($monitors as $monitor_id) {
echo "<div class=\"tab_content\" id=\"tab$monitor_id\">"; echo "<div class=\"tab_content\" id=\"tab$monitor_id\">";
echo '<h2>Monitor: ' . $monitorNames[$monitor_id] . ' </h2>'; echo '<h2>Monitor: ' . $monitorNames[$monitor_id] . ' </h2>';
foreach ( $eids as $eid ) { foreach ( $events as $event ) {
$Event = new ZM\Event($eid); if ( $event->MonitorId() == $monitor_id ) {
if ( $Event->MonitorId() == $monitor_id ) { eventlist_html($event);
eventlist_html($Event);
} # end if its the right monitor } # end if its the right monitor
} # end foreach event } # end foreach event
echo '</div>'; echo '</div>';
@ -780,7 +778,7 @@ function exportFileList($event, $exportDetail, $exportFrames, $exportImages, $ex
} }
fwrite($fp, exportEventDetail($event, $exportFrames, $exportImages)); fwrite($fp, exportEventDetail($event, $exportFrames, $exportImages));
fclose($fp); fclose($fp);
$exportFileList[$file] = $event->Id().'/'.$file; $exportFileList[$file] = $file;
} }
if ( $exportFrames ) { if ( $exportFrames ) {
$file = 'zmEventFrames.html'; $file = 'zmEventFrames.html';
@ -789,7 +787,7 @@ function exportFileList($event, $exportDetail, $exportFrames, $exportImages, $ex
} }
fwrite($fp, exportEventFrames($event, $exportDetail, $exportImages)); fwrite($fp, exportEventFrames($event, $exportDetail, $exportImages));
fclose($fp); fclose($fp);
$exportFileList[$file] = $event->Id().'/'.$file; $exportFileList[$file] = $file;
} }
if ( $exportImages ) { if ( $exportImages ) {
@ -797,7 +795,7 @@ function exportFileList($event, $exportDetail, $exportFrames, $exportImages, $ex
$myfilelist = array(); $myfilelist = array();
foreach ( $files as $file ) { foreach ( $files as $file ) {
if ( preg_match('/-(?:capture|analyse).jpg$/', $file ) ) { if ( preg_match('/-(?:capture|analyse).jpg$/', $file ) ) {
$myfilelist[$file] = $exportFileList[$file] = $event->Id().'/'.$file; $myfilelist[$file] = $exportFileList[$file] = $file;
} else { } else {
$filesLeft[$file] = $file; $filesLeft[$file] = $file;
} }
@ -806,12 +804,12 @@ function exportFileList($event, $exportDetail, $exportFrames, $exportImages, $ex
// create an image slider // create an image slider
if ( !empty($myfilelist) ) { if ( !empty($myfilelist) ) {
$file = $event->Id().'/zmEventImages.html'; $file = 'zmEventImages.html';
if ( !($fp = fopen($file, 'w')) ) if ( !($fp = fopen($file, 'w')) )
ZM\Fatal("Can't open event images export file '$file'"); ZM\Fatal("Can't open event images export file '$file'");
fwrite($fp, exportEventImages($event, $exportDetail, $exportFrames, $myfilelist)); fwrite($fp, exportEventImages($event, $exportDetail, $exportFrames, $myfilelist));
fclose($fp); fclose($fp);
$exportFileList[$file] = $event->Id().'/'.$file; $exportFileList[$file] = $file;
} }
} # end if exportImages } # end if exportImages
@ -819,7 +817,7 @@ function exportFileList($event, $exportDetail, $exportFrames, $exportImages, $ex
$filesLeft = array(); $filesLeft = array();
foreach ( $files as $file ) { foreach ( $files as $file ) {
if ( preg_match('/\.(?:mpg|mpeg|mov|swf|mp4|mkv|avi|asf|3gp)$/', $file) ) { if ( preg_match('/\.(?:mpg|mpeg|mov|swf|mp4|mkv|avi|asf|3gp)$/', $file) ) {
$exportFileList[$file] = $event->Id().'/'.$file; $exportFileList[$file] = $file;
} else { } else {
$filesLeft[$file] = $file; $filesLeft[$file] = $file;
} }
@ -829,7 +827,7 @@ function exportFileList($event, $exportDetail, $exportFrames, $exportImages, $ex
if ( $exportMisc ) { if ( $exportMisc ) {
foreach ( $files as $file ) { foreach ( $files as $file ) {
$exportFileList[$file] = $event->Id().'/'.$file; $exportFileList[$file] = $file;
} }
$files = array(); $files = array();
} }
@ -850,10 +848,10 @@ function exportEvents(
) { ) {
if ( !canView('Events') ) { 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; return false;
} else if ( empty($eids) ) { } 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; return false;
} }
@ -863,23 +861,22 @@ function exportEvents(
} }
# Ensure that we are going to be able to do this. # Ensure that we are going to be able to do this.
if ( ! file_exists(ZM_DIR_EXPORTS) ) { if ( ! ( mkdir(ZM_DIR_EXPORTS) or file_exists(ZM_DIR_EXPORTS) ) ) {
if ( ! mkdir(ZM_DIR_EXPORTS) ) { ZM\Fatal('Can\'t create exports dir at \''.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; $export_dir = ZM_DIR_EXPORTS.'/zmExport_'.$connkey;
# Ensure that we are going to be able to do this. # Ensure that we are going to be able to do this.
if ( ! file_exists($export_dir) ) { if ( ! ( mkdir($export_dir) or file_exists($export_dir) ) ) {
if ( ! mkdir($export_dir) ) { ZM\Fatal("Can't create exports dir at '$export_dir'");
ZM\Fatal("Can't create exports dir at '$export_dir'"); } else {
} else { ZM\Logger::Debug("Successfully created dir '$export_dir'");
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"); ZM\Fatal("Can't chdir to $export_dir");
}
$export_root = 'zmExport'; $export_root = 'zmExport';
$export_listFile = 'zmFileList.txt'; $export_listFile = 'zmFileList.txt';
@ -889,27 +886,30 @@ function exportEvents(
if ( !is_array($eids) ) { if ( !is_array($eids) ) {
$eids = 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 ) { foreach ( $eids as $eid ) {
$event = new ZM\Event($eid); $event = new ZM\Event($eid);
$event_dir = $export_dir.'/'.$event->Id(); $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"); ZM\Error("Can't mkdir $event_dir");
}
$event_exportFileList = exportFileList($event, $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc); $event_exportFileList = exportFileList($event, $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc);
ZM\Logger::Debug("File list for event $eid " . print_r($event_exportFileList, true)); ZM\Logger::Debug("File list for event $eid " . print_r($event_exportFileList, true));
$exportFileList = array_merge($exportFileList,$event_exportFileList); $exportFileList = array_merge($exportFileList,$event_exportFileList);
foreach ( $event_exportFileList as $file ) { foreach ( $event_exportFileList as $file ) {
if ( preg_match('/\.html$/', $file ) ) if ( preg_match('/\.html$/', $file) )
continue; continue;
ZM\Logger::Debug('cp -as '.$event->Path().'/../'.$file.' '.$export_dir.'/'.$file); #exec('cp -as '.$event->Path().'/../'.$file.' '.$export_dir.'/'.$file, $output, $return);
exec('cp -as '.$event->Path().'/../'.$file.' '.$export_dir.'/'.$file); $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 // create an master image
if ( $exportImages ) { if ( $exportImages ) {
if ( !symlink(ZM_PATH_WEB.'/'.ZM_SKIN_PATH.'/js/jquery.js', $export_dir.'/jquery.js') ) 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') ) //if ( !symlink(ZM_PATH_WEB.'/'.ZM_SKIN_PATH.'/js/video.js', $export_dir.'/video.js') )
//Error("Failed linking video.js"); //Error("Failed linking video.js");
@ -960,12 +960,12 @@ function exportEvents(
@unlink($archive); @unlink($archive);
$command .= ' zmExport_' . $connkey.'/'; $command .= ' zmExport_' . $connkey.'/';
ZM\Logger::Debug("Command is $command");
exec($command, $output, $status); exec($command, $output, $status);
if ( $status ) { if ( $status ) {
ZM\Error("Command '$command' returned with status $status"); ZM\Error("Command '$command' returned with status $status");
if ( isset($output[0]) ) if ( isset($output[0]) ) {
ZM\Error("First line of output is '".$output[0]."'"); ZM\Error('First line of output is \''.$output[0].'\'');
}
return false; return false;
} }

View File

@ -389,8 +389,8 @@ if ( (!ZM_OPT_USE_AUTH) or $user ) {
<li class="Load"><i class="material-icons md-18">trending_up</i>&nbsp;<?php echo translate('Load') ?>: <?php echo getLoad() ?></li> <li class="Load"><i class="material-icons md-18">trending_up</i>&nbsp;<?php echo translate('Load') ?>: <?php echo getLoad() ?></li>
<i class="material-icons md-18">storage</i> <i class="material-icons md-18">storage</i>
<?php <?php
$connections = dbFetchOne( "SHOW status WHERE variable_name='threads_connected'", 'Value' ); $connections = dbFetchOne('SHOW status WHERE variable_name=\'threads_connected\'', 'Value');
$max_connections = dbFetchOne( "SHOW variables WHERE variable_name='max_connections'", 'Value' ); $max_connections = dbFetchOne('SHOW variables WHERE variable_name=\'max_connections\'', 'Value');
$percent_used = $max_connections ? 100 * $connections / $max_connections : 100; $percent_used = $max_connections ? 100 * $connections / $max_connections : 100;
echo '<li'. ( $percent_used > 90 ? ' class="warning"' : '' ).'>'.translate('DB').':'.$connections.'/'.$max_connections.'</li>'; echo '<li'. ( $percent_used > 90 ? ' class="warning"' : '' ).'>'.translate('DB').':'.$connections.'/'.$max_connections.'</li>';
?> ?>
@ -398,8 +398,12 @@ if ( (!ZM_OPT_USE_AUTH) or $user ) {
<?php <?php
$storage_areas = ZM\Storage::find(); $storage_areas = ZM\Storage::find();
$storage_paths = null; $storage_paths = null;
$storage_areas_with_no_server_id = array();
foreach ( $storage_areas as $area ) { foreach ( $storage_areas as $area ) {
$storage_paths[$area->Path()] = $area; $storage_paths[$area->Path()] = $area;
if ( ! $area->ServerId() ) {
$storage_areas_with_no_server_id[] = $area;
}
} }
$func = function($S){ $func = function($S){
$class = ''; $class = '';
@ -415,9 +419,9 @@ if ( (!ZM_OPT_USE_AUTH) or $user ) {
'; }; '; };
#$func = function($S){ return '<span title="">'.$S->Name() . ': ' . $S->disk_usage_percent().'%' . '</span>'; }; #$func = function($S){ return '<span title="">'.$S->Name() . ': ' . $S->disk_usage_percent().'%' . '</span>'; };
if ( count($storage_areas) > 4 ) if ( count($storage_areas) > 4 )
$storage_areas = ZM\Storage::find( array('ServerId'=>null) ); $storage_areas = $storage_areas_with_no_server_id;
if ( count($storage_areas) <= 4 ) if ( count($storage_areas) <= 4 )
echo implode( ', ', array_map ( $func, $storage_areas ) ); echo implode(', ', array_map($func, $storage_areas));
echo ' ' . ZM_PATH_MAP .': '. getDiskPercent(ZM_PATH_MAP).'%'; echo ' ' . ZM_PATH_MAP .': '. getDiskPercent(ZM_PATH_MAP).'%';
?></li> ?></li>
</ul> </ul>

View File

@ -46,7 +46,7 @@ var popupSizes = {
'group': {'width': 760, 'height': 600}, 'group': {'width': 760, 'height': 600},
'groups': {'width': 540, 'height': 420}, 'groups': {'width': 540, 'height': 420},
'image': {'addWidth': 48, 'addHeight': 80}, 'image': {'addWidth': 48, 'addHeight': 80},
'log': {'width': 1080, 'height': 720}, 'log': {'width': 1180, 'height': 720},
'login': {'width': 720, 'height': 480}, 'login': {'width': 720, 'height': 480},
'logout': {'width': 260, 'height': 150}, 'logout': {'width': 260, 'height': 150},
'monitor': {'width': 800, 'height': 780}, 'monitor': {'width': 800, 'height': 780},

View File

@ -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. // '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"); var fnName = el.getAttribute("data-on-click");
if ( !window[fnName] ) { if ( !window[fnName] ) {
console.error("Nothing found to bind to " + fnName + " on element " + el.name); console.error("Nothing found to bind to " + fnName + " on element " + el.name);
return; return;
} }
el.onclick = function() { el.onclick = function() {
window[fnName](); window[fnName]();
}; };

View File

@ -18,40 +18,31 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
// //
if ( !canEdit( 'Control' ) ) if ( !canEdit('Control') ) {
{ $view = 'error';
$view = "error"; return;
return;
} }
$tabs = array(); $tabs = array();
$tabs["main"] = translate('Main'); $tabs['main'] = translate('Main');
$tabs["move"] = translate('Move'); $tabs['move'] = translate('Move');
$tabs["pan"] = translate('Pan'); $tabs['pan'] = translate('Pan');
$tabs["tilt"] = translate('Tilt'); $tabs['tilt'] = translate('Tilt');
$tabs["zoom"] = translate('Zoom'); $tabs['zoom'] = translate('Zoom');
$tabs["focus"] = translate('Focus'); $tabs['focus'] = translate('Focus');
$tabs["white"] = translate('White'); $tabs['gain'] = translate('Gain');
$tabs["iris"] = translate('Iris'); $tabs['white'] = translate('White');
$tabs["presets"] = translate('Presets'); $tabs['iris'] = translate('Iris');
$tabs['presets'] = translate('Presets');
if ( isset($_REQUEST['tab']) ) $tab = isset($_REQUEST['tab']) ? validHtmlStr($_REQUEST['tab']) :'main';
$tab = validHtmlStr($_REQUEST['tab']);
else
$tab = "main";
if ( isset( $_REQUEST['newControl'] ) ) if ( isset($_REQUEST['newControl']) ) {
{
$newControl = $_REQUEST['newControl']; $newControl = $_REQUEST['newControl'];
} } else {
else if ( !empty($_REQUEST['cid']) ) {
{ $control = dbFetchOne('SELECT * FROM Controls WHERE Id = ?', NULL, array($_REQUEST['cid']));
if ( !empty($_REQUEST['cid']) ) } else {
{
$control = dbFetchOne( 'SELECT * FROM Controls WHERE Id = ?', NULL, array($_REQUEST['cid'] ) );
}
else
{
$control = array( $control = array(
'Name' => translate('New'), 'Name' => translate('New'),
'Type' => "Local", 'Type' => "Local",
@ -166,16 +157,12 @@ xhtmlHeaders(__FILE__, translate('ControlCap')." - ".$newControl['Name'] );
<div id="content"> <div id="content">
<ul class="tabList"> <ul class="tabList">
<?php <?php
foreach ( $tabs as $name=>$value ) foreach ( $tabs as $name=>$value ) {
{ if ( $tab == $name ) {
if ( $tab == $name )
{
?> ?>
<li class="active"><?php echo $value ?></li> <li class="active"><?php echo $value ?></li>
<?php <?php
} } else {
else
{
?> ?>
<li><a href="#" data-tab-name="<?php echo $name ?>"><?php echo $value ?></a></li> <li><a href="#" data-tab-name="<?php echo $name ?>"><?php echo $value ?></a></li>
<?php <?php
@ -190,8 +177,7 @@ foreach ( $tabs as $name=>$value )
<input type="hidden" name="action" value="controlcap"/> <input type="hidden" name="action" value="controlcap"/>
<input type="hidden" name="cid" value="<?php echo requestVar('cid') ?>"/> <input type="hidden" name="cid" value="<?php echo requestVar('cid') ?>"/>
<?php <?php
if ( $tab != 'main' ) if ( $tab != 'main' ) {
{
?> ?>
<input type="hidden" name="newControl[Name]" value="<?php echo validHtmlStr($newControl['Name']) ?>"/> <input type="hidden" name="newControl[Name]" value="<?php echo validHtmlStr($newControl['Name']) ?>"/>
<input type="hidden" name="newControl[Type]" value="<?php echo validHtmlStr($newControl['Type']) ?>"/> <input type="hidden" name="newControl[Type]" value="<?php echo validHtmlStr($newControl['Type']) ?>"/>
@ -201,8 +187,7 @@ if ( $tab != 'main' )
<input type="hidden" name="newControl[CanReset]" value="<?php echo !empty($newControl['CanReset']) ?>"/> <input type="hidden" name="newControl[CanReset]" value="<?php echo !empty($newControl['CanReset']) ?>"/>
<?php <?php
} }
if ( $tab != 'move' ) if ( $tab != 'move' ) {
{
?> ?>
<input type="hidden" name="newControl[CanMove]" value="<?php echo !empty($newControl['CanMove']) ?>"/> <input type="hidden" name="newControl[CanMove]" value="<?php echo !empty($newControl['CanMove']) ?>"/>
<input type="hidden" name="newControl[CanMoveDiag]" value="<?php echo !empty($newControl['CanMoveDiag']) ?>"/> <input type="hidden" name="newControl[CanMoveDiag]" value="<?php echo !empty($newControl['CanMoveDiag']) ?>"/>
@ -212,8 +197,7 @@ if ( $tab != 'move' )
<input type="hidden" name="newControl[CanMoveCon]" value="<?php echo !empty($newControl['CanMoveCon']) ?>"/> <input type="hidden" name="newControl[CanMoveCon]" value="<?php echo !empty($newControl['CanMoveCon']) ?>"/>
<?php <?php
} }
if ( $tab != 'pan' ) if ( $tab != 'pan' ) {
{
?> ?>
<input type="hidden" name="newControl[CanPan]" value="<?php echo !empty($newControl['CanPan']) ?>"/> <input type="hidden" name="newControl[CanPan]" value="<?php echo !empty($newControl['CanPan']) ?>"/>
<input type="hidden" name="newControl[MinPanRange]" value="<?php echo validHtmlStr($newControl['MinPanRange']) ?>"/> <input type="hidden" name="newControl[MinPanRange]" value="<?php echo validHtmlStr($newControl['MinPanRange']) ?>"/>
@ -227,8 +211,7 @@ if ( $tab != 'pan' )
<input type="hidden" name="newControl[TurboPanSpeed]" value="<?php echo validHtmlStr($newControl['TurboPanSpeed']) ?>"/> <input type="hidden" name="newControl[TurboPanSpeed]" value="<?php echo validHtmlStr($newControl['TurboPanSpeed']) ?>"/>
<?php <?php
} }
if ( $tab != 'tilt' ) if ( $tab != 'tilt' ) {
{
?> ?>
<input type="hidden" name="newControl[CanTilt]" value="<?php echo !empty($newControl['CanTilt']) ?>"/> <input type="hidden" name="newControl[CanTilt]" value="<?php echo !empty($newControl['CanTilt']) ?>"/>
<input type="hidden" name="newControl[MinTiltRange]" value="<?php echo validHtmlStr($newControl['MinTiltRange']) ?>"/> <input type="hidden" name="newControl[MinTiltRange]" value="<?php echo validHtmlStr($newControl['MinTiltRange']) ?>"/>
@ -242,8 +225,7 @@ if ( $tab != 'tilt' )
<input type="hidden" name="newControl[TurboTiltSpeed]" value="<?php echo validHtmlStr($newControl['TurboTiltSpeed']) ?>"/> <input type="hidden" name="newControl[TurboTiltSpeed]" value="<?php echo validHtmlStr($newControl['TurboTiltSpeed']) ?>"/>
<?php <?php
} }
if ( $tab != 'zoom' ) if ( $tab != 'zoom' ) {
{
?> ?>
<input type="hidden" name="newControl[CanZoom]" value="<?php echo !empty($newControl['CanZoom']) ?>"/> <input type="hidden" name="newControl[CanZoom]" value="<?php echo !empty($newControl['CanZoom']) ?>"/>
<input type="hidden" name="newControl[CanZoomAbs]" value="<?php echo !empty($newControl['CanZoomAbs']) ?>"/> <input type="hidden" name="newControl[CanZoomAbs]" value="<?php echo !empty($newControl['CanZoomAbs']) ?>"/>
@ -258,8 +240,7 @@ if ( $tab != 'zoom' )
<input type="hidden" name="newControl[MaxZoomSpeed]" value="<?php echo validHtmlStr($newControl['MaxZoomSpeed']) ?>"/> <input type="hidden" name="newControl[MaxZoomSpeed]" value="<?php echo validHtmlStr($newControl['MaxZoomSpeed']) ?>"/>
<?php <?php
} }
if ( $tab != 'focus' ) if ( $tab != 'focus' ) {
{
?> ?>
<input type="hidden" name="newControl[CanFocus]" value="<?php echo !empty($newControl['CanFocus']) ?>"/> <input type="hidden" name="newControl[CanFocus]" value="<?php echo !empty($newControl['CanFocus']) ?>"/>
<input type="hidden" name="newControl[CanAutoFocus]" value="<?php echo !empty($newControl['CanAutoFocus']) ?>"/> <input type="hidden" name="newControl[CanAutoFocus]" value="<?php echo !empty($newControl['CanAutoFocus']) ?>"/>
@ -275,8 +256,7 @@ if ( $tab != 'focus' )
<input type="hidden" name="newControl[MaxFocusSpeed]" value="<?php echo validHtmlStr($newControl['MaxFocusSpeed']) ?>"/> <input type="hidden" name="newControl[MaxFocusSpeed]" value="<?php echo validHtmlStr($newControl['MaxFocusSpeed']) ?>"/>
<?php <?php
} }
if ( $tab != 'iris' ) if ( $tab != 'iris' ) {
{
?> ?>
<input type="hidden" name="newControl[CanIris]" value="<?php echo !empty($newControl['CanIris']) ?>"/> <input type="hidden" name="newControl[CanIris]" value="<?php echo !empty($newControl['CanIris']) ?>"/>
<input type="hidden" name="newControl[CanAutoIris]" value="<?php echo !empty($newControl['CanAutoIris']) ?>"/> <input type="hidden" name="newControl[CanAutoIris]" value="<?php echo !empty($newControl['CanAutoIris']) ?>"/>
@ -292,8 +272,7 @@ if ( $tab != 'iris' )
<input type="hidden" name="newControl[MaxIrisSpeed]" value="<?php echo validHtmlStr($newControl['MaxIrisSpeed']) ?>"/> <input type="hidden" name="newControl[MaxIrisSpeed]" value="<?php echo validHtmlStr($newControl['MaxIrisSpeed']) ?>"/>
<?php <?php
} }
if ( $tab != 'gain' ) if ( $tab != 'gain' ) {
{
?> ?>
<input type="hidden" name="newControl[CanGain]" value="<?php echo !empty($newControl['CanGain']) ?>"/> <input type="hidden" name="newControl[CanGain]" value="<?php echo !empty($newControl['CanGain']) ?>"/>
<input type="hidden" name="newControl[CanAutoGain]" value="<?php echo !empty($newControl['CanAutoGain']) ?>"/> <input type="hidden" name="newControl[CanAutoGain]" value="<?php echo !empty($newControl['CanAutoGain']) ?>"/>
@ -309,8 +288,7 @@ if ( $tab != 'gain' )
<input type="hidden" name="newControl[MaxGainSpeed]" value="<?php echo validHtmlStr($newControl['MaxGainSpeed']) ?>"/> <input type="hidden" name="newControl[MaxGainSpeed]" value="<?php echo validHtmlStr($newControl['MaxGainSpeed']) ?>"/>
<?php <?php
} }
if ( $tab != 'white' ) if ( $tab != 'white' ) {
{
?> ?>
<input type="hidden" name="newControl[CanWhite]" value="<?php echo !empty($newControl['CanWhite']) ?>"/> <input type="hidden" name="newControl[CanWhite]" value="<?php echo !empty($newControl['CanWhite']) ?>"/>
<input type="hidden" name="newControl[CanAutoWhite]" value="<?php echo !empty($newControl['CanAutoWhite']) ?>"/> <input type="hidden" name="newControl[CanAutoWhite]" value="<?php echo !empty($newControl['CanAutoWhite']) ?>"/>
@ -326,8 +304,7 @@ if ( $tab != 'white' )
<input type="hidden" name="newControl[MaxWhiteSpeed]" value="<?php echo validHtmlStr($newControl['MaxWhiteSpeed']) ?>"/> <input type="hidden" name="newControl[MaxWhiteSpeed]" value="<?php echo validHtmlStr($newControl['MaxWhiteSpeed']) ?>"/>
<?php <?php
} }
if ( $tab != 'presets' ) if ( $tab != 'presets' ) {
{
?> ?>
<input type="hidden" name="newControl[HasPresets]" value="<?php echo !empty($newControl['HasPresets']) ?>"/> <input type="hidden" name="newControl[HasPresets]" value="<?php echo !empty($newControl['HasPresets']) ?>"/>
<input type="hidden" name="newControl[NumPresets]" value="<?php echo validHtmlStr($newControl['NumPresets']) ?>"/> <input type="hidden" name="newControl[NumPresets]" value="<?php echo validHtmlStr($newControl['NumPresets']) ?>"/>
@ -336,19 +313,17 @@ if ( $tab != 'presets' )
<?php <?php
} }
?> ?>
<table id="contentTable" class="major" cellspacing="0"> <table id="contentTable" class="major">
<tbody> <tbody>
<?php <?php
switch ( $tab ) switch ( $tab ) {
{ case 'main' :
case 'main' : {
{
?> ?>
<tr><th scope="row"><?php echo translate('Name') ?></th><td><input type="text" name="newControl[Name]" value="<?php echo validHtmlStr($newControl['Name']) ?>" size="24"/></td></tr> <tr><th scope="row"><?php echo translate('Name') ?></th><td><input type="text" name="newControl[Name]" value="<?php echo validHtmlStr($newControl['Name']) ?>"/></td></tr>
<?php <tr><th scope="row"><?php echo translate('Type') ?></th><td><?php
$types = array( 'Local'=>translate('Local'), 'Remote'=>translate('Remote'), 'Ffmpeg'=>translate('Ffmpeg'), 'Libvlc'=>translate('Libvlc'), 'cURL'=>"cURL"); $types = array( 'Local'=>translate('Local'), 'Remote'=>translate('Remote'), 'Ffmpeg'=>translate('Ffmpeg'), 'Libvlc'=>translate('Libvlc'), 'cURL'=>'cURL');
?> echo buildSelect('newControl[Type]', $types); ?></td></tr>
<tr><th scope="row"><?php echo translate('Type') ?></th><td><?php echo buildSelect( "newControl[Type]", $types ); ?></td></tr>
<tr><th scope="row"><?php echo translate('Protocol') ?></th><td><input type="text" name="newControl[Protocol]" value="<?php echo validHtmlStr($newControl['Protocol']) ?>" size="24"/></td></tr> <tr><th scope="row"><?php echo translate('Protocol') ?></th><td><input type="text" name="newControl[Protocol]" value="<?php echo validHtmlStr($newControl['Protocol']) ?>" size="24"/></td></tr>
<tr><th scope="row"><?php echo translate('CanWake') ?></th><td><input type="checkbox" name="newControl[CanWake]" value="1"<?php if ( !empty($newControl['CanWake']) ) { ?> checked="checked"<?php } ?>/></td></tr> <tr><th scope="row"><?php echo translate('CanWake') ?></th><td><input type="checkbox" name="newControl[CanWake]" value="1"<?php if ( !empty($newControl['CanWake']) ) { ?> checked="checked"<?php } ?>/></td></tr>
<tr><th scope="row"><?php echo translate('CanSleep') ?></th><td><input type="checkbox" name="newControl[CanSleep]" value="1"<?php if ( !empty($newControl['CanSleep']) ) { ?> checked="checked"<?php } ?>/></td></tr> <tr><th scope="row"><?php echo translate('CanSleep') ?></th><td><input type="checkbox" name="newControl[CanSleep]" value="1"<?php if ( !empty($newControl['CanSleep']) ) { ?> checked="checked"<?php } ?>/></td></tr>
@ -373,15 +348,15 @@ switch ( $tab )
{ {
?> ?>
<tr><th scope="row"><?php echo translate('CanPan') ?></th><td><input type="checkbox" name="newControl[CanPan]" value="1"<?php if ( !empty($newControl['CanPan']) ) { ?> checked="checked"<?php } ?>></td></tr> <tr><th scope="row"><?php echo translate('CanPan') ?></th><td><input type="checkbox" name="newControl[CanPan]" value="1"<?php if ( !empty($newControl['CanPan']) ) { ?> checked="checked"<?php } ?>></td></tr>
<tr><th scope="row"><?php echo translate('MinPanRange') ?></th><td><input type="text" name="newControl[MinPanRange]" value="<?php echo validHtmlStr($newControl['MinPanRange']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MinPanRange') ?></th><td><input type="number" name="newControl[MinPanRange]" value="<?php echo validHtmlStr($newControl['MinPanRange']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('MaxPanRange') ?></th><td><input type="text" name="newControl[MaxPanRange]" value="<?php echo validHtmlStr($newControl['MaxPanRange']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MaxPanRange') ?></th><td><input type="number" name="newControl[MaxPanRange]" value="<?php echo validHtmlStr($newControl['MaxPanRange']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('MinPanStep') ?></th><td><input type="text" name="newControl[MinPanStep]" value="<?php echo validHtmlStr($newControl['MinPanStep']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MinPanStep') ?></th><td><input type="number" name="newControl[MinPanStep]" value="<?php echo validHtmlStr($newControl['MinPanStep']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('MaxPanStep') ?></th><td><input type="text" name="newControl[MaxPanStep]" value="<?php echo validHtmlStr($newControl['MaxPanStep']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MaxPanStep') ?></th><td><input type="number" name="newControl[MaxPanStep]" value="<?php echo validHtmlStr($newControl['MaxPanStep']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('HasPanSpeed') ?></th><td><input type="checkbox" name="newControl[HasPanSpeed]" value="1"<?php if ( !empty($newControl['HasPanSpeed']) ) { ?> checked="checked"<?php } ?>/></td></tr> <tr><th scope="row"><?php echo translate('HasPanSpeed') ?></th><td><input type="checkbox" name="newControl[HasPanSpeed]" value="1"<?php if ( !empty($newControl['HasPanSpeed']) ) { ?> checked="checked"<?php } ?>/></td></tr>
<tr><th scope="row"><?php echo translate('MinPanSpeed') ?></th><td><input type="text" name="newControl[MinPanSpeed]" value="<?php echo validHtmlStr($newControl['MinPanSpeed']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MinPanSpeed') ?></th><td><input type="number" name="newControl[MinPanSpeed]" value="<?php echo validHtmlStr($newControl['MinPanSpeed']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('MaxPanSpeed') ?></th><td><input type="text" name="newControl[MaxPanSpeed]" value="<?php echo validHtmlStr($newControl['MaxPanSpeed']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MaxPanSpeed') ?></th><td><input type="number" name="newControl[MaxPanSpeed]" value="<?php echo validHtmlStr($newControl['MaxPanSpeed']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('HasTurboPan') ?></th><td><input type="checkbox" name="newControl[HasTurboPan]" value="1"<?php if ( !empty($newControl['HasTurboPan']) ) { ?> checked="checked"<?php } ?>/></td></tr> <tr><th scope="row"><?php echo translate('HasTurboPan') ?></th><td><input type="checkbox" name="newControl[HasTurboPan]" value="1"<?php if ( !empty($newControl['HasTurboPan']) ) { ?> checked="checked"<?php } ?>/></td></tr>
<tr><th scope="row"><?php echo translate('TurboPanSpeed') ?></th><td><input type="text" name="newControl[TurboPanSpeed]" value="<?php echo validHtmlStr($newControl['TurboPanSpeed']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('TurboPanSpeed') ?></th><td><input type="number" name="newControl[TurboPanSpeed]" value="<?php echo validHtmlStr($newControl['TurboPanSpeed']) ?>"/></td></tr>
<?php <?php
break; break;
} }
@ -389,15 +364,15 @@ switch ( $tab )
{ {
?> ?>
<tr><th scope="row"><?php echo translate('CanTilt') ?></th><td><input type="checkbox" name="newControl[CanTilt]" value="1"<?php if ( !empty($newControl['CanTilt']) ) { ?> checked="checked"<?php } ?>></td></tr> <tr><th scope="row"><?php echo translate('CanTilt') ?></th><td><input type="checkbox" name="newControl[CanTilt]" value="1"<?php if ( !empty($newControl['CanTilt']) ) { ?> checked="checked"<?php } ?>></td></tr>
<tr><th scope="row"><?php echo translate('MinTiltRange') ?></th><td><input type="text" name="newControl[MinTiltRange]" value="<?php echo validHtmlStr($newControl['MinTiltRange']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MinTiltRange') ?></th><td><input type="number" name="newControl[MinTiltRange]" value="<?php echo validHtmlStr($newControl['MinTiltRange']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('MaxTiltRange') ?></th><td><input type="text" name="newControl[MaxTiltRange]" value="<?php echo validHtmlStr($newControl['MaxTiltRange']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MaxTiltRange') ?></th><td><input type="number" name="newControl[MaxTiltRange]" value="<?php echo validHtmlStr($newControl['MaxTiltRange']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('MinTiltStep') ?></th><td><input type="text" name="newControl[MinTiltStep]" value="<?php echo validHtmlStr($newControl['MinTiltStep']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MinTiltStep') ?></th><td><input type="number" name="newControl[MinTiltStep]" value="<?php echo validHtmlStr($newControl['MinTiltStep']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('MaxTiltStep') ?></th><td><input type="text" name="newControl[MaxTiltStep]" value="<?php echo validHtmlStr($newControl['MaxTiltStep']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MaxTiltStep') ?></th><td><input type="number" name="newControl[MaxTiltStep]" value="<?php echo validHtmlStr($newControl['MaxTiltStep']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('HasTiltSpeed') ?></th><td><input type="checkbox" name="newControl[HasTiltSpeed]" value="1"<?php if ( !empty($newControl['HasTiltSpeed']) ) { ?> checked="checked"<?php } ?>/></td></tr> <tr><th scope="row"><?php echo translate('HasTiltSpeed') ?></th><td><input type="checkbox" name="newControl[HasTiltSpeed]" value="1"<?php if ( !empty($newControl['HasTiltSpeed']) ) { ?> checked="checked"<?php } ?>/></td></tr>
<tr><th scope="row"><?php echo translate('MinTiltSpeed') ?></th><td><input type="text" name="newControl[MinTiltSpeed]" value="<?php echo validHtmlStr($newControl['MinTiltSpeed']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MinTiltSpeed') ?></th><td><input type="number" name="newControl[MinTiltSpeed]" value="<?php echo validHtmlStr($newControl['MinTiltSpeed']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('MaxTiltSpeed') ?></th><td><input type="text" name="newControl[MaxTiltSpeed]" value="<?php echo validHtmlStr($newControl['MaxTiltSpeed']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MaxTiltSpeed') ?></th><td><input type="number" name="newControl[MaxTiltSpeed]" value="<?php echo validHtmlStr($newControl['MaxTiltSpeed']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('HasTurboTilt') ?></th><td><input type="checkbox" name="newControl[HasTurboTilt]" value="1"<?php if ( !empty($newControl['HasTurboTilt']) ) { ?> checked="checked"<?php } ?>/></td></tr> <tr><th scope="row"><?php echo translate('HasTurboTilt') ?></th><td><input type="checkbox" name="newControl[HasTurboTilt]" value="1"<?php if ( !empty($newControl['HasTurboTilt']) ) { ?> checked="checked"<?php } ?>/></td></tr>
<tr><th scope="row"><?php echo translate('TurboTiltSpeed') ?></th><td><input type="text" name="newControl[TurboTiltSpeed]" value="<?php echo validHtmlStr($newControl['TurboTiltSpeed']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('TurboTiltSpeed') ?></th><td><input type="number" name="newControl[TurboTiltSpeed]" value="<?php echo validHtmlStr($newControl['TurboTiltSpeed']) ?>"/></td></tr>
<?php <?php
break; break;
} }
@ -408,13 +383,13 @@ switch ( $tab )
<tr><th scope="row"><?php echo translate('CanZoomAbs') ?></th><td><input type="checkbox" name="newControl[CanZoomAbs]" value="1"<?php if ( !empty($newControl['CanZoomAbs']) ) { ?> checked="checked"<?php } ?>/></td></tr> <tr><th scope="row"><?php echo translate('CanZoomAbs') ?></th><td><input type="checkbox" name="newControl[CanZoomAbs]" value="1"<?php if ( !empty($newControl['CanZoomAbs']) ) { ?> checked="checked"<?php } ?>/></td></tr>
<tr><th scope="row"><?php echo translate('CanZoomRel') ?></th><td><input type="checkbox" name="newControl[CanZoomRel]" value="1"<?php if ( !empty($newControl['CanZoomRel']) ) { ?> checked="checked"<?php } ?>/></td></tr> <tr><th scope="row"><?php echo translate('CanZoomRel') ?></th><td><input type="checkbox" name="newControl[CanZoomRel]" value="1"<?php if ( !empty($newControl['CanZoomRel']) ) { ?> checked="checked"<?php } ?>/></td></tr>
<tr><th scope="row"><?php echo translate('CanZoomCon') ?></th><td><input type="checkbox" name="newControl[CanZoomCon]" value="1"<?php if ( !empty($newControl['CanZoomCon']) ) { ?> checked="checked"<?php } ?>/></td></tr> <tr><th scope="row"><?php echo translate('CanZoomCon') ?></th><td><input type="checkbox" name="newControl[CanZoomCon]" value="1"<?php if ( !empty($newControl['CanZoomCon']) ) { ?> checked="checked"<?php } ?>/></td></tr>
<tr><th scope="row"><?php echo translate('MinZoomRange') ?></th><td><input type="text" name="newControl[MinZoomRange]" value="<?php echo validHtmlStr($newControl['MinZoomRange']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MinZoomRange') ?></th><td><input type="number" name="newControl[MinZoomRange]" value="<?php echo validHtmlStr($newControl['MinZoomRange']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('MaxZoomRange') ?></th><td><input type="text" name="newControl[MaxZoomRange]" value="<?php echo validHtmlStr($newControl['MaxZoomRange']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MaxZoomRange') ?></th><td><input type="number" name="newControl[MaxZoomRange]" value="<?php echo validHtmlStr($newControl['MaxZoomRange']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('MinZoomStep') ?></th><td><input type="text" name="newControl[MinZoomStep]" value="<?php echo validHtmlStr($newControl['MinZoomStep']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MinZoomStep') ?></th><td><input type="number" name="newControl[MinZoomStep]" value="<?php echo validHtmlStr($newControl['MinZoomStep']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('MaxZoomStep') ?></th><td><input type="text" name="newControl[MaxZoomStep]" value="<?php echo validHtmlStr($newControl['MaxZoomStep']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MaxZoomStep') ?></th><td><input type="number" name="newControl[MaxZoomStep]" value="<?php echo validHtmlStr($newControl['MaxZoomStep']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('HasZoomSpeed') ?></th><td><input type="checkbox" name="newControl[HasZoomSpeed]" value="1"<?php if ( !empty($newControl['HasZoomSpeed']) ) { ?> checked="checked"<?php } ?>/></td></tr> <tr><th scope="row"><?php echo translate('HasZoomSpeed') ?></th><td><input type="checkbox" name="newControl[HasZoomSpeed]" value="1"<?php if ( !empty($newControl['HasZoomSpeed']) ) { ?> checked="checked"<?php } ?>/></td></tr>
<tr><th scope="row"><?php echo translate('MinZoomSpeed') ?></th><td><input type="text" name="newControl[MinZoomSpeed]" value="<?php echo validHtmlStr($newControl['MinZoomSpeed']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MinZoomSpeed') ?></th><td><input type="number" name="newControl[MinZoomSpeed]" value="<?php echo validHtmlStr($newControl['MinZoomSpeed']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('MaxZoomSpeed') ?></th><td><input type="text" name="newControl[MaxZoomSpeed]" value="<?php echo validHtmlStr($newControl['MaxZoomSpeed']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MaxZoomSpeed') ?></th><td><input type="number" name="newControl[MaxZoomSpeed]" value="<?php echo validHtmlStr($newControl['MaxZoomSpeed']) ?>"/></td></tr>
<?php <?php
break; break;
} }
@ -426,13 +401,13 @@ switch ( $tab )
<tr><th scope="row"><?php echo translate('CanFocusAbs') ?></th><td><input type="checkbox" name="newControl[CanFocusAbs]" value="1"<?php if ( !empty($newControl['CanFocusAbs']) ) { ?> checked="checked"<?php } ?>/></td></tr> <tr><th scope="row"><?php echo translate('CanFocusAbs') ?></th><td><input type="checkbox" name="newControl[CanFocusAbs]" value="1"<?php if ( !empty($newControl['CanFocusAbs']) ) { ?> checked="checked"<?php } ?>/></td></tr>
<tr><th scope="row"><?php echo translate('CanFocusRel') ?></th><td><input type="checkbox" name="newControl[CanFocusRel]" value="1"<?php if ( !empty($newControl['CanFocusRel']) ) { ?> checked="checked"<?php } ?>/></td></tr> <tr><th scope="row"><?php echo translate('CanFocusRel') ?></th><td><input type="checkbox" name="newControl[CanFocusRel]" value="1"<?php if ( !empty($newControl['CanFocusRel']) ) { ?> checked="checked"<?php } ?>/></td></tr>
<tr><th scope="row"><?php echo translate('CanFocusCon') ?></th><td><input type="checkbox" name="newControl[CanFocusCon]" value="1"<?php if ( !empty($newControl['CanFocusCon']) ) { ?> checked="checked"<?php } ?>/></td></tr> <tr><th scope="row"><?php echo translate('CanFocusCon') ?></th><td><input type="checkbox" name="newControl[CanFocusCon]" value="1"<?php if ( !empty($newControl['CanFocusCon']) ) { ?> checked="checked"<?php } ?>/></td></tr>
<tr><th scope="row"><?php echo translate('MinFocusRange') ?></th><td><input type="text" name="newControl[MinFocusRange]" value="<?php echo validHtmlStr($newControl['MinFocusRange']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MinFocusRange') ?></th><td><input type="number" name="newControl[MinFocusRange]" value="<?php echo validHtmlStr($newControl['MinFocusRange']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('MaxFocusRange') ?></th><td><input type="text" name="newControl[MaxFocusRange]" value="<?php echo validHtmlStr($newControl['MaxFocusRange']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MaxFocusRange') ?></th><td><input type="number" name="newControl[MaxFocusRange]" value="<?php echo validHtmlStr($newControl['MaxFocusRange']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('MinFocusStep') ?></th><td><input type="text" name="newControl[MinFocusStep]" value="<?php echo validHtmlStr($newControl['MinFocusStep']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MinFocusStep') ?></th><td><input type="number" name="newControl[MinFocusStep]" value="<?php echo validHtmlStr($newControl['MinFocusStep']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('MaxFocusStep') ?></th><td><input type="text" name="newControl[MaxFocusStep]" value="<?php echo validHtmlStr($newControl['MaxFocusStep']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MaxFocusStep') ?></th><td><input type="number" name="newControl[MaxFocusStep]" value="<?php echo validHtmlStr($newControl['MaxFocusStep']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('HasFocusSpeed') ?></th><td><input type="checkbox" name="newControl[HasFocusSpeed]" value="1"<?php if ( !empty($newControl['HasFocusSpeed']) ) { ?> checked="checked"<?php } ?>/></td></tr> <tr><th scope="row"><?php echo translate('HasFocusSpeed') ?></th><td><input type="checkbox" name="newControl[HasFocusSpeed]" value="1"<?php if ( !empty($newControl['HasFocusSpeed']) ) { ?> checked="checked"<?php } ?>/></td></tr>
<tr><th scope="row"><?php echo translate('MinFocusSpeed') ?></th><td><input type="text" name="newControl[MinFocusSpeed]" value="<?php echo validHtmlStr($newControl['MinFocusSpeed']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MinFocusSpeed') ?></th><td><input type="number" name="newControl[MinFocusSpeed]" value="<?php echo validHtmlStr($newControl['MinFocusSpeed']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('MaxFocusSpeed') ?></th><td><input type="text" name="newControl[MaxFocusSpeed]" value="<?php echo validHtmlStr($newControl['MaxFocusSpeed']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MaxFocusSpeed') ?></th><td><input type="number" name="newControl[MaxFocusSpeed]" value="<?php echo validHtmlStr($newControl['MaxFocusSpeed']) ?>"/></td></tr>
<?php <?php
break; break;
} }
@ -444,13 +419,13 @@ switch ( $tab )
<tr><th scope="row"><?php echo translate('CanIrisAbs') ?></th><td><input type="checkbox" name="newControl[CanIrisAbs]" value="1"<?php if ( !empty($newControl['CanIrisAbs']) ) { ?> checked="checked"<?php } ?>/></td></tr> <tr><th scope="row"><?php echo translate('CanIrisAbs') ?></th><td><input type="checkbox" name="newControl[CanIrisAbs]" value="1"<?php if ( !empty($newControl['CanIrisAbs']) ) { ?> checked="checked"<?php } ?>/></td></tr>
<tr><th scope="row"><?php echo translate('CanIrisRel') ?></th><td><input type="checkbox" name="newControl[CanIrisRel]" value="1"<?php if ( !empty($newControl['CanIrisRel']) ) { ?> checked="checked"<?php } ?>/></td></tr> <tr><th scope="row"><?php echo translate('CanIrisRel') ?></th><td><input type="checkbox" name="newControl[CanIrisRel]" value="1"<?php if ( !empty($newControl['CanIrisRel']) ) { ?> checked="checked"<?php } ?>/></td></tr>
<tr><th scope="row"><?php echo translate('CanIrisCon') ?></th><td><input type="checkbox" name="newControl[CanIrisCon]" value="1"<?php if ( !empty($newControl['CanIrisCon']) ) { ?> checked="checked"<?php } ?>/></td></tr> <tr><th scope="row"><?php echo translate('CanIrisCon') ?></th><td><input type="checkbox" name="newControl[CanIrisCon]" value="1"<?php if ( !empty($newControl['CanIrisCon']) ) { ?> checked="checked"<?php } ?>/></td></tr>
<tr><th scope="row"><?php echo translate('MinIrisRange') ?></th><td><input type="text" name="newControl[MinIrisRange]" value="<?php echo validHtmlStr($newControl['MinIrisRange']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MinIrisRange') ?></th><td><input type="number" name="newControl[MinIrisRange]" value="<?php echo validHtmlStr($newControl['MinIrisRange']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('MaxIrisRange') ?></th><td><input type="text" name="newControl[MaxIrisRange]" value="<?php echo validHtmlStr($newControl['MaxIrisRange']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MaxIrisRange') ?></th><td><input type="number" name="newControl[MaxIrisRange]" value="<?php echo validHtmlStr($newControl['MaxIrisRange']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('MinIrisStep') ?></th><td><input type="text" name="newControl[MinIrisStep]" value="<?php echo validHtmlStr($newControl['MinIrisStep']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MinIrisStep') ?></th><td><input type="number" name="newControl[MinIrisStep]" value="<?php echo validHtmlStr($newControl['MinIrisStep']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('MaxIrisStep') ?></th><td><input type="text" name="newControl[MaxIrisStep]" value="<?php echo validHtmlStr($newControl['MaxIrisStep']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MaxIrisStep') ?></th><td><input type="number" name="newControl[MaxIrisStep]" value="<?php echo validHtmlStr($newControl['MaxIrisStep']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('HasIrisSpeed') ?></th><td><input type="checkbox" name="newControl[HasIrisSpeed]" value="1"<?php if ( !empty($newControl['HasIrisSpeed']) ) { ?> checked="checked"<?php } ?>/></td></tr> <tr><th scope="row"><?php echo translate('HasIrisSpeed') ?></th><td><input type="checkbox" name="newControl[HasIrisSpeed]" value="1"<?php if ( !empty($newControl['HasIrisSpeed']) ) { ?> checked="checked"<?php } ?>/></td></tr>
<tr><th scope="row"><?php echo translate('MinIrisSpeed') ?></th><td><input type="text" name="newControl[MinIrisSpeed]" value="<?php echo validHtmlStr($newControl['MinIrisSpeed']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MinIrisSpeed') ?></th><td><input type="number" name="newControl[MinIrisSpeed]" value="<?php echo validHtmlStr($newControl['MinIrisSpeed']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('MaxIrisSpeed') ?></th><td><input type="text" name="newControl[MaxIrisSpeed]" value="<?php echo validHtmlStr($newControl['MaxIrisSpeed']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MaxIrisSpeed') ?></th><td><input type="number" name="newControl[MaxIrisSpeed]" value="<?php echo validHtmlStr($newControl['MaxIrisSpeed']) ?>"/></td></tr>
<?php <?php
break; break;
} }
@ -462,13 +437,13 @@ switch ( $tab )
<tr><th scope="row"><?php echo translate('CanGainAbs') ?></th><td><input type="checkbox" name="newControl[CanGainAbs]" value="1"<?php if ( !empty($newControl['CanGainAbs']) ) { ?> checked="checked"<?php } ?>/></td></tr> <tr><th scope="row"><?php echo translate('CanGainAbs') ?></th><td><input type="checkbox" name="newControl[CanGainAbs]" value="1"<?php if ( !empty($newControl['CanGainAbs']) ) { ?> checked="checked"<?php } ?>/></td></tr>
<tr><th scope="row"><?php echo translate('CanGainRel') ?></th><td><input type="checkbox" name="newControl[CanGainRel]" value="1"<?php if ( !empty($newControl['CanGainRel']) ) { ?> checked="checked"<?php } ?>/></td></tr> <tr><th scope="row"><?php echo translate('CanGainRel') ?></th><td><input type="checkbox" name="newControl[CanGainRel]" value="1"<?php if ( !empty($newControl['CanGainRel']) ) { ?> checked="checked"<?php } ?>/></td></tr>
<tr><th scope="row"><?php echo translate('CanGainCon') ?></th><td><input type="checkbox" name="newControl[CanGainCon]" value="1"<?php if ( !empty($newControl['CanGainCon']) ) { ?> checked="checked"<?php } ?>/></td></tr> <tr><th scope="row"><?php echo translate('CanGainCon') ?></th><td><input type="checkbox" name="newControl[CanGainCon]" value="1"<?php if ( !empty($newControl['CanGainCon']) ) { ?> checked="checked"<?php } ?>/></td></tr>
<tr><th scope="row"><?php echo translate('MinGainRange') ?></th><td><input type="text" name="newControl[MinGainRange]" value="<?php echo validHtmlStr($newControl['MinGainRange']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MinGainRange') ?></th><td><input type="number" name="newControl[MinGainRange]" value="<?php echo validHtmlStr($newControl['MinGainRange']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('MaxGainRange') ?></th><td><input type="text" name="newControl[MaxGainRange]" value="<?php echo validHtmlStr($newControl['MaxGainRange']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MaxGainRange') ?></th><td><input type="number" name="newControl[MaxGainRange]" value="<?php echo validHtmlStr($newControl['MaxGainRange']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('MinGainStep') ?></th><td><input type="text" name="newControl[MinGainStep]" value="<?php echo validHtmlStr($newControl['MinGainStep']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MinGainStep') ?></th><td><input type="number" name="newControl[MinGainStep]" value="<?php echo validHtmlStr($newControl['MinGainStep']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('MaxGainStep') ?></th><td><input type="text" name="newControl[MaxGainStep]" value="<?php echo validHtmlStr($newControl['MaxGainStep']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MaxGainStep') ?></th><td><input type="number" name="newControl[MaxGainStep]" value="<?php echo validHtmlStr($newControl['MaxGainStep']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('HasGainSpeed') ?></th><td><input type="checkbox" name="newControl[HasGainSpeed]" value="1"<?php if ( !empty($newControl['HasGainSpeed']) ) { ?> checked="checked"<?php } ?>/></td></tr> <tr><th scope="row"><?php echo translate('HasGainSpeed') ?></th><td><input type="checkbox" name="newControl[HasGainSpeed]" value="1"<?php if ( !empty($newControl['HasGainSpeed']) ) { ?> checked="checked"<?php } ?>/></td></tr>
<tr><th scope="row"><?php echo translate('MinGainSpeed') ?></th><td><input type="text" name="newControl[MinGainSpeed]" value="<?php echo validHtmlStr($newControl['MinGainSpeed']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MinGainSpeed') ?></th><td><input type="number" name="newControl[MinGainSpeed]" value="<?php echo validHtmlStr($newControl['MinGainSpeed']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('MaxGainSpeed') ?></th><td><input type="text" name="newControl[MaxGainSpeed]" value="<?php echo validHtmlStr($newControl['MaxGainSpeed']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MaxGainSpeed') ?></th><td><input type="number" name="newControl[MaxGainSpeed]" value="<?php echo validHtmlStr($newControl['MaxGainSpeed']) ?>"/></td></tr>
<?php <?php
break; break;
} }
@ -480,13 +455,13 @@ switch ( $tab )
<tr><th scope="row"><?php echo translate('CanWhiteAbs') ?></th><td><input type="checkbox" name="newControl[CanWhiteAbs]" value="1"<?php if ( !empty($newControl['CanWhiteAbs']) ) { ?> checked="checked"<?php } ?>/></td></tr> <tr><th scope="row"><?php echo translate('CanWhiteAbs') ?></th><td><input type="checkbox" name="newControl[CanWhiteAbs]" value="1"<?php if ( !empty($newControl['CanWhiteAbs']) ) { ?> checked="checked"<?php } ?>/></td></tr>
<tr><th scope="row"><?php echo translate('CanWhiteRel') ?></th><td><input type="checkbox" name="newControl[CanWhiteRel]" value="1"<?php if ( !empty($newControl['CanWhiteRel']) ) { ?> checked="checked"<?php } ?>/></td></tr> <tr><th scope="row"><?php echo translate('CanWhiteRel') ?></th><td><input type="checkbox" name="newControl[CanWhiteRel]" value="1"<?php if ( !empty($newControl['CanWhiteRel']) ) { ?> checked="checked"<?php } ?>/></td></tr>
<tr><th scope="row"><?php echo translate('CanWhiteCon') ?></th><td><input type="checkbox" name="newControl[CanWhiteCon]" value="1"<?php if ( !empty($newControl['CanWhiteCon']) ) { ?> checked="checked"<?php } ?>/></td></tr> <tr><th scope="row"><?php echo translate('CanWhiteCon') ?></th><td><input type="checkbox" name="newControl[CanWhiteCon]" value="1"<?php if ( !empty($newControl['CanWhiteCon']) ) { ?> checked="checked"<?php } ?>/></td></tr>
<tr><th scope="row"><?php echo translate('MinWhiteRange') ?></th><td><input type="text" name="newControl[MinWhiteRange]" value="<?php echo validHtmlStr($newControl['MinWhiteRange']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MinWhiteRange') ?></th><td><input type="number" name="newControl[MinWhiteRange]" value="<?php echo validHtmlStr($newControl['MinWhiteRange']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('MaxWhiteRange') ?></th><td><input type="text" name="newControl[MaxWhiteRange]" value="<?php echo validHtmlStr($newControl['MaxWhiteRange']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MaxWhiteRange') ?></th><td><input type="number" name="newControl[MaxWhiteRange]" value="<?php echo validHtmlStr($newControl['MaxWhiteRange']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('MinWhiteStep') ?></th><td><input type="text" name="newControl[MinWhiteStep]" value="<?php echo validHtmlStr($newControl['MinWhiteStep']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MinWhiteStep') ?></th><td><input type="number" name="newControl[MinWhiteStep]" value="<?php echo validHtmlStr($newControl['MinWhiteStep']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('MaxWhiteStep') ?></th><td><input type="text" name="newControl[MaxWhiteStep]" value="<?php echo validHtmlStr($newControl['MaxWhiteStep']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MaxWhiteStep') ?></th><td><input type="number" name="newControl[MaxWhiteStep]" value="<?php echo validHtmlStr($newControl['MaxWhiteStep']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('HasWhiteSpeed') ?></th><td><input type="checkbox" name="newControl[HasWhiteSpeed]" value="1"<?php if ( !empty($newControl['HasWhiteSpeed']) ) { ?> checked="checked"<?php } ?>/></td></tr> <tr><th scope="row"><?php echo translate('HasWhiteSpeed') ?></th><td><input type="checkbox" name="newControl[HasWhiteSpeed]" value="1"<?php if ( !empty($newControl['HasWhiteSpeed']) ) { ?> checked="checked"<?php } ?>/></td></tr>
<tr><th scope="row"><?php echo translate('MinWhiteSpeed') ?></th><td><input type="text" name="newControl[MinWhiteSpeed]" value="<?php echo validHtmlStr($newControl['MinWhiteSpeed']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MinWhiteSpeed') ?></th><td><input type="number" name="newControl[MinWhiteSpeed]" value="<?php echo validHtmlStr($newControl['MinWhiteSpeed']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('MaxWhiteSpeed') ?></th><td><input type="text" name="newControl[MaxWhiteSpeed]" value="<?php echo validHtmlStr($newControl['MaxWhiteSpeed']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('MaxWhiteSpeed') ?></th><td><input type="number" name="newControl[MaxWhiteSpeed]" value="<?php echo validHtmlStr($newControl['MaxWhiteSpeed']) ?>"/></td></tr>
<?php <?php
break; break;
} }
@ -494,7 +469,7 @@ switch ( $tab )
{ {
?> ?>
<tr><th scope="row"><?php echo translate('HasPresets') ?></th><td><input type="checkbox" name="newControl[HasPresets]" value="1"<?php if ( !empty($newControl['HasPresets']) ) { ?> checked="checked"<?php } ?>/></td></tr> <tr><th scope="row"><?php echo translate('HasPresets') ?></th><td><input type="checkbox" name="newControl[HasPresets]" value="1"<?php if ( !empty($newControl['HasPresets']) ) { ?> checked="checked"<?php } ?>/></td></tr>
<tr><th scope="row"><?php echo translate('NumPresets') ?></th><td><input type="text" name="newControl[NumPresets]" value="<?php echo validHtmlStr($newControl['NumPresets']) ?>" size="8"/></td></tr> <tr><th scope="row"><?php echo translate('NumPresets') ?></th><td><input type="number" name="newControl[NumPresets]" value="<?php echo validHtmlStr($newControl['NumPresets']) ?>"/></td></tr>
<tr><th scope="row"><?php echo translate('HasHomePreset') ?></th><td><input type="checkbox" name="newControl[HasHomePreset]" value="1"<?php if ( !empty($newControl['HasHomePreset']) ) { ?> checked="checked"<?php } ?>/></td></tr> <tr><th scope="row"><?php echo translate('HasHomePreset') ?></th><td><input type="checkbox" name="newControl[HasHomePreset]" value="1"<?php if ( !empty($newControl['HasHomePreset']) ) { ?> checked="checked"<?php } ?>/></td></tr>
<tr><th scope="row"><?php echo translate('CanSetPresets') ?></th><td><input type="checkbox" name="newControl[CanSetPresets]" value="1"<?php if ( !empty($newControl['CanSetPresets']) ) { ?> checked="checked"<?php } ?>/></td></tr> <tr><th scope="row"><?php echo translate('CanSetPresets') ?></th><td><input type="checkbox" name="newControl[CanSetPresets]" value="1"<?php if ( !empty($newControl['CanSetPresets']) ) { ?> checked="checked"<?php } ?>/></td></tr>
<?php <?php
@ -505,7 +480,8 @@ switch ( $tab )
</tbody> </tbody>
</table> </table>
<div id="contentButtons"> <div id="contentButtons">
<input type="submit" value="<?php echo translate('Save') ?>"<?php if ( !canEdit( 'Control' ) ) { ?> disabled="disabled"<?php } ?>/><input type="button" value="<?php echo translate('Cancel') ?>" data-on-click="closeWindow"/> <button type="submit" value="Save"<?php if ( !canEdit( 'Control' ) ) { ?> disabled="disabled"<?php } ?>><?php echo translate('Save') ?></button>
<button type="button" data-on-click="closeWindow"><?php echo translate('Cancel') ?></button>
</div> </div>
</form> </form>
</div> </div>

View File

@ -138,7 +138,7 @@ $disk_space_total = 0;
$event_count = 0; $event_count = 0;
while ( $event_row = dbFetchNext($results) ) { while ( $event_row = dbFetchNext($results) ) {
$event = new ZM\Event($event_row); $event = new ZM\Event($event_row);
$scale = max(reScale(SCALE_BASE, $event->DefaultScale(), ZM_WEB_DEFAULT_SCALE), SCALE_BASE); $scale = max(reScale(SCALE_BASE, $event->Monitor()->DefaultScale(), ZM_WEB_DEFAULT_SCALE), SCALE_BASE);
?> ?>
<tr<?php echo $event->Archived() ? ' class="archived"' : '' ?>> <tr<?php echo $event->Archived() ? ' class="archived"' : '' ?>>
<td class="colId"> <td class="colId">

View File

@ -3,21 +3,131 @@ function validateForm( form ) {
// If "Can Move" is enabled, then the end user must also select at least one of the other check boxes (excluding Can Move Diagonally) // If "Can Move" is enabled, then the end user must also select at least one of the other check boxes (excluding Can Move Diagonally)
if ( form.elements['newControl[CanMove]'].checked ) { if ( form.elements['newControl[CanMove]'].checked ) {
if ( !(form.elements['newControl[CanMoveCon]'].checked || form.elements['newControl[CanMoveRel]'].checked || form.elements['newControl[CanMoveAbs]'].checked || form.elements['newControl[CanMoveMap]'].checked) ) { if ( !(
errors[errors.length] = "In addition to \"Can Move\", you also must select at least one of: \"Can Move Mapped\", \"Can Move Absolute\", \"Can Move Relative\", or \"Can Move Continuous\""; form.elements['newControl[CanMoveCon]'].checked
||
form.elements['newControl[CanMoveRel]'].checked
||
form.elements['newControl[CanMoveAbs]'].checked
||
form.elements['newControl[CanMoveMap]'].checked
) ) {
errors[errors.length] = 'In addition to "Can Move", you also must select at least one of: "Can Move Mapped", "Can Move Absolute", "Can Move Relative", or "Can Move Continuous"';
} }
} else { } else {
// Now lets check for the opposite condition. If any of the boxes below Can Move are checked, but Can Move is not checked then signal an error // Now lets check for the opposite condition. If any of the boxes below Can Move are checked, but Can Move is not checked then signal an error
if ( form.elements['newControl[CanMoveCon]'].checked || form.elements['newControl[CanMoveRel]'].checked || form.elements['newControl[CanMoveAbs]'].checked || form.elements['newControl[CanMoveMap]'].checked || form.elements['newControl[CanMoveDiag]'].checked ) { if ( form.elements['newControl[CanMoveCon]'].checked
errors[errors.length] = "\"Can Move\" must also be selected if any one of the movement types are sleceted"; ||
form.elements['newControl[CanMoveRel]'].checked
||
form.elements['newControl[CanMoveAbs]'].checked
||
form.elements['newControl[CanMoveMap]'].checked
||
form.elements['newControl[CanMoveDiag]'].checked
) {
errors[errors.length] = '"Can Move" must also be selected if any one of the movement types are selected.';
}
}
// If "Can Zoom" is enabled, then the end user must also select at least one of the other check boxes
if ( form.elements['newControl[CanZoom]'].checked ) {
if ( !(
form.elements['newControl[CanZoomCon]'].checked
||
form.elements['newControl[CanZoomRel]'].checked
||
form.elements['newControl[CanZoomAbs]'].checked
) ) {
errors[errors.length] = 'In addition to "Can Zoom", you also must select at least one of: "Can Zoom Absolute", "Can Zoom Relative", or "Can Zoom Continuous"';
}
} else {
// Now lets check for the opposite condition. If any of the boxes below Can Zoom are checked, but Can Zoom is not checked then signal an error
if ( form.elements['newControl[CanZoomCon]'].checked
||
form.elements['newControl[CanZoomRel]'].checked
||
form.elements['newControl[CanZoomAbs]'].checked
) {
errors[errors.length] = '"Can Move" must also be selected if any one of the zoom types are selected.';
}
}
// If "Can Zoom" is enabled, then the end user must also select at least one of the other check boxes
if ( form.elements['newControl[CanFocus]'].checked ) {
if ( !(
form.elements['newControl[CanFocusCon]'].checked
||
form.elements['newControl[CanFocusRel]'].checked
||
form.elements['newControl[CanFocusAbs]'].checked
) ) {
errors[errors.length] = 'In addition to "Can Focus", you also must select at least one of: "Can Focus Absolute", "Can Focus Relative", or "Can Focus Continuous"';
}
} else {
// Now lets check for the opposite condition. If any of the boxes below Can Zoom are checked, but Can Zoom is not checked then signal an error
if ( form.elements['newControl[CanFocusCon]'].checked
||
form.elements['newControl[CanFocusRel]'].checked
||
form.elements['newControl[CanFocusAbs]'].checked
) {
errors[errors.length] = '"Can Focus" must also be selected if any one of the focus types are selected.';
}
}
// If "Can White" is enabled, then the end user must also select at least one of the other check boxes
if ( form.elements['newControl[CanWhite]'].checked ) {
if ( !(
form.elements['newControl[CanWhiteCon]'].checked
||
form.elements['newControl[CanWhiteRel]'].checked
||
form.elements['newControl[CanWhiteAbs]'].checked
) ) {
errors[errors.length] = 'In addition to "Can White Balance", you also must select at least one of: "Can White Bal Absolute", "Can White Bal Relative", or "Can White Bal Continuous"';
}
} else {
// Now lets check for the opposite condition. If any of the boxes below Can Zoom are checked, but Can Zoom is not checked then signal an error
if ( form.elements['newControl[CanWhiteCon]'].checked
||
form.elements['newControl[CanWhiteRel]'].checked
||
form.elements['newControl[CanWhiteAbs]'].checked
) {
errors[errors.length] = '"Can White Balance" must also be selected if any one of the white balance types are selected.';
}
}
// If "Can Iris" is enabled, then the end user must also select at least one of the other check boxes
if ( form.elements['newControl[CanIris]'].checked ) {
if ( !(
form.elements['newControl[CanIrisCon]'].checked
||
form.elements['newControl[CanIrisRel]'].checked
||
form.elements['newControl[CanIrisAbs]'].checked
) ) {
errors[errors.length] = 'In addition to "Can Iris", you also must select at least one of: "Can Iris Absolute", "Can Iris Relative", or "Can Iris Continuous"';
}
} else {
// Now lets check for the opposite condition. If any of the boxes below Can Zoom are checked, but Can Zoom is not checked then signal an error
if ( form.elements['newControl[CanIrisCon]'].checked
||
form.elements['newControl[CanIrisRel]'].checked
||
form.elements['newControl[CanIrisAbs]'].checked
) {
errors[errors.length] = '"Can Iris" must also be selected if any one of the iris types are selected.';
} }
} }
if ( errors.length ) { if ( errors.length ) {
alert( errors.join( "\n" ) ); alert(errors.join("\n"));
return ( false ); return false;
} }
return ( true ); return true;
} }

View File

@ -146,10 +146,12 @@ if ( openFilterWindow ) {
function thumbnail_onmouseover(event) { function thumbnail_onmouseover(event) {
var img = event.target; var img = event.target;
img.src = '';
img.src = img.getAttribute('stream_src'); img.src = img.getAttribute('stream_src');
} }
function thumbnail_onmouseout(event) { function thumbnail_onmouseout(event) {
var img = event.target; var img = event.target;
img.src = '';
img.src = img.getAttribute('still_src'); img.src = img.getAttribute('still_src');
} }

View File

@ -4,7 +4,7 @@ function configureExportButton(element) {
var form = element.form; var form = element.form;
var eventCount = 0; var eventCount = 0;
document.querySelectorAll('input[name="eids[]"]').forEach(function(el){ document.querySelectorAll('input[name="eids[]"]').forEach(function(el) {
if ( el.checked ) { if ( el.checked ) {
eventCount ++; eventCount ++;
} }
@ -43,7 +43,6 @@ function exportProgress() {
} }
function exportResponse(respObj, respText) { function exportResponse(respObj, respText) {
clearInterval(exportTimer); clearInterval(exportTimer);
if ( respObj.result != 'Ok' ) { if ( respObj.result != 'Ok' ) {
$('exportProgressTicker').set('text', respObj.message); $('exportProgressTicker').set('text', respObj.message);

View File

@ -172,9 +172,9 @@ function clearLog() {
logReq.cancel(); logReq.cancel();
var clearParms = 'view=request&request=log&task=delete'; var clearParms = 'view=request&request=log&task=delete';
var clearReq = new Request.JSON( {url: thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: clearResponse} ); var clearReq = new Request.JSON({url: thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: clearResponse});
var tbody = $(logTable).getElement( 'tbody' ); var tbody = $(logTable).getElement('tbody');
var rows = tbody.getElements( 'tr' ); var rows = tbody.getElements('tr');
if ( rows ) { if ( rows ) {
var minTime = rows[0].getElement('td').get('text'); var minTime = rows[0].getElement('td').get('text');
clearParms += "&minTime="+encodeURIComponent(minTime); clearParms += "&minTime="+encodeURIComponent(minTime);
@ -190,7 +190,7 @@ function filterLog() {
filterFields.each( filterFields.each(
function( field ) { function( field ) {
var selector = $('filter['+field+']'); var selector = $('filter['+field+']');
if ( ! selector ) { if ( !selector ) {
if ( window.console && window.console.log ) { if ( window.console && window.console.log ) {
window.console.log('No selector found for ' + field); window.console.log('No selector found for ' + field);
} }
@ -226,9 +226,9 @@ function exportResponse( response ) {
function exportFail( request ) { function exportFail( request ) {
$('exportLog').unspin(); $('exportLog').unspin();
$('exportErrorText').set('text', request.status+' / '+request.statusText ); $('exportErrorText').set('text', request.status+' / '+request.statusText);
$('exportError').show(); $('exportError').show();
Error('Export request failed: '+request.status+' / '+request.statusText ); Error('Export request failed: '+request.status+' / '+request.statusText);
} }
function exportRequest() { function exportRequest() {
@ -237,7 +237,7 @@ function exportRequest() {
$('exportError').hide(); $('exportError').hide();
if ( form.validate() ) { if ( form.validate() ) {
var exportParms = "view=request&request=log&task=export"; var exportParms = "view=request&request=log&task=export";
var exportReq = new Request.JSON( {url: thisUrl, method: 'post', link: 'cancel', onSuccess: exportResponse, onFailure: exportFail} ); var exportReq = new Request.JSON({url: thisUrl, method: 'post', link: 'cancel', onSuccess: exportResponse, onFailure: exportFail});
var selection = form.getElement('input[name=selector]:checked').get('value'); var selection = form.getElement('input[name=selector]:checked').get('value');
if ( selection == 'filter' || selection == 'current' ) { if ( selection == 'filter' || selection == 'current' ) {
$$('#filters select').each( $$('#filters select').each(
@ -256,7 +256,7 @@ function exportRequest() {
exportParms += "&maxTime="+encodeURIComponent(maxTime); exportParms += "&maxTime="+encodeURIComponent(maxTime);
} }
} }
exportReq.send( exportParms+"&"+form.toQueryString() ); exportReq.send(exportParms+"&"+form.toQueryString());
$('exportLog').spin(); $('exportLog').spin();
} }
} }
@ -265,7 +265,7 @@ function updateFilterSelectors() {
Object.each(options, Object.each(options,
function( values, key ) { function( values, key ) {
var selector = $('filter['+key+']'); var selector = $('filter['+key+']');
if ( ! selector ) { if ( !selector ) {
if ( window.console && window.console.log ) { if ( window.console && window.console.log ) {
window.console.log('No selector found for ' + key); window.console.log('No selector found for ' + key);
} }

View File

@ -131,9 +131,36 @@ function initPage() {
document.querySelectorAll('select[name="newMonitor[ControlId]"]').forEach(function(el) { document.querySelectorAll('select[name="newMonitor[ControlId]"]').forEach(function(el) {
el.onchange = window['loadLocations'].bind(el, el); el.onchange = window['loadLocations'].bind(el, el);
}); });
document.querySelectorAll('input[name="newMonitor[WebColour]"]').forEach(function(el) {
el.onchange = window['change_WebColour'].bind(el);
});
$j('.chosen').chosen(); $j('.chosen').chosen();
} // end function initPage() } // end function initPage()
function change_WebColour() {
$j('#WebSwatch').css(
'backgroundColor',
$j('input[name="newMonitor[WebColour]"]').val()
);
}
function getRandomColour() {
var letters = '0123456789ABCDEF';
var colour = '#';
for (var i = 0; i < 6; i++) {
colour += letters[Math.floor(Math.random() * 16)];
}
return colour;
}
function random_WebColour() {
var new_colour = getRandomColour();
$j('input[name="newMonitor[WebColour]"]').val(new_colour);
$j('#WebSwatch').css(
'backgroundColor', new_colour
);
}
window.addEventListener('DOMContentLoaded', initPage); window.addEventListener('DOMContentLoaded', initPage);

View File

@ -35,7 +35,7 @@ monitorData[monitorData.length] = {
'connKey': <?php echo $monitor->connKey() ?>, 'connKey': <?php echo $monitor->connKey() ?>,
'width': <?php echo $monitor->ViewWidth() ?>, 'width': <?php echo $monitor->ViewWidth() ?>,
'height':<?php echo $monitor->ViewHeight() ?>, 'height':<?php echo $monitor->ViewHeight() ?>,
'url': '<?php echo $monitor->UrlToIndex() ?>', 'url': '<?php echo $monitor->UrlToIndex( $monitor->Id() + ZM_MIN_STREAMING_PORT) ?>',
'onclick': function(){createPopup( '?view=watch&mid=<?php echo $monitor->Id() ?>', 'zmWatch<?php echo $monitor->Id() ?>', 'watch', <?php echo reScale( $monitor->ViewWidth(), $monitor->PopupScale() ); ?>, <?php echo reScale( $monitor->ViewHeight(), $monitor->PopupScale() ); ?> );}, 'onclick': function(){createPopup( '?view=watch&mid=<?php echo $monitor->Id() ?>', 'zmWatch<?php echo $monitor->Id() ?>', 'watch', <?php echo reScale( $monitor->ViewWidth(), $monitor->PopupScale() ); ?>, <?php echo reScale( $monitor->ViewHeight(), $monitor->PopupScale() ); ?> );},
'type': '<?php echo $monitor->Type() ?>', 'type': '<?php echo $monitor->Type() ?>',
'refresh': '<?php echo $monitor->Refresh() ?>' 'refresh': '<?php echo $monitor->Refresh() ?>'

View File

@ -54,7 +54,7 @@ $j(document).ready(function() {
url: thisUrl, url: thisUrl,
data: formData, data: formData,
dataType: 'html', dataType: 'html',
enocde: true timeout: 0
}).done(function(data) { }).done(function(data) {
location.reload(); location.reload();
}); });

View File

@ -122,9 +122,12 @@ xhtmlHeaders(__FILE__, translate('SystemLog') );
<form id="exportForm" action="" method="post"> <form id="exportForm" action="" method="post">
<fieldset> <fieldset>
<legend><?php echo translate('SelectLog') ?></legend> <legend><?php echo translate('SelectLog') ?></legend>
<label for="selectorAll"><?php echo translate('All') ?></label><input type="radio" id="selectorAll" name="selector" value="all"/> <label for="selectorAll"><?php echo translate('All') ?></label>
<label for="selectorFilter"><?php echo translate('Filter') ?></label><input type="radio" id="selectorFilter" name="selector" value="filter"/> <input type="radio" id="selectorAll" name="selector" value="all"/>
<label for="selectorCurrent"><?php echo translate('Current') ?></label><input type="radio" id="selectorCurrent" name="selector" value="current" title="<?php echo translate('ChooseLogSelection') ?>" data-validators="validate-one-required"/> <label for="selectorFilter"><?php echo translate('Filter') ?></label>
<input type="radio" id="selectorFilter" name="selector" value="filter"/>
<label for="selectorCurrent"><?php echo translate('Current') ?></label>
<input type="radio" id="selectorCurrent" name="selector" value="current" title="<?php echo translate('ChooseLogSelection') ?>" data-validators="validate-one-required"/>
</fieldset> </fieldset>
<fieldset> <fieldset>
<legend><?php echo translate('SelectFormat') ?></legend> <legend><?php echo translate('SelectFormat') ?></legend>

View File

@ -40,8 +40,8 @@ if ( !empty($_REQUEST['mid']) ) {
if ( $monitor and ZM_OPT_X10 ) if ( $monitor and ZM_OPT_X10 )
$x10Monitor = dbFetchOne('SELECT * FROM TriggersX10 WHERE MonitorId = ?', NULL, array($_REQUEST['mid'])); $x10Monitor = dbFetchOne('SELECT * FROM TriggersX10 WHERE MonitorId = ?', NULL, array($_REQUEST['mid']));
} }
if ( !$monitor ) {
if ( !$monitor ) {
$nextId = getTableAutoInc('Monitors'); $nextId = getTableAutoInc('Monitors');
if ( isset($_REQUEST['dupId']) ) { if ( isset($_REQUEST['dupId']) ) {
$monitor = new ZM\Monitor($_REQUEST['dupId']); $monitor = new ZM\Monitor($_REQUEST['dupId']);
@ -54,6 +54,7 @@ if ( !$monitor ) {
$monitor = new ZM\Monitor(); $monitor = new ZM\Monitor();
} # end if $_REQUEST['dupID'] } # end if $_REQUEST['dupID']
$monitor->Name(translate('Monitor').'-'.$nextId); $monitor->Name(translate('Monitor').'-'.$nextId);
$monitor->WebColour(random_colour());
} # end if $_REQUEST['mid'] } # end if $_REQUEST['mid']
if ( ZM_OPT_X10 && empty($x10Monitor) ) { if ( ZM_OPT_X10 && empty($x10Monitor) ) {
@ -67,7 +68,6 @@ if ( ZM_OPT_X10 && empty($x10Monitor) ) {
function fourcc($a, $b, $c, $d) { function fourcc($a, $b, $c, $d) {
return ord($a) | (ord($b) << 8) | (ord($c) << 16) | (ord($d) << 24); return ord($a) | (ord($b) << 8) | (ord($c) << 16) | (ord($d) << 24);
} }
if ( isset($_REQUEST['newMonitor']) ) { if ( isset($_REQUEST['newMonitor']) ) {
# Update the monitor object with whatever has been set so far. # Update the monitor object with whatever has been set so far.
$monitor->set($_REQUEST['newMonitor']); $monitor->set($_REQUEST['newMonitor']);
@ -371,13 +371,6 @@ $label_size = array(
'Large' => 2 'Large' => 2
); );
$savejpegopts = array(
'Disabled' => 0,
'Frames only' => 1,
'Analysis images only (if available)' => 2,
'Frames + Analysis images (if available)' => 3,
);
$codecs = array( $codecs = array(
'auto' => translate('Auto'), 'auto' => translate('Auto'),
'MP4' => translate('MP4'), 'MP4' => translate('MP4'),
@ -459,8 +452,8 @@ foreach ( $tabs as $name=>$value ) {
if ( $tab != 'general' ) { if ( $tab != 'general' ) {
?> ?>
<input type="hidden" name="newMonitor[Name]" value="<?php echo validHtmlStr($monitor->Name()) ?>"/> <input type="hidden" name="newMonitor[Name]" value="<?php echo validHtmlStr($monitor->Name()) ?>"/>
<input type="hidden" name="newMonitor[Notes]" value="<?php echo validHtmlStr($monitor->Notes()) ?>"/>
<input type="hidden" name="newMonitor[ServerId]" value="<?php echo validHtmlStr($monitor->ServerId() ) ?>"/> <input type="hidden" name="newMonitor[ServerId]" value="<?php echo validHtmlStr($monitor->ServerId() ) ?>"/>
<input type="hidden" name="newMonitor[StorageId]" value="<?= validHtmlStr($monitor->StorageId() ) ?>"/>
<input type="hidden" name="newMonitor[LinkedMonitors]" value="<?php echo (null !== $monitor->LinkedMonitors())?validHtmlStr($monitor->LinkedMonitors()):'' ?>"/> <input type="hidden" name="newMonitor[LinkedMonitors]" value="<?php echo (null !== $monitor->LinkedMonitors())?validHtmlStr($monitor->LinkedMonitors()):'' ?>"/>
<?php <?php
foreach ( $monitor->GroupIds() as $group_id ) { foreach ( $monitor->GroupIds() as $group_id ) {
@ -529,6 +522,7 @@ if ( $tab != 'source' ) {
} }
if ( $tab != 'storage' ) { if ( $tab != 'storage' ) {
?> ?>
<input type="hidden" name="newMonitor[StorageId]" value="<?php echo validHtmlStr($monitor->StorageId()) ?>"/>
<input type="hidden" name="newMonitor[SaveJPEGs]" value="<?php echo validHtmlStr($monitor->SaveJPEGs()) ?>"/> <input type="hidden" name="newMonitor[SaveJPEGs]" value="<?php echo validHtmlStr($monitor->SaveJPEGs()) ?>"/>
<input type="hidden" name="newMonitor[VideoWriter]" value="<?php echo validHtmlStr($monitor->VideoWriter()) ?>"/> <input type="hidden" name="newMonitor[VideoWriter]" value="<?php echo validHtmlStr($monitor->VideoWriter()) ?>"/>
<input type="hidden" name="newMonitor[EncoderParameters]" value="<?php echo validHtmlStr($monitor->EncoderParameters()) ?>"/> <input type="hidden" name="newMonitor[EncoderParameters]" value="<?php echo validHtmlStr($monitor->EncoderParameters()) ?>"/>
@ -612,6 +606,10 @@ switch ( $tab ) {
<td><?php echo translate('Name') ?></td> <td><?php echo translate('Name') ?></td>
<td><input type="text" name="newMonitor[Name]" value="<?php echo validHtmlStr($monitor->Name()) ?>"/></td> <td><input type="text" name="newMonitor[Name]" value="<?php echo validHtmlStr($monitor->Name()) ?>"/></td>
</tr> </tr>
<tr class="Notes">
<td><?php echo translate('Notes') ?></td>
<td><textarea name="newMonitor[Notes]" rows="4"><?php echo validHtmlStr($monitor->Notes()) ?></textarea></td>
</tr>
<tr> <tr>
<td><?php echo translate('Server') ?></td><td> <td><?php echo translate('Server') ?></td><td>
<?php <?php
@ -620,18 +618,6 @@ switch ( $tab ) {
$servers[$Server->Id()] = $Server->Name(); $servers[$Server->Id()] = $Server->Name();
} }
echo htmlSelect( 'newMonitor[ServerId]', $servers, $monitor->ServerId() ); echo htmlSelect( 'newMonitor[ServerId]', $servers, $monitor->ServerId() );
?>
</td>
</tr>
<tr>
<td><?php echo translate('StorageArea') ?></td>
<td>
<?php
$storage_areas = array(0=>'Default');
foreach ( ZM\Storage::find(NULL, array('order'=>'lower(Name)')) as $Storage ) {
$storage_areas[$Storage->Id()] = $Storage->Name();
}
echo htmlSelect('newMonitor[StorageId]', $storage_areas, $monitor->StorageId());
?> ?>
</td> </td>
</tr> </tr>
@ -921,7 +907,32 @@ if ( $monitor->Type() == 'Local' ) {
} }
case 'storage' : case 'storage' :
?> ?>
<tr><td><?php echo translate('SaveJPEGs') ?></td><td><select name="newMonitor[SaveJPEGs]"><?php foreach ( $savejpegopts as $name => $value ) { ?><option value="<?php echo validHtmlStr($value); ?>"<?php if ( $value == $monitor->SaveJPEGs() ) { ?> selected="selected"<?php } ?>><?php echo validHtmlStr($name); ?></option><?php } ?></select></td></tr> <tr>
<td><?php echo translate('StorageArea') ?></td>
<td>
<?php
$storage_areas = array(0=>'Default');
foreach ( ZM\Storage::find(NULL, array('order'=>'lower(Name)')) as $Storage ) {
$storage_areas[$Storage->Id()] = $Storage->Name();
}
echo htmlSelect('newMonitor[StorageId]', $storage_areas, $monitor->StorageId());
?>
</td>
</tr>
<tr>
<td><?php echo translate('SaveJPEGs') ?></td>
<td>
<?php
$savejpegopts = array(
0 => 'Disabled',
1 => 'Frames only',
2 => 'Analysis images only (if available)',
3 => 'Frames + Analysis images (if available)',
);
echo htmlSelect('newMonitor[SaveJPEGs]', $savejpegopts, $monitor->SaveJPEGs());
?>
</td>
</tr>
<tr><td><?php echo translate('VideoWriter') ?></td><td> <tr><td><?php echo translate('VideoWriter') ?></td><td>
<?php <?php
$videowriteropts = array( $videowriteropts = array(
@ -1102,15 +1113,17 @@ if ( canEdit('Control') ) {
<tr> <tr>
<td><?php echo translate('SignalCheckColour') ?></td> <td><?php echo translate('SignalCheckColour') ?></td>
<td> <td>
<input type="text" name="newMonitor[SignalCheckColour]" value="<?php echo validHtmlStr($monitor->SignalCheckColour()) ?>"/> <input type="color" name="newMonitor[SignalCheckColour]" value="<?php echo validHtmlStr($monitor->SignalCheckColour()) ?>"/>
<span id="SignalCheckSwatch" class="swatch" style="background-color: <?php echo validHtmlStr($monitor->SignalCheckColour()); ?>;">&nbsp;&nbsp;&nbsp;&nbsp;</span> <span id="SignalCheckSwatch" class="swatch" style="background-color: <?php echo validHtmlStr($monitor->SignalCheckColour()); ?>;">&nbsp;&nbsp;&nbsp;&nbsp;</span>
</td> </td>
</tr> </tr>
<tr> <tr>
<td><?php echo translate('WebColour') ?></td> <td><?php echo translate('WebColour') ?></td>
<td> <td>
<input type="text" name="newMonitor[WebColour]" value="<?php echo validHtmlStr($monitor->WebColour()) ?>" onchange="$('WebSwatch').setStyle( 'backgroundColor', this.value )"/> <input type="color" name="newMonitor[WebColour]" value="<?php echo validHtmlStr($monitor->WebColour()) ?>"/>
<span id="WebSwatch" class="swatch" style="background-color: <?php echo validHtmlStr($monitor->WebColour()) ?>;">&nbsp;&nbsp;&nbsp;&nbsp;</span> <span id="WebSwatch" class="swatch" style="background-color: <?php echo validHtmlStr($monitor->WebColour()) ?>;">&nbsp;&nbsp;&nbsp;&nbsp;</span>
<i class="material-icons" data-on-click="random_WebColour">sync</i>
</td> </td>
</tr> </tr>
<tr> <tr>

View File

@ -110,8 +110,6 @@ foreach ( array_map('basename', glob('skins/'.$skin.'/css/*',GLOB_ONLYDIR)) as $
<button value="Save" type="submit"><?php echo translate('Save') ?></button> <button value="Save" type="submit"><?php echo translate('Save') ?></button>
</div> </div>
</form> </form>
<?php <?php
} else if ( $tab == 'users' ) { } else if ( $tab == 'users' ) {
?> ?>
@ -319,23 +317,28 @@ foreach ( array_map('basename', glob('skins/'.$skin.'/css/*',GLOB_ONLYDIR)) as $
} }
function updateSelected() { function updateSelected() {
# Turn them all off, then selectively turn the checked ones back on
dbQuery('UPDATE `Users` SET `APIEnabled`=0'); dbQuery('UPDATE `Users` SET `APIEnabled`=0');
foreach ( $_REQUEST["tokenUids"] as $markUid ) {
$minTime = time();
dbQuery('UPDATE `Users` SET `TokenMinExpiry`=? WHERE `Id`=?', array($minTime, $markUid));
}
foreach ( $_REQUEST["apiUids"] as $markUid ) {
dbQuery('UPDATE `Users` SET `APIEnabled`=1 WHERE `Id`=?', array($markUid));
if ( isset($_REQUEST['tokenUids']) ) {
foreach ( $_REQUEST['tokenUids'] as $markUid ) {
$minTime = time();
dbQuery('UPDATE `Users` SET `TokenMinExpiry`=? WHERE `Id`=?', array($minTime, $markUid));
}
}
if ( isset($_REQUEST['apiUids']) ) {
foreach ( $_REQUEST['apiUids'] as $markUid ) {
dbQuery('UPDATE `Users` SET `APIEnabled`=1 WHERE `Id`=?', array($markUid));
}
} }
echo '<span class="timedSuccessBox">'.translate('Updated').'</span>'; echo '<span class="timedSuccessBox">'.translate('Updated').'</span>';
} }
if ( array_key_exists('revokeAllTokens',$_POST) ) { if ( array_key_exists('revokeAllTokens', $_POST) ) {
revokeAllTokens(); revokeAllTokens();
} }
if ( array_key_exists('updateSelected',$_POST) ) { if ( array_key_exists('updateSelected', $_POST) ) {
updateSelected(); updateSelected();
} }
?> ?>

View File

@ -24,7 +24,11 @@ if ( !canEdit('System') ) {
} }
?> ?>
<div id="modalState" class="modal fade"> <div id="modalState" class="modal fade">
<form class="form-horizontal" name="contentForm" id="contentForm" method="get" action="?view=state"> <form class="form-horizontal" name="contentForm" method="get" action="?view=state">
<input type="hidden" name="view" value="state"/>
<input type="hidden" name="action" value="state"/>
<input type="hidden" name="apply" value="1"/>
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
@ -32,9 +36,6 @@ if ( !canEdit('System') ) {
<h2 class="modal-title"><?php echo translate('RunState') ?></h2> <h2 class="modal-title"><?php echo translate('RunState') ?></h2>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<input type="hidden" name="view" value="state"/>
<input type="hidden" name="action" value="state"/>
<input type="hidden" name="apply" value="1"/>
<div class="form-group"> <div class="form-group">
<label for="runState" class="col-sm-3 control-label">Change State</label> <label for="runState" class="col-sm-3 control-label">Change State</label>

View File

@ -69,6 +69,7 @@ if ( !isset($newZone) ) {
'Id' => 0, 'Id' => 0,
'Name' => translate('New'), 'Name' => translate('New'),
'Type' => 'Active', 'Type' => 'Active',
'Units' => 'Pixels',
'MonitorId' => $monitor->Id(), 'MonitorId' => $monitor->Id(),
'NumCoords' => 4, 'NumCoords' => 4,
'Coords' => sprintf('%d,%d %d,%d, %d,%d %d,%d', $minX, $minY, $maxX, $minY, $maxX, $maxY, $minX, $maxY), 'Coords' => sprintf('%d,%d %d,%d, %d,%d %d,%d', $minX, $minY, $maxX, $minY, $maxX, $maxY, $minX, $maxY),