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

pull/2993/head
Isaac Connor 2020-07-20 18:40:59 -04:00
commit a70b329ce3
69 changed files with 1304 additions and 1025 deletions

4
.github/stale.yml vendored
View File

@ -1,10 +1,10 @@
# Configuration for probot-stale - https://github.com/probot/stale
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 60
daysUntilStale: 180
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
daysUntilClose: 30
# Issues with these labels will never be considered stale
exemptLabels:

View File

@ -357,6 +357,7 @@ EOF
%{_bindir}/zmtelemetry.pl
%{_bindir}/zmx10.pl
%{_bindir}/zmonvif-probe.pl
%{_bindir}/zmonvif-trigger.pl
%{_bindir}/zmstats.pl
%{_bindir}/zmrecover.pl

View File

@ -21,8 +21,8 @@ override_dh_auto_configure:
-DCMAKE_BUILD_TYPE=Release \
-DZM_CONFIG_DIR="/etc/zm" \
-DZM_CONFIG_SUBDIR="/etc/zm/conf.d" \
-DZM_RUNDIR="/var/run/zm" \
-DZM_SOCKDIR="/var/run/zm" \
-DZM_RUNDIR="/run/zm" \
-DZM_SOCKDIR="/run/zm" \
-DZM_TMPDIR="/tmp/zm" \
-DZM_CGIDIR="/usr/lib/zoneminder/cgi-bin" \
-DZM_CACHEDIR="/var/cache/zoneminder/cache" \

View File

@ -21,8 +21,8 @@ override_dh_auto_configure:
-DCMAKE_BUILD_TYPE=Release \
-DZM_CONFIG_DIR="/etc/zm" \
-DZM_CONFIG_SUBDIR="/etc/zm/conf.d" \
-DZM_RUNDIR="/var/run/zm" \
-DZM_SOCKDIR="/var/run/zm" \
-DZM_RUNDIR="/run/zm" \
-DZM_SOCKDIR="/run/zm" \
-DZM_TMPDIR="/tmp/zm" \
-DZM_CGIDIR="/usr/lib/zoneminder/cgi-bin" \
-DZM_CACHEDIR="/var/cache/zoneminder/cache" \

View File

@ -3,10 +3,157 @@ Debian
.. contents::
Easy Way: Debian Buster
------------------------
This procedure will guide you through the installation of ZoneMinder on Debian 10 (Buster).
**Step 1:** Make sure your system is up to date
Open a console and use ``su`` command to become root.
::
apt update
apt upgrade
**Step 2:** Setup Sudo (optional but recommended)
By default Debian does not come with sudo, so you have to install it and configure it manually.
This step is optional but recommended and the following instructions assume that you have setup sudo.
If you prefer to setup ZoneMinder as root, do it at your own risk and adapt the following instructions accordingly.
::
apt install sudo
usermod -a -G sudo <username>
exit
Now your terminal session is back under your normal user. You can check that
you are now part of the sudo group with the command ``groups``, "sudo" should
appear in the list. If not, run ``newgrp sudo`` and check again with ``groups``.
**Step 3:** Install Apache and MySQL
These are not dependencies for the ZoneMinder package as they could be
installed elsewhere. If they are not installed yet in your system, you have to
trigger their installation manually.
::
sudo apt install apache2 mysql-server
**Step 4:** Add ZoneMinder's Package repository to your apt sources
ZoneMinder's Debian packages are not included in Debian's official package
repositories. To be able to install ZoneMinder with APT, you have to edit the
list of apt sources and add ZoneMinder's repository.
::
sudo nano /etc/apt/sources.list
Add the following to the bottom of the file
::
# ZoneMinder repository
deb https://zmrepo.zoneminder.com/debian/release-1.34 stretch/
CTRL+o and <Enter> to save
CTRL+x to exit
Because ZoneMinder's package repository provides a secure connection through HTTPS, apt must be enabled for HTTPS.
::
sudo apt install apt-transport-https
Finally, download the GPG key for ZoneMinder's repository:
::
wget -O - https://zmrepo.zoneminder.com/debian/archive-keyring.gpg | sudo apt-key add -
**Step 5:** Install ZoneMinder
::
sudo apt update
sudo apt install zoneminder
**Step 6:** Read the Readme
The rest of the install process is covered in the README.Debian, so feel free to have
a read.
::
zcat /usr/share/doc/zoneminder/README.Debian.gz
**Step 7:** Enable ZoneMinder service
::
sudo systemctl enable zoneminder.service
**Step 8:** Configure Apache
The following commands will setup the default /zm virtual directory and configure
required apache modules.
::
sudo a2enconf zoneminder
sudo a2enmod rewrite
sudo a2enmod cgi # this is done automatically when installing the package. Redo this command manually only for troubleshooting.
**Step 9:** Edit Timezone in PHP
Automated way:
::
sudo sed -i "s/;date.timezone =/date.timezone = $(sed 's/\//\\\//' /etc/timezone)/g" /etc/php/7.0/apache2/php.ini
Manual way
::
sudo nano /etc/php/7.0/apache2/php.ini
Search for [Date] (Ctrl + w then type Date and press Enter) and change
date.timezone for your time zone. Don't forget to remove the ; from in front
of date.timezone.
::
[Date]
; Defines the default timezone used by the date functions
; http://php.net/date.timezone
date.timezone = America/New_York
CTRL+o then [Enter] to save
CTRL+x to exit
**Step 10:** Start ZoneMinder
Reload Apache to enable your changes and then start ZoneMinder.
::
sudo systemctl reload apache2
sudo systemctl start zoneminder
You are now ready to go with ZoneMinder. Open a browser and type either ``localhost/zm`` one the local machine or ``{IP-OF-ZM-SERVER}/zm`` if you connect from a remote computer.
Easy Way: Debian Stretch
------------------------
This procedure will guide you through the installation of ZoneMinder on Debian 9 (Stretch). This section has been tested with ZoneMinder 1.32.3 on Debian 9.8.
This procedure will guide you through the installation of ZoneMinder on Debian 9 (Stretch). This section has been tested with ZoneMinder 1.34 on Debian 9.8.
**Step 1:** Make sure your system is up to date
@ -52,7 +199,7 @@ Add the following to the bottom of the file
::
# ZoneMinder repository
deb https://zmrepo.zoneminder.com/debian/release stretch/
deb https://zmrepo.zoneminder.com/debian/release-1.34 stretch/
CTRL+o and <Enter> to save
CTRL+x to exit
@ -275,7 +422,6 @@ CTRL+x to exit
**Step 12:** Please check the configuration
Zoneminder 1.32.x
1. Check path of ZM_PATH in '/etc/zm/conf.d/zmcustom.conf' is ZM_PATH_ZMS=/zm/cgi-bin/nph-zms
::
cat /etc/zm/conf.d/zmcustom.conf
@ -309,8 +455,8 @@ Reload Apache to enable your changes and then start ZoneMinder.
::
{
"version": "1.29.0",
"apiversion": "1.29.0.1"
"version": "1.34.0",
"apiversion": "1.34.0.1"
}
**Congratulations** Your installation is complete

View File

@ -53,7 +53,7 @@ ZoneMinder releases are now being hosted at RPM Fusion. New users should navigat
Note that RHEL/CentOS 7 users should use yum instead of dnf.
Once ZoneMinder has been installed, it is critically important that you read the README file under /usr/share/doc/zoneminder. ZoneMinder will not run without completing the steps outlined in the README.
Once ZoneMinder has been installed, it is critically important that you read the README file under /usr/share/doc/zoneminder-common. ZoneMinder will not run without completing the steps outlined in the README.
How to Install Nightly Development Builds
-----------------------------------------
@ -191,7 +191,7 @@ Now clone the ZoneMinder git repository from your home folder:
git clone https://github.com/ZoneMinder/zoneminder
cd zoneminder
This will create a sub-folder called ZoneMinder, which will contain the latest development source code.
This will create a sub-folder called zoneminder, which will contain the latest development source code.
If you have previsouly cloned the ZoneMinder git repo and wish to update it to the most recent, then issue these commands instead:

View File

@ -32,12 +32,10 @@ BULK_FRAME_INTERVAL - Traditionally ZoneMinder writes an entry into the Frames d
EVENT_CLOSE_MODE - When a monitor is running in a continuous recording mode (Record or Mocord) events are usually closed after a fixed period of time (the section length). However in Mocord mode it is possible that motion detection may occur near the end of a section. This option controls what happens when an alarm occurs in Mocord mode. The 'time' setting means that the event will be closed at the end of the section regardless of alarm activity. The 'idle' setting means that the event will be closed at the end of the section if there is no alarm activity occurring at the time otherwise it will be closed once the alarm is over meaning the event may end up being longer than the normal section length. The 'alarm' setting means that if an alarm occurs during the event, the event will be closed once the alarm is over regardless of when this occurs. This has the effect of limiting the number of alarms to one per event and the events will be shorter than the section length if an alarm has occurred.
CREATE_ANALYSIS_IMAGES - By default during an alarm ZoneMinder records both the raw captured image and one that has been analysed and had areas where motion was detected outlined. This can be very useful during zone configuration or in analysing why events occurred. However it also incurs some overhead and in a stable system may no longer be necessary. This parameter allows you to switch the generation of these images off.
WEIGHTED_ALARM_CENTRES - ZoneMinder will always calculate the centre point of an alarm in a zone to give some indication of where on the screen it is. This can be used by the experimental motion tracking feature or your own custom extensions. In the alarmed or filtered pixels mode this is a simple midpoint between the extents of the detected pxiesl. However in the blob method this can instead be calculated using weighted pixel locations to give more accurate positioning for irregularly shaped blobs. This method, while more precise is also slower and so is turned off by default.
EVENT_IMAGE_DIGITS - As event images are captured they are stored to the filesystem with a numerical index. By default this index has three digits so the numbers start 001, 002 etc. This works works for most scenarios as events with more than 999 frames are rarely captured. However if you have extremely long events and use external applications then you may wish to increase this to ensure correct sorting of images in listings etc. Warning, increasing this value on a live system may render existing events unviewable as the event will have been saved with the previous scheme. Decreasing this value should have no ill effects.
DEFAULT_ASPECT_RATIO - When specifying the dimensions of monitors you can click a checkbox to ensure that the width stays in the correct ratio to the height, or vice versa. This setting allows you to indicate what the ratio of these settings should be. This should be specified in the format <width value>:<height value> and the default of 4:3 normally be acceptable but 11:9 is another common setting. If the checkbox is not clicked when specifying monitor dimensions this setting has no effect.
USER_SELF_EDIT - Ordinarily only users with system edit privilege are able to change users details. Switching this option on allows ordinary users to change their passwords and their language settings
USER_SELF_EDIT - Ordinarily only users with system edit privilege are able to change users details. Switching this option on allows ordinary users to change their passwords and their language settings

View File

@ -252,7 +252,7 @@ our @options = (
authentication which passes an independently authentication
'remote' user via http. In this case ZoneMinder would use the
supplied user without additional authentication provided such a
user is configured ion ZoneMinder.
user is configured in ZoneMinder.
`,
requires => [ { name=>'ZM_OPT_USE_AUTH', value=>'yes' } ],
type => {
@ -2635,22 +2635,6 @@ our @options = (
type => $types{boolean},
category => 'hidden',
},
{
name => 'ZM_CREATE_ANALYSIS_IMAGES',
default => 'yes',
description => 'Create analysed alarm images with motion outlined',
help => q`
By default during an alarm ZoneMinder records both the raw
captured image and one that has been analysed and had areas
where motion was detected outlined. This can be very useful
during zone configuration or in analysing why events occurred.
However it also incurs some overhead and in a stable system may
no longer be necessary. This parameter allows you to switch the
generation of these images off.
`,
type => $types{boolean},
category => 'config',
},
{
name => 'ZM_WEIGHTED_ALARM_CENTRES',
default => 'no',

View File

@ -45,7 +45,7 @@ use ZoneMinder::Config qw(:all);
use Time::HiRes qw( usleep );
use URI;
our $ADDRESS;
our $uri;
sub open {
my $self = shift;
@ -55,8 +55,7 @@ sub open {
# Has no scheme at the beginning, so won't parse as a URI
$self->{Monitor}->{ControlAddress} = 'http://'.$self->{Monitor}->{ControlAddress};
}
my $uri = URI->new($self->{Monitor}->{ControlAddress});
$ADDRESS = $uri->scheme.'://'.$uri->authority().$uri->path().($uri->port()?':'.$uri->port():'');
$uri = URI->new($self->{Monitor}->{ControlAddress});
use LWP::UserAgent;
$self->{ua} = LWP::UserAgent->new;
@ -65,14 +64,21 @@ sub open {
$self->{state} = 'closed';
my ( $username, $password, $host ) = ( $uri->authority() =~ /^([^:]+):([^@]*)@(.+)$/ );
$uri->userinfo(undef);
my $realm = $self->{Monitor}->{ControlDevice};
$self->{ua}->credentials($ADDRESS, $realm, $username, $password);
$self->{ua}->credentials($uri->host_port(), $realm, $username, $password);
my $url = '/axis-cgi/param.cgi?action=list&group=Properties.PTZ.PTZ';
# test auth
my $res = $self->{ua}->get($ADDRESS.'/cgi/ptdc.cgi');
my $res = $self->{ua}->get($uri->canonical().$url);
if ( $res->is_success ) {
if ( $res->content() ne "Properties.PTZ.PTZ=yes\n" ) {
Warning('Response suggests that camera doesn\'t support PTZ. Content:('.$res->content().')');
}
$self->{state} = 'open';
return;
}
@ -85,23 +91,18 @@ sub open {
}
if ( $$headers{'www-authenticate'} ) {
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($host, $realm, $username, $password);
$res = $self->{ua}->get($ADDRESS);
$self->{ua}->credentials($uri->host_port(), $realm, $username, $password);
$res = $self->{ua}->get($uri->canonical().$url);
if ( $res->is_success() ) {
Info("Auth succeeded after setting realm to $realm. You can set this value in the Control Device field to speed up connections and remove these log entries.");
$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
Error('Authentication still failed after updating REALM status: '.$res->status_line);
} else {
Error('Authentication failed, not a REALM problem');
}
@ -111,6 +112,8 @@ sub open {
} else {
Debug('No headers line');
} # end if headers
} else {
Warning('Failed to open '.$uri->canonical().$url.' status: '.$res->status_line());
} # end if $res->status_line() eq '401 Unauthorized'
} # end sub open
@ -120,11 +123,11 @@ sub sendCmd {
$self->printMsg($cmd, 'Tx');
my $url = $ADDRESS.$cmd;
my $url = $uri->canonical().$cmd;
my $res = $self->{ua}->get($url);
if ( $res->is_success ) {
Debug('sndCmd command: ' . $url . ' content: '.$res->content);
Debug('sndCmd command: '.$url.' content: '.$res->content);
return !undef;
}

View File

@ -143,10 +143,10 @@ sub PutCmd {
} else {
Info('Missing username and password in Control Address.');
}
Fatal($res->status_line);
Error($res->status_line);
}
} else {
Fatal($res->status_line);
Error($res->status_line);
}
} # end unless res->is_success
} # end sub putCmd

View File

@ -133,6 +133,7 @@ sub sendCmd {
my $result = undef;
$self->printMsg($cmd, 'Tx');
$self->printMsg($msg, 'Tx');
my $server_endpoint = 'http://'.$address.':'.$port.'/'.$cmd;
my $req = HTTP::Request->new(POST => $server_endpoint);
@ -147,6 +148,7 @@ sub sendCmd {
if ( $res->is_success ) {
$result = !undef;
Debug("Result: " . $res->content());
} else {
Error("After sending PTZ command, camera returned the following error:'".$res->status_line()."'\nMSG:$msg\nResponse:".$res->content);
}
@ -208,12 +210,56 @@ sub reset {
$self->sendCmd($cmd, $msg, $content_type);
}
sub moveMap {
my $self = shift;
my $params = shift;
my $x = $self->getParam($params,'xcoord');
my $y = $self->getParam($params,'ycoord');
Debug("Move map to $x x $y");
my $cmd = 'onvif/PTZ';
my $msg ='<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">' . ((%identity) ? authentificationHeader($identity{username}, $identity{password}) : '') . '<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<AbsoluteMove xmlns="http://www.onvif.org/ver20/ptz/wsdl">
<ProfileToken>' . $profileToken . '</ProfileToken>
<Position><PanTilt x="'.$x.'" y="'.$y.'" xmlns="http://www.onvif.org/ver10/schema"/></Position>
<Speed><Zoom x="1" xmlns="http://www.onvif.org/ver10/schema"/></Speed>
</AbsoluteMove></s:Body></s:Envelope>';
my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/ContinuousMove"';
$self->sendCmd($cmd, $msg, $content_type);
}
sub moveRel {
my $self = shift;
my $params = shift;
my $x = $self->getParam($params,'xcoord');
my $speed = $self->getParam($params,'speed');
my $y = $self->getParam($params,'ycoord');
Debug("Move rel to $x x $y");
my $cmd = 'onvif/PTZ';
my $msg ='<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">' . ((%identity) ? authentificationHeader($identity{username}, $identity{password}) : '') . '<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<RelativeMove xmlns="http://www.onvif.org/ver20/ptz/wsdl">
<ProfileToken>' . $profileToken . '</ProfileToken>
<Translation>
<PanTilt x="'.$x.'" y="'.$y.'" xmlns="http://www.onvif.org/ver10/schema" space="http://www.onvif.org/ver10/tptz/PanTiltSpaces/PositionGenericSpace"/>
<Zoom x="1"/>
</Translation>
<!--<Speed><Zoom x="'.$speed.'" xmlns="http://www.onvif.org/ver10/schema" space="http://www.onvif.org/ver10/tptz/PanTiltSpaces/PositionGenericSpace"/></Speed>_-->
</RelativeMove></s:Body></s:Envelope>';
my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/ContinuousMove"';
$self->sendCmd($cmd, $msg, $content_type);
}
#Up Arrow
sub moveConUp {
Debug('Move Up');
my $self = shift;
my $cmd = 'onvif/PTZ';
my $msg ='<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">' . ((%identity) ? authentificationHeader($identity{username}, $identity{password}) : '') . '<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><ContinuousMove xmlns="http://www.onvif.org/ver20/ptz/wsdl"><ProfileToken>' . $profileToken . '</ProfileToken><Velocity><PanTilt x="0" y="0.5" xmlns="http://www.onvif.org/ver10/schema"/></Velocity></ContinuousMove></s:Body></s:Envelope>';
my $msg ='<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">' . ((%identity) ? authentificationHeader($identity{username}, $identity{password}) : '') . '<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ContinuousMove xmlns="http://www.onvif.org/ver20/ptz/wsdl">
<ProfileToken>' . $profileToken . '</ProfileToken>
<Velocity><PanTilt x="0" y="0.5" xmlns="http://www.onvif.org/ver10/schema"/></Velocity>
</ContinuousMove></s:Body></s:Envelope>';
my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/ContinuousMove"';
$self->sendCmd($cmd, $msg, $content_type);
$self->autoStop($self->{Monitor}->{AutoStopTimeout});

View File

@ -146,15 +146,15 @@ sub zmDbGetMonitors {
if ( $function ) {
if ( $function == DB_MON_CAPT ) {
$sql .= " where Function >= 'Monitor'";
$sql .= " where `Function` >= 'Monitor'";
} elsif ( $function == DB_MON_ACTIVE ) {
$sql .= " where Function > 'Monitor'";
$sql .= " where `Function` > 'Monitor'";
} elsif ( $function == DB_MON_MOTION ) {
$sql .= " where Function = 'Modect' or Function = 'Mocord'";
$sql .= " where `Function` = 'Modect' or Function = 'Mocord'";
} elsif ( $function == DB_MON_RECORD ) {
$sql .= " where Function = 'Record' or Function = 'Mocord'";
$sql .= " where `Function` = 'Record' or Function = 'Mocord'";
} elsif ( $function == DB_MON_PASSIVE ) {
$sql .= " where Function = 'Nodect'";
$sql .= " where `Function` = 'Nodect'";
}
}
my $sth = $dbh->prepare_cached( $sql );

View File

@ -368,7 +368,7 @@ sub delete {
return;
}
if ( !($event->Storage()->Path() and -e $event->Storage()->Path()) ) {
Warning('Not deleting event because storage path doesn\'t exist');
Warning('Not deleting event because storage path ('.$event->Storage()->Path().') doesn\'t exist');
return;
}
}

View File

@ -345,7 +345,7 @@ sub createEvent {
." to ".$frame->{capturePath}.": $!"
);
setFileOwner( $frame->{capturePath} );
if ( 0 && $Config{ZM_CREATE_ANALYSIS_IMAGES} ) {
if ( $event->{SaveJPEGs} > 1 ) {
$frame->{analysePath} = sprintf(
"%s/%0".$Config{ZM_EVENT_IMAGE_DIGITS}
."d-analyse.jpg"

View File

@ -162,6 +162,8 @@ our $mem_data = {
imagesize => { type=>'uint32', seq=>$mem_seq++ },
epadding1 => { type=>'uint32', seq=>$mem_seq++ },
startup_time => { type=>'time_t64', seq=>$mem_seq++ },
zmc_heartbeat_time => { type=>'time_t64', seq=>$mem_seq++ },
zma_heartbeat_time => { type=>'time_t64', seq=>$mem_seq++ },
last_write_time => { type=>'time_t64', seq=>$mem_seq++ },
last_read_time => { type=>'time_t64', seq=>$mem_seq++ },
control_state => { type=>'uint8[256]', seq=>$mem_seq++ },

View File

@ -49,9 +49,9 @@ my %options;
GetOptions(
'id=i' =>\$id,
'command=s' =>\$options{command},
'xcoord=i' =>\$options{xcoord},
'ycoord=i' =>\$options{ycoord},
'speed=i' =>\$options{speed},
'xcoord=f' =>\$options{xcoord},
'ycoord=f' =>\$options{ycoord},
'speed=f' =>\$options{speed},
'step=i' =>\$options{step},
'panspeed=i' =>\$options{panspeed},
'tiltspeed=i' =>\$options{tiltspeed},

View File

@ -160,7 +160,7 @@ if ( !$server_up ) {
use ZoneMinder::Server qw(CpuLoad);
if ( ! defined $dbh->do(q{UPDATE Servers SET Status=?,TotalMem=?,FreeMem=?,TotalSwap=?,FreeSwap=? WHERE Id=?}, undef,
'NotRunning', &totalmem, &freemem, &totalswap, &freeswap, $Config{ZM_SERVER_ID} ) ) {
Error("Failed Updating status of Server record to Not RUnning for Id=$Config{ZM_SERVER_ID}" . $dbh->errstr());
Error('Failed Updating status of Server record to Not Running for Id='.$Config{ZM_SERVER_ID}.': '.$dbh->errstr());
}
}
# Server is not up. Some commands can still be handled
@ -173,7 +173,7 @@ if ( !$server_up ) {
print("stopped\n");
exit();
} elsif ( $command ne 'startup' ) {
print('Unable to connect to server using socket at ' . SOCK_FILE . "\n");
print('Unable to connect to server using socket at '.SOCK_FILE."\n");
exit(-1);
}
@ -189,10 +189,10 @@ if ( !$server_up ) {
socket(CLIENT, PF_UNIX, SOCK_STREAM, 0) or Fatal("Can't open socket: $!");
my $attempts = 0;
while( !connect(CLIENT, $saddr) ) {
while ( !connect(CLIENT, $saddr) ) {
$attempts++;
Debug('Waiting for zmdc.pl server process at '.SOCK_FILE.", attempt $attempts");
Fatal("Can't connect: $!") if $attempts > MAX_CONNECT_DELAY;
Debug('Waiting for zmdc.pl server process at '.SOCK_FILE.', attempt '.$attempts);
Fatal('Can\'t connect to zmdc.pl server process at '.SOCK_FILE.': '.$!) if $attempts > MAX_CONNECT_DELAY;
usleep(200000);
} # end while
} elsif ( defined($cpid) ) {
@ -255,13 +255,13 @@ sub run {
close($PID);
} else {
# Log not initialized at this point so use die instead
die "Can't open pid file at ".ZM_PID."\n";
die 'Can\'t open pid file at '.ZM_PID."\n";
}
my $fd = 0;
# This also closes dbh and CLIENT and SERVER
while( $fd < POSIX::sysconf(&POSIX::_SC_OPEN_MAX) ) {
while ( $fd < POSIX::sysconf(&POSIX::_SC_OPEN_MAX) ) {
POSIX::close($fd++);
}
@ -301,13 +301,14 @@ sub run {
my $timeout = 1;
my $secs_count = 0;
while( !$zm_terminate ) {
while ( !$zm_terminate ) {
if ( $Config{ZM_SERVER_ID} ) {
if ( ! ( $secs_count % 60 ) ) {
while ( (!$zm_terminate) and !($dbh and $dbh->ping()) ) {
Warning("Not connected to db ($dbh)".($dbh?' ping('.$dbh->ping().')':''). ($DBI::errstr?" errstr($DBI::errstr)":'').' Reconnecting');
$dbh = zmDbConnect();
sleep 10 if !$dbh;
}
last if $zm_terminate;

View File

@ -102,7 +102,7 @@ $SIG{__DIE__} = \&handler;
# =========================================================================
# Debug
use Data::Hexdumper qw(hexdump);
#use Data::Hexdumper qw(hexdump);
#use Devel::Peek;
sub dump_mapped {
@ -116,12 +116,12 @@ sub dump_mapped {
printf("Mapped at %x\n", $monitor->{MMapAddr});
# Dump($mmap);
if ( $mmap && $$mmap ) {
print hexdump(
data => $$mmap, # what to dump
output_format => ' %4a : %S %S %S %S %S %S %S %S : %d',
# start_position => 336, # start at this offset ...
end_position => 400 # ... and end at this offset
);
#print hexdump(
#data => $$mmap, # what to dump
#output_format => ' %4a : %S %S %S %S %S %S %S %S : %d',
## start_position => 336, # start at this offset ...
#end_position => 400 # ... and end at this offset
#);
}
}

View File

@ -48,6 +48,49 @@ while( 1 ) {
$dbh->do('DELETE FROM Events_Week WHERE StartTime < DATE_SUB(NOW(), INTERVAL 1 week)') or Error($dbh->errstr());
$dbh->do('DELETE FROM Events_Month WHERE StartTime < DATE_SUB(NOW(), INTERVAL 1 month)') or Error($dbh->errstr());
# Prune the Logs table if required
if ( $Config{ZM_LOG_DATABASE_LIMIT} ) {
if ( $Config{ZM_LOG_DATABASE_LIMIT} =~ /^\d+$/ ) {
# Number of rows
my $selectLogRowCountSql = 'SELECT count(*) AS `Rows` FROM `Logs`';
my $selectLogRowCountSth = $dbh->prepare_cached( $selectLogRowCountSql )
or Fatal("Can't prepare '$selectLogRowCountSql': ".$dbh->errstr());
my $res = $selectLogRowCountSth->execute()
or Fatal("Can't execute: ".$selectLogRowCountSth->errstr());
my $row = $selectLogRowCountSth->fetchrow_hashref();
my $logRows = $row->{Rows};
if ( $logRows > $Config{ZM_LOG_DATABASE_LIMIT} ) {
my $deleteLogByRowsSql = 'DELETE low_priority FROM `Logs` ORDER BY `TimeKey` ASC LIMIT ?';
my $deleteLogByRowsSth = $dbh->prepare_cached( $deleteLogByRowsSql )
or Fatal("Can't prepare '$deleteLogByRowsSql': ".$dbh->errstr());
$res = $deleteLogByRowsSth->execute( $logRows - $Config{ZM_LOG_DATABASE_LIMIT} )
or Fatal("Can't execute: ".$deleteLogByRowsSth->errstr());
if ( $deleteLogByRowsSth->rows() ) {
Debug('Deleted '.$deleteLogByRowsSth->rows().' log table entries by count');
}
}
} else {
# Time of record
# 7 days is invalid. We need to remove the s
if ( $Config{ZM_LOG_DATABASE_LIMIT} =~ /^(.*)s$/ ) {
$Config{ZM_LOG_DATABASE_LIMIT} = $1;
}
my $deleted_rows;
do {
my $deleteLogByTimeSql =
'DELETE FROM `Logs`
WHERE `TimeKey` < unix_timestamp(now() - interval '.$Config{ZM_LOG_DATABASE_LIMIT}.') LIMIT 100';
my $deleteLogByTimeSth = $dbh->prepare_cached( $deleteLogByTimeSql )
or Fatal("Can't prepare '$deleteLogByTimeSql': ".$dbh->errstr());
my $res = $deleteLogByTimeSth->execute()
or Fatal("Can't execute: ".$deleteLogByTimeSth->errstr());
$deleted_rows = $deleteLogByTimeSth->rows();
Debug("Deleted $deleted_rows log table entries by time");
} while ( $deleted_rows );
}
} # end if ZM_LOG_DATABASE_LIMIT
sleep($Config{ZM_STATS_UPDATE_INTERVAL});
} # end while (1)

View File

@ -119,7 +119,6 @@ if ( !$monitor->{CanMoveMap} ) {
}
}
Debug("Found monitor for id '$monitor'");
exit(-1) if !zmMemVerify($monitor);
sub Suspend {

View File

@ -48,11 +48,12 @@ Camera::Camera(
record_audio(p_record_audio),
bytes(0)
{
linesize = width * colours;
pixels = width * height;
imagesize = pixels * colours;
imagesize = height * linesize;
Debug(2,"New camera id: %d width: %d height: %d colours: %d subpixelorder: %d capture: %d",
monitor_id, width, height, colours, subpixelorder, capture);
Debug(2, "New camera id: %d width: %d line size: %d height: %d colours: %d subpixelorder: %d capture: %d",
monitor_id, width, linesize, height, colours, subpixelorder, capture);
monitor = NULL;
}

View File

@ -41,6 +41,7 @@ protected:
Monitor * monitor; // Null on instantiation, set as soon as possible.
SourceType type;
unsigned int width;
unsigned int linesize;
unsigned int height;
unsigned int colours;
unsigned int subpixelorder;
@ -70,6 +71,7 @@ public:
bool IscURL() const { return type == CURL_SRC; }
bool IsVNC() const { return type == VNC_SRC; }
unsigned int Width() const { return width; }
unsigned int LineSize() const { return linesize; }
unsigned int Height() const { return height; }
unsigned int Colours() const { return colours; }
unsigned int SubpixelOrder() const { return subpixelorder; }

View File

@ -63,31 +63,31 @@ static enum AVPixelFormat get_hw_format(
}
#if !LIBAVUTIL_VERSION_CHECK(56, 22, 0, 14, 0)
static enum AVPixelFormat find_fmt_by_hw_type(const enum AVHWDeviceType type) {
enum AVPixelFormat fmt;
switch (type) {
enum AVPixelFormat fmt;
switch (type) {
case AV_HWDEVICE_TYPE_VAAPI:
fmt = AV_PIX_FMT_VAAPI;
break;
fmt = AV_PIX_FMT_VAAPI;
break;
case AV_HWDEVICE_TYPE_DXVA2:
fmt = AV_PIX_FMT_DXVA2_VLD;
break;
fmt = AV_PIX_FMT_DXVA2_VLD;
break;
case AV_HWDEVICE_TYPE_D3D11VA:
fmt = AV_PIX_FMT_D3D11;
break;
fmt = AV_PIX_FMT_D3D11;
break;
case AV_HWDEVICE_TYPE_VDPAU:
fmt = AV_PIX_FMT_VDPAU;
break;
fmt = AV_PIX_FMT_VDPAU;
break;
case AV_HWDEVICE_TYPE_CUDA:
fmt = AV_PIX_FMT_CUDA;
break;
fmt = AV_PIX_FMT_CUDA;
break;
case AV_HWDEVICE_TYPE_VIDEOTOOLBOX:
fmt = AV_PIX_FMT_VIDEOTOOLBOX;
break;
fmt = AV_PIX_FMT_VIDEOTOOLBOX;
break;
default:
fmt = AV_PIX_FMT_NONE;
break;
}
return fmt;
fmt = AV_PIX_FMT_NONE;
break;
}
return fmt;
}
#endif
#endif
@ -174,6 +174,20 @@ FfmpegCamera::FfmpegCamera(
} else {
Panic("Unexpected colours: %d", colours);
}
// sws_scale needs 32bit aligned width and an extra 16 bytes padding, so recalculate imagesize, which was width*height*bytes_per_pixel
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
alignment = 32;
imagesize = av_image_get_buffer_size(imagePixFormat, width, height, alignment);
// av_image_get_linesize isn't aligned, so we have to do that.
linesize = FFALIGN(av_image_get_linesize(imagePixFormat, width, 0), alignment);
#else
alignment = 1;
linesize = FFALIGN(av_image_get_linesize(imagePixFormat, width, 0), alignment);
imagesize = avpicture_get_size(imagePixFormat, width, height);
#endif
Debug(1, "ffmpegcamera: width %d height %d linesize %d colours %d imagesize %d", width, height, linesize, colours, imagesize);
} // FfmpegCamera::FfmpegCamera
FfmpegCamera::~FfmpegCamera() {
@ -194,12 +208,12 @@ void FfmpegCamera::Terminate() {
int FfmpegCamera::PrimeCapture() {
if ( mCanCapture ) {
Info("Priming capture from %s, Closing", mPath.c_str());
Debug(1, "Priming capture from %s, Closing", mPath.c_str());
Close();
}
mVideoStreamId = -1;
mAudioStreamId = -1;
Info("Priming capture from %s", mPath.c_str());
Debug(1, "Priming capture from %s", mPath.c_str());
return OpenFfmpeg();
}
@ -608,16 +622,6 @@ int FfmpegCamera::OpenFfmpeg() {
mFrame->width = width;
mFrame->height = height;
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
int pSize = av_image_get_buffer_size(imagePixFormat, width, height, 1);
#else
int pSize = avpicture_get_size(imagePixFormat, width, height);
#endif
if ( (unsigned int)pSize != imagesize ) {
Error("Image size mismatch. Required: %d Available: %d", pSize, imagesize);
return -1;
}
#if HAVE_LIBSWSCALE
if ( !sws_isSupportedInput(mVideoCodecContext->pix_fmt) ) {
@ -1089,11 +1093,18 @@ int FfmpegCamera::transfer_to_image(
int size = av_image_fill_arrays(
output_frame->data, output_frame->linesize,
directbuffer, imagePixFormat, width, height,
(AV_PIX_FMT_RGBA == imagePixFormat ? 32 : 1)
alignment
);
if ( size < 0 ) {
Error("Problem setting up data pointers into image %s",
av_make_error_string(size).c_str());
} else {
Debug(4, "av_image_fill_array %dx%d alignment: %d = %d, buffer size is %d",
width, height, alignment, size, image.Size());
}
Debug(1, "ffmpegcamera: width %d height %d linesize %d colours %d imagesize %d", width, height, linesize, colours, imagesize);
if ( linesize != (unsigned int)output_frame->linesize[0] ) {
Error("Bad linesize expected %d got %d", linesize, output_frame->linesize[0]);
}
#else
avpicture_fill((AVPicture *)output_frame, directbuffer,

View File

@ -45,6 +45,8 @@ class FfmpegCamera : public Camera {
std::string hwaccel_device;
int frameCount;
int alignment; /* ffmpeg wants line sizes to be 32bit aligned. Especially 4.3+ */
#if HAVE_LIBAVFORMAT
AVFormatContext *mFormatContext;

View File

@ -108,6 +108,7 @@ Image::Image() {
if ( !initialised )
Initialise();
width = 0;
linesize = 0;
height = 0;
pixels = 0;
colours = 0;
@ -125,6 +126,7 @@ Image::Image( const char *filename ) {
if ( !initialised )
Initialise();
width = 0;
linesize = 0;
height = 0;
pixels = 0;
colours = 0;
@ -139,15 +141,42 @@ Image::Image( const char *filename ) {
update_function_pointers();
}
Image::Image( int p_width, int p_height, int p_colours, int p_subpixelorder, uint8_t *p_buffer ) {
Image::Image( int p_width, int p_height, int p_colours, int p_subpixelorder, uint8_t *p_buffer, unsigned int p_padding) {
if ( !initialised )
Initialise();
width = p_width;
height = p_height;
pixels = width*height;
colours = p_colours;
linesize = p_width * p_colours;
padding = p_padding;
subpixelorder = p_subpixelorder;
size = pixels*colours;
size = linesize*height + padding;
buffer = 0;
holdbuffer = 0;
if ( p_buffer ) {
allocation = size;
buffertype = ZM_BUFTYPE_DONTFREE;
buffer = p_buffer;
} else {
AllocImgBuffer(size);
}
text[0] = '\0';
update_function_pointers();
}
Image::Image( int p_width, int p_linesize, int p_height, int p_colours, int p_subpixelorder, uint8_t *p_buffer, unsigned int p_padding) {
if ( !initialised )
Initialise();
width = p_width;
linesize = p_linesize;
height = p_height;
pixels = width*height;
colours = p_colours;
padding = p_padding;
subpixelorder = p_subpixelorder;
size = linesize*height + padding;
buffer = 0;
holdbuffer = 0;
if ( p_buffer ) {
@ -167,20 +196,21 @@ Image::Image(const AVFrame *frame) {
text[0] = '\0';
width = frame->width;
linesize = frame->linesize[0];
height = frame->height;
pixels = width*height;
colours = ZM_COLOUR_RGB32;
subpixelorder = ZM_SUBPIX_ORDER_RGBA;
size = pixels*colours;
size = linesize * height;
buffer = 0;
holdbuffer = 0;
AllocImgBuffer(size);
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
av_image_fill_arrays(dest_frame->data, dest_frame->linesize,
buffer, AV_PIX_FMT_RGBA, width, height, 1);
buffer, AV_PIX_FMT_RGBA, width, height, 32);
#else
avpicture_fill( (AVPicture *)dest_frame, buffer,
AV_PIX_FMT_RGBA, width, height);
@ -212,6 +242,7 @@ Image::Image(const Image &p_image) {
if ( !initialised )
Initialise();
width = p_image.width;
linesize = p_image.linesize;
height = p_image.height;
pixels = p_image.pixels;
colours = p_image.colours;
@ -268,26 +299,26 @@ void Image::Deinitialise() {
void Image::Initialise() {
/* Assign the blend pointer to function */
if ( config.fast_image_blends ) {
if ( config.cpu_extensions && sseversion >= 20 ) {
if ( config.cpu_extensions && sse_version >= 20 ) {
fptr_blend = &sse2_fastblend; /* SSE2 fast blend */
Debug(4,"Blend: Using SSE2 fast blend function");
Debug(4, "Blend: Using SSE2 fast blend function");
} else if ( config.cpu_extensions && neonversion >= 1 ) {
#if defined(__aarch64__)
fptr_blend = &neon64_armv8_fastblend; /* ARM Neon (AArch64) fast blend */
Debug(4,"Blend: Using ARM Neon (AArch64) fast blend function");
Debug(4, "Blend: Using ARM Neon (AArch64) fast blend function");
#elif defined(__arm__)
fptr_blend = &neon32_armv7_fastblend; /* ARM Neon (AArch32) fast blend */
Debug(4,"Blend: Using ARM Neon (AArch32) fast blend function");
Debug(4, "Blend: Using ARM Neon (AArch32) fast blend function");
#else
Panic("Bug: Non ARM platform but neon present");
#endif
} else {
fptr_blend = &std_fastblend; /* standard fast blend */
Debug(4,"Blend: Using fast blend function");
Debug(4, "Blend: Using fast blend function");
}
} else {
fptr_blend = &std_blend;
Debug(4,"Blend: Using standard blend function");
Debug(4, "Blend: Using standard blend function");
}
__attribute__((aligned(64))) uint8_t blend1[128] = {
@ -325,22 +356,22 @@ void Image::Initialise() {
/* Assign the delta functions */
if ( config.cpu_extensions ) {
if ( sseversion >= 35 ) {
if ( sse_version >= 35 ) {
/* SSSE3 available */
fptr_delta8_rgba = &ssse3_delta8_rgba;
fptr_delta8_bgra = &ssse3_delta8_bgra;
fptr_delta8_argb = &ssse3_delta8_argb;
fptr_delta8_abgr = &ssse3_delta8_abgr;
fptr_delta8_gray8 = &sse2_delta8_gray8;
Debug(4,"Delta: Using SSSE3 delta functions");
} else if ( sseversion >= 20 ) {
Debug(4, "Delta: Using SSSE3 delta functions");
} else if ( sse_version >= 20 ) {
/* SSE2 available */
fptr_delta8_rgba = &sse2_delta8_rgba;
fptr_delta8_bgra = &sse2_delta8_bgra;
fptr_delta8_argb = &sse2_delta8_argb;
fptr_delta8_abgr = &sse2_delta8_abgr;
fptr_delta8_gray8 = &sse2_delta8_gray8;
Debug(4,"Delta: Using SSE2 delta functions");
Debug(4, "Delta: Using SSE2 delta functions");
} else if ( neonversion >= 1 ) {
/* ARM Neon available */
#if defined(__aarch64__)
@ -349,14 +380,14 @@ void Image::Initialise() {
fptr_delta8_argb = &neon64_armv8_delta8_argb;
fptr_delta8_abgr = &neon64_armv8_delta8_abgr;
fptr_delta8_gray8 = &neon64_armv8_delta8_gray8;
Debug(4,"Delta: Using ARM Neon (AArch64) delta functions");
Debug(4, "Delta: Using ARM Neon (AArch64) delta functions");
#elif defined(__arm__)
fptr_delta8_rgba = &neon32_armv7_delta8_rgba;
fptr_delta8_bgra = &neon32_armv7_delta8_bgra;
fptr_delta8_argb = &neon32_armv7_delta8_argb;
fptr_delta8_abgr = &neon32_armv7_delta8_abgr;
fptr_delta8_gray8 = &neon32_armv7_delta8_gray8;
Debug(4,"Delta: Using ARM Neon (AArch32) delta functions");
Debug(4, "Delta: Using ARM Neon (AArch32) delta functions");
#else
Panic("Bug: Non ARM platform but neon present");
#endif
@ -433,68 +464,28 @@ void Image::Initialise() {
fptr_deinterlace_4field_argb = &std_deinterlace_4field_argb;
fptr_deinterlace_4field_abgr = &std_deinterlace_4field_abgr;
fptr_deinterlace_4field_gray8 = &std_deinterlace_4field_gray8;
Debug(4,"Deinterlace: Using standard functions");
Debug(4, "Deinterlace: Using standard functions");
#if defined(__i386__) && !defined(__x86_64__)
/* Use SSE2 aligned memory copy? */
if ( config.cpu_extensions && sseversion >= 20 ) {
if ( config.cpu_extensions && sse_version >= 20 ) {
fptr_imgbufcpy = &sse2_aligned_memcpy;
Debug(4,"Image buffer copy: Using SSE2 aligned memcpy");
Debug(4, "Image buffer copy: Using SSE2 aligned memcpy");
} else {
fptr_imgbufcpy = &memcpy;
Debug(4,"Image buffer copy: Using standard memcpy");
Debug(4, "Image buffer copy: Using standard memcpy");
}
#else
fptr_imgbufcpy = &memcpy;
Debug(4,"Image buffer copy: Using standard memcpy");
Debug(4, "Image buffer copy: Using standard memcpy");
#endif
/* Code below relocated from zm_local_camera */
Debug( 3, "Setting up static colour tables" );
y_table = y_table_global;
uv_table = uv_table_global;
r_v_table = r_v_table_global;
g_v_table = g_v_table_global;
g_u_table = g_u_table_global;
b_u_table = b_u_table_global;
/*
y_table = new unsigned char[256];
for ( int i = 0; i <= 255; i++ )
{
unsigned char c = i;
if ( c <= 16 )
y_table[c] = 0;
else if ( c >= 235 )
y_table[c] = 255;
else
y_table[c] = (255*(c-16))/219;
}
uv_table = new signed char[256];
for ( int i = 0; i <= 255; i++ )
{
unsigned char c = i;
if ( c <= 16 )
uv_table[c] = -127;
else if ( c >= 240 )
uv_table[c] = 127;
else
uv_table[c] = (127*(c-128))/112;
}
r_v_table = new short[255];
g_v_table = new short[255];
g_u_table = new short[255];
b_u_table = new short[255];
for ( int i = 0; i < 255; i++ )
{
r_v_table[i] = (1402*(i-128))/1000;
g_u_table[i] = (344*(i-128))/1000;
g_v_table[i] = (714*(i-128))/1000;
b_u_table[i] = (1772*(i-128))/1000;
}
*/
initialised = true;
}
@ -503,7 +494,7 @@ void Image::Initialise() {
uint8_t* Image::WriteBuffer(const unsigned int p_width, const unsigned int p_height, const unsigned int p_colours, const unsigned int p_subpixelorder) {
if ( p_colours != ZM_COLOUR_GRAY8 && p_colours != ZM_COLOUR_RGB24 && p_colours != ZM_COLOUR_RGB32 ) {
Error("WriteBuffer called with unexpected colours: %d",p_colours);
Error("WriteBuffer called with unexpected colours: %d", p_colours);
return NULL;
}
@ -536,20 +527,30 @@ uint8_t* Image::WriteBuffer(const unsigned int p_width, const unsigned int p_hei
subpixelorder = p_subpixelorder;
pixels = height*width;
size = newsize;
} // end if need to re-alloc buffer
} // end if need to re-alloc buffer
return buffer;
}
/* Assign an existing buffer to the image instead of copying from a source buffer. The goal is to reduce the amount of memory copying and increase efficiency and buffer reusing. */
void Image::AssignDirect( const unsigned int p_width, const unsigned int p_height, const unsigned int p_colours, const unsigned int p_subpixelorder, uint8_t *new_buffer, const size_t buffer_size, const int p_buffertype) {
/* Assign an existing buffer to the image instead of copying from a source buffer.
The goal is to reduce the amount of memory copying and increase efficiency and buffer reusing.
*/
void Image::AssignDirect(
const unsigned int p_width,
const unsigned int p_height,
const unsigned int p_colours,
const unsigned int p_subpixelorder,
uint8_t *new_buffer,
const size_t buffer_size,
const int p_buffertype) {
if ( new_buffer == NULL ) {
Error("Attempt to directly assign buffer from a NULL pointer");
return;
}
if ( !p_height || !p_width ) {
Error("Attempt to directly assign buffer with invalid width or height: %d %d",p_width,p_height);
Error("Attempt to directly assign buffer with invalid width or height: %d %d", p_width, p_height);
return;
}
@ -561,7 +562,8 @@ void Image::AssignDirect( const unsigned int p_width, const unsigned int p_heigh
unsigned int new_buffer_size = ((p_width*p_height)*p_colours);
if ( buffer_size < new_buffer_size ) {
Error("Attempt to directly assign buffer from an undersized buffer of size: %zu, needed %dx%d*%d colours = %zu",buffer_size, p_width, p_height, p_colours, new_buffer_size );
Error("Attempt to directly assign buffer from an undersized buffer of size: %zu, needed %dx%d*%d colours = %zu",
buffer_size, p_width, p_height, p_colours, new_buffer_size);
return;
}
@ -573,6 +575,7 @@ void Image::AssignDirect( const unsigned int p_width, const unsigned int p_heigh
width = p_width;
height = p_height;
colours = p_colours;
linesize = width*colours;
subpixelorder = p_subpixelorder;
pixels = height*width;
size = new_buffer_size; // was pixels*colours, but we already calculated it above as new_buffer_size
@ -591,6 +594,7 @@ void Image::AssignDirect( const unsigned int p_width, const unsigned int p_heigh
width = p_width;
height = p_height;
colours = p_colours;
linesize = width*colours;
subpixelorder = p_subpixelorder;
pixels = height*width;
size = new_buffer_size; // was pixels*colours, but we already calculated it above as new_buffer_size
@ -599,7 +603,6 @@ void Image::AssignDirect( const unsigned int p_width, const unsigned int p_heigh
buffertype = p_buffertype;
buffer = new_buffer;
}
}
void Image::Assign(const unsigned int p_width, const unsigned int p_height, const unsigned int p_colours, const unsigned int p_subpixelorder, const uint8_t* new_buffer, const size_t buffer_size) {
@ -611,17 +614,17 @@ void Image::Assign(const unsigned int p_width, const unsigned int p_height, cons
}
if ( buffer_size < new_size ) {
Error("Attempt to assign buffer from an undersized buffer of size: %zu",buffer_size);
Error("Attempt to assign buffer from an undersized buffer of size: %zu", buffer_size);
return;
}
if ( !p_height || !p_width ) {
Error("Attempt to assign buffer with invalid width or height: %d %d",p_width,p_height);
Error("Attempt to assign buffer with invalid width or height: %d %d", p_width, p_height);
return;
}
if ( p_colours != ZM_COLOUR_GRAY8 && p_colours != ZM_COLOUR_RGB24 && p_colours != ZM_COLOUR_RGB32 ) {
Error("Attempt to assign buffer with unexpected colours per pixel: %d",p_colours);
Error("Attempt to assign buffer with unexpected colours per pixel: %d", p_colours);
return;
}
@ -647,9 +650,9 @@ void Image::Assign(const unsigned int p_width, const unsigned int p_height, cons
size = new_size;
}
if(new_buffer != buffer)
if ( new_buffer != buffer )
(*fptr_imgbufcpy)(buffer, new_buffer, size);
Debug(1,"Assign");
}
void Image::Assign( const Image &image ) {
@ -688,7 +691,7 @@ void Image::Assign( const Image &image ) {
size = new_size;
}
if(image.buffer != buffer)
if ( image.buffer != buffer )
(*fptr_imgbufcpy)(buffer, image.buffer, size);
}
@ -698,7 +701,7 @@ Image *Image::HighlightEdges( Rgb colour, unsigned int p_colours, unsigned int p
}
/* Convert the colour's RGBA subpixel order into the image's subpixel order */
colour = rgb_convert(colour,p_subpixelorder);
colour = rgb_convert(colour, p_subpixelorder);
/* Create a new image of the target format */
Image *high_image = new Image( width, height, p_colours, p_subpixelorder );
@ -707,84 +710,67 @@ Image *Image::HighlightEdges( Rgb colour, unsigned int p_colours, unsigned int p
/* Set image to all black */
high_image->Clear();
unsigned int lo_x = limits?limits->Lo().X():0;
unsigned int lo_y = limits?limits->Lo().Y():0;
unsigned int hi_x = limits?limits->Hi().X():width-1;
unsigned int hi_y = limits?limits->Hi().Y():height-1;
unsigned int lo_x = limits ? limits->Lo().X() : 0;
unsigned int lo_y = limits ? limits->Lo().Y() : 0;
unsigned int hi_x = limits ? limits->Hi().X() : width-1;
unsigned int hi_y = limits ? limits->Hi().Y() : height-1;
if ( p_colours == ZM_COLOUR_GRAY8 )
{
for ( unsigned int y = lo_y; y <= hi_y; y++ )
{
const uint8_t* p = buffer + (y * width) + lo_x;
uint8_t* phigh = high_buff + (y * width) + lo_x;
for ( unsigned int x = lo_x; x <= hi_x; x++, p++, phigh++ )
{
if ( p_colours == ZM_COLOUR_GRAY8 ) {
for ( unsigned int y = lo_y; y <= hi_y; y++ ) {
const uint8_t* p = buffer + (y * linesize) + lo_x;
uint8_t* phigh = high_buff + (y * linesize) + lo_x;
for ( unsigned int x = lo_x; x <= hi_x; x++, p++, phigh++ ) {
bool edge = false;
if ( *p )
{
if ( *p ) {
if ( !edge && x > 0 && !*(p-1) ) edge = true;
if ( !edge && x < (width-1) && !*(p+1) ) edge = true;
if ( !edge && y > 0 && !*(p-width) ) edge = true;
if ( !edge && y < (height-1) && !*(p+width) ) edge = true;
}
if ( edge )
{
if ( edge ) {
*phigh = colour;
}
}
}
}
else if ( p_colours == ZM_COLOUR_RGB24 )
{
for ( unsigned int y = lo_y; y <= hi_y; y++ )
{
const uint8_t* p = buffer + (y * width) + lo_x;
uint8_t* phigh = high_buff + (((y * width) + lo_x) * 3);
for ( unsigned int x = lo_x; x <= hi_x; x++, p++, phigh += 3 )
{
} else if ( p_colours == ZM_COLOUR_RGB24 ) {
for ( unsigned int y = lo_y; y <= hi_y; y++ ) {
const uint8_t* p = buffer + (y * linesize) + lo_x;
uint8_t* phigh = high_buff + (((y * linesize) + lo_x) * 3);
for ( unsigned int x = lo_x; x <= hi_x; x++, p++, phigh += 3 ) {
bool edge = false;
if ( *p )
{
if ( *p ) {
if ( !edge && x > 0 && !*(p-1) ) edge = true;
if ( !edge && x < (width-1) && !*(p+1) ) edge = true;
if ( !edge && y > 0 && !*(p-width) ) edge = true;
if ( !edge && y < (height-1) && !*(p+width) ) edge = true;
}
if ( edge )
{
if ( edge ) {
RED_PTR_RGBA(phigh) = RED_VAL_RGBA(colour);
GREEN_PTR_RGBA(phigh) = GREEN_VAL_RGBA(colour);
BLUE_PTR_RGBA(phigh) = BLUE_VAL_RGBA(colour);
}
}
}
}
else if ( p_colours == ZM_COLOUR_RGB32 )
{
for ( unsigned int y = lo_y; y <= hi_y; y++ )
{
const uint8_t* p = buffer + (y * width) + lo_x;
Rgb* phigh = (Rgb*)(high_buff + (((y * width) + lo_x) * 4));
for ( unsigned int x = lo_x; x <= hi_x; x++, p++, phigh++ )
{
} else if ( p_colours == ZM_COLOUR_RGB32 ) {
for ( unsigned int y = lo_y; y <= hi_y; y++ ) {
const uint8_t* p = buffer + (y * linesize) + lo_x;
Rgb* phigh = (Rgb*)(high_buff + (((y * linesize) + lo_x) * 4));
for ( unsigned int x = lo_x; x <= hi_x; x++, p++, phigh++ ) {
bool edge = false;
if ( *p )
{
if ( *p ) {
if ( !edge && x > 0 && !*(p-1) ) edge = true;
if ( !edge && x < (width-1) && !*(p+1) ) edge = true;
if ( !edge && y > 0 && !*(p-width) ) edge = true;
if ( !edge && y < (height-1) && !*(p+width) ) edge = true;
}
if ( edge )
{
if ( edge ) {
*phigh = colour;
}
}
}
}
return( high_image );
return high_image;
}
bool Image::ReadRaw( const char *filename ) {
@ -881,10 +867,10 @@ bool Image::ReadJpeg(const char *filename, unsigned int p_colours, unsigned int
new_height = cinfo->image_height;
if ( width != new_width || height != new_height ) {
Debug(9,"Image dimensions differ. Old: %ux%u New: %ux%u",width,height,new_width,new_height);
Debug(9, "Image dimensions differ. Old: %ux%u New: %ux%u", width, height, new_width, new_height);
}
switch(p_colours) {
switch (p_colours) {
case ZM_COLOUR_GRAY8:
{
cinfo->out_color_space = JCS_GRAYSCALE;
@ -986,13 +972,14 @@ bool Image::WriteJpeg(const char *filename, struct timeval timestamp) const {
bool Image::WriteJpeg(const char *filename, int quality_override, struct timeval timestamp) const {
return Image::WriteJpeg(filename, quality_override, timestamp, false);
}
bool Image::WriteJpeg(const char *filename, int quality_override, struct timeval timestamp, bool on_blocking_abort) const {
if ( config.colour_jpeg_files && (colours == ZM_COLOUR_GRAY8) ) {
Image temp_image(*this);
temp_image.Colourise(ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB);
return temp_image.WriteJpeg(filename, quality_override, timestamp, on_blocking_abort);
}
int quality = quality_override?quality_override:config.jpeg_file_quality;
int quality = quality_override ? quality_override : config.jpeg_file_quality;
struct jpeg_compress_struct *cinfo = writejpg_ccinfo[quality];
FILE *outfile = NULL;
@ -1046,7 +1033,7 @@ bool Image::WriteJpeg(const char *filename, int quality_override, struct timeval
cinfo->image_width = width; /* image width and height, in pixels */
cinfo->image_height = height;
switch (colours) {
switch ( colours ) {
case ZM_COLOUR_GRAY8:
cinfo->input_components = 1;
cinfo->in_color_space = JCS_GRAYSCALE;
@ -1131,7 +1118,8 @@ cinfo->out_color_space = JCS_RGB;
}
JSAMPROW row_pointer; /* pointer to a single row */
int row_stride = cinfo->image_width * colours; /* physical row width in buffer */
int row_stride = linesize;
//cinfo->image_width * colours; /* physical row width in buffer */
while ( cinfo->next_scanline < cinfo->image_height ) {
row_pointer = &buffer[cinfo->next_scanline * row_stride];
jpeg_write_scanlines(cinfo, &row_pointer, 1);
@ -1271,7 +1259,7 @@ bool Image::EncodeJpeg(JOCTET *outbuffer, int *outbuffer_size, int quality_overr
return temp_image.EncodeJpeg(outbuffer, outbuffer_size, quality_override);
}
int quality = quality_override?quality_override:config.jpeg_stream_quality;
int quality = quality_override ? quality_override : config.jpeg_stream_quality;
struct jpeg_compress_struct *cinfo = encodejpg_ccinfo[quality];
@ -1344,7 +1332,7 @@ cinfo->out_color_space = JCS_RGB;
jpeg_start_compress(cinfo, TRUE);
JSAMPROW row_pointer; /* pointer to a single row */
int row_stride = cinfo->image_width * colours; /* physical row width in buffer */
int row_stride = linesize; /* physical row width in buffer */
while ( cinfo->next_scanline < cinfo->image_height ) {
row_pointer = &buffer[cinfo->next_scanline * row_stride];
jpeg_write_scanlines(cinfo, &row_pointer, 1);
@ -1385,11 +1373,12 @@ bool Image::Crop( unsigned int lo_x, unsigned int lo_y, unsigned int hi_x, unsig
unsigned int new_height = (hi_y-lo_y)+1;
if ( lo_x > hi_x || lo_y > hi_y ) {
Error( "Invalid or reversed crop region %d,%d -> %d,%d", lo_x, lo_y, hi_x, hi_y );
return( false );
Error("Invalid or reversed crop region %d,%d -> %d,%d", lo_x, lo_y, hi_x, hi_y);
return false;
}
if ( hi_x > (width-1) || ( hi_y > (height-1) ) ) {
Error( "Attempting to crop outside image, %d,%d -> %d,%d not in %d,%d", lo_x, lo_y, hi_x, hi_y, width-1, height-1 );
Error("Attempting to crop outside image, %d,%d -> %d,%d not in %d,%d",
lo_x, lo_y, hi_x, hi_y, width-1, height-1);
return false;
}
@ -1400,9 +1389,9 @@ bool Image::Crop( unsigned int lo_x, unsigned int lo_y, unsigned int hi_x, unsig
unsigned int new_size = new_width*new_height*colours;
uint8_t *new_buffer = AllocBuffer(new_size);
unsigned int new_stride = new_width*colours;
unsigned int new_stride = new_width * colours;
for ( unsigned int y = lo_y, ny = 0; y <= hi_y; y++, ny++ ) {
unsigned char *pbuf = &buffer[((y*width)+lo_x)*colours];
unsigned char *pbuf = &buffer[((y*linesize)+lo_x)];
unsigned char *pnbuf = &new_buffer[(ny*new_width)*colours];
memcpy( pnbuf, pbuf, new_stride );
}
@ -1412,8 +1401,8 @@ bool Image::Crop( unsigned int lo_x, unsigned int lo_y, unsigned int hi_x, unsig
return true;
}
bool Image::Crop( const Box &limits ) {
return Crop( limits.LoX(), limits.LoY(), limits.HiX(), limits.HiY() );
bool Image::Crop(const Box &limits) {
return Crop(limits.LoX(), limits.LoY(), limits.HiX(), limits.HiY());
}
/* Far from complete */
@ -1434,7 +1423,7 @@ void Image::Overlay( const Image &image ) {
const uint8_t* psrc = image.buffer;
uint8_t* pdest = buffer;
while( pdest < max_ptr ) {
while ( pdest < max_ptr ) {
if ( *psrc ) {
*pdest = *psrc;
}
@ -1450,7 +1439,7 @@ void Image::Overlay( const Image &image ) {
const uint8_t* psrc = image.buffer;
uint8_t* pdest = buffer;
while( pdest < max_ptr ) {
while ( pdest < max_ptr ) {
if ( RED_PTR_RGBA(psrc) || GREEN_PTR_RGBA(psrc) || BLUE_PTR_RGBA(psrc) ) {
RED_PTR_RGBA(pdest) = RED_PTR_RGBA(psrc);
GREEN_PTR_RGBA(pdest) = GREEN_PTR_RGBA(psrc);
@ -1461,7 +1450,7 @@ void Image::Overlay( const Image &image ) {
}
/* RGB32 ontop of grayscale - convert to same format first - complete */
} else if( colours == ZM_COLOUR_GRAY8 && image.colours == ZM_COLOUR_RGB32 ) {
} else if ( colours == ZM_COLOUR_GRAY8 && image.colours == ZM_COLOUR_RGB32 ) {
Colourise(image.colours, image.subpixelorder);
const Rgb* const max_ptr = (Rgb*)(buffer+size);
@ -1470,7 +1459,7 @@ void Image::Overlay( const Image &image ) {
if ( subpixelorder == ZM_SUBPIX_ORDER_RGBA || subpixelorder == ZM_SUBPIX_ORDER_BGRA ) {
/* RGB\BGR\RGBA\BGRA subpixel order - Alpha byte is last */
while (prdest < max_ptr) {
while ( prdest < max_ptr) {
if ( RED_PTR_RGBA(prsrc) || GREEN_PTR_RGBA(prsrc) || BLUE_PTR_RGBA(prsrc) ) {
*prdest = *prsrc;
}
@ -1479,7 +1468,7 @@ void Image::Overlay( const Image &image ) {
}
} else {
/* ABGR\ARGB subpixel order - Alpha byte is first */
while (prdest < max_ptr) {
while ( prdest < max_ptr) {
if ( RED_PTR_ABGR(prsrc) || GREEN_PTR_ABGR(prsrc) || BLUE_PTR_ABGR(prsrc) ) {
*prdest = *prsrc;
}
@ -1494,7 +1483,7 @@ void Image::Overlay( const Image &image ) {
const uint8_t* psrc = image.buffer;
uint8_t* pdest = buffer;
while( pdest < max_ptr ) {
while ( pdest < max_ptr ) {
if ( *psrc ) {
RED_PTR_RGBA(pdest) = GREEN_PTR_RGBA(pdest) = BLUE_PTR_RGBA(pdest) = *psrc;
}
@ -1508,7 +1497,7 @@ void Image::Overlay( const Image &image ) {
const uint8_t* psrc = image.buffer;
uint8_t* pdest = buffer;
while( pdest < max_ptr ) {
while ( pdest < max_ptr ) {
if ( RED_PTR_RGBA(psrc) || GREEN_PTR_RGBA(psrc) || BLUE_PTR_RGBA(psrc) ) {
RED_PTR_RGBA(pdest) = RED_PTR_RGBA(psrc);
GREEN_PTR_RGBA(pdest) = GREEN_PTR_RGBA(psrc);
@ -1631,8 +1620,8 @@ void Image::Overlay( const Image &image, unsigned int x, unsigned int y ) {
} else {
Error("Overlay called with unexpected colours: %d", colours);
}
}
Debug(1, "Overlay");
} // end void Image::Overlay( const Image &image, unsigned int x, unsigned int y )
void Image::Blend( const Image &image, int transparency ) {
#ifdef ZM_IMAGE_PROFILING
@ -1794,7 +1783,7 @@ void Image::Delta( const Image &image, Image* targetimage) const {
clock_gettime(CLOCK_THREAD_CPUTIME_ID,&start);
#endif
switch (colours) {
switch ( colours ) {
case ZM_COLOUR_RGB24:
if ( subpixelorder == ZM_SUBPIX_ORDER_BGR ) {
/* BGR subpixel order */
@ -1858,7 +1847,7 @@ const Coord Image::centreCoord( const char *text ) const {
}
int x = (width - (max_line_len * ZM_CHAR_WIDTH) ) / 2;
int y = (height - (line_no * LINE_HEIGHT) ) / 2;
return( Coord( x, y ) );
return Coord(x, y);
}
/* RGB32 compatible: complete */
@ -2150,7 +2139,7 @@ void Image::DeColourise() {
subpixelorder = ZM_SUBPIX_ORDER_NONE;
size = width * height;
if ( colours == ZM_COLOUR_RGB32 && config.cpu_extensions && sseversion >= 35 ) {
if ( colours == ZM_COLOUR_RGB32 && config.cpu_extensions && sse_version >= 35 ) {
/* Use SSSE3 functions */
switch (subpixelorder) {
case ZM_SUBPIX_ORDER_BGRA:
@ -2277,12 +2266,12 @@ void Image::Fill( Rgb colour, int density, const Box *limits ) {
if ( density <= 1 )
return Fill(colour,limits);
if ( !(colours == ZM_COLOUR_GRAY8 || colours == ZM_COLOUR_RGB24 || colours == ZM_COLOUR_RGB32 ) ) {
if ( !(colours == ZM_COLOUR_GRAY8 || colours == ZM_COLOUR_RGB24 || colours == ZM_COLOUR_RGB32 ) ) {
Panic("Attempt to fill image with unexpected colours %d", colours);
}
/* Convert the colour's RGBA subpixel order into the image's subpixel order */
colour = rgb_convert(colour,subpixelorder);
colour = rgb_convert(colour, subpixelorder);
unsigned int lo_x = limits?limits->Lo().X():0;
unsigned int lo_y = limits?limits->Lo().Y():0;
@ -2407,20 +2396,20 @@ void Image::Outline( Rgb colour, const Polygon &polygon ) {
}
/* RGB32 compatible: complete */
void Image::Fill( Rgb colour, int density, const Polygon &polygon ) {
void Image::Fill(Rgb colour, int density, const Polygon &polygon) {
if ( !(colours == ZM_COLOUR_GRAY8 || colours == ZM_COLOUR_RGB24 || colours == ZM_COLOUR_RGB32 ) ) {
Panic( "Attempt to fill image with unexpected colours %d", colours );
Panic("Attempt to fill image with unexpected colours %d", colours);
}
/* Convert the colour's RGBA subpixel order into the image's subpixel order */
colour = rgb_convert(colour,subpixelorder);
colour = rgb_convert(colour, subpixelorder);
int n_coords = polygon.getNumCoords();
int n_global_edges = 0;
Edge global_edges[n_coords];
for ( int j = 0, i = n_coords-1; j < n_coords; i = j++ ) {
const Coord &p1 = polygon.getCoord( i );
const Coord &p2 = polygon.getCoord( j );
const Coord &p1 = polygon.getCoord(i);
const Coord &p2 = polygon.getCoord(j);
int x1 = p1.X();
int x2 = p2.X();
@ -2717,7 +2706,7 @@ void Image::Flip( bool leftright ) {
void Image::Scale( unsigned int factor ) {
if ( !factor ) {
Error( "Bogus scale factor %d found", factor );
Error("Bogus scale factor %d found", factor);
return;
}
if ( factor == ZM_SCALE_BASE ) {
@ -2727,6 +2716,7 @@ void Image::Scale( unsigned int factor ) {
unsigned int new_width = (width*factor)/ZM_SCALE_BASE;
unsigned int new_height = (height*factor)/ZM_SCALE_BASE;
// Why larger than we need?
size_t scale_buffer_size = (new_width+1) * (new_height+1) * colours;
uint8_t* scale_buffer = AllocBuffer(scale_buffer_size);
@ -2801,10 +2791,8 @@ void Image::Scale( unsigned int factor ) {
}
new_width = last_w_index;
new_height = last_h_index;
}
} // end foreach line
AssignDirect( new_width, new_height, colours, subpixelorder, scale_buffer, scale_buffer_size, ZM_BUFTYPE_ZM);
}
void Image::Deinterlace_Discard() {

View File

@ -152,9 +152,11 @@ protected:
static struct zm_error_mgr jpg_err;
unsigned int width;
unsigned int linesize;
unsigned int height;
unsigned int pixels;
unsigned int colours;
unsigned int padding;
unsigned int size;
unsigned int subpixelorder;
unsigned long allocation;
@ -166,14 +168,17 @@ protected:
public:
Image();
explicit Image( const char *filename );
Image( int p_width, int p_height, int p_colours, int p_subpixelorder, uint8_t *p_buffer=0);
Image(int p_width, int p_height, int p_colours, int p_subpixelorder, uint8_t *p_buffer=0, unsigned int padding=0);
Image(int p_width, int p_linesize, int p_height, int p_colours, int p_subpixelorder, uint8_t *p_buffer=0, unsigned int padding=0);
explicit Image( const Image &p_image );
explicit Image( const AVFrame *frame );
~Image();
static void Initialise();
static void Deinitialise();
inline unsigned int Width() const { return width; }
inline unsigned int LineSize() const { return linesize; }
inline unsigned int Height() const { return height; }
inline unsigned int Pixels() const { return pixels; }
inline unsigned int Colours() const { return colours; }
@ -182,7 +187,7 @@ public:
/* Internal buffer should not be modified from functions outside of this class */
inline const uint8_t* Buffer() const { return buffer; }
inline const uint8_t* Buffer( unsigned int x, unsigned int y= 0 ) const { return &buffer[colours*((y*width)+x)]; }
inline const uint8_t* Buffer( unsigned int x, unsigned int y= 0 ) const { return &buffer[(y*linesize)+x]; }
/* Request writeable buffer */
uint8_t* WriteBuffer(const unsigned int p_width, const unsigned int p_height, const unsigned int p_colours, const unsigned int p_subpixelorder);
@ -193,7 +198,7 @@ public:
if ( !holdbuffer )
DumpImgBuffer();
width = height = colours = size = pixels = subpixelorder = 0;
width = linesize = height = colours = size = pixels = subpixelorder = 0;
}
void Assign( unsigned int p_width, unsigned int p_height, unsigned int p_colours, unsigned int p_subpixelorder, const uint8_t* new_buffer, const size_t buffer_size);

View File

@ -198,8 +198,7 @@ void LibvlcCamera::Terminate() {
}
int LibvlcCamera::PrimeCapture() {
Info("Priming capture from %s", mPath.c_str());
Info("Libvlc Version %s", (*libvlc_get_version_f)());
Debug(1, "Priming capture from %s, libvlc version %s", mPath.c_str(), (*libvlc_get_version_f)());
StringVector opVect = split(Options(), ",");

View File

@ -148,7 +148,7 @@ void VncCamera::Terminate() {
}
int VncCamera::PrimeCapture() {
Info("Priming capture from %s", mHost.c_str());
Debug(1, "Priming capture from %s", mHost.c_str());
return 0;
}

View File

@ -504,7 +504,7 @@ LocalCamera::LocalCamera(
subpixelorder = ZM_SUBPIX_ORDER_NONE;
} else if ( palette == V4L2_PIX_FMT_YUYV && colours == ZM_COLOUR_GRAY8 ) {
/* Fast YUYV->Grayscale conversion by extracting the Y channel */
if ( config.cpu_extensions && sseversion >= 35 ) {
if ( config.cpu_extensions && sse_version >= 35 ) {
conversion_fptr = &ssse3_convert_yuyv_gray8;
Debug(2,"Using SSSE3 YUYV->grayscale fast conversion");
} else {
@ -616,7 +616,7 @@ LocalCamera::LocalCamera(
}
} else if ( (palette == VIDEO_PALETTE_YUYV || palette == VIDEO_PALETTE_YUV422) && colours == ZM_COLOUR_GRAY8 ) {
/* Fast YUYV->Grayscale conversion by extracting the Y channel */
if ( config.cpu_extensions && sseversion >= 35 ) {
if ( config.cpu_extensions && sse_version >= 35 ) {
conversion_fptr = &ssse3_convert_yuyv_gray8;
Debug(2,"Using SSSE3 YUYV->grayscale fast conversion");
} else {

View File

@ -135,61 +135,61 @@ Monitor::MonitorLink::~MonitorLink() {
}
bool Monitor::MonitorLink::connect() {
if ( !last_connect_time || (time( 0 ) - last_connect_time) > 60 ) {
last_connect_time = time( 0 );
if ( !last_connect_time || (time(0) - last_connect_time) > 60 ) {
last_connect_time = time(0);
mem_size = sizeof(SharedData) + sizeof(TriggerData);
Debug( 1, "link.mem.size=%d", mem_size );
Debug(1, "link.mem.size=%d", mem_size);
#if ZM_MEM_MAPPED
map_fd = open( mem_file, O_RDWR, (mode_t)0600 );
map_fd = open(mem_file, O_RDWR, (mode_t)0600);
if ( map_fd < 0 ) {
Debug( 3, "Can't open linked memory map file %s: %s", mem_file, strerror(errno) );
Debug(3, "Can't open linked memory map file %s: %s", mem_file, strerror(errno));
disconnect();
return( false );
return false;
}
while ( map_fd <= 2 ) {
int new_map_fd = dup(map_fd);
Warning( "Got one of the stdio fds for our mmap handle. map_fd was %d, new one is %d", map_fd, new_map_fd );
Warning("Got one of the stdio fds for our mmap handle. map_fd was %d, new one is %d", map_fd, new_map_fd);
close(map_fd);
map_fd = new_map_fd;
}
struct stat map_stat;
if ( fstat( map_fd, &map_stat ) < 0 ) {
Error( "Can't stat linked memory map file %s: %s", mem_file, strerror(errno) );
if ( fstat(map_fd, &map_stat) < 0 ) {
Error("Can't stat linked memory map file %s: %s", mem_file, strerror(errno));
disconnect();
return( false );
return false;
}
if ( map_stat.st_size == 0 ) {
Error( "Linked memory map file %s is empty: %s", mem_file, strerror(errno) );
Error("Linked memory map file %s is empty: %s", mem_file, strerror(errno));
disconnect();
return( false );
return false;
} else if ( map_stat.st_size < mem_size ) {
Error( "Got unexpected memory map file size %ld, expected %d", map_stat.st_size, mem_size );
Error("Got unexpected memory map file size %ld, expected %d", map_stat.st_size, mem_size);
disconnect();
return( false );
return false;
}
mem_ptr = (unsigned char *)mmap( NULL, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED, map_fd, 0 );
mem_ptr = (unsigned char *)mmap(NULL, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED, map_fd, 0);
if ( mem_ptr == MAP_FAILED ) {
Error( "Can't map file %s (%d bytes) to memory: %s", mem_file, mem_size, strerror(errno) );
Error("Can't map file %s (%d bytes) to memory: %s", mem_file, mem_size, strerror(errno));
disconnect();
return( false );
return false;
}
#else // ZM_MEM_MAPPED
shm_id = shmget( (config.shm_key&0xffff0000)|id, mem_size, 0700 );
if ( shm_id < 0 ) {
Debug( 3, "Can't shmget link memory: %s", strerror(errno) );
Debug(3, "Can't shmget link memory: %s", strerror(errno );
connected = false;
return( false );
return false;
}
mem_ptr = (unsigned char *)shmat( shm_id, 0, 0 );
mem_ptr = (unsigned char *)shmat(shm_id, 0, 0);
if ( mem_ptr < (void *)0 ) {
Debug( 3, "Can't shmat link memory: %s", strerror(errno) );
Debug(3, "Can't shmat link memory: %s", strerror(errno));
connected = false;
return( false );
return false;
}
#endif // ZM_MEM_MAPPED
@ -197,18 +197,18 @@ bool Monitor::MonitorLink::connect() {
trigger_data = (TriggerData *)((char *)shared_data + sizeof(SharedData));
if ( !shared_data->valid ) {
Debug( 3, "Linked memory not initialised by capture daemon" );
Debug(3, "Linked memory not initialised by capture daemon");
disconnect();
return( false );
return false;
}
last_state = shared_data->state;
last_event = shared_data->last_event;
connected = true;
return( true );
return true;
}
return( false );
return false;
}
bool Monitor::MonitorLink::disconnect() {
@ -529,6 +529,7 @@ Monitor::Monitor(
shared_data->last_write_index, shared_data->last_write_time );
sleep(1);
}
ref_image.Assign( width, height, camera->Colours(), camera->SubpixelOrder(),
image_buffer[shared_data->last_write_index].image->Buffer(), camera->ImageSize());
adaptive_skip = true;
@ -538,7 +539,7 @@ Monitor::Monitor(
if ( config.record_diag_images ) {
diag_path_r = stringtf(config.record_diag_images_fifo ? "%s/%d/diagpipe-r.jpg" : "%s/%d/diag-r.jpg", storage->Path(), id);
diag_path_d = stringtf(config.record_diag_images_fifo ? "%s/%d/diagpipe-d.jpg" : "%s/%d/diag-d.jpg", storage->Path(), id);
if (config.record_diag_images_fifo){
if ( config.record_diag_images_fifo ) {
FifoStream::fifo_create_if_missing(diag_path_r.c_str());
FifoStream::fifo_create_if_missing(diag_path_d.c_str());
}
@ -602,7 +603,7 @@ bool Monitor::connect() {
if ( mem_ptr == MAP_FAILED )
Fatal("Can't map file %s (%d bytes) to memory: %s(%d)", mem_file, mem_size, strerror(errno), errno);
if ( mem_ptr == NULL ) {
Error("mmap gave a null address:");
Error("mmap gave a NULL address:");
} else {
Debug(3, "mmapped to %p", mem_ptr);
}
@ -631,7 +632,7 @@ bool Monitor::connect() {
image_buffer = new Snapshot[image_buffer_count];
for ( int i = 0; i < image_buffer_count; i++ ) {
image_buffer[i].timestamp = &(shared_timestamps[i]);
image_buffer[i].image = new Image( width, height, camera->Colours(), camera->SubpixelOrder(), &(shared_images[i*camera->ImageSize()]) );
image_buffer[i].image = new Image( width, camera->LineSize(), height, camera->Colours(), camera->SubpixelOrder(), &(shared_images[i*camera->ImageSize()]) );
image_buffer[i].image->HoldBuffer(true); /* Don't release the internal buffer or replace it with another */
}
if ( (deinterlacing & 0xff) == 4) {
@ -1403,9 +1404,6 @@ bool Monitor::Analyse() {
score += trigger_data->trigger_score;
Debug(1, "Triggered on score += %d => %d", trigger_data->trigger_score, score);
if ( !event ) {
// How could it have a length already?
//if ( cause.length() )
//cause += ", ";
cause += trigger_data->trigger_cause;
}
Event::StringSet noteSet;
@ -1485,6 +1483,7 @@ bool Monitor::Analyse() {
score += 50;
}
} else {
Debug(1, "Linked monitor %d %d is not connected. Connecting.", i, linked_monitors[i]->Id());
linked_monitors[i]->connect();
}
} // end foreach linked_monit
@ -1499,7 +1498,7 @@ bool Monitor::Analyse() {
if ( section_length
&& ( ( timestamp->tv_sec - video_store_data->recording.tv_sec ) >= section_length )
&& ( (event_close_mode != CLOSE_TIME) || ! ( timestamp->tv_sec % section_length ) )
&& ( (function == MOCORD && (event_close_mode != CLOSE_TIME)) || ! ( timestamp->tv_sec % section_length ) )
) {
Info("%s: %03d - Closing event %" PRIu64 ", section end forced %d - %d = %d >= %d",
name, image_count, event->Id(),
@ -1512,7 +1511,6 @@ bool Monitor::Analyse() {
} // end if event
if ( !event ) {
// Create event
event = new Event(this, *timestamp, "Continuous", noteSetMap, videoRecording);
shared_data->last_event = event->Id();
@ -1526,7 +1524,6 @@ bool Monitor::Analyse() {
if ( state == IDLE ) {
shared_data->state = state = TAPE;
}
} // end if ! event
} // end if function == RECORD || function == MOCORD)
} // end if !signal_change && signal
@ -1539,7 +1536,7 @@ bool Monitor::Analyse() {
&& (event_close_mode == CLOSE_ALARM)
&& ( ( timestamp->tv_sec - video_store_data->recording.tv_sec ) >= min_section_length )
) {
Info("%s: %03d - Closing event %" PRIu64 ", continuous end, alarm begins",
Info("%s: %03d - Closing event %" PRIu64 ", continuous end, alarm begins",
name, image_count, event->Id());
closeEvent();
} else if ( event ) {
@ -1550,7 +1547,6 @@ bool Monitor::Analyse() {
);
}
if ( (!pre_event_count) || (Event::PreAlarmCount() >= alarm_frame_count-1) ) {
shared_data->state = state = ALARM;
// lets construct alarm cause. It will contain cause + names of zones alarmed
std::string alarm_cause = "";
for ( int i=0; i < n_zones; i++ ) {
@ -1608,6 +1604,7 @@ bool Monitor::Analyse() {
event = new Event(this, *(image_buffer[pre_index].timestamp), cause, noteSetMap);
} // end if analysis_fps && pre_event_count
shared_data->state = state = ALARM;
shared_data->last_event = event->Id();
//set up video store data
snprintf(video_store_data->event_file, sizeof(video_store_data->event_file), "%s", event->getEventFile());
@ -1680,7 +1677,7 @@ bool Monitor::Analyse() {
if ( state != IDLE ) {
if ( state == PREALARM || state == ALARM ) {
if ( config.create_analysis_images ) {
if ( savejpegs > 1 ) {
bool got_anal_image = false;
alarm_image.Assign(*snap_image);
for ( int i = 0; i < n_zones; i++ ) {
@ -1694,17 +1691,10 @@ bool Monitor::Analyse() {
} // end if zone is alarmed
} // end foreach zone
if ( got_anal_image ) {
if ( state == PREALARM )
Event::AddPreAlarmFrame(snap_image, *timestamp, score, &alarm_image);
else
event->AddFrame(snap_image, *timestamp, score, &alarm_image);
} else {
if ( state == PREALARM )
Event::AddPreAlarmFrame(snap_image, *timestamp, score);
else
event->AddFrame(snap_image, *timestamp, score);
}
if ( state == PREALARM )
Event::AddPreAlarmFrame(snap_image, *timestamp, score, (got_anal_image?&alarm_image:NULL));
else
event->AddFrame(snap_image, *timestamp, score, (got_anal_image?&alarm_image:NULL));
} else {
// Not doing alarm frame storage
if ( state == PREALARM ) {
@ -1718,7 +1708,7 @@ bool Monitor::Analyse() {
}
} // end if config.record_event_stats
}
} // end if config.create_analysis_images
} // end if savejpegs > 1
if ( event ) {
if ( noteSetMap.size() > 0 )
@ -1740,7 +1730,6 @@ bool Monitor::Analyse() {
//set up video store data
snprintf(video_store_data->event_file, sizeof(video_store_data->event_file), "%s", event->getEventFile());
video_store_data->recording = event->StartTime();
}
} // end if event
@ -2516,7 +2505,7 @@ int Monitor::Capture() {
if ( capture_image->Size() > camera->ImageSize() ) {
Error("Captured image %d does not match expected size %d check width, height and colour depth",
capture_image->Size(),camera->ImageSize() );
capture_image->Size(), camera->ImageSize() );
return -1;
}

View File

@ -138,15 +138,23 @@ protected:
time_t startup_time; /* When the zmc process started. zmwatch uses this to see how long the process has been running without getting any images */
uint64_t extrapad1;
};
union { /* +72 */
time_t last_write_time;
union { /* +72 */
time_t zmc_heartbeat_time; /* Constantly updated by zmc. Used to determine if the process is alive or hung or dead */
uint64_t extrapad2;
};
union { /* +80 */
time_t last_read_time;
union { /* +80 */
time_t zma_heartbeat_time; /* Constantly updated by zma. Used to determine if the process is alive or hung or dead */
uint64_t extrapad3;
};
uint8_t control_state[256]; /* +88 */
union { /* +88 */
time_t last_write_time;
uint64_t extrapad4;
};
union { /* +96 */
time_t last_read_time;
uint64_t extrapad5;
};
uint8_t control_state[256]; /* +104 */
char alarm_cause[256];
@ -210,21 +218,21 @@ protected:
uint64_t last_event;
public:
MonitorLink( int p_id, const char *p_name );
MonitorLink(int p_id, const char *p_name);
~MonitorLink();
inline int Id() const {
return id;
}
inline const char *Name() const {
return( name );
return name;
}
inline bool isConnected() const {
return( connected );
return connected && shared_data->valid;
}
inline time_t getLastConnectTime() const {
return( last_connect_time );
return last_connect_time;
}
bool connect();
@ -415,8 +423,9 @@ public:
void AddPrivacyBitmask( Zone *p_zones[] );
bool connect();
inline int ShmValid() const {
return( shared_data->valid );
return shared_data->valid;
}
inline int Id() const {

View File

@ -387,6 +387,7 @@ bool MonitorStream::sendFrame(Image *image, struct timeval *timestamp) {
struct timeval frameStartTime;
gettimeofday(&frameStartTime, NULL);
fputs("--ZoneMinderFrame\r\n", stdout);
switch( type ) {
case STREAM_JPEG :
send_image->EncodeJpeg(img_buffer, &img_buffer_size);

View File

@ -35,7 +35,7 @@
#include <curl/curl.h>
#endif
unsigned int sseversion = 0;
unsigned int sse_version = 0;
unsigned int neonversion = 0;
std::string trimSet(std::string str, std::string trimset) {
@ -44,12 +44,9 @@ std::string trimSet(std::string str, std::string trimset) {
size_t endpos = str.find_last_not_of(trimset); // Find the first character position from reverse af
// if all spaces or empty return an empty string
if(( std::string::npos == startpos ) || ( std::string::npos == endpos))
{
if ( ( std::string::npos == startpos ) || ( std::string::npos == endpos ) )
return std::string("");
}
else
return str.substr( startpos, endpos-startpos+1 );
return str.substr(startpos, endpos-startpos+1);
}
std::string trimSpaces(const std::string &str) {
@ -57,48 +54,46 @@ std::string trimSpaces(const std::string &str) {
}
std::string replaceAll(std::string str, std::string from, std::string to) {
if(from.empty())
if ( from.empty() )
return str;
size_t start_pos = 0;
while((start_pos = str.find(from, start_pos)) != std::string::npos) {
while ( (start_pos = str.find(from, start_pos)) != std::string::npos ) {
str.replace(start_pos, from.length(), to);
start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
}
return str;
}
const std::string stringtf( const char *format, ... )
{
const std::string stringtf( const char *format, ... ) {
va_list ap;
char tempBuffer[8192];
std::string tempString;
va_start(ap, format );
vsnprintf( tempBuffer, sizeof(tempBuffer), format , ap );
va_start(ap, format);
vsnprintf(tempBuffer, sizeof(tempBuffer), format , ap);
va_end(ap);
tempString = tempBuffer;
return( tempString );
return tempString;
}
const std::string stringtf( const std::string format, ... )
{
const std::string stringtf(const std::string format, ...) {
va_list ap;
char tempBuffer[8192];
std::string tempString;
va_start(ap, format );
vsnprintf( tempBuffer, sizeof(tempBuffer), format.c_str() , ap );
va_start(ap, format);
vsnprintf(tempBuffer, sizeof(tempBuffer), format.c_str(), ap);
va_end(ap);
tempString = tempBuffer;
return( tempString );
return tempString;
}
bool startsWith(const std::string &haystack, const std::string &needle) {
return( haystack.substr(0, needle.length()) == needle );
return ( haystack.substr(0, needle.length()) == needle );
}
StringVector split(const std::string &string, const std::string &chars, int limit) {
@ -145,8 +140,7 @@ const std::string join(const StringVector &v, const char * delim=",") {
const std::string base64Encode(const std::string &inString) {
static char base64_table[64] = { '\0' };
if ( !base64_table[0] )
{
if ( !base64_table[0] ) {
int i = 0;
for ( char c = 'A'; c <= 'Z'; c++ )
base64_table[i++] = c;
@ -159,59 +153,52 @@ const std::string base64Encode(const std::string &inString) {
}
std::string outString;
outString.reserve( 2 * inString.size() );
outString.reserve(2 * inString.size());
const char *inPtr = inString.c_str();
while( *inPtr )
{
while ( *inPtr ) {
unsigned char selection = *inPtr >> 2;
unsigned char remainder = (*inPtr++ & 0x03) << 4;
outString += base64_table[selection];
if ( *inPtr )
{
if ( *inPtr ) {
selection = remainder | (*inPtr >> 4);
remainder = (*inPtr++ & 0x0f) << 2;
outString += base64_table[selection];
if ( *inPtr )
{
if ( *inPtr ) {
selection = remainder | (*inPtr >> 6);
outString += base64_table[selection];
selection = (*inPtr++ & 0x3f);
outString += base64_table[selection];
}
else
{
} else {
outString += base64_table[remainder];
outString += '=';
}
}
else
{
} else {
outString += base64_table[remainder];
outString += '=';
outString += '=';
}
}
return( outString );
return outString;
}
int split(const char* string, const char delim, std::vector<std::string>& items) {
if(string == NULL)
if ( string == NULL )
return -1;
if(string[0] == 0)
if ( string[0] == 0 )
return -2;
std::string str(string);
while(true) {
while ( true ) {
size_t pos = str.find(delim);
items.push_back(str.substr(0, pos));
str.erase(0, pos+1);
if(pos == std::string::npos)
if ( pos == std::string::npos )
break;
}
@ -219,16 +206,16 @@ int split(const char* string, const char delim, std::vector<std::string>& items)
}
int pairsplit(const char* string, const char delim, std::string& name, std::string& value) {
if(string == NULL)
if ( string == NULL )
return -1;
if(string[0] == 0)
if ( string[0] == 0 )
return -2;
std::string str(string);
size_t pos = str.find(delim);
if(pos == std::string::npos || pos == 0 || pos >= str.length())
if ( pos == std::string::npos || pos == 0 || pos >= str.length() )
return -3;
name = str.substr(0, pos);
@ -240,7 +227,7 @@ int pairsplit(const char* string, const char delim, std::string& name, std::stri
/* Detect special hardware features, such as SIMD instruction sets */
void hwcaps_detect() {
neonversion = 0;
sseversion = 0;
sse_version = 0;
#if (defined(__i386__) || defined(__x86_64__))
/* x86 or x86-64 processor */
uint32_t r_edx, r_ecx, r_ebx;
@ -277,33 +264,33 @@ void hwcaps_detect() {
);
#endif
if (r_ebx & 0x00000020) {
sseversion = 52; /* AVX2 */
Debug(1,"Detected a x86\\x86-64 processor with AVX2");
} else if (r_ecx & 0x10000000) {
sseversion = 51; /* AVX */
Debug(1,"Detected a x86\\x86-64 processor with AVX");
} else if (r_ecx & 0x00100000) {
sseversion = 42; /* SSE4.2 */
Debug(1,"Detected a x86\\x86-64 processor with SSE4.2");
} else if (r_ecx & 0x00080000) {
sseversion = 41; /* SSE4.1 */
Debug(1,"Detected a x86\\x86-64 processor with SSE4.1");
} else if (r_ecx & 0x00000200) {
sseversion = 35; /* SSSE3 */
if ( r_ebx & 0x00000020 ) {
sse_version = 52; /* AVX2 */
Debug(1, "Detected a x86\\x86-64 processor with AVX2");
} else if ( r_ecx & 0x10000000 ) {
sse_version = 51; /* AVX */
Debug(1, "Detected a x86\\x86-64 processor with AVX");
} else if ( r_ecx & 0x00100000 ) {
sse_version = 42; /* SSE4.2 */
Debug(1, "Detected a x86\\x86-64 processor with SSE4.2");
} else if ( r_ecx & 0x00080000 ) {
sse_version = 41; /* SSE4.1 */
Debug(1, "Detected a x86\\x86-64 processor with SSE4.1");
} else if ( r_ecx & 0x00000200 ) {
sse_version = 35; /* SSSE3 */
Debug(1,"Detected a x86\\x86-64 processor with SSSE3");
} else if (r_ecx & 0x00000001) {
sseversion = 30; /* SSE3 */
Debug(1,"Detected a x86\\x86-64 processor with SSE3");
} else if (r_edx & 0x04000000) {
sseversion = 20; /* SSE2 */
Debug(1,"Detected a x86\\x86-64 processor with SSE2");
} else if (r_edx & 0x02000000) {
sseversion = 10; /* SSE */
Debug(1,"Detected a x86\\x86-64 processor with SSE");
} else if ( r_ecx & 0x00000001 ) {
sse_version = 30; /* SSE3 */
Debug(1, "Detected a x86\\x86-64 processor with SSE3");
} else if ( r_edx & 0x04000000 ) {
sse_version = 20; /* SSE2 */
Debug(1, "Detected a x86\\x86-64 processor with SSE2");
} else if ( r_edx & 0x02000000 ) {
sse_version = 10; /* SSE */
Debug(1, "Detected a x86\\x86-64 processor with SSE");
} else {
sseversion = 0;
Debug(1,"Detected a x86\\x86-64 processor");
sse_version = 0;
Debug(1, "Detected a x86\\x86-64 processor");
}
#elif defined(__arm__)
// ARM processor in 32bit mode

View File

@ -59,7 +59,7 @@ void* sse2_aligned_memcpy(void* dest, const void* src, size_t bytes);
void timespec_diff(struct timespec *start, struct timespec *end, struct timespec *diff);
void hwcaps_detect();
extern unsigned int sseversion;
extern unsigned int sse_version;
extern unsigned int neonversion;
char *timeval_to_string( struct timeval tv );

View File

@ -229,7 +229,7 @@ bool Zone::CheckAlarms(const Image *delta_image) {
Debug(4, "Checking alarms for zone %d/%s in lines %d -> %d", id, label, lo_y, hi_y);
/* if(config.cpu_extensions && sseversion >= 20) {
/* if(config.cpu_extensions && sse_version >= 20) {
sse2_alarmedpixels(diff_image, pg_image, &alarm_pixels, &pixel_diff_count);
} else {
std_alarmedpixels(diff_image, pg_image, &alarm_pixels, &pixel_diff_count);
@ -505,7 +505,7 @@ bool Zone::CheckAlarms(const Image *delta_image) {
||
(max_blob_pixels && bs->count > max_blob_pixels)
) {
if ( config.create_analysis_images || config.record_diag_images ) {
if ( ( monitor->GetOptSaveJPEGs() > 1 ) || config.record_diag_images ) {
for ( int sy = bs->lo_y; sy <= bs->hi_y; sy++ ) {
spdiff = diff_buff + ((diff_width * sy) + bs->lo_x);
for ( int sx = bs->lo_x; sx <= bs->hi_x; sx++, spdiff++ ) {
@ -574,7 +574,7 @@ bool Zone::CheckAlarms(const Image *delta_image) {
BlobStats *bs = &blob_stats[i];
if ( bs->count ) {
if ( (min_blob_pixels && bs->count < min_blob_pixels) || (max_blob_pixels && bs->count > max_blob_pixels) ) {
if ( config.create_analysis_images || config.record_diag_images ) {
if ( ( monitor->GetOptSaveJPEGs() > 1 ) || config.record_diag_images ) {
for ( int sy = bs->lo_y; sy <= bs->hi_y; sy++ ) {
spdiff = diff_buff + ((diff_width * sy) + bs->lo_x);
for ( int sx = bs->lo_x; sx <= bs->hi_x; sx++, spdiff++ ) {
@ -702,7 +702,7 @@ bool Zone::CheckAlarms(const Image *delta_image) {
alarm_centre = alarm_box.Centre();
}
if ( (type < PRECLUSIVE) && (check_method >= BLOBS) && config.create_analysis_images ) {
if ( (type < PRECLUSIVE) && (check_method >= BLOBS) && (monitor->GetOptSaveJPEGs() > 1) ) {
// First mask out anything we don't want
for ( unsigned int y = lo_y; y <= hi_y; y++ ) {

View File

@ -259,7 +259,8 @@ int main(int argc, char *argv[]) {
Debug(1, "Failed to prime capture of initial monitor");
}
prime_capture_log_count ++;
sleep(10);
if ( !zm_terminate )
sleep(10);
continue;
}

View File

@ -37,7 +37,7 @@ 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,buildinfo,changes} zmrepo@zmrepo.zoneminder.com:${targetfolder}/ 2>&1
rsync -v --ignore-missing-args --exclude 'external-repo.noarch.rpm' -e 'ssh -v' build/*.{rpm,deb,dsc,tar.xz,buildinfo,changes} zmrepo@zmrepo.zoneminder.com:${targetfolder}/ 2>&1
if [ "$?" -eq 0 ]; then
echo
echo "Files copied successfully."

View File

@ -16,7 +16,7 @@ my @monitors;
my $dbh = zmDbConnect();
my $sql = "SELECT * FROM Monitors
WHERE find_in_set( Function, 'Modect,Mocord,Nodect' )".
WHERE find_in_set( `Function`, 'Modect,Mocord,Nodect' )".
( $Config{ZM_SERVER_ID} ? 'AND ServerId=?' : '' )
;

View File

@ -102,21 +102,21 @@ CakeLog::config('debug', array(
'engine' => 'File',
'types' => array('notice', 'info', 'debug'),
'file' => 'cake_debug',
'path' => '@ZM_LOGDIR@/'
'path' => '@ZM_LOGDIR@/'
));
CakeLog::config('error', array(
'engine' => 'File',
'types' => array('warning', 'error', 'critical', 'alert', 'emergency'),
'file' => 'cake_error',
'path' => '@ZM_LOGDIR@/'
'path' => '@ZM_LOGDIR@/'
));
CakeLog::config('custom_path', array(
'engine' => 'File',
'path' => '@ZM_LOGDIR@/'
'engine' => 'File',
'path' => '@ZM_LOGDIR@/'
));
Configure::write('ZM_CONFIG', '@ZM_CONFIG@');
Configure::write('ZM_CONFIG_SUBDIR', '@ZM_CONFIG_SUBDIR@');
Configure::write('ZM_CONFIG', '@ZM_CONFIG@');
Configure::write('ZM_CONFIG_SUBDIR', '@ZM_CONFIG_SUBDIR@');
Configure::write('ZM_VERSION', '@VERSION@');
Configure::write('ZM_API_VERSION', '@API_VERSION@');
@ -128,27 +128,3 @@ global $configvals;
foreach( $configvals as $key => $value) {
Configure::write($key, $value);
}
if ( 0 ) {
// No longer needed, but I want to keep the code for reference
//
// 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') ) {
App::uses('ClassRegistry', 'Utility');
$ServerModel = ClassRegistry::init('Server');
if ( defined('ZM_SERVER_NAME') and ZM_SERVER_NAME ) {
$Server = $ServerModel->find( 'first', array( 'conditions'=>array('Name'=>ZM_SERVER_NAME) ) );
if ( ! $Server ) {
Error('Invalid Multi-Server configration detected. ZM_SERVER_NAME set to ' . ZM_SERVER_NAME . ' in zm.conf, but no corresponding entry found in Servers table.');
} else {
define( 'ZM_SERVER_ID', $Server['Server']['Id'] );
}
} else if ( defined('ZM_SERVER_HOST') and ZM_SERVER_HOST ) {
$Server = $ServerModel->find( 'first', array( 'conditions'=>array('Name'=>ZM_SERVER_HOST) ) );
if ( ! $Server ) {
Error('Invalid Multi-Server configration detected. ZM_SERVER_HOST set to ' . ZM_SERVER_HOST . ' in zm.conf, but no corresponding entry found in Servers table.');
} else {
define( 'ZM_SERVER_ID', $Server['Server']['Id'] );
}
}
}
}

View File

@ -36,12 +36,6 @@ class UsersController extends AppController {
* @return void
*/
public function view($id = null) {
$this->loadModel('Config');
$configs = $this->Config->find('list', array(
'fields' => array('Name', 'Value'),
'conditions' => array('Name' => array('ZM_DIR_EVENTS'))
));
$this->User->recursive = 1;
if (!$this->User->exists($id)) {
throw new NotFoundException(__('Invalid user'));
@ -86,16 +80,16 @@ class UsersController extends AppController {
throw new NotFoundException(__('Invalid user'));
}
if ($this->request->is('post') || $this->request->is('put')) {
if ($this->User->save($this->request->data)) {
if ( $this->request->is('post') || $this->request->is('put') ) {
if ( $this->User->save($this->request->data) ) {
$message = 'Saved';
} else {
$message = 'Error';
}
} else {
$this->request->data = $this->User->read(null, $id);
unset($this->request->data['User']['password']);
}
$this->request->data = $this->User->read(null, $id);
unset($this->request->data['User']['password']);
}
$this->set(array(
'message' => $message,
@ -112,11 +106,11 @@ class UsersController extends AppController {
*/
public function delete($id = null) {
$this->User->id = $id;
if (!$this->User->exists()) {
if ( !$this->User->exists() ) {
throw new NotFoundException(__('Invalid user'));
}
$this->request->allowMethod('post', 'delete');
if ($this->User->delete()) {
if ( $this->User->delete() ) {
$message = 'The user has been deleted.';
} else {
$message = 'The user could not be deleted. Please, try again.';
@ -127,29 +121,18 @@ class UsersController extends AppController {
));
}
public function beforeFilter() {
parent::beforeFilter();
public function beforeFilter() {
parent::beforeFilter();
$this->loadModel('Config');
$configs = $this->Config->find('list', array(
'fields' => array('Name', 'Value'),
'conditions' => array('Name' => array('ZM_OPT_USE_AUTH'))
));
if ( $configs['ZM_OPT_USE_AUTH'] ) {
$this->Auth->allow('add','logout');
} else {
$this->Auth->allow();
}
if ( ZM_OPT_USE_AUTH ) {
$this->Auth->allow('add', 'logout');
} else {
$this->Auth->allow();
}
}
public function login() {
$this->loadModel('Config');
$configs = $this->Config->find('list', array(
'fields' => array('Name', 'Value'),
'conditions' => array('Name' => array('ZM_OPT_USE_AUTH'))
));
if ( ! $configs['ZM_OPT_USE_AUTH'] ) {
if ( !ZM_OPT_USE_AUTH ) {
$this->set(array(
'message' => 'Login is not required.',
'_serialize' => array('message')
@ -157,8 +140,8 @@ class UsersController extends AppController {
return;
}
if ($this->request->is('post')) {
if ($this->Auth->login()) {
if ( $this->request->is('post') ) {
if ( $this->Auth->login() ) {
return $this->redirect($this->Auth->redirectUrl());
}
$this->Session->setFlash(__('Invalid username or password, try again'));
@ -168,5 +151,4 @@ class UsersController extends AppController {
public function logout() {
return $this->redirect($this->Auth->logout());
}
}

View File

@ -40,6 +40,7 @@ class ZonesController extends AppController {
'_serialize' => array('zones')
));
}
public function index() {
$this->Zone->recursive = -1;
@ -63,23 +64,43 @@ class ZonesController extends AppController {
* @return void
*/
public function add() {
if ( $this->request->is('post') ) {
global $user;
$canEdit = (!$user) || $user['Monitors'] == 'Edit';
if ( !$canEdit ) {
throw new UnauthorizedException(__('Insufficient Privileges'));
return;
}
if ( !$this->request->is('post') ) {
throw new BadRequestException(__('Invalid method. Should be post'));
return;
}
$this->Zone->create();
if ( $this->Zone->save($this->request->data) ) {
return $this->flash(__('The zone has been saved.'), array('action' => 'index'));
global $user;
$canEdit = (!$user) || $user['Monitors'] == 'Edit';
if ( !$canEdit ) {
throw new UnauthorizedException(__('Insufficient Privileges'));
return;
}
$zone = null;
$this->Zone->create();
$zone = $this->Zone->save($this->request->data);
if ( $zone ) {
require_once __DIR__ .'/../../../includes/Monitor.php';
$monitor = new ZM\Monitor($zone['Zone']['MonitorId']);
$monitor->zmaControl('restart');
$message = 'Saved';
//$zone = $this->Zone->find('first', array('conditions' => array( array('Zone.' . $this->Zone->primaryKey => $this->Zone),
} else {
$message = 'Error: ';
// if there is a validation message, use it
if ( !$this->Zone->validates() ) {
$message = $this->Zone->validationErrors;
}
}
$monitors = $this->Zone->Monitor->find('list');
$this->set(compact('monitors'));
}
$this->set(array(
'message' => $message,
'zone' => $zone,
'_serialize' => array('message','zone')
));
} // end function add()
/**
* edit method

View File

@ -3,8 +3,6 @@ App::uses('AppModel', 'Model');
/**
* User Model
*
* @property Monitor $Monitor
* @property Frame $Frame
*/
class User extends AppModel {
@ -53,14 +51,6 @@ class User extends AppModel {
* @var array
*/
public $belongsTo = array(
/*'Monitor' => array(
'className' => 'Monitor',
'foreignKey' => 'MonitorId',
'conditions' => '',
'fields' => '',
'order' => ''
)
*/
);
/**
@ -69,21 +59,6 @@ class User extends AppModel {
* @var array
*/
public $hasMany = array(
/*
'Frame' => array(
'className' => 'Frame',
'foreignKey' => 'UserId',
'dependent' => true,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
*/
);
}

View File

@ -30,6 +30,32 @@ class Zone extends AppModel {
public $recursive = -1;
/**
* Validation rules
*
* @var array
*/
public $validate = array(
'MonitorId' => array(
'rule' => 'checkMonitorId',
//array('naturalNumber'),
'message' => 'Zones must have a valid MonitorId',
'allowEmpty' => false,
'required' => true,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
'Name' => array(
'required' => array(
//'on' => 'create',
'rule' => 'notBlank',
'message' => 'Zone Name must be specified for creation',
'required' => true,
),
)
);
//The Associations below have been created with all possible keys, those that are not needed can be removed
/**
@ -41,9 +67,17 @@ class Zone extends AppModel {
'Monitor' => array(
'className' => 'Monitor',
'foreignKey' => 'MonitorId',
'conditions' => '',
'fields' => '',
'order' => ''
//'conditions' => '',
//'fields' => '',
//'order' => ''
)
);
public function checkMonitorId($data) {
if ( !$this->Monitor->find('first', array('conditions'=>array('Id'=>$data['MonitorId']))) ) {
//$this->invalidate('MonitorId', 'Invalid Monitor Id');
return false;
}
return true;
}
}

View File

@ -205,6 +205,11 @@ class Monitor extends ZM_Object {
if ( ZM_RAND_STREAM ) {
$args['rand'] = time();
}
foreach ( array('scale','height','width') as $int_arg ) {
if ( isset($args[$int_arg]) and (!is_int($args[$int_arg]) or !$args[$int_arg] ) ) {
unset($args[$int_arg]);
}
}
$streamSrc .= '?'.http_build_query($args, '', $querySep);
@ -297,12 +302,12 @@ class Monitor extends ZM_Object {
return;
}
}
Logger::Debug("sending command to $url");
Logger::Debug('sending command to '.$url);
$context = stream_context_create();
try {
$result = file_get_contents($url, false, $context);
if ($result === FALSE) { /* Handle error */
if ( $result === FALSE ) { /* Handle error */
Error("Error restarting zmc using $url");
}
} catch ( Exception $e ) {
@ -314,14 +319,15 @@ class Monitor extends ZM_Object {
} // end function zmcControl
function zmaControl($mode=false) {
if ( ! $this->{'Id'} ) {
if ( !$this->{'Id'} ) {
Warning('Attempt to control a monitor with no Id');
return;
}
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 ) {
if ( ZM_OPT_CONTROL && $this->Controllable() && $this->TrackMotion() &&
( $this->{'Function'} == 'Modect' || $this->{'Function'} == 'Mocord' ) ) {
daemonControl('stop', 'zmtrack.pl', '-m '.$this->{'Id'});
}
daemonControl('stop', 'zma', '-m '.$this->{'Id'});
@ -344,7 +350,7 @@ class Monitor extends ZM_Object {
} else if ( $this->ServerId() ) {
$Server = $this->Server();
$url = ZM_BASE_PROTOCOL . '://'.$Server->Hostname().'/zm/api/monitors/daemonControl/'.$this->{'Id'}.'/'.$mode.'/zma.json';
$url = $Server->UrlToApi().'/monitors/daemonControl/'.$this->{'Id'}.'/'.$mode.'/zma.json';
if ( ZM_OPT_USE_AUTH ) {
if ( ZM_AUTH_RELAY == 'hashed' ) {
$url .= '?auth='.generateAuthHash(ZM_AUTH_HASH_IPS);
@ -358,10 +364,10 @@ class Monitor extends ZM_Object {
}
Logger::Debug("sending command to $url");
$context = stream_context_create();
$context = stream_context_create();
try {
$result = file_get_contents($url, false, $context);
if ($result === FALSE) { /* Handle error */
if ( $result === FALSE ) { /* Handle error */
Error("Error restarting zma using $url");
}
} catch ( Exception $e ) {
@ -497,12 +503,11 @@ class Monitor extends ZM_Object {
foreach ( explode(' ', $command) as $option ) {
if ( preg_match('/--([^=]+)(?:=(.+))?/', $option, $matches) ) {
$options[$matches[1]] = $matches[2]?$matches[2]:1;
} else if ( $option != '' and $option != 'quit' ) {
} else if ( $option != '' and $option != 'quit' and $option != 'start' and $option != 'stop' ) {
Warning("Ignored command for zmcontrol $option in $command");
}
}
if ( !count($options) ) {
if ( $command == 'quit' or $command == 'start' or $command == 'stop' ) {
# These are special as we now run zmcontrol as a daemon through zmdc.
$status = daemonStatus('zmcontrol.pl', array('--id', $this->{'Id'}));
@ -546,7 +551,7 @@ class Monitor extends ZM_Object {
} else if ( $this->ServerId() ) {
$Server = $this->Server();
$url = ZM_BASE_PROTOCOL . '://'.$Server->Hostname().'/zm/api/monitors/daemonControl/'.$this->{'Id'}.'/'.$command.'/zmcontrol.pl.json';
$url = $Server->UrlToApi().'/monitors/daemonControl/'.$this->{'Id'}.'/'.$command.'/zmcontrol.pl.json';
if ( ZM_OPT_USE_AUTH ) {
if ( ZM_AUTH_RELAY == 'hashed' ) {
$url .= '?auth='.generateAuthHash(ZM_AUTH_HASH_IPS);

View File

@ -85,8 +85,6 @@ if ( isset($_REQUEST['object']) and ( $_REQUEST['object'] == 'filter' ) ) {
// We update the request id so that the newly saved filter is auto-selected
$_REQUEST['Id'] = $filter->Id();
}
if ( $filter->Background() )
$filter->control('start');
if ( $action == 'execute' ) {
$filter->execute();
@ -94,6 +92,8 @@ if ( isset($_REQUEST['object']) and ( $_REQUEST['object'] == 'filter' ) ) {
$filter->delete();
$view = 'events';
} else if ( $filter->Background() ) {
$filter->control('start');
}
} else if ( $action == 'control' ) {

View File

@ -18,27 +18,36 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
if ( $action == 'user' ) {
if ( $action == 'Save' ) {
if ( canEdit('System') ) {
if ( !empty($_REQUEST['uid']) )
if ( !empty($_REQUEST['uid']) ) {
$dbUser = dbFetchOne('SELECT * FROM Users WHERE Id=?', NULL, array($_REQUEST['uid']));
else
} else {
$dbUser = array();
}
$types = array();
if ( isset($_REQUEST['newUser']['MonitorIds']) and is_array($_REQUEST['newUser']['MonitorIds']) )
$_REQUEST['newUser']['MonitorIds'] = implode(',', $_REQUEST['newUser']['MonitorIds']);
if ( !$_REQUEST['newUser']['Password'] )
unset($_REQUEST['newUser']['Password']);
$changes = getFormChanges($dbUser, $_REQUEST['newUser'], $types);
if ( function_exists('password_hash') ) {
$pass_hash = '"'.password_hash($_REQUEST['newUser']['Password'], PASSWORD_BCRYPT).'"';
} else {
$pass_hash = ' PASSWORD('.dbEscape($_REQUEST['newUser']['Password']).') ';
ZM\Info('Cannot use bcrypt as you are using PHP < 5.3');
}
if ( $_REQUEST['newUser']['Password'] ) {
$changes['Password'] = 'Password = '.$pass_hash;
} else {
unset($changes['Password']);
if ( isset($_REQUEST['newUser']['Password']) ) {
if ( function_exists('password_hash') ) {
$pass_hash = '"'.password_hash($_REQUEST['newUser']['Password'], PASSWORD_BCRYPT).'"';
} else {
$pass_hash = ' PASSWORD('.dbEscape($_REQUEST['newUser']['Password']).') ';
ZM\Info('Cannot use bcrypt as you are using PHP < 5.3');
}
if ( $_REQUEST['newUser']['Password'] ) {
$changes['Password'] = 'Password = '.$pass_hash;
} else {
unset($changes['Password']);
}
}
if ( count($changes) ) {

View File

@ -2,21 +2,21 @@
//
// ZoneMinder web function library, $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.
//
//
// Compatibility functions
if ( version_compare(phpversion(), '4.3.0', '<') ) {
@ -299,7 +299,7 @@ function outputHelperStream($id, $src, $width, $height, $title='') {
}
function getHelperStream($id, $src, $width, $height, $title='') {
return '<object type="application/x-java-applet" id="'.$id.'" code="com.charliemouse.cambozola.Viewer"
archive="'. ZM_PATH_CAMBOZOLA .'"
archive="'. ZM_PATH_CAMBOZOLA .'"
align="middle"
width="'. $width .'"
height="'. $height .'"
@ -1244,7 +1244,7 @@ function parseFilter(&$filter, $saveToSession=false, $querySep='&amp;') {
if ( !isset($term['val']) ) $term['val'] = '';
foreach ( preg_split('/["\'\s]*?,["\'\s]*?/', preg_replace('/^["\']+?(.+)["\']+?$/', '$1', $term['val'])) as $value ) {
switch ( $term['attr'] ) {
case 'AlarmedZoneId':
$value = '(SELECT * FROM Stats WHERE EventId=E.Id AND ZoneId='.$value.')';
break;
@ -1386,7 +1386,7 @@ function parseFilter(&$filter, $saveToSession=false, $querySep='&amp;') {
function addFilterTerm($filter, $position, $term=false) {
if ( $position < 0 )
$position = 0;
if ( !isset($filter['Query']['terms']) )
$filter['Query']['terms'] = array();
else if ( $position > count($filter['Query']['terms']) )
@ -1578,7 +1578,7 @@ function systemStats() {
function getcpus() {
if ( is_readable('/proc/cpuinfo') ) { # Works on Linux
preg_match_all('/^processor/m', file_get_contents('/proc/cpuinfo'), $matches);
preg_match_all('/^processor/m', file_get_contents('/proc/cpuinfo'), $matches);
$num_cpus = count($matches[0]);
} else { # Works on BSD
$matches = explode(':', shell_exec('sysctl hw.ncpu'));
@ -1588,8 +1588,8 @@ function getcpus() {
return $num_cpus;
}
// Function to fix a problem whereby the built in PHP session handling
// features want to put the sid as a hidden field after the form or
// Function to fix a problem whereby the built in PHP session handling
// features want to put the sid as a hidden field after the form or
// fieldset tag, neither of which will work with strict XHTML Basic.
function sidField() {
if ( SID ) {
@ -1684,7 +1684,7 @@ function linesIntersect($line1, $line2) {
return false;
}
} elseif ( $b1 == $b2 ) {
// Colinear, must overlap due to box check, intersect?
// Colinear, must overlap due to box check, intersect?
if ( $debug ) echo 'Intersecting, colinear<br>';
return true;
} else {
@ -1692,7 +1692,7 @@ function linesIntersect($line1, $line2) {
if ( $debug ) echo 'Not intersecting, parallel<br>';
return false;
}
} elseif ( !$dx1 ) { // Line 1 is vertical
} elseif ( !$dx1 ) { // Line 1 is vertical
$y = ( $m2 * $line1[0]['x'] ) * $b2;
if ( $y >= $min_y1 && $y <= $max_y1 ) {
if ( $debug ) echo "Intersecting, at y $y<br>";
@ -1701,7 +1701,7 @@ function linesIntersect($line1, $line2) {
if ( $debug ) echo "Not intersecting, out of range at y $y<br>";
return false;
}
} elseif ( !$dx2 ) { // Line 2 is vertical
} elseif ( !$dx2 ) { // Line 2 is vertical
$y = ( $m1 * $line2[0]['x'] ) * $b1;
if ( $y >= $min_y2 && $y <= $max_y2 ) {
if ( $debug ) echo "Intersecting, at y $y<br>";
@ -1712,7 +1712,7 @@ function linesIntersect($line1, $line2) {
}
} else { // Both lines are vertical
if ( $line1[0]['x'] == $line2[0]['x'] ) {
// Colinear, must overlap due to box check, intersect?
// Colinear, must overlap due to box check, intersect?
if ( $debug ) echo 'Intersecting, vertical, colinear<br>';
return true;
} else {
@ -2169,7 +2169,7 @@ function jsonDecode($value) {
} else if ( $value[$i] == ':' ) {
$out .= '=>';
} else {
$out .= $value[$i];
$out .= $value[$i];
}
} else if ( !$unescape ) {
if ( $value[$i] == '\\' )
@ -2311,7 +2311,8 @@ function validHtmlStr($input) {
function getStreamHTML($monitor, $options = array()) {
if ( isset($options['scale']) ) {
if ( $options['scale'] and ( $options['scale'] != 'auto' ) ) {
if ( $options['scale'] != 'auto' && $options['scale'] != '0' and $options['scale'] != '' ) {
ZM\Logger::Debug("Setting dimensions from scale:".$options['scale']);
$options['width'] = reScale($monitor->ViewWidth(), $options['scale']).'px';
$options['height'] = reScale($monitor->ViewHeight(), $options['scale']).'px';
} else {
@ -2363,8 +2364,8 @@ function getStreamHTML($monitor, $options = array()) {
return getImageStreamHTML( 'liveStream'.$monitor->Id(), $streamSrc, $options['width'], $options['height'], $monitor->Name());
elseif ( canStreamApplet() )
// Helper, empty widths and heights really don't work.
return getHelperStream( 'liveStream'.$monitor->Id(), $streamSrc,
$options['width'] ? $options['width'] : $monitor->ViewWidth(),
return getHelperStream( 'liveStream'.$monitor->Id(), $streamSrc,
$options['width'] ? $options['width'] : $monitor->ViewWidth(),
$options['height'] ? $options['height'] : $monitor->ViewHeight(),
$monitor->Name());
} else {
@ -2423,8 +2424,8 @@ function check_timezone() {
'TIME_FORMAT(TIMEDIFF(NOW(), UTC_TIMESTAMP),\'%H%i\')'
));
#Logger::Debug("System timezone offset determine to be: $sys_tzoffset,\x20
#PHP timezone offset determine to be: $php_tzoffset,\x20
#Logger::Debug("System timezone offset determine to be: $sys_tzoffset,\x20
#PHP timezone offset determine to be: $php_tzoffset,\x20
#Mysql timezone offset determine to be: $mysql_tzoffset
#");
@ -2439,7 +2440,7 @@ function check_timezone() {
}
function unparse_url($parsed_url, $substitutions = array() ) {
function unparse_url($parsed_url, $substitutions = array() ) {
$fields = array('scheme','host','port','user','pass','path','query','fragment');
foreach ( $fields as $field ) {
@ -2447,16 +2448,16 @@ function unparse_url($parsed_url, $substitutions = array() ) {
$parsed_url[$field] = $substitutions[$field];
}
}
$scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : '';
$host = isset($parsed_url['host']) ? $parsed_url['host'] : '';
$port = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : '';
$user = isset($parsed_url['user']) ? $parsed_url['user'] : '';
$pass = isset($parsed_url['pass']) ? ':' . $parsed_url['pass'] : '';
$pass = ($user || $pass) ? "$pass@" : '';
$path = isset($parsed_url['path']) ? $parsed_url['path'] : '';
$query = isset($parsed_url['query']) ? '?' . $parsed_url['query'] : '';
$fragment = isset($parsed_url['fragment']) ? '#' . $parsed_url['fragment'] : '';
return "$scheme$user$pass$host$port$path$query$fragment";
$scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : '';
$host = isset($parsed_url['host']) ? $parsed_url['host'] : '';
$port = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : '';
$user = isset($parsed_url['user']) ? $parsed_url['user'] : '';
$pass = isset($parsed_url['pass']) ? ':' . $parsed_url['pass'] : '';
$pass = ($user || $pass) ? $pass.'@' : '';
$path = isset($parsed_url['path']) ? $parsed_url['path'] : '';
$query = isset($parsed_url['query']) ? '?' . $parsed_url['query'] : '';
$fragment = isset($parsed_url['fragment']) ? '#' . $parsed_url['fragment'] : '';
return $scheme.$user.$pass.$host.$port.$path.$query.$fragment;
}
// PP - POST request handler for PHP which does not need extensions

View File

@ -52,6 +52,14 @@ require_once('includes/Event.php');
require_once('includes/Group.php');
require_once('includes/Monitor.php');
// Useful debugging lines for mobile devices
if ( ZM\Logger::fetch()->debugOn() ) {
ob_start();
phpinfo(INFO_VARIABLES);
ZM\Logger::Debug(ob_get_contents());
ob_end_clean();
}
global $Servers;
$Servers = ZM\Server::find();

View File

@ -87,6 +87,7 @@ $SLANG = array(
'Actual' => 'Actual',
'AddNewControl' => 'Add New Control',
'AddNewMonitor' => 'Add',
'AddMonitorDisabled' => 'Your user is not allowed to add a new monitor',
'AddNewServer' => 'Add New Server',
'AddNewStorage' => 'Add New Storage',
'AddNewUser' => 'Add New User',

View File

@ -83,8 +83,8 @@ $SLANG = array(
'Actual' => 'Attuale',
'AddNewControl' => 'Aggiungi nuovo Controllo',
'AddNewMonitor' => 'Aggiungi nuovo Monitor',
'AddNewServer' => 'Add New Server', // Added - 2018-08-30
'AddNewStorage' => 'Add New Storage', // Added - 2018-08-30
'AddNewServer' => 'Aggiungi nuovo Server', // Added - 2018-08-30
'AddNewStorage' => 'Aggiungi nuovo Storage', // Added - 2018-08-30
'AddNewUser' => 'Aggiungi nuovo Utente',
'AddNewZone' => 'Aggiungi nuova Zona',
'Alarm' => 'Allarme',
@ -103,7 +103,7 @@ $SLANG = array(
'Apply' => 'Applica',
'ApplyingStateChange' => 'Sto applicando le modifiche',
'ArchArchived' => 'Archiviato',
'ArchUnarchived' => 'Non archiviare',
'ArchUnarchived' => 'Non archiviato',
'Archive' => 'Archivio',
'Archived' => 'Archiviato',
'Area' => 'Area',
@ -142,14 +142,14 @@ $SLANG = array(
'AutoStopTimeout' => 'Auto Stop Timeout',
'Available' => 'Disponibile', // Added - 2009-03-31
'AvgBrScore' => 'Punteggio<br/>medio',
'Background' => 'Background',
'Background' => 'Sfondo',
'BackgroundFilter' => 'Esegui filtro in background',
'BadAlarmFrameCount' => 'Il numero di frame di un allarme deve essere un numero intero superiore a uno',
'BadAlarmMaxFPS' => 'Il numero massimo di FPS dell\'allarme deve essere un numero intero positivo o un valore in virgola mobile',
'BadAnalysisFPS' => 'Analysis FPS must be a positive integer or floating point value', // Added - 2015-07-22
'BadAnalysisUpdateDelay'=> 'Analysis update delay must be set to an integer of zero or more', // Added - 2015-07-23
'BadAlarmFrameCount' => 'Il numero di immagini per secondo (FPS) di un allarme deve essere un numero intero superiore a uno',
'BadAlarmMaxFPS' => 'Il numero massimo di immagini per secondo (FPS) dell\'allarme deve essere un numero intero positivo o un valore in virgola mobile',
'BadAnalysisFPS' => 'Il numero di immagini per secondo (FPS) di analisi deve essere un numero intero positivo o un valore in virgola mobile', // Added - 2015-07-22
'BadAnalysisUpdateDelay'=> 'Il ritardo di aggiornamento dell\'analisi deve essere impostato su un numero intero pari a zero o superiore', // Added - 2015-07-23
'BadChannel' => 'Il canale deve essere settato con un numero intero uguale o maggiore di zero',
'BadColours' => 'Target colour must be set to a valid value', // Added - 2011-06-15
'BadColours' => 'Il colore target deve essere impostato su un valore valido', // Added - 2011-06-15
'BadDevice' => 'Il dispositivo deve essere impostato con un valore valido',
'BadFPSReportInterval' => 'L\'intervallo di FPS per i report deve essere un numero intero superiore a 0',
'BadFormat' => 'Il formato deve essere impostato con un numero intero come 0 o maggiore',
@ -160,24 +160,24 @@ $SLANG = array(
'BadLabelX' => 'L\'etichetta della coordinata X deve essere un numero intero pari a 0 o maggiore',
'BadLabelY' => 'L\'etichetta della coordinata Y deve essere un numero intero pari a 0 o maggiore',
'BadMaxFPS' => 'I frame per secondo (FPS) massimi devono essere un numero intero positivo o un valore in virgola mobile',
'BadMotionFrameSkip' => 'Motion Frame skip count must be an integer of zero or more',
'BadMotionFrameSkip' => 'Il conteggio dei salti di Motion Frame deve essere un numero intero pari a zero o superiore',
'BadNameChars' => 'I nomi possono contenere solo caratteri alfanumerici pi&ugrave; i caratteri - e _',
'BadPalette' => 'La palette dei colori deve essere impostata ad un valore valido', // Added - 2009-03-31
'BadPalette' => 'La tavolozza dei colori deve essere impostata ad un valore valido', // Added - 2009-03-31
'BadPath' => 'Il percorso deve essere impostato con un valore valido',
'BadPort' => 'La porta deve essere settata con un valore valido',
'BadPostEventCount' => 'Il buffer d\'immagine successivo ad un evento deve essere un numero maggiore o uguale a zero',
'BadPreEventCount' => 'Il buffer d\'immagine antecedente ad un evento deve essere minimo 0 e comunque minore della dimensione del buffer d\'immagine',
'BadRefBlendPerc' => 'La percentuale di miscela di riferimento deve essere un intero positivo',
'BadSectionLength' => 'La lunghezza della sezione deve essere un numero intero pari a 30 o maggiore',
'BadSignalCheckColour' => 'Signal check colour must be a valid RGB colour string',
'BadSourceType' => 'Source Type \"Web Site\" requires the Function to be set to \"Monitor\"', // Added - 2018-08-30
'BadStreamReplayBuffer'=> 'Stream replay buffer must be an integer of zero or more',
'BadSignalCheckColour' => 'Il colore di controllo del segnale deve essere una stringa di colore RGB valida',
'BadSourceType' => 'Il tipo di origine \"Sito Web\" richiede che la funzione sia impostata su \"Monitor\"', // Added - 2018-08-30
'BadStreamReplayBuffer'=> 'Il buffer di riproduzione dello stream deve essere un numero intero pari a zero o superiore',
'BadWarmupCount' => 'Il numero di frame di allarme deve essere un numero intero maggiore o uguale a zero',
'BadWebColour' => 'L\'identificativo del colore deve essere una stringa valida',
'BadWebSitePath' => 'Please enter a complete website url, including the http:// or https:// prefix.', // Added - 2018-08-30
'BadWebSitePath' => 'Inserisci un URL completo del sito Web, incluso il prefisso http: // o https: //.', // Added - 2018-08-30
'BadWidth' => 'La larghezza deve essere impostata con un valore valido',
'Bandwidth' => 'Banda',
'BandwidthHead' => 'Bandwidth', // This is the end of the bandwidth status on the top of the console, different in many language due to phrasing
'BandwidthHead' => 'Larghezza di banda', // This is the end of the bandwidth status on the top of the console, different in many language due to phrasing
'BlobPx' => 'Blob Px',
'BlobSizes' => 'Dimensioni Blob',
'Blobs' => 'Blobs',
@ -228,15 +228,15 @@ $SLANG = array(
'CancelForcedAlarm' => 'Annulla Allarme Forzato',
'CaptureHeight' => 'Altezza img catturata',
'CaptureMethod' => 'Metodo di cattura', // Added - 2009-02-08
'CapturePalette' => 'Paletta img Catturata',
'CaptureResolution' => 'Capture Resolution', // Added - 2015-04-18
'CapturePalette' => 'Paletta img catturata',
'CaptureResolution' => 'Risoluzione di cattura', // Added - 2015-04-18
'CaptureWidth' => 'Larghezza img Catturata',
'Cause' => 'Causa',
'CheckMethod' => 'Metodo di Controllo Allarme',
'ChooseDetectedCamera' => 'Scegli telecamera rilevata', // Added - 2009-03-31
'ChooseFilter' => 'Scegli Filtro',
'ChooseLogFormat' => 'Choose a log format', // Added - 2011-06-17
'ChooseLogSelection' => 'Choose a log selection', // Added - 2011-06-17
'ChooseLogFormat' => 'Scegli un formato di registro', // Added - 2011-06-17
'ChooseLogSelection' => 'Scegli una selezione del registro', // Added - 2011-06-17
'ChoosePreset' => 'Scegli Preset',
'Clear' => 'Clear', // Added - 2011-06-16
'CloneMonitor' => 'Clone', // Added - 2018-08-30
@ -301,12 +301,12 @@ $SLANG = array(
'DonateRemindNever' => 'No, io non voglio donare, non lo faro\' mai',
'DonateRemindWeek' => 'Non ancora, ricordamelo ancora tra 1 settimana',
'DonateYes' => 'Si,mi piacerebbe donare qualcosa ora',
'Download' => 'Download',
'DownloadVideo' => 'Download Video', // Added - 2018-08-30
'DuplicateMonitorName' => 'Il nome del monitor e\' gia\' presente', // Added - 2009-03-31
'Download' => 'Scarica',
'DownloadVideo' => 'Scarica video', // Added - 2018-08-30
'DuplicateMonitorName' => 'Il nome del monitor è già presente', // Added - 2009-03-31
'Duration' => 'Durata',
'Edit' => 'Modifica',
'EditLayout' => 'Edit Layout', // Added - 2018-08-30
'EditLayout' => 'Modifica Layout', // Added - 2018-08-30
'Email' => 'Email',
'EnableAlarms' => 'Abilita Allarmi',
'Enabled' => 'Attivo',
@ -323,7 +323,7 @@ $SLANG = array(
'Events' => 'Eventi',
'Exclude' => 'Escludi',
'Execute' => 'Esegui',
'Exif' => 'Embed EXIF data into image', // Added - 2018-08-30
'Exif' => 'Includi dati EXIF nell\'immagine', // Added - 2018-08-30
'Export' => 'Esporta',
'ExportDetails' => 'Esp. dettagli eventi',
'ExportFailed' => 'Esp. Fallita ',
@ -346,17 +346,17 @@ $SLANG = array(
'Feed' => 'Feed',
'Ffmpeg' => 'Ffmpeg', // Added - 2009-02-08
'File' => 'File',
'Filter' => 'Filter', // Added - 2015-04-18
'Filter' => 'Filtro', // Added - 2015-04-18
'FilterArchiveEvents' => 'Archivia gli eventi',
'FilterDeleteEvents' => 'Elimina gli eventi',
'FilterEmailEvents' => 'Invia dettagli via email',
'FilterExecuteEvents' => 'Esegui un comando',
'FilterLog' => 'Filter log', // Added - 2015-04-18
'FilterMessageEvents' => 'Invia dettagli tramite messaggio',
'FilterMoveEvents' => 'Move all matches', // Added - 2018-08-30
'FilterMoveEvents' => 'Sposta tutti gli eventi', // Added - 2018-08-30
'FilterPx' => 'Px Filtro',
'FilterUnset' => 'Devi specificare altezza e larghezza per il filtro',
'FilterUpdateDiskSpace'=> 'Update used disk space', // Added - 2018-08-30
'FilterUpdateDiskSpace'=> 'Aggiorna spazio disco utilizzato', // Added - 2018-08-30
'FilterUploadEvents' => 'Fai upload eventi (FTP)',
'FilterVideoEvents' => 'Crea video per tutte le corrispondenze',
'Filters' => 'Filtri',
@ -381,9 +381,9 @@ $SLANG = array(
'Function' => 'Funzione',
'Gain' => 'Gain',
'General' => 'Generale',
'GenerateDownload' => 'Generate Download', // Added - 2018-08-30
'GenerateVideo' => 'Genera Video',
'GeneratingVideo' => 'Sto generando il Video',
'GenerateDownload' => 'Genera download', // Added - 2018-08-30
'GenerateVideo' => 'Genera video',
'GeneratingVideo' => 'Sto generando il video',
'GoToZoneMinder' => 'Vai su zoneminder.com',
'Grey' => 'Grigio',
'Group' => 'Gruppo',
@ -402,7 +402,7 @@ $SLANG = array(
'High' => 'Alta',
'HighBW' => 'Banda&nbsp;Alta',
'Home' => 'Home',
'Hostname' => 'Hostname', // Added - 2018-08-30
'Hostname' => 'Nome Host', // Added - 2018-08-30
'Hour' => 'Ora',
'Hue' => 'Tinta',
'Id' => 'Id',
@ -420,14 +420,14 @@ $SLANG = array(
'Language' => 'Linguaggio',
'Last' => 'Ultimo',
'Layout' => 'Layout', // Added - 2009-02-08
'Level' => 'Level', // Added - 2011-06-16
'Level' => 'Livello', // Added - 2011-06-16
'Libvlc' => 'Libvlc',
'LimitResultsPost' => 'risultati;', // This is used at the end of the phrase 'Limit to first N results only'
'LimitResultsPre' => 'Limita ai primi', // This is used at the beginning of the phrase 'Limit to first N results only'
'Line' => 'Line', // Added - 2011-06-16
'LinkedMonitors' => 'Monitor Collegati',
'List' => 'Lista',
'ListMatches' => 'List Matches', // Added - 2018-08-30
'ListMatches' => 'Elenca le corrispondenze', // Added - 2018-08-30
'Load' => 'Carico Sistema',
'Local' => 'Locale',
'Log' => 'Log', // Added - 2011-06-16
@ -505,12 +505,12 @@ $SLANG = array(
'MinZoomSpeed' => 'Velocita\' minima dello zoom',
'MinZoomStep' => 'Step minimo dello zoom',
'Misc' => 'Altro',
'Mode' => 'Mode', // Added - 2015-04-18
'Mode' => 'Modalità', // Added - 2015-04-18
'Monitor' => 'Monitor',
'MonitorIds' => 'Monitor&nbsp;Ids',
'MonitorPreset' => 'Monitor Presenti',
'MonitorPresetIntro' => 'Selezionare un appropriato pre settaggio dalla lista riportata qui sotto.<br><br>Per favore notare che questo potrebbe sovrascrivere ogni valore che hai gi&agrave; configurato su questo monitor.<br><br>',
'MonitorProbe' => 'Monitor Probe', // Added - 2009-03-31
'MonitorProbe' => 'Prova Monitor', // Added - 2009-03-31
'MonitorProbeIntro' => 'The list below shows detected analog and network cameras and whether they are already being used or available for selection.<br/><br/>Select the desired entry from the list below.<br/><br/>Please note that not all cameras may be detected and that choosing a camera here may overwrite any values you already have configured for the current monitor.<br/><br/>', // Added - 2009-03-31
'Monitors' => 'Monitors',
'Montage' => 'Montaggio',
@ -523,7 +523,7 @@ $SLANG = array(
'Mtg3widgrd' => '3-wide grid', // Added 2013.08.15.
'Mtg3widgrx' => '3-wide grid, scaled, enlarge on alarm', // Added 2013.08.15.
'Mtg4widgrd' => '4-wide grid', // Added 2013.08.15.
'MtgDefault' => 'Default', // Added 2013.08.15.
'MtgDefault' => 'Predefinito', // Added 2013.08.15.
'MustBeGe' => 'deve essere superiore a',
'MustBeLe' => 'deve essere inferiore o pari a',
'MustConfirmPassword' => 'Devi confermare la password',
@ -541,10 +541,10 @@ $SLANG = array(
'Next' => 'Prossimo',
'No' => 'No',
'NoDetectedCameras' => 'Nessuna telecamera rilevata', // Added - 2009-03-31
'NoDetectedProfiles' => 'No Detected Profiles', // Added - 2018-08-30
'NoDetectedProfiles' => 'Nessun profilo rilevato', // Added - 2018-08-30
'NoFramesRecorded' => 'Non ci sono immagini salvate per questo evento',
'NoGroup' => 'Nessun gruppo', // Added - 2009-02-08
'NoSavedFilters' => 'NessunFiltroSalvato',
'NoSavedFilters' => 'Nessun filtro salvato',
'NoStatisticsRecorded' => 'Non ci sono statistiche salvate per questo evento/immagine',
'None' => 'Nessuno',
'NoneAvailable' => 'Nessuno disponibile',
@ -553,15 +553,15 @@ $SLANG = array(
'NumPresets' => 'Num Presets',
'Off' => 'Off',
'On' => 'On',
'OnvifCredentialsIntro'=> 'Please supply user name and password for the selected camera.<br/>If no user has been created for the camera then the user given here will be created with the given password.<br/><br/>', // Added - 2015-04-18
'OnvifCredentialsIntro'=> 'Fornire nome utente e password per la telecamera selezionata.<br/>Se non è stato creato alcun utente per la videocamera, l\'utente qui indicato verrà creato con la password specificata.<br/><br/>', // Added - 2015-04-18
'OnvifProbe' => 'ONVIF', // Added - 2015-04-18
'OnvifProbeIntro' => 'The list below shows detected ONVIF cameras and whether they are already being used or available for selection.<br/><br/>Select the desired entry from the list below.<br/><br/>Please note that not all cameras may be detected and that choosing a camera here may overwrite any values you already have configured for the current monitor.<br/><br/>', // Added - 2015-04-18
'OnvifProbeIntro' => 'L\'elenco seguente mostra le telecamere ONVIF rilevate e se sono già in uso o disponibili per la selezione. Selezionare la voce desiderata dall\'elenco seguente. Si noti che non tutte le telecamere potrebbero essere rilevate e che la scelta di una telecamera qui può sovrascrivere tutti i valori già configurati per il monitor corrente.', // Added - 2015-04-18
'OpEq' => 'uguale a',
'OpGt' => 'maggiore di',
'OpGtEq' => 'maggiore o uguale a',
'OpIn' => 'impostato',
'OpIs' => 'is', // Added - 2018-08-30
'OpIsNot' => 'is not', // Added - 2018-08-30
'OpIs' => 'è', // Added - 2018-08-30
'OpIsNot' => 'non è', // Added - 2018-08-30
'OpLt' => 'minore di',
'OpLtEq' => 'minore o uguale a',
'OpMatches' => 'corrisponde',
@ -571,7 +571,7 @@ $SLANG = array(
'Open' => 'Apri',
'OptionHelp' => 'Opzioni di Aiuto',
'OptionRestartWarning' => 'Queste modifiche potrebbero essere attive solo dopo un riavvio del sistema. Riavviare ZoneMinder.',
'OptionalEncoderParam' => 'Optional Encoder Parameters', // Added - 2018-08-30
'OptionalEncoderParam' => 'Parametri Encoder opzionali', // Added - 2018-08-30
'Options' => 'Opzioni',
'OrEnterNewName' => 'o inserisci un nuovo nome',
'Order' => 'Ordine',
@ -605,24 +605,24 @@ $SLANG = array(
'Presets' => 'Presets',
'Prev' => 'Prec',
'Probe' => 'Prova la telecamera', // Added - 2009-03-31
'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18
'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .<br/><br/>Select the desired entry from the list below.<br/><br/>Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.<br/><br/>', // Added - 2015-04-18
'Progress' => 'Progress', // Added - 2015-04-18
'Protocol' => 'Protocol',
'ProfileProbe' => 'Prova lo stream', // Added - 2015-04-18
'ProfileProbeIntro' => 'L\'elenco seguente mostra i profili di streaming esistenti della telecamera selezionata.<br/><br/>Selezionare la voce desiderata dall\'elenco seguente.<br/><br/>Si noti che ZoneMinder non è in grado di configurare profili aggiuntivi e che la scelta di una telecamera qui può sovrascrivere qualsiasi valore già configurato per il monitor corrente.<br/><br/>', // Added - 2015-04-18
'Progress' => 'Progresso', // Added - 2015-04-18
'Protocol' => 'Protocollo',
'RTSPDescribe' => 'Use RTSP Response Media URL', // Added - 2018-08-30
'RTSPTransport' => 'RTSP Transport Protocol', // Added - 2018-08-30
'Rate' => 'Velocita\'',
'Rate' => 'Velocità',
'Real' => 'Reale',
'RecaptchaWarning' => 'Your reCaptcha secret key is invalid. Please correct it, or reCaptcha will not work', // Added - 2018-08-30
'RecaptchaWarning' => 'La chiave segreta reCaptcha non è valida. Correggila o reCaptcha non funzionerà', // Added - 2018-08-30
'Record' => 'Registra',
'RecordAudio' => 'Whether to store the audio stream when saving an event.', // Added - 2018-08-30
'RecordAudio' => 'Memorizza flusso audio quando salva un evento.', // Added - 2018-08-30
'RefImageBlendPct' => 'Riferimento Miscela Immagine percentuale',
'Refresh' => 'Aggiorna',
'Remote' => 'Remoto',
'RemoteHostName' => 'Nome dell\'Host Remoto',
'RemoteHostPath' => 'Percorso dell\'Host Remoto',
'RemoteHostPort' => 'Porta dell\'Host Remoto',
'RemoteHostSubPath' => 'Remote Host SubPath', // Added - 2009-02-08
'RemoteHostSubPath' => 'SubPath host remoto', // Added - 2009-02-08
'RemoteImageColours' => 'Colori delle immagini Remote',
'RemoteMethod' => 'Metodo Remoto', // Added - 2009-02-08
'RemoteProtocol' => 'Protocollo Remoto', // Added - 2009-02-08
@ -631,7 +631,7 @@ $SLANG = array(
'ReplayAll' => 'All Events',
'ReplayGapless' => 'Gapless Events',
'ReplaySingle' => 'Single Event',
'ReportEventAudit' => 'Audit Events Report', // Added - 2018-08-30
'ReportEventAudit' => 'Rapporto Eventi di controllo', // Added - 2018-08-30
'Reset' => 'Resetta',
'ResetEventCounts' => 'Resetta Contatore Eventi',
'Restart' => 'Riavvia',
@ -643,21 +643,21 @@ $SLANG = array(
'Rewind' => 'Riavvolgi',
'RotateLeft' => 'Ruota a Sinista',
'RotateRight' => 'Ruota a Destra',
'RunLocalUpdate' => 'Please run zmupdate.pl to update', // Added - 2011-05-25
'RunLocalUpdate' => 'Eseguire zmupdate.pl per l\'aggiornamento', // Added - 2011-05-25
'RunMode' => 'Modalita\' funzionamento',
'RunState' => 'Stato di funzionamento',
'Running' => 'Attivo',
'Save' => 'Salva',
'SaveAs' => 'Salva come',
'SaveFilter' => 'salva Filtro',
'SaveJPEGs' => 'Save JPEGs', // Added - 2018-08-30
'SaveFilter' => 'Salva Filtro',
'SaveJPEGs' => 'Salva JPEGs', // Added - 2018-08-30
'Scale' => 'Scala',
'Score' => 'Punteggio',
'Secs' => 'Secs',
'Sectionlength' => 'Lunghezza Sezione',
'Select' => 'Seleziona',
'SelectFormat' => 'Select Format', // Added - 2011-06-17
'SelectLog' => 'Select Log', // Added - 2011-06-17
'SelectFormat' => 'Seleziona Formato', // Added - 2011-06-17
'SelectLog' => 'Seleziona Log', // Added - 2011-06-17
'SelectMonitors' => 'Monitor Selezionati',
'SelfIntersecting' => 'I vertici del poligono non devono intersecarsi',
'Set' => 'Imposta',
@ -666,10 +666,10 @@ $SLANG = array(
'Settings' => 'Impostazioni',
'ShowFilterWindow' => 'MostraFinestraFiltri',
'ShowTimeline' => 'Mostra linea temporale',
'SignalCheckColour' => 'Signal Check Colour',
'SignalCheckPoints' => 'Signal Check Points', // Added - 2018-08-30
'SignalCheckColour' => 'Colore controllo segnale',
'SignalCheckPoints' => 'Punti di controllo segnale', // Added - 2018-08-30
'Size' => 'grandezza',
'SkinDescription' => 'Change the default skin for this computer', // Added - 2011-01-30
'SkinDescription' => 'Cambia la skin predefinita per questo computer', // Added - 2011-01-30
'Sleep' => 'Sleep',
'SortAsc' => 'Cresc',
'SortBy' => 'Ordina per',
@ -692,8 +692,8 @@ $SLANG = array(
'StatusRunning' => 'Not Capturing', // Added - 2018-08-30
'StatusUnknown' => 'Unknown', // Added - 2018-08-30
'Step' => 'Passo',
'StepBack' => 'Step Back',
'StepForward' => 'Step Forward',
'StepBack' => 'Passo indietro',
'StepForward' => 'Passo avanti',
'StepLarge' => 'Lungo passo',
'StepMedium' => 'Medio passo',
'StepNone' => 'No passo',
@ -701,13 +701,13 @@ $SLANG = array(
'Stills' => 'Foto',
'Stop' => 'Stop',
'Stopped' => 'Inattivo',
'StorageArea' => 'Storage Area', // Added - 2018-08-30
'StorageArea' => 'Area di salvataggio', // Added - 2018-08-30
'StorageScheme' => 'Scheme', // Added - 2018-08-30
'Stream' => 'Flusso',
'StreamReplayBuffer' => 'Stream Replay Image Buffer',
'Submit' => 'Accetta',
'System' => 'Sistema',
'SystemLog' => 'System Log', // Added - 2011-06-16
'SystemLog' => 'Log di sistema', // Added - 2011-06-16
'TargetColorspace' => 'Target colorspace', // Added - 2015-04-18
'Tele' => 'Tele',
'Thumbnail' => 'Anteprima',
@ -716,18 +716,18 @@ $SLANG = array(
'TimeDelta' => 'Tempo di Delta',
'TimeStamp' => 'Time Stamp',
'Timeline' => 'Linea Temporale',
'TimelineTip1' => 'Pass your mouse over the graph to view a snapshot image and event details.', // Added 2013.08.15.
'TimelineTip2' => 'Click on the coloured sections of the graph, or the image, to view the event.', // Added 2013.08.15.
'TimelineTip3' => 'Click on the background to zoom in to a smaller time period based around your click.', // Added 2013.08.15.
'TimelineTip4' => 'Use the controls below to zoom out or navigate back and forward through the time range.', // Added 2013.08.15.
'TimelineTip1' => 'Passa il mouse sul grafico per visualizzare un\'immagine dell\'istantanea e i dettagli dell\'evento.', // Added 2013.08.15.
'TimelineTip2' => 'Fai clic sulle sezioni colorate del grafico o sull\'immagine per visualizzare l\'evento.', // Added 2013.08.15.
'TimelineTip3' => 'Fare clic sullo sfondo per ingrandire un periodo di tempo più piccolo basato sul clic.', // Added 2013.08.15.
'TimelineTip4' => 'Utilizzare i controlli seguenti per ridurre o spostarsi avanti e indietro nell\'intervallo di tempo.', // Added 2013.08.15.
'Timestamp' => 'Timestamp',
'TimestampLabelFormat' => 'Formato etichetta timestamp',
'TimestampLabelSize' => 'Font Size', // Added - 2018-08-30
'TimestampLabelSize' => 'Dimensione carattere', // Added - 2018-08-30
'TimestampLabelX' => 'coordinata X etichetta',
'TimestampLabelY' => 'coordinata Y etichetta',
'Today' => 'Oggi ',
'Tools' => 'Strumenti',
'Total' => 'Total', // Added - 2011-06-16
'Total' => 'Totale', // Added - 2011-06-16
'TotalBrScore' => 'Punteggio<br/>Totale',
'TrackDelay' => 'Track Delay',
'TrackMotion' => 'Track Motion',
@ -737,10 +737,10 @@ $SLANG = array(
'Type' => 'Tipo',
'Unarchive' => 'Togli dall\'archivio',
'Undefined' => 'Non specificato', // Added - 2009-02-08
'Units' => 'Unit&agrave;',
'Units' => 'Unità',
'Unknown' => 'Sconosciuto',
'Update' => 'Aggiorna',
'UpdateAvailable' => 'Un aggiornamento di ZoneMinder &egrave; disponibilie.',
'UpdateAvailable' => 'Un aggiornamento di ZoneMinder è disponibilie.',
'UpdateNotNecessary' => 'Nessun aggiornamento necessario.',
'Updated' => 'Updated', // Added - 2011-06-16
'Upload' => 'Upload', // Added - 2011-08-23
@ -769,8 +769,8 @@ $SLANG = array(
'VideoGenParms' => 'Parametri Generazione Video',
'VideoGenSucceeded' => 'Successo: Generato Video !',
'VideoSize' => 'Dimensioni Video',
'VideoWriter' => 'Video Writer', // Added - 2018-08-30
'View' => 'vedi',
'VideoWriter' => 'Scrittore video', // Added - 2018-08-30
'View' => 'Vedi',
'ViewAll' => 'Vedi Tutto',
'ViewEvent' => 'Vedi Evento',
'ViewPaged' => 'Vedi con paginazione',
@ -819,7 +819,7 @@ $CLANG = array(
'MonitorCount' => '%1$s %2$s', // For example '4 Monitors' (from Vlang below)
'MonitorFunction' => 'Funzione Monitor %1$s',
'RunningRecentVer' => 'Stai usando la versione pi&ugrave; aggiornata di ZoneMinder, v%s.',
'VersionMismatch' => 'Version mismatch, system is version %1$s, database is %2$s.', // Added - 2011-05-25
'VersionMismatch' => 'Versioni non corrispondenti: versione sistema %1$s, versione database %2$s.', // Added - 2011-05-25
);
// The next section allows you to describe a series of word ending and counts used to
@ -876,7 +876,7 @@ function zmVlang( $langVarArray, $count )
return( $value );
}
}
die( 'Errore, sono incapace di correlare le stringhe del file-linguaggio');
die( 'Errore, non sono in grado di correlare le stringhe del file-linguaggio');
}
// This is an version that could be used in the Russian example above

View File

@ -864,10 +864,6 @@ $OLANG = array(
'Prompt' => "&#206;nregistrare imagini intermediare de diagnosticare, foarte lent",
'Help' => "Pe l&#226;ng&#259; faptul c&#259; se pot &#238;nregistra statisticile evenimentelor se pot deasemenea &#238;nregistra imagini intermediare de diagnosticare care afi&#351;eaz&#259; rezultatele diferitelor verific&#259;ri care au loc c&#226;nd se &#238;ncearc&#259; determinarea unei posibile alarme. Aceste imagini sunt generate pentru fiecare cadru, zon&#259; &#351;i alarm&#259;, deci impactul asupra performan&#355;ei va fi foarte mare. Activa&#355;i aceast&#259; op&#355;iune doar pentru depanare sau analiz&#259; &#351;i nu uita&#355;i s&#259; o dezactiva&#355;i."
),
'CREATE_ANALYSIS_IMAGES' => array(
'Prompt' => "Creaz&#259; imagini analizate cu marcaje ale mi&#351;c&#259;rii",
'Help' => "Implicit, &#238;n cazul unei alarme, ZoneMinder &#238;nregistreaz&#259; at&#226;t imaginile neprelucrate c&#226;t &#351;i cele ce au fost analizate &#351;i au zone marcate unde a fost detectat&#259; mi&#351;care. Acest lucru poate fi foarte folositor la configurarea zonelor sau &#238;n analiza evenimentelor. Acest parametru permite oprirea &#238;nregistr&#259;rii imaginilor cu zone de mi&#351;care marcate."
),
'OPT_CONTROL' => array(
'Prompt' => "Suport camere controlabile (rotire/&#238;nclinare/zoom)",
'Help' => "ZoneMinder include suport limitat pentru camere controlabile. Sunt incluse c&#226;teva protocoale mostr&#259; &#351;i pot fi ad&#259;ugate cu u&#351;urin&#355;&#259; &#351;i altele. Dac&#259; vre&#355;i s&#259; controla&#355;i camerele prin intermediul ZoneMinder selecta&#355;i aceast&#259; op&#355;iune."

View File

@ -509,7 +509,7 @@ th.table-th-sort-rev span.table-th-sort-span {
}
#content {
width: 96%;
width: 100%;
margin: 0 auto 8px auto;
line-height: 130%;
text-align: center;

View File

@ -15,6 +15,25 @@ input[name="newMonitor[ControlDevice]"],
input[name="newMonitor[ControlAddress]"] {
width: 100%;
}
input[name="newMonitor[AnalysisFPSLimit]"],
input[name="newMonitor[MaxFPS]"],
input[name="newMonitor[AlarmMaxFPS]"],
input[name="newMonitor[V4LCapturesPerFrame]"]{
width: 60px;
}
input[name="newMonitor[Port]"],
input[name="newMonitor[Refresh]"],
input[name="newMonitor[LabelX]"],
input[name="newMonitor[LabelY]"],
input[name="newMonitor[ImageBufferCount]"],
input[name="newMonitor[WarmupCount]"],
input[name="newMonitor[PreEventCount]"],
input[name="newMonitor[PostEventCount]"],
input[name="newMonitor[StreamReplayBuffer]"],
input[name="newMonitor[AlarmFrameCount]"],
input[name="newMonitor[AutoStopTimeout]"],
input[name="newMonitor[TrackDelay]"],
input[name="newMonitor[ReturnDelay]"],
input[name="newMonitor[Width]"],
input[name="newMonitor[Height]"] {
width: 80px;

View File

@ -3,7 +3,9 @@
}
#content {
/*
width: 99%;
*/
}
#monitors:after {

View File

@ -178,7 +178,7 @@ getBodyTopHTML();
<div class="container-fluid">
<button type="button" name="addBtn" data-on-click-this="addMonitor"
<?php echo (canEdit('Monitors') && !$user['MonitorIds']) ? '' : ' disabled="disabled"' ?>
<?php echo (canEdit('Monitors') && !$user['MonitorIds']) ? '' : ' disabled="disabled" title="'.translate('AddMonitorDisabled').'"' ?>
>
<i class="material-icons md-18">add_circle</i>
&nbsp;<?php echo translate('AddNewMonitor') ?>

View File

@ -58,32 +58,6 @@ $heights = array(
'1080px' => '1080px',
);
session_start();
if ( isset($_REQUEST['scale']) ) {
$options['scale'] = validInt($_REQUEST['scale']);
} else if ( isset($_COOKIE['zmCycleScale']) ) {
$options['scale'] = $_COOKIE['zmCycleScale'];
}
if ( !isset($options['scale']) )
$options['scale'] = 100;
if ( isset($_COOKIE['zmCycleWidth']) and $_COOKIE['zmCycleWidth'] ) {
$_SESSION['zmCycleWidth'] = $options['width'] = $_COOKIE['zmCycleWidth'];
#} elseif ( isset($_SESSION['zmCycleWidth']) and $_SESSION['zmCycleWidth'] ) {
#$options['width'] = $_SESSION['zmCycleWidth'];
} else
$options['width'] = '';
if ( isset($_COOKIE['zmCycleHeight']) and $_COOKIE['zmCycleHeight'] )
$_SESSION['zmCycleHeight'] = $options['height'] = $_COOKIE['zmCycleHeight'];
#else if ( isset($_SESSION['zmCycleHeight']) and $_SESSION['zmCycleHeight'] )
#$options['height'] = $_SESSION['zmCycleHeight'];
else
$options['height'] = '';
session_write_close();
$monIdx = 0;
$monitors = array();
@ -104,7 +78,6 @@ foreach( $displayMonitors as &$row ) {
$heights[$row['Height'].'px'] = $row['Height'].'px';
}
$row['connKey'] = generateConnKey();
$monitors[] = new ZM\Monitor($row);
unset($row);
} # end foreach Monitor
@ -113,6 +86,41 @@ if ( $monitors ) {
$monitor = $monitors[$monIdx];
$nextMid = $monIdx==(count($monitors)-1)?$monitors[0]->Id():$monitors[$monIdx+1]->Id();
}
if ( !$monitor ) {
ZM\Error('There was no monitor to display.');
}
$options['connkey'] = generateConnKey();
session_start();
if ( isset($_REQUEST['scale']) ) {
$options['scale'] = validInt($_REQUEST['scale']);
} else if ( isset($_COOKIE['zmCycleScale']) ) {
$options['scale'] = $_COOKIE['zmCycleScale'];
} else if ( $monitor ) {
$options['scale'] = $monitor->DefaultScale();
}
if ( !isset($options['scale']) )
$options['scale'] = 100;
if ( isset($_COOKIE['zmCycleWidth']) and $_COOKIE['zmCycleWidth'] ) {
$_SESSION['zmCycleWidth'] = $options['width'] = $_COOKIE['zmCycleWidth'];
#} elseif ( isset($_SESSION['zmCycleWidth']) and $_SESSION['zmCycleWidth'] ) {
#$options['width'] = $_SESSION['zmCycleWidth'];
} else {
$options['width'] = '';
}
if ( isset($_COOKIE['zmCycleHeight']) and $_COOKIE['zmCycleHeight'] ) {
$_SESSION['zmCycleHeight'] = $options['height'] = $_COOKIE['zmCycleHeight'];
#else if ( isset($_SESSION['zmCycleHeight']) and $_SESSION['zmCycleHeight'] )
#$options['height'] = $_SESSION['zmCycleHeight'];
} else {
$options['height'] = '';
}
session_write_close();
ZM\Logger::Debug(print_r($options,true));
@ -151,7 +159,19 @@ xhtmlHeaders(__FILE__, translate('CycleWatch'));
</span>
</div>
</div>
<div id="content">
<div class="container-fluid">
<div class="row" id="content">
<div class="col-sm-2 sidebar">
<ul class="nav nav-pills nav-stacked">
<?php
foreach ( $monitors as $m ) {
echo '<li'.( $m->Id() == $monitor->Id() ? ' class="active"' : '' ).'><a href="?view=cycle&amp;mid='.$m->Id().'">'.$m->Name().'</a></li>';
}
?>
</ul>
</div>
<div class="col-sm-10 col-sm-offset-2">
<div id="imageFeed">
<?php
if ( $monitor ) {
@ -170,5 +190,6 @@ xhtmlHeaders(__FILE__, translate('CycleWatch'));
</div>
</div>
</div>
</div>
<?php xhtmlFooter() ?>

View File

@ -35,7 +35,7 @@ xhtmlHeaders(__FILE__, translate('Error') );
<?php echo translate('ContactAdmin') ?>
</p>
<p>
<a href="#" data-on-click="closeWindow"><?php echo translate('Close') ?></a>
<button type="button" data-on-click="closeWindow"><?php echo translate('Close') ?></button>
</p>
</div>
</div>

View File

@ -106,7 +106,7 @@ xhtmlHeaders(__FILE__, translate('Events') );
<?php
if ( $pagination ) {
?>
<h2 class="pagination"><?php echo $pagination ?></h2>
<h2 class="pagination hidden-xs"><?php echo $pagination ?></h2>
<?php
}
?>
@ -138,6 +138,7 @@ if ( $pages > 1 ) {
<input type="hidden" name="sort_field" value="<?php echo validHtmlStr($_REQUEST['sort_field']) ?>"/>
<input type="hidden" name="sort_asc" value="<?php echo validHtmlStr($_REQUEST['sort_asc']) ?>"/>
<input type="hidden" name="limit" value="<?php echo $limit ?>"/>
<div class="table-responsive">
<table id="contentTable" class="major">
<tbody>
<?php
@ -299,6 +300,7 @@ while ( $event_row = dbFetchNext($results) ) {
}
?>
</table>
</div>
<?php
if ( $pagination ) {
?>

View File

@ -9,24 +9,27 @@ function cyclePause() {
$('pauseBtn').disabled = true;
$('playBtn').disabled = false;
}
function cycleStart() {
periodical_id = nextCycleView.periodical(cycleRefreshTimeout);
$('pauseBtn').disabled = false;
$('playBtn').disabled = true;
}
function cycleNext() {
monIdx ++;
if ( monIdx >= monitorData.length ) {
monIdx = 0;
}
if ( !monitorData[monIdx] ) {
console.log("No monitorData for " + monIdx);
console.log('No monitorData for ' + monIdx);
}
window.location.replace('?view=cycle&mid='+monitorData[monIdx].id+'&mode='+mode, cycleRefreshTimeout);
}
function cyclePrev() {
if (monIdx) {
if ( monIdx ) {
monIdx -= 1;
} else {
monIdx = monitorData.length - 1;
@ -71,7 +74,7 @@ function changeSize() {
streamImg.style.width = width ? width : null;
streamImg.style.height = height ? height : null;
} else {
console.log("Did not find liveStream"+monitorData[monIdx].id);
console.log('Did not find liveStream'+monitorData[monIdx].id);
}
$('scale').set('value', '');
Cookie.write('zmCycleScale', '', {duration: 10*365});
@ -96,7 +99,7 @@ function changeScale() {
return;
}
if ( scale != '0' ) {
if ( scale != '0' && scale != '' && scale != 'auto' ) {
if ( newWidth ) {
monitor_frame.css('width', newWidth+'px');
}
@ -107,33 +110,36 @@ function changeScale() {
monitor_frame.css('width', '100%');
monitor_frame.css('height', 'auto');
}
/*Stream could be an applet so can't use moo tools*/
var streamImg = $j('#liveStream'+monitorData[monIdx].id)[0];
if ( streamImg ) {
if ( streamImg.nodeName == 'IMG' ) {
var src = streamImg.src;
streamImg.src = '';
//src = src.replace(/rand=\d+/i,'rand='+Math.floor((Math.random() * 1000000) ));
src = src.replace(/scale=[\.\d]+/i, 'scale='+scale);
if ( scale != '0' ) {
src = src.replace(/width=[\.\d]+/i, 'width='+newWidth);
src = src.replace(/height=[\.\d]+/i, 'height='+newHeight);
} else {
src = src.replace(/width=[\.\d]+/i, 'width='+monitorData[monIdx].width);
src = src.replace(/height=[\.\d]+/i, 'height='+monitorData[monIdx].height);
}
streamImg.src = src;
}
if ( scale != '0' ) {
streamImg.style.width = newWidth+'px';
streamImg.style.height = newHeight+'px';
} else {
streamImg.style.width = '100%';
streamImg.style.height = 'auto';
}
} else {
if ( !streamImg ) {
console.log("Did not find liveStream"+monitorData[monIdx].id);
return;
}
if ( streamImg.nodeName == 'IMG' ) {
var src = streamImg.src;
streamImg.src = '';
//src = src.replace(/rand=\d+/i,'rand='+Math.floor((Math.random() * 1000000) ));
src = src.replace(/scale=[\.\d]+/i, 'scale='+scale);
if ( scale != '0' && scale != '' && scale != 'auto' ) {
src = src.replace(/width=[\.\d]+/i, 'width='+newWidth);
src = src.replace(/height=[\.\d]+/i, 'height='+newHeight);
} else {
src = src.replace(/width=[\.\d]+/i, 'width='+monitorData[monIdx].width);
src = src.replace(/height=[\.\d]+/i, 'height='+monitorData[monIdx].height);
}
streamImg.src = src;
}
if ( scale != '0' && scale != '' && scale != 'auto' ) {
streamImg.style.width = newWidth+'px';
streamImg.style.height = newHeight+'px';
} else {
streamImg.style.width = '100%';
streamImg.style.height = 'auto';
}
} // end function changeScale()

View File

@ -9,7 +9,6 @@ foreach ( $monitors as $monitor ) {
?>
monitorData[monitorData.length] = {
'id': <?php echo $monitor->Id() ?>,
'connKey': <?php echo $monitor->connKey() ?>,
'width': <?php echo $monitor->ViewWidth() ?>,
'height':<?php echo $monitor->ViewHeight() ?>,
'url': '<?php echo $monitor->UrlToIndex() ?>',

View File

@ -285,8 +285,8 @@ function selectLayout(element) {
* called when the widthControl|heightControl select elements are changed
*/
function changeSize() {
var width = $('width').get('value');
var height = $('height').get('value');
var width = parseInt($('width').get('value'));
var height = parseInt($('height').get('value'));
for ( var i = 0, length = monitors.length; i < length; i++ ) {
var monitor = monitors[i];
@ -297,12 +297,8 @@ function changeSize() {
console.log("Error finding frame for " + monitor.id);
continue;
}
if ( width ) {
monitor_frame.css('width', width);
}
if ( height ) {
monitor_frame.css('height', height);
}
monitor_frame.css('width', ( width ? width+'px' : 'auto') );
monitor_frame.css('height', ( height ? height+'px' : 'auto') );
/*Stream could be an applet so can't use moo tools*/
var streamImg = $('liveStream'+monitor.id);
@ -315,8 +311,8 @@ function changeSize() {
src = src.replace(/rand=\d+/i, 'rand='+Math.floor((Math.random() * 1000000) ));
streamImg.src = src;
}
streamImg.style.width = width ? width : null;
streamImg.style.height = height ? height : null;
streamImg.style.width = width ? width+'px' : null;
streamImg.style.height = height ? height+'px' : null;
//streamImg.style.height = '';
}
}
@ -383,8 +379,8 @@ function changeScale() {
streamImg.src = src;
}
if ( scale != '0' ) {
streamImg.style.width = newWidth + "px";
streamImg.style.height = newHeight + "px";
streamImg.style.width = newWidth + 'px';
streamImg.style.height = newHeight + 'px';
} else {
streamImg.style.width = '100%';
streamImg.style.height = 'auto';

View File

@ -12,16 +12,22 @@ function validateForm( form, newUser ) {
} else if ( newUser ) {
errors[errors.length] = "You must supply a password";
}
var monitorIds = new Array();
for ( var i = 0; i < form.elements['monitorIds'].options.length; i++ ) {
if ( form.elements['monitorIds'].options[i].selected ) {
monitorIds[monitorIds.length] = form.elements['monitorIds'].options[i].value;
}
}
form.elements['newUser[MonitorIds]'].value = monitorIds.join( ',' );
if ( errors.length ) {
alert( errors.join( "\n" ) );
return ( false );
alert(errors.join("\n"));
return false;
}
return ( true );
return true;
}
function initPage() {
$j('#contentForm').submit(function(event) {
if ( validateForm(this) ) {
$j('#contentButtons').hide();
return true;
} else {
return false;
};
});
} // end function initPage
window.addEventListener('DOMContentLoaded', initPage);

View File

@ -244,12 +244,14 @@ function limitArea(field) {
limitRange(field, minValue, maxValue);
}
function highlightOn(index) {
function highlightOn(point) {
var index = point.getAttribute('data-index');
$('row'+index).addClass('highlight');
$('point'+index).addClass('highlight');
}
function highlightOff(index) {
function highlightOff(point) {
var index = point.getAttribute('data-index');
$('row'+index).removeClass('highlight');
$('point'+index).removeClass('highlight');
}
@ -310,9 +312,11 @@ function updateActivePoint(index) {
$('newZone[Points]['+index+'][y]').value = y;
zone['Points'][index].x = x;
zone['Points'][index].y = y;
console.log('hello');
var Point = $('zonePoly').points.getItem(index);
Point.x =x;
Point.y =y;
console.log('hello');
Point.x = x;
Point.y = y;
updateArea();
}
@ -353,15 +357,17 @@ function updateArea( ) {
} else if ( form.elements['newZone[Units]'].value == 'Pixels' ) {
form.elements['newZone[TempArea]'].value = area;
} else {
alert("Unknown units: " + form.elements['newZone[Units]'].value);
alert('Unknown units: ' + form.elements['newZone[Units]'].value);
}
}
function updateX(index) {
limitPointValue($('newZone[Points]['+index+'][x]'), 0, maxX);
function updateX(input) {
index = input.getAttribute('data-point-index');
limitPointValue(input, 0, maxX);
var point = $('point'+index);
var x = $('newZone[Points]['+index+'][x]').get('value');
var x = input.value;
point.setStyle('left', x+'px');
zone['Points'][index].x = x;
@ -370,11 +376,12 @@ function updateX(index) {
updateArea();
}
function updateY(index) {
limitPointValue($('newZone[Points]['+index+'][y]'), 0, maxY);
function updateY(input) {
index = input.getAttribute('data-point-index');
limitPointValue(input, 0, maxY);
var point = $('point'+index);
var y = $('newZone[Points]['+index+'][y]').get('value');
var y = input.value;
point.setStyle('top', y+'px');
zone['Points'][index].y = y;
@ -403,6 +410,7 @@ function drawZonePoints() {
for ( var i = 0; i < zone['Points'].length; i++ ) {
var div = new Element('div', {
'id': 'point'+i,
'data-index': i,
'class': 'zonePoint',
'title': 'Point '+(i+1),
'styles': {
@ -410,7 +418,9 @@ function drawZonePoints() {
'top': zone['Points'][i].y
}
});
div.addEvent('mouseover', highlightOn.pass(i));
//div.addEvent('mouseover', highlightOn.pass(i));
div.onmouseover = window['highlightOn'].bind(div, div);
div.onmouseout = window['highlightOff'].bind(div, div);
div.addEvent('mouseout', highlightOff.pass(i));
div.inject($('imageFrame'));
div.makeDraggable( {
@ -439,9 +449,12 @@ function drawZonePoints() {
'id': 'newZone[Points]['+i+'][x]',
'name': 'newZone[Points]['+i+'][x]',
'value': zone['Points'][i].x,
'size': 5
'type': 'number',
'min': '0',
'max': maxX,
'data-point-index': i
});
input.addEvent('input', updateX.pass(i));
input.oninput = window['updateX'].bind(input, input);
input.inject(cell);
cell.inject(row);
@ -450,9 +463,12 @@ function drawZonePoints() {
'id': 'newZone[Points]['+i+'][y]',
'name': 'newZone[Points]['+i+'][y]',
'value': zone['Points'][i].y,
'size': 5
'type': 'number',
'min': '0',
'max': maxY,
'data-point-index': i
} );
input.addEvent('input', updateY.pass(i));
input.oninput = window['updateY'].bind(input, input);
input.inject(cell);
cell.inject(row);
@ -499,34 +515,6 @@ function setAlarmState( currentAlarmState ) {
} else {
$('stateValue').removeProperty('class');
}
var isAlarmed = ( alarmState == STATE_ALARM || alarmState == STATE_ALERT );
var wasAlarmed = ( lastAlarmState == STATE_ALARM || lastAlarmState == STATE_ALERT );
var newAlarm = ( isAlarmed && !wasAlarmed );
var oldAlarm = ( !isAlarmed && wasAlarmed );
if ( newAlarm ) {
if ( SOUND_ON_ALARM ) {
// Enable the alarm sound
if ( !canPlayPauseAudio ) {
$('alarmSound').removeClass('hidden');
} else {
$('MediaPlayer').Play();
}
}
}
if ( SOUND_ON_ALARM ) {
if ( oldAlarm ) {
// Disable alarm sound
if ( !canPlayPauseAudio ) {
$('alarmSound').addClass('hidden');
} else {
$('MediaPlayer').Stop();
}
}
}
lastAlarmState = alarmState;
}
var streamCmdParms = "view=request&request=stream&connkey="+connKey;

View File

@ -21,7 +21,7 @@
require_once('includes/Server.php');
require_once('includes/Storage.php');
if ( !canView('Monitors') ) {
if ( !canEdit('Monitors', empty($_REQUEST['mid'])?0:$_REQUEST['mid']) ) {
$view = 'error';
return;
}
@ -171,14 +171,14 @@ unset($httpMethods['jpegTags']);
if ( ZM_HAS_V4L1 ) {
$v4l1DeviceFormats = array(
'PAL' => 0,
'NTSC' => 1,
'SECAM' => 2,
'AUTO' => 3,
'FMT4' => 4,
'FMT5' => 5,
'FMT6' => 6,
'FMT7' => 7
0 => 'PAL',
1 => 'NTSC',
2 => 'SECAM',
3 => 'AUTO',
4 => 'FMT4',
5 => 'FMT5',
6 => 'FMT6',
7 => 'FMT7'
);
$v4l1MaxChannels = 15;
@ -187,48 +187,48 @@ if ( ZM_HAS_V4L1 ) {
$v4l1DeviceChannels[$i] = $i;
$v4l1LocalPalettes = array(
translate('Grey') => 1,
'BGR32' => 5,
'BGR24' => 4,
'*YUYV' => 8,
'*RGB565' => 3,
'*RGB555' => 6,
'*YUV422' => 7,
'*YUV422P' => 13,
'*YUV420P' => 15
1 => translate('Grey'),
5 => 'BGR32',
4 => 'BGR24',
8 => '*YUYV',
3 => '*RGB565',
6 => '*RGB555',
7 => '*YUV422',
13 => '*YUV422P',
15 => '*YUV420P',
);
}
if ( ZM_HAS_V4L2 ) {
$v4l2DeviceFormats = array(
'PAL' => 0x000000ff,
'NTSC' => 0x0000b000,
'PAL B' => 0x00000001,
'PAL B1' => 0x00000002,
'PAL G' => 0x00000004,
'PAL H' => 0x00000008,
'PAL I' => 0x00000010,
'PAL D' => 0x00000020,
'PAL D1' => 0x00000040,
'PAL K' => 0x00000080,
'PAL M' => 0x00000100,
'PAL N' => 0x00000200,
'PAL Nc' => 0x00000400,
'PAL 60' => 0x00000800,
'NTSC M' => 0x00001000,
'NTSC M JP' => 0x00002000,
'NTSC 443' => 0x00004000,
'NTSC M KR' => 0x00008000,
'SECAM B' => 0x00010000,
'SECAM D' => 0x00020000,
'SECAM G' => 0x00040000,
'SECAM H' => 0x00080000,
'SECAM K' => 0x00100000,
'SECAM K1' => 0x00200000,
'SECAM L' => 0x00400000,
'SECAM LC' => 0x00800000,
'ATSC 8 VSB' => 0x01000000,
'ATSC 16 VSB' => 0x02000000,
0x000000ff => 'PAL',
0x0000b000 => 'NTSC',
0x00000001 => 'PAL B',
0x00000002 => 'PAL B1',
0x00000004 => 'PAL G',
0x00000008 => 'PAL H',
0x00000010 => 'PAL I',
0x00000020 => 'PAL D',
0x00000040 => 'PAL D1',
0x00000080 => 'PAL K',
0x00000100 => 'PAL M',
0x00000200 => 'PAL N',
0x00000400 => 'PAL Nc',
0x00000800 => 'PAL 60',
0x00001000 => 'NTSC M',
0x00002000 => 'NTSC M JP',
0x00004000 => 'NTSC 443',
0x00008000 => 'NTSC M KR',
0x00010000 => 'SECAM B',
0x00020000 => 'SECAM D',
0x00040000 => 'SECAM G',
0x00080000 => 'SECAM H',
0x00100000 => 'SECAM K',
0x00200000 => 'SECAM K1',
0x00400000 => 'SECAM L',
0x00800000 => 'SECAM LC',
0x01000000 => 'ATSC 8 VSB',
0x02000000 => 'ATSC 16 VSB',
);
$v4l2MaxChannels = 31;
@ -237,57 +237,58 @@ if ( ZM_HAS_V4L2 ) {
$v4l2DeviceChannels[$i] = $i;
$v4l2LocalPalettes = array(
'Auto' => 0, /* Automatic palette selection */
0 => 'Auto', /* Automatic palette selection */
/* Pixel format FOURCC depth Description */
translate('Grey') => fourcc('G','R','E','Y'), /* 8 Greyscale */
'BGR32' => fourcc('B','G','R','4'), /* 32 BGR-8-8-8-8 */
'RGB32' => fourcc('R','G','B','4'), /* 32 RGB-8-8-8-8 */
'BGR24' => fourcc('B','G','R','3'), /* 24 BGR-8-8-8 */
'RGB24' => fourcc('R','G','B','3'), /* 24 RGB-8-8-8 */
'*YUYV' => fourcc('Y','U','Y','V'), /* 16 YUV 4:2:2 */
/* FOURCC => Pixel format depth Description */
fourcc('G','R','E','Y') => translate('Grey'), /* 8 Greyscale */
fourcc('B','G','R','4') => 'BGR32', /* 32 BGR-8-8-8-8 */
fourcc('R','G','B','4') => 'RGB32', /* 32 RGB-8-8-8-8 */
fourcc('B','G','R','3') => 'BGR24', /* 24 BGR-8-8-8 */
fourcc('R','G','B','3') => 'RGB24', /* 24 RGB-8-8-8 */
fourcc('Y','U','Y','V') => '*YUYV', /* 16 YUV 4:2:2 */
/* compressed formats */
'*JPEG' => fourcc('J','P','E','G'), /* JFIF JPEG */
'*MJPEG' => fourcc('M','J','P','G'), /* Motion-JPEG */
//'DV' => fourcc('d','v','s','d'), /* 1394 */
//'MPEG' => fourcc('M','P','E','G'), /* MPEG-1/2/4 */
fourcc('J','P','E','G') => '*JPEG', /* JFIF JPEG */
fourcc('M','J','P','G') => '*MJPEG', /* Motion-JPEG */
// fourcc('d','v','s','d') => 'DV', /* 1394 */
// fourcc('M','P','E','G') => 'MPEG', /* MPEG-1/2/4 */
//'RGB332' => fourcc('R','G','B','1'), /* 8 RGB-3-3-2 */
'*RGB444' => fourcc('R','4','4','4'), /* 16 xxxxrrrr ggggbbbb */
'*RGB555' => fourcc('R','G','B','O'), /* 16 RGB-5-5-5 */
'*RGB565' => fourcc('R','G','B','P'), /* 16 RGB-5-6-5 */
//'RGB555X' => fourcc('R','G','B','Q'), /* 16 RGB-5-5-5 BE */
//'RGB565X' => fourcc('R','G','B','R'), /* 16 RGB-5-6-5 BE */
//'Y16' => fourcc('Y','1','6',''), /* 16 Greyscale */
//'PAL8' => fourcc('P','A','L','8'), /* 8 8-bit palette */
//'YVU410' => fourcc('Y','V','U','9'), /* 9 YVU 4:1:0 */
//'YVU420' => fourcc('Y','V','1','2'), /* 12 YVU 4:2:0 */
//
fourcc('R','G','B','1') => 'RGB332', /* 8 RGB-3-3-2 */
fourcc('R','4','4','4') => '*RGB444', /* 16 xxxxrrrr ggggbbbb */
fourcc('R','G','B','O') => '*RGB555', /* 16 RGB-5-5-5 */
fourcc('R','G','B','P') => '*RGB565', /* 16 RGB-5-6-5 */
// fourcc('R','G','B','Q') => 'RGB555X', /* 16 RGB-5-5-5 BE */
// fourcc('R','G','B','R') => 'RGB565X', /* 16 RGB-5-6-5 BE */
// fourcc('Y','1','6','') => 'Y16', /* 16 Greyscale */
// fourcc('P','A','L','8') => 'PAL8', /* 8 8-bit palette */
// fourcc('Y','V','U','9') => 'YVU410', /* 9 YVU 4:1:0 */
// fourcc('Y','V','1','2') => 'YVU420', /* 12 YVU 4:2:0 */
'*UYVY' => fourcc('U','Y','V','Y'), /* 16 YUV 4:2:2 */
'*YUV422P' => fourcc('4','2','2','P'), /* 16 YVU422 planar */
'*YUV411P' => fourcc('4','1','1','P'), /* 16 YVU411 planar */
//'Y41P' => fourcc('Y','4','1','P'), /* 12 YUV 4:1:1 */
'*YUV444' => fourcc('Y','4','4','4'), /* 16 xxxxyyyy uuuuvvvv */
//'YUV555' => fourcc('Y','U','V','O'), /* 16 YUV-5-5-5 */
//'YUV565' => fourcc('Y','U','V','P'), /* 16 YUV-5-6-5 */
//'YUV32' => fourcc('Y','U','V','4'), /* 32 YUV-8-8-8-8 */
fourcc('U','Y','V','Y') => '*UYVY', /* 16 YUV 4:2:2 */
fourcc('4','2','2','P') => '*YUV422P', /* 16 YVU422 planar */
fourcc('4','1','1','P') => '*YUV411P', /* 16 YVU411 planar */
// fourcc('Y','4','1','P') => 'Y41P', /* 12 YUV 4:1:1 */
fourcc('Y','4','4','4') => '*YUV444', /* 16 xxxxyyyy uuuuvvvv */
// fourcc('Y','U','V','O') => 'YUV555', /* 16 YUV-5-5-5 */
// fourcc('Y','U','V','P') => 'YUV565', /* 16 YUV-5-6-5 */
// fourcc('Y','U','V','4') => 'YUV32', /* 32 YUV-8-8-8-8 */
/* two planes -- one Y, one Cr + Cb interleaved */
//'NV12' => fourcc('N','V','1','2'), /* 12 Y/CbCr 4:2:0 */
//'NV21' => fourcc('N','V','2','1'), /* 12 Y/CrCb 4:2:0 */
fourcc('N','V','1','2') => 'NV12', /* 12 Y/CbCr 4:2:0 */
// fourcc('N','V','2','1') => 'NV21', /* 12 Y/CrCb 4:2:0 */
/* The following formats are not defined in the V4L2 specification */
'*YUV410' => fourcc('Y','U','V','9'), /* 9 YUV 4:1:0 */
'*YUV420' => fourcc('Y','U','1','2'), /* 12 YUV 4:2:0 */
//'YYUV' => fourcc('Y','Y','U','V'), /* 16 YUV 4:2:2 */
//'HI240' => fourcc('H','I','2','4'), /* 8 8-bit color */
//'HM12' => fourcc('H','M','1','2'), /* 8 YUV 4:2:0 16x16 macroblocks */
fourcc('Y','U','V','9') => '*YUV410', /* 9 YUV 4:1:0 */
fourcc('Y','U','1','2') => '*YUV420', /* 12 YUV 4:2:0 */
// fourcc('Y','Y','U','V') => 'YYUV', /* 16 YUV 4:2:2 */
// fourcc('H','I','2','4') => 'HI240', /* 8 8-bit color */
// fourcc('H','M','1','2') => 'HM12', /* 8 YUV 4:2:0 16x16 macroblocks */
/* see http://www.siliconimaging.com/RGB%20Bayer.htm */
//'SBGGR8' => fourcc('B','A','8','1'), /* 8 BGBG.. GRGR.. */
//'SGBRG8' => fourcc('G','B','R','G'), /* 8 GBGB.. RGRG.. */
//'SBGGR16' => fourcc('B','Y','R','2'), /* 16 BGBG.. GRGR.. */
// fourcc('B','A','8','1') => 'SBGGR8', /* 8 BGBG.. GRGR.. */
// fourcc('G','B','R','G') => 'SGBRG8', /* 8 GBGB.. RGRG.. */
// fourcc('B','Y','R','2') => 'SBGGR16', /* 16 BGBG.. GRGR.. */
/* Vendor-specific formats */
//'WNVA' => fourcc('W','N','V','A'), /* Winnov hw compress */
@ -348,23 +349,23 @@ $deinterlaceopts_v4l2 = array(
);
$fastblendopts = array(
'No blending' => 0,
'1.5625%' => 1,
'3.125%' => 3,
'6.25% (Indoor)' => 6,
'12.5% (Outdoor)' => 12,
'25%' => 25,
'50%' => 50
0 => 'No blending',
1 => '1.5625%',
3 => '3.125%',
6 => '6.25% (Indoor)',
12 => '12.5% (Outdoor)',
25 => '25%',
50 => '50%',
);
$fastblendopts_alarm = array(
'No blending (Alarm lasts forever)' => 0,
'1.5625%' => 1,
'3.125%' => 3,
'6.25%' => 6,
'12.5%' => 12,
'25%' => 25,
'50% (Alarm lasts a moment)' => 50
0 => 'No blending (Alarm lasts forever)',
1 => '1.5625%',
3 => '3.125%',
6 => '6.25%',
12 => '12.5%',
25 => '25%',
50 => '50% (Alarm lasts a moment)',
);
$label_size = array(
@ -681,45 +682,50 @@ switch ( $tab ) {
echo htmlOptions(ZM\Group::get_dropdown_options(), $monitor->GroupIds());
?></select></td>
</tr>
<tr><td><?php echo translate('AnalysisFPS') ?></td><td><input type="text" name="newMonitor[AnalysisFPSLimit]" value="<?php echo validHtmlStr($monitor->AnalysisFPSLimit()) ?>" size="6"/></td></tr>
<tr>
<td><?php echo translate('AnalysisFPS') ?></td>
<td><input type="number" name="newMonitor[AnalysisFPSLimit]" value="<?php echo validHtmlStr($monitor->AnalysisFPSLimit()) ?>" min="0" step="any"/></td>
</tr>
<?php
if ( $monitor->Type() != 'Local' && $monitor->Type() != 'File' && $monitor->Type() != 'NVSocket' ) {
?>
<tr>
<td><?php echo translate('MaximumFPS') ?>&nbsp;(<?php echo makePopupLink('?view=optionhelp&amp;option=OPTIONS_MAXFPS', 'zmOptionHelp', 'optionhelp', '?' ) ?>)</td>
<td>
<input type="text" name="newMonitor[MaxFPS]" value="<?php echo validHtmlStr($monitor->MaxFPS()) ?>" size="5"/>
<input type="number" name="newMonitor[MaxFPS]" value="<?php echo validHtmlStr($monitor->MaxFPS()) ?>" min="0" step="any"/>
<span id="newMonitor[MaxFPS]" style="color:red;<?php echo $monitor->MaxFPS() ? '' : 'display:none;' ?>">CAUTION: See the help text</span>
</td>
</tr>
<tr>
<td><?php echo translate('AlarmMaximumFPS') ?>&nbsp;(<?php echo makePopupLink('?view=optionhelp&amp;option=OPTIONS_MAXFPS', 'zmOptionHelp', 'optionhelp', '?' ) ?>)</td>
<td>
<input type="text" name="newMonitor[AlarmMaxFPS]" value="<?php echo validHtmlStr($monitor->AlarmMaxFPS()) ?>" size="5"/>
<input type="number" name="newMonitor[AlarmMaxFPS]" value="<?php echo validHtmlStr($monitor->AlarmMaxFPS()) ?>" min="0" step="any"/>
<span id="newMonitor[AlarmMaxFPS]" style="color:red;<?php echo $monitor->AlarmMaxFPS() ? '' : 'display:none;' ?>">CAUTION: See the help text</span>
</td>
</tr>
<?php
} else {
?>
<tr><td><?php echo translate('MaximumFPS') ?></td><td><input type="text" name="newMonitor[MaxFPS]" value="<?php echo validHtmlStr($monitor->MaxFPS()) ?>" size="5"/></td></tr>
<tr><td><?php echo translate('AlarmMaximumFPS') ?></td><td><input type="text" name="newMonitor[AlarmMaxFPS]" value="<?php echo validHtmlStr($monitor->AlarmMaxFPS()) ?>" size="5"/></td></tr>
<tr>
<td><?php echo translate('MaximumFPS') ?></td>
<td><input type="number" name="newMonitor[MaxFPS]" value="<?php echo validHtmlStr($monitor->MaxFPS()) ?>" min="0" step="any"/></td>
</tr>
<tr>
<td><?php echo translate('AlarmMaximumFPS') ?></td>
<td><input type="number" name="newMonitor[AlarmMaxFPS]" value="<?php echo validHtmlStr($monitor->AlarmMaxFPS()) ?>" min="0" step="any"/></td>
</tr>
<?php
}
if ( ZM_FAST_IMAGE_BLENDS ) {
?>
<tr>
<td><?php echo translate('RefImageBlendPct') ?></td>
<td><select name="newMonitor[RefBlendPerc]"><?php foreach ( $fastblendopts as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $monitor->RefBlendPerc() ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td>
<td><?php echo htmlSelect('newMonitor[RefBlendPerc]', $fastblendopts, $monitor->RefBlendPerc()); ?></td>
</tr>
<tr>
<td><?php echo translate('AlarmRefImageBlendPct') ?></td>
<td>
<select name="newMonitor[AlarmRefBlendPerc]">
<?php foreach ( $fastblendopts_alarm as $name => $value ) { ?>
<option value="<?php echo $value ?>"<?php if ( $value == $monitor->AlarmRefBlendPerc() ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option>
<?php } ?>
</select></td></tr>
<td><?php echo htmlSelect('newMonitor[AlarmRefBlendPerc]', $fastblendopts_alarm, $monitor->AlarmRefBlendPerc()); ?></td>
</tr>
<?php
} else {
?>
@ -778,17 +784,26 @@ switch ( $tab ) {
{
if ( ZM_HAS_V4L && $monitor->Type() == 'Local' ) {
?>
<tr><td><?php echo translate('DevicePath') ?></td><td><input type="text" name="newMonitor[Device]" value="<?php echo validHtmlStr($monitor->Device()) ?>" size="24"/></td></tr>
<tr><td><?php echo translate('CaptureMethod') ?></td><td><?php echo htmlSelect( "newMonitor[Method]", $localMethods, $monitor->Method(), "submitTab( '$tab' );" ); ?></td></tr>
<tr><td><?php echo translate('DevicePath') ?></td><td><input type="text" name="newMonitor[Device]" value="<?php echo validHtmlStr($monitor->Device()) ?>"/></td></tr>
<tr>
<td><?php echo translate('CaptureMethod') ?></td>
<td><?php echo htmlSelect('newMonitor[Method]', $localMethods, $monitor->Method(), array('onchange'=>'submitTab', 'data-tab-name'=>$tab) ); ?></td>
</tr>
<?php
if ( ZM_HAS_V4L1 && $monitor->Method() == 'v4l1' ) {
?>
<tr>
<td><?php echo translate('DeviceChannel') ?></td>
<td><select name="newMonitor[Channel]"><?php foreach ( $v4l1DeviceChannels as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $monitor->Channel()) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td>
<td><?php echo htmlSelect('newMonitor[Channel]', $v4l1DeviceChannels, $monitor->Channel()); ?></td>
</tr>
<tr>
<td><?php echo translate('DeviceFormat') ?></td>
<td><?php echo htmlSelect('newMonitor[Format]', $v4l1DeviceFormats, $monitor->Format()); ?></td>
</tr>
<tr>
<td><?php echo translate('CapturePalette') ?></td>
<td><?php echo htmlSelect('newMonitor[Palette]', $v4l1LocalPalettes, $monitor->Palette()); ?></td>
</tr>
<tr><td><?php echo translate('DeviceFormat') ?></td><td><select name="newMonitor[Format]"><?php foreach ( $v4l1DeviceFormats as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $monitor->Format()) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
<tr><td><?php echo translate('CapturePalette') ?></td><td><select name="newMonitor[Palette]"><?php foreach ( $v4l1LocalPalettes as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $monitor->Palette()) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
<?php
} else {
?>
@ -806,7 +821,10 @@ switch ( $tab ) {
<input type="radio" name="newMonitor[V4LMultiBuffer]" id="newMonitor[V4LMultiBuffer]" value="" <?php echo ( $monitor->V4LMultiBuffer() == '' ? 'checked="checked"' : '' ) ?>/>
<label for="newMonitor[V4LMultiBuffer]">Use Config Value</label>
</td></tr>
<tr><td><?php echo translate('V4LCapturesPerFrame') ?></td><td><input type="number" name="newMonitor[V4LCapturesPerFrame]" value="<?php echo validHtmlStr($monitor->V4LCapturesPerFrame()); ?>"/></td></tr>
<tr>
<td><?php echo translate('V4LCapturesPerFrame') ?></td>
<td><input type="number" name="newMonitor[V4LCapturesPerFrame]" value="<?php echo validHtmlStr($monitor->V4LCapturesPerFrame()); ?>" min="1"/></td>
</tr>
<?php
} else if ( $monitor->Type() == 'NVSocket' ) {
@ -832,28 +850,29 @@ include('_monitor_source_nvsocket.php');
<?php
} else if ( $monitor->Type() == 'Remote' ) {
?>
<tr><td><?php echo translate('RemoteProtocol') ?></td><td><?php echo htmlSelect( "newMonitor[Protocol]", $remoteProtocols, $monitor->Protocol(), "updateMethods( this );if(this.value=='rtsp'){\$('RTSPDescribe').setStyle('display','table-row');}else{\$('RTSPDescribe').hide();}" ); ?></td></tr>
<?php
?>
<tr>
<td><?php echo translate('RemoteProtocol') ?></td>
<td><?php echo htmlSelect('newMonitor[Protocol]', $remoteProtocols, $monitor->Protocol(), "updateMethods( this );if(this.value=='rtsp'){\$('RTSPDescribe').setStyle('display','table-row');}else{\$('RTSPDescribe').hide();}" ); ?></td>
</tr>
<tr>
<td><?php echo translate('RemoteMethod') ?></td>
<td>
<?php
if ( !$monitor->Protocol() || $monitor->Protocol() == 'http' ) {
echo htmlSelect('newMonitor[Method]', $httpMethods, $monitor->Method() );
echo htmlSelect('newMonitor[Method]', $httpMethods, $monitor->Method());
} else {
echo htmlSelect('newMonitor[Method]', $rtspMethods, $monitor->Method() );
echo htmlSelect('newMonitor[Method]', $rtspMethods, $monitor->Method());
}
?>
</td>
</tr>
<tr><td><?php echo translate('RemoteHostName') ?></td><td><input type="text" name="newMonitor[Host]" value="<?php echo validHtmlStr($monitor->Host()) ?>"/></td></tr>
<tr><td><?php echo translate('RemoteHostPort') ?></td><td><input type="number" name="newMonitor[Port]" value="<?php echo validHtmlStr($monitor->Port()) ?>" size="6"/></td></tr>
<tr><td><?php echo translate('RemoteHostPort') ?></td><td><input type="number" name="newMonitor[Port]" value="<?php echo validHtmlStr($monitor->Port()) ?>" min="0" max="65535"/></td></tr>
<tr><td><?php echo translate('RemoteHostPath') ?></td><td><input type="text" name="newMonitor[Path]" value="<?php echo validHtmlStr($monitor->Path()) ?>"/></td></tr>
<?php
} else if ( $monitor->Type() == 'File' ) {
?>
<tr><td><?php echo translate('SourcePath') ?></td><td><input type="text" name="newMonitor[Path]" value="<?php echo validHtmlStr($monitor->Path()) ?>" size="36"/></td></tr>
<tr><td><?php echo translate('SourcePath') ?></td><td><input type="text" name="newMonitor[Path]" value="<?php echo validHtmlStr($monitor->Path()) ?>"/></td></tr>
<?php
} elseif ( $monitor->Type() == 'cURL' ) {
?>
@ -869,15 +888,15 @@ include('_monitor_source_nvsocket.php');
</tr>
<tr>
<td><?php echo translate('Width') ?> (<?php echo translate('Pixels') ?>)</td>
<td><input type="number" name="newMonitor[Width]" value="<?php echo validHtmlStr($monitor->Width()) ?>" size="4"/></td>
<td><input type="number" name="newMonitor[Width]" value="<?php echo validHtmlStr($monitor->Width()) ?>" min="1"/></td>
</tr>
<tr>
<td><?php echo translate('Height') ?> (<?php echo translate('Pixels') ?>)</td>
<td><input type="number" name="newMonitor[Height]" value="<?php echo validHtmlStr($monitor->Height()) ?>" size="4"/></td>
<td><input type="number" name="newMonitor[Height]" value="<?php echo validHtmlStr($monitor->Height()) ?>" min="1"/></td>
</tr>
<tr>
<td><?php echo 'Web Site Refresh (Optional)' ?></td>
<td><input type="number" name="newMonitor[Refresh]" value="<?php echo validHtmlStr($monitor->Refresh()) ?>"/></td>
<td><input type="number" name="newMonitor[Refresh]" value="<?php echo validHtmlStr($monitor->Refresh()) ?>" min="1"/></td>
</tr>
<?php
} else if ( $monitor->Type() == 'Ffmpeg' || $monitor->Type() == 'Libvlc' ) {
@ -924,8 +943,8 @@ include('_monitor_source_nvsocket.php');
<tr>
<td><?php echo translate('CaptureResolution') ?> (<?php echo translate('Pixels') ?>)</td>
<td>
<input type="number" name="newMonitor[Width]" value="<?php echo validHtmlStr($monitor->Width()) ?>"/>
<input type="number" name="newMonitor[Height]" value="<?php echo validHtmlStr($monitor->Height()) ?>"/>
<input type="number" name="newMonitor[Width]" value="<?php echo validHtmlStr($monitor->Width()) ?>" min="1"/>
<input type="number" name="newMonitor[Height]" value="<?php echo validHtmlStr($monitor->Height()) ?>" min="1"/>
<?php echo htmlselect('dimensions_select', array(
''=>translate('Custom'),
'176x120'=>'176x120 QCIF',
@ -1054,11 +1073,11 @@ include('_monitor_source_nvsocket.php');
</tr>
<tr>
<td><?php echo translate('TimestampLabelX') ?></td>
<td><input type="number" name="newMonitor[LabelX]" value="<?php echo validHtmlStr($monitor->LabelX()) ?>" size="4"/></td>
<td><input type="number" name="newMonitor[LabelX]" value="<?php echo validHtmlStr($monitor->LabelX()) ?>" min="1"/></td>
</tr>
<tr>
<td><?php echo translate('TimestampLabelY') ?></td>
<td><input type="number" name="newMonitor[LabelY]" value="<?php echo validHtmlStr($monitor->LabelY()) ?>" size="4"/></td>
<td><input type="number" name="newMonitor[LabelY]" value="<?php echo validHtmlStr($monitor->LabelY()) ?>" min="1"/></td>
</tr>
<tr>
<td><?php echo translate('TimestampLabelSize') ?></td>
@ -1072,27 +1091,27 @@ include('_monitor_source_nvsocket.php');
?>
<tr>
<td><?php echo translate('ImageBufferSize') ?></td>
<td><input type="number" name="newMonitor[ImageBufferCount]" value="<?php echo validHtmlStr($monitor->ImageBufferCount()) ?>" size="6"/></td>
<td><input type="number" name="newMonitor[ImageBufferCount]" value="<?php echo validHtmlStr($monitor->ImageBufferCount()) ?>" min="1"/></td>
</tr>
<tr>
<td><?php echo translate('WarmupFrames') ?></td>
<td><input type="number" name="newMonitor[WarmupCount]" value="<?php echo validHtmlStr($monitor->WarmupCount()) ?>" size="4"/></td>
<td><input type="number" name="newMonitor[WarmupCount]" value="<?php echo validHtmlStr($monitor->WarmupCount()) ?>" min="0"/></td>
</tr>
<tr>
<td><?php echo translate('PreEventImageBuffer') ?></td>
<td><input type="number" name="newMonitor[PreEventCount]" value="<?php echo validHtmlStr($monitor->PreEventCount()) ?>" size="4"/></td>
<td><input type="number" name="newMonitor[PreEventCount]" value="<?php echo validHtmlStr($monitor->PreEventCount()) ?>" min="0"/></td>
</tr>
<tr>
<td><?php echo translate('PostEventImageBuffer') ?></td>
<td><input type="number" name="newMonitor[PostEventCount]" value="<?php echo validHtmlStr($monitor->PostEventCount()) ?>" size="4"/></td>
<td><input type="number" name="newMonitor[PostEventCount]" value="<?php echo validHtmlStr($monitor->PostEventCount()) ?>" min="0"/></td>
</tr>
<tr>
<td><?php echo translate('StreamReplayBuffer') ?></td>
<td><input type="number" name="newMonitor[StreamReplayBuffer]" value="<?php echo validHtmlStr($monitor->StreamReplayBuffer()) ?>" size="6"/></td>
<td><input type="number" name="newMonitor[StreamReplayBuffer]" value="<?php echo validHtmlStr($monitor->StreamReplayBuffer()) ?>" min="0"/></td>
</tr>
<tr>
<td><?php echo translate('AlarmFrameCount') ?></td>
<td><input type="number" name="newMonitor[AlarmFrameCount]" value="<?php echo validHtmlStr($monitor->AlarmFrameCount()) ?>" size="4"/></td>
<td><input type="number" name="newMonitor[AlarmFrameCount]" value="<?php echo validHtmlStr($monitor->AlarmFrameCount()) ?>" min="1"/></td>
</tr>
<?php
break;
@ -1122,7 +1141,7 @@ if ( canEdit('Control') ) {
</tr>
<tr>
<td><?php echo translate('AutoStopTimeout') ?></td>
<td><input type="number" name="newMonitor[AutoStopTimeout]" value="<?php echo validHtmlStr($monitor->AutoStopTimeout()) ?>"/></td>
<td><input type="number" name="newMonitor[AutoStopTimeout]" value="<?php echo validHtmlStr($monitor->AutoStopTimeout()) ?>" min="0" step="any"/></td>
</tr>
<tr>
<td><?php echo translate('TrackMotion') ?></td>
@ -1130,7 +1149,7 @@ if ( canEdit('Control') ) {
</tr>
<tr>
<td><?php echo translate('TrackDelay') ?></td>
<td><input type="number" name="newMonitor[TrackDelay]" value="<?php echo validHtmlStr($monitor->TrackDelay()) ?>"/></td>
<td><input type="number" name="newMonitor[TrackDelay]" value="<?php echo validHtmlStr($monitor->TrackDelay()) ?>" min="0" step="any"/></td>
</tr>
<tr>
<td><?php echo translate('ReturnLocation') ?></td>
@ -1144,7 +1163,7 @@ echo htmlSelect('newMonitor[ReturnLocation]', $return_options, $monitor->ReturnL
</tr>
<tr>
<td><?php echo translate('ReturnDelay') ?></td>
<td><input type="number" name="newMonitor[ReturnDelay]" value="<?php echo validHtmlStr($monitor->ReturnDelay()) ?>"/></td>
<td><input type="number" name="newMonitor[ReturnDelay]" value="<?php echo validHtmlStr($monitor->ReturnDelay()) ?>" min="0" step="any"/></td>
</tr>
<?php
break;
@ -1168,41 +1187,41 @@ echo htmlSelect('newMonitor[ReturnLocation]', $return_options, $monitor->ReturnL
<tr>
<td><?php echo translate('Sectionlength') ?></td>
<td>
<input type="number" name="newMonitor[SectionLength]" value="<?php echo validHtmlStr($monitor->SectionLength()) ?>"/>
<input type="number" name="newMonitor[SectionLength]" value="<?php echo validHtmlStr($monitor->SectionLength()) ?>" min="0"/>
<?php echo translate('seconds')?>
</td>
</tr>
<tr>
<td><?php echo translate('MinSectionlength') ?></td>
<td>
<input type="number" name="newMonitor[MinSectionLength]" value="<?php echo validHtmlStr($monitor->MinSectionLength()) ?>"/>
<input type="number" name="newMonitor[MinSectionLength]" value="<?php echo validHtmlStr($monitor->MinSectionLength()) ?>" min="0"/>
<?php echo translate('seconds')?>
</td>
</tr>
<tr>
<td><?php echo translate('FrameSkip') ?></td>
<td>
<input type="number" name="newMonitor[FrameSkip]" value="<?php echo validHtmlStr($monitor->FrameSkip()) ?>"/>
<input type="number" name="newMonitor[FrameSkip]" value="<?php echo validHtmlStr($monitor->FrameSkip()) ?>" min="0"/>
<?php echo translate('frames')?>
</td>
</tr>
<tr>
<td><?php echo translate('MotionFrameSkip') ?></td>
<td>
<input type="number" name="newMonitor[MotionFrameSkip]" value="<?php echo validHtmlStr($monitor->MotionFrameSkip()) ?>"/>
<input type="number" name="newMonitor[MotionFrameSkip]" value="<?php echo validHtmlStr($monitor->MotionFrameSkip()) ?>" min="0"/>
<?php echo translate('frames')?>
</td>
</tr>
<tr>
<td><?php echo translate('AnalysisUpdateDelay') ?></td>
<td>
<input type="number" name="newMonitor[AnalysisUpdateDelay]" value="<?php echo validHtmlStr($monitor->AnalysisUpdateDelay()) ?>"/>
<input type="number" name="newMonitor[AnalysisUpdateDelay]" value="<?php echo validHtmlStr($monitor->AnalysisUpdateDelay()) ?>" min="0"/>
<?php echo translate('seconds')?>
</td></tr>
<tr>
<td><?php echo translate('FPSReportInterval') ?></td>
<td>
<input type="number" name="newMonitor[FPSReportInterval]" value="<?php echo validHtmlStr($monitor->FPSReportInterval()) ?>"/>
<input type="number" name="newMonitor[FPSReportInterval]" value="<?php echo validHtmlStr($monitor->FPSReportInterval()) ?>" min="0"/>
<?php echo translate('frames')?>
</td>
</tr>
@ -1221,7 +1240,7 @@ echo htmlSelect('newMonitor[ReturnLocation]', $return_options, $monitor->ReturnL
<tr>
<td><?php echo translate('SignalCheckPoints') ?></td>
<td>
<input type="number" name="newMonitor[SignalCheckPoints]" value="<?php echo validInt($monitor->SignalCheckPoints()) ?>"/>
<input type="number" name="newMonitor[SignalCheckPoints]" value="<?php echo validInt($monitor->SignalCheckPoints()) ?>" min="0"/>
</td>
</tr>
<tr>

View File

@ -33,20 +33,20 @@ if ( isset($_REQUEST['showZones']) ) {
}
}
$widths = array(
'auto' => 'auto',
'160px' => '160px',
'320px' => '320px',
'352px' => '352px',
'640px' => '640px',
'1280px' => '1280px' );
'0' => 'auto',
'160' => '160px',
'320' => '320px',
'352' => '352px',
'640' => '640px',
'1280' => '1280px' );
$heights = array(
'auto' => 'auto',
'240px' => '240px',
'320px' => '320px',
'480px' => '480px',
'720px' => '720px',
'1080px' => '1080px',
'0' => 'auto',
'240' => '240px',
'320' => '320px',
'480' => '480px',
'720' => '720px',
'1080' => '1080px',
);
$scale = '100'; # actual
@ -54,7 +54,7 @@ $scale = '100'; # actual
if ( isset($_REQUEST['scale']) ) {
$scale = validInt($_REQUEST['scale']);
} else if ( isset($_COOKIE['zmMontageScale']) ) {
$scale = $_COOKIE['zmMontageScale'];
$scale = validInt($_COOKIE['zmMontageScale']);
}
$layouts = ZM\MontageLayout::find(NULL, array('order'=>"lower('Name')"));
@ -92,19 +92,20 @@ if ( $Layout and ( $Layout->Name() != 'Freeform' ) ) {
// Use layout instead of other options
}
if ( isset($_COOKIE['zmMontageWidth']) and $_COOKIE['zmMontageWidth'] ) {
$_SESSION['zmMontageWidth'] = $options['width'] = $_COOKIE['zmMontageWidth'];
if ( isset($_COOKIE['zmMontageWidth']) ) {
$_SESSION['zmMontageWidth'] = $options['width'] = validInt($_COOKIE['zmMontageWidth']);
#} elseif ( isset($_SESSION['zmMontageWidth']) and $_SESSION['zmMontageWidth'] ) {
#$options['width'] = $_SESSION['zmMontageWidth'];
} else
$options['width'] = '';
$options['width'] = 0;
if ( isset($_COOKIE['zmMontageHeight']) and $_COOKIE['zmMontageHeight'] )
$_SESSION['zmMontageHeight'] = $options['height'] = $_COOKIE['zmMontageHeight'];
if ( isset($_COOKIE['zmMontageHeight']) ) {
$_SESSION['zmMontageHeight'] = $options['height'] = validInt($_COOKIE['zmMontageHeight']);
#else if ( isset($_SESSION['zmMontageHeight']) and $_SESSION['zmMontageHeight'] )
#$options['height'] = $_SESSION['zmMontageHeight'];
else
$options['height'] = '';
} else {
$options['height'] = 0;
}
#if ( $scale )
$options['scale'] = $scale;
@ -128,10 +129,10 @@ foreach( $displayMonitors as &$row ) {
$showControl = true;
$row['connKey'] = generateConnKey();
if ( ! isset($widths[$row['Width']]) ) {
$widths[$row['Width'].'px'] = $row['Width'].'px';
$widths[$row['Width']] = $row['Width'].'px';
}
if ( ! isset($heights[$row['Height']]) ) {
$heights[$row['Height'].'px'] = $row['Height'].'px';
$heights[$row['Height']] = $row['Height'].'px';
}
$monitors[] = new ZM\Monitor($row);
} # end foreach Monitor
@ -200,23 +201,28 @@ if ( $showZones ) {
<div id="monitors">
<?php
foreach ( $monitors as $monitor ) {
$connkey = $monitor->connKey(); // Minor hack
?>
<div
id="monitorFrame<?php echo $monitor->Id() ?>"
class="monitorFrame"
title="<?php echo $monitor->Id() . ' ' .$monitor->Name() ?>"
style="<?php echo $options['width'] ? 'width:'.$options['width'].';':''?>"
style="<?php echo $options['width'] ? 'width:'.$options['width'].'px;':''?>"
>
<div id="monitor<?php echo $monitor->Id() ?>" class="monitor idle">
<div
id="imageFeed<?php echo $monitor->Id() ?>"
class="imageFeed"
data-monitor-id="<?php echo $monitor->Id() ?>"
data-width="<?php echo reScale( $monitor->Width(), $monitor->PopupScale() ); ?>"
data-height="<?php echo reScale( $monitor->Height(), $monitor->PopupScale() ); ?>">
data-width="<?php echo reScale($monitor->ViewWidth(), $monitor->PopupScale()); ?>"
data-height="<?php echo reScale($monitor->ViewHeight(), $monitor->PopupScale()); ?>"
>
<?php
$monitor_options = $options;
$monitor_options['width'] = $monitor_options['width'].'px';
$monitor_options['height'] = $monitor_options['height']?$monitor_options['height'].'px' : null;
$monitor_options['connkey'] = $monitor->connKey();
ZM\Logger::Debug("Options: " . print_r($monitor_options,true));
if (0 and $Positions ) {
$monitor_options['width'] = '100%';
$monitor_options['height'] = '100%';
@ -235,8 +241,8 @@ foreach ( $monitors as $monitor ) {
echo getWebSiteUrl(
'liveStream'.$monitor->Id(),
$monitor->Path(),
(isset($options['width']) ? $options['width'] : reScale($monitor->Width(), $scale).'px' ),
( isset($options['height']) ? $options['height'] : reScale($monitor->Height(), $scale).'px' ),
(isset($options['width']) ? $options['width'].'px' : reScale($monitor->ViewWidth(), $scale).'px' ),
( isset($options['height']) ? $options['height'].'px' : reScale($monitor->ViewHeight(), $scale).'px' ),
$monitor->Name()
);
} else {
@ -249,17 +255,17 @@ foreach ( $monitors as $monitor ) {
$width = $options['width'];
if ( !$options['height'] ) {
$scale = (int)( 100 * $options['width'] / $monitor->Width() );
$height = reScale($monitor->Height(), $scale).'px';
$height = reScale($monitor->Height(), $scale);
}
} else if ( $options['height'] ) {
$height = $options['height'];
if ( !$options['width'] ) {
$scale = (int)( 100 * $options['height'] / $monitor->Height() );
$width = reScale($monitor->Width(), $scale).'px';
$width = reScale($monitor->Width(), $scale);
}
} else if ( $scale ) {
$width = reScale($monitor->Width(), $scale).'px';
$height = reScale($monitor->Height(), $scale).'px';
$width = reScale($monitor->Width(), $scale);
$height = reScale($monitor->Height(), $scale);
}
$zones = array();
@ -270,8 +276,8 @@ foreach ( $monitors as $monitor ) {
limitPoints($row['Points'], 0, 0, $monitor->Width(), $monitor->Height());
} else {
limitPoints($row['Points'], 0, 0,
( $width ? $width-1 : $monitor->Width()-1 ),
( $height ? $height-1 : $monitor->Height()-1 )
( $width ? $width-1 : $monitor->ViewWidth()-1 ),
( $height ? $height-1 : $monitor->ViewHeight()-1 )
);
}
$row['Coords'] = pointsToCoords($row['Points']);
@ -280,7 +286,7 @@ foreach ( $monitors as $monitor ) {
} // end foreach Zone
?>
<svg class="zones" id="zones<?php echo $monitor->Id() ?>" style="position:absolute; top: 0; left: 0; background: none; width: 100%; height: 100%;" viewBox="0 0 <?php echo $monitor->Width() ?> <?php echo $monitor->Height() ?>" preserveAspectRatio="none">
<svg class="zones" id="zones<?php echo $monitor->Id() ?>" style="position:absolute; top: 0; left: 0; background: none; width: 100%; height: 100%;" viewBox="0 0 <?php echo $monitor->ViewWidth() ?> <?php echo $monitor->ViewHeight() ?>" preserveAspectRatio="none">
<?php
foreach( array_reverse($zones) as $zone ) {
echo '<polygon points="'. $zone['AreaCoords'] .'" class="'. $zone['Type'].'" />';

View File

@ -139,36 +139,37 @@ foreach ( array_map('basename', glob('skins/'.$skin.'/css/*',GLOB_ONLYDIR)) as $
<?php
$sql = 'SELECT * FROM Monitors ORDER BY Sequence ASC';
$monitors = array();
foreach( dbFetchAll($sql) as $monitor ) {
foreach ( dbFetchAll($sql) as $monitor ) {
$monitors[$monitor['Id']] = $monitor;
}
$sql = 'SELECT * FROM Users ORDER BY Username';
foreach( dbFetchAll($sql) as $row ) {
foreach ( dbFetchAll($sql) as $user_row ) {
$userMonitors = array();
if ( !empty($row['MonitorIds']) ) {
foreach ( explode(',', $row['MonitorIds']) as $monitorId ) {
if ( !empty($user_row['MonitorIds']) ) {
foreach ( explode(',', $user_row['MonitorIds']) as $monitorId ) {
// A deleted monitor will cause an error since we don't update
// the user monitors list on monitor delete
if ( ! isset($monitors[$monitorId]) ) continue;
if ( !isset($monitors[$monitorId]) ) continue;
$userMonitors[] = $monitors[$monitorId]['Name'];
}
}
ZM\Logger::Debug("monitors: ".$user_row['Username'] . ' ' . $user_row['MonitorIds']. ' :' . print_r($userMonitors, true));
?>
<tr>
<td class="colUsername"><?php echo makePopupLink('?view=user&amp;uid='.$row['Id'], 'zmUser', 'user', validHtmlStr($row['Username']).($user['Username']==$row['Username']?"*":""), $canEdit) ?></td>
<td class="colLanguage"><?php echo $row['Language']?validHtmlStr($row['Language']):'default' ?></td>
<td class="colEnabled"><?php echo $row['Enabled']?translate('Yes'):translate('No') ?></td>
<td class="colStream"><?php echo validHtmlStr($row['Stream']) ?></td>
<td class="colEvents"><?php echo validHtmlStr($row['Events']) ?></td>
<td class="colControl"><?php echo validHtmlStr($row['Control']) ?></td>
<td class="colMonitors"><?php echo validHtmlStr($row['Monitors']) ?></td>
<td class="colGroups"><?php echo validHtmlStr($row['Groups']) ?></td>
<td class="colSystem"><?php echo validHtmlStr($row['System']) ?></td>
<td class="colBandwidth"><?php echo $row['MaxBandwidth']?$bandwidth_options[$row['MaxBandwidth']]:'&nbsp;' ?></td>
<td class="colMonitor"><?php echo $row['MonitorIds']?(join( ", ", $userMonitors )):"&nbsp;" ?></td>
<?php if ( ZM_OPT_USE_API ) { ?><td class="colAPIEnabled"><?php echo $row['APIEnabled']?translate('Yes'):translate('No') ?></td><?php } ?>
<td class="colMark"><input type="checkbox" name="markUids[]" value="<?php echo $row['Id'] ?>" data-on-click-this="configureDeleteButton"<?php if ( !$canEdit ) { ?> disabled="disabled"<?php } ?>/></td>
<td class="colUsername"><?php echo makePopupLink('?view=user&amp;uid='.$user_row['Id'], 'zmUser', 'user', validHtmlStr($user_row['Username']).($user['Username']==$user_row['Username']?'*':''), $canEdit) ?></td>
<td class="colLanguage"><?php echo $user_row['Language']?validHtmlStr($user_row['Language']):'default' ?></td>
<td class="colEnabled"><?php echo translate($user_row['Enabled']?'Yes':'No') ?></td>
<td class="colStream"><?php echo validHtmlStr($user_row['Stream']) ?></td>
<td class="colEvents"><?php echo validHtmlStr($user_row['Events']) ?></td>
<td class="colControl"><?php echo validHtmlStr($user_row['Control']) ?></td>
<td class="colMonitors"><?php echo validHtmlStr($user_row['Monitors']) ?></td>
<td class="colGroups"><?php echo validHtmlStr($user_row['Groups']) ?></td>
<td class="colSystem"><?php echo validHtmlStr($user_row['System']) ?></td>
<td class="colBandwidth"><?php echo $user_row['MaxBandwidth']?$bandwidth_options[$user_row['MaxBandwidth']]:'&nbsp;' ?></td>
<td class="colMonitor"><?php echo count($userMonitors)?(join(', ', $userMonitors)):'&nbsp;' ?></td>
<?php if ( ZM_OPT_USE_API ) { ?><td class="colAPIEnabled"><?php echo translate($user_row['APIEnabled']?'Yes':'No') ?></td><?php } ?>
<td class="colMark"><input type="checkbox" name="markUids[]" value="<?php echo $user_row['Id'] ?>" data-on-click-this="configureDeleteButton"<?php if ( !$canEdit ) { ?> disabled="disabled"<?php } ?>/></td>
</tr>
<?php
}
@ -351,7 +352,6 @@ foreach ( array_map('basename', glob('skins/'.$skin.'/css/*',GLOB_ONLYDIR)) as $
</thead>
<tbody>
<?php
$sql = 'SELECT * FROM Users ORDER BY Username';
foreach ( dbFetchAll($sql) as $row ) {
?>
@ -379,7 +379,7 @@ foreach ( array_map('basename', glob('skins/'.$skin.'/css/*',GLOB_ONLYDIR)) as $
$result = $dbConn->query('SELECT * FROM `Config` ORDER BY `Id` ASC');
if ( !$result )
echo mysql_error();
while( $row = dbFetchNext($result) ) {
while ( $row = dbFetchNext($result) ) {
$config[$row['Name']] = $row;
if ( !($configCat = &$configCats[$row['Category']]) ) {
$configCats[$row['Category']] = array();

View File

@ -18,7 +18,7 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
$selfEdit = ZM_USER_SELF_EDIT && $_REQUEST['uid'] == $user['Id'];
$selfEdit = ZM_USER_SELF_EDIT && ($_REQUEST['uid'] == $user['Id']);
if ( !canEdit('System') && !$selfEdit ) {
$view = 'error';
@ -45,10 +45,12 @@ $nve = array( 'None'=>translate('None'), 'View'=>translate('View'), 'Edit'=>tran
$bandwidths = array_merge( array( ''=>'' ), $bandwidth_options );
$langs = array_merge( array( ''=>'' ), getLanguages() );
$sql = 'SELECT Id,Name FROM Monitors ORDER BY Sequence ASC';
$sql = 'SELECT Id, Name FROM Monitors ORDER BY Sequence ASC';
$monitors = array();
foreach( dbFetchAll($sql) as $monitor ) {
$monitors[] = $monitor;
foreach ( dbFetchAll($sql) as $monitor ) {
if ( visibleMonitor($monitor['Id']) ) {
$monitors[$monitor['Id']] = $monitor;
}
}
$focusWindow = true;
@ -61,11 +63,8 @@ xhtmlHeaders(__FILE__, translate('User').' - '.$newUser['Username']);
<h2><?php echo translate('User').' - '.validHtmlStr($newUser['Username']); ?></h2>
</div>
<div id="content">
<form name="contentForm" method="post" action="?" onsubmit="return validateForm( this, <?php echo empty($newUser['Password'])?'true':'false' ?> )">
<input type="hidden" name="view" value="<?php echo $view ?>"/>
<input type="hidden" name="action" value="user"/>
<form id="contentForm" name="contentForm" method="post" action="?view=user">
<input type="hidden" name="uid" value="<?php echo validHtmlStr($_REQUEST['uid']) ?>"/>
<input type="hidden" name="newUser[MonitorIds]" value="<?php echo validHtmlStr($newUser['MonitorIds']); ?>"/>
<table id="contentTable" class="major">
<tbody>
<?php
@ -73,7 +72,7 @@ if ( canEdit('System') ) {
?>
<tr>
<th scope="row"><?php echo translate('Username') ?></th>
<td><input type="text" name="newUser[Username]" value="<?php echo validHtmlStr($newUser['Username']); ?>"/></td>
<td><input type="text" name="newUser[Username]" value="<?php echo validHtmlStr($newUser['Username']); ?>"<?php echo $newUser['Username'] == 'admin' ? ' readonly="readonly"':''?>/></td>
</tr>
<?php
}
@ -88,63 +87,53 @@ if ( canEdit('System') ) {
</tr>
<tr>
<th scope="row"><?php echo translate('Language') ?></th>
<td><?php echo buildSelect( "newUser[Language]", $langs ) ?></td>
<td><?php echo htmlSelect('newUser[Language]', $langs, $newUser['Language']) ?></td>
</tr>
<?php
if ( canEdit('System') ) {
if ( canEdit('System') and ( $newUser['Username'] != 'admin' ) ) {
?>
<tr>
<th scope="row"><?php echo translate('Enabled') ?></th>
<td><?php echo buildSelect( "newUser[Enabled]", $yesno ) ?></td>
<td><?php echo htmlSelect('newUser[Enabled]', $yesno, $newUser['Enabled']) ?></td>
</tr>
<tr>
<th scope="row"><?php echo translate('Stream') ?></th>
<td><?php echo buildSelect( "newUser[Stream]", $nv ) ?></td>
<td><?php echo htmlSelect('newUser[Stream]', $nv, $newUser['Stream']) ?></td>
</tr>
<tr>
<th scope="row"><?php echo translate('Events') ?></th>
<td><?php echo buildSelect( "newUser[Events]", $nve ) ?></td>
<td><?php echo htmlSelect('newUser[Events]', $nve, $newUser['Events']) ?></td>
</tr>
<tr>
<th scope="row"><?php echo translate('Control') ?></th>
<td><?php echo buildSelect( "newUser[Control]", $nve ) ?></td>
<td><?php echo htmlSelect('newUser[Control]', $nve, $newUser['Control']) ?></td>
</tr>
<tr>
<th scope="row"><?php echo translate('Monitors') ?></th>
<td><?php echo buildSelect( "newUser[Monitors]", $nve ) ?></td>
<td><?php echo htmlSelect('newUser[Monitors]', $nve, $newUser['Monitors']) ?></td>
</tr>
<tr>
<th scope="row"><?php echo translate('Groups') ?></th>
<td><?php echo buildSelect( "newUser[Groups]", $nve ) ?></td>
<td><?php echo htmlSelect('newUser[Groups]', $nve, $newUser['Groups']) ?></td>
</tr>
<tr>
<th scope="row"><?php echo translate('System') ?></th>
<td><?php echo buildSelect( "newUser[System]", $nve ) ?></td>
<td><?php echo htmlSelect('newUser[System]', $nve, $newUser['System']) ?></td>
</tr>
<tr>
<th scope="row"><?php echo translate('MaxBandwidth') ?></th>
<td><?php echo buildSelect( "newUser[MaxBandwidth]", $bandwidths ) ?></td>
<td><?php echo htmlSelect('newUser[MaxBandwidth]', $bandwidths, $newUser['MaxBandwidth']) ?></td>
</tr>
<tr>
<th scope="row"><?php echo translate('RestrictedMonitors') ?></th>
<td>
<select name="monitorIds" size="4" multiple="multiple">
<?php
foreach ( $monitors as $monitor ) {
if ( visibleMonitor($monitor['Id']) ) {
?>
<option value="<?php echo $monitor['Id'] ?>"<?php if ( array_key_exists($monitor['Id'], $monitorIds) ) { ?> selected="selected"<?php } ?>><?php echo htmlentities($monitor['Name']) ?></option>
<?php
}
}
?>
</select>
<?php echo htmlSelect('newUser[MonitorIds][]', $monitors, explode(',', $newUser['MonitorIds']), array('multiple'=>'multiple')); ?>
</td>
</tr>
<?php if ( ZM_OPT_USE_API ) { ?>
<tr>
<th scope="row"><?php echo translate('APIEnabled')?></th>
<td><?php echo buildSelect( "newUser[APIEnabled]", $yesno ) ?></td>
<td><?php echo htmlSelect('newUser[APIEnabled]', $yesno, $newUser['APIEnabled']) ?></td>
</tr>
<?php
@ -154,7 +143,7 @@ if ( canEdit('System') ) {
</tbody>
</table>
<div id="contentButtons">
<button type="submit" value="Save"><?php echo translate('Save') ?></button>
<button type="submit" name="action" value="Save"><?php echo translate('Save') ?></button>
<button type="button" data-on-click="closeWindow"><?php echo translate('Cancel') ?></button>
</div>
</form>

View File

@ -18,12 +18,12 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
if ( !canView('Monitors') ) {
$mid = empty($_REQUEST['mid']) ? 0 : validInt($_REQUEST['mid']);
if ( !($mid and canEdit('Monitors', $mid)) ) {
$view = 'error';
return;
}
$mid = validInt($_REQUEST['mid']);
$zid = (!empty($_REQUEST['zid'])) ? validInt($_REQUEST['zid']) : 0;
$scale = SCALE_BASE;
@ -212,8 +212,8 @@ xhtmlHeaders(__FILE__, translate('Zone'));
</tr>
<tr>
<th scope="row"><?php echo translate('ZoneMinMaxPixelThres') ?></th>
<td><input type="number" name="newZone[MinPixelThreshold]" value="<?php echo $newZone['MinPixelThreshold'] ?>"/></td>
<td><input type="number" name="newZone[MaxPixelThreshold]" value="<?php echo $newZone['MaxPixelThreshold'] ?>"/></td>
<td><input type="number" name="newZone[MinPixelThreshold]" value="<?php echo $newZone['MinPixelThreshold'] ?>" min="0" max="255"/></td>
<td><input type="number" name="newZone[MaxPixelThreshold]" value="<?php echo $newZone['MaxPixelThreshold'] ?>" min="0" max="255"/></td>
</tr>
<tr>
<th scope="row"><?php echo translate('ZoneFilterSize') ?></th>

View File

@ -18,12 +18,12 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
if ( !canView('Monitors') ) {
$mid = empty($_REQUEST['mid']) ? 0 : validInt($_REQUEST['mid']);
if ( !($mid and canEdit('Monitors', $mid)) ) {
$view = 'error';
return;
}
$mid = validInt($_REQUEST['mid']);
$monitor = new ZM\Monitor($mid);
# ViewWidth() and ViewHeight() are already rotated
$minX = 0;