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")
|
experience problems with the shared memory. default: OFF")
|
||||||
set(ZM_NO_LIBVLC "OFF" CACHE BOOL
|
set(ZM_NO_LIBVLC "OFF" CACHE BOOL
|
||||||
"Set to ON to skip libvlc checks and force building ZM without libvlc. default: OFF")
|
"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(ZM_NO_CURL "OFF" CACHE BOOL
|
||||||
"Set to ON to skip cURL checks and force building ZM without cURL. default: OFF")
|
"Set to ON to skip cURL checks and force building ZM without cURL. default: OFF")
|
||||||
set(ZM_NO_X10 "OFF" CACHE BOOL
|
set(ZM_NO_X10 "OFF" CACHE BOOL
|
||||||
|
@ -553,6 +555,7 @@ if(AVCODEC_LIBRARIES)
|
||||||
check_include_file("libavcodec/avcodec.h" HAVE_LIBAVCODEC_AVCODEC_H)
|
check_include_file("libavcodec/avcodec.h" HAVE_LIBAVCODEC_AVCODEC_H)
|
||||||
set(optlibsfound "${optlibsfound} AVCodec")
|
set(optlibsfound "${optlibsfound} AVCodec")
|
||||||
else(AVCODEC_LIBRARIES)
|
else(AVCODEC_LIBRARIES)
|
||||||
|
message(WARNING "\nWhile it should be possible to build ZM without AVCODEC the result will pretty useless.")
|
||||||
set(optlibsnotfound "${optlibsnotfound} AVCodec")
|
set(optlibsnotfound "${optlibsnotfound} AVCodec")
|
||||||
endif(AVCODEC_LIBRARIES)
|
endif(AVCODEC_LIBRARIES)
|
||||||
|
|
||||||
|
@ -674,6 +677,25 @@ if(NOT ZM_NO_LIBVLC)
|
||||||
endif(LIBVLC_LIBRARIES)
|
endif(LIBVLC_LIBRARIES)
|
||||||
endif(NOT ZM_NO_LIBVLC)
|
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)
|
#find_package(Boost 1.36.0)
|
||||||
#if(Boost_FOUND)
|
#if(Boost_FOUND)
|
||||||
#include_directories(${Boost_INCLUDE_DIRS})
|
#include_directories(${Boost_INCLUDE_DIRS})
|
||||||
|
@ -908,7 +930,7 @@ message(STATUS "Optional libraries not found:${optlibsnotfound}")
|
||||||
|
|
||||||
# Run ZM configuration generator
|
# Run ZM configuration generator
|
||||||
message(STATUS "Running ZoneMinder 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)
|
if(zmconfgen_result EQUAL 0)
|
||||||
message(STATUS
|
message(STATUS
|
||||||
"ZoneMinder configuration generator completed successfully")
|
"ZoneMinder configuration generator completed successfully")
|
||||||
|
|
|
@ -63,7 +63,7 @@ DROP TABLE IF EXISTS `Controls`;
|
||||||
CREATE TABLE `Controls` (
|
CREATE TABLE `Controls` (
|
||||||
`Id` int(10) unsigned NOT NULL auto_increment,
|
`Id` int(10) unsigned NOT NULL auto_increment,
|
||||||
`Name` varchar(64) NOT NULL default '',
|
`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,
|
`Protocol` varchar(64) default NULL,
|
||||||
`CanWake` tinyint(3) unsigned NOT NULL default '0',
|
`CanWake` tinyint(3) unsigned NOT NULL default '0',
|
||||||
`CanSleep` 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',
|
`AutoVideo` tinyint(3) unsigned NOT NULL default '0',
|
||||||
`AutoUpload` tinyint(3) unsigned NOT NULL default '0',
|
`AutoUpload` tinyint(3) unsigned NOT NULL default '0',
|
||||||
`AutoEmail` 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',
|
`AutoMessage` tinyint(3) unsigned NOT NULL default '0',
|
||||||
`AutoExecute` tinyint(3) unsigned NOT NULL default '0',
|
`AutoExecute` tinyint(3) unsigned NOT NULL default '0',
|
||||||
`AutoExecuteCmd` tinytext,
|
`AutoExecuteCmd` tinytext,
|
||||||
|
@ -403,7 +406,7 @@ DROP TABLE IF EXISTS `MonitorPresets`;
|
||||||
CREATE TABLE `MonitorPresets` (
|
CREATE TABLE `MonitorPresets` (
|
||||||
`Id` int(10) unsigned NOT NULL auto_increment,
|
`Id` int(10) unsigned NOT NULL auto_increment,
|
||||||
`Name` varchar(64) NOT NULL default '',
|
`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,
|
`Device` tinytext,
|
||||||
`Channel` tinyint(3) unsigned default NULL,
|
`Channel` tinyint(3) unsigned default NULL,
|
||||||
`Format` int(10) unsigned default NULL,
|
`Format` int(10) unsigned default NULL,
|
||||||
|
@ -437,7 +440,7 @@ CREATE TABLE `Monitors` (
|
||||||
`Notes` TEXT,
|
`Notes` TEXT,
|
||||||
`ServerId` int(10) unsigned,
|
`ServerId` int(10) unsigned,
|
||||||
`StorageId` smallint(5) unsigned default 0,
|
`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',
|
`Function` enum('None','Monitor','Modect','Record','Mocord','Nodect') NOT NULL default 'Monitor',
|
||||||
`Enabled` tinyint(3) unsigned NOT NULL default '1',
|
`Enabled` tinyint(3) unsigned NOT NULL default '1',
|
||||||
`LinkedMonitors` varchar(255),
|
`LinkedMonitors` varchar(255),
|
||||||
|
@ -730,13 +733,14 @@ CREATE TABLE `Storage` (
|
||||||
`Scheme` enum('Deep','Medium','Shallow') NOT NULL default 'Medium',
|
`Scheme` enum('Deep','Medium','Shallow') NOT NULL default 'Medium',
|
||||||
`ServerId` int(10) unsigned,
|
`ServerId` int(10) unsigned,
|
||||||
`DoDelete` BOOLEAN NOT NULL DEFAULT true,
|
`DoDelete` BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
`Enabled` BOOLEAN NOT NULL DEFAULT true,
|
||||||
PRIMARY KEY (`Id`)
|
PRIMARY KEY (`Id`)
|
||||||
) ENGINE=@ZM_MYSQL_ENGINE@;
|
) ENGINE=@ZM_MYSQL_ENGINE@;
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Create a default storage location
|
-- Create a default storage location
|
||||||
--
|
--
|
||||||
insert into Storage VALUES (NULL, '@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 */;
|
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
|
||||||
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
||||||
|
@ -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
|
-- 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/*AutoArchive*/,
|
||||||
0/*AutoVideo*/,
|
0/*AutoVideo*/,
|
||||||
0/*AutoUpload*/,
|
0/*AutoUpload*/,
|
||||||
0/*AutoEmail*/,
|
0/*AutoEmail*/,
|
||||||
|
''/*EmailTo*/,
|
||||||
|
''/*EmailSubject*/,
|
||||||
|
''/*EmailBody*/,
|
||||||
0/*AutoMessage*/,
|
0/*AutoMessage*/,
|
||||||
0/*AutoExecute*/,'',
|
0/*AutoExecute*/,'',
|
||||||
1/*AutoDelete*/,
|
1/*AutoDelete*/,
|
||||||
0/*AutoMove*/,0/*MoveTo*/,
|
0/*AutoMove*/,0/*MoveTo*/,
|
||||||
0/*AutoCopy*/,0/*CopyTo*/,
|
0/*AutoCopy*/,0/*CopyTo*/,
|
||||||
0/*UpdateDiskSpace*/,1/*Background*/,0/*Concurrent*/);
|
0/*UpdateDiskSpace*/,
|
||||||
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/*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*/,'',
|
||||||
|
0/*AutoDelete*/,
|
||||||
|
0/*AutoMove*/,0/*MoveTo*/,
|
||||||
|
0/*AutoCopy*/,0/*CopyTo*/,
|
||||||
|
1/*UpdateDiskSpace*/,
|
||||||
|
1/*Background*/,
|
||||||
|
0/*Concurrent*/
|
||||||
|
);
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Add in some sample control protocol definitions
|
-- 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
|
-- 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','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, 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);
|
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
|
%global _hardened_build 1
|
||||||
|
|
||||||
Name: zoneminder
|
Name: zoneminder
|
||||||
Version: 1.34.9
|
Version: 1.35.2
|
||||||
Release: 1%{?dist}
|
Release: 1%{?dist}
|
||||||
Summary: A camera monitoring and analysis tool
|
Summary: A camera monitoring and analysis tool
|
||||||
Group: System Environment/Daemons
|
Group: System Environment/Daemons
|
||||||
|
|
|
@ -33,6 +33,7 @@ Build-Depends: debhelper (>= 9), dh-systemd, python-sphinx | python3-sphinx, apa
|
||||||
,libssl-dev
|
,libssl-dev
|
||||||
,libcrypt-eksblowfish-perl
|
,libcrypt-eksblowfish-perl
|
||||||
,libdata-entropy-perl
|
,libdata-entropy-perl
|
||||||
|
,libvncserver-dev
|
||||||
# Unbundled (dh_linktree):
|
# Unbundled (dh_linktree):
|
||||||
,libjs-jquery
|
,libjs-jquery
|
||||||
,libjs-mootools
|
,libjs-mootools
|
||||||
|
@ -82,6 +83,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
|
||||||
,libssl | libssl1.0.0 | libssl1.1
|
,libssl | libssl1.0.0 | libssl1.1
|
||||||
,libcrypt-eksblowfish-perl
|
,libcrypt-eksblowfish-perl
|
||||||
,libdata-entropy-perl
|
,libdata-entropy-perl
|
||||||
|
,libvncclient1
|
||||||
Recommends: ${misc:Recommends}
|
Recommends: ${misc:Recommends}
|
||||||
,libapache2-mod-php5 | libapache2-mod-php | php5-fpm | php-fpm
|
,libapache2-mod-php5 | libapache2-mod-php | php5-fpm | php-fpm
|
||||||
,mysql-server | mariadb-server | virtual-mysql-server
|
,mysql-server | mariadb-server | virtual-mysql-server
|
||||||
|
|
|
@ -482,6 +482,7 @@ Create a Zone
|
||||||
&Zone[Units]=Percent\
|
&Zone[Units]=Percent\
|
||||||
&Zone[NumCoords]=4\
|
&Zone[NumCoords]=4\
|
||||||
&Zone[Coords]=0,0 639,0 639,479 0,479\
|
&Zone[Coords]=0,0 639,0 639,479 0,479\
|
||||||
|
&Zone[Area]=307200\
|
||||||
&Zone[AlarmRGB]=16711680\
|
&Zone[AlarmRGB]=16711680\
|
||||||
&Zone[CheckMethod]=Blobs\
|
&Zone[CheckMethod]=Blobs\
|
||||||
&Zone[MinPixelThreshold]=25\
|
&Zone[MinPixelThreshold]=25\
|
||||||
|
|
|
@ -68,9 +68,13 @@ Here is what the filter window looks like
|
||||||
* %ESM% Maximum score of the event
|
* %ESM% Maximum score of the event
|
||||||
* %EP% Path to the event
|
* %EP% Path to the event
|
||||||
* %EPS% Path to the event stream
|
* %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
|
* %EPI% Path to the event images
|
||||||
* %EPI1% Path to the first alarmed event image
|
* %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
|
* %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
|
* %EI1% Attach first alarmed event image
|
||||||
* %EIM% Attach (first) event image with the highest score
|
* %EIM% Attach (first) event image with the highest score
|
||||||
* %EV% Attach event mpeg video
|
* %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
|
* %MEW% Number of events for the monitor in the last week
|
||||||
* %MEM% Number of events for the monitor in the last month
|
* %MEM% Number of events for the monitor in the last month
|
||||||
* %MEA% Number of archived events for the monitor
|
* %MEA% Number of archived events for the monitor
|
||||||
* %MOD% Path to image containing object detection
|
|
||||||
* %MP% Path to the monitor window
|
* %MP% Path to the monitor window
|
||||||
* %MPS% Path to the monitor stream
|
* %MPS% Path to the monitor stream
|
||||||
* %MPI% Path to the monitor recent image
|
* %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 %is_success_of :ATTR(:name<is_success> :default<()>);
|
||||||
|
|
||||||
my %local_addr_of :ATTR(:name<local_addr> :init_arg<local_addr> :default<()>);
|
my %local_addr_of :ATTR(:name<local_addr> :init_arg<local_addr> :default<()>);
|
||||||
|
my $net_interface;
|
||||||
|
|
||||||
# create methods normally inherited from SOAP::Client
|
# create methods normally inherited from SOAP::Client
|
||||||
SUBFACTORY: {
|
SUBFACTORY: {
|
||||||
|
@ -60,14 +60,22 @@ sub _notify_response
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub set_net_interface {
|
||||||
|
my $self = shift;
|
||||||
|
$net_interface = shift;
|
||||||
|
}
|
||||||
|
|
||||||
sub send_multi() {
|
sub send_multi() {
|
||||||
my ($self, $address, $port, $utf8_string) = @_;
|
my ($self, $address, $port, $utf8_string) = @_;
|
||||||
|
|
||||||
my $destination = $address . ':' . $port;
|
my $destination = $address . ':' . $port;
|
||||||
my $socket = IO::Socket::Multicast->new(PROTO => 'udp',
|
my $socket = IO::Socket::Multicast->new(
|
||||||
LocalPort=>$port, PeerAddr=>$destination, ReuseAddr=>1)
|
PROTO => 'udp',
|
||||||
|
LocalPort=>$port,
|
||||||
or die 'Cannot open multicast socket to ' . ${address} . ':' . ${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;
|
my $bytes = $utf8_string;
|
||||||
utf8::encode($bytes);
|
utf8::encode($bytes);
|
||||||
|
@ -80,14 +88,16 @@ sub receive_multi() {
|
||||||
my ($self, $address, $port) = @_;
|
my ($self, $address, $port) = @_;
|
||||||
my $data = undef;
|
my $data = undef;
|
||||||
|
|
||||||
my $socket = IO::Socket::Multicast->new(PROTO => 'udp',
|
my $socket = IO::Socket::Multicast->new(
|
||||||
LocalPort=>$port, ReuseAddr=>1);
|
PROTO => 'udp',
|
||||||
$socket->mcast_add($address);
|
LocalPort=>$port,
|
||||||
|
ReuseAddr=>1);
|
||||||
|
$socket->mcast_add($address, $net_interface);
|
||||||
|
|
||||||
my $readbits = '';
|
my $readbits = '';
|
||||||
vec($readbits, $socket->fileno, 1) = 1;
|
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);
|
$socket->recv($data, 9999);
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
@ -98,15 +108,19 @@ sub receive_uni() {
|
||||||
my ($self, $address, $port, $localaddr) = @_;
|
my ($self, $address, $port, $localaddr) = @_;
|
||||||
my $data = undef;
|
my $data = undef;
|
||||||
|
|
||||||
my $socket = IO::Socket::Multicast->new(PROTO => 'udp',
|
my $socket = IO::Socket::Multicast->new(
|
||||||
LocalAddr => $localaddr, LocalPort=>$port, ReuseAddr=>1);
|
PROTO => 'udp',
|
||||||
|
LocalAddr => $localaddr,
|
||||||
|
LocalPort=>$port,
|
||||||
|
ReuseAddr=>1
|
||||||
|
);
|
||||||
|
|
||||||
$socket->mcast_add($address);
|
$socket->mcast_add($address, $net_interface);
|
||||||
|
|
||||||
my $readbits = '';
|
my $readbits = '';
|
||||||
vec($readbits, $socket->fileno, 1) = 1;
|
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);
|
$socket->recv($data, 9999);
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
@ -120,39 +134,39 @@ sub send_receive {
|
||||||
|
|
||||||
my ($address,$port) = ($endpoint =~ /([^:\/]+):([0-9]+)/);
|
my ($address,$port) = ($endpoint =~ /([^:\/]+):([0-9]+)/);
|
||||||
|
|
||||||
#warn "address = ${address}";
|
#warn "address = ${address}";
|
||||||
#warn "port = ${port}";
|
#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 ($response, $last_response);
|
||||||
my $wait = WAIT_COUNT;
|
my $wait = WAIT_COUNT;
|
||||||
while ( $wait >= 0 ) {
|
while ( $wait >= 0 ) {
|
||||||
if($localaddr) {
|
if ( $localaddr ) {
|
||||||
if($response = $self->receive_uni($address, $port, $localaddr)) {
|
if ( $response = $self->receive_uni($address, $port, $localaddr) ) {
|
||||||
$last_response = $response;
|
$last_response = $response;
|
||||||
$self->_notify_response($response);
|
$self->_notify_response($response);
|
||||||
}
|
}
|
||||||
$wait --;
|
$wait --;
|
||||||
}
|
}
|
||||||
if($response = $self->receive_multi($address, $port)) {
|
if ( $response = $self->receive_multi($address, $port) ) {
|
||||||
$last_response = $response;
|
$last_response = $response;
|
||||||
$self->_notify_response($response);
|
$self->_notify_response($response);
|
||||||
}
|
}
|
||||||
$wait --;
|
$wait --;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($last_response) {
|
if ( $last_response ) {
|
||||||
$self->set_code();
|
$self->set_code();
|
||||||
$self->set_message("");
|
$self->set_message('');
|
||||||
$self->set_is_success(1);
|
$self->set_is_success(1);
|
||||||
$self->set_status('OK');
|
$self->set_status('OK');
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
$self->set_code();
|
$self->set_code();
|
||||||
$self->set_message("Timed out waiting for response");
|
$self->set_message('Timed out waiting for response');
|
||||||
$self->set_is_success(0);
|
$self->set_is_success(0);
|
||||||
$self->set_status('TIMEOUT');
|
$self->set_status('TIMEOUT');
|
||||||
}
|
}
|
||||||
|
@ -161,3 +175,4 @@ sub send_receive {
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
__END__
|
||||||
|
|
|
@ -2213,7 +2213,7 @@ our @options = (
|
||||||
that match the appropriate filters will be sent to.
|
that match the appropriate filters will be sent to.
|
||||||
`,
|
`,
|
||||||
type => $types{email},
|
type => $types{email},
|
||||||
category => 'mail',
|
category => 'hidden',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name => 'ZM_EMAIL_TEXT',
|
name => 'ZM_EMAIL_TEXT',
|
||||||
|
@ -2253,7 +2253,7 @@ our @options = (
|
||||||
sent for any events that match the appropriate filters.
|
sent for any events that match the appropriate filters.
|
||||||
`,
|
`,
|
||||||
type => $types{string},
|
type => $types{string},
|
||||||
category => 'mail',
|
category => 'hidden',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name => 'ZM_EMAIL_BODY',
|
name => 'ZM_EMAIL_BODY',
|
||||||
|
@ -2280,7 +2280,7 @@ our @options = (
|
||||||
sent for any events that match the appropriate filters.
|
sent for any events that match the appropriate filters.
|
||||||
`,
|
`,
|
||||||
type => $types{text},
|
type => $types{text},
|
||||||
category => 'mail',
|
category => 'hidden',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name => 'ZM_OPT_MESSAGE',
|
name => 'ZM_OPT_MESSAGE',
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# ==========================================================================
|
# ==========================================================================
|
||||||
#
|
#
|
||||||
# ZoneMinder Base Control Module, $Date$, $Revision$
|
# ZoneMinder Base Control Module
|
||||||
# Copyright (C) 2001-2008 Philip Coombes
|
# Copyright (C) 2001-2008 Philip Coombes
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or
|
# This program is free software; you can redistribute it and/or
|
||||||
|
@ -46,13 +46,13 @@ our $AUTOLOAD;
|
||||||
sub new {
|
sub new {
|
||||||
my $class = shift;
|
my $class = shift;
|
||||||
my $id = shift;
|
my $id = shift;
|
||||||
|
if ( !defined($id) ) {
|
||||||
|
Fatal('No monitor defined when invoking protocol '.$class);
|
||||||
|
}
|
||||||
my $self = {};
|
my $self = {};
|
||||||
$self->{name} = $class;
|
$self->{name} = $class;
|
||||||
if ( !defined($id) ) {
|
|
||||||
Fatal('No monitor defined when invoking protocol '.$self->{name});
|
|
||||||
}
|
|
||||||
$self->{id} = $id;
|
$self->{id} = $id;
|
||||||
bless( $self, $class );
|
bless($self, $class);
|
||||||
return $self;
|
return $self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ sub AUTOLOAD {
|
||||||
|
|
||||||
sub getKey {
|
sub getKey {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
return( $self->{id} );
|
return $self->{id};
|
||||||
}
|
}
|
||||||
|
|
||||||
sub open {
|
sub open {
|
||||||
|
|
|
@ -46,96 +46,54 @@ use ZoneMinder::Config qw(:all);
|
||||||
|
|
||||||
use Time::HiRes qw( usleep );
|
use Time::HiRes qw( usleep );
|
||||||
|
|
||||||
sub new
|
sub open {
|
||||||
{
|
|
||||||
my $class = shift;
|
|
||||||
my $id = shift;
|
|
||||||
my $self = ZoneMinder::Control->new( $id );
|
|
||||||
bless( $self, $class );
|
|
||||||
srand( time() );
|
|
||||||
return $self;
|
|
||||||
}
|
|
||||||
|
|
||||||
our $AUTOLOAD;
|
|
||||||
|
|
||||||
sub AUTOLOAD
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
my $class = ref($self) || croak( "$self not object" );
|
|
||||||
my $name = $AUTOLOAD;
|
|
||||||
$name =~ s/.*://;
|
|
||||||
if ( exists($self->{$name}) )
|
|
||||||
{
|
|
||||||
return( $self->{$name} );
|
|
||||||
}
|
|
||||||
Fatal( "Can't access $name member of object of class $class" );
|
|
||||||
}
|
|
||||||
|
|
||||||
sub open
|
|
||||||
{
|
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
|
||||||
$self->loadMonitor();
|
$self->loadMonitor();
|
||||||
|
|
||||||
use LWP::UserAgent;
|
use LWP::UserAgent;
|
||||||
$self->{ua} = LWP::UserAgent->new;
|
$self->{ua} = LWP::UserAgent->new;
|
||||||
$self->{ua}->agent( "ZoneMinder Control Agent/" . ZoneMinder::Base::ZM_VERSION );
|
$self->{ua}->agent('ZoneMinder Control Agent/' . ZoneMinder::Base::ZM_VERSION);
|
||||||
$self->{state} = 'open';
|
$self->{state} = 'open';
|
||||||
}
|
}
|
||||||
|
|
||||||
sub close
|
sub close {
|
||||||
{
|
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
$self->{state} = 'closed';
|
$self->{state} = 'closed';
|
||||||
}
|
}
|
||||||
|
|
||||||
sub printMsg
|
sub sendCmd {
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
my $msg = shift;
|
|
||||||
my $msg_len = length($msg);
|
|
||||||
|
|
||||||
Debug( $msg."[".$msg_len."]" );
|
|
||||||
}
|
|
||||||
|
|
||||||
sub sendCmd
|
|
||||||
{
|
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $cmd = shift;
|
my $cmd = shift;
|
||||||
my $cgi = shift;
|
my $cgi = shift;
|
||||||
|
|
||||||
my $result = undef;
|
my $result = undef;
|
||||||
|
|
||||||
printMsg( $cmd, "Tx" );
|
printMsg($cmd, 'Tx');
|
||||||
|
|
||||||
my $req = HTTP::Request->new( POST=>"http://$self->{Monitor}->{ControlAddress}/$cgi.cgi" );
|
my $req = HTTP::Request->new( POST=>"http://$self->{Monitor}->{ControlAddress}/$cgi.cgi" );
|
||||||
$req->content($cmd);
|
$req->content($cmd);
|
||||||
my $res = $self->{ua}->request($req);
|
my $res = $self->{ua}->request($req);
|
||||||
|
|
||||||
if ( $res->is_success )
|
if ( $res->is_success ) {
|
||||||
{
|
|
||||||
$result = !undef;
|
$result = !undef;
|
||||||
}
|
} else {
|
||||||
else
|
Error("Error check failed: '".$res->status_line()."'");
|
||||||
{
|
|
||||||
Error( "Error check failed: '".$res->status_line()."'" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return( $result );
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub move
|
sub move {
|
||||||
{
|
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $dir = shift;
|
my $dir = shift;
|
||||||
my $panStep = shift;
|
my $panStep = shift;
|
||||||
my $tiltStep = shift;
|
my $tiltStep = shift;
|
||||||
my $cmd = "PanSingleMoveDegree=$panStep&TiltSingleMoveDegree=$tiltStep&PanTiltSingleMove=$dir";
|
my $cmd = "PanSingleMoveDegree=$panStep&TiltSingleMoveDegree=$tiltStep&PanTiltSingleMove=$dir";
|
||||||
$self->sendCmd( $cmd, 'pantiltcontrol' );
|
$self->sendCmd($cmd, 'pantiltcontrol');
|
||||||
}
|
}
|
||||||
|
|
||||||
sub moveRel
|
sub moveRel {
|
||||||
{
|
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $params = shift;
|
my $params = shift;
|
||||||
my $panStep = $self->getParam($params, 'panstep', 0);
|
my $panStep = $self->getParam($params, 'panstep', 0);
|
||||||
|
@ -144,66 +102,57 @@ sub moveRel
|
||||||
$self->move( $dir, $panStep, $tiltStep );
|
$self->move( $dir, $panStep, $tiltStep );
|
||||||
}
|
}
|
||||||
|
|
||||||
sub moveRelUpLeft
|
sub moveRelUpLeft {
|
||||||
{
|
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $params = shift;
|
my $params = shift;
|
||||||
$self->moveRel( $params, 0 );
|
$self->moveRel($params, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub moveRelUp
|
sub moveRelUp {
|
||||||
{
|
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $params = shift;
|
my $params = shift;
|
||||||
$self->moveRel( $params, 1 );
|
$self->moveRel($params, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub moveRelUpRight
|
sub moveRelUpRight {
|
||||||
{
|
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $params = shift;
|
my $params = shift;
|
||||||
$self->moveRel( $params, 2 );
|
$self->moveRel($params, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub moveRelLeft
|
sub moveRelLeft {
|
||||||
{
|
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $params = shift;
|
my $params = shift;
|
||||||
$self->moveRel( $params, 3 );
|
$self->moveRel($params, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub moveRelRight
|
sub moveRelRight {
|
||||||
{
|
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $params = shift;
|
my $params = shift;
|
||||||
$self->moveRel( $params, 5 );
|
$self->moveRel($params, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub moveRelDownLeft
|
sub moveRelDownLeft {
|
||||||
{
|
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $params = shift;
|
my $params = shift;
|
||||||
$self->moveRel( $params, 6 );
|
$self->moveRel($params, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub moveRelDown
|
sub moveRelDown {
|
||||||
{
|
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $params = shift;
|
my $params = shift;
|
||||||
$self->moveRel( $params, 7 );
|
$self->moveRel($params, 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub moveRelDownRight
|
sub moveRelDownRight {
|
||||||
{
|
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $params = shift;
|
my $params = shift;
|
||||||
$self->moveRel( $params, 8 );
|
$self->moveRel($params, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
# moves the camera to center on the point that the user clicked on in the video image.
|
# 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
|
# This isn't extremely accurate but good enough for most purposes
|
||||||
sub moveMap
|
sub moveMap {
|
||||||
{
|
|
||||||
# if the camera moves too much or too little, try increasing or decreasing this value
|
# if the camera moves too much or too little, try increasing or decreasing this value
|
||||||
my $f = 11;
|
my $f = 11;
|
||||||
|
|
||||||
|
@ -241,12 +190,11 @@ sub moveMap
|
||||||
}
|
}
|
||||||
my $v = int($verSteps + .5);
|
my $v = int($verSteps + .5);
|
||||||
my $h = int($horSteps + .5);
|
my $h = int($horSteps + .5);
|
||||||
Debug( "Move Map to $xcoord,$ycoord, hor=$h, ver=$v with direction $direction" );
|
Debug("Move Map to $xcoord,$ycoord, hor=$h, ver=$v with direction $direction");
|
||||||
$self->move( $direction, $h, $v );
|
$self->move($direction, $h, $v);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub presetClear
|
sub presetClear {
|
||||||
{
|
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $params = shift;
|
my $params = shift;
|
||||||
my $preset = $self->getParam( $params, 'preset' );
|
my $preset = $self->getParam( $params, 'preset' );
|
||||||
|
@ -255,8 +203,7 @@ sub presetClear
|
||||||
$self->sendCmd( $cmd, 'pantiltcontrol' );
|
$self->sendCmd( $cmd, 'pantiltcontrol' );
|
||||||
}
|
}
|
||||||
|
|
||||||
sub presetSet
|
sub presetSet {
|
||||||
{
|
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $params = shift;
|
my $params = shift;
|
||||||
my $preset = $self->getParam( $params, 'preset' );
|
my $preset = $self->getParam( $params, 'preset' );
|
||||||
|
@ -265,8 +212,7 @@ sub presetSet
|
||||||
$self->sendCmd( $cmd, 'pantiltcontrol' );
|
$self->sendCmd( $cmd, 'pantiltcontrol' );
|
||||||
}
|
}
|
||||||
|
|
||||||
sub presetGoto
|
sub presetGoto {
|
||||||
{
|
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $params = shift;
|
my $params = shift;
|
||||||
my $preset = $self->getParam( $params, 'preset' );
|
my $preset = $self->getParam( $params, 'preset' );
|
||||||
|
@ -275,14 +221,12 @@ sub presetGoto
|
||||||
$self->sendCmd( $cmd, 'pantiltcontrol' );
|
$self->sendCmd( $cmd, 'pantiltcontrol' );
|
||||||
}
|
}
|
||||||
|
|
||||||
sub presetHome
|
sub presetHome {
|
||||||
{
|
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
Debug( "Home Preset" );
|
Debug( "Home Preset" );
|
||||||
$self->move( 4, 0, 0 );
|
$self->move( 4, 0, 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# IR Controls
|
# IR Controls
|
||||||
#
|
#
|
||||||
# wake = IR on
|
# wake = IR on
|
||||||
|
@ -293,37 +237,33 @@ sub setDayNightMode {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $mode = shift;
|
my $mode = shift;
|
||||||
my $cmd = "DayNightMode=$mode&ConfigReboot=No";
|
my $cmd = "DayNightMode=$mode&ConfigReboot=No";
|
||||||
$self->sendCmd( $cmd, 'daynight' );
|
$self->sendCmd($cmd, 'daynight');
|
||||||
}
|
}
|
||||||
|
|
||||||
sub wake
|
sub wake {
|
||||||
{
|
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
Debug( "Wake - IR on" );
|
Debug('Wake - IR on');
|
||||||
$self->setDayNightMode(2);
|
$self->setDayNightMode(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub sleep
|
sub sleep {
|
||||||
{
|
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
Debug( "Sleep - IR off" );
|
Debug('Sleep - IR off');
|
||||||
$self->setDayNightMode(3);
|
$self->setDayNightMode(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub reset
|
sub reset {
|
||||||
{
|
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
Debug( "Reset - IR auto" );
|
Debug('Reset - IR auto');
|
||||||
$self->setDayNightMode(0);
|
$self->setDayNightMode(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
__END__
|
__END__
|
||||||
# Below is stub documentation for your module. You'd better edit it!
|
|
||||||
|
|
||||||
=head1 NAME
|
=head1 NAME
|
||||||
|
|
||||||
ZoneMinder::Database - Perl extension for DCS-5020L
|
ZoneMinder::Control::DCS5020L - Perl extension for DCS-5020L
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
@ -351,6 +291,20 @@ Art Scheel <lt>ascheel (at) gmail<gt>
|
||||||
|
|
||||||
=head1 COPYRIGHT AND LICENSE
|
=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
|
=cut
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# ==========================================================================
|
# ==========================================================================
|
||||||
#
|
#
|
||||||
# ZoneMinder Filter Module, $Date$, $Revision$
|
# ZoneMinder Filter Module
|
||||||
# Copyright (C) 2001-2008 Philip Coombes
|
# Copyright (C) 2001-2008 Philip Coombes
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or
|
# This program is free software; you can redistribute it and/or
|
||||||
|
@ -162,7 +162,9 @@ sub Sql {
|
||||||
my $value = $term->{val};
|
my $value = $term->{val};
|
||||||
my @value_list;
|
my @value_list;
|
||||||
if ( $term->{attr} ) {
|
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(.+)$/;
|
my ( $temp_attr_name ) = $term->{attr} =~ /^Monitor(.+)$/;
|
||||||
$self->{Sql} .= 'M.'.$temp_attr_name;
|
$self->{Sql} .= 'M.'.$temp_attr_name;
|
||||||
} elsif ( $term->{attr} eq 'ServerId' or $term->{attr} eq 'MonitorServerId' ) {
|
} elsif ( $term->{attr} eq 'ServerId' or $term->{attr} eq 'MonitorServerId' ) {
|
||||||
|
@ -214,7 +216,10 @@ sub Sql {
|
||||||
|
|
||||||
( my $stripped_value = $value ) =~ s/^["\']+?(.+)["\']+?$/$1/;
|
( my $stripped_value = $value ) =~ s/^["\']+?(.+)["\']+?$/$1/;
|
||||||
foreach my $temp_value ( split( /["'\s]*?,["'\s]*?/, $stripped_value ) ) {
|
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'";
|
$value = "'$temp_value'";
|
||||||
} elsif ( $term->{attr} =~ /ServerId/) {
|
} elsif ( $term->{attr} =~ /ServerId/) {
|
||||||
Debug("ServerId, temp_value is ($temp_value) ($ZoneMinder::Config::Config{ZM_SERVER_ID})");
|
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' ) {
|
} elsif ( $term->{attr} eq 'Date' or $term->{attr} eq 'StartDate' or $term->{attr} eq 'EndDate' ) {
|
||||||
if ( $temp_value eq 'NULL' ) {
|
if ( $temp_value eq 'NULL' ) {
|
||||||
$value = $temp_value;
|
$value = $temp_value;
|
||||||
|
} elsif ( $temp_value eq 'CURDATE()' or $temp_value eq 'NOW()' ) {
|
||||||
|
$value = 'to_days('.$temp_value.')';
|
||||||
} else {
|
} else {
|
||||||
$value = DateTimeToSQL($temp_value);
|
$value = DateTimeToSQL($temp_value);
|
||||||
if ( !$value ) {
|
if ( !$value ) {
|
||||||
|
@ -294,6 +301,8 @@ sub Sql {
|
||||||
} else {
|
} else {
|
||||||
$self->{Sql} .= " IS $value";
|
$self->{Sql} .= " IS $value";
|
||||||
}
|
}
|
||||||
|
} elsif ( $term->{op} eq 'EXISTS' ) {
|
||||||
|
$self->{Sql} .= " EXISTS $value";
|
||||||
} elsif ( $term->{op} eq 'IS NOT' ) {
|
} elsif ( $term->{op} eq 'IS NOT' ) {
|
||||||
$self->{Sql} .= " IS NOT $value";
|
$self->{Sql} .= " IS NOT $value";
|
||||||
} elsif ( $term->{op} eq '=[]' ) {
|
} elsif ( $term->{op} eq '=[]' ) {
|
||||||
|
|
|
@ -172,7 +172,7 @@ sub interpret_messages {
|
||||||
# functions
|
# functions
|
||||||
|
|
||||||
sub discover {
|
sub discover {
|
||||||
my ( $soap_version ) = @_;
|
my ( $soap_version, $net_interface ) = @_;
|
||||||
my @results;
|
my @results;
|
||||||
|
|
||||||
## collect all responses
|
## collect all responses
|
||||||
|
@ -192,13 +192,18 @@ sub discover {
|
||||||
if ( ( ! $soap_version ) or ( $soap_version eq '1.1' ) ) {
|
if ( ( ! $soap_version ) or ( $soap_version eq '1.1' ) ) {
|
||||||
my %services;
|
my %services;
|
||||||
|
|
||||||
if($verbose) {
|
if ( $verbose ) {
|
||||||
print "Probing for SOAP 1.1\n"
|
print "Probing for SOAP 1.1\n";
|
||||||
}
|
}
|
||||||
my $svc_discover = WSDiscovery10::Interfaces::WSDiscovery::WSDiscoveryPort->new({
|
my $svc_discover = WSDiscovery10::Interfaces::WSDiscovery::WSDiscoveryPort->new({
|
||||||
# no_dispatch => '1',
|
# no_dispatch => '1',
|
||||||
});
|
});
|
||||||
$svc_discover->set_soap_version('1.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 $uuid = $uuid_gen->create_str();
|
||||||
|
|
||||||
|
@ -221,13 +226,18 @@ sub discover {
|
||||||
|
|
||||||
if ( ( ! $soap_version ) or ( $soap_version eq '1.2' ) ) {
|
if ( ( ! $soap_version ) or ( $soap_version eq '1.2' ) ) {
|
||||||
my %services;
|
my %services;
|
||||||
if($verbose) {
|
if ( $verbose ) {
|
||||||
print "Probing for SOAP 1.2\n"
|
print "Probing for SOAP 1.2\n";
|
||||||
}
|
}
|
||||||
my $svc_discover = WSDiscovery10::Interfaces::WSDiscovery::WSDiscoveryPort->new({
|
my $svc_discover = WSDiscovery10::Interfaces::WSDiscovery::WSDiscoveryPort->new({
|
||||||
# no_dispatch => '1',
|
# no_dispatch => '1',
|
||||||
});
|
});
|
||||||
$svc_discover->set_soap_version('1.2');
|
$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.
|
# copies of the same Probe message must have the same MessageID.
|
||||||
# This is not a copy. So we generate a new uuid.
|
# 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);
|
push @results, interpret_messages($svc_discover, \%services, @responses);
|
||||||
} # end if doing soap 1.2
|
} # end if doing soap 1.2
|
||||||
return @results;
|
return @results;
|
||||||
}
|
} # end sub discover
|
||||||
|
|
||||||
sub profiles {
|
sub profiles {
|
||||||
my ( $client ) = @_;
|
my ( $client ) = @_;
|
||||||
|
|
|
@ -352,9 +352,13 @@ sub exportsql {
|
||||||
}
|
}
|
||||||
|
|
||||||
my $name = $ARGV[0];
|
my $name = $ARGV[0];
|
||||||
if ($name && $name =~ /^([A-Za-z0-9 ,.&()\/\-]+)$/) { # Allow alphanumeric and " ,.&()/-"
|
if ( $name ) {
|
||||||
|
if ( $name =~ /^([A-Za-z0-9 ,.&()\/\-]+)$/ ) { # Allow alphanumeric and " ,.&()/-"
|
||||||
$name = $1;
|
$name = $1;
|
||||||
$command .= qq( --where="Name = '$name'");
|
$command .= qq( --where="Name = '$name'");
|
||||||
|
} else {
|
||||||
|
print "Invalid characters in Name\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$command .= " zm Controls MonitorPresets";
|
$command .= " zm Controls MonitorPresets";
|
||||||
|
|
|
@ -196,7 +196,7 @@ my $last_action = 0;
|
||||||
while( !$zm_terminate ) {
|
while( !$zm_terminate ) {
|
||||||
my $now = time;
|
my $now = time;
|
||||||
if ( ($now - $last_action) > $Config{ZM_FILTER_RELOAD_DELAY} ) {
|
if ( ($now - $last_action) > $Config{ZM_FILTER_RELOAD_DELAY} ) {
|
||||||
Debug("Reloading filters");
|
Debug('Reloading filters');
|
||||||
$last_action = $now;
|
$last_action = $now;
|
||||||
@filters = getFilters({ Name=>$filter_name, Id=>$filter_id });
|
@filters = getFilters({ Name=>$filter_name, Id=>$filter_id });
|
||||||
}
|
}
|
||||||
|
@ -699,8 +699,10 @@ sub substituteTags {
|
||||||
$text =~ s/%ESM%/$Event->{MaxScore}/g;
|
$text =~ s/%ESM%/$Event->{MaxScore}/g;
|
||||||
|
|
||||||
if ( $first_alarm_frame ) {
|
if ( $first_alarm_frame ) {
|
||||||
$text =~ s/%EPI1%/$url?view=frame&mid=$Event->{MonitorId}&eid=$Event->{Id}&fid=$first_alarm_frame->{FrameId}/g;
|
$text =~ s/%EPF1%/$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/%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 ( $attachments_ref ) {
|
||||||
if ( $text =~ s/%EI1%//g ) {
|
if ( $text =~ s/%EI1%//g ) {
|
||||||
my $path = generateImage($Event, $first_alarm_frame);
|
my $path = generateImage($Event, $first_alarm_frame);
|
||||||
|
@ -748,13 +750,14 @@ sub substituteTags {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $text =~ s/%EIMOD%//g ) {
|
if ( $text =~ s/%EIMOD%//g or $text =~ s/%EFMOD%//g ) {
|
||||||
$text =~ s/%EIMOD%/$url?view=frame&mid=$Event->{MonitorId}&eid=$Event->{Id}&fid=objdetect/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';
|
my $path = $Event->Path().'/objdetect.jpg';
|
||||||
if ( -e $path ) {
|
if ( -e $path ) {
|
||||||
push @$attachments_ref, { type=>'image/jpeg', path=>$path };
|
push @$attachments_ref, { type=>'image/jpeg', path=>$path };
|
||||||
} else {
|
} 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');
|
Error('No from email address defined, not sending email');
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if ( ! $Config{ZM_EMAIL_ADDRESS} ) {
|
if ( ! $$filter{EmailTo} ) {
|
||||||
Error('No email address defined, not sending email');
|
Error('No email address defined, not sending email');
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Info('Creating notification email');
|
Info('Creating notification email');
|
||||||
|
|
||||||
my $subject = substituteTags($Config{ZM_EMAIL_SUBJECT}, $filter, $Event);
|
my $subject = substituteTags($$filter{EmailSubject}, $filter, $Event);
|
||||||
return 0 if !$subject;
|
return 0 if !$subject;
|
||||||
my @attachments;
|
my @attachments;
|
||||||
my $body = substituteTags($Config{ZM_EMAIL_BODY}, $filter, $Event, \@attachments);
|
my $body = substituteTags($$filter{EmailBody}, $filter, $Event, \@attachments);
|
||||||
return 0 if !$body;
|
return 0 if !$body;
|
||||||
|
|
||||||
Info("Sending notification email '$subject'");
|
Info("Sending notification email '$subject'");
|
||||||
|
@ -816,7 +819,7 @@ sub sendEmail {
|
||||||
### Create the multipart container
|
### Create the multipart container
|
||||||
my $mail = MIME::Lite->new (
|
my $mail = MIME::Lite->new (
|
||||||
From => $Config{ZM_FROM_EMAIL},
|
From => $Config{ZM_FROM_EMAIL},
|
||||||
To => $Config{ZM_EMAIL_ADDRESS},
|
To => $$filter{EmailTo},
|
||||||
Subject => $subject,
|
Subject => $subject,
|
||||||
Type => 'multipart/mixed'
|
Type => 'multipart/mixed'
|
||||||
);
|
);
|
||||||
|
@ -826,14 +829,20 @@ sub sendEmail {
|
||||||
Data => $body
|
Data => $body
|
||||||
);
|
);
|
||||||
### Add the attachments
|
### Add the attachments
|
||||||
|
my $total_size = 0;
|
||||||
foreach my $attachment ( @attachments ) {
|
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(
|
$mail->attach(
|
||||||
Path => $attachment->{path},
|
Path => $attachment->{path},
|
||||||
Type => $attachment->{type},
|
Type => $attachment->{type},
|
||||||
Disposition => 'attachment'
|
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
|
### Send the Message
|
||||||
if ( $Config{ZM_SSMTP_MAIL} ) {
|
if ( $Config{ZM_SSMTP_MAIL} ) {
|
||||||
my $ssmtp_location = $Config{ZM_SSMTP_PATH};
|
my $ssmtp_location = $Config{ZM_SSMTP_PATH};
|
||||||
|
@ -849,7 +858,7 @@ sub sendEmail {
|
||||||
$mail->send();
|
$mail->send();
|
||||||
} else {
|
} else {
|
||||||
### Send using SSMTP
|
### Send using SSMTP
|
||||||
$mail->send('sendmail', $ssmtp_location, $Config{ZM_EMAIL_ADDRESS});
|
$mail->send('sendmail', $ssmtp_location, $$filter{EmailTo});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
MIME::Lite->send('smtp', $Config{ZM_EMAIL_HOST}, Timeout=>60);
|
MIME::Lite->send('smtp', $Config{ZM_EMAIL_HOST}, Timeout=>60);
|
||||||
|
@ -858,19 +867,26 @@ sub sendEmail {
|
||||||
} else {
|
} else {
|
||||||
my $mail = MIME::Entity->build(
|
my $mail = MIME::Entity->build(
|
||||||
From => $Config{ZM_FROM_EMAIL},
|
From => $Config{ZM_FROM_EMAIL},
|
||||||
To => $Config{ZM_EMAIL_ADDRESS},
|
To => $$filter{EmailTo},
|
||||||
Subject => $subject,
|
Subject => $subject,
|
||||||
Type => (($body=~/<html>/)?'text/html':'text/plain'),
|
Type => (($body=~/<html/)?'text/html':'text/plain'),
|
||||||
Data => $body
|
Data => $body
|
||||||
);
|
);
|
||||||
|
|
||||||
|
my $total_size = 0;
|
||||||
foreach my $attachment ( @attachments ) {
|
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(
|
$mail->attach(
|
||||||
Path => $attachment->{path},
|
Path => $attachment->{path},
|
||||||
Type => $attachment->{type},
|
Type => $attachment->{type},
|
||||||
Encoding => 'base64'
|
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});
|
$mail->smtpsend(Host => $Config{ZM_EMAIL_HOST}, MailFrom => $Config{ZM_FROM_EMAIL});
|
||||||
}
|
}
|
||||||
|
@ -962,7 +978,7 @@ sub sendMessage {
|
||||||
From => $Config{ZM_FROM_EMAIL},
|
From => $Config{ZM_FROM_EMAIL},
|
||||||
To => $Config{ZM_MESSAGE_ADDRESS},
|
To => $Config{ZM_MESSAGE_ADDRESS},
|
||||||
Subject => $subject,
|
Subject => $subject,
|
||||||
Type => (($body=~/<html>/)?'text/html':'text/plain'),
|
Type => (($body=~/<html/)?'text/html':'text/plain'),
|
||||||
Data => $body
|
Data => $body
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ my $OPTIONS = 'v';
|
||||||
|
|
||||||
sub HELP_MESSAGE {
|
sub HELP_MESSAGE {
|
||||||
my ($fh, $pkg, $ver, $opts) = @_;
|
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 " " . __FILE__ . " [-v] <command> <device URI> <soap version> <user> <password>\n";
|
||||||
print $fh <<EOF
|
print $fh <<EOF
|
||||||
Commands are:
|
Commands are:
|
||||||
|
@ -69,7 +69,7 @@ if ( !getopts($OPTIONS) ) {
|
||||||
|
|
||||||
my $action = shift;
|
my $action = shift;
|
||||||
|
|
||||||
if(!defined $action) {
|
if ( ! defined $action ) {
|
||||||
HELP_MESSAGE(\*STDOUT);
|
HELP_MESSAGE(\*STDOUT);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,8 @@ if ( defined $opt_v ) {
|
||||||
|
|
||||||
if ( $action eq 'probe' ) {
|
if ( $action eq 'probe' ) {
|
||||||
my $soap_version = shift;
|
my $soap_version = shift;
|
||||||
ZoneMinder::ONVIF::discover($soap_version);
|
my $net_interface = shift;
|
||||||
|
ZoneMinder::ONVIF::discover($soap_version, $net_interface);
|
||||||
} else {
|
} else {
|
||||||
# all other actions need URI and credentials
|
# all other actions need URI and credentials
|
||||||
my $url_svc_device = shift @ARGV;
|
my $url_svc_device = shift @ARGV;
|
||||||
|
|
|
@ -214,7 +214,7 @@ sub getUUID {
|
||||||
$uuid = $Config{ZM_TELEMETRY_UUID} = $sth->fetchrow_array();
|
$uuid = $Config{ZM_TELEMETRY_UUID} = $sth->fetchrow_array();
|
||||||
$sth->finish();
|
$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() );
|
$sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||||
$res = $sth->execute( "$uuid" ) or die( "Can't execute: ".$sth->errstr() );
|
$res = $sth->execute( "$uuid" ) or die( "Can't execute: ".$sth->errstr() );
|
||||||
$sth->finish();
|
$sth->finish();
|
||||||
|
@ -250,9 +250,9 @@ sub countQuery {
|
||||||
my $dbh = shift;
|
my $dbh = shift;
|
||||||
my $table = shift;
|
my $table = shift;
|
||||||
|
|
||||||
my $sql = "SELECT count(*) FROM $table";
|
my $sql = "SELECT count(*) FROM `$table`";
|
||||||
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
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 $res = $sth->execute() or die 'Can\'t execute: '.$sth->errstr();
|
||||||
my $count = $sth->fetchrow_array();
|
my $count = $sth->fetchrow_array();
|
||||||
$sth->finish();
|
$sth->finish();
|
||||||
|
|
||||||
|
@ -263,7 +263,7 @@ sub countQuery {
|
||||||
sub getMonitorRef {
|
sub getMonitorRef {
|
||||||
my $dbh = shift;
|
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 $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 $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() );
|
||||||
my $arrayref = $sth->fetchall_arrayref({});
|
my $arrayref = $sth->fetchall_arrayref({});
|
||||||
|
|
|
@ -847,9 +847,9 @@ if ( $version ) {
|
||||||
}
|
}
|
||||||
$cascade = !undef;
|
$cascade = !undef;
|
||||||
}
|
}
|
||||||
if ( $cascade || $version eq "1.24.4" ) {
|
if ( $cascade || $version eq '1.24.4' ) {
|
||||||
# Patch the database
|
# Patch the database
|
||||||
patchDB( $dbh, "1.24.4" );
|
patchDB($dbh, '1.24.4');
|
||||||
|
|
||||||
# Copy the FTP specific values to the new general config
|
# Copy the FTP specific values to the new general config
|
||||||
my $fetchSql = "select * from Config where Name like 'ZM_UPLOAD_FTP_%'";
|
my $fetchSql = "select * from Config where Name like 'ZM_UPLOAD_FTP_%'";
|
||||||
|
@ -863,12 +863,12 @@ if ( $version ) {
|
||||||
}
|
}
|
||||||
$cascade = !undef;
|
$cascade = !undef;
|
||||||
}
|
}
|
||||||
if ( $cascade || $version lt "1.26.0" ) {
|
if ( $cascade || $version lt '1.26.0' ) {
|
||||||
my $sth = $dbh->prepare_cached( 'select * from Monitors LIMIT 0,1' );
|
my $sth = $dbh->prepare_cached('SELECT * FROM Monitors LIMIT 0,1');
|
||||||
die "Error: " . $dbh->errstr . "\n" unless ($sth);
|
die "Error: " . $dbh->errstr . "\n" unless ($sth);
|
||||||
die "Error: " . $sth->errstr . "\n" unless ($sth->execute);
|
die "Error: " . $sth->errstr . "\n" unless ($sth->execute);
|
||||||
|
|
||||||
my $columns = $sth->{'NAME'};
|
my $columns = $sth->{NAME};
|
||||||
if ( ! grep(/^Colours$/, @$columns ) ) {
|
if ( ! grep(/^Colours$/, @$columns ) ) {
|
||||||
$dbh->do(q{alter table Monitors add column `Colours` tinyint(3) unsigned NOT NULL default '1' after `Height`;});
|
$dbh->do(q{alter table Monitors add column `Colours` tinyint(3) unsigned NOT NULL default '1' after `Height`;});
|
||||||
} # end if
|
} # end if
|
||||||
|
@ -898,28 +898,31 @@ if ( $version ) {
|
||||||
die "Should have found upgrade scripts at $updateDir\n";
|
die "Should have found upgrade scripts at $updateDir\n";
|
||||||
} # end if
|
} # 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 ) {
|
foreach my $patch ( @files ) {
|
||||||
my ( $v ) = $patch =~ /^zm_update\-([\d\.]+)\.sql$/;
|
my ( $v ) = $patch =~ /^zm_update\-([\d\.]+)\.sql$/;
|
||||||
#PP make sure we use version compare
|
#PP make sure we use version compare
|
||||||
if ( version->parse('v' . $v) > version->parse('v' . $version) ) {
|
if ( version->parse('v'.$v) > version->parse('v'.$version) ) {
|
||||||
print( "Upgrading DB to $v from $version\n" );
|
print("Upgrading DB to $v from $version\n");
|
||||||
patchDB( $dbh, $v );
|
if ( patchDB($dbh, $v) ) {
|
||||||
my $sql = "update Config set Value = ? where Name = 'ZM_DYN_DB_VERSION'";
|
my $res = $sth->execute($version) or die( "Can't execute: ".$sth->errstr() );
|
||||||
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();
|
|
||||||
#patchDB_using_do( $dbh, $version, $updateDir.'/'.$patch );
|
#patchDB_using_do( $dbh, $version, $updateDir.'/'.$patch );
|
||||||
} # end if newer version
|
} # end if newer version
|
||||||
} # end foreach patchfile
|
} # end foreach patchfile
|
||||||
|
|
||||||
|
$sth->finish();
|
||||||
$cascade = !undef;
|
$cascade = !undef;
|
||||||
} # end if
|
} # end if
|
||||||
|
|
||||||
if ( $cascade ) {
|
if ( $cascade ) {
|
||||||
my $installed_version = ZM_VERSION;
|
# 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 $sql = 'UPDATE `Config` SET `Value` = ? WHERE `Name` = ?';
|
||||||
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
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() );
|
$sth->execute(ZM_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_CURR_VERSION') or die( "Can't execute: ".$sth->errstr() );
|
||||||
$sth->finish();
|
$sth->finish();
|
||||||
} else {
|
} else {
|
||||||
zmDbDisconnect();
|
zmDbDisconnect();
|
||||||
|
@ -930,41 +933,42 @@ if ( $version ) {
|
||||||
#my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
#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 $res = $sth->execute( ) or die( "Can't execute: ".$sth->errstr() );
|
||||||
#$sth->finish();
|
#$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();
|
zmDbDisconnect();
|
||||||
exit( 0 );
|
exit(0);
|
||||||
|
|
||||||
sub patchDB_using_do {
|
sub patchDB_using_do {
|
||||||
my ( $dbh, $version, $file ) = @_;
|
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;
|
$/ = undef;
|
||||||
my $sql = <$fh>;
|
my $sql = <$fh>;
|
||||||
close $fh;
|
close $fh;
|
||||||
if ( $sql ) {
|
if ( $sql ) {
|
||||||
$dbh->{'AutoCommit'} = 0;
|
$dbh->{AutoCommit} = 0;
|
||||||
$dbh->do($sql);
|
$dbh->do($sql);
|
||||||
if ( $dbh->errstr() ) {
|
if ( $dbh->errstr() ) {
|
||||||
$dbh->rollback();
|
$dbh->rollback();
|
||||||
die "Error: " . $dbh->errstr(). ". Rolled back.\n";
|
die 'Error: '.$dbh->errstr().". Rolled back.\n";
|
||||||
} # end if error
|
} # end if error
|
||||||
|
|
||||||
my $sql = "update Config set Value = ? where Name = 'ZM_DYN_DB_VERSION'";
|
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 $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 $res = $sth->execute($version) or die 'Can\'t execute: '.$sth->errstr();
|
||||||
$sth->finish();
|
$sth->finish();
|
||||||
|
|
||||||
$dbh->{'AutoCommit'} = 1;
|
$dbh->{AutoCommit} = 1;
|
||||||
} else {
|
} else {
|
||||||
Warning("Empty db update file at $file");
|
Warning("Empty db update file at $file");
|
||||||
}
|
}
|
||||||
}
|
} # end sub patchDB_using_do
|
||||||
|
|
||||||
sub patchDB {
|
sub patchDB {
|
||||||
my $dbh = shift;
|
my $dbh = shift;
|
||||||
my $version = shift;
|
my $version = shift;
|
||||||
|
|
||||||
|
|
||||||
my ( $host, $portOrSocket ) = ( $Config{ZM_DB_HOST} =~ /^([^:]+)(?::(.+))?$/ );
|
my ( $host, $portOrSocket ) = ( $Config{ZM_DB_HOST} =~ /^([^:]+)(?::(.+))?$/ );
|
||||||
my $command = 'mysql';
|
my $command = 'mysql';
|
||||||
if ( defined($portOrSocket) ) {
|
if ( defined($portOrSocket) ) {
|
||||||
|
@ -988,39 +992,38 @@ sub patchDB {
|
||||||
}
|
}
|
||||||
$command .= '/zm_update-'.$version.'.sql';
|
$command .= '/zm_update-'.$version.'.sql';
|
||||||
|
|
||||||
print( "Executing '$command'\n" ) if ( logDebugging() );
|
print("Executing '$command'\n") if logDebugging();
|
||||||
my $output = qx($command);
|
my $output = qx($command);
|
||||||
my $status = $? >> 8;
|
my $status = $? >> 8;
|
||||||
if ( $status || logDebugging() ) {
|
if ( $status || logDebugging() ) {
|
||||||
chomp( $output );
|
chomp($output);
|
||||||
print( "Output: $output\n" );
|
print("Output: $output\n");
|
||||||
}
|
}
|
||||||
if ( $status ) {
|
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 {
|
sub migratePasswords {
|
||||||
print ("Migratings passwords, if any...\n");
|
print ("Migratings passwords, if any...\n");
|
||||||
my $sql = "select * from Users";
|
my $sql = 'SELECT * FROM `Users`';
|
||||||
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
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 $res = $sth->execute() or die("Can't execute: ".$sth->errstr());
|
||||||
while( my $user = $sth->fetchrow_hashref() ) {
|
while( my $user = $sth->fetchrow_hashref() ) {
|
||||||
my $scheme = substr($user->{Password}, 0, 1);
|
my $scheme = substr($user->{Password}, 0, 1);
|
||||||
if ($scheme eq "*") {
|
if ($scheme eq '*') {
|
||||||
print ("-->".$user->{Username}. " password will be migrated\n");
|
print ('-->'.$user->{Username}." password will be migrated\n");
|
||||||
my $salt = Crypt::Eksblowfish::Bcrypt::en_base64(rand_bits(16*8));
|
my $salt = Crypt::Eksblowfish::Bcrypt::en_base64(rand_bits(16*8));
|
||||||
my $settings = '$2a$10$'.$salt;
|
my $settings = '$2a$10$'.$salt;
|
||||||
my $pass_hash = Crypt::Eksblowfish::Bcrypt::bcrypt($user->{Password},$settings);
|
my $pass_hash = Crypt::Eksblowfish::Bcrypt::bcrypt($user->{Password},$settings);
|
||||||
my $new_pass_hash = "-ZM-".$pass_hash;
|
my $new_pass_hash = '-ZM-'.$pass_hash;
|
||||||
$sql = "UPDATE Users SET PASSWORD=? WHERE Username=?";
|
$sql = 'UPDATE Users SET `Password`=? WHERE `Username`=?';
|
||||||
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
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() );
|
my $res = $sth->execute($new_pass_hash, $user->{Username}) or die("Can't execute: ".$sth->errstr());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} # end sub migratePasswords
|
||||||
|
|
||||||
sub migratePaths {
|
sub migratePaths {
|
||||||
|
|
||||||
|
|
|
@ -93,62 +93,54 @@ if ( $version ) {
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
die( 'No command given' ) unless( $command );
|
die 'No command given' unless $command;
|
||||||
die( 'No unit code given' )
|
die 'No unit code given'
|
||||||
unless( $unit_code || ($command =~ /(?:start|status|shutdown)/) );
|
unless( $unit_code || ($command =~ /(?:start|status|shutdown)/) );
|
||||||
|
|
||||||
if ( $command eq 'start' )
|
if ( $command eq 'start' ) {
|
||||||
{
|
|
||||||
X10Server::runServer();
|
X10Server::runServer();
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
socket( CLIENT, PF_UNIX, SOCK_STREAM, 0 )
|
socket(CLIENT, PF_UNIX, SOCK_STREAM, 0)
|
||||||
or Fatal( "Can't open socket: $!" );
|
or Fatal("Can't open socket: $!");
|
||||||
|
|
||||||
my $saddr = sockaddr_un( SOCK_FILE );
|
my $saddr = sockaddr_un(SOCK_FILE);
|
||||||
|
|
||||||
if ( !connect( CLIENT, $saddr ) )
|
if ( !connect(CLIENT, $saddr) ) {
|
||||||
{
|
|
||||||
# The server isn't there
|
# The server isn't there
|
||||||
print( "Unable to connect, starting server\n" );
|
print("Unable to connect, starting server\n");
|
||||||
close( CLIENT );
|
close(CLIENT);
|
||||||
|
|
||||||
if ( my $cpid = fork() )
|
if ( my $cpid = fork() ) {
|
||||||
{
|
|
||||||
# Parent process just sleep and fall through
|
# Parent process just sleep and fall through
|
||||||
sleep( 2 );
|
sleep(2);
|
||||||
logReinit();
|
logReinit();
|
||||||
socket( CLIENT, PF_UNIX, SOCK_STREAM, 0 )
|
socket(CLIENT, PF_UNIX, SOCK_STREAM, 0)
|
||||||
or Fatal( "Can't open socket: $!" );
|
or Fatal("Can't open socket: $!");
|
||||||
connect( CLIENT, $saddr )
|
connect(CLIENT, $saddr)
|
||||||
or Fatal( "Can't connect: $!" );
|
or Fatal("Can't connect: $!");
|
||||||
}
|
} elsif ( defined($cpid) ) {
|
||||||
elsif ( defined($cpid) )
|
|
||||||
{
|
|
||||||
setpgrp();
|
setpgrp();
|
||||||
|
|
||||||
logReinit();
|
logReinit();
|
||||||
X10Server::runServer();
|
X10Server::runServer();
|
||||||
}
|
} else {
|
||||||
else
|
Fatal("Can't fork: $!");
|
||||||
{
|
|
||||||
Fatal( "Can't fork: $!" );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
# The server is there, connect to it
|
# The server is there, connect to it
|
||||||
#print( "Writing commands\n" );
|
#print( "Writing commands\n" );
|
||||||
CLIENT->autoflush();
|
CLIENT->autoflush();
|
||||||
my $message = "$command";
|
my $message = $command;
|
||||||
$message .= ";$unit_code" if ( $unit_code );
|
$message .= ';'.$unit_code if $unit_code;
|
||||||
print( CLIENT $message );
|
print(CLIENT $message);
|
||||||
shutdown( CLIENT, 1 );
|
shutdown(CLIENT, 1);
|
||||||
while ( my $line = <CLIENT> )
|
while ( my $line = <CLIENT> ) {
|
||||||
{
|
chomp($line);
|
||||||
chomp( $line );
|
print("$line\n");
|
||||||
print( "$line\n" );
|
|
||||||
}
|
}
|
||||||
close( CLIENT );
|
close(CLIENT);
|
||||||
#print( "Finished writing, bye\n" );
|
#print( "Finished writing, bye\n" );
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
|
@ -178,73 +170,68 @@ our %monitor_hash;
|
||||||
our %device_hash;
|
our %device_hash;
|
||||||
our %pending_tasks;
|
our %pending_tasks;
|
||||||
|
|
||||||
sub runServer
|
sub runServer {
|
||||||
{
|
Info('X10 server starting');
|
||||||
Info( "X10 server starting\n" );
|
|
||||||
|
|
||||||
socket( SERVER, PF_UNIX, SOCK_STREAM, 0 )
|
socket(SERVER, PF_UNIX, SOCK_STREAM, 0)
|
||||||
or Fatal( "Can't open socket: $!" );
|
or Fatal("Can't open socket: $!");
|
||||||
unlink( main::SOCK_FILE );
|
unlink(main::SOCK_FILE);
|
||||||
my $saddr = sockaddr_un( main::SOCK_FILE );
|
my $saddr = sockaddr_un(main::SOCK_FILE);
|
||||||
bind( SERVER, $saddr ) or Fatal( "Can't bind: $!" );
|
bind(SERVER, $saddr) or Fatal("Can't bind: $!");
|
||||||
listen( SERVER, SOMAXCONN ) or Fatal( "Can't listen: $!" );
|
listen(SERVER, SOMAXCONN) or Fatal("Can't listen: $!");
|
||||||
|
|
||||||
$dbh = zmDbConnect();
|
$dbh = zmDbConnect();
|
||||||
|
|
||||||
$x10 = new X10::ActiveHome( port=>$Config{ZM_X10_DEVICE}, house_code=>$Config{ZM_X10_HOUSE_CODE}, debug=>0 );
|
$x10 = new X10::ActiveHome(
|
||||||
|
port=>$Config{ZM_X10_DEVICE},
|
||||||
|
house_code=>$Config{ZM_X10_HOUSE_CODE},
|
||||||
|
debug=>0
|
||||||
|
);
|
||||||
|
|
||||||
loadTasks();
|
loadTasks();
|
||||||
|
|
||||||
$x10->register_listener( \&x10listen );
|
$x10->register_listener(\&x10listen);
|
||||||
|
|
||||||
my $rin = '';
|
my $rin = '';
|
||||||
vec( $rin, fileno(SERVER),1) = 1;
|
vec($rin, fileno(SERVER),1) = 1;
|
||||||
vec( $rin, $x10->select_fds(),1) = 1;
|
vec($rin, $x10->select_fds(),1) = 1;
|
||||||
my $timeout = 0.2;
|
my $timeout = 0.2;
|
||||||
#print( 'F:'.fileno(SERVER)."\n" );
|
#print( 'F:'.fileno(SERVER)."\n" );
|
||||||
my $reload = undef;
|
my $reload = undef;
|
||||||
my $reload_count = 0;
|
my $reload_count = 0;
|
||||||
my $reload_limit = $Config{ZM_X10_DB_RELOAD_INTERVAL} / $timeout;
|
my $reload_limit = $Config{ZM_X10_DB_RELOAD_INTERVAL} / $timeout;
|
||||||
while( 1 )
|
while( 1 ) {
|
||||||
{
|
my $nfound = select(my $rout = $rin, undef, undef, $timeout);
|
||||||
my $nfound = select( my $rout = $rin, undef, undef, $timeout );
|
|
||||||
#print( "Off select, NF:$nfound, ER:$!\n" );
|
#print( "Off select, NF:$nfound, ER:$!\n" );
|
||||||
#print( vec( $rout, fileno(SERVER),1)."\n" );
|
#print( vec( $rout, fileno(SERVER),1)."\n" );
|
||||||
#print( vec( $rout, $x10->select_fds(),1)."\n" );
|
#print( vec( $rout, $x10->select_fds(),1)."\n" );
|
||||||
if ( $nfound > 0 )
|
if ( $nfound > 0 ) {
|
||||||
{
|
if ( vec($rout, fileno(SERVER),1) ) {
|
||||||
if ( vec( $rout, fileno(SERVER),1) )
|
my $paddr = accept(CLIENT, SERVER);
|
||||||
{
|
|
||||||
my $paddr = accept( CLIENT, SERVER );
|
|
||||||
my $message = <CLIENT>;
|
my $message = <CLIENT>;
|
||||||
|
|
||||||
my ( $command, $unit_code ) = split( /;/, $message );
|
my ($command, $unit_code) = split(';', $message);
|
||||||
|
|
||||||
my $device;
|
my $device;
|
||||||
if ( defined($unit_code) )
|
if ( defined($unit_code) ) {
|
||||||
{
|
if ( $unit_code < 1 || $unit_code > 16 ) {
|
||||||
if ( $unit_code < 1 || $unit_code > 16 )
|
dPrint(ZoneMinder::Logger::ERROR, "Invalid unit code '$unit_code'\n");
|
||||||
{
|
|
||||||
dPrint( ZoneMinder::Logger::ERROR, "Invalid unit code '$unit_code'\n" );
|
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
|
|
||||||
$device = $device_hash{$unit_code};
|
$device = $device_hash{$unit_code};
|
||||||
if ( !$device )
|
if ( !$device ) {
|
||||||
{
|
$device = $device_hash{$unit_code} = {
|
||||||
$device = $device_hash{$unit_code} = { appliance=>$x10->Appliance( unit_code=>$unit_code ),
|
appliance=>$x10->Appliance(unit_code=>$unit_code),
|
||||||
status=>'unknown'
|
status=>'unknown'
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
} # end if defined($unit_code)
|
||||||
|
|
||||||
my $result;
|
my $result;
|
||||||
if ( $command eq 'on' )
|
if ( $command eq 'on' ) {
|
||||||
{
|
|
||||||
$result = $device->{appliance}->on();
|
$result = $device->{appliance}->on();
|
||||||
}
|
} elsif ( $command eq 'off' ) {
|
||||||
elsif ( $command eq 'off' )
|
|
||||||
{
|
|
||||||
$result = $device->{appliance}->off();
|
$result = $device->{appliance}->off();
|
||||||
}
|
}
|
||||||
#elsif ( $command eq 'dim' )
|
#elsif ( $command eq 'dim' )
|
||||||
|
@ -255,528 +242,425 @@ sub runServer
|
||||||
#{
|
#{
|
||||||
#$result = $device->{appliance}->bright();
|
#$result = $device->{appliance}->bright();
|
||||||
#}
|
#}
|
||||||
elsif ( $command eq 'status' )
|
elsif ( $command eq 'status' ) {
|
||||||
{
|
if ( $device ) {
|
||||||
if ( $device )
|
dPrint(ZoneMinder::Logger::DEBUG, $unit_code.' '.$device->{status}."\n");
|
||||||
{
|
} else {
|
||||||
dPrint( ZoneMinder::Logger::DEBUG, $unit_code.' '.$device->{status}."\n" );
|
foreach my $unit_code ( sort( keys(%device_hash) ) ) {
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach my $unit_code ( sort( keys(%device_hash) ) )
|
|
||||||
{
|
|
||||||
my $device = $device_hash{$unit_code};
|
my $device = $device_hash{$unit_code};
|
||||||
dPrint( ZoneMinder::Logger::DEBUG, $unit_code.' '.$device->{status}."\n" );
|
dPrint(ZoneMinder::Logger::DEBUG, $unit_code.' '.$device->{status}."\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} elsif ( $command eq 'shutdown' ) {
|
||||||
elsif ( $command eq 'shutdown' )
|
|
||||||
{
|
|
||||||
last;
|
last;
|
||||||
|
} else {
|
||||||
|
dPrint(ZoneMinder::Logger::ERROR, "Invalid command '$command'\n");
|
||||||
}
|
}
|
||||||
else
|
if ( defined($result) ) {
|
||||||
{
|
# FIXME
|
||||||
dPrint( ZoneMinder::Logger::ERROR, "Invalid command '$command'\n" );
|
if ( 1 || $result ) {
|
||||||
}
|
|
||||||
if ( defined($result) )
|
|
||||||
{
|
|
||||||
if ( 1 || $result )
|
|
||||||
{
|
|
||||||
$device->{status} = uc($command);
|
$device->{status} = uc($command);
|
||||||
dPrint( ZoneMinder::Logger::DEBUG, $device->{appliance}->address()." $command, ok\n" );
|
dPrint(ZoneMinder::Logger::DEBUG, $device->{appliance}->address()." $command, ok\n");
|
||||||
#x10listen( new X10::Event( sprintf("%s %s", $device->{appliance}->address, uc($command) ) ) );
|
#x10listen( new X10::Event( sprintf("%s %s", $device->{appliance}->address, uc($command) ) ) );
|
||||||
|
} else {
|
||||||
|
dPrint(ZoneMinder::Logger::ERROR, $device->{appliance}->address()." $command, failed\n");
|
||||||
}
|
}
|
||||||
else
|
} # end if defined result
|
||||||
{
|
close(CLIENT);
|
||||||
dPrint( ZoneMinder::Logger::ERROR, $device->{appliance}->address()." $command, failed\n" );
|
} elsif ( vec($rout, $x10->select_fds(),1) ) {
|
||||||
}
|
|
||||||
}
|
|
||||||
close( CLIENT );
|
|
||||||
}
|
|
||||||
elsif ( vec( $rout, $x10->select_fds(),1) )
|
|
||||||
{
|
|
||||||
$x10->handle_input();
|
$x10->handle_input();
|
||||||
|
} else {
|
||||||
|
Fatal('Bogus descriptor');
|
||||||
}
|
}
|
||||||
else
|
} elsif ( $nfound < 0 ) {
|
||||||
{
|
if ( $! != EINTR ) {
|
||||||
Fatal( 'Bogus descriptor' );
|
Fatal("Can't select: $!");
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
elsif ( $nfound < 0 )
|
|
||||||
{
|
|
||||||
if ( $! != EINTR )
|
|
||||||
{
|
|
||||||
Fatal( "Can't select: $!" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#print( "Select timed out\n" );
|
#print( "Select timed out\n" );
|
||||||
# Check for state changes
|
# Check for state changes
|
||||||
foreach my $monitor_id ( sort(keys(%monitor_hash) ) )
|
foreach my $monitor_id ( sort(keys(%monitor_hash) ) ) {
|
||||||
{
|
|
||||||
my $monitor = $monitor_hash{$monitor_id};
|
my $monitor = $monitor_hash{$monitor_id};
|
||||||
my $state = zmGetMonitorState( $monitor );
|
my $state = zmGetMonitorState($monitor);
|
||||||
if ( !defined($state) )
|
if ( !defined($state) ) {
|
||||||
{
|
|
||||||
$reload = !undef;
|
$reload = !undef;
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
if ( defined( $monitor->{LastState} ) )
|
if ( defined( $monitor->{LastState} ) ) {
|
||||||
{
|
|
||||||
my $task_list;
|
my $task_list;
|
||||||
if ( ($state == STATE_ALARM || $state == STATE_ALERT)
|
if ( ($state == STATE_ALARM || $state == STATE_ALERT)
|
||||||
&& ($monitor->{LastState} == STATE_IDLE || $monitor->{LastState} == STATE_TAPE)
|
&& ($monitor->{LastState} == STATE_IDLE || $monitor->{LastState} == STATE_TAPE)
|
||||||
) # Gone into alarm state
|
) # Gone into alarm state
|
||||||
{
|
{
|
||||||
Debug( "Applying ON_list for $monitor_id\n" );
|
Debug("Applying ON_list for $monitor_id");
|
||||||
$task_list = $monitor->{'ON_list'};
|
$task_list = $monitor->{ON_list};
|
||||||
}
|
} elsif ( ($state == STATE_IDLE && $monitor->{LastState} != STATE_IDLE)
|
||||||
elsif ( ($state == STATE_IDLE && $monitor->{LastState} != STATE_IDLE)
|
|
||||||
|| ($state == STATE_TAPE && $monitor->{LastState} != STATE_TAPE)
|
|| ($state == STATE_TAPE && $monitor->{LastState} != STATE_TAPE)
|
||||||
) # Come out of alarm state
|
) # Come out of alarm state
|
||||||
{
|
{
|
||||||
Debug( "Applying OFF_list for $monitor_id\n" );
|
Debug("Applying OFF_list for $monitor_id");
|
||||||
$task_list = $monitor->{'OFF_list'};
|
$task_list = $monitor->{OFF_list};
|
||||||
}
|
|
||||||
if ( $task_list )
|
|
||||||
{
|
|
||||||
foreach my $task ( @$task_list )
|
|
||||||
{
|
|
||||||
processTask( $task );
|
|
||||||
}
|
}
|
||||||
|
if ( $task_list ) {
|
||||||
|
foreach my $task ( @$task_list ) {
|
||||||
|
processTask($task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} # end if defined laststate
|
||||||
$monitor->{LastState} = $state;
|
$monitor->{LastState} = $state;
|
||||||
}
|
} # end foreach monitor
|
||||||
|
|
||||||
# Check for pending tasks
|
# Check for pending tasks
|
||||||
my $now = time();
|
my $now = time();
|
||||||
foreach my $activation_time ( sort(keys(%pending_tasks) ) )
|
foreach my $activation_time ( sort(keys(%pending_tasks) ) ) {
|
||||||
{
|
|
||||||
last if ( $activation_time > $now );
|
last if ( $activation_time > $now );
|
||||||
my $pending_list = $pending_tasks{$activation_time};
|
my $pending_list = $pending_tasks{$activation_time};
|
||||||
foreach my $task ( @$pending_list )
|
foreach my $task ( @$pending_list ) {
|
||||||
{
|
processTask($task);
|
||||||
processTask( $task );
|
|
||||||
}
|
}
|
||||||
delete( $pending_tasks{$activation_time} );
|
delete $pending_tasks{$activation_time};
|
||||||
}
|
}
|
||||||
if ( $reload || ++$reload_count >= $reload_limit )
|
if ( $reload or (++$reload_count >= $reload_limit) ) {
|
||||||
{
|
|
||||||
loadTasks();
|
loadTasks();
|
||||||
$reload = undef;
|
$reload = undef;
|
||||||
$reload_count = 0;
|
$reload_count = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Info( "X10 server exiting\n" );
|
Info("X10 server exiting");
|
||||||
close( SERVER );
|
close(SERVER);
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
sub addToDeviceList
|
sub addToDeviceList {
|
||||||
{
|
|
||||||
my $unit_code = shift;
|
my $unit_code = shift;
|
||||||
my $event = shift;
|
my $event = shift;
|
||||||
my $monitor = shift;
|
my $monitor = shift;
|
||||||
my $function = shift;
|
my $function = shift;
|
||||||
my $limit = shift;
|
my $limit = shift;
|
||||||
|
|
||||||
Debug( "Adding to device list, uc:$unit_code, ev:$event, mo:"
|
Debug("Adding to device list, uc:$unit_code, ev:$event, mo:"
|
||||||
.$monitor->{Id}.", fu:$function, li:$limit\n"
|
.$monitor->{Id}.", fu:$function, li:$limit"
|
||||||
);
|
);
|
||||||
my $device = $device_hash{$unit_code};
|
my $device = $device_hash{$unit_code};
|
||||||
if ( !$device )
|
if ( !$device ) {
|
||||||
{
|
$device = $device_hash{$unit_code} = {
|
||||||
$device = $device_hash{$unit_code} = { appliance=>$x10->Appliance( unit_code=>$unit_code ),
|
appliance=>$x10->Appliance(unit_code=>$unit_code),
|
||||||
status=>'unknown'
|
status=>'unknown'
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
my $task = { type=>'device',
|
my $task = {
|
||||||
|
type=>'device',
|
||||||
monitor=>$monitor,
|
monitor=>$monitor,
|
||||||
address=>$device->{appliance}->address(),
|
address=>$device->{appliance}->address(),
|
||||||
function=>$function
|
function=>$function
|
||||||
};
|
};
|
||||||
if ( $limit )
|
|
||||||
{
|
if ( $limit ) {
|
||||||
$task->{limit} = $limit
|
$task->{limit} = $limit
|
||||||
}
|
}
|
||||||
|
|
||||||
my $task_list = $device->{$event.'_list'};
|
my $task_list = $device->{$event.'_list'};
|
||||||
if ( !$task_list )
|
if ( !$task_list ) {
|
||||||
{
|
|
||||||
$task_list = $device->{$event.'_list'} = [];
|
$task_list = $device->{$event.'_list'} = [];
|
||||||
}
|
}
|
||||||
push( @$task_list, $task );
|
push @$task_list, $task;
|
||||||
}
|
} # end sub addToDeviceList
|
||||||
|
|
||||||
sub addToMonitorList
|
sub addToMonitorList {
|
||||||
{
|
|
||||||
my $monitor = shift;
|
my $monitor = shift;
|
||||||
my $event = shift;
|
my $event = shift;
|
||||||
my $unit_code = shift;
|
my $unit_code = shift;
|
||||||
my $function = shift;
|
my $function = shift;
|
||||||
my $limit = shift;
|
my $limit = shift;
|
||||||
|
|
||||||
Debug( "Adding to monitor list, uc:$unit_code, ev:$event, mo:".$monitor->{Id}
|
Debug("Adding to monitor list, uc:$unit_code, ev:$event, mo:".$monitor->{Id}
|
||||||
.", fu:$function, li:$limit\n"
|
.", fu:$function, li:$limit"
|
||||||
);
|
);
|
||||||
my $device = $device_hash{$unit_code};
|
my $device = $device_hash{$unit_code};
|
||||||
if ( !$device )
|
if ( !$device ) {
|
||||||
{
|
$device = $device_hash{$unit_code} = {
|
||||||
$device = $device_hash{$unit_code} = { appliance=>$x10->Appliance( unit_code=>$unit_code ),
|
appliance=>$x10->Appliance(unit_code=>$unit_code),
|
||||||
status=>'unknown'
|
status=>'unknown'
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
my $task = { type=>'monitor',
|
my $task = {
|
||||||
|
type=>'monitor',
|
||||||
device=>$device,
|
device=>$device,
|
||||||
id=>$monitor->{Id},
|
id=>$monitor->{Id},
|
||||||
function=>$function
|
function=>$function
|
||||||
};
|
};
|
||||||
if ( $limit )
|
if ( $limit ) {
|
||||||
{
|
|
||||||
$task->{limit} = $limit;
|
$task->{limit} = $limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
my $task_list = $monitor->{$event.'_list'};
|
my $task_list = $monitor->{$event.'_list'};
|
||||||
if ( !$task_list )
|
if ( !$task_list ) {
|
||||||
{
|
|
||||||
$task_list = $monitor->{$event.'_list'} = [];
|
$task_list = $monitor->{$event.'_list'} = [];
|
||||||
}
|
}
|
||||||
push( @$task_list, $task );
|
push @$task_list, $task;
|
||||||
}
|
} # end sub addToMonitorList
|
||||||
|
|
||||||
sub loadTasks
|
sub loadTasks {
|
||||||
{
|
|
||||||
%monitor_hash = ();
|
%monitor_hash = ();
|
||||||
|
|
||||||
Debug( "Loading tasks\n" );
|
Debug('Loading tasks');
|
||||||
# Clear out all old device task lists
|
# Clear out all old device task lists
|
||||||
foreach my $unit_code ( sort( keys(%device_hash) ) )
|
foreach my $unit_code ( sort keys(%device_hash) ) {
|
||||||
{
|
|
||||||
my $device = $device_hash{$unit_code};
|
my $device = $device_hash{$unit_code};
|
||||||
$device->{ON_list} = [];
|
$device->{ON_list} = [];
|
||||||
$device->{OFF_list} = [];
|
$device->{OFF_list} = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
my $sql = "SELECT M.*,T.* from Monitors as M
|
my $sql = 'SELECT M.*,T.* FROM Monitors as M
|
||||||
INNER JOIN TriggersX10 as T on (M.Id = T.MonitorId)
|
INNER JOIN TriggersX10 as T on (M.Id = T.MonitorId)
|
||||||
WHERE find_in_set( M.Function, 'Modect,Record,Mocord,Nodect' )
|
WHERE find_in_set(M.`Function`, \'Modect,Record,Mocord,Nodect\')
|
||||||
AND M.Enabled = 1
|
AND M.`Enabled` = 1
|
||||||
AND find_IN_set( 'X10', M.Triggers )"
|
AND find_IN_set(\'X10\', M.Triggers)';
|
||||||
;
|
|
||||||
my $sth = $dbh->prepare_cached( $sql )
|
my $sth = $dbh->prepare_cached( $sql )
|
||||||
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
|
or Fatal("Can't prepare '$sql': ".$dbh->errstr());
|
||||||
my $res = $sth->execute()
|
my $res = $sth->execute()
|
||||||
or Fatal( "Can't execute: ".$sth->errstr() );
|
or Fatal("Can't execute: ".$sth->errstr());
|
||||||
while( my $monitor = $sth->fetchrow_hashref() )
|
while( my $monitor = $sth->fetchrow_hashref() ) {
|
||||||
{
|
# Check shared memory ok
|
||||||
# Check shared memory ok
|
if ( !zmMemVerify($monitor) ) {
|
||||||
if ( !zmMemVerify( $monitor ) ) {
|
zmMemInvalidate($monitor);
|
||||||
zmMemInvalidate( $monitor );
|
next;
|
||||||
next ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$monitor_hash{$monitor->{Id}} = $monitor;
|
$monitor_hash{$monitor->{Id}} = $monitor;
|
||||||
|
|
||||||
if ( $monitor->{Activation} )
|
if ( $monitor->{Activation} ) {
|
||||||
{
|
Debug("$monitor->{Name} has active string '$monitor->{Activation}'");
|
||||||
Debug( "$monitor->{Name} has active string '$monitor->{Activation}'\n" );
|
foreach my $code_string ( split(',', $monitor->{Activation}) ) {
|
||||||
foreach my $code_string ( split( /,/, $monitor->{Activation} ) )
|
|
||||||
{
|
|
||||||
#Debug( "Code string: $code_string\n" );
|
#Debug( "Code string: $code_string\n" );
|
||||||
my ( $invert, $unit_code, $modifier, $limit )
|
my ( $invert, $unit_code, $modifier, $limit )
|
||||||
= ( $code_string =~ /^([!~])?(\d+)(?:([+-])(\d+)?)?$/ );
|
= ( $code_string =~ /^([!~])?(\d+)(?:([+-])(\d+)?)?$/ );
|
||||||
$limit = 0 if ( !$limit );
|
$limit = 0 if !$limit;
|
||||||
if ( $unit_code )
|
if ( $unit_code ) {
|
||||||
{
|
if ( !$modifier || $modifier eq '+' ) {
|
||||||
if ( !$modifier || $modifier eq '+' )
|
|
||||||
{
|
|
||||||
addToDeviceList( $unit_code,
|
addToDeviceList( $unit_code,
|
||||||
'ON',
|
'ON',
|
||||||
$monitor,
|
$monitor,
|
||||||
!$invert ? 'start_active'
|
(!$invert ? 'start_active' : 'stop_active'),
|
||||||
: 'stop_active',
|
|
||||||
$limit
|
$limit
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if ( !$modifier || $modifier eq '-' )
|
if ( !$modifier || $modifier eq '-' ) {
|
||||||
{
|
|
||||||
addToDeviceList( $unit_code,
|
addToDeviceList( $unit_code,
|
||||||
'OFF',
|
'OFF',
|
||||||
$monitor,
|
$monitor,
|
||||||
!$invert ? 'stop_active'
|
(!$invert ? 'stop_active' : 'start_active'),
|
||||||
: 'start_active',
|
|
||||||
$limit
|
$limit
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
} # end if unit_code
|
||||||
|
} # end foreach code_string
|
||||||
}
|
}
|
||||||
}
|
if ( $monitor->{AlarmInput} ) {
|
||||||
}
|
Debug("$monitor->{Name} has alarm input string '$monitor->{AlarmInput}'");
|
||||||
if ( $monitor->{AlarmInput} )
|
foreach my $code_string ( split(',', $monitor->{AlarmInput}) ) {
|
||||||
{
|
|
||||||
Debug( "$monitor->{Name} has alarm input string '$monitor->{AlarmInput}'\n" );
|
|
||||||
foreach my $code_string ( split( /,/, $monitor->{AlarmInput} ) )
|
|
||||||
{
|
|
||||||
#Debug( "Code string: $code_string\n" );
|
#Debug( "Code string: $code_string\n" );
|
||||||
my ( $invert, $unit_code, $modifier, $limit )
|
my ( $invert, $unit_code, $modifier, $limit )
|
||||||
= ( $code_string =~ /^([!~])?(\d+)(?:([+-])(\d+)?)?$/ );
|
= ( $code_string =~ /^([!~])?(\d+)(?:([+-])(\d+)?)?$/ );
|
||||||
$limit = 0 if ( !$limit );
|
$limit = 0 if !$limit;
|
||||||
if ( $unit_code )
|
if ( $unit_code ) {
|
||||||
{
|
if ( !$modifier || $modifier eq '+' ) {
|
||||||
if ( !$modifier || $modifier eq '+' )
|
|
||||||
{
|
|
||||||
addToDeviceList( $unit_code,
|
addToDeviceList( $unit_code,
|
||||||
'ON',
|
'ON',
|
||||||
$monitor,
|
$monitor,
|
||||||
!$invert ? 'start_alarm'
|
(!$invert ? 'start_alarm' : 'stop_alarm'),
|
||||||
: 'stop_alarm',
|
|
||||||
$limit
|
$limit
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if ( !$modifier || $modifier eq '-' )
|
if ( !$modifier || $modifier eq '-' ) {
|
||||||
{
|
|
||||||
addToDeviceList( $unit_code,
|
addToDeviceList( $unit_code,
|
||||||
'OFF',
|
'OFF',
|
||||||
$monitor,
|
$monitor,
|
||||||
!$invert ? 'stop_alarm'
|
(!$invert ? 'stop_alarm' : 'start_alarm'),
|
||||||
: 'start_alarm',
|
|
||||||
$limit
|
$limit
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
} # end if unit_code
|
||||||
}
|
} # end foreach code_string
|
||||||
}
|
} # end if AlarmInput
|
||||||
if ( $monitor->{AlarmOutput} )
|
if ( $monitor->{AlarmOutput} ) {
|
||||||
{
|
Debug("$monitor->{Name} has alarm output string '$monitor->{AlarmOutput}'");
|
||||||
Debug( "$monitor->{Name} has alarm output string '$monitor->{AlarmOutput}'\n" );
|
foreach my $code_string ( split( ',', $monitor->{AlarmOutput} ) ) {
|
||||||
foreach my $code_string ( split( /,/, $monitor->{AlarmOutput} ) )
|
|
||||||
{
|
|
||||||
#Debug( "Code string: $code_string\n" );
|
#Debug( "Code string: $code_string\n" );
|
||||||
my ( $invert, $unit_code, $modifier, $limit )
|
my ( $invert, $unit_code, $modifier, $limit )
|
||||||
= ( $code_string =~ /^([!~])?(\d+)(?:([+-])(\d+)?)?$/ );
|
= ( $code_string =~ /^([!~])?(\d+)(?:([+-])(\d+)?)?$/ );
|
||||||
$limit = 0 if ( !$limit );
|
$limit = 0 if !$limit;
|
||||||
if ( $unit_code )
|
if ( $unit_code ) {
|
||||||
{
|
if ( !$modifier || $modifier eq '+' ) {
|
||||||
if ( !$modifier || $modifier eq '+' )
|
|
||||||
{
|
|
||||||
addToMonitorList( $monitor,
|
addToMonitorList( $monitor,
|
||||||
'ON',
|
'ON',
|
||||||
$unit_code,
|
$unit_code,
|
||||||
!$invert ? 'on'
|
(!$invert ? 'on' : 'off'),
|
||||||
: 'off',
|
|
||||||
$limit
|
$limit
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if ( !$modifier || $modifier eq '-' )
|
if ( !$modifier || $modifier eq '-' ) {
|
||||||
{
|
|
||||||
addToMonitorList( $monitor,
|
addToMonitorList( $monitor,
|
||||||
'OFF',
|
'OFF',
|
||||||
$unit_code,
|
$unit_code,
|
||||||
!$invert ? 'off'
|
(!$invert ? 'off' : 'on'),
|
||||||
: 'on',
|
|
||||||
$limit
|
$limit
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
} # end if unit_code
|
||||||
|
} # end foreach code_string
|
||||||
|
} # end if AlarmOutput
|
||||||
|
zmMemInvalidate($monitor);
|
||||||
}
|
}
|
||||||
}
|
} # end sub loadTasks
|
||||||
}
|
|
||||||
zmMemInvalidate( $monitor );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub addPendingTask
|
sub addPendingTask {
|
||||||
{
|
|
||||||
my $task = shift;
|
my $task = shift;
|
||||||
|
|
||||||
# Check whether we are just extending a previous pending task
|
# Check whether we are just extending a previous pending task
|
||||||
# and remove it if it's there
|
# and remove it if it's there
|
||||||
foreach my $activation_time ( sort(keys(%pending_tasks) ) )
|
foreach my $activation_time ( sort keys(%pending_tasks) ) {
|
||||||
{
|
|
||||||
my $pending_list = $pending_tasks{$activation_time};
|
my $pending_list = $pending_tasks{$activation_time};
|
||||||
my $new_pending_list = [];
|
my $new_pending_list = [];
|
||||||
foreach my $pending_task ( @$pending_list )
|
foreach my $pending_task ( @$pending_list ) {
|
||||||
{
|
if ( $task->{type} ne $pending_task->{type} ) {
|
||||||
if ( $task->{type} ne $pending_task->{type} )
|
|
||||||
{
|
|
||||||
push( @$new_pending_list, $pending_task )
|
push( @$new_pending_list, $pending_task )
|
||||||
}
|
} elsif ( $task->{type} eq 'device' ) {
|
||||||
elsif ( $task->{type} eq 'device' )
|
|
||||||
{
|
|
||||||
if (( $task->{monitor}->{Id} != $pending_task->{monitor}->{Id} )
|
if (( $task->{monitor}->{Id} != $pending_task->{monitor}->{Id} )
|
||||||
|| ( $task->{function} ne $pending_task->{function} ))
|
|| ( $task->{function} ne $pending_task->{function} ))
|
||||||
{
|
{
|
||||||
push( @$new_pending_list, $pending_task )
|
push @$new_pending_list, $pending_task;
|
||||||
}
|
}
|
||||||
}
|
} elsif ( $task->{type} eq 'monitor' ) {
|
||||||
elsif ( $task->{type} eq 'monitor' )
|
|
||||||
{
|
|
||||||
if (( $task->{device}->{appliance}->unit_code()
|
if (( $task->{device}->{appliance}->unit_code()
|
||||||
!= $pending_task->{device}->{appliance}->unit_code()
|
!= $pending_task->{device}->{appliance}->unit_code()
|
||||||
)
|
)
|
||||||
|| ( $task->{function} ne $pending_task->{function} )
|
|| ( $task->{function} ne $pending_task->{function} )
|
||||||
)
|
) {
|
||||||
{
|
push @$new_pending_list, $pending_task;
|
||||||
push( @$new_pending_list, $pending_task )
|
|
||||||
}
|
}
|
||||||
}
|
} # end switch task->type
|
||||||
}
|
} # end foreach pending_task
|
||||||
if ( @$new_pending_list )
|
|
||||||
{
|
if ( @$new_pending_list ) {
|
||||||
$pending_tasks{$activation_time} = $new_pending_list;
|
$pending_tasks{$activation_time} = $new_pending_list;
|
||||||
|
} else {
|
||||||
|
delete $pending_tasks{$activation_time};
|
||||||
}
|
}
|
||||||
else
|
} # end foreach activation_time
|
||||||
{
|
|
||||||
delete( $pending_tasks{$activation_time} );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
my $end_time = time() + $task->{limit};
|
my $end_time = time() + $task->{limit};
|
||||||
my $pending_list = $pending_tasks{$end_time};
|
my $pending_list = $pending_tasks{$end_time};
|
||||||
if ( !$pending_list )
|
if ( !$pending_list ) {
|
||||||
{
|
|
||||||
$pending_list = $pending_tasks{$end_time} = [];
|
$pending_list = $pending_tasks{$end_time} = [];
|
||||||
}
|
}
|
||||||
my $pending_task;
|
my $pending_task;
|
||||||
if ( $task->{type} eq 'device' )
|
if ( $task->{type} eq 'device' ) {
|
||||||
{
|
$pending_task = {
|
||||||
$pending_task = { type=>$task->{type},
|
type=>$task->{type},
|
||||||
monitor=>$task->{monitor},
|
monitor=>$task->{monitor},
|
||||||
function=>$task->{function}
|
function=>$task->{function}
|
||||||
};
|
};
|
||||||
$pending_task->{function} =~ s/start/stop/;
|
$pending_task->{function} =~ s/start/stop/;
|
||||||
}
|
} elsif ( $task->{type} eq 'monitor' ) {
|
||||||
elsif ( $task->{type} eq 'monitor' )
|
$pending_task = {
|
||||||
{
|
type=>$task->{type},
|
||||||
$pending_task = { type=>$task->{type},
|
|
||||||
device=>$task->{device},
|
device=>$task->{device},
|
||||||
function=>$task->{function}
|
function=>$task->{function}
|
||||||
};
|
};
|
||||||
$pending_task->{function} =~ s/on/off/;
|
$pending_task->{function} =~ s/on/off/;
|
||||||
}
|
}
|
||||||
push( @$pending_list, $pending_task );
|
push @$pending_list, $pending_task;
|
||||||
}
|
} # end sub addPendingTask
|
||||||
|
|
||||||
sub processTask
|
sub processTask {
|
||||||
{
|
|
||||||
my $task = shift;
|
my $task = shift;
|
||||||
|
|
||||||
if ( $task->{type} eq 'device' )
|
if ( $task->{type} eq 'device' ) {
|
||||||
{
|
|
||||||
my ( $instruction, $class ) = ( $task->{function} =~ /^(.+)_(.+)$/ );
|
my ( $instruction, $class ) = ( $task->{function} =~ /^(.+)_(.+)$/ );
|
||||||
|
|
||||||
if ( $class eq 'active' )
|
if ( $class eq 'active' ) {
|
||||||
{
|
if ( $instruction eq 'start' ) {
|
||||||
if ( $instruction eq 'start' )
|
zmMonitorEnable($task->{monitor});
|
||||||
{
|
if ( $task->{limit} ) {
|
||||||
zmMonitorEnable( $task->{monitor} );
|
addPendingTask($task);
|
||||||
if ( $task->{limit} )
|
|
||||||
{
|
|
||||||
addPendingTask( $task );
|
|
||||||
}
|
}
|
||||||
|
} elsif( $instruction eq 'stop' ) {
|
||||||
|
zmMonitorDisable($task->{monitor});
|
||||||
}
|
}
|
||||||
elsif( $instruction eq 'stop' )
|
} elsif( $class eq 'alarm' ) {
|
||||||
{
|
if ( $instruction eq 'start' ) {
|
||||||
zmMonitorDisable( $task->{monitor} );
|
zmTriggerEventOn(
|
||||||
}
|
$task->{monitor},
|
||||||
}
|
|
||||||
elsif( $class eq 'alarm' )
|
|
||||||
{
|
|
||||||
if ( $instruction eq 'start' )
|
|
||||||
{
|
|
||||||
zmTriggerEventOn( $task->{monitor},
|
|
||||||
0,
|
0,
|
||||||
main::CAUSE_STRING,
|
main::CAUSE_STRING,
|
||||||
$task->{address}
|
$task->{address}
|
||||||
);
|
);
|
||||||
if ( $task->{limit} )
|
if ( $task->{limit} ) {
|
||||||
{
|
addPendingTask($task);
|
||||||
addPendingTask( $task );
|
|
||||||
}
|
}
|
||||||
|
} elsif( $instruction eq 'stop' ) {
|
||||||
|
zmTriggerEventCancel($task->{monitor});
|
||||||
}
|
}
|
||||||
elsif( $instruction eq 'stop' )
|
} # end switch class
|
||||||
{
|
} elsif( $task->{type} eq 'monitor' ) {
|
||||||
zmTriggerEventCancel( $task->{monitor} );
|
if ( $task->{function} eq 'on' ) {
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
elsif( $task->{type} eq 'monitor' )
|
|
||||||
{
|
|
||||||
if ( $task->{function} eq 'on' )
|
|
||||||
{
|
|
||||||
$task->{device}->{appliance}->on();
|
$task->{device}->{appliance}->on();
|
||||||
if ( $task->{limit} )
|
if ( $task->{limit} ) {
|
||||||
{
|
addPendingTask($task);
|
||||||
addPendingTask( $task );
|
|
||||||
}
|
}
|
||||||
}
|
} elsif ( $task->{function} eq 'off' ) {
|
||||||
elsif ( $task->{function} eq 'off' )
|
|
||||||
{
|
|
||||||
$task->{device}->{appliance}->off();
|
$task->{device}->{appliance}->off();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub dPrint
|
sub dPrint {
|
||||||
{
|
|
||||||
my $dbg_level = shift;
|
my $dbg_level = shift;
|
||||||
if ( fileno(CLIENT) )
|
if ( fileno(CLIENT) ) {
|
||||||
{
|
|
||||||
print CLIENT @_
|
print CLIENT @_
|
||||||
}
|
}
|
||||||
if ( $dbg_level == ZoneMinder::Logger::DEBUG )
|
if ( $dbg_level == ZoneMinder::Logger::DEBUG ) {
|
||||||
{
|
Debug(@_);
|
||||||
Debug( @_ );
|
} elsif ( $dbg_level == ZoneMinder::Logger::INFO ) {
|
||||||
|
Info(@_);
|
||||||
|
} elsif ( $dbg_level == ZoneMinder::Logger::WARNING ) {
|
||||||
|
Warning(@_);
|
||||||
}
|
}
|
||||||
elsif ( $dbg_level == ZoneMinder::Logger::INFO )
|
elsif ( $dbg_level == ZoneMinder::Logger::ERROR ) {
|
||||||
{
|
|
||||||
Info( @_ );
|
|
||||||
}
|
|
||||||
elsif ( $dbg_level == ZoneMinder::Logger::WARNING )
|
|
||||||
{
|
|
||||||
Warning( @_ );
|
|
||||||
}
|
|
||||||
elsif ( $dbg_level == ZoneMinder::Logger::ERROR )
|
|
||||||
{
|
|
||||||
Error( @_ );
|
Error( @_ );
|
||||||
}
|
} elsif ( $dbg_level == ZoneMinder::Logger::FATAL ) {
|
||||||
elsif ( $dbg_level == ZoneMinder::Logger::FATAL )
|
|
||||||
{
|
|
||||||
Fatal( @_ );
|
Fatal( @_ );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub x10listen
|
sub x10listen {
|
||||||
{
|
foreach my $event ( @_ ) {
|
||||||
foreach my $event ( @_ )
|
|
||||||
{
|
|
||||||
#print( Data::Dumper( $_ )."\n" );
|
#print( Data::Dumper( $_ )."\n" );
|
||||||
if ( $event->house_code() eq $Config{ZM_X10_HOUSE_CODE} )
|
if ( $event->house_code() eq $Config{ZM_X10_HOUSE_CODE} ) {
|
||||||
{
|
|
||||||
my $unit_code = $event->unit_code();
|
my $unit_code = $event->unit_code();
|
||||||
my $device = $device_hash{$unit_code};
|
my $device = $device_hash{$unit_code};
|
||||||
if ( !$device )
|
if ( !$device ) {
|
||||||
{
|
$device = $device_hash{$unit_code} = {
|
||||||
$device = $device_hash{$unit_code} = { appliance=>$x10->Appliance( unit_code=>$unit_code ),
|
appliance=>$x10->Appliance(unit_code=>$unit_code),
|
||||||
status=>'unknown'
|
status=>'unknown'
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
next if ( $event->func() !~ /(?:ON|OFF)/ );
|
next if ( $event->func() !~ /(?:ON|OFF)/ );
|
||||||
$device->{status} = $event->func();
|
$device->{status} = $event->func();
|
||||||
my $task_list = $device->{$event->func().'_list'};
|
my $task_list = $device->{$event->func().'_list'};
|
||||||
if ( $task_list )
|
if ( $task_list ) {
|
||||||
{
|
foreach my $task ( @$task_list ) {
|
||||||
foreach my $task ( @$task_list )
|
processTask($task);
|
||||||
{
|
|
||||||
processTask( $task );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} # end if correct house code
|
||||||
|
Info('Got event - '.$event->as_string());
|
||||||
}
|
}
|
||||||
Info( "Got event - ".$event->as_string()."\n" );
|
} # end sub x10listen
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
__END__
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
configure_file(zm_config.h.in "${CMAKE_CURRENT_BINARY_DIR}/zm_config.h" @ONLY)
|
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)
|
# 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.
|
# 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
|
// Class used for storing a box, which is defined as a region
|
||||||
// defined by two coordinates
|
// defined by two coordinates
|
||||||
//
|
//
|
||||||
class Box
|
class Box {
|
||||||
{
|
|
||||||
private:
|
private:
|
||||||
Coord lo, hi;
|
Coord lo, hi;
|
||||||
Coord size;
|
Coord size;
|
||||||
|
|
||||||
public:
|
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 ) ) { }
|
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 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( 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 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 const Coord &Lo() const { return lo; }
|
||||||
inline int LoX() const { return( lo.X() ); }
|
inline int LoX() const { return lo.X(); }
|
||||||
inline int LoY() const { return( lo.Y() ); }
|
inline int LoY() const { return lo.Y(); }
|
||||||
inline const Coord &Hi() const { return( hi ); }
|
inline const Coord &Hi() const { return hi; }
|
||||||
inline int HiX() const { return( hi.X() ); }
|
inline int HiX() const { return hi.X(); }
|
||||||
inline int HiY() const { return( hi.Y() ); }
|
inline int HiY() const { return hi.Y(); }
|
||||||
inline const Coord &Size() const { return( size ); }
|
inline const Coord &Size() const { return size; }
|
||||||
inline int Width() const { return( size.X() ); }
|
inline int Width() const { return size.X(); }
|
||||||
inline int Height() const { return( size.Y() ); }
|
inline int Height() const { return size.Y(); }
|
||||||
inline int Area() const { return( size.X()*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_x = int(round(lo.X()+(size.X()/2.0)));
|
||||||
int mid_y = int(round(lo.Y()+(size.Y()/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
|
inline bool Inside( const Coord &coord ) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -35,7 +35,7 @@ class Camera;
|
||||||
//
|
//
|
||||||
class Camera {
|
class Camera {
|
||||||
protected:
|
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;
|
unsigned int monitor_id;
|
||||||
Monitor * monitor; // Null on instantiation, set as soon as possible.
|
Monitor * monitor; // Null on instantiation, set as soon as possible.
|
||||||
|
@ -68,6 +68,7 @@ public:
|
||||||
bool IsFfmpeg() const { return type == FFMPEG_SRC; }
|
bool IsFfmpeg() const { return type == FFMPEG_SRC; }
|
||||||
bool IsLibvlc() const { return type == LIBVLC_SRC; }
|
bool IsLibvlc() const { return type == LIBVLC_SRC; }
|
||||||
bool IscURL() const { return type == CURL_SRC; }
|
bool IscURL() const { return type == CURL_SRC; }
|
||||||
|
bool IsVNC() const { return type == VNC_SRC; }
|
||||||
unsigned int Width() const { return width; }
|
unsigned int Width() const { return width; }
|
||||||
unsigned int Height() const { return height; }
|
unsigned int Height() const { return height; }
|
||||||
unsigned int Colours() const { return colours; }
|
unsigned int Colours() const { return colours; }
|
||||||
|
|
|
@ -63,7 +63,9 @@ void zmLoadConfig() {
|
||||||
closedir(configSubFolder);
|
closedir(configSubFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
zmDbConnect();
|
if ( !zmDbConnect() ) {
|
||||||
|
Fatal("Can't connect to db. Can't continue.");
|
||||||
|
}
|
||||||
config.Load();
|
config.Load();
|
||||||
config.Assign();
|
config.Assign();
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,7 @@
|
||||||
//
|
//
|
||||||
// Class used for storing an x,y pair, i.e. a coordinate
|
// Class used for storing an x,y pair, i.e. a coordinate
|
||||||
//
|
//
|
||||||
class Coord
|
class Coord {
|
||||||
{
|
|
||||||
private:
|
private:
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
|
@ -44,8 +43,7 @@ public:
|
||||||
inline int &Y() { return( y ); }
|
inline int &Y() { return( y ); }
|
||||||
inline const int &Y() const { 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 );
|
Coord result( (coord1.x-coord2.x)+1, (coord1.y-coord2.y)+1 );
|
||||||
return( result );
|
return( result );
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,6 +108,23 @@ Event::Event(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
id = mysql_insert_id(&dbconn);
|
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();
|
db_mutex.unlock();
|
||||||
if ( untimedEvent ) {
|
if ( untimedEvent ) {
|
||||||
Warning("Event %d has zero time, setting to current", id);
|
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 ) {
|
if ( init_frame_id >= event_data->frame_count ) {
|
||||||
Error("Invalid frame id specified. %d > %d", 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_stream_time = event_data->start_time;
|
||||||
|
curr_frame_id = 1;
|
||||||
} else {
|
} else {
|
||||||
curr_stream_time = event_data->frames[init_frame_id-1].timestamp;
|
curr_stream_time = event_data->frames[init_frame_id-1].timestamp;
|
||||||
curr_frame_id = init_frame_id;
|
curr_frame_id = init_frame_id;
|
||||||
|
@ -373,18 +374,20 @@ void EventStream::processCommand(const CmdMsg *msg) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CMD_SLOWFWD :
|
case CMD_SLOWFWD :
|
||||||
Debug(1, "Got SLOW FWD command");
|
|
||||||
paused = true;
|
paused = true;
|
||||||
replay_rate = ZM_RATE_BASE;
|
replay_rate = ZM_RATE_BASE;
|
||||||
step = 1;
|
step = 1;
|
||||||
if ( (unsigned int)curr_frame_id < event_data->frame_count )
|
if ( (unsigned int)curr_frame_id < event_data->frame_count )
|
||||||
curr_frame_id += 1;
|
curr_frame_id += 1;
|
||||||
|
Debug(1, "Got SLOWFWD command new frame id %d", curr_frame_id);
|
||||||
break;
|
break;
|
||||||
case CMD_SLOWREV :
|
case CMD_SLOWREV :
|
||||||
Debug(1, "Got SLOW REV command");
|
|
||||||
paused = true;
|
paused = true;
|
||||||
replay_rate = ZM_RATE_BASE;
|
replay_rate = ZM_RATE_BASE;
|
||||||
step = -1;
|
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;
|
break;
|
||||||
case CMD_FASTREV :
|
case CMD_FASTREV :
|
||||||
Debug(1, "Got FAST REV command");
|
Debug(1, "Got FAST REV command");
|
||||||
|
@ -929,7 +932,7 @@ void EventStream::runStream() {
|
||||||
send_frame = true;
|
send_frame = true;
|
||||||
}
|
}
|
||||||
} else if ( step != 0 ) {
|
} 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
|
// We are paused and are just stepping forward or backward one frame
|
||||||
step = 0;
|
step = 0;
|
||||||
send_frame = true;
|
send_frame = true;
|
||||||
|
|
|
@ -20,9 +20,6 @@
|
||||||
#ifndef ZM_EVENTSTREAM_H
|
#ifndef ZM_EVENTSTREAM_H
|
||||||
#define ZM_EVENTSTREAM_H
|
#define ZM_EVENTSTREAM_H
|
||||||
|
|
||||||
#include <set>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
#include "zm_image.h"
|
#include "zm_image.h"
|
||||||
#include "zm_stream.h"
|
#include "zm_stream.h"
|
||||||
#include "zm_video.h"
|
#include "zm_video.h"
|
||||||
|
|
|
@ -321,6 +321,7 @@ void zm_dump_codecpar(const AVCodecParameters *par);
|
||||||
frame->pts \
|
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, \
|
#define zm_dump_video_frame(frame,text) Debug(1, "%s: format %d %s %dx%d linesize:%dx%d pts: %" PRId64, \
|
||||||
text, \
|
text, \
|
||||||
frame->format, \
|
frame->format, \
|
||||||
|
@ -331,6 +332,18 @@ void zm_dump_codecpar(const AVCodecParameters *par);
|
||||||
frame->pts \
|
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)
|
#if LIBAVCODEC_VERSION_CHECK(56, 8, 0, 60, 100)
|
||||||
#define zm_av_packet_unref( packet ) av_packet_unref( packet )
|
#define zm_av_packet_unref( packet ) av_packet_unref( packet )
|
||||||
#define zm_av_packet_ref( dst, src ) av_packet_ref( dst, src )
|
#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());
|
Error("Unable to allocate frame for %s", mPath.c_str());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
mFrame->width = width;
|
||||||
|
mFrame->height = height;
|
||||||
|
|
||||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||||
int pSize = av_image_get_buffer_size(imagePixFormat, width, height, 1);
|
int pSize = av_image_get_buffer_size(imagePixFormat, width, height, 1);
|
||||||
|
@ -630,20 +632,6 @@ int FfmpegCamera::OpenFfmpeg() {
|
||||||
return -1;
|
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
|
#else // HAVE_LIBSWSCALE
|
||||||
Fatal("You must compile ffmpeg with the --enable-swscale "
|
Fatal("You must compile ffmpeg with the --enable-swscale "
|
||||||
"option to use ffmpeg cameras");
|
"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.
|
// 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(
|
int size = av_image_fill_arrays(
|
||||||
output_frame->data, output_frame->linesize,
|
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 ) {
|
if ( size < 0 ) {
|
||||||
Error("Problem setting up data pointers into image %s",
|
Error("Problem setting up data pointers into image %s",
|
||||||
av_make_error_string(size).c_str());
|
av_make_error_string(size).c_str());
|
||||||
|
@ -1130,12 +1120,12 @@ int FfmpegCamera::transfer_to_image(
|
||||||
0, mVideoCodecContext->height,
|
0, mVideoCodecContext->height,
|
||||||
output_frame->data, output_frame->linesize);
|
output_frame->data, output_frame->linesize);
|
||||||
if ( ret < 0 ) {
|
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->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,
|
imagePixFormat,
|
||||||
av_get_pix_fmt_name(imagePixFormat),
|
av_get_pix_fmt_name(imagePixFormat),
|
||||||
output_frame->linesize,
|
output_frame->linesize[0], output_frame->linesize[1],
|
||||||
frameCount,
|
frameCount,
|
||||||
mVideoCodecContext->pix_fmt, av_get_pix_fmt_name(mVideoCodecContext->pix_fmt),
|
mVideoCodecContext->pix_fmt, av_get_pix_fmt_name(mVideoCodecContext->pix_fmt),
|
||||||
mVideoCodecContext->height,
|
mVideoCodecContext->height,
|
||||||
|
@ -1143,6 +1133,17 @@ int FfmpegCamera::transfer_to_image(
|
||||||
);
|
);
|
||||||
return -1;
|
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
|
#else // HAVE_LIBSWSCALE
|
||||||
Fatal("You must compile ffmpeg with the --enable-swscale "
|
Fatal("You must compile ffmpeg with the --enable-swscale "
|
||||||
"option to use ffmpeg cameras");
|
"option to use ffmpeg cameras");
|
||||||
|
|
|
@ -145,8 +145,12 @@ AVFrame *FFmpeg_Input::get_frame(int stream_id) {
|
||||||
av_frame_free(&frame);
|
av_frame_free(&frame);
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
|
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");
|
zm_dump_frame(frame, "resulting frame");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
frameComplete = 1;
|
frameComplete = 1;
|
||||||
} // end if it's the right stream
|
} // end if it's the right stream
|
||||||
|
|
|
@ -167,8 +167,10 @@ Image::Image( const AVFrame *frame ) {
|
||||||
width = frame->width;
|
width = frame->width;
|
||||||
height = frame->height;
|
height = frame->height;
|
||||||
pixels = width*height;
|
pixels = width*height;
|
||||||
|
|
||||||
colours = ZM_COLOUR_RGB32;
|
colours = ZM_COLOUR_RGB32;
|
||||||
subpixelorder = ZM_SUBPIX_ORDER_RGBA;
|
subpixelorder = ZM_SUBPIX_ORDER_RGBA;
|
||||||
|
|
||||||
size = pixels*colours;
|
size = pixels*colours;
|
||||||
buffer = 0;
|
buffer = 0;
|
||||||
holdbuffer = 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 ZM_HAS_V4L2
|
||||||
if ( v4l_version == 2 ) {
|
if ( v4l_version == 2 ) {
|
||||||
switch( palette ) {
|
switch ( palette ) {
|
||||||
#if defined(V4L2_PIX_FMT_RGB444) && defined(AV_PIX_FMT_RGB444)
|
#if defined(V4L2_PIX_FMT_RGB444) && defined(AV_PIX_FMT_RGB444)
|
||||||
case V4L2_PIX_FMT_RGB444 :
|
case V4L2_PIX_FMT_RGB444 :
|
||||||
pixFormat = AV_PIX_FMT_RGB444;
|
pixFormat = AV_PIX_FMT_RGB444;
|
||||||
|
@ -745,12 +745,12 @@ void LocalCamera::Initialise() {
|
||||||
|
|
||||||
Debug(4,
|
Debug(4,
|
||||||
" v4l2_data.fmt.type = %08x\n"
|
" v4l2_data.fmt.type = %08x\n"
|
||||||
" v4l2_data.fmt.fmt.pix.width = %08x\n"
|
" v4l2_data.fmt.fmt.pix.width = %d\n"
|
||||||
" v4l2_data.fmt.fmt.pix.height = %08x\n"
|
" v4l2_data.fmt.fmt.pix.height = %d\n"
|
||||||
" v4l2_data.fmt.fmt.pix.pixelformat = %08x\n"
|
" v4l2_data.fmt.fmt.pix.pixelformat = %08x\n"
|
||||||
" v4l2_data.fmt.fmt.pix.field = %08x\n"
|
" v4l2_data.fmt.fmt.pix.field = %08x\n"
|
||||||
" v4l2_data.fmt.fmt.pix.bytesperline = %08x\n"
|
" v4l2_data.fmt.fmt.pix.bytesperline = %d\n"
|
||||||
" v4l2_data.fmt.fmt.pix.sizeimage = %08x\n"
|
" v4l2_data.fmt.fmt.pix.sizeimage = %d\n"
|
||||||
" v4l2_data.fmt.fmt.pix.colorspace = %08x\n"
|
" v4l2_data.fmt.fmt.pix.colorspace = %08x\n"
|
||||||
" v4l2_data.fmt.fmt.pix.priv = %08x\n"
|
" v4l2_data.fmt.fmt.pix.priv = %08x\n"
|
||||||
, v4l2_data.fmt.type
|
, v4l2_data.fmt.type
|
||||||
|
@ -788,12 +788,12 @@ void LocalCamera::Initialise() {
|
||||||
/* Note VIDIOC_S_FMT may change width and height. */
|
/* Note VIDIOC_S_FMT may change width and height. */
|
||||||
Debug(4,
|
Debug(4,
|
||||||
" v4l2_data.fmt.type = %08x\n"
|
" v4l2_data.fmt.type = %08x\n"
|
||||||
" v4l2_data.fmt.fmt.pix.width = %08x\n"
|
" v4l2_data.fmt.fmt.pix.width = %d\n"
|
||||||
" v4l2_data.fmt.fmt.pix.height = %08x\n"
|
" v4l2_data.fmt.fmt.pix.height = %d\n"
|
||||||
" v4l2_data.fmt.fmt.pix.pixelformat = %08x\n"
|
" v4l2_data.fmt.fmt.pix.pixelformat = %08x\n"
|
||||||
" v4l2_data.fmt.fmt.pix.field = %08x\n"
|
" v4l2_data.fmt.fmt.pix.field = %08x\n"
|
||||||
" v4l2_data.fmt.fmt.pix.bytesperline = %08x\n"
|
" v4l2_data.fmt.fmt.pix.bytesperline = %d\n"
|
||||||
" v4l2_data.fmt.fmt.pix.sizeimage = %08x\n"
|
" v4l2_data.fmt.fmt.pix.sizeimage = %d\n"
|
||||||
" v4l2_data.fmt.fmt.pix.colorspace = %08x\n"
|
" v4l2_data.fmt.fmt.pix.colorspace = %08x\n"
|
||||||
" v4l2_data.fmt.fmt.pix.priv = %08x\n"
|
" v4l2_data.fmt.fmt.pix.priv = %08x\n"
|
||||||
, v4l2_data.fmt.type
|
, v4l2_data.fmt.type
|
||||||
|
|
|
@ -536,8 +536,11 @@ void Logger::logPrint(bool hex, const char * const filepath, const int line, con
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
if ( level <= mFileLevel ) {
|
if ( level <= mFileLevel ) {
|
||||||
if ( !mLogFileFP )
|
if ( !mLogFileFP ) {
|
||||||
|
log_mutex.unlock();
|
||||||
openFile();
|
openFile();
|
||||||
|
log_mutex.lock();
|
||||||
|
}
|
||||||
if ( mLogFileFP ) {
|
if ( mLogFileFP ) {
|
||||||
fputs(logString, mLogFileFP);
|
fputs(logString, mLogFileFP);
|
||||||
if ( mFlush )
|
if ( mFlush )
|
||||||
|
|
|
@ -51,6 +51,9 @@
|
||||||
#if HAVE_LIBCURL
|
#if HAVE_LIBCURL
|
||||||
#include "zm_curl_camera.h"
|
#include "zm_curl_camera.h"
|
||||||
#endif // HAVE_LIBCURL
|
#endif // HAVE_LIBCURL
|
||||||
|
#if HAVE_LIBVNC
|
||||||
|
#include "zm_libvnc_camera.h"
|
||||||
|
#endif // HAVE_LIBVNC
|
||||||
|
|
||||||
#if ZM_MEM_MAPPED
|
#if ZM_MEM_MAPPED
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
@ -89,6 +92,7 @@ std::string CameraType_Strings[] = {
|
||||||
"Ffmpeg",
|
"Ffmpeg",
|
||||||
"LibVLC",
|
"LibVLC",
|
||||||
"CURL",
|
"CURL",
|
||||||
|
"VNC",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -2332,6 +2336,27 @@ Monitor *Monitor::Load(MYSQL_ROW dbrow, bool load_zones, Purpose purpose) {
|
||||||
#else // HAVE_LIBCURL
|
#else // HAVE_LIBCURL
|
||||||
Fatal("You must have libcurl installed to use ffmpeg cameras for monitor %d", id);
|
Fatal("You must have libcurl installed to use ffmpeg cameras for monitor %d", id);
|
||||||
#endif // HAVE_LIBCURL
|
#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 {
|
} else {
|
||||||
Fatal("Bogus monitor type '%s' for monitor %d", type.c_str(), id);
|
Fatal("Bogus monitor type '%s' for monitor %d", type.c_str(), id);
|
||||||
} // end if type
|
} // end if type
|
||||||
|
|
|
@ -75,6 +75,7 @@ public:
|
||||||
FFMPEG,
|
FFMPEG,
|
||||||
LIBVLC,
|
LIBVLC,
|
||||||
CURL,
|
CURL,
|
||||||
|
VNC,
|
||||||
} CameraType;
|
} CameraType;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
|
@ -26,11 +26,9 @@
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Polygon::calcArea()
|
void Polygon::calcArea() {
|
||||||
{
|
|
||||||
double float_area = 0.0L;
|
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;
|
double trap_area = ((coords[i].X()-coords[j].X())*((coords[i].Y()+coords[j].Y())))/2.0L;
|
||||||
float_area += trap_area;
|
float_area += trap_area;
|
||||||
//printf( "%.2f (%.2f)\n", 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));
|
area = (int)round(fabs(float_area));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Polygon::calcCentre()
|
void Polygon::calcCentre() {
|
||||||
{
|
|
||||||
if ( !area && n_coords )
|
if ( !area && n_coords )
|
||||||
calcArea();
|
calcArea();
|
||||||
double float_x = 0.0L, float_y = 0.0L;
|
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_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)));
|
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) );
|
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];
|
coords = new Coord[n_coords];
|
||||||
|
|
||||||
int min_x = -1;
|
int min_x = -1;
|
||||||
int max_x = -1;
|
int max_x = -1;
|
||||||
int min_y = -1;
|
int min_y = -1;
|
||||||
int max_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];
|
coords[i] = p_coords[i];
|
||||||
if ( min_x == -1 || coords[i].X() < min_x )
|
if ( min_x == -1 || coords[i].X() < min_x )
|
||||||
min_x = coords[i].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();
|
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];
|
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];
|
coords[i] = p_polygon.coords[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Polygon &Polygon::operator=( const Polygon &p_polygon )
|
Polygon &Polygon::operator=( const Polygon &p_polygon ) {
|
||||||
{
|
if ( n_coords < p_polygon.n_coords ) {
|
||||||
if ( n_coords < p_polygon.n_coords )
|
|
||||||
{
|
|
||||||
delete[] coords;
|
delete[] coords;
|
||||||
coords = new Coord[p_polygon.n_coords];
|
coords = new Coord[p_polygon.n_coords];
|
||||||
}
|
}
|
||||||
n_coords = 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];
|
coords[i] = p_polygon.coords[i];
|
||||||
}
|
}
|
||||||
extent = p_polygon.extent;
|
extent = p_polygon.extent;
|
||||||
area = p_polygon.area;
|
area = p_polygon.area;
|
||||||
centre = p_polygon.centre;
|
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;
|
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()) )
|
if ( (((coords[i].Y() <= coord.Y()) && (coord.Y() < coords[j].Y()) )
|
||||||
|| ((coords[j].Y() <= coord.Y()) && (coord.Y() < coords[i].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()))
|
&& (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;
|
inside = !inside;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return( inside );
|
return inside;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,13 +41,13 @@ protected:
|
||||||
static int CompareYX( const void *p1, const void *p2 ) {
|
static int CompareYX( const void *p1, const void *p2 ) {
|
||||||
const Edge *e1 = reinterpret_cast<const Edge *>(p1), *e2 = reinterpret_cast<const Edge *>(p2);
|
const Edge *e1 = reinterpret_cast<const Edge *>(p1), *e2 = reinterpret_cast<const Edge *>(p2);
|
||||||
if ( e1->min_y == e2->min_y )
|
if ( e1->min_y == e2->min_y )
|
||||||
return( int(e1->min_x - e2->min_x) );
|
return int(e1->min_x - e2->min_x);
|
||||||
else
|
else
|
||||||
return( int(e1->min_y - e2->min_y) );
|
return int(e1->min_y - e2->min_y);
|
||||||
}
|
}
|
||||||
static int CompareX( const void *p1, const void *p2 ) {
|
static int CompareX( const void *p1, const void *p2 ) {
|
||||||
const Edge *e1 = reinterpret_cast<const Edge *>(p1), *e2 = reinterpret_cast<const Edge *>(p2);
|
const Edge *e1 = reinterpret_cast<const Edge *>(p1), *e2 = reinterpret_cast<const Edge *>(p2);
|
||||||
return( int(e1->min_x - e2->min_x) );
|
return int(e1->min_x - e2->min_x);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -83,32 +83,32 @@ protected:
|
||||||
void calcCentre();
|
void calcCentre();
|
||||||
|
|
||||||
public:
|
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(int p_n_coords, const Coord *p_coords);
|
||||||
Polygon( const Polygon &p_polygon );
|
Polygon(const Polygon &p_polygon);
|
||||||
~Polygon() {
|
~Polygon() {
|
||||||
delete[] coords;
|
delete[] coords;
|
||||||
}
|
}
|
||||||
|
|
||||||
Polygon &operator=( const Polygon &p_polygon );
|
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 {
|
inline const Coord &getCoord( int index ) const {
|
||||||
return( coords[index] );
|
return coords[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const Box &Extent() const { return( extent ); }
|
inline const Box &Extent() const { return extent; }
|
||||||
inline int LoX() const { return( extent.LoX() ); }
|
inline int LoX() const { return extent.LoX(); }
|
||||||
inline int HiX() const { return( extent.HiX() ); }
|
inline int HiX() const { return extent.HiX(); }
|
||||||
inline int LoY() const { return( extent.LoY() ); }
|
inline int LoY() const { return extent.LoY(); }
|
||||||
inline int HiY() const { return( extent.HiY() ); }
|
inline int HiY() const { return extent.HiY(); }
|
||||||
inline int Width() const { return( extent.Width() ); }
|
inline int Width() const { return extent.Width(); }
|
||||||
inline int Height() const { return( extent.Height() ); }
|
inline int Height() const { return extent.Height(); }
|
||||||
|
|
||||||
inline int Area() const { return( area ); }
|
inline int Area() const { return area; }
|
||||||
inline const Coord &Centre() const {
|
inline const Coord &Centre() const {
|
||||||
return( centre );
|
return centre;
|
||||||
}
|
}
|
||||||
bool isInside( const Coord &coord ) const;
|
bool isInside( const Coord &coord ) const;
|
||||||
};
|
};
|
||||||
|
|
|
@ -234,7 +234,7 @@ int RemoteCameraHttp::ReadData( Buffer &buffer, unsigned int bytes_expected ) {
|
||||||
} else {
|
} else {
|
||||||
if ( ioctl( sd, FIONREAD, &total_bytes_to_read ) < 0 ) {
|
if ( ioctl( sd, FIONREAD, &total_bytes_to_read ) < 0 ) {
|
||||||
Error( "Can't ioctl(): %s", strerror(errno) );
|
Error( "Can't ioctl(): %s", strerror(errno) );
|
||||||
return( -1 );
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( total_bytes_to_read == 0 ) {
|
if ( total_bytes_to_read == 0 ) {
|
||||||
|
@ -242,20 +242,20 @@ int RemoteCameraHttp::ReadData( Buffer &buffer, unsigned int bytes_expected ) {
|
||||||
int error = 0;
|
int error = 0;
|
||||||
socklen_t len = sizeof (error);
|
socklen_t len = sizeof (error);
|
||||||
int retval = getsockopt( sd, SOL_SOCKET, SO_ERROR, &error, &len );
|
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) );
|
Debug( 1, "error getting socket error code %s", strerror(retval) );
|
||||||
}
|
}
|
||||||
if (error != 0) {
|
if ( error != 0 ) {
|
||||||
return -1;
|
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.
|
// 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
|
// 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.
|
// 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.
|
//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.
|
// 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;
|
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 RemoteCameraHttp::GetResponse() {
|
||||||
int buffer_len;
|
int buffer_len;
|
||||||
#if HAVE_LIBPCRE
|
#if HAVE_LIBPCRE
|
||||||
|
@ -314,9 +326,7 @@ int RemoteCameraHttp::GetResponse() {
|
||||||
switch( state ) {
|
switch( state ) {
|
||||||
case HEADER :
|
case HEADER :
|
||||||
{
|
{
|
||||||
while ( !( buffer_len = ReadData(buffer) ) && !zm_terminate ) {
|
buffer_len = GetData();
|
||||||
Debug(4, "Timeout waiting for REGEXP HEADER");
|
|
||||||
}
|
|
||||||
if ( buffer_len < 0 ) {
|
if ( buffer_len < 0 ) {
|
||||||
Error("Unable to read header data");
|
Error("Unable to read header data");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -478,9 +488,7 @@ int RemoteCameraHttp::GetResponse() {
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug( 3, "Unable to extract subheader from stream, retrying" );
|
Debug( 3, "Unable to extract subheader from stream, retrying" );
|
||||||
while ( !( buffer_len = ReadData(buffer) ) && !zm_terminate ) {
|
buffer_len = GetData();
|
||||||
Debug(4, "Timeout waiting to extract subheader");
|
|
||||||
}
|
|
||||||
if ( buffer_len < 0 ) {
|
if ( buffer_len < 0 ) {
|
||||||
Error( "Unable to extract subheader data" );
|
Error( "Unable to extract subheader data" );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
@ -521,7 +529,7 @@ int RemoteCameraHttp::GetResponse() {
|
||||||
while ( ((long)buffer.size() < content_length ) && ! zm_terminate )
|
while ( ((long)buffer.size() < content_length ) && ! zm_terminate )
|
||||||
{
|
{
|
||||||
Debug(3, "Need more data buffer %d < content length %d", buffer.size(), content_length );
|
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 ) {
|
if ( bytes_read < 0 ) {
|
||||||
Error( "Unable to read content" );
|
Error( "Unable to read content" );
|
||||||
|
@ -535,9 +543,7 @@ int RemoteCameraHttp::GetResponse() {
|
||||||
{
|
{
|
||||||
while ( !content_length )
|
while ( !content_length )
|
||||||
{
|
{
|
||||||
while ( !( buffer_len = ReadData(buffer) ) && !zm_terminate ) {
|
buffer_len = GetData();
|
||||||
Debug(4, "Timeout waiting for content");
|
|
||||||
}
|
|
||||||
if ( buffer_len < 0 ) {
|
if ( buffer_len < 0 ) {
|
||||||
Error( "Unable to read content" );
|
Error( "Unable to read content" );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
@ -652,9 +658,7 @@ int RemoteCameraHttp::GetResponse() {
|
||||||
}
|
}
|
||||||
case HEADERCONT :
|
case HEADERCONT :
|
||||||
{
|
{
|
||||||
while ( !( buffer_len = ReadData(buffer) ) && !zm_terminate ) {
|
buffer_len = GetData();
|
||||||
Debug(1, "Timeout waiting for HEADERCONT");
|
|
||||||
}
|
|
||||||
if ( buffer_len < 0 ) {
|
if ( buffer_len < 0 ) {
|
||||||
Error("Unable to read header");
|
Error("Unable to read header");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -939,9 +943,7 @@ int RemoteCameraHttp::GetResponse() {
|
||||||
state = CONTENT;
|
state = CONTENT;
|
||||||
} else {
|
} else {
|
||||||
Debug( 3, "Unable to extract subheader from stream, retrying" );
|
Debug( 3, "Unable to extract subheader from stream, retrying" );
|
||||||
while ( !( buffer_len = ReadData(buffer) ) &&!zm_terminate ) {
|
buffer_len = GetData();
|
||||||
Debug(1, "Timeout waiting to extra subheader non regexp");
|
|
||||||
}
|
|
||||||
if ( buffer_len < 0 ) {
|
if ( buffer_len < 0 ) {
|
||||||
Error( "Unable to read subheader" );
|
Error( "Unable to read subheader" );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
@ -981,7 +983,7 @@ int RemoteCameraHttp::GetResponse() {
|
||||||
if ( content_length ) {
|
if ( content_length ) {
|
||||||
while ( ( (long)buffer.size() < content_length ) && ! zm_terminate ) {
|
while ( ( (long)buffer.size() < content_length ) && ! zm_terminate ) {
|
||||||
Debug(4, "getting more data");
|
Debug(4, "getting more data");
|
||||||
int bytes_read = ReadData(buffer);
|
int bytes_read = GetData();
|
||||||
if ( bytes_read < 0 ) {
|
if ( bytes_read < 0 ) {
|
||||||
Error("Unable to read content");
|
Error("Unable to read content");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -994,8 +996,7 @@ int RemoteCameraHttp::GetResponse() {
|
||||||
while ( !content_length && !zm_terminate ) {
|
while ( !content_length && !zm_terminate ) {
|
||||||
Debug(4, "!content_length, ReadData");
|
Debug(4, "!content_length, ReadData");
|
||||||
buffer_len = ReadData( buffer );
|
buffer_len = ReadData( buffer );
|
||||||
if ( buffer_len < 0 )
|
if ( buffer_len < 0 ) {
|
||||||
{
|
|
||||||
Error( "Unable to read content" );
|
Error( "Unable to read content" );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@ public:
|
||||||
int Disconnect();
|
int Disconnect();
|
||||||
int SendRequest();
|
int SendRequest();
|
||||||
int ReadData( Buffer &buffer, unsigned int bytes_expected=0 );
|
int ReadData( Buffer &buffer, unsigned int bytes_expected=0 );
|
||||||
|
int GetData();
|
||||||
int GetResponse();
|
int GetResponse();
|
||||||
int PreCapture();
|
int PreCapture();
|
||||||
int Capture( Image &image );
|
int Capture( Image &image );
|
||||||
|
|
|
@ -84,7 +84,7 @@ int SWScale::SetDefaults(enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf,
|
||||||
return 0;
|
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 */
|
/* Parameter checking */
|
||||||
if(in_buffer == NULL || out_buffer == NULL) {
|
if(in_buffer == NULL || out_buffer == NULL) {
|
||||||
Error("NULL Input or output buffer");
|
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");
|
// Error("Invalid input or output pixel formats");
|
||||||
// return -2;
|
// return -2;
|
||||||
// }
|
// }
|
||||||
if (!width || !height) {
|
if (!width || !height || !new_height || !new_width) {
|
||||||
Error("Invalid width or height");
|
Error("Invalid width or height");
|
||||||
return -3;
|
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 */
|
/* Check the buffer sizes */
|
||||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
#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
|
#else
|
||||||
size_t insize = avpicture_get_size(in_pf, width, height);
|
size_t insize = avpicture_get_size(in_pf, width, height);
|
||||||
#endif
|
#endif
|
||||||
|
@ -120,9 +120,9 @@ int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint
|
||||||
return -4;
|
return -4;
|
||||||
}
|
}
|
||||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
#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
|
#else
|
||||||
size_t outsize = avpicture_get_size(out_pf, width, height);
|
size_t outsize = avpicture_get_size(out_pf, new_width, new_height);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(outsize < out_buffer_size) {
|
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 */
|
/* 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) {
|
if(swscale_ctx == NULL) {
|
||||||
Error("Failed getting swscale context");
|
Error("Failed getting swscale context");
|
||||||
return -6;
|
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 LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||||
if (av_image_fill_arrays(output_avframe->data, output_avframe->linesize,
|
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
|
#else
|
||||||
if (avpicture_fill((AVPicture*) output_avframe, out_buffer, out_pf, width,
|
if (avpicture_fill((AVPicture*) output_avframe, out_buffer, out_pf, new_width,
|
||||||
height) <= 0) {
|
new_height) <= 0) {
|
||||||
#endif
|
#endif
|
||||||
Error("Failed filling output frame with output buffer");
|
Error("Failed filling output frame with output buffer");
|
||||||
return -8;
|
return -8;
|
||||||
|
@ -168,6 +168,10 @@ int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint
|
||||||
return 0;
|
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) {
|
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) {
|
if(img->Width() != width) {
|
||||||
Error("Source image width differs. Source: %d Output: %d",img->Width(), width);
|
Error("Source image width differs. Source: %d Output: %d",img->Width(), width);
|
||||||
|
|
|
@ -16,6 +16,7 @@ class SWScale {
|
||||||
int ConvertDefaults(const uint8_t* in_buffer, const size_t in_buffer_size, 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 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);
|
||||||
|
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:
|
protected:
|
||||||
bool gotdefaults;
|
bool gotdefaults;
|
||||||
|
|
159
src/zm_user.cpp
159
src/zm_user.cpp
|
@ -26,6 +26,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#if HAVE_GNUTLS_GNUTLS_H
|
#if HAVE_GNUTLS_GNUTLS_H
|
||||||
#include <gnutls/gnutls.h>
|
#include <gnutls/gnutls.h>
|
||||||
|
@ -35,7 +36,7 @@
|
||||||
#include <gcrypt.h>
|
#include <gcrypt.h>
|
||||||
#elif HAVE_LIBCRYPTO
|
#elif HAVE_LIBCRYPTO
|
||||||
#include <openssl/md5.h>
|
#include <openssl/md5.h>
|
||||||
#endif // HAVE_L || HAVE_LIBCRYPTO
|
#endif // HAVE_GCRYPT_H || HAVE_LIBCRYPTO
|
||||||
|
|
||||||
#include "zm_utils.h"
|
#include "zm_utils.h"
|
||||||
#include "zm_crypt.h"
|
#include "zm_crypt.h"
|
||||||
|
@ -52,7 +53,7 @@ User::User(const MYSQL_ROW &dbrow) {
|
||||||
id = atoi(dbrow[index++]);
|
id = atoi(dbrow[index++]);
|
||||||
strncpy(username, dbrow[index++], sizeof(username)-1);
|
strncpy(username, dbrow[index++], sizeof(username)-1);
|
||||||
strncpy(password, dbrow[index++], sizeof(password)-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++]);
|
stream = (Permission)atoi(dbrow[index++]);
|
||||||
events = (Permission)atoi(dbrow[index++]);
|
events = (Permission)atoi(dbrow[index++]);
|
||||||
control = (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++];
|
char *monitor_ids_str = dbrow[index++];
|
||||||
if ( monitor_ids_str && *monitor_ids_str ) {
|
if ( monitor_ids_str && *monitor_ids_str ) {
|
||||||
StringVector ids = split(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()));
|
monitor_ids.push_back(atoi((*i).c_str()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,7 +73,7 @@ User::~User() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void User::Copy(const User &u) {
|
void User::Copy(const User &u) {
|
||||||
id=u.id;
|
id = u.id;
|
||||||
strncpy(username, u.username, sizeof(username)-1);
|
strncpy(username, u.username, sizeof(username)-1);
|
||||||
strncpy(password, u.password, sizeof(password)-1);
|
strncpy(password, u.password, sizeof(password)-1);
|
||||||
enabled = u.enabled;
|
enabled = u.enabled;
|
||||||
|
@ -88,7 +89,8 @@ bool User::canAccess(int monitor_id) {
|
||||||
if ( monitor_ids.empty() )
|
if ( monitor_ids.empty() )
|
||||||
return true;
|
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 ) {
|
if ( *i == monitor_id ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -103,12 +105,16 @@ User *zmLoadUser(const char *username, const char *password) {
|
||||||
int username_length = strlen(username);
|
int username_length = strlen(username);
|
||||||
char *safer_username = new char[(username_length * 2) + 1];
|
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);
|
mysql_real_escape_string(&dbconn, safer_username, username, username_length);
|
||||||
|
|
||||||
snprintf(sql, sizeof(sql),
|
snprintf(sql, sizeof(sql),
|
||||||
"SELECT `Id`, `Username`, `Password`, `Enabled`, `Stream`+0, `Events`+0, `Control`+0, `Monitors`+0, `System`+0, `MonitorIds`"
|
"SELECT `Id`, `Username`, `Password`, `Enabled`,"
|
||||||
" FROM `Users` WHERE `Username` = '%s' AND `Enabled` = 1", safer_username);
|
" `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) ) {
|
if ( mysql_query(&dbconn, sql) ) {
|
||||||
Error("Can't run query: %s", mysql_error(&dbconn));
|
Error("Can't run query: %s", mysql_error(&dbconn));
|
||||||
|
@ -146,31 +152,34 @@ User *zmLoadUser(const char *username, const char *password) {
|
||||||
return NULL;
|
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 key = config.auth_hash_secret;
|
||||||
std::string remote_addr = "";
|
std::string remote_addr = "";
|
||||||
|
|
||||||
if (use_remote_addr) {
|
if ( use_remote_addr ) {
|
||||||
remote_addr = std::string(getenv( "REMOTE_ADDR" ));
|
remote_addr = std::string(getenv("REMOTE_ADDR"));
|
||||||
if ( remote_addr == "" ) {
|
if ( remote_addr == "" ) {
|
||||||
Warning( "Can't determine remote address, using null" );
|
Warning("Can't determine remote address, using null");
|
||||||
remote_addr = "";
|
remote_addr = "";
|
||||||
}
|
}
|
||||||
key += 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::pair<std::string, unsigned int> ans = verifyToken(jwt_token_str, key);
|
||||||
std::string username = ans.first;
|
std::string username = ans.first;
|
||||||
unsigned int iat = ans.second;
|
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] = "";
|
char sql[ZM_SQL_MED_BUFSIZ] = "";
|
||||||
snprintf(sql, sizeof(sql),
|
snprintf(sql, sizeof(sql),
|
||||||
"SELECT `Id`, `Username`, `Password`, `Enabled`, `Stream`+0, `Events`+0, `Control`+0, `Monitors`+0, `System`+0, `MonitorIds`, `TokenMinExpiry`"
|
"SELECT `Id`, `Username`, `Password`, `Enabled`,"
|
||||||
" FROM `Users` WHERE `Username` = '%s' AND `Enabled` = 1", username.c_str() );
|
" `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) ) {
|
if ( mysql_query(&dbconn, sql) ) {
|
||||||
Error("Can't run query: %s", mysql_error(&dbconn));
|
Error("Can't run query: %s", mysql_error(&dbconn));
|
||||||
|
@ -192,70 +201,71 @@ User *zmLoadTokenUser (std::string jwt_token_str, bool use_remote_addr ) {
|
||||||
|
|
||||||
MYSQL_ROW dbrow = mysql_fetch_row(result);
|
MYSQL_ROW dbrow = mysql_fetch_row(result);
|
||||||
User *user = new User(dbrow);
|
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);
|
mysql_free_result(result);
|
||||||
Error("Token was revoked for '%s'", username.c_str());
|
Error("Token was revoked for '%s'", username.c_str());
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug (1,"Got stored expiry time of %u",stored_iat);
|
Debug(1, "Authenticated user '%s' via token with last revoke time: %u",
|
||||||
Debug (1,"Authenticated user '%s' via token", username.c_str());
|
username.c_str(), stored_iat);
|
||||||
mysql_free_result(result);
|
mysql_free_result(result);
|
||||||
return user;
|
return user;
|
||||||
|
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
} // end User *zmLoadTokenUser(std::string jwt_token_str, bool use_remote_addr)
|
||||||
}
|
|
||||||
|
|
||||||
// Function to validate an authentication string
|
// 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
|
#if HAVE_DECL_MD5 || HAVE_DECL_GNUTLS_FINGERPRINT
|
||||||
#ifdef HAVE_GCRYPT_H
|
#ifdef HAVE_GCRYPT_H
|
||||||
// Special initialisation for libgcrypt
|
// Special initialisation for libgcrypt
|
||||||
if ( !gcry_check_version( GCRYPT_VERSION ) ) {
|
if ( !gcry_check_version(GCRYPT_VERSION) ) {
|
||||||
Fatal( "Unable to initialise libgcrypt" );
|
Fatal("Unable to initialise libgcrypt");
|
||||||
}
|
}
|
||||||
gcry_control( GCRYCTL_DISABLE_SECMEM, 0 );
|
gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
|
||||||
gcry_control( GCRYCTL_INITIALIZATION_FINISHED, 0 );
|
gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
|
||||||
#endif // HAVE_GCRYPT_H
|
#endif // HAVE_GCRYPT_H
|
||||||
|
|
||||||
const char *remote_addr = "";
|
const char *remote_addr = "";
|
||||||
if ( use_remote_addr ) {
|
if ( use_remote_addr ) {
|
||||||
remote_addr = getenv( "REMOTE_ADDR" );
|
remote_addr = getenv("REMOTE_ADDR");
|
||||||
if ( !remote_addr ) {
|
if ( !remote_addr ) {
|
||||||
Warning( "Can't determine remote address, using null" );
|
Warning("Can't determine remote address, using null");
|
||||||
remote_addr = "";
|
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] = "";
|
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 ) ) {
|
if ( mysql_query(&dbconn, sql) ) {
|
||||||
Error( "Can't run query: %s", mysql_error( &dbconn ) );
|
Error("Can't run query: %s", mysql_error(&dbconn));
|
||||||
exit( mysql_errno( &dbconn ) );
|
exit(mysql_errno(&dbconn));
|
||||||
}
|
}
|
||||||
|
|
||||||
MYSQL_RES *result = mysql_store_result( &dbconn );
|
MYSQL_RES *result = mysql_store_result(&dbconn);
|
||||||
if ( !result ) {
|
if ( !result ) {
|
||||||
Error( "Can't use query result: %s", mysql_error( &dbconn ) );
|
Error("Can't use query result: %s", mysql_error(&dbconn));
|
||||||
exit( mysql_errno( &dbconn ) );
|
exit(mysql_errno(&dbconn));
|
||||||
}
|
}
|
||||||
int n_users = mysql_num_rows( result );
|
int n_users = mysql_num_rows(result);
|
||||||
|
|
||||||
if ( n_users < 1 ) {
|
if ( n_users < 1 ) {
|
||||||
mysql_free_result( result );
|
mysql_free_result(result);
|
||||||
Warning( "Unable to authenticate user" );
|
Warning("Unable to authenticate user");
|
||||||
return( 0 );
|
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 *user = dbrow[1];
|
||||||
const char *pass = dbrow[2];
|
const char *pass = dbrow[2];
|
||||||
|
|
||||||
|
@ -264,20 +274,20 @@ User *zmLoadAuthUser( const char *auth, bool use_remote_addr ) {
|
||||||
size_t md5len = 16;
|
size_t md5len = 16;
|
||||||
unsigned char md5sum[md5len];
|
unsigned char md5sum[md5len];
|
||||||
|
|
||||||
time_t now = time( 0 );
|
time_t now = time(0);
|
||||||
unsigned int hours = config.auth_hash_ttl;
|
unsigned int hours = config.auth_hash_ttl;
|
||||||
|
|
||||||
if ( ! hours ) {
|
if ( !hours ) {
|
||||||
Warning("No value set for ZM_AUTH_HASH_TTL. Defaulting to 2.");
|
Warning("No value set for ZM_AUTH_HASH_TTL. Defaulting to 2.");
|
||||||
hours = 2;
|
hours = 2;
|
||||||
} else {
|
} 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 ) {
|
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,
|
config.auth_hash_secret,
|
||||||
user,
|
user,
|
||||||
pass,
|
pass,
|
||||||
|
@ -285,50 +295,51 @@ User *zmLoadAuthUser( const char *auth, bool use_remote_addr ) {
|
||||||
now_tm->tm_hour,
|
now_tm->tm_hour,
|
||||||
now_tm->tm_mday,
|
now_tm->tm_mday,
|
||||||
now_tm->tm_mon,
|
now_tm->tm_mon,
|
||||||
now_tm->tm_year
|
now_tm->tm_year);
|
||||||
);
|
|
||||||
|
|
||||||
#if HAVE_DECL_MD5
|
#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
|
#elif HAVE_DECL_GNUTLS_FINGERPRINT
|
||||||
gnutls_datum_t md5data = { (unsigned char *)auth_key, strlen(auth_key) };
|
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
|
#endif
|
||||||
for ( unsigned int j = 0; j < md5len; j++ ) {
|
for ( unsigned int j = 0; j < md5len; j++ ) {
|
||||||
snprintf(&auth_md5[2*j], 2, "%02x", md5sum[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
|
// We have a match
|
||||||
User *user = new User( dbrow );
|
User *user = new User(dbrow);
|
||||||
Debug(1, "Authenticated user '%s'", user->getUsername() );
|
Debug(1, "Authenticated user '%s'", user->getUsername());
|
||||||
mysql_free_result( result );
|
mysql_free_result(result);
|
||||||
return( user );
|
return user;
|
||||||
} else {
|
} else {
|
||||||
Debug(1, "No match for %s", auth );
|
Debug(1, "No match for %s", auth);
|
||||||
}
|
}
|
||||||
}
|
} // end foreach hour
|
||||||
}
|
} // end foreach user
|
||||||
mysql_free_result( result );
|
mysql_free_result(result);
|
||||||
#else // HAVE_DECL_MD5
|
#else // HAVE_DECL_MD5 || HAVE_DECL_GNUTLS_FINGERPRINT
|
||||||
Error( "You need to build with gnutls or openssl installed to use hash based authentication" );
|
Error("You need to build with gnutls or openssl to use hash based auth");
|
||||||
#endif // HAVE_DECL_MD5
|
#endif // HAVE_DECL_MD5 || HAVE_DECL_GNUTLS_FINGERPRINT
|
||||||
Debug(1, "No user found for auth_key %s", auth );
|
Debug(1, "No user found for auth_key %s", auth);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
} // end User *zmLoadAuthUser( const char *auth, bool use_remote_addr )
|
||||||
|
|
||||||
//Function to check Username length
|
// Function to check Username length
|
||||||
bool checkUser ( const char *username) {
|
bool checkUser(const char *username) {
|
||||||
if ( ! username )
|
if ( !username )
|
||||||
return false;
|
return false;
|
||||||
if ( strlen(username) > 32 )
|
if ( strlen(username) > 32 )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//Function to check password length
|
|
||||||
bool checkPass (const char *password) {
|
// Function to check password length
|
||||||
|
bool checkPass(const char *password) {
|
||||||
if ( !password )
|
if ( !password )
|
||||||
return false;
|
return false;
|
||||||
if ( strlen(password) > 64 )
|
if ( strlen(password) > 64 )
|
||||||
|
|
|
@ -409,7 +409,7 @@ bool VideoStore::open() {
|
||||||
AVDictionary *opts = NULL;
|
AVDictionary *opts = NULL;
|
||||||
// av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0);
|
// av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0);
|
||||||
// Shiboleth reports that this may break seeking in mp4 before it downloads
|
// 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",
|
// av_dict_set(&opts, "movflags",
|
||||||
// "frag_keyframe+empty_moov+default_base_moof", 0);
|
// "frag_keyframe+empty_moov+default_base_moof", 0);
|
||||||
if ( (ret = avformat_write_header(oc, &opts)) < 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++ ) {
|
for ( int p = 0; p < parm_no; p++ ) {
|
||||||
char *name = strtok(parms[p], "=");
|
char *name = strtok(parms[p], "=");
|
||||||
char *value = strtok(NULL, "=");
|
char const *value = strtok(NULL, "=");
|
||||||
if ( !value )
|
if ( !value )
|
||||||
value = (char *)"";
|
value = "";
|
||||||
if ( !strcmp(name, "source") ) {
|
if ( !strcmp(name, "source") ) {
|
||||||
source = !strcmp(value, "event")?ZMS_EVENT:ZMS_MONITOR;
|
source = !strcmp(value, "event")?ZMS_EVENT:ZMS_MONITOR;
|
||||||
if ( !strcmp(value, "fifo") )
|
if ( !strcmp(value, "fifo") )
|
||||||
|
@ -127,10 +127,10 @@ int main(int argc, const char *argv[]) {
|
||||||
} else if ( !strcmp(name, "time") ) {
|
} else if ( !strcmp(name, "time") ) {
|
||||||
event_time = atoi(value);
|
event_time = atoi(value);
|
||||||
} else if ( !strcmp(name, "event") ) {
|
} else if ( !strcmp(name, "event") ) {
|
||||||
event_id = strtoull(value, (char **)NULL, 10);
|
event_id = strtoull(value, NULL, 10);
|
||||||
source = ZMS_EVENT;
|
source = ZMS_EVENT;
|
||||||
} else if ( !strcmp(name, "frame") ) {
|
} else if ( !strcmp(name, "frame") ) {
|
||||||
frame_id = strtoull(value, (char **)NULL, 10);
|
frame_id = strtoull(value, NULL, 10);
|
||||||
source = ZMS_EVENT;
|
source = ZMS_EVENT;
|
||||||
} else if ( !strcmp(name, "scale") ) {
|
} else if ( !strcmp(name, "scale") ) {
|
||||||
scale = atoi(value);
|
scale = atoi(value);
|
||||||
|
@ -159,7 +159,7 @@ int main(int argc, const char *argv[]) {
|
||||||
} else if ( !strcmp(name, "buffer") ) {
|
} else if ( !strcmp(name, "buffer") ) {
|
||||||
playback_buffer = atoi(value);
|
playback_buffer = atoi(value);
|
||||||
} else if ( !strcmp(name, "auth") ) {
|
} else if ( !strcmp(name, "auth") ) {
|
||||||
strncpy( auth, value, sizeof(auth)-1 );
|
strncpy(auth, value, sizeof(auth)-1);
|
||||||
} else if ( !strcmp(name, "token") ) {
|
} else if ( !strcmp(name, "token") ) {
|
||||||
jwt_token_str = value;
|
jwt_token_str = value;
|
||||||
Debug(1, "ZMS: JWT token found: %s", jwt_token_str.c_str());
|
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);
|
time_t now = time(0);
|
||||||
char date_string[64];
|
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(
|
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: no-store, no-cache, must-revalidate\r\n"
|
||||||
"Cache-Control: post-check=0, pre-check=0\r\n"
|
"Cache-Control: post-check=0, pre-check=0\r\n"
|
||||||
"Pragma: no-cache\r\n",
|
"Pragma: no-cache\r\n",
|
||||||
|
@ -279,7 +281,9 @@ int main(int argc, const char *argv[]) {
|
||||||
stream.setStreamType(MonitorStream::STREAM_MPEG);
|
stream.setStreamType(MonitorStream::STREAM_MPEG);
|
||||||
#else // HAVE_LIBAVCODEC
|
#else // HAVE_LIBAVCODEC
|
||||||
Error("MPEG streaming of '%s' attempted while disabled", query);
|
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();
|
logTerm();
|
||||||
zmDbClose();
|
zmDbClose();
|
||||||
return -1;
|
return -1;
|
||||||
|
|
48
src/zmu.cpp
48
src/zmu.cpp
|
@ -476,14 +476,12 @@ int main(int argc, char *argv[]) {
|
||||||
} // end if auth
|
} // end if auth
|
||||||
|
|
||||||
if ( mon_id > 0 ) {
|
if ( mon_id > 0 ) {
|
||||||
//fprintf(stderr,"Monitor %d\n", mon_id);
|
|
||||||
Monitor *monitor = Monitor::Load(mon_id, function&(ZMU_QUERY|ZMU_ZONES), Monitor::QUERY);
|
Monitor *monitor = Monitor::Load(mon_id, function&(ZMU_QUERY|ZMU_ZONES), Monitor::QUERY);
|
||||||
if ( monitor ) {
|
if ( monitor ) {
|
||||||
//fprintf(stderr,"Monitor %d(%s)\n", monitor->Id(), monitor->Name());
|
|
||||||
if ( verbose ) {
|
if ( verbose ) {
|
||||||
printf("Monitor %d(%s)\n", monitor->Id(), monitor->Name());
|
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());
|
Error("Can't connect to capture daemon: %d %s", monitor->Id(), monitor->Name());
|
||||||
exit_zmu(-1);
|
exit_zmu(-1);
|
||||||
}
|
}
|
||||||
|
@ -495,13 +493,13 @@ int main(int argc, char *argv[]) {
|
||||||
if ( verbose ) {
|
if ( verbose ) {
|
||||||
printf("Current state: %s\n", state==Monitor::ALARM?"Alarm":(state==Monitor::ALERT?"Alert":"Idle"));
|
printf("Current state: %s\n", state==Monitor::ALARM?"Alarm":(state==Monitor::ALERT?"Alert":"Idle"));
|
||||||
} else {
|
} else {
|
||||||
if ( have_output ) printf("%c", separator);
|
if ( have_output ) fputc(separator, stdout);
|
||||||
printf("%d", state);
|
printf("%d", state);
|
||||||
have_output = true;
|
have_output = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( function & ZMU_TIME ) {
|
if ( function & ZMU_TIME ) {
|
||||||
struct timeval timestamp = monitor->GetTimestamp( image_idx );
|
struct timeval timestamp = monitor->GetTimestamp(image_idx);
|
||||||
if ( verbose ) {
|
if ( verbose ) {
|
||||||
char timestamp_str[64] = "None";
|
char timestamp_str[64] = "None";
|
||||||
if ( timestamp.tv_sec )
|
if ( timestamp.tv_sec )
|
||||||
|
@ -511,7 +509,7 @@ int main(int argc, char *argv[]) {
|
||||||
else
|
else
|
||||||
printf("Time of image %d capture: %s.%02ld\n", image_idx, timestamp_str, timestamp.tv_usec/10000);
|
printf("Time of image %d capture: %s.%02ld\n", image_idx, timestamp_str, timestamp.tv_usec/10000);
|
||||||
} else {
|
} else {
|
||||||
if ( have_output ) printf("%c", separator);
|
if ( have_output ) fputc(separator, stdout);
|
||||||
printf("%ld.%02ld", timestamp.tv_sec, timestamp.tv_usec/10000);
|
printf("%ld.%02ld", timestamp.tv_sec, timestamp.tv_usec/10000);
|
||||||
have_output = true;
|
have_output = true;
|
||||||
}
|
}
|
||||||
|
@ -520,7 +518,7 @@ int main(int argc, char *argv[]) {
|
||||||
if ( verbose )
|
if ( verbose )
|
||||||
printf("Last read index: %d\n", monitor->GetLastReadIndex());
|
printf("Last read index: %d\n", monitor->GetLastReadIndex());
|
||||||
else {
|
else {
|
||||||
if ( have_output ) printf("%c", separator);
|
if ( have_output ) fputc(separator, stdout);
|
||||||
printf("%d", monitor->GetLastReadIndex());
|
printf("%d", monitor->GetLastReadIndex());
|
||||||
have_output = true;
|
have_output = true;
|
||||||
}
|
}
|
||||||
|
@ -529,7 +527,7 @@ int main(int argc, char *argv[]) {
|
||||||
if ( verbose ) {
|
if ( verbose ) {
|
||||||
printf("Last write index: %d\n", monitor->GetLastWriteIndex());
|
printf("Last write index: %d\n", monitor->GetLastWriteIndex());
|
||||||
} else {
|
} else {
|
||||||
if ( have_output ) printf("%c", separator);
|
if ( have_output ) fputc(separator, stdout);
|
||||||
printf("%d", monitor->GetLastWriteIndex());
|
printf("%d", monitor->GetLastWriteIndex());
|
||||||
have_output = true;
|
have_output = true;
|
||||||
}
|
}
|
||||||
|
@ -538,16 +536,16 @@ int main(int argc, char *argv[]) {
|
||||||
if ( verbose ) {
|
if ( verbose ) {
|
||||||
printf("Last event id: %" PRIu64 "\n", monitor->GetLastEventId());
|
printf("Last event id: %" PRIu64 "\n", monitor->GetLastEventId());
|
||||||
} else {
|
} else {
|
||||||
if ( have_output ) printf("%c", separator);
|
if ( have_output ) fputc(separator, stdout);
|
||||||
printf("%" PRIu64, monitor->GetLastEventId());
|
printf("%" PRIu64, monitor->GetLastEventId());
|
||||||
have_output = true;
|
have_output = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( function & ZMU_FPS ) {
|
if ( function & ZMU_FPS ) {
|
||||||
if ( verbose )
|
if ( verbose ) {
|
||||||
printf("Current capture rate: %.2f frames per second\n", monitor->GetFPS());
|
printf("Current capture rate: %.2f frames per second\n", monitor->GetFPS());
|
||||||
else {
|
} else {
|
||||||
if ( have_output ) printf("%c", separator);
|
if ( have_output ) fputc(separator, stdout);
|
||||||
printf("%.2f", monitor->GetFPS());
|
printf("%.2f", monitor->GetFPS());
|
||||||
have_output = true;
|
have_output = true;
|
||||||
}
|
}
|
||||||
|
@ -573,10 +571,16 @@ int main(int argc, char *argv[]) {
|
||||||
if ( monitor->GetFunction() == Monitor::Function::MONITOR ) {
|
if ( monitor->GetFunction() == Monitor::Function::MONITOR ) {
|
||||||
printf("A Monitor in monitor mode cannot handle alarms. Please use NoDect\n");
|
printf("A Monitor in monitor mode cannot handle alarms. Please use NoDect\n");
|
||||||
} else {
|
} else {
|
||||||
if ( verbose )
|
Monitor::State state = monitor->GetState();
|
||||||
printf("Forcing alarm on\n");
|
|
||||||
|
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");
|
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.
|
// Wait for monitor to notice.
|
||||||
usleep(1000);
|
usleep(1000);
|
||||||
}
|
}
|
||||||
|
@ -630,7 +634,7 @@ int main(int argc, char *argv[]) {
|
||||||
else
|
else
|
||||||
printf("Current brightness: %d\n", monitor->actionBrightness());
|
printf("Current brightness: %d\n", monitor->actionBrightness());
|
||||||
} else {
|
} else {
|
||||||
if ( have_output ) printf("%c", separator);
|
if ( have_output ) fputc(separator, stdout);
|
||||||
if ( brightness >= 0 )
|
if ( brightness >= 0 )
|
||||||
printf("%d", monitor->actionBrightness(brightness));
|
printf("%d", monitor->actionBrightness(brightness));
|
||||||
else
|
else
|
||||||
|
@ -645,7 +649,7 @@ int main(int argc, char *argv[]) {
|
||||||
else
|
else
|
||||||
printf("Current contrast: %d\n", monitor->actionContrast());
|
printf("Current contrast: %d\n", monitor->actionContrast());
|
||||||
} else {
|
} else {
|
||||||
if ( have_output ) printf("%c", separator);
|
if ( have_output ) fputc(separator, stdout);
|
||||||
if ( contrast >= 0 )
|
if ( contrast >= 0 )
|
||||||
printf("%d", monitor->actionContrast(contrast));
|
printf("%d", monitor->actionContrast(contrast));
|
||||||
else
|
else
|
||||||
|
@ -660,7 +664,7 @@ int main(int argc, char *argv[]) {
|
||||||
else
|
else
|
||||||
printf("Current hue: %d\n", monitor->actionHue());
|
printf("Current hue: %d\n", monitor->actionHue());
|
||||||
} else {
|
} else {
|
||||||
if ( have_output ) printf("%c", separator);
|
if ( have_output ) fputc(separator, stdout);
|
||||||
if ( hue >= 0 )
|
if ( hue >= 0 )
|
||||||
printf("%d", monitor->actionHue(hue));
|
printf("%d", monitor->actionHue(hue));
|
||||||
else
|
else
|
||||||
|
@ -675,7 +679,7 @@ int main(int argc, char *argv[]) {
|
||||||
else
|
else
|
||||||
printf("Current colour: %d\n", monitor->actionColour());
|
printf("Current colour: %d\n", monitor->actionColour());
|
||||||
} else {
|
} else {
|
||||||
if ( have_output ) printf("%c", separator);
|
if ( have_output ) fputc(separator, stdout);
|
||||||
if ( colour >= 0 )
|
if ( colour >= 0 )
|
||||||
printf("%d", monitor->actionColour(colour));
|
printf("%d", monitor->actionColour(colour));
|
||||||
else
|
else
|
||||||
|
@ -708,11 +712,11 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( function & ZMU_LIST ) {
|
if ( function & ZMU_LIST ) {
|
||||||
std::string sql = "select Id, Function+0 from Monitors";
|
std::string sql = "SELECT `Id`, `Function`+0 FROM `Monitors`";
|
||||||
if ( !verbose ) {
|
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()) ) {
|
if ( mysql_query(&dbconn, sql.c_str()) ) {
|
||||||
Error("Can't run query: %s", mysql_error(&dbconn));
|
Error("Can't run query: %s", mysql_error(&dbconn));
|
||||||
|
|
|
@ -110,7 +110,12 @@ else
|
||||||
fi;
|
fi;
|
||||||
if [ "$SNAPSHOT" == "stable" ]; then
|
if [ "$SNAPSHOT" == "stable" ]; then
|
||||||
if [ "$BRANCH" == "" ]; 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";
|
echo "Latest stable branch is $BRANCH";
|
||||||
fi;
|
fi;
|
||||||
else
|
else
|
||||||
|
|
|
@ -50,8 +50,10 @@ class HostController extends AppController {
|
||||||
$cred_depr = [];
|
$cred_depr = [];
|
||||||
|
|
||||||
if ( $username && $password ) {
|
if ( $username && $password ) {
|
||||||
|
ZM\Logger::Debug('Username and password provided, generating access and refresh tokens');
|
||||||
$cred = $this->_getCredentials(true, '', $username); // generate refresh
|
$cred = $this->_getCredentials(true, '', $username); // generate refresh
|
||||||
} else {
|
} else {
|
||||||
|
ZM\Logger::Debug('Only generating access token');
|
||||||
$cred = $this->_getCredentials(false, $token); // don't generate refresh
|
$cred = $this->_getCredentials(false, $token); // don't generate refresh
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,6 +71,8 @@ class HostController extends AppController {
|
||||||
$cred_depr = $this->_getCredentialsDeprecated();
|
$cred_depr = $this->_getCredentialsDeprecated();
|
||||||
$login_array['credentials'] = $cred_depr[0];
|
$login_array['credentials'] = $cred_depr[0];
|
||||||
$login_array['append_password'] = $cred_depr[1];
|
$login_array['append_password'] = $cred_depr[1];
|
||||||
|
} else {
|
||||||
|
ZM\Logger::Debug('Legacy Auth is disabled, not generating auth= credentials');
|
||||||
}
|
}
|
||||||
|
|
||||||
$login_array['version'] = $ver[0];
|
$login_array['version'] = $ver[0];
|
||||||
|
@ -108,8 +112,11 @@ class HostController extends AppController {
|
||||||
|
|
||||||
private function _getCredentials($generate_refresh_token=false, $token='', $username='') {
|
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;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if ( !ZM_AUTH_HASH_SECRET )
|
if ( !ZM_AUTH_HASH_SECRET )
|
||||||
throw new ForbiddenException(__('Please create a valid AUTH_HASH_SECRET in ZoneMinder'));
|
throw new ForbiddenException(__('Please create a valid AUTH_HASH_SECRET in ZoneMinder'));
|
||||||
|
|
|
@ -17,12 +17,17 @@ class ServersController extends AppController {
|
||||||
|
|
||||||
public function beforeFilter() {
|
public function beforeFilter() {
|
||||||
parent::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;
|
global $user;
|
||||||
$canView = (!$user) || ($user['System'] != 'None');
|
$canView = (!$user) || ($user['System'] != 'None');
|
||||||
if ( !$canView ) {
|
if ( !$canView ) {
|
||||||
throw new UnauthorizedException(__('Insufficient Privileges'));
|
throw new UnauthorizedException(__('Insufficient Privileges'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -34,7 +39,7 @@ class ServersController extends AppController {
|
||||||
$this->Server->recursive = 0;
|
$this->Server->recursive = 0;
|
||||||
|
|
||||||
$options = '';
|
$options = '';
|
||||||
$servers = $this->Server->find('all',$options);
|
$servers = $this->Server->find('all', $options);
|
||||||
$this->set(array(
|
$this->set(array(
|
||||||
'servers' => $servers,
|
'servers' => $servers,
|
||||||
'_serialize' => array('servers')
|
'_serialize' => array('servers')
|
||||||
|
@ -50,13 +55,13 @@ class ServersController extends AppController {
|
||||||
*/
|
*/
|
||||||
public function view($id = null) {
|
public function view($id = null) {
|
||||||
$this->Server->recursive = 0;
|
$this->Server->recursive = 0;
|
||||||
if (!$this->Server->exists($id)) {
|
if ( !$this->Server->exists($id) ) {
|
||||||
throw new NotFoundException(__('Invalid server'));
|
throw new NotFoundException(__('Invalid server'));
|
||||||
}
|
}
|
||||||
$restricted = '';
|
$restricted = '';
|
||||||
|
|
||||||
$options = array('conditions' => array(
|
$options = array('conditions' => array(
|
||||||
array('Server.' . $this->Server->primaryKey => $id),
|
array('Server.'.$this->Server->primaryKey => $id),
|
||||||
$restricted
|
$restricted
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
|
@ -119,7 +119,7 @@ class Monitor extends AppModel {
|
||||||
);
|
);
|
||||||
public $actsAs = array(
|
public $actsAs = array(
|
||||||
'CakePHP-Enum-Behavior.Enum' => 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'),
|
'Function' => array('None','Monitor','Modect','Record','Mocord','Nodect'),
|
||||||
'Orientation' => array('ROTATE_0','ROTATE_90','ROTATE_180','ROTATE_270','FLIP_HORI','FLIP_VERT'),
|
'Orientation' => array('ROTATE_0','ROTATE_90','ROTATE_180','ROTATE_270','FLIP_HORI','FLIP_VERT'),
|
||||||
'OutputCodec' => array('h264','mjpeg','mpeg1','mpeg2'),
|
'OutputCodec' => array('h264','mjpeg','mpeg1','mpeg2'),
|
||||||
|
|
|
@ -417,31 +417,27 @@ class Event extends ZM_Object {
|
||||||
}
|
}
|
||||||
} // end if capture file exists
|
} // end if capture file exists
|
||||||
} // end if analyze file exists
|
} // end if analyze file exists
|
||||||
}
|
} // end if frame or snapshot
|
||||||
|
|
||||||
$captPath = $eventPath.'/'.$captImage;
|
$captPath = $eventPath.'/'.$captImage;
|
||||||
if ( ! file_exists($captPath) ) {
|
if ( ! file_exists($captPath) ) {
|
||||||
Error("Capture file does not exist at $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']);
|
$analImage = sprintf('%0'.ZM_EVENT_IMAGE_DIGITS.'d-analyse.jpg', $frame['FrameId']);
|
||||||
$analPath = $eventPath.'/'.$analImage;
|
$analPath = $eventPath.'/'.$analImage;
|
||||||
|
|
||||||
//echo "AI:$analImage, AP:$analPath, TAP:$analPath<br>";
|
|
||||||
|
|
||||||
$alarmFrame = $frame['Type']=='Alarm';
|
$alarmFrame = $frame['Type']=='Alarm';
|
||||||
|
|
||||||
$hasAnalImage = $alarmFrame && file_exists($analPath) && filesize($analPath);
|
$hasAnalImage = $alarmFrame && file_exists($analPath) && filesize($analPath);
|
||||||
$isAnalImage = $hasAnalImage && !$captureOnly;
|
$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;
|
$imagePath = $thumbPath = $isAnalImage ? $analPath : $captPath;
|
||||||
$imageFile = $imagePath;
|
$imageFile = $imagePath;
|
||||||
$thumbFile = $thumbPath;
|
$thumbFile = $thumbPath;
|
||||||
} else {
|
} else {
|
||||||
if ( version_compare( phpversion(), '4.3.10', '>=') )
|
if ( version_compare(phpversion(), '4.3.10', '>=') )
|
||||||
$fraction = sprintf('%.3F', $scale/SCALE_BASE);
|
$fraction = sprintf('%.3F', $scale/SCALE_BASE);
|
||||||
else
|
else
|
||||||
$fraction = sprintf('%.3f', $scale/SCALE_BASE);
|
$fraction = sprintf('%.3f', $scale/SCALE_BASE);
|
||||||
|
@ -459,19 +455,19 @@ class Event extends ZM_Object {
|
||||||
}
|
}
|
||||||
|
|
||||||
$thumbFile = $thumbPath;
|
$thumbFile = $thumbPath;
|
||||||
if ( $overwrite || ! file_exists( $thumbFile ) || ! filesize( $thumbFile ) ) {
|
if ( $overwrite || ! file_exists($thumbFile) || ! filesize($thumbFile) ) {
|
||||||
// Get new dimensions
|
// Get new dimensions
|
||||||
list( $imageWidth, $imageHeight ) = getimagesize( $imagePath );
|
list( $imageWidth, $imageHeight ) = getimagesize($imagePath);
|
||||||
$thumbWidth = $imageWidth * $fraction;
|
$thumbWidth = $imageWidth * $fraction;
|
||||||
$thumbHeight = $imageHeight * $fraction;
|
$thumbHeight = $imageHeight * $fraction;
|
||||||
|
|
||||||
// Resample
|
// Resample
|
||||||
$thumbImage = imagecreatetruecolor( $thumbWidth, $thumbHeight );
|
$thumbImage = imagecreatetruecolor($thumbWidth, $thumbHeight);
|
||||||
$image = imagecreatefromjpeg( $imagePath );
|
$image = imagecreatefromjpeg($imagePath);
|
||||||
imagecopyresampled( $thumbImage, $image, 0, 0, 0, 0, $thumbWidth, $thumbHeight, $imageWidth, $imageHeight );
|
imagecopyresampled($thumbImage, $image, 0, 0, 0, 0, $thumbWidth, $thumbHeight, $imageWidth, $imageHeight);
|
||||||
|
|
||||||
if ( !imagejpeg( $thumbImage, $thumbPath ) )
|
if ( !imagejpeg($thumbImage, $thumbPath) )
|
||||||
Error( "Can't create thumbnail '$thumbPath'" );
|
Error("Can't create thumbnail '$thumbPath'");
|
||||||
}
|
}
|
||||||
} # Create thumbnails
|
} # Create thumbnails
|
||||||
|
|
||||||
|
@ -555,7 +551,7 @@ class Event extends ZM_Object {
|
||||||
$Server = $Storage->ServerId() ? $Storage->Server() : $this->Monitor()->Server();
|
$Server = $Storage->ServerId() ? $Storage->Server() : $this->Monitor()->Server();
|
||||||
if ( $Server->Id() != ZM_SERVER_ID ) {
|
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_OPT_USE_AUTH ) {
|
||||||
if ( ZM_AUTH_RELAY == 'hashed' ) {
|
if ( ZM_AUTH_RELAY == 'hashed' ) {
|
||||||
$url .= '?auth='.generateAuthHash(ZM_AUTH_HASH_IPS);
|
$url .= '?auth='.generateAuthHash(ZM_AUTH_HASH_IPS);
|
||||||
|
|
|
@ -11,6 +11,9 @@ class Filter extends ZM_Object {
|
||||||
'AutoExecute' => 0,
|
'AutoExecute' => 0,
|
||||||
'AutoExecuteCmd' => 0,
|
'AutoExecuteCmd' => 0,
|
||||||
'AutoEmail' => 0,
|
'AutoEmail' => 0,
|
||||||
|
'EmailTo' => '',
|
||||||
|
'EmailSubject' => '',
|
||||||
|
'EmailBody' => '',
|
||||||
'AutoDelete' => 0,
|
'AutoDelete' => 0,
|
||||||
'AutoArchive' => 0,
|
'AutoArchive' => 0,
|
||||||
'AutoVideo' => 0,
|
'AutoVideo' => 0,
|
||||||
|
|
|
@ -441,14 +441,17 @@ class Monitor extends ZM_Object {
|
||||||
$source = '';
|
$source = '';
|
||||||
if ( $this->{'Type'} == 'Local' ) {
|
if ( $this->{'Type'} == 'Local' ) {
|
||||||
$source = $this->{'Device'}.' ('.$this->{'Channel'}.')';
|
$source = $this->{'Device'}.' ('.$this->{'Channel'}.')';
|
||||||
} elseif ( $this->{'Type'} == 'Remote' ) {
|
} else if ( $this->{'Type'} == 'Remote' ) {
|
||||||
$source = preg_replace( '/^.*@/', '', $this->{'Host'} );
|
$source = preg_replace( '/^.*@/', '', $this->{'Host'} );
|
||||||
if ( $this->{'Port'} != '80' and $this->{'Port'} != '554' ) {
|
if ( $this->{'Port'} != '80' and $this->{'Port'} != '554' ) {
|
||||||
$source .= ':'.$this->{'Port'};
|
$source .= ':'.$this->{'Port'};
|
||||||
}
|
}
|
||||||
} elseif ( $this->{'Type'} == 'File' || $this->{'Type'} == 'cURL' ) {
|
} else if ( $this->{'Type'} == 'VNC' ) {
|
||||||
$source = preg_replace( '/^.*\//', '', $this->{'Path'} );
|
$source = preg_replace( '/^.*@/', '', $this->{'Host'} );
|
||||||
} elseif ( $this->{'Type'} == 'Ffmpeg' || $this->{'Type'} == 'Libvlc' || $this->{'Type'} == 'WebSite' ) {
|
if ( $this->{'Port'} != '5900' ) {
|
||||||
|
$source .= ':'.$this->{'Port'};
|
||||||
|
}
|
||||||
|
} else if ( $this->{'Type'} == 'Ffmpeg' || $this->{'Type'} == 'Libvlc' || $this->{'Type'} == 'WebSite' ) {
|
||||||
$url_parts = parse_url( $this->{'Path'} );
|
$url_parts = parse_url( $this->{'Path'} );
|
||||||
if ( ZM_WEB_FILTER_SOURCE == 'Hostname' ) {
|
if ( ZM_WEB_FILTER_SOURCE == 'Hostname' ) {
|
||||||
# Filter out everything but the hostname
|
# Filter out everything but the hostname
|
||||||
|
@ -457,7 +460,7 @@ class Monitor extends ZM_Object {
|
||||||
} else {
|
} else {
|
||||||
$source = $this->{'Path'};
|
$source = $this->{'Path'};
|
||||||
}
|
}
|
||||||
} elseif ( ZM_WEB_FILTER_SOURCE == 'NoCredentials' ) {
|
} else if ( ZM_WEB_FILTER_SOURCE == 'NoCredentials' ) {
|
||||||
# Filter out sensitive and common items
|
# Filter out sensitive and common items
|
||||||
unset($url_parts['user']);
|
unset($url_parts['user']);
|
||||||
unset($url_parts['pass']);
|
unset($url_parts['pass']);
|
||||||
|
|
|
@ -216,7 +216,8 @@ Logger::Debug("$k => Have default for $v: ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} # end foreach default
|
} # end foreach default
|
||||||
}
|
} # end if defaults
|
||||||
|
|
||||||
foreach ( $new_values as $field => $value ) {
|
foreach ( $new_values as $field => $value ) {
|
||||||
|
|
||||||
if ( method_exists($this, $field) ) {
|
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
|
# 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
|
# 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 ) {
|
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) ) {
|
if ( is_array($default) ) {
|
||||||
$this->{$field} = $default['default'];
|
$this->{$field} = $default['default'];
|
||||||
} else if ( $default == null ) {
|
} else if ( $default == null ) {
|
||||||
|
|
|
@ -16,6 +16,7 @@ class Storage extends ZM_Object {
|
||||||
'Scheme' => 'Medium',
|
'Scheme' => 'Medium',
|
||||||
'ServerId' => 0,
|
'ServerId' => 0,
|
||||||
'DoDelete' => 1,
|
'DoDelete' => 1,
|
||||||
|
'Enabled' => 1,
|
||||||
);
|
);
|
||||||
public static function find($parameters = array(), $options = array()) {
|
public static function find($parameters = array(), $options = array()) {
|
||||||
return ZM_Object::_find(get_class(), $parameters, $options);
|
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,38 +21,27 @@
|
||||||
// Group edit actions
|
// Group edit actions
|
||||||
# Should probably verify that each monitor id is a valid monitor, that we have access to.
|
# 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
|
# 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');
|
ZM\Warning('Need group edit permissions to edit groups');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $action == 'Save' ) {
|
if ( $action == 'Save' ) {
|
||||||
$monitors = empty($_POST['newGroup']['MonitorIds']) ? '' : implode(',', $_POST['newGroup']['MonitorIds']);
|
|
||||||
$group_id = null;
|
$group_id = null;
|
||||||
if ( !empty($_POST['gid']) ) {
|
if ( !empty($_POST['gid']) )
|
||||||
$group_id = $_POST['gid'];
|
$group_id = $_POST['gid'];
|
||||||
dbQuery(
|
$group = new ZM\Group($group_id);
|
||||||
'UPDATE Groups SET Name=?, ParentId=? WHERE Id=?',
|
$group->save(
|
||||||
array(
|
array(
|
||||||
$_POST['newGroup']['Name'],
|
'Name'=> $_POST['newGroup']['Name'],
|
||||||
( $_POST['newGroup']['ParentId'] == '' ? null : $_POST['newGroup']['ParentId'] ),
|
'ParentId'=>( $_POST['newGroup']['ParentId'] == '' ? null : $_POST['newGroup']['ParentId'] ),
|
||||||
$group_id,
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
dbQuery('DELETE FROM Groups_Monitors WHERE GroupId=?', array($group_id));
|
dbQuery('DELETE FROM `Groups_Monitors` WHERE `GroupId`=?', array($group_id));
|
||||||
} else {
|
$group_id = $group->Id();
|
||||||
dbQuery(
|
|
||||||
'INSERT INTO Groups (Name,ParentId) VALUES (?,?)',
|
|
||||||
array(
|
|
||||||
$_POST['newGroup']['Name'],
|
|
||||||
( $_POST['newGroup']['ParentId'] == '' ? null : $_POST['newGroup']['ParentId'] ),
|
|
||||||
)
|
|
||||||
);
|
|
||||||
$group_id = dbInsertId();
|
|
||||||
}
|
|
||||||
if ( $group_id ) {
|
if ( $group_id ) {
|
||||||
foreach ( $_POST['newGroup']['MonitorIds'] as $mid ) {
|
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';
|
$view = 'none';
|
||||||
|
|
|
@ -442,9 +442,10 @@ function makeLink($url, $label, $condition=1, $options='') {
|
||||||
*/
|
*/
|
||||||
function makePopupLink($url, $winName, $winSize, $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.
|
// 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 = '<a';
|
||||||
$string .= ' data-window-name="' . htmlspecialchars($winName) . '"';
|
|
||||||
if ( $condition ) {
|
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 ) ) {
|
if ( is_array( $winSize ) ) {
|
||||||
$string .= ' data-window-tag="' . htmlspecialchars($winSize[0]) . '"';
|
$string .= ' data-window-tag="' . htmlspecialchars($winSize[0]) . '"';
|
||||||
$string .= ' data-window-width="' . htmlspecialchars($winSize[1]) . '"';
|
$string .= ' data-window-width="' . htmlspecialchars($winSize[1]) . '"';
|
||||||
|
@ -455,7 +456,7 @@ function makePopupLink($url, $winName, $winSize, $label, $condition=1, $options=
|
||||||
|
|
||||||
$string .= ($options ? (' ' . $options ) : '') . '>';
|
$string .= ($options ? (' ' . $options ) : '') . '>';
|
||||||
} else {
|
} else {
|
||||||
$string .= '<a>';
|
$string .= '>';
|
||||||
}
|
}
|
||||||
$string .= $label;
|
$string .= $label;
|
||||||
$string .= '</a>';
|
$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).'"'.
|
$options_html .= '<option value="'.htmlspecialchars($value, ENT_COMPAT | ENT_HTML401, ini_get('default_charset'), false).'"'.
|
||||||
($selected?' selected="selected"':'').
|
($selected?' selected="selected"':'').
|
||||||
($disabled?' disabled="disabled"':'').
|
($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;
|
return $options_html;
|
||||||
}
|
}
|
||||||
|
@ -776,7 +778,7 @@ function canStreamIframe() {
|
||||||
|
|
||||||
function canStreamNative() {
|
function canStreamNative() {
|
||||||
// Old versions of Chrome can display the stream, but then it blocks everything else (Chrome bug 5876)
|
// 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() {
|
function canStreamApplet() {
|
||||||
|
@ -908,11 +910,11 @@ function createListThumbnail($event, $overwrite=false) {
|
||||||
if ( ZM_WEB_LIST_THUMB_WIDTH ) {
|
if ( ZM_WEB_LIST_THUMB_WIDTH ) {
|
||||||
$thumbWidth = ZM_WEB_LIST_THUMB_WIDTH;
|
$thumbWidth = ZM_WEB_LIST_THUMB_WIDTH;
|
||||||
$scale = (SCALE_BASE*ZM_WEB_LIST_THUMB_WIDTH)/$event['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 ) {
|
} elseif ( ZM_WEB_LIST_THUMB_HEIGHT ) {
|
||||||
$thumbHeight = ZM_WEB_LIST_THUMB_HEIGHT;
|
$thumbHeight = ZM_WEB_LIST_THUMB_HEIGHT;
|
||||||
$scale = (SCALE_BASE*ZM_WEB_LIST_THUMB_HEIGHT)/$event['Height'];
|
$scale = (SCALE_BASE*ZM_WEB_LIST_THUMB_HEIGHT)/$event['Height'];
|
||||||
$thumbWidth = reScale( $event['Width'], $scale );
|
$thumbWidth = reScale($event['Width'], $scale);
|
||||||
} else {
|
} else {
|
||||||
ZM\Fatal('No thumbnail width or height specified, please check in Options->Web');
|
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.
|
# 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.
|
# I can't imagine why you would want to do that.
|
||||||
function reScale( $dimension, $dummy ) {
|
function reScale($dimension, $dummy) {
|
||||||
$new_dimension = $dimension;
|
$new_dimension = $dimension;
|
||||||
for ( $i = 1; $i < func_num_args(); $i++ ) {
|
for ( $i = 1; $i < func_num_args(); $i++ ) {
|
||||||
$scale = func_get_arg( $i );
|
$scale = func_get_arg($i);
|
||||||
if ( !empty($scale) && ($scale != 'auto') && ($scale != SCALE_BASE) )
|
if ( !empty($scale) && ($scale != '0') && ($scale != 'auto') && ($scale != SCALE_BASE) )
|
||||||
$new_dimension = (int)(($new_dimension*$scale)/SCALE_BASE);
|
$new_dimension = (int)(($new_dimension*$scale)/SCALE_BASE);
|
||||||
}
|
}
|
||||||
return $new_dimension;
|
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['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";
|
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[Query][terms][$i][attr]\" value=\"".htmlspecialchars($term['attr'])."\"/>\n";
|
||||||
switch ( $term['attr'] ) {
|
switch ( $term['attr'] ) {
|
||||||
|
case 'AlarmedZoneId':
|
||||||
|
$term['op'] = 'EXISTS';
|
||||||
|
break;
|
||||||
case 'MonitorName':
|
case 'MonitorName':
|
||||||
$filter['sql'] .= 'M.Name';
|
$filter['sql'] .= 'M.Name';
|
||||||
break;
|
break;
|
||||||
|
@ -1232,11 +1237,15 @@ function parseFilter(&$filter, $saveToSession=false, $querySep='&') {
|
||||||
$valueList = array();
|
$valueList = array();
|
||||||
foreach ( preg_split('/["\'\s]*?,["\'\s]*?/', preg_replace('/^["\']+?(.+)["\']+?$/', '$1', $term['val'])) as $value ) {
|
foreach ( preg_split('/["\'\s]*?,["\'\s]*?/', preg_replace('/^["\']+?(.+)["\']+?$/', '$1', $term['val'])) as $value ) {
|
||||||
switch ( $term['attr'] ) {
|
switch ( $term['attr'] ) {
|
||||||
|
|
||||||
|
case 'AlarmedZoneId':
|
||||||
|
$value = '(SELECT * FROM Stats WHERE EventId=E.Id AND ZoneId='.$value.')';
|
||||||
|
break;
|
||||||
case 'MonitorName':
|
case 'MonitorName':
|
||||||
case 'Name':
|
case 'Name':
|
||||||
case 'Cause':
|
case 'Cause':
|
||||||
case 'Notes':
|
case 'Notes':
|
||||||
if($term['op'] == 'LIKE' || $term['op'] == 'NOT LIKE') {
|
if ( $term['op'] == 'LIKE' || $term['op'] == 'NOT LIKE' ) {
|
||||||
$value = '%'.$value.'%';
|
$value = '%'.$value.'%';
|
||||||
}
|
}
|
||||||
$value = dbEscape($value);
|
$value = dbEscape($value);
|
||||||
|
@ -1267,8 +1276,11 @@ function parseFilter(&$filter, $saveToSession=false, $querySep='&') {
|
||||||
case 'Date':
|
case 'Date':
|
||||||
case 'StartDate':
|
case 'StartDate':
|
||||||
case 'EndDate':
|
case 'EndDate':
|
||||||
if ( $value != 'NULL' )
|
if ( $value == 'CURDATE()' or $value == 'NOW()' ) {
|
||||||
|
$value = 'to_days('.$value.')';
|
||||||
|
} else if ( $value != 'NULL' ) {
|
||||||
$value = 'to_days(\''.strftime(STRF_FMT_DATETIME_DB, strtotime($value)).'\')';
|
$value = 'to_days(\''.strftime(STRF_FMT_DATETIME_DB, strtotime($value)).'\')';
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'Time':
|
case 'Time':
|
||||||
case 'StartTime':
|
case 'StartTime':
|
||||||
|
@ -1303,10 +1315,13 @@ function parseFilter(&$filter, $saveToSession=false, $querySep='&') {
|
||||||
break;
|
break;
|
||||||
case '=[]' :
|
case '=[]' :
|
||||||
case 'IN' :
|
case 'IN' :
|
||||||
$filter['sql'] .= ' in ('.join(',', $valueList).')';
|
$filter['sql'] .= ' IN ('.join(',', $valueList).')';
|
||||||
break;
|
break;
|
||||||
case '![]' :
|
case '![]' :
|
||||||
$filter['sql'] .= ' not in ('.join(',', $valueList).')';
|
$filter['sql'] .= ' not in ('.join(',', $valueList).')';
|
||||||
|
break;
|
||||||
|
case 'EXISTS' :
|
||||||
|
$filter['sql'] .= ' EXISTS ' .$value;
|
||||||
break;
|
break;
|
||||||
case 'IS' :
|
case 'IS' :
|
||||||
if ( $value == 'Odd' ) {
|
if ( $value == 'Odd' ) {
|
||||||
|
@ -2289,7 +2304,7 @@ function validHtmlStr($input) {
|
||||||
function getStreamHTML($monitor, $options = array()) {
|
function getStreamHTML($monitor, $options = array()) {
|
||||||
|
|
||||||
if ( isset($options['scale']) ) {
|
if ( isset($options['scale']) ) {
|
||||||
if ( $options['scale'] != 'auto' ) {
|
if ( $options['scale'] and ( $options['scale'] != 'auto' ) ) {
|
||||||
$options['width'] = reScale($monitor->ViewWidth(), $options['scale']).'px';
|
$options['width'] = reScale($monitor->ViewWidth(), $options['scale']).'px';
|
||||||
$options['height'] = reScale($monitor->ViewHeight(), $options['scale']).'px';
|
$options['height'] = reScale($monitor->ViewHeight(), $options['scale']).'px';
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -18,32 +18,44 @@
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
//
|
//
|
||||||
|
|
||||||
function translate( $name ) {
|
function translate($name) {
|
||||||
global $SLANG;
|
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];
|
return $SLANG[$name];
|
||||||
else
|
else
|
||||||
return $name;
|
return $name;
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadLanguage( $prefix='' ) {
|
function loadLanguage($prefix='') {
|
||||||
global $user;
|
global $user;
|
||||||
|
|
||||||
if ( $prefix )
|
if ( $prefix )
|
||||||
$prefix = $prefix.'/';
|
$prefix = $prefix.'/';
|
||||||
|
|
||||||
$fallbackLangFile = $prefix.'lang/en_gb.php';
|
if ( isset($user['Language']) and $user['Language'] ) {
|
||||||
$systemLangFile = $prefix.'lang/'.ZM_LANG_DEFAULT.'.php';
|
|
||||||
if ( isset($user['Language']) )
|
|
||||||
$userLangFile = $prefix.'lang/'.$user['Language'].'.php';
|
$userLangFile = $prefix.'lang/'.$user['Language'].'.php';
|
||||||
|
|
||||||
if ( isset($userLangFile) && file_exists($userLangFile) )
|
if ( file_exists($userLangFile) ) {
|
||||||
return $userLangFile;
|
return $userLangFile;
|
||||||
elseif ( file_exists($systemLangFile) )
|
} else {
|
||||||
|
ZM\Warning("User language file $userLangFile does not exist.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$systemLangFile = $prefix.'lang/'.ZM_LANG_DEFAULT.'.php';
|
||||||
|
if ( file_exists($systemLangFile) ) {
|
||||||
return $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;
|
return $fallbackLangFile;
|
||||||
else
|
} else {
|
||||||
|
ZM\Error("Default language file $fallbackLangFile does not exist.");
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +63,7 @@ if ( $langFile = loadLanguage() ) {
|
||||||
require_once($langFile);
|
require_once($langFile);
|
||||||
require_once('lang/default.php');
|
require_once('lang/default.php');
|
||||||
foreach ($DLANG as $key => $value) {
|
foreach ($DLANG as $key => $value) {
|
||||||
if ( ! array_key_exists($key, $SLANG) )
|
if ( ! (isset($SLANG[$key]) || array_key_exists($key, $SLANG)) )
|
||||||
$SLANG[$key] = $DLANG[$key];
|
$SLANG[$key] = $DLANG[$key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ if ( version_compare(phpversion(), '4.1.0', '<') ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Useful debugging lines for mobile devices
|
// Useful debugging lines for mobile devices
|
||||||
if ( false ) {
|
if ( true ) {
|
||||||
ob_start();
|
ob_start();
|
||||||
phpinfo(INFO_VARIABLES);
|
phpinfo(INFO_VARIABLES);
|
||||||
$fp = fopen('/tmp/env.html', 'w+');
|
$fp = fopen('/tmp/env.html', 'w+');
|
||||||
|
@ -52,6 +52,8 @@ require_once('includes/Event.php');
|
||||||
require_once('includes/Group.php');
|
require_once('includes/Group.php');
|
||||||
require_once('includes/Monitor.php');
|
require_once('includes/Monitor.php');
|
||||||
|
|
||||||
|
$Servers = ZM\Server::find();
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on')
|
(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on')
|
||||||
or
|
or
|
||||||
|
@ -71,7 +73,7 @@ define('ZM_BASE_URL', '');
|
||||||
|
|
||||||
require_once('includes/functions.php');
|
require_once('includes/functions.php');
|
||||||
if ( $_SERVER['REQUEST_METHOD'] == 'OPTIONS' ) {
|
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
|
# Add Cross domain access headers
|
||||||
CORSHeaders();
|
CORSHeaders();
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -49,6 +49,8 @@ function logReport( level, message, file, line ) {
|
||||||
/* eslint-disable no-caller */
|
/* eslint-disable no-caller */
|
||||||
if ( arguments && arguments.callee && arguments.callee.caller && arguments.callee.caller.caller && arguments.callee.caller.caller.name ) {
|
if ( arguments && arguments.callee && arguments.callee.caller && arguments.callee.caller.caller && arguments.callee.caller.caller.name ) {
|
||||||
message += ' - '+arguments.callee.caller.caller.name+'()';
|
message += ' - '+arguments.callee.caller.caller.name+'()';
|
||||||
|
} else {
|
||||||
|
message += new Error().stack;
|
||||||
}
|
}
|
||||||
/* eslint-enable no-caller */
|
/* eslint-enable no-caller */
|
||||||
|
|
||||||
|
|
|
@ -51,8 +51,8 @@ var Overlay = new Class({
|
||||||
},
|
},
|
||||||
show: function() {
|
show: function() {
|
||||||
this.mask.show();
|
this.mask.show();
|
||||||
window.addEventListener( 'resize', this.update.bind(this) );
|
window.addEventListener( 'resize', this.update.bind(this), {passive: true} );
|
||||||
window.addEventListener( 'scroll', this.update.bind(this) );
|
window.addEventListener( 'scroll', this.update.bind(this), {passive: true} );
|
||||||
this.element.tween( 'opacity', [0, 1.0] );
|
this.element.tween( 'opacity', [0, 1.0] );
|
||||||
this.element.show();
|
this.element.show();
|
||||||
this.element.position();
|
this.element.position();
|
||||||
|
@ -80,8 +80,8 @@ var Overlay = new Class({
|
||||||
}
|
}
|
||||||
updateOverlayLoading();
|
updateOverlayLoading();
|
||||||
this.loading.setStyle( 'display', 'block' );
|
this.loading.setStyle( 'display', 'block' );
|
||||||
window.addEventListener( 'resize', this.update.bind(this) );
|
window.addEventListener( 'resize', this.update.bind(this), {passive: true} );
|
||||||
window.addEventListener( 'scroll', this.update.bind(this) );
|
window.addEventListener( 'scroll', this.update.bind(this), {passive: true} );
|
||||||
},
|
},
|
||||||
hideAnimation: function() {
|
hideAnimation: function() {
|
||||||
if ( this.loading ) {
|
if ( this.loading ) {
|
||||||
|
|
|
@ -116,6 +116,7 @@ $SLANG = array(
|
||||||
'Area' => 'Area',
|
'Area' => 'Area',
|
||||||
'AreaUnits' => 'Area (px/%)',
|
'AreaUnits' => 'Area (px/%)',
|
||||||
'AttrAlarmFrames' => 'Alarm Frames',
|
'AttrAlarmFrames' => 'Alarm Frames',
|
||||||
|
'AttrAlarmedZone' => 'Alarmed Zone',
|
||||||
'AttrArchiveStatus' => 'Archive Status',
|
'AttrArchiveStatus' => 'Archive Status',
|
||||||
'AttrAvgScore' => 'Avg. Score',
|
'AttrAvgScore' => 'Avg. Score',
|
||||||
'AttrCause' => 'Cause',
|
'AttrCause' => 'Cause',
|
||||||
|
@ -361,6 +362,9 @@ $SLANG = array(
|
||||||
'FilterCopyEvents' => 'Copy all matches',
|
'FilterCopyEvents' => 'Copy all matches',
|
||||||
'FilterMoveEvents' => 'Move all matches',
|
'FilterMoveEvents' => 'Move all matches',
|
||||||
'FilterEmailEvents' => 'Email details of all matches',
|
'FilterEmailEvents' => 'Email details of all matches',
|
||||||
|
'FilterEmailTo' => 'Email To',
|
||||||
|
'FilterEmailSubject' => 'Email Subject',
|
||||||
|
'FilterEmailBody' => 'Email Body',
|
||||||
'FilterExecuteEvents' => 'Execute command on all matches',
|
'FilterExecuteEvents' => 'Execute command on all matches',
|
||||||
'FilterLog' => 'Filter log',
|
'FilterLog' => 'Filter log',
|
||||||
'FilterMessageEvents' => 'Message details of all matches',
|
'FilterMessageEvents' => 'Message details of all matches',
|
||||||
|
|
|
@ -56,9 +56,14 @@ select {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
input[name="filter[EmailSubject]"],
|
||||||
|
input[name="filter[EmailTo]"],
|
||||||
|
textarea[name="filter[EmailBody]"] {
|
||||||
|
width: 500px;
|
||||||
|
}
|
||||||
select#Id {
|
select#Id {
|
||||||
min-width: 400px;
|
min-width: 500px;
|
||||||
}
|
}
|
||||||
.Name input {
|
.Name input {
|
||||||
min-width: 400px;
|
min-width: 500px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
textarea,
|
textarea,
|
||||||
input[name="newMonitor[Name]"] {
|
input[name="newMonitor[Name]"],
|
||||||
|
input[name="newMonitor[ControlDevice]"],
|
||||||
|
input[name="newMonitor[ControlAddress]"] {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
input[name="newMonitor[Width]"],
|
input[name="newMonitor[Width]"],
|
||||||
|
|
|
@ -31,7 +31,7 @@ $rates = array(
|
||||||
);
|
);
|
||||||
|
|
||||||
$scales = array(
|
$scales = array(
|
||||||
'auto' => translate('Scale to Fit'),
|
'0' => translate('Scale to Fit'),
|
||||||
'' => translate('Fixed Width/Height'),
|
'' => translate('Fixed Width/Height'),
|
||||||
'400' => '4x',
|
'400' => '4x',
|
||||||
'300' => '3x',
|
'300' => '3x',
|
||||||
|
@ -45,7 +45,7 @@ $scales = array(
|
||||||
'12.5' => '1/8x',
|
'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
|
unset($scales['auto']); //Remove auto on montage, use everywhere else
|
||||||
} else {
|
} else {
|
||||||
unset($scales['']); //Remove fixed on everything but montage
|
unset($scales['']); //Remove fixed on everything but montage
|
||||||
|
|
|
@ -352,7 +352,7 @@ if ( ZM_OPT_USE_AUTH and $user ) {
|
||||||
?>
|
?>
|
||||||
<p class="navbar-text">
|
<p class="navbar-text">
|
||||||
<i class="material-icons">account_circle</i>
|
<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>
|
</p>
|
||||||
<?php
|
<?php
|
||||||
}
|
}
|
||||||
|
@ -396,7 +396,7 @@ if ( (!ZM_OPT_USE_AUTH) or $user ) {
|
||||||
?>
|
?>
|
||||||
<li><?php echo translate('Storage') ?>:
|
<li><?php echo translate('Storage') ?>:
|
||||||
<?php
|
<?php
|
||||||
$storage_areas = ZM\Storage::find();
|
$storage_areas = ZM\Storage::find(array('Enabled'=>true));
|
||||||
$storage_paths = null;
|
$storage_paths = null;
|
||||||
$storage_areas_with_no_server_id = array();
|
$storage_areas_with_no_server_id = array();
|
||||||
foreach ( $storage_areas as $area ) {
|
foreach ( $storage_areas as $area ) {
|
||||||
|
|
|
@ -63,7 +63,7 @@ var popupSizes = {
|
||||||
'shutdown': {'width': 400, 'height': 400},
|
'shutdown': {'width': 400, 'height': 400},
|
||||||
'state': {'width': 400, 'height': 170},
|
'state': {'width': 400, 'height': 170},
|
||||||
'stats': {'width': 840, 'height': 200},
|
'stats': {'width': 840, 'height': 200},
|
||||||
'storage': {'width': 600, 'height': 405},
|
'storage': {'width': 600, 'height': 425},
|
||||||
'timeline': {'width': 760, 'height': 540},
|
'timeline': {'width': 760, 'height': 540},
|
||||||
'user': {'width': 460, 'height': 720},
|
'user': {'width': 460, 'height': 720},
|
||||||
'version': {'width': 360, 'height': 210},
|
'version': {'width': 360, 'height': 210},
|
||||||
|
|
|
@ -63,7 +63,7 @@ var popupSizes = {
|
||||||
'settings': {'width': 220, 'height': 225},
|
'settings': {'width': 220, 'height': 225},
|
||||||
'state': {'width': 370, 'height': 134},
|
'state': {'width': 370, 'height': 134},
|
||||||
'stats': {'width': 840, 'height': 200},
|
'stats': {'width': 840, 'height': 200},
|
||||||
'storage': {'width': 600, 'height': 405},
|
'storage': {'width': 600, 'height': 425},
|
||||||
'timeline': {'width': 760, 'height': 540},
|
'timeline': {'width': 760, 'height': 540},
|
||||||
'user': {'width': 360, 'height': 720},
|
'user': {'width': 360, 'height': 720},
|
||||||
'version': {'width': 360, 'height': 140},
|
'version': {'width': 360, 'height': 140},
|
||||||
|
|
|
@ -530,3 +530,17 @@ function scaleToFit(baseWidth, baseHeight, scaleEl, bottomEl) {
|
||||||
autoScale = closest;
|
autoScale = closest;
|
||||||
return {width: Math.floor(newWidth), height: Math.floor(newHeight), autoScale: autoScale};
|
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) ) {
|
if ( count($selected_monitor_ids) and ! in_array($monitors[$i]['Id'], $selected_monitor_ids) ) {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -40,7 +40,7 @@ if ( empty($_REQUEST['mode']) ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
$widths = array(
|
$widths = array(
|
||||||
'' => translate('auto'),
|
'auto' => translate('auto'),
|
||||||
'100%' => '100%',
|
'100%' => '100%',
|
||||||
'160px' => '160px',
|
'160px' => '160px',
|
||||||
'320px' => '320px',
|
'320px' => '320px',
|
||||||
|
@ -62,13 +62,11 @@ session_start();
|
||||||
|
|
||||||
if ( isset($_REQUEST['scale']) ) {
|
if ( isset($_REQUEST['scale']) ) {
|
||||||
$options['scale'] = validInt($_REQUEST['scale']);
|
$options['scale'] = validInt($_REQUEST['scale']);
|
||||||
ZM\Logger::Debug('Setting scale from request to '.$options['scale']);
|
|
||||||
} else if ( isset($_COOKIE['zmCycleScale']) ) {
|
} else if ( isset($_COOKIE['zmCycleScale']) ) {
|
||||||
$options['scale'] = $_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;
|
$options['scale'] = 100;
|
||||||
|
|
||||||
if ( isset($_COOKIE['zmCycleWidth']) and $_COOKIE['zmCycleWidth'] ) {
|
if ( isset($_COOKIE['zmCycleWidth']) and $_COOKIE['zmCycleWidth'] ) {
|
||||||
|
|
|
@ -48,7 +48,7 @@ if ( isset($_REQUEST['scale']) ) {
|
||||||
$scale = validInt($_REQUEST['scale']);
|
$scale = validInt($_REQUEST['scale']);
|
||||||
} else if ( isset($_COOKIE['zmEventScaleAuto']) ) {
|
} else if ( isset($_COOKIE['zmEventScaleAuto']) ) {
|
||||||
// If we're using scale to fit use it on all monitors
|
// If we're using scale to fit use it on all monitors
|
||||||
$scale = 'auto';
|
$scale = '0';
|
||||||
} else if ( isset($_COOKIE['zmEventScale'.$Event->MonitorId()]) ) {
|
} else if ( isset($_COOKIE['zmEventScale'.$Event->MonitorId()]) ) {
|
||||||
$scale = $_COOKIE['zmEventScale'.$Event->MonitorId()];
|
$scale = $_COOKIE['zmEventScale'.$Event->MonitorId()];
|
||||||
} else {
|
} else {
|
||||||
|
@ -85,9 +85,9 @@ else
|
||||||
$streamMode = 'video';
|
$streamMode = 'video';
|
||||||
|
|
||||||
$replayMode = '';
|
$replayMode = '';
|
||||||
if ( isset( $_REQUEST['replayMode'] ) )
|
if ( isset($_REQUEST['replayMode']) )
|
||||||
$replayMode = validHtmlStr($_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']);
|
$replayMode = validHtmlStr($_COOKIE['replayMode']);
|
||||||
|
|
||||||
if ( ( ! $replayMode ) or ( ! $replayModes[$replayMode] ) ) {
|
if ( ( ! $replayMode ) or ( ! $replayModes[$replayMode] ) ) {
|
||||||
|
@ -104,7 +104,10 @@ if ( $Monitor->VideoWriter() == '2' ) {
|
||||||
$Zoom = $Event->Height()/$Event->Width();
|
$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();
|
parseSort();
|
||||||
parseFilter($_REQUEST['filter']);
|
parseFilter($_REQUEST['filter']);
|
||||||
$filterQuery = $_REQUEST['filter']['query'];
|
$filterQuery = $_REQUEST['filter']['query'];
|
||||||
|
@ -122,7 +125,7 @@ xhtmlHeaders(__FILE__, translate('Event'));
|
||||||
<?php if ( !$popup ) echo getNavBarHTML() ?>
|
<?php if ( !$popup ) echo getNavBarHTML() ?>
|
||||||
<div id="header">
|
<div id="header">
|
||||||
<?php
|
<?php
|
||||||
if ( ! $Event->Id() ) {
|
if ( !$Event->Id() ) {
|
||||||
echo 'Event was not found.';
|
echo 'Event was not found.';
|
||||||
} else {
|
} else {
|
||||||
?>
|
?>
|
||||||
|
@ -193,9 +196,9 @@ if ( ($codec == 'MP4' || $codec == 'auto' ) && $Event->DefaultVideo() ) {
|
||||||
?>
|
?>
|
||||||
<div id="videoFeed">
|
<div id="videoFeed">
|
||||||
<video id="videoobj" class="video-js vjs-default-skin"
|
<video id="videoobj" class="video-js vjs-default-skin"
|
||||||
style="transform: matrix(1, 0, 0, 1, 0, 0)"
|
style="transform: matrix(1, 0, 0, 1, 0, 0);"
|
||||||
width="<?php echo reScale($Event->Width(), $scale) ?>"
|
<?php echo $scale ? 'width="'.reScale($Event->Width(), $scale).'"' : '' ?>
|
||||||
height="<?php echo reScale($Event->Height(), $scale) ?>"
|
<?php echo $scale ? 'height="'.reScale($Event->Height(), $scale).'"' : '' ?>
|
||||||
data-setup='{ "controls": true, "autoplay": true, "preload": "auto", "plugins": { "zoomrotate": { "zoom": "<?php echo $Zoom ?>"}}}'
|
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">
|
<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">
|
<div id="imageFeed">
|
||||||
<?php
|
<?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),'&');
|
$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 );
|
outputVideoStream('evtStream', $streamSrc, reScale( $Event->Width(), $scale ).'px', reScale( $Event->Height(), $scale ).'px', ZM_MPEG_LIVE_FORMAT );
|
||||||
} else {
|
} else {
|
||||||
|
@ -257,7 +260,12 @@ if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT ) {
|
||||||
</p>
|
</p>
|
||||||
<div id="replayStatus">
|
<div id="replayStatus">
|
||||||
<span id="mode"><?php echo translate('Mode') ?>: <span id="modeValue">Replay</span></span>
|
<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="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>
|
<span id="zoom"><?php echo translate('Zoom') ?>: <span id="zoomValue">1</span>x</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -191,21 +191,25 @@ while ( $event_row = dbFetchNext($results) ) {
|
||||||
?>
|
?>
|
||||||
<tr<?php if ($event->Archived()) echo ' class="archived"' ?>>
|
<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="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="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()).'"' ) ?>
|
<td class="colCause"><?php echo makePopupLink( '?view=eventdetail&eid='.$event->Id(), 'zmEventDetail', 'eventdetail', validHtmlStr($event->Cause()), canEdit( 'Events' ), 'title="'.htmlspecialchars($event->Notes()).'"' ) ?>
|
||||||
<?php
|
<?php
|
||||||
# display notes as small text
|
# display notes as small text
|
||||||
if ($event->Notes()) {
|
if ( $event->Notes() ) {
|
||||||
# if notes include detection objects, then link it to objdetect.jpg
|
# 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
|
# make a link
|
||||||
echo makePopupLink( '?view=image&eid='.$event->Id().'&fid=objdetect', 'zmImage',
|
echo makePopupLink( '?view=image&eid='.$event->Id().'&fid=objdetect', 'zmImage',
|
||||||
array('image', reScale($event->Width(), $scale), reScale($event->Height(), $scale)),
|
array('image', reScale($event->Width(), $scale), reScale($event->Height(), $scale)),
|
||||||
"<div class=\"small text-nowrap text-muted\"><u>".$event->Notes()."</u></div>");
|
'<div class="small text-nowrap text-muted"><u>'.$event->Notes().'</u></div>');
|
||||||
}
|
} else if ( $event->Notes() != 'Forced Web: ' ) {
|
||||||
elseif ($event->Notes() != 'Forced Web: ') {
|
echo '<br/><div class="small text-nowrap text-muted">'.$event->Notes().'</div>';
|
||||||
echo "<br/><div class=\"small text-nowrap text-muted\">".$event->Notes()."</div>";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
//
|
//
|
||||||
// ZoneMinder web filter view file, $Date$, $Revision$
|
// ZoneMinder web filter view file
|
||||||
// Copyright (C) 2001-2008 Philip Coombes
|
// Copyright (C) 2001-2008 Philip Coombes
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or
|
// 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/Object.php');
|
||||||
require_once('includes/Storage.php');
|
require_once('includes/Storage.php');
|
||||||
require_once('includes/Filter.php');
|
require_once('includes/Filter.php');
|
||||||
|
require_once('includes/Monitor.php');
|
||||||
|
require_once('includes/Zone.php');
|
||||||
parseSort();
|
parseSort();
|
||||||
|
|
||||||
$filterNames = array(''=>translate('ChooseFilter'));
|
$filterNames = array(''=>translate('ChooseFilter'));
|
||||||
|
@ -69,6 +71,7 @@ if ( count($terms) ) {
|
||||||
|
|
||||||
$attrTypes = array(
|
$attrTypes = array(
|
||||||
'AlarmFrames' => translate('AttrAlarmFrames'),
|
'AlarmFrames' => translate('AttrAlarmFrames'),
|
||||||
|
'AlarmedZoneId' => translate('AttrAlarmedZone'),
|
||||||
'Archived' => translate('AttrArchiveStatus'),
|
'Archived' => translate('AttrArchiveStatus'),
|
||||||
'AvgScore' => translate('AttrAvgScore'),
|
'AvgScore' => translate('AttrAvgScore'),
|
||||||
'Cause' => translate('AttrCause'),
|
'Cause' => translate('AttrCause'),
|
||||||
|
@ -78,17 +81,17 @@ $attrTypes = array(
|
||||||
'EndDateTime' => translate('AttrEndDateTime'),
|
'EndDateTime' => translate('AttrEndDateTime'),
|
||||||
'EndDate' => translate('AttrEndDate'),
|
'EndDate' => translate('AttrEndDate'),
|
||||||
'EndTime' => translate('AttrEndTime'),
|
'EndTime' => translate('AttrEndTime'),
|
||||||
|
'EndWeekday' => translate('AttrEndWeekday'),
|
||||||
'FilterServerId' => translate('AttrFilterServer'),
|
'FilterServerId' => translate('AttrFilterServer'),
|
||||||
'Frames' => translate('AttrFrames'),
|
'Frames' => translate('AttrFrames'),
|
||||||
'EndWeekday' => translate('AttrEndWeekday'),
|
|
||||||
'Id' => translate('AttrId'),
|
'Id' => translate('AttrId'),
|
||||||
'Length' => translate('AttrDuration'),
|
'Length' => translate('AttrDuration'),
|
||||||
'Name' => translate('AttrName'),
|
|
||||||
'Notes' => translate('AttrNotes'),
|
|
||||||
'MaxScore' => translate('AttrMaxScore'),
|
'MaxScore' => translate('AttrMaxScore'),
|
||||||
'MonitorId' => translate('AttrMonitorId'),
|
'MonitorId' => translate('AttrMonitorId'),
|
||||||
'MonitorName' => translate('AttrMonitorName'),
|
'MonitorName' => translate('AttrMonitorName'),
|
||||||
'MonitorServerId' => translate('AttrMonitorServer'),
|
'MonitorServerId' => translate('AttrMonitorServer'),
|
||||||
|
'Name' => translate('AttrName'),
|
||||||
|
'Notes' => translate('AttrNotes'),
|
||||||
'SecondaryStorageId' => translate('AttrSecondaryStorageArea'),
|
'SecondaryStorageId' => translate('AttrSecondaryStorageArea'),
|
||||||
'ServerId' => translate('AttrMonitorServer'),
|
'ServerId' => translate('AttrMonitorServer'),
|
||||||
'StartDateTime' => translate('AttrStartDateTime'),
|
'StartDateTime' => translate('AttrStartDateTime'),
|
||||||
|
@ -143,13 +146,22 @@ foreach ( dbFetchAll('SELECT `Id`, `Name` FROM `Servers` ORDER BY lower(`Name`)
|
||||||
$servers[$server['Id']] = validHtmlStr($server['Name']);
|
$servers[$server['Id']] = validHtmlStr($server['Name']);
|
||||||
}
|
}
|
||||||
$monitors = array();
|
$monitors = array();
|
||||||
|
$monitor_names = array();
|
||||||
foreach ( dbFetchAll('SELECT `Id`, `Name` FROM `Monitors` ORDER BY lower(`Name`) ASC') as $monitor ) {
|
foreach ( dbFetchAll('SELECT `Id`, `Name` FROM `Monitors` ORDER BY lower(`Name`) ASC') as $monitor ) {
|
||||||
if ( visibleMonitor($monitor['Id']) ) {
|
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>
|
<body>
|
||||||
<div id="page">
|
<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][op]", $opTypes, $term['op']); ?></td>
|
||||||
<td><?php echo htmlSelect("filter[Query][terms][$i][val]", $weekdays, $term['val']); ?></td>
|
<td><?php echo htmlSelect("filter[Query][terms][$i][val]", $weekdays, $term['val']); ?></td>
|
||||||
<?php
|
<?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][op]", $opTypes, $term['op']); ?></td>
|
||||||
<td><?php echo htmlSelect("filter[Query][terms][$i][val]", $monitors, $term['val']); ?></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
|
<?php
|
||||||
} elseif ( $term['attr'] == 'ServerId' || $term['attr'] == 'MonitorServerId' || $term['attr'] == 'StorageServerId' || $term['attr'] == 'FilterServerId' ) {
|
} 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][op]", $opTypes, $term['op']); ?></td>
|
||||||
<td><?php echo htmlSelect("filter[Query][terms][$i][val]", $storageareas, $term['val']); ?></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
|
<?php
|
||||||
} else {
|
} else {
|
||||||
?>
|
?>
|
||||||
|
@ -365,8 +387,22 @@ if ( ZM_OPT_EMAIL ) {
|
||||||
?>
|
?>
|
||||||
<p>
|
<p>
|
||||||
<label><?php echo translate('FilterEmailEvents') ?></label>
|
<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>
|
</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
|
<?php
|
||||||
}
|
}
|
||||||
if ( ZM_OPT_MESSAGE ) {
|
if ( ZM_OPT_MESSAGE ) {
|
||||||
|
@ -409,7 +445,7 @@ if ( ZM_OPT_MESSAGE ) {
|
||||||
<hr/>
|
<hr/>
|
||||||
<div id="contentButtons">
|
<div id="contentButtons">
|
||||||
<button type="submit" data-on-click-this="submitToEvents"><?php echo translate('ListMatches') ?></button>
|
<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" 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>
|
<button type="button" name="executeButton" id="executeButton" data-on-click-this="executeFilter"><?php echo translate('Execute') ?></button>
|
||||||
<?php
|
<?php
|
||||||
|
|
|
@ -46,7 +46,7 @@ function changeSize() {
|
||||||
// Scale the frame
|
// Scale the frame
|
||||||
monitor_frame = $j('#imageFeed');
|
monitor_frame = $j('#imageFeed');
|
||||||
if ( !monitor_frame ) {
|
if ( !monitor_frame ) {
|
||||||
console.log("Error finding frame");
|
console.log('Error finding frame');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ( width ) {
|
if ( width ) {
|
||||||
|
@ -92,15 +92,21 @@ function changeScale() {
|
||||||
// Scale the frame
|
// Scale the frame
|
||||||
monitor_frame = $j('#imageFeed');
|
monitor_frame = $j('#imageFeed');
|
||||||
if ( !monitor_frame ) {
|
if ( !monitor_frame ) {
|
||||||
console.log("Error finding frame");
|
console.log('Error finding frame');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( scale != '0' ) {
|
||||||
if ( newWidth ) {
|
if ( newWidth ) {
|
||||||
monitor_frame.css('width', newWidth+'px');
|
monitor_frame.css('width', newWidth+'px');
|
||||||
}
|
}
|
||||||
if ( newHeight ) {
|
if ( newHeight ) {
|
||||||
monitor_frame.css('height', newHeight+'px');
|
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*/
|
/*Stream could be an applet so can't use moo tools*/
|
||||||
var streamImg = $j('#liveStream'+monitorData[monIdx].id)[0];
|
var streamImg = $j('#liveStream'+monitorData[monIdx].id)[0];
|
||||||
if ( streamImg ) {
|
if ( streamImg ) {
|
||||||
|
@ -110,12 +116,22 @@ function changeScale() {
|
||||||
|
|
||||||
//src = src.replace(/rand=\d+/i,'rand='+Math.floor((Math.random() * 1000000) ));
|
//src = src.replace(/rand=\d+/i,'rand='+Math.floor((Math.random() * 1000000) ));
|
||||||
src = src.replace(/scale=[\.\d]+/i, 'scale='+scale);
|
src = src.replace(/scale=[\.\d]+/i, 'scale='+scale);
|
||||||
|
if ( scale != '0' ) {
|
||||||
src = src.replace(/width=[\.\d]+/i, 'width='+newWidth);
|
src = src.replace(/width=[\.\d]+/i, 'width='+newWidth);
|
||||||
src = src.replace(/height=[\.\d]+/i, 'height='+newHeight);
|
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.src = src;
|
||||||
}
|
}
|
||||||
streamImg.style.width = newWidth + 'px';
|
if ( scale != '0' ) {
|
||||||
streamImg.style.height = newHeight + 'px';
|
streamImg.style.width = newWidth+'px';
|
||||||
|
streamImg.style.height = newHeight+'px';
|
||||||
|
} else {
|
||||||
|
streamImg.style.width = '100%';
|
||||||
|
streamImg.style.height = 'auto';
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log("Did not find liveStream"+monitorData[monIdx].id);
|
console.log("Did not find liveStream"+monitorData[monIdx].id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
var vid = null;
|
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 called when video.js hits the end of the video
|
||||||
function vjsReplay() {
|
function vjsReplay() {
|
||||||
|
@ -39,7 +42,7 @@ function vjsReplay() {
|
||||||
streamNext(true);
|
streamNext(true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
} // end function vjsReplay
|
||||||
|
|
||||||
$j.ajaxSetup({timeout: AJAX_TIMEOUT}); //sets timeout for all getJSON.
|
$j.ajaxSetup({timeout: AJAX_TIMEOUT}); //sets timeout for all getJSON.
|
||||||
|
|
||||||
|
@ -67,14 +70,14 @@ function renderAlarmCues(containerEl) {
|
||||||
var spanTimeStart = 0;
|
var spanTimeStart = 0;
|
||||||
var spanTimeEnd = 0;
|
var spanTimeEnd = 0;
|
||||||
var alarmed = 0;
|
var alarmed = 0;
|
||||||
var alarmHtml = "";
|
var alarmHtml = '';
|
||||||
var pixSkew = 0;
|
var pixSkew = 0;
|
||||||
var skip = 0;
|
var skip = 0;
|
||||||
var num_cueFrames = cueFrames.length;
|
var num_cueFrames = cueFrames.length;
|
||||||
for ( var i = 0; i < num_cueFrames; i++ ) {
|
for ( var i = 0; i < num_cueFrames; i++ ) {
|
||||||
skip = 0;
|
skip = 0;
|
||||||
frame = cueFrames[i];
|
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;
|
alarmed = 1;
|
||||||
if (frame.Delta == 0) continue; //If event starts with an alarm or too few for a nonespan
|
if (frame.Delta == 0) continue; //If event starts with an alarm or too few for a nonespan
|
||||||
spanTimeEnd = frame.Delta * 100;
|
spanTimeEnd = frame.Delta * 100;
|
||||||
|
@ -88,24 +91,24 @@ function renderAlarmCues(containerEl) {
|
||||||
}
|
}
|
||||||
alarmHtml += '<span class="alarmCue noneCue" style="width: ' + pix + 'px;"></span>';
|
alarmHtml += '<span class="alarmCue noneCue" style="width: ' + pix + 'px;"></span>';
|
||||||
spanTimeStart = spanTimeEnd;
|
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;
|
futNone = 0;
|
||||||
indexPlus = i+1;
|
indexPlus = i+1;
|
||||||
if (((frame.Delta * 100) - spanTimeStart) < minAlarm && indexPlus < num_cueFrames) {
|
if (((frame.Delta * 100) - spanTimeStart) < minAlarm && indexPlus < num_cueFrames) {
|
||||||
//alarm is too short and there is more event
|
//alarm is too short and there is more event
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
while (futNone < minAlarm) { //check ahead to see if there's enough for a nonespan
|
while ( futNone < minAlarm ) { //check ahead to see if there's enough for a nonespan
|
||||||
if (indexPlus >= cueFrames.length) break; //check if end of event.
|
if ( indexPlus >= cueFrames.length ) break; //check if end of event.
|
||||||
futNone = (cueFrames[indexPlus].Delta *100) - (frame.Delta *100);
|
futNone = (cueFrames[indexPlus].Delta *100) - (frame.Delta *100);
|
||||||
if (cueFrames[indexPlus].Type == "Alarm") {
|
if ( cueFrames[indexPlus].Type == 'Alarm' ) {
|
||||||
i = --indexPlus;
|
i = --indexPlus;
|
||||||
skip = 1;
|
skip = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
indexPlus++;
|
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;
|
spanTimeEnd = frame.Delta *100;
|
||||||
spanTime = spanTimeEnd - spanTimeStart;
|
spanTime = spanTimeEnd - spanTimeStart;
|
||||||
alarmed = 0;
|
alarmed = 0;
|
||||||
|
@ -118,7 +121,7 @@ function renderAlarmCues(containerEl) {
|
||||||
}
|
}
|
||||||
alarmHtml += '<span class="alarmCue" style="width: ' + pix + 'px;"></span>';
|
alarmHtml += '<span class="alarmCue" style="width: ' + pix + 'px;"></span>';
|
||||||
spanTimeStart = spanTimeEnd;
|
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;
|
spanTimeEnd = frame.Delta * 100;
|
||||||
spanTime = spanTimeEnd - spanTimeStart;
|
spanTime = spanTimeEnd - spanTimeStart;
|
||||||
alarmed = 0;
|
alarmed = 0;
|
||||||
|
@ -130,18 +133,6 @@ function renderAlarmCues(containerEl) {
|
||||||
return alarmHtml;
|
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() {
|
function changeCodec() {
|
||||||
location.replace(thisUrl + '?view=event&eid=' + eventData.Id + filterQuery + sortQuery+'&codec='+$j('#codec').val());
|
location.replace(thisUrl + '?view=event&eid=' + eventData.Id + filterQuery + sortQuery+'&codec='+$j('#codec').val());
|
||||||
|
@ -155,12 +146,12 @@ function changeScale() {
|
||||||
var eventViewer;
|
var eventViewer;
|
||||||
var alarmCue = $j('div.alarmCue');
|
var alarmCue = $j('div.alarmCue');
|
||||||
var bottomEl = streamMode == 'stills' ? $j('#eventImageNav') : $j('#replayStatus');
|
var bottomEl = streamMode == 'stills' ? $j('#eventImageNav') : $j('#replayStatus');
|
||||||
if (streamMode == 'stills') {
|
if ( streamMode == 'stills' ) {
|
||||||
eventViewer = $j('#eventThumbs');
|
eventViewer = $j('#eventThumbs');
|
||||||
} else {
|
} else {
|
||||||
eventViewer = $j(vid ? '#videoobj' : '#evtStream');
|
eventViewer = $j(vid ? '#videoobj' : '#evtStream');
|
||||||
}
|
}
|
||||||
if ( scale == "auto" ) {
|
if ( scale == '0' || scale == 'auto' ) {
|
||||||
var newSize = scaleToFit(eventData.Width, eventData.Height, eventViewer, bottomEl);
|
var newSize = scaleToFit(eventData.Width, eventData.Height, eventViewer, bottomEl);
|
||||||
newWidth = newSize.width;
|
newWidth = newSize.width;
|
||||||
newHeight = newSize.height;
|
newHeight = newSize.height;
|
||||||
|
@ -172,10 +163,10 @@ function changeScale() {
|
||||||
}
|
}
|
||||||
if ( !(streamMode == 'stills') ) {
|
if ( !(streamMode == 'stills') ) {
|
||||||
eventViewer.width(newWidth);
|
eventViewer.width(newWidth);
|
||||||
} //stills handles its own width
|
} // stills handles its own width
|
||||||
eventViewer.height(newHeight);
|
eventViewer.height(newHeight);
|
||||||
if ( !vid ) { // zms needs extra sizing
|
if ( !vid ) { // zms needs extra sizing
|
||||||
streamScale(scale == "auto" ? autoScale : scale);
|
streamScale(scale == '0' ? autoScale : scale);
|
||||||
drawProgressBar();
|
drawProgressBar();
|
||||||
}
|
}
|
||||||
if ( streamMode == 'stills' ) {
|
if ( streamMode == 'stills' ) {
|
||||||
|
@ -184,7 +175,7 @@ function changeScale() {
|
||||||
} else {
|
} else {
|
||||||
alarmCue.html(renderAlarmCues(eventViewer));//just re-render alarmCues. skip ajax call
|
alarmCue.html(renderAlarmCues(eventViewer));//just re-render alarmCues. skip ajax call
|
||||||
}
|
}
|
||||||
if ( scale == "auto" ) {
|
if ( scale == '0' ) {
|
||||||
Cookie.write('zmEventScaleAuto', 'auto', {duration: 10*365});
|
Cookie.write('zmEventScaleAuto', 'auto', {duration: 10*365});
|
||||||
} else {
|
} else {
|
||||||
Cookie.write('zmEventScale'+eventData.MonitorId, scale, {duration: 10*365});
|
Cookie.write('zmEventScale'+eventData.MonitorId, scale, {duration: 10*365});
|
||||||
|
@ -200,6 +191,32 @@ function changeReplayMode() {
|
||||||
refreshWindow();
|
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;
|
var streamParms = "view=request&request=stream&connkey="+connKey;
|
||||||
if ( auth_hash ) {
|
if ( auth_hash ) {
|
||||||
streamParms += '&auth='+auth_hash;
|
streamParms += '&auth='+auth_hash;
|
||||||
|
@ -245,7 +262,8 @@ function getCmdResponse( respObj, respText ) {
|
||||||
if ( streamStatus.paused == true ) {
|
if ( streamStatus.paused == true ) {
|
||||||
streamPause( );
|
streamPause( );
|
||||||
} else {
|
} 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});
|
Cookie.write('zmEventRate', streamStatus.rate*100, {duration: 10*365});
|
||||||
streamPlay( );
|
streamPlay( );
|
||||||
}
|
}
|
||||||
|
@ -280,23 +298,18 @@ var streamReq = new Request.JSON( {
|
||||||
|
|
||||||
function pauseClicked() {
|
function pauseClicked() {
|
||||||
if ( vid ) {
|
if ( vid ) {
|
||||||
|
if ( intervalRewind ) {
|
||||||
|
stopFastRev();
|
||||||
|
}
|
||||||
vid.pause();
|
vid.pause();
|
||||||
} else {
|
} else {
|
||||||
streamReq.send(streamParms+"&command="+CMD_PAUSE);
|
streamReq.send(streamParms+"&command="+CMD_PAUSE);
|
||||||
streamPause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function vjsPause() {
|
|
||||||
if ( intervalRewind ) {
|
|
||||||
stopFastRev();
|
|
||||||
}
|
}
|
||||||
streamPause();
|
streamPause();
|
||||||
}
|
}
|
||||||
|
|
||||||
function streamPause( ) {
|
function streamPause( ) {
|
||||||
$j('#modeValue').html('Paused');
|
$j('#modeValue').html('Paused');
|
||||||
$j('#rateValue').html('0');
|
|
||||||
setButtonState( $('pauseBtn'), 'active' );
|
setButtonState( $('pauseBtn'), 'active' );
|
||||||
setButtonState( $('playBtn'), 'inactive' );
|
setButtonState( $('playBtn'), 'inactive' );
|
||||||
setButtonState( $('fastFwdBtn'), 'unavail' );
|
setButtonState( $('fastFwdBtn'), 'unavail' );
|
||||||
|
@ -306,6 +319,10 @@ function streamPause( ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function playClicked( ) {
|
function playClicked( ) {
|
||||||
|
var rate_select = $j('select[name="rate"]');
|
||||||
|
if ( ! rate_select.val() ) {
|
||||||
|
$j('select[name="rate"]').val(100);
|
||||||
|
}
|
||||||
if ( vid ) {
|
if ( vid ) {
|
||||||
if ( vid.paused() ) {
|
if ( vid.paused() ) {
|
||||||
vid.play();
|
vid.play();
|
||||||
|
@ -314,21 +331,20 @@ function playClicked( ) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
streamReq.send(streamParms+"&command="+CMD_PLAY);
|
streamReq.send(streamParms+"&command="+CMD_PLAY);
|
||||||
streamPlay();
|
|
||||||
}
|
}
|
||||||
|
streamPlay();
|
||||||
}
|
}
|
||||||
|
|
||||||
function vjsPlay() { //catches if we change mode programatically
|
function vjsPlay() { //catches if we change mode programatically
|
||||||
if ( intervalRewind ) {
|
if ( intervalRewind ) {
|
||||||
stopFastRev();
|
stopFastRev();
|
||||||
}
|
}
|
||||||
$j('#rateValue').html(vid.playbackRate());
|
$j('select[name="rate"]').val(vid.playbackRate()*100);
|
||||||
Cookie.write('zmEventRate', vid.playbackRate()*100, {duration: 10*365});
|
Cookie.write('zmEventRate', vid.playbackRate()*100, {duration: 10*365});
|
||||||
streamPlay();
|
streamPlay();
|
||||||
}
|
}
|
||||||
|
|
||||||
function streamPlay( ) {
|
function streamPlay( ) {
|
||||||
$j('#modeValue').html('Replay');
|
|
||||||
setButtonState( $('pauseBtn'), 'inactive' );
|
setButtonState( $('pauseBtn'), 'inactive' );
|
||||||
setButtonState( $('playBtn'), 'active' );
|
setButtonState( $('playBtn'), 'active' );
|
||||||
setButtonState( $('fastFwdBtn'), 'inactive' );
|
setButtonState( $('fastFwdBtn'), 'inactive' );
|
||||||
|
@ -350,16 +366,13 @@ function streamFastFwd( action ) {
|
||||||
if ( rates.indexOf(vid.playbackRate()*100)-1 == -1 ) {
|
if ( rates.indexOf(vid.playbackRate()*100)-1 == -1 ) {
|
||||||
setButtonState($('fastFwdBtn'), 'unavail');
|
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});
|
Cookie.write('zmEventRate', vid.playbackRate()*100, {duration: 10*365});
|
||||||
} else {
|
} else {
|
||||||
streamReq.send(streamParms+"&command="+CMD_FASTFWD);
|
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 ) {
|
function streamSlowFwd( action ) {
|
||||||
if ( vid ) {
|
if ( vid ) {
|
||||||
|
@ -380,6 +393,7 @@ function streamSlowRev( action ) {
|
||||||
function stopFastRev() {
|
function stopFastRev() {
|
||||||
clearInterval(intervalRewind);
|
clearInterval(intervalRewind);
|
||||||
vid.playbackRate(1);
|
vid.playbackRate(1);
|
||||||
|
$j('select[name="rate"]').val(vid.playbackRate()*100);
|
||||||
Cookie.write('zmEventRate', vid.playbackRate()*100, {duration: 10*365});
|
Cookie.write('zmEventRate', vid.playbackRate()*100, {duration: 10*365});
|
||||||
revSpeed = .5;
|
revSpeed = .5;
|
||||||
}
|
}
|
||||||
|
@ -397,7 +411,7 @@ function streamFastRev( action ) {
|
||||||
setButtonState( $('fastRevBtn'), 'unavail' );
|
setButtonState( $('fastRevBtn'), 'unavail' );
|
||||||
}
|
}
|
||||||
clearInterval(intervalRewind);
|
clearInterval(intervalRewind);
|
||||||
$j('#rateValue').html(-revSpeed);
|
$j('select[name="rate"]').val(-revSpeed*100);
|
||||||
Cookie.write('zmEventRate', vid.playbackRate()*100, {duration: 10*365});
|
Cookie.write('zmEventRate', vid.playbackRate()*100, {duration: 10*365});
|
||||||
intervalRewind = setInterval(function() {
|
intervalRewind = setInterval(function() {
|
||||||
if (vid.currentTime() <= 0) {
|
if (vid.currentTime() <= 0) {
|
||||||
|
@ -588,7 +602,7 @@ function getEventResponse(respObj, respText) {
|
||||||
CurEventDefVideoPath = null;
|
CurEventDefVideoPath = null;
|
||||||
$j('#modeValue').html('Replay');
|
$j('#modeValue').html('Replay');
|
||||||
$j('#zoomValue').html('1');
|
$j('#zoomValue').html('1');
|
||||||
$j('#rateValue').html('1');
|
$j('#rate').val('100');
|
||||||
vjsPanZoom('zoomOut');
|
vjsPanZoom('zoomOut');
|
||||||
} else {
|
} else {
|
||||||
drawProgressBar();
|
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
|
$j('.vjs-progress-control').append('<div class="alarmCue"></div>');//add a place for videojs only on first load
|
||||||
vid.on('ended', vjsReplay);
|
vid.on('ended', vjsReplay);
|
||||||
vid.on('play', vjsPlay);
|
vid.on('play', vjsPlay);
|
||||||
vid.on('pause', vjsPause);
|
vid.on('pause', pauseClicked);
|
||||||
vid.on('click', function(event) {
|
vid.on('click', function(event) {
|
||||||
handleClick(event);
|
handleClick(event);
|
||||||
});
|
});
|
||||||
|
@ -1067,7 +1081,8 @@ function initPage() {
|
||||||
$j('#progressValue').html(secsToTime(Math.floor(vid.currentTime())));
|
$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.
|
// rate should be 100 = 1x, etc.
|
||||||
vid.playbackRate(rate/100);
|
vid.playbackRate(rate/100);
|
||||||
}
|
}
|
||||||
|
@ -1091,7 +1106,10 @@ function initPage() {
|
||||||
}
|
}
|
||||||
nearEventsQuery(eventData.Id);
|
nearEventsQuery(eventData.Id);
|
||||||
initialAlarmCues(eventData.Id); //call ajax+renderAlarmCues
|
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
|
// 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) {
|
function click_automove(element) {
|
||||||
updateButtons(this);
|
updateButtons(this);
|
||||||
if ( this.checked ) {
|
if ( this.checked ) {
|
||||||
|
@ -105,10 +114,11 @@ function submitToEvents( element ) {
|
||||||
history.replaceState(null, null, '?view=filter&' + $j(form).serialize());
|
history.replaceState(null, null, '?view=filter&' + $j(form).serialize());
|
||||||
}
|
}
|
||||||
|
|
||||||
function submitToMontageReview( element ) {
|
function submitToMontageReview(element) {
|
||||||
var form = element.form;
|
var form = element.form;
|
||||||
form.action = thisUrl + '?view=montagereview';
|
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) {
|
function submitToExport(element) {
|
||||||
|
@ -183,7 +193,8 @@ function parseRows(rows) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var attr = inputTds.eq(2).children().val();
|
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="=">');
|
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]');
|
var archiveSelect = $j('<select></select>').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]');
|
||||||
for (var i = 0; i < archiveTypes.length; i++) {
|
for (var i = 0; i < archiveTypes.length; i++) {
|
||||||
|
@ -191,6 +202,18 @@ function parseRows(rows) {
|
||||||
}
|
}
|
||||||
var archiveVal = inputTds.eq(4).children().val();
|
var archiveVal = inputTds.eq(4).children().val();
|
||||||
inputTds.eq(4).html(archiveSelect).children().val(archiveVal).chosen({width: "101%"});
|
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
|
} else if ( attr.indexOf('Weekday') >= 0 ) { //Weekday selection
|
||||||
var weekdaySelect = $j('<select></select>').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]');
|
var weekdaySelect = $j('<select></select>').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]');
|
||||||
for (var i = 0; i < weekdays.length; i++) {
|
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%"});
|
inputTds.eq(4).html(storageSelect).children().val(storageVal).chosen({width: "101%"});
|
||||||
} else if ( attr == 'MonitorName' ) { //Monitor names
|
} else if ( attr == 'MonitorName' ) { //Monitor names
|
||||||
var monitorSelect = $j('<select></select>').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]');
|
var monitorSelect = $j('<select></select>').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]');
|
||||||
for (var key in monitors) {
|
for ( var monitor_id in monitors ) {
|
||||||
monitorSelect.append('<option value="' + key + '">' + monitors[key] + '</option>');
|
monitorSelect.append('<option value="' + monitors[monitor_id].Name + '">' + monitors[monitor_id].Name + '</option>');
|
||||||
}
|
}
|
||||||
var monitorVal = inputTds.eq(4).children().val();
|
var monitorVal = inputTds.eq(4).children().val();
|
||||||
inputTds.eq(4).html(monitorSelect).children().val(monitorVal);
|
inputTds.eq(4).html(monitorSelect).children().val(monitorVal);
|
||||||
} else { //Reset to regular text field and operator for everything that isn't special
|
} 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%"});
|
|
||||||
var textInput = $j('<input></input>').attr('type', 'text').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]');
|
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();
|
var textVal = inputTds.eq(4).children().val();
|
||||||
inputTds.eq(4).html(textInput).children().val(textVal);
|
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
|
if ( attr.endsWith('DateTime') ) { //Start/End DateTime
|
||||||
inputTds.eq(4).children().datetimepicker({timeFormat: "HH:mm:ss", dateFormat: "yy-mm-dd", maxDate: 0, constrainInput: false});
|
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
|
} 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 servers = <?php echo isset($servers) ? json_encode($servers) : '' ?>;
|
||||||
var storageareas = <?php echo isset($storageareas) ? json_encode($storageareas) : '' ?>;
|
var storageareas = <?php echo isset($storageareas) ? json_encode($storageareas) : '' ?>;
|
||||||
var monitors = <?php echo isset($monitors) ? json_encode($monitors) : '' ?>;
|
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 errorBrackets = '<?php echo translate('ErrorBrackets') ?>';
|
||||||
var errorValue = '<?php echo translate('ErrorValidValue') ?>';
|
var errorValue = '<?php echo translate('ErrorValidValue') ?>';
|
||||||
|
|
|
@ -334,7 +334,7 @@ function changeScale() {
|
||||||
Cookie.write('zmMontageScale', scale, {duration: 10*365});
|
Cookie.write('zmMontageScale', scale, {duration: 10*365});
|
||||||
Cookie.write('zmMontageWidth', '', {duration: 10*365});
|
Cookie.write('zmMontageWidth', '', {duration: 10*365});
|
||||||
Cookie.write('zmMontageHeight', '', {duration: 10*365});
|
Cookie.write('zmMontageHeight', '', {duration: 10*365});
|
||||||
if ( !scale ) {
|
if ( scale == '' ) {
|
||||||
selectLayout('#zmMontageLayout');
|
selectLayout('#zmMontageLayout');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -349,9 +349,13 @@ function changeScale() {
|
||||||
console.log("Error finding frame for " + monitor.id);
|
console.log("Error finding frame for " + monitor.id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if ( scale != '0' ) {
|
||||||
if ( newWidth ) {
|
if ( newWidth ) {
|
||||||
monitor_frame.css('width', 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
|
// We don't set the frame height because it has the status bar as well
|
||||||
//if ( height ) {
|
//if ( height ) {
|
||||||
////monitor_frame.css('height', height+'px');
|
////monitor_frame.css('height', height+'px');
|
||||||
|
@ -364,13 +368,24 @@ function changeScale() {
|
||||||
streamImg.src = '';
|
streamImg.src = '';
|
||||||
|
|
||||||
//src = src.replace(/rand=\d+/i,'rand='+Math.floor((Math.random() * 1000000) ));
|
//src = src.replace(/rand=\d+/i,'rand='+Math.floor((Math.random() * 1000000) ));
|
||||||
|
if ( scale != '0' ) {
|
||||||
src = src.replace(/scale=[\.\d]+/i, 'scale='+scale);
|
src = src.replace(/scale=[\.\d]+/i, 'scale='+scale);
|
||||||
src = src.replace(/width=[\.\d]+/i, 'width='+newWidth);
|
src = src.replace(/width=[\.\d]+/i, 'width='+newWidth);
|
||||||
src = src.replace(/height=[\.\d]+/i, 'height='+newHeight);
|
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.src = src;
|
||||||
}
|
}
|
||||||
|
if ( scale != '0' ) {
|
||||||
streamImg.style.width = newWidth + "px";
|
streamImg.style.width = newWidth + "px";
|
||||||
streamImg.style.height = newHeight + "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
|
// 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 );
|
var delay = Math.round( (Math.random()+0.5)*statusRefreshTimeout );
|
||||||
|
console.log("delay: " + delay);
|
||||||
monitors[i].start(delay);
|
monitors[i].start(delay);
|
||||||
|
|
||||||
var interval = monitors[i].refresh;
|
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];
|
var uri = "?view=" + currentView + fitStr + minStr + maxStr + liveStr + zoomStr + "&scale=" + $j("#scaleslider")[0].value + "&speed=" + speeds[$j("#speedslider")[0].value];
|
||||||
window.location = uri;
|
window.location = uri;
|
||||||
}
|
}
|
||||||
|
@ -967,6 +971,7 @@ function initPage() {
|
||||||
imagedone(this, this.monId, false);
|
imagedone(this, this.monId, false);
|
||||||
};
|
};
|
||||||
loadImage2Monitor(monId, monitorImageURL[monId]);
|
loadImage2Monitor(monId, monitorImageURL[monId]);
|
||||||
|
monitorCanvasObj[monId].addEventListener('click', clickMonitor, false);
|
||||||
}
|
}
|
||||||
} // end foreach monitor
|
} // end foreach monitor
|
||||||
|
|
||||||
|
@ -982,15 +987,6 @@ function initPage() {
|
||||||
ctx = canvas.getContext('2d');
|
ctx = canvas.getContext('2d');
|
||||||
drawGraph();
|
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);
|
setSpeed(speedIndex);
|
||||||
//setFit(fitMode); // will redraw
|
//setFit(fitMode); // will redraw
|
||||||
//setLive(liveMode); // will redraw
|
//setLive(liveMode); // will redraw
|
||||||
|
|
|
@ -68,7 +68,7 @@ if ( !$liveMode ) {
|
||||||
$frame['NextFrameId'] = $next_frames[$frame['EventId']]['Id'];
|
$frame['NextFrameId'] = $next_frames[$frame['EventId']]['Id'];
|
||||||
}
|
}
|
||||||
$event['FramesById'] += array($frame['Id']=>$frame);
|
$event['FramesById'] += array($frame['Id']=>$frame);
|
||||||
$next_frames[$frame['EventId']] = $frame;
|
$next_frames[$frame['EventId']] = &$event['FramesById'][$frame['Id']];
|
||||||
}
|
}
|
||||||
} // end if dbQuery
|
} // end if dbQuery
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
function deleteVideo( e ) {
|
function deleteVideo(e) {
|
||||||
index = e.getAttribute('data-file-index');
|
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');
|
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;
|
var generateVideoTimer = null;
|
||||||
|
@ -13,25 +13,25 @@ var generateVideoTimer = null;
|
||||||
function generateVideoProgress() {
|
function generateVideoProgress() {
|
||||||
var tickerText = $('videoProgressTicker').get('text');
|
var tickerText = $('videoProgressTicker').get('text');
|
||||||
if ( tickerText.length < 1 || tickerText.length > 4 ) {
|
if ( tickerText.length < 1 || tickerText.length > 4 ) {
|
||||||
$('videoProgressTicker').set( 'text', '.' );
|
$('videoProgressTicker').set('text', '.');
|
||||||
} else {
|
} else {
|
||||||
$('videoProgressTicker').appendText( '.' );
|
$('videoProgressTicker').appendText('.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateVideoResponse( respObj, respText ) {
|
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() {
|
function generateVideo() {
|
||||||
form = $j('#contentForm')[0];
|
form = $j('#contentForm')[0];
|
||||||
var parms = 'view=request&request=event&action=video';
|
var parms = 'view=request&request=event&action=video';
|
||||||
parms += '&'+$(form).toQueryString();
|
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();
|
query.send();
|
||||||
$('videoProgress').removeClass( 'hidden' );
|
$('videoProgress').removeClass('hidden');
|
||||||
$('videoProgress').setProperty( 'class', 'warnText' );
|
$('videoProgress').setProperty('class', 'warnText');
|
||||||
$('videoProgressText').set( 'text', videoGenProgressString );
|
$('videoProgressText').set('text', videoGenProgressString);
|
||||||
generateVideoProgress();
|
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() {
|
function showEvents() {
|
||||||
$('ptzControls').addClass( 'hidden' );
|
$('ptzControls').addClass('hidden');
|
||||||
$('events').removeClass( 'hidden' );
|
$('events').removeClass('hidden');
|
||||||
if ( $('eventsControl') ) {
|
if ( $('eventsControl') ) {
|
||||||
$('eventsControl').addClass('hidden');
|
$('eventsControl').addClass('hidden');
|
||||||
}
|
}
|
||||||
if ( $('controlControl') ) {
|
if ( $('controlControl') ) {
|
||||||
$('controlControl').removeClass('hidden');
|
$('controlControl').removeClass('hidden');
|
||||||
}
|
}
|
||||||
showMode = "events";
|
showMode = 'events';
|
||||||
}
|
}
|
||||||
|
|
||||||
function showPtzControls() {
|
function showPtzControls() {
|
||||||
$('events').addClass( 'hidden' );
|
$('events').addClass('hidden');
|
||||||
$('ptzControls').removeClass( 'hidden' );
|
$('ptzControls').removeClass('hidden');
|
||||||
if ( $('eventsControl') ) {
|
if ( $('eventsControl') ) {
|
||||||
$('eventsControl').removeClass('hidden');
|
$('eventsControl').removeClass('hidden');
|
||||||
}
|
}
|
||||||
if ( $('controlControl') ) {
|
if ( $('controlControl') ) {
|
||||||
$('controlControl').addClass('hidden');
|
$('controlControl').addClass('hidden');
|
||||||
}
|
}
|
||||||
showMode = "control";
|
showMode = 'control';
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeScale() {
|
function changeScale() {
|
||||||
var scale = $('scale').get('value');
|
var scale = $('scale').get('value');
|
||||||
var newWidth;
|
var newWidth;
|
||||||
var newHeight;
|
var newHeight;
|
||||||
if (scale == "auto") {
|
if ( scale == '0' || scale == 'auto' ) {
|
||||||
var newSize = scaleToFit(monitorWidth, monitorHeight, $j('#liveStream'+monitorId), $j('#replayStatus'));
|
var newSize = scaleToFit(monitorWidth, monitorHeight, $j('#liveStream'+monitorId), $j('#replayStatus'));
|
||||||
newWidth = newSize.width;
|
newWidth = newSize.width;
|
||||||
newHeight = newSize.height;
|
newHeight = newSize.height;
|
||||||
|
@ -87,7 +81,7 @@ function setAlarmState( currentAlarmState ) {
|
||||||
if ( SOUND_ON_ALARM ) {
|
if ( SOUND_ON_ALARM ) {
|
||||||
// Enable the alarm sound
|
// Enable the alarm sound
|
||||||
if ( !canPlayPauseAudio ) {
|
if ( !canPlayPauseAudio ) {
|
||||||
$('alarmSound').removeClass( 'hidden' );
|
$('alarmSound').removeClass('hidden');
|
||||||
} else {
|
} else {
|
||||||
$('MediaPlayer').Play();
|
$('MediaPlayer').Play();
|
||||||
}
|
}
|
||||||
|
@ -96,22 +90,20 @@ function setAlarmState( currentAlarmState ) {
|
||||||
window.focus();
|
window.focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ( oldAlarm ) { // done with an event do a refresh
|
||||||
if ( SOUND_ON_ALARM ) {
|
if ( SOUND_ON_ALARM ) {
|
||||||
if ( oldAlarm ) {
|
|
||||||
// Disable alarm sound
|
// Disable alarm sound
|
||||||
if ( !canPlayPauseAudio ) {
|
if ( !canPlayPauseAudio ) {
|
||||||
$('alarmSound').addClass( 'hidden' );
|
$('alarmSound').addClass('hidden');
|
||||||
} else {
|
} else {
|
||||||
$('MediaPlayer').Stop();
|
$('MediaPlayer').Stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (oldAlarm) { // done with an event do a refresh
|
|
||||||
eventCmdQuery();
|
eventCmdQuery();
|
||||||
}
|
}
|
||||||
|
|
||||||
lastAlarmState = alarmState;
|
lastAlarmState = alarmState;
|
||||||
}
|
} // end function setAlarmState( currentAlarmState )
|
||||||
|
|
||||||
if ( monitorType != 'WebSite' ) {
|
if ( monitorType != 'WebSite' ) {
|
||||||
var streamCmdParms = 'view=request&request=stream&connkey='+connKey;
|
var streamCmdParms = 'view=request&request=stream&connkey='+connKey;
|
||||||
|
@ -155,11 +147,11 @@ function getStreamCmdResponse(respObj, respText) {
|
||||||
|
|
||||||
$('levelValue').set('text', streamStatus.level);
|
$('levelValue').set('text', streamStatus.level);
|
||||||
if ( streamStatus.level > 95 ) {
|
if ( streamStatus.level > 95 ) {
|
||||||
$('levelValue').className = "alarm";
|
$('levelValue').className = 'alarm';
|
||||||
} else if ( streamStatus.level > 80 ) {
|
} else if ( streamStatus.level > 80 ) {
|
||||||
$('levelValue').className = "alert";
|
$('levelValue').className = 'alert';
|
||||||
} else {
|
} else {
|
||||||
$('levelValue').className = "ok";
|
$('levelValue').className = 'ok';
|
||||||
}
|
}
|
||||||
|
|
||||||
var delayString = secsToTime(streamStatus.delay);
|
var delayString = secsToTime(streamStatus.delay);
|
||||||
|
@ -194,7 +186,7 @@ function getStreamCmdResponse(respObj, respText) {
|
||||||
}
|
}
|
||||||
} // rate
|
} // rate
|
||||||
} else {
|
} else {
|
||||||
$('modeValue').set( 'text', "Live" );
|
$('modeValue').set( 'text', 'Live' );
|
||||||
$('rate').addClass( 'hidden' );
|
$('rate').addClass( 'hidden' );
|
||||||
$('delay').addClass( 'hidden' );
|
$('delay').addClass( 'hidden' );
|
||||||
$('level').addClass( 'hidden' );
|
$('level').addClass( 'hidden' );
|
||||||
|
@ -203,9 +195,9 @@ function getStreamCmdResponse(respObj, respText) {
|
||||||
|
|
||||||
$('zoomValue').set('text', streamStatus.zoom);
|
$('zoomValue').set('text', streamStatus.zoom);
|
||||||
if ( streamStatus.zoom == '1.0' ) {
|
if ( streamStatus.zoom == '1.0' ) {
|
||||||
setButtonState($('zoomOutBtn'), 'unavail');
|
setButtonState('zoomOutBtn', 'unavail');
|
||||||
} else {
|
} else {
|
||||||
setButtonState($('zoomOutBtn'), 'inactive');
|
setButtonState('zoomOutBtn', 'inactive');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( canEditMonitors ) {
|
if ( canEditMonitors ) {
|
||||||
|
@ -230,7 +222,6 @@ function getStreamCmdResponse(respObj, respText) {
|
||||||
|
|
||||||
if ( streamStatus.auth ) {
|
if ( streamStatus.auth ) {
|
||||||
auth_hash = streamStatus.auth;
|
auth_hash = streamStatus.auth;
|
||||||
console.log("Have a new auth hash" + streamStatus.auth);
|
|
||||||
// Try to reload the image stream.
|
// Try to reload the image stream.
|
||||||
var streamImg = $('liveStream');
|
var streamImg = $('liveStream');
|
||||||
if ( streamImg ) {
|
if ( streamImg ) {
|
||||||
|
@ -243,7 +234,7 @@ function getStreamCmdResponse(respObj, respText) {
|
||||||
} // end if have a new auth hash
|
} // end if have a new auth hash
|
||||||
} // end if respObj.status
|
} // end if respObj.status
|
||||||
} else {
|
} else {
|
||||||
checkStreamForErrors("getStreamCmdResponse", respObj);//log them
|
checkStreamForErrors('getStreamCmdResponse', respObj);//log them
|
||||||
// Try to reload the image stream.
|
// Try to reload the image stream.
|
||||||
// If it's an auth error, we should reload the whole page.
|
// If it's an auth error, we should reload the whole page.
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
|
@ -251,9 +242,9 @@ function getStreamCmdResponse(respObj, respText) {
|
||||||
var streamImg = $('liveStream'+monitorId);
|
var streamImg = $('liveStream'+monitorId);
|
||||||
if ( streamImg ) {
|
if ( streamImg ) {
|
||||||
streamImg.src = streamImg.src.replace(/rand=\d+/i, 'rand='+Math.floor((Math.random() * 1000000) ));
|
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 {
|
} 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 ) {
|
if ( alarmState == STATE_ALARM || alarmState == STATE_ALERT ) {
|
||||||
streamCmdTimeout = streamCmdTimeout/5;
|
streamCmdTimeout = streamCmdTimeout/5;
|
||||||
}
|
}
|
||||||
streamCmdTimer = streamCmdQuery.delay( streamCmdTimeout );
|
streamCmdTimer = streamCmdQuery.delay(streamCmdTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
function streamCmdPause( action ) {
|
function streamCmdPause( action ) {
|
||||||
setButtonState( $('pauseBtn'), 'active' );
|
setButtonState('pauseBtn', 'active');
|
||||||
setButtonState( $('playBtn'), 'inactive' );
|
setButtonState('playBtn', 'inactive');
|
||||||
setButtonState( $('stopBtn'), 'inactive' );
|
setButtonState('stopBtn', 'inactive');
|
||||||
setButtonState( $('fastFwdBtn'), 'inactive' );
|
if ( monitorStreamReplayBuffer ) {
|
||||||
setButtonState( $('slowFwdBtn'), 'inactive' );
|
setButtonState('fastFwdBtn', 'inactive');
|
||||||
setButtonState( $('slowRevBtn'), 'inactive' );
|
setButtonState('slowFwdBtn', 'inactive');
|
||||||
setButtonState( $('fastRevBtn'), 'inactive' );
|
setButtonState('slowRevBtn', 'inactive');
|
||||||
|
setButtonState('fastRevBtn', 'inactive');
|
||||||
|
}
|
||||||
if ( action ) {
|
if ( action ) {
|
||||||
streamCmdReq.send( streamCmdParms+"&command="+CMD_PAUSE );
|
streamCmdReq.send(streamCmdParms+"&command="+CMD_PAUSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function streamCmdPlay( action ) {
|
function streamCmdPlay( action ) {
|
||||||
setButtonState( $('pauseBtn'), 'inactive' );
|
setButtonState('pauseBtn', 'inactive');
|
||||||
setButtonState( $('playBtn'), 'active' );
|
setButtonState('playBtn', 'active');
|
||||||
if ( streamStatus.delayed == true ) {
|
if ( streamStatus.delayed == true ) {
|
||||||
setButtonState( $('stopBtn'), 'inactive' );
|
setButtonState('stopBtn', 'inactive');
|
||||||
setButtonState( $('fastFwdBtn'), 'inactive' );
|
if ( monitorStreamReplayBuffer ) {
|
||||||
setButtonState( $('slowFwdBtn'), 'inactive' );
|
setButtonState('fastFwdBtn', 'inactive');
|
||||||
setButtonState( $('slowRevBtn'), 'inactive' );
|
setButtonState('slowFwdBtn', 'inactive');
|
||||||
setButtonState( $('fastRevBtn'), 'inactive' );
|
setButtonState('slowRevBtn', 'inactive');
|
||||||
|
setButtonState('fastRevBtn', 'inactive');
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
setButtonState( $('stopBtn'), 'unavail' );
|
setButtonState('stopBtn', 'unavail');
|
||||||
setButtonState( $('fastFwdBtn'), 'unavail' );
|
if ( monitorStreamReplayBuffer ) {
|
||||||
setButtonState( $('slowFwdBtn'), 'unavail' );
|
setButtonState('fastFwdBtn', 'unavail');
|
||||||
setButtonState( $('slowRevBtn'), 'unavail' );
|
setButtonState('slowFwdBtn', 'unavail');
|
||||||
setButtonState( $('fastRevBtn'), 'unavail' );
|
setButtonState('slowRevBtn', 'unavail');
|
||||||
|
setButtonState('fastRevBtn', 'unavail');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ( action ) {
|
if ( action ) {
|
||||||
streamCmdReq.send( streamCmdParms+"&command="+CMD_PLAY );
|
streamCmdReq.send(streamCmdParms+"&command="+CMD_PLAY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function streamCmdStop( action ) {
|
function streamCmdStop( action ) {
|
||||||
setButtonState( $('pauseBtn'), 'inactive' );
|
setButtonState('pauseBtn', 'inactive');
|
||||||
setButtonState( $('playBtn'), 'unavail' );
|
setButtonState('playBtn', 'unavail');
|
||||||
setButtonState( $('stopBtn'), 'active' );
|
setButtonState('stopBtn', 'active');
|
||||||
setButtonState( $('fastFwdBtn'), 'unavail' );
|
if ( monitorStreamReplayBuffer ) {
|
||||||
setButtonState( $('slowFwdBtn'), 'unavail' );
|
setButtonState('fastFwdBtn', 'unavail');
|
||||||
setButtonState( $('slowRevBtn'), 'unavail' );
|
setButtonState('slowFwdBtn', 'unavail');
|
||||||
setButtonState( $('fastRevBtn'), 'unavail' );
|
setButtonState('slowRevBtn', 'unavail');
|
||||||
if ( action ) {
|
setButtonState('fastRevBtn', 'unavail');
|
||||||
streamCmdReq.send( streamCmdParms+"&command="+CMD_STOP );
|
|
||||||
}
|
}
|
||||||
setButtonState( $('stopBtn'), 'unavail' );
|
if ( action ) {
|
||||||
setButtonState( $('playBtn'), 'active' );
|
streamCmdReq.send(streamCmdParms+"&command="+CMD_STOP);
|
||||||
|
}
|
||||||
|
setButtonState('stopBtn', 'unavail');
|
||||||
|
setButtonState('playBtn', 'active');
|
||||||
}
|
}
|
||||||
|
|
||||||
function streamCmdFastFwd( action ) {
|
function streamCmdFastFwd( action ) {
|
||||||
setButtonState( $('pauseBtn'), 'inactive' );
|
setButtonState('pauseBtn', 'inactive');
|
||||||
setButtonState( $('playBtn'), 'inactive' );
|
setButtonState('playBtn', 'inactive');
|
||||||
setButtonState( $('stopBtn'), 'inactive' );
|
setButtonState('stopBtn', 'inactive');
|
||||||
setButtonState( $('fastFwdBtn'), 'inactive' );
|
if ( monitorStreamReplayBuffer ) {
|
||||||
setButtonState( $('slowFwdBtn'), 'inactive' );
|
setButtonState('fastFwdBtn', 'inactive');
|
||||||
setButtonState( $('slowRevBtn'), 'inactive' );
|
setButtonState('slowFwdBtn', 'inactive');
|
||||||
setButtonState( $('fastRevBtn'), 'inactive' );
|
setButtonState('slowRevBtn', 'inactive');
|
||||||
|
setButtonState('fastRevBtn', 'inactive');
|
||||||
|
}
|
||||||
if ( action ) {
|
if ( action ) {
|
||||||
streamCmdReq.send( streamCmdParms+"&command="+CMD_FASTFWD );
|
streamCmdReq.send(streamCmdParms+"&command="+CMD_FASTFWD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function streamCmdSlowFwd( action ) {
|
function streamCmdSlowFwd( action ) {
|
||||||
setButtonState( $('pauseBtn'), 'inactive' );
|
setButtonState('pauseBtn', 'inactive');
|
||||||
setButtonState( $('playBtn'), 'inactive' );
|
setButtonState('playBtn', 'inactive');
|
||||||
setButtonState( $('stopBtn'), 'inactive' );
|
setButtonState('stopBtn', 'inactive');
|
||||||
setButtonState( $('fastFwdBtn'), 'inactive' );
|
if ( monitorStreamReplayBuffer ) {
|
||||||
setButtonState( $('slowFwdBtn'), 'active' );
|
setButtonState('fastFwdBtn', 'inactive');
|
||||||
setButtonState( $('slowRevBtn'), 'inactive' );
|
setButtonState('slowFwdBtn', 'active');
|
||||||
setButtonState( $('fastRevBtn'), 'inactive' );
|
setButtonState('slowRevBtn', 'inactive');
|
||||||
if ( action ) {
|
setButtonState('fastRevBtn', 'inactive');
|
||||||
streamCmdReq.send( streamCmdParms+"&command="+CMD_SLOWFWD );
|
}
|
||||||
|
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 ) {
|
function streamCmdSlowRev( action ) {
|
||||||
setButtonState( $('pauseBtn'), 'inactive' );
|
setButtonState('pauseBtn', 'inactive');
|
||||||
setButtonState( $('playBtn'), 'inactive' );
|
setButtonState('playBtn', 'inactive');
|
||||||
setButtonState( $('stopBtn'), 'inactive' );
|
setButtonState('stopBtn', 'inactive');
|
||||||
setButtonState( $('fastFwdBtn'), 'inactive' );
|
if ( monitorStreamReplayBuffer ) {
|
||||||
setButtonState( $('slowFwdBtn'), 'inactive' );
|
setButtonState('fastFwdBtn', 'inactive');
|
||||||
setButtonState( $('slowRevBtn'), 'active' );
|
setButtonState('slowFwdBtn', 'inactive');
|
||||||
setButtonState( $('fastRevBtn'), 'inactive' );
|
setButtonState('slowRevBtn', 'active');
|
||||||
if ( action ) {
|
setButtonState('fastRevBtn', 'inactive');
|
||||||
streamCmdReq.send( streamCmdParms+"&command="+CMD_SLOWREV );
|
}
|
||||||
|
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 ) {
|
function streamCmdFastRev( action ) {
|
||||||
setButtonState( $('pauseBtn'), 'inactive' );
|
setButtonState('pauseBtn', 'inactive');
|
||||||
setButtonState( $('playBtn'), 'inactive' );
|
setButtonState('playBtn', 'inactive');
|
||||||
setButtonState( $('stopBtn'), 'inactive' );
|
setButtonState('stopBtn', 'inactive');
|
||||||
setButtonState( $('fastFwdBtn'), 'inactive' );
|
if ( monitorStreamReplayBuffer ) {
|
||||||
setButtonState( $('slowFwdBtn'), 'inactive' );
|
setButtonState('fastFwdBtn', 'inactive');
|
||||||
setButtonState( $('slowRevBtn'), 'inactive' );
|
setButtonState('slowFwdBtn', 'inactive');
|
||||||
setButtonState( $('fastRevBtn'), 'inactive' );
|
setButtonState('slowRevBtn', 'inactive');
|
||||||
|
setButtonState('fastRevBtn', 'inactive');
|
||||||
|
}
|
||||||
if ( action ) {
|
if ( action ) {
|
||||||
streamCmdReq.send( streamCmdParms+"&command="+CMD_FASTREV );
|
streamCmdReq.send(streamCmdParms+"&command="+CMD_FASTREV);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function streamCmdZoomIn( x, y ) {
|
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() {
|
function streamCmdZoomOut() {
|
||||||
streamCmdReq.send( streamCmdParms+"&command="+CMD_ZOOMOUT );
|
streamCmdReq.send(streamCmdParms+"&command="+CMD_ZOOMOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
function streamCmdScale( scale ) {
|
function streamCmdScale( scale ) {
|
||||||
streamCmdReq.send( streamCmdParms+"&command="+CMD_SCALE+"&scale="+scale );
|
streamCmdReq.send(streamCmdParms+"&command="+CMD_SCALE+"&scale="+scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
function streamCmdPan( x, y ) {
|
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() {
|
function streamCmdQuery() {
|
||||||
streamCmdReq.send( streamCmdParms+"&command="+CMD_QUERY );
|
streamCmdReq.send(streamCmdParms+"&command="+CMD_QUERY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( monitorType != 'WebSite' ) {
|
if ( monitorType != 'WebSite' ) {
|
||||||
|
@ -395,12 +406,18 @@ if ( monitorType != 'WebSite' ) {
|
||||||
if ( auth_hash ) {
|
if ( auth_hash ) {
|
||||||
statusCmdParms += '&auth='+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;
|
var statusCmdTimer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getStatusCmdResponse(respObj, respText) {
|
function getStatusCmdResponse(respObj, respText) {
|
||||||
watchdogOk("status");
|
watchdogOk('status');
|
||||||
if ( statusCmdTimer ) {
|
if ( statusCmdTimer ) {
|
||||||
statusCmdTimer = clearTimeout(statusCmdTimer);
|
statusCmdTimer = clearTimeout(statusCmdTimer);
|
||||||
}
|
}
|
||||||
|
@ -409,22 +426,22 @@ function getStatusCmdResponse(respObj, respText) {
|
||||||
$('fpsValue').set('text', respObj.monitor.FrameRate);
|
$('fpsValue').set('text', respObj.monitor.FrameRate);
|
||||||
setAlarmState(respObj.monitor.Status);
|
setAlarmState(respObj.monitor.Status);
|
||||||
} else {
|
} else {
|
||||||
checkStreamForErrors("getStatusCmdResponse", respObj);
|
checkStreamForErrors('getStatusCmdResponse', respObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
var statusCmdTimeout = statusRefreshTimeout;
|
var statusCmdTimeout = statusRefreshTimeout;
|
||||||
if ( alarmState == STATE_ALARM || alarmState == STATE_ALERT ) {
|
if ( alarmState == STATE_ALARM || alarmState == STATE_ALERT ) {
|
||||||
statusCmdTimeout = statusCmdTimeout/5;
|
statusCmdTimeout = statusCmdTimeout/5;
|
||||||
}
|
}
|
||||||
statusCmdTimer = statusCmdQuery.delay( statusCmdTimeout );
|
statusCmdTimer = statusCmdQuery.delay(statusCmdTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
function statusCmdQuery() {
|
function statusCmdQuery() {
|
||||||
statusCmdReq.send();
|
statusCmdReq.send(statusCmdParms);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( monitorType != 'WebSite' ) {
|
if ( monitorType != 'WebSite' ) {
|
||||||
var alarmCmdParms = "view=request&request=alarm&id="+monitorId;
|
var alarmCmdParms = 'view=request&request=alarm&id='+monitorId;
|
||||||
if ( auth_hash ) {
|
if ( auth_hash ) {
|
||||||
alarmCmdParms += '&auth='+auth_hash;
|
alarmCmdParms += '&auth='+auth_hash;
|
||||||
}
|
}
|
||||||
|
@ -439,8 +456,8 @@ if ( monitorType != 'WebSite' ) {
|
||||||
var alarmCmdFirst = true;
|
var alarmCmdFirst = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAlarmCmdResponse( respObj, respText ) {
|
function getAlarmCmdResponse(respObj, respText) {
|
||||||
checkStreamForErrors("getAlarmCmdResponse", respObj);
|
checkStreamForErrors('getAlarmCmdResponse', respObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
function cmdDisableAlarms() {
|
function cmdDisableAlarms() {
|
||||||
|
@ -453,14 +470,14 @@ function cmdEnableAlarms() {
|
||||||
|
|
||||||
function cmdForceAlarm() {
|
function cmdForceAlarm() {
|
||||||
alarmCmdReq.send(alarmCmdParms+"&command=forceAlarm");
|
alarmCmdReq.send(alarmCmdParms+"&command=forceAlarm");
|
||||||
if (window.event) {
|
if ( window.event ) {
|
||||||
window.event.preventDefault();
|
window.event.preventDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function cmdCancelForcedAlarm() {
|
function cmdCancelForcedAlarm() {
|
||||||
alarmCmdReq.send(alarmCmdParms+"&command=cancelForcedAlarm");
|
alarmCmdReq.send(alarmCmdParms+"&command=cancelForcedAlarm");
|
||||||
if (window.event) {
|
if ( window.event ) {
|
||||||
window.event.preventDefault();
|
window.event.preventDefault();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -476,8 +493,8 @@ function getActResponse( respObj, respText ) {
|
||||||
eventCmdQuery();
|
eventCmdQuery();
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteEvent( event, eventId ) {
|
function deleteEvent(event, eventId) {
|
||||||
var actParms = "view=request&request=event&action=delete&id="+eventId;
|
var actParms = 'view=request&request=event&action=delete&id='+eventId;
|
||||||
if ( auth_hash ) {
|
if ( auth_hash ) {
|
||||||
actParms += '&auth='+auth_hash;
|
actParms += '&auth='+auth_hash;
|
||||||
}
|
}
|
||||||
|
@ -485,10 +502,9 @@ function deleteEvent( event, eventId ) {
|
||||||
url: thisUrl,
|
url: thisUrl,
|
||||||
method: 'post',
|
method: 'post',
|
||||||
timeout: 3000,
|
timeout: 3000,
|
||||||
data: actParms,
|
|
||||||
onSuccess: getActResponse
|
onSuccess: getActResponse
|
||||||
} );
|
} );
|
||||||
actReq.send();
|
actReq.send(actParms);
|
||||||
event.stop();
|
event.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -501,7 +517,6 @@ if ( monitorType != 'WebSite' ) {
|
||||||
url: monitorUrl,
|
url: monitorUrl,
|
||||||
method: 'get',
|
method: 'get',
|
||||||
timeout: AJAX_TIMEOUT,
|
timeout: AJAX_TIMEOUT,
|
||||||
data: eventCmdParms,
|
|
||||||
link: 'cancel',
|
link: 'cancel',
|
||||||
onSuccess: getEventCmdResponse,
|
onSuccess: getEventCmdResponse,
|
||||||
onTimeout: eventCmdQuery
|
onTimeout: eventCmdQuery
|
||||||
|
@ -515,19 +530,19 @@ function highlightRow( row ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getEventCmdResponse( respObj, respText ) {
|
function getEventCmdResponse( respObj, respText ) {
|
||||||
watchdogOk("event");
|
watchdogOk('event');
|
||||||
if ( eventCmdTimer ) {
|
if ( eventCmdTimer ) {
|
||||||
eventCmdTimer = clearTimeout( eventCmdTimer );
|
eventCmdTimer = clearTimeout(eventCmdTimer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( respObj.result == 'Ok' ) {
|
if ( respObj.result == 'Ok' ) {
|
||||||
var dbEvents = respObj.events.reverse();
|
var dbEvents = respObj.events.reverse();
|
||||||
var eventList = $('eventList');
|
var eventList = $('eventList');
|
||||||
var eventListBody = $(eventList).getElement( 'tbody' );
|
var eventListBody = $(eventList).getElement('tbody');
|
||||||
var eventListRows = $(eventListBody).getElements( 'tr' );
|
var eventListRows = $(eventListBody).getElements('tr');
|
||||||
|
|
||||||
eventListRows.each( function( row ) {
|
eventListRows.each( function(row) {
|
||||||
row.removeClass( 'updated' );
|
row.removeClass('updated');
|
||||||
} );
|
} );
|
||||||
|
|
||||||
for ( var i = 0; i < dbEvents.length; i++ ) {
|
for ( var i = 0; i < dbEvents.length; i++ ) {
|
||||||
|
@ -581,30 +596,30 @@ function getEventCmdResponse( respObj, respText ) {
|
||||||
'mouseout': highlightRow.pass(row)
|
'mouseout': highlightRow.pass(row)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
link.set( 'text', 'X' );
|
link.set('text', 'X');
|
||||||
link.inject( row.getElement( 'td.colDelete' ) );
|
link.inject(row.getElement('td.colDelete'));
|
||||||
|
|
||||||
if ( i == 0 ) {
|
if ( i == 0 ) {
|
||||||
row.inject( $(eventListBody) );
|
row.inject($(eventListBody));
|
||||||
} else {
|
} else {
|
||||||
row.inject( $(eventListBody), 'top' );
|
row.inject($(eventListBody), 'top');
|
||||||
if ( !eventCmdFirst ) {
|
if ( !eventCmdFirst ) {
|
||||||
row.addClass( 'recent' );
|
row.addClass('recent');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
row.getElement( 'td.colName a' ).set( 'text', event.Name );
|
row.getElement('td.colName a').set('text', event.Name);
|
||||||
row.getElement( 'td.colSecs' ).set( 'text', event.Length );
|
row.getElement('td.colSecs').set('text', event.Length);
|
||||||
row.getElement( 'td.colFrames a' ).set( 'text', event.Frames+'/'+event.AlarmFrames );
|
row.getElement('td.colFrames a').set('text', event.Frames+'/'+event.AlarmFrames);
|
||||||
row.getElement( 'td.colScore a' ).set( 'text', event.AvgScore+'/'+event.MaxScore );
|
row.getElement('td.colScore a').set('text', event.AvgScore+'/'+event.MaxScore);
|
||||||
row.removeClass( 'recent' );
|
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++ ) {
|
for ( var i = 0; i < rows.length; i++ ) {
|
||||||
if ( !rows[i].hasClass( 'updated' ) ) {
|
if ( !rows[i].hasClass('updated') ) {
|
||||||
rows[i].destroy();
|
rows[i].destroy();
|
||||||
rows.splice( i, 1 );
|
rows.splice( i, 1 );
|
||||||
i--;
|
i--;
|
||||||
|
@ -615,39 +630,45 @@ function getEventCmdResponse( respObj, respText ) {
|
||||||
rows.length--;
|
rows.length--;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
checkStreamForErrors("getEventCmdResponse", respObj);
|
checkStreamForErrors('getEventCmdResponse', respObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
var eventCmdTimeout = eventsRefreshTimeout;
|
var eventCmdTimeout = eventsRefreshTimeout;
|
||||||
if ( alarmState == STATE_ALARM || alarmState == STATE_ALERT ) {
|
if ( alarmState == STATE_ALARM || alarmState == STATE_ALERT ) {
|
||||||
eventCmdTimeout = eventCmdTimeout/5;
|
eventCmdTimeout = eventCmdTimeout/5;
|
||||||
}
|
}
|
||||||
eventCmdTimer = eventCmdQuery.delay( eventCmdTimeout );
|
eventCmdTimer = eventCmdQuery.delay(eventCmdTimeout);
|
||||||
eventCmdFirst = false;
|
eventCmdFirst = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function eventCmdQuery() {
|
function eventCmdQuery() {
|
||||||
if ( eventCmdTimer ) { // avoid firing another if we are firing one
|
if ( eventCmdTimer ) { // avoid firing another if we are firing one
|
||||||
eventCmdTimer = clearTimeout( eventCmdTimer );
|
eventCmdTimer = clearTimeout(eventCmdTimer);
|
||||||
}
|
}
|
||||||
eventCmdReq.send();
|
eventCmdReq.send(eventCmdParms);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( monitorType != 'WebSite' ) {
|
if ( monitorType != 'WebSite' ) {
|
||||||
var controlParms = "view=request&request=control&id="+monitorId;
|
var controlParms = 'view=request&request=control&id='+monitorId;
|
||||||
if ( auth_hash ) {
|
if ( auth_hash ) {
|
||||||
controlParms += '&auth='+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 ) {
|
if ( !respObj ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//console.log( respText );
|
//console.log( respText );
|
||||||
if ( respObj.result != 'Ok' ) {
|
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;
|
locParms += "&yge="+yge;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
controlReq.send( controlParms+"&control="+control+locParms );
|
controlReq.send(controlParms+"&control="+control+locParms);
|
||||||
if ( streamMode == "single" ) {
|
if ( streamMode == 'single' ) {
|
||||||
fetchImage.pass( $('imageFeed').getElement('img') ).delay( 1000 );
|
fetchImage.pass($('imageFeed').getElement('img')).delay(1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function controlCmdImage( x, y ) {
|
function controlCmdImage( x, y ) {
|
||||||
var imageControlParms = controlParms;
|
var imageControlParms = controlParms;
|
||||||
imageControlParms += "&scale="+scale;
|
imageControlParms += '&scale='+scale;
|
||||||
imageControlParms += "&control="+imageControlMode;
|
imageControlParms += '&control='+imageControlMode;
|
||||||
|
|
||||||
controlReq.send( imageControlParms+"&x="+x+"&y="+y );
|
controlReq.send( imageControlParms+"&x="+x+"&y="+y );
|
||||||
if ( streamMode == "single" ) {
|
if ( streamMode == 'single' ) {
|
||||||
fetchImage.pass( $('imageFeed').getElement('img') ).delay( 1000 );
|
fetchImage.pass( $('imageFeed').getElement('img') ).delay( 1000 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -706,7 +727,7 @@ function handleClick( event ) {
|
||||||
var x = event.page.x - $(target).getLeft();
|
var x = event.page.x - $(target).getLeft();
|
||||||
var y = event.page.y - $(target).getTop();
|
var y = event.page.y - $(target).getTop();
|
||||||
|
|
||||||
if ( showMode == "events" || !imageControlMode ) {
|
if ( showMode == 'events' || !imageControlMode ) {
|
||||||
if ( event.shift ) {
|
if ( event.shift ) {
|
||||||
streamCmdPan( x, y );
|
streamCmdPan( x, y );
|
||||||
} else if ( event.event.ctrlKey ) {
|
} else if ( event.event.ctrlKey ) {
|
||||||
|
@ -803,7 +824,7 @@ function initPage() {
|
||||||
if ( refreshApplet && appletRefreshTime ) {
|
if ( refreshApplet && appletRefreshTime ) {
|
||||||
appletRefresh.delay(appletRefreshTime*1000);
|
appletRefresh.delay(appletRefreshTime*1000);
|
||||||
}
|
}
|
||||||
if ( scale == "auto" ) changeScale();
|
if ( scale == 'auto' ) changeScale();
|
||||||
if ( window.history.length == 1 ) {
|
if ( window.history.length == 1 ) {
|
||||||
$j('#closeControl').html('');
|
$j('#closeControl').html('');
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,13 +44,13 @@ var showMode = "<?php echo ($showPtzControls && !empty($control))?"control":"eve
|
||||||
var connKey = '<?php echo $connkey ?>';
|
var connKey = '<?php echo $connkey ?>';
|
||||||
var maxDisplayEvents = <?php echo 2 * MAX_EVENTS ?>;
|
var maxDisplayEvents = <?php echo 2 * MAX_EVENTS ?>;
|
||||||
|
|
||||||
|
|
||||||
var monitorId = <?php echo $monitor->Id() ?>;
|
var monitorId = <?php echo $monitor->Id() ?>;
|
||||||
var monitorWidth = <?php echo $monitor->ViewWidth() ?>;
|
var monitorWidth = <?php echo $monitor->ViewWidth() ?>;
|
||||||
var monitorHeight = <?php echo $monitor->ViewHeight() ?>;
|
var monitorHeight = <?php echo $monitor->ViewHeight() ?>;
|
||||||
var monitorUrl = '<?php echo $monitor->UrlToIndex(); ?>';
|
var monitorUrl = '<?php echo $monitor->UrlToIndex() ?>';
|
||||||
var monitorType = '<?php echo ( $monitor->Type() ) ?>';
|
var monitorType = '<?php echo $monitor->Type() ?>';
|
||||||
var monitorRefresh = '<?php echo ( $monitor->Refresh() ) ?>';
|
var monitorRefresh = '<?php echo $monitor->Refresh() ?>';
|
||||||
|
var monitorStreamReplayBuffer = <?php echo $monitor->StreamReplayBuffer() ?>;
|
||||||
|
|
||||||
var scale = '<?php echo $scale ?>';
|
var scale = '<?php echo $scale ?>';
|
||||||
|
|
||||||
|
|
|
@ -123,7 +123,8 @@ $sourceTypes = array(
|
||||||
'Libvlc' => translate('Libvlc'),
|
'Libvlc' => translate('Libvlc'),
|
||||||
'cURL' => 'cURL (HTTP(S) only)',
|
'cURL' => 'cURL (HTTP(S) only)',
|
||||||
'WebSite'=> 'Web Site',
|
'WebSite'=> 'Web Site',
|
||||||
'NVSocket' => translate('NVSocket')
|
'NVSocket' => translate('NVSocket'),
|
||||||
|
'VNC' => translate('VNC'),
|
||||||
);
|
);
|
||||||
if ( !ZM_HAS_V4L )
|
if ( !ZM_HAS_V4L )
|
||||||
unset($sourceTypes['Local']);
|
unset($sourceTypes['Local']);
|
||||||
|
@ -367,8 +368,8 @@ $fastblendopts_alarm = array(
|
||||||
);
|
);
|
||||||
|
|
||||||
$label_size = array(
|
$label_size = array(
|
||||||
'Default' => 1,
|
1 => translate('Default'),
|
||||||
'Large' => 2
|
2 => translate('Large'),
|
||||||
);
|
);
|
||||||
|
|
||||||
$codecs = array(
|
$codecs = array(
|
||||||
|
@ -639,7 +640,7 @@ switch ( $tab ) {
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><?php echo translate('Enabled') ?></td>
|
<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>
|
</tr>
|
||||||
<?php
|
<?php
|
||||||
if ( $monitor->Type() != 'WebSite' ) {
|
if ( $monitor->Type() != 'WebSite' ) {
|
||||||
|
@ -779,23 +780,45 @@ switch ( $tab ) {
|
||||||
|
|
||||||
} else if ( $monitor->Type() == 'NVSocket' ) {
|
} else if ( $monitor->Type() == 'NVSocket' ) {
|
||||||
include('_monitor_source_nvsocket.php');
|
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' ) {
|
} 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>
|
<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
|
<?php
|
||||||
if ( !$monitor->Protocol() || $monitor->Protocol() == 'http' ) {
|
if ( !$monitor->Protocol() || $monitor->Protocol() == 'http' ) {
|
||||||
?>
|
echo htmlSelect('newMonitor[Method]', $httpMethods, $monitor->Method() );
|
||||||
<tr><td><?php echo translate('RemoteMethod') ?></td><td><?php echo htmlSelect( "newMonitor[Method]", $httpMethods, $monitor->Method() ); ?></td></tr>
|
|
||||||
<?php
|
|
||||||
} else {
|
} else {
|
||||||
?>
|
echo htmlSelect('newMonitor[Method]', $rtspMethods, $monitor->Method() );
|
||||||
<tr><td><?php echo translate('RemoteMethod') ?></td><td><?php echo htmlSelect( "newMonitor[Method]", $rtspMethods, $monitor->Method() ); ?></td></tr>
|
|
||||||
<?php
|
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
<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('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
|
<?php
|
||||||
} else if ( $monitor->Type() == 'File' ) {
|
} else if ( $monitor->Type() == 'File' ) {
|
||||||
?>
|
?>
|
||||||
|
@ -803,23 +826,44 @@ include('_monitor_source_nvsocket.php');
|
||||||
<?php
|
<?php
|
||||||
} elseif ( $monitor->Type() == 'cURL' ) {
|
} 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 '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()) ?>" size="12"/></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()) ?>" size="12"/></td></tr>
|
<tr><td><?php echo 'Password' ?></td><td><input type="text" name="newMonitor[Pass]" value="<?php echo validHtmlStr($monitor->Pass()) ?>"/></td></tr>
|
||||||
<?php
|
<?php
|
||||||
} elseif ( $monitor->Type() == 'WebSite' ) {
|
} 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>
|
||||||
<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>
|
<td><?php echo translate('WebSiteUrl') ?></td>
|
||||||
<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>
|
<td><input type="text" name="newMonitor[Path]" value="<?php echo validHtmlStr($monitor->Path()) ?>"/></td>
|
||||||
<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>
|
||||||
|
<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
|
<?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 class="SourcePath">
|
||||||
<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>
|
<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">
|
<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>
|
<td><input type="text" name="newMonitor[Options]" value="<?php echo validHtmlStr($monitor->Options()) ?>"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php
|
<?php
|
||||||
|
@ -840,10 +884,12 @@ include('_monitor_source_nvsocket.php');
|
||||||
</tr>
|
</tr>
|
||||||
<?php
|
<?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() ); ?>
|
<tr>
|
||||||
</td></tr>
|
<td><?php echo translate('TargetColorspace') ?></td>
|
||||||
|
<td><?php echo htmlSelect('newMonitor[Colours]', $Colours, $monitor->Colours()) ?></td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><?php echo translate('CaptureResolution') ?> (<?php echo translate('Pixels') ?>)</td>
|
<td><?php echo translate('CaptureResolution') ?> (<?php echo translate('Pixels') ?>)</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -884,23 +930,30 @@ if ( $monitor->Type() != 'NVSocket' && $monitor->Type() != 'WebSite' ) {
|
||||||
<td><?php echo htmlselect('newMonitor[Orientation]', $orientations, $monitor->Orientation());?></td>
|
<td><?php echo htmlselect('newMonitor[Orientation]', $orientations, $monitor->Orientation());?></td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php
|
<?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>
|
<tr>
|
||||||
<?php
|
<td><?php echo translate('Deinterlacing') ?></td>
|
||||||
|
<td><?php echo htmlselect('newMonitor[Deinterlacing]', $deinterlaceopts_v4l2, $monitor->Deinterlacing())?></td>
|
||||||
|
</tr>
|
||||||
|
<?php
|
||||||
} else if ( $monitor->Type() != 'WebSite' ) {
|
} 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
|
||||||
}
|
}
|
||||||
?>
|
|
||||||
<?php
|
|
||||||
if ( $monitor->Type() == 'Remote' ) {
|
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
|
<?php
|
||||||
}
|
} # end if monitor->Type() == 'Remote'
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'storage' :
|
case 'storage' :
|
||||||
|
@ -910,7 +963,7 @@ if ( $monitor->Type() == 'Local' ) {
|
||||||
<td>
|
<td>
|
||||||
<?php
|
<?php
|
||||||
$storage_areas = array(0=>'Default');
|
$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();
|
$storage_areas[$Storage->Id()] = $Storage->Name();
|
||||||
}
|
}
|
||||||
echo htmlSelect('newMonitor[StorageId]', $storage_areas, $monitor->StorageId());
|
echo htmlSelect('newMonitor[StorageId]', $storage_areas, $monitor->StorageId());
|
||||||
|
@ -939,15 +992,17 @@ if ( $monitor->Type() == 'Local' ) {
|
||||||
|
|
||||||
$videowriteropts[1] = 'X264 Encode';
|
$videowriteropts[1] = 'X264 Encode';
|
||||||
|
|
||||||
if ($monitor->Type() == 'Ffmpeg' )
|
if ( $monitor->Type() == 'Ffmpeg' )
|
||||||
$videowriteropts[2] = 'H264 Camera Passthrough';
|
$videowriteropts[2] = 'H264 Camera Passthrough';
|
||||||
else
|
else
|
||||||
$videowriteropts[2] = array('text'=>'H264 Camera Passthrough - only for FFMPEG','disabled'=>1);
|
$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>
|
</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>
|
<tr><td><?php echo translate('RecordAudio') ?></td><td>
|
||||||
<?php if ( $monitor->Type() == 'Ffmpeg' ) { ?>
|
<?php if ( $monitor->Type() == 'Ffmpeg' ) { ?>
|
||||||
<input type="checkbox" name="newMonitor[RecordAudio]" value="1"<?php if ( $monitor->RecordAudio() ) { ?> checked="checked"<?php } ?>/>
|
<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' :
|
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>
|
||||||
<tr><td><?php echo translate('TimestampLabelX') ?></td><td><input type="text" name="newMonitor[LabelX]" value="<?php echo validHtmlStr($monitor->LabelX()) ?>" size="4"/></td></tr>
|
<td><?php echo translate('TimestampLabelFormat') ?></td>
|
||||||
<tr><td><?php echo translate('TimestampLabelY') ?></td><td><input type="text" name="newMonitor[LabelY]" value="<?php echo validHtmlStr($monitor->LabelY()) ?>" size="4"/></td></tr>
|
<td><input type="text" name="newMonitor[LabelFormat]" value="<?php echo validHtmlStr($monitor->LabelFormat()) ?>"/></td>
|
||||||
<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>
|
||||||
|
<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
|
<?php
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'buffers' :
|
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>
|
||||||
<tr><td><?php echo translate('WarmupFrames') ?></td><td><input type="text" name="newMonitor[WarmupCount]" value="<?php echo validHtmlStr($monitor->WarmupCount()) ?>" size="4"/></td></tr>
|
<td><?php echo translate('ImageBufferSize') ?></td>
|
||||||
<tr><td><?php echo translate('PreEventImageBuffer') ?></td><td><input type="text" name="newMonitor[PreEventCount]" value="<?php echo validHtmlStr($monitor->PreEventCount()) ?>" size="4"/></td></tr>
|
<td><input type="number" name="newMonitor[ImageBufferCount]" value="<?php echo validHtmlStr($monitor->ImageBufferCount()) ?>" size="6"/></td>
|
||||||
<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>
|
||||||
<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>
|
||||||
<tr><td><?php echo translate('AlarmFrameCount') ?></td><td><input type="text" name="newMonitor[AlarmFrameCount]" value="<?php echo validHtmlStr($monitor->AlarmFrameCount()) ?>" size="4"/></td></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
|
<?php
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -986,7 +1071,8 @@ if ( $monitor->Type() == 'Local' ) {
|
||||||
?>
|
?>
|
||||||
<tr>
|
<tr>
|
||||||
<td><?php echo translate('Controllable') ?></td>
|
<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>
|
<tr>
|
||||||
<td><?php echo translate('ControlType') ?></td>
|
<td><?php echo translate('ControlType') ?></td>
|
||||||
<td><?php echo htmlSelect('newMonitor[ControlId]', $controlTypes, $monitor->ControlId());
|
<td><?php echo htmlSelect('newMonitor[ControlId]', $controlTypes, $monitor->ControlId());
|
||||||
|
@ -1011,20 +1097,19 @@ if ( canEdit('Control') ) {
|
||||||
<td><?php echo translate('TrackMotion') ?></td>
|
<td><?php echo translate('TrackMotion') ?></td>
|
||||||
<td><input type="checkbox" name="newMonitor[TrackMotion]" value="1"<?php if ( $monitor->TrackMotion() ) { ?> checked="checked"<?php } ?>/></td>
|
<td><input type="checkbox" name="newMonitor[TrackMotion]" value="1"<?php if ( $monitor->TrackMotion() ) { ?> checked="checked"<?php } ?>/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php
|
|
||||||
$return_options = array(
|
|
||||||
'-1' => translate('None'),
|
|
||||||
'0' => translate('Home'),
|
|
||||||
'1' => translate('Preset').' 1',
|
|
||||||
);
|
|
||||||
?>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td><?php echo translate('TrackDelay') ?></td>
|
<td><?php echo translate('TrackDelay') ?></td>
|
||||||
<td><input type="number" name="newMonitor[TrackDelay]" value="<?php echo validHtmlStr($monitor->TrackDelay()) ?>"/></td>
|
<td><input type="number" name="newMonitor[TrackDelay]" value="<?php echo validHtmlStr($monitor->TrackDelay()) ?>"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><?php echo translate('ReturnLocation') ?></td>
|
<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>
|
||||||
<tr>
|
<tr>
|
||||||
<td><?php echo translate('ReturnDelay') ?></td>
|
<td><?php echo translate('ReturnDelay') ?></td>
|
||||||
|
|
|
@ -57,9 +57,6 @@ if ( isset($_REQUEST['scale']) ) {
|
||||||
$scale = $_COOKIE['zmMontageScale'];
|
$scale = $_COOKIE['zmMontageScale'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! $scale )
|
|
||||||
$scale = 100;
|
|
||||||
|
|
||||||
$layouts = ZM\MontageLayout::find(NULL, array('order'=>"lower('Name')"));
|
$layouts = ZM\MontageLayout::find(NULL, array('order'=>"lower('Name')"));
|
||||||
$layoutsById = array();
|
$layoutsById = array();
|
||||||
foreach ( $layouts as $l ) {
|
foreach ( $layouts as $l ) {
|
||||||
|
@ -111,7 +108,7 @@ if ( isset($_COOKIE['zmMontageHeight']) and $_COOKIE['zmMontageHeight'] )
|
||||||
else
|
else
|
||||||
$options['height'] = '';
|
$options['height'] = '';
|
||||||
|
|
||||||
if ( $scale )
|
#if ( $scale )
|
||||||
$options['scale'] = $scale;
|
$options['scale'] = $scale;
|
||||||
|
|
||||||
session_write_close();
|
session_write_close();
|
||||||
|
@ -127,7 +124,7 @@ foreach( $displayMonitors as &$row ) {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
$row['Scale'] = $scale;
|
$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'] )
|
if ( ZM_OPT_CONTROL && $row['ControlId'] && $row['Controllable'] )
|
||||||
$showControl = true;
|
$showControl = true;
|
||||||
|
@ -207,7 +204,12 @@ if ( $showZones ) {
|
||||||
foreach ( $monitors as $monitor ) {
|
foreach ( $monitors as $monitor ) {
|
||||||
$connkey = $monitor->connKey(); // Minor hack
|
$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="monitor<?php echo $monitor->Id() ?>" class="monitor idle">
|
||||||
<div
|
<div
|
||||||
id="imageFeed<?php echo $monitor->Id() ?>"
|
id="imageFeed<?php echo $monitor->Id() ?>"
|
||||||
|
|
|
@ -62,6 +62,17 @@ ob_end_clean();
|
||||||
$filter = array();
|
$filter = array();
|
||||||
if ( isset($_REQUEST['filter']) ) {
|
if ( isset($_REQUEST['filter']) ) {
|
||||||
$filter = $_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 {
|
} else {
|
||||||
|
|
||||||
if ( isset($_REQUEST['minTime']) && isset($_REQUEST['maxTime']) && (count($displayMonitors) != 0) ) {
|
if ( isset($_REQUEST['minTime']) && isset($_REQUEST['maxTime']) && (count($displayMonitors) != 0) ) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
//
|
//
|
||||||
// ZoneMinder web user view file, $Date$, $Revision$
|
// ZoneMinder web user view file
|
||||||
// Copyright (C) 2001-2008 Philip Coombes
|
// Copyright (C) 2020 ZoneMinder LLC
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or
|
// This program is free software; you can redistribute it and/or
|
||||||
// modify it under the terms of the GNU General Public License
|
// modify it under the terms of the GNU General Public License
|
||||||
|
@ -23,22 +23,17 @@ if ( !canEdit('System') ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
require_once('includes/Server.php');
|
||||||
|
require_once('includes/Storage.php');
|
||||||
|
|
||||||
if ( $_REQUEST['id'] ) {
|
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';
|
$view = 'error';
|
||||||
return;
|
return;
|
||||||
$newStorage['ServerId'] = '';
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$newStorage = array();
|
$newStorage = new ZM\Storage();
|
||||||
$newStorage['Name'] = translate('NewStorage');
|
$newStorage->Name(translate('NewStorage'));
|
||||||
$newStorage['Path'] = '';
|
|
||||||
$newStorage['Type'] = 'local';
|
|
||||||
$newStorage['Url'] = '';
|
|
||||||
$newStorage['Scheme'] = 'Medium';
|
|
||||||
$newStorage['StorageId'] = '';
|
|
||||||
$newStorage['ServerId'] = '';
|
|
||||||
$newStorage['DoDelete'] = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$type_options = array( 'local' => translate('Local'), 's3fs' => translate('s3fs') );
|
$type_options = array( 'local' => translate('Local'), 's3fs' => translate('s3fs') );
|
||||||
|
@ -55,12 +50,12 @@ foreach ( $servers as $S ) {
|
||||||
}
|
}
|
||||||
$focusWindow = true;
|
$focusWindow = true;
|
||||||
|
|
||||||
xhtmlHeaders(__FILE__, translate('Storage').' - '.$newStorage['Name']);
|
xhtmlHeaders(__FILE__, translate('Storage').' - '.$newStorage->Name());
|
||||||
?>
|
?>
|
||||||
<body>
|
<body>
|
||||||
<div id="page">
|
<div id="page">
|
||||||
<div id="header">
|
<div id="header">
|
||||||
<h2><?php echo translate('Storage').' - '.$newStorage['Name'] ?></h2>
|
<h2><?php echo translate('Storage').' - '.$newStorage->Name() ?></h2>
|
||||||
</div>
|
</div>
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<form name="contentForm" method="post" action="?" class="validateFormOnSubmit">
|
<form name="contentForm" method="post" action="?" class="validateFormOnSubmit">
|
||||||
|
@ -71,33 +66,40 @@ xhtmlHeaders(__FILE__, translate('Storage').' - '.$newStorage['Name']);
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row"><?php echo translate('Name') ?></th>
|
<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>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row"><?php echo translate('Path') ?></th>
|
<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>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row"><?php echo translate('Url') ?></th>
|
<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>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row"><?php echo translate('Server') ?></th>
|
<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>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row"><?php echo translate('Type') ?></th>
|
<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>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row"><?php echo translate('StorageScheme') ?></th>
|
<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>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row"><?php echo translate('StorageDoDelete') ?></th>
|
<th scope="row"><?php echo translate('StorageDoDelete') ?></th>
|
||||||
<td>
|
<td>
|
||||||
<input type="radio" name="newStorage[DoDelete]" value="1"<?php echo $newStorage['DoDelete'] ? 'checked="checked"' : '' ?>/>Yes
|
<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="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>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
@ -57,6 +57,7 @@ $filename = '';
|
||||||
$Frame = null;
|
$Frame = null;
|
||||||
$Event = null;
|
$Event = null;
|
||||||
$path = null;
|
$path = null;
|
||||||
|
$media_type='image/jpeg';
|
||||||
|
|
||||||
if ( empty($_REQUEST['path']) ) {
|
if ( empty($_REQUEST['path']) ) {
|
||||||
|
|
||||||
|
@ -77,6 +78,47 @@ if ( empty($_REQUEST['path']) ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $_REQUEST['fid'] == 'objdetect' ) {
|
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';
|
$path = $Event->Path().'/objdetect.jpg';
|
||||||
if ( !file_exists($path) ) {
|
if ( !file_exists($path) ) {
|
||||||
header('HTTP/1.0 404 Not Found');
|
header('HTTP/1.0 404 Not Found');
|
||||||
|
@ -281,7 +323,7 @@ if ( !empty($_REQUEST['height']) ) {
|
||||||
if ( $errorText ) {
|
if ( $errorText ) {
|
||||||
ZM\Error($errorText);
|
ZM\Error($errorText);
|
||||||
} else {
|
} else {
|
||||||
header('Content-type: image/jpeg');
|
header("Content-type: $media_type");
|
||||||
if ( ( $scale==0 || $scale==100 ) && ($width==0) && ($height==0) ) {
|
if ( ( $scale==0 || $scale==100 ) && ($width==0) && ($height==0) ) {
|
||||||
# This is so that Save Image As give a useful filename
|
# This is so that Save Image As give a useful filename
|
||||||
if ( $Event ) {
|
if ( $Event ) {
|
||||||
|
|
|
@ -25,13 +25,13 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
use strict;
|
use strict;
|
||||||
use lib './scripts/ZoneMinder/lib';
|
use lib '@CMAKE_CURRENT_BINARY_DIR@/scripts/ZoneMinder/lib';
|
||||||
use ZoneMinder::ConfigData qw/:data/;
|
use ZoneMinder::ConfigData qw/:data/;
|
||||||
|
|
||||||
$| = 1;
|
$| = 1;
|
||||||
|
|
||||||
my $config_header = "src/zm_config_defines.h";
|
my $config_header = '@CMAKE_CURRENT_BINARY_DIR@/src/zm_config_defines.h';
|
||||||
my $config_sql = "db/zm_create.sql";
|
my $config_sql = '@CMAKE_CURRENT_BINARY_DIR@/db/zm_create.sql';
|
||||||
|
|
||||||
generateConfigFiles();
|
generateConfigFiles();
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,8 @@
|
||||||
#cmakedefine HAVE_LIBAVRESAMPLE_AVRESAMPLE_H 1
|
#cmakedefine HAVE_LIBAVRESAMPLE_AVRESAMPLE_H 1
|
||||||
#cmakedefine HAVE_LIBVLC 1
|
#cmakedefine HAVE_LIBVLC 1
|
||||||
#cmakedefine HAVE_VLC_VLC_H 1
|
#cmakedefine HAVE_VLC_VLC_H 1
|
||||||
|
#cmakedefine HAVE_LIBVNC 1
|
||||||
|
#cmakedefine HAVE_RFB_RFB_H 1
|
||||||
#cmakedefine HAVE_LIBX264 1
|
#cmakedefine HAVE_LIBX264 1
|
||||||
#cmakedefine HAVE_X264_H 1
|
#cmakedefine HAVE_X264_H 1
|
||||||
#cmakedefine HAVE_LIBMP4V2 1
|
#cmakedefine HAVE_LIBMP4V2 1
|
||||||
|
|
Loading…
Reference in New Issue