Merge branch 'storageareas' of github.com:ConnorTechnology/ZoneMinder into storageareas
commit
f9be7f0fa0
|
@ -28,7 +28,7 @@ New installs
|
|||
1. Unless you are already using MariaDB server, you need to ensure that the
|
||||
server is configured to start during boot and properly secured by running:
|
||||
|
||||
sudo dnf install mariadb-server
|
||||
sudo yum install mariadb-server
|
||||
sudo systemctl enable mariadb
|
||||
sudo systemctl start mariadb.service
|
||||
mysql_secure_installation
|
||||
|
|
|
@ -18,7 +18,7 @@ Alias /zm "@ZM_WEBDIR@"
|
|||
Allow from all
|
||||
</Directory>
|
||||
|
||||
ScriptAlias /cgi-bin/zm "@ZM_CGIDIR@"
|
||||
ScriptAlias /cgi-bin-zm "@ZM_CGIDIR@"
|
||||
<Directory "@ZM_CGIDIR@">
|
||||
SSLRequireSSL
|
||||
AllowOverride All
|
||||
|
|
|
@ -4,3 +4,5 @@ var/cache/zoneminder/events
|
|||
var/cache/zoneminder/images
|
||||
var/cache/zoneminder/temp
|
||||
usr/share/zoneminder/db
|
||||
etc/zm
|
||||
etc/zm/conf.d
|
||||
|
|
|
@ -4,51 +4,51 @@ set -e
|
|||
|
||||
if [ "$1" = "configure" ]; then
|
||||
|
||||
. /etc/zm/zm.conf
|
||||
. /etc/zm/zm.conf
|
||||
|
||||
# The logs can contain passwords, etc... so by setting group root, only www-data can read them, not people in the www-data group
|
||||
chown www-data:root /var/log/zm
|
||||
chown www-data:www-data /var/lib/zm
|
||||
if [ -z "$2" ]; then
|
||||
chown www-data:www-data /var/cache/zoneminder /var/cache/zoneminder/*
|
||||
fi
|
||||
# The logs can contain passwords, etc... so by setting group root, only www-data can read them, not people in the www-data group
|
||||
chown www-data:root /var/log/zm
|
||||
chown www-data:www-data /var/lib/zm
|
||||
if [ -z "$2" ]; then
|
||||
chown www-data:www-data /var/cache/zoneminder /var/cache/zoneminder/*
|
||||
fi
|
||||
|
||||
# Do this every time the package is installed or upgraded
|
||||
# Do this every time the package is installed or upgraded
|
||||
# Ensure zoneminder is stopped
|
||||
invoke-rc.d zoneminder stop || true
|
||||
|
||||
if [ "$ZM_DB_HOST" = "localhost" ]; then
|
||||
if [ -e "/etc/init.d/mysql" ]; then
|
||||
#
|
||||
# Get mysql started if it isn't
|
||||
#
|
||||
if ! $(/etc/init.d/mysql status >/dev/null 2>&1); then
|
||||
invoke-rc.d mysql start
|
||||
fi
|
||||
if $(/etc/init.d/mysql status >/dev/null 2>&1); then
|
||||
mysqladmin --defaults-file=/etc/mysql/debian.cnf -f reload
|
||||
# test if database if already present...
|
||||
if ! $(echo quit | mysql --defaults-file=/etc/mysql/debian.cnf zm > /dev/null 2> /dev/null) ; then
|
||||
cat /usr/share/zoneminder/db/zm_create.sql | mysql --defaults-file=/etc/mysql/debian.cnf
|
||||
# This creates the user.
|
||||
echo "grant lock tables, alter,select,insert,update,delete,create,index on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost identified by \"${ZM_DB_PASS}\";" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
|
||||
else
|
||||
echo "grant lock tables, alter,select,insert,update,delete,create,index on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost;" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
|
||||
fi
|
||||
|
||||
# Ensure zoneminder is stopped
|
||||
invoke-rc.d zoneminder stop || true
|
||||
zmupdate.pl --nointeractive
|
||||
zmupdate.pl --nointeractive -f
|
||||
echo "Done Updating, starting ZoneMinder"
|
||||
invoke-rc.d zoneminder start || true
|
||||
else
|
||||
echo 'NOTE: mysql not running, please start mysql and run dpkg-reconfigure zoneminder when it is running.'
|
||||
fi
|
||||
else
|
||||
echo 'mysql not found, assuming remote server.'
|
||||
if [ "$ZM_DB_HOST" = "localhost" ]; then
|
||||
if [ -e "/etc/init.d/mysql" ]; then
|
||||
#
|
||||
# Get mysql started if it isn't
|
||||
#
|
||||
if ! $(/etc/init.d/mysql status >/dev/null 2>&1); then
|
||||
invoke-rc.d mysql start
|
||||
fi
|
||||
if $(/etc/init.d/mysql status >/dev/null 2>&1); then
|
||||
mysqladmin --defaults-file=/etc/mysql/debian.cnf -f reload
|
||||
# test if database if already present...
|
||||
if ! $(echo quit | mysql --defaults-file=/etc/mysql/debian.cnf zm > /dev/null 2> /dev/null) ; then
|
||||
cat /usr/share/zoneminder/db/zm_create.sql | mysql --defaults-file=/etc/mysql/debian.cnf
|
||||
# This creates the user.
|
||||
echo "grant lock tables, alter,select,insert,update,delete,create,index on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost identified by \"${ZM_DB_PASS}\";" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
|
||||
else
|
||||
echo "grant lock tables, alter,select,insert,update,delete,create,index on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost;" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
|
||||
fi
|
||||
|
||||
zmupdate.pl --nointeractive
|
||||
zmupdate.pl --nointeractive -f
|
||||
else
|
||||
echo 'NOTE: mysql not running, please start mysql and run dpkg-reconfigure zoneminder when it is running.'
|
||||
fi
|
||||
else
|
||||
echo "Not doing database upgrade due to remote db server ($ZM_DB_HOST)"
|
||||
echo 'mysql not found, assuming remote server.'
|
||||
fi
|
||||
else
|
||||
echo "Not doing database upgrade due to remote db server ($ZM_DB_HOST)"
|
||||
fi
|
||||
echo "Done Updating, starting ZoneMinder"
|
||||
invoke-rc.d zoneminder start || true
|
||||
fi
|
||||
|
||||
#DEBHELPER#
|
||||
|
|
|
@ -13,11 +13,11 @@ Build-Depends: debhelper (>= 9), dh-systemd, python-sphinx | python3-sphinx, apa
|
|||
,libavutil-dev (>= 6:10~)
|
||||
,libswscale-dev (>= 6:10~)
|
||||
,libbz2-dev
|
||||
,libgcrypt-dev
|
||||
,libgcrypt-dev | libgcrypt11-dev
|
||||
,libcurl4-gnutls-dev
|
||||
,libgnutls-openssl-dev
|
||||
,libjpeg8-dev | libjpeg9-dev | libjpeg62-turbo-dev
|
||||
,libmysqlclient-dev
|
||||
,libmysqlclient-dev | libmariadbclient-dev
|
||||
,libpcre3-dev
|
||||
,libpolkit-gobject-1-dev
|
||||
,libv4l-dev (>= 0.8.3) [!hurd-any]
|
||||
|
|
|
@ -21,6 +21,8 @@ if [ "$1" = "configure" ]; then
|
|||
# Ensure zoneminder is stopped
|
||||
deb-systemd-invoke stop zoneminder.service || exit $?
|
||||
|
||||
# Ensure zoneminder is stopped
|
||||
deb-systemd-invoke stop zoneminder.service || exit $?
|
||||
if [ "$ZM_DB_HOST" = "localhost" ]; then
|
||||
|
||||
if [ -e "/etc/init.d/mysql" ]; then
|
||||
|
@ -46,10 +48,10 @@ if [ "$1" = "configure" ]; then
|
|||
zmupdate.pl --nointeractive
|
||||
zmupdate.pl --nointeractive -f
|
||||
else
|
||||
echo 'NOTE: mysql not running, please start mysql and run dpkg-reconfigure zoneminder when it is running.'
|
||||
echo 'NOTE: mysql not running, please start mysql and run dpkg-reconfigure zoneminder when it is running.'
|
||||
fi
|
||||
else
|
||||
echo 'mysql not found, assuming remote server.'
|
||||
echo 'mysql not found, assuming remote server.'
|
||||
fi
|
||||
|
||||
else
|
||||
|
|
|
@ -297,24 +297,28 @@ sub terminate {
|
|||
sub reinitialise {
|
||||
my $this = shift;
|
||||
|
||||
# So if the logger is initialized, we just return. Since the logger is NORMALLY initialized... the rest of this function never executes.
|
||||
return unless ( $this->{initialised} );
|
||||
|
||||
# Bit of a nasty hack to reopen connections to log files and the DB
|
||||
my $syslogLevel = $this->syslogLevel();
|
||||
$this->syslogLevel( NOLOG );
|
||||
$this->syslogLevel( $syslogLevel ) if ( $syslogLevel > NOLOG );
|
||||
|
||||
my $logfileLevel = $this->fileLevel();
|
||||
$this->fileLevel( NOLOG );
|
||||
$this->fileLevel( $logfileLevel ) if ( $logfileLevel > NOLOG );
|
||||
|
||||
my $databaseLevel = $this->databaseLevel();
|
||||
$this->databaseLevel( NOLOG );
|
||||
$this->databaseLevel( $databaseLevel ) if ( $databaseLevel > NOLOG );
|
||||
|
||||
my $screenLevel = $this->termLevel();
|
||||
$this->termLevel( NOLOG );
|
||||
|
||||
$this->syslogLevel( $syslogLevel ) if ( $syslogLevel > NOLOG );
|
||||
$this->fileLevel( $logfileLevel ) if ( $logfileLevel > NOLOG );
|
||||
$this->databaseLevel( $databaseLevel ) if ( $databaseLevel > NOLOG );
|
||||
$this->databaseLevel( $databaseLevel ) if ( $databaseLevel > NOLOG );
|
||||
$this->termLevel( $screenLevel ) if ( $screenLevel > NOLOG );
|
||||
}
|
||||
|
||||
# Prevents undefined logging levels
|
||||
sub limit {
|
||||
my $this = shift;
|
||||
my $level = shift;
|
||||
|
@ -375,12 +379,16 @@ sub level {
|
|||
my $level = shift;
|
||||
if ( defined($level) ) {
|
||||
$this->{level} = $this->limit( $level );
|
||||
|
||||
# effectiveLevel is the highest logging level used by any of the outputs.
|
||||
$this->{effectiveLevel} = NOLOG;
|
||||
$this->{effectiveLevel} = $this->{termLevel} if ( $this->{termLevel} > $this->{effectiveLevel} );
|
||||
$this->{effectiveLevel} = $this->{databaseLevel} if ( $this->{databaseLevel} > $this->{effectiveLevel} );
|
||||
$this->{effectiveLevel} = $this->{fileLevel} if ( $this->{fileLevel} > $this->{effectiveLevel} );
|
||||
$this->{effectiveLevel} = $this->{syslogLevel} if ( $this->{syslogLevel} > $this->{effectiveLevel} );
|
||||
$this->{effectiveLevel} = $this->{level} if ( $this->{effectiveLevel} > $this->{effectiveLevel} );
|
||||
|
||||
# ICON: I am remarking this out because I don't see the point of having an effective level, if we are just going to set it to level.
|
||||
#$this->{effectiveLevel} = $this->{level} if ( $this->{level} > $this->{effectiveLevel} );
|
||||
}
|
||||
return( $this->{level} );
|
||||
}
|
||||
|
@ -400,6 +408,7 @@ sub termLevel {
|
|||
my $this = shift;
|
||||
my $termLevel = shift;
|
||||
if ( defined($termLevel) ) {
|
||||
# What is the point of this next lint if we are just going to overwrite it with the next line? I propose we move it down one line or remove it altogether
|
||||
$termLevel = NOLOG if ( !$this->{hasTerm} );
|
||||
$termLevel = $this->limit( $termLevel );
|
||||
if ( $this->{termLevel} != $termLevel ) {
|
||||
|
|
|
@ -174,7 +174,7 @@ if ( ! $server_up ) {
|
|||
$attempts++;
|
||||
Error("Waiting for zmdc.pl server process, attempt $attempts" );
|
||||
Fatal( "Can't connect: $!" ) if ($attempts > MAX_CONNECT_DELAY);
|
||||
usleep(20000);
|
||||
usleep(200000);
|
||||
} # end while
|
||||
} elsif ( defined($cpid) ) {
|
||||
ZMServer::run();
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# ==========================================================================
|
||||
|
||||
use strict;
|
||||
use bytes;
|
||||
|
||||
|
@ -62,57 +63,56 @@ if ( ! defined $interval ) {
|
|||
$interval = eval($Config{ZM_TELEMETRY_INTERVAL});
|
||||
}
|
||||
|
||||
if ( $Config{ZM_TELEMETRY_DATA} or $force )
|
||||
{
|
||||
print "Update agent starting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n";
|
||||
if ( $Config{ZM_TELEMETRY_DATA} or $force ) {
|
||||
print "Update agent starting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n";
|
||||
|
||||
my $lastCheck = $Config{ZM_TELEMETRY_LAST_UPLOAD};
|
||||
my $lastCheck = $Config{ZM_TELEMETRY_LAST_UPLOAD};
|
||||
|
||||
while( 1 ) {
|
||||
my $now = time();
|
||||
my $since_last_check = $now-$lastCheck;
|
||||
Debug(" Last Check time (now($now) - lastCheck($lastCheck)) = $since_last_check > interval($interval) or force($force)");
|
||||
if ( $since_last_check < 0 ) {
|
||||
Warning( "Seconds since last check is negative! Which means that lastCheck is in the future!" );
|
||||
next;
|
||||
}
|
||||
if ( ( ($now-$lastCheck) > $interval ) or $force ) {
|
||||
print "Collecting data to send to ZoneMinder Telemetry server.\n";
|
||||
my $dbh = zmDbConnect();
|
||||
# Build the telemetry hash
|
||||
# We should keep *BSD systems in mind when calling system commands
|
||||
my %telemetry;
|
||||
$telemetry{uuid} = getUUID($dbh);
|
||||
$telemetry{ip} = getIP();
|
||||
$telemetry{timestamp} = strftime( "%Y-%m-%dT%H:%M:%S%z", localtime() );
|
||||
$telemetry{monitor_count} = countQuery($dbh,"Monitors");
|
||||
$telemetry{event_count} = countQuery($dbh,"Events");
|
||||
$telemetry{architecture} = runSysCmd("uname -p");
|
||||
($telemetry{kernel}, $telemetry{distro}, $telemetry{version}) = getDistro();
|
||||
$telemetry{zm_version} = ZoneMinder::Base::ZM_VERSION;
|
||||
$telemetry{system_memory} = totalmem();
|
||||
$telemetry{processor_count} = cpu_count();
|
||||
$telemetry{monitors} = getMonitorRef($dbh);
|
||||
|
||||
Info( "Sending data to ZoneMinder Telemetry server." );
|
||||
|
||||
my $result = jsonEncode( \%telemetry );
|
||||
|
||||
if ( sendData($result) ) {
|
||||
|
||||
my $sql = q`UPDATE Config SET Value = ? WHERE Name = 'ZM_TELEMETRY_LAST_UPLOAD'`;
|
||||
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute( $now ) or die( "Can't execute: ".$sth->errstr() );
|
||||
$sth->finish();
|
||||
$Config{ZM_TELEMETRY_LAST_UPLOAD} = $now;
|
||||
}
|
||||
zmDbDisconnect();
|
||||
} elsif ( -t STDIN ) {
|
||||
print "Update agent sleeping for 1 hour because ($now-$lastCheck=$since_last_check > $interval\n";
|
||||
}
|
||||
sleep( 3600 );
|
||||
while( 1 ) {
|
||||
my $now = time();
|
||||
my $since_last_check = $now-$lastCheck;
|
||||
Debug(" Last Check time (now($now) - lastCheck($lastCheck)) = $since_last_check > interval($interval) or force($force)");
|
||||
if ( $since_last_check < 0 ) {
|
||||
Warning( "Seconds since last check is negative! Which means that lastCheck is in the future!" );
|
||||
next;
|
||||
}
|
||||
print "Update agent exiting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n";
|
||||
if ( ( ($now-$lastCheck) > $interval ) or $force ) {
|
||||
print "Collecting data to send to ZoneMinder Telemetry server.\n";
|
||||
my $dbh = zmDbConnect();
|
||||
# Build the telemetry hash
|
||||
# We should keep *BSD systems in mind when calling system commands
|
||||
my %telemetry;
|
||||
$telemetry{uuid} = getUUID($dbh);
|
||||
$telemetry{ip} = getIP();
|
||||
$telemetry{timestamp} = strftime( '%Y-%m-%dT%H:%M:%S%z', localtime() );
|
||||
$telemetry{monitor_count} = countQuery($dbh,'Monitors');
|
||||
$telemetry{event_count} = countQuery($dbh,'Events');
|
||||
$telemetry{architecture} = runSysCmd('uname -p');
|
||||
($telemetry{kernel}, $telemetry{distro}, $telemetry{version}) = getDistro();
|
||||
$telemetry{zm_version} = ZoneMinder::Base::ZM_VERSION;
|
||||
$telemetry{system_memory} = totalmem();
|
||||
$telemetry{processor_count} = cpu_count();
|
||||
$telemetry{monitors} = getMonitorRef($dbh);
|
||||
|
||||
Info( 'Sending data to ZoneMinder Telemetry server.' );
|
||||
|
||||
my $result = jsonEncode( \%telemetry );
|
||||
|
||||
if ( sendData($result) ) {
|
||||
|
||||
my $sql = q`UPDATE Config SET Value = ? WHERE Name = 'ZM_TELEMETRY_LAST_UPLOAD'`;
|
||||
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute( $now ) or die( "Can't execute: ".$sth->errstr() );
|
||||
$sth->finish();
|
||||
$Config{ZM_TELEMETRY_LAST_UPLOAD} = $now;
|
||||
}
|
||||
zmDbDisconnect();
|
||||
} elsif ( -t STDIN ) {
|
||||
print "Update agent sleeping for 1 hour because ($now-$lastCheck=$since_last_check > $interval\n";
|
||||
}
|
||||
sleep( 3600 );
|
||||
}
|
||||
print 'Update agent exiting at '.strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n";
|
||||
}
|
||||
|
||||
###############
|
||||
|
@ -121,227 +121,227 @@ if ( $Config{ZM_TELEMETRY_DATA} or $force )
|
|||
|
||||
# Find, verify, then run the supplied system command
|
||||
sub runSysCmd {
|
||||
my $msg = shift;
|
||||
my @arguments = split(/ /,$msg);
|
||||
chomp($arguments[0]);
|
||||
my $path = qx( which $arguments[0] );
|
||||
my $msg = shift;
|
||||
my @arguments = split(/ /,$msg);
|
||||
chomp($arguments[0]);
|
||||
my $path = qx( which $arguments[0] );
|
||||
|
||||
my $status = $? >> 8;
|
||||
my $result = "";
|
||||
if ( !$path || $status ) {
|
||||
Warning( "Cannot find the $arguments[0] executable." );
|
||||
} else {
|
||||
chomp($path);
|
||||
$arguments[0] = $path;
|
||||
my $cmd = join(" ",@arguments);
|
||||
$result = qx( $cmd );
|
||||
chomp($result);
|
||||
}
|
||||
my $status = $? >> 8;
|
||||
my $result = '';
|
||||
if ( !$path || $status ) {
|
||||
Warning( "Cannot find the $arguments[0] executable." );
|
||||
} else {
|
||||
chomp($path);
|
||||
$arguments[0] = $path;
|
||||
my $cmd = join(' ',@arguments);
|
||||
$result = qx( $cmd );
|
||||
chomp($result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
return $result;
|
||||
}
|
||||
|
||||
# Upload message data to ZoneMinder telemetry server
|
||||
sub sendData {
|
||||
my $msg = shift;
|
||||
my $msg = shift;
|
||||
|
||||
my $ua = LWP::UserAgent->new;
|
||||
my $server_endpoint = $Config{ZM_TELEMETRY_SERVER_ENDPOINT};
|
||||
my $ua = LWP::UserAgent->new;
|
||||
my $server_endpoint = $Config{ZM_TELEMETRY_SERVER_ENDPOINT};
|
||||
|
||||
if ( $Config{ZM_UPDATE_CHECK_PROXY} ) {
|
||||
$ua->proxy( "https", $Config{ZM_UPDATE_CHECK_PROXY} );
|
||||
}
|
||||
if ( $Config{ZM_UPDATE_CHECK_PROXY} ) {
|
||||
$ua->proxy( 'https', $Config{ZM_UPDATE_CHECK_PROXY} );
|
||||
}
|
||||
|
||||
Debug("Posting telemetry data to: $server_endpoint");
|
||||
Debug("Posting telemetry data to: $server_endpoint");
|
||||
|
||||
# set custom HTTP request header fields
|
||||
my $req = HTTP::Request->new(POST => $server_endpoint);
|
||||
$req->header('content-type' => 'application/x-www-form-urlencoded');
|
||||
$req->header('content-length' => length($msg));
|
||||
$req->header('connection' => 'Close');
|
||||
|
||||
$req->content($msg);
|
||||
|
||||
my $resp = $ua->request($req);
|
||||
my $resp_msg = $resp->decoded_content;
|
||||
my $resp_code = $resp->code;
|
||||
if ($resp->is_success) {
|
||||
Info("Telemetry data uploaded successfully.");
|
||||
Debug("Telemetry server upload success response message: $resp_msg");
|
||||
} else {
|
||||
Warning("Telemetry server returned HTTP POST error code: $resp_code");
|
||||
Debug("Telemetry server upload failure response message: $resp_msg");
|
||||
}
|
||||
return $resp->is_success;
|
||||
# set custom HTTP request header fields
|
||||
my $req = HTTP::Request->new(POST => $server_endpoint);
|
||||
$req->header('content-type' => 'application/x-www-form-urlencoded');
|
||||
$req->header('content-length' => length($msg));
|
||||
$req->header('connection' => 'Close');
|
||||
|
||||
$req->content($msg);
|
||||
|
||||
my $resp = $ua->request($req);
|
||||
my $resp_msg = $resp->decoded_content;
|
||||
my $resp_code = $resp->code;
|
||||
if ($resp->is_success) {
|
||||
Info('Telemetry data uploaded successfully.');
|
||||
Debug("Telemetry server upload success response message: $resp_msg");
|
||||
} else {
|
||||
Warning("Telemetry server returned HTTP POST error code: $resp_code");
|
||||
Debug("Telemetry server upload failure response message: $resp_msg");
|
||||
}
|
||||
return $resp->is_success;
|
||||
}
|
||||
|
||||
# Retrieves the UUID from the database. Creates a new UUID if one does not exist.
|
||||
sub getUUID {
|
||||
my $dbh = shift;
|
||||
my $uuid= "";
|
||||
my $dbh = shift;
|
||||
my $uuid= "";
|
||||
|
||||
# Verify the current UUID is valid and not nil
|
||||
if (( $Config{ZM_TELEMETRY_UUID} =~ /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/i ) && ( $Config{ZM_TELEMETRY_UUID} ne "00000000-0000-0000-0000-000000000000" )) {
|
||||
$uuid = $Config{ZM_TELEMETRY_UUID};
|
||||
} else {
|
||||
my $sql = "SELECT uuid()";
|
||||
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() );
|
||||
$uuid = $Config{ZM_TELEMETRY_UUID} = $sth->fetchrow_array();
|
||||
$sth->finish();
|
||||
# Verify the current UUID is valid and not nil
|
||||
if (( $Config{ZM_TELEMETRY_UUID} =~ /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/i ) && ( $Config{ZM_TELEMETRY_UUID} ne '00000000-0000-0000-0000-000000000000' )) {
|
||||
$uuid = $Config{ZM_TELEMETRY_UUID};
|
||||
} else {
|
||||
my $sql = 'SELECT uuid()';
|
||||
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() );
|
||||
$uuid = $Config{ZM_TELEMETRY_UUID} = $sth->fetchrow_array();
|
||||
$sth->finish();
|
||||
|
||||
$sql = "UPDATE Config set Value = ? WHERE Name = 'ZM_TELEMETRY_UUID'";
|
||||
$sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
$res = $sth->execute( "$uuid" ) or die( "Can't execute: ".$sth->errstr() );
|
||||
$sth->finish();
|
||||
}
|
||||
Debug("Using UUID of: $uuid");
|
||||
$sql = q`UPDATE Config set Value = ? WHERE Name = 'ZM_TELEMETRY_UUID'`;
|
||||
$sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
$res = $sth->execute( "$uuid" ) or die( "Can't execute: ".$sth->errstr() );
|
||||
$sth->finish();
|
||||
}
|
||||
Debug("Using UUID of: $uuid");
|
||||
|
||||
return $uuid;
|
||||
return $uuid;
|
||||
}
|
||||
|
||||
# Retrieves the local server's external IP address
|
||||
sub getIP {
|
||||
my $ipaddr = "0.0.0.0";
|
||||
my $ua = LWP::UserAgent->new;
|
||||
my $server_endpoint = "https://wiki.zoneminder.com/ip.php";
|
||||
my $ipaddr = '0.0.0.0';
|
||||
my $ua = LWP::UserAgent->new;
|
||||
my $server_endpoint = 'https://wiki.zoneminder.com/ip.php';
|
||||
|
||||
my $req = HTTP::Request->new(GET => $server_endpoint);
|
||||
my $resp = $ua->request($req);
|
||||
my $req = HTTP::Request->new(GET => $server_endpoint);
|
||||
my $resp = $ua->request($req);
|
||||
|
||||
if ($resp->is_success) {
|
||||
$ipaddr = $resp->decoded_content;
|
||||
}
|
||||
if ($resp->is_success) {
|
||||
$ipaddr = $resp->decoded_content;
|
||||
}
|
||||
|
||||
Debug("Found external ip address of: $ipaddr");
|
||||
Debug("Found external ip address of: $ipaddr");
|
||||
|
||||
return $ipaddr;
|
||||
return $ipaddr;
|
||||
}
|
||||
|
||||
# As the name implies, just your average mysql count query
|
||||
sub countQuery {
|
||||
my $dbh = shift;
|
||||
my $table = shift;
|
||||
my $dbh = shift;
|
||||
my $table = shift;
|
||||
|
||||
my $sql = "SELECT count(*) FROM $table";
|
||||
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() );
|
||||
my $count = $sth->fetchrow_array();
|
||||
$sth->finish();
|
||||
my $sql = "SELECT count(*) FROM $table";
|
||||
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() );
|
||||
my $count = $sth->fetchrow_array();
|
||||
$sth->finish();
|
||||
|
||||
return $count
|
||||
return $count
|
||||
}
|
||||
|
||||
# Returns a reference to an array of hashes containing data from all monitors
|
||||
sub getMonitorRef {
|
||||
my $dbh = shift;
|
||||
my $dbh = shift;
|
||||
|
||||
my $sql = "SELECT Id,Name,Type,Function,Width,Height,Colours,MaxFPS,AlarmMaxFPS FROM Monitors";
|
||||
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() );
|
||||
my $arrayref = $sth->fetchall_arrayref({});
|
||||
my $sql = 'SELECT Id,Name,Type,Function,Width,Height,Colours,MaxFPS,AlarmMaxFPS FROM Monitors';
|
||||
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() );
|
||||
my $arrayref = $sth->fetchall_arrayref({});
|
||||
|
||||
return $arrayref;
|
||||
return $arrayref;
|
||||
}
|
||||
|
||||
sub getDistro {
|
||||
my $kernel = "";
|
||||
my $distro = "";
|
||||
my $version = "";
|
||||
my @uname = uname();
|
||||
my $kernel = '';
|
||||
my $distro = '';
|
||||
my $version = '';
|
||||
my @uname = uname();
|
||||
|
||||
if ( $uname[0] =~ /Linux/ ) {
|
||||
Debug("Linux distro detected.");
|
||||
($kernel, $distro, $version) = linuxDistro();
|
||||
} elsif ( $uname[0] =~ /.*BSD/ ) {
|
||||
Debug("BSD distro detected.");
|
||||
$kernel = $uname[3];
|
||||
$distro = $uname[0];
|
||||
$version = $uname[2];
|
||||
} elsif ( $uname[0] =~ /Darwin/ ) {
|
||||
Debug("Mac OS distro detected.");
|
||||
$kernel = $uname[3];
|
||||
$distro = runSysCmd("sw_vers -productName");
|
||||
$version = runSysCmd("sw_vers -productVersion");
|
||||
} elsif ( $uname[0] =~ /SunOS|Solaris/ ) {
|
||||
Debug("Sun Solaris detected.");
|
||||
$kernel = $uname[3];
|
||||
$distro = $uname[1];
|
||||
$version = $uname[2];
|
||||
} else {
|
||||
Warning("ZoneMinder was unable to determine the host system. Please report.");
|
||||
$kernel = "Unknown";
|
||||
$distro = "Unknown";
|
||||
$version = "Unknown";
|
||||
}
|
||||
if ( $uname[0] =~ /Linux/ ) {
|
||||
Debug('Linux distro detected.');
|
||||
($kernel, $distro, $version) = linuxDistro();
|
||||
} elsif ( $uname[0] =~ /.*BSD/ ) {
|
||||
Debug('BSD distro detected.');
|
||||
$kernel = $uname[3];
|
||||
$distro = $uname[0];
|
||||
$version = $uname[2];
|
||||
} elsif ( $uname[0] =~ /Darwin/ ) {
|
||||
Debug('Mac OS distro detected.');
|
||||
$kernel = $uname[3];
|
||||
$distro = runSysCmd('sw_vers -productName');
|
||||
$version = runSysCmd('sw_vers -productVersion');
|
||||
} elsif ( $uname[0] =~ /SunOS|Solaris/ ) {
|
||||
Debug('Sun Solaris detected.');
|
||||
$kernel = $uname[3];
|
||||
$distro = $uname[1];
|
||||
$version = $uname[2];
|
||||
} else {
|
||||
Warning('ZoneMinder was unable to determine the host system. Please report.');
|
||||
$kernel = 'Unknown';
|
||||
$distro = 'Unknown';
|
||||
$version = 'Unknown';
|
||||
}
|
||||
|
||||
return ($kernel, $distro, $version);
|
||||
return ($kernel, $distro, $version);
|
||||
}
|
||||
|
||||
sub linuxDistro {
|
||||
my @uname = uname();
|
||||
my $kernel = $uname[2];
|
||||
my $distro = "Unknown Linux Distro";
|
||||
my $version = "Unknown Linux Version";
|
||||
my $found = 0;
|
||||
my @uname = uname();
|
||||
my $kernel = $uname[2];
|
||||
my $distro = 'Unknown Linux Distro';
|
||||
my $version = 'Unknown Linux Version';
|
||||
my $found = 0;
|
||||
|
||||
# os-release is the standard for many new distros based on systemd
|
||||
if ( -f "/etc/os-release" ) {
|
||||
open(my $RELFILE,"<","/etc/os-release") or die( "Can't Open file: $!\n" );
|
||||
# os-release is the standard for many new distros based on systemd
|
||||
if ( -f '/etc/os-release' ) {
|
||||
open(my $RELFILE,'<','/etc/os-release') or die( "Can't Open file: $!\n" );
|
||||
while (<$RELFILE>) {
|
||||
if ( /^NAME=(")?(.*)(?(1)\1|).*$/ ) {
|
||||
$distro = $2;
|
||||
$found = 1;
|
||||
}
|
||||
if ( /^VERSION_ID=(")?(.*)(?(1)\1|).*$/ ) {
|
||||
$version = $2;
|
||||
$found = 1;
|
||||
}
|
||||
}
|
||||
close $RELFILE;
|
||||
# exists on many distros but does not always contain useful information, such as redhat
|
||||
} elsif ( -f '/etc/lsb-release' ) {
|
||||
open(my $RELFILE,'<','/etc/lsb-release') or die( "Can't Open file: $!\n" );
|
||||
while (<$RELFILE>) {
|
||||
if ( /^DISTRIB_DESCRIPTION=(")?(.*)(?(1)\1|).*$/ ) {
|
||||
$distro = $2;
|
||||
$found = 1;
|
||||
}
|
||||
if ( /^DISTRIB_RELEASE=(")?(.*)(?(1)\1|).*$/ ) {
|
||||
$version = $2;
|
||||
$found = 1;
|
||||
}
|
||||
}
|
||||
close $RELFILE;
|
||||
}
|
||||
|
||||
# If all else fails, search through a list of known release files until we find one
|
||||
if ( !$found ) {
|
||||
my @releasefile = ('/etc/SuSE-release', '/etc/redhat-release', '/etc/redhat_version',
|
||||
'/etc/fedora-release', '/etc/slackware-release', '/etc/slackware-version',
|
||||
'/etc/debian_release', '/etc/debian_version', '/etc/mandrake-release',
|
||||
'/etc/yellowdog-release', '/etc/gentoo-release');
|
||||
foreach (@releasefile) {
|
||||
if ( -f $_ ) {
|
||||
open(my $RELFILE,'<',$_) or die( "Can't Open file: $!\n" );
|
||||
while (<$RELFILE>) {
|
||||
if ( /^NAME=(")?(.*)(?(1)\1|).*$/ ) {
|
||||
$distro = $2;
|
||||
$found = 1;
|
||||
}
|
||||
if ( /^VERSION_ID=(")?(.*)(?(1)\1|).*$/ ) {
|
||||
$version = $2;
|
||||
$found = 1;
|
||||
}
|
||||
if ( /(.*).* (\d+\.?\d*) .*/ ) {
|
||||
$distro = $1;
|
||||
$version = $2;
|
||||
$found = 1;
|
||||
}
|
||||
}
|
||||
close $RELFILE;
|
||||
# exists on many distros but does not always contain useful information, such as redhat
|
||||
} elsif ( -f "/etc/lsb-release" ) {
|
||||
open(my $RELFILE,"<","/etc/lsb-release") or die( "Can't Open file: $!\n" );
|
||||
while (<$RELFILE>) {
|
||||
if ( /^DISTRIB_DESCRIPTION=(")?(.*)(?(1)\1|).*$/ ) {
|
||||
$distro = $2;
|
||||
$found = 1;
|
||||
}
|
||||
if ( /^DISTRIB_RELEASE=(")?(.*)(?(1)\1|).*$/ ) {
|
||||
$version = $2;
|
||||
$found = 1;
|
||||
}
|
||||
}
|
||||
close $RELFILE;
|
||||
close $RELFILE;
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# If all else fails, search through a list of known release files until we find one
|
||||
if ( !$found ) {
|
||||
my @releasefile = ("/etc/SuSE-release", "/etc/redhat-release", "/etc/redhat_version",
|
||||
"/etc/fedora-release", "/etc/slackware-release", "/etc/slackware-version",
|
||||
"/etc/debian_release", "/etc/debian_version", "/etc/mandrake-release",
|
||||
"/etc/yellowdog-release", "/etc/gentoo-release");
|
||||
foreach (@releasefile) {
|
||||
if ( -f $_ ) {
|
||||
open(my $RELFILE,"<",$_) or die( "Can't Open file: $!\n" );
|
||||
while (<$RELFILE>) {
|
||||
if ( /(.*).* (\d+\.?\d*) .*/ ) {
|
||||
$distro = $1;
|
||||
$version = $2;
|
||||
$found = 1;
|
||||
}
|
||||
}
|
||||
close $RELFILE;
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( !$found ) {
|
||||
Warning('ZoneMinder was unable to determine Linux distro. Please report.');
|
||||
}
|
||||
|
||||
if ( !$found ) {
|
||||
Warning("ZoneMinder was unable to determine Linux distro. Please report.");
|
||||
}
|
||||
|
||||
return ($kernel, $distro, $version);
|
||||
return ($kernel, $distro, $version);
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
@ -39,24 +39,24 @@ void zmLoadConfig() {
|
|||
// update the Config hash with those values
|
||||
DIR* configSubFolder = opendir(ZM_CONFIG_SUBDIR);
|
||||
if ( configSubFolder ) { // subfolder exists and is readable
|
||||
char glob_pattern[PATH_MAX] = "";
|
||||
snprintf( glob_pattern, sizeof(glob_pattern), "%s/*.conf", ZM_CONFIG_SUBDIR );
|
||||
char glob_pattern[PATH_MAX] = "";
|
||||
snprintf( glob_pattern, sizeof(glob_pattern), "%s/*.conf", ZM_CONFIG_SUBDIR );
|
||||
|
||||
glob_t pglob;
|
||||
int glob_status = glob( glob_pattern, 0, 0, &pglob );
|
||||
if ( glob_status != 0 ) {
|
||||
if ( glob_status < 0 ) {
|
||||
Error( "Can't glob '%s': %s", glob_pattern, strerror(errno) );
|
||||
} else {
|
||||
Debug( 1, "Can't glob '%s': %d", glob_pattern, glob_status );
|
||||
}
|
||||
glob_t pglob;
|
||||
int glob_status = glob( glob_pattern, 0, 0, &pglob );
|
||||
if ( glob_status != 0 ) {
|
||||
if ( glob_status < 0 ) {
|
||||
Error( "Can't glob '%s': %s", glob_pattern, strerror(errno) );
|
||||
} else {
|
||||
for ( unsigned int i = 0; i < pglob.gl_pathc; i++ ) {
|
||||
process_configfile(pglob.gl_pathv[i]);
|
||||
}
|
||||
closedir(configSubFolder);
|
||||
Debug( 1, "Can't glob '%s': %d", glob_pattern, glob_status );
|
||||
}
|
||||
globfree( &pglob );
|
||||
} else {
|
||||
for ( unsigned int i = 0; i < pglob.gl_pathc; i++ ) {
|
||||
process_configfile(pglob.gl_pathv[i]);
|
||||
}
|
||||
closedir(configSubFolder);
|
||||
}
|
||||
globfree( &pglob );
|
||||
}
|
||||
|
||||
zmDbConnect();
|
||||
|
|
|
@ -195,7 +195,7 @@ void Logger::initialise( const std::string &id, const Options &options ) {
|
|||
level( tempLevel );
|
||||
|
||||
mFlush = false;
|
||||
if (envPtr = getenv( "LOG_FLUSH")) {
|
||||
if ( (envPtr = getenv("LOG_FLUSH")) ) {
|
||||
mFlush = atoi( envPtr );
|
||||
} else if ( config.log_debug ) {
|
||||
mFlush = true;
|
||||
|
|
|
@ -30,8 +30,7 @@ class Monitor;
|
|||
|
||||
#define TV_2_FLOAT( tv ) ( double((tv).tv_sec) + (double((tv).tv_usec) / 1000000.0) )
|
||||
|
||||
class StreamBase
|
||||
{
|
||||
class StreamBase {
|
||||
public:
|
||||
typedef enum { STREAM_JPEG, STREAM_RAW, STREAM_ZIP, STREAM_SINGLE, STREAM_MPEG } StreamType;
|
||||
|
||||
|
@ -110,8 +109,7 @@ protected:
|
|||
virtual void processCommand( const CmdMsg *msg )=0;
|
||||
|
||||
public:
|
||||
StreamBase()
|
||||
{
|
||||
StreamBase() {
|
||||
monitor = 0;
|
||||
|
||||
type = DEFAULT_TYPE;
|
||||
|
@ -145,32 +143,27 @@ public:
|
|||
}
|
||||
virtual ~StreamBase();
|
||||
|
||||
void setStreamType( StreamType p_type )
|
||||
{
|
||||
void setStreamType( StreamType p_type ) {
|
||||
type = p_type;
|
||||
}
|
||||
void setStreamFormat( const char *p_format )
|
||||
{
|
||||
void setStreamFormat( const char *p_format ) {
|
||||
format = p_format;
|
||||
}
|
||||
void setStreamScale( int p_scale )
|
||||
{
|
||||
void setStreamScale( int p_scale ) {
|
||||
scale = p_scale;
|
||||
if ( ! scale )
|
||||
scale = DEFAULT_SCALE;
|
||||
}
|
||||
void setStreamReplayRate( int p_rate )
|
||||
{
|
||||
void setStreamReplayRate( int p_rate ) {
|
||||
replay_rate = p_rate;
|
||||
}
|
||||
void setStreamMaxFPS( double p_maxfps )
|
||||
{
|
||||
void setStreamMaxFPS( double p_maxfps ) {
|
||||
maxfps = p_maxfps;
|
||||
}
|
||||
void setStreamBitrate( int p_bitrate )
|
||||
{
|
||||
void setStreamBitrate( int p_bitrate ) {
|
||||
bitrate = p_bitrate;
|
||||
}
|
||||
void setStreamQueue( int p_connkey )
|
||||
{
|
||||
void setStreamQueue( int p_connkey ) {
|
||||
connkey = p_connkey;
|
||||
}
|
||||
virtual void openComms();
|
||||
|
|
|
@ -155,7 +155,7 @@ int X264MP4Writer::Open() {
|
|||
}
|
||||
|
||||
/* Search SPS NAL for AVC information */
|
||||
for ( unsigned int i = 0; i < i_nals; i++ ) {
|
||||
for ( int i = 0; i < i_nals; i++ ) {
|
||||
if ( nals[i].i_type == NAL_SPS ) {
|
||||
x264_profleindication = nals[i].p_payload[5];
|
||||
x264_profilecompat = nals[i].p_payload[6];
|
||||
|
@ -467,7 +467,7 @@ void X264MP4Writer::x264encodeloop(bool bFlush) {
|
|||
/* Got a frame. Copy this new frame into the previous frame */
|
||||
if ( frame_size > 0 ) {
|
||||
/* Copy the NALs and the payloads */
|
||||
for ( unsigned int i = 0; i < i_nals; i++ ) {
|
||||
for ( int i = 0; i < i_nals; i++ ) {
|
||||
prevnals.push_back(nals[i]);
|
||||
prevpayload.append(nals[i].p_payload, nals[i].i_payload);
|
||||
}
|
||||
|
|
|
@ -618,7 +618,7 @@ int VideoStore::writeVideoFramePacket( AVPacket *ipkt ) {
|
|||
int duration;
|
||||
|
||||
//Scale the PTS of the outgoing packet to be the correct time base
|
||||
if (ipkt->pts != AV_NOPTS_VALUE) {
|
||||
if ( ipkt->pts != AV_NOPTS_VALUE ) {
|
||||
|
||||
if ( ! video_last_pts ) {
|
||||
// This is the first packet.
|
||||
|
@ -696,9 +696,9 @@ int VideoStore::writeVideoFramePacket( AVPacket *ipkt ) {
|
|||
}
|
||||
|
||||
AVPacket safepkt;
|
||||
memcpy(&safepkt, &opkt, sizeof(AVPacket));
|
||||
memcpy( &safepkt, &opkt, sizeof(AVPacket) );
|
||||
|
||||
Debug(1, "writing video packet pts(%d) dts(%d) duration(%d)", opkt.pts, opkt.dts, opkt.duration );
|
||||
Debug(1, "writing video packet pts(%d) dts(%d) duration(%d)", opkt.pts, opkt.dts, opkt.duration );
|
||||
if ((opkt.data == NULL)||(opkt.size < 1)) {
|
||||
Warning("%s:%d: Mangled AVPacket: discarding frame", __FILE__, __LINE__ );
|
||||
dumpPacket( ipkt);
|
||||
|
@ -714,10 +714,14 @@ Debug(1, "writing video packet pts(%d) dts(%d) duration(%d)", opkt.pts, opkt.dts
|
|||
video_previous_dts = opkt.dts; // Unsure if av_interleaved_write_frame() clobbers opkt.dts when out of order, so storing in advance
|
||||
video_previous_pts = opkt.pts;
|
||||
ret = av_interleaved_write_frame(oc, &opkt);
|
||||
if(ret<0){
|
||||
if ( ret < 0 ) {
|
||||
// There's nothing we can really do if the frame is rejected, just drop it and get on with the next
|
||||
Warning("%s:%d: Writing frame [av_interleaved_write_frame()] failed: %s(%d) ", __FILE__, __LINE__, av_make_error_string(ret).c_str(), (ret));
|
||||
dumpPacket(&safepkt);
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||
zm_dump_codecpar( video_input_stream->codecpar );
|
||||
zm_dump_codecpar( video_output_stream->codecpar );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
348
src/zms.cpp
348
src/zms.cpp
|
@ -28,44 +28,41 @@
|
|||
#include "zm_monitorstream.h"
|
||||
|
||||
bool ValidateAccess( User *user, int mon_id ) {
|
||||
bool allowed = true;
|
||||
bool allowed = true;
|
||||
|
||||
if ( mon_id > 0 ) {
|
||||
if ( user->getStream() < User::PERM_VIEW )
|
||||
allowed = false;
|
||||
if ( !user->canAccess( mon_id ) )
|
||||
allowed = false;
|
||||
} else {
|
||||
if ( user->getEvents() < User::PERM_VIEW )
|
||||
allowed = false;
|
||||
}
|
||||
if ( !allowed ) {
|
||||
Error( "Error, insufficient privileges for requested action" );
|
||||
exit( -1 );
|
||||
if ( mon_id > 0 ) {
|
||||
if ( user->getStream() < User::PERM_VIEW )
|
||||
allowed = false;
|
||||
if ( !user->canAccess( mon_id ) )
|
||||
allowed = false;
|
||||
} else {
|
||||
Debug( 1, "User allowed.");
|
||||
}
|
||||
return( allowed );
|
||||
if ( user->getEvents() < User::PERM_VIEW )
|
||||
allowed = false;
|
||||
}
|
||||
if ( !allowed ) {
|
||||
Error( "Error, insufficient privileges for requested action" );
|
||||
exit( -1 );
|
||||
}
|
||||
return( allowed );
|
||||
}
|
||||
|
||||
int main( int argc, const char *argv[] )
|
||||
{
|
||||
self = argv[0];
|
||||
int main( int argc, const char *argv[] ) {
|
||||
self = argv[0];
|
||||
|
||||
srand( getpid() * time( 0 ) );
|
||||
srand( getpid() * time( 0 ) );
|
||||
|
||||
enum { ZMS_MONITOR, ZMS_EVENT } source = ZMS_MONITOR;
|
||||
enum { ZMS_JPEG, ZMS_MPEG, ZMS_RAW, ZMS_ZIP, ZMS_SINGLE } mode = ZMS_JPEG;
|
||||
char format[32] = "";
|
||||
int monitor_id = 0;
|
||||
time_t event_time = 0;
|
||||
int event_id = 0;
|
||||
unsigned int frame_id = 1;
|
||||
unsigned int scale = 100;
|
||||
unsigned int rate = 100;
|
||||
double maxfps = 10.0;
|
||||
unsigned int bitrate = 100000;
|
||||
unsigned int ttl = 0;
|
||||
enum { ZMS_MONITOR, ZMS_EVENT } source = ZMS_MONITOR;
|
||||
enum { ZMS_JPEG, ZMS_MPEG, ZMS_RAW, ZMS_ZIP, ZMS_SINGLE } mode = ZMS_JPEG;
|
||||
char format[32] = "";
|
||||
int monitor_id = 0;
|
||||
time_t event_time = 0;
|
||||
int event_id = 0;
|
||||
unsigned int frame_id = 1;
|
||||
unsigned int scale = 100;
|
||||
unsigned int rate = 100;
|
||||
double maxfps = 10.0;
|
||||
unsigned int bitrate = 100000;
|
||||
unsigned int ttl = 0;
|
||||
EventStream::StreamMode replay = EventStream::MODE_SINGLE;
|
||||
std::string username;
|
||||
std::string password;
|
||||
|
@ -73,163 +70,158 @@ int main( int argc, const char *argv[] )
|
|||
unsigned int connkey = 0;
|
||||
unsigned int playback_buffer = 0;
|
||||
|
||||
bool nph = false;
|
||||
const char *basename = strrchr( argv[0], '/' );
|
||||
if (basename) //if we found a / lets skip past it
|
||||
basename++;
|
||||
else //argv[0] will not always contain the full path, but rather just the script name
|
||||
basename = argv[0];
|
||||
const char *nph_prefix = "nph-";
|
||||
if ( basename && !strncmp( basename, nph_prefix, strlen(nph_prefix) ) ) {
|
||||
nph = true;
|
||||
}
|
||||
|
||||
zmLoadConfig();
|
||||
|
||||
logInit( "zms" );
|
||||
bool nph = false;
|
||||
const char *basename = strrchr( argv[0], '/' );
|
||||
if (basename) //if we found a / lets skip past it
|
||||
basename++;
|
||||
else //argv[0] will not always contain the full path, but rather just the script name
|
||||
basename = argv[0];
|
||||
const char *nph_prefix = "nph-";
|
||||
if ( basename && !strncmp( basename, nph_prefix, strlen(nph_prefix) ) ) {
|
||||
nph = true;
|
||||
}
|
||||
|
||||
hwcaps_detect();
|
||||
zmLoadConfig();
|
||||
|
||||
zmSetDefaultTermHandler();
|
||||
zmSetDefaultDieHandler();
|
||||
logInit( "zms" );
|
||||
|
||||
hwcaps_detect();
|
||||
|
||||
const char *query = getenv( "QUERY_STRING" );
|
||||
if ( query ) {
|
||||
Debug( 1, "Query: %s", query );
|
||||
|
||||
char temp_query[1024];
|
||||
strncpy( temp_query, query, sizeof(temp_query) );
|
||||
char *q_ptr = temp_query;
|
||||
char *parms[16]; // Shouldn't be more than this
|
||||
int parm_no = 0;
|
||||
while( (parm_no < 16) && (parms[parm_no] = strtok( q_ptr, "&" )) ) {
|
||||
parm_no++;
|
||||
q_ptr = NULL;
|
||||
}
|
||||
|
||||
for ( int p = 0; p < parm_no; p++ ) {
|
||||
char *name = strtok( parms[p], "=" );
|
||||
char *value = strtok( NULL, "=" );
|
||||
zmSetDefaultTermHandler();
|
||||
zmSetDefaultDieHandler();
|
||||
|
||||
const char *query = getenv( "QUERY_STRING" );
|
||||
if ( query ) {
|
||||
Debug( 1, "Query: %s", query );
|
||||
|
||||
char temp_query[1024];
|
||||
strncpy( temp_query, query, sizeof(temp_query) );
|
||||
char *q_ptr = temp_query;
|
||||
char *parms[16]; // Shouldn't be more than this
|
||||
int parm_no = 0;
|
||||
while( (parm_no < 16) && (parms[parm_no] = strtok( q_ptr, "&" )) ) {
|
||||
parm_no++;
|
||||
q_ptr = NULL;
|
||||
}
|
||||
|
||||
for ( int p = 0; p < parm_no; p++ ) {
|
||||
char *name = strtok( parms[p], "=" );
|
||||
char *value = strtok( NULL, "=" );
|
||||
if ( !value )
|
||||
value = (char *)"";
|
||||
if ( !strcmp( name, "source" ) ) {
|
||||
source = !strcmp( value, "event" )?ZMS_EVENT:ZMS_MONITOR;
|
||||
} else if ( !strcmp( name, "mode" ) ) {
|
||||
mode = !strcmp( value, "jpeg" )?ZMS_JPEG:ZMS_MPEG;
|
||||
mode = !strcmp( value, "raw" )?ZMS_RAW:mode;
|
||||
mode = !strcmp( value, "zip" )?ZMS_ZIP:mode;
|
||||
mode = !strcmp( value, "single" )?ZMS_SINGLE:mode;
|
||||
} else if ( !strcmp( name, "format" ) )
|
||||
strncpy( format, value, sizeof(format) );
|
||||
else if ( !strcmp( name, "monitor" ) )
|
||||
monitor_id = atoi( value );
|
||||
else if ( !strcmp( name, "time" ) )
|
||||
event_time = atoi( value );
|
||||
else if ( !strcmp( name, "event" ) )
|
||||
event_id = strtoull( value, (char **)NULL, 10 );
|
||||
else if ( !strcmp( name, "frame" ) )
|
||||
frame_id = strtoull( value, (char **)NULL, 10 );
|
||||
else if ( !strcmp( name, "scale" ) )
|
||||
scale = atoi( value );
|
||||
else if ( !strcmp( name, "rate" ) )
|
||||
rate = atoi( value );
|
||||
else if ( !strcmp( name, "maxfps" ) )
|
||||
maxfps = atof( value );
|
||||
else if ( !strcmp( name, "bitrate" ) )
|
||||
bitrate = atoi( value );
|
||||
else if ( !strcmp( name, "ttl" ) )
|
||||
ttl = atoi(value);
|
||||
else if ( !strcmp( name, "replay" ) ) {
|
||||
replay = !strcmp( value, "gapless" )?EventStream::MODE_ALL_GAPLESS:EventStream::MODE_SINGLE;
|
||||
replay = !strcmp( value, "all" )?EventStream::MODE_ALL:replay;
|
||||
} else if ( !strcmp( name, "connkey" ) )
|
||||
connkey = atoi(value);
|
||||
else if ( !strcmp( name, "buffer" ) )
|
||||
playback_buffer = atoi(value);
|
||||
else if ( config.opt_use_auth ) {
|
||||
if ( strcmp( config.auth_relay, "none" ) == 0 ) {
|
||||
if ( !strcmp( name, "user" ) ) {
|
||||
username = UriDecode( value );
|
||||
}
|
||||
} else {
|
||||
//if ( strcmp( config.auth_relay, "hashed" ) == 0 )
|
||||
{
|
||||
if ( !strcmp( name, "auth" ) ) {
|
||||
strncpy( auth, value, sizeof(auth) );
|
||||
}
|
||||
}
|
||||
//else if ( strcmp( config.auth_relay, "plain" ) == 0 )
|
||||
{
|
||||
if ( !strcmp( name, "user" ) ) {
|
||||
if ( !strcmp( name, "source" ) ) {
|
||||
source = !strcmp( value, "event" )?ZMS_EVENT:ZMS_MONITOR;
|
||||
} else if ( !strcmp( name, "mode" ) ) {
|
||||
mode = !strcmp( value, "jpeg" )?ZMS_JPEG:ZMS_MPEG;
|
||||
mode = !strcmp( value, "raw" )?ZMS_RAW:mode;
|
||||
mode = !strcmp( value, "zip" )?ZMS_ZIP:mode;
|
||||
mode = !strcmp( value, "single" )?ZMS_SINGLE:mode;
|
||||
} else if ( !strcmp( name, "format" ) ) {
|
||||
strncpy( format, value, sizeof(format) );
|
||||
} else if ( !strcmp( name, "monitor" ) ) {
|
||||
monitor_id = atoi( value );
|
||||
} else if ( !strcmp( name, "time" ) ) {
|
||||
event_time = atoi( value );
|
||||
} else if ( !strcmp( name, "event" ) ) {
|
||||
event_id = strtoull( value, (char **)NULL, 10 );
|
||||
} else if ( !strcmp( name, "frame" ) ) {
|
||||
frame_id = strtoull( value, (char **)NULL, 10 );
|
||||
} else if ( !strcmp( name, "scale" ) ) {
|
||||
scale = atoi( value );
|
||||
} else if ( !strcmp( name, "rate" ) ) {
|
||||
rate = atoi( value );
|
||||
} else if ( !strcmp( name, "maxfps" ) ) {
|
||||
maxfps = atof( value );
|
||||
} else if ( !strcmp( name, "bitrate" ) ) {
|
||||
bitrate = atoi( value );
|
||||
} else if ( !strcmp( name, "ttl" ) ) {
|
||||
ttl = atoi(value);
|
||||
} else if ( !strcmp( name, "replay" ) ) {
|
||||
replay = !strcmp( value, "gapless" )?EventStream::MODE_ALL_GAPLESS:EventStream::MODE_SINGLE;
|
||||
replay = !strcmp( value, "all" )?EventStream::MODE_ALL:replay;
|
||||
} else if ( !strcmp( name, "connkey" ) ) {
|
||||
connkey = atoi(value);
|
||||
} else if ( !strcmp( name, "buffer" ) ) {
|
||||
playback_buffer = atoi(value);
|
||||
} else if ( config.opt_use_auth ) {
|
||||
if ( strcmp( config.auth_relay, "none" ) == 0 ) {
|
||||
if ( !strcmp( name, "user" ) ) {
|
||||
username = value;
|
||||
}
|
||||
} else {
|
||||
//if ( strcmp( config.auth_relay, "hashed" ) == 0 )
|
||||
{
|
||||
if ( !strcmp( name, "auth" ) ) {
|
||||
strncpy( auth, value, sizeof(auth) );
|
||||
}
|
||||
}
|
||||
//else if ( strcmp( config.auth_relay, "plain" ) == 0 )
|
||||
{
|
||||
if ( !strcmp( name, "user" ) ) {
|
||||
username = UriDecode( value );
|
||||
Debug( 1, "Have %s for username", username.c_str() );
|
||||
}
|
||||
if ( !strcmp( name, "pass" ) ) {
|
||||
}
|
||||
if ( !strcmp( name, "pass" ) ) {
|
||||
password = UriDecode( value );
|
||||
Debug( 1, "Have %s for password", password.c_str() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end foreach parm
|
||||
} // end if query
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end foreach parm
|
||||
} // end if query
|
||||
|
||||
if ( config.opt_use_auth ) {
|
||||
User *user = 0;
|
||||
if ( config.opt_use_auth ) {
|
||||
User *user = 0;
|
||||
|
||||
if ( strcmp( config.auth_relay, "none" ) == 0 ) {
|
||||
if ( username.length() ) {
|
||||
user = zmLoadUser( username.c_str() );
|
||||
}
|
||||
} else {
|
||||
//if ( strcmp( config.auth_relay, "hashed" ) == 0 )
|
||||
{
|
||||
if ( *auth ) {
|
||||
user = zmLoadAuthUser( auth, config.auth_hash_ips );
|
||||
} else {
|
||||
Debug( 1, "Need both username and password" );
|
||||
}
|
||||
}
|
||||
//else if ( strcmp( config.auth_relay, "plain" ) == 0 )
|
||||
{
|
||||
if ( username.length() && password.length() ) {
|
||||
user = zmLoadUser( username.c_str(), password.c_str() );
|
||||
} else {
|
||||
Debug( 1, "Need both username and password" );
|
||||
}
|
||||
}
|
||||
} // auth is none or something else
|
||||
if ( !user ) {
|
||||
Error( "Unable to authenticate user" );
|
||||
logTerm();
|
||||
zmDbClose();
|
||||
return( -1 );
|
||||
}
|
||||
ValidateAccess( user, monitor_id );
|
||||
} // end if use_auth
|
||||
if ( strcmp( config.auth_relay, "none" ) == 0 ) {
|
||||
if ( username.length() ) {
|
||||
user = zmLoadUser( username.c_str() );
|
||||
}
|
||||
} else {
|
||||
//if ( strcmp( config.auth_relay, "hashed" ) == 0 )
|
||||
{
|
||||
if ( *auth ) {
|
||||
user = zmLoadAuthUser( auth, config.auth_hash_ips );
|
||||
}
|
||||
}
|
||||
//else if ( strcmp( config.auth_relay, "plain" ) == 0 )
|
||||
{
|
||||
if ( username.length() && password.length() ) {
|
||||
user = zmLoadUser( username.c_str(), password.c_str() );
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( !user ) {
|
||||
Error( "Unable to authenticate user" );
|
||||
logTerm();
|
||||
zmDbClose();
|
||||
return( -1 );
|
||||
}
|
||||
ValidateAccess( user, monitor_id );
|
||||
}
|
||||
|
||||
setbuf( stdout, 0 );
|
||||
if ( nph ) {
|
||||
fprintf( stdout, "HTTP/1.0 200 OK\r\n" );
|
||||
}
|
||||
fprintf( stdout, "Server: ZoneMinder Video Server/%s\r\n", ZM_VERSION );
|
||||
|
||||
time_t now = time( 0 );
|
||||
char date_string[64];
|
||||
strftime( date_string, sizeof(date_string)-1, "%a, %d %b %Y %H:%M:%S GMT", gmtime( &now ) );
|
||||
setbuf( stdout, 0 );
|
||||
if ( nph ) {
|
||||
fprintf( stdout, "HTTP/1.0 200 OK\r\n" );
|
||||
}
|
||||
fprintf( stdout, "Server: ZoneMinder Video Server/%s\r\n", ZM_VERSION );
|
||||
|
||||
time_t now = time( 0 );
|
||||
char date_string[64];
|
||||
strftime( date_string, sizeof(date_string)-1, "%a, %d %b %Y %H:%M:%S GMT", gmtime( &now ) );
|
||||
|
||||
fprintf( stdout, "Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n" );
|
||||
fprintf( stdout, "Last-Modified: %s\r\n", date_string );
|
||||
fprintf( stdout, "Cache-Control: no-store, no-cache, must-revalidate\r\n" );
|
||||
fprintf( stdout, "Cache-Control: post-check=0, pre-check=0\r\n" );
|
||||
fprintf( stdout, "Pragma: no-cache\r\n");
|
||||
// Removed as causing more problems than it fixed.
|
||||
//if ( !nph )
|
||||
//{
|
||||
//fprintf( stdout, "Content-Length: 0\r\n");
|
||||
//}
|
||||
fprintf( stdout, "Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n" );
|
||||
fprintf( stdout, "Last-Modified: %s\r\n", date_string );
|
||||
fprintf( stdout, "Cache-Control: no-store, no-cache, must-revalidate\r\n" );
|
||||
fprintf( stdout, "Cache-Control: post-check=0, pre-check=0\r\n" );
|
||||
fprintf( stdout, "Pragma: no-cache\r\n");
|
||||
// Removed as causing more problems than it fixed.
|
||||
//if ( !nph )
|
||||
//{
|
||||
//fprintf( stdout, "Content-Length: 0\r\n");
|
||||
//}
|
||||
|
||||
if ( source == ZMS_MONITOR ) {
|
||||
if ( source == ZMS_MONITOR ) {
|
||||
MonitorStream stream;
|
||||
stream.setStreamScale( scale );
|
||||
stream.setStreamReplayRate( rate );
|
||||
|
@ -249,9 +241,9 @@ int main( int argc, const char *argv[] )
|
|||
stream.setStreamType( MonitorStream::STREAM_JPEG );
|
||||
} else if ( mode == ZMS_RAW ) {
|
||||
stream.setStreamType( MonitorStream::STREAM_RAW );
|
||||
} else if ( mode == ZMS_ZIP ) {
|
||||
} else if ( mode == ZMS_ZIP ) {
|
||||
stream.setStreamType( MonitorStream::STREAM_ZIP );
|
||||
} else if ( mode == ZMS_SINGLE ) {
|
||||
} else if ( mode == ZMS_SINGLE ) {
|
||||
stream.setStreamType( MonitorStream::STREAM_SINGLE );
|
||||
} else {
|
||||
#if HAVE_LIBAVCODEC
|
||||
|
|
|
@ -263,16 +263,15 @@ if [ $TYPE == "binary" ]; then
|
|||
if [[ $REPLY == [yY] ]]; then
|
||||
sudo dpkg -i $DIRECTORY*.deb
|
||||
fi;
|
||||
|
||||
read -p "Do you want to upload this binary to zmrepo? (y/N)"
|
||||
if [[ $REPLY == [yY] ]]; then
|
||||
if [ "$RELEASE" != "" ]; then
|
||||
scp "zoneminder_${VERSION}-${DISTRO}*" "zmrepo@zmrepo.connortechnology.com:debian/stable/mini-dinstall/incoming/"
|
||||
scp "zoneminder_${VERSION}-${DISTRO}"* "zoneminder-doc_${VERSION}-${DISTRO}"* "zoneminder-dbg_${VERSION}-${DISTRO}"* "zoneminder_${VERSION}.orig.tar.gz" "zmrepo@zmrepo.connortechnology.com:debian/stable/mini-dinstall/incoming/"
|
||||
else
|
||||
if [ "$BRANCH" == "" ]; then
|
||||
scp "zoneminder_${VERSION}-${DISTRO}*" "zmrepo@zmrepo.connortechnology.com:debian/master/mini-dinstall/incoming/"
|
||||
scp "zoneminder_${VERSION}-${DISTRO}"* "zoneminder-doc_${VERSION}-${DISTRO}"* "zoneminder-dbg_${VERSION}-${DISTRO}"* "zoneminder_${VERSION}.orig.tar.gz" "zmrepo@zmrepo.connortechnology.com:debian/master/mini-dinstall/incoming/"
|
||||
else
|
||||
scp "$DIRECTORY-${DISTRO}*" "zmrepo@zmrepo.connortechnology.com:debian/${BRANCH}/mini-dinstall/incoming/"
|
||||
scp "$DIRECTORY-${DISTRO}"* "zoneminder-doc_${VERSION}-${DISTRO}"* "zoneminder-dbg_${VERSION}-${DISTRO}"* "zoneminder_${VERSION}.orig.tar.gz" "zmrepo@zmrepo.connortechnology.com:debian/${BRANCH}/mini-dinstall/incoming/"
|
||||
fi;
|
||||
fi;
|
||||
fi;
|
||||
|
|
|
@ -42,26 +42,27 @@ switch ( $_REQUEST['task'] )
|
|||
$servers_by_Id[$server->Id()] = $server;
|
||||
}
|
||||
|
||||
$minTime = isset($_POST['minTime'])?$_POST['minTime']:NULL;
|
||||
$maxTime = isset($_POST['maxTime'])?$_POST['maxTime']:NULL;
|
||||
$minTime = isset($_REQUEST['minTime'])?$_REQUEST['minTime']:NULL;
|
||||
$maxTime = isset($_REQUEST['maxTime'])?$_REQUEST['maxTime']:NULL;
|
||||
|
||||
$limit = 100;
|
||||
if ( isset($_POST['limit']) ) {
|
||||
if ( ( !is_integer( $_POST['limit'] ) and !ctype_digit($_POST['limit']) ) ) {
|
||||
Error("Invalid value for limit " . $_POST['limit'] );
|
||||
if ( isset($_REQUEST['limit']) ) {
|
||||
if ( ( !is_integer( $_REQUEST['limit'] ) and !ctype_digit($_REQUEST['limit']) ) ) {
|
||||
Error("Invalid value for limit " . $_REQUEST['limit'] );
|
||||
} else {
|
||||
$limit = $_POST['limit'];
|
||||
$limit = $_REQUEST['limit'];
|
||||
}
|
||||
}
|
||||
$sortField = 'TimeKey';
|
||||
if ( isset($_POST['sortField']) ) {
|
||||
if ( ! in_array( $_POST['sortField'], $filterFields ) and ( $_POST['sortField'] != 'TimeKey' ) ) {
|
||||
Error("Invalid sort field " . $_POST['sortField'] );
|
||||
if ( isset($_REQUEST['sortField']) ) {
|
||||
if ( ! in_array( $_REQUEST['sortField'], $filterFields ) and ( $_REQUEST['sortField'] != 'TimeKey' ) ) {
|
||||
Error("Invalid sort field " . $_REQUEST['sortField'] );
|
||||
} else {
|
||||
$sortField = $_POST['sortField'];
|
||||
$sortField = $_REQUEST['sortField'];
|
||||
}
|
||||
}
|
||||
$sortOrder = (isset($_POST['sortOrder']) and $_POST['sortOrder']) == 'asc' ? 'asc':'desc';
|
||||
$filter = isset($_POST['filter'])?$_POST['filter']:array();
|
||||
$sortOrder = (isset($_REQUEST['sortOrder']) and $_REQUEST['sortOrder']) == 'asc' ? 'asc':'desc';
|
||||
$filter = isset($_REQUEST['filter'])?$_REQUEST['filter']:array();
|
||||
|
||||
$total = dbFetchOne( 'SELECT count(*) AS Total FROM Logs', 'Total' );
|
||||
$sql = 'SELECT * FROM Logs';
|
||||
|
@ -95,6 +96,8 @@ switch ( $_REQUEST['task'] )
|
|||
foreach ( dbFetchAll( $sql, NULL, $values ) as $log ) {
|
||||
$log['DateTime'] = preg_replace( '/^\d+/', strftime( "%Y-%m-%d %H:%M:%S", intval($log['TimeKey']) ), $log['TimeKey'] );
|
||||
$log['Server'] = ( $log['ServerId'] and isset($servers_by_Id[$log['ServerId']]) ) ? $servers_by_Id[$log['ServerId']]->Name() : '';
|
||||
#$log['Message'] = preg_replace('/[\x00-\x1F\x7F]/u', '', $log['Message'] );
|
||||
$log['Message'] = preg_replace('/[\x00-\x1F\x7F-\xFF]/', '', $log['Message'] );
|
||||
$logs[] = $log;
|
||||
}
|
||||
$options = array();
|
||||
|
|
|
@ -171,14 +171,13 @@ Warning("Addterm");
|
|||
} else if ( $action == 'eventdetail' ) {
|
||||
if ( !empty($_REQUEST['eid']) ) {
|
||||
dbQuery( 'UPDATE Events SET Cause=?, Notes=? WHERE Id=?', array( $_REQUEST['newEvent']['Cause'], $_REQUEST['newEvent']['Notes'], $_REQUEST['eid'] ) );
|
||||
$refreshParent = true;
|
||||
} else {
|
||||
foreach( getAffectedIds( 'markEid' ) as $markEid ) {
|
||||
dbQuery( 'UPDATE Events SET Cause=?, Notes=? WHERE Id=?', array( $_REQUEST['newEvent']['Cause'], $_REQUEST['newEvent']['Notes'], $markEid ) );
|
||||
$refreshParent = true;
|
||||
}
|
||||
$refreshParent = '/index.php?view=filter&Id='.$_REQUEST['Id'];
|
||||
}
|
||||
$refreshParent = true;
|
||||
$closePopup = true;
|
||||
} elseif ( $action == 'archive' || $action == 'unarchive' ) {
|
||||
$archiveVal = ($action == 'archive')?1:0;
|
||||
if ( !empty($_REQUEST['eid']) ) {
|
||||
|
@ -186,14 +185,14 @@ Warning("Addterm");
|
|||
} else {
|
||||
foreach( getAffectedIds( 'markEid' ) as $markEid ) {
|
||||
dbQuery( 'UPDATE Events SET Archived=? WHERE Id=?', array( $archiveVal, $markEid ) );
|
||||
$refreshParent = true;
|
||||
}
|
||||
$refreshParent = true;
|
||||
}
|
||||
} elseif ( $action == 'delete' ) {
|
||||
foreach( getAffectedIds( 'markEid' ) as $markEid ) {
|
||||
deleteEvent( $markEid );
|
||||
$refreshParent = true;
|
||||
}
|
||||
$refreshParent = true;
|
||||
}
|
||||
} // end if canEdit(Events)
|
||||
} // end if filter or something else
|
||||
|
|
|
@ -1146,24 +1146,26 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&' ) {
|
|||
|
||||
$StorageArea = NULL;
|
||||
|
||||
if ( isset($filter['terms']) && count($filter['terms']) ) {
|
||||
for ( $i = 0; $i < count($filter['terms']); $i++ ) {
|
||||
if ( isset($filter['terms'][$i]['cnj']) ) {
|
||||
$filter['query'] .= $querySep.urlencode("filter[terms][$i][cnj]").'='.urlencode($filter['terms'][$i]['cnj']);
|
||||
$filter['sql'] .= ' '.$filter['terms'][$i]['cnj'].' ';
|
||||
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[terms][$i][cnj]\" value=\"".htmlspecialchars($filter['terms'][$i]['cnj'])."\"/>\n";
|
||||
$terms = $filter['Query']['terms'];
|
||||
|
||||
if ( isset($terms) && count($terms) ) {
|
||||
for ( $i = 0; $i < count($terms); $i++ ) {
|
||||
if ( isset($terms[$i]['cnj']) ) {
|
||||
$filter['query'] .= $querySep.urlencode("filter[Query][terms][$i][cnj]").'='.urlencode($terms[$i]['cnj']);
|
||||
$filter['sql'] .= ' '.$terms[$i]['cnj'].' ';
|
||||
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[Query][terms][$i][cnj]\" value=\"".htmlspecialchars($terms[$i]['cnj'])."\"/>\n";
|
||||
}
|
||||
if ( isset($filter['terms'][$i]['obr']) ) {
|
||||
$filter['query'] .= $querySep.urlencode("filter[terms][$i][obr]").'='.urlencode($filter['terms'][$i]['obr']);
|
||||
$filter['sql'] .= ' '.str_repeat( '(', $filter['terms'][$i]['obr'] ).' ';
|
||||
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[terms][$i][obr]\" value=\"".htmlspecialchars($filter['terms'][$i]['obr'])."\"/>\n";
|
||||
if ( isset($terms[$i]['obr']) ) {
|
||||
$filter['query'] .= $querySep.urlencode("filter[Query][terms][$i][obr]").'='.urlencode($terms[$i]['obr']);
|
||||
$filter['sql'] .= ' '.str_repeat( '(', $terms[$i]['obr'] ).' ';
|
||||
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[Query][terms][$i][obr]\" value=\"".htmlspecialchars($terms[$i]['obr'])."\"/>\n";
|
||||
}
|
||||
if ( isset($filter['terms'][$i]['attr']) ) {
|
||||
$filter['query'] .= $querySep.urlencode("filter[terms][$i][attr]").'='.urlencode($filter['terms'][$i]['attr']);
|
||||
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[terms][$i][attr]\" value=\"".htmlspecialchars($filter['terms'][$i]['attr'])."\"/>\n";
|
||||
switch ( $filter['terms'][$i]['attr'] ) {
|
||||
if ( isset($terms[$i]['attr']) ) {
|
||||
$filter['query'] .= $querySep.urlencode("filter[Query][terms][$i][attr]").'='.urlencode($terms[$i]['attr']);
|
||||
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[Query][terms][$i][attr]\" value=\"".htmlspecialchars($terms[$i]['attr'])."\"/>\n";
|
||||
switch ( $terms[$i]['attr'] ) {
|
||||
case 'MonitorName':
|
||||
$filter['sql'] .= 'M.'.preg_replace( '/^Monitor/', '', $filter['terms'][$i]['attr'] );
|
||||
$filter['sql'] .= 'M.'.preg_replace( '/^Monitor/', '', $terms[$i]['attr'] );
|
||||
break;
|
||||
case 'ServerId':
|
||||
$filter['sql'] .= 'M.ServerId';
|
||||
|
@ -1194,14 +1196,14 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&' ) {
|
|||
case 'Notes':
|
||||
case 'StateId':
|
||||
case 'Archived':
|
||||
$filter['sql'] .= 'E.'.$filter['terms'][$i]['attr'];
|
||||
$filter['sql'] .= 'E.'.$terms[$i]['attr'];
|
||||
break;
|
||||
case 'DiskPercent':
|
||||
// Need to specify a storage area, so need to look through other terms looking for a storage area, else we default to ZM_EVENTS_PATH
|
||||
if ( ! $StorageArea ) {
|
||||
for ( $j = 0; $j < count($filter['terms']); $j++ ) {
|
||||
if ( isset($filter['terms'][$j]['attr']) and $filter['terms'][$j]['attr'] == 'StorageId' ) {
|
||||
$StorageArea = new Storage( $filter['terms'][$j]['val'] );
|
||||
for ( $j = 0; $j < count($terms); $j++ ) {
|
||||
if ( isset($terms[$j]['attr']) and $terms[$j]['attr'] == 'StorageId' ) {
|
||||
$StorageArea = new Storage( $terms[$j]['val'] );
|
||||
}
|
||||
} // end foreach remaining term
|
||||
if ( ! $StorageArea ) $StorageArea = new Storage();
|
||||
|
@ -1212,9 +1214,9 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&' ) {
|
|||
case 'DiskBlocks':
|
||||
// Need to specify a storage area, so need to look through other terms looking for a storage area, else we default to ZM_EVENTS_PATH
|
||||
if ( ! $StorageArea ) {
|
||||
for ( $j = $i; $j < count($filter['terms']); $j++ ) {
|
||||
if ( isset($filter['terms'][$i]['attr']) and $filter['terms'][$i]['attr'] == 'StorageId' ) {
|
||||
$StorageArea = new Storage( $filter['terms'][$i]['val'] );
|
||||
for ( $j = $i; $j < count($terms); $j++ ) {
|
||||
if ( isset($terms[$i]['attr']) and $terms[$i]['attr'] == 'StorageId' ) {
|
||||
$StorageArea = new Storage( $terms[$i]['val'] );
|
||||
}
|
||||
} // end foreach remaining term
|
||||
} // end no StorageArea found yet
|
||||
|
@ -1225,8 +1227,8 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&' ) {
|
|||
break;
|
||||
}
|
||||
$valueList = array();
|
||||
foreach ( preg_split( '/["\'\s]*?,["\'\s]*?/', preg_replace( '/^["\']+?(.+)["\']+?$/', '$1', $filter['terms'][$i]['val'] ) ) as $value ) {
|
||||
switch ( $filter['terms'][$i]['attr'] ) {
|
||||
foreach ( preg_split( '/["\'\s]*?,["\'\s]*?/', preg_replace( '/^["\']+?(.+)["\']+?$/', '$1', $terms[$i]['val'] ) ) as $value ) {
|
||||
switch ( $terms[$i]['attr'] ) {
|
||||
case 'MonitorName':
|
||||
case 'Name':
|
||||
case 'Cause':
|
||||
|
@ -1260,14 +1262,14 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&' ) {
|
|||
$valueList[] = $value;
|
||||
}
|
||||
|
||||
switch ( $filter['terms'][$i]['op'] ) {
|
||||
switch ( $terms[$i]['op'] ) {
|
||||
case '=' :
|
||||
case '!=' :
|
||||
case '>=' :
|
||||
case '>' :
|
||||
case '<' :
|
||||
case '<=' :
|
||||
$filter['sql'] .= ' '.$filter['terms'][$i]['op'].' '. $value;
|
||||
$filter['sql'] .= ' '.$terms[$i]['op'].' '. $value;
|
||||
break;
|
||||
case '=~' :
|
||||
$filter['sql'] .= ' regexp '.$value;
|
||||
|
@ -1283,15 +1285,15 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&' ) {
|
|||
break;
|
||||
}
|
||||
|
||||
$filter['query'] .= $querySep.urlencode("filter[terms][$i][op]").'='.urlencode($filter['terms'][$i]['op']);
|
||||
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[terms][$i][op]\" value=\"".htmlspecialchars($filter['terms'][$i]['op'])."\"/>\n";
|
||||
$filter['query'] .= $querySep.urlencode("filter[terms][$i][val]").'='.urlencode($filter['terms'][$i]['val']);
|
||||
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[terms][$i][val]\" value=\"".htmlspecialchars($filter['terms'][$i]['val'])."\"/>\n";
|
||||
$filter['query'] .= $querySep.urlencode("filter[Query][terms][$i][op]").'='.urlencode($terms[$i]['op']);
|
||||
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[Query][terms][$i][op]\" value=\"".htmlspecialchars($terms[$i]['op'])."\"/>\n";
|
||||
$filter['query'] .= $querySep.urlencode("filter[Query][terms][$i][val]").'='.urlencode($terms[$i]['val']);
|
||||
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[Query][terms][$i][val]\" value=\"".htmlspecialchars($terms[$i]['val'])."\"/>\n";
|
||||
}
|
||||
if ( isset($filter['terms'][$i]['cbr']) ) {
|
||||
$filter['query'] .= $querySep.urlencode("filter[terms][$i][cbr]").'='.urlencode($filter['terms'][$i]['cbr']);
|
||||
$filter['sql'] .= ' '.str_repeat( ')', $filter['terms'][$i]['cbr'] ).' ';
|
||||
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[terms][$i][cbr]\" value=\"".htmlspecialchars($filter['terms'][$i]['cbr'])."\"/>\n";
|
||||
if ( isset($terms[$i]['cbr']) ) {
|
||||
$filter['query'] .= $querySep.urlencode("filter[Query][terms][$i][cbr]").'='.urlencode($terms[$i]['cbr']);
|
||||
$filter['sql'] .= ' '.str_repeat( ')', $terms[$i]['cbr'] ).' ';
|
||||
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[Query][terms][$i][cbr]\" value=\"".htmlspecialchars($terms[$i]['cbr'])."\"/>\n";
|
||||
}
|
||||
}
|
||||
if ( $filter['sql'] )
|
||||
|
|
|
@ -28,7 +28,7 @@ if ( $debug ) {
|
|||
}
|
||||
|
||||
// Use new style autoglobals where possible
|
||||
if ( version_compare( phpversion(), "4.1.0", "<") ) {
|
||||
if ( version_compare( phpversion(), '4.1.0', '<') ) {
|
||||
$_SESSION = &$HTTP_SESSION_VARS;
|
||||
$_SERVER = &$HTTP_SERVER_VARS;
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ if ( version_compare( phpversion(), "4.1.0", "<") ) {
|
|||
if ( false ) {
|
||||
ob_start();
|
||||
phpinfo( INFO_VARIABLES );
|
||||
$fp = fopen( "/tmp/env.html", "w" );
|
||||
$fp = fopen( '/tmp/env.html', 'w' );
|
||||
fwrite( $fp, ob_get_contents() );
|
||||
fclose( $fp );
|
||||
ob_end_clean();
|
||||
|
@ -114,10 +114,10 @@ $skinBase[] = $skin;
|
|||
$currentCookieParams = session_get_cookie_params();
|
||||
Logger::Debug('Setting cookie parameters to lifetime('.$currentCookieParams['lifetime'].') path('.$currentCookieParams['path'].') domain ('.$currentCookieParams['domain'].') secure('.$currentCookieParams['secure'].') httpOnly(1)');
|
||||
session_set_cookie_params(
|
||||
$currentCookieParams["lifetime"],
|
||||
$currentCookieParams["path"],
|
||||
$currentCookieParams["domain"],
|
||||
$currentCookieParams["secure"],
|
||||
$currentCookieParams['lifetime'],
|
||||
$currentCookieParams['path'],
|
||||
$currentCookieParams['domain'],
|
||||
$currentCookieParams['secure'],
|
||||
true
|
||||
);
|
||||
|
||||
|
@ -205,7 +205,7 @@ require_once( 'includes/actions.php' );
|
|||
|
||||
# If I put this here, it protects all views and popups, but it has to go after actions.php because actions.php does the actual logging in.
|
||||
if ( ZM_OPT_USE_AUTH && ! isset($user) ) {
|
||||
Logger::Debug("Redirecting to login" );
|
||||
Logger::Debug("Redirecting to login" );
|
||||
$view = 'login';
|
||||
$request = null;
|
||||
}
|
||||
|
|
|
@ -38,8 +38,8 @@ var popupSizes = {
|
|||
'events': { 'width': 960, 'height': 780 },
|
||||
'export': { 'width': 400, 'height': 340 },
|
||||
'filter': { 'width': 820, 'height': 700 },
|
||||
'frame': { 'addWidth': 32, 'minWidth': 384, 'addHeight': 100 },
|
||||
'frames': { 'width': 600, 'height': 600 },
|
||||
'frame': { 'addWidth': 32, 'minWidth': 384, 'addHeight': 200 },
|
||||
'frames': { 'width': 600, 'height': 700 },
|
||||
'function': { 'width': 300, 'height': 92 },
|
||||
'group': { 'width': 360, 'height': 180 },
|
||||
'groups': { 'width': 440, 'height': 220 },
|
||||
|
|
|
@ -38,8 +38,8 @@ var popupSizes = {
|
|||
'events': { 'width': 960, 'height': 780 },
|
||||
'export': { 'width': 400, 'height': 340 },
|
||||
'filter': { 'width': 900, 'height': 700 },
|
||||
'frame': { 'addWidth': 32, 'minWidth': 384, 'addHeight': 100 },
|
||||
'frames': { 'width': 600, 'height': 600 },
|
||||
'frame': { 'addWidth': 32, 'minWidth': 384, 'addHeight': 200 },
|
||||
'frames': { 'width': 600, 'height': 700 },
|
||||
'function': { 'width': 300, 'height': 160 },
|
||||
'group': { 'width': 360, 'height': 300 },
|
||||
'groups': { 'width': 540, 'height': 420 },
|
||||
|
|
|
@ -38,7 +38,7 @@ var popupSizes = {
|
|||
'events': { 'width': 1220, 'height': 780 },
|
||||
'export': { 'width': 400, 'height': 340 },
|
||||
'filter': { 'width': 900, 'height': 700 },
|
||||
'frame': { 'addWidth': 32, 'minWidth': 384, 'addHeight': 100 },
|
||||
'frame': { 'addWidth': 32, 'minWidth': 384, 'addHeight': 200 },
|
||||
'frames': { 'width': 600, 'height': 600 },
|
||||
'function': { 'width': 300, 'height': 160 },
|
||||
'group': { 'width': 360, 'height': 300 },
|
||||
|
|
|
@ -253,8 +253,11 @@ if ( refreshParent ) {
|
|||
if ( focusWindow ) {
|
||||
windowToFront();
|
||||
}
|
||||
if ( closePopup ) {
|
||||
closeWindow();
|
||||
}
|
||||
|
||||
window.addEvent( 'domready', checkSize);
|
||||
window.addEvent( 'domready', checkSize );
|
||||
|
||||
function convertLabelFormat(LabelFormat, monitorName){
|
||||
//convert label format from strftime to moment's format (modified from
|
||||
|
|
|
@ -49,6 +49,13 @@ if ( ! empty($refreshParent) ) {
|
|||
echo 'false';
|
||||
}
|
||||
?>;
|
||||
var closePopup = <?php
|
||||
if ( ( ! empty($closePopup) ) and ( $closePopup == true ) ) {
|
||||
echo 'true';
|
||||
} else {
|
||||
echo 'false';
|
||||
}
|
||||
?>;
|
||||
|
||||
var focusWindow = <?php echo !empty($focusWindow)?'true':'false' ?>;
|
||||
|
||||
|
|
|
@ -29,7 +29,8 @@ $eventCounts = array(
|
|||
array(
|
||||
'title' => translate('Events'),
|
||||
'filter' => array(
|
||||
'terms' => array(
|
||||
'Query' => array (
|
||||
'terms' => array()
|
||||
)
|
||||
),
|
||||
'total' => 0,
|
||||
|
@ -37,48 +38,58 @@ $eventCounts = array(
|
|||
array(
|
||||
'title' => translate('Hour'),
|
||||
'filter' => array(
|
||||
'Query' => array(
|
||||
'terms' => array(
|
||||
array( 'attr' => 'DateTime', 'op' => '>=', 'val' => '-1 hour' ),
|
||||
array( 'attr' => 'DateTime', 'op' => '>=', 'val' => '-1 hour' ),
|
||||
)
|
||||
)
|
||||
),
|
||||
),
|
||||
'total' => 0,
|
||||
),
|
||||
array(
|
||||
'title' => translate('Day'),
|
||||
'filter' => array(
|
||||
'Query' => array(
|
||||
'terms' => array(
|
||||
array( 'attr' => "DateTime", 'op' => '>=', 'val' => '-1 day' ),
|
||||
array( 'attr' => "DateTime", 'op' => '>=', 'val' => '-1 day' ),
|
||||
)
|
||||
)
|
||||
),
|
||||
),
|
||||
'total' => 0,
|
||||
),
|
||||
array(
|
||||
'title' => translate('Week'),
|
||||
'filter' => array(
|
||||
'Query' => array(
|
||||
'terms' => array(
|
||||
array( 'attr' => "DateTime", 'op' => '>=', 'val' => '-7 day' ),
|
||||
array( 'attr' => "DateTime", 'op' => '>=', 'val' => '-7 day' ),
|
||||
)
|
||||
)
|
||||
),
|
||||
),
|
||||
'total' => 0,
|
||||
),
|
||||
array(
|
||||
'title' => translate('Month'),
|
||||
'filter' => array(
|
||||
'Query' => array(
|
||||
'terms' => array(
|
||||
array( 'attr' => "DateTime", 'op' => '>=', 'val' => '-1 month' ),
|
||||
array( 'attr' => "DateTime", 'op' => '>=', 'val' => '-1 month' ),
|
||||
)
|
||||
)
|
||||
),
|
||||
),
|
||||
'total' => 0,
|
||||
),
|
||||
array(
|
||||
'title' => translate('Archived'),
|
||||
'filter' => array(
|
||||
'Query' => array(
|
||||
'terms' => array(
|
||||
array( 'attr' => "Archived", 'op' => '=', 'val' => '1' ),
|
||||
array( 'attr' => "Archived", 'op' => '=', 'val' => '1' ),
|
||||
)
|
||||
)
|
||||
),
|
||||
),
|
||||
'total' => 0,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$displayMonitors = NULL;
|
||||
|
@ -94,7 +105,7 @@ for( $i = 0; $i < count($displayMonitors); $i += 1 ) {
|
|||
$monitor['ZoneCount'] = dbFetchOne( 'select count(Id) as ZoneCount from Zones where MonitorId = ?', 'ZoneCount', array($monitor['Id']) );
|
||||
$counts = array();
|
||||
for ( $j = 0; $j < count($eventCounts); $j += 1 ) {
|
||||
$filter = addFilterTerm( $eventCounts[$j]['filter'], count($eventCounts[$j]['filter']['terms']), array( 'cnj' => 'and', 'attr' => 'MonitorId', 'op' => '=', 'val' => $monitor['Id'] ) );
|
||||
$filter = addFilterTerm( $eventCounts[$j]['filter'], count($eventCounts[$j]['filter']['Query']['terms']), array( 'cnj' => 'and', 'attr' => 'MonitorId', 'op' => '=', 'val' => $monitor['Id'] ) );
|
||||
parseFilter( $filter );
|
||||
$counts[] = "count(if(1".$filter['sql'].",1,NULL)) as EventCount$j";
|
||||
$monitor['eventCounts'][$j]['filter'] = $filter;
|
||||
|
|
|
@ -155,7 +155,7 @@ if ( $Event->DefaultVideo() ) {
|
|||
?>
|
||||
<div id="videoFeed">
|
||||
<video id="videoobj" class="video-js vjs-default-skin" width="<?php echo reScale( $Event->Width(), $scale ) ?>" height="<?php echo reScale( $Event->Height(), $scale ) ?>" data-setup='{ "controls": true, "playbackRates": [0.5, 1, 1.5, 2, 4, 8, 16, 32, 64, 128, 256], "autoplay": true, "preload": "auto", "plugins": { "zoomrotate": { "zoom": "<?php echo $Zoom ?>"}}}'>
|
||||
<source src="<?php echo $Event->getStreamSrc( array( "mode=mpeg&format=h264" ) ); ?>" type="video/mp4">
|
||||
<source src="<?php echo $Event->getStreamSrc( array( 'mode'=>'mpeg','format'=>'h264' ) ); ?>" type="video/mp4">
|
||||
Your browser does not support the video tag.
|
||||
</video>
|
||||
</div>
|
||||
|
@ -170,7 +170,8 @@ if ( $Event->DefaultVideo() ) {
|
|||
<?php
|
||||
} // end if DefaultVideo
|
||||
?>
|
||||
<div id="imageFeed" <?php if ( $Event->DefaultVideo() ) { ?>class="hidden"<?php } ?> >
|
||||
</div><!--eventVideo-->
|
||||
<div id="imageFeed"<?php if ( $Event->DefaultVideo() ) { ?> class="hidden"<?php } ?>>
|
||||
<?php
|
||||
if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT ) {
|
||||
$streamSrc = $Event->getStreamSrc( array( 'mode'=>'mpeg', 'scale'=>$scale, 'rate'=>$rate, 'bitrate'=>ZM_WEB_VIDEO_BITRATE, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'format'=>ZM_MPEG_REPLAY_FORMAT, 'replay'=>$replayMode ) );
|
||||
|
@ -184,7 +185,6 @@ if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT ) {
|
|||
}
|
||||
} // end if stream method
|
||||
?>
|
||||
</div>
|
||||
<p id="dvrControls">
|
||||
<input type="button" value="<+" id="prevBtn" title="<?php echo translate('Prev') ?>" class="inactive" onclick="streamPrev( true );"/>
|
||||
<input type="button" value="<<" id="fastRevBtn" title="<?php echo translate('Rewind') ?>" class="inactive" disabled="disabled" onclick="streamFastRev( true );"/>
|
||||
|
@ -206,8 +206,8 @@ if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT ) {
|
|||
<?php for ( $i = 0; $i < $panelSections; $i++ ) { ?>
|
||||
<div class="progressBox" id="progressBox<?php echo $i ?>" title=""></div>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
</div><!--progressBar-->
|
||||
</div><!--imageFeed-->
|
||||
</div>
|
||||
<?php
|
||||
if ( $Event->SaveJPEGs() & 3 ) { // frames or analysis
|
||||
|
|
|
@ -18,50 +18,43 @@
|
|||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
//
|
||||
|
||||
if ( !canEdit( 'Events' ) )
|
||||
{
|
||||
$view = "error";
|
||||
return;
|
||||
if ( !canEdit( 'Events' ) ) {
|
||||
$view = 'error';
|
||||
return;
|
||||
}
|
||||
if ( isset($_REQUEST['eid']) ) {
|
||||
$mode = 'single';
|
||||
$eid = validInt($_REQUEST['eid']);
|
||||
$newEvent = dbFetchOne( 'SELECT E.* FROM Events AS E WHERE E.Id = ?', NULL, array($eid) );
|
||||
$mode = 'single';
|
||||
$eid = validInt($_REQUEST['eid']);
|
||||
$newEvent = dbFetchOne( 'SELECT E.* FROM Events AS E WHERE E.Id = ?', NULL, array($eid) );
|
||||
} elseif ( isset($_REQUEST['eids']) ) {
|
||||
$mode = 'multi';
|
||||
$sql = 'SELECT E.* FROM Events AS E WHERE ';
|
||||
$sqlWhere = array();
|
||||
$sqlValues = array();
|
||||
foreach ( $_REQUEST['eids'] as $eid ) {
|
||||
$sqlWhere[] = 'E.Id = ?';
|
||||
$sqlValues[] = $eid;
|
||||
$mode = 'multi';
|
||||
$sql = 'SELECT E.* FROM Events AS E WHERE ';
|
||||
$sqlWhere = array();
|
||||
$sqlValues = array();
|
||||
foreach ( $_REQUEST['eids'] as $eid ) {
|
||||
$sqlWhere[] = 'E.Id = ?';
|
||||
$sqlValues[] = $eid;
|
||||
}
|
||||
unset( $eid );
|
||||
$sql .= join( " or ", $sqlWhere );
|
||||
foreach( dbFetchAll( $sql, NULL, $sqlValues ) as $row ) {
|
||||
if ( !isset($newEvent) ) {
|
||||
$newEvent = $row;
|
||||
} else {
|
||||
if ( $newEvent['Cause'] && $newEvent['Cause'] != $row['Cause'] )
|
||||
$newEvent['Cause'] = '';
|
||||
if ( $newEvent['Notes'] && $newEvent['Notes'] != $row['Notes'] )
|
||||
$newEvent['Notes'] = '';
|
||||
}
|
||||
unset( $eid );
|
||||
$sql .= join( " or ", $sqlWhere );
|
||||
foreach( dbFetchAll( $sql, NULL, $sqlValues ) as $row )
|
||||
{
|
||||
if ( !isset($newEvent) )
|
||||
{
|
||||
$newEvent = $row;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( $newEvent['Cause'] && $newEvent['Cause'] != $row['Cause'] )
|
||||
$newEvent['Cause'] = "";
|
||||
if ( $newEvent['Notes'] && $newEvent['Notes'] != $row['Notes'] )
|
||||
$newEvent['Notes'] = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$mode = '';
|
||||
}
|
||||
} else {
|
||||
$mode = '';
|
||||
}
|
||||
|
||||
$focusWindow = true;
|
||||
|
||||
if ( $mode == 'single' )
|
||||
xhtmlHeaders(__FILE__, translate('Event')." - ".$eid );
|
||||
xhtmlHeaders(__FILE__, translate('Event').' - '.$eid );
|
||||
else
|
||||
xhtmlHeaders(__FILE__, translate('Events') );
|
||||
?>
|
||||
|
@ -69,14 +62,11 @@ else
|
|||
<div id="page">
|
||||
<div id="header">
|
||||
<?php
|
||||
if ( $mode == 'single' )
|
||||
{
|
||||
if ( $mode == 'single' ) {
|
||||
?>
|
||||
<h2><?php echo translate('Event') ?> <?php echo $eid ?></h2>
|
||||
<?php
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
?>
|
||||
<h2><?php echo translate('Events') ?></h2>
|
||||
<?php
|
||||
|
@ -87,22 +77,18 @@ else
|
|||
<form name="contentForm" id="contentForm" method="post" action="<?php echo $_SERVER['PHP_SELF'] ?>">
|
||||
<input type="hidden" name="view" value="none"/>
|
||||
<?php
|
||||
if ( $mode == 'single' )
|
||||
{
|
||||
if ( $mode == 'single' ) {
|
||||
?>
|
||||
<input type="hidden" name="view" value="<?php echo $view ?>"/>
|
||||
<input type="hidden" name="action" value="eventdetail"/>
|
||||
<input type="hidden" name="eid" value="<?php echo $eid ?>"/>
|
||||
<?php
|
||||
}
|
||||
elseif ( $mode = 'multi' )
|
||||
{
|
||||
} elseif ( $mode = 'multi' ) {
|
||||
?>
|
||||
<input type="hidden" name="view" value="none"/>
|
||||
<input type="hidden" name="action" value="eventdetail"/>
|
||||
<?php
|
||||
foreach ( $_REQUEST['eids'] as $eid )
|
||||
{
|
||||
foreach ( $_REQUEST['eids'] as $eid ) {
|
||||
?>
|
||||
<input type="hidden" name="markEids[]" value="<?php echo validHtmlStr($eid) ?>"/>
|
||||
<?php
|
||||
|
@ -122,7 +108,8 @@ elseif ( $mode = 'multi' )
|
|||
</tbody>
|
||||
</table>
|
||||
<div id="contentButtons">
|
||||
<input type="submit" value="<?php echo translate('Save') ?>"<?php if ( !canEdit( 'Events' ) ) { ?> disabled="disabled"<?php } ?>/><input type="button" value="<?php echo translate('Cancel') ?>" onclick="closeWindow()"/>
|
||||
<input type="submit" value="<?php echo translate('Save') ?>"<?php if ( !canEdit( 'Events' ) ) { ?> disabled="disabled"<?php } ?>/>
|
||||
<input type="button" value="<?php echo translate('Cancel') ?>" onclick="closeWindow()"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -214,7 +214,7 @@ foreach ( $events as $event ) {
|
|||
<td class="colThumbnail">
|
||||
<?php
|
||||
$imgSrc = '?view=image&eid='.$event->Id().'&fid='.$thumbData['FrameId'].'&width='.$thumbData['Width'].'&height='.$thumbData['Height'];
|
||||
$streamSrc = getStreamSrc( array( "source=event", "mode=jpeg", "event=".$event->Id(), "scale=".$scale, "maxfps=".ZM_WEB_VIDEO_MAXFPS, "replay=single") );
|
||||
$streamSrc = $event->getStreamSrc( array( 'mode'=>'jpeg', 'scale'=>$scale, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'replay'=>'single') );
|
||||
|
||||
$imgHtml = '<img id="thumbnail'.$event->id().'" src="'.$imgSrc.'" alt="'. validHtmlStr('Event '.$event->Id()) .'" style="width:'. validInt($thumbData['Width']) .'px;height:'. validInt( $thumbData['Height'] ).'px;" onmouseover="this.src=\''.$streamSrc.'\';" onmouseout="this.src=\''.$imgSrc.'\';"/>';
|
||||
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
//
|
||||
|
||||
if ( !canView( 'Events' ) ) {
|
||||
$view = 'error';
|
||||
return;
|
||||
$view = 'error';
|
||||
return;
|
||||
}
|
||||
require_once( 'includes/Frame.php' );
|
||||
$Event = new Event( $_REQUEST['eid'] );
|
||||
|
@ -61,10 +61,10 @@ xhtmlHeaders(__FILE__, translate('Frames')." - ".$Event->Id() );
|
|||
<tbody>
|
||||
<?php
|
||||
if ( count($frames) ) {
|
||||
foreach ( $frames as $frame ) {
|
||||
$Frame = new Frame( $frame );
|
||||
foreach ( $frames as $frame ) {
|
||||
$Frame = new Frame( $frame );
|
||||
|
||||
$class = strtolower($frame['Type']);
|
||||
$class = strtolower($frame['Type']);
|
||||
?>
|
||||
<tr class="<?php echo $class ?>">
|
||||
<td class="colId"><?php echo makePopupLink( '?view=frame&eid='.$Event->Id().'&fid='.$frame['FrameId'], 'zmImage', array( 'frame', $Event->Width(), $Event->Height() ), $frame['FrameId'] ) ?></td>
|
||||
|
@ -72,16 +72,16 @@ if ( count($frames) ) {
|
|||
<td class="colTimeStamp"><?php echo strftime( STRF_FMT_TIME, $frame['UnixTimeStamp'] ) ?></td>
|
||||
<td class="colTimeDelta"><?php echo number_format( $frame['Delta'], 2 ) ?></td>
|
||||
<?php
|
||||
if ( ZM_RECORD_EVENT_STATS && ($frame['Type'] == 'Alarm') ) {
|
||||
if ( ZM_RECORD_EVENT_STATS && ($frame['Type'] == 'Alarm') ) {
|
||||
?>
|
||||
<td class="colScore"><?php echo makePopupLink( '?view=stats&eid='.$Event->Id().'&fid='.$frame['FrameId'], 'zmStats', 'stats', $frame['Score'] ) ?></td>
|
||||
<?php
|
||||
} else {
|
||||
} else {
|
||||
?>
|
||||
<td class="colScore"><?php echo $frame['Score'] ?></td>
|
||||
<?php
|
||||
}
|
||||
if ( ZM_WEB_LIST_THUMBS ) {
|
||||
}
|
||||
if ( ZM_WEB_LIST_THUMBS ) {
|
||||
?>
|
||||
<td class="colThumbnail"><?php echo makePopupLink( '?view=frame&eid='.$Event->Id().'&fid='.$frame['FrameId'], 'zmImage', array( 'image', $Event->Width(), $Event->Height() ), '<img src="?view=image&fid='.$Frame->Id().'&'.
|
||||
(ZM_WEB_LIST_THUMB_WIDTH?'width='.ZM_WEB_LIST_THUMB_WIDTH.'&':'').
|
||||
|
@ -89,11 +89,11 @@ if ( count($frames) ) {
|
|||
(ZM_WEB_LIST_THUMB_WIDTH?'width="'.ZM_WEB_LIST_THUMB_WIDTH.'" ':'').
|
||||
(ZM_WEB_LIST_THUMB_HEIGHT?'height="'.ZM_WEB_LIST_THUMB_HEIGHT.'" ':'').' alt="'.$frame['FrameId'].'"/>' ) ?></td>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
?>
|
||||
</tr>
|
||||
<?php
|
||||
} // end foreach frame
|
||||
} // end foreach frame
|
||||
} else {
|
||||
?>
|
||||
<tr>
|
||||
|
|
|
@ -11,7 +11,7 @@ var logCodes = new Object({
|
|||
'-4': 'PNC',
|
||||
});
|
||||
|
||||
var minSampleTime = 1000;
|
||||
var minSampleTime = 2000;
|
||||
var maxSampleTime = 16000;
|
||||
var minLogTime = 0;
|
||||
var maxLogTime = 0;
|
||||
|
@ -56,11 +56,12 @@ function logResponse( respObj ) {
|
|||
try {
|
||||
respObj.logs.each(
|
||||
function( log ) {
|
||||
if ( !maxLogTime || log.TimeKey > maxLogTime )
|
||||
if ( ( !maxLogTime ) || ( log.TimeKey > maxLogTime ) )
|
||||
maxLogTime = log.TimeKey;
|
||||
if ( !minLogTime || log.TimeKey < minLogTime )
|
||||
if ( ( !minLogTime ) || ( log.TimeKey < minLogTime ) )
|
||||
minLogTime = log.TimeKey;
|
||||
var row = logTable.push( [{ content: log.DateTime, properties: { style: 'white-space: nowrap' }}, log.Component, log.Server, log.Pid, log.Code, log.Message, log.File, log.Line] );
|
||||
|
||||
delete log.Message;
|
||||
row.tr.store( 'log', log );
|
||||
if ( log.Level <= -3 )
|
||||
|
@ -106,8 +107,8 @@ function logResponse( respObj ) {
|
|||
logTimeout *= 2;
|
||||
if ( logTimeout > maxSampleTime )
|
||||
logTimeout = maxSampleTime;
|
||||
}
|
||||
}
|
||||
} // end logs.length > 0
|
||||
} // end if result == Ok
|
||||
logTimer = fetchNextLogs.delay( logTimeout );
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,720 @@
|
|||
function evaluateLoadTimes() {
|
||||
// Only consider it a completed event if we load ALL monitors, then zero all and start again
|
||||
var start=0;
|
||||
var end=0;
|
||||
if ( liveMode != 1 && currentSpeed == 0 ) return; // don't evaluate when we are not moving as we can do nothing really fast.
|
||||
for ( var i = 0; i < monitorIndex.length; i++ ) {
|
||||
if ( monitorName[i] > "" ) {
|
||||
if ( monitorLoadEndTimems[i] ==0 ) return; // if we have a monitor with no time yet just wait
|
||||
if ( start == 0 || start > monitorLoadStartTimems[i] ) start = monitorLoadStartTimems[i];
|
||||
if ( end == 0 || end < monitorLoadEndTimems[i] ) end = monitorLoadEndTimems[i];
|
||||
}
|
||||
}
|
||||
if ( start == 0 || end == 0 ) return; // we really should not get here
|
||||
for ( var i=0; i < numMonitors; i++ ) {
|
||||
var monId = monitorPtr[i];
|
||||
monitorLoadStartTimems[monId] = 0;
|
||||
monitorLoadEndTimems[monId] = 0;
|
||||
}
|
||||
freeTimeLastIntervals[imageLoadTimesEvaluated++] = 1 - ((end - start)/currentDisplayInterval);
|
||||
if( imageLoadTimesEvaluated < imageLoadTimesNeeded ) return;
|
||||
var avgFrac=0;
|
||||
for ( var i=0; i < imageLoadTimesEvaluated; i++ )
|
||||
avgFrac += freeTimeLastIntervals[i];
|
||||
avgFrac = avgFrac / imageLoadTimesEvaluated;
|
||||
// The larger this is(positive) the faster we can go
|
||||
if (avgFrac >= 0.9) currentDisplayInterval = (currentDisplayInterval * 0.50).toFixed(1); // we can go much faster
|
||||
else if (avgFrac >= 0.8) currentDisplayInterval = (currentDisplayInterval * 0.55).toFixed(1);
|
||||
else if (avgFrac >= 0.7) currentDisplayInterval = (currentDisplayInterval * 0.60).toFixed(1);
|
||||
else if (avgFrac >= 0.6) currentDisplayInterval = (currentDisplayInterval * 0.65).toFixed(1);
|
||||
else if (avgFrac >= 0.5) currentDisplayInterval = (currentDisplayInterval * 0.70).toFixed(1);
|
||||
else if (avgFrac >= 0.4) currentDisplayInterval = (currentDisplayInterval * 0.80).toFixed(1);
|
||||
else if (avgFrac >= 0.35) currentDisplayInterval = (currentDisplayInterval * 0.90).toFixed(1);
|
||||
else if (avgFrac >= 0.3) currentDisplayInterval = (currentDisplayInterval * 1.00).toFixed(1);
|
||||
else if (avgFrac >= 0.25) currentDisplayInterval = (currentDisplayInterval * 1.20).toFixed(1);
|
||||
else if (avgFrac >= 0.2) currentDisplayInterval = (currentDisplayInterval * 1.50).toFixed(1);
|
||||
else if (avgFrac >= 0.1) currentDisplayInterval = (currentDisplayInterval * 2.00).toFixed(1);
|
||||
else currentDisplayInterval = (currentDisplayInterval * 2.50).toFixed(1);
|
||||
currentDisplayInterval=Math.min(Math.max(currentDisplayInterval, 30),10000); // limit this from about 30fps to .1 fps
|
||||
imageLoadTimesEvaluated=0;
|
||||
setSpeed(speedIndex);
|
||||
$('fps').innerHTML="Display refresh rate is " + (1000 / currentDisplayInterval).toFixed(1) + " per second, avgFrac=" + avgFrac.toFixed(3) + ".";
|
||||
}
|
||||
|
||||
function SetImageSource( monId, val ) {
|
||||
if ( liveMode == 1 ) {
|
||||
return monitorImageObject[monId].src.replace(/rand=\d+/i, 'rand='+Math.floor((Math.random() * 1000000) ));
|
||||
|
||||
} else {
|
||||
for ( var i=0, eIdlength = eId.length; i < eIdlength; i++ ) {
|
||||
// Search for a match
|
||||
if ( eMonId[i] == monId && val >= eStartSecs[i] && val <= eEndSecs[i] ) {
|
||||
var frame = parseInt((val - eStartSecs[i])/(eEndSecs[i]-eStartSecs[i])*eventFrames[i])+1;
|
||||
return "index.php?view=image&eid=" + eId[i] + '&fid='+frame + "&width=" + monitorCanvasObj[monId].width + "&height=" + monitorCanvasObj[monId].height;
|
||||
}
|
||||
} // end for
|
||||
return "no data";
|
||||
}
|
||||
}
|
||||
|
||||
// callback when loading an image. Will load itself to the canvas, or draw no data
|
||||
function imagedone( obj, monId, success ) {
|
||||
if ( success ) {
|
||||
var canvasCtx = monitorCanvasCtx[monId];
|
||||
var canvasObj = monitorCanvasObj[monId];
|
||||
|
||||
canvasCtx.drawImage( monitorImageObject[monId], 0, 0, canvasObj.width, canvasObj.height );
|
||||
var iconSize=(Math.max(canvasObj.width, canvasObj.height) * 0.10);
|
||||
canvasCtx.font = "600 " + iconSize.toString() + "px Arial";
|
||||
canvasCtx.fillStyle = "white";
|
||||
canvasCtx.globalCompositeOperation = "difference";
|
||||
canvasCtx.fillText( "+", iconSize*0.2, iconSize*1.2 );
|
||||
canvasCtx.fillText( "-", canvasObj.width - iconSize*1.2, iconSize*1.2 );
|
||||
canvasCtx.globalCompositeOperation = "source-over";
|
||||
monitorLoadEndTimems[monId] = new Date().getTime(); // elapsed time to load
|
||||
evaluateLoadTimes();
|
||||
}
|
||||
monitorLoading[monId] = false;
|
||||
if ( ! success ) {
|
||||
// if we had a failrue queue up the no-data image
|
||||
//loadImage2Monitor(monId,"no data"); // leave the staged URL if there is one, just ignore it here.
|
||||
loadNoData( monId );
|
||||
} else {
|
||||
if ( monitorLoadingStageURL[monId] == "" ) {
|
||||
console.log("Not showing image for " + monId );
|
||||
// This means that there wasn't a loading image placeholder.
|
||||
// So we weren't actually loading an image... which seems weird.
|
||||
return;
|
||||
}
|
||||
//loadImage2Monitor(monId,monitorLoadingStageURL[monId] );
|
||||
//monitorLoadingStageURL[monId]="";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
function loadNoData( monId ) {
|
||||
if ( monId ) {
|
||||
var canvasCtx = monitorCanvasCtx[monId];
|
||||
var canvasObj = monitorCanvasObj[monId];
|
||||
canvasCtx.fillStyle="white";
|
||||
canvasCtx.fillRect(0, 0, canvasObj.width, canvasObj.height);
|
||||
var textSize=canvasObj.width * 0.15;
|
||||
var text="No Data";
|
||||
canvasCtx.font = "600 " + textSize.toString() + "px Arial";
|
||||
canvasCtx.fillStyle="black";
|
||||
var textWidth = canvasCtx.measureText(text).width;
|
||||
canvasCtx.fillText(text,canvasObj.width/2 - textWidth/2,canvasObj.height/2);
|
||||
} else {
|
||||
console.log("No monId in loadNoData");
|
||||
}
|
||||
}
|
||||
|
||||
// Either draws the
|
||||
function loadImage2Monitor( monId, url ) {
|
||||
if ( monitorLoading[monId] && monitorImageObject[monId].src != url ) {
|
||||
// never queue the same image twice (if it's loading it has to be defined, right?
|
||||
monitorLoadingStageURL[monId] = url; // we don't care if we are overriting, it means it didn't change fast enough
|
||||
} else {
|
||||
if ( monitorImageObject[monId].src == url ) return; // do nothing if it's the same
|
||||
if ( url == 'no data' ) {
|
||||
loadNoData( monId );
|
||||
} else {
|
||||
monitorLoading[monId] = true;
|
||||
monitorLoadStartTimems[monId] = new Date().getTime();
|
||||
monitorImageObject[monId].src = url; // starts a load but doesn't refresh yet, wait until ready
|
||||
}
|
||||
}
|
||||
}
|
||||
function timerFire() {
|
||||
// See if we need to reschedule
|
||||
if(currentDisplayInterval != timerInterval || currentSpeed == 0) {
|
||||
// zero just turn off interrupts
|
||||
clearInterval(timerObj);
|
||||
timerInterval=currentDisplayInterval;
|
||||
if(currentSpeed>0 || liveMode!=0) timerObj=setInterval(timerFire,timerInterval); // don't fire out of live mode if speed is zero
|
||||
}
|
||||
|
||||
if (liveMode) outputUpdate(currentTimeSecs); // In live mode we basically do nothing but redisplay
|
||||
else if (currentTimeSecs + playSecsperInterval >= maxTimeSecs) // beyond the end just stop
|
||||
{
|
||||
setSpeed(0);
|
||||
outputUpdate(currentTimeSecs);
|
||||
}
|
||||
else outputUpdate(currentTimeSecs + playSecsperInterval);
|
||||
return;
|
||||
}
|
||||
|
||||
function drawSliderOnGraph(val) {
|
||||
var sliderWidth=10;
|
||||
var sliderLineWidth=1;
|
||||
var sliderHeight=cHeight;
|
||||
|
||||
if(liveMode==1) {
|
||||
val=Math.floor( Date.now() / 1000);
|
||||
}
|
||||
// Set some sizes
|
||||
|
||||
var labelpx = Math.max( 6, Math.min( 20, parseInt(cHeight * timeLabelsFractOfRow / (numMonitors+1)) ) );
|
||||
var labbottom=parseInt(cHeight * 0.2 / (numMonitors+1)).toString() + "px"; // This is positioning same as row labels below, but from bottom so 1-position
|
||||
var labfont=labelpx + "px Georgia"; // set this like below row labels
|
||||
|
||||
if(numMonitors>0) {
|
||||
// if we have no data to display don't do the slider itself
|
||||
var sliderX=parseInt( (val - minTimeSecs) / rangeTimeSecs * cWidth - sliderWidth/2); // position left side of slider
|
||||
if(sliderX < 0) sliderX=0;
|
||||
if(sliderX+sliderWidth > cWidth) sliderX=cWidth-sliderWidth-1;
|
||||
|
||||
// If we have data already saved first restore it from LAST time
|
||||
|
||||
if(typeof underSlider !== 'undefined')
|
||||
{
|
||||
ctx.putImageData(underSlider,underSliderX, 0, 0, 0, sliderWidth, sliderHeight);
|
||||
underSlider=undefined;
|
||||
}
|
||||
if(liveMode==0) // we get rid of the slider if we switch to live (since it may not be in the "right" place)
|
||||
{
|
||||
// Now save where we are putting it THIS time
|
||||
underSlider=ctx.getImageData(sliderX, 0, sliderWidth, sliderHeight);
|
||||
// And add in the slider'
|
||||
ctx.lineWidth=sliderLineWidth;
|
||||
ctx.strokeStyle='black';
|
||||
// looks like strokes are on the outside (or could be) so shrink it by the line width so we replace all the pixels
|
||||
ctx.strokeRect(sliderX+sliderLineWidth,sliderLineWidth,sliderWidth - 2*sliderLineWidth, sliderHeight - 2*sliderLineWidth);
|
||||
underSliderX=sliderX;
|
||||
}
|
||||
var o = $('scruboutput');
|
||||
if(liveMode==1)
|
||||
{
|
||||
o.innerHTML="Live Feed @ " + (1000 / currentDisplayInterval).toFixed(1) + " fps";
|
||||
o.style.color="red";
|
||||
}
|
||||
else
|
||||
{
|
||||
o.innerHTML=secs2dbstr(val);
|
||||
o.style.color="blue";
|
||||
}
|
||||
o.style.position="absolute";
|
||||
o.style.bottom=labbottom;
|
||||
o.style.font=labfont;
|
||||
// try to get length and then when we get too close to the right switch to the left
|
||||
var len = o.offsetWidth;
|
||||
var x;
|
||||
if(sliderX > cWidth/2)
|
||||
x=sliderX - len - 10;
|
||||
else
|
||||
x=sliderX + 10;
|
||||
o.style.left=x.toString() + "px";
|
||||
}
|
||||
|
||||
// This displays (or not) the left/right limits depending on how close the slider is.
|
||||
// Because these change widths if the slider is too close, use the slider width as an estimate for the left/right label length (i.e. don't recalculate len from above)
|
||||
// If this starts to collide increase some of the extra space
|
||||
|
||||
var o = $('scrubleft');
|
||||
o.innerHTML=secs2dbstr(minTimeSecs);
|
||||
o.style.position="absolute";
|
||||
o.style.bottom=labbottom;
|
||||
o.style.font=labfont;
|
||||
o.style.left="5px";
|
||||
if(numMonitors==0) // we need a len calculation if we skipped the slider
|
||||
len = o.offsetWidth;
|
||||
// If the slider will overlay part of this suppress (this is the left side)
|
||||
if(len + 10 > sliderX || cWidth < len * 4 ) // that last check is for very narrow browsers
|
||||
o.style.display="none";
|
||||
else
|
||||
{
|
||||
o.style.display="inline";
|
||||
o.style.display="inline-flex"; // safari won't take this but will just ignore
|
||||
}
|
||||
|
||||
var o = $('scrubright');
|
||||
o.innerHTML=secs2dbstr(maxTimeSecs);
|
||||
o.style.position="absolute";
|
||||
o.style.bottom=labbottom;
|
||||
o.style.font=labfont;
|
||||
// If the slider will overlay part of this suppress (this is the right side)
|
||||
o.style.left=(cWidth - len - 15).toString() + "px";
|
||||
if(sliderX > cWidth - len - 20 || cWidth < len * 4 )
|
||||
o.style.display="none";
|
||||
else
|
||||
{
|
||||
o.style.display="inline";
|
||||
o.style.display="inline-flex";
|
||||
}
|
||||
}
|
||||
|
||||
function drawGraph()
|
||||
{
|
||||
var divWidth=$('timelinediv').clientWidth
|
||||
canvas.width = cWidth = divWidth; // Let it float and determine width (it should be sized a bit smaller percentage of window)
|
||||
canvas.height=cHeight = parseInt(window.innerHeight * 0.10);
|
||||
if(eId.length==0)
|
||||
{
|
||||
ctx.font="40px Georgia";
|
||||
ctx.fillStyle="Black";
|
||||
ctx.globalAlpha=1;
|
||||
var t="No data found in range - choose differently";
|
||||
var l=ctx.measureText(t).width;
|
||||
ctx.fillText(t,(cWidth - l)/2, cHeight-10);
|
||||
underSlider=undefined;
|
||||
return;
|
||||
}
|
||||
var rowHeight=parseInt(cHeight / (numMonitors + 1) ); // Leave room for a scale of some sort
|
||||
|
||||
// first fill in the bars for the events (not alarms)
|
||||
|
||||
for(var i=0; i<eId.length; i++) // Display all we loaded
|
||||
{
|
||||
var x1=parseInt( (eStartSecs[i] - minTimeSecs) / rangeTimeSecs * cWidth) ; // round low end down
|
||||
var x2=parseInt( (eEndSecs[i] - minTimeSecs) / rangeTimeSecs * cWidth + 0.5 ) ; // round high end up to be sure consecutive ones connect
|
||||
ctx.fillStyle=monitorColour[eMonId[i]];
|
||||
ctx.globalAlpha = 0.2; // light color for background
|
||||
ctx.clearRect(x1,monitorIndex[eMonId[i]]*rowHeight,x2-x1,rowHeight); // Erase any overlap so it doesn't look artificially darker
|
||||
ctx.fillRect (x1,monitorIndex[eMonId[i]]*rowHeight,x2-x1,rowHeight);
|
||||
}
|
||||
for(var i=0; (i<fScore.length) && (maxScore>0); i++) // Now put in scored frames (if any)
|
||||
{
|
||||
var x1=parseInt( (fTimeFromSecs[i] - minTimeSecs) / rangeTimeSecs * cWidth) ; // round low end down
|
||||
var x2=parseInt( (fTimeToSecs[i] - minTimeSecs) / rangeTimeSecs * cWidth + 0.5 ) ; // round up
|
||||
if(x2-x1 < 2) x2=x1+2; // So it is visible make them all at least this number of seconds wide
|
||||
ctx.fillStyle=monitorColour[fMonId[i]];
|
||||
ctx.globalAlpha = 0.4 + 0.6 * (1 - fScore[i]/maxScore); // Background is scaled but even lowest is twice as dark as the background
|
||||
ctx.fillRect(x1,monitorIndex[fMonId[i]]*rowHeight,x2-x1,rowHeight);
|
||||
}
|
||||
for(var i=0; i<numMonitors; i++) // Note that this may be a sparse array
|
||||
{
|
||||
ctx.font= parseInt(rowHeight * timeLabelsFractOfRow).toString() + "px Georgia";
|
||||
ctx.fillStyle="Black";
|
||||
ctx.globalAlpha=1;
|
||||
ctx.fillText(monitorName[monitorPtr[i]], 0, (i + 1 - (1 - timeLabelsFractOfRow)/2 ) * rowHeight ); // This should roughly center font in row
|
||||
}
|
||||
underSlider=undefined; // flag we don't have a slider cached
|
||||
drawSliderOnGraph(currentTimeSecs);
|
||||
return;
|
||||
}
|
||||
|
||||
function redrawScreen()
|
||||
{
|
||||
if(fitMode==0) // if we fit, then monitors were absolutely positioned already (or will be) otherwise release them to float
|
||||
{
|
||||
for(var i=0; i<numMonitors; i++)
|
||||
monitorCanvasObj[monitorPtr[i]].style.position="";
|
||||
$('monitors').setStyle('height',"auto");
|
||||
}
|
||||
if(liveMode==1) // if we are not in live view switch to history -- this has to come before fit in case we re-establish the timeline
|
||||
{
|
||||
$('SpeedDiv').style.display="none";
|
||||
$('timelinediv').style.display="none";
|
||||
$('live').innerHTML="History";
|
||||
$('zoomin').style.display="none";
|
||||
$('zoomout').style.display="none";
|
||||
$('panleft').style.display="none";
|
||||
$('panright').style.display="none";
|
||||
|
||||
}
|
||||
else // switch out of liveview mode
|
||||
{
|
||||
$('SpeedDiv').style.display="inline";
|
||||
$('SpeedDiv').style.display="inline-flex";
|
||||
$('timelinediv').style.display=null;
|
||||
$('live').innerHTML="Live";
|
||||
$('zoomin').style.display="inline";
|
||||
$('zoomin').style.display="inline-flex";
|
||||
$('zoomout').style.display="inline";
|
||||
$('zoomout').style.display="inline-flex";
|
||||
$('panleft').style.display="inline";
|
||||
$('panleft').style.display="inline-flex";
|
||||
$('panright').style.display="inline";
|
||||
$('panright').style.display="inline-flex";
|
||||
}
|
||||
|
||||
if(fitMode==1)
|
||||
{
|
||||
$('ScaleDiv').style.display="none";
|
||||
$('fit').innerHTML="Scale";
|
||||
var vh=window.innerHeight;
|
||||
var vw=window.innerWidth;
|
||||
var pos=$('monitors').getPosition();
|
||||
var mh=(vh - pos.y - $('fps').getSize().y);
|
||||
$('monitors').setStyle('height',mh.toString() + "px"); // leave a small gap at bottom
|
||||
if(maxfit2($('monitors').getSize().x,$('monitors').getSize().y) == 0) /// if we fail to fix we back out of fit mode -- ??? This may need some better handling
|
||||
fitMode=1-fitMode;
|
||||
}
|
||||
else // switch out of fit mode
|
||||
{
|
||||
$('ScaleDiv').style.display="inline";
|
||||
$('ScaleDiv').style.display="inline-flex";
|
||||
$('fit').innerHTML="Fit";
|
||||
setScale(currentScale);
|
||||
}
|
||||
drawGraph();
|
||||
outputUpdate(currentTimeSecs);
|
||||
timerFire(); // force a fire in case it's not timing
|
||||
}
|
||||
|
||||
|
||||
function outputUpdate(val)
|
||||
{
|
||||
drawSliderOnGraph(val);
|
||||
for(var i=0; i<numMonitors; i++)
|
||||
{
|
||||
loadImage2Monitor(monitorPtr[i],SetImageSource(monitorPtr[i],val));
|
||||
}
|
||||
var currentTimeMS = new Date(val*1000);
|
||||
currentTimeSecs=val;
|
||||
}
|
||||
|
||||
|
||||
/// Found this here: http://stackoverflow.com/questions/55677/how-do-i-get-the-coordinates-of-a-mouse-click-on-a-canvas-element
|
||||
function relMouseCoords(event){
|
||||
var totalOffsetX = 0;
|
||||
var totalOffsetY = 0;
|
||||
var canvasX = 0;
|
||||
var canvasY = 0;
|
||||
var currentElement = this;
|
||||
|
||||
do{
|
||||
totalOffsetX += currentElement.offsetLeft - currentElement.scrollLeft;
|
||||
totalOffsetY += currentElement.offsetTop - currentElement.scrollTop;
|
||||
}
|
||||
while(currentElement = currentElement.offsetParent)
|
||||
|
||||
canvasX = event.pageX - totalOffsetX;
|
||||
canvasY = event.pageY - totalOffsetY;
|
||||
|
||||
return {x:canvasX, y:canvasY}
|
||||
}
|
||||
HTMLCanvasElement.prototype.relMouseCoords = relMouseCoords;
|
||||
|
||||
// These are the functions for mouse movement in the timeline. Note that touch is treated as a mouse move with mouse down
|
||||
|
||||
var mouseisdown=false;
|
||||
function mdown(event) {mouseisdown=true; mmove(event);}
|
||||
function mup(event) {mouseisdown=false;}
|
||||
function mout(event) {mouseisdown=false;} // if we go outside treat it as release
|
||||
function tmove(event) {mouseisdown=true; mmove(event);}
|
||||
|
||||
function mmove(event) {
|
||||
if(mouseisdown) {
|
||||
// only do anything if the mouse is depressed while on the sheet
|
||||
var sec = minTimeSecs + rangeTimeSecs / event.target.width * event.target.relMouseCoords(event).x;
|
||||
outputUpdate(sec);
|
||||
}
|
||||
}
|
||||
|
||||
function secs2dbstr (s)
|
||||
{
|
||||
var st = (new Date(s * 1000)).format("%Y-%m-%d %H:%M:%S");
|
||||
return st;
|
||||
}
|
||||
|
||||
function setFit(value)
|
||||
{
|
||||
fitMode=value;
|
||||
redrawScreen();
|
||||
}
|
||||
|
||||
function showScale(newscale) // updates slider only
|
||||
{
|
||||
$('scaleslideroutput').innerHTML = parseFloat(newscale).toFixed(2).toString() + " x";
|
||||
return;
|
||||
}
|
||||
|
||||
function setScale(newscale) // makes actual change
|
||||
{
|
||||
showScale(newscale);
|
||||
for(var i=0; i<numMonitors; i++)
|
||||
{
|
||||
monitorCanvasObj[monitorPtr[i]].width=monitorWidth[monitorPtr[i]]*monitorNormalizeScale[monitorPtr[i]]*monitorZoomScale[monitorPtr[i]]*newscale;
|
||||
monitorCanvasObj[monitorPtr[i]].height=monitorHeight[monitorPtr[i]]*monitorNormalizeScale[monitorPtr[i]]*monitorZoomScale[monitorPtr[i]]*newscale;
|
||||
}
|
||||
currentScale=newscale;
|
||||
}
|
||||
|
||||
function showSpeed(val) // updates slider only
|
||||
{
|
||||
$('speedslideroutput').innerHTML = parseFloat(speeds[val]).toFixed(2).toString() + " x";
|
||||
}
|
||||
|
||||
function setSpeed(val) // Note parameter is the index not the speed
|
||||
{
|
||||
var t;
|
||||
if(liveMode==1) return; // we shouldn't actually get here but just in case
|
||||
currentSpeed=parseFloat(speeds[val]);
|
||||
speedIndex=val;
|
||||
playSecsperInterval = currentSpeed * currentDisplayInterval / 1000;
|
||||
showSpeed(val);
|
||||
if( timerInterval != currentDisplayInterval || currentSpeed == 0 ) timerFire(); // if the timer isn't firing we need to trigger it to update
|
||||
}
|
||||
|
||||
function setLive(value)
|
||||
{
|
||||
liveMode=value;
|
||||
redrawScreen();
|
||||
}
|
||||
|
||||
|
||||
//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
// The section below are to reload this program with new parameters
|
||||
|
||||
function clicknav(minSecs,maxSecs,arch,live) {// we use the current time if we can
|
||||
var now = new Date() / 1000;
|
||||
var minStr="";
|
||||
var maxStr="";
|
||||
var currentStr="";
|
||||
if ( minSecs > 0 ) {
|
||||
if(maxSecs > now)
|
||||
maxSecs = parseInt(now);
|
||||
maxStr="&maxTime=" + secs2dbstr(maxSecs);
|
||||
}
|
||||
if ( maxSecs > 0 )
|
||||
minStr="&minTime=" + secs2dbstr(minSecs);
|
||||
if ( maxSecs == 0 && minSecs == 0 ) {
|
||||
minStr="&minTime=01/01/1950 12:00:00";
|
||||
maxStr="&maxTime=12/31/2035 12:00:00";
|
||||
}
|
||||
var intervalStr="&displayinterval=" + currentDisplayInterval.toString();
|
||||
if ( minSecs && maxSecs ) {
|
||||
if ( currentTimeSecs > minSecs && currentTimeSecs < maxSecs ) // make sure time is in the new range
|
||||
currentStr="¤t=" + secs2dbstr(currentTimeSecs);
|
||||
}
|
||||
|
||||
var liveStr="&live=0";
|
||||
if ( live == 1 )
|
||||
liveStr="&live=1";
|
||||
|
||||
var fitStr="&fit=0";
|
||||
if ( fitMode == 1 )
|
||||
fitStr="&fit=1";
|
||||
|
||||
var zoomStr="";
|
||||
for ( var i=0; i < numMonitors; i++ )
|
||||
if ( monitorZoomScale[monitorPtr[i]] < 0.99 || monitorZoomScale[monitorPtr[i]] > 1.01 ) // allow for some up/down changes and just treat as 1 of almost 1
|
||||
zoomStr += "&z" + monitorPtr[i].toString() + "=" + monitorZoomScale[monitorPtr[i]].toFixed(2);
|
||||
|
||||
var uri = "?view=" + currentView + fitStr + groupStr + minStr + maxStr + currentStr + intervalStr + liveStr + zoomStr + "&scale=" + document.getElementById("scaleslider").value + "&speed=" + speeds[$j("#speedslider").value];
|
||||
window.location = uri;
|
||||
}
|
||||
|
||||
function lastHour() {
|
||||
var now = new Date() / 1000;
|
||||
clicknav(now - 3600 + 1, now,1,0);
|
||||
}
|
||||
function lastEight() {
|
||||
var now = new Date() / 1000;
|
||||
clicknav(now - 3600*8 + 1, now,1,0);
|
||||
}
|
||||
function zoomin() {
|
||||
rangeTimeSecs = parseInt(rangeTimeSecs / 2);
|
||||
minTimeSecs = parseInt(currentTimeSecs - rangeTimeSecs/2); // this is the slider current time, we center on that
|
||||
maxTimeSecs = parseInt(currentTimeSecs + rangeTimeSecs/2);
|
||||
clicknav(minTimeSecs,maxTimeSecs,1,0);
|
||||
}
|
||||
|
||||
function zoomout() {
|
||||
rangeTimeSecs = parseInt(rangeTimeSecs * 2);
|
||||
minTimeSecs = parseInt(currentTimeSecs - rangeTimeSecs/2); // this is the slider current time, we center on that
|
||||
maxTimeSecs = parseInt(currentTimeSecs + rangeTimeSecs/2);
|
||||
clicknav(minTimeSecs,maxTimeSecs,1,0);
|
||||
}
|
||||
function panleft() {
|
||||
minTimeSecs = parseInt(minTimeSecs - rangeTimeSecs/2);
|
||||
maxTimeSecs = minTimeSecs + rangeTimeSecs - 1;
|
||||
clicknav(minTimeSecs,maxTimeSecs,1,0);
|
||||
}
|
||||
function panright() {
|
||||
minTimeSecs = parseInt(minTimeSecs + rangeTimeSecs/2);
|
||||
maxTimeSecs = minTimeSecs + rangeTimeSecs - 1;
|
||||
clicknav(minTimeSecs,maxTimeSecs,1,0);
|
||||
}
|
||||
function allof() {
|
||||
clicknav(0,0,1,0);
|
||||
}
|
||||
function allnon() {
|
||||
clicknav(0,0,0,0);
|
||||
}
|
||||
/// >>>>>>>>>>>>>>>>> handles packing different size/aspect monitors on screen <<<<<<<<<<<<<<<<<<<<<<<<
|
||||
|
||||
function compSize(a, b) { // sort array by some size parameter - height seems to work best. A semi-greedy algorithm
|
||||
var a_value = monitorHeight[a] * monitorWidth[a] * monitorNormalizeScale[a] * monitorZoomScale[a] * monitorNormalizeScale[a] * monitorZoomScale[a];
|
||||
var b_value = monitorHeight[b] * monitorWidth[b] * monitorNormalizeScale[b] * monitorZoomScale[b] * monitorNormalizeScale[b] * monitorZoomScale[b];
|
||||
|
||||
if ( a_value > b_value ) return -1;
|
||||
else if ( a_value == b_value ) return 0;
|
||||
else return 1;
|
||||
}
|
||||
|
||||
|
||||
function maxfit2(divW, divH) {
|
||||
var bestFitX=[]; // how we arranged the so-far best match
|
||||
var bestFitX2=[];
|
||||
var bestFitY=[];
|
||||
var bestFitY2=[];
|
||||
var bestFitScale;
|
||||
|
||||
var minScale=0.05;
|
||||
var maxScale=5.00;
|
||||
var bestFitArea=0;
|
||||
|
||||
var borders=-1;
|
||||
|
||||
monitorPtr.sort(compSize);
|
||||
|
||||
while(1) {
|
||||
if( maxScale - minScale < 0.01 ) break;
|
||||
var thisScale = (maxScale + minScale) / 2;
|
||||
var allFit=1;
|
||||
var thisArea=0;
|
||||
var thisX=[]; // top left
|
||||
var thisY=[];
|
||||
var thisX2=[]; // bottom right
|
||||
var thisY2=[];
|
||||
|
||||
for ( var m = 0; m < numMonitors; m++ ) {
|
||||
// this loop places each monitor (if it can)
|
||||
var monId = monitorPtr[m];
|
||||
|
||||
function doesItFit(x,y,w,h,d) { // does block (w,h) fit at position (x,y) relative to edge and other nodes already done (0..d)
|
||||
if(x+w>=divW) return 0;
|
||||
if(y+h>=divH) return 0;
|
||||
for(var i=0; i<=d; i++)
|
||||
if( !( thisX[i]>x+w-1 || thisX2[i] < x || thisY[i] > y+h-1 || thisY2[i] < y ) ) return 0;
|
||||
return 1; // it's OK
|
||||
}
|
||||
|
||||
if ( borders <= 0 )
|
||||
borders=$("Monitor"+monId).getStyle("border").toInt() * 2; // assume fixed size border, and added to both sides and top/bottom
|
||||
// try fitting over first, then down. Each new one must land at either upper right or lower left corner of last (try in that order)
|
||||
// Pick the one with the smallest Y, then smallest X if Y equal
|
||||
var fitX = 999999999;
|
||||
var fitY = 999999999;
|
||||
for ( adjacent = 0; adjacent < m; adjacent ++ ) {
|
||||
// try top right of adjacent
|
||||
if ( doesItFit(thisX2[adjacent]+1, thisY[adjacent], monitorWidth[monId] * thisScale * monitorNormalizeScale[monId] * monitorZoomScale[monId] + borders, monitorHeight[monId] * thisScale * monitorNormalizeScale[monId] * monitorZoomScale[monId] + borders, m-1) == 1 ) {
|
||||
if ( thisY[adjacent]<fitY || ( thisY[adjacent] == fitY && thisX2[adjacent]+1 < fitX ) ) {
|
||||
fitX = thisX2[adjacent] + 1;
|
||||
fitY = thisY[adjacent];
|
||||
}
|
||||
}
|
||||
// try bottom left
|
||||
if ( doesItFit(thisX[adjacent], thisY2[adjacent]+1, monitorWidth[monId] * thisScale * monitorNormalizeScale[monId] * monitorZoomScale[monId] + borders, monitorHeight[monId] * thisScale * monitorNormalizeScale[monId] * monitorZoomScale[monId] + borders, m-1) == 1 ) {
|
||||
if ( thisY2[adjacent]+1 < fitY || ( thisY2[adjacent]+1 == fitY && thisX[adjacent] < fitX ) ) {
|
||||
fitX = thisX[adjacent];
|
||||
fitY = thisY2[adjacent] + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( m == 0 ) { // note for the very first one there were no adjacents so the above loop didn't run
|
||||
if ( doesItFit(0,0,monitorWidth[monId] * thisScale * monitorNormalizeScale[monId] * monitorZoomScale[monId] + borders, monitorHeight[monId] * thisScale * monitorNormalizeScale[monId] * monitorZoomScale[monId] + borders, -1) == 1 ) {
|
||||
fitX = 0;
|
||||
fitY = 0;
|
||||
}
|
||||
}
|
||||
if ( fitX == 999999999 ) {
|
||||
allFit = 0;
|
||||
break; // break out of monitor loop flagging we didn't fit
|
||||
}
|
||||
thisX[m] =fitX;
|
||||
thisX2[m]=fitX + monitorWidth[monitorPtr[m]] * thisScale * monitorNormalizeScale[monitorPtr[m]] * monitorZoomScale[monitorPtr[m]] + borders;
|
||||
thisY[m] =fitY;
|
||||
thisY2[m]=fitY + monitorHeight[monitorPtr[m]] * thisScale * monitorNormalizeScale[monitorPtr[m]] * monitorZoomScale[monitorPtr[m]] + borders;
|
||||
thisArea += (thisX2[m] - thisX[m])*(thisY2[m] - thisY[m]);
|
||||
}
|
||||
if ( allFit == 1 ) {
|
||||
minScale=thisScale;
|
||||
if(bestFitArea<thisArea) {
|
||||
bestFitArea=thisArea;
|
||||
bestFitX=thisX;
|
||||
bestFitY=thisY;
|
||||
bestFitX2=thisX2;
|
||||
bestFitY2=thisY2;
|
||||
bestFitScale=thisScale;
|
||||
}
|
||||
} else {
|
||||
// didn't fit
|
||||
maxScale=thisScale;
|
||||
}
|
||||
}
|
||||
if ( bestFitArea > 0 ) { // only rearrange if we could fit -- otherwise just do nothing, let them start coming out, whatever
|
||||
for ( m = 0; m < numMonitors; m++ ) {
|
||||
c = $("Monitor" + monitorPtr[m]);
|
||||
c.style.position="absolute";
|
||||
c.style.left=bestFitX[m].toString() + "px";
|
||||
c.style.top=bestFitY[m].toString() + "px";
|
||||
c.width = bestFitX2[m] - bestFitX[m] + 1 - borders;
|
||||
c.height= bestFitY2[m] - bestFitY[m] + 1 - borders;
|
||||
}
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// >>>>>>>>>>>>>>>> Handles individual monitor clicks and navigation to the standard event/watch display
|
||||
|
||||
function showOneMonitor(monId) {
|
||||
// link out to the normal view of one event's data
|
||||
// We know the monitor, need to determine the event based on current time
|
||||
var url;
|
||||
if ( liveMode != 0 )
|
||||
url="?view=watch&mid=" + monId.toString();
|
||||
else
|
||||
for ( var i=0, len=eId.length; i<len; i++ ) {
|
||||
if ( eMonId[i] == monId && currentTimeSecs >= eStartSecs[i] && currentTimeSecs <= eEndSecs[i] )
|
||||
url="?view=event&eid=" + eId[i] + '&fid=' + parseInt(Math.max(1, Math.min(eventFrames[i], eventFrames[i] * (currentTimeSecs - eStartSecs[i]) / (eEndSecs[i] - eStartSecs[i] + 1) ) ));
|
||||
break;
|
||||
}
|
||||
createPopup(url, 'zmEvent', 'event', monitorWidth[eMonId[i]], monitorHeight[eMonId[i]]);
|
||||
}
|
||||
|
||||
function zoom(monId,scale) {
|
||||
var lastZoomMonPriorScale = monitorZoomScale[monId];
|
||||
monitorZoomScale[monId] *= scale;
|
||||
if ( redrawScreen() == 0 ) {// failure here is probably because we zoomed too far
|
||||
monitorZoomScale[monId] = lastZoomMonPriorScale;
|
||||
alert("You can't zoom that far -- rolling back");
|
||||
redrawScreen(); // put things back and hope it works
|
||||
}
|
||||
}
|
||||
|
||||
function clickMonitor(event,monId) {
|
||||
var monitor_element = $("Monitor"+monId.toString());
|
||||
var pos_x = event.offsetX ? (event.offsetX) : event.pageX - monitor_element.offsetLeft;
|
||||
var pos_y = event.offsetY ? (event.offsetY) : event.pageY - monitor_element.offsetTop;
|
||||
if ( pos_x < monitor_element.width/4 && pos_y < monitor_element.height/4 )
|
||||
zoom(monId,1.15);
|
||||
else if ( pos_x > monitor_element.width * 3/4 && pos_y < monitor_element.height/4 )
|
||||
zoom(monId,1/1.15);
|
||||
else
|
||||
showOneMonitor(monId);
|
||||
return;
|
||||
}
|
||||
|
||||
// >>>>>>>>> Initialization that runs on window load by being at the bottom
|
||||
|
||||
function initPage() {
|
||||
canvas = $("timeline");
|
||||
ctx = canvas.getContext('2d');
|
||||
for ( var i = 0, len = monitorPtr.length; i < len; i += 1 ) {
|
||||
var monId = monitorPtr[i];
|
||||
if ( ! monId ) continue;
|
||||
monitorCanvasObj[monId] = $('Monitor'+monId );
|
||||
if ( ! monitorCanvasObj[monId] ) {
|
||||
alert("Couldn't find DOM element for Monitor"+monId + "monitorPtr.length="+len);
|
||||
} else {
|
||||
monitorCanvasCtx[monId] = monitorCanvasObj[monId].getContext('2d');
|
||||
var imageObject = monitorImageObject[monId] = new Image();
|
||||
imageObject.monId = monId;
|
||||
imageObject.onload = function() {imagedone(this, this.monId, true )};
|
||||
imageObject.onerror = function() {imagedone(this, this.monId, false )};
|
||||
loadImage2Monitor( monId, monitorImageURL[monId] );
|
||||
}
|
||||
}
|
||||
drawGraph();
|
||||
setSpeed(speedIndex);
|
||||
setFit(fitMode); // will redraw
|
||||
setLive(liveMode); // will redraw
|
||||
}
|
||||
window.addEventListener("resize",redrawScreen);
|
||||
// Kick everything off
|
||||
window.addEvent( 'domready', initPage );
|
|
@ -0,0 +1,194 @@
|
|||
|
||||
var currentScale=<?php echo $defaultScale?>;
|
||||
var liveMode=<?php echo $initialModeIsLive?>;
|
||||
console.log("Live mode?"+liveMode);
|
||||
var fitMode=<?php echo $fitMode?>;
|
||||
var currentSpeed=<?php echo $speeds[$speedIndex]?>; // slider scale, which is only for replay and relative to real time
|
||||
var speedIndex=<?php echo $speedIndex?>;
|
||||
var currentDisplayInterval=<?php echo $initialDisplayInterval?>; // will be set based on performance, this is the display interval in milliseconds for history, and fps for live, and dynamically determined (in ms)
|
||||
var playSecsperInterval=1; // How many seconds of recorded image we play per refresh determined by speed (replay rate) and display interval; (default=1 if coming from live)
|
||||
var timerInterval; // milliseconds between interrupts
|
||||
var timerObj; // object to hold timer interval;
|
||||
var freeTimeLastIntervals=[]; // Percentage of current interval used in loading most recent image
|
||||
var imageLoadTimesEvaluated=0; // running count
|
||||
var imageLoadTimesNeeded=15; // and how many we need
|
||||
var timeLabelsFractOfRow = 0.9;
|
||||
var eMonId = [];
|
||||
var eId = [];
|
||||
var eStartSecs = [];
|
||||
var eEndSecs = [];
|
||||
var eventFrames = []; // this is going to presume all frames equal durationlength
|
||||
var groupStr=<?php if($group=="") echo '""'; else echo "\"&group=$group\""; ?>;
|
||||
|
||||
<?php
|
||||
|
||||
// Because we might not have time as the criteria, figure out the min/max time when we run the query
|
||||
|
||||
$minTimeSecs = strtotime('2036-01-01 01:01:01');
|
||||
$maxTimeSecs = strtotime('1950-01-01 01:01:01');
|
||||
|
||||
// This builds the list of events that are eligible from this range
|
||||
|
||||
$index=0;
|
||||
$anyAlarms=false;
|
||||
|
||||
foreach( dbFetchAll( $eventsSql ) as $event ) {
|
||||
if ( $minTimeSecs > $event['StartTimeSecs'] ) $minTimeSecs = $event['StartTimeSecs'];
|
||||
if ( $maxTimeSecs < $event['CalcEndTimeSecs'] ) $maxTimeSecs = $event['CalcEndTimeSecs'];
|
||||
echo "
|
||||
eMonId[$index]=" . $event['MonitorId'] . ";
|
||||
eId[$index]=" . $event['Id'] . ";
|
||||
eStartSecs[$index]=" . $event['StartTimeSecs'] . ";
|
||||
eEndSecs[$index]=" . $event['CalcEndTimeSecs'] . ";
|
||||
eventFrames[$index]=" . $event['Frames'] . ";
|
||||
|
||||
";
|
||||
|
||||
$index = $index + 1;
|
||||
if ( $event['MaxScore'] > 0 )
|
||||
$anyAlarms = true;
|
||||
}
|
||||
|
||||
// if there is no data set the min/max to the passed in values
|
||||
if ( $index == 0 ) {
|
||||
if ( isset($minTime) && isset($maxTime) ) {
|
||||
$minTimeSecs = strtotime($minTime);
|
||||
$maxTimeSecs = strtotime($maxTime);
|
||||
} else {
|
||||
// this is the case of no passed in times AND no data -- just set something arbitrary
|
||||
$minTimeSecs = strtotime('1950-06-01 01:01:01'); // random time so there's something to display
|
||||
$maxTimeSecs = time() + 86400;
|
||||
}
|
||||
}
|
||||
|
||||
// We only reset the calling time if there was no calling time
|
||||
if ( !isset($minTime) || !isset($maxTime) ) {
|
||||
$maxTime = strftime($maxTimeSecs);
|
||||
$minTime = strftime($minTimeSecs);
|
||||
} else {
|
||||
$minTimeSecs = strtotime($minTime);
|
||||
$maxTimeSecs = strtotime($maxTime);
|
||||
}
|
||||
|
||||
// If we had any alarms in those events, this builds the list of all alarm frames, but consolidated down to (nearly) contiguous segments
|
||||
// comparison in else governs how aggressively it consolidates
|
||||
|
||||
echo "var fMonId = [];\n";
|
||||
echo "var fTimeFromSecs = [];\n";
|
||||
echo "var fTimeToSecs = [];\n";
|
||||
echo "var fScore = [];\n";
|
||||
$maxScore=0;
|
||||
$index=0;
|
||||
$mId=-1;
|
||||
$fromSecs=-1;
|
||||
$toSecs=-1;
|
||||
$maxScore=-1;
|
||||
|
||||
if ( $anyAlarms ) {
|
||||
foreach( dbFetchAll ($frameSql) as $frame ) {
|
||||
if ( $mId < 0 ) {
|
||||
$mId = $frame['MonitorId'];
|
||||
$fromSecs = $frame['TimeStampSecs'];
|
||||
$toSecs = $frame['TimeStampSecs'];
|
||||
$maxScore = $frame['Score'];
|
||||
} else if ( $mId != $frame['MonitorId'] || $frame['TimeStampSecs'] - $toSecs > 10 ) {
|
||||
// dump this one start a new
|
||||
$index++;
|
||||
echo "
|
||||
fMonId[$index]= $mId;
|
||||
fTimeFromSecs[$index]= $fromSecs;
|
||||
fTimeToSecs[$index]= $toSecs;
|
||||
fScore[$index]= $maxScore;
|
||||
";
|
||||
$mId = $frame['MonitorId'];
|
||||
$fromSecs = $frame['TimeStampSecs'];
|
||||
$toSecs = $frame['TimeStampSecs'];
|
||||
$maxScore = $frame['Score'];
|
||||
} else {
|
||||
// just add this one on
|
||||
$toSecs = $frame['TimeStampSecs'];
|
||||
if ( $maxScore < $frame['Score'] ) $maxScore = $frame['Score'];
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( $mId > 0 ) {
|
||||
echo "
|
||||
fMonId[$index]= $mId;
|
||||
fTimeFromSecs[$index]= $fromSecs;
|
||||
fTimeToSecs[$index]= $toSecs;
|
||||
fScore[$index]= $maxScore;
|
||||
";
|
||||
}
|
||||
|
||||
echo "var maxScore=$maxScore;\n"; // used to skip frame load if we find no alarms.
|
||||
echo "var monitorName = [];\n";
|
||||
echo "var monitorLoading = [];\n";
|
||||
echo "var monitorImageObject = [];\n";
|
||||
echo "var monitorImageURL = [];\n";
|
||||
echo "var monitorLoadingStageURL = [];\n";
|
||||
echo "var monitorLoadStartTimems = [];\n";
|
||||
echo "var monitorLoadEndTimems = [];\n";
|
||||
echo "var monitorColour = [];\n";
|
||||
echo "var monitorWidth = [];\n";
|
||||
echo "var monitorHeight = [];\n";
|
||||
echo "var monitorIndex = [];\n";
|
||||
echo "var monitorNormalizeScale = [];\n";
|
||||
echo "var monitorZoomScale = [];\n";
|
||||
echo "var monitorCanvasObj = [];\n"; // stash location of these here so we don't have to search
|
||||
echo "var monitorCanvasCtx = [];\n";
|
||||
echo "var monitorPtr = []; // monitorName[monitorPtr[0]] is first monitor\n";
|
||||
|
||||
|
||||
$numMonitors=0; // this array is indexed by the monitor ID for faster access later, so it may be sparse
|
||||
$avgArea=floatval(0); // Calculations the normalizing scale
|
||||
|
||||
foreach ( $monitors as $m ) {
|
||||
$avgArea = $avgArea + floatval($m->Width() * $m->Height());
|
||||
$numMonitors++;
|
||||
}
|
||||
|
||||
if ( $numMonitors > 0 ) $avgArea = $avgArea / $numMonitors;
|
||||
|
||||
$numMonitors = 0;
|
||||
foreach ( $monitors as $m ) {
|
||||
echo " monitorLoading[" . $m->Id() . "]=false;\n";
|
||||
echo " monitorImageURL[" . $m->Id() . "]='".$m->getStreamSrc( array('mode'=>'single','scale'=>$defaultScale*100), '&' )."';\n";
|
||||
echo " monitorLoadingStageURL[" . $m->Id() . "] = '';\n";
|
||||
echo " monitorColour[" . $m->Id() . "]=\"" . $m->WebColour() . "\";\n";
|
||||
echo " monitorWidth[" . $m->Id() . "]=" . $m->Width() . ";\n";
|
||||
echo " monitorHeight[" . $m->Id() . "]=" . $m->Height() . ";\n";
|
||||
echo " monitorIndex[" . $m->Id() . "]=" . $numMonitors . ";\n";
|
||||
echo " monitorName[" . $m->Id() . "]=\"" . $m->Name() . "\";\n";
|
||||
echo " monitorLoadStartTimems[" . $m->Id() . "]=0;\n";
|
||||
echo " monitorLoadEndTimems[" . $m->Id() . "]=0;\n";
|
||||
echo " monitorNormalizeScale[" . $m->Id() . "]=" . sqrt($avgArea / ($m->Width() * $m->Height() )) . ";\n";
|
||||
$zoomScale=1.0;
|
||||
if(isset($_REQUEST[ 'z' . $m->Id() ]) )
|
||||
$zoomScale = floatval( validHtmlStr($_REQUEST[ 'z' . $m->Id() ]) );
|
||||
echo " monitorZoomScale[" . $m->Id() . "]=" . $zoomScale . ";\n";
|
||||
echo " monitorPtr[" . $numMonitors . "]=" . $m->Id() . ";\n";
|
||||
$numMonitors += 1;
|
||||
}
|
||||
echo "var numMonitors = $numMonitors;\n";
|
||||
echo "var minTimeSecs=" . $minTimeSecs . ";\n";
|
||||
echo "var maxTimeSecs=" . $maxTimeSecs . ";\n";
|
||||
echo "var rangeTimeSecs=" . ( $maxTimeSecs - $minTimeSecs + 1) . ";\n";
|
||||
if(isset($defaultCurrentTime))
|
||||
echo "var currentTimeSecs=" . strtotime($defaultCurrentTime) . ";\n";
|
||||
else
|
||||
echo "var currentTimeSecs=" . ($minTimeSecs + $maxTimeSecs)/2 . ";\n";
|
||||
|
||||
echo 'var speeds=[';
|
||||
for ($i=0; $i<count($speeds); $i++)
|
||||
echo (($i>0)?', ':'') . $speeds[$i];
|
||||
echo "];\n";
|
||||
?>
|
||||
|
||||
var scrubAsObject=$('scrub');
|
||||
var cWidth; // save canvas width
|
||||
var cHeight; // save canvas height
|
||||
var canvas; // global canvas definition so we don't have to keep looking it up
|
||||
var ctx;
|
||||
var underSlider; // use this to hold what is hidden by the slider
|
||||
var underSliderX; // Where the above was taken from (left side, Y is zero)
|
||||
|
|
@ -31,7 +31,7 @@ function changeScale() {
|
|||
Cookie.write( 'zmWatchScale'+monitorId, scale, { duration: 10*365 } );
|
||||
|
||||
/*Stream could be an applet so can't use moo tools*/
|
||||
var streamImg = document.getElementById('liveStream'+monitorId);
|
||||
var streamImg = $('#liveStream'+monitorId);
|
||||
if ( streamImg ) {
|
||||
streamImg.style.width = newWidth + "px";
|
||||
streamImg.style.height = newHeight + "px";
|
||||
|
@ -187,14 +187,14 @@ function getStreamCmdResponse( respObj, respText ) {
|
|||
if ( streamStatus.auth ) {
|
||||
console.log("Haev a new auth hash" + streamStatus.auth);
|
||||
// Try to reload the image stream.
|
||||
var streamImg = document.getElementById('liveStream');
|
||||
var streamImg = $('liveStream');
|
||||
if ( streamImg )
|
||||
streamImg.src = streamImg.src.replace( /auth=\w+/i, 'auth='+streamStatus.auth );
|
||||
} // end if haev a new auth hash
|
||||
} else {
|
||||
checkStreamForErrors("getStreamCmdResponse",respObj);//log them
|
||||
// Try to reload the image stream.
|
||||
var streamImg = document.getElementById('liveStream'+monitorId);
|
||||
var streamImg = $('liveStream'+monitorId);
|
||||
if ( streamImg ) {
|
||||
streamImg.src = streamImg.src.replace(/rand=\d+/i,'rand='+Math.floor((Math.random() * 1000000) ));
|
||||
console.log("Changing lviestream src to " + streamImg.src);
|
||||
|
|
|
@ -41,6 +41,7 @@ if ( isset( $_REQUEST['showZones'] ) ) {
|
|||
}
|
||||
}
|
||||
$monitors = array();
|
||||
<<<<<<< HEAD
|
||||
$widths = array(
|
||||
'' => 'auto',
|
||||
160 => 160,
|
||||
|
@ -63,8 +64,10 @@ if ( isset( $_REQUEST['scale'] ) ) {
|
|||
} else if ( isset( $_COOKIE['zmMontageScale'] ) ) {
|
||||
$scale = $_COOKIE['zmMontageScale'];
|
||||
Logger::Debug("Setting scale from cookie to $scale");
|
||||
} else {
|
||||
Logger::Debug("scale is $scale");
|
||||
}
|
||||
|
||||
if ( ! $scale )
|
||||
$scale = 100;
|
||||
}
|
||||
|
||||
foreach( dbFetchAll( $sql ) as $row ) {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue