Merge branch 'master' into wip_axisv2

This commit is contained in:
Isaac Connor 2020-01-10 17:20:32 -05:00
commit 80c95d5afe
78 changed files with 1809 additions and 1636 deletions

12
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,12 @@
# These are supported funding model platforms
github: [connortechnology,pliablepixels] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: zoneminder # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

View File

@ -33,24 +33,23 @@ install:
env:
- SMPFLAGS=-j4 OS=el DIST=7
- SMPFLAGS=-j4 OS=el DIST=8
- SMPFLAGS=-j4 OS=fedora DIST=29 DOCKER_REPO=knnniggett/packpack
- SMPFLAGS=-j4 OS=el DIST=8 DOCKER_REPO=knnniggett/packpack
- SMPFLAGS=-j4 OS=fedora DIST=30
- SMPFLAGS=-j4 OS=ubuntu DIST=trusty DOCKER_REPO=iconzm/packpack USE_SFTP=yes
- SMPFLAGS=-j4 OS=ubuntu DIST=xenial DOCKER_REPO=iconzm/packpack USE_SFTP=yes
- SMPFLAGS=-j4 OS=ubuntu DIST=bionic DOCKER_REPO=iconzm/packpack USE_SFTP=yes
- SMPFLAGS=-j4 OS=ubuntu DIST=disco DOCKER_REPO=iconzm/packpack USE_SFTP=yes
- SMPFLAGS=-j4 OS=ubuntu DIST=eoan DOCKER_REPO=iconzm/packpack USE_SFTP=yes
- SMPFLAGS=-j4 OS=debian DIST=jessie DOCKER_REPO=iconzm/packpack USE_SFTP=yes
- SMPFLAGS=-j4 OS=debian DIST=stretch DOCKER_REPO=iconzm/packpack USE_SFTP=yes
- SMPFLAGS=-j4 OS=debian DIST=buster DOCKER_REPO=iconzm/packpack USE_SFTP=yes
- SMPFLAGS=-j4 OS=fedora DIST=31
- SMPFLAGS=-j4 OS=ubuntu DIST=trusty DOCKER_REPO=iconzm/packpack
- SMPFLAGS=-j4 OS=ubuntu DIST=xenial DOCKER_REPO=iconzm/packpack
- SMPFLAGS=-j4 OS=ubuntu DIST=bionic DOCKER_REPO=iconzm/packpack
- SMPFLAGS=-j4 OS=ubuntu DIST=disco DOCKER_REPO=iconzm/packpack
- SMPFLAGS=-j4 OS=ubuntu DIST=eoan DOCKER_REPO=iconzm/packpack
- SMPFLAGS=-j4 OS=debian DIST=jessie DOCKER_REPO=iconzm/packpack
- SMPFLAGS=-j4 OS=debian DIST=stretch DOCKER_REPO=iconzm/packpack
- SMPFLAGS=-j4 OS=debian DIST=buster DOCKER_REPO=iconzm/packpack
- SMPFLAGS=-j4 OS=ubuntu DIST=trusty ARCH=i386
- SMPFLAGS=-j4 OS=ubuntu DIST=xenial ARCH=i386
- SMPFLAGS=-j4 OS=ubuntu DIST=bionic ARCH=i386
- SMPFLAGS=-j4 OS=ubuntu DIST=disco ARCH=i386
- SMPFLAGS=-j4 OS=debian DIST=buster ARCH=i386
- SMPFLAGS=-j4 OS=debian DIST=stretch ARCH=i386
- SMPFLAGS=-j4 OS=raspbian DIST=stretch ARCH=armhf DOCKER_REPO=knnniggett/packpack
- SMPFLAGS=-j4 OS=eslint DIST=eslint
compiler:
- gcc
@ -58,12 +57,6 @@ services:
- mysql
- docker
jobs:
include:
- name: eslint
install: npm install -g eslint@5.12.0 eslint-config-google@0.11.0 eslint-plugin-html@5.0.0 eslint-plugin-php-markup@0.2.5
script: eslint --ext .php,.js .
script:
- utils/packpack/startpackpack.sh

View File

@ -1,9 +1,10 @@
ZoneMinder
==========
[![Build Status](https://travis-ci.org/ZoneMinder/zoneminder.png)](https://travis-ci.org/ZoneMinder/zoneminder) [![Bountysource](https://api.bountysource.com/badge/team?team_id=204&style=bounties_received)](https://www.bountysource.com/teams/zoneminder/issues?utm_source=ZoneMinder&utm_medium=shield&utm_campaign=bounties_received)
[![Build Status](https://travis-ci.org/ZoneMinder/zoneminder.png)](https://travis-ci.org/ZoneMinder/zoneminder)
[![Bounty Source](https://api.bountysource.com/badge/team?team_id=204&style=bounties_received)](https://www.bountysource.com/teams/zoneminder/issues?utm_source=ZoneMinder&utm_medium=shield&utm_campaign=bounties_received)
[![Join Slack](https://github.com/ozonesecurity/ozonebase/blob/master/img/slacksm.png?raw=true)](https://join.slack.com/t/zoneminder-chat/shared_invite/enQtNTU0NDkxMDM5NDQwLTdhZmQ5Y2M2NWQyN2JkYTBiN2ZkMzIzZGQ0MDliMTRmM2FjZWRlYzUwYTQ2MjMwMTVjMzQ1NjYxOTdmMjE2MTE)
[![IRC Network](https://img.shields.io/badge/irc-%23zoneminder-blue.svg "IRC Freenode")](https://webchat.freenode.net/?channels=zoneminder)
All documentation for ZoneMinder is now online at https://zoneminder.readthedocs.org

View File

@ -434,6 +434,7 @@ DROP TABLE IF EXISTS `Monitors`;
CREATE TABLE `Monitors` (
`Id` int(10) unsigned NOT NULL auto_increment,
`Name` varchar(64) NOT NULL default '',
`Notes` TEXT,
`ServerId` int(10) unsigned,
`StorageId` smallint(5) unsigned default 0,
`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
all event folders and the php session folder after the change.
4. If you have installed ZoneMinder from the FedBerry repositories, this build
of ZoneMinder has support for Raspberry Pi hardware acceleration when using
ffmpeg. Unforunately, there is a problem with the same hardware acceleration
when using libvlc. Consequently, libvlc support in this build of ZoneMinder
has been disabled until the problem is resolved. See the following bug
report for details: https://trac.videolan.org/vlc/ticket/18594
4. The timezone must now be set from the ZoneMinder web console. See the
appropriate README, mentioned in the next step, for details.
5. Continue on to the next README that corresponds to the chosen webserver:
6. Continue on to the next README that corresponds to your chosen webserver:
README.httpd - Follow these steps when using Apache
README.nginx - Follow these steps when using Nginx

View File

@ -36,20 +36,17 @@ NOTE: EL7 users should replace "dnf" with "yum" in the instructions below.
sudo chown root:apache *.conf
sudo chmod 640 *.conf
4. Edit /etc/php.ini, uncomment the date.timezone line, and add your local
timezone. PHP will complain loudly if this is not set, or if it is set
incorrectly, and these complaints will show up in the zoneminder logging
system as errors.
4. Manually setting the timezone in /etc/php.ini is deprecated.
If you are not sure of the proper timezone specification to use, look at
http://php.net/date.timezone
Instead, navigate to Options -> System from the ZoneMinder web console.
Do this after completing step 10, below.
Note that timezone errors will appear in the ZoneMinder log until this
has been completed.
5. Disable SELinux
We currently do not have the resources to create and maintain an accurate
SELinux policy for ZoneMinder on Fedora. We will gladly accept pull
reqeusts from anyone who wishes to do the work. In the meantime, SELinux
will need to be disabled or put into permissive mode.
SELinux must be disabled or put into permissive mode. This is not optional!
To immediately disbale SELinux for the current seesion, issue the following
from the command line:
@ -166,3 +163,11 @@ Upgrades
sudo systemctl restart httpd
sudo systemctl start zoneminder
6. Manually setting the timezone in /etc/php.ini is deprecated.
Instead, navigate to Options -> System from the ZoneMinder web console.
Do this now.
Note that timezone errors will appear in the ZoneMinder log until this
has been completed.

View File

@ -34,13 +34,13 @@ New installs
sudo chown root:nginx *.conf
sudo chmod 640 *.conf
4. Edit /etc/php.ini, uncomment the date.timezone line, and add your local
timezone. PHP will complain loudly if this is not set, or if it is set
incorrectly, and these complaints will show up in the zoneminder logging
system as errors.
4. Manually setting the timezone in /etc/php.ini is deprecated.
If you are not sure of the proper timezone specification to use, look at
http://php.net/date.timezone
Instead, navigate to Options -> System from the ZoneMinder web console.
Do this after completing step 10, below.
Note that timezone errors will appear in the ZoneMinder log until this
has been completed.
5. Disable SELinux
@ -169,3 +169,11 @@ Upgrades
sudo systemctl restart php-fpm
sudo systemctl start zoneminder
6. Manually setting the timezone in /etc/php.ini is deprecated.
Instead, navigate to Options -> System from the ZoneMinder web console.
Do this now.
Note that timezone errors will appear in the ZoneMinder log until this
has been completed.

View File

@ -14,16 +14,21 @@
# This will tell zoneminder's cmake process we are building against a known distro
%global zmtargetdistro %{?rhel:el%{rhel}}%{!?rhel:fc%{fedora}}
# Fedora >= 25 needs apcu backwards compatibility module
%if 0%{?fedora} >= 25
# Fedora needs apcu backwards compatibility module
%if 0%{?fedora}
%global with_apcu_bc 1
%endif
# Newer php's keep json functions in a subpackage
%if 0%{?fedora} || 0%{?rhel} >= 8
%global with_php_json 1
%endif
# The default for everything but el7 these days
%global _hardened_build 1
Name: zoneminder
Version: 1.33.14
Version: 1.33.16
Release: 1%{?dist}
Summary: A camera monitoring and analysis tool
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-common
Requires: php-gd
%{?fedora:Requires: php-json}
%{?with_php_json:Requires: php-json}
Requires: php-pecl-apcu
%{?with_apcu_bc:Requires: php-pecl-apcu-bc}
Requires: cambozola
@ -411,6 +416,9 @@ EOF
%dir %attr(755,nginx,nginx) %{_localstatedir}/spool/zoneminder-upload
%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
- Bump to 1.33.13 Development

View File

@ -1,10 +1,3 @@
# Remember to enable cgi mod (i.e. "a2enmod cgi").
ScriptAlias /zm/cgi-bin "/usr/lib/zoneminder/cgi-bin"
<Directory "/usr/lib/zoneminder/cgi-bin">
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
AllowOverride All
Require all granted
</Directory>
# Order matters. This alias must come first.
Alias /zm/cache /var/cache/zoneminder/cache
@ -30,6 +23,14 @@ Alias /zm /usr/share/zoneminder/www
</IfModule>
</Directory>
# Remember to enable cgi mod (i.e. "a2enmod cgi").
ScriptAlias /zm/cgi-bin "/usr/lib/zoneminder/cgi-bin"
<Directory "/usr/lib/zoneminder/cgi-bin">
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
AllowOverride All
Require all granted
</Directory>
# For better visibility, the following directives have been migrated from the
# default .htaccess files included with the CakePHP project.
# Parameters not set here are inherited from the parent directive above.

View File

@ -61,7 +61,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
,libjson-maybexs-perl
,libsys-mmap-perl [!hurd-any]
,liburi-encode-perl
,libwww-perl
,libwww-perl, liburi-perl
,libdata-dump-perl
,libdatetime-perl
,libclass-std-fast-perl
@ -74,7 +74,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
,libfile-slurp-perl
,mysql-client | mariadb-client | virtual-mysql-client
,perl-modules
,php5-mysql | php-mysql, php5-gd | php-gd , php5-apcu | php-apcu , php-apc | php-apcu-bc
,php5-mysql | php-mysql, php5-gd | php-gd , php5-apcu | php-apcu , php-apc | php-apcu-bc, php-json | php5-json
,policykit-1
,rsyslog | system-log-daemon
,zip

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 \[Collec?ting data to send to ZoneMinder Telemetry server.\]$
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',
default => '-5',
default => '1',
description => 'Save logging output to component files',
help => q`
ZoneMinder logging is now more integrated between
@ -1312,7 +1312,7 @@ our @options = (
},
{
name => 'ZM_LOG_DEBUG_FILE',
default => '@ZM_LOGDIR@/zm_debug.log+',
default => '',
description => 'Where extra debug is output to',
help => q`
This option allows you to specify a different target for debug
@ -2468,7 +2468,7 @@ our @options = (
},
{
name => 'ZM_WATCH_MAX_DELAY',
default => '5',
default => '45',
description => 'The maximum delay allowed since the last captured image',
help => q`
The zmwatch daemon checks the image capture performance of the

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
#
@ -8,7 +8,7 @@
# - Fixes incorrect method names
# - Updates control sequences to Amcrest HTTP Protocol API v 2.12
# - Extends control features
#
#
# Rev 2.0:
# - Fixed installation instructions text, no changes to functionality.
#
@ -38,6 +38,7 @@ use Time::HiRes qw( usleep );
require ZoneMinder::Base;
require ZoneMinder::Control;
require LWP::UserAgent;
our @ISA = qw(ZoneMinder::Control);
@ -50,130 +51,109 @@ our @ISA = qw(ZoneMinder::Control);
use ZoneMinder::Logger qw(:all);
use ZoneMinder::Config qw(:all);
sub new
{
my $class = shift;
my $id = shift;
my $self = ZoneMinder::Control->new( $id );
bless( $self, $class );
srand( time() );
return $self;
sub new {
my $class = shift;
my $id = shift;
my $self = ZoneMinder::Control->new($id);
bless($self, $class);
return $self;
}
our $AUTOLOAD;
sub open {
my $self = shift;
sub AUTOLOAD
{
my $self = shift;
my $class = ref($self) || croak( "$self not object" );
my $name = $AUTOLOAD;
$name =~ s/.*://;
Debug( "Received command: $name" );
if ( exists($self->{$name}) )
{
return( $self->{$name} );
}
Fatal( "Can't access $name member of object of class $class" );
}
$self->loadMonitor();
my $username;
my $password;
my $realm = 'Login to ' . $self->{Monitor}->{ControlDevice};
sub open
{
my $self = shift;
if ( $self->{Monitor}->{ControlAddress} =~ /(.*):(.*)@(.*)/ ) {
$username = $1;
$password = $2;
$$self{address} = $3;
}
$self->loadMonitor();
$self->{ua} = LWP::UserAgent->new;
$self->{ua}->credentials($$self{address}, $realm, $username, $password);
$self->{ua}->agent('ZoneMinder Control Agent/'.ZoneMinder::Base::ZM_VERSION);
# Detect REALM
my $res = $self->{ua}->get($$self{address}.'/cgi-bin/ptz.cgi');
if ( $res->is_success ) {
$self->{state} = 'open';
}
return;
}
sub initUA
{
my $self = shift;
my $user = undef;
my $password = undef;
my $address = undef;
if ( $res->status_line() eq '401 Unauthorized' ) {
if ( $self->{Monitor}->{ControlAddress} =~ /(.*):(.*)@(.*)/ )
{
$user = $1;
$password = $2;
$address = $3;
my $headers = $res->headers();
foreach my $k ( keys %$headers ) {
Debug("Initial Header $k => $$headers{$k}");
}
use LWP::UserAgent;
$self->{ua} = LWP::UserAgent->new;
$self->{ua}->credentials("$address", "Login to " . $self->{Monitor}->{ControlDevice}, "$user", "$password");
$self->{ua}->agent( "ZoneMinder Control Agent/".ZoneMinder::Base::ZM_VERSION );
if ( $$headers{'www-authenticate'} ) {
my ( $auth, $tokens ) = $$headers{'www-authenticate'} =~ /^(\w+)\s+(.*)$/;
if ( $tokens =~ /\w+="([^"]+)"/i ) {
if ( $realm ne $1 ) {
$realm = $1;
Debug("Changing REALM to $realm");
$self->{ua}->credentials($$self{address}, $realm, $username, $password);
$res = $self->{ua}->get($$self{address}.'/cgi-bin/ptz.cgi');
if ( $res->is_success() ) {
$self->{state} = 'open';
return;
}
Error('Authentication still failed after updating REALM' . $res->status_line);
$headers = $res->headers();
foreach my $k ( keys %$headers ) {
Debug("Initial Header $k => $$headers{$k}");
} # end foreach
} else {
Error('Authentication failed, not a REALM problem');
}
} else {
Error('Failed to match realm in tokens');
} # end if
} else {
Debug('No headers line');
} # end if headers
} # end if $res->status_line() eq '401 Unauthorized'
$self->{state} = 'open';
}
sub destroyUA
{
my $self = shift;
$self->{ua} = undef;
sub close {
my $self = shift;
$self->{state} = 'closed';
}
sub close
{
my $self = shift;
$self->{state} = 'closed';
sub sendCmd {
my $self = shift;
my $cmd = shift;
my $result = undef;
$self->printMsg($cmd, 'Tx');
my $req = HTTP::Request->new( GET=>"http://$$self{address}/$cmd" );
my $res = $self->{ua}->request($req);
if ( $res->is_success ) {
$result = !undef;
# Command to camera appears successful, write Info item to log
Info('Camera control: \''.$res->status_line().'\' for URL '.$self->{Monitor}->{ControlAddress}.'/'.$cmd);
# TODO: Add code to retrieve $res->message_decode or some such. Then we could do things like check the camera status.
} else {
Error('Camera control command FAILED: \''.$res->status_line().'\' for URL '.$self->{Monitor}->{ControlAddress}.'/'.$cmd);
}
return $result;
}
sub printMsg
{
my $self = shift;
my $msg = shift;
my $msg_len = length($msg);
Debug( $msg."[".$msg_len."]" );
}
sub sendCmd
{
my $self = shift;
my $cmd = shift;
my $result = undef;
destroyUA($self);
initUA($self);
my $user = undef;
my $password = undef;
my $address = undef;
if ( $self->{Monitor}->{ControlAddress} =~ /(.*):(.*)@(.*)/ )
{
$user = $1;
$password = $2;
$address = $3;
}
printMsg( $cmd, "Tx" );
my $req = HTTP::Request->new( GET=>"http://$address/$cmd" );
my $res = $self->{ua}->request($req);
if ( $res->is_success )
{
$result = !undef;
# Command to camera appears successful, write Info item to log
Info( "Camera control: '".$res->status_line()."' for URL ".$self->{Monitor}->{ControlAddress}."/$cmd" );
# TODO: Add code to retrieve $res->message_decode or some such. Then we could do things like check the camera status.
}
else
{
Error( "Camera control command FAILED: '".$res->status_line()."' for URL ".$self->{Monitor}->{ControlAddress}."/$cmd" );
}
return( $result );
}
sub reset
{
my $self = shift;
# This reboots the camera effectively resetting it
Debug( "Camera Reset" );
$self->sendCmd( 'cgi-bin/magicBox.cgi?action=reboot' );
##FIXME: Exit is a bad idea as it appears to cause zmc to run away.
#Exit (0);
sub reset {
my $self = shift;
# This reboots the camera effectively resetting it
$self->sendCmd('cgi-bin/magicBox.cgi?action=reboot');
}
# NOTE: I'm putting this in, but absolute camera movement does not seem to be well supported in the classic skin ATM.
@ -184,163 +164,148 @@ sub reset
sub moveAbs ## Up, Down, Left, Right, etc. ??? Doesn't make sense here...
{
my $self = shift;
my $pan_degrees = shift || 0;
my $tilt_degrees = shift || 0;
my $speed = shift || 1;
Debug( "Move ABS" );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=PositionABS&channel=0&arg1='.$pan_degrees.'&arg2='.$tilt_degrees.'&arg3=0&arg4='.$speed );
my $self = shift;
my $pan_degrees = shift || 0;
my $tilt_degrees = shift || 0;
my $speed = shift || 1;
Debug('Move ABS');
$self->sendCmd('cgi-bin/ptz.cgi?action=start&code=PositionABS&channel=0&arg1='.$pan_degrees.'&arg2='.$tilt_degrees.'&arg3=0&arg4='.$speed);
}
sub moveConUp
{
my $self = shift;
Debug( "Move Up" );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=Up&channel=0&arg1=0&arg2=1&arg3=0' );
usleep (500); ##XXX Should this be passed in as a "speed" parameter?
$self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=Up&channel=0&arg1=0&arg2=1&arg3=0' );
sub moveConUp {
my $self = shift;
Debug('Move Up');
$self->sendCmd('cgi-bin/ptz.cgi?action=start&code=Up&channel=0&arg1=0&arg2=1&arg3=0');
usleep(500); ##XXX Should this be passed in as a "speed" parameter?
$self->sendCmd('cgi-bin/ptz.cgi?action=stop&code=Up&channel=0&arg1=0&arg2=1&arg3=0');
}
sub moveConDown
{
my $self = shift;
Debug( "Move Down" );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=Down&channel=0&arg1=0&arg2=1&arg3=0' );
usleep (500);
$self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=Down&channel=0&arg1=0&arg2=1&arg3=0' );
sub moveConDown {
my $self = shift;
Debug('Move Down');
$self->sendCmd('cgi-bin/ptz.cgi?action=start&code=Down&channel=0&arg1=0&arg2=1&arg3=0');
usleep(500);
$self->sendCmd('cgi-bin/ptz.cgi?action=stop&code=Down&channel=0&arg1=0&arg2=1&arg3=0');
}
sub moveConLeft
{
my $self = shift;
Debug( "Move Left" );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=Left&channel=0&arg1=0&arg2=1&arg3=0' );
usleep (500);
$self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=Left&channel=0&arg1=0&arg2=1&arg3=0' );
sub moveConLeft {
my $self = shift;
Debug('Move Left');
$self->sendCmd('cgi-bin/ptz.cgi?action=start&code=Left&channel=0&arg1=0&arg2=1&arg3=0');
usleep(500);
$self->sendCmd('cgi-bin/ptz.cgi?action=stop&code=Left&channel=0&arg1=0&arg2=1&arg3=0');
}
sub moveConRight
{
my $self = shift;
Debug( "Move Right" );
# $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=PositionABS&channel=0&arg1=270&arg2=5&arg3=0' );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=Right&channel=0&arg1=0&arg2=1&arg3=0' );
usleep (500);
Debug( "Move Right Stop" );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=Right&channel=0&arg1=0&arg2=1&arg3=0' );
sub moveConRight {
my $self = shift;
Debug('Move Right');
# $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=PositionABS&channel=0&arg1=270&arg2=5&arg3=0' );
$self->sendCmd('cgi-bin/ptz.cgi?action=start&code=Right&channel=0&arg1=0&arg2=1&arg3=0');
usleep(500);
Debug('Move Right Stop');
$self->sendCmd('cgi-bin/ptz.cgi?action=stop&code=Right&channel=0&arg1=0&arg2=1&arg3=0');
}
sub moveConUpRight
{
my $self = shift;
Debug( "Move Diagonally Up Right" );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=RightUp&channel=0&arg1=1&arg2=1&arg3=0' );
usleep (500);
$self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=RightUp&channel=0&arg1=0&arg2=1&arg3=0' );
sub moveConUpRight {
my $self = shift;
Debug('Move Diagonally Up Right');
$self->sendCmd('cgi-bin/ptz.cgi?action=start&code=RightUp&channel=0&arg1=1&arg2=1&arg3=0');
usleep(500);
$self->sendCmd('cgi-bin/ptz.cgi?action=stop&code=RightUp&channel=0&arg1=0&arg2=1&arg3=0');
}
sub moveConDownRight
{
my $self = shift;
Debug( "Move Diagonally Down Right" );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=RightDown&channel=0&arg1=1&arg2=1&arg3=0' );
usleep (500);
$self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=RightDown&channel=0&arg1=0&arg2=1&arg3=0' );
sub moveConDownRight {
my $self = shift;
Debug('Move Diagonally Down Right');
$self->sendCmd('cgi-bin/ptz.cgi?action=start&code=RightDown&channel=0&arg1=1&arg2=1&arg3=0');
usleep(500);
$self->sendCmd('cgi-bin/ptz.cgi?action=stop&code=RightDown&channel=0&arg1=0&arg2=1&arg3=0');
}
sub moveConUpLeft
{
my $self = shift;
Debug( "Move Diagonally Up Left" );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=LeftUp&channel=0&arg1=1&arg2=1&arg3=0' );
usleep (500);
$self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=LeftUp&channel=0&arg1=0&arg2=1&arg3=0' );
sub moveConUpLeft {
my $self = shift;
Debug('Move Diagonally Up Left');
$self->sendCmd('cgi-bin/ptz.cgi?action=start&code=LeftUp&channel=0&arg1=1&arg2=1&arg3=0');
usleep(500);
$self->sendCmd('cgi-bin/ptz.cgi?action=stop&code=LeftUp&channel=0&arg1=0&arg2=1&arg3=0');
}
sub moveConDownLeft
{
my $self = shift;
Debug( "Move Diagonally Down Left" );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=LeftDown&channel=0&arg1=1&arg2=1&arg3=0' );
usleep (500);
$self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=LeftDown&channel=0&arg1=0&arg2=1&arg3=0' );
sub moveConDownLeft {
my $self = shift;
Debug('Move Diagonally Down Left');
$self->sendCmd('cgi-bin/ptz.cgi?action=start&code=LeftDown&channel=0&arg1=1&arg2=1&arg3=0');
usleep (500);
$self->sendCmd('cgi-bin/ptz.cgi?action=stop&code=LeftDown&channel=0&arg1=0&arg2=1&arg3=0');
}
# Stop is not "correctly" implemented as control_functions.php translates this to "Center"
# So we'll just send the camera to 0* Horz, 0* Vert, zoom out; Also, Amcrest does not seem to
# support a generic stop-all-current-action command.
sub moveStop
{
my $self = shift;
Debug( "Move Stop/Center" );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=PositionABS&channel=0&arg1=0&arg2=0&arg3=0&arg4=1' );
sub moveStop {
my $self = shift;
Debug('Move Stop/Center');
$self->sendCmd('cgi-bin/ptz.cgi?action=start&code=PositionABS&channel=0&arg1=0&arg2=0&arg3=0&arg4=1');
}
# Move Camera to Home Position
# The current API does not support a Home per se, so we'll just send the camera to preset #1
# NOTE: It goes without saying that the user must have set up preset #1 for this to work.
sub presetHome
{
my $self = shift;
Debug( "Home Preset" );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&channel=0&code=GotoPreset&&arg1=0&arg2=1&arg3=0&arg4=0' );
sub presetHome {
my $self = shift;
Debug('Home Preset');
$self->sendCmd('cgi-bin/ptz.cgi?action=start&channel=0&code=GotoPreset&&arg1=0&arg2=1&arg3=0&arg4=0');
}
sub presetGoto
{
my $self = shift;
my $params = shift;
my $preset = $self->getParam( $params, 'preset' );
Debug( "Go To Preset $preset" );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&channel=0&code=GotoPreset&&arg1=0&arg2='.$preset.'&arg3=0&arg4=0' );
sub presetGoto {
my $self = shift;
my $params = shift;
my $preset = $self->getParam($params, 'preset');
Debug("Go To Preset $preset");
$self->sendCmd('cgi-bin/ptz.cgi?action=start&channel=0&code=GotoPreset&&arg1=0&arg2='.$preset.'&arg3=0&arg4=0');
}
sub presetSet
{
my $self = shift;
my $params = shift;
my $preset = $self->getParam( $params, 'preset' );
Debug( "Set Preset" );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&channel=0&code=SetPreset&arg1=0&arg2='.$preset.'&arg3=0&arg4=0' );
sub presetSet {
my $self = shift;
my $params = shift;
my $preset = $self->getParam($params, 'preset');
Debug('Set Preset');
$self->sendCmd('cgi-bin/ptz.cgi?action=start&channel=0&code=SetPreset&arg1=0&arg2='.$preset.'&arg3=0&arg4=0');
}
# NOTE: This does not appear to be implemented in the classic skin. But we'll leave it here for later.
sub moveMap
{
my $self = shift;
my $params = shift;
sub moveMap {
my $self = shift;
my $params = shift;
my $xcoord = $self->getParam( $params, 'xcoord', $self->{Monitor}{Width}/2 );
my $ycoord = $self->getParam( $params, 'ycoord', $self->{Monitor}{Height}/2 );
# if the camera is mounted upside down, you may have to inverse these coordinates
# just use 360 minus pan instead of pan, 90 minus tilt instead of tilt
# Convert xcoord into pan position 0 to 359
my $pan = int(360 * $xcoord / $self->{Monitor}{Width});
# Convert ycoord into tilt position 0 to 89
my $tilt = 90 - int(90 * $ycoord / $self->{Monitor}{Height});
# Now get the following url:
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=PositionABS&channel=0&arg1='.$pan.'&arg2='.$tilt.'&arg3=1&arg4=1');
my $xcoord = $self->getParam( $params, 'xcoord', $self->{Monitor}{Width}/2 );
my $ycoord = $self->getParam( $params, 'ycoord', $self->{Monitor}{Height}/2 );
# if the camera is mounted upside down, you may have to inverse these coordinates
# just use 360 minus pan instead of pan, 90 minus tilt instead of tilt
# Convert xcoord into pan position 0 to 359
my $pan = int(360 * $xcoord / $self->{Monitor}{Width});
# Convert ycoord into tilt position 0 to 89
my $tilt = 90 - int(90 * $ycoord / $self->{Monitor}{Height});
# Now get the following url:
$self->sendCmd('cgi-bin/ptz.cgi?action=start&code=PositionABS&channel=0&arg1='.$pan.'&arg2='.$tilt.'&arg3=1&arg4=1');
}
sub zoomConTele
{
my $self = shift;
Debug( "Zoom continuous tele" );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&channel=0&code=ZoomTele&arg1=0&arg2=0&arg3=0&arg4=0' );
usleep (100000);
$self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&channel=0&code=ZoomTele&arg1=0&arg2=0&arg3=0&arg4=0' );
sub zoomConTele {
my $self = shift;
Debug('Zoom continuous tele');
$self->sendCmd('cgi-bin/ptz.cgi?action=start&channel=0&code=ZoomTele&arg1=0&arg2=0&arg3=0&arg4=0');
usleep(100000);
$self->sendCmd('cgi-bin/ptz.cgi?action=stop&channel=0&code=ZoomTele&arg1=0&arg2=0&arg3=0&arg4=0');
}
sub zoomConWide
{
my $self = shift;
Debug( "Zoom continuous wide" );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&channel=0&code=ZoomWide&arg1=0&arg2=0&arg3=0&arg4=0' );
usleep (100000);
$self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&channel=0&code=ZoomWide&arg1=0&arg2=0&arg3=0&arg4=0' );
sub zoomConWide {
my $self = shift;
Debug('Zoom continuous wide');
$self->sendCmd('cgi-bin/ptz.cgi?action=start&channel=0&code=ZoomWide&arg1=0&arg2=0&arg3=0&arg4=0');
usleep (100000);
$self->sendCmd('cgi-bin/ptz.cgi?action=stop&channel=0&code=ZoomWide&arg1=0&arg2=0&arg3=0&arg4=0');
}
1;
@ -355,7 +320,7 @@ ZoneMinder::Control::Amcrest_HTTP - Amcrest camera control
=head1 DESCRIPTION
This module contains the implementation of the Amcrest Camera
This module contains the implementation of the Amcrest Camera
controllable SDK API.
NOTE: This module implements interaction with the camera in clear text.

View File

@ -1,6 +1,6 @@
# ==========================================================================
#
# ZoneMinder Axis version 2 API Control Protocol Module, $Date$, $Revision$
# ZoneMinder Axis version 2 API Control Protocol Module
# Copyright (C) 2001-2008 Philip Coombes
#
# This program is free software; you can redistribute it and/or
@ -33,12 +33,6 @@ require ZoneMinder::Control;
our @ISA = qw(ZoneMinder::Control);
our $REALM = '';
our $PROTOCOL = 'http://';
our $USERNAME = 'admin';
our $PASSWORD = '';
our $ADDRESS = '';
our $PORT = '';
# ==========================================================================
#
# Axis V2 Control Protocol
@ -51,39 +45,27 @@ use ZoneMinder::Config qw(:all);
use Time::HiRes qw( usleep );
use URI;
our $ADDRESS;
sub open {
my $self = shift;
$self->loadMonitor();
my $uri = URI->new($self->{Monitor}->{ControlAddress});
Debug("Have " . $uri);
#my($scheme, $authority, $path, $query, $fragment) =
# $self->{Monitor}->{ControlAddress} =~ m|(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?|;
#Debug("Have $scheme, $authority, $path, $query, $fragment)");
# $PROTOCOL = $scheme;
#($USERNAME, $PASSWORD) = split(':', $authority);
# $ADDRESS = $path;
$ADDRESS = $uri->scheme.'://'.$uri->host().$uri->path().($uri->port()?':'.$uri->port():'');
Debug($uri->authority());
my $self = shift;
$self->loadMonitor();
my $uri = URI->new($self->{Monitor}->{ControlAddress});
$ADDRESS = $uri->scheme.'://'.$uri->host().$uri->path().($uri->port()?':'.$uri->port():'');
use LWP::UserAgent;
$self->{ua} = LWP::UserAgent->new;
$self->{ua}->cookie_jar( {} );
$self->{ua}->agent('ZoneMinder Control Agent/'.ZoneMinder::Base::ZM_VERSION);
$self->{state} = 'closed';
# credentials: ("ip:port" (no prefix!), realm (string), username (string), password (string)
Debug("sendCmd credentials control address:'".$ADDRESS
."' realm:'".$REALM
."' username:'".$USERNAME
."' password:'".$PASSWORD
."'"
);
$self->{ua}->credentials($ADDRESS, $REALM, $USERNAME, $PASSWORD);
# Detect REALM
my ( $username, $password, $host ) = ( $uri->authority() =~ /^([^:]+):([^@]*)@(.+)$/ );
my $realm = $self->{Monitor}->{ControlDevice};
$self->{ua}->credentials($ADDRESS, $realm, $username, $password);
# test auth
my $res = $self->{ua}->get($ADDRESS.'/cgi/ptdc.cgi');
if ( $res->is_success ) {
@ -99,13 +81,13 @@ Debug($uri->authority());
}
if ( $$headers{'www-authenticate'} ) {
Debug("Authenticating");
Debug('Authenticating');
my ( $auth, $tokens ) = $$headers{'www-authenticate'} =~ /^(\w+)\s+(.*)$/;
if ( $tokens =~ /\w+="([^"]+)"/i ) {
if ( $REALM ne $1 ) {
$REALM = $1;
Debug("Changing REALM to $REALM");
$self->{ua}->credentials($ADDRESS,$REALM,$USERNAME,$PASSWORD);
if ( $realm ne $1 ) {
$realm = $1;
Debug("Changing REALM to $realm");
$self->{ua}->credentials($host, $realm, $username, $password);
$res = $self->{ua}->get($ADDRESS);
if ( $res->is_success() ) {
$self->{state} = 'open';
@ -148,288 +130,268 @@ sub sendCmd {
}
sub cameraReset {
my $self = shift;
Debug('Camera Reset');
my $cmd = '/axis-cgi/admin/restart.cgi';
$self->sendCmd( $cmd );
my $self = shift;
Debug('Camera Reset');
my $cmd = '/axis-cgi/admin/restart.cgi';
$self->sendCmd($cmd);
}
sub moveConUp
{
my $self = shift;
Debug( "Move Up" );
my $cmd = "/axis-cgi/com/ptz.cgi?move=up";
$self->sendCmd( $cmd );
sub moveConUp {
my $self = shift;
Debug('Move Up');
my $cmd = '/axis-cgi/com/ptz.cgi?move=up';
$self->sendCmd($cmd);
}
sub moveConDown
{
my $self = shift;
Debug( "Move Down" );
my $cmd = "/axis-cgi/com/ptz.cgi?move=down";
$self->sendCmd( $cmd );
sub moveConDown {
my $self = shift;
Debug('Move Down');
my $cmd = '/axis-cgi/com/ptz.cgi?move=down';
$self->sendCmd($cmd);
}
sub moveConLeft
{
my $self = shift;
Debug( "Move Left" );
my $cmd = "/axis-cgi/com/ptz.cgi?move=left";
$self->sendCmd( $cmd );
sub moveConLeft {
my $self = shift;
Debug('Move Left');
my $cmd = '/axis-cgi/com/ptz.cgi?move=left';
$self->sendCmd($cmd);
}
sub moveConRight {
my $self = shift;
Debug('Move Right');
$self->sendCmd('/axis-cgi/com/ptz.cgi?move=right');
my $self = shift;
Debug('Move Right');
my $cmd = '/axis-cgi/com/ptz.cgi?move=right';
$self->sendCmd($cmd);
}
sub moveConUpRight {
my $self = shift;
Debug('Move Up/Right');
$self->sendCmd('/axis-cgi/com/ptz.cgi?move=upright');
my $self = shift;
Debug('Move Up/Right');
my $cmd = '/axis-cgi/com/ptz.cgi?move=upright';
$self->sendCmd($cmd);
}
sub moveConUpLeft {
my $self = shift;
Debug( "Move Up/Left" );
$self->sendCmd('/axis-cgi/com/ptz.cgi?move=upleft');
my $self = shift;
Debug('Move Up/Left');
my $cmd = '/axis-cgi/com/ptz.cgi?move=upleft';
$self->sendCmd($cmd);
}
sub moveConDownRight {
my $self = shift;
Debug('Move Down/Right');
$self->sendCmd('/axis-cgi/com/ptz.cgi?move=downright');
my $self = shift;
Debug('Move Down/Right');
my $cmd = '/axis-cgi/com/ptz.cgi?move=downright';
$self->sendCmd( $cmd );
}
sub moveConDownLeft {
my $self = shift;
Debug('Move Down/Left');
my $cmd = '/axis-cgi/com/ptz.cgi?move=downleft';
$self->sendCmd($cmd);
my $self = shift;
Debug('Move Down/Left');
my $cmd = '/axis-cgi/com/ptz.cgi?move=downleft';
$self->sendCmd($cmd);
}
sub moveMap {
my $self = shift;
my $params = shift;
my $xcoord = $self->getParam($params, 'xcoord');
my $ycoord = $self->getParam($params, 'ycoord');
Debug( "Move Map to $xcoord,$ycoord" );
my $cmd = "/axis-cgi/com/ptz.cgi?center=$xcoord,$ycoord&imagewidth=".$self->{Monitor}->{Width}."&imageheight=".$self->{Monitor}->{Height};
$self->sendCmd( $cmd );
my $self = shift;
my $params = shift;
my $xcoord = $self->getParam($params, 'xcoord');
my $ycoord = $self->getParam($params, 'ycoord');
Debug("Move Map to $xcoord,$ycoord");
my $cmd = "/axis-cgi/com/ptz.cgi?center=$xcoord,$ycoord&imagewidth=".$self->{Monitor}->{Width}.'&imageheight='.$self->{Monitor}->{Height};
$self->sendCmd($cmd);
}
sub moveRelUp
{
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'tiltstep' );
Debug( "Step Up $step" );
my $cmd = "/axis-cgi/com/ptz.cgi?rtilt=$step";
$self->sendCmd( $cmd );
sub moveRelUp {
my $self = shift;
my $params = shift;
my $step = $self->getParam($params, 'tiltstep');
Debug("Step Up $step");
my $cmd = '/axis-cgi/com/ptz.cgi?rtilt='.$step;
$self->sendCmd($cmd);
}
sub moveRelDown
{
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'tiltstep' );
Debug( "Step Down $step" );
my $cmd = "/axis-cgi/com/ptz.cgi?rtilt=-$step";
$self->sendCmd( $cmd );
sub moveRelDown {
my $self = shift;
my $params = shift;
my $step = $self->getParam($params, 'tiltstep');
Debug("Step Down $step");
my $cmd = '/axis-cgi/com/ptz.cgi?rtilt=-'.$step;
$self->sendCmd($cmd);
}
sub moveRelLeft
{
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'panstep' );
Debug( "Step Left $step" );
my $cmd = "/axis-cgi/com/ptz.cgi?rpan=-$step";
$self->sendCmd( $cmd );
sub moveRelLeft {
my $self = shift;
my $params = shift;
my $step = $self->getParam($params, 'panstep');
Debug("Step Left $step");
my $cmd = '/axis-cgi/com/ptz.cgi?rpan=-'.$step;
$self->sendCmd($cmd);
}
sub moveRelRight
{
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'panstep' );
Debug( "Step Right $step" );
$self->sendCmd("/axis-cgi/com/ptz.cgi?rpan=$step&camera=1&whoami=1");
sub moveRelRight {
my $self = shift;
my $params = shift;
my $step = $self->getParam($params, 'panstep');
Debug("Step Right $step");
my $cmd = '/axis-cgi/com/ptz.cgi?rpan='.$step;
$self->sendCmd($cmd);
}
sub moveRelUpRight
{
my $self = shift;
my $params = shift;
my $panstep = $self->getParam( $params, 'panstep' );
my $tiltstep = $self->getParam( $params, 'tiltstep' );
Debug( "Step Up/Right $tiltstep/$panstep" );
my $cmd = "/axis-cgi/com/ptz.cgi?rpan=$panstep&rtilt=$tiltstep";
$self->sendCmd( $cmd );
sub moveRelUpRight {
my $self = shift;
my $params = shift;
my $panstep = $self->getParam($params, 'panstep');
my $tiltstep = $self->getParam($params, 'tiltstep');
Debug("Step Up/Right $tiltstep/$panstep");
my $cmd = "/axis-cgi/com/ptz.cgi?rpan=$panstep&rtilt=$tiltstep";
$self->sendCmd($cmd);
}
sub moveRelUpLeft
{
my $self = shift;
my $params = shift;
my $panstep = $self->getParam( $params, 'panstep' );
my $tiltstep = $self->getParam( $params, 'tiltstep' );
Debug( "Step Up/Left $tiltstep/$panstep" );
my $cmd = "/axis-cgi/com/ptz.cgi?rpan=-$panstep&rtilt=$tiltstep";
$self->sendCmd( $cmd );
sub moveRelUpLeft {
my $self = shift;
my $params = shift;
my $panstep = $self->getParam($params, 'panstep');
my $tiltstep = $self->getParam($params, 'tiltstep');
Debug("Step Up/Left $tiltstep/$panstep");
my $cmd = "/axis-cgi/com/ptz.cgi?rpan=-$panstep&rtilt=$tiltstep";
$self->sendCmd($cmd);
}
sub moveRelDownRight
{
my $self = shift;
my $params = shift;
my $panstep = $self->getParam( $params, 'panstep' );
my $tiltstep = $self->getParam( $params, 'tiltstep' );
Debug( "Step Down/Right $tiltstep/$panstep" );
my $cmd = "/axis-cgi/com/ptz.cgi?rpan=$panstep&rtilt=-$tiltstep";
$self->sendCmd( $cmd );
sub moveRelDownRight {
my $self = shift;
my $params = shift;
my $panstep = $self->getParam($params, 'panstep');
my $tiltstep = $self->getParam($params, 'tiltstep');
Debug("Step Down/Right $tiltstep/$panstep");
my $cmd = "/axis-cgi/com/ptz.cgi?rpan=$panstep&rtilt=-$tiltstep";
$self->sendCmd($cmd);
}
sub moveRelDownLeft
{
my $self = shift;
my $params = shift;
my $panstep = $self->getParam( $params, 'panstep' );
my $tiltstep = $self->getParam( $params, 'tiltstep' );
Debug( "Step Down/Left $tiltstep/$panstep" );
my $cmd = "/axis-cgi/com/ptz.cgi?rpan=-$panstep&rtilt=-$tiltstep";
$self->sendCmd( $cmd );
sub moveRelDownLeft {
my $self = shift;
my $params = shift;
my $panstep = $self->getParam($params, 'panstep');
my $tiltstep = $self->getParam($params, 'tiltstep');
Debug("Step Down/Left $tiltstep/$panstep");
my $cmd = "/axis-cgi/com/ptz.cgi?rpan=-$panstep&rtilt=-$tiltstep";
$self->sendCmd($cmd);
}
sub zoomRelTele
{
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'step' );
Debug( "Zoom Tele" );
my $cmd = "/axis-cgi/com/ptz.cgi?rzoom=$step";
$self->sendCmd( $cmd );
sub zoomRelTele {
my $self = shift;
my $params = shift;
my $step = $self->getParam($params, 'step');
Debug('Zoom Tele');
my $cmd = "/axis-cgi/com/ptz.cgi?rzoom=$step";
$self->sendCmd($cmd);
}
sub zoomRelWide
{
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'step' );
Debug( "Zoom Wide" );
my $cmd = "/axis-cgi/com/ptz.cgi?rzoom=-$step";
$self->sendCmd( $cmd );
sub zoomRelWide {
my $self = shift;
my $params = shift;
my $step = $self->getParam($params, 'step');
Debug('Zoom Wide');
my $cmd = "/axis-cgi/com/ptz.cgi?rzoom=-$step";
$self->sendCmd($cmd);
}
sub focusRelNear
{
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'step' );
Debug( "Focus Near" );
my $cmd = "/axis-cgi/com/ptz.cgi?rfocus=-$step";
$self->sendCmd( $cmd );
sub focusRelNear {
my $self = shift;
my $params = shift;
my $step = $self->getParam($params, 'step');
Debug('Focus Near');
my $cmd = "/axis-cgi/com/ptz.cgi?rfocus=-$step";
$self->sendCmd($cmd);
}
sub focusRelFar
{
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'step' );
Debug( "Focus Far" );
my $cmd = "/axis-cgi/com/ptz.cgi?rfocus=$step";
$self->sendCmd( $cmd );
sub focusRelFar {
my $self = shift;
my $params = shift;
my $step = $self->getParam($params, 'step');
Debug('Focus Far');
my $cmd = "/axis-cgi/com/ptz.cgi?rfocus=$step";
$self->sendCmd($cmd);
}
sub focusAuto
{
my $self = shift;
Debug( "Focus Auto" );
my $cmd = "/axis-cgi/com/ptz.cgi?autofocus=on";
$self->sendCmd( $cmd );
sub focusAuto {
my $self = shift;
Debug('Focus Auto');
my $cmd = '/axis-cgi/com/ptz.cgi?autofocus=on';
$self->sendCmd($cmd);
}
sub focusMan
{
my $self = shift;
Debug( "Focus Manual" );
my $cmd = "/axis-cgi/com/ptz.cgi?autofocus=off";
$self->sendCmd( $cmd );
sub focusMan {
my $self = shift;
Debug('Focus Manual');
my $cmd = '/axis-cgi/com/ptz.cgi?autofocus=off';
$self->sendCmd($cmd);
}
sub irisRelOpen
{
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'step' );
Debug( "Iris Open" );
my $cmd = "/axis-cgi/com/ptz.cgi?riris=$step";
$self->sendCmd( $cmd );
sub irisRelOpen {
my $self = shift;
my $params = shift;
my $step = $self->getParam($params, 'step');
Debug('Iris Open');
my $cmd = "/axis-cgi/com/ptz.cgi?riris=$step";
$self->sendCmd($cmd);
}
sub irisRelClose
{
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'step' );
Debug( "Iris Close" );
my $cmd = "/axis-cgi/com/ptz.cgi?riris=-$step";
$self->sendCmd( $cmd );
sub irisRelClose {
my $self = shift;
my $params = shift;
my $step = $self->getParam($params, 'step');
Debug('Iris Close');
my $cmd = "/axis-cgi/com/ptz.cgi?riris=-$step";
$self->sendCmd($cmd);
}
sub irisAuto
{
my $self = shift;
Debug( "Iris Auto" );
my $cmd = "/axis-cgi/com/ptz.cgi?autoiris=on";
$self->sendCmd( $cmd );
sub irisAuto {
my $self = shift;
Debug('Iris Auto');
my $cmd = '/axis-cgi/com/ptz.cgi?autoiris=on';
$self->sendCmd($cmd);
}
sub irisMan
{
my $self = shift;
Debug( "Iris Manual" );
my $cmd = "/axis-cgi/com/ptz.cgi?autoiris=off";
$self->sendCmd( $cmd );
sub irisMan {
my $self = shift;
Debug('Iris Manual');
my $cmd = '/axis-cgi/com/ptz.cgi?autoiris=off';
$self->sendCmd($cmd);
}
sub presetClear
{
my $self = shift;
my $params = shift;
my $preset = $self->getParam( $params, 'preset' );
Debug( "Clear Preset $preset" );
my $cmd = "/axis-cgi/com/ptz.cgi?removeserverpresetno=$preset";
$self->sendCmd( $cmd );
sub presetClear {
my $self = shift;
my $params = shift;
my $preset = $self->getParam($params, 'preset');
Debug("Clear Preset $preset");
my $cmd = "/axis-cgi/com/ptz.cgi?removeserverpresetno=$preset";
$self->sendCmd($cmd);
}
sub presetSet
{
my $self = shift;
my $params = shift;
my $preset = $self->getParam( $params, 'preset' );
Debug( "Set Preset $preset" );
my $cmd = "/axis-cgi/com/ptz.cgi?setserverpresetno=$preset";
$self->sendCmd( $cmd );
sub presetSet {
my $self = shift;
my $params = shift;
my $preset = $self->getParam($params, 'preset');
Debug("Set Preset $preset");
my $cmd = "/axis-cgi/com/ptz.cgi?setserverpresetno=$preset";
$self->sendCmd($cmd);
}
sub presetGoto
{
my $self = shift;
my $params = shift;
my $preset = $self->getParam( $params, 'preset' );
Debug( "Goto Preset $preset" );
my $cmd = "/axis-cgi/com/ptz.cgi?gotoserverpresetno=$preset";
$self->sendCmd( $cmd );
sub presetGoto {
my $self = shift;
my $params = shift;
my $preset = $self->getParam($params, 'preset');
Debug("Goto Preset $preset");
my $cmd = "/axis-cgi/com/ptz.cgi?gotoserverpresetno=$preset";
$self->sendCmd($cmd);
}
sub presetHome
{
my $self = shift;
Debug( "Home Preset" );
my $cmd = "/axis-cgi/com/ptz.cgi?move=home";
$self->sendCmd( $cmd );
sub presetHome {
my $self = shift;
Debug('Home Preset');
my $cmd = '/axis-cgi/com/ptz.cgi?move=home';
$self->sendCmd($cmd);
}
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)
#
# 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::Config qw(:all);
use Time::HiRes qw( usleep );
sub open {
my $self = shift;
@ -52,58 +50,50 @@ sub open {
use LWP::UserAgent;
$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';
}
sub printMsg {
my $self = shift;
my $msg = shift;
my $msg_len = length($msg);
Debug( $msg."[".$msg_len."]" );
}
sub sendCmd {
my $self = shift;
my $cmd = shift;
my $result = undef;
printMsg( $cmd, "Tx" );
$self->printMsg($cmd, 'Tx');
my $url;
if ( $self->{Monitor}->{ControlAddress} =~ /^http/ ) {
if ( $self->{Monitor}->{ControlAddress} =~ /^http/i ) {
$url = $self->{Monitor}->{ControlAddress}.$cmd;
} else {
$url = 'http://'.$self->{Monitor}->{ControlAddress}.$cmd;
} # en dif
my $req = HTTP::Request->new( GET=>$url );
} # end if
my $req = HTTP::Request->new(GET=>$url);
my $res = $self->{ua}->request($req);
if ( $res->is_success ) {
$result = !undef;
} else {
Error( "Error check failed: '".$res->status_line()."'" );
Error('Error check failed: \''.$res->status_line().'\'');
}
return( $result );
return $result;
}
sub reset {
my $self = shift;
Debug( "Camera Reset" );
my $cmd = "/admin/ptctl.cgi?move=reset";
$self->sendCmd( $cmd );
Debug('Camera Reset');
my $cmd = '/admin/ptctl.cgi?move=reset';
$self->sendCmd($cmd);
}
sub moveMap {
my $self = shift;
my $params = shift;
my $xcoord = $self->getParam( $params, 'xcoord' );
my $ycoord = $self->getParam( $params, 'ycoord' );
my $xcoord = $self->getParam($params, 'xcoord');
my $ycoord = $self->getParam($params, 'ycoord');
my $hor = $xcoord * 100 / $self->{Monitor}->{Width};
my $ver = $ycoord * 100 / $self->{Monitor}->{Height};
@ -125,81 +115,81 @@ sub moveMap {
elsif ( $hor > 50 ) {
# right
$horSteps = (($hor - 50) / 50) * $maxhor;
$horDir = "right";
$horDir = 'right';
}
# Vertical movement
if ( $ver < 50 ) {
# up
$verSteps = ((50 - $ver) / 50) * $maxver;
$verDir = "up";
$verDir = 'up';
}
elsif ( $ver > 50 ) {
# down
$verSteps = (($ver - 50) / 50) * $maxver;
$verDir = "down";
$verDir = 'down';
}
my $v = int($verSteps);
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";
$self->sendCmd( $cmd );
$self->sendCmd($cmd);
$cmd = "/cgi/admin/ptctrl.cgi?action=movedegree&Cmd=$verDir&Degree=$v";
$self->sendCmd( $cmd );
$self->sendCmd($cmd);
}
sub moveRelUp {
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'tiltstep' );
Debug( "Step Up $step" );
my $cmd = "/admin/ptctl.cgi?move=up";
$self->sendCmd( $cmd );
my $step = $self->getParam($params, 'tiltstep');
Debug("Step Up $step");
my $cmd = '/admin/ptctl.cgi?move=up';
$self->sendCmd($cmd);
}
sub moveRelDown {
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'tiltstep' );
Debug( "Step Down $step" );
my $cmd = "/admin/ptctl.cgi?move=down";
$self->sendCmd( $cmd );
my $step = $self->getParam($params, 'tiltstep');
Debug("Step Down $step");
my $cmd = '/admin/ptctl.cgi?move=down';
$self->sendCmd($cmd);
}
sub moveRelLeft {
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'panstep' );
my $step = $self->getParam($params, 'panstep');
if ( $self->{Monitor}->{Orientation} eq "hori" ) {
Debug( "Stepping Right because flipped horizontally " );
$self->sendCmd( "/admin/ptctl.cgi?move=right" );
if ( $self->{Monitor}->{Orientation} eq 'FLIP_HORI' ) {
Debug('Stepping Right because flipped horizontally');
$self->sendCmd('/admin/ptctl.cgi?move=right');
} else {
Debug( "Step Left" );
$self->sendCmd( "/admin/ptctl.cgi?move=left" );
Debug('Step Left');
$self->sendCmd('/admin/ptctl.cgi?move=left');
}
}
sub moveRelRight {
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'panstep' );
if ( $self->{Monitor}->{Orientation} eq "hori" ) {
Debug( "Stepping Left because flipped horizontally " );
$self->sendCmd( "/admin/ptctl.cgi?move=left" );
my $step = $self->getParam($params, 'panstep');
if ( $self->{Monitor}->{Orientation} eq 'FLIP_HORI' ) {
Debug('Stepping Left because flipped horizontally');
$self->sendCmd('/admin/ptctl.cgi?move=left');
} else {
Debug( "Step Right" );
$self->sendCmd( "/admin/ptctl.cgi?move=right" );
Debug('Step Right');
$self->sendCmd('/admin/ptctl.cgi?move=right');
}
}
sub presetClear {
my $self = shift;
my $params = shift;
my $preset = $self->getParam( $params, 'preset' );
Debug( "Clear Preset $preset" );
my $preset = $self->getParam($params, 'preset');
Debug("Clear Preset $preset");
#my $cmd = "/axis-cgi/com/ptz.cgi?removeserverpresetno=$preset";
#$self->sendCmd( $cmd );
}
@ -207,26 +197,26 @@ sub presetClear {
sub presetSet {
my $self = shift;
my $params = shift;
my $preset = $self->getParam( $params, 'preset' );
Debug( "Set Preset $preset" );
my $cmd = "/admin/ptctl.cgi?position=" . ($preset - 1) . "&positionname=zm$preset";
my $preset = $self->getParam($params, 'preset');
Debug("Set Preset $preset");
my $cmd = '/admin/ptctl.cgi?position=' . ($preset - 1) . "&positionname=zm$preset";
$self->sendCmd( $cmd );
}
sub presetGoto {
my $self = shift;
my $params = shift;
my $preset = $self->getParam( $params, 'preset' );
Debug( "Goto Preset $preset" );
my $cmd = "/admin/ptctl.cgi?move=p" . ($preset - 1);
$self->sendCmd( $cmd );
my $preset = $self->getParam($params, 'preset');
Debug("Goto Preset $preset");
my $cmd = '/admin/ptctl.cgi?move=p'.($preset - 1);
$self->sendCmd($cmd);
}
sub presetHome {
my $self = shift;
Debug( "Home Preset" );
my $cmd = "/admin/ptctl.cgi?move=h";
$self->sendCmd( $cmd );
Debug('Home Preset');
my $cmd = '/admin/ptctl.cgi?move=h';
$self->sendCmd($cmd);
}
1;

View File

@ -108,6 +108,9 @@ if ( $options{command} ) {
Fatal("Unable to load control data for monitor $id");
}
my $protocol = $monitor->{Protocol};
if ( !$protocol ) {
Fatal('No protocol is set in monitor. Please edit the monitor, edit control type, select the control capability and fill in the Protocol field');
}
if ( -x $protocol ) {
# Protocol is actually a script!

View File

@ -23,6 +23,7 @@
use strict;
use bytes;
use utf8;
@EXTRA_PERL_LIB@
use ZoneMinder;
@ -34,6 +35,7 @@ use Sys::MemInfo qw(totalmem);
use Sys::CPU qw(cpu_count);
use POSIX qw(strftime uname);
use JSON::MaybeXS;
use Encode;
$ENV{PATH} = '/bin:/usr/bin:/usr/local/bin';
$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL};
@ -166,7 +168,7 @@ sub sendData {
$req->header('content-length' => length($msg));
$req->header('connection' => 'Close');
$req->content($msg);
$req->content(encode('UTF-8',$msg));
my $resp = $ua->request($req);
my $resp_msg = $resp->decoded_content;

View File

@ -81,7 +81,7 @@ void FFMPEGInit() {
av_log_set_callback(log_libav_callback);
Info("Enabling ffmpeg logs, as LOG_DEBUG+LOG_FFMPEG are enabled in options");
} else {
Info("Not enabling ffmpeg logs, as LOG_FFMPEG and/or LOG_DEBUG is disabled in options, or this monitor not part of your debug targets");
Info("Not enabling ffmpeg logs, as LOG_FFMPEG and/or LOG_DEBUG is disabled in options, or this monitor is not part of your debug targets");
av_log_set_level(AV_LOG_QUIET);
}
#if !LIBAVFORMAT_VERSION_CHECK(58, 9, 0, 64, 0)
@ -291,17 +291,18 @@ static void zm_log_fps(double d, const char *postfix) {
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
void zm_dump_codecpar ( const AVCodecParameters *par ) {
Debug(1, "Dumping codecpar codec_type(%d) codec_id(%d %s) codec_tag(%d) width(%d) height(%d) bit_rate(%d) format(%d = %s)",
par->codec_type,
par->codec_id,
avcodec_get_name(par->codec_id),
par->codec_tag,
par->width,
par->height,
par->bit_rate,
par->format,
((AVPixelFormat)par->format == AV_PIX_FMT_NONE ? "none" : av_get_pix_fmt_name((AVPixelFormat)par->format))
);
Debug(1, "Dumping codecpar codec_type(%d %s) codec_id(%d %s) codec_tag(%" PRIu32 ") width(%d) height(%d) bit_rate(%" PRIu64 ") format(%d %s)",
par->codec_type,
av_get_media_type_string(par->codec_type),
par->codec_id,
avcodec_get_name(par->codec_id),
par->codec_tag,
par->width,
par->height,
par->bit_rate,
par->format,
(((AVPixelFormat)par->format == AV_PIX_FMT_NONE) ? "none" : av_get_pix_fmt_name((AVPixelFormat)par->format))
);
}
#endif

View File

@ -517,19 +517,19 @@ int FfmpegCamera::OpenFfmpeg() {
Debug(1, "Selected hw_pix_fmt %d %s",
hw_pix_fmt, av_get_pix_fmt_name(hw_pix_fmt));
mVideoCodecContext->get_format = get_hw_format;
ret = av_hwdevice_ctx_create(&hw_device_ctx, type,
(hwaccel_device != "" ? hwaccel_device.c_str(): NULL), NULL, 0);
if ( ret < 0 ) {
Error("Failed to create hwaccel device.");
return -1;
Error("Failed to create hwaccel device. %s",av_make_error_string(ret).c_str());
hw_pix_fmt = AV_PIX_FMT_NONE;
} else {
Debug(1, "Created hwdevice for %s", hwaccel_device.c_str());
mVideoCodecContext->get_format = get_hw_format;
mVideoCodecContext->hw_device_ctx = av_buffer_ref(hw_device_ctx);
hwFrame = zm_av_frame_alloc();
}
Debug(1, "Created hwdevice for %s", hwaccel_device.c_str());
mVideoCodecContext->hw_device_ctx = av_buffer_ref(hw_device_ctx);
hwFrame = zm_av_frame_alloc();
} else {
Debug(1, "Failed to setup hwaccel.");
Debug(1, "Failed to find suitable hw_pix_fmt.");
}
#else
Debug(1, "AVCodec not new enough for hwaccel");
@ -537,7 +537,7 @@ int FfmpegCamera::OpenFfmpeg() {
#else
Warning("HWAccel support not compiled in.");
#endif
} // end if hwacel_name
} // end if hwaccel_name
// Open the codec
#if !LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 8, 0)
@ -1087,6 +1087,7 @@ int FfmpegCamera::transfer_to_image(
return -1;
}
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
// From what I've read, we should align the linesizes to 32bit so that ffmpeg can use SIMD instructions too.
int size = av_image_fill_arrays(
output_frame->data, output_frame->linesize,
directbuffer, imagePixFormat, width, height, 32);
@ -1128,8 +1129,8 @@ int FfmpegCamera::transfer_to_image(
mConvertContext, input_frame->data, input_frame->linesize,
0, mVideoCodecContext->height,
output_frame->data, output_frame->linesize);
if ( ret <= 0 ) {
Error("Unable to convert format %u %s linesize %d height %d to format %u %s linesize %d at frame %d codec %u %s : code: %d",
if ( ret < 0 ) {
Error("Unable to convert format %u %s linesize %d height %d to format %u %s linesize %d at frame %d codec %u %s lines %d: code: %d",
input_frame->format, av_get_pix_fmt_name((AVPixelFormat)input_frame->format),
input_frame->linesize, mVideoCodecContext->height,
imagePixFormat,
@ -1137,6 +1138,7 @@ int FfmpegCamera::transfer_to_image(
output_frame->linesize,
frameCount,
mVideoCodecContext->pix_fmt, av_get_pix_fmt_name(mVideoCodecContext->pix_fmt),
mVideoCodecContext->height,
ret
);
return -1;

View File

@ -10,6 +10,7 @@ FFmpeg_Input::FFmpeg_Input() {
FFMPEGInit();
streams = NULL;
frame = NULL;
last_seek_request = -1;
}
FFmpeg_Input::~FFmpeg_Input() {
@ -102,7 +103,6 @@ int FFmpeg_Input::Open(const char *filepath) {
} // end int FFmpeg_Input::Open( const char * filepath )
AVFrame *FFmpeg_Input::get_frame(int stream_id) {
Debug(1, "Getting frame from stream %d", stream_id);
int frameComplete = false;
AVPacket packet;
@ -138,12 +138,14 @@ AVFrame *FFmpeg_Input::get_frame(int stream_id) {
frame = zm_av_frame_alloc();
}
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",
streams[packet.stream_index].frame_count, av_make_error_string(ret).c_str());
zm_av_packet_unref(&packet);
av_frame_free(&frame);
continue;
} else {
zm_dump_frame(frame, "resulting frame");
}
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
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");
// 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,
@ -191,6 +204,8 @@ AVFrame *FFmpeg_Input::get_frame(int stream_id, double at) {
zm_dump_frame(frame, "frame->pts > seek_target, got");
} // 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.
if ( frame->pts <= seek_target ) {
zm_dump_frame(frame, "pts <= seek_target");

View File

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

View File

@ -156,6 +156,7 @@ void Logger::initialise(const std::string &id, const Options &options) {
if ( options.mTerminalLevel != NOOPT )
tempTerminalLevel = options.mTerminalLevel;
// DEBUG1 == 1. So >= DEBUG1, we set to DEBUG9?! Why?
if ( options.mDatabaseLevel != NOOPT )
tempDatabaseLevel = options.mDatabaseLevel;
else
@ -359,7 +360,7 @@ Logger::Level Logger::databaseLevel(Logger::Level databaseLevel) {
if ( databaseLevel > NOOPT ) {
databaseLevel = limit(databaseLevel);
if ( mDatabaseLevel != databaseLevel ) {
if ( databaseLevel > NOLOG && mDatabaseLevel <= NOLOG ) {
if ( (databaseLevel > NOLOG) && (mDatabaseLevel <= NOLOG) ) { // <= NOLOG would be NOOPT
if ( !zmDbConnect() ) {
databaseLevel = NOLOG;
}

View File

@ -1,21 +1,21 @@
//
// ZoneMinder Monitor Class Implementation, $Date$, $Revision$
// Copyright (C) 2001-2008 Philip Coombes
//
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
//
#include "zm.h"
#include "zm_db.h"
@ -73,7 +73,7 @@ bool MonitorStream::checkSwapPath(const char *path, bool create_path) {
return false;
}
return true;
} // end bool MonitorStream::checkSwapPath( const char *path, bool create_path )
} // end bool MonitorStream::checkSwapPath( const char *path, bool create_path )
void MonitorStream::processCommand(const CmdMsg *msg) {
Debug( 2, "Got message, type %d, msg %d", msg->msg_type, msg->msg_data[0] );
@ -265,7 +265,7 @@ void MonitorStream::processCommand(const CmdMsg *msg) {
//status_data.enabled = monitor->shared_data->active;
status_data.enabled = monitor->trigger_data->trigger_state!=Monitor::TRIGGER_OFF;
status_data.forced = monitor->trigger_data->trigger_state==Monitor::TRIGGER_ON;
Debug(2, "Buffer Level:%d, Delayed:%d, Paused:%d, Rate:%d, delay:%.3f, Zoom:%d, Enabled:%d Forced:%d",
Debug(2, "Buffer Level:%d, Delayed:%d, Paused:%d, Rate:%d, delay:%.3f, Zoom:%d, Enabled:%d Forced:%d",
status_data.buffer_level,
status_data.delayed,
status_data.paused,
@ -327,7 +327,7 @@ bool MonitorStream::sendFrame(const char *filepath, struct timeval *timestamp) {
// Calculate how long it takes to actually send the frame
struct timeval frameStartTime;
gettimeofday(&frameStartTime, NULL);
fputs("--ZoneMinderFrame\r\nContent-Type: image/jpeg\r\n", stdout);
fprintf(stdout, "Content-Length: %d\r\n\r\n", img_buffer_size);
if ( fwrite(img_buffer, img_buffer_size, 1, stdout) != 1 ) {
@ -383,7 +383,7 @@ bool MonitorStream::sendFrame(Image *image, struct timeval *timestamp) {
// Calculate how long it takes to actually send the frame
struct timeval frameStartTime;
gettimeofday(&frameStartTime, NULL);
fputs("--ZoneMinderFrame\r\n", stdout);
switch( type ) {
case STREAM_JPEG :
@ -412,7 +412,7 @@ bool MonitorStream::sendFrame(Image *image, struct timeval *timestamp) {
}
fprintf(stdout, "Content-Length: %d\r\n\r\n", img_buffer_size);
if ( fwrite(img_buffer, img_buffer_size, 1, stdout) != 1 ) {
if ( !zm_terminate ) {
if ( !zm_terminate ) {
// If the pipe was closed, we will get signalled SIGPIPE to exit, which will set zm_terminate
Warning("Unable to send stream frame: %s", strerror(errno));
}
@ -430,7 +430,7 @@ bool MonitorStream::sendFrame(Image *image, struct timeval *timestamp) {
Warning("Frame send time %d msec too slow, throttling maxfps to %.2f",
frameSendTime, maxfps);
}
}
} // Not mpeg
last_frame_sent = TV_2_FLOAT(now);
return true;
} // end bool MonitorStream::sendFrame( Image *image, struct timeval *timestamp )
@ -455,7 +455,7 @@ void MonitorStream::runStream() {
fputs("Content-Type: multipart/x-mixed-replace;boundary=ZoneMinderFrame\r\n\r\n", stdout);
// point to end which is theoretically not a valid value because all indexes are % image_buffer_count
unsigned int last_read_index = monitor->image_buffer_count;
unsigned int last_read_index = monitor->image_buffer_count;
time_t stream_start_time;
time(&stream_start_time);
@ -474,22 +474,21 @@ void MonitorStream::runStream() {
Image *paused_image = NULL;
struct timeval paused_timestamp;
// 15 is the max length for the swap path suffix, /zmswap-whatever, assuming max 6 digits for monitor id
const int max_swap_len_suffix = 15;
int swap_path_length = staticConfig.PATH_SWAP.length() + 1; // +1 for NULL terminator
int subfolder1_length = snprintf(NULL, 0, "/zmswap-m%d", monitor->Id()) + 1;
int subfolder2_length = snprintf(NULL, 0, "/zmswap-q%06d", connkey) + 1;
int total_swap_path_length = swap_path_length + subfolder1_length + subfolder2_length;
if ( connkey && ( playback_buffer > 0 ) ) {
// 15 is the max length for the swap path suffix, /zmswap-whatever, assuming max 6 digits for monitor id
const int max_swap_len_suffix = 15;
int swap_path_length = staticConfig.PATH_SWAP.length() + 1; // +1 for NULL terminator
int subfolder1_length = snprintf(NULL, 0, "/zmswap-m%d", monitor->Id()) + 1;
int subfolder2_length = snprintf(NULL, 0, "/zmswap-q%06d", connkey) + 1;
int total_swap_path_length = swap_path_length + subfolder1_length + subfolder2_length;
if ( total_swap_path_length + max_swap_len_suffix > PATH_MAX ) {
Error("Swap Path is too long. %d > %d ", total_swap_path_length+max_swap_len_suffix, PATH_MAX);
} else {
swap_path = staticConfig.PATH_SWAP;
Debug( 3, "Checking swap path folder: %s", swap_path.c_str() );
Debug(3, "Checking swap path folder: %s", swap_path.c_str());
if ( checkSwapPath(swap_path.c_str(), true) ) {
swap_path += stringtf("/zmswap-m%d", monitor->Id());
@ -509,8 +508,8 @@ void MonitorStream::runStream() {
} else {
Debug(2, "Assigning temporary buffer");
temp_image_buffer = new SwapImage[temp_image_buffer_count];
memset( temp_image_buffer, 0, sizeof(*temp_image_buffer)*temp_image_buffer_count );
Debug( 2, "Assigned temporary buffer" );
memset(temp_image_buffer, 0, sizeof(*temp_image_buffer)*temp_image_buffer_count);
Debug(2, "Assigned temporary buffer");
}
}
} else {
@ -525,7 +524,7 @@ void MonitorStream::runStream() {
Debug(1, "Using %.3f for fps instead of current fps %.3f", capture_max_fps, capture_fps);
capture_fps = capture_max_fps;
}
if ( capture_fps < 1 ) {
max_secs_since_last_sent_frame = 10/capture_fps;
Debug(1, "Adjusting max_secs_since_last_sent_frame to %.2f from current fps %.2f",
@ -562,7 +561,7 @@ void MonitorStream::runStream() {
touch(sock_path_lock);
last_comm_update = now;
}
} // end if connkey
} // end if connkey
if ( paused ) {
if ( !was_paused ) {
@ -589,7 +588,7 @@ void MonitorStream::runStream() {
} else {
if ( !paused ) {
int temp_index = MOD_ADD(temp_read_index, 0, temp_image_buffer_count);
//Debug( 3, "tri: %d, ti: %d", temp_read_index, temp_index );
// Debug( 3, "tri: %d, ti: %d", temp_read_index, temp_index );
SwapImage *swap_image = &temp_image_buffer[temp_index];
if ( !swap_image->valid ) {
@ -597,51 +596,61 @@ void MonitorStream::runStream() {
delayed = true;
temp_read_index = MOD_ADD(temp_read_index, (replay_rate>=0?-1:1), temp_image_buffer_count);
} else {
//Debug( 3, "siT: %f, lfT: %f", TV_2_FLOAT( swap_image->timestamp ), TV_2_FLOAT( last_frame_timestamp ) );
double expected_delta_time = ((TV_2_FLOAT( swap_image->timestamp ) - TV_2_FLOAT( last_frame_timestamp )) * ZM_RATE_BASE)/replay_rate;
double actual_delta_time = TV_2_FLOAT( now ) - last_frame_sent;
// Debug( 3, "siT: %f, lfT: %f", TV_2_FLOAT( swap_image->timestamp ), TV_2_FLOAT( last_frame_timestamp ) );
double expected_delta_time = ((TV_2_FLOAT(swap_image->timestamp) - TV_2_FLOAT(last_frame_timestamp)) * ZM_RATE_BASE)/replay_rate;
double actual_delta_time = TV_2_FLOAT(now) - last_frame_sent;
//Debug( 3, "eDT: %.3lf, aDT: %.3f, lFS:%.3f, NOW:%.3f", expected_delta_time, actual_delta_time, last_frame_sent, TV_2_FLOAT( now ) );
// Debug( 3, "eDT: %.3lf, aDT: %.3f, lFS:%.3f, NOW:%.3f", expected_delta_time, actual_delta_time, last_frame_sent, TV_2_FLOAT( now ) );
// If the next frame is due
if ( actual_delta_time > expected_delta_time ) {
//Debug( 2, "eDT: %.3lf, aDT: %.3f", expected_delta_time, actual_delta_time );
// Debug( 2, "eDT: %.3lf, aDT: %.3f", expected_delta_time, actual_delta_time );
if ( temp_index%frame_mod == 0 ) {
Debug( 2, "Sending delayed frame %d", temp_index );
Debug(2, "Sending delayed frame %d", temp_index);
// Send the next frame
if ( ! sendFrame(temp_image_buffer[temp_index].file_name, &temp_image_buffer[temp_index].timestamp) )
if ( ! sendFrame(temp_image_buffer[temp_index].file_name, &temp_image_buffer[temp_index].timestamp) ) {
zm_terminate = true;
}
memcpy(&last_frame_timestamp, &(swap_image->timestamp), sizeof(last_frame_timestamp));
//frame_sent = true;
// frame_sent = true;
}
temp_read_index = MOD_ADD(temp_read_index, (replay_rate>0?1:-1), temp_image_buffer_count);
}
}
} else if ( step != 0 ) {
temp_read_index = MOD_ADD( temp_read_index, (step>0?1:-1), temp_image_buffer_count );
temp_read_index = MOD_ADD(temp_read_index, (step>0?1:-1), temp_image_buffer_count);
SwapImage *swap_image = &temp_image_buffer[temp_read_index];
// Send the next frame
if ( !sendFrame( temp_image_buffer[temp_read_index].file_name, &temp_image_buffer[temp_read_index].timestamp ) )
if ( !sendFrame(
temp_image_buffer[temp_read_index].file_name,
&temp_image_buffer[temp_read_index].timestamp
) ) {
zm_terminate = true;
memcpy( &last_frame_timestamp, &(swap_image->timestamp), sizeof(last_frame_timestamp) );
//frame_sent = true;
}
memcpy(
&last_frame_timestamp,
&(swap_image->timestamp),
sizeof(last_frame_timestamp)
);
// frame_sent = true;
step = 0;
} else {
//paused?
int temp_index = MOD_ADD(temp_read_index, 0, temp_image_buffer_count);
double actual_delta_time = TV_2_FLOAT( now ) - last_frame_sent;
if ( got_command || actual_delta_time > 5 ) {
double actual_delta_time = TV_2_FLOAT(now) - last_frame_sent;
if ( got_command || (actual_delta_time > 5) ) {
// Send keepalive
Debug(2, "Sending keepalive frame %d", temp_index);
// Send the next frame
if ( !sendFrame( temp_image_buffer[temp_index].file_name, &temp_image_buffer[temp_index].timestamp ) )
if ( !sendFrame(temp_image_buffer[temp_index].file_name, &temp_image_buffer[temp_index].timestamp) ) {
zm_terminate = true;
//frame_sent = true;
}
// frame_sent = true;
}
} // end if (!paused) or step or paused
} // end if have exceeded buffer or not
} // end if (!paused) or step or paused
} // end if have exceeded buffer or not
if ( temp_read_index == temp_write_index ) {
// Go back to live viewing
@ -652,16 +661,16 @@ void MonitorStream::runStream() {
delayed = false;
replay_rate = ZM_RATE_BASE;
}
} // end if ( buffered_playback && delayed )
} // end if ( buffered_playback && delayed )
if ( last_read_index != monitor->shared_data->last_write_index ) {
// have a new image to send
int index = monitor->shared_data->last_write_index % monitor->image_buffer_count; // % shouldn't be neccessary
int index = monitor->shared_data->last_write_index % monitor->image_buffer_count; // % shouldn't be neccessary
if ( (frame_mod == 1) || ((frame_count%frame_mod) == 0) ) {
if ( !paused && !delayed ) {
last_read_index = monitor->shared_data->last_write_index;
Debug(2, "index: %d: frame_mod: %d frame count: %d paused(%d) delayed(%d)",
index, frame_mod, frame_count, paused, delayed );
index, frame_mod, frame_count, paused, delayed);
// Send the next frame
Monitor::Snapshot *snap = &monitor->image_buffer[index];
@ -670,9 +679,13 @@ void MonitorStream::runStream() {
Debug(2, "sendFrame failed, quiting.");
zm_terminate = true;
}
// Perhaps we should use NOW instead.
memcpy(&last_frame_timestamp, snap->timestamp, sizeof(last_frame_timestamp));
//frame_sent = true;
// Perhaps we should use NOW instead.
memcpy(
&last_frame_timestamp,
snap->timestamp,
sizeof(last_frame_timestamp)
);
// frame_sent = true;
temp_read_index = temp_write_index;
} else {
@ -697,7 +710,7 @@ void MonitorStream::runStream() {
if ( !sendFrame(paused_image, &paused_timestamp) )
zm_terminate = true;
} else {
Debug(2, "Would have sent keepalive frame, but had no paused_image ");
Debug(2, "Would have sent keepalive frame, but had no paused_image");
}
} // end if actual_delta_time > 5
} // end if change in zoom
@ -718,27 +731,27 @@ void MonitorStream::runStream() {
temp_index);
temp_image_buffer[temp_index].valid = true;
}
memcpy( &(temp_image_buffer[temp_index].timestamp), monitor->image_buffer[index].timestamp, sizeof(temp_image_buffer[0].timestamp) );
monitor->image_buffer[index].image->WriteJpeg( temp_image_buffer[temp_index].file_name, config.jpeg_file_quality );
temp_write_index = MOD_ADD( temp_write_index, 1, temp_image_buffer_count );
memcpy(&(temp_image_buffer[temp_index].timestamp), monitor->image_buffer[index].timestamp, sizeof(temp_image_buffer[0].timestamp));
monitor->image_buffer[index].image->WriteJpeg(temp_image_buffer[temp_index].file_name, config.jpeg_file_quality);
temp_write_index = MOD_ADD(temp_write_index, 1, temp_image_buffer_count);
if ( temp_write_index == temp_read_index ) {
// Go back to live viewing
Warning( "Exceeded temporary buffer, resuming live play" );
Warning("Exceeded temporary buffer, resuming live play");
paused = false;
delayed = false;
replay_rate = ZM_RATE_BASE;
}
} else {
Warning( "Unable to store frame as timestamp invalid" );
Warning("Unable to store frame as timestamp invalid");
}
} else {
Warning( "Unable to store frame as shared memory invalid" );
Warning("Unable to store frame as shared memory invalid");
}
} // end if buffered playback
frame_count++;
} else {
Debug(3, "Waiting for capture last_write_index=%u", monitor->shared_data->last_write_index);
} // end if ( (unsigned int)last_read_index != monitor->shared_data->last_write_index )
} // end if ( (unsigned int)last_read_index != monitor->shared_data->last_write_index )
unsigned long sleep_time = (unsigned long)((1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2)));
Debug(3, "Sleeping for (%d)", sleep_time);
@ -755,10 +768,10 @@ void MonitorStream::runStream() {
break;
}
}
if ( ! last_frame_sent ) {
if ( !last_frame_sent ) {
// If we didn't capture above, because frame_mod was bad? Then last_frame_sent will not have a value.
last_frame_sent = now.tv_sec;
Warning("no last_frame_sent. Shouldn't happen. frame_mod was (%d) frame_count (%d) ",
Warning("no last_frame_sent. Shouldn't happen. frame_mod was (%d) frame_count (%d)",
frame_mod, frame_count);
} else if (
(!paused)
@ -799,9 +812,9 @@ void MonitorStream::runStream() {
}
}
}
globfree( &pglob );
globfree(&pglob);
if ( rmdir(swap_path.c_str()) < 0 ) {
Error( "Can't rmdir '%s': %s", swap_path.c_str(), strerror(errno) );
Error("Can't rmdir '%s': %s", swap_path.c_str(), strerror(errno));
}
} // end if checking for swap_path
} // end if buffered_playback
@ -809,7 +822,7 @@ void MonitorStream::runStream() {
closeComms();
} // end MonitorStream::runStream
void MonitorStream::SingleImage( int scale ) {
void MonitorStream::SingleImage(int scale) {
int img_buffer_size = 0;
static JOCTET img_buffer[ZM_MAX_IMAGE_SIZE];
Image scaled_image;
@ -817,42 +830,45 @@ void MonitorStream::SingleImage( int scale ) {
Image *snap_image = snap->image;
if ( scale != ZM_SCALE_BASE ) {
scaled_image.Assign( *snap_image );
scaled_image.Scale( scale );
scaled_image.Assign(*snap_image);
scaled_image.Scale(scale);
snap_image = &scaled_image;
}
if ( !config.timestamp_on_capture ) {
monitor->TimestampImage( snap_image, snap->timestamp );
monitor->TimestampImage(snap_image, snap->timestamp);
}
snap_image->EncodeJpeg( img_buffer, &img_buffer_size );
fprintf( stdout, "Content-Length: %d\r\n", img_buffer_size );
fprintf( stdout, "Content-Type: image/jpeg\r\n\r\n" );
fwrite( img_buffer, img_buffer_size, 1, stdout );
snap_image->EncodeJpeg(img_buffer, &img_buffer_size);
fprintf(stdout,
"Content-Length: %d\r\n"
"Content-Type: image/jpeg\r\n\r\n",
img_buffer_size);
fwrite(img_buffer, img_buffer_size, 1, stdout);
}
void MonitorStream::SingleImageRaw( int scale ) {
void MonitorStream::SingleImageRaw(int scale) {
Image scaled_image;
Monitor::Snapshot *snap = monitor->getSnapshot();
Image *snap_image = snap->image;
if ( scale != ZM_SCALE_BASE ) {
scaled_image.Assign( *snap_image );
scaled_image.Scale( scale );
scaled_image.Assign(*snap_image);
scaled_image.Scale(scale);
snap_image = &scaled_image;
}
if ( !config.timestamp_on_capture ) {
monitor->TimestampImage( snap_image, snap->timestamp );
monitor->TimestampImage(snap_image, snap->timestamp);
}
fprintf( stdout, "Content-Length: %d\r\n", snap_image->Size() );
fprintf( stdout, "Content-Type: image/x-rgb\r\n\r\n" );
fwrite( snap_image->Buffer(), snap_image->Size(), 1, stdout );
fprintf(stdout,
"Content-Length: %d\r\n"
"Content-Type: image/x-rgb\r\n\r\n",
snap_image->Size());
fwrite(snap_image->Buffer(), snap_image->Size(), 1, stdout);
}
#ifdef HAVE_ZLIB_H
void MonitorStream::SingleImageZip( int scale ) {
void MonitorStream::SingleImageZip(int scale) {
unsigned long img_buffer_size = 0;
static Bytef img_buffer[ZM_MAX_IMAGE_SIZE];
Image scaled_image;
@ -861,17 +877,19 @@ void MonitorStream::SingleImageZip( int scale ) {
Image *snap_image = snap->image;
if ( scale != ZM_SCALE_BASE ) {
scaled_image.Assign( *snap_image );
scaled_image.Scale( scale );
scaled_image.Assign(*snap_image);
scaled_image.Scale(scale);
snap_image = &scaled_image;
}
if ( !config.timestamp_on_capture ) {
monitor->TimestampImage( snap_image, snap->timestamp );
monitor->TimestampImage(snap_image, snap->timestamp);
}
snap_image->Zip( img_buffer, &img_buffer_size );
fprintf( stdout, "Content-Length: %ld\r\n", img_buffer_size );
fprintf( stdout, "Content-Type: image/x-rgbz\r\n\r\n" );
fwrite( img_buffer, img_buffer_size, 1, stdout );
snap_image->Zip(img_buffer, &img_buffer_size);
fprintf(stdout,
"Content-Length: %ld\r\n"
"Content-Type: image/x-rgbz\r\n\r\n",
img_buffer_size);
fwrite(img_buffer, img_buffer_size, 1, stdout);
}
#endif // HAVE_ZLIB_H

View File

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

View File

@ -1,5 +1,10 @@
#!/bin/bash
# We don't deploy during eslint checks, so exit immediately
if [ "${DIST}" == "eslint" ]; then
exit 0
fi
# Check to see if this script has access to all the commands it needs
for CMD in sshfs rsync find fusermount mkdir; do
type $CMD 2>&1 > /dev/null
@ -12,53 +17,26 @@ for CMD in sshfs rsync find fusermount mkdir; do
fi
done
# We only want to deploy packages during cron events
# See https://docs.travis-ci.com/user/cron-jobs/
if [ "${TRAVIS_EVENT_TYPE}" == "cron" ] || [ "${OS}" == "debian" ] || [ "${OS}" == "ubuntu" ]; then
if [ "${OS}" == "debian" ] || [ "${OS}" == "ubuntu" ]; then
targetfolder="debian/master/mini-dinstall/incoming"
else
targetfolder="travis"
fi
echo
echo "Target subfolder set to $targetfolder"
echo
if [ "${USE_SFTP}" == "yes" ]; then
echo "Running \$(rsync -v -e 'ssh -vvv' build/* zmrepo@zmrepo.zoneminder.com:${targetfolder}/ 2>&1)"
rsync -v -e 'ssh -vvv' build/* zmrepo@zmrepo.zoneminder.com:${targetfolder}/ 2>&1
if [ $? -eq 0 ]; then
echo
echo "Files copied successfully."
echo
else
echo
echo "ERROR: Attempt to rsync to zmrepo.zoneminder.com failed!"
echo
exit 99
fi
else
mkdir -p ./zmrepo
ssh_mntchk="$(sshfs zmrepo@zmrepo.zoneminder.com:./ ./zmrepo -o workaround=rename,reconnect 2>&1)"
if [ -z "$ssh_mntchk" ]; then
echo
echo "Remote filesystem mounted successfully."
echo "Begin transfering files..."
echo
# Don't keep packages older than 5 days
find ./zmrepo/$targetfolder/ -maxdepth 1 -type f,l -mtime +5 -delete
rsync -vzlh --ignore-errors build/* zmrepo/$targetfolder/
fusermount -zu zmrepo
else
echo
echo "ERROR: Attempt to mount zmrepo.zoneminder.com failed!"
echo "sshfs gave the following error message:"
echo \"$ssh_mntchk\"
echo
exit 99
fi
fi
if [ "${OS}" == "debian" ] || [ "${OS}" == "ubuntu" ] || [ "${OS}" == "raspbian" ]; then
targetfolder="debian/master/mini-dinstall/incoming"
else
targetfolder="travis"
fi
echo
echo "Target subfolder set to $targetfolder"
echo
echo "Running \$(rsync -v -e 'ssh -vvv' build/*.{rpm,deb,dsc,tar.xz,buildinfo,changes} zmrepo@zmrepo.zoneminder.com:${targetfolder}/ 2>&1)"
rsync -v --ignore-missing-args --exclude 'external-repo.noarch.rpm' -e 'ssh -vvv' build/*.{rpm,deb,dsc,tar.xz,changes} zmrepo@zmrepo.zoneminder.com:${targetfolder}/ 2>&1
if [ "$?" -eq 0 ]; then
echo
echo "Files copied successfully."
echo
else
echo
echo "ERROR: Attempt to rsync to zmrepo.zoneminder.com failed!"
echo "See log output for details."
echo
exit 99
fi

View File

@ -9,7 +9,7 @@
# General sanity checks
checksanity () {
# Check to see if this script has access to all the commands it needs
for CMD in set echo curl git ln mkdir rmdir cat patch; do
for CMD in set echo curl git ln mkdir rmdir cat patch sed; do
type $CMD 2>&1 > /dev/null
if [ $? -ne 0 ]; then
@ -30,7 +30,7 @@ checksanity () {
ARCH="x86_64"
fi
if [[ "${ARCH}" != "x86_64" && "${ARCH}" != "i386" && "${ARCH}" != "armhf" ]]; then
if [[ "${ARCH}" != "x86_64" && "${ARCH}" != "i386" && "${ARCH}" != "armhf" && "${ARCH}" != "aarch64" ]]; then
echo
echo "ERROR: Unsupported architecture specified \"${ARCH}\"."
echo
@ -150,7 +150,7 @@ install_deb () {
exit 1
fi
# Install and test the zoneminder package (only) for Ubuntu Trusty
# Install and test the zoneminder package (only) for Ubuntu Xenial
pkgname="build/zoneminder_${VERSION}-${RELEASE}_amd64.deb"
if [ -e $pkgname ]; then
@ -275,6 +275,8 @@ checkdeploytarget () {
echo "*** TRACEROUTE ***"
echo
traceroute -w 2 -m 15 ${DEPLOYTARGET}
exit 97
fi
}
@ -291,43 +293,43 @@ if [ "${TRAVIS}" == "true" ]; then
fi
checksanity
# We don't want to build packages for all supported distros after every commit
# Only build all packages when executed via cron
# See https://docs.travis-ci.com/user/cron-jobs/
# Steps common to Redhat distros
if [ "${OS}" == "el" ] || [ "${OS}" == "fedora" ]; then
if [ "${TRAVIS_EVENT_TYPE}" == "cron" ] || [ "${TRAVIS}" != "true" ]; then
commonprep
echo "Begin Redhat build..."
commonprep
echo "Begin Redhat build..."
setrpmpkgname
# Newer Redhat distros use dnf package manager rather than yum
if [ "${DIST}" -gt "7" ]; then
sed -i 's\yum\dnf\' utils/packpack/redhat_package.mk
fi
ln -sfT distros/redhat rpm
setrpmpkgname
# The rpm specfile requires the Crud submodule folder to be empty
rm -rf web/api/app/Plugin/Crud
mkdir web/api/app/Plugin/Crud
ln -sfT distros/redhat rpm
reporpm="rpmfusion-free-release"
dlurl="https://download1.rpmfusion.org/free/${OS}/${reporpm}-${DIST}.noarch.rpm"
# The rpm specfile requires the Crud submodule folder to be empty
rm -rf web/api/app/Plugin/Crud
mkdir web/api/app/Plugin/Crud
# Give our downloaded repo rpm a common name so redhat_package.mk can find it
if [ -n "$dlurl" ] && [ $? -eq 0 ]; then
echo "Retrieving ${reporpm} repo rpm..."
curl $dlurl > build/external-repo.noarch.rpm
else
echo "ERROR: Failed to retrieve ${reporpm} repo rpm..."
echo "Download url was: $dlurl"
exit 1
fi
reporpm="rpmfusion-free-release"
dlurl="https://download1.rpmfusion.org/free/${OS}/${reporpm}-${DIST}.noarch.rpm"
setrpmchangelog
# Give our downloaded repo rpm a common name so redhat_package.mk can find it
if [ -n "$dlurl" ] && [ $? -eq 0 ]; then
echo "Retrieving ${reporpm} repo rpm..."
curl $dlurl > build/external-repo.noarch.rpm
else
echo "ERROR: Failed to retrieve ${reporpm} repo rpm..."
echo "Download url was: $dlurl"
exit 1
fi
echo "Starting packpack..."
execpackpack
fi;
# Steps common to Debian based distros
setrpmchangelog
echo "Starting packpack..."
execpackpack
# Steps common to Debian based distros
elif [ "${OS}" == "debian" ] || [ "${OS}" == "ubuntu" ] || [ "${OS}" == "raspbian" ]; then
commonprep
echo "Begin ${OS} ${DIST} build..."
@ -348,14 +350,27 @@ elif [ "${OS}" == "debian" ] || [ "${OS}" == "ubuntu" ] || [ "${OS}" == "raspbia
echo "Starting packpack..."
execpackpack
# We were not triggered via cron so just build and test trusty
if [ "${OS}" == "ubuntu" ] && [ "${DIST}" == "xenial" ] && [ "${ARCH}" == "x86_64" ]; then
# If we are running inside Travis then attempt to install the deb we just built
if [ "${TRAVIS}" == "true" ]; then
# Try to install and run the newly built zoneminder package
if [ "${OS}" == "ubuntu" ] && [ "${DIST}" == "xenial" ] && [ "${ARCH}" == "x86_64" ] && [ "${TRAVIS}" == "true" ]; then
echo "Begin Deb package installation..."
install_deb
fi
fi
# Steps common to eslint checks
elif [ "${OS}" == "eslint" ] || [ "${DIST}" == "eslint" ]; then
# Check we've got npm installed
type npm 2>&1 > /dev/null
if [ $? -ne 0 ]; then
echo
echo "ERROR: The script cannot find the required command \"npm\"."
echo
exit 1
fi
npm install -g eslint@5.12.0 eslint-config-google@0.11.0 eslint-plugin-html@5.0.0 eslint-plugin-php-markup@0.2.5
echo "Begin eslint checks..."
eslint --ext .php,.js .
fi
exit 0

View File

@ -1 +1 @@
1.33.15
1.33.16

View File

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

View File

@ -83,8 +83,8 @@ $statusData = array(
'MinEventId' => array( 'sql' => '(SELECT min(Events.Id) FROM Events WHERE Events.MonitorId = Monitors.Id' ),
'MaxEventId' => array( 'sql' => '(SELECT max(Events.Id) FROM Events WHERE Events.MonitorId = Monitors.Id' ),
'TotalEvents' => array( 'sql' => '(SELECT count(Events.Id) FROM Events WHERE Events.MonitorId = Monitors.Id' ),
'Status' => array( 'zmu' => '-m '.escapeshellarg($_REQUEST['id'][0]).' -s' ),
'FrameRate' => array( 'zmu' => '-m '.escapeshellarg($_REQUEST['id'][0]).' -f' ),
'Status' => (isset($_REQUEST['id'])?array( 'zmu' => '-m '.escapeshellarg($_REQUEST['id'][0]).' -s' ):null),
'FrameRate' => (isset($_REQUEST['id'])?array( 'zmu' => '-m '.escapeshellarg($_REQUEST['id'][0]).' -f' ):null),
),
),
'events' => array(
@ -204,6 +204,7 @@ function collectData() {
$fieldSql = array();
$joinSql = array();
$groupSql = array();
$values = array();
$elements = &$entitySpec['elements'];
$lc_elements = array_change_key_case( $elements );
@ -258,7 +259,6 @@ function collectData() {
if ( $id && !empty($entitySpec['selector']) ) {
$index = 0;
$where = array();
$values = array();
foreach( $entitySpec['selector'] as $selIndex => $selector ) {
$selectorParamName = ':selector' . $selIndex;
if ( is_array( $selector ) ) {

View File

@ -119,13 +119,11 @@ if ( sem_acquire($semaphore,1) !== false ) {
switch ( $data['type'] ) {
case MSG_DATA_WATCH :
$data = unpack('ltype/imonitor/istate/dfps/ilevel/irate/ddelay/izoom/Cdelayed/Cpaused/Cenabled/Cforced', $msg);
ZM\Logger::Debug('FPS: ' . $data['fps']);
$data['fps'] = round( $data['fps'], 2 );
ZM\Logger::Debug('FPS: ' . $data['fps'] );
$data['rate'] /= RATE_BASE;
$data['delay'] = round( $data['delay'], 2 );
$data['zoom'] = round( $data['zoom']/SCALE_BASE, 1 );
if ( ZM_OPT_USE_AUTH && ZM_AUTH_RELAY == 'hashed' ) {
if ( ZM_OPT_USE_AUTH && (ZM_AUTH_RELAY == 'hashed') ) {
$time = time();
// Regenerate auth hash after half the lifetime of the hash
if ( (!isset($_SESSION['AuthHashGeneratedAt'])) or ( $_SESSION['AuthHashGeneratedAt'] < $time - (ZM_AUTH_HASH_TTL * 1800) ) ) {
@ -144,7 +142,7 @@ if ( sem_acquire($semaphore,1) !== false ) {
}
$data['rate'] /= RATE_BASE;
$data['zoom'] = round( $data['zoom']/SCALE_BASE, 1 );
if ( ZM_OPT_USE_AUTH && ZM_AUTH_RELAY == 'hashed' ) {
if ( ZM_OPT_USE_AUTH && (ZM_AUTH_RELAY == 'hashed') ) {
$time = time();
// Regenerate auth hash after half the lifetime of the hash
if ( (!isset($_SESSION['AuthHashGeneratedAt'])) or ( $_SESSION['AuthHashGeneratedAt'] < $time - (ZM_AUTH_HASH_TTL * 1800) ) ) {

View File

@ -77,16 +77,24 @@ class GroupsController extends AppController {
}
$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(
__('The group has been saved.'),
array('action' => 'index')
);
}
}
$monitors = $this->Group->Monitor->find('list');
} else {
ZM\Error("Failed to save Group");
debug($this->Group->invalidFields());
}
} # end if post
$monitors = $this->Group->Monitor->find('list');
$this->set(compact('monitors'));
}
} # end add
/**
* edit method

View File

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

View File

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

View File

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

View File

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

View File

@ -51,10 +51,10 @@ class Event extends ZM_Object {
if ( $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'} )
$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);
}
return $this->{'Storage'};
@ -64,10 +64,10 @@ class Event extends ZM_Object {
if ( $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'} )
$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);
}
return $this->{'SecondaryStorage'};
@ -262,7 +262,7 @@ class Event extends ZM_Object {
if ( is_null($new) or ( $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());
dbQuery('UPDATE Events SET DiskSpace=? WHERE Id=?', array($this->{'DiskSpace'}, $this->{'Id'}));
}
@ -298,7 +298,7 @@ class Event extends ZM_Object {
} // end function createListThumbnail
function ThumbnailWidth( ) {
if ( ! ( array_key_exists('ThumbnailWidth', $this) ) ) {
if ( ! ( property_exists($this, 'ThumbnailWidth') ) ) {
if ( ZM_WEB_LIST_THUMB_WIDTH ) {
$this->{'ThumbnailWidth'} = ZM_WEB_LIST_THUMB_WIDTH;
$scale = (SCALE_BASE*ZM_WEB_LIST_THUMB_WIDTH)/$this->{'Width'};
@ -315,7 +315,7 @@ class Event extends ZM_Object {
} // end function ThumbnailWidth
function ThumbnailHeight( ) {
if ( ! ( array_key_exists('ThumbnailHeight', $this) ) ) {
if ( ! ( property_exists($this, 'ThumbnailHeight') ) ) {
if ( ZM_WEB_LIST_THUMB_WIDTH ) {
$this->{'ThumbnailWidth'} = ZM_WEB_LIST_THUMB_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_json'} = jsonEncode($this->{'Query'});
}
if ( !array_key_exists('Query', $this) ) {
if ( array_key_exists('Query_json', $this) and $this->{'Query_json'} ) {
if ( !property_exists($this, 'Query') ) {
if ( property_exists($this, 'Query_json') and $this->{'Query_json'} ) {
$this->{'Query'} = jsonDecode($this->{'Query_json'});
} else {
$this->{'Query'} = array();

View File

@ -18,7 +18,7 @@ class Group extends ZM_Object {
}
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('UPDATE Groups SET ParentId=NULL WHERE ParentId=?', array($this->{'Id'}));
dbQuery('DELETE FROM Groups WHERE Id=?', array($this->{'Id'}));
@ -35,7 +35,7 @@ class Group extends ZM_Object {
if ( isset($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;
if ( $this->{'ParentId'} != null ) {
$Parent = Group::find_one(array('Id'=>$this->{'ParentId'}));
@ -46,7 +46,7 @@ class Group extends ZM_Object {
} // end public function depth
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'}));
}
return $this->{'MonitorIds'};

View File

@ -9,125 +9,126 @@ require_once('Storage.php');
class Monitor extends ZM_Object {
protected static $table = 'Monitors';
protected $defaults = array(
'Id' => null,
'Name' => '',
'ServerId' => 0,
'StorageId' => 0,
'Type' => 'Ffmpeg',
'Function' => 'Mocord',
'Enabled' => array('type'=>'boolean','default'=>1),
'LinkedMonitors' => array('type'=>'set', 'default'=>null),
'Triggers' => array('type'=>'set','default'=>''),
'Device' => '',
'Channel' => 0,
'Format' => '0',
'V4LMultiBuffer' => null,
'V4LCapturesPerFrame' => 1,
'Protocol' => null,
'Method' => '',
'Host' => null,
'Port' => '',
'SubPath' => '',
'Path' => null,
'Options' => null,
'User' => null,
'Pass' => null,
// These are NOT NULL default 0 in the db, but 0 is not a valid value. FIXME
'Width' => null,
'Height' => null,
'Colours' => 4,
'Palette' => '0',
'Orientation' => null,
'Deinterlacing' => 0,
'DecoderHWAccelName' => null,
'DecoderHWAccelDevice' => null,
'SaveJPEGs' => 3,
'VideoWriter' => '0',
'OutputCodec' => null,
'OutputContainer' => 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",
'RecordAudio' => array('type'=>'boolean', 'default'=>0),
'RTSPDescribe' => array('type'=>'boolean','default'=>0),
'Brightness' => -1,
'Contrast' => -1,
'Hue' => -1,
'Colour' => -1,
'EventPrefix' => 'Event-',
'LabelFormat' => '%N - %d/%m/%y %H:%M:%S',
'LabelX' => 0,
'LabelY' => 0,
'LabelSize' => 1,
'ImageBufferCount' => 100,
'WarmupCount' => 0,
'PreEventCount' => 0,
'PostEventCount' => 0,
'StreamReplayBuffer' => 0,
'AlarmFrameCount' => 1,
'SectionLength' => 600,
'MinSectionLength' => 10,
'FrameSkip' => 0,
'MotionFrameSkip' => 0,
'AnalysisFPSLimit' => null,
'AnalysisUpdateDelay' => 0,
'MaxFPS' => null,
'AlarmMaxFPS' => null,
'FPSReportInterval' => 100,
'RefBlendPerc' => 6,
'AlarmRefBlendPerc' => 6,
'Controllable' => array('type'=>'boolean','default'=>0),
'ControlId' => null,
'ControlDevice' => null,
'ControlAddress' => null,
'AutoStopTimeout' => null,
'TrackMotion' => array('type'=>'boolean','default'=>0),
'TrackDelay' => null,
'ReturnLocation' => -1,
'ReturnDelay' => null,
'DefaultRate' => 100,
'DefaultScale' => 100,
'SignalCheckPoints' => 0,
'SignalCheckColour' => '#0000BE',
'WebColour' => 'red',
'Exif' => array('type'=>'boolean','default'=>0),
'Sequence' => null,
'TotalEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'TotalEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'HourEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'HourEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'DayEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'DayEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'WeekEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'WeekEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'MonthEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'MonthEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'ArchivedEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'ArchivedEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'ZoneCount' => 0,
'Refresh' => null,
'DefaultCodec' => 'auto',
'GroupIds' => array('default'=>array(), 'do_not_update'=>1),
);
private $status_fields = array(
'Status' => null,
'AnalysisFPS' => null,
'CaptureFPS' => null,
'CaptureBandwidth' => null,
);
protected $defaults = array(
'Id' => null,
'Name' => '',
'Notes' => '',
'ServerId' => 0,
'StorageId' => 0,
'Type' => 'Ffmpeg',
'Function' => 'Mocord',
'Enabled' => array('type'=>'boolean','default'=>1),
'LinkedMonitors' => array('type'=>'set', 'default'=>null),
'Triggers' => array('type'=>'set','default'=>''),
'Device' => '',
'Channel' => 0,
'Format' => '0',
'V4LMultiBuffer' => null,
'V4LCapturesPerFrame' => 1,
'Protocol' => null,
'Method' => '',
'Host' => null,
'Port' => '',
'SubPath' => '',
'Path' => null,
'Options' => null,
'User' => null,
'Pass' => null,
// These are NOT NULL default 0 in the db, but 0 is not a valid value. FIXME
'Width' => null,
'Height' => null,
'Colours' => 4,
'Palette' => '0',
'Orientation' => null,
'Deinterlacing' => 0,
'DecoderHWAccelName' => null,
'DecoderHWAccelDevice' => null,
'SaveJPEGs' => 3,
'VideoWriter' => '0',
'OutputCodec' => null,
'OutputContainer' => 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",
'RecordAudio' => array('type'=>'boolean', 'default'=>0),
'RTSPDescribe' => array('type'=>'boolean','default'=>0),
'Brightness' => -1,
'Contrast' => -1,
'Hue' => -1,
'Colour' => -1,
'EventPrefix' => 'Event-',
'LabelFormat' => '%N - %d/%m/%y %H:%M:%S',
'LabelX' => 0,
'LabelY' => 0,
'LabelSize' => 1,
'ImageBufferCount' => 20,
'WarmupCount' => 0,
'PreEventCount' => 5,
'PostEventCount' => 5,
'StreamReplayBuffer' => 0,
'AlarmFrameCount' => 1,
'SectionLength' => 600,
'MinSectionLength' => 10,
'FrameSkip' => 0,
'MotionFrameSkip' => 0,
'AnalysisFPSLimit' => null,
'AnalysisUpdateDelay' => 0,
'MaxFPS' => null,
'AlarmMaxFPS' => null,
'FPSReportInterval' => 100,
'RefBlendPerc' => 6,
'AlarmRefBlendPerc' => 6,
'Controllable' => array('type'=>'boolean','default'=>0),
'ControlId' => null,
'ControlDevice' => null,
'ControlAddress' => null,
'AutoStopTimeout' => null,
'TrackMotion' => array('type'=>'boolean','default'=>0),
'TrackDelay' => null,
'ReturnLocation' => -1,
'ReturnDelay' => null,
'DefaultRate' => 100,
'DefaultScale' => 100,
'SignalCheckPoints' => 0,
'SignalCheckColour' => '#0000BE',
'WebColour' => '#ff0000',
'Exif' => array('type'=>'boolean','default'=>0),
'Sequence' => null,
'TotalEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'TotalEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'HourEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'HourEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'DayEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'DayEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'WeekEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'WeekEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'MonthEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'MonthEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'ArchivedEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'ArchivedEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'ZoneCount' => 0,
'Refresh' => null,
'DefaultCodec' => 'auto',
'GroupIds' => array('default'=>array(), 'do_not_update'=>1),
);
private $status_fields = array(
'Status' => null,
'AnalysisFPS' => null,
'CaptureFPS' => null,
'CaptureBandwidth' => null,
);
public function Control() {
if ( !array_key_exists('Control', $this) ) {
if ( !property_exists($this, 'Control') ) {
if ( $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();
}
return $this->{'Control'};
}
public function Server() {
return new Server($this->{'ServerId'});
return Server::find_one(array('Id'=>$this->{'ServerId'}));
}
public function __call($fn, array $args){
@ -138,7 +139,7 @@ private $status_fields = array(
$this->{$fn} = $args[0];
}
}
if ( array_key_exists($fn, $this) ) {
if ( property_exists($this, $fn) ) {
return $this->{$fn};
} else if ( array_key_exists($fn, $this->defaults) ) {
if ( is_array($this->defaults[$fn]) ) {
@ -211,9 +212,9 @@ private $status_fields = array(
$this->{'Width'} = $new;
$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->defaults{$field};
return $this->defaults[$field];
} // end function Width
public function ViewHeight($new=null) {
@ -221,9 +222,9 @@ private $status_fields = array(
$this->{'Height'} = $new;
$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->defaults{$field};
return $this->defaults[$field];
} // end function Height
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).
// 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->defaults{$field};
return $this->defaults[$field];
} // end function SignalCheckColour
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');
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' ) {
$zmcArgs = '-d '.$this->{'Device'};
} else {
@ -306,7 +307,7 @@ private $status_fields = array(
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 ( ZM_OPT_CONTROL ) {
daemonControl('stop', 'zmtrack.pl', '-m '.$this->{'Id'});
@ -367,8 +368,8 @@ private $status_fields = array(
}
}
if ( !array_key_exists('GroupIds', $this) ) {
if ( array_key_exists('Id', $this) and $this->{'Id'} ) {
if ( !property_exists($this, 'GroupIds') ) {
if ( property_exists($this, 'Id') and $this->{'Id'} ) {
$this->{'GroupIds'} = dbFetchAll('SELECT `GroupId` FROM `Groups_Monitors` WHERE `MonitorId`=?', 'GroupId', array($this->{'Id'}) );
if ( ! $this->{'GroupIds'} )
$this->{'GroupIds'} = array();
@ -417,7 +418,7 @@ private $status_fields = array(
if ( $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'}) ?
Storage::find_one(array('Id'=>$this->{'StorageId'})) :
new Storage(NULL);
@ -467,58 +468,58 @@ private $status_fields = array(
return $source;
} // end function Source
public function UrlToIndex() {
return $this->Server()->UrlToIndex();
public function UrlToIndex($port=null) {
return $this->Server()->UrlToIndex($port);
//ZM_MIN_STREAMING_PORT ? (ZM_MIN_STREAMING_PORT+$this->Id()) : null);
}
public function sendControlCommand($command) {
// command is generally a command option list like --command=blah but might be just the word quit
public function sendControlCommand($command) {
// command is generally a command option list like --command=blah but might be just the word quit
$options = array();
# Convert from a command line params to an option array
foreach ( explode(' ', $command) as $option ) {
if ( preg_match('/--([^=]+)(?:=(.+))?/', $option, $matches) ) {
$options[$matches[1]] = $matches[2]?$matches[2]:1;
} else if ( $option != '' and $option != 'quit' ) {
Warning("Ignored command for zmcontrol $option in $command");
}
}
if ( !count($options) ) {
if ( $command == 'quit' ) {
$options['command'] = 'quit';
} else {
Warning("No commands to send to zmcontrol from $command");
return false;
}
}
if ( (!defined('ZM_SERVER_ID')) or ( 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;
$options = array();
# Convert from a command line params to an option array
foreach ( explode(' ', $command) as $option ) {
if ( preg_match('/--([^=]+)(?:=(.+))?/', $option, $matches) ) {
$options[$matches[1]] = $matches[2]?$matches[2]:1;
} else if ( $option != '' and $option != 'quit' ) {
Warning("Ignored command for zmcontrol $option in $command");
}
} else if ( $command != 'quit' ) {
$command = ZM_PATH_BIN.'/zmcontrol.pl '.$command.' --id='.$this->{'Id'};
// Can't connect so use script
$ctrlOutput = exec(escapeshellcmd($command));
}
socket_close($socket);
} else if ( $this->ServerId() ) {
if ( !count($options) ) {
if ( $command == 'quit' ) {
$options['command'] = 'quit';
} else {
Warning("No commands to send to zmcontrol from $command");
return false;
}
}
if ( (!defined('ZM_SERVER_ID')) or ( property_exists($this, 'ServerId') and (ZM_SERVER_ID==$this->{'ServerId'}) ) ) {
# Local
Logger::Debug('Trying to send options ' . print_r($options, true));
$optionString = jsonEncode($options);
Logger::Debug("Trying to send options $optionString");
// Either connects to running zmcontrol.pl or runs zmcontrol.pl to send the command.
$socket = socket_create(AF_UNIX, SOCK_STREAM, 0);
if ( $socket < 0 ) {
Error('socket_create() failed: '.socket_strerror($socket));
return false;
}
$sockFile = ZM_PATH_SOCKS.'/zmcontrol-'.$this->{'Id'}.'.sock';
if ( @socket_connect($socket, $sockFile) ) {
if ( !socket_write($socket, $optionString) ) {
Error('Can\'t write to control socket: '.socket_strerror(socket_last_error($socket)));
return false;
}
} else if ( $command != 'quit' ) {
$command = ZM_PATH_BIN.'/zmcontrol.pl '.$command.' --id='.$this->{'Id'};
// Can't connect so use script
$ctrlOutput = exec(escapeshellcmd($command));
}
socket_close($socket);
} else if ( $this->ServerId() ) {
$Server = $this->Server();
$url = ZM_BASE_PROTOCOL . '://'.$Server->Hostname().'/zm/api/monitors/daemonControl/'.$this->{'Id'}.'/'.$mode.'/zmcontrol.json';
@ -543,7 +544,7 @@ public function sendControlCommand($command) {
}
} catch ( Exception $e ) {
Error("Except $e thrown trying to restart zma");
return false;
return false;
}
} else {
Error('Server not assigned to Monitor in a multi-server setup. Please assign a server to the Monitor.');

View File

@ -1,133 +1,22 @@
<?php
namespace ZM;
require_once('Object.php');
require_once('database.php');
class MontageLayout {
private $defaults = array(
class MontageLayout extends ZM_Object {
protected static $table = 'MontageLayouts';
protected $defaults = array(
'Id' => null,
'Name' => '',
'Positions' => 0,
);
public function __construct( $IdOrRow = NULL ) {
if ( $IdOrRow ) {
$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 static function find( $parameters = array(), $options = array() ) {
return ZM_Object::_find(get_class(), $parameters, $options);
}
public function set( $data ) {
foreach ($data as $k => $v) {
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_one( $parameters = array(), $options = array() ) {
return ZM_Object::_find_one(get_class(), $parameters, $options);
}
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
?>

View File

@ -45,7 +45,7 @@ class ZM_Object {
$this->{$fn} = $args[0];
}
if ( array_key_exists($fn, $this) ) {
if ( property_exists($this, $fn) ) {
return $this->{$fn};
} else {
if ( array_key_exists($fn, $this->defaults) ) {
@ -110,8 +110,9 @@ class ZM_Object {
public static function _find_one($class, $parameters = array(), $options = array() ) {
global $object_cache;
if ( ! isset($object_cache[$class]) )
if ( ! isset($object_cache[$class]) ) {
$object_cache[$class] = array();
}
$cache = &$object_cache[$class];
if (
( count($parameters) == 1 ) and
@ -140,10 +141,10 @@ class ZM_Object {
foreach ($this->defaults as $key => $value) {
if ( is_callable(array($this, $key)) ) {
$json[$key] = $this->$key();
} else if ( array_key_exists($key, $this) ) {
} else if ( property_exists($this, $key) ) {
$json[$key] = $this->{$key};
} else {
$json[$key] = $this->defaults{$key};
$json[$key] = $this->defaults[$key];
}
}
return json_encode($json);
@ -158,14 +159,24 @@ class ZM_Object {
# perhaps should turn into a comma-separated string
$this->{$k} = implode(',', $v);
} else if ( is_string($v) ) {
if ( $v == '' and array_key_exists($k, $this->defaults) ) {
if ( is_array($this->defaults[$k]) )
if ( 0 ) {
# 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'];
else
$this->{$k} = $this->defaults[$k];
} else {
$this->{$k} = trim($v);
} else {
$this->{$k} = $this->defaults[$k];
Logger::Debug("$k => Have default for $v: " . $this->{$k});
}
} else {
$this->{$k} = trim($v);
}
} else {
$this->{$k} = trim($v);
}
} else if ( is_integer($v) ) {
$this->{$k} = $v;
} else if ( is_bool($v) ) {
@ -215,7 +226,7 @@ class ZM_Object {
} else if ( $this->$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';
Logger::Debug("Checking field $field => current ".
(is_array($this->{$field}) ? implode(',',$this->{$field}) : $this->{$field}) . ' ?= ' .
@ -280,6 +291,18 @@ class ZM_Object {
$this->set($new_values);
}
# Set defaults. Note that we only replace "" with null, not other values
# because for example if we want to clear TimestampFormat, we clear it, but the default is a string value
foreach ( $this->defaults as $field => $default ) {
if ( (!array_key_exists($field, $this)) or ($this->{$field} == '') ) {
if ( is_array($default) ) {
$this->{$field} = $default['default'];
} else if ( $default == null ) {
$this->{$field} = $default;
}
}
}
$fields = array_filter(
$this->defaults,
function($v) {

View File

@ -80,7 +80,7 @@ class Server extends ZM_Object {
public function PathToZMS( $new = null ) {
if ( $new != null )
$this{'PathToZMS'} = $new;
$this->{'PathToZMS'} = $new;
if ( $this->Id() and $this->{'PathToZMS'} ) {
return $this->{'PathToZMS'};
} else {

View File

@ -80,7 +80,7 @@ class Storage extends ZM_Object {
}
public function disk_total_space() {
if ( !array_key_exists('disk_total_space', $this) ) {
if ( !property_exists($this, 'disk_total_space') ) {
$path = $this->Path();
if ( file_exists($path) ) {
$this->{'disk_total_space'} = disk_total_space($path);
@ -94,7 +94,7 @@ class Storage extends ZM_Object {
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.
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' ) {
$this->{'disk_used_space'} = $this->event_disk_space();
} else {
@ -112,7 +112,7 @@ class Storage extends ZM_Object {
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.
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()));
do {
@ -130,8 +130,8 @@ class Storage extends ZM_Object {
} // end function event_disk_space
public function Server() {
if ( ! array_key_exists('Server',$this) ) {
if ( array_key_exists('ServerId', $this) ) {
if ( ! property_exists($this, 'Server') ) {
if ( property_exists($this, 'ServerId') ) {
$this->{'Server'} = Server::find_one(array('Id'=>$this->{'ServerId'}));
if ( !$this->{'Server'} ) {

View File

@ -28,6 +28,65 @@ if ( $action == 'controlcap' ) {
require_once('includes/Control.php');
$Control = new ZM\Control( !empty($_REQUEST['cid']) ? $_REQUEST['cid'] : null );
$field_defaults = array(
'CanWake' => 0,
'CanSleep' => 0,
'CanReset' => 0,
'CanReboot' => 0,
'CanMove' => 0,
'CanMoveDiag' => 0,
'CanMoveMap' => 0,
'CanMoveRel' => 0,
'CanMoveAbs' => 0,
'CanMoveCon' => 0,
'CanPan' => 0,
'HasPanSpeed' => 0,
'HasTurboPan' => 0,
'CanTilt' => 0,
'HasTiltSpeed' => 0,
'HasTurboTilt' => 0,
'CanZoom' => 0,
'CanZoomRel' => 0,
'CanZoomAbs' => 0,
'CanZoomCon' => 0,
'HasZoomSpeed' => 0,
'CanFocus' => 0,
'CanAutoFocus' => 0,
'CanFocusRel' => 0,
'CanFocusAbs' => 0,
'CanFocusCon' => 0,
'HasFocusSpeed' => 0,
'CanGain' => 0,
'CanAutoGain' => 0,
'CanGainRel' => 0,
'CanGainAbs' => 0,
'CanGainCon' => 0,
'HasGainSpeed' => 0,
'CanWhite' => 0,
'CanAutoWhite' => 0,
'CanWhiteRel' => 0,
'CanWhiteAbs' => 0,
'CanWhiteCon' => 0,
'HasWhiteSpeed' => 0,
'CanIris' => 0,
'CanAutoIris' => 0,
'CanIrisRel' => 0,
'CanIrisAbs' => 0,
'CanIrisCon' => 0,
'HasIrisSpeed' => 0,
'HasPresets' => 0,
'HasHomePreset' => 0,
'CanSetPresets' => 0,
);
# Checkboxes don't return an element in the POST data, so won't be present in newControl.
# So force a value for these fields
foreach ( $field_defaults as $field => $value ) {
if ( ! (isset($_REQUEST['newControl'][$field]) and $_REQUEST['newControl'][$field]) ) {
$_REQUEST['newControl'][$field] = $value;
}
} # end foreach type
//$changes = getFormChanges( $control, $_REQUEST['newControl'], $types, $columns );
$Control->save($_REQUEST['newControl']);
$refreshParent = true;

View File

@ -39,7 +39,7 @@ if ( $action == 'function' ) {
$oldFunction = $monitor['Function'];
$oldEnabled = $monitor['Enabled'];
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));
$monitor['Function'] = $newFunction;

View File

@ -219,7 +219,6 @@ if ( $action == 'monitor' ) {
} else {
ZM\Error('Error saving new Monitor.');
$error_message = dbError($sql);
return;
}
}

View File

@ -31,19 +31,19 @@ if ( $action == 'state' ) {
}
} else if ( $action == 'save' ) {
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();
foreach( dbFetchAll($sql) as $monitor ) {
foreach ( dbFetchAll($sql) as $monitor ) {
$definitions[] = $monitor['Id'].':'.$monitor['Function'].':'.$monitor['Enabled'];
}
$definition = join(',', $definitions);
if ( $_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' ) {
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 File

@ -220,19 +220,19 @@ function generateAuthHash($useRemoteAddr, $force=false) {
function visibleMonitor($mid) {
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) {
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) {
global $user;
return ( $user[$area] == 'Edit' && ( !$mid || visibleMonitor($mid) ));
return ( $user && ($user[$area] == 'Edit') && ( !$mid || visibleMonitor($mid) ));
}
function userFromSession() {

View File

@ -33,9 +33,9 @@ $configFile = ZM_CONFIG;
$localConfigFile = basename($configFile);
if ( file_exists( $localConfigFile ) && filesize( $localConfigFile ) > 0 ) {
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
error_log( "Warning, overriding installed $localConfigFile file with local copy" );
error_log("Warning, overriding installed $localConfigFile file with local copy");
$configFile = $localConfigFile;
}
@ -49,19 +49,19 @@ if ( is_dir($configSubFolder) ) {
if ( is_readable($configSubFolder) ) {
foreach ( glob("$configSubFolder/*.conf") as $filename ) {
//error_log("processing $filename");
$configvals = array_replace($configvals, process_configfile($filename) );
$configvals = array_replace($configvals, process_configfile($filename));
}
} 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 {
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
# pair in the array as a constant
foreach( $configvals as $key => $value) {
define( $key, $value );
foreach ( $configvals as $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( '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( 'logger.php' );
require_once('database.php');
require_once('logger.php');
loadConfig();
ZM\Logger::fetch()->initialise();
@ -165,28 +165,30 @@ function loadConfig( $defineConsts=true ) {
$result = $dbConn->query('SELECT Name,Value FROM Config');
if ( !$result )
echo mysql_error();
while( $row = dbFetchNext( $result ) ) {
while( $row = dbFetchNext($result) ) {
if ( $defineConsts )
define( $row['Name'], $row['Value'] );
define($row['Name'], $row['Value']);
$config[$row['Name']] = $row;
}
} # 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
if ( ! defined('ZM_SERVER_ID') ) {
require_once('Server.php');
if ( defined('ZM_SERVER_NAME') and ZM_SERVER_NAME ) {
$server_id = dbFetchOne('SELECT Id FROM Servers WHERE Name=?', 'Id', array(ZM_SERVER_NAME));
if ( ! $server_id ) {
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.');
# Use Server lookup so that it caches
$Server = ZM\Server::find_one(array('Name'=>ZM_SERVER_NAME));
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 {
define( 'ZM_SERVER_ID', $server_id );
define('ZM_SERVER_ID', $Server->Id());
}
} else if ( defined('ZM_SERVER_HOST') and ZM_SERVER_HOST ) {
$server_id = dbFetchOne('SELECT Id FROM Servers WHERE Name=?', 'Id', array(ZM_SERVER_HOST));
if ( ! $server_id ) {
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.');
$Server = ZM\Server::find_one(array('Name'=>ZM_SERVER_HOST));
if ( ! $Server ) {
ZM\Error('Invalid Multi-Server configration detected. ZM_SERVER_HOST set to ' . ZM_SERVER_HOST . ' in zm.conf, but no corresponding entry found in Servers table.');
} else {
define( 'ZM_SERVER_ID', $server_id );
define('ZM_SERVER_ID', $Server->Id());
}
}
}
@ -197,21 +199,22 @@ function process_configfile($configFile) {
if ( is_readable( $configFile ) ) {
$configvals = array();
$cfg = fopen( $configFile, 'r') or Error("Could not open config file: $configFile.");
$cfg = fopen($configFile, 'r') or ZM\Error("Could not open config file: $configFile.");
while ( !feof($cfg) ) {
$str = fgets( $cfg, 256 );
if ( preg_match( '/^\s*$/', $str ))
$str = fgets($cfg, 256);
if ( preg_match('/^\s*(#.*)?$/', $str) ) {
continue;
elseif ( preg_match( '/^\s*#/', $str ))
continue;
elseif ( preg_match( '/^\s*([^=\s]+)\s*=\s*[\'"]*(.*?)[\'"]*\s*$/', $str, $matches ))
} else if ( preg_match( '/^\s*([^=\s]+)\s*=\s*[\'"]*(.*?)[\'"]*\s*$/', $str, $matches )) {
$configvals[$matches[1]] = $matches[2];
} else {
ZM\Error("Malformed line in config $configFile\n$str");
}
}
fclose( $cfg );
return( $configvals );
fclose($cfg);
return $configvals;
} else {
error_log( "WARNING: ZoneMinder configuration file found but is not readable. Check file permissions on $configFile." );
return( false );
error_log("WARNING: ZoneMinder configuration file found but is not readable. Check file permissions on $configFile.");
return false;
}
}

View File

@ -110,16 +110,10 @@ function dbError($sql) {
function dbEscape( $string ) {
global $dbConn;
if ( version_compare(phpversion(), '4.3.0', '<'))
if ( get_magic_quotes_gpc() )
return $dbConn->quote(stripslashes($string));
else
return $dbConn->quote($string);
if ( version_compare(phpversion(), '5.4', '<=') and get_magic_quotes_gpc() )
return $dbConn->quote(stripslashes($string));
else
if ( get_magic_quotes_gpc() )
return $dbConn->quote(stripslashes($string));
else
return $dbConn->quote($string);
return $dbConn->quote($string);
}
function dbQuery($sql, $params=NULL) {
@ -212,6 +206,10 @@ function dbFetch($sql, $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) )
return $col ? $dbRow[$col] : $dbRow;
return false;

View File

@ -409,6 +409,11 @@ ZM\Logger::Debug("Event type: " . gettype($event));
global $user;
if ( $event->Archived() ) {
ZM\Info('Cannot delete Archived event.');
return;
} # end if Archived
if ( $user['Events'] == 'Edit' ) {
$event->delete();
} # CAN EDIT
@ -1085,9 +1090,8 @@ function parseFilter(&$filter, $saveToSession=false, $querySep='&amp;') {
$terms = isset($filter['Query']) ? $filter['Query']['terms'] : NULL;
if ( !isset($terms) ) {
$backTrace = debug_backtrace();
$file = $backTrace[1]['file'];
$line = $backTrace[1]['line'];
ZM\Warning("No terms in filter from $file:$line");
ZM\Warning('No terms in filter');
ZM\Warning(print_r($backTrace, true));
ZM\Warning(print_r($filter, true));
}
if ( isset($terms) && count($terms) ) {
@ -1324,7 +1328,7 @@ function parseFilter(&$filter, $saveToSession=false, $querySep='&amp;') {
$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";
}
} // end if ( isset($term['attr']) )
} // end if isset($term['attr'])
if ( isset($term['cbr']) && (string)(int)$term['cbr'] == $term['cbr'] ) {
$filter['query'] .= $querySep.urlencode("filter[Query][terms][$i][cbr]").'='.urlencode($term['cbr']);
$filter['sql'] .= ' '.str_repeat(')', $term['cbr']).' ';
@ -1336,6 +1340,8 @@ function parseFilter(&$filter, $saveToSession=false, $querySep='&amp;') {
if ( $saveToSession ) {
$_SESSION['filter'] = $filter;
}
} else {
$filter['query'] = $querySep.urlencode('filter[Query][terms]=[]');
} // end if terms
#if ( 0 ) {
@ -2580,21 +2586,23 @@ function html_radio($name, $values, $selected=null, $options=array(), $attrs=arr
if ( isset($options['container']) ) {
$html .= $options['container'][0];
}
$attributes = array_map(
function($attr, $value){return $attr.'="'.$value.'"';},
array_keys($attrs),
array_values($attrs)
);
$attributes_string = implode(' ', $attributes);
$html .= sprintf('
<div class="form-check%7$s">
<label class="form-check-label radio%7$s" for="%1$s%6$s%2$s">
<input class="form-check-input" type="radio" name="%1$s" value="%2$s" id="%1$s%6$s%2$s" %4$s%5$s />
%3$s</label></div>
', $name, $value, $label, ($value==$selected?' checked="checked"':''),
implode(' ', array_map(
function($attr, $value){return $attr.'="'.$value.'"';},
array_keys($attrs),
array_values($attrs)
),
),
( isset($options['id']) ? $options['id'] : ''),
( ( (!isset($options['inline'])) or $options['inline'] ) ? '-inline' : ''),
);
$attributes_string,
(isset($options['id']) ? $options['id'] : ''),
( ( (!isset($options['inline'])) or $options['inline'] ) ? '-inline' : '')
);
if ( isset($options['container']) ) {
$html .= $options['container'][1];
}
@ -2602,4 +2610,12 @@ function html_radio($name, $values, $selected=null, $options=array(), $attrs=arr
return $html;
} # end sub html_radio
function random_colour() {
return '#'.
str_pad( dechex( mt_rand( 0, 255 ) ), 2, '0', STR_PAD_LEFT).
str_pad( dechex( mt_rand( 0, 255 ) ), 2, '0', STR_PAD_LEFT).
str_pad( dechex( mt_rand( 0, 255 ) ), 2, '0', STR_PAD_LEFT);
}
?>

View File

@ -274,7 +274,7 @@ class Logger {
}
}
}
return( $this->databaseLevel );
return $this->databaseLevel;
}
public function fileLevel( $fileLevel ) {
@ -288,7 +288,7 @@ class Logger {
$this->openFile();
}
}
return( $this->fileLevel );
return $this->fileLevel;
}
public function weblogLevel( $weblogLevel ) {
@ -303,7 +303,7 @@ class Logger {
$this->weblogLevel = $weblogLevel;
}
}
return( $this->weblogLevel );
return $this->weblogLevel;
}
public function syslogLevel( $syslogLevel ) {
@ -317,30 +317,31 @@ class Logger {
$this->openSyslog();
}
}
return( $this->syslogLevel );
return $this->syslogLevel;
}
private function openSyslog() {
openlog( $this->id, LOG_PID|LOG_NDELAY, LOG_LOCAL1 );
openlog($this->id, LOG_PID|LOG_NDELAY, LOG_LOCAL1);
}
private function closeSyslog() {
closelog();
}
private function logFile( $logFile ) {
if ( preg_match( '/^(.+)\+$/', $logFile, $matches ) )
private function logFile($logFile) {
if ( preg_match('/^(.+)\+$/', $logFile, $matches) ) {
$this->logFile = $matches[1].'.'.getmypid();
else
} else {
$this->logFile = $logFile;
}
}
private function openFile() {
if ( !$this->useErrorLog ) {
if ( $this->logFd = fopen( $this->logFile, 'a+' ) ) {
if ( strnatcmp( phpversion(), '5.2.0' ) >= 0 ) {
if ( $this->logFd = fopen($this->logFile, 'a+') ) {
if ( strnatcmp(phpversion(), '5.2.0') >= 0 ) {
$error = error_get_last();
trigger_error( "Can't open log file '$logFile': ".$error['message'].' @ '.$error['file'].'/'.$error['line'], E_USER_ERROR );
trigger_error("Can't open log file '$logFile': ".$error['message'].' @ '.$error['file'].'/'.$error['line'], E_USER_ERROR);
}
$this->fileLevel = self::NOLOG;
}
@ -349,73 +350,80 @@ class Logger {
private function closeFile() {
if ( $this->logFd )
fclose( $this->logFd );
fclose($this->logFd);
}
public function logPrint( $level, $string, $file=NULL, $line=NULL ) {
if ( $level <= $this->effectiveLevel ) {
$string = preg_replace( '/[\r\n]+$/', '', $string );
$code = self::$codes[$level];
if ( $level > $this->effectiveLevel ) {
return;
}
$time = gettimeofday();
$message = sprintf( '%s.%06d %s[%d].%s [%s]', strftime( '%x %H:%M:%S', $time['sec'] ), $time['usec'], $this->id, getmypid(), $code, $string );
$string = preg_replace('/[\r\n]+$/', '', $string);
$code = self::$codes[$level];
if ( is_null($file) ) {
if ( $this->useErrorLog || $this->databaseLevel > self::NOLOG ) {
$backTrace = debug_backtrace();
$file = $backTrace[1]['file'];
$line = $backTrace[1]['line'];
if ( $this->hasTerm )
$rootPath = getcwd();
else
$rootPath = $_SERVER['DOCUMENT_ROOT'];
$file = preg_replace( '/^'.addcslashes($rootPath,'/').'\/?/', '', $file );
}
}
$time = gettimeofday();
$message = sprintf('%s.%06d %s[%d].%s [%s] [%s]', strftime('%x %H:%M:%S', $time['sec']), $time['usec'], $this->id, getmypid(), $code, $_SERVER['REMOTE_ADDR'], $string);
if ( $this->useErrorLog )
$message .= ' at '.$file.' line '.$line;
else
$message = $message;
if ( $level <= $this->termLevel )
if ( is_null($file) ) {
if ( $this->useErrorLog || $this->databaseLevel > self::NOLOG ) {
$backTrace = debug_backtrace();
$file = $backTrace[1]['file'];
$line = $backTrace[1]['line'];
if ( $this->hasTerm )
print( $message."\n" );
$rootPath = getcwd();
else
print( preg_replace( "/\n/", '<br/>', htmlspecialchars($message) ).'<br/>' );
if ( $level <= $this->fileLevel )
if ( $this->useErrorLog ) {
if ( !error_log( $message."\n", 3, $this->logFile ) ) {
if ( strnatcmp( phpversion(), '5.2.0' ) >= 0 ) {
$error = error_get_last();
trigger_error( "Can't write to log file '".$this->logFile."': ".$error['message'].' @ '.$error['file'].'/'.$error['line'], E_USER_ERROR );
}
}
} elseif ( $this->logFd ) {
fprintf( $this->logFd, $message."\n" );
}
$message = $code.' ['.$string.']';
if ( $level <= $this->syslogLevel )
syslog( self::$syslogPriorities[$level], $message );
if ( $level <= $this->databaseLevel ) {
try {
global $dbConn;
$sql = 'INSERT INTO Logs ( TimeKey, Component, Pid, Level, Code, Message, File, Line ) values ( ?, ?, ?, ?, ?, ?, ?, ? )';
$stmt = $dbConn->prepare( $sql );
$result = $stmt->execute( array( sprintf( '%d.%06d', $time['sec'], $time['usec'] ), $this->id, getmypid(), $level, $code, $string, $file, $line ) );
} catch(PDOException $ex) {
$this->databaseLevel = self::NOLOG;
Error("Can't write log entry '$sql': ". $ex->getMessage());
}
$rootPath = $_SERVER['DOCUMENT_ROOT'];
$file = preg_replace('/^'.addcslashes($rootPath,'/').'\/?/', '', $file);
}
// This has to be last as trigger_error can be fatal
if ( $level <= $this->weblogLevel ) {
if ( $this->useErrorLog )
error_log( $message, 0 );
else
trigger_error( $message, self::$phpErrorLevels[$level] );
}
if ( $this->useErrorLog ) {
$message .= ' at '.$file.' line '.$line;
} else {
$message = $message;
}
if ( $level <= $this->termLevel ) {
if ( $this->hasTerm )
print($message."\n");
else
print(preg_replace("/\n/", '<br/>', htmlspecialchars($message) ).'<br/>');
}
if ( $level <= $this->fileLevel ) {
if ( $this->useErrorLog ) {
if ( !error_log($message."\n", 3, $this->logFile) ) {
if ( strnatcmp(phpversion(), '5.2.0') >= 0 ) {
$error = error_get_last();
trigger_error("Can't write to log file '".$this->logFile."': ".$error['message'].' @ '.$error['file'].'/'.$error['line'], E_USER_ERROR);
}
}
} else if ( $this->logFd ) {
fprintf($this->logFd, $message."\n");
}
}
$message = $code.' ['.$string.']';
if ( $level <= $this->syslogLevel )
syslog( self::$syslogPriorities[$level], $message );
if ( $level <= $this->databaseLevel ) {
try {
global $dbConn;
$sql = 'INSERT INTO Logs ( TimeKey, Component, Pid, Level, Code, Message, File, Line ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ? )';
$stmt = $dbConn->prepare($sql);
$result = $stmt->execute(array(sprintf('%d.%06d', $time['sec'], $time['usec']), $this->id, getmypid(), $level, $code, $string, $file, $line));
} catch(PDOException $ex) {
$this->databaseLevel = self::NOLOG;
Error("Can't write log entry '$sql': ". $ex->getMessage());
}
}
// This has to be last as trigger_error can be fatal
if ( $level <= $this->weblogLevel ) {
if ( $this->useErrorLog ) {
error_log($message, 0);
} else {
trigger_error($message, self::$phpErrorLevels[$level]);
}
}
}

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;
}

View File

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

View File

@ -113,17 +113,17 @@ function exportEventDetail($event, $exportFrames, $exportImages) {
<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('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('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('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('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('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>
</div>
</div>
@ -226,13 +226,13 @@ function exportEventImages($event, $exportDetail, $exportFrames, $myfilelist) {
?>
<body>
<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_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;}
*.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_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;}
.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_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_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;}
.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;}
</style>
@ -247,7 +247,7 @@ function exportEventImages($event, $exportDetail, $exportFrames, $myfilelist) {
if ( $Monitor->VideoWriter() == '2' ) {
# Passthrough
$Rotation = $event->Orientation();
if ( in_array($event->Orientation(),array('90','270')) )
if ( in_array($event->Orientation(),array('ROTATE_90','ROTATE_270')) )
$Zoom = $event->Height()/$event->Width();
}
?>
@ -280,7 +280,7 @@ function exportEventImages($event, $exportDetail, $exportFrames, $myfilelist) {
<div align="center"><div class="horizontal_track">
<div class="horizontal_slit">&nbsp;</div>
<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 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>
<h2><?php echo translate('Images') ?> Master</h2>
<?php
// TODO: Should use find to make this 1 db query
foreach ($eids as $eid) {
$events = ZM\Event::find(array('Id'=>$eids));
foreach ($events as $event) {
//get monitor id and event id
$event = new ZM\Event($eid);
$eventMonitorId[$eid] = $event->MonitorId();
$eventPath[$eid] = $event->Relative_Path();
}
@ -653,20 +653,18 @@ function exportEventImagesMaster($eids) {
<div class="tab_content" id="all">
<h2> All </h2>
<?php
foreach($eids as $eid) {
$Event = new ZM\Event($eid);
eventlist_html($Event);
} # end foreach event id
foreach($events as $event) {
eventlist_html($event);
} # end foreach event
?>
</div>
<?php
foreach ($monitors as $monitor_id) {
echo "<div class=\"tab_content\" id=\"tab$monitor_id\">";
echo '<h2>Monitor: ' . $monitorNames[$monitor_id] . ' </h2>';
foreach ( $eids as $eid ) {
$Event = new ZM\Event($eid);
if ( $Event->MonitorId() == $monitor_id ) {
eventlist_html($Event);
foreach ( $events as $event ) {
if ( $event->MonitorId() == $monitor_id ) {
eventlist_html($event);
} # end if its the right monitor
} # end foreach event
echo '</div>';
@ -780,7 +778,7 @@ function exportFileList($event, $exportDetail, $exportFrames, $exportImages, $ex
}
fwrite($fp, exportEventDetail($event, $exportFrames, $exportImages));
fclose($fp);
$exportFileList[$file] = $event->Id().'/'.$file;
$exportFileList[$file] = $file;
}
if ( $exportFrames ) {
$file = 'zmEventFrames.html';
@ -789,7 +787,7 @@ function exportFileList($event, $exportDetail, $exportFrames, $exportImages, $ex
}
fwrite($fp, exportEventFrames($event, $exportDetail, $exportImages));
fclose($fp);
$exportFileList[$file] = $event->Id().'/'.$file;
$exportFileList[$file] = $file;
}
if ( $exportImages ) {
@ -797,7 +795,7 @@ function exportFileList($event, $exportDetail, $exportFrames, $exportImages, $ex
$myfilelist = array();
foreach ( $files as $file ) {
if ( preg_match('/-(?:capture|analyse).jpg$/', $file ) ) {
$myfilelist[$file] = $exportFileList[$file] = $event->Id().'/'.$file;
$myfilelist[$file] = $exportFileList[$file] = $file;
} else {
$filesLeft[$file] = $file;
}
@ -806,12 +804,12 @@ function exportFileList($event, $exportDetail, $exportFrames, $exportImages, $ex
// create an image slider
if ( !empty($myfilelist) ) {
$file = $event->Id().'/zmEventImages.html';
$file = 'zmEventImages.html';
if ( !($fp = fopen($file, 'w')) )
ZM\Fatal("Can't open event images export file '$file'");
fwrite($fp, exportEventImages($event, $exportDetail, $exportFrames, $myfilelist));
fclose($fp);
$exportFileList[$file] = $event->Id().'/'.$file;
$exportFileList[$file] = $file;
}
} # end if exportImages
@ -819,7 +817,7 @@ function exportFileList($event, $exportDetail, $exportFrames, $exportImages, $ex
$filesLeft = array();
foreach ( $files as $file ) {
if ( preg_match('/\.(?:mpg|mpeg|mov|swf|mp4|mkv|avi|asf|3gp)$/', $file) ) {
$exportFileList[$file] = $event->Id().'/'.$file;
$exportFileList[$file] = $file;
} else {
$filesLeft[$file] = $file;
}
@ -829,7 +827,7 @@ function exportFileList($event, $exportDetail, $exportFrames, $exportImages, $ex
if ( $exportMisc ) {
foreach ( $files as $file ) {
$exportFileList[$file] = $event->Id().'/'.$file;
$exportFileList[$file] = $file;
}
$files = array();
}
@ -850,10 +848,10 @@ function exportEvents(
) {
if ( !canView('Events') ) {
ZM\Error("You do not have permission to view events.");
ZM\Error('You do not have permission to view events.');
return false;
} else if ( empty($eids) ) {
ZM\Error("Attempt to export an empty list of events.");
ZM\Error('Attempt to export an empty list of events.');
return false;
}
@ -863,23 +861,22 @@ function exportEvents(
}
# Ensure that we are going to be able to do this.
if ( ! file_exists(ZM_DIR_EXPORTS) ) {
if ( ! mkdir(ZM_DIR_EXPORTS) ) {
ZM\Fatal("Can't create exports dir at '".ZM_DIR_EXPORTS."'");
}
if ( ! ( mkdir(ZM_DIR_EXPORTS) or file_exists(ZM_DIR_EXPORTS) ) ) {
ZM\Fatal('Can\'t create exports dir at \''.ZM_DIR_EXPORTS.'\'');
}
chmod(ZM_DIR_EXPORTS, 0700);
$export_dir = ZM_DIR_EXPORTS.'/zmExport_'.$connkey;
# Ensure that we are going to be able to do this.
if ( ! file_exists($export_dir) ) {
if ( ! mkdir($export_dir) ) {
ZM\Fatal("Can't create exports dir at '$export_dir'");
} else {
ZM\Logger::Debug("Successfully created dir '$export_dir'");
}
if ( ! ( mkdir($export_dir) or file_exists($export_dir) ) ) {
ZM\Fatal("Can't create exports dir at '$export_dir'");
} else {
ZM\Logger::Debug("Successfully created dir '$export_dir'");
}
if ( !chdir($export_dir) )
chmod($export_dir, 0700);
if ( !chdir($export_dir) ) {
ZM\Fatal("Can't chdir to $export_dir");
}
$export_root = 'zmExport';
$export_listFile = 'zmFileList.txt';
@ -889,27 +886,30 @@ function exportEvents(
if ( !is_array($eids) ) {
$eids = array($eids);
}
ZM\Logger::Debug("Eids: " . print_r($eids,true));
ZM\Logger::Debug('Eids: ' . print_r($eids,true));
foreach ( $eids as $eid ) {
$event = new ZM\Event($eid);
$event_dir = $export_dir.'/'.$event->Id();
if ( !mkdir($event_dir) )
if ( !(mkdir($event_dir) or file_exists($event_dir) ) ) {
ZM\Error("Can't mkdir $event_dir");
}
$event_exportFileList = exportFileList($event, $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc);
ZM\Logger::Debug("File list for event $eid " . print_r($event_exportFileList, true));
$exportFileList = array_merge($exportFileList,$event_exportFileList);
foreach ( $event_exportFileList as $file ) {
if ( preg_match('/\.html$/', $file ) )
if ( preg_match('/\.html$/', $file) )
continue;
ZM\Logger::Debug('cp -as '.$event->Path().'/../'.$file.' '.$export_dir.'/'.$file);
exec('cp -as '.$event->Path().'/../'.$file.' '.$export_dir.'/'.$file);
#exec('cp -as '.$event->Path().'/../'.$file.' '.$export_dir.'/'.$file, $output, $return);
$cmd = 'cp -as '.$event->Path().'/'.$file.' '.$export_dir.'/'.$event->Id().'/'.$file. ' 2>&1';
exec($cmd, $output, $return);
ZM\Logger::Debug($cmd.' return code: '.$return.' output: '.print_r($output,true));
}
}
} # end foreach event
// create an master image
if ( $exportImages ) {
if ( !symlink(ZM_PATH_WEB.'/'.ZM_SKIN_PATH.'/js/jquery.js', $export_dir.'/jquery.js') )
ZM\Error("Failed linking jquery.js");
ZM\Error('Failed linking jquery.js');
//if ( !symlink(ZM_PATH_WEB.'/'.ZM_SKIN_PATH.'/js/video.js', $export_dir.'/video.js') )
//Error("Failed linking video.js");
@ -960,12 +960,12 @@ function exportEvents(
@unlink($archive);
$command .= ' zmExport_' . $connkey.'/';
ZM\Logger::Debug("Command is $command");
exec($command, $output, $status);
if ( $status ) {
ZM\Error("Command '$command' returned with status $status");
if ( isset($output[0]) )
ZM\Error("First line of output is '".$output[0]."'");
if ( isset($output[0]) ) {
ZM\Error('First line of output is \''.$output[0].'\'');
}
return false;
}

View File

@ -290,12 +290,12 @@ if ( $user and $user['Username'] ) {
# zmaudit can clean the logs, but if we aren't running it, then we should clean them regularly
if ( preg_match('/^\d+$/', ZM_LOG_DATABASE_LIMIT) ) {
# Number of lines, instead of an interval
$rows = dbFetchOne('SELECT Count(*) AS Rows FROM Logs', 'Rows');
$rows = dbFetchOne('SELECT Count(*) AS `Rows` FROM `Logs`', 'Rows');
if ( $rows > ZM_LOG_DATABASE_LIMIT ) {
dbQuery('DELETE low_priority FROM Logs ORDER BY TimeKey ASC LIMIT ?', array($rows - ZM_LOG_DATABASE_LIMIT));
dbQuery('DELETE low_priority FROM `Logs` ORDER BY `TimeKey` ASC LIMIT ?', array($rows - ZM_LOG_DATABASE_LIMIT));
}
} else if ( preg_match('/^\d\s*(hour|minute|day|week|month|year)$/', ZM_LOG_DATABASE_LIMIT, $matches) ) {
dbQuery('DELETE FROM Logs WHERE TimeKey < unix_timestamp( NOW() - interval '.ZM_LOG_DATABASE_LIMIT.') LIMIT 100');
dbQuery('DELETE FROM `Logs` WHERE `TimeKey` < unix_timestamp( NOW() - interval '.ZM_LOG_DATABASE_LIMIT.') LIMIT 100');
} else {
ZM\Error('Potentially invalid value for ZM_LOG_DATABASE_LIMIT: ' . ZM_LOG_DATABASE_LIMIT);
}
@ -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>
<i class="material-icons md-18">storage</i>
<?php
$connections = dbFetchOne( "SHOW status WHERE variable_name='threads_connected'", 'Value' );
$max_connections = dbFetchOne( "SHOW variables WHERE variable_name='max_connections'", 'Value' );
$connections = dbFetchOne('SHOW status WHERE variable_name=\'threads_connected\'', 'Value');
$max_connections = dbFetchOne('SHOW variables WHERE variable_name=\'max_connections\'', 'Value');
$percent_used = $max_connections ? 100 * $connections / $max_connections : 100;
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
$storage_areas = ZM\Storage::find();
$storage_paths = null;
$storage_areas_with_no_server_id = array();
foreach ( $storage_areas as $area ) {
$storage_paths[$area->Path()] = $area;
if ( ! $area->ServerId() ) {
$storage_areas_with_no_server_id[] = $area;
}
}
$func = function($S){
$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>'; };
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 )
echo implode( ', ', array_map ( $func, $storage_areas ) );
echo implode(', ', array_map($func, $storage_areas));
echo ' ' . ZM_PATH_MAP .': '. getDiskPercent(ZM_PATH_MAP).'%';
?></li>
</ul>

View File

@ -29,7 +29,7 @@ var popupSizes = {
'console': {'width': 750, 'height': 312},
'control': {'width': 480, 'height': 480},
'controlcaps': {'width': 780, 'height': 320},
'controlcap': {'width': 400, 'height': 400},
'controlcap': {'width': 600, 'height': 500},
'cycle': {'addWidth': 32, 'minWidth': 384, 'addHeight': 62},
'device': {'width': 260, 'height': 150},
'devices': {'width': 400, 'height': 240},
@ -46,7 +46,7 @@ var popupSizes = {
'group': {'width': 760, 'height': 600},
'groups': {'width': 540, 'height': 420},
'image': {'addWidth': 48, 'addHeight': 80},
'log': {'width': 1080, 'height': 720},
'log': {'width': 1180, 'height': 720},
'login': {'width': 720, 'height': 480},
'logout': {'width': 260, 'height': 150},
'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.
document.querySelectorAll("a[data-on-click], button[data-on-click], input[data-on-click]").forEach(function attachOnClick(el) {
document.querySelectorAll("i[data-on-click], a[data-on-click], button[data-on-click], input[data-on-click]").forEach(function attachOnClick(el) {
var fnName = el.getAttribute("data-on-click");
if ( !window[fnName] ) {
console.error("Nothing found to bind to " + fnName + " on element " + el.name);
return;
}
el.onclick = function() {
window[fnName]();
};

View File

@ -187,7 +187,8 @@ getBodyTopHTML();
<button type="button" name="cloneBtn" data-on-click-this="cloneMonitor"
<?php echo (canEdit('Monitors') && !$user['MonitorIds']) ? '' : ' disabled="disabled"' ?>
style="display:none;">
<i class="material-icons md-18">copy</i>
<i class="material-icons md-18">content_copy</i>
<!--content_copy used instead of file_copy as there is a bug in material-icons -->
&nbsp;<?php echo translate('CloneMonitor') ?>
</button>
<button type="button" name="editBtn" data-on-click-this="editMonitor" disabled="disabled">
@ -200,7 +201,7 @@ getBodyTopHTML();
</button>
<button type="button" name="selectBtn" data-on-click-this="selectMonitor" disabled="disabled">
<i class="material-icons md-18">view_list</i>
&nbsp;<?php echo translate('Select')?>
&nbsp;<?php echo translate('Select') ?>
</button>
<?php
ob_start();

View File

@ -18,40 +18,31 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
if ( !canEdit( 'Control' ) )
{
$view = "error";
return;
if ( !canEdit('Control') ) {
$view = 'error';
return;
}
$tabs = array();
$tabs["main"] = translate('Main');
$tabs["move"] = translate('Move');
$tabs["pan"] = translate('Pan');
$tabs["tilt"] = translate('Tilt');
$tabs["zoom"] = translate('Zoom');
$tabs["focus"] = translate('Focus');
$tabs["white"] = translate('White');
$tabs["iris"] = translate('Iris');
$tabs["presets"] = translate('Presets');
$tabs['main'] = translate('Main');
$tabs['move'] = translate('Move');
$tabs['pan'] = translate('Pan');
$tabs['tilt'] = translate('Tilt');
$tabs['zoom'] = translate('Zoom');
$tabs['focus'] = translate('Focus');
$tabs['gain'] = translate('Gain');
$tabs['white'] = translate('White');
$tabs['iris'] = translate('Iris');
$tabs['presets'] = translate('Presets');
if ( isset($_REQUEST['tab']) )
$tab = validHtmlStr($_REQUEST['tab']);
else
$tab = "main";
$tab = isset($_REQUEST['tab']) ? validHtmlStr($_REQUEST['tab']) :'main';
if ( isset( $_REQUEST['newControl'] ) )
{
if ( isset($_REQUEST['newControl']) ) {
$newControl = $_REQUEST['newControl'];
}
else
{
if ( !empty($_REQUEST['cid']) )
{
$control = dbFetchOne( 'SELECT * FROM Controls WHERE Id = ?', NULL, array($_REQUEST['cid'] ) );
}
else
{
} else {
if ( !empty($_REQUEST['cid']) ) {
$control = dbFetchOne('SELECT * FROM Controls WHERE Id = ?', NULL, array($_REQUEST['cid']));
} else {
$control = array(
'Name' => translate('New'),
'Type' => "Local",
@ -166,16 +157,12 @@ xhtmlHeaders(__FILE__, translate('ControlCap')." - ".$newControl['Name'] );
<div id="content">
<ul class="tabList">
<?php
foreach ( $tabs as $name=>$value )
{
if ( $tab == $name )
{
foreach ( $tabs as $name=>$value ) {
if ( $tab == $name ) {
?>
<li class="active"><?php echo $value ?></li>
<?php
}
else
{
} else {
?>
<li><a href="#" data-tab-name="<?php echo $name ?>"><?php echo $value ?></a></li>
<?php
@ -190,8 +177,7 @@ foreach ( $tabs as $name=>$value )
<input type="hidden" name="action" value="controlcap"/>
<input type="hidden" name="cid" value="<?php echo requestVar('cid') ?>"/>
<?php
if ( $tab != 'main' )
{
if ( $tab != 'main' ) {
?>
<input type="hidden" name="newControl[Name]" value="<?php echo validHtmlStr($newControl['Name']) ?>"/>
<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']) ?>"/>
<?php
}
if ( $tab != 'move' )
{
if ( $tab != 'move' ) {
?>
<input type="hidden" name="newControl[CanMove]" value="<?php echo !empty($newControl['CanMove']) ?>"/>
<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']) ?>"/>
<?php
}
if ( $tab != 'pan' )
{
if ( $tab != 'pan' ) {
?>
<input type="hidden" name="newControl[CanPan]" value="<?php echo !empty($newControl['CanPan']) ?>"/>
<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']) ?>"/>
<?php
}
if ( $tab != 'tilt' )
{
if ( $tab != 'tilt' ) {
?>
<input type="hidden" name="newControl[CanTilt]" value="<?php echo !empty($newControl['CanTilt']) ?>"/>
<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']) ?>"/>
<?php
}
if ( $tab != 'zoom' )
{
if ( $tab != 'zoom' ) {
?>
<input type="hidden" name="newControl[CanZoom]" value="<?php echo !empty($newControl['CanZoom']) ?>"/>
<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']) ?>"/>
<?php
}
if ( $tab != 'focus' )
{
if ( $tab != 'focus' ) {
?>
<input type="hidden" name="newControl[CanFocus]" value="<?php echo !empty($newControl['CanFocus']) ?>"/>
<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']) ?>"/>
<?php
}
if ( $tab != 'iris' )
{
if ( $tab != 'iris' ) {
?>
<input type="hidden" name="newControl[CanIris]" value="<?php echo !empty($newControl['CanIris']) ?>"/>
<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']) ?>"/>
<?php
}
if ( $tab != 'gain' )
{
if ( $tab != 'gain' ) {
?>
<input type="hidden" name="newControl[CanGain]" value="<?php echo !empty($newControl['CanGain']) ?>"/>
<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']) ?>"/>
<?php
}
if ( $tab != 'white' )
{
if ( $tab != 'white' ) {
?>
<input type="hidden" name="newControl[CanWhite]" value="<?php echo !empty($newControl['CanWhite']) ?>"/>
<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']) ?>"/>
<?php
}
if ( $tab != 'presets' )
{
if ( $tab != 'presets' ) {
?>
<input type="hidden" name="newControl[HasPresets]" value="<?php echo !empty($newControl['HasPresets']) ?>"/>
<input type="hidden" name="newControl[NumPresets]" value="<?php echo validHtmlStr($newControl['NumPresets']) ?>"/>
@ -336,19 +313,17 @@ if ( $tab != 'presets' )
<?php
}
?>
<table id="contentTable" class="major" cellspacing="0">
<table id="contentTable" class="major">
<tbody>
<?php
switch ( $tab )
{
case 'main' :
{
switch ( $tab ) {
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>
<?php
$types = array( 'Local'=>translate('Local'), 'Remote'=>translate('Remote'), 'Ffmpeg'=>translate('Ffmpeg'), 'Libvlc'=>translate('Libvlc'), 'cURL'=>"cURL");
?>
<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('Name') ?></th><td><input type="text" name="newControl[Name]" value="<?php echo validHtmlStr($newControl['Name']) ?>"/></td></tr>
<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');
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('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>
@ -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('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('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('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('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('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="number" name="newControl[MaxPanRange]" value="<?php echo validHtmlStr($newControl['MaxPanRange']) ?>"/></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="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('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('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('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="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('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
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('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('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('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('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('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="number" name="newControl[MaxTiltRange]" value="<?php echo validHtmlStr($newControl['MaxTiltRange']) ?>"/></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="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('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('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('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="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('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
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('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('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('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('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('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('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="number" name="newControl[MaxZoomRange]" value="<?php echo validHtmlStr($newControl['MaxZoomRange']) ?>"/></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="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('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('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('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="number" name="newControl[MaxZoomSpeed]" value="<?php echo validHtmlStr($newControl['MaxZoomSpeed']) ?>"/></td></tr>
<?php
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('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('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('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('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('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('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="number" name="newControl[MaxFocusRange]" value="<?php echo validHtmlStr($newControl['MaxFocusRange']) ?>"/></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="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('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('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('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="number" name="newControl[MaxFocusSpeed]" value="<?php echo validHtmlStr($newControl['MaxFocusSpeed']) ?>"/></td></tr>
<?php
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('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('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('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('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('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('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="number" name="newControl[MaxIrisRange]" value="<?php echo validHtmlStr($newControl['MaxIrisRange']) ?>"/></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="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('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('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('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="number" name="newControl[MaxIrisSpeed]" value="<?php echo validHtmlStr($newControl['MaxIrisSpeed']) ?>"/></td></tr>
<?php
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('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('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('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('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('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('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="number" name="newControl[MaxGainRange]" value="<?php echo validHtmlStr($newControl['MaxGainRange']) ?>"/></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="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('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('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('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="number" name="newControl[MaxGainSpeed]" value="<?php echo validHtmlStr($newControl['MaxGainSpeed']) ?>"/></td></tr>
<?php
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('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('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('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('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('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('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="number" name="newControl[MaxWhiteRange]" value="<?php echo validHtmlStr($newControl['MaxWhiteRange']) ?>"/></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="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('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('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('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="number" name="newControl[MaxWhiteSpeed]" value="<?php echo validHtmlStr($newControl['MaxWhiteSpeed']) ?>"/></td></tr>
<?php
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('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('CanSetPresets') ?></th><td><input type="checkbox" name="newControl[CanSetPresets]" value="1"<?php if ( !empty($newControl['CanSetPresets']) ) { ?> checked="checked"<?php } ?>/></td></tr>
<?php
@ -505,7 +480,8 @@ switch ( $tab )
</tbody>
</table>
<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>
</form>
</div>

View File

@ -138,7 +138,7 @@ $disk_space_total = 0;
$event_count = 0;
while ( $event_row = dbFetchNext($results) ) {
$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"' : '' ?>>
<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 ( 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) ) {
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\"";
if ( !(
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 {
// 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 ) {
errors[errors.length] = "\"Can Move\" must also be selected if any one of the movement types are sleceted";
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
) {
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 ) {
alert( errors.join( "\n" ) );
return ( false );
alert(errors.join("\n"));
return false;
}
return ( true );
return true;
}

View File

@ -57,7 +57,7 @@ function setAlarmCues(data) {
function renderAlarmCues(containerEl) {
if ( !( cueFrames && cueFrames.length ) ) {
console.log("No cue frames for event");
console.log('No cue frames for event');
return;
}
// This uses the Delta of the last frame to get the length of the event. I can't help but wonder though
@ -139,7 +139,7 @@ function setButtonState( element, butClass ) {
element.disabled = false;
}
} else {
console.log("Element was null in setButtonState");
console.log('Element was null in setButtonState');
}
}
@ -211,7 +211,7 @@ var lastEventId = 0;
var zmsBroke = false; //Use alternate navigation if zms has crashed
function getCmdResponse( respObj, respText ) {
if ( checkStreamForErrors("getCmdResponse", respObj) ) {
if ( checkStreamForErrors('getCmdResponse', respObj) ) {
console.log('Got an error from getCmdResponse');
console.log(respObj);
console.log(respText);
@ -541,9 +541,9 @@ var scroll = null;
var currEventId = null;
var CurEventDefVideoPath = null;
function getEventResponse( respObj, respText ) {
if ( checkStreamForErrors( "getEventResponse", respObj ) ) {
console.log("getEventResponse: errors" );
function getEventResponse(respObj, respText) {
if ( checkStreamForErrors('getEventResponse', respObj) ) {
console.log('getEventResponse: errors');
return;
}
@ -582,7 +582,7 @@ function getEventResponse( respObj, respText ) {
//eventImg.setStyles( { 'width': eventData.width, 'height': eventData.height } );
if ( vid && CurEventDefVideoPath ) {
vid.src({type: 'video/mp4', src: CurEventDefVideoPath}); //Currently mp4 is all we use
console.log("getEventResponse");
console.log('getEventResponse');
initialAlarmCues(eventData.Id);//ajax and render, new event
addVideoTimingTrack(vid, LabelFormat, eventData.MonitorName, eventData.Length, eventData.StartTime);
CurEventDefVideoPath = null;
@ -644,7 +644,7 @@ var frameBatch = 40;
function loadEventThumb( event, frame, loadImage ) {
var thumbImg = $('eventThumb'+frame.FrameId);
if ( !thumbImg ) {
console.error( "No holder found for frame "+frame.FrameId );
console.error('No holder found for frame '+frame.FrameId);
return;
}
var img = new Asset.image( imagePrefix+frame.EventId+"&fid="+frame.FrameId,
@ -666,31 +666,31 @@ function loadEventThumb( event, frame, loadImage ) {
);
}
function loadEventImage( event, frame ) {
console.debug( "Loading "+event.Id+"/"+frame.FrameId );
function loadEventImage(event, frame) {
console.debug('Loading '+event.Id+'/'+frame.FrameId);
var eventImg = $('eventImage');
var thumbImg = $('eventThumb'+frame.FrameId);
if ( eventImg.getProperty( 'src' ) != thumbImg.getProperty( 'src' ) ) {
if ( eventImg.getProperty('src') != thumbImg.getProperty('src') ) {
var eventImagePanel = $('eventImagePanel');
if ( eventImagePanel.getStyle( 'display' ) != 'none' ) {
var lastThumbImg = $('eventThumb'+eventImg.getProperty( 'alt' ));
if ( eventImagePanel.getStyle('display') != 'none' ) {
var lastThumbImg = $('eventThumb'+eventImg.getProperty('alt'));
lastThumbImg.removeClass('selected');
lastThumbImg.setOpacity( 1.0 );
lastThumbImg.setOpacity(1.0);
}
$('eventImageBar').setStyle( 'width', event.Width );
if ( frame.Type=='Alarm' ) {
$('eventImageStats').removeClass( 'hidden' );
$('eventImageBar').setStyle('width', event.Width);
if ( frame.Type == 'Alarm' ) {
$('eventImageStats').removeClass('hidden');
} else {
$('eventImageStats').addClass( 'hidden' );
$('eventImageStats').addClass('hidden');
}
thumbImg.addClass( 'selected' );
thumbImg.setOpacity( 0.5 );
thumbImg.addClass('selected');
thumbImg.setOpacity(0.5);
if ( eventImagePanel.getStyle( 'display' ) == 'none' ) {
eventImagePanel.setOpacity( 0 );
eventImagePanel.setStyle( 'display', 'inline-block' );
if ( eventImagePanel.getStyle('display') == 'none' ) {
eventImagePanel.setOpacity(0);
eventImagePanel.setStyle('display', 'inline-block');
new Fx.Tween( eventImagePanel, {duration: 500, transition: Fx.Transitions.Sine} ).start( 'opacity', 0, 1 );
}
@ -702,29 +702,29 @@ function loadEventImage( event, frame ) {
'height': $j('#eventThumbs').height() - $j('#eventImageBar').outerHeight(true)-10
} );
$('eventImageNo').set( 'text', frame.FrameId );
$('eventImageNo').set('text', frame.FrameId);
$('prevImageBtn').disabled = (frame.FrameId==1);
$('nextImageBtn').disabled = (frame.FrameId==event.Frames);
}
}
function hideEventImageComplete() {
var thumbImg = $('eventThumb'+$('eventImage').getProperty( 'alt' ));
var thumbImg = $('eventThumb'+$('eventImage').getProperty('alt'));
if ( thumbImg ) {
thumbImg.removeClass('selected');
thumbImg.setOpacity( 1.0 );
thumbImg.setOpacity(1.0);
} else {
console.log("Unable to find eventThumb at " + 'eventThumb'+$('eventImage').getProperty( 'alt' ) );
console.log('Unable to find eventThumb at eventThumb'+$('eventImage').getProperty('alt'));
}
$('prevImageBtn').disabled = true;
$('nextImageBtn').disabled = true;
$('eventImagePanel').setStyle( 'display', 'none' );
$('eventImageStats').addClass( 'hidden' );
$('eventImagePanel').setStyle('display', 'none');
$('eventImageStats').addClass('hidden');
}
function hideEventImage() {
if ( $('eventImagePanel').getStyle( 'display' ) != 'none' ) {
new Fx.Tween( $('eventImagePanel'), {duration: 500, transition: Fx.Transitions.Sine, onComplete: hideEventImageComplete} ).start( 'opacity', 1, 0 );
if ( $('eventImagePanel').getStyle('display') != 'none' ) {
new Fx.Tween( $('eventImagePanel'), {duration: 500, transition: Fx.Transitions.Sine, onComplete: hideEventImageComplete} ).start('opacity', 1, 0);
}
}
@ -751,15 +751,15 @@ function resetEventStills() {
}
}
function getFrameResponse( respObj, respText ) {
if ( checkStreamForErrors( "getFrameResponse", respObj ) ) {
function getFrameResponse(respObj, respText) {
if ( checkStreamForErrors('getFrameResponse', respObj) ) {
return;
}
var frame = respObj.frameimage;
if ( !eventData ) {
console.error( "No event "+frame.EventId+" found" );
console.error('No event '+frame.EventId+' found');
return;
}
@ -769,21 +769,21 @@ function getFrameResponse( respObj, respText ) {
eventData['frames'][frame.FrameId] = frame;
loadEventThumb( eventData, frame, respObj.loopback=="true" );
loadEventThumb(eventData, frame, respObj.loopback=="true");
}
var frameReq = new Request.JSON( {url: thisUrl, method: 'get', timeout: AJAX_TIMEOUT, link: 'chain', onSuccess: getFrameResponse} );
function frameQuery( eventId, frameId, loadImage ) {
var parms = "view=request&request=status&entity=frameimage&id[0]="+eventId+"&id[1]="+frameId+"&loopback="+loadImage;
frameReq.send( parms );
frameReq.send(parms);
}
var currFrameId = null;
function checkFrames( eventId, frameId, loadImage ) {
if ( !eventData ) {
console.error( "No event "+eventId+" found" );
console.error("No event "+eventId+" found");
return;
}
@ -804,29 +804,30 @@ function checkFrames( eventId, frameId, loadImage ) {
for ( var fid = loFid; fid <= hiFid; fid++ ) {
if ( !$('eventThumb'+fid) ) {
var img = new Element( 'img', {'id': 'eventThumb'+fid, 'src': 'graphics/transparent.png', 'alt': fid, 'class': 'placeholder'} );
img.addEvent( 'click', function() {
eventData['frames'][fid] = null; checkFrames( eventId, fid );
} );
frameQuery( eventId, fid, loadImage && (fid == frameId) );
var imgs = $('eventThumbs').getElements( 'img' );
var img = new Element('img', {'id': 'eventThumb'+fid, 'src': 'graphics/transparent.png', 'alt': fid, 'class': 'placeholder'});
img.addEvent('click', function() {
eventData['frames'][fid] = null;
checkFrames(eventId, fid);
});
frameQuery(eventId, fid, loadImage && (fid == frameId));
var imgs = $('eventThumbs').getElements('img');
var injected = false;
if ( fid < imgs.length ) {
img.inject( imgs[fid-1], 'before' );
img.inject(imgs[fid-1], 'before');
injected = true;
} else {
injected = imgs.some(
function( thumbImg, index ) {
if ( parseInt(img.getProperty( 'alt' )) < parseInt(thumbImg.getProperty( 'alt' )) ) {
img.inject( thumbImg, 'before' );
return ( true );
if ( parseInt(img.getProperty('alt')) < parseInt(thumbImg.getProperty('alt')) ) {
img.inject(thumbImg, 'before');
return true;
}
return ( false );
return false;
}
);
}
if ( !injected ) {
img.inject( $('eventThumbs') );
img.inject($('eventThumbs'));
}
var scale = parseInt(img.getStyle('height'));
img.setStyles( {
@ -923,7 +924,7 @@ function deleteEvent() {
getActResponse(respObj, respText);
// We must wait for the deletion to happen before navigating to the next
// event or this request will be cancelled.
streamNext( true );
streamNext(true);
},
});
deleteReq.send("view=request&request=event&id="+eventData.Id+"&action=delete");
@ -931,43 +932,43 @@ function deleteEvent() {
function renameEvent() {
var newName = $('eventName').get('value');
actQuery( 'rename', {eventName: newName} );
actQuery('rename', {eventName: newName});
}
function editEvent() {
createPopup( '?view=eventdetail&eid='+eventData.Id, 'zmEventDetail', 'eventdetail' );
createPopup('?view=eventdetail&eid='+eventData.Id, 'zmEventDetail', 'eventdetail');
}
function exportEvent() {
createPopup( '?view=export&eid='+eventData.Id, 'zmExport', 'export' );
createPopup('?view=export&eid='+eventData.Id, 'zmExport', 'export');
}
function archiveEvent() {
actQuery( 'archive' );
actQuery('archive');
}
function unarchiveEvent() {
actQuery( 'unarchive' );
actQuery('unarchive');
}
function showEventFrames() {
createPopup( '?view=frames&eid='+eventData.Id, 'zmFrames', 'frames', WEB_LIST_THUMB_WIDTH, WEB_LIST_THUMB_HEIGHT );
createPopup('?view=frames&eid='+eventData.Id, 'zmFrames', 'frames', WEB_LIST_THUMB_WIDTH, WEB_LIST_THUMB_HEIGHT);
}
function showStream() {
$('eventStills').addClass( 'hidden' );
$('eventVideo').removeClass( 'hidden' );
$('eventStills').addClass('hidden');
$('eventVideo').removeClass('hidden');
$('stillsEvent').removeClass( 'hidden' );
$('streamEvent').addClass( 'hidden' );
$('stillsEvent').removeClass('hidden');
$('streamEvent').addClass('hidden');
streamMode = 'video';
if (scale == 'auto') changeScale();
}
function showStills() {
$('eventStills').removeClass( 'hidden' );
$('eventVideo').addClass( 'hidden' );
$('eventStills').removeClass('hidden');
$('eventVideo').addClass('hidden');
if (vid && ( vid.paused != true ) ) {
// Pause the video
@ -978,14 +979,14 @@ function showStills() {
//playButton.innerHTML = "Play";
}
$('stillsEvent').addClass( 'hidden' );
$('streamEvent').removeClass( 'hidden' );
$('stillsEvent').addClass('hidden');
$('streamEvent').removeClass('hidden');
streamMode = 'stills';
pauseClicked();
if ( !scroll ) {
scroll = new Fx.Scroll( 'eventThumbs', {
scroll = new Fx.Scroll('eventThumbs', {
wait: false,
duration: 500,
offset: {'x': 0, 'y': 0},
@ -999,17 +1000,17 @@ function showStills() {
function showFrameStats() {
var fid = $('eventImageNo').get('text');
createPopup( '?view=stats&eid='+eventData.Id+'&fid='+fid, 'zmStats', 'stats', eventData.Width, eventData.Height );
createPopup('?view=stats&eid='+eventData.Id+'&fid='+fid, 'zmStats', 'stats', eventData.Width, eventData.Height);
}
function videoEvent() {
createPopup( '?view=video&eid='+eventData.Id, 'zmVideo', 'video', eventData.Width, eventData.Height );
createPopup('?view=video&eid='+eventData.Id, 'zmVideo', 'video', eventData.Width, eventData.Height);
}
// Called on each event load because each event can be a different width
function drawProgressBar() {
var barWidth = $j('#evtStream').width();
$j('#progressBar').css( 'width', barWidth );
$j('#progressBar').css('width', barWidth);
}
// Shows current stream progress.
@ -1032,8 +1033,8 @@ function progressBarNav() {
function handleClick( event ) {
var target = event.target;
if (vid) {
if (target.id != 'videoobj') return; //ignore clicks on control bar
if ( vid ) {
if (target.id != 'videoobj') return; // ignore clicks on control bar
var x = event.offsetX;
var y = event.offsetY;
} else {
@ -1041,9 +1042,9 @@ function handleClick( event ) {
var y = event.page.y - $(target).getTop();
}
if (event.shift || event.shiftKey) {//handle both jquery and mootools
if ( event.shift || event.shiftKey ) { // handle both jquery and mootools
streamPan(x, y);
} else if (vid && event.ctrlKey) { //allow zoom out by control click. useful in fullscreen
} else if ( vid && event.ctrlKey ) { // allow zoom out by control click. useful in fullscreen
vjsPanZoom('zoomOut', x, y);
} else {
streamZoomIn(x, y);
@ -1072,7 +1073,7 @@ function initPage() {
}
} else {
progressBarNav();
streamCmdTimer = streamQuery.delay( 250 );
streamCmdTimer = streamQuery.delay(250);
if ( canStreamNative ) {
var imageFeed = $('imageFeed');
if ( !imageFeed ) {
@ -1082,16 +1083,16 @@ function initPage() {
if ( !streamImg ) {
streamImg = imageFeed.getElement('object');
}
$(streamImg).addEvent( 'click', function( event ) {
handleClick( event );
} );
$(streamImg).addEvent('click', function(event) {
handleClick(event);
});
}
}
}
nearEventsQuery(eventData.Id);
initialAlarmCues(eventData.Id); //call ajax+renderAlarmCues
if (scale == "auto") changeScale();
if ( scale == 'auto' ) changeScale();
}
// Kick everything off
window.addEventListener( 'DOMContentLoaded', initPage );
window.addEventListener('DOMContentLoaded', initPage);

View File

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

View File

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

View File

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

View File

@ -35,7 +35,7 @@ monitorData[monitorData.length] = {
'connKey': <?php echo $monitor->connKey() ?>,
'width': <?php echo $monitor->ViewWidth() ?>,
'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() ); ?> );},
'type': '<?php echo $monitor->Type() ?>',
'refresh': '<?php echo $monitor->Refresh() ?>'

View File

@ -18,7 +18,7 @@ var speedIndex=<?php echo $speedIndex?>;
// for history, and fps for live, and dynamically determined (in ms)
var currentDisplayInterval=<?php echo $initialDisplayInterval?>;
var playSecsperInterval=1; // How many seconds of recorded image we play per refresh determined by speed (replay rate) and display interval; (default=1 if coming from live)
var playSecsPerInterval=1; // How many seconds of recorded image we play per refresh determined by speed (replay rate) and display interval; (default=1 if coming from live)
var timerInterval; // milliseconds between interrupts
var timerObj; // object to hold timer interval;
var freeTimeLastIntervals=[]; // Percentage of current interval used in loading most recent image

View File

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

View File

@ -44,17 +44,17 @@ function changeScale() {
newHeight = monitorHeight * scale / SCALE_BASE;
}
Cookie.write( 'zmWatchScale'+monitorId, scale, {duration: 10*365} );
Cookie.write('zmWatchScale'+monitorId, scale, {duration: 10*365});
/*Stream could be an applet so can't use moo tools*/
var streamImg = $('liveStream'+monitorId);
if ( streamImg ) {
streamImg.style.width = newWidth + "px";
streamImg.style.height = newHeight + "px";
streamImg.style.width = newWidth + 'px';
streamImg.style.height = newHeight + 'px';
streamImg.src = streamImg.src.replace(/scale=\d+/i, 'scale='+(scale== 'auto' ? autoScale : scale));
} else {
console.error("No element found for liveStream.");
console.error('No element found for liveStream.');
}
}
@ -64,17 +64,17 @@ var lastAlarmState = STATE_IDLE;
function setAlarmState( currentAlarmState ) {
alarmState = currentAlarmState;
var stateClass = "";
var stateClass = '';
if ( alarmState == STATE_ALARM ) {
stateClass = "alarm";
stateClass = 'alarm';
} else if ( alarmState == STATE_ALERT ) {
stateClass = "alert";
stateClass = 'alert';
}
$('stateValue').set( 'text', stateStrings[alarmState] );
$('stateValue').set('text', stateStrings[alarmState]);
if ( stateClass ) {
$('stateValue').setProperty( 'class', stateClass );
$('stateValue').setProperty('class', stateClass);
} else {
$('stateValue').removeProperty( 'class' );
$('stateValue').removeProperty('class');
}
var isAlarmed = ( alarmState == STATE_ALARM || alarmState == STATE_ALERT );
@ -114,7 +114,7 @@ function setAlarmState( currentAlarmState ) {
}
if ( monitorType != 'WebSite' ) {
var streamCmdParms = "view=request&request=stream&connkey="+connKey;
var streamCmdParms = 'view=request&request=stream&connkey='+connKey;
if ( auth_hash ) {
streamCmdParms += '&auth='+auth_hash;
}
@ -141,7 +141,7 @@ function getStreamCmdFailure(xhr) {
console.log(xhr);
}
function getStreamCmdResponse(respObj, respText) {
watchdogOk("stream");
watchdogOk('stream');
if ( streamCmdTimer ) {
streamCmdTimer = clearTimeout(streamCmdTimer);
}
@ -229,12 +229,18 @@ function getStreamCmdResponse(respObj, respText) {
} // end if canEditMonitors
if ( streamStatus.auth ) {
auth_hash = streamStatus.auth;
console.log("Have a new auth hash" + streamStatus.auth);
// Try to reload the image stream.
var streamImg = $('liveStream');
if ( streamImg ) {
streamImg.src = streamImg.src.replace(/auth=\w+/i, 'auth='+streamStatus.auth);
}
streamCmdParms = streamCmdParms.replace(/auth=\w+/i, 'auth='+streamStatus.auth);
statusCmdParms = statusCmdParms.replace(/auth=\w+/i, 'auth='+streamStatus.auth);
eventCmdParms = eventCmdParms.replace(/auth=\w+/i, 'auth='+streamStatus.auth);
actParms = actParms.replace(/auth=\w+/i, 'auth='+streamStatus.auth);
controlParms = controlParms.replace(/auth=\w+/i, 'auth='+streamStatus.auth);
} // end if have a new auth hash
} // end if respObj.status
} else {
@ -473,6 +479,9 @@ function getActResponse( respObj, respText ) {
function deleteEvent( event, eventId ) {
var actParms = "view=request&request=event&action=delete&id="+eventId;
if ( auth_hash ) {
actParms += '&auth='+auth_hash;
}
var actReq = new Request.JSON( {
url: thisUrl,
method: 'post',

View File

@ -122,9 +122,12 @@ xhtmlHeaders(__FILE__, translate('SystemLog') );
<form id="exportForm" action="" method="post">
<fieldset>
<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="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"/>
<label for="selectorAll"><?php echo translate('All') ?></label>
<input type="radio" id="selectorAll" name="selector" value="all"/>
<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>
<legend><?php echo translate('SelectFormat') ?></legend>

View File

@ -40,8 +40,8 @@ if ( !empty($_REQUEST['mid']) ) {
if ( $monitor and ZM_OPT_X10 )
$x10Monitor = dbFetchOne('SELECT * FROM TriggersX10 WHERE MonitorId = ?', NULL, array($_REQUEST['mid']));
}
if ( !$monitor ) {
if ( !$monitor ) {
$nextId = getTableAutoInc('Monitors');
if ( isset($_REQUEST['dupId']) ) {
$monitor = new ZM\Monitor($_REQUEST['dupId']);
@ -54,6 +54,7 @@ if ( !$monitor ) {
$monitor = new ZM\Monitor();
} # end if $_REQUEST['dupID']
$monitor->Name(translate('Monitor').'-'.$nextId);
$monitor->WebColour(random_colour());
} # end if $_REQUEST['mid']
if ( ZM_OPT_X10 && empty($x10Monitor) ) {
@ -67,7 +68,6 @@ if ( ZM_OPT_X10 && empty($x10Monitor) ) {
function fourcc($a, $b, $c, $d) {
return ord($a) | (ord($b) << 8) | (ord($c) << 16) | (ord($d) << 24);
}
if ( isset($_REQUEST['newMonitor']) ) {
# Update the monitor object with whatever has been set so far.
$monitor->set($_REQUEST['newMonitor']);
@ -371,13 +371,6 @@ $label_size = array(
'Large' => 2
);
$savejpegopts = array(
'Disabled' => 0,
'Frames only' => 1,
'Analysis images only (if available)' => 2,
'Frames + Analysis images (if available)' => 3,
);
$codecs = array(
'auto' => translate('Auto'),
'MP4' => translate('MP4'),
@ -459,8 +452,8 @@ foreach ( $tabs as $name=>$value ) {
if ( $tab != 'general' ) {
?>
<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[StorageId]" value="<?= validHtmlStr($monitor->StorageId() ) ?>"/>
<input type="hidden" name="newMonitor[LinkedMonitors]" value="<?php echo (null !== $monitor->LinkedMonitors())?validHtmlStr($monitor->LinkedMonitors()):'' ?>"/>
<?php
foreach ( $monitor->GroupIds() as $group_id ) {
@ -529,6 +522,7 @@ if ( $tab != 'source' ) {
}
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[VideoWriter]" value="<?php echo validHtmlStr($monitor->VideoWriter()) ?>"/>
<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><input type="text" name="newMonitor[Name]" value="<?php echo validHtmlStr($monitor->Name()) ?>"/></td>
</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>
<td><?php echo translate('Server') ?></td><td>
<?php
@ -620,18 +618,6 @@ switch ( $tab ) {
$servers[$Server->Id()] = $Server->Name();
}
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>
</tr>
@ -921,7 +907,32 @@ if ( $monitor->Type() == 'Local' ) {
}
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>
<?php
$videowriteropts = array(
@ -1102,15 +1113,17 @@ if ( canEdit('Control') ) {
<tr>
<td><?php echo translate('SignalCheckColour') ?></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>
</td>
</tr>
<tr>
<td><?php echo translate('WebColour') ?></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>
<i class="material-icons" data-on-click="random_WebColour">sync</i>
</td>
</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>
</div>
</form>
<?php
} else if ( $tab == 'users' ) {
?>
@ -278,15 +276,10 @@ foreach ( array_map('basename', glob('skins/'.$skin.'/css/*',GLOB_ONLYDIR)) as $
<td class="colPath"><?php echo makePopupLink('?view=storage&amp;id='.$Storage->Id(), 'zmStorage', 'storage', validHtmlStr($Storage->Path()), $canEdit ) ?></td>
<td class="colType"><?php echo makePopupLink('?view=storage&amp;id='.$Storage->Id(), 'zmStorage', 'storage', validHtmlStr($Storage->Type()), $canEdit ) ?></td>
<td class="colScheme"><?php echo makePopupLink('?view=storage&amp;id='.$Storage->Id(), 'zmStorage', 'storage', validHtmlStr($Storage->Scheme()), $canEdit ) ?></td>
<td class="colServer"><?php
echo makePopupLink('?view=storage&amp;id='.$Storage->Id(), 'zmStorage', 'storage', validHtmlStr($Storage->Server()->Name()), $canEdit ) ?></td>
<td class="colDiskSpace">
<?php echo
human_filesize($Storage->disk_used_space()) . ' of ' . human_filesize($Storage->disk_total_space())
?>
</td>
<td class="colServer"><?php echo makePopupLink('?view=storage&amp;id='.$Storage->Id(), 'zmStorage', 'storage', validHtmlStr($Storage->Server()->Name()), $canEdit ) ?></td>
<td class="colDiskSpace"><?php echo human_filesize($Storage->disk_used_space()) . ' of ' . human_filesize($Storage->disk_total_space()) ?></td>
<td class="ColEvents"><?php echo count($Storage->Events()).' using '.human_filesize($Storage->event_disk_space()) ?></td>
<td class="colMark"><input type="checkbox" name="markIds[]" value="<?php echo $Storage->Id() ?>" data-on-click-this="configureDeleteButton"<?php if ( count($Storage->Events()) or !$canEdit ) { ?> disabled="disabled"<?php } ?><?php echo count($Storage->Events()) ? ' title="Can\' delete as long as there are events stored here."' : ''?>/></td>
<td class="colMark"><input type="checkbox" name="markIds[]" value="<?php echo $Storage->Id() ?>" data-on-click-this="configureDeleteButton"<?php if ( count($Storage->Events()) or !$canEdit ) { ?> disabled="disabled"<?php } ?><?php echo count($Storage->Events()) ? ' title="Can\'t delete as long as there are events stored here."' : ''?>/></td>
</tr>
<?php } #end foreach Server ?>
</tbody>
@ -319,23 +312,28 @@ foreach ( array_map('basename', glob('skins/'.$skin.'/css/*',GLOB_ONLYDIR)) as $
}
function updateSelected() {
# Turn them all off, then selectively turn the checked ones back on
dbQuery('UPDATE `Users` SET `APIEnabled`=0');
foreach ( $_REQUEST["tokenUids"] as $markUid ) {
$minTime = time();
dbQuery('UPDATE `Users` SET `TokenMinExpiry`=? WHERE `Id`=?', array($minTime, $markUid));
if ( isset($_REQUEST['tokenUids']) ) {
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['apiUids']) ) {
foreach ( $_REQUEST['apiUids'] as $markUid ) {
dbQuery('UPDATE `Users` SET `APIEnabled`=1 WHERE `Id`=?', array($markUid));
}
}
echo '<span class="timedSuccessBox">'.translate('Updated').'</span>';
}
if ( array_key_exists('revokeAllTokens',$_POST) ) {
if ( array_key_exists('revokeAllTokens', $_POST) ) {
revokeAllTokens();
}
if ( array_key_exists('updateSelected',$_POST) ) {
if ( array_key_exists('updateSelected', $_POST) ) {
updateSelected();
}
?>

View File

@ -24,7 +24,11 @@ if ( !canEdit('System') ) {
}
?>
<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-content">
<div class="modal-header">
@ -32,9 +36,6 @@ if ( !canEdit('System') ) {
<h2 class="modal-title"><?php echo translate('RunState') ?></h2>
</div>
<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">
<label for="runState" class="col-sm-3 control-label">Change State</label>

View File

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