Merge branch 'storageareas' of github.com:connortechnology/ZoneMinder into storageareas

This commit is contained in:
Isaac Connor 2017-12-03 16:05:43 -05:00
commit 9aa94bd3ab
143 changed files with 5694 additions and 4539 deletions

View File

@ -30,6 +30,7 @@ env:
- OS=el DIST=7
- OS=fedora DIST=25
- OS=fedora DIST=26 DOCKER_REPO=knnniggett/packpack
- OS=fedora DIST=27 DOCKER_REPO=knnniggett/packpack
- OS=ubuntu DIST=trusty
- OS=ubuntu DIST=xenial
- OS=ubuntu DIST=trusty ARCH=i386

View File

@ -31,6 +31,8 @@ This is the recommended method to install ZoneMinder onto your system. ZoneMinde
- Fedora via [RPM Fusion](http://rpmfusion.org)
- OpenSuse via [third party repository](http://www.zoneminder.com/wiki/index.php/Installing_using_ZoneMinder_RPMs_for_SuSE)
- Mageia from their default repository
- Arch via the [AUR](https://aur.archlinux.org/packages/zoneminder/)
- Gentoo from their [default repository](https://packages.gentoo.org/packages/www-misc/zoneminder)
If a repository that hosts ZoneMinder packages is not available for your distro, then you are encouraged to build your own package, rather than build from source. While each distro is different in ways that set it apart from all the others, they are often similar enough to allow you to adapt another distro's package building instructions to your own.

View File

@ -195,6 +195,7 @@ CREATE TABLE `Events` (
`Frames` int(10) unsigned default NULL,
`AlarmFrames` int(10) unsigned default NULL,
`DefaultVideo` VARCHAR( 64 ) DEFAULT '' NOT NULL,
`SaveJPEGs` TINYINT,
`TotScore` int(10) unsigned NOT NULL default '0',
`AvgScore` smallint(5) unsigned default '0',
`MaxScore` smallint(5) unsigned default '0',
@ -384,6 +385,8 @@ CREATE TABLE `Monitors` (
`Deinterlacing` int(10) unsigned NOT NULL default '0',
`SaveJPEGs` TINYINT NOT NULL DEFAULT '3' ,
`VideoWriter` TINYINT NOT NULL DEFAULT '0',
`OutputCodec` enum('h264','mjpeg','mpeg1','mpeg2'),
`OutputContainer` enum('auto','mp4','mkv'),
`EncoderParameters` TEXT,
`RecordAudio` TINYINT NOT NULL DEFAULT '0',
`RTSPDescribe` tinyint(1) unsigned,
@ -431,6 +434,19 @@ CREATE TABLE `Monitors` (
`Status` enum('Unknown','NotRunning','Running','NoSignal','Signal') NOT NULL default 'Unknown',
`CaptureFPS` DECIMAL(10,2) NOT NULL default 0,
`AnalysisFPS` DECIMAL(5,2) NOT NULL default 0,
`TotalEvents` int(10) unsigned,
`TotalEventDiskSpace` bigint unsigned,
`HourEvents` int(10) unsigned,
`HourEventDiskSpace` bigint unsigned,
`DayEvents` int(10) unsigned,
`DayEventDiskSpace` bigint unsigned,
`WeekEvents` int(10) unsigned,
`WeekEventDiskSpace` bigint unsigned,
`MonthEvents` int(10) unsigned,
`MonthEventDiskSpace` bigint unsigned,
`ArchivedEvents` int(10) unsigned,
`ArchivedEventDiskSpace` bigint unsigned,
`ZoneCount` TINYINT NOT NULL DEFAULT 0,
PRIMARY KEY (`Id`)
) ENGINE=@ZM_MYSQL_ENGINE@;
@ -606,13 +622,14 @@ CREATE TABLE `Storage` (
`Path` varchar(64) NOT NULL default '',
`Name` varchar(64) NOT NULL default '',
`Type` enum('local','s3fs') NOT NULL default 'local',
`DiskSpace` bigint unsigned default NULL,
PRIMARY KEY (`Id`)
) ENGINE=@ZM_MYSQL_ENGINE@;
--
-- Create a default storage location
--
insert into Storage VALUES (NULL, '/var/cache/zoneminder/events', 'Default', 'local' );
insert into Storage VALUES (NULL, '/var/cache/zoneminder/events', 'Default', 'local', NULL );
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;

View File

@ -67,3 +67,4 @@ SET @s = (SELECT IF(
PREPARE stmt FROM @s;
EXECUTE stmt;

26
db/zm_update-1.31.13.sql Normal file
View File

@ -0,0 +1,26 @@
ALTER TABLE `Monitors` MODIFY `OutputCodec` enum('h264','mjpeg','mpeg1','mpeg2') default 'h264';
ALTER TABLE `Monitors` MODIFY `OutputContainer` enum('auto','mp4','mkv') default 'auto';
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Events'
AND column_name = 'SaveJPEGs'
) > 0,
"SELECT 'Column SaveJPEGs already exists in Events'",
"ALTER TABLE `Events` ADD `SaveJPEGs` TINYINT AFTER `DefaultVideo`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Storage'
AND column_name = 'DiskSpace'
) > 0,
"SELECT 'Column DiskSpace already exists in Events'",
"ALTER TABLE `Storage` ADD `DiskSpace` bigint unsigned default NULL AFTER `Type`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;

148
db/zm_update-1.31.14.sql Normal file
View File

@ -0,0 +1,148 @@
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Monitors'
AND column_name = 'TotalEvents'
) > 0,
"SELECT 'Column TotalEvents already exists in Monitors'",
"ALTER TABLE `Monitors` ADD `TotalEvents` INT(10) AFTER `AnalysisFPS`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Monitors'
AND column_name = 'TotalEventDiskSpace'
) > 0,
"SELECT 'Column TotalEventDiskSpace already exists in Monitors'",
"ALTER TABLE `Monitors` ADD `TotalEventDiskSpace` BIGINT AFTER `TotalEvents`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Monitors'
AND column_name = 'HourEvents'
) > 0,
"SELECT 'Column HourEvents already exists in Monitors'",
"ALTER TABLE `Monitors` ADD `HourEvents` INT(10) AFTER `TotalEvents`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Monitors'
AND column_name = 'HourEventDiskSpace'
) > 0,
"SELECT 'Column HourEventDiskSpace already exists in Monitors'",
"ALTER TABLE `Monitors` ADD `HourEventDiskSpace` BIGINT AFTER `HourEvents`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Monitors'
AND column_name = 'DayEvents'
) > 0,
"SELECT 'Column DayEvents already exists in Monitors'",
"ALTER TABLE `Monitors` ADD `DayEvents` INT(10) AFTER `HourEvents`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Monitors'
AND column_name = 'DayEventDiskSpace'
) > 0,
"SELECT 'Column DayEventDiskSpace already exists in Monitors'",
"ALTER TABLE `Monitors` ADD `DayEventDiskSpace` BIGINT AFTER `DayEvents`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Monitors'
AND column_name = 'WeekEvents'
) > 0,
"SELECT 'Column WeekEvents already exists in Monitors'",
"ALTER TABLE `Monitors` ADD `WeekEvents` INT(10) AFTER `DayEvents`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Monitors'
AND column_name = 'WeekEventDiskSpace'
) > 0,
"SELECT 'Column WeekEventDiskSpace already exists in Monitors'",
"ALTER TABLE `Monitors` ADD `WeekEventDiskSpace` BIGINT AFTER `WeekEvents`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Monitors'
AND column_name = 'MonthEvents'
) > 0,
"SELECT 'Column MonthEvents already exists in Monitors'",
"ALTER TABLE `Monitors` ADD `MonthEvents` INT(10) AFTER `WeekEvents`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Monitors'
AND column_name = 'MonthEventDiskSpace'
) > 0,
"SELECT 'Column MonthEventDiskSpace already exists in Monitors'",
"ALTER TABLE `Monitors` ADD `MonthEventDiskSpace` BIGINT AFTER `MonthEvents`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Monitors'
AND column_name = 'ArchivedEvents'
) > 0,
"SELECT 'Column ArchivedEvents already exists in Monitors'",
"ALTER TABLE `Monitors` ADD `ArchivedEvents` INT(10) AFTER `MonthEvents`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Monitors'
AND column_name = 'ArchivedEventDiskSpace'
) > 0,
"SELECT 'Column ArchivedEventDiskSpace already exists in Monitors'",
"ALTER TABLE `Monitors` ADD `ArchivedEventDiskSpace` BIGINT AFTER `ArchivedEvents`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;

14
db/zm_update-1.31.15.sql Normal file
View File

@ -0,0 +1,14 @@
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Monitors'
AND column_name = 'ZoneCount'
) > 0,
"SELECT 'Column ZoneCount already exists in Monitors'",
"ALTER TABLE `Monitors` ADD `ZoneCount` TINYINT NOT NULL DEFAULT 0 AFTER `ArchivedEventDiskSpace`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
UPDATE Monitors SET ZoneCount=(SELECT COUNT(Id) FROM Zones WHERE MonitorId=Monitors.Id);

View File

@ -16,3 +16,5 @@ SET @s = (SELECT IF(
PREPARE stmt FROM @s;
EXECUTE stmt;
INSERT INTO `Controls` VALUES (28,'Floureon 1080P','Ffmpeg','Floureon',0,0,0,1,0,0,0,1,1,18,1,1,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,20,0,1,1,1,0,0,0,1,1,0,0,0,0,1,1,8,0,0,1,0,0,0,0,1,1,8,0,0,0,0);

View File

@ -10,30 +10,23 @@ if [ "$1" = "configure" ]; then
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/*
chown www-data:www-data /var/cache/zoneminder /var/cache/zoneminder/* /usr/share/zoneminder/www/cache
fi
if [ ! -e "/etc/apache2/mods-enabled/cgi.load" ]; then
echo "The cgi module is not enabled in apache2. I am enabling it using a2enmod cgi."
a2enmod cgi
fi
# Do this every time the package is installed or upgraded
# 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 [ "$ZM_DB_HOST" = "localhost" ]; then
if [ -e "/etc/init.d/mysql" ]; then
# Do this every time the package is installed or upgraded
# Ensure zoneminder is stopped
deb-systemd-invoke stop zoneminder.service || exit $?
#
# Get mysql started if it isn't
#
if ! $(/etc/init.d/mysql status >/dev/null 2>&1); then
deb-systemd-invoke start mysql.service || exit $?
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...

View File

@ -15,9 +15,11 @@ achieve the same result by running:
::
tasksel install lamp-server
sudo tasksel install lamp-server
During installation it will ask you to set up a master/root password for the MySQL.
Installing LAMP is not ZoneMinder specific so you will find plenty of resources to
guide you with a quick search.
**Step 1:** Either run commands in this install using sudo or use the below to become root
::

View File

@ -2933,6 +2933,16 @@ our @options = (
type => $types{integer},
category => 'highband',
},
{
name => 'ZM_WEB_H_REFRESH_NAVBAR',
default => '5',
description => 'How often (in seconds) the navigation header should refresh itself',
help => q`
The navigation header contains the general status information about server load and storage space.
`,
type => $types{integer},
category => 'highband',
},
{
name => 'ZM_WEB_H_REFRESH_CYCLE',
default => '10',
@ -3196,6 +3206,16 @@ our @options = (
`,
category => 'medband',
},
{
name => 'ZM_WEB_M_REFRESH_NAVBAR',
default => '15',
description => 'How often (in seconds) the navigation header should refresh itself',
help => q`
The navigation header contains the general status information about server load and storage space.
`,
type => $types{integer},
category => 'medband',
},
{
name => 'ZM_WEB_M_REFRESH_CYCLE',
default => '20',
@ -3459,6 +3479,16 @@ our @options = (
type => $types{integer},
category => 'lowband',
},
{
name => 'ZM_WEB_L_REFRESH_NAVBAR',
default => '35',
description => 'How often (in seconds) the navigation header should refresh itself',
help => q`
The navigation header contains the general status information about server load and storage space.
`,
type => $types{integer},
category => 'lowband',
},
{
name => 'ZM_WEB_L_REFRESH_CYCLE',
default => '30',

View File

@ -0,0 +1,390 @@
# Modified on 2017-11-17 by Ognyan Bankov
# ==========================================================================
#
# ZoneMinder Floureon 1080p IP Control Protocol Module, $Date: 2017-11-17 09:20:00 +0000 $, $Revision: 0001 $
# Copyright (C) 2017 Ognyan Bankov
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# ==========================================================================
#
# This module contains the implementation of the Floureon 1080p 18x (Model: BT-HD54F) IP camera control
# protocol. It should work with other Floureon cameras too.
#
#
package MyAgent;
use base 'LWP::UserAgent';
package ZoneMinder::Control::Floureon;
use 5.006;
use strict;
use warnings;
require ZoneMinder::Base;
require ZoneMinder::Control;
our @ISA = qw(ZoneMinder::Control);
our $VERSION = $ZoneMinder::Base::VERSION;
# ==========================================================================
#
# Floureon IP Control Protocol
#
# ==========================================================================
use ZoneMinder::Logger qw(:all);
use ZoneMinder::Config qw(:all);
use Time::HiRes qw( usleep );
sub new
{
my $class = shift;
my $id = shift;
my $self = ZoneMinder::Control->new( $id );
my $logindetails = "";
bless( $self, $class );
srand( time() );
return $self;
}
our $AUTOLOAD;
sub AUTOLOAD
{
my $self = shift;
my $class = ref($self) || croak( "$self not object" );
my $name = $AUTOLOAD;
$name =~ s/.*://;
if ( exists($self->{$name}) )
{
return( $self->{$name} );
}
Fatal( "Can't access $name member of object of class $class" );
}
our $stop_command;
sub open
{
my $self = shift;
$self->loadMonitor();
$self->{ua} = MyAgent->new;
$self->{ua}->agent( "ZoneMinder Control Agent/" );
$self->{state} = 'open';
}
sub close
{
my $self = shift;
$self->{state} = 'closed';
}
sub printMsg
{
my $self = shift;
my $msg = shift;
my $msg_len = length($msg);
Debug( $msg."[".$msg_len."]" );
}
sub sendCmd
{
my $self = shift;
my $cmd = shift;
my $result = undef;
printMsg( $cmd, "Tx" );
my $req = HTTP::Request->new( GET=>"http://".$self->{Monitor}->{ControlAddress}."/$cmd"."&".$self->{Monitor}->{ControlDevice});
print ("Sending $req\n");
my $res = $self->{ua}->request($req);
if ( $res->is_success )
{
$result = !undef;
}
else
{
Error( "Error REALLY check failed:'".$res->status_line()."'" );
Error ("Cmd:".$req);
}
return( $result );
}
sub reset
{
my $self = shift;
Debug( "Camera Reset" );
my $cmd = "reboot.cgi?";
$self->sendCmd( $cmd );
}
# PP - in all move operations, added auto stop after timeout
#Up Arrow
sub moveConUp
{
my $self = shift;
my $params = shift;
my $tiltspeed = $self->getParam( $params, 'tiltspeed' );
Debug( "Move Up" );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Direction=1&PanSpeed=6&TiltSpeed=$tiltspeed";
$self->sendCmd( $cmd );
$self->autoStop($tiltspeed);
}
#Down Arrow
sub moveConDown
{
my $self = shift;
my $params = shift;
my $tiltspeed = $self->getParam( $params, 'tiltspeed' );
Debug( "Move Down" );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Direction=2&PanSpeed=6&TiltSpeed=$tiltspeed";
$self->sendCmd( $cmd );
$self->autoStop($tiltspeed);
}
#Left Arrow
sub moveConLeft
{
my $self = shift;
my $params = shift;
my $panspeed = $self->getParam( $params, 'panspeed' );
Debug( "Move Left" );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Direction=3&PanSpeed=$panspeed&TiltSpeed=6";
$self->sendCmd( $cmd );
$self->autoStop($panspeed);
}
#Right Arrow
sub moveConRight
{
my $self = shift;
my $params = shift;
my $panspeed = $self->getParam( $params, 'panspeed' );
Debug( "Move Right" );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Direction=4&PanSpeed=$panspeed&TiltSpeed=6";
$self->sendCmd( $cmd );
$self->autoStop($panspeed);
}
#Diagonally Up Right Arrow
sub moveConUpRight
{
my $self = shift;
my $params = shift;
my $panspeed = $self->getParam( $params, 'panspeed' );
my $tiltspeed = $self->getParam( $params, 'tiltspeed' );
Debug( "Move Diagonally Up Right" );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Direction=7&PanSpeed=$panspeed&TiltSpeed=$tiltspeed";
$self->sendCmd( $cmd );
$self->autoStop($tiltspeed);
}
#Diagonally Down Right Arrow
sub moveConDownRight
{
my $self = shift;
my $params = shift;
my $panspeed = $self->getParam( $params, 'panspeed' );
my $tiltspeed = $self->getParam( $params, 'tiltspeed' );
Debug( "Move Diagonally Down Right" );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Direction=8&PanSpeed=$panspeed&TiltSpeed=$tiltspeed";
$self->sendCmd( $cmd );
$self->autoStop($tiltspeed);
}
#Diagonally Up Left Arrow
sub moveConUpLeft
{
my $self = shift;
my $params = shift;
my $panspeed = $self->getParam( $params, 'panspeed' );
my $tiltspeed = $self->getParam( $params, 'tiltspeed' );
Debug( "Move Diagonally Up Left" );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Direction=5&PanSpeed=$panspeed&TiltSpeed=$tiltspeed";
$self->sendCmd( $cmd );
$self->autoStop($tiltspeed);
}
#Diagonally Down Left Arrow
sub moveConDownLeft
{
my $self = shift;
my $params = shift;
my $panspeed = $self->getParam( $params, 'panspeed' );
my $tiltspeed = $self->getParam( $params, 'tiltspeed' );
Debug( "Move Diagonally Down Left" );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Direction=6&PanSpeed=$panspeed&TiltSpeed=$tiltspeed";
$self->sendCmd( $cmd );
$self->autoStop($tiltspeed);
}
#Stop
sub moveStop
{
my $self = shift;
Debug( "Move Stop" );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Stop=0";
$self->sendCmd( $cmd );
}
sub zoomConTele
{
my $self = shift;
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Zoom=1";
$self->sendCmd( $cmd );
$self->autoStop();
}
sub zoomConWide
{
my $self = shift;
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Zoom=0";
$self->sendCmd( $cmd );
$self->autoStop();
}
sub focusConNear
{
my $self = shift;
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Focus=1";
$self->sendCmd( $cmd );
$self->autoStop();
}
sub focusConFar
{
my $self = shift;
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Focus=0";
$self->sendCmd( $cmd );
$self->autoStop();
}
sub irisConOpen
{
my $self = shift;
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Iris=1";
$self->sendCmd( $cmd );
$self->autoStop();
}
sub irisConClose
{
my $self = shift;
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Iris=0";
$self->sendCmd( $cmd );
$self->autoStop();
}
#Set preset
sub presetSet
{
my $self = shift;
my $params = shift;
my $preset = $self->getParam( $params, 'preset' );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&PresetNumber=1&Preset=0";
$self->sendCmd( $cmd );
}
#Goto preset
sub presetGoto
{
my $self = shift;
my $params = shift;
my $preset = $self->getParam( $params, 'preset' );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&PresetNumber=1&Preset=1";
$self->sendCmd( $cmd );
}
sub autoStop
{
my $self = shift;
my $timeout = shift;
if ($timeout)
{
if ($timeout > 1) {
usleep(100000*$timeout);
}
}
Debug( "Auto Stop" );
my $cmd = "cgi/ptz_set?Channel=1&Group=PTZCtrlInfo&Stop=0";
$self->sendCmd( $cmd );
}
1;
__END__
=head1 Floureon
ZoneMinder::Database - Perl extension for Floureon 1080P
=head1 SYNOPSIS
Control script for Floureon 1080P IP camera
=head1 DESCRIPTION
When setuping you monitor in the "Control" tab:
1. Select "Control type": Floureon 1080P
2. Leave "Control device" empty
3. Fill "Control Address" like username:password@ip/domain. Example: admin:admin123@192.168.1.110
=head2 EXPORT
None by default.
=head1 SEE ALSO
=head1 AUTHOR
Ognyan Bankov, E<lt>ogibankov@gmail.comE<gt>
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2017 Ognyan Bankov
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.3 or,
at your option, any later version of Perl 5 you may have available.
=cut

View File

@ -390,7 +390,7 @@ sub age {
sub DiskSpace {
if ( @_ > 1 ) {
Debug("Cleared DiskSpace, was $_[0]{DiskSpace}");
Debug("Cleared DiskSpace, was $_[0]{DiskSpace}") if $_[0]{DiskSpace};
$_[0]{DiskSpace} = $_[1];
}
if ( ! defined $_[0]{DiskSpace} ) {

View File

@ -225,29 +225,41 @@ sub Sql {
) {
$value = "'$temp_value'";
} elsif ( $term->{attr} eq 'DateTime' or $term->{attr} eq 'StartDateTime' or $term->{attr} eq 'EndDateTime' ) {
$value = DateTimeToSQL( $temp_value );
if ( !$value ) {
Error( "Error parsing date/time '$temp_value', "
."skipping filter '$self->{Name}'\n" );
return;
if ( $temp_value == 'NULL' ) {
$value = $temp_value;
} else {
$value = DateTimeToSQL( $temp_value );
if ( !$value ) {
Error( "Error parsing date/time '$temp_value', "
."skipping filter '$self->{Name}'\n" );
return;
}
$value = "'$value'";
}
$value = "'$value'";
} elsif ( $term->{attr} eq 'Date' or $term->{attr} eq 'StartDate' or $term->{attr} eq 'EndDate' ) {
$value = DateTimeToSQL( $temp_value );
if ( !$value ) {
Error( "Error parsing date/time '$temp_value', "
."skipping filter '$self->{Name}'\n" );
return;
if ( $temp_value == 'NULL' ) {
$value = $temp_value;
} else {
$value = DateTimeToSQL( $temp_value );
if ( !$value ) {
Error( "Error parsing date/time '$temp_value', "
."skipping filter '$self->{Name}'\n" );
return;
}
$value = "to_days( '$value' )";
}
$value = "to_days( '$value' )";
} elsif ( $term->{attr} eq 'Time' or $term->{attr} eq 'StartTime' or $term->{attr} eq 'EndTime' ) {
$value = DateTimeToSQL( $temp_value );
if ( !$value ) {
Error( "Error parsing date/time '$temp_value', "
."skipping filter '$self->{Name}'\n" );
return;
if ( $temp_value == 'NULL' ) {
$value = $temp_value;
} else {
$value = DateTimeToSQL( $temp_value );
if ( !$value ) {
Error( "Error parsing date/time '$temp_value', "
."skipping filter '$self->{Name}'\n" );
return;
}
$value = "extract( hour_second from '$value' )";
}
$value = "extract( hour_second from '$value' )";
} else {
$value = $temp_value;
}

View File

@ -21,34 +21,6 @@
#
# ==========================================================================
=head1 NAME
zmaudit.pl - ZoneMinder event file system and database consistency checker
=head1 SYNOPSIS
zmaudit.pl [-r,-report|-i,-interactive]
=head1 DESCRIPTION
This script checks for consistency between the event filesystem and
the database. If events are found in one and not the other they are
deleted (optionally). Additionally any monitor event directories that
do not correspond to a database monitor are similarly disposed of.
However monitors in the database that don't have a directory are left
alone as this is valid if they are newly created and have no events
yet.
=head1 OPTIONS
-c, --continuous - Run continuously
-i, --interactive - Ask before applying any changes
-m, --monitor_id - Restrict zmaudit actions to events pertaining to the specified monitor id
-r, --report - Just report don't actually do anything
-v, --version - Print the installed version of ZoneMinder
=cut
use strict;
use bytes;
@ -81,6 +53,7 @@ use constant EVENT_PATH => ($Config{ZM_DIR_EVENTS}=~m|/|)
? $Config{ZM_DIR_EVENTS}
: ($Config{ZM_PATH_WEB}.'/'.$Config{ZM_DIR_EVENTS})
;
use constant ZM_AUDIT_PID => '@ZM_RUNDIR@/zmaudit.pid';
$| = 1;
@ -118,6 +91,17 @@ if ( ! exists $Config{ZM_AUDIT_MIN_AGE} ) {
Fatal('ZM_AUDIT_MIN_AGE is not set in config.');
}
if ( -e ZM_AUDIT_PID ) {
Fatal('zmaudit.pl appears to already be running. If not, please delete ' . ZM_AUDIT_PID );
} else {
if ( open( my $PID, '>', ZM_AUDIT_PID ) ) {
print( $PID $$ );
close( $PID );
} else {
Error( "Can't open pid file at " . ZM_PID );
}
}
my $dbh = zmDbConnect();
require ZoneMinder::Monitor;
@ -598,6 +582,7 @@ Debug("Event $db_event is not in fs.");
sleep( $Config{ZM_AUDIT_CHECK_INTERVAL} ) if $continuous;
};
unlink ZM_AUDIT_PID;
exit( 0 );
sub aud_print {
@ -688,3 +673,30 @@ sub delete_empty_directories {
1;
__END__
=head1 NAME
zmaudit.pl - ZoneMinder event file system and database consistency checker
=head1 SYNOPSIS
zmaudit.pl [-r,-report|-i,-interactive]
=head1 DESCRIPTION
This script checks for consistency between the event filesystem and
the database. If events are found in one and not the other they are
deleted (optionally). Additionally any monitor event directories that
do not correspond to a database monitor are similarly disposed of.
However monitors in the database that don't have a directory are left
alone as this is valid if they are newly created and have no events
yet.
=head1 OPTIONS
-c, --continuous - Run continuously
-i, --interactive - Ask before applying any changes
-r, --report - Just report don't actually do anything
-v, --version - Print the installed version of ZoneMinder
=cut

View File

@ -21,20 +21,6 @@
#
# ==========================================================================
=head1 NAME
zmpkg.pl - ZoneMinder Package Control Script
=head1 SYNOPSIS
zmpkg.pl {start|stop|restart|status|logrot|'state'|version}
=head1 DESCRIPTION
This script is used to start and stop the ZoneMinder package primarily to
allow command line control for automatic restart on reboot (see zm script)
=cut
use strict;
use bytes;
@ -61,48 +47,41 @@ logInit();
my $command = $ARGV[0]||'';
if ( $command eq 'version' ) {
print ZoneMinder::Base::ZM_VERSION . "\n";
exit(0);
print ZoneMinder::Base::ZM_VERSION . "\n";
exit(0);
}
my $state;
my $dbh;
if ( !$command || $command !~ /^(?:start|stop|restart|status|logrot|version)$/ )
{
if ( $command )
{
$dbh = zmDbConnect();
# Check to see if it's a valid run state
my $sql = 'select * from States where Name = ?';
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $command )
or Fatal( "Can't execute: ".$sth->errstr() );
if ( $state = $sth->fetchrow_hashref() )
{
$state->{Name} = $command;
$state->{Definitions} = [];
foreach( split( /,/, $state->{Definition} ) )
{
my ( $id, $function, $enabled ) = split( /:/, $_ );
push( @{$state->{Definitions}},
{ Id=>$id, Function=>$function, Enabled=>$enabled }
);
}
$store_state=$command; # PP - Remember the name that was passed to search in DB
$command = 'state';
}
else
{
$command = undef;
}
}
if ( !$command )
{
pod2usage(-exitstatus => -1);
if ( !$command || $command !~ /^(?:start|stop|restart|status|logrot|version)$/ ) {
if ( $command ) {
$dbh = zmDbConnect();
# Check to see if it's a valid run state
my $sql = 'SELECT * FROM States WHERE Name=?';
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $command )
or Fatal( "Can't execute: ".$sth->errstr() );
if ( $state = $sth->fetchrow_hashref() ) {
$state->{Name} = $command;
$state->{Definitions} = [];
foreach( split( /,/, $state->{Definition} ) ) {
my ( $id, $function, $enabled ) = split( /:/, $_ );
push( @{$state->{Definitions}},
{ Id=>$id, Function=>$function, Enabled=>$enabled }
);
}
$store_state=$command; # PP - Remember the name that was passed to search in DB
$command = 'state';
} else {
$command = undef;
}
}
if ( !$command ) {
pod2usage(-exitstatus => -1);
}
}
$dbh = zmDbConnect() if ! $dbh;
# PP - Sane state check
@ -110,324 +89,297 @@ isActiveSanityCheck();
# Move to the right place
chdir( $Config{ZM_PATH_WEB} )
or Fatal( "Can't chdir to '".$Config{ZM_PATH_WEB}."': $!" );
or Fatal( "Can't chdir to '".$Config{ZM_PATH_WEB}."': $!" );
my $dbg_id = "";
my $dbg_id = '';
Info( "Command: $command\n" );
Info( "Command: $command\n" );
my $retval = 0;
my $retval = 0;
if ( $command eq "state" )
{
if ( $command eq 'state' ) {
Info( "Updating DB: $state->{Name}\n" );
my $sql = $Config{ZM_SERVER_ID} ? 'SELECT * FROM Monitors WHERE ServerId=? ORDER BY Id ASC' : 'SELECT * FROM Monitors ORDER BY Id ASC';
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID}: () )
or Fatal( "Can't execute: ".$sth->errstr() );
while( my $monitor = $sth->fetchrow_hashref() )
{
foreach my $definition ( @{$state->{Definitions}} )
{
if ( $monitor->{Id} =~ /^$definition->{Id}$/ )
{
$monitor->{NewFunction} = $definition->{Function};
$monitor->{NewEnabled} = $definition->{Enabled};
}
}
#next if ( !$monitor->{NewFunction} );
$monitor->{NewFunction} = 'None'
if ( !$monitor->{NewFunction} );
$monitor->{NewEnabled} = 0
if ( !$monitor->{NewEnabled} );
if ( $monitor->{Function} ne $monitor->{NewFunction}
|| $monitor->{Enabled} ne $monitor->{NewEnabled}
)
{
my $sql = "update Monitors set Function = ?, Enabled = ? where Id = ?";
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $monitor->{NewFunction}, $monitor->{NewEnabled}, $monitor->{Id} )
or Fatal( "Can't execute: ".$sth->errstr() );
or Fatal( "Can't execute: ".$sth->errstr() );
while( my $monitor = $sth->fetchrow_hashref() ) {
foreach my $definition ( @{$state->{Definitions}} ) {
if ( $monitor->{Id} =~ /^$definition->{Id}$/ ) {
$monitor->{NewFunction} = $definition->{Function};
$monitor->{NewEnabled} = $definition->{Enabled};
}
}
#next if ( !$monitor->{NewFunction} );
$monitor->{NewFunction} = 'None'
if ( !$monitor->{NewFunction} );
$monitor->{NewEnabled} = 0
if ( !$monitor->{NewEnabled} );
if ( $monitor->{Function} ne $monitor->{NewFunction}
|| $monitor->{Enabled} ne $monitor->{NewEnabled}
) {
my $sql = 'UPDATE Monitors SET Function=?, Enabled=? WHERE Id=?';
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $monitor->{NewFunction}, $monitor->{NewEnabled}, $monitor->{Id} )
or Fatal( "Can't execute: ".$sth->errstr() );
}
}
$sth->finish();
# PP - Now mark a specific state as active
# PP - Now mark a specific state as active
resetStates();
Info ("Marking $store_state as Enabled");
$sql = "update States set IsActive = '1' where Name = ?";
$sql = "UPDATE States SET IsActive = '1' WHERE Name = ?";
$sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute( $store_state )
or Fatal( "Can't execute: ".$sth->errstr() );
or Fatal( "Can't execute: ".$sth->errstr() );
# PP - zero out other states isActive
$command = "restart";
}
# PP - zero out other states isActive
$command = 'restart';
}
# Check if we are running systemd and if we have been called by the system
if ( $command =~ /^(start|stop|restart)$/ )
{
# We have to detaint to keep perl from complaining
$command = $1;
if ( $command =~ /^(start|stop|restart)$/ ) {
# We have to detaint to keep perl from complaining
$command = $1;
if ( systemdRunning() && !calledBysystem() ) {
qx(@BINDIR@/zmsystemctl.pl $command);
$command = "";
}
if ( systemdRunning() && !calledBysystem() ) {
qx(@BINDIR@/zmsystemctl.pl $command);
$command = '';
}
}
if ( $command =~ /^(?:stop|restart)$/ )
{
my $status = runCommand( "zmdc.pl check" );
if ( $command =~ /^(?:stop|restart)$/ ) {
my $status = runCommand('zmdc.pl check');
if ( $status eq "running" )
{
runCommand( "zmdc.pl shutdown" );
zmMemTidy();
}
else
{
$retval = 1;
}
if ( $status eq 'running' ) {
runCommand('zmdc.pl shutdown');
zmMemTidy();
} else {
$retval = 1;
}
}
#runCommand( "zmupdate.pl -f" );
if ( $command =~ /^(?:start|restart)$/ )
{
my $status = runCommand( "zmdc.pl check" );
if ( $command =~ /^(?:start|restart)$/ ) {
my $status = runCommand('zmdc.pl check');
if ( $status eq "stopped" )
{
if ( $Config{ZM_DYN_DB_VERSION}
and ( $Config{ZM_DYN_DB_VERSION} ne ZM_VERSION )
)
{
Fatal( "Version mismatch, system is version ".ZM_VERSION
.", database is ".$Config{ZM_DYN_DB_VERSION}
.", please run zmupdate.pl to update."
);
exit( -1 );
}
if ( $status eq 'stopped' ) {
if ( $Config{ZM_DYN_DB_VERSION}
and ( $Config{ZM_DYN_DB_VERSION} ne ZM_VERSION )
) {
Fatal( 'Version mismatch, system is version '.ZM_VERSION
.', database is '.$Config{ZM_DYN_DB_VERSION}
.', please run zmupdate.pl to update.'
);
exit( -1 );
}
# Recreate the temporary directory if it's been wiped
verifyFolder("@ZM_TMPDIR@");
# Recreate the temporary directory if it's been wiped
verifyFolder('@ZM_TMPDIR@');
# Recreate the run directory if it's been wiped
verifyFolder("@ZM_RUNDIR@");
# Recreate the run directory if it's been wiped
verifyFolder('@ZM_RUNDIR@');
# Recreate the sock directory if it's been wiped
verifyFolder("@ZM_SOCKDIR@");
# Recreate the sock directory if it's been wiped
verifyFolder('@ZM_SOCKDIR@');
zmMemTidy();
runCommand( "zmdc.pl startup" );
zmMemTidy();
runCommand('zmdc.pl startup');
if ( $Config{ZM_SERVER_ID} ) {
Info( "Multi-server configuration detected. Starting up services for server $Config{ZM_SERVER_ID}\n");
if ( $Config{ZM_SERVER_ID} ) {
Info("Multi-server configuration detected. Starting up services for server $Config{ZM_SERVER_ID}\n");
} else {
Info('Single server configuration detected. Starting up services.');
}
my $sql = $Config{ZM_SERVER_ID} ? 'SELECT * FROM Monitors WHERE ServerId=?' : 'SELECT * FROM Monitors';
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID} : () )
or Fatal( "Can't execute: ".$sth->errstr() );
while( my $monitor = $sth->fetchrow_hashref() ) {
if ( $monitor->{Function} ne 'None' ) {
if ( $monitor->{Type} eq 'Local' ) {
runCommand( "zmdc.pl start zmc -d $monitor->{Device}" );
} else {
Info( "Single server configuration detected. Starting up services." );
runCommand( "zmdc.pl start zmc -m $monitor->{Id}" );
}
my $sql = $Config{ZM_SERVER_ID} ? 'SELECT * FROM Monitors WHERE ServerId=?' : 'SELECT * FROM Monitors';
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID} : () )
or Fatal( "Can't execute: ".$sth->errstr() );
while( my $monitor = $sth->fetchrow_hashref() )
{
if ( $monitor->{Function} ne 'None' )
{
if ( $monitor->{Type} eq 'Local' )
{
runCommand( "zmdc.pl start zmc -d $monitor->{Device}" );
}
else
{
runCommand( "zmdc.pl start zmc -m $monitor->{Id}" );
}
if ( $monitor->{Function} ne 'Monitor' )
{
runCommand( "zmdc.pl start zma -m $monitor->{Id}" );
}
if ( $Config{ZM_OPT_CONTROL} )
{
if ( $monitor->{Function} eq 'Modect' || $monitor->{Function} eq 'Mocord' )
{
if ( $monitor->{Controllable} && $monitor->{TrackMotion} )
{
runCommand( "zmdc.pl start zmtrack.pl -m $monitor->{Id}" );
}
}
}
if ( $monitor->{Function} ne 'Monitor' ) {
runCommand( "zmdc.pl start zma -m $monitor->{Id}" );
}
if ( $Config{ZM_OPT_CONTROL} ) {
if ( $monitor->{Function} eq 'Modect' || $monitor->{Function} eq 'Mocord' ) {
if ( $monitor->{Controllable} && $monitor->{TrackMotion} ) {
runCommand( "zmdc.pl start zmtrack.pl -m $monitor->{Id}" );
}
}
}
$sth->finish();
}
}
$sth->finish();
# This is now started unconditionally
runCommand( "zmdc.pl start zmfilter.pl" );
if ( $Config{ZM_RUN_AUDIT} )
{
runCommand( "zmdc.pl start zmaudit.pl -c" );
}
if ( $Config{ZM_OPT_TRIGGERS} )
{
runCommand( "zmdc.pl start zmtrigger.pl" );
}
if ( $Config{ZM_OPT_X10} )
{
runCommand( "zmdc.pl start zmx10.pl -c start" );
}
runCommand( "zmdc.pl start zmwatch.pl" );
if ( $Config{ZM_CHECK_FOR_UPDATES} )
{
runCommand( "zmdc.pl start zmupdate.pl -c" );
}
if ( $Config{ZM_TELEMETRY_DATA} )
{
runCommand( "zmdc.pl start zmtelemetry.pl" );
}
# This is now started unconditionally
runCommand('zmdc.pl start zmfilter.pl');
if ( $Config{ZM_RUN_AUDIT} ) {
runCommand('zmdc.pl start zmaudit.pl -c');
}
else
{
$retval = 1;
if ( $Config{ZM_OPT_TRIGGERS} ) {
runCommand('zmdc.pl start zmtrigger.pl');
}
if ( $Config{ZM_OPT_X10} ) {
runCommand('zmdc.pl start zmx10.pl -c start');
}
runCommand('zmdc.pl start zmwatch.pl');
if ( $Config{ZM_CHECK_FOR_UPDATES} ) {
runCommand('zmdc.pl start zmupdate.pl -c');
}
if ( $Config{ZM_TELEMETRY_DATA} ) {
runCommand('zmdc.pl start zmtelemetry.pl');
}
} else {
$retval = 1;
}
}
if ( $command eq "status" )
{
my $status = runCommand( "zmdc.pl check" );
if ( $command eq 'status' ) {
my $status = runCommand('zmdc.pl check');
print( STDOUT $status."\n" );
}
if ( $command eq "logrot" )
{
runCommand( "zmdc.pl logrot" );
print( STDOUT $status."\n" );
} elsif ( $command eq 'logrot' ) {
runCommand('zmdc.pl logrot');
}
exit( $retval );
# PP - Make sure isActive is on and only one
sub isActiveSanityCheck
{
sub isActiveSanityCheck {
Info ("Sanity checking States table...");
$dbh = zmDbConnect() if ! $dbh;
Info ('Sanity checking States table...');
$dbh = zmDbConnect() if ! $dbh;
# PP - First, make sure default exists and there is only one
my $sql = "select Name from States where Name = 'default'";
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
# PP - First, make sure default exists and there is only one
my $sql = "SELECT Name FROM States WHERE Name='default'";
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
if ($sth->rows != 1) # PP - no row, or too many rows. Either case is an error
{
Info( "Fixing States table - either no default state or duplicate default states" );
$sql = "delete from States where Name = 'default'";
$sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
$sql = "insert into States (Name,Definition,IsActive) VALUES ('default','','1');";
$sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
}
if ($sth->rows != 1) {
# PP - no row, or too many rows. Either case is an error
Info( 'Fixing States table - either no default state or duplicate default states' );
$sql = "DELETE FROM States WHERE Name='default'";
$sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
$sql = "INSERT INTO States (Name,Definition,IsActive) VALUES ('default','','1');";
$sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
}
# PP - Now make sure no two states have IsActive=1
$sql = "select Name from States where IsActive = '1'";
$sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
# PP - Now make sure no two states have IsActive=1
$sql = "SELECT Name FROM States WHERE IsActive = '1'";
$sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
if ( $sth->rows != 1 )
{
Info( "Fixing States table so only one run state is active" );
resetStates();
$sql = "update States set IsActive='1' WHERE Name='default'";
$sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
}
if ( $sth->rows != 1 ) {
Info( 'Fixing States table so only one run state is active' );
resetStates();
$sql = "UPDATE States SET IsActive='1' WHERE Name='default'";
$sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
}
}
# PP - zeroes out isActive for all states
sub resetStates
{
$dbh = zmDbConnect() if ! $dbh;
my $sql = "update States set IsActive = '0'";
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
sub resetStates {
$dbh = zmDbConnect() if ! $dbh;
my $sql = "UPDATE States SET IsActive='0'";
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() );
}
sub systemdRunning
{
my $result = 0;
sub systemdRunning {
my $result = 0;
my $output = qx(ps -o comm="" -p 1);
chomp( $output );
my $output = qx(ps -o comm="" -p 1);
chomp( $output );
if ($output =~ /systemd/) {
$result = 1;
if ( $output =~ /systemd/ ) {
$result = 1;
}
return $result;
}
sub calledBysystem {
my $result = 0;
my $ppid = getppid();
my $output = qx(ps -o comm="" -p $ppid);
chomp( $output );
if ($output =~ /^(?:systemd|init)$/) {
$result = 1;
}
return $result;
}
sub verifyFolder {
my $folder = shift;
# Recreate the temporary directory if it's been wiped
if ( !-e $folder ) {
Debug( "Recreating directory '$folder'" );
mkdir( $folder, 0774 )
or Fatal( "Can't create missing temporary directory '$folder': $!" );
my ( $runName ) = getpwuid( $> );
if ( $runName ne $Config{ZM_WEB_USER} ) {
# Not running as web user, so should be root in which case
# chown the directory
my ( $webName, $webPass, $webUid, $webGid ) = getpwnam( $Config{ZM_WEB_USER} )
or Fatal( "Can't get user details for web user '"
.$Config{ZM_WEB_USER}."': $!"
);
chown( $webUid, $webGid, "$folder" )
or Fatal( "Can't change ownership of directory '$folder' to '"
.$Config{ZM_WEB_USER}.":".$Config{ZM_WEB_GROUP}."': $!"
);
}
return $result;
}
}
sub calledBysystem
{
my $result = 0;
my $ppid = getppid();
my $output = qx(ps -o comm="" -p $ppid);
chomp( $output );
if ($output =~ /^(?:systemd|init)$/) {
$result = 1;
}
return $result;
}
sub verifyFolder
{
my $folder = shift;
# Recreate the temporary directory if it's been wiped
if ( !-e $folder )
{
Debug( "Recreating directory '$folder'" );
mkdir( "$folder", 0774 )
or Fatal( "Can't create missing temporary directory '$folder': $!" );
my ( $runName ) = getpwuid( $> );
if ( $runName ne $Config{ZM_WEB_USER} )
{
# Not running as web user, so should be root in which case
# chown the directory
my ( $webName, $webPass, $webUid, $webGid ) = getpwnam( $Config{ZM_WEB_USER} )
or Fatal( "Can't get user details for web user '"
.$Config{ZM_WEB_USER}."': $!"
);
chown( $webUid, $webGid, "$folder" )
or Fatal( "Can't change ownership of directory '$folder' to '"
.$Config{ZM_WEB_USER}.":".$Config{ZM_WEB_GROUP}."': $!"
);
}
}
}
1;
__END__
=head1 NAME
zmpkg.pl - ZoneMinder Package Control Script
=head1 SYNOPSIS
zmpkg.pl {start|stop|restart|status|logrot|'state'|version}
=head1 DESCRIPTION
This script is used to start and stop the ZoneMinder package primarily to
allow command line control for automatic restart on reboot (see zm script)
=cut

View File

@ -55,6 +55,7 @@ use constant START_DELAY => 30; # To give everything else time to start
@EXTRA_PERL_LIB@
use ZoneMinder;
use ZoneMinder::Storage;
use POSIX;
use DBI;
use autouse 'Data::Dumper'=>qw(Dumper);
@ -78,24 +79,42 @@ my $sql = $Config{ZM_SERVER_ID} ? 'SELECT * FROM Monitors WHERE ServerId=?' : 'S
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $eventcounts_sql = q`
UPDATE Monitors SET
TotalEvents=(SELECT COUNT(Id) FROM Events WHERE MonitorId=Monitors.Id),
TotalEventDiskSpace=(SELECT SUM(DiskSpace) FROM Events WHERE MonitorId=Monitors.Id AND DiskSpace IS NOT NULL),
HourEvents=(SELECT COUNT(Id) FROM Events WHERE MonitorId=Monitors.Id AND StartTime > DATE_SUB( NOW(), INTERVAL 1 hour) ),
HourEventDiskSpace=(SELECT SUM(DiskSpace) FROM Events WHERE MonitorId=Monitors.Id AND StartTime > DATE_SUB(NOW(), INTERVAL 1 hour) AND DiskSpace IS NOT NULL),
DayEvents=(SELECT COUNT(Id) FROM Events WHERE MonitorId=Monitors.Id AND StartTime > DATE_SUB(NOW(), INTERVAL 1 day)),
DayEventDiskSpace=(SELECT SUM(DiskSpace) FROM Events WHERE MonitorId=Monitors.Id AND StartTime > DATE_SUB(NOW(), INTERVAL 1 day) AND DiskSpace IS NOT NULL),
WeekEvents=(SELECT COUNT(Id) FROM Events WHERE MonitorId=Monitors.Id AND StartTime > DATE_SUB(NOW(), INTERVAL 1 week)),
WeekEventDiskSpace=(SELECT SUM(DiskSpace) FROM Events WHERE MonitorId=Monitors.Id AND StartTime > DATE_SUB(NOW(), INTERVAL 1 week) AND DiskSpace IS NOT NULL),
MonthEvents=(SELECT COUNT(Id) FROM Events WHERE MonitorId=Monitors.Id AND StartTime > DATE_SUB( NOW(), INTERVAL 1 month)),
MonthEventDiskSpace=(SELECT SUM(DiskSpace) FROM Events WHERE MonitorId=Monitors.Id AND StartTime > DATE_SUB(NOW(), INTERVAL 1 month) AND DiskSpace IS NOT NULL),
ArchivedEvents=(SELECT COUNT(Id) FROM Events WHERE MonitorId=Monitors.Id AND Archived=1),
ArchivedEventDiskSpace=(SELECT SUM(DiskSpace) FROM Events WHERE MonitorId=Monitors.Id AND Archived=1 AND DiskSpace IS NOT NULL)
WHERE Id=?`;
my $eventcounts_sth = $dbh->prepare_cached( $eventcounts_sql );
while( 1 ) {
my $now = time();
my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID} : () )
or Fatal( "Can't execute: ".$sth->errstr() );
while( my $monitor = $sth->fetchrow_hashref() ) {
my $now = time();
next if $monitor->{Function} eq 'None';
my $restart = 0;
if ( zmMemVerify( $monitor ) ) {
# Check we have got an image recently
my $image_time = zmGetLastWriteTime( $monitor );
if ( !defined($image_time) ) {
my $capture_time = zmGetLastWriteTime( $monitor );
if ( !defined($capture_time) ) {
# Can't read from shared data
Debug( "LastWriteTime is not defined." );
zmMemInvalidate( $monitor );
next;
}
Debug( "LastWriteTime is = $image_time." );
if ( !$image_time ) {
Debug( "LastWriteTime is = $capture_time." );
if ( !$capture_time ) {
my $startup_time = zmGetStartupTime( $monitor );
if ( $now - $startup_time > $Config{ZM_WATCH_MAX_DELAY} ) {
Info( "Restarting capture daemon for ".$monitor->{Name}.", no image since startup. Startup time was $startup_time - now $now > $Config{ZM_WATCH_MAX_DELAY}\n" );
@ -103,7 +122,7 @@ while( 1 ) {
} else {
# We can't get the last capture time so can't be sure it's died, it might just be starting up.
zmMemInvalidate( $monitor );
next;
next;
}
}
if ( ! $restart ) {
@ -113,11 +132,11 @@ while( 1 ) {
) ? (3/$monitor->{MaxFPS})
: $Config{ZM_WATCH_MAX_DELAY}
;
my $image_delay = $now-$image_time;
my $image_delay = $now-$capture_time;
Debug( "Monitor $monitor->{Id} last captured $image_delay seconds ago, max is $max_image_delay\n" );
if ( $image_delay > $max_image_delay ) {
Info( "Restarting capture daemon for "
.$monitor->{Name}.", time since last capture $image_delay seconds ($now-$image_time)\n"
.$monitor->{Name}.", time since last capture $image_delay seconds ($now-$capture_time)\n"
);
$restart = 1;
}
@ -147,7 +166,7 @@ while( 1 ) {
} elsif ( !$image_time ) {
# We can't get the last capture time so can't be sure it's died.
$restart = 1;
Error( "Error getting last capture time for $$monitor{Id} $$monitor{Name}\n");
Error( "Error getting last analyse time for $$monitor{Id} $$monitor{Name}\n");
} else {
my $max_image_delay = ( $monitor->{MaxFPS}
@ -174,7 +193,23 @@ while( 1 ) {
} # end if check analysis daemon
# Prevent open handles building up if we have connect to shared memory
zmMemInvalidate( $monitor ); # Close our file handle to the zmc process we are about to end
$eventcounts_sth->execute( $$monitor{Id} ) or Error( "Can't execute: ".$eventcounts_sth->errstr() );
} # end foreach monitor
$eventcounts_sth->finish();
my $diskspace_sql = 'UPDATE Storage SET DiskSpace =(SELECT SUM(DiskSpace) FROM Events WHERE StorageId=? AND DiskSpace IS NOT NULL)';
my $diskspace_sth = $dbh->prepare_cached( $diskspace_sql )
or Fatal( "Can't prepare '$diskspace_sql': ".$dbh->errstr() );
foreach my $Storage ( ZoneMinder::Storage->find() ) {
Debug("Updating disk space for $$Storage{Name} was $$Storage{DiskSpace}");
$diskspace_sth->execute( $$Storage{Id} ) or Error( "Can't execute: ".$diskspace_sth->errstr() );
$Storage->load();
Debug("Updated disk space for $$Storage{Name} to $$Storage{DiskSpace}");
}
$diskspace_sth->finish();
sleep( $Config{ZM_WATCH_CHECK_INTERVAL} );
} # end while (1)

View File

@ -42,11 +42,10 @@
#include <sys/filio.h> // define FIONREAD
#endif
int CommsBase::readV( int iovcnt, /* const void *, int, */ ... )
{
int CommsBase::readV( int iovcnt, /* const void *, int, */ ... ) {
va_list arg_ptr;
//struct iovec iov[iovcnt];
struct iovec *iov = (struct iovec *)alloca( sizeof(struct iovec)*iovcnt );
struct iovec iov[iovcnt];
//struct iovec *iov = (struct iovec *)alloca( sizeof(struct iovec)*iovcnt );
va_start( arg_ptr, iovcnt );
for ( int i = 0; i < iovcnt; i++ )
@ -62,11 +61,10 @@ int CommsBase::readV( int iovcnt, /* const void *, int, */ ... )
return( nBytes );
}
int CommsBase::writeV( int iovcnt, /* const void *, int, */ ... )
{
int CommsBase::writeV( int iovcnt, /* const void *, int, */ ... ) {
va_list arg_ptr;
//struct iovec iov[iovcnt];
struct iovec *iov = (struct iovec *)alloca( sizeof(struct iovec)*iovcnt );
struct iovec iov[iovcnt];
//struct iovec *iov = (struct iovec *)alloca( sizeof(struct iovec)*iovcnt );
va_start( arg_ptr, iovcnt );
for ( int i = 0; i < iovcnt; i++ )

View File

@ -37,26 +37,20 @@
#include <netinet/in.h>
#endif
class CommsException : public Exception
{
class CommsException : public Exception {
public:
CommsException( const std::string &message ) : Exception( message )
{
}
explicit CommsException( const std::string &message ) : Exception( message ) { }
};
class CommsBase
{
class CommsBase {
protected:
const int &mRd;
const int &mWd;
protected:
CommsBase( int &rd, int &wd ) : mRd( rd ), mWd( wd )
{
CommsBase( int &rd, int &wd ) : mRd( rd ), mWd( wd ) {
}
virtual ~CommsBase()
{
virtual ~CommsBase() {
}
public:
@ -66,42 +60,35 @@ public:
virtual bool setBlocking( bool blocking )=0;
public:
int getReadDesc() const
{
int getReadDesc() const {
return( mRd );
}
int getWriteDesc() const
{
int getWriteDesc() const {
return( mWd );
}
int getMaxDesc() const
{
int getMaxDesc() const {
return( mRd>mWd?mRd:mWd );
}
virtual int read( void *msg, int len )
{
virtual int read( void *msg, int len ) {
ssize_t nBytes = ::read( mRd, msg, len );
if ( nBytes < 0 )
Debug( 1, "Read of %d bytes max on rd %d failed: %s", len, mRd, strerror(errno) );
return( nBytes );
}
virtual int write( const void *msg, int len )
{
virtual int write( const void *msg, int len ) {
ssize_t nBytes = ::write( mWd, msg, len );
if ( nBytes < 0 )
Debug( 1, "Write of %d bytes on wd %d failed: %s", len, mWd, strerror(errno) );
return( nBytes );
}
virtual int readV( const struct iovec *iov, int iovcnt )
{
virtual int readV( const struct iovec *iov, int iovcnt ) {
int nBytes = ::readv( mRd, iov, iovcnt );
if ( nBytes < 0 )
Debug( 1, "Readv of %d buffers max on rd %d failed: %s", iovcnt, mRd, strerror(errno) );
return( nBytes );
}
virtual int writeV( const struct iovec *iov, int iovcnt )
{
virtual int writeV( const struct iovec *iov, int iovcnt ) {
ssize_t nBytes = ::writev( mWd, iov, iovcnt );
if ( nBytes < 0 )
Debug( 1, "Writev of %d buffers on wd %d failed: %s", iovcnt, mWd, strerror(errno) );
@ -111,19 +98,16 @@ public:
virtual int writeV( int iovcnt, /* const void *msg1, int len1, */ ... );
};
class Pipe : public CommsBase
{
class Pipe : public CommsBase {
protected:
int mFd[2];
public:
Pipe() : CommsBase( mFd[0], mFd[1] )
{
Pipe() : CommsBase( mFd[0], mFd[1] ) {
mFd[0] = -1;
mFd[1] = -1;
}
~Pipe()
{
~Pipe() {
close();
}
@ -147,46 +131,39 @@ public:
bool setBlocking( bool blocking );
};
class SockAddr
{
class SockAddr {
private:
const struct sockaddr *mAddr;
public:
SockAddr( const struct sockaddr *addr );
virtual ~SockAddr()
{
explicit SockAddr( const struct sockaddr *addr );
virtual ~SockAddr() {
}
static SockAddr *newSockAddr( const struct sockaddr &addr, socklen_t len );
static SockAddr *newSockAddr( const SockAddr *addr );
int getDomain() const
{
int getDomain() const {
return( mAddr?mAddr->sa_family:AF_UNSPEC );
}
const struct sockaddr *getAddr() const
{
const struct sockaddr *getAddr() const {
return( mAddr );
}
virtual socklen_t getAddrSize() const=0;
virtual struct sockaddr *getTempAddr() const=0;
};
class SockAddrInet : public SockAddr
{
class SockAddrInet : public SockAddr {
private:
struct sockaddr_in mAddrIn;
struct sockaddr_in mTempAddrIn;
public:
SockAddrInet();
SockAddrInet( const SockAddrInet &addr ) : SockAddr( (const struct sockaddr *)&mAddrIn ), mAddrIn( addr.mAddrIn )
{
explicit SockAddrInet( const SockAddrInet &addr ) : SockAddr( (const struct sockaddr *)&mAddrIn ), mAddrIn( addr.mAddrIn ) {
}
SockAddrInet( const struct sockaddr_in *addr ) : SockAddr( (const struct sockaddr *)&mAddrIn ), mAddrIn( *addr )
{
explicit SockAddrInet( const struct sockaddr_in *addr ) : SockAddr( (const struct sockaddr *)&mAddrIn ), mAddrIn( *addr ) {
}
@ -195,57 +172,47 @@ public:
bool resolve( const char *serv, const char *proto );
bool resolve( int port, const char *proto );
socklen_t getAddrSize() const
{
socklen_t getAddrSize() const {
return( sizeof(mAddrIn) );
}
struct sockaddr *getTempAddr() const
{
struct sockaddr *getTempAddr() const {
return( (sockaddr *)&mTempAddrIn );
}
public:
static socklen_t addrSize()
{
static socklen_t addrSize() {
return( sizeof(sockaddr_in) );
}
};
class SockAddrUnix : public SockAddr
{
class SockAddrUnix : public SockAddr {
private:
struct sockaddr_un mAddrUn;
struct sockaddr_un mTempAddrUn;
public:
SockAddrUnix();
SockAddrUnix( const SockAddrUnix &addr ) : SockAddr( (const struct sockaddr *)&mAddrUn ), mAddrUn( addr.mAddrUn )
{
SockAddrUnix( const SockAddrUnix &addr ) : SockAddr( (const struct sockaddr *)&mAddrUn ), mAddrUn( addr.mAddrUn ) {
}
SockAddrUnix( const struct sockaddr_un *addr ) : SockAddr( (const struct sockaddr *)&mAddrUn ), mAddrUn( *addr )
{
SockAddrUnix( const struct sockaddr_un *addr ) : SockAddr( (const struct sockaddr *)&mAddrUn ), mAddrUn( *addr ) {
}
bool resolve( const char *path, const char *proto );
socklen_t getAddrSize() const
{
socklen_t getAddrSize() const {
return( sizeof(mAddrUn) );
}
struct sockaddr *getTempAddr() const
{
struct sockaddr *getTempAddr() const {
return( (sockaddr *)&mTempAddrUn );
}
public:
static socklen_t addrSize()
{
static socklen_t addrSize() {
return( sizeof(sockaddr_un) );
}
};
class Socket : public CommsBase
{
class Socket : public CommsBase {
protected:
typedef enum { CLOSED, DISCONNECTED, LISTENING, CONNECTED } State;
@ -256,45 +223,37 @@ protected:
SockAddr *mRemoteAddr;
protected:
Socket() : CommsBase( mSd, mSd ), mSd( -1 ), mState( CLOSED ), mLocalAddr( 0 ), mRemoteAddr( 0 )
{
Socket() : CommsBase( mSd, mSd ), mSd( -1 ), mState( CLOSED ), mLocalAddr( 0 ), mRemoteAddr( 0 ) {
}
Socket( const Socket &socket, int newSd ) : CommsBase( mSd, mSd ), mSd( newSd ), mState( CONNECTED ), mLocalAddr( 0 ), mRemoteAddr( 0 )
{
Socket( const Socket &socket, int newSd ) : CommsBase( mSd, mSd ), mSd( newSd ), mState( CONNECTED ), mLocalAddr( 0 ), mRemoteAddr( 0 ) {
if ( socket.mLocalAddr )
mLocalAddr = SockAddr::newSockAddr( mLocalAddr );
if ( socket.mRemoteAddr )
mRemoteAddr = SockAddr::newSockAddr( mRemoteAddr );
}
virtual ~Socket()
{
virtual ~Socket() {
close();
delete mLocalAddr;
delete mRemoteAddr;
}
public:
bool isOpen() const
{
bool isOpen() const {
return( !isClosed() );
}
bool isClosed() const
{
bool isClosed() const {
return( mState == CLOSED );
}
bool isDisconnected() const
{
bool isDisconnected() const {
return( mState == DISCONNECTED );
}
bool isConnected() const
{
bool isConnected() const {
return( mState == CONNECTED );
}
virtual bool close();
protected:
bool isListening() const
{
bool isListening() const {
return( mState == LISTENING );
}
@ -309,33 +268,28 @@ protected:
virtual bool accept( int & );
public:
virtual int send( const void *msg, int len ) const
{
virtual int send( const void *msg, int len ) const {
ssize_t nBytes = ::send( mSd, msg, len, 0 );
if ( nBytes < 0 )
Debug( 1, "Send of %d bytes on sd %d failed: %s", len, mSd, strerror(errno) );
return( nBytes );
}
virtual int recv( void *msg, int len ) const
{
virtual int recv( void *msg, int len ) const {
ssize_t nBytes = ::recv( mSd, msg, len, 0 );
if ( nBytes < 0 )
Debug( 1, "Recv of %d bytes max on sd %d failed: %s", len, mSd, strerror(errno) );
return( nBytes );
}
virtual int send( const std::string &msg ) const
{
virtual int send( const std::string &msg ) const {
ssize_t nBytes = ::send( mSd, msg.data(), msg.size(), 0 );
if ( nBytes < 0 )
Debug( 1, "Send of string '%s' (%zd bytes) on sd %d failed: %s", msg.c_str(), msg.size(), mSd, strerror(errno) );
return( nBytes );
}
virtual int recv( std::string &msg ) const
{
virtual int recv( std::string &msg ) const {
char buffer[msg.capacity()];
int nBytes = 0;
if ( (nBytes = ::recv( mSd, buffer, sizeof(buffer), 0 )) < 0 )
{
if ( (nBytes = ::recv( mSd, buffer, sizeof(buffer), 0 )) < 0 ) {
Debug( 1, "Recv of %zd bytes max to string on sd %d failed: %s", sizeof(buffer), mSd, strerror(errno) );
return( nBytes );
}
@ -343,12 +297,10 @@ public:
msg = buffer;
return( nBytes );
}
virtual int recv( std::string &msg, size_t maxLen ) const
{
virtual int recv( std::string &msg, size_t maxLen ) const {
char buffer[maxLen];
int nBytes = 0;
if ( (nBytes = ::recv( mSd, buffer, sizeof(buffer), 0 )) < 0 )
{
if ( (nBytes = ::recv( mSd, buffer, sizeof(buffer), 0 )) < 0 ) {
Debug( 1, "Recv of %zd bytes max to string on sd %d failed: %s", maxLen, mSd, strerror(errno) );
return( nBytes );
}
@ -358,8 +310,7 @@ public:
}
virtual int bytesToRead() const;
int getDesc() const
{
int getDesc() const {
return( mSd );
}
//virtual bool isOpen() const
@ -371,12 +322,10 @@ public:
virtual int getType() const=0;
virtual const char *getProtocol() const=0;
const SockAddr *getLocalAddr() const
{
const SockAddr *getLocalAddr() const {
return( mLocalAddr );
}
const SockAddr *getRemoteAddr() const
{
const SockAddr *getRemoteAddr() const {
return( mRemoteAddr );
}
virtual socklen_t getAddrSize() const=0;
@ -403,12 +352,10 @@ protected:
int mAddressFamily;
public:
int getDomain() const
{
int getDomain() const {
return( mAddressFamily );
}
virtual socklen_t getAddrSize() const
{
virtual socklen_t getAddrSize() const {
return( SockAddrInet::addrSize() );
}
@ -422,58 +369,48 @@ protected:
bool bind( int port );
};
class UnixSocket : virtual public Socket
{
class UnixSocket : virtual public Socket {
public:
int getDomain() const
{
int getDomain() const {
return( AF_UNIX );
}
virtual socklen_t getAddrSize() const
{
virtual socklen_t getAddrSize() const {
return( SockAddrUnix::addrSize() );
}
protected:
bool resolveLocal( const char *serv, const char *proto )
{
bool resolveLocal( const char *serv, const char *proto ) {
SockAddrUnix *addr = new SockAddrUnix;
mLocalAddr = addr;
return( addr->resolve( serv, proto ) );
}
bool resolveRemote( const char *path, const char *proto )
{
bool resolveRemote( const char *path, const char *proto ) {
SockAddrUnix *addr = new SockAddrUnix;
mRemoteAddr = addr;
return( addr->resolve( path, proto ) );
}
protected:
bool bind( const char *path )
{
bool bind( const char *path ) {
if ( !UnixSocket::resolveLocal( path, getProtocol() ) )
return( false );
return( Socket::bind() );
}
bool connect( const char *path )
{
bool connect( const char *path ) {
if ( !UnixSocket::resolveRemote( path, getProtocol() ) )
return( false );
return( Socket::connect() );
}
};
class UdpSocket : virtual public Socket
{
class UdpSocket : virtual public Socket {
public:
int getType() const
{
int getType() const {
return( SOCK_DGRAM );
}
const char *getProtocol() const
{
const char *getProtocol() const {
return( "udp" );
}
@ -492,8 +429,6 @@ public:
nBytes = ::recvfrom( mSd, msg, len, 0, &sockAddr, &sockLen );
if ( nBytes < 0 ) {
Debug( 1, "Recvfrom of %d bytes max on sd %d (with address) failed: %s", len, mSd, strerror(errno) );
} else if ( sockLen ) {
addr = SockAddr::newSockAddr( sockAddr, sockLen );
}
} else {
nBytes = ::recvfrom( mSd, msg, len, 0, NULL, 0 );
@ -504,194 +439,150 @@ public:
}
};
class UdpInetSocket : virtual public UdpSocket, virtual public InetSocket
{
class UdpInetSocket : virtual public UdpSocket, virtual public InetSocket {
public:
bool bind( const char *host, const char *serv )
{
bool bind( const char *host, const char *serv ) {
return( InetSocket::bind( host, serv ) );
}
bool bind( const char *host, int port )
{
bool bind( const char *host, int port ) {
return( InetSocket::bind( host, port ) );
}
bool bind( const char *serv )
{
bool bind( const char *serv ) {
return( InetSocket::bind( serv ) );
}
bool bind( int port )
{
bool bind( int port ) {
return( InetSocket::bind( port ) );
}
bool connect( const char *host, const char *serv )
{
bool connect( const char *host, const char *serv ) {
return( InetSocket::connect( host, serv ) );
}
bool connect( const char *host, int port )
{
bool connect( const char *host, int port ) {
return( InetSocket::connect( host, port ) );
}
};
class UdpUnixSocket : virtual public UdpSocket, virtual public UnixSocket
{
class UdpUnixSocket : virtual public UdpSocket, virtual public UnixSocket {
public:
bool bind( const char *path )
{
bool bind( const char *path ) {
return( UnixSocket::bind( path ) );
}
bool connect( const char *path )
{
bool connect( const char *path ) {
return( UnixSocket::connect( path ) );
}
};
class UdpInetClient : public UdpInetSocket
{
class UdpInetClient : public UdpInetSocket {
public:
bool connect( const char *host, const char *serv )
{
bool connect( const char *host, const char *serv ) {
return( UdpInetSocket::connect( host, serv ) );
}
bool connect( const char *host, int port )
{
bool connect( const char *host, int port ) {
return( UdpInetSocket::connect( host, port ) );
}
};
class UdpUnixClient : public UdpUnixSocket
{
class UdpUnixClient : public UdpUnixSocket {
public:
bool bind( const char *path )
{
bool bind( const char *path ) {
return( UdpUnixSocket::bind( path ) );
}
public:
bool connect( const char *path )
{
bool connect( const char *path ) {
return( UdpUnixSocket::connect( path) );
}
};
class UdpInetServer : public UdpInetSocket
{
class UdpInetServer : public UdpInetSocket {
public:
bool bind( const char *host, const char *serv )
{
bool bind( const char *host, const char *serv ) {
return( UdpInetSocket::bind( host, serv ) );
}
bool bind( const char *host, int port )
{
bool bind( const char *host, int port ) {
return( UdpInetSocket::bind( host, port ) );
}
bool bind( const char *serv )
{
bool bind( const char *serv ) {
return( UdpInetSocket::bind( serv ) );
}
bool bind( int port )
{
bool bind( int port ) {
return( UdpInetSocket::bind( port ) );
}
protected:
bool connect( const char *host, const char *serv )
{
bool connect( const char *host, const char *serv ) {
return( UdpInetSocket::connect( host, serv ) );
}
bool connect( const char *host, int port )
{
bool connect( const char *host, int port ) {
return( UdpInetSocket::connect( host, port ) );
}
};
class UdpUnixServer : public UdpUnixSocket
{
class UdpUnixServer : public UdpUnixSocket {
public:
bool bind( const char *path )
{
bool bind( const char *path ) {
return( UdpUnixSocket::bind( path ) );
}
protected:
bool connect( const char *path )
{
bool connect( const char *path ) {
return( UdpUnixSocket::connect( path ) );
}
};
class TcpSocket : virtual public Socket
{
class TcpSocket : virtual public Socket {
public:
TcpSocket()
{
TcpSocket() {
}
TcpSocket( const TcpSocket &socket, int newSd ) : Socket( socket, newSd )
{
TcpSocket( const TcpSocket &socket, int newSd ) : Socket( socket, newSd ) {
}
public:
int getType() const
{
int getType() const {
return( SOCK_STREAM );
}
const char *getProtocol() const
{
const char *getProtocol() const {
return( "tcp" );
}
};
class TcpInetSocket : virtual public TcpSocket, virtual public InetSocket
{
class TcpInetSocket : virtual public TcpSocket, virtual public InetSocket {
public:
TcpInetSocket()
{
TcpInetSocket() {
}
TcpInetSocket( const TcpInetSocket &socket, int newSd ) : TcpSocket( socket, newSd )
{
TcpInetSocket( const TcpInetSocket &socket, int newSd ) : TcpSocket( socket, newSd ) {
}
};
class TcpUnixSocket : virtual public TcpSocket, virtual public UnixSocket
{
class TcpUnixSocket : virtual public TcpSocket, virtual public UnixSocket {
public:
TcpUnixSocket()
{
TcpUnixSocket() {
}
TcpUnixSocket( const TcpUnixSocket &socket, int newSd ) : TcpSocket( socket, newSd )
{
TcpUnixSocket( const TcpUnixSocket &socket, int newSd ) : TcpSocket( socket, newSd ) {
}
};
class TcpInetClient : public TcpInetSocket
{
class TcpInetClient : public TcpInetSocket {
public:
bool connect( const char *host, const char *serv )
{
bool connect( const char *host, const char *serv ) {
return( TcpInetSocket::connect( host, serv ) );
}
bool connect( const char *host, int port )
{
bool connect( const char *host, int port ) {
return( TcpInetSocket::connect( host, port ) );
}
};
class TcpUnixClient : public TcpUnixSocket
{
class TcpUnixClient : public TcpUnixSocket {
public:
bool connect( const char *path )
{
bool connect( const char *path ) {
return( TcpUnixSocket::connect( path) );
}
};
class TcpInetServer : public TcpInetSocket
{
class TcpInetServer : public TcpInetSocket {
public:
bool bind( int port )
{
bool bind( int port ) {
return( TcpInetSocket::bind( port ) );
}
@ -702,11 +593,9 @@ public:
bool accept( TcpInetSocket *&newSocket );
};
class TcpUnixServer : public TcpUnixSocket
{
class TcpUnixServer : public TcpUnixSocket {
public:
bool bind( const char *path )
{
bool bind( const char *path ) {
return( TcpUnixSocket::bind( path ) );
}
@ -717,8 +606,7 @@ public:
bool accept( TcpUnixSocket *&newSocket );
};
class Select
{
class Select {
public:
typedef std::set<CommsBase *> CommsSet;
typedef std::vector<CommsBase *> CommsList;

View File

@ -229,10 +229,13 @@ ConfigItem::ConfigItem( const ConfigItem &item ) {
accessed = false;
}
void ConfigItem::Copy( const ConfigItem &item ) {
if (name) delete name;
name = new char[strlen(item.name)+1];
strcpy( name, item.name );
if (value) delete value;
value = new char[strlen(item.value)+1];
strcpy( value, item.value );
if (type) delete type;
type = new char[strlen(item.type)+1];
strcpy( type, item.type );

View File

@ -110,12 +110,16 @@ public:
ConfigItem(const char *p_name, const char *p_value, const char *const p_type);
ConfigItem(const ConfigItem &);
~ConfigItem();
void Copy(const ConfigItem&);
void ConvertValue() const;
bool BooleanValue() const;
int IntegerValue() const;
double DecimalValue() const;
const char *StringValue() const;
ConfigItem &operator=(const ConfigItem item) {
Copy(item);return *this;
}
inline operator bool() const {
return BooleanValue();
}

View File

@ -236,10 +236,10 @@ int cURLCamera::Capture( Image &image ) {
if(!SubHeadersParsingComplete) {
/* We haven't parsed all headers yet */
need_more_data = true;
} else if(frame_content_length <= 0) {
} else if ( ! frame_content_length ) {
/* Invalid frame */
Error("Invalid frame: invalid content length");
} else if(frame_content_type != "image/jpeg") {
} else if ( frame_content_type != "image/jpeg" ) {
/* Unsupported frame type */
Error("Unsupported frame: %s",frame_content_type.c_str());
} else if(frame_content_length > databuffer.size()) {

View File

@ -28,8 +28,9 @@ MYSQL dbconn;
int zmDbConnected = false;
void zmDbConnect() {
if ( zmDbConnected )
return;
// For some reason having these lines causes memory corruption and crashing on newer debian/ubuntu
//if ( zmDbConnected )
//return;
if ( !mysql_init( &dbconn ) ) {
Error( "Can't initialise database connection: %s", mysql_error( &dbconn ) );

View File

@ -71,7 +71,7 @@ Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string
static char sql[ZM_SQL_MED_BUFSIZ];
struct tm *stime = localtime( &start_time.tv_sec );
snprintf( sql, sizeof(sql), "insert into Events ( MonitorId, StorageId, Name, StartTime, Width, Height, Cause, Notes, StateId, Orientation, Videoed ) values ( %d, %d, 'New Event', from_unixtime( %ld ), %d, %d, '%s', '%s', %d, %d, %d )",
snprintf( sql, sizeof(sql), "INSERT INTO Events ( MonitorId, StorageId, Name, StartTime, Width, Height, Cause, Notes, StateId, Orientation, Videoed, DefaultVideo, SaveJPEGs ) values ( %d, %d, 'New Event', from_unixtime( %ld ), %d, %d, '%s', '%s', %d, %d, %d, '', %d )",
monitor->Id(),
storage->Id(),
start_time.tv_sec,
@ -81,7 +81,8 @@ Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string
notes.c_str(),
state_id,
monitor->getOrientation(),
videoEvent
videoEvent,
monitor->GetOptSaveJPEGs()
);
if ( mysql_query( &dbconn, sql ) ) {
Error( "Can't insert event: %s. sql was (%s)", mysql_error( &dbconn ), sql );
@ -181,7 +182,7 @@ Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string
if ( videowriter != NULL ) {
/* Open the video stream */
int nRet = videowriter->Open();
if(nRet != 0) {
if ( nRet != 0 ) {
Error("Failed opening video stream");
delete videowriter;
videowriter = NULL;
@ -211,7 +212,9 @@ Event::~Event() {
if ( frames > last_db_frame ) {
Debug( 1, "Adding closing frame %d to DB", frames );
snprintf( sql, sizeof(sql), "insert into Frames ( EventId, FrameId, TimeStamp, Delta ) values ( %d, %d, from_unixtime( %ld ), %s%ld.%02ld )", id, frames, end_time.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec );
snprintf( sql, sizeof(sql),
"insert into Frames ( EventId, FrameId, TimeStamp, Delta ) values ( %d, %d, from_unixtime( %ld ), %s%ld.%02ld )",
id, frames, end_time.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec );
if ( mysql_query( &dbconn, sql ) ) {
Error( "Can't insert frame: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
@ -228,8 +231,10 @@ Event::~Event() {
videowriter = NULL;
/* Close the timecodes file */
fclose(timecodes_fd);
timecodes_fd = NULL;
if ( timecodes_fd ) {
fclose(timecodes_fd);
timecodes_fd = NULL;
}
}
snprintf( sql, sizeof(sql), "update Events set Name='%s%d', EndTime = from_unixtime( %ld ), Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d, DefaultVideo = '%s' where Id = %d", monitor->EventPrefix(), id, end_time.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, frames, alarm_frames, tot_score, (int)(alarm_frames?(tot_score/alarm_frames):0), max_score, video_name, id );
@ -302,7 +307,8 @@ bool Event::WriteFrameVideo( const Image *image, const struct timeval timestamp,
}
/* Add the frame to the timecodes file */
fprintf(timecodes_fd, "%u\n", timeMS);
if ( timecodes_fd )
fprintf(timecodes_fd, "%u\n", timeMS);
return( true );
}

View File

@ -116,7 +116,8 @@ int av_dict_parse_string(AVDictionary **pm, const char *str,
flags &= ~(AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
while (*str) {
if ((int ret = parse_key_value_pair(pm, &str, key_val_sep, pairs_sep, flags)) < 0)
int ret;
if ( (ret = parse_key_value_pair(pm, &str, key_val_sep, pairs_sep, flags)) < 0)
return ret;
if (*str)
@ -184,27 +185,13 @@ int hacked_up_context2_for_older_ffmpeg(AVFormatContext **avctx, AVOutputFormat
}
}
if (!oformat) {
if (format) {
oformat = av_guess_format(format, NULL, NULL);
if (!oformat) {
av_log(s, AV_LOG_ERROR, "Requested output format '%s' is not a suitable output format\n", format);
ret = AVERROR(EINVAL);
}
} else {
oformat = av_guess_format(NULL, filename, NULL);
if (!oformat) {
ret = AVERROR(EINVAL);
av_log(s, AV_LOG_ERROR, "Unable to find a suitable output format for '%s'\n", filename);
}
}
}
if (ret) {
avformat_free_context(s);
return ret;
} else {
s->oformat = oformat;
#if 1
// This is some very wrong code, and I don't think it is neccessary
if (s->oformat->priv_data_size > 0) {
s->priv_data = av_mallocz(s->oformat->priv_data_size);
if (s->priv_data) {
@ -219,6 +206,7 @@ int hacked_up_context2_for_older_ffmpeg(AVFormatContext **avctx, AVOutputFormat
}
s->priv_data = NULL;
}
#endif
if (filename) strncpy(s->filename, filename, sizeof(s->filename));
*avctx = s;

View File

@ -328,6 +328,9 @@ int FfmpegCamera::PostCapture() {
int FfmpegCamera::OpenFfmpeg() {
Debug ( 2, "OpenFfmpeg called." );
uint32_t last_event_id = monitor->GetLastEventId() ;
uint32_t video_writer_event_id = monitor->GetVideoWriterEventId();
Debug(2, "last_event(%d), our current (%d)", last_event_id, video_writer_event_id );
int ret;
@ -372,6 +375,9 @@ int FfmpegCamera::OpenFfmpeg() {
//FIXME can speed up initial analysis but need sensible parameters...
//mFormatContext->probesize = 32;
//mFormatContext->max_analyze_duration = 32;
last_event_id = monitor->GetLastEventId() ;
video_writer_event_id = monitor->GetVideoWriterEventId();
Debug(2, "last_event(%d), our current (%d), mpath (%s)", last_event_id, video_writer_event_id, mPath.c_str() );
if ( avformat_open_input( &mFormatContext, mPath.c_str(), NULL, &opts ) != 0 )
#endif
@ -380,12 +386,18 @@ int FfmpegCamera::OpenFfmpeg() {
Error( "Unable to open input %s due to: %s", mPath.c_str(), strerror(errno) );
return -1;
}
AVDictionaryEntry *e;
if ( (e = av_dict_get(opts, "", NULL, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
last_event_id = monitor->GetLastEventId() ;
video_writer_event_id = monitor->GetVideoWriterEventId();
Debug(2, "last_event(%d), our current (%d)", last_event_id, video_writer_event_id );
AVDictionaryEntry *e=NULL;
while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
Warning( "Option %s not recognized by ffmpeg", e->key);
}
last_event_id = monitor->GetLastEventId() ;
video_writer_event_id = monitor->GetVideoWriterEventId();
Debug(2, "last_event(%d), our current (%d)", last_event_id, video_writer_event_id );
mIsOpening = false;
Debug ( 1, "Opened input" );
@ -524,15 +536,15 @@ int FfmpegCamera::OpenFfmpeg() {
Debug ( 1, "Calling avcodec_open2" );
if ( avcodec_open2(mVideoCodecContext, mVideoCodec, &opts) < 0 ) {
#endif
AVDictionaryEntry *e;
if ( (e = av_dict_get(opts, "", NULL, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
AVDictionaryEntry *e = NULL;
while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
Warning( "Option %s not recognized by ffmpeg", e->key);
}
Fatal( "Unable to open codec for video stream from %s", mPath.c_str() );
} else {
AVDictionaryEntry *e;
if ( (e = av_dict_get(opts, "", NULL, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
AVDictionaryEntry *e = NULL;
if ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
Warning( "Option %s not recognized by ffmpeg", e->key);
}
}
@ -567,7 +579,7 @@ int FfmpegCamera::OpenFfmpeg() {
}
}
Debug ( 1, "Opened codec" );
Debug ( 1, "Opened audio codec" );
// Allocate space for the native video frame
mRawFrame = zm_av_frame_alloc();
@ -666,12 +678,16 @@ int FfmpegCamera::CloseFfmpeg() {
if ( mVideoCodecContext ) {
avcodec_close(mVideoCodecContext);
//av_free(mVideoCodecContext);
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
avcodec_free_context(&mVideoCodecContext);
#endif
mVideoCodecContext = NULL; // Freed by av_close_input_file
}
if ( mAudioCodecContext ) {
avcodec_close(mAudioCodecContext);
//av_free(mAudioCodecContext);
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
avcodec_free_context(&mAudioCodecContext);
#endif
mAudioCodecContext = NULL; // Freed by av_close_input_file
}
@ -780,9 +796,10 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
if ( recording.tv_sec ) {
uint32_t last_event_id = monitor->GetLastEventId() ;
uint32_t video_writer_event_id = monitor->GetVideoWriterEventId();
if ( last_event_id != monitor->GetVideoWriterEventId() ) {
Debug(2, "Have change of event. last_event(%d), our current (%d)", last_event_id, monitor->GetVideoWriterEventId() );
if ( last_event_id != video_writer_event_id ) {
Debug(2, "Have change of event. last_event(%d), our current (%d)", last_event_id, video_writer_event_id );
if ( videoStore ) {
Info("Re-starting video storage module");

View File

@ -85,7 +85,6 @@ class FfmpegCamera : public Camera {
#endif // HAVE_LIBAVFORMAT
VideoStore *videoStore;
unsigned int old_event_id;
zm_packetqueue packetqueue;
bool have_video_keyframe;

View File

@ -9,9 +9,14 @@ FFmpeg_Input::FFmpeg_Input() {
audio_stream_id = -1;
av_register_all();
avcodec_register_all();
streams = NULL;
}
FFmpeg_Input::~FFmpeg_Input() {
if ( streams ) {
delete streams;
streams = NULL;
}
}
int FFmpeg_Input::Open( const char *filepath ) {
@ -35,6 +40,8 @@ int FFmpeg_Input::Open( const char *filepath ) {
return error;
}
streams = new stream[input_format_context->nb_streams];
for ( unsigned int i = 0; i < input_format_context->nb_streams; i += 1 ) {
if ( is_video_stream( input_format_context->streams[i] ) ) {
zm_dump_stream_format(input_format_context, i, 0, 0);
@ -162,7 +169,7 @@ AVFrame *FFmpeg_Input::get_frame( int stream_id ) {
frameComplete = 1;
# else
ret = zm_avcodec_decode_video( streams[packet.stream_index].context, frame, &frameComplete, &packet );
ret = zm_avcodec_decode_video( context, frame, &frameComplete, &packet );
if ( ret < 0 ) {
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
Error( "Unable to decode frame at frame %d: %s, continuing", streams[packet.stream_index].frame_count, errbuf );

View File

@ -36,7 +36,7 @@ class FFmpeg_Input {
int frame_count;
} stream;
stream streams[2];
stream *streams;
int video_stream_id;
int audio_stream_id;
AVFormatContext *input_format_context;

View File

@ -131,6 +131,7 @@ Image::Image( int p_width, int p_height, int p_colours, int p_subpixelorder, uin
Image::Image( const AVFrame *frame ) {
AVFrame *dest_frame = zm_av_frame_alloc();
text[0] = '\0';
width = frame->width;
height = frame->height;
@ -612,12 +613,12 @@ void Image::Assign(const unsigned int p_width, const unsigned int p_height, cons
void Image::Assign( const Image &image ) {
unsigned int new_size = (image.width * image.height) * image.colours;
if(image.buffer == NULL) {
if ( image.buffer == NULL ) {
Error("Attempt to assign image with an empty buffer");
return;
}
if(image.colours != ZM_COLOUR_GRAY8 && image.colours != ZM_COLOUR_RGB24 && image.colours != ZM_COLOUR_RGB32) {
if ( image.colours != ZM_COLOUR_GRAY8 && image.colours != ZM_COLOUR_RGB24 && image.colours != ZM_COLOUR_RGB32 ) {
Error("Attempt to assign image with unexpected colours per pixel: %d",image.colours);
return;
}
@ -1847,8 +1848,7 @@ void Image::Delta( const Image &image, Image* targetimage) const
#endif
}
const Coord Image::centreCoord( const char *text ) const
{
const Coord Image::centreCoord( const char *text ) const {
int index = 0;
int line_no = 0;
int text_len = strlen( text );
@ -1856,14 +1856,12 @@ const Coord Image::centreCoord( const char *text ) const
int max_line_len = 0;
const char *line = text;
while ( (index < text_len) && (line_len = strcspn( line, "\n" )) )
{
while ( (index < text_len) && (line_len = strcspn( line, "\n" )) ) {
if ( line_len > max_line_len )
max_line_len = line_len;
index += line_len;
while ( text[index] == '\n' )
{
while ( text[index] == '\n' ) {
index++;
}
line = text+index;
@ -1875,8 +1873,7 @@ const Coord Image::centreCoord( const char *text ) const
}
/* RGB32 compatible: complete */
void Image::MaskPrivacy( const unsigned char *p_bitmask, const Rgb pixel_colour )
{
void Image::MaskPrivacy( const unsigned char *p_bitmask, const Rgb pixel_colour ) {
const uint8_t pixel_r_col = RED_VAL_RGBA(pixel_colour);
const uint8_t pixel_g_col = GREEN_VAL_RGBA(pixel_colour);
const uint8_t pixel_b_col = BLUE_VAL_RGBA(pixel_colour);

View File

@ -95,14 +95,14 @@ protected:
double _1_m;
static int CompareYX( const void *p1, const void *p2 ) {
const Edge *e1 = (const Edge *)p1, *e2 = (const Edge *)p2;
const Edge *e1 = reinterpret_cast<const Edge *>(p1), *e2 = reinterpret_cast<const Edge *>(p2);
if ( e1->min_y == e2->min_y )
return( int(e1->min_x - e2->min_x) );
else
return( int(e1->min_y - e2->min_y) );
}
static int CompareX( const void *p1, const void *p2 ) {
const Edge *e1 = (const Edge *)p1, *e2 = (const Edge *)p2;
const Edge *e1 = reinterpret_cast<const Edge *>(p1), *e2 = reinterpret_cast<const Edge *>(p2);
return( int(e1->min_x - e2->min_x) );
}
};
@ -152,10 +152,10 @@ protected:
public:
Image();
Image( const char *filename );
explicit Image( const char *filename );
Image( int p_width, int p_height, int p_colours, int p_subpixelorder, uint8_t *p_buffer=0);
Image( const Image &p_image );
Image( const AVFrame *frame );
explicit Image( const Image &p_image );
explicit Image( const AVFrame *frame );
~Image();
static void Initialise();
static void Deinitialise();

View File

@ -24,7 +24,7 @@
// Do all the buffer checking work here to avoid unnecessary locking
void* LibvlcLockBuffer(void* opaque, void** planes) {
LibvlcPrivateData* data = (LibvlcPrivateData*)opaque;
LibvlcPrivateData* data = reinterpret_cast<LibvlcPrivateData*>(opaque);
data->mutex.lock();
uint8_t* buffer = data->buffer;
@ -36,7 +36,7 @@ void* LibvlcLockBuffer(void* opaque, void** planes) {
}
void LibvlcUnlockBuffer(void* opaque, void* picture, void *const *planes) {
LibvlcPrivateData* data = (LibvlcPrivateData*)opaque;
LibvlcPrivateData* data = reinterpret_cast<LibvlcPrivateData*>(opaque);
bool newFrame = false;
for( uint32_t i = 0; i < data->bufferSize; i++ ) {
@ -67,6 +67,7 @@ LibvlcCamera::LibvlcCamera( int p_id, const std::string &p_path, const std::stri
mLibvlcMediaPlayer = NULL;
mLibvlcData.buffer = NULL;
mLibvlcData.prevBuffer = NULL;
mOptArgV = NULL;
/* Has to be located inside the constructor so other components such as zma will receive correct colours and subpixel order */
if(colours == ZM_COLOUR_RGB32) {

View File

@ -1712,8 +1712,8 @@ bool LocalCamera::GetCurrentSettings( const char *device, char *output, int vers
sprintf( output+strlen(output), " Name: %s\n", vid_src.name );
sprintf( output+strlen(output), " Channel: %d\n", vid_src.channel );
sprintf( output+strlen(output), " Flags: %d\n%s%s", vid_src.flags,
vid_src.flags&VIDEO_VC_TUNER?" Channel has a tuner\n":"",
vid_src.flags&VIDEO_VC_AUDIO?" Channel has audio\n":""
(vid_src.flags&VIDEO_VC_TUNER)?" Channel has a tuner\n":"",
(vid_src.flags&VIDEO_VC_AUDIO)?" Channel has audio\n":""
);
sprintf( output+strlen(output), " Type: %d - %s\n", vid_src.type,
vid_src.type==VIDEO_TYPE_TV?"TV":(

View File

@ -26,7 +26,7 @@
inline void* zm_mallocaligned(unsigned int reqalignment, size_t reqsize) {
uint8_t* retptr;
#if HAVE_POSIX_MEMALIGN
if(posix_memalign((void**)&retptr,reqalignment,reqsize) != 0)
if ( posix_memalign((void**)&retptr,reqalignment,reqsize) != 0 )
return NULL;
return retptr;
@ -34,7 +34,7 @@ inline void* zm_mallocaligned(unsigned int reqalignment, size_t reqsize) {
uint8_t* alloc;
retptr = (uint8_t*)malloc(reqsize+reqalignment+sizeof(void*));
if(retptr == NULL)
if ( retptr == NULL )
return NULL;
alloc = retptr + sizeof(void*);
@ -58,20 +58,16 @@ inline void zm_freealigned(void* ptr) {
#endif
}
inline char *mempbrk( register const char *s, const char *accept, size_t limit )
{
if ( limit <= 0 || !s || !accept || !*accept )
return( 0 );
inline char *mempbrk( register const char *s, const char *accept, size_t limit ) {
if ( limit == 0 || !s || !accept || !*accept )
return 0;
register unsigned int i,j;
size_t acc_len = strlen( accept );
for ( i = 0; i < limit; s++, i++ )
{
for ( j = 0; j < acc_len; j++ )
{
if ( *s == accept[j] )
{
for ( i = 0; i < limit; s++, i++ ) {
for ( j = 0; j < acc_len; j++ ) {
if ( *s == accept[j] ) {
return( (char *)s );
}
}
@ -79,9 +75,8 @@ inline char *mempbrk( register const char *s, const char *accept, size_t limit )
return( 0 );
}
inline char *memstr( register const char *s, const char *n, size_t limit )
{
if ( limit <= 0 || !s || !n )
inline char *memstr( register const char *s, const char *n, size_t limit ) {
if ( limit == 0 || !s || !n )
return( 0 );
if ( !*n )
@ -90,14 +85,12 @@ inline char *memstr( register const char *s, const char *n, size_t limit )
register unsigned int i,j,k;
size_t n_len = strlen( n );
for ( i = 0; i < limit; i++, s++ )
{
for ( i = 0; i < limit; i++, s++ ) {
if ( *s != *n )
continue;
j = 1;
k = 1;
while ( true )
{
while ( true ) {
if ( k >= n_len )
return( (char *)s );
if ( s[j++] != n[k++] )
@ -107,36 +100,30 @@ inline char *memstr( register const char *s, const char *n, size_t limit )
return( 0 );
}
inline size_t memspn( register const char *s, const char *accept, size_t limit )
{
if ( limit <= 0 || !s || !accept || !*accept )
inline size_t memspn( register const char *s, const char *accept, size_t limit ) {
if ( limit == 0 || !s || !accept || !*accept )
return( 0 );
register unsigned int i,j;
size_t acc_len = strlen( accept );
for ( i = 0; i < limit; s++, i++ )
{
for ( i = 0; i < limit; s++, i++ ) {
register bool found = false;
for ( j = 0; j < acc_len; j++ )
{
if ( *s == accept[j] )
{
for ( j = 0; j < acc_len; j++ ) {
if ( *s == accept[j] ) {
found = true;
break;
}
}
if ( !found )
{
if ( !found ) {
return( i );
}
}
return( limit );
}
inline size_t memcspn( register const char *s, const char *reject, size_t limit )
{
if ( limit <= 0 || !s || !reject )
inline size_t memcspn( register const char *s, const char *reject, size_t limit ) {
if ( limit == 0 || !s || !reject )
return( 0 );
if ( !*reject )
@ -145,12 +132,9 @@ inline size_t memcspn( register const char *s, const char *reject, size_t limit
register unsigned int i,j;
size_t rej_len = strlen( reject );
for ( i = 0; i < limit; s++, i++ )
{
for ( j = 0; j < rej_len; j++ )
{
if ( *s == reject[j] )
{
for ( i = 0; i < limit; s++, i++ ) {
for ( j = 0; j < rej_len; j++ ) {
if ( *s == reject[j] ) {
return( i );
}
}

View File

@ -73,7 +73,12 @@ std::vector<std::string> split(const std::string &s, char delim) {
return elems;
}
Monitor::MonitorLink::MonitorLink( int p_id, const char *p_name ) : id( p_id ) {
Monitor::MonitorLink::MonitorLink( int p_id, const char *p_name ) :
id( p_id ),
shared_data(NULL),
trigger_data(NULL),
video_store_data(NULL)
{
strncpy( name, p_name, sizeof(name) );
#if ZM_MEM_MAPPED
@ -468,9 +473,12 @@ Monitor::Monitor(
videoRecording = ((GetOptVideoWriter() == H264PASSTHROUGH) && camera->SupportsNativeVideo());
if ( purpose == ANALYSIS ) {
while( shared_data->last_write_index == (unsigned int)image_buffer_count
&& shared_data->last_write_time == 0) {
Debug(2,"last_write_index(%d), last_write_time(%d)", shared_data->last_write_index, shared_data->last_write_time );
while(
( shared_data->last_write_index == (unsigned int)image_buffer_count )
&&
( shared_data->last_write_time == 0)
) {
Warning( "Waiting for capture daemon" );
sleep( 1 );
}
@ -605,7 +613,7 @@ Monitor::~Monitor() {
}
if ( mem_ptr ) {
if ( event ) {
Info( "%s: %03d - Closing event %d, shutting down", name, image_count, event->Id() );
Info( "%s: image_count:%d - Closing event %d, shutting down", name, image_count, event->Id() );
closeEvent();
}
@ -771,30 +779,40 @@ unsigned int Monitor::GetLastWriteIndex() const {
return( shared_data->last_write_index!=(unsigned int)image_buffer_count?shared_data->last_write_index:-1 );
}
unsigned int Monitor::GetLastEvent() const {
uint32_t Monitor::GetLastEventId() const {
Debug(2, "mem_ptr(%x), State(%d) last_read_index(%d) last_read_time(%d) last_event(%d)",
mem_ptr,
shared_data->state,
shared_data->last_read_index,
shared_data->last_read_time,
shared_data->last_event
);
return( shared_data->last_event );
}
// This function is crap.
double Monitor::GetFPS() const {
int index1 = shared_data->last_write_index;
if ( index1 == image_buffer_count ) {
return( 0.0 );
// last_write_index only has this value on startup before capturing anything.
return 0.0;
}
Snapshot *snap1 = &image_buffer[index1];
if ( !snap1->timestamp || !snap1->timestamp->tv_sec ) {
return( 0.0 );
// This should be impossible
return 0.0;
}
struct timeval time1 = *snap1->timestamp;
int image_count = image_buffer_count;
int index2 = (index1+1)%image_buffer_count;
if ( index2 == image_buffer_count ) {
return( 0.0 );
}
Snapshot *snap2 = &image_buffer[index2];
// the timestamp pointers are initialized on connection, so that's redundant
// tv_sec is probably only zero during the first loop of capturing, so this basically just counts the unused images.
while ( !snap2->timestamp || !snap2->timestamp->tv_sec ) {
if ( index1 == index2 ) {
return( 0.0 );
// We didn't find any initialized images
return 0.0;
}
index2 = (index2+1)%image_buffer_count;
snap2 = &image_buffer[index2];
@ -807,10 +825,10 @@ double Monitor::GetFPS() const {
double curr_fps = image_count/time_diff;
if ( curr_fps < 0.0 ) {
//Error( "Negative FPS %f, time_diff = %lf (%d:%ld.%ld - %d:%ld.%ld), ibc: %d", curr_fps, time_diff, index2, time2.tv_sec, time2.tv_usec, index1, time1.tv_sec, time1.tv_usec, image_buffer_count );
return( 0.0 );
Error( "Negative FPS %f, time_diff = %lf (%d:%ld.%ld - %d:%ld.%ld), ibc: %d", curr_fps, time_diff, index2, time2.tv_sec, time2.tv_usec, index1, time1.tv_sec, time1.tv_usec, image_buffer_count );
return 0.0;
}
return( curr_fps );
return curr_fps;
}
useconds_t Monitor::GetAnalysisRate() {
@ -2974,29 +2992,24 @@ Debug(4, "Return from Capture (%d)", captureResult);
shared_data->last_write_time = image_buffer[index].timestamp->tv_sec;
image_count++;
} // end if captureResult
if ( image_count && fps_report_interval && !(image_count%fps_report_interval) ) {
struct timeval now;
if ( !captureResult ) {
gettimeofday( &now, NULL );
} else {
now.tv_sec = image_buffer[index].timestamp->tv_sec;
}
// If we are too fast, we get div by zero. This seems to happen in the case of audio packets.
if ( now.tv_sec != last_fps_time ) {
fps = double(fps_report_interval)/(now.tv_sec-last_fps_time);
Info( "%d -> %d -> %d", fps_report_interval, now.tv_sec, last_fps_time );
//Info( "%d -> %d -> %lf -> %lf", now-last_fps_time, fps_report_interval/(now-last_fps_time), double(fps_report_interval)/(now-last_fps_time), fps );
Info( "%s: %d - Capturing at %.2lf fps", name, image_count, fps );
last_fps_time = now.tv_sec;
static char sql[ZM_SQL_SML_BUFSIZ];
snprintf( sql, sizeof(sql), "UPDATE Monitors SET CaptureFPS='%.2lf' WHERE Id=%d", fps, id );
if ( mysql_query( &dbconn, sql ) ) {
Error( "Can't run query: %s", mysql_error( &dbconn ) );
if ( image_count && fps_report_interval && !(image_count%fps_report_interval) ) {
time_t now = image_buffer[index].timestamp->tv_sec;
// If we are too fast, we get div by zero. This seems to happen in the case of audio packets.
if ( now != last_fps_time ) {
// # of images per interval / the amount of time it took
fps = double(fps_report_interval)/(now-last_fps_time);
Info( "%d -> %d -> %d", fps_report_interval, now, last_fps_time );
//Info( "%d -> %d -> %lf -> %lf", now-last_fps_time, fps_report_interval/(now-last_fps_time), double(fps_report_interval)/(now-last_fps_time), fps );
Info( "%s: images:%d - Capturing at %.2lf fps", name, image_count, fps );
last_fps_time = now;
static char sql[ZM_SQL_SML_BUFSIZ];
snprintf( sql, sizeof(sql), "UPDATE Monitors SET CaptureFPS='%.2lf' WHERE Id=%d", fps, id );
if ( mysql_query( &dbconn, sql ) ) {
Error( "Can't run query: %s", mysql_error( &dbconn ) );
}
}
}
} // end if captureResult
}
// Icon: I'm not sure these should be here. They have nothing to do with capturing

View File

@ -432,7 +432,6 @@ public:
int GetOptSaveJPEGs() const { return( savejpegspref ); }
VideoWriter GetOptVideoWriter() const { return( videowriter ); }
const std::vector<EncoderParameter_t>* GetOptEncoderParams() const { return( &encoderparamsvec ); }
uint32_t GetLastEventId() const { return shared_data->last_event; }
uint32_t GetVideoWriterEventId() const { return video_store_data->current_event; }
void SetVideoWriterEventId( uint32_t p_event_id ) { video_store_data->current_event = p_event_id; }
@ -448,7 +447,7 @@ public:
int GetAlarmCaptureDelay() const { return( alarm_capture_delay ); }
unsigned int GetLastReadIndex() const;
unsigned int GetLastWriteIndex() const;
unsigned int GetLastEvent() const;
uint32_t GetLastEventId() const;
double GetFPS() const;
void ForceAlarmOn( int force_score, const char *force_case, const char *force_text="" );
void ForceAlarmOff();

View File

@ -498,7 +498,8 @@ void MonitorStream::runStream() {
if ( type == STREAM_JPEG )
fprintf( stdout, "Content-Type: multipart/x-mixed-replace;boundary=ZoneMinderFrame\r\n\r\n" );
int last_read_index = monitor->image_buffer_count;
// point to end which is theoretically not a valid value because all indexes are % image_buffer_count
unsigned int last_read_index = monitor->image_buffer_count;
time_t stream_start_time;
time( &stream_start_time );
@ -557,6 +558,8 @@ void MonitorStream::runStream() {
Debug( 2, "Assigned temporary buffer" );
}
}
} else {
Debug(2, "Not using playback_buffer");
} // end if connkey & playback_buffer
float max_secs_since_last_sent_frame = 10.0; //should be > keep alive amount (5 secs)
@ -576,7 +579,7 @@ void MonitorStream::runStream() {
gettimeofday( &now, NULL );
if ( connkey ) {
//Debug(2, "checking command Queue for connkey: %d", connkey );
Debug(2, "checking command Queue for connkey: %d", connkey );
while(checkCommandQueue()) {
Debug(2, "Have checking command Queue for connkey: %d", connkey );
got_command = true;
@ -657,26 +660,29 @@ Debug(2, "Have checking command Queue for connkey: %d", connkey );
delayed = false;
replay_rate = ZM_RATE_BASE;
}
}
if ( (unsigned int)last_read_index != monitor->shared_data->last_write_index ) {
int index = monitor->shared_data->last_write_index%monitor->image_buffer_count;
} // end if ( buffered_playback && delayed )
if ( last_read_index != monitor->shared_data->last_write_index ) {
int index = monitor->shared_data->last_write_index % monitor->image_buffer_count; // % shouldn't be neccessary
last_read_index = monitor->shared_data->last_write_index;
//Debug( 1, "%d: %x - %x", index, image_buffer[index].image, image_buffer[index].image->buffer );
Debug( 1, "index: %d: frame_mod: %d frame count: %d", index, frame_mod, frame_count );
if ( (frame_mod == 1) || ((frame_count%frame_mod) == 0) ) {
if ( !paused && !delayed ) {
// Send the next frame
Monitor::Snapshot *snap = &monitor->image_buffer[index];
//Debug(2, "sending Frame.");
if ( !sendFrame( snap->image, snap->timestamp ) ) {
Debug(2, "sendFrame failed, quiting.");
zm_terminate = true;
}
// Perhaps we should use NOW instead.
memcpy( &last_frame_timestamp, snap->timestamp, sizeof(last_frame_timestamp) );
//frame_sent = true;
temp_read_index = temp_write_index;
}
}
} // end if should send frame
if ( buffered_playback ) {
if ( monitor->shared_data->valid ) {
if ( monitor->image_buffer[index].timestamp->tv_sec ) {
@ -706,17 +712,24 @@ Debug(2, "Have checking command Queue for connkey: %d", connkey );
}
} // end if buffered playback
frame_count++;
}
} else {
Debug(2,"Waiting for capture");
} // end if ( (unsigned int)last_read_index != monitor->shared_data->last_write_index )
unsigned long sleep_time = (unsigned long)((1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2)));
Debug(2, "Sleeping for (%d)", sleep_time);
usleep( (unsigned long)((1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2))) );
usleep( sleep_time );
if ( ttl ) {
if ( (now.tv_sec - stream_start_time) > ttl ) {
Debug(2, "now(%d) - start(%d) > ttl(%d) break", now.tv_sec, stream_start_time, ttl);
break;
}
}
if ( (TV_2_FLOAT( now ) - last_frame_sent) > max_secs_since_last_sent_frame ) {
if ( ! last_frame_sent ) {
// If we didn't capture above, because frame_mod was bad? Then last_frame_sent will not have a value.
last_frame_sent = now.tv_sec;
Warning( "no last_frame_sent. Shouldn't happen. frame_mod was (%d) frame_count (%d) ", frame_mod, frame_count );
} else if ( (TV_2_FLOAT( now ) - last_frame_sent) > max_secs_since_last_sent_frame ) {
Error( "Terminating, last frame sent time %f secs more than maximum of %f", TV_2_FLOAT( now ) - last_frame_sent, max_secs_since_last_sent_frame );
break;
}

View File

@ -62,6 +62,7 @@ void VideoStream::SetupFormat( ) {
AVFormatContext *s= avformat_alloc_context();
if(!s) {
Fatal( "avformat_alloc_context failed %d \"%s\"", (size_t)ofc, av_err2str((size_t)ofc) );
return;
}
AVOutputFormat *oformat;
@ -417,9 +418,15 @@ void VideoStream::OpenStream( ) {
VideoStream::VideoStream( const char *in_filename, const char *in_format, int bitrate, double frame_rate, int colours, int subpixelorder, int width, int height ) :
filename(in_filename),
format(in_format),
opicture(NULL),
tmp_opicture(NULL),
video_outbuf(NULL),
video_outbuf_size(0),
last_pts( -1 ),
streaming_thread(0),
do_streaming(true),
add_timestamp(false),
timestamp(0),
buffer_copy(NULL),
buffer_copy_lock(new pthread_mutex_t),
buffer_copy_size(0),
@ -573,11 +580,11 @@ double VideoStream::EncodeFrame( const uint8_t *buffer, int buffer_size, bool _a
}
double VideoStream::ActuallyEncodeFrame( const uint8_t *buffer, int buffer_size, bool add_timestamp, unsigned int timestamp ) {
if ( codec_context->pix_fmt != pf ) {
#ifdef HAVE_LIBSWSCALE
static struct SwsContext *img_convert_ctx = 0;
#endif // HAVE_LIBSWSCALE
if ( codec_context->pix_fmt != pf ) {
memcpy( tmp_opicture->data[0], buffer, buffer_size );
#ifdef HAVE_LIBSWSCALE
if ( !img_convert_ctx ) {

View File

@ -24,11 +24,9 @@
#if HAVE_LIBAVCODEC
class VideoStream
{
class VideoStream {
protected:
struct MimeData
{
struct MimeData {
const char *format;
const char *mime_type;
};
@ -56,9 +54,9 @@ protected:
pthread_t streaming_thread;
bool do_streaming;
uint8_t *buffer_copy;
bool add_timestamp;
unsigned int timestamp;
uint8_t *buffer_copy;
pthread_mutex_t *buffer_copy_lock;
int buffer_copy_size;
int buffer_copy_used;

View File

@ -39,14 +39,14 @@ protected:
double _1_m;
static int CompareYX( const void *p1, const void *p2 ) {
const Edge *e1 = (const Edge *)p1, *e2 = (const Edge *)p2;
const Edge *e1 = reinterpret_cast<const Edge *>(p1), *e2 = reinterpret_cast<const Edge *>(p2);
if ( e1->min_y == e2->min_y )
return( int(e1->min_x - e2->min_x) );
else
return( int(e1->min_y - e2->min_y) );
}
static int CompareX( const void *p1, const void *p2 ) {
const Edge *e1 = (const Edge *)p1, *e2 = (const Edge *)p2;
const Edge *e1 = reinterpret_cast<const Edge *>(p1), *e2 = reinterpret_cast<const Edge *>(p2);
return( int(e1->min_x - e2->min_x) );
}
};

View File

@ -159,8 +159,7 @@ SessionDescriptor::SessionDescriptor( const std::string &url, const std::string
MediaDescriptor *currMedia = 0;
StringVector lines = split( sdp, "\r\n" );
for ( StringVector::const_iterator iter = lines.begin(); iter != lines.end(); iter++ )
{
for ( StringVector::const_iterator iter = lines.begin(); iter != lines.end(); ++iter ) {
std::string line = *iter;
if ( line.empty() )
break;
@ -276,48 +275,26 @@ SessionDescriptor::SessionDescriptor( const std::string &url, const std::string
{
StringVector attr3Tokens = split( attr2Tokens[i], "=" );
//Info( "Name = %s, Value = %s", attr3Tokens[0].c_str(), attr3Tokens[1].c_str() );
if ( attr3Tokens[0] == "profile-level-id" )
{
}
else if ( attr3Tokens[0] == "config" )
{
}
else if ( attr3Tokens[0] == "sprop-parameter-sets" )
{
if ( attr3Tokens[0] == "profile-level-id" ) {
} else if ( attr3Tokens[0] == "config" ) {
} else if ( attr3Tokens[0] == "sprop-parameter-sets" ) {
size_t t = attr2Tokens[i].find("=");
char *c = (char *)attr2Tokens[i].c_str() + t + 1;
Debug(4, "sprop-parameter-sets value %s", c);
currMedia->setSprops(std::string(c));
}
else if ( attr3Tokens[0] == "sprop-parameter-sets" )
{
size_t t = attr2Tokens[i].find("=");
char *c = (char *)attr2Tokens[i].c_str() + t + 1;
Debug(4, "sprop-parameter-sets value %s", c);
currMedia->setSprops(std::string(c));
}
else
{
} else {
Debug( 3, "Ignoring SDP fmtp attribute '%s' for media '%s'", attr3Tokens[0].c_str(), currMedia->getType().c_str() )
}
}
}
}
else if ( attrName == "mpeg4-iod" )
{
} else if ( attrName == "mpeg4-iod" ) {
// a=mpeg4-iod: "data:application/mpeg4-iod;base64,AoEAAE8BAf73AQOAkwABQHRkYXRhOmFwcGxpY2F0aW9uL21wZWc0LW9kLWF1O2Jhc2U2NCxBVGdCR3dVZkF4Y0F5U1FBWlFRTklCRUVrK0FBQWEyd0FBR3RzQVlCQkFFWkFwOERGUUJsQlFRTlFCVUFDN2dBQVBvQUFBRDZBQVlCQXc9PQQNAQUABAAAAAAAAAAAAAYJAQAAAAAAAAAAA0IAAkA+ZGF0YTphcHBsaWNhdGlvbi9tcGVnNC1iaWZzLWF1O2Jhc2U2NCx3QkFTZ1RBcUJYSmhCSWhRUlFVL0FBPT0EEgINAAACAAAAAAAAAAAFAwAAQAYJAQAAAAAAAAAA"
}
else if ( attrName == "mpeg4-esid" )
{
} else if ( attrName == "mpeg4-esid" ) {
// a=mpeg4-esid:201
}
else
{
} else {
Debug( 3, "Ignoring SDP attribute '%s' for media '%s'", line.c_str(), currMedia->getType().c_str() )
}
}
else
{
} else {
Debug( 3, "Ignoring general SDP attribute '%s'", line.c_str() );
}
break;
@ -369,8 +346,7 @@ AVFormatContext *SessionDescriptor::generateFormatContext() const
strncpy( formatContext->comment, mInfo.c_str(), sizeof(formatContext->comment) );
*/
//formatContext->nb_streams = mMediaList.size();
for ( unsigned int i = 0; i < mMediaList.size(); i++ )
{
for ( unsigned int i = 0; i < mMediaList.size(); i++ ) {
const MediaDescriptor *mediaDesc = mMediaList[i];
#if !LIBAVFORMAT_VERSION_CHECK(53, 10, 0, 17, 0)
AVStream *stream = av_new_stream( formatContext, i );
@ -379,16 +355,13 @@ AVFormatContext *SessionDescriptor::generateFormatContext() const
stream->id = i;
#endif
AVCodecContext *codec_context = NULL;
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
codec_context = avcodec_alloc_context3(NULL);
avcodec_parameters_to_context(codec_context, stream->codecpar);
AVCodecContext *codec_context = avcodec_alloc_context3(NULL);
avcodec_parameters_to_context(codec_context, stream->codecpar);
#else
codec_context = stream->codec;
AVCodecContext *codec_context = stream->codec;
#endif
Debug( 1, "Looking for codec for %s payload type %d / %s", mediaDesc->getType().c_str(), mediaDesc->getPayloadType(), mediaDesc->getPayloadDesc().c_str() );
#if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0))
if ( mediaDesc->getType() == "video" )
@ -409,13 +382,10 @@ AVFormatContext *SessionDescriptor::generateFormatContext() const
#if LIBAVCODEC_VERSION_CHECK(55, 50, 3, 60, 103)
std::string codec_name;
#endif
if ( mediaDesc->getPayloadType() < PAYLOAD_TYPE_DYNAMIC )
{
if ( mediaDesc->getPayloadType() < PAYLOAD_TYPE_DYNAMIC ) {
// Look in static table
for ( unsigned int i = 0; i < (sizeof(smStaticPayloads)/sizeof(*smStaticPayloads)); i++ )
{
if ( smStaticPayloads[i].payloadType == mediaDesc->getPayloadType() )
{
for ( unsigned int i = 0; i < (sizeof(smStaticPayloads)/sizeof(*smStaticPayloads)); i++ ) {
if ( smStaticPayloads[i].payloadType == mediaDesc->getPayloadType() ) {
Debug( 1, "Got static payload type %d, %s", smStaticPayloads[i].payloadType, smStaticPayloads[i].payloadName );
#if LIBAVCODEC_VERSION_CHECK(55, 50, 3, 60, 103)
codec_name = std::string( smStaticPayloads[i].payloadName );

View File

@ -69,12 +69,13 @@ void StreamBase::updateFrameRate( double fps ) {
while( effective_fps > maxfps ) {
effective_fps /= 2.0;
frame_mod *= 2;
}
Debug( 3, "aEFPS:%.2f, aFM:%d", effective_fps, frame_mod );
}
}
bool StreamBase::checkCommandQueue() {
if ( sd >= 0 ) {
Debug(2, "sd is (%d)", sd );
CmdMsg msg;
memset( &msg, 0, sizeof(msg) );
int nbytes = recvfrom( sd, &msg, sizeof(msg), MSG_DONTWAIT, 0, 0 );
@ -92,6 +93,8 @@ Debug(2, "Message length is (%d)", nbytes );
processCommand( &msg );
return( true );
}
} else {
Error("sd is < 0");
}
return( false );
}
@ -288,7 +291,7 @@ void StreamBase::openComms() {
if ( sd < 0 ) {
Fatal( "Can't create socket: %s", strerror(errno) );
} else {
Debug(3, "Have socket %d", sd );
Debug(1, "Have socket %d", sd );
}
length = snprintf( loc_sock_path, sizeof(loc_sock_path), "%s/zms-%06ds.sock", staticConfig.PATH_SOCKS.c_str(), connkey );
@ -296,6 +299,7 @@ void StreamBase::openComms() {
Warning("Socket path was truncated.");
length = sizeof(loc_sock_path)-1;
}
// Unlink before bind, in case it already exists
unlink( loc_sock_path );
if ( sizeof(loc_addr.sun_path) < length ) {
Error("Not enough space %d in loc_addr.sun_path for socket file %s", sizeof(loc_addr.sun_path), loc_sock_path );
@ -313,7 +317,7 @@ void StreamBase::openComms() {
rem_addr.sun_family = AF_UNIX;
} // end if connKey > 0
Debug(2, "comms open" );
}
} // end void StreamBase::openComms()
void StreamBase::closeComms() {
if ( connkey > 0 ) {
@ -324,10 +328,10 @@ void StreamBase::closeComms() {
if ( loc_sock_path[0] ) {
unlink( loc_sock_path );
}
if (lock_fd > 0) {
if ( lock_fd > 0 ) {
close(lock_fd); //close it rather than unlock it incase it got deleted.
unlink(sock_path_lock);
// You cannot unlink the lockfile. You have to leave a mess around. SUCKS
//unlink(sock_path_lock);
}
}
}

View File

@ -32,8 +32,7 @@
#include <sys/thr.h>
#endif
class ThreadException : public Exception
{
class ThreadException : public Exception {
private:
#ifndef SOLARIS
pid_t pid() {
@ -55,12 +54,11 @@ private:
pthread_t pid() { return( pthread_self() ); }
#endif
public:
ThreadException( const std::string &message ) : Exception( stringtf( "(%d) "+message, (long int)pid() ) ) {
explicit ThreadException( const std::string &message ) : Exception( stringtf( "(%d) "+message, (long int)pid() ) ) {
}
};
class Mutex
{
class Mutex {
friend class Condition;
private:
@ -71,8 +69,7 @@ public:
~Mutex();
private:
pthread_mutex_t *getMutex()
{
pthread_mutex_t *getMutex() {
return( &mMutex );
}
@ -84,18 +81,15 @@ public:
bool locked();
};
class ScopedMutex
{
class ScopedMutex {
private:
Mutex &mMutex;
public:
ScopedMutex( Mutex &mutex ) : mMutex( mutex )
{
explicit ScopedMutex( Mutex &mutex ) : mMutex( mutex ) {
mMutex.lock();
}
~ScopedMutex()
{
~ScopedMutex() {
mMutex.unlock();
}
@ -164,8 +158,7 @@ public:
}
};
template <class T> class ThreadData
{
template <class T> class ThreadData {
private:
T mValue;
mutable bool mChanged;
@ -173,11 +166,11 @@ private:
mutable Condition mCondition;
public:
__attribute__((used)) ThreadData() : mCondition( mMutex )
{
__attribute__((used)) ThreadData() : mCondition( mMutex ) {
mChanged = false;
}
__attribute__((used)) ThreadData( T value ) : mValue( value ), mCondition( mMutex )
{
__attribute__((used)) ThreadData( T value ) : mValue( value ), mCondition( mMutex ) {
mChanged = false;
}
//~ThreadData() {}

View File

@ -27,11 +27,12 @@
#include <string.h>
#include <time.h>
#include "zm_utils.h"
User::User() {
username[0] = password[0] = 0;
enabled = false;
stream = events = control = monitors = system = PERM_NONE;
monitor_ids = 0;
}
User::User( MYSQL_ROW &dbrow ) {
@ -44,45 +45,41 @@ User::User( MYSQL_ROW &dbrow ) {
control = (Permission)atoi( dbrow[index++] );
monitors = (Permission)atoi( dbrow[index++] );
system = (Permission)atoi( dbrow[index++] );
monitor_ids = 0;
char *monitor_ids_str = dbrow[index++];
if ( monitor_ids_str && *monitor_ids_str ) {
monitor_ids = new int[strlen(monitor_ids_str)];
int n_monitor_ids = 0;
const char *ptr = monitor_ids_str;
do {
int id = 0;
while( isdigit( *ptr ) ) {
id *= 10;
id += *ptr-'0';
ptr++;
}
if ( id ) {
monitor_ids[n_monitor_ids++] = id;
if ( !*ptr )
break;
}
while ( !isdigit( *ptr ) )
ptr++;
} while( *ptr );
monitor_ids[n_monitor_ids] = 0;
StringVector ids = split(monitor_ids_str, ",");
for( StringVector::iterator i = ids.begin(); i < ids.end(); ++i ) {
monitor_ids.push_back( atoi( (*i).c_str()) );
}
}
}
User::~User() {
delete monitor_ids;
monitor_ids.clear();
}
void User::Copy( const User &u ) {
strncpy( username, u.username, sizeof(username)-1 );
strncpy( password, u.password, sizeof(password)-1 );
enabled = u.enabled;
stream = u.stream;
events = u.events;
control = u.control;
monitors = u.monitors;
system = u.system;
monitor_ids = u.monitor_ids;
}
bool User::canAccess( int monitor_id ) {
if ( !monitor_ids ) {
return( true );
}
for ( int i = 0; monitor_ids[i]; i++ ) {
if ( monitor_ids[i] == monitor_id ) {
return( true );
if ( monitor_ids.empty() )
return true;
for ( std::vector<int>::iterator i = monitor_ids.begin(); i != monitor_ids.end(); ++i ) {
if ( *i == monitor_id ) {
return true;
}
}
return( false );
return false;
}
// Function to load a user from username and password

View File

@ -36,8 +36,8 @@
#include <openssl/md5.h>
#endif // HAVE_L || HAVE_LIBCRYPTO
class User
{
#include <vector>
class User {
public:
typedef enum { PERM_NONE=1, PERM_VIEW, PERM_EDIT } Permission;
@ -50,12 +50,17 @@ protected:
Permission control;
Permission monitors;
Permission system;
int *monitor_ids;
std::vector<int> monitor_ids;
public:
User();
User( MYSQL_ROW &dbrow );
explicit User( MYSQL_ROW &dbrow );
~User();
User( User &u ) { Copy(u); }
void Copy( const User &u );
User operator=(const User &u) {
Copy(u); return *this;
}
const char *getUsername() const { return( username ); }
const char *getPassword() const { return( password ); }

View File

@ -49,8 +49,7 @@ std::string trimSet(std::string str, std::string trimset) {
return str.substr( startpos, endpos-startpos+1 );
}
std::string trimSpaces(std::string str)
{
std::string trimSpaces(std::string str) {
return trimSet(str, " \t");
}
@ -80,7 +79,7 @@ const std::string stringtf( const char *format, ... )
return( tempString );
}
const std::string stringtf( const std::string &format, ... )
const std::string stringtf( const std::string format, ... )
{
va_list ap;
char tempBuffer[8192];
@ -209,10 +208,9 @@ int split(const char* string, const char delim, std::vector<std::string>& items)
return -2;
std::string str(string);
size_t pos;
while(true) {
pos = str.find(delim);
size_t pos = str.find(delim);
items.push_back(str.substr(0, pos));
str.erase(0, pos+1);

View File

@ -33,7 +33,7 @@ std::string trimSet(std::string str, std::string trimset);
std::string replaceAll(std::string str, std::string from, std::string to);
const std::string stringtf( const char *format, ... );
const std::string stringtf( const std::string &format, ... );
const std::string stringtf( const std::string format, ... );
bool startsWith( const std::string &haystack, const std::string &needle );
StringVector split( const std::string &string, const std::string &chars, int limit=0 );

View File

@ -125,7 +125,8 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
#else
video_out_stream =
avformat_new_stream(oc,(const AVCodec *)(video_in_ctx->codec));
avformat_new_stream(oc,(AVCodec *)(video_in_ctx->codec));
//avformat_new_stream(oc,(const AVCodec *)(video_in_ctx->codec));
if (!video_out_stream) {
Fatal("Unable to create video out stream\n");
} else {
@ -194,6 +195,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
converted_in_samples = NULL;
audio_out_codec = NULL;
audio_in_codec = NULL;
audio_in_ctx = NULL;
audio_out_stream = NULL;
in_frame = NULL;
@ -226,7 +228,11 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
Debug(3, "Got AAC");
audio_out_stream =
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
avformat_new_stream(oc, (const AVCodec *)(audio_in_ctx->codec));
#else
avformat_new_stream(oc, (AVCodec *)audio_in_ctx->codec);
#endif
if (!audio_out_stream) {
Error("Unable to create audio out stream\n");
audio_out_stream = NULL;
@ -406,12 +412,34 @@ VideoStore::~VideoStore() {
// Just do a file open/close/writeheader/etc.
// What if we were only doing audio recording?
if (video_out_stream) {
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
// We allocate and copy in newer ffmpeg, so need to free it
avcodec_free_context(&video_in_ctx);
#endif
video_in_ctx=NULL;
avcodec_close(video_out_ctx);
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
avcodec_free_context(&video_out_ctx);
#endif
video_out_ctx = NULL;
Debug(4, "Success freeing video_out_ctx");
}
if (audio_out_stream) {
if ( audio_out_stream ) {
if ( audio_in_codec ) {
avcodec_close(audio_in_ctx);
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
// We allocate and copy in newer ffmpeg, so need to free it
avcodec_free_context(&audio_in_ctx);
#endif
audio_in_ctx = NULL;
audio_in_codec = NULL;
} // end if audio_in_codec
avcodec_close(audio_out_ctx);
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
avcodec_free_context(&audio_out_ctx);
#endif
audio_out_ctx = NULL;
#ifdef HAVE_LIBAVRESAMPLE
if (resample_ctx) {
@ -454,10 +482,10 @@ bool VideoStore::setup_resampler() {
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
// Newer ffmpeg wants to keep everything separate... so have to lookup our own
// decoder, can't reuse the one from the camera.
AVCodec *audio_in_codec =
audio_in_codec =
avcodec_find_decoder(audio_in_stream->codecpar->codec_id);
#else
AVCodec *audio_in_codec =
audio_in_codec =
avcodec_find_decoder(audio_in_ctx->codec_id);
#endif
ret = avcodec_open2(audio_in_ctx, audio_in_codec, NULL);
@ -778,7 +806,6 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
}
opkt.flags = ipkt->flags;
int keyframe = opkt.flags & AV_PKT_FLAG_KEY;
opkt.pos = -1;
opkt.data = ipkt->data;
@ -792,7 +819,7 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
Debug(1,
"writing video packet keyframe(%d) pts(%d) dts(%d) duration(%d) "
"ipkt.duration(%d)",
keyframe, opkt.pts, opkt.dts, duration, ipkt->duration);
opkt.flags & AV_PKT_FLAG_KEY, opkt.pts, opkt.dts, duration, ipkt->duration);
if ((opkt.data == NULL) || (opkt.size < 1)) {
Warning("%s:%d: Mangled AVPacket: discarding frame", __FILE__, __LINE__);
dumpPacket(ipkt);
@ -865,6 +892,7 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
* If we are at the end of the file, pass an empty packet to the decoder
* to flush it.
*/
int data_present;
if ((ret = avcodec_decode_audio4(audio_in_ctx, in_frame,
&data_present, ipkt)) < 0) {
Error("Could not decode frame (error '%s')\n",

View File

@ -16,7 +16,6 @@ extern "C" {
class VideoStore {
private:
unsigned int packets_written;
AVOutputFormat *out_format;
AVFormatContext *oc;
@ -34,13 +33,13 @@ private:
AVFrame *out_frame;
AVCodecContext *video_in_ctx;
AVCodec *audio_in_codec;
AVCodecContext *audio_in_ctx;
int ret;
// The following are used when encoding the audio stream to AAC
AVCodec *audio_out_codec;
AVCodecContext *audio_out_ctx;
int data_present;
AVAudioFifo *fifo;
int out_frame_size;
#ifdef HAVE_LIBAVRESAMPLE

View File

@ -946,13 +946,9 @@ bool Zone::DumpSettings( char *output, bool /*verbose*/ ) {
void Zone::std_alarmedpixels(Image* pdiff_image, const Image* ppoly_image, unsigned int* pixel_count, unsigned int* pixel_sum) {
uint32_t pixelsalarmed = 0;
uint32_t pixelsdifference = 0;
uint8_t *pdiff;
const uint8_t *ppoly;
uint8_t calc_max_pixel_threshold = 255;
unsigned int lo_y;
unsigned int hi_y;
unsigned int lo_x;
unsigned int hi_x;
if(max_pixel_threshold)
calc_max_pixel_threshold = max_pixel_threshold;
@ -960,12 +956,12 @@ void Zone::std_alarmedpixels(Image* pdiff_image, const Image* ppoly_image, unsig
lo_y = polygon.LoY();
hi_y = polygon.HiY();
for ( unsigned int y = lo_y; y <= hi_y; y++ ) {
lo_x = ranges[y].lo_x;
hi_x = ranges[y].hi_x;
unsigned int lo_x = ranges[y].lo_x;
unsigned int hi_x = ranges[y].hi_x;
Debug( 7, "Checking line %d from %d -> %d", y, lo_x, hi_x );
pdiff = (uint8_t*)pdiff_image->Buffer( lo_x, y );
ppoly = ppoly_image->Buffer( lo_x, y );
uint8_t *pdiff = (uint8_t*)pdiff_image->Buffer( lo_x, y );
const uint8_t *ppoly = ppoly_image->Buffer( lo_x, y );
for ( unsigned int x = lo_x; x <= hi_x; x++, pdiff++, ppoly++ ) {
if ( *ppoly && (*pdiff > min_pixel_threshold) && (*pdiff <= calc_max_pixel_threshold) ) {

View File

@ -84,12 +84,6 @@ int main( int argc, const char *argv[] ) {
zmLoadConfig();
logInit( "zms" );
hwcaps_detect();
zmSetDefaultTermHandler();
zmSetDefaultDieHandler();
const char *query = getenv( "QUERY_STRING" );
if ( query ) {
@ -175,6 +169,14 @@ int main( int argc, const char *argv[] ) {
} // end foreach parm
} // end if query
char log_id_string[32] = "zms";
if ( monitor_id ) {
snprintf(log_id_string, sizeof(log_id_string), "zms_m%d", monitor_id);
} else {
snprintf(log_id_string, sizeof(log_id_string), "zms_e%d", event_id);
}
logInit( log_id_string );
if ( config.opt_use_auth ) {
User *user = 0;
@ -205,6 +207,10 @@ int main( int argc, const char *argv[] ) {
ValidateAccess( user, monitor_id );
}
hwcaps_detect();
zmSetDefaultTermHandler();
zmSetDefaultDieHandler();
setbuf( stdout, 0 );
if ( nph ) {
fprintf( stdout, "HTTP/1.0 200 OK\r\n" );

View File

@ -514,10 +514,10 @@ int main( int argc, char *argv[] ) {
}
if ( function & ZMU_EVENT ) {
if ( verbose )
printf( "Last event id: %d\n", monitor->GetLastEvent() );
printf( "Last event id: %d\n", monitor->GetLastEventId() );
else {
if ( have_output ) printf( "%c", separator );
printf( "%d", monitor->GetLastEvent() );
printf( "%d", monitor->GetLastEventId() );
have_output = true;
}
}
@ -693,8 +693,7 @@ int main( int argc, char *argv[] ) {
Error( "Can't use query result: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) );
}
int n_monitors = mysql_num_rows( result );
Debug( 1, "Got %d monitors", n_monitors );
Debug( 1, "Got %d monitors", mysql_num_rows( result ) );
printf( "%4s%5s%6s%9s%14s%6s%6s%8s%8s\n", "Id", "Func", "State", "TrgState", "LastImgTim", "RdIdx", "WrIdx", "LastEvt", "FrmRate" );
for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) {
@ -713,7 +712,7 @@ int main( int argc, char *argv[] ) {
tv.tv_sec, tv.tv_usec/10000,
monitor->GetLastReadIndex(),
monitor->GetLastWriteIndex(),
monitor->GetLastEvent(),
monitor->GetLastEventId(),
monitor->GetFPS()
);
delete monitor;

View File

@ -8,6 +8,13 @@ exit;
fi
DEBUILD=`which debuild`;
if [ "$DEBUILD" == "" ]; then
echo "You must install the devscripts package. Try sudo apt-get install devscripts";
exit;
fi
for i in "$@"
do
case $i in

View File

@ -1 +1 @@
1.31.12
1.31.15

View File

@ -76,6 +76,19 @@ if ( canView( 'Events' ) ) {
ajaxError( 'Export Failed' );
break;
}
case 'download' :
{
require_once( ZM_SKIN_PATH.'/includes/export_functions.php' );
$exportVideo = 1;
$exportFormat = $_REQUEST['exportFormat'];
$exportStructure = 'flat';
$exportIds = !empty($_REQUEST['eids'])?$_REQUEST['eids']:$_REQUEST['id'];
if ( $exportFile = exportEvents( $exportIds, false, false, false, $exportVideo, false, $exportFormat, $exportStructure ) )
ajaxResponse( array( 'exportFile'=>$exportFile ) );
else
ajaxError( 'Export Failed' );
break;
}
}
}

View File

@ -1,4 +1,8 @@
<?php
if ($_REQUEST['entity'] == "navBar") {
ajaxResponse(getNavBarHtml('reload'));
return;
}
$statusData = array(
'system' => array(
@ -137,6 +141,17 @@ $statusData = array(
//'Path' => array( 'postFunc' => 'getEventPath' ),
),
),
'frames' => array(
'permission' => 'Events',
'table' => 'Frames',
'selector' => 'EventId',
'elements' => array(
'EventId' => true,
'FrameId' => true,
'Type' => true,
'Delta' => true,
),
),
'frame' => array(
'permission' => 'Events',
'table' => 'Frames',

View File

@ -15,6 +15,7 @@ if ( !($socket = @socket_create( AF_UNIX, SOCK_DGRAM, 0 )) ) {
$locSockFile = ZM_PATH_SOCKS.'/zms-'.sprintf("%06d",$_REQUEST['connkey']).'w.sock';
if ( file_exists( $locSockFile ) ) {
Warning("sock file $locSockFile already exists?! Is someone else talking to zms?");
// They could be. We can maybe have concurrent requests from a browser.
} else {
Logger::Debug("socket file does not exist, we should be good to connect.");
}
@ -115,7 +116,9 @@ switch ( $data['type'] ) {
case MSG_DATA_WATCH :
{
$data = unpack( "ltype/imonitor/istate/dfps/ilevel/irate/ddelay/izoom/Cdelayed/Cpaused/Cenabled/Cforced", $msg );
Logger::Debug("FPS: " . $data['fps'] );
$data['fps'] = round( $data['fps'], 2 );
Logger::Debug("FPS: " . $data['fps'] );
$data['rate'] /= RATE_BASE;
$data['delay'] = round( $data['delay'], 2 );
$data['zoom'] = round( $data['zoom']/SCALE_BASE, 1 );

View File

@ -124,7 +124,7 @@ public function beforeFilter() {
if (!$this->Monitor->exists($id)) {
throw new NotFoundException(__('Invalid monitor'));
}
if ($this->Session->Read('systemPermission') != 'Edit')
if ($this->Session->Read('monitorPermission') != 'Edit')
{
throw new UnauthorizedException(__('Insufficient privileges'));
return;

View File

@ -9,6 +9,7 @@ class Event {
'StorageId',
'Name',
'DiskSpace',
'SaveJPEGs',
);
public function __construct( $IdOrRow = null ) {
$row = NULL;

View File

@ -15,6 +15,9 @@ private $defaults = array(
'Height' => null,
'Orientation' => null,
'AnalysisFPSLimit' => null,
'AnalysisFPS' => null,
'CaptureFPS' => null,
'ZoneCount' => 0,
);
private $control_fields = array(
'Name' => '',
@ -185,11 +188,13 @@ private $control_fields = array(
}
public function getStreamSrc( $args, $querySep='&amp;' ) {
$streamSrc = ZM_BASE_PROTOCOL.'://';
if ( isset($this->{'ServerId'}) and $this->{'ServerId'} ) {
$Server = new Server( $this->{'ServerId'} );
$streamSrc = ZM_BASE_PROTOCOL.'://'.$Server->Hostname();
$streamSrc .= $Server->Hostname();
} else {
$streamSrc = ZM_BASE_URL;
$streamSrc .= $_SERVER['HTTP_HOST'];
}
if ( ZM_MIN_STREAMING_PORT )
$streamSrc .= ':'. (ZM_MIN_STREAMING_PORT+$this->{'Id'});

View File

@ -18,7 +18,7 @@ class MontageLayout {
if ( ! $row ) {
Error("Unable to load MontageLayout record for Id=" . $IdOrRow );
}
} elseif ( is_array( $IdOrRow ) ) {
} else if ( is_array( $IdOrRow ) ) {
$row = $IdOrRow;
} else {
Error("Unknown argument passed to MontageLayout Constructor ($IdOrRow)");

View File

@ -110,23 +110,23 @@ class Storage {
}
public function disk_used_space() {
# This isn't a function like this in php, so we have to add up the space used in each event.
if ( ! array_key_exists( 'disk_used_space', $this ) ) {
if ( ! array_key_exists( 'DiskSpace', $this ) ) {
$used = 0;
if ( $this->{'Type'} == 's3fs' ) {
$used = dbFetchOne('SELECT SUM(DiskSpace) AS DiskSpace FROM Events WHERE StorageId=? AND DiskSpace IS NOT NULL', 'DiskSpace', array($this->Id()) );
foreach ( Event::find_all( array( 'StorageId'=>$this->Id(), 'DiskSpace'=>null ) ) as $Event ) {
$Event->Storage( $this ); // Prevent further db hit
$used += $Event->DiskSpace();
}
foreach ( Event::find_all( array( 'StorageId'=>$this->Id(), 'DiskSpace'=>null ) ) as $Event ) {
$Event->Storage( $this ); // Prevent further db hit
$used += $Event->DiskSpace();
}
} else {
$path = $this->Path();
$used = disk_total_space( $path ) - disk_free_space( $path );;
$path = $this->Path();
$used = disk_total_space( $path ) - disk_free_space( $path );;
}
$this->{'disk_used_space'} = $used;
$this->{'DiskSpace'} = $used;
}
return $this->{'disk_used_space'};
return $this->{'DiskSpace'};
}
}
?>

View File

@ -151,14 +151,16 @@ Warning("Addterm");
if ( ! empty($_REQUEST['Id']) ) {
dbQuery( 'DELETE FROM Filters WHERE Id=?', array( $_REQUEST['Id'] ) );
}
} else if ( ( $action == 'save' ) or ( $action == 'execute' ) or ( $action == 'submit' ) ) {
} else if ( ( $action == 'Save' ) or ( $action == 'SaveAs' ) or ( $action == 'execute' ) ) {
# or ( $action == 'submit' ) ) {
$sql = '';
$_REQUEST['filter']['Query']['sort_field'] = validStr($_REQUEST['filter']['Query']['sort_field']);
$_REQUEST['filter']['Query']['sort_asc'] = validStr($_REQUEST['filter']['Query']['sort_asc']);
$_REQUEST['filter']['Query']['limit'] = validInt($_REQUEST['filter']['Query']['limit']);
if ( $action == 'execute' or $action == 'submit' ) {
$sql .= ' Name = \'_TempFilter'.time().'\'';
if ( $action == 'execute' ) {
$tempFilterName = '_TempFilter'.time();
$sql .= ' Name = \''.$tempFilterName.'\'';
} else {
$sql .= ' Name = '.dbEscape($_REQUEST['filter']['Name']);
}
@ -175,12 +177,15 @@ Warning("Addterm");
$sql .= ', Background = '. ( !empty($_REQUEST['filter']['Background']) ? 1 : 0);
$sql .= ', Concurrent = '. ( !empty($_REQUEST['filter']['Concurrent']) ? 1 : 0);
if ( $_REQUEST['Id'] ) {
if ( $_REQUEST['Id'] and ( $action == 'Save' ) ) {
dbQuery( 'UPDATE Filters SET ' . $sql. ' WHERE Id=?', array($_REQUEST['Id']) );
} else {
dbQuery( 'INSERT INTO Filters SET' . $sql );
$_REQUEST['Id'] = dbInsertId();
}
if ( $action == 'execute' ) {
executeFilter( $tempFilterName );
}
} // end if save or execute
} // end if canEdit(Events)
@ -370,6 +375,7 @@ if ( !empty($_REQUEST['mid']) && canEdit( 'Monitors', $_REQUEST['mid'] ) ) {
dbQuery( "UPDATE Zones SET ".implode( ", ", $changes )." WHERE MonitorId=? AND Id=?", array( $mid, $zid) );
} else {
dbQuery( "INSERT INTO Zones SET MonitorId=?, ".implode( ", ", $changes ), array( $mid ) );
dbQuery( 'UPDATE Monitors SET ZoneCount=(SELECT COUNT(Id) FROM Zones WHERE MonitorId=Monitors.Id) WHERE Id=?', array($mid));
}
//if ( $cookies ) session_write_close();
if ( daemonCheck() ) {
@ -422,6 +428,7 @@ if ( !empty($_REQUEST['mid']) && canEdit( 'Monitors', $_REQUEST['mid'] ) ) {
foreach( $_REQUEST['markZids'] as $markZid ) {
$zone = dbFetchOne( 'select * from Zones where Id=?', NULL, array($markZid) );
dbQuery( 'delete from Zones WHERE MonitorId=? AND Id=?', array( $mid, $markZid) );
dbQuery( 'UPDATE Monitors SET ZoneCount=(SELECT COUNT(Id) FROM Zones WHERE MonitorId=Monitors.Id) WHERE Id=?', array($mid));
$deletedZid = 1;
}
if ( $deletedZid ) {
@ -601,10 +608,10 @@ if ( canEdit( 'Monitors' ) ) {
} // end if ZM_OPT_FAST_DELETE
// This is the important stuff
dbQuery( 'DELETE FROM Monitors WHERE Id = ?', array($markMid) );
dbQuery( 'DELETE FROM Zones WHERE MonitorId = ?', array($markMid) );
if ( ZM_OPT_X10 )
dbQuery( 'DELETE FROM TriggersX10 WHERE MonitorId=?', array($markMid) );
dbQuery( 'DELETE FROM Monitors WHERE Id = ?', array($markMid) );
fixSequences();

View File

@ -189,21 +189,21 @@ function csrf_check($fatal = true) {
$tokens = '';
do {
if (!isset($_POST[$name])) {
Logger::Debug("POST[$name] is not set");
#Logger::Debug("POST[$name] is not set");
break;
} else {
Logger::Debug("POST[$name] is set as " . $_POST[$name] );
#} else {
#Logger::Debug("POST[$name] is set as " . $_POST[$name] );
}
// we don't regenerate a token and check it because some token creation
// schemes are volatile.
$tokens = $_POST[$name];
if (!csrf_check_tokens($tokens)) {
Logger::Debug("Failed checking tokens");
#Logger::Debug("Failed checking tokens");
break;
} else {
Logger::Debug("Token passed");
#} else {
#Logger::Debug("Token passed");
}
$ok = true;
} while (false);
@ -308,27 +308,27 @@ function csrf_check_tokens($tokens) {
* Checks if a token is valid.
*/
function csrf_check_token($token) {
Logger::Debug("Checking CSRF token $token");
#Logger::Debug("Checking CSRF token $token");
if (strpos($token, ':') === false) {
Logger::Debug("Checking CSRF token $token bad because no :");
#Logger::Debug("Checking CSRF token $token bad because no :");
return false;
}
list($type, $value) = explode(':', $token, 2);
if (strpos($value, ',') === false) {
Logger::Debug("Checking CSRF token $token bad because no ,");
#Logger::Debug("Checking CSRF token $token bad because no ,");
return false;
}
list($x, $time) = explode(',', $token, 2);
if ($GLOBALS['csrf']['expires']) {
if (time() > $time + $GLOBALS['csrf']['expires']) {
Logger::Debug("Checking CSRF token $token bad because expired");
#Logger::Debug("Checking CSRF token $token bad because expired");
return false;
}
}
switch ($type) {
case 'sid':
{
Logger::Debug("Checking sid: $value === " . csrf_hash(session_id(), $time) );
#Logger::Debug("Checking sid: $value === " . csrf_hash(session_id(), $time) );
return $value === csrf_hash(session_id(), $time);
}
case 'cookie':
@ -341,7 +341,7 @@ return false;
Logger::Debug("Checking key: no key set" );
return false;
}
Logger::Debug("Checking sid: $value === " . csrf_hash($GLOBALS['csrf']['key'], $time) );
#Logger::Debug("Checking sid: $value === " . csrf_hash($GLOBALS['csrf']['key'], $time) );
return $value === csrf_hash($GLOBALS['csrf']['key'], $time);
// We could disable these 'weaker' checks if 'key' was set, but
// that doesn't make me feel good then about the cookie-based

View File

@ -134,7 +134,7 @@ function dbQuery( $sql, $params=NULL ) {
} else {
$result = $dbConn->query( $sql );
}
if ( 0 ) {
if ( 1 ) {
if ( $params )
Warning("SQL: $sql" . implode(',',$params) . ' rows: '.$result->rowCount() );
else

View File

@ -28,13 +28,13 @@ if ( version_compare( phpversion(), '4.3.0', '<') ) {
}
# We are requiring these because this file is getting included from the api, which hasn't already included them.
require_once( 'logger.php' );
require_once( 'database.php' );
require_once('logger.php');
require_once('database.php');
function userLogin( $username, $password='', $passwordHashed=false ) {
global $user, $cookies;
$sql = 'SELECT * FROM Users WHERE Enabled = 1';
$sql = 'SELECT * FROM Users WHERE Enabled=1';
$sql_values = NULL;
if ( ZM_AUTH_TYPE == 'builtin' ) {
if ( $passwordHashed ) {
@ -44,7 +44,7 @@ function userLogin( $username, $password='', $passwordHashed=false ) {
}
$sql_values = array( $username, $password );
} else {
$sql .= ' AND Username = ?';
$sql .= ' AND Username=?';
$sql_values = array( $username );
}
$_SESSION['username'] = $username;
@ -138,26 +138,27 @@ function getAuthUser( $auth ) {
$authHash = md5( $authKey );
if ( $auth == $authHash ) {
return( $user );
return $user;
}
} // end foreach hour
} // end foreach user
} // end if using auth hash
Error( "Unable to authenticate user from auth hash '$auth'" );
return( false );
}
} // end getAuthUser($auth)
function generateAuthHash( $useRemoteAddr ) {
if ( ZM_OPT_USE_AUTH and ZM_AUTH_RELAY == 'hashed' and isset($_SESSION['username']) and $_SESSION['passwordHash'] ) {
# regenerate a hash at half the liftetime of a hash, an hour is 3600 so half is 1800
if ( ( ! isset($_SESSION['AuthHash']) ) or ( $_SESSION['AuthHashGeneratedAt'] < time() - ( ZM_AUTH_HASH_TTL * 1800 ) ) ) {
$time = time();
if ( ( ! isset($_SESSION['AuthHash']) ) or ( $_SESSION['AuthHashGeneratedAt'] < ( $time - ( ZM_AUTH_HASH_TTL * 1800 ) ) ) ) {
# Don't both regenerating Auth Hash if an hour hasn't gone by yet
$time = localtime();
$local_time = localtime();
$authKey = '';
if ( $useRemoteAddr ) {
$authKey = ZM_AUTH_HASH_SECRET.$_SESSION['username'].$_SESSION['passwordHash'].$_SESSION['remoteAddr'].$time[2].$time[3].$time[4].$time[5];
$authKey = ZM_AUTH_HASH_SECRET.$_SESSION['username'].$_SESSION['passwordHash'].$_SESSION['remoteAddr'].$local_time[2].$local_time[3].$local_time[4].$local_time[5];
} else {
$authKey = ZM_AUTH_HASH_SECRET.$_SESSION['username'].$_SESSION['passwordHash'].$time[2].$time[3].$time[4].$time[5];
$authKey = ZM_AUTH_HASH_SECRET.$_SESSION['username'].$_SESSION['passwordHash'].$local_time[2].$local_time[3].$local_time[4].$local_time[5];
}
$auth = md5( $authKey );
if ( session_status() == PHP_SESSION_NONE ) {
@ -167,10 +168,10 @@ function generateAuthHash( $useRemoteAddr ) {
Warning("Session is not active. AuthHash will not be cached. called from $file:$line");
}
$_SESSION['AuthHash'] = $auth;
$_SESSION['AuthHashGeneratedAt'] = time();
$_SESSION['AuthHashGeneratedAt'] = $time;
Logger::Debug("Generated new auth $auth at " . $_SESSION['AuthHashGeneratedAt']. " using $authKey" );
} else {
Logger::Debug( "Using cached auth " . $_SESSION['AuthHash'] );
Logger::Debug( "Using cached auth " . $_SESSION['AuthHash'] ." beacuse " . $_SESSION['AuthHashGeneratedAt'] . ' < '. $time . ' - ' . ZM_AUTH_HASH_TTL . ' * 1800 = '.( $time - (ZM_AUTH_HASH_TTL * 1800) ));
} # end if AuthHash is not cached
return $_SESSION['AuthHash'];
} else {
@ -347,7 +348,7 @@ function getImageStreamHTML( $id, $src, $width, $height, $title='' ) {
if ( canStreamIframe() ) {
return '<iframe id="'.$id.'" src="'.$src.'" alt="'. validHtmlStr($title) .'" '.($width? ' width="'. validInt($width).'"' : '').($height?' height="'.validInt($height).'"' : '' ).'/>';
} else {
return '<img id="'.$id.'" src="'.$src.'" alt="'. validHtmlStr($title) .'" style="'.($width? ' width:'. validInt($width) .'px;': '').($height ? ' height:'. validInt( $height ).'px;':'').'"/>';
return '<img id="'.$id.'" src="'.$src.'" alt="'. validHtmlStr($title) .'" style="'.($width? ' width:'.$width.';' : '' ).($height ? ' height:'. $height.';' : '' ).'"/>';
}
}
@ -1449,6 +1450,66 @@ function getDiskBlocks() {
return( $space );
}
function systemStats() {
$load = getLoad();
$diskPercent = getDiskPercent();
$pathMapPercent = getDiskPercent(ZM_PATH_MAP);
$cpus = getcpus();
$normalized_load = $load / $cpus;
# Colorize the system load stat
if ( $normalized_load <= 0.75 ) {
$htmlLoad=$load;
} elseif ( $normalized_load <= 0.9 ) {
$htmlLoad="<span class=\"warning\">$load</span>";
} elseif ( $normalized_load <= 1.1 ) {
$htmlLoad="<span class=\"error\">$load</span>";
} else {
$htmlLoad="<span class=\"critical\">$load</span>";
}
# Colorize the disk space stat
if ( $diskPercent < 98 ) {
$htmlDiskPercent="$diskPercent%";
} elseif ( $diskPercent <= 99 ) {
$htmlDiskPercent="<span class=\"warning\">$diskPercent%</span>";
} else {
$htmlDiskPercent="<span class=\"error\">$diskPercent%</span>";
}
# Colorize the PATH_MAP (usually /dev/shm) stat
if ( $pathMapPercent < 90 ) {
if ( disk_free_space(ZM_PATH_MAP) > 209715200 ) { # have to always have at least 200MiB free
$htmlPathMapPercent="$pathMapPercent%";
} else {
$htmlPathMapPercent="<span class=\"warning\">$pathMapPercent%</span>";
}
} elseif ( $pathMapPercent < 100 ) {
$htmlPathMapPercent="<span class=\"warning\">$pathMapPercent%</span>";
} else {
$htmlPathMapPercent="<span class=\"critical\">$pathMapPercent%</span>";
}
$htmlString = translate('Load').": $htmlLoad - ".translate('Disk').": $htmlDiskPercent - ".ZM_PATH_MAP.": $htmlPathMapPercent";
return( $htmlString );
}
function getcpus() {
if (is_readable("/proc/cpuinfo") ) { # Works on Linux
preg_match_all('/^processor/m', file_get_contents('/proc/cpuinfo'), $matches);
$num_cpus = count($matches[0]);
} else { # Works on BSD
$matches = explode(":", shell_exec("sysctl hw.ncpu"));
$num_cpus = trim($matches[1]);
}
return( $num_cpus );
}
// Function to fix a problem whereby the built in PHP session handling
// features want to put the sid as a hidden field after the form or
// fieldset tag, neither of which will work with strict XHTML Basic.
@ -2076,7 +2137,7 @@ function cache_bust( $file ) {
# Use the last modified timestamp to create a link that gets a different filename
# To defeat caching. Should probably use md5 hash
$parts = pathinfo($file);
$cacheFile = 'cache/'.$parts['filename'].'-'.filemtime($file).'.'.$parts['extension'];
$cacheFile = 'cache/'.$parts['filename'].'-'.$_COOKIE['zmCSS'].'-'.filemtime($file).'.'.$parts['extension'];
if ( file_exists( ZM_PATH_WEB.'/'.$cacheFile ) or symlink( ZM_PATH_WEB.'/'.$file, ZM_PATH_WEB.'/'.$cacheFile ) ) {
return $cacheFile;
} else {
@ -2151,16 +2212,18 @@ function getStreamHTML( $monitor, $options = array() ) {
if ( isset($options['scale']) and $options['scale'] and ( $options['scale'] != 100 ) ) {
//Warning("Scale to " . $options['scale'] );
$options['width'] = reScale( $monitor->Width(), $options['scale'] );
$options['height'] = reScale( $monitor->Height(), $options['scale'] );
$options['width'] = reScale( $monitor->Width(), $options['scale'] ) . 'px';
$options['height'] = reScale( $monitor->Height(), $options['scale'] ) . 'px';
} else {
# scale is empty or 100
# There may be a fixed width applied though, in which case we need to leave the height empty
if ( ! ( isset($options['width']) and $options['width'] ) ) {
$options['width'] = $monitor->Width();
$options['width'] = $monitor->Width() . 'px';
if ( ! ( isset($options['height']) and $options['height'] ) ) {
$options['height'] = $monitor->Height();
$options['height'] = $monitor->Height() . 'px';
}
} else if ( ! isset($options['height']) ) {
$options['height'] = '';
}
}
if ( ! isset($options['mode'] ) ) {
@ -2213,6 +2276,7 @@ function getStreamMode( ) {
$streamMode = 'single';
Info( 'The system has fallen back to single jpeg mode for streaming. Consider enabling Cambozola or upgrading the client browser.' );
}
return $streamMode;
} // end function getStreamMode
function folder_size($dir) {

View File

@ -37,7 +37,7 @@ function loadLanguage( $prefix="" )
$fallbackLangFile = $prefix.'lang/en_gb.php';
$systemLangFile = $prefix.'lang/'.ZM_LANG_DEFAULT.'.php';
if ( isset($user['Language']) )
$userLangFile = $prefix.$user['Language'].'.php';
$userLangFile = $prefix.'lang/'.$user['Language'].'.php';
if ( isset($userLangFile) && file_exists( $userLangFile ) )
return( $userLangFile );

View File

@ -34,7 +34,7 @@ if ( version_compare( phpversion(), '4.1.0', '<') ) {
}
// Useful debugging lines for mobile devices
if ( true ) {
if ( false ) {
ob_start();
phpinfo( INFO_VARIABLES );
$fp = fopen( '/tmp/env.html', 'w' );
@ -195,7 +195,7 @@ isset($action) || $action = NULL;
if ( ZM_ENABLE_CSRF_MAGIC && $action != 'login' && $view != 'view_video' && $view != 'video' && $request != 'control' && $view != 'frames') {
require_once( 'includes/csrf/csrf-magic.php' );
Logger::Debug("Calling csrf_check with the following values: \$request = \"$request\", \$view = \"$view\", \$action = \"$action\"");
#Logger::Debug("Calling csrf_check with the following values: \$request = \"$request\", \$view = \"$view\", \$action = \"$action\"");
csrf_check();
}

View File

@ -50,7 +50,10 @@ function logReport( level, message, file, line )
if ( !debugReq )
{
debugParms = "view=request&request=log&task=create&browser[name]="+Browser.name+"&browser[version]="+Browser.version+"&browser[platform]="+Browser.Platform.name;
if ( Browser )
debugParms = "view=request&request=log&task=create&browser[name]="+Browser.name+"&browser[version]="+Browser.version+"&browser[platform]="+(Browser.Platform?Browser.Platform.name:'unknown');
else
debugParms = "view=request&request=log&task=create&browser[name]=unknown&browser[version]=unknown&browser[platform]=unknown";
debugReq = new Request.JSON( { url: thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'chain' } );
}
var requestParms = debugParms;

View File

@ -322,6 +322,8 @@ $SLANG = array(
'ExportDetails' => 'Export Event Details',
'Exif' => 'Embed EXIF data into image',
'Export' => 'Export',
'DownloadVideo' => 'Download Video',
'GenerateDownload' => 'Generate Download',
'ExportFailed' => 'Export Failed',
'ExportFormat' => 'Export File Format',
'ExportFormatTar' => 'Tar',

View File

@ -1,3 +1,4 @@
/*
* ZoneMinder Base Stylesheet, $Date$, $Revision$
* Copyright (C) 2001-2008 Philip Coombes
@ -95,9 +96,6 @@ input.noborder {
border: 0;
}
input[disabled] {
color: #888888;
}
img {
display: inline-block;
@ -349,9 +347,11 @@ th.table-th-sort-rev span.table-th-sort-span {
#header {
width: 100%;
line-height: 24px;
margin: 8px auto;
margin: 0 auto 4px auto;
line-height: 1;
text-align: left;
padding: 3px 0;
border-bottom: 1px solid #555555;
}
#header h2 {
@ -381,7 +381,7 @@ th.table-th-sort-rev span.table-th-sort-span {
#content {
width: 96%;
margin: 8px auto;
margin: 0 auto 8px auto;
line-height: 130%;
text-align: center;
}
@ -407,11 +407,15 @@ th.table-th-sort-rev span.table-th-sort-span {
}
*/
#content > input[type=submit], #content > input[type=button], #content > button {
#content > input[type=submit],
#content > input[type=button],
#content > button {
margin-top: 8px;
}
#content table input[type=submit], #content table input[type=button], #content table button {
#content table input[type=submit],
#content table input[type=button],
#content table button {
margin-top: 0;
}
@ -420,6 +424,7 @@ th.table-th-sort-rev span.table-th-sort-span {
float: right;
}
#contentButtons button,
#contentButtons input {
margin-left: 8px;
margin-bottom: 4px;
@ -487,3 +492,36 @@ margin-left: 0px;
.nav-pills > li > a {
border-radius: 0;
}
button,
input[type=button],
input[type=submit] {
padding: 1px 6px;
/*
background-color: #3498db;
color: #fff;
border-color: #3498db;
font-weight: 200;
padding: 5px 10px;
cursor: pointer;
*/
}
button:hover,
input[type=button]:hover,
input[type=submit]:hover {
/*
background-color: #34a2ee;
*/
}
button:disabled,
input[disabled],
input[type=button]:disabled,
input[type=submit]:disabled {
color: #888888;
/*
background-color: #aaaaaa;
*/
border-color: #bbbbbb;
}

View File

@ -12,6 +12,19 @@
float: right;
}
#systemStats .warning {
color: orange;
}
#systemStats .error {
color: red;
}
#systemStats .critical {
color: red;
text-decoration: blink;
}
#monitorSummary {
float: left;
text-align: left;

View File

@ -12,108 +12,64 @@
.alarmCue {
background-color: #222222;
height: 1.5em;
height: 1.25em;
text-align: left;
margin: 0 auto 0 auto;
border-radius: 0 0 .3em .3em;
}
.alarmCue span {
background-color:red;
height: 1.5em;
height: 100%;
display: inline-block;
border-radius: 0;
}
span.noneCue {
background: none;
}
#header {
display: flex;
justify-content: space-between;
flex-direction: column;
}
#header h2, #header a {
line-height: 1.1;
margin:5px 0 0 0;
}
#dataBar {
width: 100%;
margin: 2px auto;
text-align: center;
display: flex;
flex-wrap:wrap;
justify-content: space-between;
}
#dataBar #dataTable {
#menuBar1 {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
width: 100%;
text-align: center;
margin: 4px 0 0 0;
}
#dataBar #dataTable td {
text-align: center;
padding: 2px;
#menuBar1 #replayControl {
margin: 0 4px 0 auto;
}
#menuBar1 div {
margin: auto 5px;
}
#nameControl input[type="button"]{
height: 100%;
}
#eventVideo {
display: inline-block;
postion: relative;
}
#menuBar1 {
width: 100%;
padding: 3px 0;
text-align: center;
clear: both;
}
#menuBar1 #nameControl {
float: left;
}
#menuBar1 #nameControl #eventName {
margin-right: 4px;
}
#menuBar1 #replayControl {
float: right;
margin-left: 8px;
}
#menuBar1 #scaleControl {
float: right;
margin-left: 8px;
}
#menuBar2 {
width: 100%;
padding: 3px 0;
margin-bottom: 4px;
}
#menuBar2 div {
text-align: left;
float: left;
padding: 0 12px;
}
#menuBar2 #closeWindow {
float: right;
text-align: right;
}
#menuBar1:after,
#menuBar2:after {
content: ".";
display: block;
height: 0;
font-size: 0;
clear: both;
visibility: hidden;
}
#videoBar1 div {
text-align: center;
float: center;
}
#videoBar1 #prevEvent {
float: left;
}
#videoBar1 #dlEvent {
float: center;
}
#videoBar1 #nextEvent {
float: right;
position: relative;
}
#imageFeed {
@ -142,32 +98,32 @@ span.noneCue {
#monitorStatus #monitorState {
}
.dvrControls {
#dvrControls {
margin-top: 3px;
margin-bottom: 2px;
text-align: center;
}
.dvrControls input {
height: 20px;
width: 28px;
padding-bottom: 3px;
#dvrControls input {
height: 1.5em;
width: 2em;
padding: 0 ;
margin: 0 3px;
}
.dvrControls input[disabled=disabled] {
#dvrControls input[disabled=disabled] {
color: #aaaaaa;
}
.dvrControls input.active {
#dvrControls input.active {
border: 1px solid blue;
}
.dvrControls input.inactive {
#dvrControls input.inactive {
border: 1px solid green;
}
.dvrControls input.unavail {
#dvrControls input.unavail {
border: 1px solid red;
}
@ -183,31 +139,29 @@ span.noneCue {
#progressBar {
position: relative;
top: -1.5em;
height: 1.5em;
margin: 0 auto -1.5em auto;
top: -1.25em;
height: 1.25em;
margin: 0 auto -1.25em auto;
}
#progressBar .progressBox {
height: 1.5em;
transition: width .1s;
height: 100%;
background: rgba(170, 170, 170, .7);
border-radius: 0 0 .3em .3em;
}
#eventStills {
width: 100%;
position: relative;
}
#eventThumbsPanel {
position: relative;
width: 100%;
margin: 4px auto;
z-index: 1;
}
#eventThumbs {
margin: 0 auto;
width: 100%;
overflow: hidden;
height: 300px;
}
@ -226,14 +180,19 @@ span.noneCue {
}
#eventImagePanel {
display: none;
position: absolute;
top: 0;
left: 0;
z-index: 10;
width: 100%;
}
#eventImageFrame {
border: 2px solid gray;
background-color: white;
padding: 4px;
display: inline-block;
}
#eventImage {
@ -243,6 +202,14 @@ span.noneCue {
margin-top: 2px;
}
#eventImageBar::after {
visibility: hidden;
display: block;
content: "";
clear: both;
height: 0;
}
#eventImageStats {
float: left;
}
@ -258,6 +225,7 @@ span.noneCue {
#eventImageNav {
position: relative;
margin: 0 0 4px 0;
}
#eventImageNav input {
@ -266,20 +234,20 @@ span.noneCue {
}
#thumbsSliderPanel {
width: 400px;
margin: 4px auto 0;
background: #888888;
padding: 1px;
width: 80%;
margin: 0px auto 4px auto;
}
#thumbsSlider {
width: 400px;
height: 10px;
background: #dddddd;
width: 100%;
height: 1.25em;
position: relative;
top: -1.25em;
margin: 0 0 -1.25em 0;
}
#thumbsKnob {
width: 8px;
height: 10px;
background-color: #444444;
width: 1em;
height: 100%;
background-color: #999999;
}

View File

@ -1,31 +1,5 @@
#controls {
height: 16px;
width: 100%;
text-align: center;
margin: 0 auto;
position: relative;
}
#controls a {
width: 32%;
}
#controls #refreshLink {
position: absolute;
left: 0%;
text-align: left;
}
#controls #filterLink {
position: absolute;
left: 34%;
text-align: center;
}
#controls #timelineLink {
position: absolute;
left: 68%;
text-align: right;
.archived {
background-color: #f8f8f8;;
}
#contentTable.major .colTime {
@ -40,3 +14,26 @@
text-align: right;
padding-right: 8px;
}
#header {
display: flex;
justify-content: space-between;
}
#header h2, #header a {
line-height: 1.1;
margin:5px 0 0 0;
}
#header #info, #header #pagination, #header #controls {
display: flex;
flex-direction: column;
}
#header #controls {
align-items: flex-end;
}
#header #pagination {
align-items: center;
}

View File

@ -31,3 +31,7 @@ table.filterTable {
width: 300px;
text-align: right;
}
input#filter\[Name\] {
width: 400px;
}

View File

@ -1,33 +1,16 @@
#scaleControl {
float: right;
}
#controls {
width: 80%;
text-align: center;
margin: 0 auto;
display: flex;
justify-content: space-between;
}
#controls a {
width: 40px;
margin-left: -20px;
}
#firstLink {
position: absolute;
left: 13%;
}
#prevLink {
position: absolute;
left: 37%;
}
#nextLink {
position: absolute;
left: 63%;
}
#lastLink {
position: absolute;
left: 87%;
}

View File

@ -19,6 +19,10 @@
#monitors .alert {
color: #ffa500;
margin: 0;
padding: 0;
border-radius: 0;
border: none;
}
#monitors .imageFeed {

View File

@ -36,3 +36,7 @@
input[type=range]::-ms-tooltip {
display: none;
}
#downloadVideo {
margin-left: 5px;
}

View File

@ -5,6 +5,25 @@
margin: 0 auto;
}
#header {
display: flex;
justify-content: space-between;
}
#header h2, #header a {
line-height: 1.1;
margin:5px 0 0 0;
}
#header #info, #header #headerButtons {
display: flex;
flex-direction: column;
}
#header #headerButtons {
align-items: flex-end;
}
#title {
position: relative;
margin: 0 auto;
@ -15,20 +34,6 @@
line-height: 20px;
}
#listLink {
position: absolute;
top: 5px;
left: 20px;
height: 15px;
}
#closeLink {
position: absolute;
top: 5px;
right: 20px;
height: 15px;
}
#topPanel {
position: relative;
height: 220px;

View File

@ -1,37 +1,17 @@
@import url(../control.css);
#menuBar {
margin: 6px auto 4px;
text-align: center;
#header {
display: flex;
justify-content: space-between;
}
#menuBar #monitorName {
float: left;
#menuControls {
display: flex;
align-items: center;
}
#menuBar #closeControl {
float: right;
}
#menuBar #menuControls {
margin: 0 auto;
width: 60%;
}
#menuBar #menuControls #controlControl {
float: left;
}
#menuBar #menuControls #eventsControl {
float: left;
}
#menuBar #menuControls #settingsControl {
float: right;
}
#menuBar #menuControls #scaleControl {
margin: 0 auto;
#menuControls div {
margin: 0 0 0 1em;
}
#imageFeed{

View File

@ -108,9 +108,6 @@ input.noborder {
border: 0;
}
input[disabled] {
color: #777777;
}
img {
display: inline-block;
@ -376,11 +373,12 @@ th.table-th-sort-rev span.table-th-sort-span {
#header {
width: 100%;
line-height: 24px;
line-height: 1;
text-align: left;
margin-bottom: 10px;
padding: 10px 20px;
padding: 5px 20px;
margin: 0 auto 4px auto;
font-weight: 300;
border-bottom: 1px solid #000000;
}
#header h2 {
@ -410,7 +408,7 @@ th.table-th-sort-rev span.table-th-sort-span {
#content {
width: 96%;
margin: 8px auto;
margin: 0 auto 8px auto;
line-height: 130%;
text-align: center;
}
@ -449,6 +447,7 @@ th.table-th-sort-rev span.table-th-sort-span {
float: right;
}
#contentButtons button,
#contentButtons input {
margin-left: 8px;
margin-bottom: 4px;
@ -459,31 +458,34 @@ th.table-th-sort-rev span.table-th-sort-span {
margin: 8px auto;
}
button,
input[type=button],
input[type=submit] {
background-color: #3498db;
color: #fff;
border-color: #3498db;
text-transform: uppercase;
font-weight: 200;
padding: 5px 10px;
cursor: pointer;
background-color: #444444;
color: #eeeeee;
border-color: #444444;
text-transform: uppercase;
font-weight: 200;
padding: 5px 10px;
cursor: pointer;
}
button:hover,
input[type=button]:hover,
input[type=submit]:hover {
background-color: #34a2ee;
background-color: #555555;
}
/* PP - make it easy to identify disabled buttons */
button:disabled,
input[disabled],
input[type=button]:disabled,
input[type=submit]:disabled {
background-color: #aaaaaa;
border-color: #bbbbbb;
color: #888888;
background-color: #666666;
border-color: #666666;
}
/*
@ -518,7 +520,6 @@ input[type=submit]:disabled {
.sidebar {
position: absolute;
top: 0;
bottom: 0;
left: 0;
z-index: 1000;
display: block;
@ -534,8 +535,10 @@ input[type=submit]:disabled {
margin-left: 0;
}
.table-striped > tbody > tr:nth-of-type(2n+1) {
background: none;
background-color: #333333;
}
.table-hover>tbody>tr:hover {
background-color: #444444;
}

View File

@ -12,6 +12,19 @@
float: right;
}
#systemStats .warning {
color: orange;
}
#systemStats .error {
color: red;
}
#systemStats .critical {
color: red;
text-decoration: blink;
}
#monitorSummary {
float: left;
text-align: left;

View File

@ -12,90 +12,63 @@
.alarmCue {
background-color: #222222;
height: 1.5em;
height: 1.25em;
text-align: left;
margin: 0 auto 0 auto;
border-radius: 0 0 .3em .3em;
}
.alarmCue span {
background-color:red;
height: 1.5em;
height: 100%;
display: inline-block;
border-radius: 0;
}
span.noneCue {
background: none;
}
#eventVideo {
display: inline-block;
#header {
display: flex;
justify-content: space-between;
flex-direction: column;
}
#header h2, #header a {
line-height: 1.1;
margin:5px 0 0 0;
}
#dataBar {
width: 100%;
margin: 2px auto;
text-align: center;
}
#dataBar #dataTable {
width: 100%;
}
#dataBar #dataTable td {
text-align: center;
padding: 2px;
display: flex;
flex-wrap:wrap;
justify-content: space-between;
}
#menuBar1 {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
width: 100%;
padding: 3px 0;
text-align: center;
clear: both;
}
#menuBar1 #nameControl {
float: left;
}
#menuBar1 #nameControl #eventName {
margin-right: 4px;
margin: 4px 0 0 0;
}
#menuBar1 #replayControl {
float: right;
margin-left: 8px;
margin: 0 4px 0 auto;
}
#menuBar1 #scaleControl {
float: right;
margin-left: 8px;
#menuBar1 div {
margin: auto 5px;
}
#menuBar2 {
width: 100%;
padding: 3px 0;
margin-bottom: 4px;
#nameControl input[type="button"]{
height: 100%;
}
#menuBar2 div {
text-align: left;
float: left;
padding: 0 12px;
}
#menuBar2 #closeWindow {
float: right;
text-align: right;
}
#menuBar1:after,
#menuBar2:after {
content: ".";
display: block;
height: 0;
font-size: 0;
clear: both;
visibility: hidden;
#eventVideo {
display: inline-block;
}
#imageFeed {
@ -124,32 +97,32 @@ span.noneCue {
#monitorStatus #monitorState {
}
.dvrControls {
#dvrControls {
margin-top: 3px;
margin-bottom: 2px;
text-align: center;
}
.dvrControls input {
height: 20px;
width: 28px;
padding-bottom: 3px;
#dvrControls input {
height: 1.5em;
width: 2em;
padding: 0;
margin: 0 3px;
}
.dvrControls input[disabled=disabled] {
#dvrControls input[disabled=disabled] {
color: #aaaaaa;
}
.dvrControls input.active {
#dvrControls input.active {
border: 1px solid blue;
}
.dvrControls input.inactive {
#dvrControls input.inactive {
border: 1px solid green;
}
.dvrControls input.unavail {
#dvrControls input.unavail {
border: 1px solid red;
}
@ -165,31 +138,30 @@ span.noneCue {
#progressBar {
position: relative;
top: -1.5em;
height: 1.5em;
margin: 0 auto -1.5em auto;
top: -1.25em;
height: 1.25em;
margin: 0 auto -1.25em auto;
}
#progressBar .progressBox {
height: 1.5em;
transition: width .1s;
height: 100%;
background: rgba(170, 170, 170, .7);
border-radius: 0 0 .3em .3em;
}
#eventStills {
width: 100%;
position: relative;
}
#eventThumbsPanel {
position: relative;
width: 100%;
margin: 4px auto;
z-index: 1;
}
#eventThumbs {
margin: 0 auto;
width: 100%;
overflow: hidden;
height: 300px;
}
@ -208,14 +180,19 @@ span.noneCue {
}
#eventImagePanel {
display: none;
position: absolute;
top: 0;
left: 0;
z-index: 10;
width: 100%;
}
#eventImageFrame {
border: 2px solid gray;
background-color: white;
padding: 4px;
display: inline-block;
}
#eventImage {
@ -225,6 +202,14 @@ span.noneCue {
margin-top: 2px;
}
#eventImageBar::after {
visibility: hidden;
display: block;
content: "";
clear: both;
height: 0;
}
#eventImageStats {
float: left;
}
@ -240,6 +225,7 @@ span.noneCue {
#eventImageNav {
position: relative;
margin: 0 0 4px 0;
}
#eventImageNav input {
@ -248,25 +234,20 @@ span.noneCue {
}
#thumbsSliderPanel {
width: 400px;
margin: 4px auto 0;
background: #888888;
padding: 1px;
width: 80%;
margin: 0px auto 4px auto;
}
#thumbsSlider {
width: 400px;
height: 10px;
background: #dddddd;
}
#eventVideo {
display: inline-block;
width: 100%;
height: 1.25em;
position: relative;
top: -1.25em;
margin: 0 0 -1.25em 0;
}
#thumbsKnob {
width: 8px;
height: 10px;
background-color: #444444;
width: 1em;
height: 100%;
background-color: #999999;
}

View File

@ -1,31 +1,5 @@
#controls {
height: 16px;
width: 100%;
text-align: center;
margin: 0 auto;
position: relative;
}
#controls a {
width: 32%;
}
#controls #refreshLink {
position: absolute;
left: 0%;
text-align: left;
}
#controls #filterLink {
position: absolute;
left: 34%;
text-align: center;
}
#controls #timelineLink {
position: absolute;
left: 68%;
text-align: right;
.archived {
background-color: #2e2e2e;
}
#contentTable.major .colTime {
@ -40,3 +14,26 @@
text-align: right;
padding-right: 8px;
}
#header {
display: flex;
justify-content: space-between;
}
#header h2, #header a {
line-height: 1.1;
margin:5px 0 0 0;
}
#header #info, #header #pagination, #header #controls {
display: flex;
flex-direction: column;
}
#header #controls {
align-items: flex-end;
}
#header #pagination {
align-items: center;
}

View File

@ -1,33 +1,16 @@
#scaleControl {
float: right;
}
#controls {
width: 80%;
text-align: center;
margin: 0 auto;
display: flex;
justify-content: space-between;
}
#controls a {
width: 40px;
margin-left: -20px;
}
#firstLink {
position: absolute;
left: 13%;
}
#prevLink {
position: absolute;
left: 37%;
}
#nextLink {
position: absolute;
left: 63%;
}
#lastLink {
position: absolute;
left: 87%;
}

View File

@ -16,6 +16,10 @@
#monitors .alert {
color: #ffa500;
margin: 0;
padding: 0;
border-radius: 0;
border: none;
}
#monitors .imageFeed {

View File

@ -36,3 +36,7 @@
input[type=range]::-ms-tooltip {
display: none;
}
#downloadVideo {
margin-left: 5px;
}

View File

@ -5,6 +5,25 @@
margin: 0 auto;
}
#header {
display: flex;
justify-content: space-between;
}
#header h2, #header a {
line-height: 1.1;
margin:5px 0 0 0;
}
#header #info, #header #headerButtons {
display: flex;
flex-direction: column;
}
#header #headerButtons {
align-items: flex-end;
}
#title {
position: relative;
margin: 0 auto;
@ -15,20 +34,6 @@
line-height: 20px;
}
#listLink {
position: absolute;
top: 5px;
left: 20px;
height: 15px;
}
#closeLink {
position: absolute;
top: 5px;
right: 20px;
height: 15px;
}
#topPanel {
position: relative;
height: 220px;

View File

@ -1,37 +1,17 @@
@import url(../control.css);
#menuBar {
margin: 6px auto 4px;
text-align: center;
#header {
display: flex;
justify-content: space-between;
}
#menuBar #monitorName {
float: left;
#menuControls {
display: flex;
align-items: center;
}
#menuBar #closeControl {
float: right;
}
#menuBar #menuControls {
margin: 0 auto;
width: 60%;
}
#menuBar #menuControls #controlControl {
float: left;
}
#menuBar #menuControls #eventsControl {
float: left;
}
#menuBar #menuControls #settingsControl {
float: right;
}
#menuBar #menuControls #scaleControl {
margin: 0 auto;
#menuControls div {
margin: 0 0 0 1em;
}
#imageFeed{

View File

@ -250,6 +250,11 @@ ul.tabList li.active a {
font-size: 120%;
}
#content table > tbody > tr:hover
{
background-color: #EEE;
}
.overlay {
font-size: 11px;
}
@ -363,11 +368,11 @@ th.table-th-sort-rev span.table-th-sort-span {
#header {
width: 100%;
line-height: 24px;
line-height: 1;
text-align: left;
background-color: #383836;
margin-bottom: 10px;
padding: 10px 20px;
padding: 5px 20px;
margin: 0 auto 4px auto;
color: #f2f2f2;
font-weight: 300;
}
@ -405,7 +410,7 @@ th.table-th-sort-rev span.table-th-sort-span {
#content {
width: 96%;
margin: 8px auto;
margin: 0 auto 8px auto;
line-height: 130%;
text-align: center;
}
@ -454,6 +459,7 @@ th.table-th-sort-rev span.table-th-sort-span {
margin: 8px auto;
}
button,
input[type=button],
input[type=submit] {
background-color: #3498db;
@ -465,6 +471,7 @@ input[type=submit] {
cursor: pointer;
}
button:hover,
input[type=button]:hover,
input[type=submit]:hover {
background-color: #34a2ee;
@ -474,6 +481,7 @@ input[type=submit]:hover {
/* PP - make it easy to identify disabled buttons */
button:disabled,
input[type=button]:disabled,
input[type=submit]:disabled {
background-color: #aaaaaa;

View File

@ -12,6 +12,19 @@
float: right;
}
#systemStats .warning {
color: orange;
}
#systemStats .error {
color: red;
}
#systemStats .critical {
color: red;
text-decoration: blink;
}
#monitorSummary {
float: left;
text-align: left;
@ -77,7 +90,3 @@
#consoleTable .colLeftButtons {
text-align: left;
}
#consoleTable .colLeftButtons input {
margin-right: 24px;
}

View File

@ -12,97 +12,71 @@
.alarmCue {
background-color: #222222;
height: 1.5em;
height: 1.25em;
text-align: left;
margin: 0 auto 0 auto;
border-radius: 0 0 .3em .3em;
}
.alarmCue span {
background-color:red;
height: 1.5em;
height: 100%;
display: inline-block;
border-radius: 0;
}
span.noneCue {
background: none;
}
#header {
display: flex;
justify-content: space-between;
flex-direction: column;
margin: 0 0 4px 0;
}
#header h2, #header a {
line-height: 1.1;
margin:5px 0 0 0;
}
#dataBar {
width: 100%;
margin: 2px auto;
text-align: center;
}
#dataBar #dataTable {
width: 100%;
}
#dataBar #dataTable td {
text-align: center;
padding: 2px;
display: flex;
flex-wrap:wrap;
justify-content: space-between;
}
#menuBar1 {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
width: 100%;
padding: 3px 0;
text-align: center;
clear: both;
margin: 4px 0 0 0;
}
#menuBar1 #nameControl {
float: left;
}
#menuBar1 #nameControl #eventName {
margin-right: 4px;
#menuBar1 input, #menuBar1 select {
padding: 2px 5px;
}
#menuBar1 #replayControl {
float: right;
margin-left: 8px;
margin: 0 4px 0 auto;
}
#menuBar1 #scaleControl {
float: right;
margin-left: 8px;
#menuBar1 div {
margin: auto 5px;
}
#menuBar2 {
width: 100%;
padding: 3px 0;
margin-bottom: 4px;
#nameControl input[type="button"]{
height: 100%;
}
#menuBar2 div {
text-align: left;
float: left;
padding: 0 12px;
#eventVideo {
display: inline-block;
position: relative;
}
#menuBar2 #closeWindow {
float: right;
text-align: right;
}
#menuBar1:after,
#menuBar2:after {
content: ".";
display: block;
height: 0;
font-size: 0;
clear: both;
visibility: hidden;
}
#menuBar1:after,
#menuBar2:after {
content: ".";
display: block;
height: 0;
font-size: 0;
clear: both;
visibility: hidden;
}
#imageFeed {
display: inline-block;
position: relative;
@ -129,36 +103,36 @@ span.noneCue {
#monitorStatus #monitorState {
}
.dvrControls {
#dvrControls {
margin-top: 3px;
margin-bottom: 2px;
text-align: center;
}
.dvrControls input {
#dvrControls input {
padding: 10px 10px;
width: 50px;
margin: 0 3px;
font-weight: 900;
}
.dvrControls input[disabled=disabled] {
#dvrControls input[disabled=disabled] {
color: #aaaaaa;
}
.dvrControls input.active {
#dvrControls input.active {
border: 0;
background-color: #2ecc71;
color: #fff;
}
.dvrControls input.inactive {
#dvrControls input.inactive {
border: 0;
background-color: #e67e22;
color: #fff;
}
.dvrControls input.unavail {
#dvrControls input.unavail {
background-color: #ccc;
border: 0;
cursor: default;
@ -176,31 +150,30 @@ span.noneCue {
#progressBar {
position: relative;
top: -1.5em;
height: 1.5em;
margin: 0 auto -1.5em auto;
top: -1.25em;
height: 1.25em;
margin: 0 auto -1.25em auto;
}
#progressBar .progressBox {
height: 1.5em;
transition: width .1s;
height: 100%;
background: rgba(170, 170, 170, .7);
border-radius: 0 0 .3em .3em;
}
#eventStills {
width: 100%;
position: relative;
}
#eventThumbsPanel {
position: relative;
width: 100%;
margin: 4px auto;
margin: 0;
z-index: 1;
}
#eventThumbs {
margin: 0 auto;
width: 100%;
overflow: hidden;
height: 300px;
}
@ -219,14 +192,19 @@ span.noneCue {
}
#eventImagePanel {
display: none;
position: absolute;
top: 0;
left: 0;
z-index: 10;
width: 100%;
}
#eventImageFrame {
border: 2px solid gray;
background-color: white;
padding: 4px;
display: inline-block;
}
#eventImage {
@ -249,8 +227,17 @@ span.noneCue {
float: right;
}
#eventImageBar::after {
visibility: hidden;
display: block;
content: "";
clear: both;
height: 0;
}
#eventImageNav {
position: relative;
margin: 0 0 4px 0;
}
#eventImageNav input {
@ -259,82 +246,20 @@ span.noneCue {
}
#thumbsSliderPanel {
width: 400px;
margin: 4px auto 0;
background: #888888;
padding: 1px;
width: 80%;
margin: 0px auto 4px auto;
}
#thumbsSlider {
width: 400px;
height: 10px;
background: #dddddd;
width: 100%;
height: 1.25em;
position: relative;
top: -1.25em;
margin: 0 0 -1.25em 0;
}
#thumbsKnob {
width: 8px;
height: 10px;
background-color: #444444;
}
#eventVideo {
display: inline-block;
position: relative;
}
#video-controls {
position: absolute;
bottom: 0;
left: 0;
right: 0;
padding: 5px;
opacity: 0;
-webkit-transition: opacity .3s;
-moz-transition: opacity .3s;
-o-transition: opacity .3s;
-ms-transition: opacity .3s;
transition: opacity .3s;
background-image: linear-gradient(bottom, rgb(3,113,168) 13%, rgb(0,136,204) 100%);
background-image: -o-linear-gradient(bottom, rgb(3,113,168) 13%, rgb(0,136,204) 100%);
background-image: -moz-linear-gradient(bottom, rgb(3,113,168) 13%, rgb(0,136,204) 100%);
background-image: -webkit-linear-gradient(bottom, rgb(3,113,168) 13%, rgb(0,136,204) 100%);
background-image: -ms-linear-gradient(bottom, rgb(3,113,168) 13%, rgb(0,136,204) 100%);
background-image: -webkit-gradient(
linear,
left bottom,
left top,
color-stop(0.13, rgb(3,113,168)),
color-stop(1, rgb(0,136,204))
);
}
#eventVideo:hover #video-controls {
opacity: .9;
}
button {
background: rgba(0,0,0,.5);
border: 0;
color: #EEE;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
-o-border-radius: 3px;
border-radius: 3px;
padding: 0;
}
button:hover {
cursor: pointer;
}
#seekbar {
width: 360px;
border: 0;
padding: 0;
}
#volume-bar {
width: 60px;
border: 0;
padding: 0;
width: 1em;
height: 100%;
background-color: #999999;
}

View File

@ -1,31 +1,5 @@
#controls {
height: 16px;
width: 100%;
text-align: center;
margin: 0 auto;
position: relative;
}
#controls a {
width: 32%;
}
#controls #refreshLink {
position: absolute;
left: 0%;
text-align: left;
}
#controls #filterLink {
position: absolute;
left: 34%;
text-align: center;
}
#controls #timelineLink {
position: absolute;
left: 68%;
text-align: right;
.archived {
background-color: #f8f8f8;;
}
#contentTable.major .colTime {
@ -40,3 +14,26 @@
text-align: right;
padding-right: 8px;
}
#header {
display: flex;
justify-content: space-between;
}
#header h2, #header a {
line-height: 1.1;
margin:5px 0 0 0;
}
#header #info, #header #pagination, #header #controls {
display: flex;
flex-direction: column;
}
#header #controls {
align-items: flex-end;
}
#header #pagination {
align-items: center;
}

View File

@ -6,29 +6,11 @@
width: 80%;
text-align: center;
margin: 0 auto;
display: flex;
justify-content: space-between;
}
#controls a {
width: 40px;
margin-left: -20px;
}
#firstLink {
position: absolute;
left: 13%;
}
#prevLink {
position: absolute;
left: 37%;
}
#nextLink {
position: absolute;
left: 63%;
}
#lastLink {
position: absolute;
left: 87%;
}

View File

@ -4,7 +4,7 @@
display: inline-flex;
border: 1px solid black;
width: 25%;
padding: 9px;
padding: 4px;
}
#ScaleDiv label,
#SpeedDiv label {
@ -42,3 +42,7 @@ input[type=range]::-ms-tooltip {
color: white;
font-size: 40px;
}
#downloadVideo {
margin-left: 5px;
}

View File

@ -5,6 +5,25 @@
margin: 0 auto;
}
#header {
display: flex;
justify-content: space-between;
}
#header h2, #header a {
line-height: 1.1;
margin:5px 0 0 0;
}
#header #info, #header #headerButtons {
display: flex;
flex-direction: column;
}
#header #headerButtons {
align-items: flex-end;
}
#title {
position: relative;
margin: 0 auto;
@ -15,20 +34,6 @@
line-height: 20px;
}
#listLink {
position: absolute;
top: 5px;
left: 20px;
height: 15px;
}
#closeLink {
position: absolute;
top: 5px;
right: 20px;
height: 15px;
}
#topPanel {
position: relative;
height: 220px;

View File

@ -1,37 +1,17 @@
@import url(../control.css);
#menuBar {
margin: 6px auto 4px;
text-align: center;
#header {
display: flex;
justify-content: space-between;
}
#menuBar #monitorName {
float: left;
#menuControls {
display: flex;
align-items: center;
}
#menuBar #closeControl {
float: right;
}
#menuBar #menuControls {
margin: 0 auto;
width: 60%;
}
#menuBar #menuControls #controlControl {
float: left;
}
#menuBar #menuControls #eventsControl {
float: left;
}
#menuBar #menuControls #settingsControl {
float: right;
}
#menuBar #menuControls #scaleControl {
margin: 0 auto;
#menuControls div {
margin: 0 0 0 1em;
}
#imageFeed{

View File

@ -45,7 +45,7 @@ $scales = array(
'12.5' => '1/8x',
);
if (isset($_REQUEST['view'])) unset($scales[$_REQUEST['view'] == 'event' ? '' : 'auto']); //Remove the option we aren't using on montage or event
if (isset($_REQUEST['view'])) unset($scales[$_REQUEST['view'] == 'montage' ? 'auto' : '']); //Only use fixed width/Height on montage
$bandwidth_options = array(
'high' => translate('High'),
@ -56,6 +56,7 @@ $bandwidth_options = array(
switch ( $_COOKIE['zmBandwidth'] ) {
case 'high' : {
define( 'ZM_WEB_REFRESH_MAIN', ZM_WEB_H_REFRESH_MAIN ); // How often (in seconds) the main console window refreshes
define( 'ZM_WEB_REFRESH_NAVBAR', ZM_WEB_H_REFRESH_NAVBAR ); // How often (in seconds) the nav header refreshes
define( 'ZM_WEB_REFRESH_CYCLE', ZM_WEB_H_REFRESH_CYCLE ); // How often the cycle watch windows swaps to the next monitor
define( 'ZM_WEB_REFRESH_IMAGE', ZM_WEB_H_REFRESH_IMAGE ); // How often the watched image is refreshed (if not streaming)
define( 'ZM_WEB_REFRESH_STATUS', ZM_WEB_H_REFRESH_STATUS ); // How often the little status frame refreshes itself in the watch window
@ -73,6 +74,7 @@ switch ( $_COOKIE['zmBandwidth'] ) {
break;
} case 'medium' : {
define( 'ZM_WEB_REFRESH_MAIN', ZM_WEB_M_REFRESH_MAIN ); // How often (in seconds) the main console window refreshes
define( 'ZM_WEB_REFRESH_NAVBAR', ZM_WEB_M_REFRESH_NAVBAR ); // How often (in seconds) the nav header refreshes
define( 'ZM_WEB_REFRESH_CYCLE', ZM_WEB_M_REFRESH_CYCLE ); // How often the cycle watch windows swaps to the next monitor
define( 'ZM_WEB_REFRESH_IMAGE', ZM_WEB_M_REFRESH_IMAGE ); // How often the watched image is refreshed (if not streaming)
define( 'ZM_WEB_REFRESH_STATUS', ZM_WEB_M_REFRESH_STATUS ); // How often the little status frame refreshes itself in the watch window
@ -90,6 +92,7 @@ switch ( $_COOKIE['zmBandwidth'] ) {
break;
} case 'low' : {
define( 'ZM_WEB_REFRESH_MAIN', ZM_WEB_L_REFRESH_MAIN ); // How often (in seconds) the main console window refreshes
define( 'ZM_WEB_REFRESH_NAVBAR', ZM_WEB_L_REFRESH_NAVBAR ); // How often (in seconds) the nav header refreshes
define( 'ZM_WEB_REFRESH_CYCLE', ZM_WEB_L_REFRESH_CYCLE ); // How often the cycle watch windows swaps to the next monitor
define( 'ZM_WEB_REFRESH_IMAGE', ZM_WEB_L_REFRESH_IMAGE ); // How often the watched image is refreshed (if not streaming)
define( 'ZM_WEB_REFRESH_STATUS', ZM_WEB_L_REFRESH_STATUS ); // How often the little status frame refreshes itself in the watch window

View File

@ -853,7 +853,7 @@ function exportFileList( $eid, $exportDetail, $exportFrames, $exportImages, $exp
return( array_values( $exportFileList ) );
}
function exportEvents( $eids, $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc, $exportFormat )
function exportEvents( $eids, $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc, $exportFormat, $exportStructure = false )
{
if ( canView( 'Events' ) && !empty($eids) )
@ -907,8 +907,12 @@ function exportEvents( $eids, $exportDetail, $exportFrames, $exportImages, $expo
{
$archive = ZM_DIR_EXPORTS."/".$export_root.".tar.gz";
@unlink( $archive );
$command = "tar --create --gzip --file=$archive --files-from=$listFile";
exec( escapeshellcmd( $command ), $output, $status );
if ($exportStructure == 'flat') { //strip file paths if we choose
$command = "tar --create --gzip --file=".escapeshellarg($archive)." --files-from=".escapeshellarg($listFile)." --xform='s#^.+/##x'";
} else {
$command = "tar --create --gzip --file=".escapeshellarg($archive)." --files-from=".escapeshellarg($listFile);
}
exec( $command, $output, $status );
if ( $status )
{
Error( "Command '$command' returned with status $status" );
@ -921,7 +925,11 @@ function exportEvents( $eids, $exportDetail, $exportFrames, $exportImages, $expo
{
$archive = ZM_DIR_EXPORTS."/".$export_root.".zip";
@unlink( $archive );
$command = "cat ".escapeshellarg($listFile)." | zip -q ".escapeshellarg($archive)." -@";
if ($exportStructure == 'flat') {
$command = "cat ".escapeshellarg($listFile)." | zip -q -j ".escapeshellarg($archive)." -@";
} else {
$command = "cat ".escapeshellarg($listFile)." | zip -q ".escapeshellarg($archive)." -@";
}
//cat zmFileList.txt | zip -q zm_export.zip -@
//-bash: zip: command not found

View File

@ -159,26 +159,29 @@ if ( file_exists( "skins/$skin/css/$css/graphics/favicon.ico" ) ) {
<?php
} // end function xhtmlHeaders( $file, $title )
function getNavBarHTML() {
function getNavBarHTML($reload = null) {
$versionClass = (ZM_DYN_DB_VERSION&&(ZM_DYN_DB_VERSION!=ZM_VERSION))?'errorText':'';
ob_start();
global $running;
if ( $running == null )
$running = daemonCheck();
$status = $running?translate('Running'):translate('Stopped');
global $user;
global $bandwidth_options;
global $view;
global $filterQuery;
if (!$filterQuery) {
parseFilter( $_REQUEST['filter'] );
$filterQuery = $_REQUEST['filter']['query'];
}
if ($reload === null) {
ob_start();
if ( $running == null )
$running = daemonCheck();
$status = $running?translate('Running'):translate('Stopped');
?>
<noscript>
<div style="background-color:red;color:white;font-size:x-large;">
ZoneMinder requires Javascript. Please enable Javascript in your browser for this site.
</div>
</noscript>
<div class="navbar navbar-inverse navbar-static-top">
<div class="container-fluid">
<div class="navbar-header">
@ -212,7 +215,7 @@ if ( ZM_OPT_X10 && canView( 'Devices' ) ) { ?>
<li><a href="?view=devices">Devices</a></li>
<?php } ?>
<li><a href="?view=groups"<?php echo $view=='groups'?' class="selected"':''?>><?php echo translate('Groups') ?></a></li>
<li><a href="?view=filter"<?php echo $view=='filter'?' class="selected"':''?>><?php echo translate('Filters') ?></a></li>
<li><a href="?view=filter<?php echo $filterQuery ?>"<?php echo $view=='filter'?' class="selected"':''?>><?php echo translate('Filters') ?></a></li>
<?php
if ( canView( 'Stream' ) ) {
@ -221,9 +224,23 @@ if ( ZM_OPT_X10 && canView( 'Devices' ) ) { ?>
<li><a href="?view=montage"<?php echo $view=='montage'?' class="selected"':''?>><?php echo translate('Montage') ?></a></li>
<?php
}
if (isset($_REQUEST['filter']['Query']['terms'])) {
$terms = $_REQUEST['filter']['Query']['terms'];
$count = 0;
foreach ($terms as $term) {
if ($term['attr'] == "StartDateTime") {
$count += 1;
if ($term['op'] == '>=') $minTime = $term['val'];
if ($term['op'] == '<=') $maxTime = $term['val'];
}
}
if ($count == 2) {
$montageReviewQuery = '&minTime='.$minTime.'&maxTime='.$maxTime;
}
}
if ( canView('Events') ) {
?>
<li><a href="?view=montagereview"<?php echo $view=='montagereview'?' class="selected"':''?>><?php echo translate('MontageReview')?></a></li>
<li><a href="?view=montagereview<?php echo isset($montageReviewQuery)?'&fit=1'.$montageReviewQuery.'&live=0':'' ?>"<?php echo $view=='montagereview'?' class="selected"':''?>><?php echo translate('MontageReview')?></a></li>
<?php
}
?>
@ -243,7 +260,11 @@ if ( ZM_OPT_X10 && canView( 'Devices' ) ) { ?>
</div>
</div><!-- End .navbar-collapse -->
</div> <!-- End .container-fluid -->
<div class="container-fluid">
<?php
}//end reload null. Runs on full page load
if ($reload == 'reload') ob_start();
?>
<div id="reload" class="container-fluid">
<div class="pull-left">
<?php echo makePopupLink( '?view=bandwidth', 'zmBandwidth', 'bandwidth', $bandwidth_options[$_COOKIE['zmBandwidth']] . ' ' . translate('BandwidthHead'), ($user && $user['MaxBandwidth'] != 'low' ) ) ?>
</div>
@ -277,9 +298,11 @@ if ( ZM_OPT_X10 && canView( 'Devices' ) ) { ?>
echo ' ' . ZM_PATH_MAP .': '. getDiskPercent(ZM_PATH_MAP).'%';
?></li>
</ul>
</div> <!-- End .footer -->
</div> <!-- End .navbar .navbar-default -->
</div> <!-- End .footer/reload -->
<?php
if ($reload == 'reload') return( ob_get_clean() );
?>
</div><!-- End .navbar .navbar-default -->
<?php
return( ob_get_clean() );
} // end function getNavBarHTML()

Some files were not shown because too many files have changed in this diff Show More