Merge branch 'master' into fix_use_of_sprintf
This commit is contained in:
commit
c6e0b9be39
|
@ -188,6 +188,8 @@ set(ZM_NO_MMAP "OFF" CACHE BOOL
|
|||
experience problems with the shared memory. default: OFF")
|
||||
set(ZM_NO_LIBVLC "OFF" CACHE BOOL
|
||||
"Set to ON to skip libvlc checks and force building ZM without libvlc. default: OFF")
|
||||
set(ZM_NO_LIBVNC "OFF" CACHE BOOL
|
||||
"Set to ON to skip libvnc checks and force building ZM without libvnc. default: OFF")
|
||||
set(ZM_NO_CURL "OFF" CACHE BOOL
|
||||
"Set to ON to skip cURL checks and force building ZM without cURL. default: OFF")
|
||||
set(ZM_NO_X10 "OFF" CACHE BOOL
|
||||
|
@ -553,6 +555,7 @@ if(AVCODEC_LIBRARIES)
|
|||
check_include_file("libavcodec/avcodec.h" HAVE_LIBAVCODEC_AVCODEC_H)
|
||||
set(optlibsfound "${optlibsfound} AVCodec")
|
||||
else(AVCODEC_LIBRARIES)
|
||||
message(WARNING "\nWhile it should be possible to build ZM without AVCODEC the result will pretty useless.")
|
||||
set(optlibsnotfound "${optlibsnotfound} AVCodec")
|
||||
endif(AVCODEC_LIBRARIES)
|
||||
|
||||
|
@ -674,6 +677,25 @@ if(NOT ZM_NO_LIBVLC)
|
|||
endif(LIBVLC_LIBRARIES)
|
||||
endif(NOT ZM_NO_LIBVLC)
|
||||
|
||||
if(NOT ZM_NO_LIBVNC)
|
||||
# libvncclient (using find_library and find_path)
|
||||
find_library(LIBVNC_LIBRARIES vncclient)
|
||||
if(LIBVNC_LIBRARIES)
|
||||
set(HAVE_LIBVNC 1)
|
||||
list(APPEND ZM_BIN_LIBS "${LIBVNC_LIBRARIES}")
|
||||
find_path(LIBVNC_INCLUDE_DIR "rfb/rfb.h")
|
||||
if(LIBVNC_INCLUDE_DIR)
|
||||
include_directories("${LIBVNC_INCLUDE_DIR}")
|
||||
set(CMAKE_REQUIRED_INCLUDES "${LIBVNC_INCLUDE_DIR}")
|
||||
endif(LIBVNC_INCLUDE_DIR)
|
||||
mark_as_advanced(FORCE LIBVNC_LIBRARIES LIBVNC_INCLUDE_DIR)
|
||||
check_include_file("rfb/rfb.h" HAVE_RFB_RFB_H)
|
||||
set(optlibsfound "${optlibsfound} libVNC")
|
||||
else(LIBVNC_LIBRARIES)
|
||||
set(optlibsnotfound "${optlibsnotfound} libVNC")
|
||||
endif(LIBVNC_LIBRARIES)
|
||||
endif(NOT ZM_NO_LIBVNC)
|
||||
|
||||
#find_package(Boost 1.36.0)
|
||||
#if(Boost_FOUND)
|
||||
#include_directories(${Boost_INCLUDE_DIRS})
|
||||
|
@ -908,7 +930,7 @@ message(STATUS "Optional libraries not found:${optlibsnotfound}")
|
|||
|
||||
# Run ZM configuration generator
|
||||
message(STATUS "Running ZoneMinder configuration generator")
|
||||
execute_process(COMMAND perl ./zmconfgen.pl RESULT_VARIABLE zmconfgen_result)
|
||||
execute_process(COMMAND perl ${CMAKE_CURRENT_BINARY_DIR}/zmconfgen.pl RESULT_VARIABLE zmconfgen_result)
|
||||
if(zmconfgen_result EQUAL 0)
|
||||
message(STATUS
|
||||
"ZoneMinder configuration generator completed successfully")
|
||||
|
|
|
@ -63,7 +63,7 @@ DROP TABLE IF EXISTS `Controls`;
|
|||
CREATE TABLE `Controls` (
|
||||
`Id` int(10) unsigned NOT NULL auto_increment,
|
||||
`Name` varchar(64) NOT NULL default '',
|
||||
`Type` enum('Local','Remote','File','Ffmpeg','Libvlc','cURL','WebSite','NVSocket') NOT NULL default 'Local',
|
||||
`Type` enum('Local','Remote','File','Ffmpeg','Libvlc','cURL','WebSite','NVSocket','VNC') NOT NULL default 'Local',
|
||||
`Protocol` varchar(64) default NULL,
|
||||
`CanWake` tinyint(3) unsigned NOT NULL default '0',
|
||||
`CanSleep` tinyint(3) unsigned NOT NULL default '0',
|
||||
|
@ -287,6 +287,9 @@ CREATE TABLE `Filters` (
|
|||
`AutoVideo` tinyint(3) unsigned NOT NULL default '0',
|
||||
`AutoUpload` tinyint(3) unsigned NOT NULL default '0',
|
||||
`AutoEmail` tinyint(3) unsigned NOT NULL default '0',
|
||||
`EmailTo` TEXT,
|
||||
`EmailSubject` TEXT,
|
||||
`EmailBody` TEXT,
|
||||
`AutoMessage` tinyint(3) unsigned NOT NULL default '0',
|
||||
`AutoExecute` tinyint(3) unsigned NOT NULL default '0',
|
||||
`AutoExecuteCmd` tinytext,
|
||||
|
@ -403,7 +406,7 @@ DROP TABLE IF EXISTS `MonitorPresets`;
|
|||
CREATE TABLE `MonitorPresets` (
|
||||
`Id` int(10) unsigned NOT NULL auto_increment,
|
||||
`Name` varchar(64) NOT NULL default '',
|
||||
`Type` enum('Local','Remote','File','Ffmpeg','Libvlc','cURL','WebSite','NVSocket') NOT NULL default 'Local',
|
||||
`Type` enum('Local','Remote','File','Ffmpeg','Libvlc','cURL','WebSite','NVSocket','VNC') NOT NULL default 'Local',
|
||||
`Device` tinytext,
|
||||
`Channel` tinyint(3) unsigned default NULL,
|
||||
`Format` int(10) unsigned default NULL,
|
||||
|
@ -437,7 +440,7 @@ CREATE TABLE `Monitors` (
|
|||
`Notes` TEXT,
|
||||
`ServerId` int(10) unsigned,
|
||||
`StorageId` smallint(5) unsigned default 0,
|
||||
`Type` enum('Local','Remote','File','Ffmpeg','Libvlc','cURL','WebSite','NVSocket') NOT NULL default 'Local',
|
||||
`Type` enum('Local','Remote','File','Ffmpeg','Libvlc','cURL','WebSite','NVSocket','VNC') NOT NULL default 'Local',
|
||||
`Function` enum('None','Monitor','Modect','Record','Mocord','Nodect') NOT NULL default 'Monitor',
|
||||
`Enabled` tinyint(3) unsigned NOT NULL default '1',
|
||||
`LinkedMonitors` varchar(255),
|
||||
|
@ -730,13 +733,14 @@ CREATE TABLE `Storage` (
|
|||
`Scheme` enum('Deep','Medium','Shallow') NOT NULL default 'Medium',
|
||||
`ServerId` int(10) unsigned,
|
||||
`DoDelete` BOOLEAN NOT NULL DEFAULT true,
|
||||
`Enabled` BOOLEAN NOT NULL DEFAULT true,
|
||||
PRIMARY KEY (`Id`)
|
||||
) ENGINE=@ZM_MYSQL_ENGINE@;
|
||||
|
||||
--
|
||||
-- Create a default storage location
|
||||
--
|
||||
insert into Storage VALUES (NULL, '@ZM_DIR_EVENTS@', 'Default', 'local', NULL, NULL, 'Medium', 0, true );
|
||||
insert into Storage VALUES (NULL, '@ZM_DIR_EVENTS@', 'Default', 'local', NULL, NULL, 'Medium', 0, true, true );
|
||||
|
||||
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
||||
|
@ -759,18 +763,91 @@ insert into Users VALUES (NULL,'admin','$2b$12$NHZsm6AM2f2LQVROriz79ul3D6DnmFiZC
|
|||
-- Add a sample filter to purge the oldest 100 events when the disk is 95% full
|
||||
--
|
||||
|
||||
insert into Filters values (NULL,'PurgeWhenFull','{"sort_field":"Id","terms":[{"val":0,"attr":"Archived","op":"="},{"cnj":"and","val":95,"attr":"DiskPercent","op":">="}],"limit":100,"sort_asc":1}',
|
||||
INSERT INTO `Filters`
|
||||
(
|
||||
`Name`,
|
||||
`Query_json`,
|
||||
`AutoArchive`,
|
||||
`AutoVideo`,
|
||||
`AutoUpload`,
|
||||
`AutoEmail`,
|
||||
`EmailTo`,
|
||||
`EmailSubject`,
|
||||
`EmailBody`,
|
||||
`AutoMessage`,
|
||||
`AutoExecute`,
|
||||
`AutoExecuteCmd`,
|
||||
`AutoDelete`,
|
||||
`AutoMove`,
|
||||
`AutoMoveTo`,
|
||||
`AutoCopy`,
|
||||
`AutoCopyTo`,
|
||||
`UpdateDiskSpace`,
|
||||
`Background`,
|
||||
`Concurrent`
|
||||
)
|
||||
VALUES
|
||||
(
|
||||
'PurgeWhenFull',
|
||||
'{"sort_field":"Id","terms":[{"val":0,"attr":"Archived","op":"="},{"cnj":"and","val":95,"attr":"DiskPercent","op":">="}],"limit":100,"sort_asc":1}',
|
||||
0/*AutoArchive*/,
|
||||
0/*AutoVideo*/,
|
||||
0/*AutoUpload*/,
|
||||
0/*AutoEmail*/,
|
||||
''/*EmailTo*/,
|
||||
''/*EmailSubject*/,
|
||||
''/*EmailBody*/,
|
||||
0/*AutoMessage*/,
|
||||
0/*AutoExecute*/,'',
|
||||
1/*AutoDelete*/,
|
||||
0/*AutoMove*/,0/*MoveTo*/,
|
||||
0/*AutoCopy*/,0/*CopyTo*/,
|
||||
0/*UpdateDiskSpace*/,
|
||||
1/*Background*/,
|
||||
0/*Concurrent*/
|
||||
);
|
||||
INSERT INTO `Filters`
|
||||
(
|
||||
`Name`,
|
||||
`Query_json`,
|
||||
`AutoArchive`,
|
||||
`AutoVideo`,
|
||||
`AutoUpload`,
|
||||
`AutoEmail`,
|
||||
`EmailTo`,
|
||||
`EmailSubject`,
|
||||
`EmailBody`,
|
||||
`AutoMessage`,
|
||||
`AutoExecute`,
|
||||
`AutoExecuteCmd`,
|
||||
`AutoDelete`,
|
||||
`AutoMove`,
|
||||
`AutoMoveTo`,
|
||||
`AutoCopy`,
|
||||
`AutoCopyTo`,
|
||||
`UpdateDiskSpace`,
|
||||
`Background`,
|
||||
`Concurrent`
|
||||
)
|
||||
VALUES (
|
||||
'Update DiskSpace',
|
||||
'{"terms":[{"attr":"DiskSpace","op":"IS","val":"NULL"}]}',
|
||||
0/*AutoArchive*/,
|
||||
0/*AutoVideo*/,
|
||||
0/*AutoUpload*/,
|
||||
0/*AutoEmail*/,
|
||||
''/*EmailTo*/,
|
||||
''/*EmailSubject*/,
|
||||
''/*EmailBody*/,
|
||||
0/*AutoMessage*/,
|
||||
0/*AutoExecute*/,'',
|
||||
1/*AutoDelete*/,
|
||||
0/*AutoDelete*/,
|
||||
0/*AutoMove*/,0/*MoveTo*/,
|
||||
0/*AutoCopy*/,0/*CopyTo*/,
|
||||
0/*UpdateDiskSpace*/,1/*Background*/,0/*Concurrent*/);
|
||||
insert into Filters values (NULL,'Update DiskSpace','{"terms":[{"attr":"DiskSpace","op":"IS","val":"NULL"}]}',0,0,0,0,0,0,'',0,0,0,0,0,1,1,0);
|
||||
1/*UpdateDiskSpace*/,
|
||||
1/*Background*/,
|
||||
0/*Concurrent*/
|
||||
);
|
||||
|
||||
--
|
||||
-- Add in some sample control protocol definitions
|
||||
|
@ -820,6 +897,9 @@ INSERT INTO `Controls` VALUES (NULL,'Amcrest HTTP API','Ffmpeg','Amcrest_HTTP',0
|
|||
--
|
||||
-- Add some monitor preset values
|
||||
--
|
||||
|
||||
INSERT into MonitorPresets VALUES (NULL,'Amcrest, IP8M-T2499EW 640x480, RTP/RTSP','Ffmpeg','rtsp',0,255,'rtsp','rtpRtsp','NULL',554,'rtsp://<username>:<password>@<ip-address>/cam/realmonitor?channel=1&subtype=1',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT into MonitorPresets VALUES (NULL,'Amcrest, IP8M-T2499EW 3840x2160, RTP/RTSP','Ffmpeg','rtsp',0,255,'rtsp','rtpRtsp','NULL',554,'rtsp://<username>:<password>@<ip-address>/cam/realmonitor?channel=1&subtype=0',NULL,3840,2160,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Axis IP, 320x240, mpjpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Axis IP, 320x240, mpjpeg, max 5 FPS','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240&req_fps=5',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Axis IP, 320x240, jpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/jpg/image.cgi?resolution=320x240',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
|
||||
AND table_name = 'Filters'
|
||||
AND column_name = 'EmailTo'
|
||||
) > 0,
|
||||
"SELECT 'Column EmailTo already exists in Filters'",
|
||||
"ALTER TABLE `Filters` ADD `EmailTo` TEXT AFTER `AutoEmail`"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
|
||||
UPDATE Filters SET EmailTo=(SELECT Value FROM Config WHERE Name='ZM_EMAIL_ADDRESS') WHERE AutoEmail=1;
|
||||
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
|
||||
AND table_name = 'Filters'
|
||||
AND column_name = 'EmailSubject'
|
||||
) > 0,
|
||||
"SELECT 'Column EmailSubject already exists in Filters'",
|
||||
"ALTER TABLE `Filters` ADD `EmailSubject` TEXT AFTER `EmailTo`"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
|
||||
UPDATE Filters SET EmailSubject=(SELECT Value FROM Config WHERE Name='ZM_EMAIL_SUBJECT') WHERE AutoEmail=1;
|
||||
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
|
||||
AND table_name = 'Filters'
|
||||
AND column_name = 'EmailBody'
|
||||
) > 0,
|
||||
"SELECT 'Column EmailBody already exists in Filters'",
|
||||
"ALTER TABLE `Filters` ADD `EmailBody` TEXT AFTER `EmailSubject`"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
|
||||
UPDATE Filters SET EmailBody=(SELECT Value FROM Config WHERE Name='ZM_EMAIL_BODY') WHERE AutoEmail=1;
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
|
||||
AND table_name = 'Storage'
|
||||
AND column_name = 'Enabled'
|
||||
) > 0,
|
||||
"SELECT 'Column Enabled already exists in Storage'",
|
||||
"ALTER TABLE `Storage` ADD `Enabled` BOOLEAN NOT NULL default true AFTER `DoDelete`"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE Monitors MODIFY `Type` enum('Local','Remote','File','Ffmpeg','Libvlc','cURL','NVSocket','VNC') NOT NULL default 'Local';
|
|
@ -28,7 +28,7 @@
|
|||
%global _hardened_build 1
|
||||
|
||||
Name: zoneminder
|
||||
Version: 1.34.9
|
||||
Version: 1.35.2
|
||||
Release: 1%{?dist}
|
||||
Summary: A camera monitoring and analysis tool
|
||||
Group: System Environment/Daemons
|
||||
|
|
|
@ -33,6 +33,7 @@ Build-Depends: debhelper (>= 9), dh-systemd, python-sphinx | python3-sphinx, apa
|
|||
,libssl-dev
|
||||
,libcrypt-eksblowfish-perl
|
||||
,libdata-entropy-perl
|
||||
,libvncserver-dev
|
||||
# Unbundled (dh_linktree):
|
||||
,libjs-jquery
|
||||
,libjs-mootools
|
||||
|
@ -82,6 +83,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
|
|||
,libssl | libssl1.0.0 | libssl1.1
|
||||
,libcrypt-eksblowfish-perl
|
||||
,libdata-entropy-perl
|
||||
,libvncclient1
|
||||
Recommends: ${misc:Recommends}
|
||||
,libapache2-mod-php5 | libapache2-mod-php | php5-fpm | php-fpm
|
||||
,mysql-server | mariadb-server | virtual-mysql-server
|
||||
|
|
|
@ -482,6 +482,7 @@ Create a Zone
|
|||
&Zone[Units]=Percent\
|
||||
&Zone[NumCoords]=4\
|
||||
&Zone[Coords]=0,0 639,0 639,479 0,479\
|
||||
&Zone[Area]=307200\
|
||||
&Zone[AlarmRGB]=16711680\
|
||||
&Zone[CheckMethod]=Blobs\
|
||||
&Zone[MinPixelThreshold]=25\
|
||||
|
|
|
@ -68,9 +68,13 @@ Here is what the filter window looks like
|
|||
* %ESM% Maximum score of the event
|
||||
* %EP% Path to the event
|
||||
* %EPS% Path to the event stream
|
||||
* %EPF1% Path to the frame view for the first alarmed event image
|
||||
* %EPFM% Path to the frame view for the (first) event image with the highest score
|
||||
* %EFMOD% Path to image containing object detection, in frame view
|
||||
* %EPI% Path to the event images
|
||||
* %EPI1% Path to the first alarmed event image
|
||||
* %EPIM% Path to the (first) event image with the highest score
|
||||
* %EPI1% Path to the first alarmed event image, suitable for use in img tags
|
||||
* %EPIM% Path to the (first) event image with the highest score, suitable for use in img tags
|
||||
* %EIMOD% Path to image containing object detection, suitable for use in img tags
|
||||
* %EI1% Attach first alarmed event image
|
||||
* %EIM% Attach (first) event image with the highest score
|
||||
* %EV% Attach event mpeg video
|
||||
|
@ -81,7 +85,6 @@ Here is what the filter window looks like
|
|||
* %MEW% Number of events for the monitor in the last week
|
||||
* %MEM% Number of events for the monitor in the last month
|
||||
* %MEA% Number of archived events for the monitor
|
||||
* %MOD% Path to image containing object detection
|
||||
* %MP% Path to the monitor window
|
||||
* %MPS% Path to the monitor stream
|
||||
* %MPI% Path to the monitor recent image
|
||||
|
|
|
@ -43,7 +43,7 @@ my %message_of :ATTR(:name<message> :default<()>);
|
|||
my %is_success_of :ATTR(:name<is_success> :default<()>);
|
||||
|
||||
my %local_addr_of :ATTR(:name<local_addr> :init_arg<local_addr> :default<()>);
|
||||
|
||||
my $net_interface;
|
||||
|
||||
# create methods normally inherited from SOAP::Client
|
||||
SUBFACTORY: {
|
||||
|
@ -60,14 +60,22 @@ sub _notify_response
|
|||
|
||||
}
|
||||
|
||||
sub set_net_interface {
|
||||
my $self = shift;
|
||||
$net_interface = shift;
|
||||
}
|
||||
|
||||
sub send_multi() {
|
||||
my ($self, $address, $port, $utf8_string) = @_;
|
||||
|
||||
my $destination = $address . ':' . $port;
|
||||
my $socket = IO::Socket::Multicast->new(PROTO => 'udp',
|
||||
LocalPort=>$port, PeerAddr=>$destination, ReuseAddr=>1)
|
||||
|
||||
or die 'Cannot open multicast socket to ' . ${address} . ':' . ${port};
|
||||
my $socket = IO::Socket::Multicast->new(
|
||||
PROTO => 'udp',
|
||||
LocalPort=>$port,
|
||||
PeerAddr=>$destination,
|
||||
ReuseAddr=>1
|
||||
) or die 'Cannot open multicast socket to ' . ${address} . ':' . ${port};
|
||||
$_ = $socket->mcast_if($net_interface) if $net_interface;
|
||||
|
||||
my $bytes = $utf8_string;
|
||||
utf8::encode($bytes);
|
||||
|
@ -80,14 +88,16 @@ sub receive_multi() {
|
|||
my ($self, $address, $port) = @_;
|
||||
my $data = undef;
|
||||
|
||||
my $socket = IO::Socket::Multicast->new(PROTO => 'udp',
|
||||
LocalPort=>$port, ReuseAddr=>1);
|
||||
$socket->mcast_add($address);
|
||||
my $socket = IO::Socket::Multicast->new(
|
||||
PROTO => 'udp',
|
||||
LocalPort=>$port,
|
||||
ReuseAddr=>1);
|
||||
$socket->mcast_add($address, $net_interface);
|
||||
|
||||
my $readbits = '';
|
||||
vec($readbits, $socket->fileno, 1) = 1;
|
||||
|
||||
if(select($readbits, undef, undef, WAIT_TIME/1000)) {
|
||||
if ( select($readbits, undef, undef, WAIT_TIME/1000) ) {
|
||||
$socket->recv($data, 9999);
|
||||
return $data;
|
||||
}
|
||||
|
@ -98,15 +108,19 @@ sub receive_uni() {
|
|||
my ($self, $address, $port, $localaddr) = @_;
|
||||
my $data = undef;
|
||||
|
||||
my $socket = IO::Socket::Multicast->new(PROTO => 'udp',
|
||||
LocalAddr => $localaddr, LocalPort=>$port, ReuseAddr=>1);
|
||||
my $socket = IO::Socket::Multicast->new(
|
||||
PROTO => 'udp',
|
||||
LocalAddr => $localaddr,
|
||||
LocalPort=>$port,
|
||||
ReuseAddr=>1
|
||||
);
|
||||
|
||||
$socket->mcast_add($address);
|
||||
$socket->mcast_add($address, $net_interface);
|
||||
|
||||
my $readbits = '';
|
||||
vec($readbits, $socket->fileno, 1) = 1;
|
||||
|
||||
if(select($readbits, undef, undef, WAIT_TIME/1000)) {
|
||||
if ( select($readbits, undef, undef, WAIT_TIME/1000) ) {
|
||||
$socket->recv($data, 9999);
|
||||
return $data;
|
||||
}
|
||||
|
@ -114,50 +128,51 @@ sub receive_uni() {
|
|||
}
|
||||
|
||||
sub send_receive {
|
||||
my ($self, %parameters) = @_;
|
||||
my ($envelope, $soap_action, $endpoint, $encoding, $content_type) =
|
||||
@parameters{qw(envelope action endpoint encoding content_type)};
|
||||
my ($self, %parameters) = @_;
|
||||
my ($envelope, $soap_action, $endpoint, $encoding, $content_type) =
|
||||
@parameters{qw(envelope action endpoint encoding content_type)};
|
||||
|
||||
my ($address,$port) = ($endpoint =~ /([^:\/]+):([0-9]+)/);
|
||||
my ($address,$port) = ($endpoint =~ /([^:\/]+):([0-9]+)/);
|
||||
|
||||
#warn "address = ${address}";
|
||||
#warn "port = ${port}";
|
||||
#warn "address = ${address}";
|
||||
#warn "port = ${port}";
|
||||
|
||||
$self->send_multi($address, $port, $envelope);
|
||||
$self->send_multi($address, $port, $envelope);
|
||||
|
||||
my $localaddr = $self->get_local_addr();
|
||||
my $localaddr = $self->get_local_addr();
|
||||
#warn "localddr $localaddr";
|
||||
|
||||
my ($response, $last_response);
|
||||
my $wait = WAIT_COUNT;
|
||||
while ( $wait >= 0 ) {
|
||||
if($localaddr) {
|
||||
if($response = $self->receive_uni($address, $port, $localaddr)) {
|
||||
$last_response = $response;
|
||||
$self->_notify_response($response);
|
||||
}
|
||||
$wait --;
|
||||
}
|
||||
if($response = $self->receive_multi($address, $port)) {
|
||||
$last_response = $response;
|
||||
$self->_notify_response($response);
|
||||
}
|
||||
$wait --;
|
||||
}
|
||||
|
||||
if($last_response) {
|
||||
$self->set_code();
|
||||
$self->set_message("");
|
||||
$self->set_is_success(1);
|
||||
$self->set_status('OK');
|
||||
}
|
||||
else{
|
||||
$self->set_code();
|
||||
$self->set_message("Timed out waiting for response");
|
||||
$self->set_is_success(0);
|
||||
$self->set_status('TIMEOUT');
|
||||
}
|
||||
my ($response, $last_response);
|
||||
my $wait = WAIT_COUNT;
|
||||
while ( $wait >= 0 ) {
|
||||
if ( $localaddr ) {
|
||||
if ( $response = $self->receive_uni($address, $port, $localaddr) ) {
|
||||
$last_response = $response;
|
||||
$self->_notify_response($response);
|
||||
}
|
||||
$wait --;
|
||||
}
|
||||
if ( $response = $self->receive_multi($address, $port) ) {
|
||||
$last_response = $response;
|
||||
$self->_notify_response($response);
|
||||
}
|
||||
$wait --;
|
||||
}
|
||||
|
||||
return $last_response;
|
||||
if ( $last_response ) {
|
||||
$self->set_code();
|
||||
$self->set_message('');
|
||||
$self->set_is_success(1);
|
||||
$self->set_status('OK');
|
||||
} else {
|
||||
$self->set_code();
|
||||
$self->set_message('Timed out waiting for response');
|
||||
$self->set_is_success(0);
|
||||
$self->set_status('TIMEOUT');
|
||||
}
|
||||
|
||||
return $last_response;
|
||||
}
|
||||
|
||||
1;
|
||||
__END__
|
||||
|
|
|
@ -2213,7 +2213,7 @@ our @options = (
|
|||
that match the appropriate filters will be sent to.
|
||||
`,
|
||||
type => $types{email},
|
||||
category => 'mail',
|
||||
category => 'hidden',
|
||||
},
|
||||
{
|
||||
name => 'ZM_EMAIL_TEXT',
|
||||
|
@ -2253,7 +2253,7 @@ our @options = (
|
|||
sent for any events that match the appropriate filters.
|
||||
`,
|
||||
type => $types{string},
|
||||
category => 'mail',
|
||||
category => 'hidden',
|
||||
},
|
||||
{
|
||||
name => 'ZM_EMAIL_BODY',
|
||||
|
@ -2280,7 +2280,7 @@ our @options = (
|
|||
sent for any events that match the appropriate filters.
|
||||
`,
|
||||
type => $types{text},
|
||||
category => 'mail',
|
||||
category => 'hidden',
|
||||
},
|
||||
{
|
||||
name => 'ZM_OPT_MESSAGE',
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# ==========================================================================
|
||||
#
|
||||
# ZoneMinder Base Control Module, $Date$, $Revision$
|
||||
# ZoneMinder Base Control Module
|
||||
# Copyright (C) 2001-2008 Philip Coombes
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
|
@ -46,13 +46,13 @@ our $AUTOLOAD;
|
|||
sub new {
|
||||
my $class = shift;
|
||||
my $id = shift;
|
||||
if ( !defined($id) ) {
|
||||
Fatal('No monitor defined when invoking protocol '.$class);
|
||||
}
|
||||
my $self = {};
|
||||
$self->{name} = $class;
|
||||
if ( !defined($id) ) {
|
||||
Fatal('No monitor defined when invoking protocol '.$self->{name});
|
||||
}
|
||||
$self->{id} = $id;
|
||||
bless( $self, $class );
|
||||
bless($self, $class);
|
||||
return $self;
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,7 @@ sub AUTOLOAD {
|
|||
|
||||
sub getKey {
|
||||
my $self = shift;
|
||||
return( $self->{id} );
|
||||
return $self->{id};
|
||||
}
|
||||
|
||||
sub open {
|
||||
|
|
|
@ -46,243 +46,187 @@ use ZoneMinder::Config qw(:all);
|
|||
|
||||
use Time::HiRes qw( usleep );
|
||||
|
||||
sub new
|
||||
{
|
||||
my $class = shift;
|
||||
my $id = shift;
|
||||
my $self = ZoneMinder::Control->new( $id );
|
||||
bless( $self, $class );
|
||||
srand( time() );
|
||||
return $self;
|
||||
sub open {
|
||||
my $self = shift;
|
||||
|
||||
$self->loadMonitor();
|
||||
|
||||
use LWP::UserAgent;
|
||||
$self->{ua} = LWP::UserAgent->new;
|
||||
$self->{ua}->agent('ZoneMinder Control Agent/' . ZoneMinder::Base::ZM_VERSION);
|
||||
$self->{state} = 'open';
|
||||
}
|
||||
|
||||
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" );
|
||||
sub close {
|
||||
my $self = shift;
|
||||
$self->{state} = 'closed';
|
||||
}
|
||||
|
||||
sub open
|
||||
{
|
||||
my $self = shift;
|
||||
sub sendCmd {
|
||||
my $self = shift;
|
||||
my $cmd = shift;
|
||||
my $cgi = shift;
|
||||
|
||||
$self->loadMonitor();
|
||||
my $result = undef;
|
||||
|
||||
use LWP::UserAgent;
|
||||
$self->{ua} = LWP::UserAgent->new;
|
||||
$self->{ua}->agent( "ZoneMinder Control Agent/" . ZoneMinder::Base::ZM_VERSION );
|
||||
$self->{state} = 'open';
|
||||
printMsg($cmd, 'Tx');
|
||||
|
||||
my $req = HTTP::Request->new( POST=>"http://$self->{Monitor}->{ControlAddress}/$cgi.cgi" );
|
||||
$req->content($cmd);
|
||||
my $res = $self->{ua}->request($req);
|
||||
|
||||
if ( $res->is_success ) {
|
||||
$result = !undef;
|
||||
} else {
|
||||
Error("Error check failed: '".$res->status_line()."'");
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
sub close
|
||||
{
|
||||
my $self = shift;
|
||||
$self->{state} = 'closed';
|
||||
sub move {
|
||||
my $self = shift;
|
||||
my $dir = shift;
|
||||
my $panStep = shift;
|
||||
my $tiltStep = shift;
|
||||
my $cmd = "PanSingleMoveDegree=$panStep&TiltSingleMoveDegree=$tiltStep&PanTiltSingleMove=$dir";
|
||||
$self->sendCmd($cmd, 'pantiltcontrol');
|
||||
}
|
||||
|
||||
sub printMsg
|
||||
{
|
||||
my $self = shift;
|
||||
my $msg = shift;
|
||||
my $msg_len = length($msg);
|
||||
|
||||
Debug( $msg."[".$msg_len."]" );
|
||||
sub moveRel {
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
my $panStep = $self->getParam($params, 'panstep', 0);
|
||||
my $tiltStep = $self->getParam($params, 'tiltstep', 0);
|
||||
my $dir = shift;
|
||||
$self->move( $dir, $panStep, $tiltStep );
|
||||
}
|
||||
|
||||
sub sendCmd
|
||||
{
|
||||
my $self = shift;
|
||||
my $cmd = shift;
|
||||
my $cgi = shift;
|
||||
|
||||
my $result = undef;
|
||||
|
||||
printMsg( $cmd, "Tx" );
|
||||
|
||||
my $req = HTTP::Request->new( POST=>"http://$self->{Monitor}->{ControlAddress}/$cgi.cgi" );
|
||||
$req->content($cmd);
|
||||
my $res = $self->{ua}->request($req);
|
||||
|
||||
if ( $res->is_success )
|
||||
{
|
||||
$result = !undef;
|
||||
}
|
||||
else
|
||||
{
|
||||
Error( "Error check failed: '".$res->status_line()."'" );
|
||||
}
|
||||
|
||||
return( $result );
|
||||
sub moveRelUpLeft {
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
$self->moveRel($params, 0);
|
||||
}
|
||||
|
||||
sub move
|
||||
{
|
||||
my $self = shift;
|
||||
my $dir = shift;
|
||||
my $panStep = shift;
|
||||
my $tiltStep = shift;
|
||||
my $cmd = "PanSingleMoveDegree=$panStep&TiltSingleMoveDegree=$tiltStep&PanTiltSingleMove=$dir";
|
||||
$self->sendCmd( $cmd, 'pantiltcontrol' );
|
||||
sub moveRelUp {
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
$self->moveRel($params, 1);
|
||||
}
|
||||
|
||||
sub moveRel
|
||||
{
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
my $panStep = $self->getParam($params, 'panstep', 0);
|
||||
my $tiltStep = $self->getParam($params, 'tiltstep', 0);
|
||||
my $dir = shift;
|
||||
$self->move( $dir, $panStep, $tiltStep );
|
||||
sub moveRelUpRight {
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
$self->moveRel($params, 2);
|
||||
}
|
||||
|
||||
sub moveRelUpLeft
|
||||
{
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
$self->moveRel( $params, 0 );
|
||||
sub moveRelLeft {
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
$self->moveRel($params, 3);
|
||||
}
|
||||
|
||||
sub moveRelUp
|
||||
{
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
$self->moveRel( $params, 1 );
|
||||
sub moveRelRight {
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
$self->moveRel($params, 5);
|
||||
}
|
||||
|
||||
sub moveRelUpRight
|
||||
{
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
$self->moveRel( $params, 2 );
|
||||
sub moveRelDownLeft {
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
$self->moveRel($params, 6);
|
||||
}
|
||||
|
||||
sub moveRelLeft
|
||||
{
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
$self->moveRel( $params, 3 );
|
||||
sub moveRelDown {
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
$self->moveRel($params, 7);
|
||||
}
|
||||
|
||||
sub moveRelRight
|
||||
{
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
$self->moveRel( $params, 5 );
|
||||
}
|
||||
|
||||
sub moveRelDownLeft
|
||||
{
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
$self->moveRel( $params, 6 );
|
||||
}
|
||||
|
||||
sub moveRelDown
|
||||
{
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
$self->moveRel( $params, 7 );
|
||||
}
|
||||
|
||||
sub moveRelDownRight
|
||||
{
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
$self->moveRel( $params, 8 );
|
||||
sub moveRelDownRight {
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
$self->moveRel($params, 8);
|
||||
}
|
||||
|
||||
# moves the camera to center on the point that the user clicked on in the video image.
|
||||
# This isn't extremely accurate but good enough for most purposes
|
||||
sub moveMap
|
||||
{
|
||||
# if the camera moves too much or too little, try increasing or decreasing this value
|
||||
my $f = 11;
|
||||
sub moveMap {
|
||||
# if the camera moves too much or too little, try increasing or decreasing this value
|
||||
my $f = 11;
|
||||
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
my $xcoord = $self->getParam( $params, 'xcoord' );
|
||||
my $ycoord = $self->getParam( $params, 'ycoord' );
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
my $xcoord = $self->getParam( $params, 'xcoord' );
|
||||
my $ycoord = $self->getParam( $params, 'ycoord' );
|
||||
|
||||
my $hor = $xcoord * 100 / $self->{Monitor}->{Width};
|
||||
my $ver = $ycoord * 100 / $self->{Monitor}->{Height};
|
||||
|
||||
my $direction;
|
||||
my $horSteps;
|
||||
my $verSteps;
|
||||
if ($hor < 50 && $ver < 50) {
|
||||
# up left
|
||||
$horSteps = (50 - $hor) / $f;
|
||||
$verSteps = (50 - $ver) / $f;
|
||||
$direction = 0;
|
||||
} elsif ($hor >= 50 && $ver < 50) {
|
||||
# up right
|
||||
$horSteps = ($hor - 50) / $f;
|
||||
$verSteps = (50 - $ver) / $f;
|
||||
$direction = 2;
|
||||
} elsif ($hor < 50 && $ver >= 50) {
|
||||
# down left
|
||||
$horSteps = (50 - $hor) / $f;
|
||||
$verSteps = ($ver - 50) / $f;
|
||||
$direction = 6;
|
||||
} elsif ($hor >= 50 && $ver >= 50) {
|
||||
# down right
|
||||
$horSteps = ($hor - 50) / $f;
|
||||
$verSteps = ($ver - 50) / $f;
|
||||
$direction = 8;
|
||||
}
|
||||
my $v = int($verSteps + .5);
|
||||
my $h = int($horSteps + .5);
|
||||
Debug( "Move Map to $xcoord,$ycoord, hor=$h, ver=$v with direction $direction" );
|
||||
$self->move( $direction, $h, $v );
|
||||
my $hor = $xcoord * 100 / $self->{Monitor}->{Width};
|
||||
my $ver = $ycoord * 100 / $self->{Monitor}->{Height};
|
||||
|
||||
my $direction;
|
||||
my $horSteps;
|
||||
my $verSteps;
|
||||
if ($hor < 50 && $ver < 50) {
|
||||
# up left
|
||||
$horSteps = (50 - $hor) / $f;
|
||||
$verSteps = (50 - $ver) / $f;
|
||||
$direction = 0;
|
||||
} elsif ($hor >= 50 && $ver < 50) {
|
||||
# up right
|
||||
$horSteps = ($hor - 50) / $f;
|
||||
$verSteps = (50 - $ver) / $f;
|
||||
$direction = 2;
|
||||
} elsif ($hor < 50 && $ver >= 50) {
|
||||
# down left
|
||||
$horSteps = (50 - $hor) / $f;
|
||||
$verSteps = ($ver - 50) / $f;
|
||||
$direction = 6;
|
||||
} elsif ($hor >= 50 && $ver >= 50) {
|
||||
# down right
|
||||
$horSteps = ($hor - 50) / $f;
|
||||
$verSteps = ($ver - 50) / $f;
|
||||
$direction = 8;
|
||||
}
|
||||
my $v = int($verSteps + .5);
|
||||
my $h = int($horSteps + .5);
|
||||
Debug("Move Map to $xcoord,$ycoord, hor=$h, ver=$v with direction $direction");
|
||||
$self->move($direction, $h, $v);
|
||||
}
|
||||
|
||||
sub presetClear
|
||||
{
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
my $preset = $self->getParam( $params, 'preset' );
|
||||
Debug( "Clear Preset $preset" );
|
||||
my $cmd = "ClearPosition=$preset";
|
||||
$self->sendCmd( $cmd, 'pantiltcontrol' );
|
||||
sub presetClear {
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
my $preset = $self->getParam( $params, 'preset' );
|
||||
Debug( "Clear Preset $preset" );
|
||||
my $cmd = "ClearPosition=$preset";
|
||||
$self->sendCmd( $cmd, 'pantiltcontrol' );
|
||||
}
|
||||
|
||||
sub presetSet
|
||||
{
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
my $preset = $self->getParam( $params, 'preset' );
|
||||
Debug( "Set Preset $preset" );
|
||||
my $cmd = "SetCurrentPosition=$preset&SetName=preset_$preset";
|
||||
$self->sendCmd( $cmd, 'pantiltcontrol' );
|
||||
sub presetSet {
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
my $preset = $self->getParam( $params, 'preset' );
|
||||
Debug( "Set Preset $preset" );
|
||||
my $cmd = "SetCurrentPosition=$preset&SetName=preset_$preset";
|
||||
$self->sendCmd( $cmd, 'pantiltcontrol' );
|
||||
}
|
||||
|
||||
sub presetGoto
|
||||
{
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
my $preset = $self->getParam( $params, 'preset' );
|
||||
Debug( "Goto Preset $preset" );
|
||||
my $cmd = "PanTiltPresetPositionMove=$preset";
|
||||
$self->sendCmd( $cmd, 'pantiltcontrol' );
|
||||
sub presetGoto {
|
||||
my $self = shift;
|
||||
my $params = shift;
|
||||
my $preset = $self->getParam( $params, 'preset' );
|
||||
Debug( "Goto Preset $preset" );
|
||||
my $cmd = "PanTiltPresetPositionMove=$preset";
|
||||
$self->sendCmd( $cmd, 'pantiltcontrol' );
|
||||
}
|
||||
|
||||
sub presetHome
|
||||
{
|
||||
my $self = shift;
|
||||
Debug( "Home Preset" );
|
||||
$self->move( 4, 0, 0 );
|
||||
sub presetHome {
|
||||
my $self = shift;
|
||||
Debug( "Home Preset" );
|
||||
$self->move( 4, 0, 0 );
|
||||
}
|
||||
|
||||
|
||||
# IR Controls
|
||||
#
|
||||
# wake = IR on
|
||||
|
@ -290,40 +234,36 @@ sub presetHome
|
|||
# reset = IR auto
|
||||
|
||||
sub setDayNightMode {
|
||||
my $self = shift;
|
||||
my $mode = shift;
|
||||
my $cmd = "DayNightMode=$mode&ConfigReboot=No";
|
||||
$self->sendCmd( $cmd, 'daynight' );
|
||||
my $self = shift;
|
||||
my $mode = shift;
|
||||
my $cmd = "DayNightMode=$mode&ConfigReboot=No";
|
||||
$self->sendCmd($cmd, 'daynight');
|
||||
}
|
||||
|
||||
sub wake
|
||||
{
|
||||
my $self = shift;
|
||||
Debug( "Wake - IR on" );
|
||||
$self->setDayNightMode(2);
|
||||
sub wake {
|
||||
my $self = shift;
|
||||
Debug('Wake - IR on');
|
||||
$self->setDayNightMode(2);
|
||||
}
|
||||
|
||||
sub sleep
|
||||
{
|
||||
my $self = shift;
|
||||
Debug( "Sleep - IR off" );
|
||||
$self->setDayNightMode(3);
|
||||
sub sleep {
|
||||
my $self = shift;
|
||||
Debug('Sleep - IR off');
|
||||
$self->setDayNightMode(3);
|
||||
}
|
||||
|
||||
sub reset
|
||||
{
|
||||
my $self = shift;
|
||||
Debug( "Reset - IR auto" );
|
||||
$self->setDayNightMode(0);
|
||||
sub reset {
|
||||
my $self = shift;
|
||||
Debug('Reset - IR auto');
|
||||
$self->setDayNightMode(0);
|
||||
}
|
||||
|
||||
1;
|
||||
__END__
|
||||
# Below is stub documentation for your module. You'd better edit it!
|
||||
|
||||
=head1 NAME
|
||||
|
||||
ZoneMinder::Database - Perl extension for DCS-5020L
|
||||
ZoneMinder::Control::DCS5020L - Perl extension for DCS-5020L
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
|
@ -351,6 +291,20 @@ Art Scheel <lt>ascheel (at) gmail<gt>
|
|||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
LGPLv3
|
||||
Copyright (C) 2018 ZoneMinder LLC
|
||||
|
||||
This library 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 library 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.
|
||||
|
||||
=cut
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# ==========================================================================
|
||||
#
|
||||
# ZoneMinder Filter Module, $Date$, $Revision$
|
||||
# ZoneMinder Filter Module
|
||||
# Copyright (C) 2001-2008 Philip Coombes
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
|
@ -162,7 +162,9 @@ sub Sql {
|
|||
my $value = $term->{val};
|
||||
my @value_list;
|
||||
if ( $term->{attr} ) {
|
||||
if ( $term->{attr} =~ /^Monitor/ ) {
|
||||
if ( $term->{attr} eq 'AlarmedZoneId' ) {
|
||||
$term->{op} = 'EXISTS';
|
||||
} elsif ( $term->{attr} =~ /^Monitor/ ) {
|
||||
my ( $temp_attr_name ) = $term->{attr} =~ /^Monitor(.+)$/;
|
||||
$self->{Sql} .= 'M.'.$temp_attr_name;
|
||||
} elsif ( $term->{attr} eq 'ServerId' or $term->{attr} eq 'MonitorServerId' ) {
|
||||
|
@ -214,7 +216,10 @@ sub Sql {
|
|||
|
||||
( my $stripped_value = $value ) =~ s/^["\']+?(.+)["\']+?$/$1/;
|
||||
foreach my $temp_value ( split( /["'\s]*?,["'\s]*?/, $stripped_value ) ) {
|
||||
if ( $term->{attr} =~ /^MonitorName/ ) {
|
||||
|
||||
if ( $term->{attr} eq 'AlarmedZoneId' ) {
|
||||
$value = '(SELECT * FROM Stats WHERE EventId=E.Id AND ZoneId='.$value.')';
|
||||
} elsif ( $term->{attr} =~ /^MonitorName/ ) {
|
||||
$value = "'$temp_value'";
|
||||
} elsif ( $term->{attr} =~ /ServerId/) {
|
||||
Debug("ServerId, temp_value is ($temp_value) ($ZoneMinder::Config::Config{ZM_SERVER_ID})");
|
||||
|
@ -256,6 +261,8 @@ sub Sql {
|
|||
} elsif ( $term->{attr} eq 'Date' or $term->{attr} eq 'StartDate' or $term->{attr} eq 'EndDate' ) {
|
||||
if ( $temp_value eq 'NULL' ) {
|
||||
$value = $temp_value;
|
||||
} elsif ( $temp_value eq 'CURDATE()' or $temp_value eq 'NOW()' ) {
|
||||
$value = 'to_days('.$temp_value.')';
|
||||
} else {
|
||||
$value = DateTimeToSQL($temp_value);
|
||||
if ( !$value ) {
|
||||
|
@ -294,6 +301,8 @@ sub Sql {
|
|||
} else {
|
||||
$self->{Sql} .= " IS $value";
|
||||
}
|
||||
} elsif ( $term->{op} eq 'EXISTS' ) {
|
||||
$self->{Sql} .= " EXISTS $value";
|
||||
} elsif ( $term->{op} eq 'IS NOT' ) {
|
||||
$self->{Sql} .= " IS NOT $value";
|
||||
} elsif ( $term->{op} eq '=[]' ) {
|
||||
|
|
|
@ -172,7 +172,7 @@ sub interpret_messages {
|
|||
# functions
|
||||
|
||||
sub discover {
|
||||
my ( $soap_version ) = @_;
|
||||
my ( $soap_version, $net_interface ) = @_;
|
||||
my @results;
|
||||
|
||||
## collect all responses
|
||||
|
@ -190,22 +190,27 @@ sub discover {
|
|||
my $uuid_gen = Data::UUID->new();
|
||||
|
||||
if ( ( ! $soap_version ) or ( $soap_version eq '1.1' ) ) {
|
||||
my %services;
|
||||
my %services;
|
||||
|
||||
if($verbose) {
|
||||
print "Probing for SOAP 1.1\n"
|
||||
if ( $verbose ) {
|
||||
print "Probing for SOAP 1.1\n";
|
||||
}
|
||||
my $svc_discover = WSDiscovery10::Interfaces::WSDiscovery::WSDiscoveryPort->new({
|
||||
# no_dispatch => '1',
|
||||
});
|
||||
$svc_discover->set_soap_version('1.1');
|
||||
if ( $net_interface ) {
|
||||
my $transport = $svc_discover->get_transport();
|
||||
print "Setting net interface for $transport to $net_interface\n";
|
||||
$transport->set_net_interface($net_interface);
|
||||
}
|
||||
|
||||
my $uuid = $uuid_gen->create_str();
|
||||
|
||||
my $result = $svc_discover->ProbeOp(
|
||||
{ # WSDiscovery::Types::ProbeType
|
||||
Types => 'http://www.onvif.org/ver10/network/wsdl:NetworkVideoTransmitter http://www.onvif.org/ver10/device/wsdl:Device', # QNameListType
|
||||
Scopes => { value => '' },
|
||||
{ # WSDiscovery::Types::ProbeType
|
||||
Types => 'http://www.onvif.org/ver10/network/wsdl:NetworkVideoTransmitter http://www.onvif.org/ver10/device/wsdl:Device', # QNameListType
|
||||
Scopes => { value => '' },
|
||||
},
|
||||
WSDiscovery10::Elements::Header->new({
|
||||
Action => { value => 'http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe' },
|
||||
|
@ -220,14 +225,19 @@ sub discover {
|
|||
} # end if doing soap 1.1
|
||||
|
||||
if ( ( ! $soap_version ) or ( $soap_version eq '1.2' ) ) {
|
||||
my %services;
|
||||
if($verbose) {
|
||||
print "Probing for SOAP 1.2\n"
|
||||
my %services;
|
||||
if ( $verbose ) {
|
||||
print "Probing for SOAP 1.2\n";
|
||||
}
|
||||
my $svc_discover = WSDiscovery10::Interfaces::WSDiscovery::WSDiscoveryPort->new({
|
||||
# no_dispatch => '1',
|
||||
});
|
||||
$svc_discover->set_soap_version('1.2');
|
||||
if ( $net_interface ) {
|
||||
my $transport = $svc_discover->get_transport();
|
||||
print "Setting net interface for $transport to $net_interface\n";
|
||||
$transport->set_net_interface($net_interface);
|
||||
}
|
||||
|
||||
# copies of the same Probe message must have the same MessageID.
|
||||
# This is not a copy. So we generate a new uuid.
|
||||
|
@ -250,7 +260,7 @@ sub discover {
|
|||
push @results, interpret_messages($svc_discover, \%services, @responses);
|
||||
} # end if doing soap 1.2
|
||||
return @results;
|
||||
}
|
||||
} # end sub discover
|
||||
|
||||
sub profiles {
|
||||
my ( $client ) = @_;
|
||||
|
|
|
@ -352,9 +352,13 @@ sub exportsql {
|
|||
}
|
||||
|
||||
my $name = $ARGV[0];
|
||||
if ($name && $name =~ /^([A-Za-z0-9 ,.&()\/\-]+)$/) { # Allow alphanumeric and " ,.&()/-"
|
||||
$name = $1;
|
||||
$command .= qq( --where="Name = '$name'");
|
||||
if ( $name ) {
|
||||
if ( $name =~ /^([A-Za-z0-9 ,.&()\/\-]+)$/ ) { # Allow alphanumeric and " ,.&()/-"
|
||||
$name = $1;
|
||||
$command .= qq( --where="Name = '$name'");
|
||||
} else {
|
||||
print "Invalid characters in Name\n";
|
||||
}
|
||||
}
|
||||
|
||||
$command .= " zm Controls MonitorPresets";
|
||||
|
|
|
@ -196,7 +196,7 @@ my $last_action = 0;
|
|||
while( !$zm_terminate ) {
|
||||
my $now = time;
|
||||
if ( ($now - $last_action) > $Config{ZM_FILTER_RELOAD_DELAY} ) {
|
||||
Debug("Reloading filters");
|
||||
Debug('Reloading filters');
|
||||
$last_action = $now;
|
||||
@filters = getFilters({ Name=>$filter_name, Id=>$filter_id });
|
||||
}
|
||||
|
@ -699,8 +699,10 @@ sub substituteTags {
|
|||
$text =~ s/%ESM%/$Event->{MaxScore}/g;
|
||||
|
||||
if ( $first_alarm_frame ) {
|
||||
$text =~ s/%EPI1%/$url?view=frame&mid=$Event->{MonitorId}&eid=$Event->{Id}&fid=$first_alarm_frame->{FrameId}/g;
|
||||
$text =~ s/%EPIM%/$url?view=frame&mid=$Event->{MonitorId}&eid=$Event->{Id}&fid=$max_alarm_frame->{FrameId}/g;
|
||||
$text =~ s/%EPF1%/$url?view=frame&mid=$Event->{MonitorId}&eid=$Event->{Id}&fid=$first_alarm_frame->{FrameId}/g;
|
||||
$text =~ s/%EPFM%/$url?view=frame&mid=$Event->{MonitorId}&eid=$Event->{Id}&fid=$max_alarm_frame->{FrameId}/g;
|
||||
$text =~ s/%EPI1%/$url?view=image&mid=$Event->{MonitorId}&eid=$Event->{Id}&fid=$first_alarm_frame->{FrameId}/g;
|
||||
$text =~ s/%EPIM%/$url?view=image&mid=$Event->{MonitorId}&eid=$Event->{Id}&fid=$max_alarm_frame->{FrameId}/g;
|
||||
if ( $attachments_ref ) {
|
||||
if ( $text =~ s/%EI1%//g ) {
|
||||
my $path = generateImage($Event, $first_alarm_frame);
|
||||
|
@ -748,13 +750,14 @@ sub substituteTags {
|
|||
}
|
||||
}
|
||||
|
||||
if ( $text =~ s/%EIMOD%//g ) {
|
||||
$text =~ s/%EIMOD%/$url?view=frame&mid=$Event->{MonitorId}&eid=$Event->{Id}&fid=objdetect/g;
|
||||
if ( $text =~ s/%EIMOD%//g or $text =~ s/%EFMOD%//g ) {
|
||||
$text =~ s/%EFMOD%/$url?view=frame&mid=$Event->{MonitorId}&eid=$Event->{Id}&fid=objdetect/g;
|
||||
$text =~ s/%EIMOD%/$url?view=image&mid=$Event->{MonitorId}&eid=$Event->{Id}&fid=objdetect/g;
|
||||
my $path = $Event->Path().'/objdetect.jpg';
|
||||
if ( -e $path ) {
|
||||
push @$attachments_ref, { type=>'image/jpeg', path=>$path };
|
||||
} else {
|
||||
Warning('No image for EIMOD at ' . $path);
|
||||
Warning('No image for MOD at '.$path);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -796,17 +799,17 @@ sub sendEmail {
|
|||
Error('No from email address defined, not sending email');
|
||||
return 0;
|
||||
}
|
||||
if ( ! $Config{ZM_EMAIL_ADDRESS} ) {
|
||||
if ( ! $$filter{EmailTo} ) {
|
||||
Error('No email address defined, not sending email');
|
||||
return 0;
|
||||
}
|
||||
|
||||
Info('Creating notification email');
|
||||
|
||||
my $subject = substituteTags($Config{ZM_EMAIL_SUBJECT}, $filter, $Event);
|
||||
my $subject = substituteTags($$filter{EmailSubject}, $filter, $Event);
|
||||
return 0 if !$subject;
|
||||
my @attachments;
|
||||
my $body = substituteTags($Config{ZM_EMAIL_BODY}, $filter, $Event, \@attachments);
|
||||
my $body = substituteTags($$filter{EmailBody}, $filter, $Event, \@attachments);
|
||||
return 0 if !$body;
|
||||
|
||||
Info("Sending notification email '$subject'");
|
||||
|
@ -816,7 +819,7 @@ sub sendEmail {
|
|||
### Create the multipart container
|
||||
my $mail = MIME::Lite->new (
|
||||
From => $Config{ZM_FROM_EMAIL},
|
||||
To => $Config{ZM_EMAIL_ADDRESS},
|
||||
To => $$filter{EmailTo},
|
||||
Subject => $subject,
|
||||
Type => 'multipart/mixed'
|
||||
);
|
||||
|
@ -826,14 +829,20 @@ sub sendEmail {
|
|||
Data => $body
|
||||
);
|
||||
### Add the attachments
|
||||
my $total_size = 0;
|
||||
foreach my $attachment ( @attachments ) {
|
||||
Info( "Attaching '$attachment->{path}'" );
|
||||
my $size = -s $attachment->{path};
|
||||
$total_size += $size;
|
||||
Info("Attaching '$attachment->{path}' which is $size bytes");
|
||||
$mail->attach(
|
||||
Path => $attachment->{path},
|
||||
Type => $attachment->{type},
|
||||
Disposition => 'attachment'
|
||||
);
|
||||
}
|
||||
if ( $total_size > 10*1024*1024 ) {
|
||||
Warning('Emails larger than 10Mb will often not be delivered! This one is '.int($total_size/(1024*1024)).'Mb');
|
||||
}
|
||||
### Send the Message
|
||||
if ( $Config{ZM_SSMTP_MAIL} ) {
|
||||
my $ssmtp_location = $Config{ZM_SSMTP_PATH};
|
||||
|
@ -849,7 +858,7 @@ sub sendEmail {
|
|||
$mail->send();
|
||||
} else {
|
||||
### Send using SSMTP
|
||||
$mail->send('sendmail', $ssmtp_location, $Config{ZM_EMAIL_ADDRESS});
|
||||
$mail->send('sendmail', $ssmtp_location, $$filter{EmailTo});
|
||||
}
|
||||
} else {
|
||||
MIME::Lite->send('smtp', $Config{ZM_EMAIL_HOST}, Timeout=>60);
|
||||
|
@ -857,20 +866,27 @@ sub sendEmail {
|
|||
}
|
||||
} else {
|
||||
my $mail = MIME::Entity->build(
|
||||
From => $Config{ZM_FROM_EMAIL},
|
||||
To => $Config{ZM_EMAIL_ADDRESS},
|
||||
Subject => $subject,
|
||||
Type => (($body=~/<html>/)?'text/html':'text/plain'),
|
||||
Data => $body
|
||||
);
|
||||
From => $Config{ZM_FROM_EMAIL},
|
||||
To => $$filter{EmailTo},
|
||||
Subject => $subject,
|
||||
Type => (($body=~/<html/)?'text/html':'text/plain'),
|
||||
Data => $body
|
||||
);
|
||||
|
||||
my $total_size = 0;
|
||||
foreach my $attachment ( @attachments ) {
|
||||
Info("Attaching '$attachment->{path}'");
|
||||
my $size = -s $attachment->{path};
|
||||
$total_size += $size;
|
||||
Info("Attaching '$attachment->{path}' which is $size bytes");
|
||||
|
||||
$mail->attach(
|
||||
Path => $attachment->{path},
|
||||
Type => $attachment->{type},
|
||||
Encoding => 'base64'
|
||||
);
|
||||
Path => $attachment->{path},
|
||||
Type => $attachment->{type},
|
||||
Encoding => 'base64'
|
||||
);
|
||||
} # end foreach attachment
|
||||
if ( $total_size > 10*1024*1024 ) {
|
||||
Warning('Emails larger than 10Mb will often not be delivered! This one is '.int($total_size/(1024*1024)).'Mb');
|
||||
}
|
||||
$mail->smtpsend(Host => $Config{ZM_EMAIL_HOST}, MailFrom => $Config{ZM_FROM_EMAIL});
|
||||
}
|
||||
|
@ -962,7 +978,7 @@ sub sendMessage {
|
|||
From => $Config{ZM_FROM_EMAIL},
|
||||
To => $Config{ZM_MESSAGE_ADDRESS},
|
||||
Subject => $subject,
|
||||
Type => (($body=~/<html>/)?'text/html':'text/plain'),
|
||||
Type => (($body=~/<html/)?'text/html':'text/plain'),
|
||||
Data => $body
|
||||
);
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ my $OPTIONS = 'v';
|
|||
|
||||
sub HELP_MESSAGE {
|
||||
my ($fh, $pkg, $ver, $opts) = @_;
|
||||
print $fh "Usage: " . __FILE__ . " [-v] probe <soap version>\n";
|
||||
print $fh "Usage: " . __FILE__ . " [-v] probe <soap version> <network interface>\n";
|
||||
print $fh " " . __FILE__ . " [-v] <command> <device URI> <soap version> <user> <password>\n";
|
||||
print $fh <<EOF
|
||||
Commands are:
|
||||
|
@ -69,7 +69,7 @@ if ( !getopts($OPTIONS) ) {
|
|||
|
||||
my $action = shift;
|
||||
|
||||
if(!defined $action) {
|
||||
if ( ! defined $action ) {
|
||||
HELP_MESSAGE(\*STDOUT);
|
||||
exit(1);
|
||||
}
|
||||
|
@ -84,7 +84,8 @@ if ( defined $opt_v ) {
|
|||
|
||||
if ( $action eq 'probe' ) {
|
||||
my $soap_version = shift;
|
||||
ZoneMinder::ONVIF::discover($soap_version);
|
||||
my $net_interface = shift;
|
||||
ZoneMinder::ONVIF::discover($soap_version, $net_interface);
|
||||
} else {
|
||||
# all other actions need URI and credentials
|
||||
my $url_svc_device = shift @ARGV;
|
||||
|
|
|
@ -214,7 +214,7 @@ sub getUUID {
|
|||
$uuid = $Config{ZM_TELEMETRY_UUID} = $sth->fetchrow_array();
|
||||
$sth->finish();
|
||||
|
||||
$sql = q`UPDATE Config set Value = ? WHERE Name = 'ZM_TELEMETRY_UUID'`;
|
||||
$sql = q`UPDATE Config SET Value = ? WHERE Name = 'ZM_TELEMETRY_UUID'`;
|
||||
$sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
$res = $sth->execute( "$uuid" ) or die( "Can't execute: ".$sth->errstr() );
|
||||
$sth->finish();
|
||||
|
@ -250,9 +250,9 @@ sub countQuery {
|
|||
my $dbh = shift;
|
||||
my $table = shift;
|
||||
|
||||
my $sql = "SELECT count(*) FROM $table";
|
||||
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() );
|
||||
my $sql = "SELECT count(*) FROM `$table`";
|
||||
my $sth = $dbh->prepare_cached($sql) or die "Can't prepare '$sql': ".$dbh->errstr();
|
||||
my $res = $sth->execute() or die 'Can\'t execute: '.$sth->errstr();
|
||||
my $count = $sth->fetchrow_array();
|
||||
$sth->finish();
|
||||
|
||||
|
@ -263,7 +263,7 @@ sub countQuery {
|
|||
sub getMonitorRef {
|
||||
my $dbh = shift;
|
||||
|
||||
my $sql = 'SELECT Id,Name,Type,Function,Width,Height,Colours,MaxFPS,AlarmMaxFPS FROM Monitors';
|
||||
my $sql = 'SELECT `Id`,`Name`,`Type`,`Function`,`Width`,`Height`,`Colours`,`MaxFPS`,`AlarmMaxFPS` FROM `Monitors`';
|
||||
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() );
|
||||
my $arrayref = $sth->fetchall_arrayref({});
|
||||
|
|
|
@ -847,9 +847,9 @@ if ( $version ) {
|
|||
}
|
||||
$cascade = !undef;
|
||||
}
|
||||
if ( $cascade || $version eq "1.24.4" ) {
|
||||
if ( $cascade || $version eq '1.24.4' ) {
|
||||
# Patch the database
|
||||
patchDB( $dbh, "1.24.4" );
|
||||
patchDB($dbh, '1.24.4');
|
||||
|
||||
# Copy the FTP specific values to the new general config
|
||||
my $fetchSql = "select * from Config where Name like 'ZM_UPLOAD_FTP_%'";
|
||||
|
@ -863,12 +863,12 @@ if ( $version ) {
|
|||
}
|
||||
$cascade = !undef;
|
||||
}
|
||||
if ( $cascade || $version lt "1.26.0" ) {
|
||||
my $sth = $dbh->prepare_cached( 'select * from Monitors LIMIT 0,1' );
|
||||
if ( $cascade || $version lt '1.26.0' ) {
|
||||
my $sth = $dbh->prepare_cached('SELECT * FROM Monitors LIMIT 0,1');
|
||||
die "Error: " . $dbh->errstr . "\n" unless ($sth);
|
||||
die "Error: " . $sth->errstr . "\n" unless ($sth->execute);
|
||||
|
||||
my $columns = $sth->{'NAME'};
|
||||
my $columns = $sth->{NAME};
|
||||
if ( ! grep(/^Colours$/, @$columns ) ) {
|
||||
$dbh->do(q{alter table Monitors add column `Colours` tinyint(3) unsigned NOT NULL default '1' after `Height`;});
|
||||
} # end if
|
||||
|
@ -898,28 +898,31 @@ if ( $version ) {
|
|||
die "Should have found upgrade scripts at $updateDir\n";
|
||||
} # end if
|
||||
|
||||
my $sql = "UPDATE `Config` SET `Value` = ? WHERE `Name` = 'ZM_DYN_DB_VERSION'";
|
||||
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
|
||||
foreach my $patch ( @files ) {
|
||||
my ( $v ) = $patch =~ /^zm_update\-([\d\.]+)\.sql$/;
|
||||
#PP make sure we use version compare
|
||||
if ( version->parse('v' . $v) > version->parse('v' . $version) ) {
|
||||
print( "Upgrading DB to $v from $version\n" );
|
||||
patchDB( $dbh, $v );
|
||||
my $sql = "update Config set Value = ? where Name = 'ZM_DYN_DB_VERSION'";
|
||||
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute( $version ) or die( "Can't execute: ".$sth->errstr() );
|
||||
$sth->finish();
|
||||
if ( version->parse('v'.$v) > version->parse('v'.$version) ) {
|
||||
print("Upgrading DB to $v from $version\n");
|
||||
if ( patchDB($dbh, $v) ) {
|
||||
my $res = $sth->execute($version) or die( "Can't execute: ".$sth->errstr() );
|
||||
}
|
||||
#patchDB_using_do( $dbh, $version, $updateDir.'/'.$patch );
|
||||
} # end if newer version
|
||||
} # end foreach patchfile
|
||||
|
||||
$sth->finish();
|
||||
$cascade = !undef;
|
||||
} # end if
|
||||
|
||||
if ( $cascade ) {
|
||||
my $installed_version = ZM_VERSION;
|
||||
my $sql = 'update Config set Value = ? where Name = ?';
|
||||
# This is basically here so that we don't need zm-update-blah.sql files for versions without db changes
|
||||
my $sql = 'UPDATE `Config` SET `Value` = ? WHERE `Name` = ?';
|
||||
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute( "$installed_version", 'ZM_DYN_DB_VERSION' ) or die( "Can't execute: ".$sth->errstr() );
|
||||
$res = $sth->execute( "$installed_version", 'ZM_DYN_CURR_VERSION' ) or die( "Can't execute: ".$sth->errstr() );
|
||||
$sth->execute(ZM_VERSION, 'ZM_DYN_DB_VERSION') or die( "Can't execute: ".$sth->errstr() );
|
||||
$sth->execute(ZM_VERSION, 'ZM_DYN_CURR_VERSION') or die( "Can't execute: ".$sth->errstr() );
|
||||
$sth->finish();
|
||||
} else {
|
||||
zmDbDisconnect();
|
||||
|
@ -930,41 +933,42 @@ if ( $version ) {
|
|||
#my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
#my $res = $sth->execute( ) or die( "Can't execute: ".$sth->errstr() );
|
||||
#$sth->finish();
|
||||
print( "\nDatabase upgrade to version ".ZM_VERSION." successful.\n\n" );
|
||||
}
|
||||
print("\nDatabase upgrade to version ".ZM_VERSION." successful.\n\n");
|
||||
} # end if version
|
||||
|
||||
zmDbDisconnect();
|
||||
exit( 0 );
|
||||
exit(0);
|
||||
|
||||
sub patchDB_using_do {
|
||||
my ( $dbh, $version, $file ) = @_;
|
||||
|
||||
open( my $fh, '<', $file ) or die "Unable to open $file $!";
|
||||
open(my $fh, '<', $file) or die "Unable to open $file $!";
|
||||
$/ = undef;
|
||||
my $sql = <$fh>;
|
||||
close $fh;
|
||||
if ( $sql ) {
|
||||
$dbh->{'AutoCommit'} = 0;
|
||||
$dbh->{AutoCommit} = 0;
|
||||
$dbh->do($sql);
|
||||
if ( $dbh->errstr() ) {
|
||||
$dbh->rollback();
|
||||
die "Error: " . $dbh->errstr(). ". Rolled back.\n";
|
||||
die 'Error: '.$dbh->errstr().". Rolled back.\n";
|
||||
} # end if error
|
||||
|
||||
my $sql = "update Config set Value = ? where Name = 'ZM_DYN_DB_VERSION'";
|
||||
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute( $version ) or die( "Can't execute: ".$sth->errstr() );
|
||||
my $sql = 'UPDATE `Config` SET `Value` = ? WHERE `Name` = \'ZM_DYN_DB_VERSION\'';
|
||||
my $sth = $dbh->prepare_cached($sql) or die "Can't prepare '$sql': ".$dbh->errstr();
|
||||
my $res = $sth->execute($version) or die 'Can\'t execute: '.$sth->errstr();
|
||||
$sth->finish();
|
||||
|
||||
$dbh->{'AutoCommit'} = 1;
|
||||
$dbh->{AutoCommit} = 1;
|
||||
} else {
|
||||
Warning("Empty db update file at $file");
|
||||
}
|
||||
}
|
||||
} # end sub patchDB_using_do
|
||||
|
||||
sub patchDB {
|
||||
my $dbh = shift;
|
||||
my $version = shift;
|
||||
|
||||
|
||||
my ( $host, $portOrSocket ) = ( $Config{ZM_DB_HOST} =~ /^([^:]+)(?::(.+))?$/ );
|
||||
my $command = 'mysql';
|
||||
if ( defined($portOrSocket) ) {
|
||||
|
@ -988,39 +992,38 @@ sub patchDB {
|
|||
}
|
||||
$command .= '/zm_update-'.$version.'.sql';
|
||||
|
||||
print( "Executing '$command'\n" ) if ( logDebugging() );
|
||||
print("Executing '$command'\n") if logDebugging();
|
||||
my $output = qx($command);
|
||||
my $status = $? >> 8;
|
||||
if ( $status || logDebugging() ) {
|
||||
chomp( $output );
|
||||
print( "Output: $output\n" );
|
||||
chomp($output);
|
||||
print("Output: $output\n");
|
||||
}
|
||||
if ( $status ) {
|
||||
die( "Command '$command' exited with status: $status\n" );
|
||||
die("Command '$command' exited with status: $status\n");
|
||||
}
|
||||
print( "\nDatabase successfully upgraded to version $version.\n" );
|
||||
|
||||
}
|
||||
print("\nDatabase successfully upgraded to version $version.\n");
|
||||
} # end sub patchDB
|
||||
|
||||
sub migratePasswords {
|
||||
print ("Migratings passwords, if any...\n");
|
||||
my $sql = "select * from Users";
|
||||
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() );
|
||||
while( my $user = $sth->fetchrow_hashref() ) {
|
||||
my $scheme = substr($user->{Password}, 0, 1);
|
||||
if ($scheme eq "*") {
|
||||
print ("-->".$user->{Username}. " password will be migrated\n");
|
||||
my $salt = Crypt::Eksblowfish::Bcrypt::en_base64(rand_bits(16*8));
|
||||
my $settings = '$2a$10$'.$salt;
|
||||
my $pass_hash = Crypt::Eksblowfish::Bcrypt::bcrypt($user->{Password},$settings);
|
||||
my $new_pass_hash = "-ZM-".$pass_hash;
|
||||
$sql = "UPDATE Users SET PASSWORD=? WHERE Username=?";
|
||||
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute($new_pass_hash, $user->{Username}) or die( "Can't execute: ".$sth->errstr() );
|
||||
}
|
||||
print ("Migratings passwords, if any...\n");
|
||||
my $sql = 'SELECT * FROM `Users`';
|
||||
my $sth = $dbh->prepare_cached($sql) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute() or die("Can't execute: ".$sth->errstr());
|
||||
while( my $user = $sth->fetchrow_hashref() ) {
|
||||
my $scheme = substr($user->{Password}, 0, 1);
|
||||
if ($scheme eq '*') {
|
||||
print ('-->'.$user->{Username}." password will be migrated\n");
|
||||
my $salt = Crypt::Eksblowfish::Bcrypt::en_base64(rand_bits(16*8));
|
||||
my $settings = '$2a$10$'.$salt;
|
||||
my $pass_hash = Crypt::Eksblowfish::Bcrypt::bcrypt($user->{Password},$settings);
|
||||
my $new_pass_hash = '-ZM-'.$pass_hash;
|
||||
$sql = 'UPDATE Users SET `Password`=? WHERE `Username`=?';
|
||||
my $sth = $dbh->prepare_cached($sql) or die("Can't prepare '$sql': ".$dbh->errstr());
|
||||
my $res = $sth->execute($new_pass_hash, $user->{Username}) or die("Can't execute: ".$sth->errstr());
|
||||
}
|
||||
}
|
||||
}
|
||||
} # end sub migratePasswords
|
||||
|
||||
sub migratePaths {
|
||||
|
||||
|
|
1144
scripts/zmx10.pl.in
1144
scripts/zmx10.pl.in
File diff suppressed because it is too large
Load Diff
|
@ -4,7 +4,7 @@
|
|||
configure_file(zm_config.h.in "${CMAKE_CURRENT_BINARY_DIR}/zm_config.h" @ONLY)
|
||||
|
||||
# Group together all the source files that are used by all the binaries (zmc, zma, zmu, zms etc)
|
||||
set(ZM_BIN_SRC_FILES zm_box.cpp zm_buffer.cpp zm_camera.cpp zm_comms.cpp zm_config.cpp zm_coord.cpp zm_curl_camera.cpp zm.cpp zm_db.cpp zm_logger.cpp zm_event.cpp zm_frame.cpp zm_eventstream.cpp zm_exception.cpp zm_file_camera.cpp zm_ffmpeg_input.cpp zm_ffmpeg_camera.cpp zm_group.cpp zm_image.cpp zm_jpeg.cpp zm_libvlc_camera.cpp zm_local_camera.cpp zm_monitor.cpp zm_monitorstream.cpp zm_ffmpeg.cpp zm_mpeg.cpp zm_packet.cpp zm_packetqueue.cpp zm_poly.cpp zm_regexp.cpp zm_remote_camera.cpp zm_remote_camera_http.cpp zm_remote_camera_nvsocket.cpp zm_remote_camera_rtsp.cpp zm_rtp.cpp zm_rtp_ctrl.cpp zm_rtp_data.cpp zm_rtp_source.cpp zm_rtsp.cpp zm_rtsp_auth.cpp zm_sdp.cpp zm_signal.cpp zm_stream.cpp zm_swscale.cpp zm_thread.cpp zm_time.cpp zm_timer.cpp zm_user.cpp zm_utils.cpp zm_video.cpp zm_videostore.cpp zm_zone.cpp zm_storage.cpp zm_fifo.cpp zm_crypt.cpp)
|
||||
set(ZM_BIN_SRC_FILES zm_box.cpp zm_buffer.cpp zm_camera.cpp zm_comms.cpp zm_config.cpp zm_coord.cpp zm_curl_camera.cpp zm.cpp zm_db.cpp zm_logger.cpp zm_event.cpp zm_frame.cpp zm_eventstream.cpp zm_exception.cpp zm_file_camera.cpp zm_ffmpeg_input.cpp zm_ffmpeg_camera.cpp zm_group.cpp zm_image.cpp zm_jpeg.cpp zm_libvlc_camera.cpp zm_libvnc_camera.cpp zm_local_camera.cpp zm_monitor.cpp zm_monitorstream.cpp zm_ffmpeg.cpp zm_mpeg.cpp zm_packet.cpp zm_packetqueue.cpp zm_poly.cpp zm_regexp.cpp zm_remote_camera.cpp zm_remote_camera_http.cpp zm_remote_camera_nvsocket.cpp zm_remote_camera_rtsp.cpp zm_rtp.cpp zm_rtp_ctrl.cpp zm_rtp_data.cpp zm_rtp_source.cpp zm_rtsp.cpp zm_rtsp_auth.cpp zm_sdp.cpp zm_signal.cpp zm_stream.cpp zm_swscale.cpp zm_thread.cpp zm_time.cpp zm_timer.cpp zm_user.cpp zm_utils.cpp zm_video.cpp zm_videostore.cpp zm_zone.cpp zm_storage.cpp zm_fifo.cpp zm_crypt.cpp)
|
||||
|
||||
|
||||
# A fix for cmake recompiling the source files for every target.
|
||||
|
|
32
src/zm_box.h
32
src/zm_box.h
|
@ -33,37 +33,33 @@
|
|||
// Class used for storing a box, which is defined as a region
|
||||
// defined by two coordinates
|
||||
//
|
||||
class Box
|
||||
{
|
||||
class Box {
|
||||
private:
|
||||
Coord lo, hi;
|
||||
Coord size;
|
||||
|
||||
public:
|
||||
inline Box()
|
||||
{
|
||||
}
|
||||
inline Box() { }
|
||||
explicit inline Box( int p_size ) : lo( 0, 0 ), hi ( p_size-1, p_size-1 ), size( Coord::Range( hi, lo ) ) { }
|
||||
inline Box( int p_x_size, int p_y_size ) : lo( 0, 0 ), hi ( p_x_size-1, p_y_size-1 ), size( Coord::Range( hi, lo ) ) { }
|
||||
inline Box( int lo_x, int lo_y, int hi_x, int hi_y ) : lo( lo_x, lo_y ), hi( hi_x, hi_y ), size( Coord::Range( hi, lo ) ) { }
|
||||
inline Box( const Coord &p_lo, const Coord &p_hi ) : lo( p_lo ), hi( p_hi ), size( Coord::Range( hi, lo ) ) { }
|
||||
|
||||
inline const Coord &Lo() const { return( lo ); }
|
||||
inline int LoX() const { return( lo.X() ); }
|
||||
inline int LoY() const { return( lo.Y() ); }
|
||||
inline const Coord &Hi() const { return( hi ); }
|
||||
inline int HiX() const { return( hi.X() ); }
|
||||
inline int HiY() const { return( hi.Y() ); }
|
||||
inline const Coord &Size() const { return( size ); }
|
||||
inline int Width() const { return( size.X() ); }
|
||||
inline int Height() const { return( size.Y() ); }
|
||||
inline int Area() const { return( size.X()*size.Y() ); }
|
||||
inline const Coord &Lo() const { return lo; }
|
||||
inline int LoX() const { return lo.X(); }
|
||||
inline int LoY() const { return lo.Y(); }
|
||||
inline const Coord &Hi() const { return hi; }
|
||||
inline int HiX() const { return hi.X(); }
|
||||
inline int HiY() const { return hi.Y(); }
|
||||
inline const Coord &Size() const { return size; }
|
||||
inline int Width() const { return size.X(); }
|
||||
inline int Height() const { return size.Y(); }
|
||||
inline int Area() const { return size.X()*size.Y(); }
|
||||
|
||||
inline const Coord Centre() const
|
||||
{
|
||||
inline const Coord Centre() const {
|
||||
int mid_x = int(round(lo.X()+(size.X()/2.0)));
|
||||
int mid_y = int(round(lo.Y()+(size.Y()/2.0)));
|
||||
return( Coord( mid_x, mid_y ) );
|
||||
return Coord( mid_x, mid_y );
|
||||
}
|
||||
inline bool Inside( const Coord &coord ) const
|
||||
{
|
||||
|
|
|
@ -35,7 +35,7 @@ class Camera;
|
|||
//
|
||||
class Camera {
|
||||
protected:
|
||||
typedef enum { LOCAL_SRC, REMOTE_SRC, FILE_SRC, FFMPEG_SRC, LIBVLC_SRC, CURL_SRC } SourceType;
|
||||
typedef enum { LOCAL_SRC, REMOTE_SRC, FILE_SRC, FFMPEG_SRC, LIBVLC_SRC, CURL_SRC, VNC_SRC } SourceType;
|
||||
|
||||
unsigned int monitor_id;
|
||||
Monitor * monitor; // Null on instantiation, set as soon as possible.
|
||||
|
@ -68,6 +68,7 @@ public:
|
|||
bool IsFfmpeg() const { return type == FFMPEG_SRC; }
|
||||
bool IsLibvlc() const { return type == LIBVLC_SRC; }
|
||||
bool IscURL() const { return type == CURL_SRC; }
|
||||
bool IsVNC() const { return type == VNC_SRC; }
|
||||
unsigned int Width() const { return width; }
|
||||
unsigned int Height() const { return height; }
|
||||
unsigned int Colours() const { return colours; }
|
||||
|
|
|
@ -63,7 +63,9 @@ void zmLoadConfig() {
|
|||
closedir(configSubFolder);
|
||||
}
|
||||
|
||||
zmDbConnect();
|
||||
if ( !zmDbConnect() ) {
|
||||
Fatal("Can't connect to db. Can't continue.");
|
||||
}
|
||||
config.Load();
|
||||
config.Assign();
|
||||
|
||||
|
|
|
@ -25,8 +25,7 @@
|
|||
//
|
||||
// Class used for storing an x,y pair, i.e. a coordinate
|
||||
//
|
||||
class Coord
|
||||
{
|
||||
class Coord {
|
||||
private:
|
||||
int x, y;
|
||||
|
||||
|
@ -44,8 +43,7 @@ public:
|
|||
inline int &Y() { return( y ); }
|
||||
inline const int &Y() const { return( y ); }
|
||||
|
||||
inline static Coord Range( const Coord &coord1, const Coord &coord2 )
|
||||
{
|
||||
inline static Coord Range( const Coord &coord1, const Coord &coord2 ) {
|
||||
Coord result( (coord1.x-coord2.x)+1, (coord1.y-coord2.y)+1 );
|
||||
return( result );
|
||||
}
|
||||
|
|
|
@ -108,6 +108,23 @@ Event::Event(
|
|||
return;
|
||||
}
|
||||
id = mysql_insert_id(&dbconn);
|
||||
//
|
||||
|
||||
/* Update event record with DefaultVideo name if possible so image.php can extract frames
|
||||
if needed, while recording is in progress */
|
||||
if ( monitor->GetOptVideoWriter() != 0 ) {
|
||||
video_name[0] = 0;
|
||||
snprintf(video_name, sizeof(video_name), "%" PRIu64 "-%s", id, "video.mp4");
|
||||
Debug(1, "Updating inserted event with DefaultVideo=%s",video_name);
|
||||
snprintf(sql, sizeof(sql), "UPDATE Events SET DefaultVideo = '%s' WHERE Id=%" PRIu64, video_name,id);
|
||||
if ( mysql_query(&dbconn, sql) ) {
|
||||
Error("Can't update event: %s. sql was (%s)", mysql_error(&dbconn), sql);
|
||||
db_mutex.unlock();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
Debug (1, "GetOptVideoWriter() returned 0, not updating DefaultVideo");
|
||||
}
|
||||
db_mutex.unlock();
|
||||
if ( untimedEvent ) {
|
||||
Warning("Event %d has zero time, setting to current", id);
|
||||
|
|
|
@ -100,6 +100,7 @@ bool EventStream::loadInitialEventData(uint64_t init_event_id, unsigned int init
|
|||
if ( init_frame_id >= event_data->frame_count ) {
|
||||
Error("Invalid frame id specified. %d > %d", init_frame_id, event_data->frame_count);
|
||||
curr_stream_time = event_data->start_time;
|
||||
curr_frame_id = 1;
|
||||
} else {
|
||||
curr_stream_time = event_data->frames[init_frame_id-1].timestamp;
|
||||
curr_frame_id = init_frame_id;
|
||||
|
@ -373,18 +374,20 @@ void EventStream::processCommand(const CmdMsg *msg) {
|
|||
}
|
||||
break;
|
||||
case CMD_SLOWFWD :
|
||||
Debug(1, "Got SLOW FWD command");
|
||||
paused = true;
|
||||
replay_rate = ZM_RATE_BASE;
|
||||
step = 1;
|
||||
if ( (unsigned int)curr_frame_id < event_data->frame_count )
|
||||
curr_frame_id += 1;
|
||||
Debug(1, "Got SLOWFWD command new frame id %d", curr_frame_id);
|
||||
break;
|
||||
case CMD_SLOWREV :
|
||||
Debug(1, "Got SLOW REV command");
|
||||
paused = true;
|
||||
replay_rate = ZM_RATE_BASE;
|
||||
step = -1;
|
||||
curr_frame_id -= 1;
|
||||
if ( curr_frame_id < 1 ) curr_frame_id = 1;
|
||||
Debug(1, "Got SLOWREV command new frame id %d", curr_frame_id);
|
||||
break;
|
||||
case CMD_FASTREV :
|
||||
Debug(1, "Got FAST REV command");
|
||||
|
@ -929,7 +932,7 @@ void EventStream::runStream() {
|
|||
send_frame = true;
|
||||
}
|
||||
} else if ( step != 0 ) {
|
||||
Debug(2, "Paused with step");
|
||||
Debug(2, "Paused with step %d", step);
|
||||
// We are paused and are just stepping forward or backward one frame
|
||||
step = 0;
|
||||
send_frame = true;
|
||||
|
|
|
@ -20,9 +20,6 @@
|
|||
#ifndef ZM_EVENTSTREAM_H
|
||||
#define ZM_EVENTSTREAM_H
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
#include "zm_image.h"
|
||||
#include "zm_stream.h"
|
||||
#include "zm_video.h"
|
||||
|
@ -97,7 +94,7 @@ class EventStream : public StreamBase {
|
|||
public:
|
||||
EventStream() {
|
||||
mode = DEFAULT_MODE;
|
||||
replay_rate = DEFAULT_RATE;
|
||||
replay_rate = DEFAULT_RATE;
|
||||
|
||||
forceEventChange = false;
|
||||
|
||||
|
@ -121,8 +118,8 @@ class EventStream : public StreamBase {
|
|||
void runStream();
|
||||
Image *getImage();
|
||||
private:
|
||||
AVCodecContext *input_codec_context;
|
||||
AVCodec *input_codec;
|
||||
AVCodecContext *input_codec_context;
|
||||
AVCodec *input_codec;
|
||||
};
|
||||
|
||||
#endif // ZM_EVENTSTREAM_H
|
||||
|
|
|
@ -321,6 +321,7 @@ void zm_dump_codecpar(const AVCodecParameters *par);
|
|||
frame->pts \
|
||||
);
|
||||
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 4, 0, 74, 100)
|
||||
#define zm_dump_video_frame(frame,text) Debug(1, "%s: format %d %s %dx%d linesize:%dx%d pts: %" PRId64, \
|
||||
text, \
|
||||
frame->format, \
|
||||
|
@ -331,6 +332,18 @@ void zm_dump_codecpar(const AVCodecParameters *par);
|
|||
frame->pts \
|
||||
);
|
||||
|
||||
#else
|
||||
#define zm_dump_video_frame(frame,text) Debug(1, "%s: format %d %s %dx%d linesize:%dx%d pts: %" PRId64, \
|
||||
text, \
|
||||
frame->format, \
|
||||
"unsupported", \
|
||||
frame->width, \
|
||||
frame->height, \
|
||||
frame->linesize[0], frame->linesize[1], \
|
||||
frame->pts \
|
||||
);
|
||||
#endif
|
||||
|
||||
#if LIBAVCODEC_VERSION_CHECK(56, 8, 0, 60, 100)
|
||||
#define zm_av_packet_unref( packet ) av_packet_unref( packet )
|
||||
#define zm_av_packet_ref( dst, src ) av_packet_ref( dst, src )
|
||||
|
|
|
@ -603,6 +603,8 @@ int FfmpegCamera::OpenFfmpeg() {
|
|||
Error("Unable to allocate frame for %s", mPath.c_str());
|
||||
return -1;
|
||||
}
|
||||
mFrame->width = width;
|
||||
mFrame->height = height;
|
||||
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
int pSize = av_image_get_buffer_size(imagePixFormat, width, height, 1);
|
||||
|
@ -630,20 +632,6 @@ int FfmpegCamera::OpenFfmpeg() {
|
|||
return -1;
|
||||
}
|
||||
|
||||
# if 0
|
||||
// Must get a frame first to find out the actual format returned by decoding
|
||||
mConvertContext = sws_getContext(
|
||||
mVideoCodecContext->width,
|
||||
mVideoCodecContext->height,
|
||||
mVideoCodecContext->pix_fmt,
|
||||
width, height,
|
||||
imagePixFormat, SWS_BICUBIC, NULL,
|
||||
NULL, NULL);
|
||||
if ( mConvertContext == NULL ) {
|
||||
Error("Unable to create conversion context for %s", mPath.c_str());
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#else // HAVE_LIBSWSCALE
|
||||
Fatal("You must compile ffmpeg with the --enable-swscale "
|
||||
"option to use ffmpeg cameras");
|
||||
|
@ -1090,7 +1078,9 @@ int FfmpegCamera::transfer_to_image(
|
|||
// From what I've read, we should align the linesizes to 32bit so that ffmpeg can use SIMD instructions too.
|
||||
int size = av_image_fill_arrays(
|
||||
output_frame->data, output_frame->linesize,
|
||||
directbuffer, imagePixFormat, width, height, 32);
|
||||
directbuffer, imagePixFormat, width, height,
|
||||
(AV_PIX_FMT_RGBA == imagePixFormat ? 32 : 1)
|
||||
);
|
||||
if ( size < 0 ) {
|
||||
Error("Problem setting up data pointers into image %s",
|
||||
av_make_error_string(size).c_str());
|
||||
|
@ -1130,12 +1120,12 @@ int FfmpegCamera::transfer_to_image(
|
|||
0, mVideoCodecContext->height,
|
||||
output_frame->data, output_frame->linesize);
|
||||
if ( ret < 0 ) {
|
||||
Error("Unable to convert format %u %s linesize %d height %d to format %u %s linesize %d at frame %d codec %u %s lines %d: code: %d",
|
||||
Error("Unable to convert format %u %s linesize %d,%d height %d to format %u %s linesize %d,%d at frame %d codec %u %s lines %d: code: %d",
|
||||
input_frame->format, av_get_pix_fmt_name((AVPixelFormat)input_frame->format),
|
||||
input_frame->linesize, mVideoCodecContext->height,
|
||||
input_frame->linesize[0], input_frame->linesize[1], mVideoCodecContext->height,
|
||||
imagePixFormat,
|
||||
av_get_pix_fmt_name(imagePixFormat),
|
||||
output_frame->linesize,
|
||||
output_frame->linesize[0], output_frame->linesize[1],
|
||||
frameCount,
|
||||
mVideoCodecContext->pix_fmt, av_get_pix_fmt_name(mVideoCodecContext->pix_fmt),
|
||||
mVideoCodecContext->height,
|
||||
|
@ -1143,6 +1133,17 @@ int FfmpegCamera::transfer_to_image(
|
|||
);
|
||||
return -1;
|
||||
}
|
||||
Debug(4, "Able to convert format %u %s linesize %d,%d height %d to format %u %s linesize %d,%d at frame %d codec %u %s %dx%d ",
|
||||
input_frame->format, av_get_pix_fmt_name((AVPixelFormat)input_frame->format),
|
||||
input_frame->linesize[0], input_frame->linesize[1], mVideoCodecContext->height,
|
||||
imagePixFormat,
|
||||
av_get_pix_fmt_name(imagePixFormat),
|
||||
output_frame->linesize[0], output_frame->linesize[1],
|
||||
frameCount,
|
||||
mVideoCodecContext->pix_fmt, av_get_pix_fmt_name(mVideoCodecContext->pix_fmt),
|
||||
output_frame->width,
|
||||
output_frame->height
|
||||
);
|
||||
#else // HAVE_LIBSWSCALE
|
||||
Fatal("You must compile ffmpeg with the --enable-swscale "
|
||||
"option to use ffmpeg cameras");
|
||||
|
|
|
@ -145,7 +145,11 @@ AVFrame *FFmpeg_Input::get_frame(int stream_id) {
|
|||
av_frame_free(&frame);
|
||||
continue;
|
||||
} else {
|
||||
zm_dump_frame(frame, "resulting frame");
|
||||
if ( is_video_stream(input_format_context->streams[packet.stream_index]) ) {
|
||||
zm_dump_video_frame(frame, "resulting video frame");
|
||||
} else {
|
||||
zm_dump_frame(frame, "resulting frame");
|
||||
}
|
||||
}
|
||||
|
||||
frameComplete = 1;
|
||||
|
|
|
@ -167,8 +167,10 @@ Image::Image( const AVFrame *frame ) {
|
|||
width = frame->width;
|
||||
height = frame->height;
|
||||
pixels = width*height;
|
||||
|
||||
colours = ZM_COLOUR_RGB32;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_RGBA;
|
||||
|
||||
size = pixels*colours;
|
||||
buffer = 0;
|
||||
holdbuffer = 0;
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
#include "zm.h"
|
||||
#include "zm_signal.h"
|
||||
#include "zm_libvnc_camera.h"
|
||||
#include "zm_swscale.h"
|
||||
|
||||
#if HAVE_LIBVNC
|
||||
|
||||
static int TAG_0;
|
||||
static int TAG_1;
|
||||
static int TAG_2;
|
||||
|
||||
static void GotFrameBufferUpdateCallback(rfbClient *rfb, int x, int y, int w, int h){
|
||||
VncPrivateData *data = (VncPrivateData *)rfbClientGetClientData(rfb, &TAG_0);
|
||||
data->buffer = rfb->frameBuffer;
|
||||
}
|
||||
|
||||
static char* GetPasswordCallback(rfbClient* cl){
|
||||
return strdup((const char *)rfbClientGetClientData(cl, &TAG_1));
|
||||
}
|
||||
|
||||
static rfbCredential* GetCredentialsCallback(rfbClient* cl, int credentialType){
|
||||
rfbCredential *c = (rfbCredential *)malloc(sizeof(rfbCredential));
|
||||
if ( credentialType != rfbCredentialTypeUser ) {
|
||||
free(c);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
c->userCredential.password = strdup((const char *)rfbClientGetClientData(cl, &TAG_1));
|
||||
c->userCredential.username = strdup((const char *)rfbClientGetClientData(cl, &TAG_2));
|
||||
return c;
|
||||
}
|
||||
|
||||
VncCamera::VncCamera(
|
||||
unsigned int p_monitor_id,
|
||||
const std::string &host,
|
||||
const std::string &port,
|
||||
const std::string &user,
|
||||
const std::string &pass,
|
||||
int p_width,
|
||||
int p_height,
|
||||
int p_colours,
|
||||
int p_brightness,
|
||||
int p_contrast,
|
||||
int p_hue,
|
||||
int p_colour,
|
||||
bool p_capture,
|
||||
bool p_record_audio ) :
|
||||
Camera(
|
||||
p_monitor_id,
|
||||
VNC_SRC,
|
||||
p_width,
|
||||
p_height,
|
||||
p_colours,
|
||||
ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours),
|
||||
p_brightness,
|
||||
p_contrast,
|
||||
p_hue,
|
||||
p_colour,
|
||||
p_capture,
|
||||
p_record_audio
|
||||
),
|
||||
mHost(host),
|
||||
mPort(port),
|
||||
mUser(user),
|
||||
mPass(pass)
|
||||
{
|
||||
Debug(2, "Host:%s Port: %s User: %s Pass:%s", mHost.c_str(), mPort.c_str(), mUser.c_str(), mPass.c_str());
|
||||
|
||||
if ( colours == ZM_COLOUR_RGB32 ) {
|
||||
subpixelorder = ZM_SUBPIX_ORDER_RGBA;
|
||||
mImgPixFmt = AV_PIX_FMT_RGBA;
|
||||
mBpp = 4;
|
||||
} else if ( colours == ZM_COLOUR_RGB24 ) {
|
||||
subpixelorder = ZM_SUBPIX_ORDER_RGB;
|
||||
mImgPixFmt = AV_PIX_FMT_RGB24;
|
||||
mBpp = 3;
|
||||
} else if ( colours == ZM_COLOUR_GRAY8 ) {
|
||||
subpixelorder = ZM_SUBPIX_ORDER_NONE;
|
||||
mImgPixFmt = AV_PIX_FMT_GRAY8;
|
||||
mBpp = 1;
|
||||
} else {
|
||||
Panic("Unexpected colours: %d", colours);
|
||||
}
|
||||
|
||||
if ( capture )
|
||||
Initialise();
|
||||
}
|
||||
|
||||
|
||||
VncCamera::~VncCamera() {
|
||||
if( capture )
|
||||
Terminate();
|
||||
}
|
||||
|
||||
void VncCamera::Initialise() {
|
||||
Debug(2, "Initializing Client");
|
||||
mRfb = rfbGetClient(8, 3, 4);
|
||||
|
||||
rfbClientSetClientData(mRfb, &TAG_0, &mVncData);
|
||||
rfbClientSetClientData(mRfb, &TAG_1, (void *)mPass.c_str());
|
||||
rfbClientSetClientData(mRfb, &TAG_2, (void *)mUser.c_str());
|
||||
|
||||
mRfb->GotFrameBufferUpdate = GotFrameBufferUpdateCallback;
|
||||
mRfb->GetPassword = GetPasswordCallback;
|
||||
mRfb->GetCredential = GetCredentialsCallback;
|
||||
|
||||
mRfb->programName = "Zoneminder VNC Monitor";
|
||||
mRfb->serverHost = strdup(mHost.c_str());
|
||||
mRfb->serverPort = atoi(mPort.c_str());
|
||||
rfbInitClient(mRfb, 0, nullptr);
|
||||
scale.init();
|
||||
}
|
||||
|
||||
void VncCamera::Terminate() {
|
||||
if(mRfb->frameBuffer)
|
||||
free(mRfb->frameBuffer);
|
||||
rfbClientCleanup(mRfb);
|
||||
return;
|
||||
}
|
||||
|
||||
int VncCamera::PrimeCapture() {
|
||||
Info("Priming capture from %s", mHost.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
int VncCamera::PreCapture() {
|
||||
Debug(2, "PreCapture");
|
||||
WaitForMessage(mRfb, 500);
|
||||
rfbBool res = HandleRFBServerMessage(mRfb);
|
||||
return res == TRUE ? 1 : -1 ;
|
||||
}
|
||||
|
||||
int VncCamera::Capture(Image &image) {
|
||||
Debug(2, "Capturing");
|
||||
uint8_t *directbuffer = image.WriteBuffer(width, height, colours, subpixelorder);
|
||||
scale.Convert(mVncData.buffer, mRfb->si.framebufferHeight * mRfb->si.framebufferWidth * 4, directbuffer, width * height * mBpp, AV_PIX_FMT_RGBA, mImgPixFmt, mRfb->si.framebufferWidth, mRfb->si.framebufferHeight, width, height);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int VncCamera::PostCapture() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int VncCamera::CaptureAndRecord(Image &image, timeval recording, char* event_directory) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int VncCamera::Close() {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,62 @@
|
|||
|
||||
#ifndef ZN_LIBVNC_CAMERA_H
|
||||
#define ZN_LIBVNC_CAMERA_H
|
||||
|
||||
#include "zm_buffer.h"
|
||||
#include "zm_camera.h"
|
||||
#include "zm_thread.h"
|
||||
#include "zm_swscale.h"
|
||||
|
||||
#if HAVE_LIBVNC
|
||||
#include <rfb/rfbclient.h>
|
||||
// Used by vnc callbacks
|
||||
struct VncPrivateData
|
||||
{
|
||||
uint8_t *buffer;
|
||||
uint8_t width;
|
||||
uint8_t height;
|
||||
};
|
||||
|
||||
class VncCamera : public Camera {
|
||||
protected:
|
||||
rfbClient *mRfb;
|
||||
VncPrivateData mVncData;
|
||||
int mBpp;
|
||||
SWScale scale;
|
||||
AVPixelFormat mImgPixFmt;
|
||||
std::string mHost;
|
||||
std::string mPort;
|
||||
std::string mUser;
|
||||
std::string mPass;
|
||||
public:
|
||||
VncCamera(
|
||||
unsigned int p_monitor_id,
|
||||
const std::string &host,
|
||||
const std::string &port,
|
||||
const std::string &user,
|
||||
const std::string &pass,
|
||||
int p_width,
|
||||
int p_height,
|
||||
int p_colours,
|
||||
int p_brightness,
|
||||
int p_contrast,
|
||||
int p_hue,
|
||||
int p_colour,
|
||||
bool p_capture,
|
||||
bool p_record_audio );
|
||||
|
||||
~VncCamera();
|
||||
|
||||
void Initialise();
|
||||
void Terminate();
|
||||
|
||||
int PreCapture();
|
||||
int PrimeCapture();
|
||||
int Capture( Image &image );
|
||||
int PostCapture();
|
||||
int CaptureAndRecord( Image &image, timeval recording, char* event_directory );
|
||||
int Close();
|
||||
};
|
||||
|
||||
#endif // HAVE_LIBVNC
|
||||
#endif // ZN_LIBVNC_CAMERA_H
|
|
@ -55,7 +55,7 @@ static _AVPIXELFORMAT getFfPixFormatFromV4lPalette(int v4l_version, int palette)
|
|||
|
||||
#if ZM_HAS_V4L2
|
||||
if ( v4l_version == 2 ) {
|
||||
switch( palette ) {
|
||||
switch ( palette ) {
|
||||
#if defined(V4L2_PIX_FMT_RGB444) && defined(AV_PIX_FMT_RGB444)
|
||||
case V4L2_PIX_FMT_RGB444 :
|
||||
pixFormat = AV_PIX_FMT_RGB444;
|
||||
|
@ -745,12 +745,12 @@ void LocalCamera::Initialise() {
|
|||
|
||||
Debug(4,
|
||||
" v4l2_data.fmt.type = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.width = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.height = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.width = %d\n"
|
||||
" v4l2_data.fmt.fmt.pix.height = %d\n"
|
||||
" v4l2_data.fmt.fmt.pix.pixelformat = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.field = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.bytesperline = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.sizeimage = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.bytesperline = %d\n"
|
||||
" v4l2_data.fmt.fmt.pix.sizeimage = %d\n"
|
||||
" v4l2_data.fmt.fmt.pix.colorspace = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.priv = %08x\n"
|
||||
, v4l2_data.fmt.type
|
||||
|
@ -788,12 +788,12 @@ void LocalCamera::Initialise() {
|
|||
/* Note VIDIOC_S_FMT may change width and height. */
|
||||
Debug(4,
|
||||
" v4l2_data.fmt.type = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.width = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.height = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.width = %d\n"
|
||||
" v4l2_data.fmt.fmt.pix.height = %d\n"
|
||||
" v4l2_data.fmt.fmt.pix.pixelformat = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.field = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.bytesperline = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.sizeimage = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.bytesperline = %d\n"
|
||||
" v4l2_data.fmt.fmt.pix.sizeimage = %d\n"
|
||||
" v4l2_data.fmt.fmt.pix.colorspace = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.priv = %08x\n"
|
||||
, v4l2_data.fmt.type
|
||||
|
|
|
@ -536,8 +536,11 @@ void Logger::logPrint(bool hex, const char * const filepath, const int line, con
|
|||
fflush(stdout);
|
||||
}
|
||||
if ( level <= mFileLevel ) {
|
||||
if ( !mLogFileFP )
|
||||
if ( !mLogFileFP ) {
|
||||
log_mutex.unlock();
|
||||
openFile();
|
||||
log_mutex.lock();
|
||||
}
|
||||
if ( mLogFileFP ) {
|
||||
fputs(logString, mLogFileFP);
|
||||
if ( mFlush )
|
||||
|
|
|
@ -51,6 +51,9 @@
|
|||
#if HAVE_LIBCURL
|
||||
#include "zm_curl_camera.h"
|
||||
#endif // HAVE_LIBCURL
|
||||
#if HAVE_LIBVNC
|
||||
#include "zm_libvnc_camera.h"
|
||||
#endif // HAVE_LIBVNC
|
||||
|
||||
#if ZM_MEM_MAPPED
|
||||
#include <sys/mman.h>
|
||||
|
@ -89,6 +92,7 @@ std::string CameraType_Strings[] = {
|
|||
"Ffmpeg",
|
||||
"LibVLC",
|
||||
"CURL",
|
||||
"VNC",
|
||||
};
|
||||
|
||||
|
||||
|
@ -2332,6 +2336,27 @@ Monitor *Monitor::Load(MYSQL_ROW dbrow, bool load_zones, Purpose purpose) {
|
|||
#else // HAVE_LIBCURL
|
||||
Fatal("You must have libcurl installed to use ffmpeg cameras for monitor %d", id);
|
||||
#endif // HAVE_LIBCURL
|
||||
} else if ( type == "VNC" ) {
|
||||
#if HAVE_LIBVNC
|
||||
camera = new VncCamera(
|
||||
id,
|
||||
host.c_str(),
|
||||
port.c_str(),
|
||||
user.c_str(),
|
||||
pass.c_str(),
|
||||
width,
|
||||
height,
|
||||
colours,
|
||||
brightness,
|
||||
contrast,
|
||||
hue,
|
||||
colour,
|
||||
purpose==CAPTURE,
|
||||
record_audio
|
||||
);
|
||||
#else // HAVE_LIBVNC
|
||||
Fatal("You must have libvnc installed to use VNC cameras for monitor id %d", id);
|
||||
#endif // HAVE_LIBVNC
|
||||
} else {
|
||||
Fatal("Bogus monitor type '%s' for monitor %d", type.c_str(), id);
|
||||
} // end if type
|
||||
|
|
|
@ -75,6 +75,7 @@ public:
|
|||
FFMPEG,
|
||||
LIBVLC,
|
||||
CURL,
|
||||
VNC,
|
||||
} CameraType;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -26,11 +26,9 @@
|
|||
#include <cmath>
|
||||
#endif
|
||||
|
||||
void Polygon::calcArea()
|
||||
{
|
||||
void Polygon::calcArea() {
|
||||
double float_area = 0.0L;
|
||||
for ( int i = 0, j = n_coords-1; i < n_coords; j = i++ )
|
||||
{
|
||||
for ( int i = 0, j = n_coords-1; i < n_coords; j = i++ ) {
|
||||
double trap_area = ((coords[i].X()-coords[j].X())*((coords[i].Y()+coords[j].Y())))/2.0L;
|
||||
float_area += trap_area;
|
||||
//printf( "%.2f (%.2f)\n", float_area, trap_area );
|
||||
|
@ -38,13 +36,11 @@ void Polygon::calcArea()
|
|||
area = (int)round(fabs(float_area));
|
||||
}
|
||||
|
||||
void Polygon::calcCentre()
|
||||
{
|
||||
void Polygon::calcCentre() {
|
||||
if ( !area && n_coords )
|
||||
calcArea();
|
||||
double float_x = 0.0L, float_y = 0.0L;
|
||||
for ( int i = 0, j = n_coords-1; i < n_coords; j = i++ )
|
||||
{
|
||||
for ( int i = 0, j = n_coords-1; i < n_coords; j = i++ ) {
|
||||
float_x += ((coords[i].Y()-coords[j].Y())*((coords[i].X()*2)+(coords[i].X()*coords[j].X())+(coords[j].X()*2)));
|
||||
float_y += ((coords[j].X()-coords[i].X())*((coords[i].Y()*2)+(coords[i].Y()*coords[j].Y())+(coords[j].Y()*2)));
|
||||
}
|
||||
|
@ -54,16 +50,14 @@ void Polygon::calcCentre()
|
|||
centre = Coord( (int)round(float_x), (int)round(float_y) );
|
||||
}
|
||||
|
||||
Polygon::Polygon( int p_n_coords, const Coord *p_coords ) : n_coords( p_n_coords )
|
||||
{
|
||||
Polygon::Polygon(int p_n_coords, const Coord *p_coords) : n_coords( p_n_coords ) {
|
||||
coords = new Coord[n_coords];
|
||||
|
||||
int min_x = -1;
|
||||
int max_x = -1;
|
||||
int min_y = -1;
|
||||
int max_y = -1;
|
||||
for( int i = 0; i < n_coords; i++ )
|
||||
{
|
||||
for ( int i = 0; i < n_coords; i++ ) {
|
||||
coords[i] = p_coords[i];
|
||||
if ( min_x == -1 || coords[i].X() < min_x )
|
||||
min_x = coords[i].X();
|
||||
|
@ -79,38 +73,36 @@ Polygon::Polygon( int p_n_coords, const Coord *p_coords ) : n_coords( p_n_coords
|
|||
calcCentre();
|
||||
}
|
||||
|
||||
Polygon::Polygon( const Polygon &p_polygon ) : n_coords( p_polygon.n_coords ), extent( p_polygon.extent ), area( p_polygon.area ), centre( p_polygon.centre )
|
||||
Polygon::Polygon( const Polygon &p_polygon ) :
|
||||
n_coords(p_polygon.n_coords),
|
||||
extent(p_polygon.extent),
|
||||
area(p_polygon.area),
|
||||
centre(p_polygon.centre)
|
||||
{
|
||||
coords = new Coord[n_coords];
|
||||
for( int i = 0; i < n_coords; i++ )
|
||||
{
|
||||
for( int i = 0; i < n_coords; i++ ) {
|
||||
coords[i] = p_polygon.coords[i];
|
||||
}
|
||||
}
|
||||
|
||||
Polygon &Polygon::operator=( const Polygon &p_polygon )
|
||||
{
|
||||
if ( n_coords < p_polygon.n_coords )
|
||||
{
|
||||
Polygon &Polygon::operator=( const Polygon &p_polygon ) {
|
||||
if ( n_coords < p_polygon.n_coords ) {
|
||||
delete[] coords;
|
||||
coords = new Coord[p_polygon.n_coords];
|
||||
}
|
||||
n_coords = p_polygon.n_coords;
|
||||
for( int i = 0; i < n_coords; i++ )
|
||||
{
|
||||
for ( int i = 0; i < n_coords; i++ ) {
|
||||
coords[i] = p_polygon.coords[i];
|
||||
}
|
||||
extent = p_polygon.extent;
|
||||
area = p_polygon.area;
|
||||
centre = p_polygon.centre;
|
||||
return( *this );
|
||||
return *this ;
|
||||
}
|
||||
|
||||
bool Polygon::isInside( const Coord &coord ) const
|
||||
{
|
||||
bool Polygon::isInside( const Coord &coord ) const {
|
||||
bool inside = false;
|
||||
for ( int i = 0, j = n_coords-1; i < n_coords; j = i++ )
|
||||
{
|
||||
for ( int i = 0, j = n_coords-1; i < n_coords; j = i++ ) {
|
||||
if ( (((coords[i].Y() <= coord.Y()) && (coord.Y() < coords[j].Y()) )
|
||||
|| ((coords[j].Y() <= coord.Y()) && (coord.Y() < coords[i].Y())))
|
||||
&& (coord.X() < (coords[j].X() - coords[i].X()) * (coord.Y() - coords[i].Y()) / (coords[j].Y() - coords[i].Y()) + coords[i].X()))
|
||||
|
@ -118,5 +110,5 @@ bool Polygon::isInside( const Coord &coord ) const
|
|||
inside = !inside;
|
||||
}
|
||||
}
|
||||
return( inside );
|
||||
return inside;
|
||||
}
|
||||
|
|
|
@ -41,13 +41,13 @@ protected:
|
|||
static int CompareYX( const void *p1, const void *p2 ) {
|
||||
const Edge *e1 = reinterpret_cast<const Edge *>(p1), *e2 = reinterpret_cast<const Edge *>(p2);
|
||||
if ( e1->min_y == e2->min_y )
|
||||
return( int(e1->min_x - e2->min_x) );
|
||||
return int(e1->min_x - e2->min_x);
|
||||
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 ) {
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -83,32 +83,32 @@ protected:
|
|||
void calcCentre();
|
||||
|
||||
public:
|
||||
inline Polygon() : n_coords( 0 ), coords( 0 ), area( 0 ), edges(0), slices(0) {
|
||||
inline Polygon() : n_coords(0), coords(0), area(0), edges(0), slices(0) {
|
||||
}
|
||||
Polygon( int p_n_coords, const Coord *p_coords );
|
||||
Polygon( const Polygon &p_polygon );
|
||||
Polygon(int p_n_coords, const Coord *p_coords);
|
||||
Polygon(const Polygon &p_polygon);
|
||||
~Polygon() {
|
||||
delete[] coords;
|
||||
}
|
||||
|
||||
Polygon &operator=( const Polygon &p_polygon );
|
||||
|
||||
inline int getNumCoords() const { return( n_coords ); }
|
||||
inline int getNumCoords() const { return n_coords; }
|
||||
inline const Coord &getCoord( int index ) const {
|
||||
return( coords[index] );
|
||||
return coords[index];
|
||||
}
|
||||
|
||||
inline const Box &Extent() const { return( extent ); }
|
||||
inline int LoX() const { return( extent.LoX() ); }
|
||||
inline int HiX() const { return( extent.HiX() ); }
|
||||
inline int LoY() const { return( extent.LoY() ); }
|
||||
inline int HiY() const { return( extent.HiY() ); }
|
||||
inline int Width() const { return( extent.Width() ); }
|
||||
inline int Height() const { return( extent.Height() ); }
|
||||
inline const Box &Extent() const { return extent; }
|
||||
inline int LoX() const { return extent.LoX(); }
|
||||
inline int HiX() const { return extent.HiX(); }
|
||||
inline int LoY() const { return extent.LoY(); }
|
||||
inline int HiY() const { return extent.HiY(); }
|
||||
inline int Width() const { return extent.Width(); }
|
||||
inline int Height() const { return extent.Height(); }
|
||||
|
||||
inline int Area() const { return( area ); }
|
||||
inline int Area() const { return area; }
|
||||
inline const Coord &Centre() const {
|
||||
return( centre );
|
||||
return centre;
|
||||
}
|
||||
bool isInside( const Coord &coord ) const;
|
||||
};
|
||||
|
|
|
@ -234,7 +234,7 @@ int RemoteCameraHttp::ReadData( Buffer &buffer, unsigned int bytes_expected ) {
|
|||
} else {
|
||||
if ( ioctl( sd, FIONREAD, &total_bytes_to_read ) < 0 ) {
|
||||
Error( "Can't ioctl(): %s", strerror(errno) );
|
||||
return( -1 );
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( total_bytes_to_read == 0 ) {
|
||||
|
@ -242,20 +242,20 @@ int RemoteCameraHttp::ReadData( Buffer &buffer, unsigned int bytes_expected ) {
|
|||
int error = 0;
|
||||
socklen_t len = sizeof (error);
|
||||
int retval = getsockopt( sd, SOL_SOCKET, SO_ERROR, &error, &len );
|
||||
if(retval != 0 ) {
|
||||
if ( retval != 0 ) {
|
||||
Debug( 1, "error getting socket error code %s", strerror(retval) );
|
||||
}
|
||||
if (error != 0) {
|
||||
if ( error != 0 ) {
|
||||
return -1;
|
||||
}
|
||||
// Case where we are grabbing a single jpg, but no content-length was given, so the expectation is that we read until close.
|
||||
return( 0 );
|
||||
return 0;
|
||||
}
|
||||
// If socket is closed locally, then select will fail, but if it is closed remotely
|
||||
// then we have an exception on our socket.. but no data.
|
||||
Debug( 3, "Socket closed remotely" );
|
||||
Debug(3, "Socket closed remotely");
|
||||
//Disconnect(); // Disconnect is done outside of ReadData now.
|
||||
return( -1 );
|
||||
return -1;
|
||||
}
|
||||
|
||||
// There can be lots of bytes available. I've seen 4MB or more. This will vastly inflate our buffer size unnecessarily.
|
||||
|
@ -292,6 +292,18 @@ int RemoteCameraHttp::ReadData( Buffer &buffer, unsigned int bytes_expected ) {
|
|||
return total_bytes_read;
|
||||
}
|
||||
|
||||
int RemoteCameraHttp::GetData() {
|
||||
time_t start_time = time(NULL);
|
||||
int buffer_len = 0;
|
||||
while ( !( buffer_len = ReadData(buffer) ) ) {
|
||||
if ( zm_terminate || ( start_time - time(NULL) < ZM_WATCH_MAX_DELAY ))
|
||||
return -1;
|
||||
Debug(4, "Timeout waiting for REGEXP HEADER");
|
||||
usleep(100000);
|
||||
}
|
||||
return buffer_len;
|
||||
}
|
||||
|
||||
int RemoteCameraHttp::GetResponse() {
|
||||
int buffer_len;
|
||||
#if HAVE_LIBPCRE
|
||||
|
@ -314,9 +326,7 @@ int RemoteCameraHttp::GetResponse() {
|
|||
switch( state ) {
|
||||
case HEADER :
|
||||
{
|
||||
while ( !( buffer_len = ReadData(buffer) ) && !zm_terminate ) {
|
||||
Debug(4, "Timeout waiting for REGEXP HEADER");
|
||||
}
|
||||
buffer_len = GetData();
|
||||
if ( buffer_len < 0 ) {
|
||||
Error("Unable to read header data");
|
||||
return -1;
|
||||
|
@ -478,9 +488,7 @@ int RemoteCameraHttp::GetResponse() {
|
|||
else
|
||||
{
|
||||
Debug( 3, "Unable to extract subheader from stream, retrying" );
|
||||
while ( !( buffer_len = ReadData(buffer) ) && !zm_terminate ) {
|
||||
Debug(4, "Timeout waiting to extract subheader");
|
||||
}
|
||||
buffer_len = GetData();
|
||||
if ( buffer_len < 0 ) {
|
||||
Error( "Unable to extract subheader data" );
|
||||
return( -1 );
|
||||
|
@ -521,7 +529,7 @@ int RemoteCameraHttp::GetResponse() {
|
|||
while ( ((long)buffer.size() < content_length ) && ! zm_terminate )
|
||||
{
|
||||
Debug(3, "Need more data buffer %d < content length %d", buffer.size(), content_length );
|
||||
int bytes_read = ReadData( buffer );
|
||||
int bytes_read = GetData();
|
||||
|
||||
if ( bytes_read < 0 ) {
|
||||
Error( "Unable to read content" );
|
||||
|
@ -535,9 +543,7 @@ int RemoteCameraHttp::GetResponse() {
|
|||
{
|
||||
while ( !content_length )
|
||||
{
|
||||
while ( !( buffer_len = ReadData(buffer) ) && !zm_terminate ) {
|
||||
Debug(4, "Timeout waiting for content");
|
||||
}
|
||||
buffer_len = GetData();
|
||||
if ( buffer_len < 0 ) {
|
||||
Error( "Unable to read content" );
|
||||
return( -1 );
|
||||
|
@ -652,9 +658,7 @@ int RemoteCameraHttp::GetResponse() {
|
|||
}
|
||||
case HEADERCONT :
|
||||
{
|
||||
while ( !( buffer_len = ReadData(buffer) ) && !zm_terminate ) {
|
||||
Debug(1, "Timeout waiting for HEADERCONT");
|
||||
}
|
||||
buffer_len = GetData();
|
||||
if ( buffer_len < 0 ) {
|
||||
Error("Unable to read header");
|
||||
return -1;
|
||||
|
@ -939,9 +943,7 @@ int RemoteCameraHttp::GetResponse() {
|
|||
state = CONTENT;
|
||||
} else {
|
||||
Debug( 3, "Unable to extract subheader from stream, retrying" );
|
||||
while ( !( buffer_len = ReadData(buffer) ) &&!zm_terminate ) {
|
||||
Debug(1, "Timeout waiting to extra subheader non regexp");
|
||||
}
|
||||
buffer_len = GetData();
|
||||
if ( buffer_len < 0 ) {
|
||||
Error( "Unable to read subheader" );
|
||||
return( -1 );
|
||||
|
@ -981,7 +983,7 @@ int RemoteCameraHttp::GetResponse() {
|
|||
if ( content_length ) {
|
||||
while ( ( (long)buffer.size() < content_length ) && ! zm_terminate ) {
|
||||
Debug(4, "getting more data");
|
||||
int bytes_read = ReadData(buffer);
|
||||
int bytes_read = GetData();
|
||||
if ( bytes_read < 0 ) {
|
||||
Error("Unable to read content");
|
||||
return -1;
|
||||
|
@ -994,8 +996,7 @@ int RemoteCameraHttp::GetResponse() {
|
|||
while ( !content_length && !zm_terminate ) {
|
||||
Debug(4, "!content_length, ReadData");
|
||||
buffer_len = ReadData( buffer );
|
||||
if ( buffer_len < 0 )
|
||||
{
|
||||
if ( buffer_len < 0 ) {
|
||||
Error( "Unable to read content" );
|
||||
return( -1 );
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ public:
|
|||
int Disconnect();
|
||||
int SendRequest();
|
||||
int ReadData( Buffer &buffer, unsigned int bytes_expected=0 );
|
||||
int GetData();
|
||||
int GetResponse();
|
||||
int PreCapture();
|
||||
int Capture( Image &image );
|
||||
|
|
|
@ -84,7 +84,7 @@ int SWScale::SetDefaults(enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height) {
|
||||
int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height, unsigned int new_width, unsigned int new_height) {
|
||||
/* Parameter checking */
|
||||
if(in_buffer == NULL || out_buffer == NULL) {
|
||||
Error("NULL Input or output buffer");
|
||||
|
@ -94,7 +94,7 @@ int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint
|
|||
// Error("Invalid input or output pixel formats");
|
||||
// return -2;
|
||||
// }
|
||||
if (!width || !height) {
|
||||
if (!width || !height || !new_height || !new_width) {
|
||||
Error("Invalid width or height");
|
||||
return -3;
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint
|
|||
|
||||
/* Check the buffer sizes */
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
size_t insize = av_image_get_buffer_size(in_pf, width, height,1);
|
||||
size_t insize = av_image_get_buffer_size(in_pf, width, height, 1);
|
||||
#else
|
||||
size_t insize = avpicture_get_size(in_pf, width, height);
|
||||
#endif
|
||||
|
@ -120,9 +120,9 @@ int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint
|
|||
return -4;
|
||||
}
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
size_t outsize = av_image_get_buffer_size(out_pf, width, height,1);
|
||||
size_t outsize = av_image_get_buffer_size(out_pf, new_width, new_height, 1);
|
||||
#else
|
||||
size_t outsize = avpicture_get_size(out_pf, width, height);
|
||||
size_t outsize = avpicture_get_size(out_pf, new_width, new_height);
|
||||
#endif
|
||||
|
||||
if(outsize < out_buffer_size) {
|
||||
|
@ -131,7 +131,7 @@ int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint
|
|||
}
|
||||
|
||||
/* Get the context */
|
||||
swscale_ctx = sws_getCachedContext( swscale_ctx, width, height, in_pf, width, height, out_pf, SWS_FAST_BILINEAR, NULL, NULL, NULL );
|
||||
swscale_ctx = sws_getCachedContext( swscale_ctx, width, height, in_pf, new_width, new_height, out_pf, SWS_FAST_BILINEAR, NULL, NULL, NULL );
|
||||
if(swscale_ctx == NULL) {
|
||||
Error("Failed getting swscale context");
|
||||
return -6;
|
||||
|
@ -150,10 +150,10 @@ int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint
|
|||
}
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
if (av_image_fill_arrays(output_avframe->data, output_avframe->linesize,
|
||||
out_buffer, out_pf, width, height, 1) <= 0) {
|
||||
out_buffer, out_pf, new_width, new_height, 1) <= 0) {
|
||||
#else
|
||||
if (avpicture_fill((AVPicture*) output_avframe, out_buffer, out_pf, width,
|
||||
height) <= 0) {
|
||||
if (avpicture_fill((AVPicture*) output_avframe, out_buffer, out_pf, new_width,
|
||||
new_height) <= 0) {
|
||||
#endif
|
||||
Error("Failed filling output frame with output buffer");
|
||||
return -8;
|
||||
|
@ -168,6 +168,10 @@ int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint
|
|||
return 0;
|
||||
}
|
||||
|
||||
int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height) {
|
||||
return Convert(in_buffer, in_buffer_size, out_buffer, out_buffer_size, in_pf, out_pf, width, height, width, height);
|
||||
}
|
||||
|
||||
int SWScale::Convert(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height) {
|
||||
if(img->Width() != width) {
|
||||
Error("Source image width differs. Source: %d Output: %d",img->Width(), width);
|
||||
|
|
|
@ -10,13 +10,14 @@ class SWScale {
|
|||
public:
|
||||
SWScale();
|
||||
~SWScale();
|
||||
bool init();
|
||||
bool init();
|
||||
int SetDefaults(enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height);
|
||||
int ConvertDefaults(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size);
|
||||
int ConvertDefaults(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size);
|
||||
int Convert(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height);
|
||||
int Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height);
|
||||
|
||||
int Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height, unsigned int new_width, unsigned int new_height);
|
||||
|
||||
protected:
|
||||
bool gotdefaults;
|
||||
struct SwsContext* swscale_ctx;
|
||||
|
|
181
src/zm_user.cpp
181
src/zm_user.cpp
|
@ -1,21 +1,21 @@
|
|||
/*
|
||||
* ZoneMinder regular expression class implementation, $Date$, $Revision$
|
||||
* Copyright (C) 2001-2008 Philip Coombes
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
*/
|
||||
|
||||
#include "zm.h"
|
||||
#include "zm_db.h"
|
||||
|
@ -26,6 +26,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <utility>
|
||||
|
||||
#if HAVE_GNUTLS_GNUTLS_H
|
||||
#include <gnutls/gnutls.h>
|
||||
|
@ -35,7 +36,7 @@
|
|||
#include <gcrypt.h>
|
||||
#elif HAVE_LIBCRYPTO
|
||||
#include <openssl/md5.h>
|
||||
#endif // HAVE_L || HAVE_LIBCRYPTO
|
||||
#endif // HAVE_GCRYPT_H || HAVE_LIBCRYPTO
|
||||
|
||||
#include "zm_utils.h"
|
||||
#include "zm_crypt.h"
|
||||
|
@ -52,7 +53,7 @@ User::User(const MYSQL_ROW &dbrow) {
|
|||
id = atoi(dbrow[index++]);
|
||||
strncpy(username, dbrow[index++], sizeof(username)-1);
|
||||
strncpy(password, dbrow[index++], sizeof(password)-1);
|
||||
enabled = (bool)atoi(dbrow[index++]);
|
||||
enabled = static_cast<bool>atoi(dbrow[index++]);
|
||||
stream = (Permission)atoi(dbrow[index++]);
|
||||
events = (Permission)atoi(dbrow[index++]);
|
||||
control = (Permission)atoi(dbrow[index++]);
|
||||
|
@ -61,7 +62,7 @@ User::User(const MYSQL_ROW &dbrow) {
|
|||
char *monitor_ids_str = dbrow[index++];
|
||||
if ( monitor_ids_str && *monitor_ids_str ) {
|
||||
StringVector ids = split(monitor_ids_str, ",");
|
||||
for( StringVector::iterator i = ids.begin(); i < ids.end(); ++i ) {
|
||||
for ( StringVector::iterator i = ids.begin(); i < ids.end(); ++i ) {
|
||||
monitor_ids.push_back(atoi((*i).c_str()));
|
||||
}
|
||||
}
|
||||
|
@ -72,7 +73,7 @@ User::~User() {
|
|||
}
|
||||
|
||||
void User::Copy(const User &u) {
|
||||
id=u.id;
|
||||
id = u.id;
|
||||
strncpy(username, u.username, sizeof(username)-1);
|
||||
strncpy(password, u.password, sizeof(password)-1);
|
||||
enabled = u.enabled;
|
||||
|
@ -87,8 +88,9 @@ void User::Copy(const User &u) {
|
|||
bool User::canAccess(int monitor_id) {
|
||||
if ( monitor_ids.empty() )
|
||||
return true;
|
||||
|
||||
for ( std::vector<int>::iterator i = monitor_ids.begin(); i != monitor_ids.end(); ++i ) {
|
||||
|
||||
for ( std::vector<int>::iterator i = monitor_ids.begin();
|
||||
i != monitor_ids.end(); ++i ) {
|
||||
if ( *i == monitor_id ) {
|
||||
return true;
|
||||
}
|
||||
|
@ -103,16 +105,20 @@ User *zmLoadUser(const char *username, const char *password) {
|
|||
int username_length = strlen(username);
|
||||
char *safer_username = new char[(username_length * 2) + 1];
|
||||
|
||||
// According to docs, size of safer_whatever must be 2*length+1 due to unicode conversions + null terminator.
|
||||
// According to docs, size of safer_whatever must be 2*length+1
|
||||
// due to unicode conversions + null terminator.
|
||||
mysql_real_escape_string(&dbconn, safer_username, username, username_length);
|
||||
|
||||
snprintf(sql, sizeof(sql),
|
||||
"SELECT `Id`, `Username`, `Password`, `Enabled`, `Stream`+0, `Events`+0, `Control`+0, `Monitors`+0, `System`+0, `MonitorIds`"
|
||||
" FROM `Users` WHERE `Username` = '%s' AND `Enabled` = 1", safer_username);
|
||||
"SELECT `Id`, `Username`, `Password`, `Enabled`,"
|
||||
" `Stream`+0, `Events`+0, `Control`+0, `Monitors`+0, `System`+0,"
|
||||
" `MonitorIds`"
|
||||
" FROM `Users` WHERE `Username` = '%s' AND `Enabled` = 1",
|
||||
safer_username);
|
||||
|
||||
if ( mysql_query(&dbconn, sql) ) {
|
||||
Error("Can't run query: %s", mysql_error(&dbconn));
|
||||
exit(mysql_errno(&dbconn));
|
||||
exit(mysql_errno(&dbconn));
|
||||
}
|
||||
delete safer_username;
|
||||
|
||||
|
@ -136,45 +142,48 @@ User *zmLoadUser(const char *username, const char *password) {
|
|||
// relay type must be none
|
||||
return user;
|
||||
}
|
||||
|
||||
|
||||
if ( verifyPassword(username, password, user->getPassword()) ) {
|
||||
Info("Authenticated user '%s'", user->getUsername());
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
||||
Warning("Unable to authenticate user %s", username);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
User *zmLoadTokenUser (std::string jwt_token_str, bool use_remote_addr ) {
|
||||
User *zmLoadTokenUser(std::string jwt_token_str, bool use_remote_addr) {
|
||||
std::string key = config.auth_hash_secret;
|
||||
std::string remote_addr = "";
|
||||
|
||||
if (use_remote_addr) {
|
||||
remote_addr = std::string(getenv( "REMOTE_ADDR" ));
|
||||
|
||||
if ( use_remote_addr ) {
|
||||
remote_addr = std::string(getenv("REMOTE_ADDR"));
|
||||
if ( remote_addr == "" ) {
|
||||
Warning( "Can't determine remote address, using null" );
|
||||
Warning("Can't determine remote address, using null");
|
||||
remote_addr = "";
|
||||
}
|
||||
key += remote_addr;
|
||||
}
|
||||
|
||||
Debug (1,"Inside zmLoadTokenUser, formed key=%s", key.c_str());
|
||||
Debug(1, "Inside zmLoadTokenUser, formed key=%s", key.c_str());
|
||||
|
||||
std::pair<std::string, unsigned int> ans = verifyToken(jwt_token_str, key);
|
||||
std::string username = ans.first;
|
||||
unsigned int iat = ans.second;
|
||||
Debug (1,"retrieved user '%s' from token", username.c_str());
|
||||
Debug(1, "retrieved user '%s' from token", username.c_str());
|
||||
|
||||
if (username != "") {
|
||||
if ( username != "" ) {
|
||||
char sql[ZM_SQL_MED_BUFSIZ] = "";
|
||||
snprintf(sql, sizeof(sql),
|
||||
"SELECT `Id`, `Username`, `Password`, `Enabled`, `Stream`+0, `Events`+0, `Control`+0, `Monitors`+0, `System`+0, `MonitorIds`, `TokenMinExpiry`"
|
||||
" FROM `Users` WHERE `Username` = '%s' AND `Enabled` = 1", username.c_str() );
|
||||
"SELECT `Id`, `Username`, `Password`, `Enabled`,"
|
||||
" `Stream`+0, `Events`+0, `Control`+0, `Monitors`+0, `System`+0,"
|
||||
" `MonitorIds`, `TokenMinExpiry`"
|
||||
" FROM `Users` WHERE `Username` = '%s' AND `Enabled` = 1",
|
||||
username.c_str());
|
||||
|
||||
if ( mysql_query(&dbconn, sql) ) {
|
||||
Error("Can't run query: %s", mysql_error(&dbconn));
|
||||
exit(mysql_errno(&dbconn));
|
||||
exit(mysql_errno(&dbconn));
|
||||
}
|
||||
|
||||
MYSQL_RES *result = mysql_store_result(&dbconn);
|
||||
|
@ -192,70 +201,71 @@ User *zmLoadTokenUser (std::string jwt_token_str, bool use_remote_addr ) {
|
|||
|
||||
MYSQL_ROW dbrow = mysql_fetch_row(result);
|
||||
User *user = new User(dbrow);
|
||||
unsigned int stored_iat = strtoul(dbrow[10], NULL,0 );
|
||||
unsigned int stored_iat = strtoul(dbrow[10], NULL, 0);
|
||||
|
||||
if (stored_iat > iat ) { // admin revoked tokens
|
||||
if ( stored_iat > iat ) { // admin revoked tokens
|
||||
mysql_free_result(result);
|
||||
Error("Token was revoked for '%s'", username.c_str());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Debug (1,"Got stored expiry time of %u",stored_iat);
|
||||
Debug (1,"Authenticated user '%s' via token", username.c_str());
|
||||
Debug(1, "Authenticated user '%s' via token with last revoke time: %u",
|
||||
username.c_str(), stored_iat);
|
||||
mysql_free_result(result);
|
||||
return user;
|
||||
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
} // end User *zmLoadTokenUser(std::string jwt_token_str, bool use_remote_addr)
|
||||
|
||||
}
|
||||
|
||||
// Function to validate an authentication string
|
||||
User *zmLoadAuthUser( const char *auth, bool use_remote_addr ) {
|
||||
User *zmLoadAuthUser(const char *auth, bool use_remote_addr) {
|
||||
#if HAVE_DECL_MD5 || HAVE_DECL_GNUTLS_FINGERPRINT
|
||||
#ifdef HAVE_GCRYPT_H
|
||||
// Special initialisation for libgcrypt
|
||||
if ( !gcry_check_version( GCRYPT_VERSION ) ) {
|
||||
Fatal( "Unable to initialise libgcrypt" );
|
||||
if ( !gcry_check_version(GCRYPT_VERSION) ) {
|
||||
Fatal("Unable to initialise libgcrypt");
|
||||
}
|
||||
gcry_control( GCRYCTL_DISABLE_SECMEM, 0 );
|
||||
gcry_control( GCRYCTL_INITIALIZATION_FINISHED, 0 );
|
||||
#endif // HAVE_GCRYPT_H
|
||||
gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
|
||||
gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
|
||||
#endif // HAVE_GCRYPT_H
|
||||
|
||||
const char *remote_addr = "";
|
||||
if ( use_remote_addr ) {
|
||||
remote_addr = getenv( "REMOTE_ADDR" );
|
||||
remote_addr = getenv("REMOTE_ADDR");
|
||||
if ( !remote_addr ) {
|
||||
Warning( "Can't determine remote address, using null" );
|
||||
Warning("Can't determine remote address, using null");
|
||||
remote_addr = "";
|
||||
}
|
||||
}
|
||||
|
||||
Debug( 1, "Attempting to authenticate user from auth string '%s'", auth );
|
||||
Debug(1, "Attempting to authenticate user from auth string '%s'", auth);
|
||||
char sql[ZM_SQL_SML_BUFSIZ] = "";
|
||||
snprintf( sql, sizeof(sql), "SELECT `Id`, `Username`, `Password`, `Enabled`, `Stream`+0, `Events`+0, `Control`+0, `Monitors`+0, `System`+0, `MonitorIds` FROM `Users` WHERE `Enabled` = 1" );
|
||||
snprintf(sql, sizeof(sql),
|
||||
"SELECT `Id`, `Username`, `Password`, `Enabled`,"
|
||||
" `Stream`+0, `Events`+0, `Control`+0, `Monitors`+0, `System`+0,"
|
||||
" `MonitorIds` FROM `Users` WHERE `Enabled` = 1");
|
||||
|
||||
if ( mysql_query( &dbconn, sql ) ) {
|
||||
Error( "Can't run query: %s", mysql_error( &dbconn ) );
|
||||
exit( mysql_errno( &dbconn ) );
|
||||
if ( mysql_query(&dbconn, sql) ) {
|
||||
Error("Can't run query: %s", mysql_error(&dbconn));
|
||||
exit(mysql_errno(&dbconn));
|
||||
}
|
||||
|
||||
MYSQL_RES *result = mysql_store_result( &dbconn );
|
||||
MYSQL_RES *result = mysql_store_result(&dbconn);
|
||||
if ( !result ) {
|
||||
Error( "Can't use query result: %s", mysql_error( &dbconn ) );
|
||||
exit( mysql_errno( &dbconn ) );
|
||||
Error("Can't use query result: %s", mysql_error(&dbconn));
|
||||
exit(mysql_errno(&dbconn));
|
||||
}
|
||||
int n_users = mysql_num_rows( result );
|
||||
int n_users = mysql_num_rows(result);
|
||||
|
||||
if ( n_users < 1 ) {
|
||||
mysql_free_result( result );
|
||||
Warning( "Unable to authenticate user" );
|
||||
return( 0 );
|
||||
mysql_free_result(result);
|
||||
Warning("Unable to authenticate user");
|
||||
return 0;
|
||||
}
|
||||
|
||||
while( MYSQL_ROW dbrow = mysql_fetch_row( result ) ) {
|
||||
while ( MYSQL_ROW dbrow = mysql_fetch_row(result) ) {
|
||||
const char *user = dbrow[1];
|
||||
const char *pass = dbrow[2];
|
||||
|
||||
|
@ -264,20 +274,20 @@ User *zmLoadAuthUser( const char *auth, bool use_remote_addr ) {
|
|||
size_t md5len = 16;
|
||||
unsigned char md5sum[md5len];
|
||||
|
||||
time_t now = time( 0 );
|
||||
time_t now = time(0);
|
||||
unsigned int hours = config.auth_hash_ttl;
|
||||
|
||||
if ( ! hours ) {
|
||||
if ( !hours ) {
|
||||
Warning("No value set for ZM_AUTH_HASH_TTL. Defaulting to 2.");
|
||||
hours = 2;
|
||||
} else {
|
||||
Debug( 1, "AUTH_HASH_TTL is %d", hours );
|
||||
Debug(1, "AUTH_HASH_TTL is %d", hours);
|
||||
}
|
||||
|
||||
for ( unsigned int i = 0; i < hours; i++, now -= 3600 ) {
|
||||
struct tm *now_tm = localtime( &now );
|
||||
struct tm *now_tm = localtime(&now);
|
||||
|
||||
snprintf( auth_key, sizeof(auth_key), "%s%s%s%s%d%d%d%d",
|
||||
snprintf(auth_key, sizeof(auth_key), "%s%s%s%s%d%d%d%d",
|
||||
config.auth_hash_secret,
|
||||
user,
|
||||
pass,
|
||||
|
@ -285,50 +295,51 @@ User *zmLoadAuthUser( const char *auth, bool use_remote_addr ) {
|
|||
now_tm->tm_hour,
|
||||
now_tm->tm_mday,
|
||||
now_tm->tm_mon,
|
||||
now_tm->tm_year
|
||||
);
|
||||
now_tm->tm_year);
|
||||
|
||||
#if HAVE_DECL_MD5
|
||||
MD5( (unsigned char *)auth_key, strlen(auth_key), md5sum );
|
||||
MD5((unsigned char *)auth_key, strlen(auth_key), md5sum);
|
||||
#elif HAVE_DECL_GNUTLS_FINGERPRINT
|
||||
gnutls_datum_t md5data = { (unsigned char *)auth_key, strlen(auth_key) };
|
||||
gnutls_fingerprint( GNUTLS_DIG_MD5, &md5data, md5sum, &md5len );
|
||||
gnutls_fingerprint(GNUTLS_DIG_MD5, &md5data, md5sum, &md5len);
|
||||
#endif
|
||||
for ( unsigned int j = 0; j < md5len; j++ ) {
|
||||
snprintf(&auth_md5[2*j], 2, "%02x", md5sum[j]);
|
||||
}
|
||||
Debug( 1, "Checking auth_key '%s' -> auth_md5 '%s' == '%s'", auth_key, auth_md5, auth );
|
||||
Debug(1, "Checking auth_key '%s' -> auth_md5 '%s' == '%s'",
|
||||
auth_key, auth_md5, auth);
|
||||
|
||||
if ( !strcmp( auth, auth_md5 ) ) {
|
||||
if ( !strcmp(auth, auth_md5) ) {
|
||||
// We have a match
|
||||
User *user = new User( dbrow );
|
||||
Debug(1, "Authenticated user '%s'", user->getUsername() );
|
||||
mysql_free_result( result );
|
||||
return( user );
|
||||
User *user = new User(dbrow);
|
||||
Debug(1, "Authenticated user '%s'", user->getUsername());
|
||||
mysql_free_result(result);
|
||||
return user;
|
||||
} else {
|
||||
Debug(1, "No match for %s", auth );
|
||||
Debug(1, "No match for %s", auth);
|
||||
}
|
||||
}
|
||||
}
|
||||
mysql_free_result( result );
|
||||
#else // HAVE_DECL_MD5
|
||||
Error( "You need to build with gnutls or openssl installed to use hash based authentication" );
|
||||
#endif // HAVE_DECL_MD5
|
||||
Debug(1, "No user found for auth_key %s", auth );
|
||||
} // end foreach hour
|
||||
} // end foreach user
|
||||
mysql_free_result(result);
|
||||
#else // HAVE_DECL_MD5 || HAVE_DECL_GNUTLS_FINGERPRINT
|
||||
Error("You need to build with gnutls or openssl to use hash based auth");
|
||||
#endif // HAVE_DECL_MD5 || HAVE_DECL_GNUTLS_FINGERPRINT
|
||||
Debug(1, "No user found for auth_key %s", auth);
|
||||
return 0;
|
||||
}
|
||||
} // end User *zmLoadAuthUser( const char *auth, bool use_remote_addr )
|
||||
|
||||
//Function to check Username length
|
||||
bool checkUser ( const char *username) {
|
||||
if ( ! username )
|
||||
// Function to check Username length
|
||||
bool checkUser(const char *username) {
|
||||
if ( !username )
|
||||
return false;
|
||||
if ( strlen(username) > 32 )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
//Function to check password length
|
||||
bool checkPass (const char *password) {
|
||||
|
||||
// Function to check password length
|
||||
bool checkPass(const char *password) {
|
||||
if ( !password )
|
||||
return false;
|
||||
if ( strlen(password) > 64 )
|
||||
|
|
|
@ -409,7 +409,7 @@ bool VideoStore::open() {
|
|||
AVDictionary *opts = NULL;
|
||||
// av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0);
|
||||
// Shiboleth reports that this may break seeking in mp4 before it downloads
|
||||
//av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0);
|
||||
av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0);
|
||||
// av_dict_set(&opts, "movflags",
|
||||
// "frag_keyframe+empty_moov+default_base_moof", 0);
|
||||
if ( (ret = avformat_write_header(oc, &opts)) < 0 ) {
|
||||
|
|
22
src/zms.cpp
22
src/zms.cpp
|
@ -106,9 +106,9 @@ int main(int argc, const char *argv[]) {
|
|||
|
||||
for ( int p = 0; p < parm_no; p++ ) {
|
||||
char *name = strtok(parms[p], "=");
|
||||
char *value = strtok(NULL, "=");
|
||||
char const *value = strtok(NULL, "=");
|
||||
if ( !value )
|
||||
value = (char *)"";
|
||||
value = "";
|
||||
if ( !strcmp(name, "source") ) {
|
||||
source = !strcmp(value, "event")?ZMS_EVENT:ZMS_MONITOR;
|
||||
if ( !strcmp(value, "fifo") )
|
||||
|
@ -127,10 +127,10 @@ int main(int argc, const char *argv[]) {
|
|||
} else if ( !strcmp(name, "time") ) {
|
||||
event_time = atoi(value);
|
||||
} else if ( !strcmp(name, "event") ) {
|
||||
event_id = strtoull(value, (char **)NULL, 10);
|
||||
event_id = strtoull(value, NULL, 10);
|
||||
source = ZMS_EVENT;
|
||||
} else if ( !strcmp(name, "frame") ) {
|
||||
frame_id = strtoull(value, (char **)NULL, 10);
|
||||
frame_id = strtoull(value, NULL, 10);
|
||||
source = ZMS_EVENT;
|
||||
} else if ( !strcmp(name, "scale") ) {
|
||||
scale = atoi(value);
|
||||
|
@ -159,7 +159,7 @@ int main(int argc, const char *argv[]) {
|
|||
} else if ( !strcmp(name, "buffer") ) {
|
||||
playback_buffer = atoi(value);
|
||||
} else if ( !strcmp(name, "auth") ) {
|
||||
strncpy( auth, value, sizeof(auth)-1 );
|
||||
strncpy(auth, value, sizeof(auth)-1);
|
||||
} else if ( !strcmp(name, "token") ) {
|
||||
jwt_token_str = value;
|
||||
Debug(1, "ZMS: JWT token found: %s", jwt_token_str.c_str());
|
||||
|
@ -237,11 +237,13 @@ int main(int argc, const char *argv[]) {
|
|||
|
||||
time_t now = time(0);
|
||||
char date_string[64];
|
||||
strftime(date_string, sizeof(date_string)-1, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&now));
|
||||
strftime(date_string, sizeof(date_string)-1,
|
||||
"%a, %d %b %Y %H:%M:%S GMT", gmtime(&now));
|
||||
|
||||
fprintf(stdout, "Last-Modified: %s\r\n", date_string);
|
||||
fputs("Last-Modified: ", stdout);
|
||||
fputs(date_string, stdout);
|
||||
fputs(
|
||||
"Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n"
|
||||
"\r\nExpires: Mon, 26 Jul 1997 05:00:00 GMT\r\n"
|
||||
"Cache-Control: no-store, no-cache, must-revalidate\r\n"
|
||||
"Cache-Control: post-check=0, pre-check=0\r\n"
|
||||
"Pragma: no-cache\r\n",
|
||||
|
@ -279,7 +281,9 @@ int main(int argc, const char *argv[]) {
|
|||
stream.setStreamType(MonitorStream::STREAM_MPEG);
|
||||
#else // HAVE_LIBAVCODEC
|
||||
Error("MPEG streaming of '%s' attempted while disabled", query);
|
||||
fprintf(stderr, "MPEG streaming is disabled.\nYou should configure with the --with-ffmpeg option and rebuild to use this functionality.\n");
|
||||
fprintf(stderr, "MPEG streaming is disabled.\n"
|
||||
"You should configure with the --with-ffmpeg"
|
||||
" option and rebuild to use this functionality.\n");
|
||||
logTerm();
|
||||
zmDbClose();
|
||||
return -1;
|
||||
|
|
48
src/zmu.cpp
48
src/zmu.cpp
|
@ -476,14 +476,12 @@ int main(int argc, char *argv[]) {
|
|||
} // end if auth
|
||||
|
||||
if ( mon_id > 0 ) {
|
||||
//fprintf(stderr,"Monitor %d\n", mon_id);
|
||||
Monitor *monitor = Monitor::Load(mon_id, function&(ZMU_QUERY|ZMU_ZONES), Monitor::QUERY);
|
||||
if ( monitor ) {
|
||||
//fprintf(stderr,"Monitor %d(%s)\n", monitor->Id(), monitor->Name());
|
||||
if ( verbose ) {
|
||||
printf("Monitor %d(%s)\n", monitor->Id(), monitor->Name());
|
||||
}
|
||||
if ( ! monitor->connect() ) {
|
||||
if ( !monitor->connect() ) {
|
||||
Error("Can't connect to capture daemon: %d %s", monitor->Id(), monitor->Name());
|
||||
exit_zmu(-1);
|
||||
}
|
||||
|
@ -495,13 +493,13 @@ int main(int argc, char *argv[]) {
|
|||
if ( verbose ) {
|
||||
printf("Current state: %s\n", state==Monitor::ALARM?"Alarm":(state==Monitor::ALERT?"Alert":"Idle"));
|
||||
} else {
|
||||
if ( have_output ) printf("%c", separator);
|
||||
if ( have_output ) fputc(separator, stdout);
|
||||
printf("%d", state);
|
||||
have_output = true;
|
||||
}
|
||||
}
|
||||
if ( function & ZMU_TIME ) {
|
||||
struct timeval timestamp = monitor->GetTimestamp( image_idx );
|
||||
struct timeval timestamp = monitor->GetTimestamp(image_idx);
|
||||
if ( verbose ) {
|
||||
char timestamp_str[64] = "None";
|
||||
if ( timestamp.tv_sec )
|
||||
|
@ -511,7 +509,7 @@ int main(int argc, char *argv[]) {
|
|||
else
|
||||
printf("Time of image %d capture: %s.%02ld\n", image_idx, timestamp_str, timestamp.tv_usec/10000);
|
||||
} else {
|
||||
if ( have_output ) printf("%c", separator);
|
||||
if ( have_output ) fputc(separator, stdout);
|
||||
printf("%ld.%02ld", timestamp.tv_sec, timestamp.tv_usec/10000);
|
||||
have_output = true;
|
||||
}
|
||||
|
@ -520,7 +518,7 @@ int main(int argc, char *argv[]) {
|
|||
if ( verbose )
|
||||
printf("Last read index: %d\n", monitor->GetLastReadIndex());
|
||||
else {
|
||||
if ( have_output ) printf("%c", separator);
|
||||
if ( have_output ) fputc(separator, stdout);
|
||||
printf("%d", monitor->GetLastReadIndex());
|
||||
have_output = true;
|
||||
}
|
||||
|
@ -529,7 +527,7 @@ int main(int argc, char *argv[]) {
|
|||
if ( verbose ) {
|
||||
printf("Last write index: %d\n", monitor->GetLastWriteIndex());
|
||||
} else {
|
||||
if ( have_output ) printf("%c", separator);
|
||||
if ( have_output ) fputc(separator, stdout);
|
||||
printf("%d", monitor->GetLastWriteIndex());
|
||||
have_output = true;
|
||||
}
|
||||
|
@ -538,16 +536,16 @@ int main(int argc, char *argv[]) {
|
|||
if ( verbose ) {
|
||||
printf("Last event id: %" PRIu64 "\n", monitor->GetLastEventId());
|
||||
} else {
|
||||
if ( have_output ) printf("%c", separator);
|
||||
if ( have_output ) fputc(separator, stdout);
|
||||
printf("%" PRIu64, monitor->GetLastEventId());
|
||||
have_output = true;
|
||||
}
|
||||
}
|
||||
if ( function & ZMU_FPS ) {
|
||||
if ( verbose )
|
||||
if ( verbose ) {
|
||||
printf("Current capture rate: %.2f frames per second\n", monitor->GetFPS());
|
||||
else {
|
||||
if ( have_output ) printf("%c", separator);
|
||||
} else {
|
||||
if ( have_output ) fputc(separator, stdout);
|
||||
printf("%.2f", monitor->GetFPS());
|
||||
have_output = true;
|
||||
}
|
||||
|
@ -573,10 +571,16 @@ int main(int argc, char *argv[]) {
|
|||
if ( monitor->GetFunction() == Monitor::Function::MONITOR ) {
|
||||
printf("A Monitor in monitor mode cannot handle alarms. Please use NoDect\n");
|
||||
} else {
|
||||
if ( verbose )
|
||||
printf("Forcing alarm on\n");
|
||||
Monitor::State state = monitor->GetState();
|
||||
|
||||
if ( verbose ) {
|
||||
printf("Forcing alarm on current state: %s, event %" PRIu64 "\n",
|
||||
state==Monitor::ALARM?"Alarm":(state==Monitor::ALERT?"Alert":"Idle"),
|
||||
monitor->GetLastEventId()
|
||||
);
|
||||
}
|
||||
monitor->ForceAlarmOn(config.forced_alarm_score, "Forced Web");
|
||||
while ( (monitor->GetState() != Monitor::ALARM) && !zm_terminate ) {
|
||||
while ( ((state = monitor->GetState()) != Monitor::ALARM) && !zm_terminate ) {
|
||||
// Wait for monitor to notice.
|
||||
usleep(1000);
|
||||
}
|
||||
|
@ -630,7 +634,7 @@ int main(int argc, char *argv[]) {
|
|||
else
|
||||
printf("Current brightness: %d\n", monitor->actionBrightness());
|
||||
} else {
|
||||
if ( have_output ) printf("%c", separator);
|
||||
if ( have_output ) fputc(separator, stdout);
|
||||
if ( brightness >= 0 )
|
||||
printf("%d", monitor->actionBrightness(brightness));
|
||||
else
|
||||
|
@ -645,7 +649,7 @@ int main(int argc, char *argv[]) {
|
|||
else
|
||||
printf("Current contrast: %d\n", monitor->actionContrast());
|
||||
} else {
|
||||
if ( have_output ) printf("%c", separator);
|
||||
if ( have_output ) fputc(separator, stdout);
|
||||
if ( contrast >= 0 )
|
||||
printf("%d", monitor->actionContrast(contrast));
|
||||
else
|
||||
|
@ -660,7 +664,7 @@ int main(int argc, char *argv[]) {
|
|||
else
|
||||
printf("Current hue: %d\n", monitor->actionHue());
|
||||
} else {
|
||||
if ( have_output ) printf("%c", separator);
|
||||
if ( have_output ) fputc(separator, stdout);
|
||||
if ( hue >= 0 )
|
||||
printf("%d", monitor->actionHue(hue));
|
||||
else
|
||||
|
@ -675,7 +679,7 @@ int main(int argc, char *argv[]) {
|
|||
else
|
||||
printf("Current colour: %d\n", monitor->actionColour());
|
||||
} else {
|
||||
if ( have_output ) printf("%c", separator);
|
||||
if ( have_output ) fputc(separator, stdout);
|
||||
if ( colour >= 0 )
|
||||
printf("%d", monitor->actionColour(colour));
|
||||
else
|
||||
|
@ -708,11 +712,11 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
if ( function & ZMU_LIST ) {
|
||||
std::string sql = "select Id, Function+0 from Monitors";
|
||||
std::string sql = "SELECT `Id`, `Function`+0 FROM `Monitors`";
|
||||
if ( !verbose ) {
|
||||
sql += "where Function != 'None'";
|
||||
sql += "WHERE `Function` != 'None'";
|
||||
}
|
||||
sql += " order by Id asc";
|
||||
sql += " ORDER BY Id ASC";
|
||||
|
||||
if ( mysql_query(&dbconn, sql.c_str()) ) {
|
||||
Error("Can't run query: %s", mysql_error(&dbconn));
|
||||
|
|
|
@ -110,7 +110,12 @@ else
|
|||
fi;
|
||||
if [ "$SNAPSHOT" == "stable" ]; then
|
||||
if [ "$BRANCH" == "" ]; then
|
||||
BRANCH=$(git describe --tags $(git rev-list --tags --max-count=1));
|
||||
#REV=$(git rev-list --tags --max-count=1)
|
||||
BRANCH=`git describe --tags $(git rev-list --tags --max-count=1)`;
|
||||
if [ "$BRANCH" == "" ]; then
|
||||
echo "Unable to determine latest stable branch!"
|
||||
exit 0;
|
||||
fi
|
||||
echo "Latest stable branch is $BRANCH";
|
||||
fi;
|
||||
else
|
||||
|
|
|
@ -50,8 +50,10 @@ class HostController extends AppController {
|
|||
$cred_depr = [];
|
||||
|
||||
if ( $username && $password ) {
|
||||
ZM\Logger::Debug('Username and password provided, generating access and refresh tokens');
|
||||
$cred = $this->_getCredentials(true, '', $username); // generate refresh
|
||||
} else {
|
||||
ZM\Logger::Debug('Only generating access token');
|
||||
$cred = $this->_getCredentials(false, $token); // don't generate refresh
|
||||
}
|
||||
|
||||
|
@ -69,6 +71,8 @@ class HostController extends AppController {
|
|||
$cred_depr = $this->_getCredentialsDeprecated();
|
||||
$login_array['credentials'] = $cred_depr[0];
|
||||
$login_array['append_password'] = $cred_depr[1];
|
||||
} else {
|
||||
ZM\Logger::Debug('Legacy Auth is disabled, not generating auth= credentials');
|
||||
}
|
||||
|
||||
$login_array['version'] = $ver[0];
|
||||
|
@ -108,8 +112,11 @@ class HostController extends AppController {
|
|||
|
||||
private function _getCredentials($generate_refresh_token=false, $token='', $username='') {
|
||||
|
||||
if ( !ZM_OPT_USE_AUTH )
|
||||
if ( !ZM_OPT_USE_AUTH ) {
|
||||
ZM\Error('OPT_USE_AUTH is turned off. Tokens will be null');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if ( !ZM_AUTH_HASH_SECRET )
|
||||
throw new ForbiddenException(__('Please create a valid AUTH_HASH_SECRET in ZoneMinder'));
|
||||
|
|
|
@ -17,12 +17,17 @@ class ServersController extends AppController {
|
|||
|
||||
public function beforeFilter() {
|
||||
parent::beforeFilter();
|
||||
/*
|
||||
* A user needs the server data to calculate how to view a monitor, and there really isn't anything sensitive in this data.
|
||||
* So it has been decided for now to just let everyone read it.
|
||||
|
||||
global $user;
|
||||
$canView = (!$user) || ($user['System'] != 'None');
|
||||
if ( !$canView ) {
|
||||
throw new UnauthorizedException(__('Insufficient Privileges'));
|
||||
return;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -34,7 +39,7 @@ class ServersController extends AppController {
|
|||
$this->Server->recursive = 0;
|
||||
|
||||
$options = '';
|
||||
$servers = $this->Server->find('all',$options);
|
||||
$servers = $this->Server->find('all', $options);
|
||||
$this->set(array(
|
||||
'servers' => $servers,
|
||||
'_serialize' => array('servers')
|
||||
|
@ -50,13 +55,13 @@ class ServersController extends AppController {
|
|||
*/
|
||||
public function view($id = null) {
|
||||
$this->Server->recursive = 0;
|
||||
if (!$this->Server->exists($id)) {
|
||||
if ( !$this->Server->exists($id) ) {
|
||||
throw new NotFoundException(__('Invalid server'));
|
||||
}
|
||||
$restricted = '';
|
||||
|
||||
$options = array('conditions' => array(
|
||||
array('Server.' . $this->Server->primaryKey => $id),
|
||||
array('Server.'.$this->Server->primaryKey => $id),
|
||||
$restricted
|
||||
)
|
||||
);
|
||||
|
|
|
@ -119,7 +119,7 @@ class Monitor extends AppModel {
|
|||
);
|
||||
public $actsAs = array(
|
||||
'CakePHP-Enum-Behavior.Enum' => array(
|
||||
'Type' => array('Local','Remote','File','Ffmpeg','Libvlc','cURL','WebSite'),
|
||||
'Type' => array('Local','Remote','File','Ffmpeg','Libvlc','cURL','WebSite', 'VNC'),
|
||||
'Function' => array('None','Monitor','Modect','Record','Mocord','Nodect'),
|
||||
'Orientation' => array('ROTATE_0','ROTATE_90','ROTATE_180','ROTATE_270','FLIP_HORI','FLIP_VERT'),
|
||||
'OutputCodec' => array('h264','mjpeg','mpeg1','mpeg2'),
|
||||
|
|
|
@ -417,31 +417,27 @@ class Event extends ZM_Object {
|
|||
}
|
||||
} // end if capture file exists
|
||||
} // end if analyze file exists
|
||||
}
|
||||
} // end if frame or snapshot
|
||||
|
||||
$captPath = $eventPath.'/'.$captImage;
|
||||
if ( ! file_exists($captPath) ) {
|
||||
Error("Capture file does not exist at $captPath");
|
||||
}
|
||||
|
||||
//echo "CI:$captImage, CP:$captPath, TCP:$captPath<br>";
|
||||
|
||||
$analImage = sprintf('%0'.ZM_EVENT_IMAGE_DIGITS.'d-analyse.jpg', $frame['FrameId']);
|
||||
$analPath = $eventPath.'/'.$analImage;
|
||||
|
||||
//echo "AI:$analImage, AP:$analPath, TAP:$analPath<br>";
|
||||
|
||||
$alarmFrame = $frame['Type']=='Alarm';
|
||||
|
||||
$hasAnalImage = $alarmFrame && file_exists($analPath) && filesize($analPath);
|
||||
$isAnalImage = $hasAnalImage && !$captureOnly;
|
||||
|
||||
if ( !ZM_WEB_SCALE_THUMBS || $scale >= SCALE_BASE || !function_exists('imagecreatefromjpeg') ) {
|
||||
if ( !ZM_WEB_SCALE_THUMBS || ($scale >= SCALE_BASE) || !function_exists('imagecreatefromjpeg') ) {
|
||||
$imagePath = $thumbPath = $isAnalImage ? $analPath : $captPath;
|
||||
$imageFile = $imagePath;
|
||||
$thumbFile = $thumbPath;
|
||||
} else {
|
||||
if ( version_compare( phpversion(), '4.3.10', '>=') )
|
||||
if ( version_compare(phpversion(), '4.3.10', '>=') )
|
||||
$fraction = sprintf('%.3F', $scale/SCALE_BASE);
|
||||
else
|
||||
$fraction = sprintf('%.3f', $scale/SCALE_BASE);
|
||||
|
@ -459,19 +455,19 @@ class Event extends ZM_Object {
|
|||
}
|
||||
|
||||
$thumbFile = $thumbPath;
|
||||
if ( $overwrite || ! file_exists( $thumbFile ) || ! filesize( $thumbFile ) ) {
|
||||
if ( $overwrite || ! file_exists($thumbFile) || ! filesize($thumbFile) ) {
|
||||
// Get new dimensions
|
||||
list( $imageWidth, $imageHeight ) = getimagesize( $imagePath );
|
||||
list( $imageWidth, $imageHeight ) = getimagesize($imagePath);
|
||||
$thumbWidth = $imageWidth * $fraction;
|
||||
$thumbHeight = $imageHeight * $fraction;
|
||||
|
||||
// Resample
|
||||
$thumbImage = imagecreatetruecolor( $thumbWidth, $thumbHeight );
|
||||
$image = imagecreatefromjpeg( $imagePath );
|
||||
imagecopyresampled( $thumbImage, $image, 0, 0, 0, 0, $thumbWidth, $thumbHeight, $imageWidth, $imageHeight );
|
||||
$thumbImage = imagecreatetruecolor($thumbWidth, $thumbHeight);
|
||||
$image = imagecreatefromjpeg($imagePath);
|
||||
imagecopyresampled($thumbImage, $image, 0, 0, 0, 0, $thumbWidth, $thumbHeight, $imageWidth, $imageHeight);
|
||||
|
||||
if ( !imagejpeg( $thumbImage, $thumbPath ) )
|
||||
Error( "Can't create thumbnail '$thumbPath'" );
|
||||
if ( !imagejpeg($thumbImage, $thumbPath) )
|
||||
Error("Can't create thumbnail '$thumbPath'");
|
||||
}
|
||||
} # Create thumbnails
|
||||
|
||||
|
@ -555,7 +551,7 @@ class Event extends ZM_Object {
|
|||
$Server = $Storage->ServerId() ? $Storage->Server() : $this->Monitor()->Server();
|
||||
if ( $Server->Id() != ZM_SERVER_ID ) {
|
||||
|
||||
$url = $Server->UrlToApi() . '/events/'.$this->{'Id'}.'.json';
|
||||
$url = $Server->UrlToApi().'/events/'.$this->{'Id'}.'.json';
|
||||
if ( ZM_OPT_USE_AUTH ) {
|
||||
if ( ZM_AUTH_RELAY == 'hashed' ) {
|
||||
$url .= '?auth='.generateAuthHash(ZM_AUTH_HASH_IPS);
|
||||
|
|
|
@ -11,6 +11,9 @@ class Filter extends ZM_Object {
|
|||
'AutoExecute' => 0,
|
||||
'AutoExecuteCmd' => 0,
|
||||
'AutoEmail' => 0,
|
||||
'EmailTo' => '',
|
||||
'EmailSubject' => '',
|
||||
'EmailBody' => '',
|
||||
'AutoDelete' => 0,
|
||||
'AutoArchive' => 0,
|
||||
'AutoVideo' => 0,
|
||||
|
|
|
@ -441,14 +441,17 @@ class Monitor extends ZM_Object {
|
|||
$source = '';
|
||||
if ( $this->{'Type'} == 'Local' ) {
|
||||
$source = $this->{'Device'}.' ('.$this->{'Channel'}.')';
|
||||
} elseif ( $this->{'Type'} == 'Remote' ) {
|
||||
} else if ( $this->{'Type'} == 'Remote' ) {
|
||||
$source = preg_replace( '/^.*@/', '', $this->{'Host'} );
|
||||
if ( $this->{'Port'} != '80' and $this->{'Port'} != '554' ) {
|
||||
$source .= ':'.$this->{'Port'};
|
||||
}
|
||||
} elseif ( $this->{'Type'} == 'File' || $this->{'Type'} == 'cURL' ) {
|
||||
$source = preg_replace( '/^.*\//', '', $this->{'Path'} );
|
||||
} elseif ( $this->{'Type'} == 'Ffmpeg' || $this->{'Type'} == 'Libvlc' || $this->{'Type'} == 'WebSite' ) {
|
||||
} else if ( $this->{'Type'} == 'VNC' ) {
|
||||
$source = preg_replace( '/^.*@/', '', $this->{'Host'} );
|
||||
if ( $this->{'Port'} != '5900' ) {
|
||||
$source .= ':'.$this->{'Port'};
|
||||
}
|
||||
} else if ( $this->{'Type'} == 'Ffmpeg' || $this->{'Type'} == 'Libvlc' || $this->{'Type'} == 'WebSite' ) {
|
||||
$url_parts = parse_url( $this->{'Path'} );
|
||||
if ( ZM_WEB_FILTER_SOURCE == 'Hostname' ) {
|
||||
# Filter out everything but the hostname
|
||||
|
@ -457,7 +460,7 @@ class Monitor extends ZM_Object {
|
|||
} else {
|
||||
$source = $this->{'Path'};
|
||||
}
|
||||
} elseif ( ZM_WEB_FILTER_SOURCE == 'NoCredentials' ) {
|
||||
} else if ( ZM_WEB_FILTER_SOURCE == 'NoCredentials' ) {
|
||||
# Filter out sensitive and common items
|
||||
unset($url_parts['user']);
|
||||
unset($url_parts['pass']);
|
||||
|
|
|
@ -216,7 +216,8 @@ Logger::Debug("$k => Have default for $v: ");
|
|||
}
|
||||
}
|
||||
} # end foreach default
|
||||
}
|
||||
} # end if defaults
|
||||
|
||||
foreach ( $new_values as $field => $value ) {
|
||||
|
||||
if ( method_exists($this, $field) ) {
|
||||
|
@ -299,7 +300,7 @@ Logger::Debug("$k => Have default for $v: ");
|
|||
# Set defaults. Note that we only replace "" with null, not other values
|
||||
# because for example if we want to clear TimestampFormat, we clear it, but the default is a string value
|
||||
foreach ( $this->defaults as $field => $default ) {
|
||||
if ( (!array_key_exists($field, $this)) or ($this->{$field} == '') ) {
|
||||
if ( (!property_exists($this, $field)) or ($this->{$field} === '') ) {
|
||||
if ( is_array($default) ) {
|
||||
$this->{$field} = $default['default'];
|
||||
} else if ( $default == null ) {
|
||||
|
|
|
@ -16,6 +16,7 @@ class Storage extends ZM_Object {
|
|||
'Scheme' => 'Medium',
|
||||
'ServerId' => 0,
|
||||
'DoDelete' => 1,
|
||||
'Enabled' => 1,
|
||||
);
|
||||
public static function find($parameters = array(), $options = array()) {
|
||||
return ZM_Object::_find(get_class(), $parameters, $options);
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
namespace ZM;
|
||||
require_once('database.php');
|
||||
require_once('Object.php');
|
||||
|
||||
|
||||
class Zone extends ZM_Object {
|
||||
protected static $table = 'Zones';
|
||||
|
||||
protected $defaults = array(
|
||||
'Id' => null,
|
||||
'Name' => '',
|
||||
'Type' => 'Active',
|
||||
'Units' => 'Pixels',
|
||||
'CheckMethod' => 'Blobs',
|
||||
'MinPixelThreshold' => null,
|
||||
'MaxPixelThreshold' => null,
|
||||
'MinAlarmPixels' => null,
|
||||
'MaxAlarmPixels' => null,
|
||||
'FilterX' => null,
|
||||
'FilterY' => null,
|
||||
'MinFilterPixels' => null,
|
||||
'MaxFilterPixels' => null,
|
||||
'MinBlobPixels' => null,
|
||||
'MaxBlobPixels' => null,
|
||||
'MinBlobs' => null,
|
||||
'MaxBlobs' => null,
|
||||
'OverloadFrames' => 0,
|
||||
'ExtendAlarmFrames' => 0,
|
||||
);
|
||||
|
||||
public static function find( $parameters = array(), $options = array() ) {
|
||||
return ZM_Object::_find(get_class(), $parameters, $options);
|
||||
}
|
||||
|
||||
public static function find_one( $parameters = array(), $options = array() ) {
|
||||
return ZM_Object::_find_one(get_class(), $parameters, $options);
|
||||
}
|
||||
|
||||
} # end class Zone
|
||||
?>
|
|
@ -21,42 +21,31 @@
|
|||
// Group edit actions
|
||||
# Should probably verify that each monitor id is a valid monitor, that we have access to.
|
||||
# However at the moment, you have to have System permissions to do this
|
||||
if ( ! canEdit('Groups') ) {
|
||||
if ( !canEdit('Groups') ) {
|
||||
ZM\Warning('Need group edit permissions to edit groups');
|
||||
return;
|
||||
}
|
||||
|
||||
if ( $action == 'Save' ) {
|
||||
$monitors = empty($_POST['newGroup']['MonitorIds']) ? '' : implode(',', $_POST['newGroup']['MonitorIds']);
|
||||
$group_id = null;
|
||||
if ( !empty($_POST['gid']) ) {
|
||||
if ( !empty($_POST['gid']) )
|
||||
$group_id = $_POST['gid'];
|
||||
dbQuery(
|
||||
'UPDATE Groups SET Name=?, ParentId=? WHERE Id=?',
|
||||
$group = new ZM\Group($group_id);
|
||||
$group->save(
|
||||
array(
|
||||
$_POST['newGroup']['Name'],
|
||||
( $_POST['newGroup']['ParentId'] == '' ? null : $_POST['newGroup']['ParentId'] ),
|
||||
$group_id,
|
||||
'Name'=> $_POST['newGroup']['Name'],
|
||||
'ParentId'=>( $_POST['newGroup']['ParentId'] == '' ? null : $_POST['newGroup']['ParentId'] ),
|
||||
)
|
||||
);
|
||||
dbQuery('DELETE FROM Groups_Monitors WHERE GroupId=?', array($group_id));
|
||||
} else {
|
||||
dbQuery(
|
||||
'INSERT INTO Groups (Name,ParentId) VALUES (?,?)',
|
||||
array(
|
||||
$_POST['newGroup']['Name'],
|
||||
( $_POST['newGroup']['ParentId'] == '' ? null : $_POST['newGroup']['ParentId'] ),
|
||||
)
|
||||
);
|
||||
$group_id = dbInsertId();
|
||||
}
|
||||
dbQuery('DELETE FROM `Groups_Monitors` WHERE `GroupId`=?', array($group_id));
|
||||
$group_id = $group->Id();
|
||||
if ( $group_id ) {
|
||||
foreach ( $_POST['newGroup']['MonitorIds'] as $mid ) {
|
||||
dbQuery('INSERT INTO Groups_Monitors (GroupId,MonitorId) VALUES (?,?)', array($group_id, $mid));
|
||||
dbQuery('INSERT INTO `Groups_Monitors` (`GroupId`,`MonitorId`) VALUES (?,?)', array($group_id, $mid));
|
||||
}
|
||||
}
|
||||
$view = 'none';
|
||||
$refreshParent = true;
|
||||
$closePopup = true;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -442,9 +442,10 @@ function makeLink($url, $label, $condition=1, $options='') {
|
|||
*/
|
||||
function makePopupLink($url, $winName, $winSize, $label, $condition=1, $options='') {
|
||||
// Avoid double-encoding since some consumers incorrectly pass a pre-escaped URL.
|
||||
$string = '<a class="popup-link" href="' . htmlspecialchars($url, ENT_COMPAT | ENT_HTML401, ini_get("default_charset"), false) . '"';
|
||||
$string .= ' data-window-name="' . htmlspecialchars($winName) . '"';
|
||||
$string = '<a';
|
||||
if ( $condition ) {
|
||||
$string .= ' class="popup-link" href="' . htmlspecialchars($url, ENT_COMPAT | ENT_HTML401, ini_get('default_charset'), false) . '"';
|
||||
$string .= ' data-window-name="' . htmlspecialchars($winName) . '"';
|
||||
if ( is_array( $winSize ) ) {
|
||||
$string .= ' data-window-tag="' . htmlspecialchars($winSize[0]) . '"';
|
||||
$string .= ' data-window-width="' . htmlspecialchars($winSize[1]) . '"';
|
||||
|
@ -455,7 +456,7 @@ function makePopupLink($url, $winName, $winSize, $label, $condition=1, $options=
|
|||
|
||||
$string .= ($options ? (' ' . $options ) : '') . '>';
|
||||
} else {
|
||||
$string .= '<a>';
|
||||
$string .= '>';
|
||||
}
|
||||
$string .= $label;
|
||||
$string .= '</a>';
|
||||
|
@ -520,7 +521,8 @@ function htmlOptions($contents, $values) {
|
|||
$options_html .= '<option value="'.htmlspecialchars($value, ENT_COMPAT | ENT_HTML401, ini_get('default_charset'), false).'"'.
|
||||
($selected?' selected="selected"':'').
|
||||
($disabled?' disabled="disabled"':'').
|
||||
'>'.htmlspecialchars($text, ENT_COMPAT | ENT_HTML401, ini_get('default_charset'), false).'</option>';
|
||||
'>'.htmlspecialchars($text, ENT_COMPAT | ENT_HTML401, ini_get('default_charset'), false).'</option>
|
||||
';
|
||||
}
|
||||
return $options_html;
|
||||
}
|
||||
|
@ -776,7 +778,7 @@ function canStreamIframe() {
|
|||
|
||||
function canStreamNative() {
|
||||
// Old versions of Chrome can display the stream, but then it blocks everything else (Chrome bug 5876)
|
||||
return( ZM_WEB_CAN_STREAM == 'yes' || ( ZM_WEB_CAN_STREAM == 'auto' && (!isInternetExplorer() && !isOldChrome()) ) );
|
||||
return ( ZM_WEB_CAN_STREAM == 'yes' || ( ZM_WEB_CAN_STREAM == 'auto' && (!isInternetExplorer() && !isOldChrome()) ) );
|
||||
}
|
||||
|
||||
function canStreamApplet() {
|
||||
|
@ -908,11 +910,11 @@ function createListThumbnail($event, $overwrite=false) {
|
|||
if ( ZM_WEB_LIST_THUMB_WIDTH ) {
|
||||
$thumbWidth = ZM_WEB_LIST_THUMB_WIDTH;
|
||||
$scale = (SCALE_BASE*ZM_WEB_LIST_THUMB_WIDTH)/$event['Width'];
|
||||
$thumbHeight = reScale( $event['Height'], $scale );
|
||||
$thumbHeight = reScale($event['Height'], $scale);
|
||||
} elseif ( ZM_WEB_LIST_THUMB_HEIGHT ) {
|
||||
$thumbHeight = ZM_WEB_LIST_THUMB_HEIGHT;
|
||||
$scale = (SCALE_BASE*ZM_WEB_LIST_THUMB_HEIGHT)/$event['Height'];
|
||||
$thumbWidth = reScale( $event['Width'], $scale );
|
||||
$thumbWidth = reScale($event['Width'], $scale);
|
||||
} else {
|
||||
ZM\Fatal('No thumbnail width or height specified, please check in Options->Web');
|
||||
}
|
||||
|
@ -949,11 +951,11 @@ function createVideo($event, $format, $rate, $scale, $overwrite=false) {
|
|||
|
||||
# This takes more than one scale amount, so it runs through each and alters dimension.
|
||||
# I can't imagine why you would want to do that.
|
||||
function reScale( $dimension, $dummy ) {
|
||||
function reScale($dimension, $dummy) {
|
||||
$new_dimension = $dimension;
|
||||
for ( $i = 1; $i < func_num_args(); $i++ ) {
|
||||
$scale = func_get_arg( $i );
|
||||
if ( !empty($scale) && ($scale != 'auto') && ($scale != SCALE_BASE) )
|
||||
$scale = func_get_arg($i);
|
||||
if ( !empty($scale) && ($scale != '0') && ($scale != 'auto') && ($scale != SCALE_BASE) )
|
||||
$new_dimension = (int)(($new_dimension*$scale)/SCALE_BASE);
|
||||
}
|
||||
return $new_dimension;
|
||||
|
@ -1115,6 +1117,9 @@ function parseFilter(&$filter, $saveToSession=false, $querySep='&') {
|
|||
$filter['query'] .= $querySep.urlencode("filter[Query][terms][$i][attr]").'='.urlencode($term['attr']);
|
||||
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[Query][terms][$i][attr]\" value=\"".htmlspecialchars($term['attr'])."\"/>\n";
|
||||
switch ( $term['attr'] ) {
|
||||
case 'AlarmedZoneId':
|
||||
$term['op'] = 'EXISTS';
|
||||
break;
|
||||
case 'MonitorName':
|
||||
$filter['sql'] .= 'M.Name';
|
||||
break;
|
||||
|
@ -1232,11 +1237,15 @@ function parseFilter(&$filter, $saveToSession=false, $querySep='&') {
|
|||
$valueList = array();
|
||||
foreach ( preg_split('/["\'\s]*?,["\'\s]*?/', preg_replace('/^["\']+?(.+)["\']+?$/', '$1', $term['val'])) as $value ) {
|
||||
switch ( $term['attr'] ) {
|
||||
|
||||
case 'AlarmedZoneId':
|
||||
$value = '(SELECT * FROM Stats WHERE EventId=E.Id AND ZoneId='.$value.')';
|
||||
break;
|
||||
case 'MonitorName':
|
||||
case 'Name':
|
||||
case 'Cause':
|
||||
case 'Notes':
|
||||
if($term['op'] == 'LIKE' || $term['op'] == 'NOT LIKE') {
|
||||
if ( $term['op'] == 'LIKE' || $term['op'] == 'NOT LIKE' ) {
|
||||
$value = '%'.$value.'%';
|
||||
}
|
||||
$value = dbEscape($value);
|
||||
|
@ -1267,8 +1276,11 @@ function parseFilter(&$filter, $saveToSession=false, $querySep='&') {
|
|||
case 'Date':
|
||||
case 'StartDate':
|
||||
case 'EndDate':
|
||||
if ( $value != 'NULL' )
|
||||
$value = 'to_days(\''.strftime(STRF_FMT_DATETIME_DB, strtotime($value)).'\')';
|
||||
if ( $value == 'CURDATE()' or $value == 'NOW()' ) {
|
||||
$value = 'to_days('.$value.')';
|
||||
} else if ( $value != 'NULL' ) {
|
||||
$value = 'to_days(\''.strftime(STRF_FMT_DATETIME_DB, strtotime($value)).'\')';
|
||||
}
|
||||
break;
|
||||
case 'Time':
|
||||
case 'StartTime':
|
||||
|
@ -1303,10 +1315,13 @@ function parseFilter(&$filter, $saveToSession=false, $querySep='&') {
|
|||
break;
|
||||
case '=[]' :
|
||||
case 'IN' :
|
||||
$filter['sql'] .= ' in ('.join(',', $valueList).')';
|
||||
$filter['sql'] .= ' IN ('.join(',', $valueList).')';
|
||||
break;
|
||||
case '![]' :
|
||||
$filter['sql'] .= ' not in ('.join(',', $valueList).')';
|
||||
break;
|
||||
case 'EXISTS' :
|
||||
$filter['sql'] .= ' EXISTS ' .$value;
|
||||
break;
|
||||
case 'IS' :
|
||||
if ( $value == 'Odd' ) {
|
||||
|
@ -2289,7 +2304,7 @@ function validHtmlStr($input) {
|
|||
function getStreamHTML($monitor, $options = array()) {
|
||||
|
||||
if ( isset($options['scale']) ) {
|
||||
if ( $options['scale'] != 'auto' ) {
|
||||
if ( $options['scale'] and ( $options['scale'] != 'auto' ) ) {
|
||||
$options['width'] = reScale($monitor->ViewWidth(), $options['scale']).'px';
|
||||
$options['height'] = reScale($monitor->ViewHeight(), $options['scale']).'px';
|
||||
} else {
|
||||
|
|
|
@ -18,40 +18,52 @@
|
|||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
//
|
||||
|
||||
function translate( $name ) {
|
||||
function translate($name) {
|
||||
global $SLANG;
|
||||
if ( array_key_exists($name, $SLANG) )
|
||||
// The isset is more performant
|
||||
if ( isset($SLANG[$name]) || array_key_exists($name, $SLANG) )
|
||||
return $SLANG[$name];
|
||||
else
|
||||
return $name;
|
||||
}
|
||||
|
||||
function loadLanguage( $prefix='' ) {
|
||||
function loadLanguage($prefix='') {
|
||||
global $user;
|
||||
|
||||
if ( $prefix )
|
||||
$prefix = $prefix.'/';
|
||||
|
||||
$fallbackLangFile = $prefix.'lang/en_gb.php';
|
||||
$systemLangFile = $prefix.'lang/'.ZM_LANG_DEFAULT.'.php';
|
||||
if ( isset($user['Language']) )
|
||||
if ( isset($user['Language']) and $user['Language'] ) {
|
||||
$userLangFile = $prefix.'lang/'.$user['Language'].'.php';
|
||||
|
||||
if ( isset($userLangFile) && file_exists($userLangFile) )
|
||||
return $userLangFile;
|
||||
elseif ( file_exists($systemLangFile) )
|
||||
if ( file_exists($userLangFile) ) {
|
||||
return $userLangFile;
|
||||
} else {
|
||||
ZM\Warning("User language file $userLangFile does not exist.");
|
||||
}
|
||||
}
|
||||
|
||||
$systemLangFile = $prefix.'lang/'.ZM_LANG_DEFAULT.'.php';
|
||||
if ( file_exists($systemLangFile) ) {
|
||||
return $systemLangFile;
|
||||
elseif ( file_exists($fallbackLangFile) )
|
||||
} else {
|
||||
ZM\Warning("System language file $systemLangFile does not exist.");
|
||||
}
|
||||
|
||||
$fallbackLangFile = $prefix.'lang/en_gb.php';
|
||||
if ( file_exists($fallbackLangFile) ) {
|
||||
return $fallbackLangFile;
|
||||
else
|
||||
return false;
|
||||
} else {
|
||||
ZM\Error("Default language file $fallbackLangFile does not exist.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $langFile = loadLanguage() ) {
|
||||
require_once($langFile);
|
||||
require_once('lang/default.php');
|
||||
foreach ($DLANG as $key => $value) {
|
||||
if ( ! array_key_exists($key, $SLANG) )
|
||||
if ( ! (isset($SLANG[$key]) || array_key_exists($key, $SLANG)) )
|
||||
$SLANG[$key] = $DLANG[$key];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ if ( version_compare(phpversion(), '4.1.0', '<') ) {
|
|||
}
|
||||
|
||||
// Useful debugging lines for mobile devices
|
||||
if ( false ) {
|
||||
if ( true ) {
|
||||
ob_start();
|
||||
phpinfo(INFO_VARIABLES);
|
||||
$fp = fopen('/tmp/env.html', 'w+');
|
||||
|
@ -52,6 +52,8 @@ require_once('includes/Event.php');
|
|||
require_once('includes/Group.php');
|
||||
require_once('includes/Monitor.php');
|
||||
|
||||
$Servers = ZM\Server::find();
|
||||
|
||||
if (
|
||||
(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on')
|
||||
or
|
||||
|
@ -71,7 +73,7 @@ define('ZM_BASE_URL', '');
|
|||
|
||||
require_once('includes/functions.php');
|
||||
if ( $_SERVER['REQUEST_METHOD'] == 'OPTIONS' ) {
|
||||
ZM\Logger::Debug("OPTIONS Method, only doing CORS");
|
||||
ZM\Logger::Debug('OPTIONS Method, only doing CORS');
|
||||
# Add Cross domain access headers
|
||||
CORSHeaders();
|
||||
return;
|
||||
|
|
|
@ -49,6 +49,8 @@ function logReport( level, message, file, line ) {
|
|||
/* eslint-disable no-caller */
|
||||
if ( arguments && arguments.callee && arguments.callee.caller && arguments.callee.caller.caller && arguments.callee.caller.caller.name ) {
|
||||
message += ' - '+arguments.callee.caller.caller.name+'()';
|
||||
} else {
|
||||
message += new Error().stack;
|
||||
}
|
||||
/* eslint-enable no-caller */
|
||||
|
||||
|
|
|
@ -51,8 +51,8 @@ var Overlay = new Class({
|
|||
},
|
||||
show: function() {
|
||||
this.mask.show();
|
||||
window.addEventListener( 'resize', this.update.bind(this) );
|
||||
window.addEventListener( 'scroll', this.update.bind(this) );
|
||||
window.addEventListener( 'resize', this.update.bind(this), {passive: true} );
|
||||
window.addEventListener( 'scroll', this.update.bind(this), {passive: true} );
|
||||
this.element.tween( 'opacity', [0, 1.0] );
|
||||
this.element.show();
|
||||
this.element.position();
|
||||
|
@ -80,8 +80,8 @@ var Overlay = new Class({
|
|||
}
|
||||
updateOverlayLoading();
|
||||
this.loading.setStyle( 'display', 'block' );
|
||||
window.addEventListener( 'resize', this.update.bind(this) );
|
||||
window.addEventListener( 'scroll', this.update.bind(this) );
|
||||
window.addEventListener( 'resize', this.update.bind(this), {passive: true} );
|
||||
window.addEventListener( 'scroll', this.update.bind(this), {passive: true} );
|
||||
},
|
||||
hideAnimation: function() {
|
||||
if ( this.loading ) {
|
||||
|
|
|
@ -116,6 +116,7 @@ $SLANG = array(
|
|||
'Area' => 'Area',
|
||||
'AreaUnits' => 'Area (px/%)',
|
||||
'AttrAlarmFrames' => 'Alarm Frames',
|
||||
'AttrAlarmedZone' => 'Alarmed Zone',
|
||||
'AttrArchiveStatus' => 'Archive Status',
|
||||
'AttrAvgScore' => 'Avg. Score',
|
||||
'AttrCause' => 'Cause',
|
||||
|
@ -361,6 +362,9 @@ $SLANG = array(
|
|||
'FilterCopyEvents' => 'Copy all matches',
|
||||
'FilterMoveEvents' => 'Move all matches',
|
||||
'FilterEmailEvents' => 'Email details of all matches',
|
||||
'FilterEmailTo' => 'Email To',
|
||||
'FilterEmailSubject' => 'Email Subject',
|
||||
'FilterEmailBody' => 'Email Body',
|
||||
'FilterExecuteEvents' => 'Execute command on all matches',
|
||||
'FilterLog' => 'Filter log',
|
||||
'FilterMessageEvents' => 'Message details of all matches',
|
||||
|
|
|
@ -56,9 +56,14 @@ select {
|
|||
width: 300px;
|
||||
text-align: right;
|
||||
}
|
||||
input[name="filter[EmailSubject]"],
|
||||
input[name="filter[EmailTo]"],
|
||||
textarea[name="filter[EmailBody]"] {
|
||||
width: 500px;
|
||||
}
|
||||
select#Id {
|
||||
min-width: 400px;
|
||||
min-width: 500px;
|
||||
}
|
||||
.Name input {
|
||||
min-width: 400px;
|
||||
min-width: 500px;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,9 @@
|
|||
}
|
||||
|
||||
textarea,
|
||||
input[name="newMonitor[Name]"] {
|
||||
input[name="newMonitor[Name]"],
|
||||
input[name="newMonitor[ControlDevice]"],
|
||||
input[name="newMonitor[ControlAddress]"] {
|
||||
width: 100%;
|
||||
}
|
||||
input[name="newMonitor[Width]"],
|
||||
|
|
|
@ -31,7 +31,7 @@ $rates = array(
|
|||
);
|
||||
|
||||
$scales = array(
|
||||
'auto' => translate('Scale to Fit'),
|
||||
'0' => translate('Scale to Fit'),
|
||||
'' => translate('Fixed Width/Height'),
|
||||
'400' => '4x',
|
||||
'300' => '3x',
|
||||
|
@ -45,7 +45,7 @@ $scales = array(
|
|||
'12.5' => '1/8x',
|
||||
);
|
||||
|
||||
if (isset($_REQUEST['view']) && ($_REQUEST['view'] == 'montage')) {
|
||||
if ( isset($_REQUEST['view']) && ($_REQUEST['view'] == 'montage') ) {
|
||||
unset($scales['auto']); //Remove auto on montage, use everywhere else
|
||||
} else {
|
||||
unset($scales['']); //Remove fixed on everything but montage
|
||||
|
|
|
@ -352,7 +352,7 @@ if ( ZM_OPT_USE_AUTH and $user ) {
|
|||
?>
|
||||
<p class="navbar-text">
|
||||
<i class="material-icons">account_circle</i>
|
||||
<?php echo makePopupLink( '?view=logout', 'zmLogout', 'logout', $user['Username'], (ZM_AUTH_TYPE == "builtin") ) ?>
|
||||
<?php echo makePopupLink('?view=logout', 'zmLogout', 'logout', $user['Username'], (ZM_AUTH_TYPE == 'builtin')) ?>
|
||||
</p>
|
||||
<?php
|
||||
}
|
||||
|
@ -396,7 +396,7 @@ if ( (!ZM_OPT_USE_AUTH) or $user ) {
|
|||
?>
|
||||
<li><?php echo translate('Storage') ?>:
|
||||
<?php
|
||||
$storage_areas = ZM\Storage::find();
|
||||
$storage_areas = ZM\Storage::find(array('Enabled'=>true));
|
||||
$storage_paths = null;
|
||||
$storage_areas_with_no_server_id = array();
|
||||
foreach ( $storage_areas as $area ) {
|
||||
|
|
|
@ -63,7 +63,7 @@ var popupSizes = {
|
|||
'shutdown': {'width': 400, 'height': 400},
|
||||
'state': {'width': 400, 'height': 170},
|
||||
'stats': {'width': 840, 'height': 200},
|
||||
'storage': {'width': 600, 'height': 405},
|
||||
'storage': {'width': 600, 'height': 425},
|
||||
'timeline': {'width': 760, 'height': 540},
|
||||
'user': {'width': 460, 'height': 720},
|
||||
'version': {'width': 360, 'height': 210},
|
||||
|
|
|
@ -63,7 +63,7 @@ var popupSizes = {
|
|||
'settings': {'width': 220, 'height': 225},
|
||||
'state': {'width': 370, 'height': 134},
|
||||
'stats': {'width': 840, 'height': 200},
|
||||
'storage': {'width': 600, 'height': 405},
|
||||
'storage': {'width': 600, 'height': 425},
|
||||
'timeline': {'width': 760, 'height': 540},
|
||||
'user': {'width': 360, 'height': 720},
|
||||
'version': {'width': 360, 'height': 140},
|
||||
|
|
|
@ -530,3 +530,17 @@ function scaleToFit(baseWidth, baseHeight, scaleEl, bottomEl) {
|
|||
autoScale = closest;
|
||||
return {width: Math.floor(newWidth), height: Math.floor(newHeight), autoScale: autoScale};
|
||||
}
|
||||
|
||||
function setButtonState(element_id, butClass) {
|
||||
var element = $(element_id);
|
||||
if ( element ) {
|
||||
element.className = butClass;
|
||||
if (butClass == 'unavail' || (butClass == 'active' && (element.id == 'pauseBtn' || element.id == 'playBtn'))) {
|
||||
element.disabled = true;
|
||||
} else {
|
||||
element.disabled = false;
|
||||
}
|
||||
} else {
|
||||
console.log('Element was null or not found in setButtonState. id:'+element_id);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -233,7 +233,7 @@ $html .= '</span>
|
|||
}
|
||||
}
|
||||
|
||||
$monitors_dropdown[$monitors[$i]['Id']] = $monitors[$i]['Name'];
|
||||
$monitors_dropdown[$monitors[$i]['Id']] = $monitors[$i]['Id'].' '.$monitors[$i]['Name'];
|
||||
|
||||
if ( count($selected_monitor_ids) and ! in_array($monitors[$i]['Id'], $selected_monitor_ids) ) {
|
||||
continue;
|
||||
|
|
|
@ -40,7 +40,7 @@ if ( empty($_REQUEST['mode']) ) {
|
|||
}
|
||||
|
||||
$widths = array(
|
||||
'' => translate('auto'),
|
||||
'auto' => translate('auto'),
|
||||
'100%' => '100%',
|
||||
'160px' => '160px',
|
||||
'320px' => '320px',
|
||||
|
@ -62,13 +62,11 @@ session_start();
|
|||
|
||||
if ( isset($_REQUEST['scale']) ) {
|
||||
$options['scale'] = validInt($_REQUEST['scale']);
|
||||
ZM\Logger::Debug('Setting scale from request to '.$options['scale']);
|
||||
} else if ( isset($_COOKIE['zmCycleScale']) ) {
|
||||
$options['scale'] = $_COOKIE['zmCycleScale'];
|
||||
ZM\Logger::Debug('Setting scale from cookie to '.$options['scale']);
|
||||
}
|
||||
|
||||
if ( !(isset($options['scale']) and $options['scale']) )
|
||||
if ( !isset($options['scale']) )
|
||||
$options['scale'] = 100;
|
||||
|
||||
if ( isset($_COOKIE['zmCycleWidth']) and $_COOKIE['zmCycleWidth'] ) {
|
||||
|
|
|
@ -48,7 +48,7 @@ if ( isset($_REQUEST['scale']) ) {
|
|||
$scale = validInt($_REQUEST['scale']);
|
||||
} else if ( isset($_COOKIE['zmEventScaleAuto']) ) {
|
||||
// If we're using scale to fit use it on all monitors
|
||||
$scale = 'auto';
|
||||
$scale = '0';
|
||||
} else if ( isset($_COOKIE['zmEventScale'.$Event->MonitorId()]) ) {
|
||||
$scale = $_COOKIE['zmEventScale'.$Event->MonitorId()];
|
||||
} else {
|
||||
|
@ -85,9 +85,9 @@ else
|
|||
$streamMode = 'video';
|
||||
|
||||
$replayMode = '';
|
||||
if ( isset( $_REQUEST['replayMode'] ) )
|
||||
if ( isset($_REQUEST['replayMode']) )
|
||||
$replayMode = validHtmlStr($_REQUEST['replayMode']);
|
||||
if ( isset( $_COOKIE['replayMode']) && preg_match('#^[a-z]+$#', $_COOKIE['replayMode']) )
|
||||
if ( isset($_COOKIE['replayMode']) && preg_match('#^[a-z]+$#', $_COOKIE['replayMode']) )
|
||||
$replayMode = validHtmlStr($_COOKIE['replayMode']);
|
||||
|
||||
if ( ( ! $replayMode ) or ( ! $replayModes[$replayMode] ) ) {
|
||||
|
@ -104,7 +104,10 @@ if ( $Monitor->VideoWriter() == '2' ) {
|
|||
$Zoom = $Event->Height()/$Event->Width();
|
||||
}
|
||||
|
||||
// These are here to figure out the next/prev event
|
||||
// These are here to figure out the next/prev event, however id there is no filter, then default to one that specifies the Monitor
|
||||
if ( !isset($_REQUEST['filter']) ) {
|
||||
$_REQUEST['filter'] = array( 'Query'=>array('terms'=> array( array('attr' => 'MonitorId', 'op' => '=', 'val' => $Event->MonitorId() ) ) ) );
|
||||
}
|
||||
parseSort();
|
||||
parseFilter($_REQUEST['filter']);
|
||||
$filterQuery = $_REQUEST['filter']['query'];
|
||||
|
@ -122,7 +125,7 @@ xhtmlHeaders(__FILE__, translate('Event'));
|
|||
<?php if ( !$popup ) echo getNavBarHTML() ?>
|
||||
<div id="header">
|
||||
<?php
|
||||
if ( ! $Event->Id() ) {
|
||||
if ( !$Event->Id() ) {
|
||||
echo 'Event was not found.';
|
||||
} else {
|
||||
?>
|
||||
|
@ -193,9 +196,9 @@ if ( ($codec == 'MP4' || $codec == 'auto' ) && $Event->DefaultVideo() ) {
|
|||
?>
|
||||
<div id="videoFeed">
|
||||
<video id="videoobj" class="video-js vjs-default-skin"
|
||||
style="transform: matrix(1, 0, 0, 1, 0, 0)"
|
||||
width="<?php echo reScale($Event->Width(), $scale) ?>"
|
||||
height="<?php echo reScale($Event->Height(), $scale) ?>"
|
||||
style="transform: matrix(1, 0, 0, 1, 0, 0);"
|
||||
<?php echo $scale ? 'width="'.reScale($Event->Width(), $scale).'"' : '' ?>
|
||||
<?php echo $scale ? 'height="'.reScale($Event->Height(), $scale).'"' : '' ?>
|
||||
data-setup='{ "controls": true, "autoplay": true, "preload": "auto", "plugins": { "zoomrotate": { "zoom": "<?php echo $Zoom ?>"}}}'
|
||||
>
|
||||
<source src="<?php echo $Event->getStreamSrc(array('mode'=>'mpeg','format'=>'h264'),'&'); ?>" type="video/mp4">
|
||||
|
@ -208,7 +211,7 @@ if ( ($codec == 'MP4' || $codec == 'auto' ) && $Event->DefaultVideo() ) {
|
|||
?>
|
||||
<div id="imageFeed">
|
||||
<?php
|
||||
if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT ) {
|
||||
if ( (ZM_WEB_STREAM_METHOD == 'mpeg') && ZM_MPEG_LIVE_FORMAT ) {
|
||||
$streamSrc = $Event->getStreamSrc(array('mode'=>'mpeg', 'scale'=>$scale, 'rate'=>$rate, 'bitrate'=>ZM_WEB_VIDEO_BITRATE, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'format'=>ZM_MPEG_REPLAY_FORMAT, 'replay'=>$replayMode),'&');
|
||||
outputVideoStream('evtStream', $streamSrc, reScale( $Event->Width(), $scale ).'px', reScale( $Event->Height(), $scale ).'px', ZM_MPEG_LIVE_FORMAT );
|
||||
} else {
|
||||
|
@ -257,7 +260,12 @@ if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT ) {
|
|||
</p>
|
||||
<div id="replayStatus">
|
||||
<span id="mode"><?php echo translate('Mode') ?>: <span id="modeValue">Replay</span></span>
|
||||
<span id="rate"><?php echo translate('Rate') ?>: <span id="rateValue"><?php echo $rate/100 ?></span>x</span>
|
||||
<span id="rate"><?php echo translate('Rate') ?>:
|
||||
<?php
|
||||
$rates = array( -800=>'-8x', -400=>'-4x', -200=>'-2x', -100=>'-1x', 0=>translate('Stop'), 100 => '1x', 200=>'2x', 400=>'4x', 800=>'8x' );
|
||||
echo htmlSelect('rate', $rates, intval($rate), array('id'=>'rateValue'));
|
||||
?>
|
||||
<!--<span id="rateValue"><?php echo $rate/100 ?></span>x</span>-->
|
||||
<span id="progress"><?php echo translate('Progress') ?>: <span id="progressValue">0</span>s</span>
|
||||
<span id="zoom"><?php echo translate('Zoom') ?>: <span id="zoomValue">1</span>x</span>
|
||||
</div>
|
||||
|
|
|
@ -191,21 +191,25 @@ while ( $event_row = dbFetchNext($results) ) {
|
|||
?>
|
||||
<tr<?php if ($event->Archived()) echo ' class="archived"' ?>>
|
||||
<td class="colId"><a href="?view=event&eid=<?php echo $event->Id().$filterQuery.$sortQuery.'&page=1">'.$event->Id().($event->Archived()?'*':'') ?></a></td>
|
||||
<td class="colName"><a href="?view=event&eid=<?php echo $event->Id().$filterQuery.$sortQuery.'&page=1">'.validHtmlStr($event->Name()).($event->Archived()?'*':'') ?></a></td>
|
||||
<td class="colName"><a href="?view=event&eid=<?php echo $event->Id().$filterQuery.$sortQuery.'&page=1">'.validHtmlStr($event->Name()).($event->Archived()?'*':'') ?></a><br/>
|
||||
<?php
|
||||
if ( $event->Emailed() )
|
||||
echo 'Emailed ';
|
||||
?>
|
||||
</td>
|
||||
<td class="colMonitorName"><?php echo makePopupLink( '?view=monitor&mid='.$event->MonitorId(), 'zmMonitor'.$event->MonitorId(), 'monitor', $event->MonitorName(), canEdit( 'Monitors' ) ) ?></td>
|
||||
<td class="colCause"><?php echo makePopupLink( '?view=eventdetail&eid='.$event->Id(), 'zmEventDetail', 'eventdetail', validHtmlStr($event->Cause()), canEdit( 'Events' ), 'title="'.htmlspecialchars($event->Notes()).'"' ) ?>
|
||||
<?php
|
||||
# display notes as small text
|
||||
if ($event->Notes()) {
|
||||
if ( $event->Notes() ) {
|
||||
# if notes include detection objects, then link it to objdetect.jpg
|
||||
if (strpos($event->Notes(),'detected:')!== false){
|
||||
if ( strpos($event->Notes(), 'detected:') !== false ) {
|
||||
# make a link
|
||||
echo makePopupLink( '?view=image&eid='.$event->Id().'&fid=objdetect', 'zmImage',
|
||||
array('image', reScale($event->Width(), $scale), reScale($event->Height(), $scale)),
|
||||
"<div class=\"small text-nowrap text-muted\"><u>".$event->Notes()."</u></div>");
|
||||
}
|
||||
elseif ($event->Notes() != 'Forced Web: ') {
|
||||
echo "<br/><div class=\"small text-nowrap text-muted\">".$event->Notes()."</div>";
|
||||
'<div class="small text-nowrap text-muted"><u>'.$event->Notes().'</u></div>');
|
||||
} else if ( $event->Notes() != 'Forced Web: ' ) {
|
||||
echo '<br/><div class="small text-nowrap text-muted">'.$event->Notes().'</div>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
//
|
||||
// ZoneMinder web filter view file, $Date$, $Revision$
|
||||
// ZoneMinder web filter view file
|
||||
// Copyright (C) 2001-2008 Philip Coombes
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
|
@ -25,6 +25,8 @@ if ( !canView('Events') ) {
|
|||
require_once('includes/Object.php');
|
||||
require_once('includes/Storage.php');
|
||||
require_once('includes/Filter.php');
|
||||
require_once('includes/Monitor.php');
|
||||
require_once('includes/Zone.php');
|
||||
parseSort();
|
||||
|
||||
$filterNames = array(''=>translate('ChooseFilter'));
|
||||
|
@ -69,6 +71,7 @@ if ( count($terms) ) {
|
|||
|
||||
$attrTypes = array(
|
||||
'AlarmFrames' => translate('AttrAlarmFrames'),
|
||||
'AlarmedZoneId' => translate('AttrAlarmedZone'),
|
||||
'Archived' => translate('AttrArchiveStatus'),
|
||||
'AvgScore' => translate('AttrAvgScore'),
|
||||
'Cause' => translate('AttrCause'),
|
||||
|
@ -78,17 +81,17 @@ $attrTypes = array(
|
|||
'EndDateTime' => translate('AttrEndDateTime'),
|
||||
'EndDate' => translate('AttrEndDate'),
|
||||
'EndTime' => translate('AttrEndTime'),
|
||||
'EndWeekday' => translate('AttrEndWeekday'),
|
||||
'FilterServerId' => translate('AttrFilterServer'),
|
||||
'Frames' => translate('AttrFrames'),
|
||||
'EndWeekday' => translate('AttrEndWeekday'),
|
||||
'Id' => translate('AttrId'),
|
||||
'Length' => translate('AttrDuration'),
|
||||
'Name' => translate('AttrName'),
|
||||
'Notes' => translate('AttrNotes'),
|
||||
'MaxScore' => translate('AttrMaxScore'),
|
||||
'MonitorId' => translate('AttrMonitorId'),
|
||||
'MonitorName' => translate('AttrMonitorName'),
|
||||
'MonitorServerId' => translate('AttrMonitorServer'),
|
||||
'Name' => translate('AttrName'),
|
||||
'Notes' => translate('AttrNotes'),
|
||||
'SecondaryStorageId' => translate('AttrSecondaryStorageArea'),
|
||||
'ServerId' => translate('AttrMonitorServer'),
|
||||
'StartDateTime' => translate('AttrStartDateTime'),
|
||||
|
@ -143,13 +146,22 @@ foreach ( dbFetchAll('SELECT `Id`, `Name` FROM `Servers` ORDER BY lower(`Name`)
|
|||
$servers[$server['Id']] = validHtmlStr($server['Name']);
|
||||
}
|
||||
$monitors = array();
|
||||
$monitor_names = array();
|
||||
foreach ( dbFetchAll('SELECT `Id`, `Name` FROM `Monitors` ORDER BY lower(`Name`) ASC') as $monitor ) {
|
||||
if ( visibleMonitor($monitor['Id']) ) {
|
||||
$monitors[$monitor['Name']] = validHtmlStr($monitor['Name']);
|
||||
$monitors[$monitor['Id']] = new ZM\Monitor($monitor);
|
||||
$monitor_names[] = validHtmlStr($monitor['Name']);
|
||||
}
|
||||
}
|
||||
$zones = array();
|
||||
foreach ( dbFetchAll('SELECT Id, Name, MonitorId FROM Zones ORDER BY lower(`Name`) ASC') as $zone ) {
|
||||
if ( visibleMonitor($zone['MonitorId']) ) {
|
||||
$zone['Name'] = validHtmlStr($monitors[$zone['MonitorId']]->Name().': '.$zone['Name']);
|
||||
$zones[$zone['Id']] = new ZM\Zone($zone);
|
||||
}
|
||||
}
|
||||
|
||||
xhtmlHeaders(__FILE__, translate('EventFilter') );
|
||||
xhtmlHeaders(__FILE__, translate('EventFilter'));
|
||||
?>
|
||||
<body>
|
||||
<div id="page">
|
||||
|
@ -259,10 +271,15 @@ for ( $i=0; $i < count($terms); $i++ ) {
|
|||
<td><?php echo htmlSelect("filter[Query][terms][$i][op]", $opTypes, $term['op']); ?></td>
|
||||
<td><?php echo htmlSelect("filter[Query][terms][$i][val]", $weekdays, $term['val']); ?></td>
|
||||
<?php
|
||||
} elseif ( $term['attr'] == 'MonitorName' ) {
|
||||
} elseif ( $term['attr'] == 'Monitor' ) {
|
||||
?>
|
||||
<td><?php echo htmlSelect("filter[Query][terms][$i][op]", $opTypes, $term['op']); ?></td>
|
||||
<td><?php echo htmlSelect("filter[Query][terms][$i][val]", $monitors, $term['val']); ?></td>
|
||||
<?php
|
||||
} elseif ( $term['attr'] == 'MonitorName' ) {
|
||||
?>
|
||||
<td><?php echo htmlSelect("filter[Query][terms][$i][op]", $opTypes, $term['op']); ?></td>
|
||||
<td><?php echo htmlSelect("filter[Query][terms][$i][val]", array_combine($monitor_names,$monitor_names), $term['val']); ?></td>
|
||||
<?php
|
||||
} elseif ( $term['attr'] == 'ServerId' || $term['attr'] == 'MonitorServerId' || $term['attr'] == 'StorageServerId' || $term['attr'] == 'FilterServerId' ) {
|
||||
?>
|
||||
|
@ -273,6 +290,11 @@ for ( $i=0; $i < count($terms); $i++ ) {
|
|||
?>
|
||||
<td><?php echo htmlSelect("filter[Query][terms][$i][op]", $opTypes, $term['op']); ?></td>
|
||||
<td><?php echo htmlSelect("filter[Query][terms][$i][val]", $storageareas, $term['val']); ?></td>
|
||||
<?php
|
||||
} elseif ( $term['attr'] == 'AlarmedZoneId' ) {
|
||||
?>
|
||||
<td><?php echo htmlSelect("filter[Query][terms][$i][op]", $opTypes, $term['op']); ?></td>
|
||||
<td><?php echo htmlSelect("filter[Query][terms][$i][val]", $zones, $term['val']); ?></td>
|
||||
<?php
|
||||
} else {
|
||||
?>
|
||||
|
@ -365,8 +387,22 @@ if ( ZM_OPT_EMAIL ) {
|
|||
?>
|
||||
<p>
|
||||
<label><?php echo translate('FilterEmailEvents') ?></label>
|
||||
<input type="checkbox" name="filter[AutoEmail]" value="1"<?php if ( $filter->AutoEmail() ) { ?> checked="checked"<?php } ?> data-on-click-this="updateButtons"/>
|
||||
<input type="checkbox" name="filter[AutoEmail]" value="1"<?php if ( $filter->AutoEmail() ) { ?> checked="checked"<?php } ?> data-on-click-this="click_AutoEmail"/>
|
||||
</p>
|
||||
<div id="EmailOptions"<?php echo $filter->AutoEmail() ? '' : ' style="display:none;"' ?>>
|
||||
<p>
|
||||
<label><?php echo translate('FilterEmailTo') ?></label>
|
||||
<input type="email" name="filter[EmailTo]" value="<?php echo validHtmlStr($filter->EmailTo()) ?>" multiple/>
|
||||
</p>
|
||||
<p>
|
||||
<label><?php echo translate('FilterEmailSubject') ?></label>
|
||||
<input type="text" name="filter[EmailSubject]" value="<?php echo validHtmlStr($filter->EmailSubject()) ?>"/>
|
||||
</p>
|
||||
<p>
|
||||
<label><?php echo translate('FilterEmailBody') ?></label>
|
||||
<textarea name="filter[EmailBody]"><?php echo validHtmlStr($filter->EmailBody()) ?></textarea>
|
||||
</p>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
if ( ZM_OPT_MESSAGE ) {
|
||||
|
@ -409,7 +445,7 @@ if ( ZM_OPT_MESSAGE ) {
|
|||
<hr/>
|
||||
<div id="contentButtons">
|
||||
<button type="submit" data-on-click-this="submitToEvents"><?php echo translate('ListMatches') ?></button>
|
||||
<!--<button type="submit" data-on-click-this="submitToMontageReview"><?php echo translate('ViewMatches') ?></button>-->
|
||||
<button type="button" data-on-click-this="submitToMontageReview"><?php echo translate('ViewMatches') ?></button>
|
||||
<button type="button" data-on-click-this="submitToExport"><?php echo translate('ExportMatches') ?></button>
|
||||
<button type="button" name="executeButton" id="executeButton" data-on-click-this="executeFilter"><?php echo translate('Execute') ?></button>
|
||||
<?php
|
||||
|
|
|
@ -46,7 +46,7 @@ function changeSize() {
|
|||
// Scale the frame
|
||||
monitor_frame = $j('#imageFeed');
|
||||
if ( !monitor_frame ) {
|
||||
console.log("Error finding frame");
|
||||
console.log('Error finding frame');
|
||||
return;
|
||||
}
|
||||
if ( width ) {
|
||||
|
@ -92,14 +92,20 @@ function changeScale() {
|
|||
// Scale the frame
|
||||
monitor_frame = $j('#imageFeed');
|
||||
if ( !monitor_frame ) {
|
||||
console.log("Error finding frame");
|
||||
console.log('Error finding frame');
|
||||
return;
|
||||
}
|
||||
if ( newWidth ) {
|
||||
monitor_frame.css('width', newWidth+'px');
|
||||
}
|
||||
if ( newHeight ) {
|
||||
monitor_frame.css('height', newHeight+'px');
|
||||
|
||||
if ( scale != '0' ) {
|
||||
if ( newWidth ) {
|
||||
monitor_frame.css('width', newWidth+'px');
|
||||
}
|
||||
if ( newHeight ) {
|
||||
monitor_frame.css('height', newHeight+'px');
|
||||
}
|
||||
} else {
|
||||
monitor_frame.css('width', '100%');
|
||||
monitor_frame.css('height', 'auto');
|
||||
}
|
||||
/*Stream could be an applet so can't use moo tools*/
|
||||
var streamImg = $j('#liveStream'+monitorData[monIdx].id)[0];
|
||||
|
@ -110,12 +116,22 @@ function changeScale() {
|
|||
|
||||
//src = src.replace(/rand=\d+/i,'rand='+Math.floor((Math.random() * 1000000) ));
|
||||
src = src.replace(/scale=[\.\d]+/i, 'scale='+scale);
|
||||
src = src.replace(/width=[\.\d]+/i, 'width='+newWidth);
|
||||
src = src.replace(/height=[\.\d]+/i, 'height='+newHeight);
|
||||
if ( scale != '0' ) {
|
||||
src = src.replace(/width=[\.\d]+/i, 'width='+newWidth);
|
||||
src = src.replace(/height=[\.\d]+/i, 'height='+newHeight);
|
||||
} else {
|
||||
src = src.replace(/width=[\.\d]+/i, 'width='+monitorData[monIdx].width);
|
||||
src = src.replace(/height=[\.\d]+/i, 'height='+monitorData[monIdx].height);
|
||||
}
|
||||
streamImg.src = src;
|
||||
}
|
||||
streamImg.style.width = newWidth + 'px';
|
||||
streamImg.style.height = newHeight + 'px';
|
||||
if ( scale != '0' ) {
|
||||
streamImg.style.width = newWidth+'px';
|
||||
streamImg.style.height = newHeight+'px';
|
||||
} else {
|
||||
streamImg.style.width = '100%';
|
||||
streamImg.style.height = 'auto';
|
||||
}
|
||||
} else {
|
||||
console.log("Did not find liveStream"+monitorData[monIdx].id);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
var vid = null;
|
||||
var spf = Math.round((eventData.Length / eventData.Frames)*1000000 )/1000000;//Seconds per frame for videojs frame by frame.
|
||||
var intervalRewind;
|
||||
var revSpeed = .5;
|
||||
|
||||
// Function called when video.js hits the end of the video
|
||||
function vjsReplay() {
|
||||
|
@ -39,7 +42,7 @@ function vjsReplay() {
|
|||
streamNext(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} // end function vjsReplay
|
||||
|
||||
$j.ajaxSetup({timeout: AJAX_TIMEOUT}); //sets timeout for all getJSON.
|
||||
|
||||
|
@ -67,14 +70,14 @@ function renderAlarmCues(containerEl) {
|
|||
var spanTimeStart = 0;
|
||||
var spanTimeEnd = 0;
|
||||
var alarmed = 0;
|
||||
var alarmHtml = "";
|
||||
var alarmHtml = '';
|
||||
var pixSkew = 0;
|
||||
var skip = 0;
|
||||
var num_cueFrames = cueFrames.length;
|
||||
for ( var i = 0; i < num_cueFrames; i++ ) {
|
||||
skip = 0;
|
||||
frame = cueFrames[i];
|
||||
if (frame.Type == "Alarm" && alarmed == 0) { //From nothing to alarm. End nothing and start alarm.
|
||||
if ( (frame.Type == 'Alarm') && (alarmed == 0) ) { //From nothing to alarm. End nothing and start alarm.
|
||||
alarmed = 1;
|
||||
if (frame.Delta == 0) continue; //If event starts with an alarm or too few for a nonespan
|
||||
spanTimeEnd = frame.Delta * 100;
|
||||
|
@ -88,24 +91,24 @@ function renderAlarmCues(containerEl) {
|
|||
}
|
||||
alarmHtml += '<span class="alarmCue noneCue" style="width: ' + pix + 'px;"></span>';
|
||||
spanTimeStart = spanTimeEnd;
|
||||
} else if (frame.Type !== "Alarm" && alarmed == 1) { //from alarm to nothing. End alarm and start nothing.
|
||||
} else if ( (frame.Type !== 'Alarm') && (alarmed == 1) ) { //from alarm to nothing. End alarm and start nothing.
|
||||
futNone = 0;
|
||||
indexPlus = i+1;
|
||||
if (((frame.Delta * 100) - spanTimeStart) < minAlarm && indexPlus < num_cueFrames) {
|
||||
//alarm is too short and there is more event
|
||||
continue;
|
||||
}
|
||||
while (futNone < minAlarm) { //check ahead to see if there's enough for a nonespan
|
||||
if (indexPlus >= cueFrames.length) break; //check if end of event.
|
||||
while ( futNone < minAlarm ) { //check ahead to see if there's enough for a nonespan
|
||||
if ( indexPlus >= cueFrames.length ) break; //check if end of event.
|
||||
futNone = (cueFrames[indexPlus].Delta *100) - (frame.Delta *100);
|
||||
if (cueFrames[indexPlus].Type == "Alarm") {
|
||||
if ( cueFrames[indexPlus].Type == 'Alarm' ) {
|
||||
i = --indexPlus;
|
||||
skip = 1;
|
||||
break;
|
||||
}
|
||||
indexPlus++;
|
||||
}
|
||||
if (skip == 1) continue; //javascript doesn't support continue 2;
|
||||
if ( skip == 1 ) continue; //javascript doesn't support continue 2;
|
||||
spanTimeEnd = frame.Delta *100;
|
||||
spanTime = spanTimeEnd - spanTimeStart;
|
||||
alarmed = 0;
|
||||
|
@ -118,7 +121,7 @@ function renderAlarmCues(containerEl) {
|
|||
}
|
||||
alarmHtml += '<span class="alarmCue" style="width: ' + pix + 'px;"></span>';
|
||||
spanTimeStart = spanTimeEnd;
|
||||
} else if (frame.Type == "Alarm" && alarmed == 1 && i + 1 >= cueFrames.length) { //event ends on an alarm
|
||||
} else if ( (frame.Type == 'Alarm') && (alarmed == 1) && (i + 1 >= cueFrames.length) ) { //event ends on an alarm
|
||||
spanTimeEnd = frame.Delta * 100;
|
||||
spanTime = spanTimeEnd - spanTimeStart;
|
||||
alarmed = 0;
|
||||
|
@ -130,18 +133,6 @@ function renderAlarmCues(containerEl) {
|
|||
return alarmHtml;
|
||||
}
|
||||
|
||||
function setButtonState( element, butClass ) {
|
||||
if ( element ) {
|
||||
element.className = butClass;
|
||||
if (butClass == 'unavail' || (butClass == 'active' && (element.id == 'pauseBtn' || element.id == 'playBtn'))) {
|
||||
element.disabled = true;
|
||||
} else {
|
||||
element.disabled = false;
|
||||
}
|
||||
} else {
|
||||
console.log('Element was null in setButtonState');
|
||||
}
|
||||
}
|
||||
|
||||
function changeCodec() {
|
||||
location.replace(thisUrl + '?view=event&eid=' + eventData.Id + filterQuery + sortQuery+'&codec='+$j('#codec').val());
|
||||
|
@ -155,12 +146,12 @@ function changeScale() {
|
|||
var eventViewer;
|
||||
var alarmCue = $j('div.alarmCue');
|
||||
var bottomEl = streamMode == 'stills' ? $j('#eventImageNav') : $j('#replayStatus');
|
||||
if (streamMode == 'stills') {
|
||||
if ( streamMode == 'stills' ) {
|
||||
eventViewer = $j('#eventThumbs');
|
||||
} else {
|
||||
eventViewer = $j(vid ? '#videoobj' : '#evtStream');
|
||||
}
|
||||
if ( scale == "auto" ) {
|
||||
if ( scale == '0' || scale == 'auto' ) {
|
||||
var newSize = scaleToFit(eventData.Width, eventData.Height, eventViewer, bottomEl);
|
||||
newWidth = newSize.width;
|
||||
newHeight = newSize.height;
|
||||
|
@ -172,10 +163,10 @@ function changeScale() {
|
|||
}
|
||||
if ( !(streamMode == 'stills') ) {
|
||||
eventViewer.width(newWidth);
|
||||
} //stills handles its own width
|
||||
} // stills handles its own width
|
||||
eventViewer.height(newHeight);
|
||||
if ( !vid ) { // zms needs extra sizing
|
||||
streamScale(scale == "auto" ? autoScale : scale);
|
||||
streamScale(scale == '0' ? autoScale : scale);
|
||||
drawProgressBar();
|
||||
}
|
||||
if ( streamMode == 'stills' ) {
|
||||
|
@ -184,7 +175,7 @@ function changeScale() {
|
|||
} else {
|
||||
alarmCue.html(renderAlarmCues(eventViewer));//just re-render alarmCues. skip ajax call
|
||||
}
|
||||
if ( scale == "auto" ) {
|
||||
if ( scale == '0' ) {
|
||||
Cookie.write('zmEventScaleAuto', 'auto', {duration: 10*365});
|
||||
} else {
|
||||
Cookie.write('zmEventScale'+eventData.MonitorId, scale, {duration: 10*365});
|
||||
|
@ -200,6 +191,32 @@ function changeReplayMode() {
|
|||
refreshWindow();
|
||||
}
|
||||
|
||||
function changeRate() {
|
||||
var rate = parseInt($j('select[name="rate"]').val());
|
||||
if ( ! rate ) {
|
||||
pauseClicked();
|
||||
} else if ( rate < 0 ) {
|
||||
if ( vid ) { //There is no reverse play with mp4. Set the speed to 0 and manually set the time back.
|
||||
revSpeed = rates[rates.indexOf(-1*rate)-1]/100;
|
||||
clearInterval(intervalRewind);
|
||||
intervalRewind = setInterval(function() {
|
||||
if ( vid.currentTime() <= 0 ) {
|
||||
clearInterval(intervalRewind);
|
||||
vid.pause();
|
||||
} else {
|
||||
vid.playbackRate(0);
|
||||
vid.currentTime(vid.currentTime() - (revSpeed/2)); //Half of reverse speed because our interval is 500ms.
|
||||
}
|
||||
}, 500); //500ms is a compromise between smooth reverse and realistic performance
|
||||
} // end if vid
|
||||
} else { // Forward rate
|
||||
if ( vid ) {
|
||||
vid.playbackRate(rate/100);
|
||||
}
|
||||
}
|
||||
Cookie.write('zmEventRate', rate, {duration: 10*365});
|
||||
} // end function changeRate
|
||||
|
||||
var streamParms = "view=request&request=stream&connkey="+connKey;
|
||||
if ( auth_hash ) {
|
||||
streamParms += '&auth='+auth_hash;
|
||||
|
@ -245,7 +262,8 @@ function getCmdResponse( respObj, respText ) {
|
|||
if ( streamStatus.paused == true ) {
|
||||
streamPause( );
|
||||
} else {
|
||||
$j('#rateValue').html(streamStatus.rate);
|
||||
console.log('streamStatus.rate: ' + streamStatus.rate);
|
||||
$j('select[name="rate"]').val(streamStatus.rate*100);
|
||||
Cookie.write('zmEventRate', streamStatus.rate*100, {duration: 10*365});
|
||||
streamPlay( );
|
||||
}
|
||||
|
@ -280,23 +298,18 @@ var streamReq = new Request.JSON( {
|
|||
|
||||
function pauseClicked() {
|
||||
if ( vid ) {
|
||||
if ( intervalRewind ) {
|
||||
stopFastRev();
|
||||
}
|
||||
vid.pause();
|
||||
} else {
|
||||
streamReq.send(streamParms+"&command="+CMD_PAUSE);
|
||||
streamPause();
|
||||
}
|
||||
}
|
||||
|
||||
function vjsPause() {
|
||||
if ( intervalRewind ) {
|
||||
stopFastRev();
|
||||
}
|
||||
streamPause();
|
||||
}
|
||||
|
||||
function streamPause( ) {
|
||||
$j('#modeValue').html('Paused');
|
||||
$j('#rateValue').html('0');
|
||||
setButtonState( $('pauseBtn'), 'active' );
|
||||
setButtonState( $('playBtn'), 'inactive' );
|
||||
setButtonState( $('fastFwdBtn'), 'unavail' );
|
||||
|
@ -306,6 +319,10 @@ function streamPause( ) {
|
|||
}
|
||||
|
||||
function playClicked( ) {
|
||||
var rate_select = $j('select[name="rate"]');
|
||||
if ( ! rate_select.val() ) {
|
||||
$j('select[name="rate"]').val(100);
|
||||
}
|
||||
if ( vid ) {
|
||||
if ( vid.paused() ) {
|
||||
vid.play();
|
||||
|
@ -314,21 +331,20 @@ function playClicked( ) {
|
|||
}
|
||||
} else {
|
||||
streamReq.send(streamParms+"&command="+CMD_PLAY);
|
||||
streamPlay();
|
||||
}
|
||||
streamPlay();
|
||||
}
|
||||
|
||||
function vjsPlay() { //catches if we change mode programatically
|
||||
if ( intervalRewind ) {
|
||||
stopFastRev();
|
||||
}
|
||||
$j('#rateValue').html(vid.playbackRate());
|
||||
$j('select[name="rate"]').val(vid.playbackRate()*100);
|
||||
Cookie.write('zmEventRate', vid.playbackRate()*100, {duration: 10*365});
|
||||
streamPlay();
|
||||
}
|
||||
|
||||
function streamPlay( ) {
|
||||
$j('#modeValue').html('Replay');
|
||||
setButtonState( $('pauseBtn'), 'inactive' );
|
||||
setButtonState( $('playBtn'), 'active' );
|
||||
setButtonState( $('fastFwdBtn'), 'inactive' );
|
||||
|
@ -350,16 +366,13 @@ function streamFastFwd( action ) {
|
|||
if ( rates.indexOf(vid.playbackRate()*100)-1 == -1 ) {
|
||||
setButtonState($('fastFwdBtn'), 'unavail');
|
||||
}
|
||||
$j('#rateValue').html(vid.playbackRate());
|
||||
$j('select[name="rate"]').val(vid.playbackRate()*100);
|
||||
Cookie.write('zmEventRate', vid.playbackRate()*100, {duration: 10*365});
|
||||
} else {
|
||||
streamReq.send(streamParms+"&command="+CMD_FASTFWD);
|
||||
}
|
||||
}
|
||||
|
||||
var spf = Math.round((eventData.Length / eventData.Frames)*1000000 )/1000000;//Seconds per frame for videojs frame by frame.
|
||||
var intervalRewind;
|
||||
var revSpeed = .5;
|
||||
|
||||
function streamSlowFwd( action ) {
|
||||
if ( vid ) {
|
||||
|
@ -380,6 +393,7 @@ function streamSlowRev( action ) {
|
|||
function stopFastRev() {
|
||||
clearInterval(intervalRewind);
|
||||
vid.playbackRate(1);
|
||||
$j('select[name="rate"]').val(vid.playbackRate()*100);
|
||||
Cookie.write('zmEventRate', vid.playbackRate()*100, {duration: 10*365});
|
||||
revSpeed = .5;
|
||||
}
|
||||
|
@ -397,7 +411,7 @@ function streamFastRev( action ) {
|
|||
setButtonState( $('fastRevBtn'), 'unavail' );
|
||||
}
|
||||
clearInterval(intervalRewind);
|
||||
$j('#rateValue').html(-revSpeed);
|
||||
$j('select[name="rate"]').val(-revSpeed*100);
|
||||
Cookie.write('zmEventRate', vid.playbackRate()*100, {duration: 10*365});
|
||||
intervalRewind = setInterval(function() {
|
||||
if (vid.currentTime() <= 0) {
|
||||
|
@ -588,7 +602,7 @@ function getEventResponse(respObj, respText) {
|
|||
CurEventDefVideoPath = null;
|
||||
$j('#modeValue').html('Replay');
|
||||
$j('#zoomValue').html('1');
|
||||
$j('#rateValue').html('1');
|
||||
$j('#rate').val('100');
|
||||
vjsPanZoom('zoomOut');
|
||||
} else {
|
||||
drawProgressBar();
|
||||
|
@ -1059,7 +1073,7 @@ function initPage() {
|
|||
$j('.vjs-progress-control').append('<div class="alarmCue"></div>');//add a place for videojs only on first load
|
||||
vid.on('ended', vjsReplay);
|
||||
vid.on('play', vjsPlay);
|
||||
vid.on('pause', vjsPause);
|
||||
vid.on('pause', pauseClicked);
|
||||
vid.on('click', function(event) {
|
||||
handleClick(event);
|
||||
});
|
||||
|
@ -1067,7 +1081,8 @@ function initPage() {
|
|||
$j('#progressValue').html(secsToTime(Math.floor(vid.currentTime())));
|
||||
});
|
||||
|
||||
if ( rate > 1 ) {
|
||||
// rate is in % so 100 would be 1x
|
||||
if ( rate > 0 ) {
|
||||
// rate should be 100 = 1x, etc.
|
||||
vid.playbackRate(rate/100);
|
||||
}
|
||||
|
@ -1091,7 +1106,10 @@ function initPage() {
|
|||
}
|
||||
nearEventsQuery(eventData.Id);
|
||||
initialAlarmCues(eventData.Id); //call ajax+renderAlarmCues
|
||||
if ( scale == 'auto' ) changeScale();
|
||||
if ( scale == '0' || scale == 'auto' ) changeScale();
|
||||
document.querySelectorAll('select[name="rate"]').forEach(function(el) {
|
||||
el.onchange = window['changeRate'];
|
||||
});
|
||||
}
|
||||
|
||||
// Kick everything off
|
||||
|
|
|
@ -66,6 +66,15 @@ function updateButtons(element) {
|
|||
}
|
||||
}
|
||||
|
||||
function click_AutoEmail(element) {
|
||||
updateButtons(this);
|
||||
if ( this.checked ) {
|
||||
$j('#EmailOptions').show();
|
||||
} else {
|
||||
$j('#EmailOptions').hide();
|
||||
}
|
||||
}
|
||||
|
||||
function click_automove(element) {
|
||||
updateButtons(this);
|
||||
if ( this.checked ) {
|
||||
|
@ -105,10 +114,11 @@ function submitToEvents( element ) {
|
|||
history.replaceState(null, null, '?view=filter&' + $j(form).serialize());
|
||||
}
|
||||
|
||||
function submitToMontageReview( element ) {
|
||||
function submitToMontageReview(element) {
|
||||
var form = element.form;
|
||||
form.action = thisUrl + '?view=montagereview';
|
||||
history.replaceState(null, null, '?view=filter&' + $j(form).serialize());
|
||||
window.location.assign('?view=montagereview&'+$j(form).serialize());
|
||||
history.replaceState(null, null, '?view=montagereview&live=0&' + $j(form).serialize());
|
||||
}
|
||||
|
||||
function submitToExport(element) {
|
||||
|
@ -183,7 +193,8 @@ function parseRows(rows) {
|
|||
}
|
||||
|
||||
var attr = inputTds.eq(2).children().val();
|
||||
if ( attr == 'Archived' ) { // Archived types
|
||||
|
||||
if ( attr == 'Archived' ) { //Archived types
|
||||
inputTds.eq(3).html('equal to<input type="hidden" name="filter[Query][terms][' + rowNum + '][op]" value="=">');
|
||||
var archiveSelect = $j('<select></select>').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]');
|
||||
for (var i = 0; i < archiveTypes.length; i++) {
|
||||
|
@ -191,6 +202,18 @@ function parseRows(rows) {
|
|||
}
|
||||
var archiveVal = inputTds.eq(4).children().val();
|
||||
inputTds.eq(4).html(archiveSelect).children().val(archiveVal).chosen({width: "101%"});
|
||||
} else if ( attr == 'AlarmedZoneId' ) {
|
||||
var zoneSelect = $j('<select></select>').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]');
|
||||
for ( monitor_id in monitors ) {
|
||||
for ( zone_id in zones ) {
|
||||
var zone = zones[zone_id];
|
||||
if ( monitor_id == zone.MonitorId ) {
|
||||
zoneSelect.append('<option value="' + zone_id + '">' + zone.Name + '</option>');
|
||||
}
|
||||
} // end foreach zone
|
||||
} // end foreach monitor
|
||||
var zoneVal = inputTds.eq(4).children().val();
|
||||
inputTds.eq(4).html(zoneSelect).children().val(zoneVal).chosen({width: "101%"});
|
||||
} else if ( attr.indexOf('Weekday') >= 0 ) { //Weekday selection
|
||||
var weekdaySelect = $j('<select></select>').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]');
|
||||
for (var i = 0; i < weekdays.length; i++) {
|
||||
|
@ -221,22 +244,29 @@ function parseRows(rows) {
|
|||
inputTds.eq(4).html(storageSelect).children().val(storageVal).chosen({width: "101%"});
|
||||
} else if ( attr == 'MonitorName' ) { //Monitor names
|
||||
var monitorSelect = $j('<select></select>').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]');
|
||||
for (var key in monitors) {
|
||||
monitorSelect.append('<option value="' + key + '">' + monitors[key] + '</option>');
|
||||
for ( var monitor_id in monitors ) {
|
||||
monitorSelect.append('<option value="' + monitors[monitor_id].Name + '">' + monitors[monitor_id].Name + '</option>');
|
||||
}
|
||||
var monitorVal = inputTds.eq(4).children().val();
|
||||
inputTds.eq(4).html(monitorSelect).children().val(monitorVal);
|
||||
} else { //Reset to regular text field and operator for everything that isn't special
|
||||
var opSelect = $j('<select></select>').attr('name', queryPrefix + rowNum + '][op]').attr('id', queryPrefix + rowNum + '][op]');
|
||||
for (var key in opTypes) {
|
||||
opSelect.append('<option value="' + key + '">' + opTypes[key] + '</option>');
|
||||
}
|
||||
var opVal = inputTds.eq(3).children().val();
|
||||
inputTds.eq(3).html(opSelect).children().val(opVal).chosen({width: "101%"});
|
||||
} else { // Reset to regular text field and operator for everything that isn't special
|
||||
var textInput = $j('<input></input>').attr('type', 'text').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]');
|
||||
var textVal = inputTds.eq(4).children().val();
|
||||
inputTds.eq(4).html(textInput).children().val(textVal);
|
||||
}
|
||||
|
||||
// Validate the operator
|
||||
var opSelect = $j('<select></select>').attr('name', queryPrefix + rowNum + '][op]').attr('id', queryPrefix + rowNum + '][op]');
|
||||
var opVal = inputTds.eq(3).children().val();
|
||||
if ( ! opVal ) {
|
||||
// Default to equals so that something gets selected
|
||||
console.log("No value for operator. Defaulting to =");
|
||||
opVal = '=';
|
||||
}
|
||||
for ( var key in opTypes ) {
|
||||
opSelect.append('<option value="' + key + '"'+(key == opVal ? ' selected="selected"' : '')+'>' + opTypes[key] + '</option>');
|
||||
}
|
||||
inputTds.eq(3).html(opSelect).children().val(opVal).chosen({width: "101%"});
|
||||
if ( attr.endsWith('DateTime') ) { //Start/End DateTime
|
||||
inputTds.eq(4).children().datetimepicker({timeFormat: "HH:mm:ss", dateFormat: "yy-mm-dd", maxDate: 0, constrainInput: false});
|
||||
} else if ( attr.endsWith('Date') ) { //Start/End Date
|
||||
|
|
|
@ -10,6 +10,7 @@ var states = <?php echo isset($states) ? json_encode($states) : '' ?>;
|
|||
var servers = <?php echo isset($servers) ? json_encode($servers) : '' ?>;
|
||||
var storageareas = <?php echo isset($storageareas) ? json_encode($storageareas) : '' ?>;
|
||||
var monitors = <?php echo isset($monitors) ? json_encode($monitors) : '' ?>;
|
||||
var zones = <?php echo isset($zones) ? json_encode($zones) : '' ?>;
|
||||
|
||||
var errorBrackets = '<?php echo translate('ErrorBrackets') ?>';
|
||||
var errorValue = '<?php echo translate('ErrorValidValue') ?>';
|
||||
|
|
|
@ -334,7 +334,7 @@ function changeScale() {
|
|||
Cookie.write('zmMontageScale', scale, {duration: 10*365});
|
||||
Cookie.write('zmMontageWidth', '', {duration: 10*365});
|
||||
Cookie.write('zmMontageHeight', '', {duration: 10*365});
|
||||
if ( !scale ) {
|
||||
if ( scale == '' ) {
|
||||
selectLayout('#zmMontageLayout');
|
||||
return;
|
||||
}
|
||||
|
@ -349,8 +349,12 @@ function changeScale() {
|
|||
console.log("Error finding frame for " + monitor.id);
|
||||
continue;
|
||||
}
|
||||
if ( newWidth ) {
|
||||
monitor_frame.css('width', newWidth);
|
||||
if ( scale != '0' ) {
|
||||
if ( newWidth ) {
|
||||
monitor_frame.css('width', newWidth);
|
||||
}
|
||||
} else {
|
||||
monitor_frame.css('width', '100%');
|
||||
}
|
||||
// We don't set the frame height because it has the status bar as well
|
||||
//if ( height ) {
|
||||
|
@ -364,13 +368,24 @@ function changeScale() {
|
|||
streamImg.src = '';
|
||||
|
||||
//src = src.replace(/rand=\d+/i,'rand='+Math.floor((Math.random() * 1000000) ));
|
||||
src = src.replace(/scale=[\.\d]+/i, 'scale='+scale);
|
||||
src = src.replace(/width=[\.\d]+/i, 'width='+newWidth);
|
||||
src = src.replace(/height=[\.\d]+/i, 'height='+newHeight);
|
||||
if ( scale != '0' ) {
|
||||
src = src.replace(/scale=[\.\d]+/i, 'scale='+scale);
|
||||
src = src.replace(/width=[\.\d]+/i, 'width='+newWidth);
|
||||
src = src.replace(/height=[\.\d]+/i, 'height='+newHeight);
|
||||
} else {
|
||||
src = src.replace(/scale=[\.\d]+/i, 'scale=100');
|
||||
src = src.replace(/width=[\.\d]+/i, 'width='+monitorData[i].width);
|
||||
src = src.replace(/height=[\.\d]+/i, 'height='+monitorData[i].height);
|
||||
}
|
||||
streamImg.src = src;
|
||||
}
|
||||
streamImg.style.width = newWidth + "px";
|
||||
streamImg.style.height = newHeight + "px";
|
||||
if ( scale != '0' ) {
|
||||
streamImg.style.width = newWidth + "px";
|
||||
streamImg.style.height = newHeight + "px";
|
||||
} else {
|
||||
streamImg.style.width = '100%';
|
||||
streamImg.style.height = 'auto';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -467,6 +482,7 @@ function initPage() {
|
|||
|
||||
// Start the fps and status updates. give a random delay so that we don't assault the server
|
||||
var delay = Math.round( (Math.random()+0.5)*statusRefreshTimeout );
|
||||
console.log("delay: " + delay);
|
||||
monitors[i].start(delay);
|
||||
|
||||
var interval = monitors[i].refresh;
|
||||
|
|
|
@ -936,6 +936,10 @@ function changeDateTime(e) {
|
|||
}
|
||||
}
|
||||
|
||||
// Reloading can take a while, so stop interrupts to reduce load
|
||||
clearInterval(timerObj);
|
||||
timerObj = null;
|
||||
|
||||
var uri = "?view=" + currentView + fitStr + minStr + maxStr + liveStr + zoomStr + "&scale=" + $j("#scaleslider")[0].value + "&speed=" + speeds[$j("#speedslider")[0].value];
|
||||
window.location = uri;
|
||||
}
|
||||
|
@ -967,6 +971,7 @@ function initPage() {
|
|||
imagedone(this, this.monId, false);
|
||||
};
|
||||
loadImage2Monitor(monId, monitorImageURL[monId]);
|
||||
monitorCanvasObj[monId].addEventListener('click', clickMonitor, false);
|
||||
}
|
||||
} // end foreach monitor
|
||||
|
||||
|
@ -982,15 +987,6 @@ function initPage() {
|
|||
ctx = canvas.getContext('2d');
|
||||
drawGraph();
|
||||
}
|
||||
for ( i=0, len=monitorPtr.length; i < len; i += 1 ) {
|
||||
var monitor_id = monitorPtr[i];
|
||||
monitor_canvas = $('Monitor'+monitor_id);
|
||||
if ( ! monitor_canvas ) {
|
||||
console.log("No canvas found for monitor " + monitor_id);
|
||||
continue;
|
||||
}
|
||||
monitor_canvas.addEventListener('click', clickMonitor, false);
|
||||
}
|
||||
setSpeed(speedIndex);
|
||||
//setFit(fitMode); // will redraw
|
||||
//setLive(liveMode); // will redraw
|
||||
|
|
|
@ -68,7 +68,7 @@ if ( !$liveMode ) {
|
|||
$frame['NextFrameId'] = $next_frames[$frame['EventId']]['Id'];
|
||||
}
|
||||
$event['FramesById'] += array($frame['Id']=>$frame);
|
||||
$next_frames[$frame['EventId']] = $frame;
|
||||
$next_frames[$frame['EventId']] = &$event['FramesById'][$frame['Id']];
|
||||
}
|
||||
} // end if dbQuery
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
function deleteVideo( e ) {
|
||||
function deleteVideo(e) {
|
||||
index = e.getAttribute('data-file-index');
|
||||
window.location.replace( thisUrl+'?view='+currentView+'&eid='+eventId+'&deleteIndex='+index );
|
||||
window.location.replace(thisUrl+'?view='+currentView+'&eid='+eventId+'&deleteIndex='+index);
|
||||
}
|
||||
|
||||
function downloadVideo( e ) {
|
||||
function downloadVideo(e) {
|
||||
index = e.getAttribute('data-file-index');
|
||||
window.location.replace( thisUrl+'?view='+currentView+'&eid='+eventId+'&downloadIndex='+index );
|
||||
window.location.replace(thisUrl+'?view='+currentView+'&eid='+eventId+'&downloadIndex='+index);
|
||||
}
|
||||
|
||||
var generateVideoTimer = null;
|
||||
|
@ -13,25 +13,25 @@ var generateVideoTimer = null;
|
|||
function generateVideoProgress() {
|
||||
var tickerText = $('videoProgressTicker').get('text');
|
||||
if ( tickerText.length < 1 || tickerText.length > 4 ) {
|
||||
$('videoProgressTicker').set( 'text', '.' );
|
||||
$('videoProgressTicker').set('text', '.');
|
||||
} else {
|
||||
$('videoProgressTicker').appendText( '.' );
|
||||
$('videoProgressTicker').appendText('.');
|
||||
}
|
||||
}
|
||||
|
||||
function generateVideoResponse( respObj, respText ) {
|
||||
window.location.replace( thisUrl+'?view='+currentView+'&eid='+eventId+'&generated='+((respObj.result=='Ok')?1:0) );
|
||||
window.location.replace(thisUrl+'?view='+currentView+'&eid='+eventId+'&generated='+((respObj.result=='Ok')?1:0));
|
||||
}
|
||||
|
||||
function generateVideo() {
|
||||
form = $j('#contentForm')[0];
|
||||
var parms = 'view=request&request=event&action=video';
|
||||
parms += '&'+$(form).toQueryString();
|
||||
var query = new Request.JSON( {url: thisUrl, method: 'post', data: parms, onSuccess: generateVideoResponse} );
|
||||
var query = new Request.JSON({url: thisUrl, method: 'post', data: parms, onSuccess: generateVideoResponse});
|
||||
query.send();
|
||||
$('videoProgress').removeClass( 'hidden' );
|
||||
$('videoProgress').setProperty( 'class', 'warnText' );
|
||||
$('videoProgressText').set( 'text', videoGenProgressString );
|
||||
$('videoProgress').removeClass('hidden');
|
||||
$('videoProgress').setProperty('class', 'warnText');
|
||||
$('videoProgressText').set('text', videoGenProgressString);
|
||||
generateVideoProgress();
|
||||
generateVideoTimer = generateVideoProgress.periodical( 500 );
|
||||
generateVideoTimer = generateVideoProgress.periodical(500);
|
||||
}
|
||||
|
|
|
@ -1,39 +1,33 @@
|
|||
function setButtonState(element, butClass) {
|
||||
if ( element ) {
|
||||
element.className = butClass;
|
||||
element.disabled = (butClass != 'inactive');
|
||||
}
|
||||
}
|
||||
|
||||
function showEvents() {
|
||||
$('ptzControls').addClass( 'hidden' );
|
||||
$('events').removeClass( 'hidden' );
|
||||
$('ptzControls').addClass('hidden');
|
||||
$('events').removeClass('hidden');
|
||||
if ( $('eventsControl') ) {
|
||||
$('eventsControl').addClass('hidden');
|
||||
}
|
||||
if ( $('controlControl') ) {
|
||||
$('controlControl').removeClass('hidden');
|
||||
}
|
||||
showMode = "events";
|
||||
showMode = 'events';
|
||||
}
|
||||
|
||||
function showPtzControls() {
|
||||
$('events').addClass( 'hidden' );
|
||||
$('ptzControls').removeClass( 'hidden' );
|
||||
$('events').addClass('hidden');
|
||||
$('ptzControls').removeClass('hidden');
|
||||
if ( $('eventsControl') ) {
|
||||
$('eventsControl').removeClass('hidden');
|
||||
}
|
||||
if ( $('controlControl') ) {
|
||||
$('controlControl').addClass('hidden');
|
||||
}
|
||||
showMode = "control";
|
||||
showMode = 'control';
|
||||
}
|
||||
|
||||
function changeScale() {
|
||||
var scale = $('scale').get('value');
|
||||
var newWidth;
|
||||
var newHeight;
|
||||
if (scale == "auto") {
|
||||
if ( scale == '0' || scale == 'auto' ) {
|
||||
var newSize = scaleToFit(monitorWidth, monitorHeight, $j('#liveStream'+monitorId), $j('#replayStatus'));
|
||||
newWidth = newSize.width;
|
||||
newHeight = newSize.height;
|
||||
|
@ -87,7 +81,7 @@ function setAlarmState( currentAlarmState ) {
|
|||
if ( SOUND_ON_ALARM ) {
|
||||
// Enable the alarm sound
|
||||
if ( !canPlayPauseAudio ) {
|
||||
$('alarmSound').removeClass( 'hidden' );
|
||||
$('alarmSound').removeClass('hidden');
|
||||
} else {
|
||||
$('MediaPlayer').Play();
|
||||
}
|
||||
|
@ -96,22 +90,20 @@ function setAlarmState( currentAlarmState ) {
|
|||
window.focus();
|
||||
}
|
||||
}
|
||||
if ( SOUND_ON_ALARM ) {
|
||||
if ( oldAlarm ) {
|
||||
if ( oldAlarm ) { // done with an event do a refresh
|
||||
if ( SOUND_ON_ALARM ) {
|
||||
// Disable alarm sound
|
||||
if ( !canPlayPauseAudio ) {
|
||||
$('alarmSound').addClass( 'hidden' );
|
||||
$('alarmSound').addClass('hidden');
|
||||
} else {
|
||||
$('MediaPlayer').Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (oldAlarm) { // done with an event do a refresh
|
||||
eventCmdQuery();
|
||||
}
|
||||
|
||||
lastAlarmState = alarmState;
|
||||
}
|
||||
} // end function setAlarmState( currentAlarmState )
|
||||
|
||||
if ( monitorType != 'WebSite' ) {
|
||||
var streamCmdParms = 'view=request&request=stream&connkey='+connKey;
|
||||
|
@ -155,11 +147,11 @@ function getStreamCmdResponse(respObj, respText) {
|
|||
|
||||
$('levelValue').set('text', streamStatus.level);
|
||||
if ( streamStatus.level > 95 ) {
|
||||
$('levelValue').className = "alarm";
|
||||
$('levelValue').className = 'alarm';
|
||||
} else if ( streamStatus.level > 80 ) {
|
||||
$('levelValue').className = "alert";
|
||||
$('levelValue').className = 'alert';
|
||||
} else {
|
||||
$('levelValue').className = "ok";
|
||||
$('levelValue').className = 'ok';
|
||||
}
|
||||
|
||||
var delayString = secsToTime(streamStatus.delay);
|
||||
|
@ -194,7 +186,7 @@ function getStreamCmdResponse(respObj, respText) {
|
|||
}
|
||||
} // rate
|
||||
} else {
|
||||
$('modeValue').set( 'text', "Live" );
|
||||
$('modeValue').set( 'text', 'Live' );
|
||||
$('rate').addClass( 'hidden' );
|
||||
$('delay').addClass( 'hidden' );
|
||||
$('level').addClass( 'hidden' );
|
||||
|
@ -203,9 +195,9 @@ function getStreamCmdResponse(respObj, respText) {
|
|||
|
||||
$('zoomValue').set('text', streamStatus.zoom);
|
||||
if ( streamStatus.zoom == '1.0' ) {
|
||||
setButtonState($('zoomOutBtn'), 'unavail');
|
||||
setButtonState('zoomOutBtn', 'unavail');
|
||||
} else {
|
||||
setButtonState($('zoomOutBtn'), 'inactive');
|
||||
setButtonState('zoomOutBtn', 'inactive');
|
||||
}
|
||||
|
||||
if ( canEditMonitors ) {
|
||||
|
@ -230,7 +222,6 @@ function getStreamCmdResponse(respObj, respText) {
|
|||
|
||||
if ( streamStatus.auth ) {
|
||||
auth_hash = streamStatus.auth;
|
||||
console.log("Have a new auth hash" + streamStatus.auth);
|
||||
// Try to reload the image stream.
|
||||
var streamImg = $('liveStream');
|
||||
if ( streamImg ) {
|
||||
|
@ -243,7 +234,7 @@ function getStreamCmdResponse(respObj, respText) {
|
|||
} // end if have a new auth hash
|
||||
} // end if respObj.status
|
||||
} else {
|
||||
checkStreamForErrors("getStreamCmdResponse", respObj);//log them
|
||||
checkStreamForErrors('getStreamCmdResponse', respObj);//log them
|
||||
// Try to reload the image stream.
|
||||
// If it's an auth error, we should reload the whole page.
|
||||
window.location.reload();
|
||||
|
@ -251,9 +242,9 @@ function getStreamCmdResponse(respObj, respText) {
|
|||
var streamImg = $('liveStream'+monitorId);
|
||||
if ( streamImg ) {
|
||||
streamImg.src = streamImg.src.replace(/rand=\d+/i, 'rand='+Math.floor((Math.random() * 1000000) ));
|
||||
console.log("Changing livestream src to " + streamImg.src);
|
||||
console.log('Changing livestream src to ' + streamImg.src);
|
||||
} else {
|
||||
console.log("Unable to find streamImg liveStream");
|
||||
console.log('Unable to find streamImg liveStream');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -262,132 +253,152 @@ function getStreamCmdResponse(respObj, respText) {
|
|||
if ( alarmState == STATE_ALARM || alarmState == STATE_ALERT ) {
|
||||
streamCmdTimeout = streamCmdTimeout/5;
|
||||
}
|
||||
streamCmdTimer = streamCmdQuery.delay( streamCmdTimeout );
|
||||
streamCmdTimer = streamCmdQuery.delay(streamCmdTimeout);
|
||||
}
|
||||
|
||||
function streamCmdPause( action ) {
|
||||
setButtonState( $('pauseBtn'), 'active' );
|
||||
setButtonState( $('playBtn'), 'inactive' );
|
||||
setButtonState( $('stopBtn'), 'inactive' );
|
||||
setButtonState( $('fastFwdBtn'), 'inactive' );
|
||||
setButtonState( $('slowFwdBtn'), 'inactive' );
|
||||
setButtonState( $('slowRevBtn'), 'inactive' );
|
||||
setButtonState( $('fastRevBtn'), 'inactive' );
|
||||
setButtonState('pauseBtn', 'active');
|
||||
setButtonState('playBtn', 'inactive');
|
||||
setButtonState('stopBtn', 'inactive');
|
||||
if ( monitorStreamReplayBuffer ) {
|
||||
setButtonState('fastFwdBtn', 'inactive');
|
||||
setButtonState('slowFwdBtn', 'inactive');
|
||||
setButtonState('slowRevBtn', 'inactive');
|
||||
setButtonState('fastRevBtn', 'inactive');
|
||||
}
|
||||
if ( action ) {
|
||||
streamCmdReq.send( streamCmdParms+"&command="+CMD_PAUSE );
|
||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_PAUSE);
|
||||
}
|
||||
}
|
||||
|
||||
function streamCmdPlay( action ) {
|
||||
setButtonState( $('pauseBtn'), 'inactive' );
|
||||
setButtonState( $('playBtn'), 'active' );
|
||||
setButtonState('pauseBtn', 'inactive');
|
||||
setButtonState('playBtn', 'active');
|
||||
if ( streamStatus.delayed == true ) {
|
||||
setButtonState( $('stopBtn'), 'inactive' );
|
||||
setButtonState( $('fastFwdBtn'), 'inactive' );
|
||||
setButtonState( $('slowFwdBtn'), 'inactive' );
|
||||
setButtonState( $('slowRevBtn'), 'inactive' );
|
||||
setButtonState( $('fastRevBtn'), 'inactive' );
|
||||
setButtonState('stopBtn', 'inactive');
|
||||
if ( monitorStreamReplayBuffer ) {
|
||||
setButtonState('fastFwdBtn', 'inactive');
|
||||
setButtonState('slowFwdBtn', 'inactive');
|
||||
setButtonState('slowRevBtn', 'inactive');
|
||||
setButtonState('fastRevBtn', 'inactive');
|
||||
}
|
||||
} else {
|
||||
setButtonState( $('stopBtn'), 'unavail' );
|
||||
setButtonState( $('fastFwdBtn'), 'unavail' );
|
||||
setButtonState( $('slowFwdBtn'), 'unavail' );
|
||||
setButtonState( $('slowRevBtn'), 'unavail' );
|
||||
setButtonState( $('fastRevBtn'), 'unavail' );
|
||||
setButtonState('stopBtn', 'unavail');
|
||||
if ( monitorStreamReplayBuffer ) {
|
||||
setButtonState('fastFwdBtn', 'unavail');
|
||||
setButtonState('slowFwdBtn', 'unavail');
|
||||
setButtonState('slowRevBtn', 'unavail');
|
||||
setButtonState('fastRevBtn', 'unavail');
|
||||
}
|
||||
}
|
||||
if ( action ) {
|
||||
streamCmdReq.send( streamCmdParms+"&command="+CMD_PLAY );
|
||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_PLAY);
|
||||
}
|
||||
}
|
||||
|
||||
function streamCmdStop( action ) {
|
||||
setButtonState( $('pauseBtn'), 'inactive' );
|
||||
setButtonState( $('playBtn'), 'unavail' );
|
||||
setButtonState( $('stopBtn'), 'active' );
|
||||
setButtonState( $('fastFwdBtn'), 'unavail' );
|
||||
setButtonState( $('slowFwdBtn'), 'unavail' );
|
||||
setButtonState( $('slowRevBtn'), 'unavail' );
|
||||
setButtonState( $('fastRevBtn'), 'unavail' );
|
||||
if ( action ) {
|
||||
streamCmdReq.send( streamCmdParms+"&command="+CMD_STOP );
|
||||
setButtonState('pauseBtn', 'inactive');
|
||||
setButtonState('playBtn', 'unavail');
|
||||
setButtonState('stopBtn', 'active');
|
||||
if ( monitorStreamReplayBuffer ) {
|
||||
setButtonState('fastFwdBtn', 'unavail');
|
||||
setButtonState('slowFwdBtn', 'unavail');
|
||||
setButtonState('slowRevBtn', 'unavail');
|
||||
setButtonState('fastRevBtn', 'unavail');
|
||||
}
|
||||
setButtonState( $('stopBtn'), 'unavail' );
|
||||
setButtonState( $('playBtn'), 'active' );
|
||||
if ( action ) {
|
||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_STOP);
|
||||
}
|
||||
setButtonState('stopBtn', 'unavail');
|
||||
setButtonState('playBtn', 'active');
|
||||
}
|
||||
|
||||
function streamCmdFastFwd( action ) {
|
||||
setButtonState( $('pauseBtn'), 'inactive' );
|
||||
setButtonState( $('playBtn'), 'inactive' );
|
||||
setButtonState( $('stopBtn'), 'inactive' );
|
||||
setButtonState( $('fastFwdBtn'), 'inactive' );
|
||||
setButtonState( $('slowFwdBtn'), 'inactive' );
|
||||
setButtonState( $('slowRevBtn'), 'inactive' );
|
||||
setButtonState( $('fastRevBtn'), 'inactive' );
|
||||
setButtonState('pauseBtn', 'inactive');
|
||||
setButtonState('playBtn', 'inactive');
|
||||
setButtonState('stopBtn', 'inactive');
|
||||
if ( monitorStreamReplayBuffer ) {
|
||||
setButtonState('fastFwdBtn', 'inactive');
|
||||
setButtonState('slowFwdBtn', 'inactive');
|
||||
setButtonState('slowRevBtn', 'inactive');
|
||||
setButtonState('fastRevBtn', 'inactive');
|
||||
}
|
||||
if ( action ) {
|
||||
streamCmdReq.send( streamCmdParms+"&command="+CMD_FASTFWD );
|
||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_FASTFWD);
|
||||
}
|
||||
}
|
||||
|
||||
function streamCmdSlowFwd( action ) {
|
||||
setButtonState( $('pauseBtn'), 'inactive' );
|
||||
setButtonState( $('playBtn'), 'inactive' );
|
||||
setButtonState( $('stopBtn'), 'inactive' );
|
||||
setButtonState( $('fastFwdBtn'), 'inactive' );
|
||||
setButtonState( $('slowFwdBtn'), 'active' );
|
||||
setButtonState( $('slowRevBtn'), 'inactive' );
|
||||
setButtonState( $('fastRevBtn'), 'inactive' );
|
||||
if ( action ) {
|
||||
streamCmdReq.send( streamCmdParms+"&command="+CMD_SLOWFWD );
|
||||
setButtonState('pauseBtn', 'inactive');
|
||||
setButtonState('playBtn', 'inactive');
|
||||
setButtonState('stopBtn', 'inactive');
|
||||
if ( monitorStreamReplayBuffer ) {
|
||||
setButtonState('fastFwdBtn', 'inactive');
|
||||
setButtonState('slowFwdBtn', 'active');
|
||||
setButtonState('slowRevBtn', 'inactive');
|
||||
setButtonState('fastRevBtn', 'inactive');
|
||||
}
|
||||
if ( action ) {
|
||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_SLOWFWD);
|
||||
}
|
||||
setButtonState('pauseBtn', 'active');
|
||||
if ( monitorStreamReplayBuffer ) {
|
||||
setButtonState('slowFwdBtn', 'inactive');
|
||||
}
|
||||
setButtonState( $('pauseBtn'), 'active' );
|
||||
setButtonState( $('slowFwdBtn'), 'inactive' );
|
||||
}
|
||||
|
||||
function streamCmdSlowRev( action ) {
|
||||
setButtonState( $('pauseBtn'), 'inactive' );
|
||||
setButtonState( $('playBtn'), 'inactive' );
|
||||
setButtonState( $('stopBtn'), 'inactive' );
|
||||
setButtonState( $('fastFwdBtn'), 'inactive' );
|
||||
setButtonState( $('slowFwdBtn'), 'inactive' );
|
||||
setButtonState( $('slowRevBtn'), 'active' );
|
||||
setButtonState( $('fastRevBtn'), 'inactive' );
|
||||
if ( action ) {
|
||||
streamCmdReq.send( streamCmdParms+"&command="+CMD_SLOWREV );
|
||||
setButtonState('pauseBtn', 'inactive');
|
||||
setButtonState('playBtn', 'inactive');
|
||||
setButtonState('stopBtn', 'inactive');
|
||||
if ( monitorStreamReplayBuffer ) {
|
||||
setButtonState('fastFwdBtn', 'inactive');
|
||||
setButtonState('slowFwdBtn', 'inactive');
|
||||
setButtonState('slowRevBtn', 'active');
|
||||
setButtonState('fastRevBtn', 'inactive');
|
||||
}
|
||||
if ( action ) {
|
||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_SLOWREV);
|
||||
}
|
||||
setButtonState('pauseBtn', 'active');
|
||||
if ( monitorStreamReplayBuffer ) {
|
||||
setButtonState('slowRevBtn', 'inactive');
|
||||
}
|
||||
setButtonState( $('pauseBtn'), 'active' );
|
||||
setButtonState( $('slowRevBtn'), 'inactive' );
|
||||
}
|
||||
|
||||
function streamCmdFastRev( action ) {
|
||||
setButtonState( $('pauseBtn'), 'inactive' );
|
||||
setButtonState( $('playBtn'), 'inactive' );
|
||||
setButtonState( $('stopBtn'), 'inactive' );
|
||||
setButtonState( $('fastFwdBtn'), 'inactive' );
|
||||
setButtonState( $('slowFwdBtn'), 'inactive' );
|
||||
setButtonState( $('slowRevBtn'), 'inactive' );
|
||||
setButtonState( $('fastRevBtn'), 'inactive' );
|
||||
setButtonState('pauseBtn', 'inactive');
|
||||
setButtonState('playBtn', 'inactive');
|
||||
setButtonState('stopBtn', 'inactive');
|
||||
if ( monitorStreamReplayBuffer ) {
|
||||
setButtonState('fastFwdBtn', 'inactive');
|
||||
setButtonState('slowFwdBtn', 'inactive');
|
||||
setButtonState('slowRevBtn', 'inactive');
|
||||
setButtonState('fastRevBtn', 'inactive');
|
||||
}
|
||||
if ( action ) {
|
||||
streamCmdReq.send( streamCmdParms+"&command="+CMD_FASTREV );
|
||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_FASTREV);
|
||||
}
|
||||
}
|
||||
|
||||
function streamCmdZoomIn( x, y ) {
|
||||
streamCmdReq.send( streamCmdParms+"&command="+CMD_ZOOMIN+"&x="+x+"&y="+y );
|
||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_ZOOMIN+"&x="+x+"&y="+y);
|
||||
}
|
||||
|
||||
function streamCmdZoomOut() {
|
||||
streamCmdReq.send( streamCmdParms+"&command="+CMD_ZOOMOUT );
|
||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_ZOOMOUT);
|
||||
}
|
||||
|
||||
function streamCmdScale( scale ) {
|
||||
streamCmdReq.send( streamCmdParms+"&command="+CMD_SCALE+"&scale="+scale );
|
||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_SCALE+"&scale="+scale);
|
||||
}
|
||||
|
||||
function streamCmdPan( x, y ) {
|
||||
streamCmdReq.send( streamCmdParms+"&command="+CMD_PAN+"&x="+x+"&y="+y );
|
||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_PAN+"&x="+x+"&y="+y);
|
||||
}
|
||||
|
||||
function streamCmdQuery() {
|
||||
streamCmdReq.send( streamCmdParms+"&command="+CMD_QUERY );
|
||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_QUERY);
|
||||
}
|
||||
|
||||
if ( monitorType != 'WebSite' ) {
|
||||
|
@ -395,12 +406,18 @@ if ( monitorType != 'WebSite' ) {
|
|||
if ( auth_hash ) {
|
||||
statusCmdParms += '&auth='+auth_hash;
|
||||
}
|
||||
var statusCmdReq = new Request.JSON( {url: monitorUrl, method: 'get', data: statusCmdParms, timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getStatusCmdResponse} );
|
||||
var statusCmdReq = new Request.JSON( {
|
||||
url: monitorUrl,
|
||||
method: 'get',
|
||||
timeout: AJAX_TIMEOUT,
|
||||
link: 'cancel',
|
||||
onSuccess: getStatusCmdResponse
|
||||
} );
|
||||
var statusCmdTimer = null;
|
||||
}
|
||||
|
||||
function getStatusCmdResponse(respObj, respText) {
|
||||
watchdogOk("status");
|
||||
watchdogOk('status');
|
||||
if ( statusCmdTimer ) {
|
||||
statusCmdTimer = clearTimeout(statusCmdTimer);
|
||||
}
|
||||
|
@ -409,22 +426,22 @@ function getStatusCmdResponse(respObj, respText) {
|
|||
$('fpsValue').set('text', respObj.monitor.FrameRate);
|
||||
setAlarmState(respObj.monitor.Status);
|
||||
} else {
|
||||
checkStreamForErrors("getStatusCmdResponse", respObj);
|
||||
checkStreamForErrors('getStatusCmdResponse', respObj);
|
||||
}
|
||||
|
||||
var statusCmdTimeout = statusRefreshTimeout;
|
||||
if ( alarmState == STATE_ALARM || alarmState == STATE_ALERT ) {
|
||||
statusCmdTimeout = statusCmdTimeout/5;
|
||||
}
|
||||
statusCmdTimer = statusCmdQuery.delay( statusCmdTimeout );
|
||||
statusCmdTimer = statusCmdQuery.delay(statusCmdTimeout);
|
||||
}
|
||||
|
||||
function statusCmdQuery() {
|
||||
statusCmdReq.send();
|
||||
statusCmdReq.send(statusCmdParms);
|
||||
}
|
||||
|
||||
if ( monitorType != 'WebSite' ) {
|
||||
var alarmCmdParms = "view=request&request=alarm&id="+monitorId;
|
||||
var alarmCmdParms = 'view=request&request=alarm&id='+monitorId;
|
||||
if ( auth_hash ) {
|
||||
alarmCmdParms += '&auth='+auth_hash;
|
||||
}
|
||||
|
@ -439,8 +456,8 @@ if ( monitorType != 'WebSite' ) {
|
|||
var alarmCmdFirst = true;
|
||||
}
|
||||
|
||||
function getAlarmCmdResponse( respObj, respText ) {
|
||||
checkStreamForErrors("getAlarmCmdResponse", respObj);
|
||||
function getAlarmCmdResponse(respObj, respText) {
|
||||
checkStreamForErrors('getAlarmCmdResponse', respObj);
|
||||
}
|
||||
|
||||
function cmdDisableAlarms() {
|
||||
|
@ -453,14 +470,14 @@ function cmdEnableAlarms() {
|
|||
|
||||
function cmdForceAlarm() {
|
||||
alarmCmdReq.send(alarmCmdParms+"&command=forceAlarm");
|
||||
if (window.event) {
|
||||
if ( window.event ) {
|
||||
window.event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
function cmdCancelForcedAlarm() {
|
||||
alarmCmdReq.send(alarmCmdParms+"&command=cancelForcedAlarm");
|
||||
if (window.event) {
|
||||
if ( window.event ) {
|
||||
window.event.preventDefault();
|
||||
}
|
||||
return false;
|
||||
|
@ -476,8 +493,8 @@ function getActResponse( respObj, respText ) {
|
|||
eventCmdQuery();
|
||||
}
|
||||
|
||||
function deleteEvent( event, eventId ) {
|
||||
var actParms = "view=request&request=event&action=delete&id="+eventId;
|
||||
function deleteEvent(event, eventId) {
|
||||
var actParms = 'view=request&request=event&action=delete&id='+eventId;
|
||||
if ( auth_hash ) {
|
||||
actParms += '&auth='+auth_hash;
|
||||
}
|
||||
|
@ -485,10 +502,9 @@ function deleteEvent( event, eventId ) {
|
|||
url: thisUrl,
|
||||
method: 'post',
|
||||
timeout: 3000,
|
||||
data: actParms,
|
||||
onSuccess: getActResponse
|
||||
} );
|
||||
actReq.send();
|
||||
actReq.send(actParms);
|
||||
event.stop();
|
||||
}
|
||||
|
||||
|
@ -501,7 +517,6 @@ if ( monitorType != 'WebSite' ) {
|
|||
url: monitorUrl,
|
||||
method: 'get',
|
||||
timeout: AJAX_TIMEOUT,
|
||||
data: eventCmdParms,
|
||||
link: 'cancel',
|
||||
onSuccess: getEventCmdResponse,
|
||||
onTimeout: eventCmdQuery
|
||||
|
@ -515,19 +530,19 @@ function highlightRow( row ) {
|
|||
}
|
||||
|
||||
function getEventCmdResponse( respObj, respText ) {
|
||||
watchdogOk("event");
|
||||
watchdogOk('event');
|
||||
if ( eventCmdTimer ) {
|
||||
eventCmdTimer = clearTimeout( eventCmdTimer );
|
||||
eventCmdTimer = clearTimeout(eventCmdTimer);
|
||||
}
|
||||
|
||||
if ( respObj.result == 'Ok' ) {
|
||||
var dbEvents = respObj.events.reverse();
|
||||
var eventList = $('eventList');
|
||||
var eventListBody = $(eventList).getElement( 'tbody' );
|
||||
var eventListRows = $(eventListBody).getElements( 'tr' );
|
||||
var eventListBody = $(eventList).getElement('tbody');
|
||||
var eventListRows = $(eventListBody).getElements('tr');
|
||||
|
||||
eventListRows.each( function( row ) {
|
||||
row.removeClass( 'updated' );
|
||||
eventListRows.each( function(row) {
|
||||
row.removeClass('updated');
|
||||
} );
|
||||
|
||||
for ( var i = 0; i < dbEvents.length; i++ ) {
|
||||
|
@ -581,30 +596,30 @@ function getEventCmdResponse( respObj, respText ) {
|
|||
'mouseout': highlightRow.pass(row)
|
||||
}
|
||||
});
|
||||
link.set( 'text', 'X' );
|
||||
link.inject( row.getElement( 'td.colDelete' ) );
|
||||
link.set('text', 'X');
|
||||
link.inject(row.getElement('td.colDelete'));
|
||||
|
||||
if ( i == 0 ) {
|
||||
row.inject( $(eventListBody) );
|
||||
row.inject($(eventListBody));
|
||||
} else {
|
||||
row.inject( $(eventListBody), 'top' );
|
||||
row.inject($(eventListBody), 'top');
|
||||
if ( !eventCmdFirst ) {
|
||||
row.addClass( 'recent' );
|
||||
row.addClass('recent');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
row.getElement( 'td.colName a' ).set( 'text', event.Name );
|
||||
row.getElement( 'td.colSecs' ).set( 'text', event.Length );
|
||||
row.getElement( 'td.colFrames a' ).set( 'text', event.Frames+'/'+event.AlarmFrames );
|
||||
row.getElement( 'td.colScore a' ).set( 'text', event.AvgScore+'/'+event.MaxScore );
|
||||
row.removeClass( 'recent' );
|
||||
row.getElement('td.colName a').set('text', event.Name);
|
||||
row.getElement('td.colSecs').set('text', event.Length);
|
||||
row.getElement('td.colFrames a').set('text', event.Frames+'/'+event.AlarmFrames);
|
||||
row.getElement('td.colScore a').set('text', event.AvgScore+'/'+event.MaxScore);
|
||||
row.removeClass('recent');
|
||||
}
|
||||
row.addClass( 'updated' );
|
||||
row.addClass('updated');
|
||||
}
|
||||
|
||||
var rows = $(eventListBody).getElements( 'tr' );
|
||||
var rows = $(eventListBody).getElements('tr');
|
||||
for ( var i = 0; i < rows.length; i++ ) {
|
||||
if ( !rows[i].hasClass( 'updated' ) ) {
|
||||
if ( !rows[i].hasClass('updated') ) {
|
||||
rows[i].destroy();
|
||||
rows.splice( i, 1 );
|
||||
i--;
|
||||
|
@ -615,39 +630,45 @@ function getEventCmdResponse( respObj, respText ) {
|
|||
rows.length--;
|
||||
}
|
||||
} else {
|
||||
checkStreamForErrors("getEventCmdResponse", respObj);
|
||||
checkStreamForErrors('getEventCmdResponse', respObj);
|
||||
}
|
||||
|
||||
var eventCmdTimeout = eventsRefreshTimeout;
|
||||
if ( alarmState == STATE_ALARM || alarmState == STATE_ALERT ) {
|
||||
eventCmdTimeout = eventCmdTimeout/5;
|
||||
}
|
||||
eventCmdTimer = eventCmdQuery.delay( eventCmdTimeout );
|
||||
eventCmdTimer = eventCmdQuery.delay(eventCmdTimeout);
|
||||
eventCmdFirst = false;
|
||||
}
|
||||
|
||||
function eventCmdQuery() {
|
||||
if ( eventCmdTimer ) { // avoid firing another if we are firing one
|
||||
eventCmdTimer = clearTimeout( eventCmdTimer );
|
||||
eventCmdTimer = clearTimeout(eventCmdTimer);
|
||||
}
|
||||
eventCmdReq.send();
|
||||
eventCmdReq.send(eventCmdParms);
|
||||
}
|
||||
|
||||
if ( monitorType != 'WebSite' ) {
|
||||
var controlParms = "view=request&request=control&id="+monitorId;
|
||||
var controlParms = 'view=request&request=control&id='+monitorId;
|
||||
if ( auth_hash ) {
|
||||
controlParms += '&auth='+auth_hash;
|
||||
}
|
||||
var controlReq = new Request.JSON( {url: monitorUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getControlResponse} );
|
||||
var controlReq = new Request.JSON( {
|
||||
url: monitorUrl,
|
||||
method: 'post',
|
||||
timeout: AJAX_TIMEOUT,
|
||||
link: 'cancel',
|
||||
onSuccess: getControlResponse
|
||||
} );
|
||||
}
|
||||
|
||||
function getControlResponse( respObj, respText ) {
|
||||
function getControlResponse(respObj, respText) {
|
||||
if ( !respObj ) {
|
||||
return;
|
||||
}
|
||||
//console.log( respText );
|
||||
if ( respObj.result != 'Ok' ) {
|
||||
alert( "Control response was status = "+respObj.status+"\nmessage = "+respObj.message );
|
||||
alert("Control response was status = "+respObj.status+"\nmessage = "+respObj.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -680,19 +701,19 @@ function controlCmd( control, event, xtell, ytell ) {
|
|||
locParms += "&yge="+yge;
|
||||
}
|
||||
}
|
||||
controlReq.send( controlParms+"&control="+control+locParms );
|
||||
if ( streamMode == "single" ) {
|
||||
fetchImage.pass( $('imageFeed').getElement('img') ).delay( 1000 );
|
||||
controlReq.send(controlParms+"&control="+control+locParms);
|
||||
if ( streamMode == 'single' ) {
|
||||
fetchImage.pass($('imageFeed').getElement('img')).delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
function controlCmdImage( x, y ) {
|
||||
var imageControlParms = controlParms;
|
||||
imageControlParms += "&scale="+scale;
|
||||
imageControlParms += "&control="+imageControlMode;
|
||||
imageControlParms += '&scale='+scale;
|
||||
imageControlParms += '&control='+imageControlMode;
|
||||
|
||||
controlReq.send( imageControlParms+"&x="+x+"&y="+y );
|
||||
if ( streamMode == "single" ) {
|
||||
if ( streamMode == 'single' ) {
|
||||
fetchImage.pass( $('imageFeed').getElement('img') ).delay( 1000 );
|
||||
}
|
||||
}
|
||||
|
@ -706,7 +727,7 @@ function handleClick( event ) {
|
|||
var x = event.page.x - $(target).getLeft();
|
||||
var y = event.page.y - $(target).getTop();
|
||||
|
||||
if ( showMode == "events" || !imageControlMode ) {
|
||||
if ( showMode == 'events' || !imageControlMode ) {
|
||||
if ( event.shift ) {
|
||||
streamCmdPan( x, y );
|
||||
} else if ( event.event.ctrlKey ) {
|
||||
|
@ -803,7 +824,7 @@ function initPage() {
|
|||
if ( refreshApplet && appletRefreshTime ) {
|
||||
appletRefresh.delay(appletRefreshTime*1000);
|
||||
}
|
||||
if ( scale == "auto" ) changeScale();
|
||||
if ( scale == 'auto' ) changeScale();
|
||||
if ( window.history.length == 1 ) {
|
||||
$j('#closeControl').html('');
|
||||
}
|
||||
|
|
|
@ -44,13 +44,13 @@ var showMode = "<?php echo ($showPtzControls && !empty($control))?"control":"eve
|
|||
var connKey = '<?php echo $connkey ?>';
|
||||
var maxDisplayEvents = <?php echo 2 * MAX_EVENTS ?>;
|
||||
|
||||
|
||||
var monitorId = <?php echo $monitor->Id() ?>;
|
||||
var monitorWidth = <?php echo $monitor->ViewWidth() ?>;
|
||||
var monitorHeight = <?php echo $monitor->ViewHeight() ?>;
|
||||
var monitorUrl = '<?php echo $monitor->UrlToIndex(); ?>';
|
||||
var monitorType = '<?php echo ( $monitor->Type() ) ?>';
|
||||
var monitorRefresh = '<?php echo ( $monitor->Refresh() ) ?>';
|
||||
var monitorUrl = '<?php echo $monitor->UrlToIndex() ?>';
|
||||
var monitorType = '<?php echo $monitor->Type() ?>';
|
||||
var monitorRefresh = '<?php echo $monitor->Refresh() ?>';
|
||||
var monitorStreamReplayBuffer = <?php echo $monitor->StreamReplayBuffer() ?>;
|
||||
|
||||
var scale = '<?php echo $scale ?>';
|
||||
|
||||
|
|
|
@ -123,7 +123,8 @@ $sourceTypes = array(
|
|||
'Libvlc' => translate('Libvlc'),
|
||||
'cURL' => 'cURL (HTTP(S) only)',
|
||||
'WebSite'=> 'Web Site',
|
||||
'NVSocket' => translate('NVSocket')
|
||||
'NVSocket' => translate('NVSocket'),
|
||||
'VNC' => translate('VNC'),
|
||||
);
|
||||
if ( !ZM_HAS_V4L )
|
||||
unset($sourceTypes['Local']);
|
||||
|
@ -367,8 +368,8 @@ $fastblendopts_alarm = array(
|
|||
);
|
||||
|
||||
$label_size = array(
|
||||
'Default' => 1,
|
||||
'Large' => 2
|
||||
1 => translate('Default'),
|
||||
2 => translate('Large'),
|
||||
);
|
||||
|
||||
$codecs = array(
|
||||
|
@ -639,7 +640,7 @@ switch ( $tab ) {
|
|||
</tr>
|
||||
<tr>
|
||||
<td><?php echo translate('Enabled') ?></td>
|
||||
<td><input type="checkbox" name="newMonitor[Enabled]" value="1"<?php if ( $monitor->Enabled() ) { ?> checked="checked"<?php } ?>/></td>
|
||||
<td><input type="checkbox" name="newMonitor[Enabled]" value="1"<?php echo $monitor->Enabled() ? ' checked="checked"' : '' ?>/></td>
|
||||
</tr>
|
||||
<?php
|
||||
if ( $monitor->Type() != 'WebSite' ) {
|
||||
|
@ -779,23 +780,45 @@ switch ( $tab ) {
|
|||
|
||||
} else if ( $monitor->Type() == 'NVSocket' ) {
|
||||
include('_monitor_source_nvsocket.php');
|
||||
} else if ( $monitor->Type() == 'VNC' ) {
|
||||
?>
|
||||
<tr>
|
||||
<td><?php echo translate('RemoteHostName') ?></td>
|
||||
<td><input type="text" name="newMonitor[Host]" value="<?php echo validHtmlStr($monitor->Host()) ?>"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><?php echo translate('RemoteHostPort') ?></td>
|
||||
<td><input type="number" name="newMonitor[Port]" value="<?php echo validHtmlStr($monitor->Port()) ?>" size="6"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><?php echo translate('Username') ?></td>
|
||||
<td><input type="text" name="newMonitor[User]" value="<?php echo validHtmlStr($monitor->User()) ?>"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><?php echo translate('Password') ?></td>
|
||||
<td><input type="text" name="newMonitor[Pass]" value="<?php echo validHtmlStr($monitor->Pass()) ?>"/></td>
|
||||
</tr>
|
||||
<?php
|
||||
} else if ( $monitor->Type() == 'Remote' ) {
|
||||
?>
|
||||
<tr><td><?php echo translate('RemoteProtocol') ?></td><td><?php echo htmlSelect( "newMonitor[Protocol]", $remoteProtocols, $monitor->Protocol(), "updateMethods( this );if(this.value=='rtsp'){\$('RTSPDescribe').setStyle('display','table-row');}else{\$('RTSPDescribe').hide();}" ); ?></td></tr>
|
||||
<?php
|
||||
?>
|
||||
<tr>
|
||||
<td><?php echo translate('RemoteMethod') ?></td>
|
||||
<td>
|
||||
<?php
|
||||
if ( !$monitor->Protocol() || $monitor->Protocol() == 'http' ) {
|
||||
?>
|
||||
<tr><td><?php echo translate('RemoteMethod') ?></td><td><?php echo htmlSelect( "newMonitor[Method]", $httpMethods, $monitor->Method() ); ?></td></tr>
|
||||
<?php
|
||||
echo htmlSelect('newMonitor[Method]', $httpMethods, $monitor->Method() );
|
||||
} else {
|
||||
?>
|
||||
<tr><td><?php echo translate('RemoteMethod') ?></td><td><?php echo htmlSelect( "newMonitor[Method]", $rtspMethods, $monitor->Method() ); ?></td></tr>
|
||||
<?php
|
||||
echo htmlSelect('newMonitor[Method]', $rtspMethods, $monitor->Method() );
|
||||
}
|
||||
?>
|
||||
<tr><td><?php echo translate('RemoteHostName') ?></td><td><input type="text" name="newMonitor[Host]" value="<?php echo validHtmlStr($monitor->Host()) ?>" size="36"/></td></tr>
|
||||
</td>
|
||||
</tr>
|
||||
<tr><td><?php echo translate('RemoteHostName') ?></td><td><input type="text" name="newMonitor[Host]" value="<?php echo validHtmlStr($monitor->Host()) ?>"/></td></tr>
|
||||
<tr><td><?php echo translate('RemoteHostPort') ?></td><td><input type="number" name="newMonitor[Port]" value="<?php echo validHtmlStr($monitor->Port()) ?>" size="6"/></td></tr>
|
||||
<tr><td><?php echo translate('RemoteHostPath') ?></td><td><input type="text" name="newMonitor[Path]" value="<?php echo validHtmlStr($monitor->Path()) ?>" size="36"/></td></tr>
|
||||
<tr><td><?php echo translate('RemoteHostPath') ?></td><td><input type="text" name="newMonitor[Path]" value="<?php echo validHtmlStr($monitor->Path()) ?>"/></td></tr>
|
||||
<?php
|
||||
} else if ( $monitor->Type() == 'File' ) {
|
||||
?>
|
||||
|
@ -803,23 +826,44 @@ include('_monitor_source_nvsocket.php');
|
|||
<?php
|
||||
} elseif ( $monitor->Type() == 'cURL' ) {
|
||||
?>
|
||||
<tr><td><?php echo 'URL' ?></td><td><input type="text" name="newMonitor[Path]" value="<?php echo validHtmlStr($monitor->Path()) ?>" size="36"/></td></tr>
|
||||
<tr><td><?php echo 'Username' ?></td><td><input type="text" name="newMonitor[User]" value="<?php echo validHtmlStr($monitor->User()) ?>" size="12"/></td></tr>
|
||||
<tr><td><?php echo 'Password' ?></td><td><input type="text" name="newMonitor[Pass]" value="<?php echo validHtmlStr($monitor->Pass()) ?>" size="12"/></td></tr>
|
||||
<tr><td><?php echo 'URL' ?></td><td><input type="text" name="newMonitor[Path]" value="<?php echo validHtmlStr($monitor->Path()) ?>"/></td></tr>
|
||||
<tr><td><?php echo 'Username' ?></td><td><input type="text" name="newMonitor[User]" value="<?php echo validHtmlStr($monitor->User()) ?>"/></td></tr>
|
||||
<tr><td><?php echo 'Password' ?></td><td><input type="text" name="newMonitor[Pass]" value="<?php echo validHtmlStr($monitor->Pass()) ?>"/></td></tr>
|
||||
<?php
|
||||
} elseif ( $monitor->Type() == 'WebSite' ) {
|
||||
?>
|
||||
<tr><td><?php echo translate('WebSiteUrl') ?></td><td><input type="text" name="newMonitor[Path]" value="<?php echo validHtmlStr($monitor->Path()) ?>" size="36"/></td></tr>
|
||||
<tr><td><?php echo translate('Width') ?> (<?php echo translate('Pixels') ?>)</td><td><input type="text" name="newMonitor[Width]" value="<?php echo validHtmlStr($monitor->Width()) ?>" size="4";"/></td></tr>
|
||||
<tr><td><?php echo translate('Height') ?> (<?php echo translate('Pixels') ?>)</td><td><input type="text" name="newMonitor[Height]" value="<?php echo validHtmlStr($monitor->Height()) ?>" size="4";"/></td></tr>
|
||||
<tr><td><?php echo 'Web Site Refresh (Optional)' ?></td><td><input type="number" name="newMonitor[Refresh]" value="<?php echo validHtmlStr($monitor->Refresh()); ?>"/></td></tr>
|
||||
<tr>
|
||||
<td><?php echo translate('WebSiteUrl') ?></td>
|
||||
<td><input type="text" name="newMonitor[Path]" value="<?php echo validHtmlStr($monitor->Path()) ?>"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><?php echo translate('Width') ?> (<?php echo translate('Pixels') ?>)</td>
|
||||
<td><input type="number" name="newMonitor[Width]" value="<?php echo validHtmlStr($monitor->Width()) ?>" size="4"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><?php echo translate('Height') ?> (<?php echo translate('Pixels') ?>)</td>
|
||||
<td><input type="number" name="newMonitor[Height]" value="<?php echo validHtmlStr($monitor->Height()) ?>" size="4"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><?php echo 'Web Site Refresh (Optional)' ?></td>
|
||||
<td><input type="number" name="newMonitor[Refresh]" value="<?php echo validHtmlStr($monitor->Refresh()) ?>"/></td>
|
||||
</tr>
|
||||
<?php
|
||||
} elseif ( $monitor->Type() == 'Ffmpeg' || $monitor->Type() == 'Libvlc' ) {
|
||||
} else if ( $monitor->Type() == 'Ffmpeg' || $monitor->Type() == 'Libvlc' ) {
|
||||
?>
|
||||
<tr class="SourcePath"><td><?php echo translate('SourcePath') ?></td><td><input type="text" name="newMonitor[Path]" value="<?php echo validHtmlStr($monitor->Path()) ?>" /></td></tr>
|
||||
<tr><td><?php echo translate('RemoteMethod') ?> (<?php echo makePopupLink('?view=optionhelp&option=OPTIONS_RTSPTrans', 'zmOptionHelp', 'optionhelp', '?' ) ?>)</td><td><?php echo htmlSelect( "newMonitor[Method]", $rtspFFMpegMethods, $monitor->Method() ); ?></td></tr>
|
||||
<tr class="SourcePath">
|
||||
<td><?php echo translate('SourcePath') ?></td>
|
||||
<td><input type="text" name="newMonitor[Path]" value="<?php echo validHtmlStr($monitor->Path()) ?>" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><?php
|
||||
echo translate('RemoteMethod');
|
||||
echo makePopupLink('?view=optionhelp&option=OPTIONS_RTSPTrans', 'zmOptionHelp', 'optionhelp', '?' );
|
||||
?>)</td>
|
||||
<td><?php echo htmlSelect('newMonitor[Method]', $rtspFFMpegMethods, $monitor->Method()) ?></td>
|
||||
</tr>
|
||||
<tr class="SourceOptions">
|
||||
<td><?php echo translate('Options') ?> (<?php echo makePopupLink( '?view=optionhelp&option=OPTIONS_'.strtoupper($monitor->Type()), 'zmOptionHelp', 'optionhelp', '?' ) ?>)</td>
|
||||
<td><?php echo translate('Options') ?> (<?php echo makePopupLink('?view=optionhelp&option=OPTIONS_'.strtoupper($monitor->Type()), 'zmOptionHelp', 'optionhelp', '?' ) ?>)</td>
|
||||
<td><input type="text" name="newMonitor[Options]" value="<?php echo validHtmlStr($monitor->Options()) ?>"/></td>
|
||||
</tr>
|
||||
<?php
|
||||
|
@ -840,10 +884,12 @@ include('_monitor_source_nvsocket.php');
|
|||
</tr>
|
||||
<?php
|
||||
}
|
||||
if ( $monitor->Type() != 'NVSocket' && $monitor->Type() != 'WebSite' ) {
|
||||
if ( $monitor->Type() != 'NVSocket' && $monitor->Type() != 'WebSite' ) {
|
||||
?>
|
||||
<tr><td><?php echo translate('TargetColorspace') ?></td><td><?php echo htmlSelect('newMonitor[Colours]', $Colours, $monitor->Colours() ); ?>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td><?php echo translate('TargetColorspace') ?></td>
|
||||
<td><?php echo htmlSelect('newMonitor[Colours]', $Colours, $monitor->Colours()) ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><?php echo translate('CaptureResolution') ?> (<?php echo translate('Pixels') ?>)</td>
|
||||
<td>
|
||||
|
@ -884,23 +930,30 @@ if ( $monitor->Type() != 'NVSocket' && $monitor->Type() != 'WebSite' ) {
|
|||
<td><?php echo htmlselect('newMonitor[Orientation]', $orientations, $monitor->Orientation());?></td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
if ( $monitor->Type() == 'Local' ) {
|
||||
}
|
||||
if ( $monitor->Type() == 'Local' ) {
|
||||
?>
|
||||
<tr><td><?php echo translate('Deinterlacing') ?></td><td><select name="newMonitor[Deinterlacing]"><?php foreach ( $deinterlaceopts_v4l2 as $name => $value ) { ?><option value="<?php echo validHtmlStr($value); ?>"<?php if ( $value == $monitor->Deinterlacing()) { ?> selected="selected"<?php } ?>><?php echo validHtmlStr($name); ?></option><?php } ?></select></td></tr>
|
||||
<?php
|
||||
<tr>
|
||||
<td><?php echo translate('Deinterlacing') ?></td>
|
||||
<td><?php echo htmlselect('newMonitor[Deinterlacing]', $deinterlaceopts_v4l2, $monitor->Deinterlacing())?></td>
|
||||
</tr>
|
||||
<?php
|
||||
} else if ( $monitor->Type() != 'WebSite' ) {
|
||||
?>
|
||||
<tr><td><?php echo translate('Deinterlacing') ?></td><td><select name="newMonitor[Deinterlacing]"><?php foreach ( $deinterlaceopts as $name => $value ) { ?><option value="<?php echo validHtmlStr($value); ?>"<?php if ( $value == $monitor->Deinterlacing()) { ?> selected="selected"<?php } ?>><?php echo validHtmlStr($name); ?></option><?php } ?></select></td></tr>
|
||||
<tr>
|
||||
<td><?php echo translate('Deinterlacing') ?></td>
|
||||
<td><?php echo htmlselect('newMonitor[Deinterlacing]', $deinterlaceopts, $monitor->Deinterlacing())?></td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<?php
|
||||
if ( $monitor->Type() == 'Remote' ) {
|
||||
?>
|
||||
<tr id="RTSPDescribe"<?php if ( $monitor->Protocol()!= 'rtsp' ) { echo ' style="display:none;"'; } ?>><td><?php echo translate('RTSPDescribe') ?> (<?php echo makePopupLink( '?view=optionhelp&option=OPTIONS_RTSPDESCRIBE', 'zmOptionHelp', 'optionhelp', '?' ) ?>) </td><td><input type="checkbox" name="newMonitor[RTSPDescribe]" value="1"<?php if ( $monitor->RTSPDescribe() ) { ?> checked="checked"<?php } ?>/></td></tr>
|
||||
<tr id="RTSPDescribe"<?php if ( $monitor->Protocol()!= 'rtsp' ) { echo ' style="display:none;"'; } ?>>
|
||||
<td><?php echo translate('RTSPDescribe') ?> (<?php echo makePopupLink( '?view=optionhelp&option=OPTIONS_RTSPDESCRIBE', 'zmOptionHelp', 'optionhelp', '?' ) ?>)</td>
|
||||
<td><input type="checkbox" name="newMonitor[RTSPDescribe]" value="1"<?php if ( $monitor->RTSPDescribe() ) { ?> checked="checked"<?php } ?>/></td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
} # end if monitor->Type() == 'Remote'
|
||||
break;
|
||||
}
|
||||
case 'storage' :
|
||||
|
@ -910,7 +963,7 @@ if ( $monitor->Type() == 'Local' ) {
|
|||
<td>
|
||||
<?php
|
||||
$storage_areas = array(0=>'Default');
|
||||
foreach ( ZM\Storage::find(NULL, array('order'=>'lower(Name)')) as $Storage ) {
|
||||
foreach ( ZM\Storage::find(array('Enabled'=>true), array('order'=>'lower(Name)')) as $Storage ) {
|
||||
$storage_areas[$Storage->Id()] = $Storage->Name();
|
||||
}
|
||||
echo htmlSelect('newMonitor[StorageId]', $storage_areas, $monitor->StorageId());
|
||||
|
@ -939,15 +992,17 @@ if ( $monitor->Type() == 'Local' ) {
|
|||
|
||||
$videowriteropts[1] = 'X264 Encode';
|
||||
|
||||
if ($monitor->Type() == 'Ffmpeg' )
|
||||
if ( $monitor->Type() == 'Ffmpeg' )
|
||||
$videowriteropts[2] = 'H264 Camera Passthrough';
|
||||
else
|
||||
$videowriteropts[2] = array('text'=>'H264 Camera Passthrough - only for FFMPEG','disabled'=>1);
|
||||
|
||||
echo htmlselect( 'newMonitor[VideoWriter]', $videowriteropts, $monitor->VideoWriter() );
|
||||
echo htmlselect('newMonitor[VideoWriter]', $videowriteropts, $monitor->VideoWriter());
|
||||
?>
|
||||
</td></tr>
|
||||
<tr><td><?php echo translate('OptionalEncoderParam') ?></td><td><textarea name="newMonitor[EncoderParameters]" rows="4" cols="36"><?php echo validHtmlStr($monitor->EncoderParameters()) ?></textarea></td></tr>
|
||||
<tr>
|
||||
<td><?php echo translate('OptionalEncoderParam') ?></td>
|
||||
<td><textarea name="newMonitor[EncoderParameters]" rows="4" cols="36"><?php echo validHtmlStr($monitor->EncoderParameters()) ?></textarea></td></tr>
|
||||
<tr><td><?php echo translate('RecordAudio') ?></td><td>
|
||||
<?php if ( $monitor->Type() == 'Ffmpeg' ) { ?>
|
||||
<input type="checkbox" name="newMonitor[RecordAudio]" value="1"<?php if ( $monitor->RecordAudio() ) { ?> checked="checked"<?php } ?>/>
|
||||
|
@ -962,22 +1017,52 @@ if ( $monitor->Type() == 'Local' ) {
|
|||
case 'timestamp' :
|
||||
{
|
||||
?>
|
||||
<tr><td><?php echo translate('TimestampLabelFormat') ?></td><td><input type="text" name="newMonitor[LabelFormat]" value="<?php echo validHtmlStr($monitor->LabelFormat()) ?>" size="32"/></td></tr>
|
||||
<tr><td><?php echo translate('TimestampLabelX') ?></td><td><input type="text" name="newMonitor[LabelX]" value="<?php echo validHtmlStr($monitor->LabelX()) ?>" size="4"/></td></tr>
|
||||
<tr><td><?php echo translate('TimestampLabelY') ?></td><td><input type="text" name="newMonitor[LabelY]" value="<?php echo validHtmlStr($monitor->LabelY()) ?>" size="4"/></td></tr>
|
||||
<tr><td><?php echo translate('TimestampLabelSize') ?></td><td><select name="newMonitor[LabelSize]"><?php foreach ( $label_size as $name => $value ) { ?><option value="<?php echo validHtmlStr($value); ?>"<?php if ( $value == $monitor->LabelSize() ) { ?> selected="selected"<?php } ?>><?php echo validHtmlStr($name); ?></option><?php } ?></select></td></tr>
|
||||
<tr>
|
||||
<td><?php echo translate('TimestampLabelFormat') ?></td>
|
||||
<td><input type="text" name="newMonitor[LabelFormat]" value="<?php echo validHtmlStr($monitor->LabelFormat()) ?>"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><?php echo translate('TimestampLabelX') ?></td>
|
||||
<td><input type="number" name="newMonitor[LabelX]" value="<?php echo validHtmlStr($monitor->LabelX()) ?>" size="4"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><?php echo translate('TimestampLabelY') ?></td>
|
||||
<td><input type="number" name="newMonitor[LabelY]" value="<?php echo validHtmlStr($monitor->LabelY()) ?>" size="4"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><?php echo translate('TimestampLabelSize') ?></td>
|
||||
<td><?php echo htmlselect('newMonitor[LabelSize]', $label_size, $monitor->LabelSize()) ?></td>
|
||||
</tr>
|
||||
<?php
|
||||
break;
|
||||
}
|
||||
case 'buffers' :
|
||||
{
|
||||
?>
|
||||
<tr><td><?php echo translate('ImageBufferSize') ?></td><td><input type="text" name="newMonitor[ImageBufferCount]" value="<?php echo validHtmlStr($monitor->ImageBufferCount()) ?>" size="6"/></td></tr>
|
||||
<tr><td><?php echo translate('WarmupFrames') ?></td><td><input type="text" name="newMonitor[WarmupCount]" value="<?php echo validHtmlStr($monitor->WarmupCount()) ?>" size="4"/></td></tr>
|
||||
<tr><td><?php echo translate('PreEventImageBuffer') ?></td><td><input type="text" name="newMonitor[PreEventCount]" value="<?php echo validHtmlStr($monitor->PreEventCount()) ?>" size="4"/></td></tr>
|
||||
<tr><td><?php echo translate('PostEventImageBuffer') ?></td><td><input type="text" name="newMonitor[PostEventCount]" value="<?php echo validHtmlStr($monitor->PostEventCount()) ?>" size="4"/></td></tr>
|
||||
<tr><td><?php echo translate('StreamReplayBuffer') ?></td><td><input type="text" name="newMonitor[StreamReplayBuffer]" value="<?php echo validHtmlStr($monitor->StreamReplayBuffer()) ?>" size="6"/></td></tr>
|
||||
<tr><td><?php echo translate('AlarmFrameCount') ?></td><td><input type="text" name="newMonitor[AlarmFrameCount]" value="<?php echo validHtmlStr($monitor->AlarmFrameCount()) ?>" size="4"/></td></tr>
|
||||
<tr>
|
||||
<td><?php echo translate('ImageBufferSize') ?></td>
|
||||
<td><input type="number" name="newMonitor[ImageBufferCount]" value="<?php echo validHtmlStr($monitor->ImageBufferCount()) ?>" size="6"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><?php echo translate('WarmupFrames') ?></td>
|
||||
<td><input type="number" name="newMonitor[WarmupCount]" value="<?php echo validHtmlStr($monitor->WarmupCount()) ?>" size="4"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><?php echo translate('PreEventImageBuffer') ?></td>
|
||||
<td><input type="number" name="newMonitor[PreEventCount]" value="<?php echo validHtmlStr($monitor->PreEventCount()) ?>" size="4"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><?php echo translate('PostEventImageBuffer') ?></td>
|
||||
<td><input type="number" name="newMonitor[PostEventCount]" value="<?php echo validHtmlStr($monitor->PostEventCount()) ?>" size="4"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><?php echo translate('StreamReplayBuffer') ?></td>
|
||||
<td><input type="number" name="newMonitor[StreamReplayBuffer]" value="<?php echo validHtmlStr($monitor->StreamReplayBuffer()) ?>" size="6"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><?php echo translate('AlarmFrameCount') ?></td>
|
||||
<td><input type="number" name="newMonitor[AlarmFrameCount]" value="<?php echo validHtmlStr($monitor->AlarmFrameCount()) ?>" size="4"/></td>
|
||||
</tr>
|
||||
<?php
|
||||
break;
|
||||
}
|
||||
|
@ -986,7 +1071,8 @@ if ( $monitor->Type() == 'Local' ) {
|
|||
?>
|
||||
<tr>
|
||||
<td><?php echo translate('Controllable') ?></td>
|
||||
<td><input type="checkbox" name="newMonitor[Controllable]" value="1"<?php if ( $monitor->Controllable() ) { ?> checked="checked"<?php } ?>/></td></tr>
|
||||
<td><input type="checkbox" name="newMonitor[Controllable]" value="1"<?php if ( $monitor->Controllable() ) { ?> checked="checked"<?php } ?>/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><?php echo translate('ControlType') ?></td>
|
||||
<td><?php echo htmlSelect('newMonitor[ControlId]', $controlTypes, $monitor->ControlId());
|
||||
|
@ -1011,20 +1097,19 @@ if ( canEdit('Control') ) {
|
|||
<td><?php echo translate('TrackMotion') ?></td>
|
||||
<td><input type="checkbox" name="newMonitor[TrackMotion]" value="1"<?php if ( $monitor->TrackMotion() ) { ?> checked="checked"<?php } ?>/></td>
|
||||
</tr>
|
||||
<?php
|
||||
$return_options = array(
|
||||
'-1' => translate('None'),
|
||||
'0' => translate('Home'),
|
||||
'1' => translate('Preset').' 1',
|
||||
);
|
||||
?>
|
||||
<tr>
|
||||
<td><?php echo translate('TrackDelay') ?></td>
|
||||
<td><input type="number" name="newMonitor[TrackDelay]" value="<?php echo validHtmlStr($monitor->TrackDelay()) ?>"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><?php echo translate('ReturnLocation') ?></td>
|
||||
<td><?php echo htmlSelect('newMonitor[ReturnLocation]', $return_options, $monitor->ReturnLocation()); ?></td>
|
||||
<td><?php
|
||||
$return_options = array(
|
||||
'-1' => translate('None'),
|
||||
'0' => translate('Home'),
|
||||
'1' => translate('Preset').' 1',
|
||||
);
|
||||
echo htmlSelect('newMonitor[ReturnLocation]', $return_options, $monitor->ReturnLocation()); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><?php echo translate('ReturnDelay') ?></td>
|
||||
|
|
|
@ -57,9 +57,6 @@ if ( isset($_REQUEST['scale']) ) {
|
|||
$scale = $_COOKIE['zmMontageScale'];
|
||||
}
|
||||
|
||||
if ( ! $scale )
|
||||
$scale = 100;
|
||||
|
||||
$layouts = ZM\MontageLayout::find(NULL, array('order'=>"lower('Name')"));
|
||||
$layoutsById = array();
|
||||
foreach ( $layouts as $l ) {
|
||||
|
@ -111,7 +108,7 @@ if ( isset($_COOKIE['zmMontageHeight']) and $_COOKIE['zmMontageHeight'] )
|
|||
else
|
||||
$options['height'] = '';
|
||||
|
||||
if ( $scale )
|
||||
#if ( $scale )
|
||||
$options['scale'] = $scale;
|
||||
|
||||
session_write_close();
|
||||
|
@ -127,7 +124,7 @@ foreach( $displayMonitors as &$row ) {
|
|||
continue;
|
||||
|
||||
$row['Scale'] = $scale;
|
||||
$row['PopupScale'] = reScale( SCALE_BASE, $row['DefaultScale'], ZM_WEB_DEFAULT_SCALE );
|
||||
$row['PopupScale'] = reScale(SCALE_BASE, $row['DefaultScale'], ZM_WEB_DEFAULT_SCALE);
|
||||
|
||||
if ( ZM_OPT_CONTROL && $row['ControlId'] && $row['Controllable'] )
|
||||
$showControl = true;
|
||||
|
@ -207,7 +204,12 @@ if ( $showZones ) {
|
|||
foreach ( $monitors as $monitor ) {
|
||||
$connkey = $monitor->connKey(); // Minor hack
|
||||
?>
|
||||
<div id="monitorFrame<?php echo $monitor->Id() ?>" class="monitorFrame" title="<?php echo $monitor->Id() . ' ' .$monitor->Name() ?>" style="<?php echo $options['width'] ? 'width:'.$options['width'].';':''?>">
|
||||
<div
|
||||
id="monitorFrame<?php echo $monitor->Id() ?>"
|
||||
class="monitorFrame"
|
||||
title="<?php echo $monitor->Id() . ' ' .$monitor->Name() ?>"
|
||||
style="<?php echo $options['width'] ? 'width:'.$options['width'].';':''?>"
|
||||
>
|
||||
<div id="monitor<?php echo $monitor->Id() ?>" class="monitor idle">
|
||||
<div
|
||||
id="imageFeed<?php echo $monitor->Id() ?>"
|
||||
|
|
|
@ -62,6 +62,17 @@ ob_end_clean();
|
|||
$filter = array();
|
||||
if ( isset($_REQUEST['filter']) ) {
|
||||
$filter = $_REQUEST['filter'];
|
||||
|
||||
# Try to guess min/max time from filter
|
||||
foreach ( $filter['Query'] as $term ) {
|
||||
if ( $term['attr'] == 'StartDateTime' ) {
|
||||
if ( $term['op'] == '<=' or $term['op'] == '<' ) {
|
||||
$maxTime = $term['val'];
|
||||
} else if ( $term['op'] == '>=' or $term['op'] == '>' ) {
|
||||
$minTime = $term['val'];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
if ( isset($_REQUEST['minTime']) && isset($_REQUEST['maxTime']) && (count($displayMonitors) != 0) ) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
//
|
||||
// ZoneMinder web user view file, $Date$, $Revision$
|
||||
// Copyright (C) 2001-2008 Philip Coombes
|
||||
// ZoneMinder web user view file
|
||||
// Copyright (C) 2020 ZoneMinder LLC
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
|
@ -23,22 +23,17 @@ if ( !canEdit('System') ) {
|
|||
return;
|
||||
}
|
||||
|
||||
require_once('includes/Server.php');
|
||||
require_once('includes/Storage.php');
|
||||
|
||||
if ( $_REQUEST['id'] ) {
|
||||
if ( !($newStorage = dbFetchOne('SELECT * FROM Storage WHERE Id=?', NULL, ARRAY($_REQUEST['id'])) ) ) {
|
||||
if ( !($newStorage = ZM\Storage::find_one(array('Id'=>$_REQUEST['id'])) ) ) {
|
||||
$view = 'error';
|
||||
return;
|
||||
$newStorage['ServerId'] = '';
|
||||
}
|
||||
} else {
|
||||
$newStorage = array();
|
||||
$newStorage['Name'] = translate('NewStorage');
|
||||
$newStorage['Path'] = '';
|
||||
$newStorage['Type'] = 'local';
|
||||
$newStorage['Url'] = '';
|
||||
$newStorage['Scheme'] = 'Medium';
|
||||
$newStorage['StorageId'] = '';
|
||||
$newStorage['ServerId'] = '';
|
||||
$newStorage['DoDelete'] = 1;
|
||||
$newStorage = new ZM\Storage();
|
||||
$newStorage->Name(translate('NewStorage'));
|
||||
}
|
||||
|
||||
$type_options = array( 'local' => translate('Local'), 's3fs' => translate('s3fs') );
|
||||
|
@ -55,12 +50,12 @@ foreach ( $servers as $S ) {
|
|||
}
|
||||
$focusWindow = true;
|
||||
|
||||
xhtmlHeaders(__FILE__, translate('Storage').' - '.$newStorage['Name']);
|
||||
xhtmlHeaders(__FILE__, translate('Storage').' - '.$newStorage->Name());
|
||||
?>
|
||||
<body>
|
||||
<div id="page">
|
||||
<div id="header">
|
||||
<h2><?php echo translate('Storage').' - '.$newStorage['Name'] ?></h2>
|
||||
<h2><?php echo translate('Storage').' - '.$newStorage->Name() ?></h2>
|
||||
</div>
|
||||
<div id="content">
|
||||
<form name="contentForm" method="post" action="?" class="validateFormOnSubmit">
|
||||
|
@ -71,33 +66,40 @@ xhtmlHeaders(__FILE__, translate('Storage').' - '.$newStorage['Name']);
|
|||
<tbody>
|
||||
<tr>
|
||||
<th scope="row"><?php echo translate('Name') ?></th>
|
||||
<td><input type="text" name="newStorage[Name]" value="<?php echo $newStorage['Name'] ?>"/></td>
|
||||
<td><input type="text" name="newStorage[Name]" value="<?php echo $newStorage->Name() ?>"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><?php echo translate('Path') ?></th>
|
||||
<td><input type="text" name="newStorage[Path]" value="<?php echo $newStorage['Path'] ?>"/></td>
|
||||
<td><input type="text" name="newStorage[Path]" value="<?php echo $newStorage->Path() ?>"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><?php echo translate('Url') ?></th>
|
||||
<td><input type="text" name="newStorage[Url]" value="<?php echo $newStorage['Url'] ?>"/></td>
|
||||
<td><input type="text" name="newStorage[Url]" value="<?php echo $newStorage->Url() ?>"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><?php echo translate('Server') ?></th>
|
||||
<td><?php echo htmlSelect('newStorage[ServerId]', array(''=>'Remote / No Specific Server') + $ServersById, $newStorage['ServerId']); ?></td>
|
||||
<td><?php echo htmlSelect('newStorage[ServerId]', array(''=>'Remote / No Specific Server') + $ServersById, $newStorage->ServerId()); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><?php echo translate('Type') ?></th>
|
||||
<td><?php echo htmlSelect('newStorage[Type]', $type_options, $newStorage['Type']); ?></td>
|
||||
<td><?php echo htmlSelect('newStorage[Type]', $type_options, $newStorage->Type()); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><?php echo translate('StorageScheme') ?></th>
|
||||
<td><?php echo htmlSelect('newStorage[Scheme]', $scheme_options, $newStorage['Scheme']); ?></td>
|
||||
<td><?php echo htmlSelect('newStorage[Scheme]', $scheme_options, $newStorage->Scheme()); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><?php echo translate('StorageDoDelete') ?></th>
|
||||
<td>
|
||||
<input type="radio" name="newStorage[DoDelete]" value="1"<?php echo $newStorage['DoDelete'] ? 'checked="checked"' : '' ?>/>Yes
|
||||
<input type="radio" name="newStorage[DoDelete]" value="0"<?php echo $newStorage['DoDelete'] ? '' : 'checked="checked"' ?>/>No
|
||||
<input type="radio" name="newStorage[DoDelete]" value="1"<?php echo $newStorage->DoDelete() ? 'checked="checked"' : '' ?>/>Yes
|
||||
<input type="radio" name="newStorage[DoDelete]" value="0"<?php echo $newStorage->DoDelete() ? '' : 'checked="checked"' ?>/>No
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><?php echo translate('Enabled') ?></th>
|
||||
<td>
|
||||
<input type="radio" name="newStorage[Enabled]" value="1"<?php echo $newStorage->Enabled() ? 'checked="checked"' : '' ?>/>Yes
|
||||
<input type="radio" name="newStorage[Enabled]" value="0"<?php echo $newStorage->Enabled() ? '' : 'checked="checked"' ?>/>No
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
|
|
@ -57,6 +57,7 @@ $filename = '';
|
|||
$Frame = null;
|
||||
$Event = null;
|
||||
$path = null;
|
||||
$media_type='image/jpeg';
|
||||
|
||||
if ( empty($_REQUEST['path']) ) {
|
||||
|
||||
|
@ -77,6 +78,47 @@ if ( empty($_REQUEST['path']) ) {
|
|||
}
|
||||
|
||||
if ( $_REQUEST['fid'] == 'objdetect' ) {
|
||||
// if animation file is found, return that, else return image
|
||||
// we are only looking for GIF or jpg here, not mp4
|
||||
// as most often, browsers asking for this link will be expecting
|
||||
// media types that can be rendered as <img src=>
|
||||
$path_anim_gif = $Event->Path().'/objdetect.gif';
|
||||
$path_image = $Event->Path().'/objdetect.jpg';
|
||||
if (file_exists($path_anim_gif)) {
|
||||
// we found the animation gif file
|
||||
$media_type = 'image/gif';
|
||||
ZM\Logger::Debug("Animation file found at $path");
|
||||
$path = $path_anim_gif;
|
||||
} else if (file_exists($path_image)) {
|
||||
// animation not found, but image found
|
||||
ZM\Logger::Debug("Image file found at $path");
|
||||
$path = $path_image;
|
||||
} else {
|
||||
// neither animation nor image found
|
||||
header('HTTP/1.0 404 Not Found');
|
||||
ZM\Fatal("Object detection animation and image not found for this event");
|
||||
}
|
||||
$Frame = new ZM\Frame();
|
||||
$Frame->Id('objdetect');
|
||||
} else if ( $_REQUEST['fid'] == 'objdetect_mp4' ) {
|
||||
$path = $Event->Path().'/objdetect.mp4';
|
||||
if ( !file_exists($path) ) {
|
||||
header('HTTP/1.0 404 Not Found');
|
||||
ZM\Fatal("File $path does not exist. You might not have enabled create_animation in objectconfig.ini. If you have, inspect debug logs for errors during creation");
|
||||
}
|
||||
$Frame = new ZM\Frame();
|
||||
$Frame->Id('objdetect');
|
||||
$media_type = 'video/mp4';
|
||||
} else if ( $_REQUEST['fid'] == 'objdetect_gif' ) {
|
||||
$path = $Event->Path().'/objdetect.gif';
|
||||
if ( !file_exists($path) ) {
|
||||
header('HTTP/1.0 404 Not Found');
|
||||
ZM\Fatal("File $path does not exist. You might not have enabled create_animation in objectconfig.ini. If you have, inspect debug logs for errors during creation");
|
||||
}
|
||||
$Frame = new ZM\Frame();
|
||||
$Frame->Id('objdetect');
|
||||
$media_type = 'image/gif';
|
||||
} else if ( $_REQUEST['fid'] == 'objdetect_jpg' ) {
|
||||
$path = $Event->Path().'/objdetect.jpg';
|
||||
if ( !file_exists($path) ) {
|
||||
header('HTTP/1.0 404 Not Found');
|
||||
|
@ -281,7 +323,7 @@ if ( !empty($_REQUEST['height']) ) {
|
|||
if ( $errorText ) {
|
||||
ZM\Error($errorText);
|
||||
} else {
|
||||
header('Content-type: image/jpeg');
|
||||
header("Content-type: $media_type");
|
||||
if ( ( $scale==0 || $scale==100 ) && ($width==0) && ($height==0) ) {
|
||||
# This is so that Save Image As give a useful filename
|
||||
if ( $Event ) {
|
||||
|
|
|
@ -25,13 +25,13 @@
|
|||
#
|
||||
|
||||
use strict;
|
||||
use lib './scripts/ZoneMinder/lib';
|
||||
use lib '@CMAKE_CURRENT_BINARY_DIR@/scripts/ZoneMinder/lib';
|
||||
use ZoneMinder::ConfigData qw/:data/;
|
||||
|
||||
$| = 1;
|
||||
|
||||
my $config_header = "src/zm_config_defines.h";
|
||||
my $config_sql = "db/zm_create.sql";
|
||||
my $config_header = '@CMAKE_CURRENT_BINARY_DIR@/src/zm_config_defines.h';
|
||||
my $config_sql = '@CMAKE_CURRENT_BINARY_DIR@/db/zm_create.sql';
|
||||
|
||||
generateConfigFiles();
|
||||
|
||||
|
|
|
@ -59,6 +59,8 @@
|
|||
#cmakedefine HAVE_LIBAVRESAMPLE_AVRESAMPLE_H 1
|
||||
#cmakedefine HAVE_LIBVLC 1
|
||||
#cmakedefine HAVE_VLC_VLC_H 1
|
||||
#cmakedefine HAVE_LIBVNC 1
|
||||
#cmakedefine HAVE_RFB_RFB_H 1
|
||||
#cmakedefine HAVE_LIBX264 1
|
||||
#cmakedefine HAVE_X264_H 1
|
||||
#cmakedefine HAVE_LIBMP4V2 1
|
||||
|
|
Loading…
Reference in New Issue