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=el DIST=7
- OS=fedora DIST=25 - OS=fedora DIST=25
- OS=fedora DIST=26 DOCKER_REPO=knnniggett/packpack - OS=fedora DIST=26 DOCKER_REPO=knnniggett/packpack
- OS=fedora DIST=27 DOCKER_REPO=knnniggett/packpack
- OS=ubuntu DIST=trusty - OS=ubuntu DIST=trusty
- OS=ubuntu DIST=xenial - OS=ubuntu DIST=xenial
- OS=ubuntu DIST=trusty ARCH=i386 - 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) - 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) - OpenSuse via [third party repository](http://www.zoneminder.com/wiki/index.php/Installing_using_ZoneMinder_RPMs_for_SuSE)
- Mageia from their default repository - 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. 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, `Frames` int(10) unsigned default NULL,
`AlarmFrames` int(10) unsigned default NULL, `AlarmFrames` int(10) unsigned default NULL,
`DefaultVideo` VARCHAR( 64 ) DEFAULT '' NOT NULL, `DefaultVideo` VARCHAR( 64 ) DEFAULT '' NOT NULL,
`SaveJPEGs` TINYINT,
`TotScore` int(10) unsigned NOT NULL default '0', `TotScore` int(10) unsigned NOT NULL default '0',
`AvgScore` smallint(5) unsigned default '0', `AvgScore` smallint(5) unsigned default '0',
`MaxScore` 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', `Deinterlacing` int(10) unsigned NOT NULL default '0',
`SaveJPEGs` TINYINT NOT NULL DEFAULT '3' , `SaveJPEGs` TINYINT NOT NULL DEFAULT '3' ,
`VideoWriter` TINYINT NOT NULL DEFAULT '0', `VideoWriter` TINYINT NOT NULL DEFAULT '0',
`OutputCodec` enum('h264','mjpeg','mpeg1','mpeg2'),
`OutputContainer` enum('auto','mp4','mkv'),
`EncoderParameters` TEXT, `EncoderParameters` TEXT,
`RecordAudio` TINYINT NOT NULL DEFAULT '0', `RecordAudio` TINYINT NOT NULL DEFAULT '0',
`RTSPDescribe` tinyint(1) unsigned, `RTSPDescribe` tinyint(1) unsigned,
@ -431,6 +434,19 @@ CREATE TABLE `Monitors` (
`Status` enum('Unknown','NotRunning','Running','NoSignal','Signal') NOT NULL default 'Unknown', `Status` enum('Unknown','NotRunning','Running','NoSignal','Signal') NOT NULL default 'Unknown',
`CaptureFPS` DECIMAL(10,2) NOT NULL default 0, `CaptureFPS` DECIMAL(10,2) NOT NULL default 0,
`AnalysisFPS` DECIMAL(5,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`) PRIMARY KEY (`Id`)
) ENGINE=@ZM_MYSQL_ENGINE@; ) ENGINE=@ZM_MYSQL_ENGINE@;
@ -606,13 +622,14 @@ CREATE TABLE `Storage` (
`Path` varchar(64) NOT NULL default '', `Path` varchar(64) NOT NULL default '',
`Name` varchar(64) NOT NULL default '', `Name` varchar(64) NOT NULL default '',
`Type` enum('local','s3fs') NOT NULL default 'local', `Type` enum('local','s3fs') NOT NULL default 'local',
`DiskSpace` bigint unsigned default NULL,
PRIMARY KEY (`Id`) PRIMARY KEY (`Id`)
) ENGINE=@ZM_MYSQL_ENGINE@; ) ENGINE=@ZM_MYSQL_ENGINE@;
-- --
-- Create a default storage location -- 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 */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;

View File

@ -67,3 +67,4 @@ SET @s = (SELECT IF(
PREPARE stmt FROM @s; PREPARE stmt FROM @s;
EXECUTE stmt; 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; PREPARE stmt FROM @s;
EXECUTE stmt; 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:root /var/log/zm
chown www-data:www-data /var/lib/zm chown www-data:www-data /var/lib/zm
if [ -z "$2" ]; then 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 fi
if [ ! -e "/etc/apache2/mods-enabled/cgi.load" ]; then 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." echo "The cgi module is not enabled in apache2. I am enabling it using a2enmod cgi."
a2enmod cgi a2enmod cgi
fi fi
if [ "$ZM_DB_HOST" = "localhost" ]; then
if [ -e "/etc/init.d/mysql" ]; then
# Do this every time the package is installed or upgraded # Do this every time the package is installed or upgraded
# Ensure zoneminder is stopped # Ensure zoneminder is stopped
deb-systemd-invoke stop zoneminder.service || exit $? deb-systemd-invoke stop zoneminder.service || exit $?
# Ensure zoneminder is stopped
deb-systemd-invoke stop zoneminder.service || exit $?
if [ "$ZM_DB_HOST" = "localhost" ]; then
if [ -e "/etc/init.d/mysql" ]; then
# #
# Get mysql started if it isn't # 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 if $(/etc/init.d/mysql status >/dev/null 2>&1); then
mysqladmin --defaults-file=/etc/mysql/debian.cnf -f reload mysqladmin --defaults-file=/etc/mysql/debian.cnf -f reload
# test if database if already present... # 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. 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 **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}, type => $types{integer},
category => 'highband', 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', name => 'ZM_WEB_H_REFRESH_CYCLE',
default => '10', default => '10',
@ -3196,6 +3206,16 @@ our @options = (
`, `,
category => 'medband', 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', name => 'ZM_WEB_M_REFRESH_CYCLE',
default => '20', default => '20',
@ -3459,6 +3479,16 @@ our @options = (
type => $types{integer}, type => $types{integer},
category => 'lowband', 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', name => 'ZM_WEB_L_REFRESH_CYCLE',
default => '30', 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 { sub DiskSpace {
if ( @_ > 1 ) { if ( @_ > 1 ) {
Debug("Cleared DiskSpace, was $_[0]{DiskSpace}"); Debug("Cleared DiskSpace, was $_[0]{DiskSpace}") if $_[0]{DiskSpace};
$_[0]{DiskSpace} = $_[1]; $_[0]{DiskSpace} = $_[1];
} }
if ( ! defined $_[0]{DiskSpace} ) { if ( ! defined $_[0]{DiskSpace} ) {

View File

@ -225,6 +225,9 @@ sub Sql {
) { ) {
$value = "'$temp_value'"; $value = "'$temp_value'";
} elsif ( $term->{attr} eq 'DateTime' or $term->{attr} eq 'StartDateTime' or $term->{attr} eq 'EndDateTime' ) { } elsif ( $term->{attr} eq 'DateTime' or $term->{attr} eq 'StartDateTime' or $term->{attr} eq 'EndDateTime' ) {
if ( $temp_value == 'NULL' ) {
$value = $temp_value;
} else {
$value = DateTimeToSQL( $temp_value ); $value = DateTimeToSQL( $temp_value );
if ( !$value ) { if ( !$value ) {
Error( "Error parsing date/time '$temp_value', " Error( "Error parsing date/time '$temp_value', "
@ -232,7 +235,11 @@ sub Sql {
return; return;
} }
$value = "'$value'"; $value = "'$value'";
}
} elsif ( $term->{attr} eq 'Date' or $term->{attr} eq 'StartDate' or $term->{attr} eq 'EndDate' ) { } elsif ( $term->{attr} eq 'Date' or $term->{attr} eq 'StartDate' or $term->{attr} eq 'EndDate' ) {
if ( $temp_value == 'NULL' ) {
$value = $temp_value;
} else {
$value = DateTimeToSQL( $temp_value ); $value = DateTimeToSQL( $temp_value );
if ( !$value ) { if ( !$value ) {
Error( "Error parsing date/time '$temp_value', " Error( "Error parsing date/time '$temp_value', "
@ -240,7 +247,11 @@ sub Sql {
return; return;
} }
$value = "to_days( '$value' )"; $value = "to_days( '$value' )";
}
} elsif ( $term->{attr} eq 'Time' or $term->{attr} eq 'StartTime' or $term->{attr} eq 'EndTime' ) { } elsif ( $term->{attr} eq 'Time' or $term->{attr} eq 'StartTime' or $term->{attr} eq 'EndTime' ) {
if ( $temp_value == 'NULL' ) {
$value = $temp_value;
} else {
$value = DateTimeToSQL( $temp_value ); $value = DateTimeToSQL( $temp_value );
if ( !$value ) { if ( !$value ) {
Error( "Error parsing date/time '$temp_value', " Error( "Error parsing date/time '$temp_value', "
@ -248,6 +259,7 @@ sub Sql {
return; return;
} }
$value = "extract( hour_second from '$value' )"; $value = "extract( hour_second from '$value' )";
}
} else { } else {
$value = $temp_value; $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 strict;
use bytes; use bytes;
@ -81,6 +53,7 @@ use constant EVENT_PATH => ($Config{ZM_DIR_EVENTS}=~m|/|)
? $Config{ZM_DIR_EVENTS} ? $Config{ZM_DIR_EVENTS}
: ($Config{ZM_PATH_WEB}.'/'.$Config{ZM_DIR_EVENTS}) : ($Config{ZM_PATH_WEB}.'/'.$Config{ZM_DIR_EVENTS})
; ;
use constant ZM_AUDIT_PID => '@ZM_RUNDIR@/zmaudit.pid';
$| = 1; $| = 1;
@ -118,6 +91,17 @@ if ( ! exists $Config{ZM_AUDIT_MIN_AGE} ) {
Fatal('ZM_AUDIT_MIN_AGE is not set in config.'); 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(); my $dbh = zmDbConnect();
require ZoneMinder::Monitor; require ZoneMinder::Monitor;
@ -598,6 +582,7 @@ Debug("Event $db_event is not in fs.");
sleep( $Config{ZM_AUDIT_CHECK_INTERVAL} ) if $continuous; sleep( $Config{ZM_AUDIT_CHECK_INTERVAL} ) if $continuous;
}; };
unlink ZM_AUDIT_PID;
exit( 0 ); exit( 0 );
sub aud_print { sub aud_print {
@ -688,3 +673,30 @@ sub delete_empty_directories {
1; 1;
__END__ __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 strict;
use bytes; use bytes;
@ -69,23 +55,19 @@ my $state;
my $dbh; my $dbh;
if ( !$command || $command !~ /^(?:start|stop|restart|status|logrot|version)$/ ) if ( !$command || $command !~ /^(?:start|stop|restart|status|logrot|version)$/ ) {
{ if ( $command ) {
if ( $command )
{
$dbh = zmDbConnect(); $dbh = zmDbConnect();
# Check to see if it's a valid run state # Check to see if it's a valid run state
my $sql = 'select * from States where Name = ?'; my $sql = 'SELECT * FROM States WHERE Name=?';
my $sth = $dbh->prepare_cached( $sql ) 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( $command ) my $res = $sth->execute( $command )
or Fatal( "Can't execute: ".$sth->errstr() ); or Fatal( "Can't execute: ".$sth->errstr() );
if ( $state = $sth->fetchrow_hashref() ) if ( $state = $sth->fetchrow_hashref() ) {
{
$state->{Name} = $command; $state->{Name} = $command;
$state->{Definitions} = []; $state->{Definitions} = [];
foreach( split( /,/, $state->{Definition} ) ) foreach( split( /,/, $state->{Definition} ) ) {
{
my ( $id, $function, $enabled ) = split( /:/, $_ ); my ( $id, $function, $enabled ) = split( /:/, $_ );
push( @{$state->{Definitions}}, push( @{$state->{Definitions}},
{ Id=>$id, Function=>$function, Enabled=>$enabled } { Id=>$id, Function=>$function, Enabled=>$enabled }
@ -93,14 +75,11 @@ if ( !$command || $command !~ /^(?:start|stop|restart|status|logrot|version)$/ )
} }
$store_state=$command; # PP - Remember the name that was passed to search in DB $store_state=$command; # PP - Remember the name that was passed to search in DB
$command = 'state'; $command = 'state';
} } else {
else
{
$command = undef; $command = undef;
} }
} }
if ( !$command ) if ( !$command ) {
{
pod2usage(-exitstatus => -1); pod2usage(-exitstatus => -1);
} }
} }
@ -112,40 +91,35 @@ isActiveSanityCheck();
chdir( $Config{ZM_PATH_WEB} ) 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" ); 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 $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 ) 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}: () ) my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID}: () )
or Fatal( "Can't execute: ".$sth->errstr() ); or Fatal( "Can't execute: ".$sth->errstr() );
while( my $monitor = $sth->fetchrow_hashref() ) while( my $monitor = $sth->fetchrow_hashref() ) {
{ foreach my $definition ( @{$state->{Definitions}} ) {
foreach my $definition ( @{$state->{Definitions}} ) if ( $monitor->{Id} =~ /^$definition->{Id}$/ ) {
{
if ( $monitor->{Id} =~ /^$definition->{Id}$/ )
{
$monitor->{NewFunction} = $definition->{Function}; $monitor->{NewFunction} = $definition->{Function};
$monitor->{NewEnabled} = $definition->{Enabled}; $monitor->{NewEnabled} = $definition->{Enabled};
} }
} }
#next if ( !$monitor->{NewFunction} ); #next if ( !$monitor->{NewFunction} );
$monitor->{NewFunction} = 'None' $monitor->{NewFunction} = 'None'
if ( !$monitor->{NewFunction} ); if ( !$monitor->{NewFunction} );
$monitor->{NewEnabled} = 0 $monitor->{NewEnabled} = 0
if ( !$monitor->{NewEnabled} ); if ( !$monitor->{NewEnabled} );
if ( $monitor->{Function} ne $monitor->{NewFunction} if ( $monitor->{Function} ne $monitor->{NewFunction}
|| $monitor->{Enabled} ne $monitor->{NewEnabled} || $monitor->{Enabled} ne $monitor->{NewEnabled}
) ) {
{ my $sql = 'UPDATE Monitors SET Function=?, Enabled=? WHERE Id=?';
my $sql = "update Monitors set Function = ?, Enabled = ? where Id = ?";
my $sth = $dbh->prepare_cached( $sql ) 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( $monitor->{NewFunction}, $monitor->{NewEnabled}, $monitor->{Id} ) my $res = $sth->execute( $monitor->{NewFunction}, $monitor->{NewEnabled}, $monitor->{Id} )
@ -154,82 +128,73 @@ if ( $command eq "state" )
} }
$sth->finish(); $sth->finish();
# PP - Now mark a specific state as active # PP - Now mark a specific state as active
resetStates(); resetStates();
Info ("Marking $store_state as Enabled"); 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 ) $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 ) $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 # PP - zero out other states isActive
$command = "restart"; $command = 'restart';
} }
# Check if we are running systemd and if we have been called by the system # Check if we are running systemd and if we have been called by the system
if ( $command =~ /^(start|stop|restart)$/ ) if ( $command =~ /^(start|stop|restart)$/ ) {
{ # We have to detaint to keep perl from complaining
# We have to detaint to keep perl from complaining
$command = $1; $command = $1;
if ( systemdRunning() && !calledBysystem() ) { if ( systemdRunning() && !calledBysystem() ) {
qx(@BINDIR@/zmsystemctl.pl $command); qx(@BINDIR@/zmsystemctl.pl $command);
$command = ""; $command = '';
} }
} }
if ( $command =~ /^(?:stop|restart)$/ ) if ( $command =~ /^(?:stop|restart)$/ ) {
{ my $status = runCommand('zmdc.pl check');
my $status = runCommand( "zmdc.pl check" );
if ( $status eq "running" ) if ( $status eq 'running' ) {
{ runCommand('zmdc.pl shutdown');
runCommand( "zmdc.pl shutdown" );
zmMemTidy(); zmMemTidy();
} } else {
else
{
$retval = 1; $retval = 1;
} }
} }
#runCommand( "zmupdate.pl -f" ); #runCommand( "zmupdate.pl -f" );
if ( $command =~ /^(?:start|restart)$/ ) if ( $command =~ /^(?:start|restart)$/ ) {
{ my $status = runCommand('zmdc.pl check');
my $status = runCommand( "zmdc.pl check" );
if ( $status eq "stopped" ) if ( $status eq 'stopped' ) {
{
if ( $Config{ZM_DYN_DB_VERSION} if ( $Config{ZM_DYN_DB_VERSION}
and ( $Config{ZM_DYN_DB_VERSION} ne ZM_VERSION ) and ( $Config{ZM_DYN_DB_VERSION} ne ZM_VERSION )
) ) {
{ Fatal( 'Version mismatch, system is version '.ZM_VERSION
Fatal( "Version mismatch, system is version ".ZM_VERSION .', database is '.$Config{ZM_DYN_DB_VERSION}
.", database is ".$Config{ZM_DYN_DB_VERSION} .', please run zmupdate.pl to update.'
.", please run zmupdate.pl to update."
); );
exit( -1 ); exit( -1 );
} }
# Recreate the temporary directory if it's been wiped # Recreate the temporary directory if it's been wiped
verifyFolder("@ZM_TMPDIR@"); verifyFolder('@ZM_TMPDIR@');
# Recreate the run directory if it's been wiped # Recreate the run directory if it's been wiped
verifyFolder("@ZM_RUNDIR@"); verifyFolder('@ZM_RUNDIR@');
# Recreate the sock directory if it's been wiped # Recreate the sock directory if it's been wiped
verifyFolder("@ZM_SOCKDIR@"); verifyFolder('@ZM_SOCKDIR@');
zmMemTidy(); zmMemTidy();
runCommand( "zmdc.pl startup" ); runCommand('zmdc.pl startup');
if ( $Config{ZM_SERVER_ID} ) { if ( $Config{ZM_SERVER_ID} ) {
Info( "Multi-server configuration detected. Starting up services for server $Config{ZM_SERVER_ID}\n"); Info("Multi-server configuration detected. Starting up services for server $Config{ZM_SERVER_ID}\n");
} else { } else {
Info( "Single server configuration detected. Starting up services." ); Info('Single server configuration detected. Starting up services.');
} }
my $sql = $Config{ZM_SERVER_ID} ? 'SELECT * FROM Monitors WHERE ServerId=?' : 'SELECT * FROM Monitors'; my $sql = $Config{ZM_SERVER_ID} ? 'SELECT * FROM Monitors WHERE ServerId=?' : 'SELECT * FROM Monitors';
@ -237,28 +202,19 @@ if ( $command =~ /^(?:start|restart)$/ )
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} : () ) my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID} : () )
or Fatal( "Can't execute: ".$sth->errstr() ); or Fatal( "Can't execute: ".$sth->errstr() );
while( my $monitor = $sth->fetchrow_hashref() ) while( my $monitor = $sth->fetchrow_hashref() ) {
{ if ( $monitor->{Function} ne 'None' ) {
if ( $monitor->{Function} ne 'None' ) if ( $monitor->{Type} eq 'Local' ) {
{
if ( $monitor->{Type} eq 'Local' )
{
runCommand( "zmdc.pl start zmc -d $monitor->{Device}" ); runCommand( "zmdc.pl start zmc -d $monitor->{Device}" );
} } else {
else
{
runCommand( "zmdc.pl start zmc -m $monitor->{Id}" ); runCommand( "zmdc.pl start zmc -m $monitor->{Id}" );
} }
if ( $monitor->{Function} ne 'Monitor' ) if ( $monitor->{Function} ne 'Monitor' ) {
{
runCommand( "zmdc.pl start zma -m $monitor->{Id}" ); runCommand( "zmdc.pl start zma -m $monitor->{Id}" );
} }
if ( $Config{ZM_OPT_CONTROL} ) if ( $Config{ZM_OPT_CONTROL} ) {
{ if ( $monitor->{Function} eq 'Modect' || $monitor->{Function} eq 'Mocord' ) {
if ( $monitor->{Function} eq 'Modect' || $monitor->{Function} eq 'Mocord' ) if ( $monitor->{Controllable} && $monitor->{TrackMotion} ) {
{
if ( $monitor->{Controllable} && $monitor->{TrackMotion} )
{
runCommand( "zmdc.pl start zmtrack.pl -m $monitor->{Id}" ); runCommand( "zmdc.pl start zmtrack.pl -m $monitor->{Id}" );
} }
} }
@ -267,73 +223,61 @@ if ( $command =~ /^(?:start|restart)$/ )
} }
$sth->finish(); $sth->finish();
# This is now started unconditionally # This is now started unconditionally
runCommand( "zmdc.pl start zmfilter.pl" ); runCommand('zmdc.pl start zmfilter.pl');
if ( $Config{ZM_RUN_AUDIT} ) if ( $Config{ZM_RUN_AUDIT} ) {
{ runCommand('zmdc.pl start zmaudit.pl -c');
runCommand( "zmdc.pl start zmaudit.pl -c" );
} }
if ( $Config{ZM_OPT_TRIGGERS} ) if ( $Config{ZM_OPT_TRIGGERS} ) {
{ runCommand('zmdc.pl start zmtrigger.pl');
runCommand( "zmdc.pl start zmtrigger.pl" );
} }
if ( $Config{ZM_OPT_X10} ) if ( $Config{ZM_OPT_X10} ) {
{ runCommand('zmdc.pl start zmx10.pl -c start');
runCommand( "zmdc.pl start zmx10.pl -c start" );
} }
runCommand( "zmdc.pl start zmwatch.pl" ); runCommand('zmdc.pl start zmwatch.pl');
if ( $Config{ZM_CHECK_FOR_UPDATES} ) if ( $Config{ZM_CHECK_FOR_UPDATES} ) {
{ runCommand('zmdc.pl start zmupdate.pl -c');
runCommand( "zmdc.pl start zmupdate.pl -c" );
} }
if ( $Config{ZM_TELEMETRY_DATA} ) if ( $Config{ZM_TELEMETRY_DATA} ) {
{ runCommand('zmdc.pl start zmtelemetry.pl');
runCommand( "zmdc.pl start zmtelemetry.pl" );
} }
} } else {
else
{
$retval = 1; $retval = 1;
} }
} }
if ( $command eq "status" ) if ( $command eq 'status' ) {
{ my $status = runCommand('zmdc.pl check');
my $status = runCommand( "zmdc.pl check" );
print( STDOUT $status."\n" ); print( STDOUT $status."\n" );
} } elsif ( $command eq 'logrot' ) {
runCommand('zmdc.pl logrot');
if ( $command eq "logrot" )
{
runCommand( "zmdc.pl logrot" );
} }
exit( $retval ); exit( $retval );
# PP - Make sure isActive is on and only one # PP - Make sure isActive is on and only one
sub isActiveSanityCheck sub isActiveSanityCheck {
{
Info ("Sanity checking States table..."); Info ('Sanity checking States table...');
$dbh = zmDbConnect() if ! $dbh; $dbh = zmDbConnect() if ! $dbh;
# PP - First, make sure default exists and there is only one # PP - First, make sure default exists and there is only one
my $sql = "select Name from States where Name = 'default'"; my $sql = "SELECT Name FROM States WHERE Name='default'";
my $sth = $dbh->prepare_cached( $sql ) 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() my $res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() ); or Fatal( "Can't execute: ".$sth->errstr() );
if ($sth->rows != 1) # PP - no row, or too many rows. Either case is an error 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" ); Info( 'Fixing States table - either no default state or duplicate default states' );
$sql = "delete from States where Name = 'default'"; $sql = "DELETE FROM States WHERE Name='default'";
$sth = $dbh->prepare_cached( $sql ) $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute() $res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() ); or Fatal( "Can't execute: ".$sth->errstr() );
$sql = "insert into States (Name,Definition,IsActive) VALUES ('default','','1');"; $sql = "INSERT INTO States (Name,Definition,IsActive) VALUES ('default','','1');";
$sth = $dbh->prepare_cached( $sql ) $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute() $res = $sth->execute()
@ -341,33 +285,29 @@ sub isActiveSanityCheck
} }
# PP - Now make sure no two states have IsActive=1 # PP - Now make sure no two states have IsActive=1
$sql = "select Name from States where IsActive = '1'"; $sql = "SELECT Name FROM States WHERE IsActive = '1'";
$sth = $dbh->prepare_cached( $sql ) $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute() $res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() ); or Fatal( "Can't execute: ".$sth->errstr() );
if ( $sth->rows != 1 ) if ( $sth->rows != 1 ) {
{ Info( 'Fixing States table so only one run state is active' );
Info( "Fixing States table so only one run state is active" );
resetStates(); resetStates();
$sql = "update States set IsActive='1' WHERE Name='default'"; $sql = "UPDATE States SET IsActive='1' WHERE Name='default'";
$sth = $dbh->prepare_cached( $sql ) $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute() $res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() ); or Fatal( "Can't execute: ".$sth->errstr() );
} }
} }
# PP - zeroes out isActive for all states # PP - zeroes out isActive for all states
sub resetStates sub resetStates {
{
$dbh = zmDbConnect() if ! $dbh; $dbh = zmDbConnect() if ! $dbh;
my $sql = "update States set IsActive = '0'"; my $sql = "UPDATE States SET IsActive='0'";
my $sth = $dbh->prepare_cached( $sql ) 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() my $res = $sth->execute()
@ -375,22 +315,20 @@ sub resetStates
} }
sub systemdRunning sub systemdRunning {
{
my $result = 0; my $result = 0;
my $output = qx(ps -o comm="" -p 1); my $output = qx(ps -o comm="" -p 1);
chomp( $output ); chomp( $output );
if ($output =~ /systemd/) { if ( $output =~ /systemd/ ) {
$result = 1; $result = 1;
} }
return $result; return $result;
} }
sub calledBysystem sub calledBysystem {
{
my $result = 0; my $result = 0;
my $ppid = getppid(); my $ppid = getppid();
@ -404,19 +342,16 @@ sub calledBysystem
return $result; return $result;
} }
sub verifyFolder sub verifyFolder {
{
my $folder = shift; my $folder = shift;
# Recreate the temporary directory if it's been wiped # Recreate the temporary directory if it's been wiped
if ( !-e $folder ) if ( !-e $folder ) {
{
Debug( "Recreating directory '$folder'" ); Debug( "Recreating directory '$folder'" );
mkdir( "$folder", 0774 ) mkdir( $folder, 0774 )
or Fatal( "Can't create missing temporary directory '$folder': $!" ); or Fatal( "Can't create missing temporary directory '$folder': $!" );
my ( $runName ) = getpwuid( $> ); my ( $runName ) = getpwuid( $> );
if ( $runName ne $Config{ZM_WEB_USER} ) if ( $runName ne $Config{ZM_WEB_USER} ) {
{
# Not running as web user, so should be root in which case # Not running as web user, so should be root in which case
# chown the directory # chown the directory
my ( $webName, $webPass, $webUid, $webGid ) = getpwnam( $Config{ZM_WEB_USER} ) my ( $webName, $webPass, $webUid, $webGid ) = getpwnam( $Config{ZM_WEB_USER} )
@ -430,4 +365,21 @@ sub verifyFolder
} }
} }
} }
1;
__END__ __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@ @EXTRA_PERL_LIB@
use ZoneMinder; use ZoneMinder;
use ZoneMinder::Storage;
use POSIX; use POSIX;
use DBI; use DBI;
use autouse 'Data::Dumper'=>qw(Dumper); 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 ) my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); 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 ) { while( 1 ) {
my $now = time();
my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID} : () ) my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID} : () )
or Fatal( "Can't execute: ".$sth->errstr() ); or Fatal( "Can't execute: ".$sth->errstr() );
while( my $monitor = $sth->fetchrow_hashref() ) { while( my $monitor = $sth->fetchrow_hashref() ) {
my $now = time();
next if $monitor->{Function} eq 'None'; next if $monitor->{Function} eq 'None';
my $restart = 0; my $restart = 0;
if ( zmMemVerify( $monitor ) ) { if ( zmMemVerify( $monitor ) ) {
# Check we have got an image recently # Check we have got an image recently
my $image_time = zmGetLastWriteTime( $monitor ); my $capture_time = zmGetLastWriteTime( $monitor );
if ( !defined($image_time) ) { if ( !defined($capture_time) ) {
# Can't read from shared data # Can't read from shared data
Debug( "LastWriteTime is not defined." ); Debug( "LastWriteTime is not defined." );
zmMemInvalidate( $monitor ); zmMemInvalidate( $monitor );
next; next;
} }
Debug( "LastWriteTime is = $image_time." ); Debug( "LastWriteTime is = $capture_time." );
if ( !$image_time ) { if ( !$capture_time ) {
my $startup_time = zmGetStartupTime( $monitor ); my $startup_time = zmGetStartupTime( $monitor );
if ( $now - $startup_time > $Config{ZM_WATCH_MAX_DELAY} ) { 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" ); Info( "Restarting capture daemon for ".$monitor->{Name}.", no image since startup. Startup time was $startup_time - now $now > $Config{ZM_WATCH_MAX_DELAY}\n" );
@ -113,11 +132,11 @@ while( 1 ) {
) ? (3/$monitor->{MaxFPS}) ) ? (3/$monitor->{MaxFPS})
: $Config{ZM_WATCH_MAX_DELAY} : $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" ); Debug( "Monitor $monitor->{Id} last captured $image_delay seconds ago, max is $max_image_delay\n" );
if ( $image_delay > $max_image_delay ) { if ( $image_delay > $max_image_delay ) {
Info( "Restarting capture daemon for " 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; $restart = 1;
} }
@ -147,7 +166,7 @@ while( 1 ) {
} elsif ( !$image_time ) { } elsif ( !$image_time ) {
# We can't get the last capture time so can't be sure it's died. # We can't get the last capture time so can't be sure it's died.
$restart = 1; $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 { } else {
my $max_image_delay = ( $monitor->{MaxFPS} my $max_image_delay = ( $monitor->{MaxFPS}
@ -174,7 +193,23 @@ while( 1 ) {
} # end if check analysis daemon } # end if check analysis daemon
# Prevent open handles building up if we have connect to shared memory # 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 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 } # 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} ); sleep( $Config{ZM_WATCH_CHECK_INTERVAL} );
} # end while (1) } # end while (1)

View File

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

View File

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

View File

@ -229,10 +229,13 @@ ConfigItem::ConfigItem( const ConfigItem &item ) {
accessed = false; accessed = false;
} }
void ConfigItem::Copy( const ConfigItem &item ) { void ConfigItem::Copy( const ConfigItem &item ) {
if (name) delete name;
name = new char[strlen(item.name)+1]; name = new char[strlen(item.name)+1];
strcpy( name, item.name ); strcpy( name, item.name );
if (value) delete value;
value = new char[strlen(item.value)+1]; value = new char[strlen(item.value)+1];
strcpy( value, item.value ); strcpy( value, item.value );
if (type) delete type;
type = new char[strlen(item.type)+1]; type = new char[strlen(item.type)+1];
strcpy( type, item.type ); 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 char *p_name, const char *p_value, const char *const p_type);
ConfigItem(const ConfigItem &); ConfigItem(const ConfigItem &);
~ConfigItem(); ~ConfigItem();
void Copy(const ConfigItem&);
void ConvertValue() const; void ConvertValue() const;
bool BooleanValue() const; bool BooleanValue() const;
int IntegerValue() const; int IntegerValue() const;
double DecimalValue() const; double DecimalValue() const;
const char *StringValue() const; const char *StringValue() const;
ConfigItem &operator=(const ConfigItem item) {
Copy(item);return *this;
}
inline operator bool() const { inline operator bool() const {
return BooleanValue(); return BooleanValue();
} }

View File

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

View File

@ -28,8 +28,9 @@ MYSQL dbconn;
int zmDbConnected = false; int zmDbConnected = false;
void zmDbConnect() { void zmDbConnect() {
if ( zmDbConnected ) // For some reason having these lines causes memory corruption and crashing on newer debian/ubuntu
return; //if ( zmDbConnected )
//return;
if ( !mysql_init( &dbconn ) ) { if ( !mysql_init( &dbconn ) ) {
Error( "Can't initialise database connection: %s", mysql_error( &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]; static char sql[ZM_SQL_MED_BUFSIZ];
struct tm *stime = localtime( &start_time.tv_sec ); 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(), monitor->Id(),
storage->Id(), storage->Id(),
start_time.tv_sec, start_time.tv_sec,
@ -81,7 +81,8 @@ Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string
notes.c_str(), notes.c_str(),
state_id, state_id,
monitor->getOrientation(), monitor->getOrientation(),
videoEvent videoEvent,
monitor->GetOptSaveJPEGs()
); );
if ( mysql_query( &dbconn, sql ) ) { if ( mysql_query( &dbconn, sql ) ) {
Error( "Can't insert event: %s. sql was (%s)", mysql_error( &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 ) { if ( videowriter != NULL ) {
/* Open the video stream */ /* Open the video stream */
int nRet = videowriter->Open(); int nRet = videowriter->Open();
if(nRet != 0) { if ( nRet != 0 ) {
Error("Failed opening video stream"); Error("Failed opening video stream");
delete videowriter; delete videowriter;
videowriter = NULL; videowriter = NULL;
@ -211,7 +212,9 @@ Event::~Event() {
if ( frames > last_db_frame ) { if ( frames > last_db_frame ) {
Debug( 1, "Adding closing frame %d to DB", frames ); 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 ) ) { if ( mysql_query( &dbconn, sql ) ) {
Error( "Can't insert frame: %s", mysql_error( &dbconn ) ); Error( "Can't insert frame: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) ); exit( mysql_errno( &dbconn ) );
@ -228,9 +231,11 @@ Event::~Event() {
videowriter = NULL; videowriter = NULL;
/* Close the timecodes file */ /* Close the timecodes file */
if ( timecodes_fd ) {
fclose(timecodes_fd); fclose(timecodes_fd);
timecodes_fd = NULL; 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 ); 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 );
if ( mysql_query( &dbconn, sql ) ) { if ( mysql_query( &dbconn, sql ) ) {
@ -302,6 +307,7 @@ bool Event::WriteFrameVideo( const Image *image, const struct timeval timestamp,
} }
/* Add the frame to the timecodes file */ /* Add the frame to the timecodes file */
if ( timecodes_fd )
fprintf(timecodes_fd, "%u\n", timeMS); fprintf(timecodes_fd, "%u\n", timeMS);
return( true ); 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); flags &= ~(AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
while (*str) { 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; return ret;
if (*str) 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) { if (ret) {
avformat_free_context(s); avformat_free_context(s);
return ret; return ret;
} else { } else {
s->oformat = oformat; 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) { if (s->oformat->priv_data_size > 0) {
s->priv_data = av_mallocz(s->oformat->priv_data_size); s->priv_data = av_mallocz(s->oformat->priv_data_size);
if (s->priv_data) { if (s->priv_data) {
@ -219,6 +206,7 @@ int hacked_up_context2_for_older_ffmpeg(AVFormatContext **avctx, AVOutputFormat
} }
s->priv_data = NULL; s->priv_data = NULL;
} }
#endif
if (filename) strncpy(s->filename, filename, sizeof(s->filename)); if (filename) strncpy(s->filename, filename, sizeof(s->filename));
*avctx = s; *avctx = s;

View File

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

View File

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

View File

@ -9,9 +9,14 @@ FFmpeg_Input::FFmpeg_Input() {
audio_stream_id = -1; audio_stream_id = -1;
av_register_all(); av_register_all();
avcodec_register_all(); avcodec_register_all();
streams = NULL;
} }
FFmpeg_Input::~FFmpeg_Input() { FFmpeg_Input::~FFmpeg_Input() {
if ( streams ) {
delete streams;
streams = NULL;
}
} }
int FFmpeg_Input::Open( const char *filepath ) { int FFmpeg_Input::Open( const char *filepath ) {
@ -35,6 +40,8 @@ int FFmpeg_Input::Open( const char *filepath ) {
return error; return error;
} }
streams = new stream[input_format_context->nb_streams];
for ( unsigned int i = 0; i < input_format_context->nb_streams; i += 1 ) { for ( unsigned int i = 0; i < input_format_context->nb_streams; i += 1 ) {
if ( is_video_stream( input_format_context->streams[i] ) ) { if ( is_video_stream( input_format_context->streams[i] ) ) {
zm_dump_stream_format(input_format_context, i, 0, 0); zm_dump_stream_format(input_format_context, i, 0, 0);
@ -162,7 +169,7 @@ AVFrame *FFmpeg_Input::get_frame( int stream_id ) {
frameComplete = 1; frameComplete = 1;
# else # 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 ) { if ( ret < 0 ) {
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE ); 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 ); 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; int frame_count;
} stream; } stream;
stream streams[2]; stream *streams;
int video_stream_id; int video_stream_id;
int audio_stream_id; int audio_stream_id;
AVFormatContext *input_format_context; 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 ) { Image::Image( const AVFrame *frame ) {
AVFrame *dest_frame = zm_av_frame_alloc(); AVFrame *dest_frame = zm_av_frame_alloc();
text[0] = '\0';
width = frame->width; width = frame->width;
height = frame->height; 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 ) { void Image::Assign( const Image &image ) {
unsigned int new_size = (image.width * image.height) * image.colours; 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"); Error("Attempt to assign image with an empty buffer");
return; 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); Error("Attempt to assign image with unexpected colours per pixel: %d",image.colours);
return; return;
} }
@ -1847,8 +1848,7 @@ void Image::Delta( const Image &image, Image* targetimage) const
#endif #endif
} }
const Coord Image::centreCoord( const char *text ) const const Coord Image::centreCoord( const char *text ) const {
{
int index = 0; int index = 0;
int line_no = 0; int line_no = 0;
int text_len = strlen( text ); int text_len = strlen( text );
@ -1856,14 +1856,12 @@ const Coord Image::centreCoord( const char *text ) const
int max_line_len = 0; int max_line_len = 0;
const char *line = text; 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 ) if ( line_len > max_line_len )
max_line_len = line_len; max_line_len = line_len;
index += line_len; index += line_len;
while ( text[index] == '\n' ) while ( text[index] == '\n' ) {
{
index++; index++;
} }
line = text+index; line = text+index;
@ -1875,8 +1873,7 @@ const Coord Image::centreCoord( const char *text ) const
} }
/* RGB32 compatible: complete */ /* 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_r_col = RED_VAL_RGBA(pixel_colour);
const uint8_t pixel_g_col = GREEN_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); const uint8_t pixel_b_col = BLUE_VAL_RGBA(pixel_colour);

View File

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

View File

@ -24,7 +24,7 @@
// Do all the buffer checking work here to avoid unnecessary locking // Do all the buffer checking work here to avoid unnecessary locking
void* LibvlcLockBuffer(void* opaque, void** planes) { void* LibvlcLockBuffer(void* opaque, void** planes) {
LibvlcPrivateData* data = (LibvlcPrivateData*)opaque; LibvlcPrivateData* data = reinterpret_cast<LibvlcPrivateData*>(opaque);
data->mutex.lock(); data->mutex.lock();
uint8_t* buffer = data->buffer; uint8_t* buffer = data->buffer;
@ -36,7 +36,7 @@ void* LibvlcLockBuffer(void* opaque, void** planes) {
} }
void LibvlcUnlockBuffer(void* opaque, void* picture, void *const *planes) { void LibvlcUnlockBuffer(void* opaque, void* picture, void *const *planes) {
LibvlcPrivateData* data = (LibvlcPrivateData*)opaque; LibvlcPrivateData* data = reinterpret_cast<LibvlcPrivateData*>(opaque);
bool newFrame = false; bool newFrame = false;
for( uint32_t i = 0; i < data->bufferSize; i++ ) { 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; mLibvlcMediaPlayer = NULL;
mLibvlcData.buffer = NULL; mLibvlcData.buffer = NULL;
mLibvlcData.prevBuffer = 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 */ /* 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) { 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), " Name: %s\n", vid_src.name );
sprintf( output+strlen(output), " Channel: %d\n", vid_src.channel ); sprintf( output+strlen(output), " Channel: %d\n", vid_src.channel );
sprintf( output+strlen(output), " Flags: %d\n%s%s", vid_src.flags, 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_TUNER)?" Channel has a tuner\n":"",
vid_src.flags&VIDEO_VC_AUDIO?" Channel has audio\n":"" (vid_src.flags&VIDEO_VC_AUDIO)?" Channel has audio\n":""
); );
sprintf( output+strlen(output), " Type: %d - %s\n", vid_src.type, sprintf( output+strlen(output), " Type: %d - %s\n", vid_src.type,
vid_src.type==VIDEO_TYPE_TV?"TV":( vid_src.type==VIDEO_TYPE_TV?"TV":(

View File

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

View File

@ -73,7 +73,12 @@ std::vector<std::string> split(const std::string &s, char delim) {
return elems; 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) ); strncpy( name, p_name, sizeof(name) );
#if ZM_MEM_MAPPED #if ZM_MEM_MAPPED
@ -468,9 +473,12 @@ Monitor::Monitor(
videoRecording = ((GetOptVideoWriter() == H264PASSTHROUGH) && camera->SupportsNativeVideo()); videoRecording = ((GetOptVideoWriter() == H264PASSTHROUGH) && camera->SupportsNativeVideo());
if ( purpose == ANALYSIS ) { if ( purpose == ANALYSIS ) {
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 while(
&& shared_data->last_write_time == 0) { ( shared_data->last_write_index == (unsigned int)image_buffer_count )
&&
( shared_data->last_write_time == 0)
) {
Warning( "Waiting for capture daemon" ); Warning( "Waiting for capture daemon" );
sleep( 1 ); sleep( 1 );
} }
@ -605,7 +613,7 @@ Monitor::~Monitor() {
} }
if ( mem_ptr ) { if ( mem_ptr ) {
if ( event ) { 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(); 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 ); 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 ); return( shared_data->last_event );
} }
// This function is crap.
double Monitor::GetFPS() const { double Monitor::GetFPS() const {
int index1 = shared_data->last_write_index; int index1 = shared_data->last_write_index;
if ( index1 == image_buffer_count ) { 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]; Snapshot *snap1 = &image_buffer[index1];
if ( !snap1->timestamp || !snap1->timestamp->tv_sec ) { if ( !snap1->timestamp || !snap1->timestamp->tv_sec ) {
return( 0.0 ); // This should be impossible
return 0.0;
} }
struct timeval time1 = *snap1->timestamp; struct timeval time1 = *snap1->timestamp;
int image_count = image_buffer_count; int image_count = image_buffer_count;
int index2 = (index1+1)%image_buffer_count; int index2 = (index1+1)%image_buffer_count;
if ( index2 == image_buffer_count ) {
return( 0.0 );
}
Snapshot *snap2 = &image_buffer[index2]; 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 ) { while ( !snap2->timestamp || !snap2->timestamp->tv_sec ) {
if ( index1 == index2 ) { if ( index1 == index2 ) {
return( 0.0 ); // We didn't find any initialized images
return 0.0;
} }
index2 = (index2+1)%image_buffer_count; index2 = (index2+1)%image_buffer_count;
snap2 = &image_buffer[index2]; snap2 = &image_buffer[index2];
@ -807,10 +825,10 @@ double Monitor::GetFPS() const {
double curr_fps = image_count/time_diff; double curr_fps = image_count/time_diff;
if ( curr_fps < 0.0 ) { 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 ); 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 0.0;
} }
return( curr_fps ); return curr_fps;
} }
useconds_t Monitor::GetAnalysisRate() { 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; shared_data->last_write_time = image_buffer[index].timestamp->tv_sec;
image_count++; image_count++;
} // end if captureResult
if ( image_count && fps_report_interval && !(image_count%fps_report_interval) ) { if ( image_count && fps_report_interval && !(image_count%fps_report_interval) ) {
time_t now = image_buffer[index].timestamp->tv_sec;
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 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 ) { if ( now != last_fps_time ) {
fps = double(fps_report_interval)/(now.tv_sec-last_fps_time); // # of images per interval / the amount of time it took
Info( "%d -> %d -> %d", fps_report_interval, now.tv_sec, last_fps_time ); 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( "%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 ); Info( "%s: images:%d - Capturing at %.2lf fps", name, image_count, fps );
last_fps_time = now.tv_sec; last_fps_time = now;
static char sql[ZM_SQL_SML_BUFSIZ]; static char sql[ZM_SQL_SML_BUFSIZ];
snprintf( sql, sizeof(sql), "UPDATE Monitors SET CaptureFPS='%.2lf' WHERE Id=%d", fps, id ); snprintf( sql, sizeof(sql), "UPDATE Monitors SET CaptureFPS='%.2lf' WHERE Id=%d", fps, id );
if ( mysql_query( &dbconn, sql ) ) { if ( mysql_query( &dbconn, sql ) ) {
Error( "Can't run query: %s", mysql_error( &dbconn ) ); 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 // 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 ); } int GetOptSaveJPEGs() const { return( savejpegspref ); }
VideoWriter GetOptVideoWriter() const { return( videowriter ); } VideoWriter GetOptVideoWriter() const { return( videowriter ); }
const std::vector<EncoderParameter_t>* GetOptEncoderParams() const { return( &encoderparamsvec ); } 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; } 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; } 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 ); } int GetAlarmCaptureDelay() const { return( alarm_capture_delay ); }
unsigned int GetLastReadIndex() const; unsigned int GetLastReadIndex() const;
unsigned int GetLastWriteIndex() const; unsigned int GetLastWriteIndex() const;
unsigned int GetLastEvent() const; uint32_t GetLastEventId() const;
double GetFPS() const; double GetFPS() const;
void ForceAlarmOn( int force_score, const char *force_case, const char *force_text="" ); void ForceAlarmOn( int force_score, const char *force_case, const char *force_text="" );
void ForceAlarmOff(); void ForceAlarmOff();

View File

@ -498,7 +498,8 @@ void MonitorStream::runStream() {
if ( type == STREAM_JPEG ) if ( type == STREAM_JPEG )
fprintf( stdout, "Content-Type: multipart/x-mixed-replace;boundary=ZoneMinderFrame\r\n\r\n" ); 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_t stream_start_time;
time( &stream_start_time ); time( &stream_start_time );
@ -557,6 +558,8 @@ void MonitorStream::runStream() {
Debug( 2, "Assigned temporary buffer" ); Debug( 2, "Assigned temporary buffer" );
} }
} }
} else {
Debug(2, "Not using playback_buffer");
} // end if connkey & playback_buffer } // end if connkey & playback_buffer
float max_secs_since_last_sent_frame = 10.0; //should be > keep alive amount (5 secs) 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 ); gettimeofday( &now, NULL );
if ( connkey ) { if ( connkey ) {
//Debug(2, "checking command Queue for connkey: %d", connkey ); Debug(2, "checking command Queue for connkey: %d", connkey );
while(checkCommandQueue()) { while(checkCommandQueue()) {
Debug(2, "Have checking command Queue for connkey: %d", connkey ); Debug(2, "Have checking command Queue for connkey: %d", connkey );
got_command = true; got_command = true;
@ -657,26 +660,29 @@ Debug(2, "Have checking command Queue for connkey: %d", connkey );
delayed = false; delayed = false;
replay_rate = ZM_RATE_BASE; replay_rate = ZM_RATE_BASE;
} }
} } // end if ( buffered_playback && delayed )
if ( (unsigned int)last_read_index != monitor->shared_data->last_write_index ) { if ( last_read_index != monitor->shared_data->last_write_index ) {
int index = monitor->shared_data->last_write_index%monitor->image_buffer_count; 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; 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 ( (frame_mod == 1) || ((frame_count%frame_mod) == 0) ) {
if ( !paused && !delayed ) { if ( !paused && !delayed ) {
// Send the next frame // Send the next frame
Monitor::Snapshot *snap = &monitor->image_buffer[index]; Monitor::Snapshot *snap = &monitor->image_buffer[index];
//Debug(2, "sending Frame.");
if ( !sendFrame( snap->image, snap->timestamp ) ) { if ( !sendFrame( snap->image, snap->timestamp ) ) {
Debug(2, "sendFrame failed, quiting."); Debug(2, "sendFrame failed, quiting.");
zm_terminate = true; zm_terminate = true;
} }
// Perhaps we should use NOW instead.
memcpy( &last_frame_timestamp, snap->timestamp, sizeof(last_frame_timestamp) ); memcpy( &last_frame_timestamp, snap->timestamp, sizeof(last_frame_timestamp) );
//frame_sent = true; //frame_sent = true;
temp_read_index = temp_write_index; temp_read_index = temp_write_index;
} }
} } // end if should send frame
if ( buffered_playback ) { if ( buffered_playback ) {
if ( monitor->shared_data->valid ) { if ( monitor->shared_data->valid ) {
if ( monitor->image_buffer[index].timestamp->tv_sec ) { 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 } // end if buffered playback
frame_count++; 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))); 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); 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 ( ttl ) {
if ( (now.tv_sec - stream_start_time) > 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); Debug(2, "now(%d) - start(%d) > ttl(%d) break", now.tv_sec, stream_start_time, ttl);
break; 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 ); 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; break;
} }

View File

@ -62,6 +62,7 @@ void VideoStream::SetupFormat( ) {
AVFormatContext *s= avformat_alloc_context(); AVFormatContext *s= avformat_alloc_context();
if(!s) { if(!s) {
Fatal( "avformat_alloc_context failed %d \"%s\"", (size_t)ofc, av_err2str((size_t)ofc) ); Fatal( "avformat_alloc_context failed %d \"%s\"", (size_t)ofc, av_err2str((size_t)ofc) );
return;
} }
AVOutputFormat *oformat; 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 ) : 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), filename(in_filename),
format(in_format), format(in_format),
opicture(NULL),
tmp_opicture(NULL),
video_outbuf(NULL),
video_outbuf_size(0),
last_pts( -1 ), last_pts( -1 ),
streaming_thread(0), streaming_thread(0),
do_streaming(true), do_streaming(true),
add_timestamp(false),
timestamp(0),
buffer_copy(NULL), buffer_copy(NULL),
buffer_copy_lock(new pthread_mutex_t), buffer_copy_lock(new pthread_mutex_t),
buffer_copy_size(0), 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 ) { 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 #ifdef HAVE_LIBSWSCALE
static struct SwsContext *img_convert_ctx = 0; static struct SwsContext *img_convert_ctx = 0;
#endif // HAVE_LIBSWSCALE #endif // HAVE_LIBSWSCALE
if ( codec_context->pix_fmt != pf ) {
memcpy( tmp_opicture->data[0], buffer, buffer_size ); memcpy( tmp_opicture->data[0], buffer, buffer_size );
#ifdef HAVE_LIBSWSCALE #ifdef HAVE_LIBSWSCALE
if ( !img_convert_ctx ) { if ( !img_convert_ctx ) {

View File

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

View File

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

View File

@ -69,12 +69,13 @@ void StreamBase::updateFrameRate( double fps ) {
while( effective_fps > maxfps ) { while( effective_fps > maxfps ) {
effective_fps /= 2.0; effective_fps /= 2.0;
frame_mod *= 2; frame_mod *= 2;
}
Debug( 3, "aEFPS:%.2f, aFM:%d", effective_fps, frame_mod ); Debug( 3, "aEFPS:%.2f, aFM:%d", effective_fps, frame_mod );
}
} }
bool StreamBase::checkCommandQueue() { bool StreamBase::checkCommandQueue() {
if ( sd >= 0 ) { if ( sd >= 0 ) {
Debug(2, "sd is (%d)", sd );
CmdMsg msg; CmdMsg msg;
memset( &msg, 0, sizeof(msg) ); memset( &msg, 0, sizeof(msg) );
int nbytes = recvfrom( sd, &msg, sizeof(msg), MSG_DONTWAIT, 0, 0 ); int nbytes = recvfrom( sd, &msg, sizeof(msg), MSG_DONTWAIT, 0, 0 );
@ -92,6 +93,8 @@ Debug(2, "Message length is (%d)", nbytes );
processCommand( &msg ); processCommand( &msg );
return( true ); return( true );
} }
} else {
Error("sd is < 0");
} }
return( false ); return( false );
} }
@ -288,7 +291,7 @@ void StreamBase::openComms() {
if ( sd < 0 ) { if ( sd < 0 ) {
Fatal( "Can't create socket: %s", strerror(errno) ); Fatal( "Can't create socket: %s", strerror(errno) );
} else { } 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 ); 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."); Warning("Socket path was truncated.");
length = sizeof(loc_sock_path)-1; length = sizeof(loc_sock_path)-1;
} }
// Unlink before bind, in case it already exists
unlink( loc_sock_path ); unlink( loc_sock_path );
if ( sizeof(loc_addr.sun_path) < length ) { 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 ); 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; rem_addr.sun_family = AF_UNIX;
} // end if connKey > 0 } // end if connKey > 0
Debug(2, "comms open" ); Debug(2, "comms open" );
} } // end void StreamBase::openComms()
void StreamBase::closeComms() { void StreamBase::closeComms() {
if ( connkey > 0 ) { if ( connkey > 0 ) {
@ -324,10 +328,10 @@ void StreamBase::closeComms() {
if ( loc_sock_path[0] ) { if ( loc_sock_path[0] ) {
unlink( loc_sock_path ); 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. 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> #include <sys/thr.h>
#endif #endif
class ThreadException : public Exception class ThreadException : public Exception {
{
private: private:
#ifndef SOLARIS #ifndef SOLARIS
pid_t pid() { pid_t pid() {
@ -55,12 +54,11 @@ private:
pthread_t pid() { return( pthread_self() ); } pthread_t pid() { return( pthread_self() ); }
#endif #endif
public: 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; friend class Condition;
private: private:
@ -71,8 +69,7 @@ public:
~Mutex(); ~Mutex();
private: private:
pthread_mutex_t *getMutex() pthread_mutex_t *getMutex() {
{
return( &mMutex ); return( &mMutex );
} }
@ -84,18 +81,15 @@ public:
bool locked(); bool locked();
}; };
class ScopedMutex class ScopedMutex {
{
private: private:
Mutex &mMutex; Mutex &mMutex;
public: public:
ScopedMutex( Mutex &mutex ) : mMutex( mutex ) explicit ScopedMutex( Mutex &mutex ) : mMutex( mutex ) {
{
mMutex.lock(); mMutex.lock();
} }
~ScopedMutex() ~ScopedMutex() {
{
mMutex.unlock(); mMutex.unlock();
} }
@ -164,8 +158,7 @@ public:
} }
}; };
template <class T> class ThreadData template <class T> class ThreadData {
{
private: private:
T mValue; T mValue;
mutable bool mChanged; mutable bool mChanged;
@ -173,11 +166,11 @@ private:
mutable Condition mCondition; mutable Condition mCondition;
public: 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() {} //~ThreadData() {}

View File

@ -27,11 +27,12 @@
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include "zm_utils.h"
User::User() { User::User() {
username[0] = password[0] = 0; username[0] = password[0] = 0;
enabled = false; enabled = false;
stream = events = control = monitors = system = PERM_NONE; stream = events = control = monitors = system = PERM_NONE;
monitor_ids = 0;
} }
User::User( MYSQL_ROW &dbrow ) { User::User( MYSQL_ROW &dbrow ) {
@ -44,45 +45,41 @@ User::User( MYSQL_ROW &dbrow ) {
control = (Permission)atoi( dbrow[index++] ); control = (Permission)atoi( dbrow[index++] );
monitors = (Permission)atoi( dbrow[index++] ); monitors = (Permission)atoi( dbrow[index++] );
system = (Permission)atoi( dbrow[index++] ); system = (Permission)atoi( dbrow[index++] );
monitor_ids = 0;
char *monitor_ids_str = dbrow[index++]; char *monitor_ids_str = dbrow[index++];
if ( monitor_ids_str && *monitor_ids_str ) { if ( monitor_ids_str && *monitor_ids_str ) {
monitor_ids = new int[strlen(monitor_ids_str)]; StringVector ids = split(monitor_ids_str, ",");
int n_monitor_ids = 0; for( StringVector::iterator i = ids.begin(); i < ids.end(); ++i ) {
const char *ptr = monitor_ids_str; monitor_ids.push_back( atoi( (*i).c_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;
} }
} }
User::~User() { 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 ) { bool User::canAccess( int monitor_id ) {
if ( !monitor_ids ) { if ( monitor_ids.empty() )
return( true ); return true;
}
for ( int i = 0; monitor_ids[i]; i++ ) { for ( std::vector<int>::iterator i = monitor_ids.begin(); i != monitor_ids.end(); ++i ) {
if ( monitor_ids[i] == monitor_id ) { if ( *i == monitor_id ) {
return( true ); return true;
} }
} }
return( false ); return false;
} }
// Function to load a user from username and password // Function to load a user from username and password

View File

@ -36,8 +36,8 @@
#include <openssl/md5.h> #include <openssl/md5.h>
#endif // HAVE_L || HAVE_LIBCRYPTO #endif // HAVE_L || HAVE_LIBCRYPTO
class User #include <vector>
{ class User {
public: public:
typedef enum { PERM_NONE=1, PERM_VIEW, PERM_EDIT } Permission; typedef enum { PERM_NONE=1, PERM_VIEW, PERM_EDIT } Permission;
@ -50,12 +50,17 @@ protected:
Permission control; Permission control;
Permission monitors; Permission monitors;
Permission system; Permission system;
int *monitor_ids; std::vector<int> monitor_ids;
public: public:
User(); User();
User( MYSQL_ROW &dbrow ); explicit User( MYSQL_ROW &dbrow );
~User(); ~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 *getUsername() const { return( username ); }
const char *getPassword() const { return( password ); } 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 ); return str.substr( startpos, endpos-startpos+1 );
} }
std::string trimSpaces(std::string str) std::string trimSpaces(std::string str) {
{
return trimSet(str, " \t"); return trimSet(str, " \t");
} }
@ -80,7 +79,7 @@ const std::string stringtf( const char *format, ... )
return( tempString ); return( tempString );
} }
const std::string stringtf( const std::string &format, ... ) const std::string stringtf( const std::string format, ... )
{ {
va_list ap; va_list ap;
char tempBuffer[8192]; char tempBuffer[8192];
@ -209,10 +208,9 @@ int split(const char* string, const char delim, std::vector<std::string>& items)
return -2; return -2;
std::string str(string); std::string str(string);
size_t pos;
while(true) { while(true) {
pos = str.find(delim); size_t pos = str.find(delim);
items.push_back(str.substr(0, pos)); items.push_back(str.substr(0, pos));
str.erase(0, pos+1); 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); std::string replaceAll(std::string str, std::string from, std::string to);
const std::string stringtf( const char *format, ... ); 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 ); bool startsWith( const std::string &haystack, const std::string &needle );
StringVector split( const std::string &string, const std::string &chars, int limit=0 ); 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 #else
video_out_stream = 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) { if (!video_out_stream) {
Fatal("Unable to create video out stream\n"); Fatal("Unable to create video out stream\n");
} else { } else {
@ -194,6 +195,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
converted_in_samples = NULL; converted_in_samples = NULL;
audio_out_codec = NULL; audio_out_codec = NULL;
audio_in_codec = NULL;
audio_in_ctx = NULL; audio_in_ctx = NULL;
audio_out_stream = NULL; audio_out_stream = NULL;
in_frame = NULL; in_frame = NULL;
@ -226,7 +228,11 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
Debug(3, "Got AAC"); Debug(3, "Got AAC");
audio_out_stream = audio_out_stream =
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
avformat_new_stream(oc, (const AVCodec *)(audio_in_ctx->codec)); 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) { if (!audio_out_stream) {
Error("Unable to create audio out stream\n"); Error("Unable to create audio out stream\n");
audio_out_stream = NULL; audio_out_stream = NULL;
@ -406,12 +412,34 @@ VideoStore::~VideoStore() {
// Just do a file open/close/writeheader/etc. // Just do a file open/close/writeheader/etc.
// What if we were only doing audio recording? // What if we were only doing audio recording?
if (video_out_stream) { 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); 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; video_out_ctx = NULL;
Debug(4, "Success freeing video_out_ctx"); 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); 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; audio_out_ctx = NULL;
#ifdef HAVE_LIBAVRESAMPLE #ifdef HAVE_LIBAVRESAMPLE
if (resample_ctx) { if (resample_ctx) {
@ -454,10 +482,10 @@ bool VideoStore::setup_resampler() {
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
// Newer ffmpeg wants to keep everything separate... so have to lookup our own // Newer ffmpeg wants to keep everything separate... so have to lookup our own
// decoder, can't reuse the one from the camera. // 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); avcodec_find_decoder(audio_in_stream->codecpar->codec_id);
#else #else
AVCodec *audio_in_codec = audio_in_codec =
avcodec_find_decoder(audio_in_ctx->codec_id); avcodec_find_decoder(audio_in_ctx->codec_id);
#endif #endif
ret = avcodec_open2(audio_in_ctx, audio_in_codec, NULL); ret = avcodec_open2(audio_in_ctx, audio_in_codec, NULL);
@ -778,7 +806,6 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
} }
opkt.flags = ipkt->flags; opkt.flags = ipkt->flags;
int keyframe = opkt.flags & AV_PKT_FLAG_KEY;
opkt.pos = -1; opkt.pos = -1;
opkt.data = ipkt->data; opkt.data = ipkt->data;
@ -792,7 +819,7 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
Debug(1, Debug(1,
"writing video packet keyframe(%d) pts(%d) dts(%d) duration(%d) " "writing video packet keyframe(%d) pts(%d) dts(%d) duration(%d) "
"ipkt.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)) { if ((opkt.data == NULL) || (opkt.size < 1)) {
Warning("%s:%d: Mangled AVPacket: discarding frame", __FILE__, __LINE__); Warning("%s:%d: Mangled AVPacket: discarding frame", __FILE__, __LINE__);
dumpPacket(ipkt); 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 * If we are at the end of the file, pass an empty packet to the decoder
* to flush it. * to flush it.
*/ */
int data_present;
if ((ret = avcodec_decode_audio4(audio_in_ctx, in_frame, if ((ret = avcodec_decode_audio4(audio_in_ctx, in_frame,
&data_present, ipkt)) < 0) { &data_present, ipkt)) < 0) {
Error("Could not decode frame (error '%s')\n", Error("Could not decode frame (error '%s')\n",

View File

@ -16,7 +16,6 @@ extern "C" {
class VideoStore { class VideoStore {
private: private:
unsigned int packets_written;
AVOutputFormat *out_format; AVOutputFormat *out_format;
AVFormatContext *oc; AVFormatContext *oc;
@ -34,13 +33,13 @@ private:
AVFrame *out_frame; AVFrame *out_frame;
AVCodecContext *video_in_ctx; AVCodecContext *video_in_ctx;
AVCodec *audio_in_codec;
AVCodecContext *audio_in_ctx; AVCodecContext *audio_in_ctx;
int ret; int ret;
// The following are used when encoding the audio stream to AAC // The following are used when encoding the audio stream to AAC
AVCodec *audio_out_codec; AVCodec *audio_out_codec;
AVCodecContext *audio_out_ctx; AVCodecContext *audio_out_ctx;
int data_present;
AVAudioFifo *fifo; AVAudioFifo *fifo;
int out_frame_size; int out_frame_size;
#ifdef HAVE_LIBAVRESAMPLE #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) { 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 pixelsalarmed = 0;
uint32_t pixelsdifference = 0; uint32_t pixelsdifference = 0;
uint8_t *pdiff;
const uint8_t *ppoly;
uint8_t calc_max_pixel_threshold = 255; uint8_t calc_max_pixel_threshold = 255;
unsigned int lo_y; unsigned int lo_y;
unsigned int hi_y; unsigned int hi_y;
unsigned int lo_x;
unsigned int hi_x;
if(max_pixel_threshold) if(max_pixel_threshold)
calc_max_pixel_threshold = 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(); lo_y = polygon.LoY();
hi_y = polygon.HiY(); hi_y = polygon.HiY();
for ( unsigned int y = lo_y; y <= hi_y; y++ ) { for ( unsigned int y = lo_y; y <= hi_y; y++ ) {
lo_x = ranges[y].lo_x; unsigned int lo_x = ranges[y].lo_x;
hi_x = ranges[y].hi_x; unsigned int hi_x = ranges[y].hi_x;
Debug( 7, "Checking line %d from %d -> %d", y, lo_x, hi_x ); Debug( 7, "Checking line %d from %d -> %d", y, lo_x, hi_x );
pdiff = (uint8_t*)pdiff_image->Buffer( lo_x, y ); uint8_t *pdiff = (uint8_t*)pdiff_image->Buffer( lo_x, y );
ppoly = ppoly_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++ ) { for ( unsigned int x = lo_x; x <= hi_x; x++, pdiff++, ppoly++ ) {
if ( *ppoly && (*pdiff > min_pixel_threshold) && (*pdiff <= calc_max_pixel_threshold) ) { 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(); zmLoadConfig();
logInit( "zms" );
hwcaps_detect();
zmSetDefaultTermHandler();
zmSetDefaultDieHandler();
const char *query = getenv( "QUERY_STRING" ); const char *query = getenv( "QUERY_STRING" );
if ( query ) { if ( query ) {
@ -175,6 +169,14 @@ int main( int argc, const char *argv[] ) {
} // end foreach parm } // end foreach parm
} // end if query } // 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 ) { if ( config.opt_use_auth ) {
User *user = 0; User *user = 0;
@ -205,6 +207,10 @@ int main( int argc, const char *argv[] ) {
ValidateAccess( user, monitor_id ); ValidateAccess( user, monitor_id );
} }
hwcaps_detect();
zmSetDefaultTermHandler();
zmSetDefaultDieHandler();
setbuf( stdout, 0 ); setbuf( stdout, 0 );
if ( nph ) { if ( nph ) {
fprintf( stdout, "HTTP/1.0 200 OK\r\n" ); 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 ( function & ZMU_EVENT ) {
if ( verbose ) if ( verbose )
printf( "Last event id: %d\n", monitor->GetLastEvent() ); printf( "Last event id: %d\n", monitor->GetLastEventId() );
else { else {
if ( have_output ) printf( "%c", separator ); if ( have_output ) printf( "%c", separator );
printf( "%d", monitor->GetLastEvent() ); printf( "%d", monitor->GetLastEventId() );
have_output = true; have_output = true;
} }
} }
@ -693,8 +693,7 @@ int main( int argc, char *argv[] ) {
Error( "Can't use query result: %s", mysql_error( &dbconn ) ); Error( "Can't use query result: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) ); exit( mysql_errno( &dbconn ) );
} }
int n_monitors = mysql_num_rows( result ); Debug( 1, "Got %d monitors", mysql_num_rows( result ) );
Debug( 1, "Got %d monitors", n_monitors );
printf( "%4s%5s%6s%9s%14s%6s%6s%8s%8s\n", "Id", "Func", "State", "TrgState", "LastImgTim", "RdIdx", "WrIdx", "LastEvt", "FrmRate" ); 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++ ) { 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, tv.tv_sec, tv.tv_usec/10000,
monitor->GetLastReadIndex(), monitor->GetLastReadIndex(),
monitor->GetLastWriteIndex(), monitor->GetLastWriteIndex(),
monitor->GetLastEvent(), monitor->GetLastEventId(),
monitor->GetFPS() monitor->GetFPS()
); );
delete monitor; delete monitor;

View File

@ -8,6 +8,13 @@ exit;
fi 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 "$@" for i in "$@"
do do
case $i in 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' ); ajaxError( 'Export Failed' );
break; 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 <?php
if ($_REQUEST['entity'] == "navBar") {
ajaxResponse(getNavBarHtml('reload'));
return;
}
$statusData = array( $statusData = array(
'system' => array( 'system' => array(
@ -137,6 +141,17 @@ $statusData = array(
//'Path' => array( 'postFunc' => 'getEventPath' ), //'Path' => array( 'postFunc' => 'getEventPath' ),
), ),
), ),
'frames' => array(
'permission' => 'Events',
'table' => 'Frames',
'selector' => 'EventId',
'elements' => array(
'EventId' => true,
'FrameId' => true,
'Type' => true,
'Delta' => true,
),
),
'frame' => array( 'frame' => array(
'permission' => 'Events', 'permission' => 'Events',
'table' => 'Frames', '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'; $locSockFile = ZM_PATH_SOCKS.'/zms-'.sprintf("%06d",$_REQUEST['connkey']).'w.sock';
if ( file_exists( $locSockFile ) ) { if ( file_exists( $locSockFile ) ) {
Warning("sock file $locSockFile already exists?! Is someone else talking to zms?"); 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 { } else {
Logger::Debug("socket file does not exist, we should be good to connect."); Logger::Debug("socket file does not exist, we should be good to connect.");
} }
@ -115,7 +116,9 @@ switch ( $data['type'] ) {
case MSG_DATA_WATCH : case MSG_DATA_WATCH :
{ {
$data = unpack( "ltype/imonitor/istate/dfps/ilevel/irate/ddelay/izoom/Cdelayed/Cpaused/Cenabled/Cforced", $msg ); $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 ); $data['fps'] = round( $data['fps'], 2 );
Logger::Debug("FPS: " . $data['fps'] );
$data['rate'] /= RATE_BASE; $data['rate'] /= RATE_BASE;
$data['delay'] = round( $data['delay'], 2 ); $data['delay'] = round( $data['delay'], 2 );
$data['zoom'] = round( $data['zoom']/SCALE_BASE, 1 ); $data['zoom'] = round( $data['zoom']/SCALE_BASE, 1 );

View File

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

View File

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

View File

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

View File

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

View File

@ -110,7 +110,7 @@ class Storage {
} }
public function disk_used_space() { public function disk_used_space() {
# This isn't a function like this in php, so we have to add up the space used in each event. # This isn't a function like this in php, so we have to add up the space used in each event.
if ( ! array_key_exists( 'disk_used_space', $this ) ) { if ( ! array_key_exists( 'DiskSpace', $this ) ) {
$used = 0; $used = 0;
if ( $this->{'Type'} == 's3fs' ) { if ( $this->{'Type'} == 's3fs' ) {
$used = dbFetchOne('SELECT SUM(DiskSpace) AS DiskSpace FROM Events WHERE StorageId=? AND DiskSpace IS NOT NULL', 'DiskSpace', array($this->Id()) ); $used = dbFetchOne('SELECT SUM(DiskSpace) AS DiskSpace FROM Events WHERE StorageId=? AND DiskSpace IS NOT NULL', 'DiskSpace', array($this->Id()) );
@ -123,10 +123,10 @@ class Storage {
$path = $this->Path(); $path = $this->Path();
$used = disk_total_space( $path ) - disk_free_space( $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']) ) { if ( ! empty($_REQUEST['Id']) ) {
dbQuery( 'DELETE FROM Filters WHERE Id=?', array( $_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 = ''; $sql = '';
$_REQUEST['filter']['Query']['sort_field'] = validStr($_REQUEST['filter']['Query']['sort_field']); $_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']['sort_asc'] = validStr($_REQUEST['filter']['Query']['sort_asc']);
$_REQUEST['filter']['Query']['limit'] = validInt($_REQUEST['filter']['Query']['limit']); $_REQUEST['filter']['Query']['limit'] = validInt($_REQUEST['filter']['Query']['limit']);
if ( $action == 'execute' or $action == 'submit' ) { if ( $action == 'execute' ) {
$sql .= ' Name = \'_TempFilter'.time().'\''; $tempFilterName = '_TempFilter'.time();
$sql .= ' Name = \''.$tempFilterName.'\'';
} else { } else {
$sql .= ' Name = '.dbEscape($_REQUEST['filter']['Name']); $sql .= ' Name = '.dbEscape($_REQUEST['filter']['Name']);
} }
@ -175,12 +177,15 @@ Warning("Addterm");
$sql .= ', Background = '. ( !empty($_REQUEST['filter']['Background']) ? 1 : 0); $sql .= ', Background = '. ( !empty($_REQUEST['filter']['Background']) ? 1 : 0);
$sql .= ', Concurrent = '. ( !empty($_REQUEST['filter']['Concurrent']) ? 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']) ); dbQuery( 'UPDATE Filters SET ' . $sql. ' WHERE Id=?', array($_REQUEST['Id']) );
} else { } else {
dbQuery( 'INSERT INTO Filters SET' . $sql ); dbQuery( 'INSERT INTO Filters SET' . $sql );
$_REQUEST['Id'] = dbInsertId(); $_REQUEST['Id'] = dbInsertId();
} }
if ( $action == 'execute' ) {
executeFilter( $tempFilterName );
}
} // end if save or execute } // end if save or execute
} // end if canEdit(Events) } // 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) ); dbQuery( "UPDATE Zones SET ".implode( ", ", $changes )." WHERE MonitorId=? AND Id=?", array( $mid, $zid) );
} else { } else {
dbQuery( "INSERT INTO Zones SET MonitorId=?, ".implode( ", ", $changes ), array( $mid ) ); 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 ( $cookies ) session_write_close();
if ( daemonCheck() ) { if ( daemonCheck() ) {
@ -422,6 +428,7 @@ if ( !empty($_REQUEST['mid']) && canEdit( 'Monitors', $_REQUEST['mid'] ) ) {
foreach( $_REQUEST['markZids'] as $markZid ) { foreach( $_REQUEST['markZids'] as $markZid ) {
$zone = dbFetchOne( 'select * from Zones where Id=?', NULL, array($markZid) ); $zone = dbFetchOne( 'select * from Zones where Id=?', NULL, array($markZid) );
dbQuery( 'delete from Zones WHERE MonitorId=? AND Id=?', array( $mid, $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; $deletedZid = 1;
} }
if ( $deletedZid ) { if ( $deletedZid ) {
@ -601,10 +608,10 @@ if ( canEdit( 'Monitors' ) ) {
} // end if ZM_OPT_FAST_DELETE } // end if ZM_OPT_FAST_DELETE
// This is the important stuff // This is the important stuff
dbQuery( 'DELETE FROM Monitors WHERE Id = ?', array($markMid) );
dbQuery( 'DELETE FROM Zones WHERE MonitorId = ?', array($markMid) ); dbQuery( 'DELETE FROM Zones WHERE MonitorId = ?', array($markMid) );
if ( ZM_OPT_X10 ) if ( ZM_OPT_X10 )
dbQuery( 'DELETE FROM TriggersX10 WHERE MonitorId=?', array($markMid) ); dbQuery( 'DELETE FROM TriggersX10 WHERE MonitorId=?', array($markMid) );
dbQuery( 'DELETE FROM Monitors WHERE Id = ?', array($markMid) );
fixSequences(); fixSequences();

View File

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

View File

@ -134,7 +134,7 @@ function dbQuery( $sql, $params=NULL ) {
} else { } else {
$result = $dbConn->query( $sql ); $result = $dbConn->query( $sql );
} }
if ( 0 ) { if ( 1 ) {
if ( $params ) if ( $params )
Warning("SQL: $sql" . implode(',',$params) . ' rows: '.$result->rowCount() ); Warning("SQL: $sql" . implode(',',$params) . ' rows: '.$result->rowCount() );
else 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. # 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('logger.php');
require_once( 'database.php' ); require_once('database.php');
function userLogin( $username, $password='', $passwordHashed=false ) { function userLogin( $username, $password='', $passwordHashed=false ) {
global $user, $cookies; global $user, $cookies;
$sql = 'SELECT * FROM Users WHERE Enabled = 1'; $sql = 'SELECT * FROM Users WHERE Enabled=1';
$sql_values = NULL; $sql_values = NULL;
if ( ZM_AUTH_TYPE == 'builtin' ) { if ( ZM_AUTH_TYPE == 'builtin' ) {
if ( $passwordHashed ) { if ( $passwordHashed ) {
@ -44,7 +44,7 @@ function userLogin( $username, $password='', $passwordHashed=false ) {
} }
$sql_values = array( $username, $password ); $sql_values = array( $username, $password );
} else { } else {
$sql .= ' AND Username = ?'; $sql .= ' AND Username=?';
$sql_values = array( $username ); $sql_values = array( $username );
} }
$_SESSION['username'] = $username; $_SESSION['username'] = $username;
@ -138,26 +138,27 @@ function getAuthUser( $auth ) {
$authHash = md5( $authKey ); $authHash = md5( $authKey );
if ( $auth == $authHash ) { if ( $auth == $authHash ) {
return( $user ); return $user;
} }
} // end foreach hour } // end foreach hour
} // end foreach user } // end foreach user
} // end if using auth hash } // end if using auth hash
Error( "Unable to authenticate user from auth hash '$auth'" ); Error( "Unable to authenticate user from auth hash '$auth'" );
return( false ); return( false );
} } // end getAuthUser($auth)
function generateAuthHash( $useRemoteAddr ) { function generateAuthHash( $useRemoteAddr ) {
if ( ZM_OPT_USE_AUTH and ZM_AUTH_RELAY == 'hashed' and isset($_SESSION['username']) and $_SESSION['passwordHash'] ) { 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 # 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 # Don't both regenerating Auth Hash if an hour hasn't gone by yet
$time = localtime(); $local_time = localtime();
$authKey = ''; $authKey = '';
if ( $useRemoteAddr ) { 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 { } 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 ); $auth = md5( $authKey );
if ( session_status() == PHP_SESSION_NONE ) { 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"); Warning("Session is not active. AuthHash will not be cached. called from $file:$line");
} }
$_SESSION['AuthHash'] = $auth; $_SESSION['AuthHash'] = $auth;
$_SESSION['AuthHashGeneratedAt'] = time(); $_SESSION['AuthHashGeneratedAt'] = $time;
Logger::Debug("Generated new auth $auth at " . $_SESSION['AuthHashGeneratedAt']. " using $authKey" ); Logger::Debug("Generated new auth $auth at " . $_SESSION['AuthHashGeneratedAt']. " using $authKey" );
} else { } 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 } # end if AuthHash is not cached
return $_SESSION['AuthHash']; return $_SESSION['AuthHash'];
} else { } else {
@ -347,7 +348,7 @@ function getImageStreamHTML( $id, $src, $width, $height, $title='' ) {
if ( canStreamIframe() ) { if ( canStreamIframe() ) {
return '<iframe id="'.$id.'" src="'.$src.'" alt="'. validHtmlStr($title) .'" '.($width? ' width="'. validInt($width).'"' : '').($height?' height="'.validInt($height).'"' : '' ).'/>'; return '<iframe id="'.$id.'" src="'.$src.'" alt="'. validHtmlStr($title) .'" '.($width? ' width="'. validInt($width).'"' : '').($height?' height="'.validInt($height).'"' : '' ).'/>';
} else { } 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 ); 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 // 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 // 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. // 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 # Use the last modified timestamp to create a link that gets a different filename
# To defeat caching. Should probably use md5 hash # To defeat caching. Should probably use md5 hash
$parts = pathinfo($file); $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 ) ) { if ( file_exists( ZM_PATH_WEB.'/'.$cacheFile ) or symlink( ZM_PATH_WEB.'/'.$file, ZM_PATH_WEB.'/'.$cacheFile ) ) {
return $cacheFile; return $cacheFile;
} else { } else {
@ -2151,16 +2212,18 @@ function getStreamHTML( $monitor, $options = array() ) {
if ( isset($options['scale']) and $options['scale'] and ( $options['scale'] != 100 ) ) { if ( isset($options['scale']) and $options['scale'] and ( $options['scale'] != 100 ) ) {
//Warning("Scale to " . $options['scale'] ); //Warning("Scale to " . $options['scale'] );
$options['width'] = reScale( $monitor->Width(), $options['scale'] ); $options['width'] = reScale( $monitor->Width(), $options['scale'] ) . 'px';
$options['height'] = reScale( $monitor->Height(), $options['scale'] ); $options['height'] = reScale( $monitor->Height(), $options['scale'] ) . 'px';
} else { } else {
# scale is empty or 100 # scale is empty or 100
# There may be a fixed width applied though, in which case we need to leave the height empty # 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'] ) ) { if ( ! ( isset($options['width']) and $options['width'] ) ) {
$options['width'] = $monitor->Width(); $options['width'] = $monitor->Width() . 'px';
if ( ! ( isset($options['height']) and $options['height'] ) ) { 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'] ) ) { if ( ! isset($options['mode'] ) ) {
@ -2213,6 +2276,7 @@ function getStreamMode( ) {
$streamMode = 'single'; $streamMode = 'single';
Info( 'The system has fallen back to single jpeg mode for streaming. Consider enabling Cambozola or upgrading the client browser.' ); 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 } // end function getStreamMode
function folder_size($dir) { function folder_size($dir) {

View File

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

View File

@ -34,7 +34,7 @@ if ( version_compare( phpversion(), '4.1.0', '<') ) {
} }
// Useful debugging lines for mobile devices // Useful debugging lines for mobile devices
if ( true ) { if ( false ) {
ob_start(); ob_start();
phpinfo( INFO_VARIABLES ); phpinfo( INFO_VARIABLES );
$fp = fopen( '/tmp/env.html', 'w' ); $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') { if ( ZM_ENABLE_CSRF_MAGIC && $action != 'login' && $view != 'view_video' && $view != 'video' && $request != 'control' && $view != 'frames') {
require_once( 'includes/csrf/csrf-magic.php' ); 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(); csrf_check();
} }

View File

@ -50,7 +50,10 @@ function logReport( level, message, file, line )
if ( !debugReq ) 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' } ); debugReq = new Request.JSON( { url: thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'chain' } );
} }
var requestParms = debugParms; var requestParms = debugParms;

View File

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

View File

@ -1,3 +1,4 @@
/* /*
* ZoneMinder Base Stylesheet, $Date$, $Revision$ * ZoneMinder Base Stylesheet, $Date$, $Revision$
* Copyright (C) 2001-2008 Philip Coombes * Copyright (C) 2001-2008 Philip Coombes
@ -95,9 +96,6 @@ input.noborder {
border: 0; border: 0;
} }
input[disabled] {
color: #888888;
}
img { img {
display: inline-block; display: inline-block;
@ -349,9 +347,11 @@ th.table-th-sort-rev span.table-th-sort-span {
#header { #header {
width: 100%; width: 100%;
line-height: 24px; margin: 0 auto 4px auto;
margin: 8px auto; line-height: 1;
text-align: left; text-align: left;
padding: 3px 0;
border-bottom: 1px solid #555555;
} }
#header h2 { #header h2 {
@ -381,7 +381,7 @@ th.table-th-sort-rev span.table-th-sort-span {
#content { #content {
width: 96%; width: 96%;
margin: 8px auto; margin: 0 auto 8px auto;
line-height: 130%; line-height: 130%;
text-align: center; 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; 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; margin-top: 0;
} }
@ -420,6 +424,7 @@ th.table-th-sort-rev span.table-th-sort-span {
float: right; float: right;
} }
#contentButtons button,
#contentButtons input { #contentButtons input {
margin-left: 8px; margin-left: 8px;
margin-bottom: 4px; margin-bottom: 4px;
@ -487,3 +492,36 @@ margin-left: 0px;
.nav-pills > li > a { .nav-pills > li > a {
border-radius: 0; 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; float: right;
} }
#systemStats .warning {
color: orange;
}
#systemStats .error {
color: red;
}
#systemStats .critical {
color: red;
text-decoration: blink;
}
#monitorSummary { #monitorSummary {
float: left; float: left;
text-align: left; text-align: left;

View File

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

View File

@ -1,31 +1,5 @@
#controls { .archived {
height: 16px; background-color: #f8f8f8;;
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;
} }
#contentTable.major .colTime { #contentTable.major .colTime {
@ -40,3 +14,26 @@
text-align: right; text-align: right;
padding-right: 8px; 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; width: 300px;
text-align: right; text-align: right;
} }
input#filter\[Name\] {
width: 400px;
}

View File

@ -1,33 +1,16 @@
#scaleControl { #scaleControl {
float: right; float: right;
} }
#controls { #controls {
width: 80%; width: 80%;
text-align: center; text-align: center;
margin: 0 auto; margin: 0 auto;
display: flex;
justify-content: space-between;
} }
#controls a { #controls a {
width: 40px; width: 40px;
margin-left: -20px; 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 { #monitors .alert {
color: #ffa500; color: #ffa500;
margin: 0;
padding: 0;
border-radius: 0;
border: none;
} }
#monitors .imageFeed { #monitors .imageFeed {

View File

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

View File

@ -5,6 +5,25 @@
margin: 0 auto; 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 { #title {
position: relative; position: relative;
margin: 0 auto; margin: 0 auto;
@ -15,20 +34,6 @@
line-height: 20px; line-height: 20px;
} }
#listLink {
position: absolute;
top: 5px;
left: 20px;
height: 15px;
}
#closeLink {
position: absolute;
top: 5px;
right: 20px;
height: 15px;
}
#topPanel { #topPanel {
position: relative; position: relative;
height: 220px; height: 220px;

View File

@ -1,37 +1,17 @@
@import url(../control.css); @import url(../control.css);
#menuBar { #header {
margin: 6px auto 4px; display: flex;
text-align: center; justify-content: space-between;
} }
#menuBar #monitorName { #menuControls {
float: left; display: flex;
align-items: center;
} }
#menuBar #closeControl { #menuControls div {
float: right; margin: 0 0 0 1em;
}
#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;
} }
#imageFeed{ #imageFeed{

View File

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

View File

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

View File

@ -1,31 +1,5 @@
#controls { .archived {
height: 16px; background-color: #2e2e2e;
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;
} }
#contentTable.major .colTime { #contentTable.major .colTime {
@ -40,3 +14,26 @@
text-align: right; text-align: right;
padding-right: 8px; 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 { #scaleControl {
float: right; float: right;
} }
#controls { #controls {
width: 80%; width: 80%;
text-align: center; text-align: center;
margin: 0 auto; margin: 0 auto;
display: flex;
justify-content: space-between;
} }
#controls a { #controls a {
width: 40px; width: 40px;
margin-left: -20px; 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 { #monitors .alert {
color: #ffa500; color: #ffa500;
margin: 0;
padding: 0;
border-radius: 0;
border: none;
} }
#monitors .imageFeed { #monitors .imageFeed {

View File

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

View File

@ -5,6 +5,25 @@
margin: 0 auto; 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 { #title {
position: relative; position: relative;
margin: 0 auto; margin: 0 auto;
@ -15,20 +34,6 @@
line-height: 20px; line-height: 20px;
} }
#listLink {
position: absolute;
top: 5px;
left: 20px;
height: 15px;
}
#closeLink {
position: absolute;
top: 5px;
right: 20px;
height: 15px;
}
#topPanel { #topPanel {
position: relative; position: relative;
height: 220px; height: 220px;

View File

@ -1,37 +1,17 @@
@import url(../control.css); @import url(../control.css);
#menuBar { #header {
margin: 6px auto 4px; display: flex;
text-align: center; justify-content: space-between;
} }
#menuBar #monitorName { #menuControls {
float: left; display: flex;
align-items: center;
} }
#menuBar #closeControl { #menuControls div {
float: right; margin: 0 0 0 1em;
}
#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;
} }
#imageFeed{ #imageFeed{

View File

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

View File

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

View File

@ -12,97 +12,71 @@
.alarmCue { .alarmCue {
background-color: #222222; background-color: #222222;
height: 1.5em; height: 1.25em;
text-align: left; text-align: left;
margin: 0 auto 0 auto; margin: 0 auto 0 auto;
border-radius: 0 0 .3em .3em;
} }
.alarmCue span { .alarmCue span {
background-color:red; background-color:red;
height: 1.5em; height: 100%;
display: inline-block; display: inline-block;
border-radius: 0;
} }
span.noneCue { span.noneCue {
background: none; 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 { #dataBar {
width: 100%; display: flex;
margin: 2px auto; flex-wrap:wrap;
text-align: center; justify-content: space-between;
}
#dataBar #dataTable {
width: 100%;
}
#dataBar #dataTable td {
text-align: center;
padding: 2px;
} }
#menuBar1 { #menuBar1 {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
width: 100%; width: 100%;
padding: 3px 0;
text-align: center; text-align: center;
clear: both; margin: 4px 0 0 0;
} }
#menuBar1 input, #menuBar1 select {
#menuBar1 #nameControl { padding: 2px 5px;
float: left;
}
#menuBar1 #nameControl #eventName {
margin-right: 4px;
} }
#menuBar1 #replayControl { #menuBar1 #replayControl {
float: right; margin: 0 4px 0 auto;
margin-left: 8px;
} }
#menuBar1 #scaleControl { #menuBar1 div {
float: right; margin: auto 5px;
margin-left: 8px;
} }
#menuBar2 { #nameControl input[type="button"]{
width: 100%; height: 100%;
padding: 3px 0;
margin-bottom: 4px;
} }
#menuBar2 div { #eventVideo {
text-align: left; display: inline-block;
float: left; position: relative;
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;
}
#menuBar1:after,
#menuBar2:after {
content: ".";
display: block;
height: 0;
font-size: 0;
clear: both;
visibility: hidden;
}
#imageFeed { #imageFeed {
display: inline-block; display: inline-block;
position: relative; position: relative;
@ -129,36 +103,36 @@ span.noneCue {
#monitorStatus #monitorState { #monitorStatus #monitorState {
} }
.dvrControls { #dvrControls {
margin-top: 3px; margin-top: 3px;
margin-bottom: 2px; margin-bottom: 2px;
text-align: center; text-align: center;
} }
.dvrControls input { #dvrControls input {
padding: 10px 10px; padding: 10px 10px;
width: 50px; width: 50px;
margin: 0 3px; margin: 0 3px;
font-weight: 900; font-weight: 900;
} }
.dvrControls input[disabled=disabled] { #dvrControls input[disabled=disabled] {
color: #aaaaaa; color: #aaaaaa;
} }
.dvrControls input.active { #dvrControls input.active {
border: 0; border: 0;
background-color: #2ecc71; background-color: #2ecc71;
color: #fff; color: #fff;
} }
.dvrControls input.inactive { #dvrControls input.inactive {
border: 0; border: 0;
background-color: #e67e22; background-color: #e67e22;
color: #fff; color: #fff;
} }
.dvrControls input.unavail { #dvrControls input.unavail {
background-color: #ccc; background-color: #ccc;
border: 0; border: 0;
cursor: default; cursor: default;
@ -176,31 +150,30 @@ span.noneCue {
#progressBar { #progressBar {
position: relative; position: relative;
top: -1.5em; top: -1.25em;
height: 1.5em; height: 1.25em;
margin: 0 auto -1.5em auto; margin: 0 auto -1.25em auto;
} }
#progressBar .progressBox { #progressBar .progressBox {
height: 1.5em; transition: width .1s;
height: 100%;
background: rgba(170, 170, 170, .7); background: rgba(170, 170, 170, .7);
border-radius: 0 0 .3em .3em;
} }
#eventStills { #eventStills {
width: 100%;
position: relative; position: relative;
} }
#eventThumbsPanel { #eventThumbsPanel {
position: relative; position: relative;
width: 100%; margin: 0;
margin: 4px auto;
z-index: 1; z-index: 1;
} }
#eventThumbs { #eventThumbs {
margin: 0 auto; margin: 0 auto;
width: 100%;
overflow: hidden; overflow: hidden;
height: 300px; height: 300px;
} }
@ -219,14 +192,19 @@ span.noneCue {
} }
#eventImagePanel { #eventImagePanel {
display: none;
position: absolute; position: absolute;
top: 0;
left: 0;
z-index: 10; z-index: 10;
width: 100%;
} }
#eventImageFrame { #eventImageFrame {
border: 2px solid gray; border: 2px solid gray;
background-color: white; background-color: white;
padding: 4px; padding: 4px;
display: inline-block;
} }
#eventImage { #eventImage {
@ -249,8 +227,17 @@ span.noneCue {
float: right; float: right;
} }
#eventImageBar::after {
visibility: hidden;
display: block;
content: "";
clear: both;
height: 0;
}
#eventImageNav { #eventImageNav {
position: relative; position: relative;
margin: 0 0 4px 0;
} }
#eventImageNav input { #eventImageNav input {
@ -259,82 +246,20 @@ span.noneCue {
} }
#thumbsSliderPanel { #thumbsSliderPanel {
width: 400px; width: 80%;
margin: 4px auto 0; margin: 0px auto 4px auto;
background: #888888;
padding: 1px;
} }
#thumbsSlider { #thumbsSlider {
width: 400px; width: 100%;
height: 10px; height: 1.25em;
background: #dddddd; position: relative;
top: -1.25em;
margin: 0 0 -1.25em 0;
} }
#thumbsKnob { #thumbsKnob {
width: 8px; width: 1em;
height: 10px; height: 100%;
background-color: #444444; background-color: #999999;
}
#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;
} }

View File

@ -1,31 +1,5 @@
#controls { .archived {
height: 16px; background-color: #f8f8f8;;
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;
} }
#contentTable.major .colTime { #contentTable.major .colTime {
@ -40,3 +14,26 @@
text-align: right; text-align: right;
padding-right: 8px; 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%; width: 80%;
text-align: center; text-align: center;
margin: 0 auto; margin: 0 auto;
display: flex;
justify-content: space-between;
} }
#controls a { #controls a {
width: 40px; width: 40px;
margin-left: -20px; 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; display: inline-flex;
border: 1px solid black; border: 1px solid black;
width: 25%; width: 25%;
padding: 9px; padding: 4px;
} }
#ScaleDiv label, #ScaleDiv label,
#SpeedDiv label { #SpeedDiv label {
@ -42,3 +42,7 @@ input[type=range]::-ms-tooltip {
color: white; color: white;
font-size: 40px; font-size: 40px;
} }
#downloadVideo {
margin-left: 5px;
}

View File

@ -5,6 +5,25 @@
margin: 0 auto; 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 { #title {
position: relative; position: relative;
margin: 0 auto; margin: 0 auto;
@ -15,20 +34,6 @@
line-height: 20px; line-height: 20px;
} }
#listLink {
position: absolute;
top: 5px;
left: 20px;
height: 15px;
}
#closeLink {
position: absolute;
top: 5px;
right: 20px;
height: 15px;
}
#topPanel { #topPanel {
position: relative; position: relative;
height: 220px; height: 220px;

View File

@ -1,37 +1,17 @@
@import url(../control.css); @import url(../control.css);
#menuBar { #header {
margin: 6px auto 4px; display: flex;
text-align: center; justify-content: space-between;
} }
#menuBar #monitorName { #menuControls {
float: left; display: flex;
align-items: center;
} }
#menuBar #closeControl { #menuControls div {
float: right; margin: 0 0 0 1em;
}
#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;
} }
#imageFeed{ #imageFeed{

View File

@ -45,7 +45,7 @@ $scales = array(
'12.5' => '1/8x', '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( $bandwidth_options = array(
'high' => translate('High'), 'high' => translate('High'),
@ -56,6 +56,7 @@ $bandwidth_options = array(
switch ( $_COOKIE['zmBandwidth'] ) { switch ( $_COOKIE['zmBandwidth'] ) {
case 'high' : { 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_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_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_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 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; break;
} case 'medium' : { } 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_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_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_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 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; break;
} case 'low' : { } 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_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_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_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 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 ) ); 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) ) if ( canView( 'Events' ) && !empty($eids) )
@ -907,8 +907,12 @@ function exportEvents( $eids, $exportDetail, $exportFrames, $exportImages, $expo
{ {
$archive = ZM_DIR_EXPORTS."/".$export_root.".tar.gz"; $archive = ZM_DIR_EXPORTS."/".$export_root.".tar.gz";
@unlink( $archive ); @unlink( $archive );
$command = "tar --create --gzip --file=$archive --files-from=$listFile"; if ($exportStructure == 'flat') { //strip file paths if we choose
exec( escapeshellcmd( $command ), $output, $status ); $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 ) if ( $status )
{ {
Error( "Command '$command' returned with status $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"; $archive = ZM_DIR_EXPORTS."/".$export_root.".zip";
@unlink( $archive ); @unlink( $archive );
if ($exportStructure == 'flat') {
$command = "cat ".escapeshellarg($listFile)." | zip -q -j ".escapeshellarg($archive)." -@";
} else {
$command = "cat ".escapeshellarg($listFile)." | zip -q ".escapeshellarg($archive)." -@"; $command = "cat ".escapeshellarg($listFile)." | zip -q ".escapeshellarg($archive)." -@";
}
//cat zmFileList.txt | zip -q zm_export.zip -@ //cat zmFileList.txt | zip -q zm_export.zip -@
//-bash: zip: command not found //-bash: zip: command not found

View File

@ -159,26 +159,29 @@ if ( file_exists( "skins/$skin/css/$css/graphics/favicon.ico" ) ) {
<?php <?php
} // end function xhtmlHeaders( $file, $title ) } // end function xhtmlHeaders( $file, $title )
function getNavBarHTML() { function getNavBarHTML($reload = null) {
$versionClass = (ZM_DYN_DB_VERSION&&(ZM_DYN_DB_VERSION!=ZM_VERSION))?'errorText':''; $versionClass = (ZM_DYN_DB_VERSION&&(ZM_DYN_DB_VERSION!=ZM_VERSION))?'errorText':'';
ob_start();
global $running; global $running;
if ( $running == null )
$running = daemonCheck();
$status = $running?translate('Running'):translate('Stopped');
global $user; global $user;
global $bandwidth_options; global $bandwidth_options;
global $view; 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> <noscript>
<div style="background-color:red;color:white;font-size:x-large;"> <div style="background-color:red;color:white;font-size:x-large;">
ZoneMinder requires Javascript. Please enable Javascript in your browser for this site. ZoneMinder requires Javascript. Please enable Javascript in your browser for this site.
</div> </div>
</noscript> </noscript>
<div class="navbar navbar-inverse navbar-static-top"> <div class="navbar navbar-inverse navbar-static-top">
<div class="container-fluid"> <div class="container-fluid">
<div class="navbar-header"> <div class="navbar-header">
@ -212,7 +215,7 @@ if ( ZM_OPT_X10 && canView( 'Devices' ) ) { ?>
<li><a href="?view=devices">Devices</a></li> <li><a href="?view=devices">Devices</a></li>
<?php } ?> <?php } ?>
<li><a href="?view=groups"<?php echo $view=='groups'?' class="selected"':''?>><?php echo translate('Groups') ?></a></li> <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 <?php
if ( canView( 'Stream' ) ) { 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> <li><a href="?view=montage"<?php echo $view=='montage'?' class="selected"':''?>><?php echo translate('Montage') ?></a></li>
<?php <?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') ) { 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 <?php
} }
?> ?>
@ -243,7 +260,11 @@ if ( ZM_OPT_X10 && canView( 'Devices' ) ) { ?>
</div> </div>
</div><!-- End .navbar-collapse --> </div><!-- End .navbar-collapse -->
</div> <!-- End .container-fluid --> </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"> <div class="pull-left">
<?php echo makePopupLink( '?view=bandwidth', 'zmBandwidth', 'bandwidth', $bandwidth_options[$_COOKIE['zmBandwidth']] . ' ' . translate('BandwidthHead'), ($user && $user['MaxBandwidth'] != 'low' ) ) ?> <?php echo makePopupLink( '?view=bandwidth', 'zmBandwidth', 'bandwidth', $bandwidth_options[$_COOKIE['zmBandwidth']] . ' ' . translate('BandwidthHead'), ($user && $user['MaxBandwidth'] != 'low' ) ) ?>
</div> </div>
@ -277,9 +298,11 @@ if ( ZM_OPT_X10 && canView( 'Devices' ) ) { ?>
echo ' ' . ZM_PATH_MAP .': '. getDiskPercent(ZM_PATH_MAP).'%'; echo ' ' . ZM_PATH_MAP .': '. getDiskPercent(ZM_PATH_MAP).'%';
?></li> ?></li>
</ul> </ul>
</div> <!-- End .footer --> </div> <!-- End .footer/reload -->
<?php
</div> <!-- End .navbar .navbar-default --> if ($reload == 'reload') return( ob_get_clean() );
?>
</div><!-- End .navbar .navbar-default -->
<?php <?php
return( ob_get_clean() ); return( ob_get_clean() );
} // end function getNavBarHTML() } // end function getNavBarHTML()

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