Merge branch 'master' of github.com:ZoneMinder/zoneminder
This commit is contained in:
commit
2b289abb95
|
@ -167,6 +167,8 @@ set(ZM_NO_X10 "OFF" CACHE BOOL
|
|||
set(ZM_ONVIF "ON" CACHE BOOL
|
||||
"Set to ON to enable basic ONVIF support. This is EXPERIMENTAL and may not
|
||||
work with all cameras claiming to be ONVIF compliant. default: ON")
|
||||
set(ZM_NO_PCRE "OFF" CACHE BOOL
|
||||
"Set to ON to skip libpcre3 checks and force building ZM without libpcre3. default: OFF")
|
||||
set(ZM_NO_RTSPSERVER "OFF" CACHE BOOL
|
||||
"Set to ON to skip building ZM with rtsp server support. default: OFF")
|
||||
set(ZM_PERL_MM_PARMS INSTALLDIRS=vendor NO_PACKLIST=1 NO_PERLLOCAL=1 CACHE STRING
|
||||
|
@ -407,6 +409,8 @@ else()
|
|||
message(FATAL_ERROR "ZoneMinder requires pthread but it was not found on your system")
|
||||
endif()
|
||||
|
||||
# Do not check for cURL if ZM_NO_CURL is on
|
||||
if(NOT ZM_NO_PRCE)
|
||||
# pcre (using find_library and find_path)
|
||||
find_library(PCRE_LIBRARIES pcre)
|
||||
if(PCRE_LIBRARIES)
|
||||
|
@ -423,6 +427,7 @@ if(PCRE_LIBRARIES)
|
|||
else()
|
||||
set(optlibsnotfound "${optlibsnotfound} PCRE")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# mysqlclient (using find_library and find_path)
|
||||
find_library(MYSQLCLIENT_LIBRARIES mysqlclient PATH_SUFFIXES mysql)
|
||||
|
@ -540,6 +545,7 @@ set(ZM_PCRE 0)
|
|||
if(HAVE_LIBPCRE AND HAVE_PCRE_H)
|
||||
set(ZM_PCRE 1)
|
||||
endif()
|
||||
|
||||
# Check for mmap and enable in all components
|
||||
set(ZM_MEM_MAPPED 0)
|
||||
set(ENABLE_MMAP no)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
configure_file(zm_create.sql.in "${CMAKE_CURRENT_BINARY_DIR}/zm_create.sql" @ONLY)
|
||||
configure_file(zm_update-1.31.30.sql.in "${CMAKE_CURRENT_BINARY_DIR}/zm_update-1.31.30.sql" @ONLY)
|
||||
configure_file(zm_update-1.35.24.sql.in "${CMAKE_CURRENT_BINARY_DIR}/zm_update-1.35.24.sql" @ONLY)
|
||||
configure_file(zm_update-1.37.4.sql.in "${CMAKE_CURRENT_BINARY_DIR}/zm_update-1.37.4.sql" @ONLY)
|
||||
|
||||
# Glob all database upgrade scripts
|
||||
file(GLOB dbfileslist RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "zm_update-*.sql")
|
||||
|
@ -15,6 +16,8 @@ install(FILES ${dbfileslist} DESTINATION "${CMAKE_INSTALL_DATADIR}/zoneminder/db
|
|||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/zm_update-1.31.30.sql" DESTINATION "${CMAKE_INSTALL_DATADIR}/zoneminder/db")
|
||||
# install zm_update-1.35.24.sql
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/zm_update-1.35.24.sql" DESTINATION "${CMAKE_INSTALL_DATADIR}/zoneminder/db")
|
||||
# install zm_update-1.37.4.sql
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/zm_update-1.37.4.sql" DESTINATION "${CMAKE_INSTALL_DATADIR}/zoneminder/db")
|
||||
|
||||
# install zm_create.sql
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/zm_create.sql" DESTINATION "${CMAKE_INSTALL_DATADIR}/zoneminder/db")
|
||||
|
@ -22,3 +25,8 @@ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/zm_create.sql" DESTINATION "${CMAKE_I
|
|||
# install triggers.sql
|
||||
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/triggers.sql" DESTINATION "${CMAKE_INSTALL_DATADIR}/zoneminder/db")
|
||||
|
||||
# install manufacturers.sql
|
||||
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/manufacturers.sql" DESTINATION "${CMAKE_INSTALL_DATADIR}/zoneminder/db")
|
||||
|
||||
# install models.sql
|
||||
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/models.sql" DESTINATION "${CMAKE_INSTALL_DATADIR}/zoneminder/db")
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
INSERT IGNORE INTO Manufacturers VALUES (1, 'Acti');
|
||||
INSERT IGNORE INTO Manufacturers VALUES (2, 'Amcrest');
|
||||
INSERT IGNORE INTO Manufacturers VALUES (3, 'Airlink101');
|
||||
INSERT IGNORE INTO Manufacturers VALUES (4, 'Arecont Vision');
|
||||
INSERT IGNORE INTO Manufacturers VALUES (5, 'Axis');
|
||||
INSERT IGNORE INTO Manufacturers VALUES (6, 'Dahua');
|
||||
INSERT IGNORE INTO Manufacturers VALUES (7, 'D-Link');
|
||||
INSERT IGNORE INTO Manufacturers VALUES (8, 'Edimax');
|
||||
INSERT IGNORE INTO Manufacturers VALUES (9, 'Foscam');
|
||||
INSERT IGNORE INTO Manufacturers VALUES (10, 'Gadspot');
|
||||
INSERT IGNORE INTO Manufacturers VALUES (11, 'GrandStream');
|
||||
INSERT IGNORE INTO Manufacturers VALUES (12, 'HikVision');
|
||||
INSERT IGNORE INTO Manufacturers VALUES (13, 'JVC');
|
||||
INSERT IGNORE INTO Manufacturers VALUES (14, 'Maginon');
|
||||
INSERT IGNORE INTO Manufacturers VALUES (15, 'Mobotix');
|
||||
INSERT IGNORE INTO Manufacturers VALUES (16, 'Oncam Grandeye');
|
||||
INSERT IGNORE INTO Manufacturers VALUES (17, 'Panasonic');
|
||||
INSERT IGNORE INTO Manufacturers VALUES (18, 'Pelco');
|
||||
INSERT IGNORE INTO Manufacturers VALUES (19, 'Sony');
|
||||
INSERT IGNORE INTO Manufacturers VALUES (20, 'TP-Link');
|
||||
INSERT IGNORE INTO Manufacturers VALUES (21, 'Trendnet');
|
||||
INSERT IGNORE INTO Manufacturers VALUES (22, 'VisionTek');
|
||||
INSERT IGNORE INTO Manufacturers VALUES (23, 'Vivotek');
|
||||
INSERT IGNORE INTO Manufacturers VALUES (24, 'Wansview');
|
|
@ -0,0 +1,56 @@
|
|||
/* INSERT INTO Manufacturers VALUES (1, 'Acti'); */
|
||||
INSERT IGNORE INTO Models (ManufacturerId,Name) VALUES (1, 'A21');
|
||||
INSERT IGNORE INTO Models (ManufacturerId,Name) VALUES (1, 'A23');
|
||||
INSERT IGNORE INTO Models (ManufacturerId,Name) VALUES (1, 'A24');
|
||||
INSERT IGNORE INTO Models (ManufacturerId,Name) VALUES (1, 'A28');
|
||||
INSERT IGNORE INTO Models (ManufacturerId,Name) VALUES (1, 'A31');
|
||||
INSERT IGNORE INTO Models (ManufacturerId,Name) VALUES (1, 'A310');
|
||||
INSERT IGNORE INTO Models (ManufacturerId,Name) VALUES (1, 'A311');
|
||||
INSERT IGNORE INTO Models (ManufacturerId,Name) VALUES (1, 'A32');
|
||||
INSERT IGNORE INTO Models (ManufacturerId,Name) VALUES (1, 'A41');
|
||||
INSERT IGNORE INTO Models (ManufacturerId,Name) VALUES (1, 'A415');
|
||||
INSERT IGNORE INTO Models (ManufacturerId,Name) VALUES (1, 'A416');
|
||||
INSERT IGNORE INTO Models (ManufacturerId,Name) VALUES (1, 'A418');
|
||||
INSERT IGNORE INTO Models (ManufacturerId,Name) VALUES (1, 'A42');
|
||||
INSERT IGNORE INTO Models (ManufacturerId,Name) VALUES (1, 'A421');
|
||||
INSERT IGNORE INTO Models (ManufacturerId,Name) VALUES (1, 'A43');
|
||||
INSERT IGNORE INTO Models (ManufacturerId,Name) VALUES (1, 'A45');
|
||||
INSERT IGNORE INTO Models (ManufacturerId,Name) VALUES (1, 'A46');
|
||||
INSERT IGNORE INTO Models (ManufacturerId,Name) VALUES (1, 'A48');
|
||||
INSERT IGNORE INTO Models (ManufacturerId,Name) VALUES (1, 'A74');
|
||||
/*
|
||||
INSERT INTO Manufacturers VALUES (2, 'Amcrest');
|
||||
*/
|
||||
INSERT IGNORE INTO Models (ManufacturerId,Name) VALUES (2, 'IP8M-T2499EW');
|
||||
INSERT IGNORE INTO Models (ManufacturerId,Name) VALUES (2, 'ASH42-B');
|
||||
/*
|
||||
INSERT INTO Manufacturers VALUES (3, 'Airlink101');
|
||||
INSERT INTO Manufacturers VALUES (4, 'Arecont Vision');
|
||||
INSERT INTO Manufacturers VALUES (5, 'Axis');
|
||||
INSERT INTO Manufacturers VALUES (6, 'Dahua');
|
||||
INSERT INTO Manufacturers VALUES (7, 'D-Link');
|
||||
*/
|
||||
INSERT IGNORE INTO Models (ManufacturerId,Name) VALUES (7, 'DCS-930L');
|
||||
INSERT IGNORE INTO Models (ManufacturerId,Name) VALUES (7, 'DCS-932L');
|
||||
INSERT IGNORE INTO Models (ManufacturerId,Name) VALUES (7, 'DCS-933L');
|
||||
INSERT IGNORE INTO Models (ManufacturerId,Name) VALUES (7, 'DCS-942L');
|
||||
INSERT IGNORE INTO Models (ManufacturerId,Name) VALUES (7, 'DCS-5020L');
|
||||
/*
|
||||
INSERT INTO Manufacturers VALUES (8, 'Edimax');
|
||||
INSERT INTO Manufacturers VALUES (9, 'Foscam');
|
||||
INSERT INTO Manufacturers VALUES (10, 'Gadspot');
|
||||
INSERT INTO Manufacturers VALUES (11, 'GrandStream');
|
||||
INSERT INTO Manufacturers VALUES (12, 'HikVision');
|
||||
INSERT INTO Manufacturers VALUES (13, 'JVC');
|
||||
INSERT INTO Manufacturers VALUES (14, 'Maginon');
|
||||
INSERT INTO Manufacturers VALUES (15, 'Mobotix');
|
||||
INSERT INTO Manufacturers VALUES (16, 'Oncam Grandeye');
|
||||
INSERT INTO Manufacturers VALUES (17, 'Panasonic');
|
||||
INSERT INTO Manufacturers VALUES (18, 'Pelco');
|
||||
INSERT INTO Manufacturers VALUES (19, 'Sony');
|
||||
INSERT INTO Manufacturers VALUES (20, 'TP-Link');
|
||||
INSERT INTO Manufacturers VALUES (21, 'Trendnet');
|
||||
INSERT INTO Manufacturers VALUES (22, 'VisionTek');
|
||||
INSERT INTO Manufacturers VALUES (23, 'Vivotek');
|
||||
INSERT INTO Manufacturers VALUES (24, 'Wansview');
|
||||
*/
|
|
@ -412,6 +412,7 @@ CREATE TABLE `Models` (
|
|||
DROP TABLE IF EXISTS `MonitorPresets`;
|
||||
CREATE TABLE `MonitorPresets` (
|
||||
`Id` int(10) unsigned NOT NULL auto_increment,
|
||||
`ModelId` int unsigned, FOREIGN KEY (`ModelId`) REFERENCES `Models` (Id),
|
||||
`Name` varchar(64) NOT NULL default '',
|
||||
`Type` enum('Local','Remote','File','Ffmpeg','Libvlc','cURL','WebSite','NVSocket','VNC') NOT NULL default 'Local',
|
||||
`Device` tinytext,
|
||||
|
@ -447,12 +448,16 @@ CREATE TABLE `Monitors` (
|
|||
`Notes` TEXT,
|
||||
`ServerId` int(10) unsigned,
|
||||
`StorageId` smallint(5) unsigned default 0,
|
||||
`ManufacturerId` int unsigned, FOREIGN KEY (`ManufacturerId`) REFERENCES `Manufacturers` (Id),
|
||||
`ModelId` int unsigned, FOREIGN KEY (`ModelId`) REFERENCES `Models` (Id),
|
||||
`Type` enum('Local','Remote','File','Ffmpeg','Libvlc','cURL','WebSite','NVSocket','VNC') NOT NULL default 'Local',
|
||||
`Function` enum('None','Monitor','Modect','Record','Mocord','Nodect') NOT NULL default 'Monitor',
|
||||
`Enabled` tinyint(3) unsigned NOT NULL default '1',
|
||||
`DecodingEnabled` tinyint(3) unsigned NOT NULL default '1',
|
||||
`LinkedMonitors` varchar(255),
|
||||
`Triggers` set('X10') NOT NULL default '',
|
||||
`EventStartCommand` VARCHAR(255) NOT NULL DEFAULT '',
|
||||
`EventEndCommand` VARCHAR(255) NOT NULL DEFAULT '',
|
||||
`ONVIF_URL` VARCHAR(255) NOT NULL DEFAULT '',
|
||||
`ONVIF_Username` VARCHAR(64) NOT NULL DEFAULT '',
|
||||
`ONVIF_Password` VARCHAR(64) NOT NULL DEFAULT '',
|
||||
|
@ -971,81 +976,81 @@ INSERT INTO `Controls` VALUES (NULL,'Amcrest HTTP API','Ffmpeg','Amcrest_HTTP',0
|
|||
-- Add some monitor preset values
|
||||
--
|
||||
|
||||
INSERT into MonitorPresets VALUES (NULL,'Amcrest, IP8M-T2499EW 640x480, RTP/RTSP','Ffmpeg','rtsp',0,255,'rtsp','rtpRtsp','NULL',554,'rtsp://<username>:<password>@<ip-address>/cam/realmonitor?channel=1&subtype=1',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT into MonitorPresets VALUES (NULL,'Amcrest, IP8M-T2499EW 3840x2160, RTP/RTSP','Ffmpeg','rtsp',0,255,'rtsp','rtpRtsp','NULL',554,'rtsp://<username>:<password>@<ip-address>/cam/realmonitor?channel=1&subtype=0',NULL,3840,2160,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Axis IP, 320x240, mpjpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Axis IP, 320x240, mpjpeg, max 5 FPS','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240&req_fps=5',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Axis IP, 320x240, jpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/jpg/image.cgi?resolution=320x240',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Axis IP, 320x240, jpeg, max 5 FPS','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/jpg/image.cgi?resolution=320x240',NULL,320,240,3,5.0,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Axis IP, 640x480, mpjpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/mjpg/video.cgi?resolution=640x480',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Axis IP, 640x480, mpjpeg, max 5 FPS','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/mjpg/video.cgi?resolution=640x480&req_fps=5',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Axis IP, 640x480, jpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/jpg/image.cgi?resolution=640x480',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Axis IP, 640x480, jpeg, max 5 FPS','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/jpg/image.cgi?resolution=640x480',NULL,640,480,3,5.0,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Axis IP, 320x240, mpjpeg, B&W','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240&color=0',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Axis IP, 640x480, mpjpeg, B&W','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/mjpg/video.cgi?resolution=640x480&color=0',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Axis IP PTZ, 320x240, mpjpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240',NULL,320,240,3,NULL,1,4,NULL,'<ip-address>:<port>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Axis IP PTZ, 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,1,4,NULL,'<ip-address>:<port>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Axis IP PTZ, 320x240, jpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/jpg/image.cgi?resolution=320x240',NULL,320,240,3,NULL,1,4,NULL,'<ip-address>:<port>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Axis IP PTZ, 320x240, jpeg, max 5 FPS','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/jpg/image.cgi?resolution=320x240',NULL,320,240,3,5.0,1,4,NULL,'<ip-address>:<port>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Axis IP PTZ, 640x480, mpjpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/mjpg/video.cgi?resolution=640x480',NULL,640,480,3,NULL,1,4,NULL,'<ip-address>:<port>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Axis IP PTZ, 640x480, mpjpeg, max 5 FPS','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/mjpg/video.cgi?resolution=640x480&req_fps=5',NULL,640,480,3,NULL,1,4,NULL,'<ip-address>:<port>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Axis IP PTZ, 640x480, jpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/jpg/image.cgi?resolution=640x480',NULL,640,480,3,NULL,1,4,NULL,'<ip-address>:<port>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Axis IP PTZ, 640x480, jpeg, max 5 FPS','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/jpg/image.cgi?resolution=640x480',NULL,640,480,3,5.0,1,4,NULL,'<ip-address>:<port>',100,100);
|
||||
INSERT into MonitorPresets VALUES (NULL,'Axis IP, mpeg4, unicast','Remote','rtsp',0,255,'rtsp','rtpUni','<ip-address>',554,'/mpeg4/media.amp','/trackID=',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT into MonitorPresets VALUES (NULL,'Axis IP, mpeg4, multicast','Remote','rtsp',0,255,'rtsp','rtpMulti','<ip-address>',554,'/mpeg4/media.amp','/trackID=',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT into MonitorPresets VALUES (NULL,'Axis IP, mpeg4, RTP/RTSP','Remote','rtsp',0,255,'rtsp','rtpRtsp','<ip-address>',554,'/mpeg4/media.amp','/trackID=',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT into MonitorPresets VALUES (NULL,'Axis IP, mpeg4, RTP/RTSP/HTTP','Remote',NULL,NULL,NULL,'rtsp','rtpRtspHttp','<ip-address>',554,'/mpeg4/media.amp','/trackID=',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'D-link DCS-930L, 640x480, mjpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/mjpeg.cgi',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'D-Link DCS-5020L, 640x480, mjpeg','Remote','http',0,0,'http','simple','<username>:<pwd>@<ip-address>','80','/video.cgi',NULL,640,480,0,NULL,1,'34',NULL,'<username>:<pwd>@<ip-address>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Panasonic IP, 320x240, mpjpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/nphMotionJpeg?Resolution=320x240&Quality=Standard',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Panasonic IP, 320x240, jpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/SnapshotJPEG?Resolution=320x240&Quality=Standard',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Panasonic IP, 320x240, jpeg, max 5 FPS','Remote','http',0,0,'http','simple','<ip-address>',80,'/SnapshotJPEG?Resolution=320x240&Quality=Standard',NULL,320,240,3,5.0,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Panasonic IP, 640x480, mpjpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/nphMotionJpeg?Resolution=640x480&Quality=Standard',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Panasonic IP, 640x480, jpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/SnapshotJPEG?Resolution=640x480&Quality=Standard',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Panasonic IP, 640x480, jpeg, max 5 FPS','Remote','http',0,0,'http','simple','<ip-address>',80,'/SnapshotJPEG?Resolution=640x480&Quality=Standard',NULL,640,480,3,5.0,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Panasonic IP PTZ, 320x240, mpjpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/nphMotionJpeg?Resolution=320x240&Quality=Standard',NULL,320,240,3,NULL,1,5,NULL,'<ip-address>:<port>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Panasonic IP PTZ, 320x240, jpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/SnapshotJPEG?Resolution=320x240&Quality=Standard',NULL,320,240,3,NULL,1,5,NULL,'<ip-address>:<port>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Panasonic IP PTZ, 320x240, jpeg, max 5 FPS','Remote','http',0,0,'http','simple','<ip-address>',80,'/SnapshotJPEG?Resolution=320x240&Quality=Standard',NULL,320,240,3,5.0,1,5,NULL,'<ip-address>:<port>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Panasonic IP PTZ, 640x480, mpjpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/nphMotionJpeg?Resolution=640x480&Quality=Standard',NULL,640,480,3,NULL,1,5,NULL,'<ip-address>:<port>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Panasonic IP PTZ, 640x480, jpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/SnapshotJPEG?Resolution=640x480&Quality=Standard',NULL,640,480,3,NULL,1,5,NULL,'<ip-address>:<port>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Panasonic IP PTZ, 640x480, jpeg, max 5 FPS','Remote','http',0,0,'http','simple','<ip-address>',80,'/SnapshotJPEG?Resolution=640x480&Quality=Standard',NULL,640,480,3,5.0,1,5,NULL,'<ip-address>:<port>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Gadspot IP, jpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/Jpeg/CamImg.jpg',NULL,NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Gadspot IP, jpeg, max 5 FPS','Remote','http',0,0,'http','simple','<ip-address>',80,'/Jpeg/CamImg.jpg',NULL,NULL,NULL,3,5.0,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Gadspot IP, mpjpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/GetData.cgi',NULL,NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Gadspot IP, mpjpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/Jpeg/CamImg.jpg',NULL,NULL,NULL,3,5.0,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'IP Webcam by Pavel Khlebovich 1920x1080','Remote','/dev/video<?>','0',255,'http','simple','<ip-address>','8080','/video','',1920,1080,0,NULL,0,'0','','',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'VEO Observer, jpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/Jpeg/CamImg.jpg',NULL,NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Blue Net Video Server, jpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/cgi-bin/image.cgi?control=0&id=admin&passwd=admin',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT into MonitorPresets VALUES (NULL,'ACTi IP, mpeg4, unicast','Remote',NULL,NULL,NULL,'rtsp','rtpUni','<ip-address>',7070,'','/track',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Axis FFMPEG H.264','Ffmpeg',NULL,NULL,NULL,NULL,NULL,'rtsp://<host/address>/axis-media/media.amp?videocodec=h264',NULL,NULL,NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Vivotek FFMPEG','Ffmpeg',NULL,NULL,NULL,NULL,NULL,'rtsp://<host/address>:554/live.sdp',NULL,NULL,NULL,352,240,NULL,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Axis FFMPEG','Ffmpeg',NULL,NULL,NULL,NULL,NULL,'rtsp://<host/address>/axis-media/media.amp',NULL,NULL,NULL,640,480,NULL,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'ACTi TCM FFMPEG','Ffmpeg',NULL,NULL,NULL,NULL,NULL,'rtsp://admin:123456@<host/address>:7070',NULL,NULL,NULL,320,240,NULL,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'BTTV Video (V4L2), PAL, 320x240','Local','/dev/video<?>',0,255,NULL,'v4l2',NULL,NULL,NULL,NULL,320,240,1345466932,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'BTTV Video (V4L2), PAL, 320x240, max 5 FPS','Local','/dev/video<?>',0,255,NULL,'v4l2',NULL,NULL,NULL,NULL,320,240,1345466932,5.0,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'BTTV Video (V4L2), PAL, 640x480','Local','/dev/video<?>',0,255,NULL,'v4l2',NULL,NULL,NULL,NULL,640,480,1345466932,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'BTTV Video (V4L2), PAL, 640x480, max 5 FPS','Local','/dev/video<?>',0,255,NULL,'v4l2',NULL,NULL,NULL,NULL,640,480,1345466932,5.0,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'BTTV Video (V4L2), NTSC, 320x240','Local','/dev/video<?>',0,45056,NULL,'v4l2',NULL,NULL,NULL,NULL,320,240,1345466932,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'BTTV Video (V4L2), NTSC, 320x240, max 5 FPS','Local','/dev/video<?>',0,45056,NULL,'v4l2',NULL,NULL,NULL,NULL,320,240,1345466932,5.0,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'BTTV Video (V4L2), NTSC, 640x480','Local','/dev/video<?>',0,45056,NULL,'v4l2',NULL,NULL,NULL,NULL,640,480,1345466932,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'BTTV Video (V4L2), NTSC, 640x480, max 5 FPS','Local','/dev/video<?>',0,45056,NULL,'v4l2',NULL,NULL,NULL,NULL,640,480,1345466932,5.0,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'BTTV Video (V4L1), PAL, 320x240','Local','/dev/video<?>',0,0,NULL,'v4l1',NULL,NULL,NULL,NULL,320,240,13,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'BTTV Video (V4L1), PAL, 320x240, max 5 FPS','Local','/dev/video<?>',0,0,NULL,'v4l1',NULL,NULL,NULL,NULL,320,240,13,5.0,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'BTTV Video (V4L1), PAL, 640x480','Local','/dev/video<?>',0,0,NULL,'v4l1',NULL,NULL,NULL,NULL,640,480,13,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'BTTV Video (V4L1), PAL, 640x480, max 5 FPS','Local','/dev/video<?>',0,0,NULL,'v4l1',NULL,NULL,NULL,NULL,640,480,13,5.0,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'BTTV Video (V4L1), NTSC, 320x240','Local','/dev/video<?>',0,1,NULL,'v4l1',NULL,NULL,NULL,NULL,320,240,13,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'BTTV Video (V4L1), NTSC, 320x240, max 5 FPS','Local','/dev/video<?>',0,1,NULL,'v4l1',NULL,NULL,NULL,NULL,320,240,13,5.0,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'BTTV Video (V4L1), NTSC, 640x480','Local','/dev/video<?>',0,1,NULL,'v4l1',NULL,NULL,NULL,NULL,640,480,13,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'BTTV Video (V4L1), NTSC, 640x480, max 5 FPS','Local','/dev/video<?>',0,1,NULL,'v4l1',NULL,NULL,NULL,NULL,640,480,13,5.0,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Remote ZoneMinder','Remote',NULL,NULL,NULL,'http','simple','<ip-address>',80,'/cgi-bin/nph-zms?mode=jpeg&monitor=<monitor-id>&scale=100&maxfps=5&buffer=0',NULL,NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Foscam FI8620 FFMPEG H.264','Ffmpeg',NULL,NULL,NULL,NULL,'','','','rtsp://<username>:<pwd>@<ip-address>:554/11',NULL,704,576,0,NULL,1,'10','<admin_pwd>','<ip-address>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Foscam FI8608W FFMPEG H.264','Ffmpeg',NULL,NULL,NULL,NULL,'','','','rtsp://<username>:<pwd>@<ip-address>:554/11',NULL,640,480,0,NULL,1,'11','<admin_pwd>','<ip-address>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Foscam FI9821W FFMPEG H.264','Ffmpeg',NULL,NULL,NULL,NULL,'','','','rtsp://<username>:<pwd>@<ip-address>:88/videoMain',NULL,1280,720,0,NULL,1,'12','<admin_pwd>','<ip-address>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Loftek Sentinel PTZ, 640x480, mjpeg','Remote','http',0,0,NULL,NULL,'<ip-address>','80','/videostream.cgi?user=<username>&pwd=<password>&resolution=32&rate=11',NULL,640,480,4,NULL,1,'13','','<username>:<pwd>@<ip-address>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Airlink 777W PTZ, 640x480, mjpeg','Remote','http',0,0,NULL,NULL,'<username>:<password>@<ip-address>','80','/cgi/mjpg/mjpg.cgi',NULL,640,480,4,NULL,1,'7','','<username>:<pwd>@<ip-address>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'SunEyes SP-P1802SWPTZ','Libvlc','/dev/video<?>','0',255,'','rtpMulti','','80','rtsp://<ip-address>:554/11','',1920,1080,0,0.00,1,'16','-speed=64','<ip-address>:<port>',100,33);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Qihan IP, 1280x720, RTP/RTSP','Ffmpeg','rtsp',0,255,'rtsp','rtpRtsp',NULL,554,'rtsp://<ip-address>/tcp_live/ch0_0',NULL,1280,720,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,'Qihan IP, 1920x1080, RTP/RTSP','Ffmpeg','rtsp',0,255,'rtsp','rtpRtsp',NULL,554,'rtsp://<ip-address>/tcp_live/ch0_0',NULL,1920,1080,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT into MonitorPresets VALUES (NULL,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,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,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,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,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,NULL,'Axis IP, 320x240, jpeg, max 5 FPS','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/jpg/image.cgi?resolution=320x240',NULL,320,240,3,5.0,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Axis IP, 640x480, mpjpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/mjpg/video.cgi?resolution=640x480',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Axis IP, 640x480, mpjpeg, max 5 FPS','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/mjpg/video.cgi?resolution=640x480&req_fps=5',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Axis IP, 640x480, jpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/jpg/image.cgi?resolution=640x480',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Axis IP, 640x480, jpeg, max 5 FPS','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/jpg/image.cgi?resolution=640x480',NULL,640,480,3,5.0,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Axis IP, 320x240, mpjpeg, B&W','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240&color=0',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Axis IP, 640x480, mpjpeg, B&W','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/mjpg/video.cgi?resolution=640x480&color=0',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Axis IP PTZ, 320x240, mpjpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240',NULL,320,240,3,NULL,1,4,NULL,'<ip-address>:<port>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Axis IP PTZ, 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,1,4,NULL,'<ip-address>:<port>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Axis IP PTZ, 320x240, jpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/jpg/image.cgi?resolution=320x240',NULL,320,240,3,NULL,1,4,NULL,'<ip-address>:<port>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Axis IP PTZ, 320x240, jpeg, max 5 FPS','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/jpg/image.cgi?resolution=320x240',NULL,320,240,3,5.0,1,4,NULL,'<ip-address>:<port>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Axis IP PTZ, 640x480, mpjpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/mjpg/video.cgi?resolution=640x480',NULL,640,480,3,NULL,1,4,NULL,'<ip-address>:<port>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Axis IP PTZ, 640x480, mpjpeg, max 5 FPS','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/mjpg/video.cgi?resolution=640x480&req_fps=5',NULL,640,480,3,NULL,1,4,NULL,'<ip-address>:<port>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Axis IP PTZ, 640x480, jpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/jpg/image.cgi?resolution=640x480',NULL,640,480,3,NULL,1,4,NULL,'<ip-address>:<port>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Axis IP PTZ, 640x480, jpeg, max 5 FPS','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/jpg/image.cgi?resolution=640x480',NULL,640,480,3,5.0,1,4,NULL,'<ip-address>:<port>',100,100);
|
||||
INSERT into MonitorPresets VALUES (NULL,NULL,'Axis IP, mpeg4, unicast','Remote','rtsp',0,255,'rtsp','rtpUni','<ip-address>',554,'/mpeg4/media.amp','/trackID=',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT into MonitorPresets VALUES (NULL,NULL,'Axis IP, mpeg4, multicast','Remote','rtsp',0,255,'rtsp','rtpMulti','<ip-address>',554,'/mpeg4/media.amp','/trackID=',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT into MonitorPresets VALUES (NULL,NULL,'Axis IP, mpeg4, RTP/RTSP','Remote','rtsp',0,255,'rtsp','rtpRtsp','<ip-address>',554,'/mpeg4/media.amp','/trackID=',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT into MonitorPresets VALUES (NULL,NULL,'Axis IP, mpeg4, RTP/RTSP/HTTP','Remote',NULL,NULL,NULL,'rtsp','rtpRtspHttp','<ip-address>',554,'/mpeg4/media.amp','/trackID=',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'D-link DCS-930L, 640x480, mjpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/mjpeg.cgi',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'D-Link DCS-5020L, 640x480, mjpeg','Remote','http',0,0,'http','simple','<username>:<pwd>@<ip-address>','80','/video.cgi',NULL,640,480,0,NULL,1,'34',NULL,'<username>:<pwd>@<ip-address>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Panasonic IP, 320x240, mpjpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/nphMotionJpeg?Resolution=320x240&Quality=Standard',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Panasonic IP, 320x240, jpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/SnapshotJPEG?Resolution=320x240&Quality=Standard',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Panasonic IP, 320x240, jpeg, max 5 FPS','Remote','http',0,0,'http','simple','<ip-address>',80,'/SnapshotJPEG?Resolution=320x240&Quality=Standard',NULL,320,240,3,5.0,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Panasonic IP, 640x480, mpjpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/nphMotionJpeg?Resolution=640x480&Quality=Standard',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Panasonic IP, 640x480, jpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/SnapshotJPEG?Resolution=640x480&Quality=Standard',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Panasonic IP, 640x480, jpeg, max 5 FPS','Remote','http',0,0,'http','simple','<ip-address>',80,'/SnapshotJPEG?Resolution=640x480&Quality=Standard',NULL,640,480,3,5.0,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Panasonic IP PTZ, 320x240, mpjpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/nphMotionJpeg?Resolution=320x240&Quality=Standard',NULL,320,240,3,NULL,1,5,NULL,'<ip-address>:<port>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Panasonic IP PTZ, 320x240, jpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/SnapshotJPEG?Resolution=320x240&Quality=Standard',NULL,320,240,3,NULL,1,5,NULL,'<ip-address>:<port>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Panasonic IP PTZ, 320x240, jpeg, max 5 FPS','Remote','http',0,0,'http','simple','<ip-address>',80,'/SnapshotJPEG?Resolution=320x240&Quality=Standard',NULL,320,240,3,5.0,1,5,NULL,'<ip-address>:<port>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Panasonic IP PTZ, 640x480, mpjpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/nphMotionJpeg?Resolution=640x480&Quality=Standard',NULL,640,480,3,NULL,1,5,NULL,'<ip-address>:<port>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Panasonic IP PTZ, 640x480, jpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/SnapshotJPEG?Resolution=640x480&Quality=Standard',NULL,640,480,3,NULL,1,5,NULL,'<ip-address>:<port>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Panasonic IP PTZ, 640x480, jpeg, max 5 FPS','Remote','http',0,0,'http','simple','<ip-address>',80,'/SnapshotJPEG?Resolution=640x480&Quality=Standard',NULL,640,480,3,5.0,1,5,NULL,'<ip-address>:<port>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Gadspot IP, jpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/Jpeg/CamImg.jpg',NULL,NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Gadspot IP, jpeg, max 5 FPS','Remote','http',0,0,'http','simple','<ip-address>',80,'/Jpeg/CamImg.jpg',NULL,NULL,NULL,3,5.0,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Gadspot IP, mpjpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/GetData.cgi',NULL,NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Gadspot IP, mpjpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/Jpeg/CamImg.jpg',NULL,NULL,NULL,3,5.0,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'IP Webcam by Pavel Khlebovich 1920x1080','Remote','/dev/video<?>','0',255,'http','simple','<ip-address>','8080','/video','',1920,1080,0,NULL,0,'0','','',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'VEO Observer, jpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/Jpeg/CamImg.jpg',NULL,NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Blue Net Video Server, jpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/cgi-bin/image.cgi?control=0&id=admin&passwd=admin',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT into MonitorPresets VALUES (NULL,NULL,'ACTi IP, mpeg4, unicast','Remote',NULL,NULL,NULL,'rtsp','rtpUni','<ip-address>',7070,'','/track',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Axis FFMPEG H.264','Ffmpeg',NULL,NULL,NULL,NULL,NULL,'rtsp://<host/address>/axis-media/media.amp?videocodec=h264',NULL,NULL,NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Vivotek FFMPEG','Ffmpeg',NULL,NULL,NULL,NULL,NULL,'rtsp://<host/address>:554/live.sdp',NULL,NULL,NULL,352,240,NULL,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Axis FFMPEG','Ffmpeg',NULL,NULL,NULL,NULL,NULL,'rtsp://<host/address>/axis-media/media.amp',NULL,NULL,NULL,640,480,NULL,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'ACTi TCM FFMPEG','Ffmpeg',NULL,NULL,NULL,NULL,NULL,'rtsp://admin:123456@<host/address>:7070',NULL,NULL,NULL,320,240,NULL,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'BTTV Video (V4L2), PAL, 320x240','Local','/dev/video<?>',0,255,NULL,'v4l2',NULL,NULL,NULL,NULL,320,240,1345466932,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'BTTV Video (V4L2), PAL, 320x240, max 5 FPS','Local','/dev/video<?>',0,255,NULL,'v4l2',NULL,NULL,NULL,NULL,320,240,1345466932,5.0,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'BTTV Video (V4L2), PAL, 640x480','Local','/dev/video<?>',0,255,NULL,'v4l2',NULL,NULL,NULL,NULL,640,480,1345466932,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'BTTV Video (V4L2), PAL, 640x480, max 5 FPS','Local','/dev/video<?>',0,255,NULL,'v4l2',NULL,NULL,NULL,NULL,640,480,1345466932,5.0,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'BTTV Video (V4L2), NTSC, 320x240','Local','/dev/video<?>',0,45056,NULL,'v4l2',NULL,NULL,NULL,NULL,320,240,1345466932,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'BTTV Video (V4L2), NTSC, 320x240, max 5 FPS','Local','/dev/video<?>',0,45056,NULL,'v4l2',NULL,NULL,NULL,NULL,320,240,1345466932,5.0,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'BTTV Video (V4L2), NTSC, 640x480','Local','/dev/video<?>',0,45056,NULL,'v4l2',NULL,NULL,NULL,NULL,640,480,1345466932,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'BTTV Video (V4L2), NTSC, 640x480, max 5 FPS','Local','/dev/video<?>',0,45056,NULL,'v4l2',NULL,NULL,NULL,NULL,640,480,1345466932,5.0,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'BTTV Video (V4L1), PAL, 320x240','Local','/dev/video<?>',0,0,NULL,'v4l1',NULL,NULL,NULL,NULL,320,240,13,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'BTTV Video (V4L1), PAL, 320x240, max 5 FPS','Local','/dev/video<?>',0,0,NULL,'v4l1',NULL,NULL,NULL,NULL,320,240,13,5.0,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'BTTV Video (V4L1), PAL, 640x480','Local','/dev/video<?>',0,0,NULL,'v4l1',NULL,NULL,NULL,NULL,640,480,13,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'BTTV Video (V4L1), PAL, 640x480, max 5 FPS','Local','/dev/video<?>',0,0,NULL,'v4l1',NULL,NULL,NULL,NULL,640,480,13,5.0,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'BTTV Video (V4L1), NTSC, 320x240','Local','/dev/video<?>',0,1,NULL,'v4l1',NULL,NULL,NULL,NULL,320,240,13,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'BTTV Video (V4L1), NTSC, 320x240, max 5 FPS','Local','/dev/video<?>',0,1,NULL,'v4l1',NULL,NULL,NULL,NULL,320,240,13,5.0,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'BTTV Video (V4L1), NTSC, 640x480','Local','/dev/video<?>',0,1,NULL,'v4l1',NULL,NULL,NULL,NULL,640,480,13,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'BTTV Video (V4L1), NTSC, 640x480, max 5 FPS','Local','/dev/video<?>',0,1,NULL,'v4l1',NULL,NULL,NULL,NULL,640,480,13,5.0,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Remote ZoneMinder','Remote',NULL,NULL,NULL,'http','simple','<ip-address>',80,'/cgi-bin/nph-zms?mode=jpeg&monitor=<monitor-id>&scale=100&maxfps=5&buffer=0',NULL,NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Foscam FI8620 FFMPEG H.264','Ffmpeg',NULL,NULL,NULL,NULL,'','','','rtsp://<username>:<pwd>@<ip-address>:554/11',NULL,704,576,0,NULL,1,'10','<admin_pwd>','<ip-address>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Foscam FI8608W FFMPEG H.264','Ffmpeg',NULL,NULL,NULL,NULL,'','','','rtsp://<username>:<pwd>@<ip-address>:554/11',NULL,640,480,0,NULL,1,'11','<admin_pwd>','<ip-address>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Foscam FI9821W FFMPEG H.264','Ffmpeg',NULL,NULL,NULL,NULL,'','','','rtsp://<username>:<pwd>@<ip-address>:88/videoMain',NULL,1280,720,0,NULL,1,'12','<admin_pwd>','<ip-address>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Loftek Sentinel PTZ, 640x480, mjpeg','Remote','http',0,0,NULL,NULL,'<ip-address>','80','/videostream.cgi?user=<username>&pwd=<password>&resolution=32&rate=11',NULL,640,480,4,NULL,1,'13','','<username>:<pwd>@<ip-address>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Airlink 777W PTZ, 640x480, mjpeg','Remote','http',0,0,NULL,NULL,'<username>:<password>@<ip-address>','80','/cgi/mjpg/mjpg.cgi',NULL,640,480,4,NULL,1,'7','','<username>:<pwd>@<ip-address>',100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'SunEyes SP-P1802SWPTZ','Libvlc','/dev/video<?>','0',255,'','rtpMulti','','80','rtsp://<ip-address>:554/11','',1920,1080,0,0.00,1,'16','-speed=64','<ip-address>:<port>',100,33);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Qihan IP, 1280x720, RTP/RTSP','Ffmpeg','rtsp',0,255,'rtsp','rtpRtsp',NULL,554,'rtsp://<ip-address>/tcp_live/ch0_0',NULL,1280,720,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
INSERT INTO MonitorPresets VALUES (NULL,NULL,'Qihan IP, 1920x1080, RTP/RTSP','Ffmpeg','rtsp',0,255,'rtsp','rtpRtsp',NULL,554,'rtsp://<ip-address>/tcp_live/ch0_0',NULL,1920,1080,3,NULL,0,NULL,NULL,NULL,100,100);
|
||||
|
||||
--
|
||||
-- Add some zone preset values
|
||||
|
@ -1115,6 +1120,9 @@ CREATE TABLE Snapshot_Events (
|
|||
|
||||
-- We generally don't alter triggers, we drop and re-create them, so let's keep them in a separate file that we can just source in update scripts.
|
||||
source @PKGDATADIR@/db/triggers.sql
|
||||
|
||||
source @PKGDATADIR@/db/manufacturers.sql
|
||||
source @PKGDATADIR@/db/models.sql
|
||||
--
|
||||
-- Apply the initial configuration
|
||||
--
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
|
||||
AND table_name = 'Monitors'
|
||||
AND column_name = 'ManufacturerId'
|
||||
) > 0,
|
||||
"SELECT 'Column ManufacturerId already exists in Monitors'",
|
||||
"ALTER TABLE `Monitors` ADD `ManufacturerId` int(10) unsigned AFTER `StorageId`"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE table_schema = DATABASE()
|
||||
AND table_name = 'Monitors'
|
||||
AND column_name = 'ManufacturerId'
|
||||
) > 0,
|
||||
"SELECT 'FOREIGN KEY for ManufacturerId already exists in Monitors'",
|
||||
"ALTER TABLE `Monitors` ADD FOREIGN KEY (`ManufacturerId`) REFERENCES `Manufacturers` (Id)"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
|
||||
AND table_name = 'Monitors'
|
||||
AND column_name = 'ModelId'
|
||||
) > 0,
|
||||
"SELECT 'Column ModelId already exists in Monitors'",
|
||||
"ALTER TABLE `Monitors` ADD `ModelId` int(10) unsigned AFTER `ManufacturerId`"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE table_schema = DATABASE()
|
||||
AND table_name = 'Monitors'
|
||||
AND column_name = 'ModelId'
|
||||
) > 0,
|
||||
"SELECT 'FOREIGN KEY for ModelId already exists in Monitors'",
|
||||
"ALTER TABLE `Monitors` ADD FOREIGN KEY (`ModelId`) REFERENCES `Models` (Id)"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
|
@ -0,0 +1,73 @@
|
|||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
|
||||
AND table_name = 'Monitors'
|
||||
AND column_name = 'ManufacturerId'
|
||||
) > 0,
|
||||
"SELECT 'Column ManufacturerId already exists in Monitors'",
|
||||
"ALTER TABLE `Monitors` ADD `ManufacturerId` int(10) unsigned AFTER `StorageId`"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE table_schema = DATABASE()
|
||||
AND table_name = 'Monitors'
|
||||
AND column_name = 'ManufacturerId'
|
||||
) > 0,
|
||||
"SELECT 'FOREIGN KEY for ManufacturerId already exists in Monitors'",
|
||||
"ALTER TABLE `Monitors` ADD FOREIGN KEY (`ManufacturerId`) REFERENCES `Manufacturers` (Id)"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
|
||||
AND table_name = 'Monitors'
|
||||
AND column_name = 'ModelId'
|
||||
) > 0,
|
||||
"SELECT 'Column ModelId already exists in Monitors'",
|
||||
"ALTER TABLE `Monitors` ADD `ModelId` int(10) unsigned AFTER `ManufacturerId`"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE table_schema = DATABASE()
|
||||
AND table_name = 'Monitors'
|
||||
AND column_name = 'ModelId'
|
||||
) > 0,
|
||||
"SELECT 'FOREIGN KEY for ModelId already exists in Monitors'",
|
||||
"ALTER TABLE `Monitors` ADD FOREIGN KEY (`ModelId`) REFERENCES `Models` (Id)"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
|
||||
AND table_name = 'MonitorPresets'
|
||||
AND column_name = 'ModelId'
|
||||
) > 0,
|
||||
"SELECT 'Column ModelId already exists in MonitorPresets'",
|
||||
"ALTER TABLE `MonitorPresets` ADD `ModelId` int(10) unsigned AFTER `Id`"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE table_schema = DATABASE()
|
||||
AND table_name = 'MonitorPresets'
|
||||
AND column_name = 'ModelId'
|
||||
) > 0,
|
||||
"SELECT 'FOREIGN KEY for ModelId already exists in MonitorPresets'",
|
||||
"ALTER TABLE `MonitorPresets` ADD FOREIGN KEY (`ModelId`) REFERENCES `Models` (Id)"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
|
||||
UPDATE `MonitorPresets` SET `ModelId`=(SELECT `Id` FROM `Models` WHERE `Name`='IP8M-T2499EW') WHERE `Name` like 'Amcrest, IP8M-T2499EW
|
||||
%';
|
|
@ -0,0 +1,2 @@
|
|||
source @PKGDATADIR@/db/manufacturers.sql
|
||||
source @PKGDATADIR@/db/models.sql
|
|
@ -0,0 +1,31 @@
|
|||
--
|
||||
-- This update adds EventStartCommand and EventEndCommand
|
||||
--
|
||||
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE table_name = 'Monitors'
|
||||
AND table_schema = DATABASE()
|
||||
AND column_name = 'EventEndCommand'
|
||||
) > 0,
|
||||
"SELECT 'Column EventEndCommand already exists in Monitors'",
|
||||
"ALTER TABLE `Monitors` ADD COLUMN `EventEndCommand` VARCHAR(255) NOT NULL DEFAULT '' AFTER `Triggers`"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE table_name = 'Monitors'
|
||||
AND table_schema = DATABASE()
|
||||
AND column_name = 'EventStartCommand'
|
||||
) > 0,
|
||||
"SELECT 'Column EventStartCommand already exists in Monitors'",
|
||||
"ALTER TABLE `Monitors` ADD COLUMN `EventStartCommand` VARCHAR(255) NOT NULL DEFAULT '' AFTER `Triggers`"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
|
@ -36,7 +36,7 @@
|
|||
%global _hardened_build 1
|
||||
|
||||
Name: zoneminder
|
||||
Version: 1.37.1
|
||||
Version: 1.37.5
|
||||
Release: 1%{?dist}
|
||||
Summary: A camera monitoring and analysis tool
|
||||
Group: System Environment/Daemons
|
||||
|
|
|
@ -16,7 +16,6 @@ Build-Depends: debhelper (>= 11), sphinx-doc, python3-sphinx, dh-linktree, dh-ap
|
|||
,libjpeg-turbo8-dev | libjpeg62-turbo-dev | libjpeg8-dev | libjpeg9-dev
|
||||
,libturbojpeg0-dev
|
||||
,default-libmysqlclient-dev | libmysqlclient-dev | libmariadbclient-dev-compat
|
||||
,libpcre3-dev
|
||||
,libpolkit-gobject-1-dev
|
||||
,libv4l-dev [!hurd-any]
|
||||
,libvlc-dev
|
||||
|
@ -70,7 +69,6 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
|
|||
,policykit-1
|
||||
,rsyslog | system-log-daemon
|
||||
,zip
|
||||
,libpcre3
|
||||
,libcrypt-eksblowfish-perl
|
||||
,libdata-entropy-perl
|
||||
,libvncclient1|libvncclient0
|
||||
|
|
|
@ -19,6 +19,7 @@ override_dh_auto_configure:
|
|||
-DCMAKE_VERBOSE_MAKEFILE=ON \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DBUILD_MAN=0 \
|
||||
-DZM_NO_PCRE=ON \
|
||||
-DZM_CONFIG_DIR="/etc/zm" \
|
||||
-DZM_CONFIG_SUBDIR="/etc/zm/conf.d" \
|
||||
-DZM_RUNDIR="/run/zm" \
|
||||
|
|
|
@ -4,7 +4,7 @@ Debian
|
|||
.. contents::
|
||||
|
||||
Easy Way: Debian 11 (Bullseye)
|
||||
------------------------
|
||||
------------------------------
|
||||
|
||||
This procedure will guide you through the installation of ZoneMinder on Debian 11 (Bullseye).
|
||||
|
||||
|
@ -104,7 +104,7 @@ Add the following to the /etc/apt/sources.list.d/zoneminder.list file
|
|||
|
||||
You can do this using:
|
||||
|
||||
.. code-block::
|
||||
::
|
||||
|
||||
echo "deb https://zmrepo.zoneminder.com/debian/release-1.36 buster/" | sudo tee /etc/apt/sources.list.d/zoneminder.list
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ require Date::Parse;
|
|||
require POSIX;
|
||||
use Date::Format qw(time2str);
|
||||
use Time::HiRes qw(gettimeofday tv_interval stat);
|
||||
use Scalar::Util qw(looks_like_number);
|
||||
|
||||
#our @ISA = qw(ZoneMinder::Object);
|
||||
use parent qw(ZoneMinder::Object);
|
||||
|
@ -601,7 +602,7 @@ sub CopyTo {
|
|||
# First determine if we can move it to the dest.
|
||||
# We do this before bothering to lock the event
|
||||
my ( $NewPath ) = ( $NewStorage->Path() =~ /^(.*)$/ ); # De-taint
|
||||
if ( ! $$NewStorage{Id} ) {
|
||||
if ( ! looks_like_number($$NewStorage{Id}) ) {
|
||||
return 'New storage does not have an id. Moving will not happen.';
|
||||
} elsif ( $$NewStorage{Id} == $$self{StorageId} ) {
|
||||
return 'Event is already located at ' . $NewPath;
|
||||
|
@ -733,19 +734,22 @@ sub MoveTo {
|
|||
|
||||
my $was_in_transaction = !$ZoneMinder::Database::dbh->{AutoCommit};
|
||||
$ZoneMinder::Database::dbh->begin_work() if !$was_in_transaction;
|
||||
$self->lock_and_load(); # The fact that we are in a transaction might not imply locking
|
||||
if (!$self->lock_and_load()) {
|
||||
Warning('Unable to lock event record '.$$self{Id}); # The fact that we are in a transaction might not imply locking
|
||||
$ZoneMinder::Database::dbh->commit() if !$was_in_transaction;
|
||||
return 'Unable to lock event record';
|
||||
}
|
||||
|
||||
my $OldStorage = $self->Storage(undef);
|
||||
|
||||
my $error = $self->CopyTo($NewStorage);
|
||||
return $error if $error;
|
||||
|
||||
if (!$error) {
|
||||
# Succeeded in copying all files, so we may now update the Event.
|
||||
$$self{StorageId} = $$NewStorage{Id};
|
||||
$self->Storage($NewStorage);
|
||||
$error .= $self->save();
|
||||
|
||||
# Going to leave it to upper layer as to whether we rollback or not
|
||||
}
|
||||
$ZoneMinder::Database::dbh->commit() if !$was_in_transaction;
|
||||
return $error if $error;
|
||||
|
||||
|
|
|
@ -230,8 +230,8 @@ sub Sql {
|
|||
# PostCondition, so no further SQL
|
||||
} else {
|
||||
( my $stripped_value = $value ) =~ s/^["\']+?(.+)["\']+?$/$1/;
|
||||
foreach my $temp_value ( split( /["'\s]*?,["'\s]*?/, $stripped_value ) ) {
|
||||
|
||||
# Empty value will result in () from split
|
||||
foreach my $temp_value ( $stripped_value ? split( /["'\s]*?,["'\s]*?/, $stripped_value ) : $stripped_value ) {
|
||||
if ( $term->{attr} eq 'AlarmedZoneId' ) {
|
||||
$value = '(SELECT * FROM Stats WHERE EventId=E.Id AND Score > 0 AND ZoneId='.$value.')';
|
||||
} elsif ( $term->{attr} =~ /^MonitorName/ ) {
|
||||
|
@ -250,7 +250,8 @@ sub Sql {
|
|||
$$self{Server} = new ZoneMinder::Server($temp_value);
|
||||
}
|
||||
} elsif ( $term->{attr} eq 'StorageId' ) {
|
||||
$value = "'$temp_value'";
|
||||
# Empty means NULL, otherwise must be an integer
|
||||
$value = $temp_value ne '' ? int($temp_value) : 'NULL';
|
||||
$$self{Storage} = new ZoneMinder::Storage($temp_value);
|
||||
} elsif ( $term->{attr} eq 'Name'
|
||||
|| $term->{attr} eq 'Cause'
|
||||
|
|
|
@ -327,17 +327,29 @@ sub resumeMotionDetection {
|
|||
sub Control {
|
||||
my $self = shift;
|
||||
if (!exists $$self{Control}) {
|
||||
if ($$self{ControlId}) {
|
||||
require ZoneMinder::Control;
|
||||
my $Control = ZoneMinder::Control->find_one(Id=>$$self{ControlId});
|
||||
if ($Control) {
|
||||
my $Protocol = $$Control{Protocol};
|
||||
|
||||
if (!$Protocol) {
|
||||
Error("No protocol set in control $$Control{Id}, trying Name $$Control{Name}");
|
||||
$Protocol = $$Control{Name};
|
||||
}
|
||||
require Module::Load::Conditional;
|
||||
if (!Module::Load::Conditional::can_load(modules => {'ZoneMinder::Control::'.$$Control{Protocol} => undef})) {
|
||||
Error("Can't load ZoneMinder::Control::$$Control{Protocol}\n$Module::Load::Conditional::ERROR");
|
||||
if (!Module::Load::Conditional::can_load(modules => {'ZoneMinder::Control::'.$Protocol => undef})) {
|
||||
Error("Can't load ZoneMinder::Control::$Protocol\n$Module::Load::Conditional::ERROR");
|
||||
return undef;
|
||||
}
|
||||
bless $Control, 'ZoneMinder::Control::'.$$Control{Protocol};
|
||||
bless $Control, 'ZoneMinder::Control::'.$Protocol;
|
||||
$$Control{MonitorId} = $$self{Id};
|
||||
$$self{Control} = $Control;
|
||||
} else {
|
||||
Error("Unable to load control for control $$self{ControlId} for monitor $$self{Id}");
|
||||
}
|
||||
} else {
|
||||
Info("No ControlId set in monitor $$self{Id}")
|
||||
}
|
||||
}
|
||||
return $$self{Control};
|
||||
|
|
|
@ -429,10 +429,20 @@ sub start {
|
|||
# It's not running, or at least it's not been started by us
|
||||
$process = { daemon=>$daemon, args=>\@args, command=>$command, keepalive=>!undef };
|
||||
} elsif ( $process->{pid} && $pid_hash{$process->{pid}} ) {
|
||||
if ($process->{term_sent_at}) {
|
||||
dPrint(ZoneMinder::Logger::INFO, "'$process->{command}' was told to term at "
|
||||
.strftime('%y/%m/%d %H:%M:%S', localtime($process->{term_sent_at}))
|
||||
.", pid = $process->{pid}\n"
|
||||
);
|
||||
$process->{keepalive} = !undef;
|
||||
$process->{delay} = 0;
|
||||
delete $terminating_processes{$command};
|
||||
} else {
|
||||
dPrint(ZoneMinder::Logger::INFO, "'$process->{command}' already running at "
|
||||
.strftime('%y/%m/%d %H:%M:%S', localtime($process->{started}))
|
||||
.", pid = $process->{pid}\n"
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -263,7 +263,10 @@ sub countQuery {
|
|||
sub getMonitorRef {
|
||||
my $dbh = shift;
|
||||
|
||||
my $sql = 'SELECT `Id`,`Name`,`Type`,`Function`,`Width`,`Height`,`Colours`,`MaxFPS`,`AlarmMaxFPS` FROM `Monitors`';
|
||||
my $sql = 'SELECT `Id`,`Name`,`Type`,`Function`,`Width`,`Height`,`Colours`,`MaxFPS`,`AlarmMaxFPS`,
|
||||
(SELECT Name FROM Manufacturers WHERE Manufacturers.Id = ManufacturerId),
|
||||
(SELECT Name FROM Models WHERE Models.Id = ModelId)
|
||||
FROM `Monitors`';
|
||||
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() );
|
||||
my $arrayref = $sth->fetchall_arrayref({});
|
||||
|
|
|
@ -251,11 +251,11 @@ void zmDbQueue::process() {
|
|||
mCondition.wait(lock);
|
||||
}
|
||||
while (!mQueue.empty()) {
|
||||
if (mQueue.size() > 10) {
|
||||
if (mQueue.size() > 20) {
|
||||
Logger *log = Logger::fetch();
|
||||
Logger::Level db_level = log->databaseLevel();
|
||||
log->databaseLevel(Logger::NOLOG);
|
||||
Warning("db queue size has grown larger %zu than 10 entries", mQueue.size());
|
||||
Warning("db queue size has grown larger %zu than 20 entries", mQueue.size());
|
||||
log->databaseLevel(db_level);
|
||||
}
|
||||
std::string sql = mQueue.front();
|
||||
|
@ -271,8 +271,10 @@ void zmDbQueue::process() {
|
|||
|
||||
void zmDbQueue::push(std::string &&sql) {
|
||||
if (mTerminate) return;
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mMutex);
|
||||
mQueue.push(std::move(sql));
|
||||
}
|
||||
mCondition.notify_all();
|
||||
}
|
||||
|
||||
|
|
|
@ -60,8 +60,8 @@ Event::Event(
|
|||
//snapshit_file(),
|
||||
//alarm_file(""),
|
||||
videoStore(nullptr),
|
||||
//video_name(""),
|
||||
//video_file(""),
|
||||
//video_path(""),
|
||||
last_db_frame(0),
|
||||
have_video_keyframe(false),
|
||||
//scheme
|
||||
|
@ -104,6 +104,13 @@ Event::Event(
|
|||
// Copy it in case opening the mp4 doesn't work we can set it to another value
|
||||
save_jpegs = monitor->GetOptSaveJPEGs();
|
||||
Storage *storage = monitor->getStorage();
|
||||
if (monitor->GetOptVideoWriter() != 0) {
|
||||
container = monitor->OutputContainer();
|
||||
if ( container == "auto" || container == "" ) {
|
||||
container = "mp4";
|
||||
}
|
||||
video_incomplete_file = "incomplete."+container;
|
||||
}
|
||||
|
||||
std::string sql = stringtf(
|
||||
"INSERT INTO `Events` "
|
||||
|
@ -120,7 +127,7 @@ Event::Event(
|
|||
state_id,
|
||||
monitor->getOrientation(),
|
||||
0,
|
||||
"",
|
||||
video_incomplete_file.c_str(),
|
||||
save_jpegs,
|
||||
storage->SchemeString().c_str()
|
||||
);
|
||||
|
@ -134,7 +141,6 @@ Event::Event(
|
|||
if (monitor->ServerId())
|
||||
sql += stringtf(" AND ServerId=%u", monitor->ServerId());
|
||||
|
||||
Debug(1, "%s", sql.c_str());
|
||||
storage = nullptr;
|
||||
|
||||
MYSQL_RES *result = zmDbFetch(sql);
|
||||
|
@ -178,24 +184,16 @@ Event::Event(
|
|||
} // end if ! setPath(Storage)
|
||||
Debug(1, "Using storage area at %s", path.c_str());
|
||||
|
||||
video_name = "";
|
||||
|
||||
snapshot_file = path + "/snapshot.jpg";
|
||||
alarm_file = path + "/alarm.jpg";
|
||||
|
||||
/* Save as video */
|
||||
video_incomplete_path = path + "/" + video_incomplete_file;
|
||||
|
||||
if (monitor->GetOptVideoWriter() != 0) {
|
||||
std::string container = monitor->OutputContainer();
|
||||
if ( container == "auto" || container == "" ) {
|
||||
container = "mp4";
|
||||
}
|
||||
/* Save as video */
|
||||
|
||||
video_name = stringtf("%" PRIu64 "-%s.%s", id, "video", container.c_str());
|
||||
video_file = path + "/" + video_name;
|
||||
Debug(1, "Writing video file to %s", video_file.c_str());
|
||||
videoStore = new VideoStore(
|
||||
video_file.c_str(),
|
||||
video_incomplete_path.c_str(),
|
||||
container.c_str(),
|
||||
monitor->GetVideoStream(),
|
||||
monitor->GetVideoCodecContext(),
|
||||
|
@ -213,10 +211,14 @@ Event::Event(
|
|||
zmDbDo(sql);
|
||||
}
|
||||
} else {
|
||||
sql = stringtf("UPDATE Events SET Videoed=1, DefaultVideo = '%s' WHERE Id=%" PRIu64, video_name.c_str(), id);
|
||||
zmDbDo(sql);
|
||||
std::string codec = videoStore->get_codec();
|
||||
video_file = stringtf("%" PRIu64 "-%s.%s.%s", id, "video", codec.c_str(), container.c_str());
|
||||
video_path = path + "/" + video_file;
|
||||
Debug(1, "Video file is %s", video_file.c_str());
|
||||
}
|
||||
} // end if GetOptVideoWriter
|
||||
if (storage != monitor->getStorage())
|
||||
delete storage;
|
||||
}
|
||||
|
||||
Event::~Event() {
|
||||
|
@ -227,6 +229,14 @@ Event::~Event() {
|
|||
Debug(4, "Deleting video store");
|
||||
delete videoStore;
|
||||
videoStore = nullptr;
|
||||
int result = rename(video_incomplete_path.c_str(), video_path.c_str());
|
||||
if (result == 0) {
|
||||
Debug(1, "File successfully renamed");
|
||||
} else {
|
||||
Error("Failed renaming %s to %s", video_incomplete_path.c_str(), video_path.c_str());
|
||||
// So that we don't update the event record
|
||||
video_file = video_incomplete_file;
|
||||
}
|
||||
}
|
||||
|
||||
// endtime is set in AddFrame, so SHOULD be set to the value of the last frame timestamp.
|
||||
|
@ -245,21 +255,23 @@ Event::~Event() {
|
|||
}
|
||||
|
||||
std::string sql = stringtf(
|
||||
"UPDATE Events SET Name='%s%" PRIu64 "', EndDateTime = from_unixtime(%ld), Length = %.2f, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d WHERE Id = %" PRIu64 " AND Name='New Event'",
|
||||
"UPDATE Events SET Name='%s%" PRIu64 "', EndDateTime = from_unixtime(%ld), Length = %.2f, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d, DefaultVideo='%s' WHERE Id = %" PRIu64 " AND Name='New Event'",
|
||||
monitor->EventPrefix(), id, std::chrono::system_clock::to_time_t(end_time),
|
||||
delta_time.count(),
|
||||
frames, alarm_frames,
|
||||
tot_score, static_cast<uint32>(alarm_frames ? (tot_score / alarm_frames) : 0), max_score,
|
||||
video_file.c_str(), // defaults to ""
|
||||
id);
|
||||
|
||||
if (!zmDbDoUpdate(sql)) {
|
||||
// Name might have been changed during recording, so just do the update without changing the name.
|
||||
sql = stringtf(
|
||||
"UPDATE Events SET EndDateTime = from_unixtime(%ld), Length = %.2f, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d WHERE Id = %" PRIu64,
|
||||
"UPDATE Events SET EndDateTime = from_unixtime(%ld), Length = %.2f, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d, DefaultVideo='%s' WHERE Id = %" PRIu64,
|
||||
std::chrono::system_clock::to_time_t(end_time),
|
||||
delta_time.count(),
|
||||
frames, alarm_frames,
|
||||
tot_score, static_cast<uint32>(alarm_frames ? (tot_score / alarm_frames) : 0), max_score,
|
||||
video_file.c_str(), // defaults to ""
|
||||
id);
|
||||
zmDbDoUpdate(sql);
|
||||
} // end if no changed rows due to Name change during recording
|
||||
|
@ -326,12 +338,12 @@ void Event::updateNotes(const StringSetMap &newNoteSetMap) {
|
|||
if (newNoteSet.size() > 0) {
|
||||
StringSetMap::iterator noteSetMapIter = noteSetMap.find(newNoteGroup);
|
||||
if (noteSetMapIter == noteSetMap.end()) {
|
||||
//Info( "Can't find note group %s, copying %d strings", newNoteGroup.c_str(), newNoteSet.size() );
|
||||
//Debug(3, "Can't find note group %s, copying %d strings", newNoteGroup.c_str(), newNoteSet.size());
|
||||
noteSetMap.insert(StringSetMap::value_type(newNoteGroup, newNoteSet));
|
||||
update = true;
|
||||
} else {
|
||||
StringSet ¬eSet = noteSetMapIter->second;
|
||||
//Info( "Found note group %s, got %d strings", newNoteGroup.c_str(), newNoteSet.size() );
|
||||
//Debug(3, "Found note group %s, got %d strings", newNoteGroup.c_str(), newNoteSet.size());
|
||||
for (StringSet::const_iterator newNoteSetIter = newNoteSet.begin();
|
||||
newNoteSetIter != newNoteSet.end();
|
||||
++newNoteSetIter) {
|
||||
|
@ -534,7 +546,7 @@ void Event::AddFrame(Image *image,
|
|||
or
|
||||
(frame_type == BULK)
|
||||
or
|
||||
(fps and (frame_data.size() > fps))) {
|
||||
(fps and (frame_data.size() > 5*fps))) {
|
||||
Debug(1, "Adding %zu frames to DB because write_to_db:%d or frames > analysis fps %f or BULK(%d)",
|
||||
frame_data.size(), write_to_db, fps, (frame_type == BULK));
|
||||
WriteDbFrames();
|
||||
|
|
|
@ -84,8 +84,13 @@ class Event {
|
|||
std::string alarm_file;
|
||||
VideoStore *videoStore;
|
||||
|
||||
std::string video_name;
|
||||
std::string container;
|
||||
std::string codec;
|
||||
std::string video_file;
|
||||
std::string video_path;
|
||||
std::string video_incomplete_file;
|
||||
std::string video_incomplete_path;
|
||||
|
||||
int last_db_frame;
|
||||
bool have_video_keyframe; // a flag to tell us if we have had a video keyframe when writing an mp4. The first frame SHOULD be a video keyframe.
|
||||
Storage::Schemes scheme;
|
||||
|
|
|
@ -141,7 +141,7 @@ bool EventStream::loadEventData(uint64_t event_id) {
|
|||
event_data->storage_id = dbrow[1] ? atoi(dbrow[1]) : 0;
|
||||
event_data->frame_count = dbrow[2] == nullptr ? 0 : atoi(dbrow[2]);
|
||||
event_data->start_time = SystemTimePoint(Seconds(atoi(dbrow[3])));
|
||||
event_data->end_time = dbrow[4] ? SystemTimePoint(Seconds(atoi(dbrow[4]))) : SystemTimePoint();
|
||||
event_data->end_time = dbrow[4] ? SystemTimePoint(Seconds(atoi(dbrow[4]))) : std::chrono::system_clock::now();
|
||||
event_data->duration = std::chrono::duration_cast<Microseconds>(event_data->end_time - event_data->start_time);
|
||||
event_data->frames_duration =
|
||||
std::chrono::duration_cast<Microseconds>(dbrow[5] ? FPSeconds(atof(dbrow[5])) : FPSeconds(0.0));
|
||||
|
|
|
@ -458,6 +458,17 @@ int FfmpegCamera::OpenFfmpeg() {
|
|||
#endif
|
||||
} // end if hwaccel_name
|
||||
|
||||
// set codec to automatically determine how many threads suits best for the decoding job
|
||||
mVideoCodecContext->thread_count = 0;
|
||||
|
||||
if (mVideoCodec->capabilities | AV_CODEC_CAP_FRAME_THREADS) {
|
||||
mVideoCodecContext->thread_type = FF_THREAD_FRAME;
|
||||
} else if (mVideoCodec->capabilities | AV_CODEC_CAP_SLICE_THREADS) {
|
||||
mVideoCodecContext->thread_type = FF_THREAD_SLICE;
|
||||
} else {
|
||||
mVideoCodecContext->thread_count = 1; //don't use multithreading
|
||||
}
|
||||
|
||||
ret = avcodec_open2(mVideoCodecContext, mVideoCodec, &opts);
|
||||
|
||||
e = nullptr;
|
||||
|
|
|
@ -143,8 +143,8 @@ bool Fifo::writePacket(std::string filename, const ZMPacket &packet) {
|
|||
bool Fifo::write(uint8_t *data, size_t bytes, int64_t pts) {
|
||||
if (!(outfile or open())) return false;
|
||||
// Going to write a brief header
|
||||
Debug(1, "Writing header ZM %lu %" PRId64, bytes, pts);
|
||||
if ( fprintf(outfile, "ZM %lu %" PRId64 "\n", bytes, pts) < 0 ) {
|
||||
Debug(1, "Writing header ZM %zu %" PRId64, bytes, pts);
|
||||
if (fprintf(outfile, "ZM %zu %" PRId64 "\n", bytes, pts) < 0) {
|
||||
if (errno != EAGAIN) {
|
||||
Error("Problem during writing: %s", strerror(errno));
|
||||
} else {
|
||||
|
|
|
@ -270,7 +270,6 @@ int Image::PopulateFrame(AVFrame *frame) {
|
|||
frame->width = width;
|
||||
frame->height = height;
|
||||
frame->format = imagePixFormat;
|
||||
Debug(1, "PopulateFrame: width %d height %d linesize %d colours %d imagesize %d", width, height, linesize, colours, size);
|
||||
zm_dump_video_frame(frame, "Image.Populate(frame)");
|
||||
return 1;
|
||||
} // int Image::PopulateFrame(AVFrame *frame)
|
||||
|
|
|
@ -23,7 +23,7 @@ void bind_libvnc_symbols() {
|
|||
|
||||
libvnc_lib = dlopen("libvncclient.so", RTLD_LAZY | RTLD_GLOBAL);
|
||||
if (!libvnc_lib) {
|
||||
Error("Error loading libvncclient: %s", dlerror());
|
||||
Error("Error loading libvncclient.so: %s", dlerror());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -135,11 +135,6 @@ VncCamera::VncCamera(
|
|||
}
|
||||
|
||||
VncCamera::~VncCamera() {
|
||||
if (capture and mRfb) {
|
||||
if (mRfb->frameBuffer)
|
||||
free(mRfb->frameBuffer);
|
||||
(*rfbClientCleanup_f)(mRfb);
|
||||
}
|
||||
if (libvnc_lib) {
|
||||
dlclose(libvnc_lib);
|
||||
libvnc_lib = nullptr;
|
||||
|
@ -253,6 +248,12 @@ int VncCamera::PostCapture() {
|
|||
}
|
||||
|
||||
int VncCamera::Close() {
|
||||
if (capture and mRfb) {
|
||||
if (mRfb->frameBuffer)
|
||||
free(mRfb->frameBuffer);
|
||||
(*rfbClientCleanup_f)(mRfb);
|
||||
mRfb = nullptr;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -47,7 +47,7 @@ void Logger::usrHandler(int sig) {
|
|||
logger->level(logger->level()+1);
|
||||
else if (sig == SIGUSR2)
|
||||
logger->level(logger->level()-1);
|
||||
Info("Logger - Level changed to %d", logger->level());
|
||||
Info("Logger - Level changed to %d %s", logger->level(), smCodes[logger->level()].c_str());
|
||||
}
|
||||
|
||||
Logger::Logger() :
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
// It will be used whereever a Monitor dbrow is needed. WHERE conditions can be appended
|
||||
std::string load_monitor_sql =
|
||||
"SELECT `Id`, `Name`, `ServerId`, `StorageId`, `Type`, `Function`+0, `Enabled`, `DecodingEnabled`, "
|
||||
"`LinkedMonitors`, `AnalysisFPSLimit`, `AnalysisUpdateDelay`, `MaxFPS`, `AlarmMaxFPS`,"
|
||||
"`LinkedMonitors`, `EventStartCommand`, `EventEndCommand`, `AnalysisFPSLimit`, `AnalysisUpdateDelay`, `MaxFPS`, `AlarmMaxFPS`,"
|
||||
"`Device`, `Channel`, `Format`, `V4LMultiBuffer`, `V4LCapturesPerFrame`, " // V4L Settings
|
||||
"`Protocol`, `Method`, `Options`, `User`, `Pass`, `Host`, `Port`, `Path`, `SecondPath`, `Width`, `Height`, `Colours`, `Palette`, `Orientation`+0, `Deinterlacing`, "
|
||||
"`DecoderHWAccelName`, `DecoderHWAccelDevice`, `RTSPDescribe`, "
|
||||
|
@ -155,7 +155,7 @@ bool Monitor::MonitorLink::connect() {
|
|||
|
||||
mem_size = sizeof(SharedData) + sizeof(TriggerData);
|
||||
|
||||
Debug(1, "link.mem.size=%jd", mem_size);
|
||||
Debug(1, "link.mem.size=%jd", static_cast<intmax_t>(mem_size));
|
||||
#if ZM_MEM_MAPPED
|
||||
map_fd = open(mem_file.c_str(), O_RDWR, (mode_t)0600);
|
||||
if (map_fd < 0) {
|
||||
|
@ -182,14 +182,14 @@ bool Monitor::MonitorLink::connect() {
|
|||
disconnect();
|
||||
return false;
|
||||
} else if (map_stat.st_size < mem_size) {
|
||||
Error("Got unexpected memory map file size %ld, expected %jd", map_stat.st_size, mem_size);
|
||||
Error("Got unexpected memory map file size %ld, expected %jd", map_stat.st_size, static_cast<intmax_t>(mem_size));
|
||||
disconnect();
|
||||
return false;
|
||||
}
|
||||
|
||||
mem_ptr = (unsigned char *)mmap(nullptr, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED, map_fd, 0);
|
||||
if (mem_ptr == MAP_FAILED) {
|
||||
Error("Can't map file %s (%jd bytes) to memory: %s", mem_file.c_str(), mem_size, strerror(errno));
|
||||
Error("Can't map file %s (%jd bytes) to memory: %s", mem_file.c_str(), static_cast<intmax_t>(mem_size), strerror(errno));
|
||||
disconnect();
|
||||
return false;
|
||||
}
|
||||
|
@ -435,7 +435,7 @@ Monitor::Monitor()
|
|||
|
||||
/*
|
||||
std::string load_monitor_sql =
|
||||
"SELECT Id, Name, ServerId, StorageId, Type, Function+0, Enabled, DecodingEnabled, LinkedMonitors, "
|
||||
"SELECT Id, Name, ServerId, StorageId, Type, Function+0, Enabled, DecodingEnabled, LinkedMonitors, `EventStartCommand`, `EventEndCommand`, "
|
||||
"AnalysisFPSLimit, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS,"
|
||||
"Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, " // V4L Settings
|
||||
"Protocol, Method, Options, User, Pass, Host, Port, Path, SecondPath, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, "
|
||||
|
@ -489,6 +489,8 @@ void Monitor::Load(MYSQL_ROW dbrow, bool load_zones=true, Purpose p = QUERY) {
|
|||
// See below after save_jpegs for a recalculation of decoding_enabled
|
||||
|
||||
ReloadLinkedMonitors(dbrow[col]); col++;
|
||||
event_start_command = dbrow[col] ? dbrow[col] : ""; col++;
|
||||
event_end_command = dbrow[col] ? dbrow[col] : ""; col++;
|
||||
|
||||
/* "AnalysisFPSLimit, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS," */
|
||||
analysis_fps_limit = dbrow[col] ? strtod(dbrow[col], nullptr) : 0.0; col++;
|
||||
|
@ -947,7 +949,7 @@ bool Monitor::connect() {
|
|||
map_fd = -1;
|
||||
return false;
|
||||
} else {
|
||||
Error("Got unexpected memory map file size %ld, expected %jd", map_stat.st_size, mem_size);
|
||||
Error("Got unexpected memory map file size %ld, expected %jd", map_stat.st_size, static_cast<intmax_t>(mem_size));
|
||||
close(map_fd);
|
||||
map_fd = -1;
|
||||
return false;
|
||||
|
@ -959,18 +961,18 @@ bool Monitor::connect() {
|
|||
mem_ptr = (unsigned char *)mmap(nullptr, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_LOCKED, map_fd, 0);
|
||||
if (mem_ptr == MAP_FAILED) {
|
||||
if (errno == EAGAIN) {
|
||||
Debug(1, "Unable to map file %s (%jd bytes) to locked memory, trying unlocked", mem_file.c_str(), mem_size);
|
||||
Debug(1, "Unable to map file %s (%jd bytes) to locked memory, trying unlocked", mem_file.c_str(), static_cast<intmax_t>(mem_size));
|
||||
#endif
|
||||
mem_ptr = (unsigned char *)mmap(nullptr, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED, map_fd, 0);
|
||||
Debug(1, "Mapped file %s (%jd bytes) to unlocked memory", mem_file.c_str(), mem_size);
|
||||
Debug(1, "Mapped file %s (%jd bytes) to unlocked memory", mem_file.c_str(), static_cast<intmax_t>(mem_size));
|
||||
#ifdef MAP_LOCKED
|
||||
} else {
|
||||
Error("Unable to map file %s (%jd bytes) to locked memory (%s)", mem_file.c_str(), mem_size, strerror(errno));
|
||||
Error("Unable to map file %s (%jd bytes) to locked memory (%s)", mem_file.c_str(), static_cast<intmax_t>(mem_size), strerror(errno));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if ((mem_ptr == MAP_FAILED) or (mem_ptr == nullptr)) {
|
||||
Error("Can't map file %s (%jd bytes) to memory: %s(%d)", mem_file.c_str(), mem_size, strerror(errno), errno);
|
||||
Error("Can't map file %s (%jd bytes) to memory: %s(%d)", mem_file.c_str(), static_cast<intmax_t>(mem_size), strerror(errno), errno);
|
||||
close(map_fd);
|
||||
map_fd = -1;
|
||||
mem_ptr = nullptr;
|
||||
|
@ -1656,7 +1658,7 @@ void Monitor::CheckAction() {
|
|||
}
|
||||
}
|
||||
|
||||
void Monitor::UpdateCaptureFPS() {
|
||||
void Monitor::UpdateFPS() {
|
||||
if ( fps_report_interval and
|
||||
(
|
||||
!(image_count%fps_report_interval)
|
||||
|
@ -1675,82 +1677,35 @@ void Monitor::UpdateCaptureFPS() {
|
|||
uint32 new_camera_bytes = camera->Bytes();
|
||||
uint32 new_capture_bandwidth =
|
||||
static_cast<uint32>((new_camera_bytes - last_camera_bytes) / elapsed.count());
|
||||
last_camera_bytes = new_camera_bytes;
|
||||
double new_analysis_fps = (motion_frame_count - last_motion_frame_count) / elapsed.count();
|
||||
|
||||
Debug(4, "%s: %d - last %d = %d now:%lf, last %lf, elapsed %lf = %lffps",
|
||||
"Capturing",
|
||||
Debug(4, "FPS: capture count %d - last capture count %d = %d now:%lf, last %lf, elapsed %lf = capture: %lf fps analysis: %lf fps",
|
||||
image_count,
|
||||
last_capture_image_count,
|
||||
image_count - last_capture_image_count,
|
||||
FPSeconds(now.time_since_epoch()).count(),
|
||||
FPSeconds(last_analysis_fps_time.time_since_epoch()).count(),
|
||||
FPSeconds(last_fps_time.time_since_epoch()).count(),
|
||||
elapsed.count(),
|
||||
new_capture_fps);
|
||||
new_capture_fps,
|
||||
new_analysis_fps);
|
||||
|
||||
Info("%s: %d - Capturing at %.2lf fps, capturing bandwidth %ubytes/sec",
|
||||
name.c_str(), image_count, new_capture_fps, new_capture_bandwidth);
|
||||
Info("%s: %d - Capturing at %.2lf fps, capturing bandwidth %ubytes/sec Analysing at %.2lf fps",
|
||||
name.c_str(), image_count, new_capture_fps, new_capture_bandwidth, new_analysis_fps);
|
||||
|
||||
shared_data->capture_fps = new_capture_fps;
|
||||
last_fps_time = now;
|
||||
last_capture_image_count = image_count;
|
||||
shared_data->analysis_fps = new_analysis_fps;
|
||||
last_motion_frame_count = motion_frame_count;
|
||||
last_camera_bytes = new_camera_bytes;
|
||||
|
||||
std::string sql = stringtf(
|
||||
"UPDATE LOW_PRIORITY Monitor_Status SET CaptureFPS = %.2lf, CaptureBandwidth=%u WHERE MonitorId=%u",
|
||||
new_capture_fps, new_capture_bandwidth, id);
|
||||
"UPDATE LOW_PRIORITY Monitor_Status SET CaptureFPS = %.2lf, CaptureBandwidth=%u, AnalysisFPS = %.2lf WHERE MonitorId=%u",
|
||||
new_capture_fps, new_capture_bandwidth, new_analysis_fps, id);
|
||||
dbQueue.push(std::move(sql));
|
||||
} // now != last_fps_time
|
||||
} // end if report fps
|
||||
} // void Monitor::UpdateCaptureFPS()
|
||||
|
||||
void Monitor::UpdateAnalysisFPS() {
|
||||
Debug(1, "analysis_image_count(%d) motion_count(%d) fps_report_interval(%d) mod%d",
|
||||
analysis_image_count, motion_frame_count, fps_report_interval,
|
||||
((analysis_image_count && fps_report_interval) ? !(analysis_image_count%fps_report_interval) : -1 ) );
|
||||
|
||||
if (
|
||||
( analysis_image_count and fps_report_interval and !(analysis_image_count%fps_report_interval) )
|
||||
or
|
||||
// In startup do faster updates
|
||||
( (analysis_image_count < fps_report_interval) and !(analysis_image_count%10) )
|
||||
) {
|
||||
SystemTimePoint now = std::chrono::system_clock::now();
|
||||
|
||||
FPSeconds elapsed = now - last_analysis_fps_time;
|
||||
Debug(4, "%s: %d - now: %.2f, last %lf, diff %lf",
|
||||
name.c_str(),
|
||||
analysis_image_count,
|
||||
FPSeconds(now.time_since_epoch()).count(),
|
||||
FPSeconds(last_analysis_fps_time.time_since_epoch()).count(),
|
||||
elapsed.count());
|
||||
|
||||
if (elapsed > Seconds(1)) {
|
||||
double new_analysis_fps = (motion_frame_count - last_motion_frame_count) / elapsed.count();
|
||||
Info("%s: %d - Analysing at %.2lf fps from %d - %d=%d / %lf - %lf = %lf",
|
||||
name.c_str(),
|
||||
analysis_image_count,
|
||||
new_analysis_fps,
|
||||
motion_frame_count,
|
||||
last_motion_frame_count,
|
||||
(motion_frame_count - last_motion_frame_count),
|
||||
FPSeconds(now.time_since_epoch()).count(),
|
||||
FPSeconds(last_analysis_fps_time.time_since_epoch()).count(),
|
||||
elapsed.count());
|
||||
|
||||
if (new_analysis_fps != shared_data->analysis_fps) {
|
||||
shared_data->analysis_fps = new_analysis_fps;
|
||||
|
||||
std::string sql = stringtf("UPDATE LOW_PRIORITY Monitor_Status SET AnalysisFPS = %.2lf WHERE MonitorId=%u",
|
||||
new_analysis_fps, id);
|
||||
dbQueue.push(std::move(sql));
|
||||
last_analysis_fps_time = now;
|
||||
last_motion_frame_count = motion_frame_count;
|
||||
} else {
|
||||
Debug(4, "No change in fps");
|
||||
} // end if change in fps
|
||||
} // end if at least 1 second has passed since last update
|
||||
|
||||
} // end if time to do an update
|
||||
} // end void Monitor::UpdateAnalysisFPS
|
||||
} // void Monitor::UpdateFPS()
|
||||
|
||||
// Would be nice if this JUST did analysis
|
||||
// This idea is that we should be analysing as close to the capture frame as possible.
|
||||
|
@ -1909,8 +1864,6 @@ bool Monitor::Analyse() {
|
|||
Debug(3, "signal and active and modect");
|
||||
Event::StringSet zoneSet;
|
||||
|
||||
int motion_score = last_motion_score;
|
||||
|
||||
if (analysis_fps_limit) {
|
||||
double capture_fps = get_capture_fps();
|
||||
motion_frame_skip = capture_fps / analysis_fps_limit;
|
||||
|
@ -1922,12 +1875,12 @@ bool Monitor::Analyse() {
|
|||
if (snap->image) {
|
||||
// decoder may not have been able to provide an image
|
||||
if (!ref_image.Buffer()) {
|
||||
Debug(1, "Assigning instead of Dectecting");
|
||||
Debug(1, "Assigning instead of Detecting");
|
||||
ref_image.Assign(*(snap->image));
|
||||
} else {
|
||||
Debug(1, "Detecting motion on image %d, image %p", snap->image_index, snap->image);
|
||||
// Get new score.
|
||||
motion_score = DetectMotion(*(snap->image), zoneSet);
|
||||
int motion_score = DetectMotion(*(snap->image), zoneSet);
|
||||
|
||||
snap->zone_stats.reserve(zones.size());
|
||||
for (const Zone &zone : zones) {
|
||||
|
@ -1939,21 +1892,20 @@ bool Monitor::Analyse() {
|
|||
Debug(3, "After motion detection, score:%d last_motion_score(%d), new motion score(%d)",
|
||||
score, last_motion_score, motion_score);
|
||||
motion_frame_count += 1;
|
||||
// Why are we updating the last_motion_score too?
|
||||
last_motion_score = motion_score;
|
||||
if (motion_score) {
|
||||
if (cause.length()) cause += ", ";
|
||||
cause += MOTION_CAUSE;
|
||||
noteSetMap[MOTION_CAUSE] = zoneSet;
|
||||
} // end if motion_score
|
||||
}
|
||||
} else {
|
||||
Debug(1, "no image so skipping motion detection");
|
||||
} // end if has image
|
||||
} else {
|
||||
Debug(1, "Skipped motion detection last motion score was %d", motion_score);
|
||||
Debug(1, "Skipped motion detection last motion score was %d", last_motion_score);
|
||||
}
|
||||
if (motion_score) {
|
||||
score += motion_score;
|
||||
if (cause.length()) cause += ", ";
|
||||
cause += MOTION_CAUSE;
|
||||
noteSetMap[MOTION_CAUSE] = zoneSet;
|
||||
} // end if motion_score
|
||||
score += last_motion_score;
|
||||
} else {
|
||||
Debug(1, "Not Active(%d) enabled %d active %d doing motion detection: %d",
|
||||
Active(), enabled, shared_data->active,
|
||||
|
@ -1966,7 +1918,7 @@ bool Monitor::Analyse() {
|
|||
if (event) {
|
||||
Debug(2, "Have event %" PRIu64 " in record", event->Id());
|
||||
|
||||
if (section_length != Seconds(0) && (timestamp - GetVideoWriterStartTime() >= section_length)
|
||||
if (section_length != Seconds(0) && (timestamp - event->StartTime() >= section_length)
|
||||
&& ((function == MOCORD && event_close_mode != CLOSE_TIME)
|
||||
|| (function == RECORD && event_close_mode == CLOSE_TIME)
|
||||
|| std::chrono::duration_cast<Seconds>(timestamp.time_since_epoch()) % section_length == Seconds(0))) {
|
||||
|
@ -1975,8 +1927,8 @@ bool Monitor::Analyse() {
|
|||
image_count,
|
||||
event->Id(),
|
||||
static_cast<int64>(std::chrono::duration_cast<Seconds>(timestamp.time_since_epoch()).count()),
|
||||
static_cast<int64>(std::chrono::duration_cast<Seconds>(GetVideoWriterStartTime().time_since_epoch()).count()),
|
||||
static_cast<int64>(std::chrono::duration_cast<Seconds>(timestamp - GetVideoWriterStartTime()).count()),
|
||||
static_cast<int64>(std::chrono::duration_cast<Seconds>(event->StartTime().time_since_epoch()).count()),
|
||||
static_cast<int64>(std::chrono::duration_cast<Seconds>(timestamp - event->StartTime()).count()),
|
||||
static_cast<int64>(Seconds(section_length).count()));
|
||||
closeEvent();
|
||||
} // end if section_length
|
||||
|
@ -2044,6 +1996,12 @@ bool Monitor::Analyse() {
|
|||
alarm_cause = cause+" Continuous "+alarm_cause;
|
||||
strncpy(shared_data->alarm_cause, alarm_cause.c_str(), sizeof(shared_data->alarm_cause)-1);
|
||||
SetVideoWriterStartTime(event->StartTime());
|
||||
if (!event_start_command.empty()) {
|
||||
if (fork() == 0) {
|
||||
execlp(event_start_command.c_str(), event_start_command.c_str(), std::to_string(event->Id()).c_str(), nullptr);
|
||||
Error("Error execing %s", event_start_command.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
Info("%s: %03d - Opened new event %" PRIu64 ", section start",
|
||||
name.c_str(), analysis_image_count, event->Id());
|
||||
|
@ -2054,26 +2012,27 @@ bool Monitor::Analyse() {
|
|||
} // end if ! event
|
||||
} // end if RECORDING
|
||||
|
||||
if (score and (function == MODECT or function == NODECT)) {
|
||||
if (score and (function != MONITOR)) {
|
||||
if ((state == IDLE) || (state == TAPE) || (state == PREALARM)) {
|
||||
// If we should end then previous continuous event and start a new non-continuous event
|
||||
if (event && event->Frames()
|
||||
&& !event->AlarmFrames()
|
||||
&& event_close_mode == CLOSE_ALARM
|
||||
&& timestamp - GetVideoWriterStartTime() >= min_section_length
|
||||
&& (!pre_event_count || Event::PreAlarmCount() >= alarm_frame_count - 1)) {
|
||||
&& (event_close_mode == CLOSE_ALARM)
|
||||
&& ((timestamp - event->StartTime()) >= min_section_length)
|
||||
&& ((!pre_event_count) || (Event::PreAlarmCount() >= alarm_frame_count - 1))) {
|
||||
Info("%s: %03d - Closing event %" PRIu64 ", continuous end, alarm begins",
|
||||
name.c_str(), image_count, event->Id());
|
||||
closeEvent();
|
||||
} else if (event) {
|
||||
// This is so if we need more than 1 alarm frame before going into alarm, so it is basically if we have enough alarm frames
|
||||
Debug(3,
|
||||
"pre_alarm_count in event %d, event frames %d, alarm frames %d event length %" PRIi64 " >=? %" PRIi64 " min",
|
||||
Event::PreAlarmCount(),
|
||||
"pre_alarm_count in event %d of %d, event frames %d, alarm frames %d event length %" PRIi64 " >=? %" PRIi64 " min close mode is ALARM? %d",
|
||||
Event::PreAlarmCount(), pre_event_count,
|
||||
event->Frames(),
|
||||
event->AlarmFrames(),
|
||||
static_cast<int64>(std::chrono::duration_cast<Seconds>(timestamp - GetVideoWriterStartTime()).count()),
|
||||
static_cast<int64>(Seconds(min_section_length).count()));
|
||||
static_cast<int64>(std::chrono::duration_cast<Seconds>(timestamp - event->StartTime()).count()),
|
||||
static_cast<int64>(Seconds(min_section_length).count()),
|
||||
(event_close_mode == CLOSE_ALARM));
|
||||
}
|
||||
if ((!pre_event_count) || (Event::PreAlarmCount() >= alarm_frame_count-1)) {
|
||||
// lets construct alarm cause. It will contain cause + names of zones alarmed
|
||||
|
@ -2133,6 +2092,13 @@ bool Monitor::Analyse() {
|
|||
delete start_it;
|
||||
start_it = nullptr;
|
||||
|
||||
if (!event_start_command.empty()) {
|
||||
if (fork() == 0) {
|
||||
execlp(event_start_command.c_str(), event_start_command.c_str(), std::to_string(event->Id()).c_str(), nullptr);
|
||||
Error("Error execing %s", event_start_command.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
Info("%s: %03d - Opening new event %" PRIu64 ", alarm start", name.c_str(), analysis_image_count, event->Id());
|
||||
} else {
|
||||
shared_data->state = state = ALARM;
|
||||
|
@ -2170,8 +2136,10 @@ bool Monitor::Analyse() {
|
|||
Info("%s: %03d - Gone into alert state", name.c_str(), analysis_image_count);
|
||||
shared_data->state = state = ALERT;
|
||||
} else if (state == ALERT) {
|
||||
if (analysis_image_count - last_alarm_count > post_event_count
|
||||
&& timestamp - GetVideoWriterStartTime() >= min_section_length) {
|
||||
if (
|
||||
((analysis_image_count - last_alarm_count) > post_event_count)
|
||||
&&
|
||||
((timestamp - event->StartTime()) >= min_section_length)) {
|
||||
Info("%s: %03d - Left alarm state (%" PRIu64 ") - %d(%d) images",
|
||||
name.c_str(), analysis_image_count, event->Id(), event->Frames(), event->AlarmFrames());
|
||||
//if ( function != MOCORD || event_close_mode == CLOSE_ALARM || event->Cause() == SIGNAL_CAUSE )
|
||||
|
@ -2189,7 +2157,8 @@ bool Monitor::Analyse() {
|
|||
shared_data->state = state = ((function != MOCORD) ? IDLE : TAPE);
|
||||
} else {
|
||||
Debug(1,
|
||||
"State %s because image_count(%d)-last_alarm_count(%d) > post_event_count(%d) and timestamp.tv_sec(%" PRIi64 ") - recording.tv_src(%" PRIi64 ") >= min_section_length(%" PRIi64 ")",
|
||||
"State %d %s because analysis_image_count(%d)-last_alarm_count(%d) > post_event_count(%d) and timestamp.tv_sec(%" PRIi64 ") - recording.tv_src(%" PRIi64 ") >= min_section_length(%" PRIi64 ")",
|
||||
state,
|
||||
State_Strings[state].c_str(),
|
||||
analysis_image_count,
|
||||
last_alarm_count,
|
||||
|
@ -2208,18 +2177,15 @@ bool Monitor::Analyse() {
|
|||
// Generate analysis images if necessary
|
||||
if ((savejpegs > 1) and snap->image) {
|
||||
for (const Zone &zone : zones) {
|
||||
if (zone.Alarmed()) {
|
||||
if (zone.AlarmImage()) {
|
||||
if (zone.Alarmed() and zone.AlarmImage()) {
|
||||
if (!snap->analysis_image)
|
||||
snap->analysis_image = new Image(*(snap->image));
|
||||
snap->analysis_image->Overlay(*(zone.AlarmImage()));
|
||||
}
|
||||
} // end if zone is alarmed
|
||||
} // end foreach zone
|
||||
} // end if savejpegs
|
||||
|
||||
// incremement pre alarm image count
|
||||
//have_pre_alarmed_frames ++;
|
||||
Event::AddPreAlarmFrame(snap->image, timestamp, score, nullptr);
|
||||
} else if (state == ALARM) {
|
||||
for (const Zone &zone : zones) {
|
||||
|
@ -2234,7 +2200,7 @@ bool Monitor::Analyse() {
|
|||
if (event) {
|
||||
if (noteSetMap.size() > 0)
|
||||
event->updateNotes(noteSetMap);
|
||||
if (section_length != Seconds(0) && (timestamp - GetVideoWriterStartTime() >= section_length)) {
|
||||
if (section_length != Seconds(0) && (timestamp - event->StartTime() >= section_length)) {
|
||||
Warning("%s: %03d - event %" PRIu64 ", has exceeded desired section length. %" PRIi64 " - %" PRIi64 " = %" PRIi64 " >= %" PRIi64,
|
||||
name.c_str(), analysis_image_count, event->Id(),
|
||||
static_cast<int64>(std::chrono::duration_cast<Seconds>(timestamp.time_since_epoch()).count()),
|
||||
|
@ -2299,8 +2265,6 @@ bool Monitor::Analyse() {
|
|||
// Only do these if it's a video packet.
|
||||
shared_data->last_read_index = snap->image_index;
|
||||
analysis_image_count++;
|
||||
if (function == MODECT or function == MOCORD)
|
||||
UpdateAnalysisFPS();
|
||||
}
|
||||
packetqueue.increment_it(analysis_it);
|
||||
packetqueue.unlock(packet_lock);
|
||||
|
@ -2363,7 +2327,7 @@ void Monitor::ReloadLinkedMonitors(const char *p_linked_monitors) {
|
|||
while ( 1 ) {
|
||||
dest_ptr = link_id_str;
|
||||
while ( *src_ptr >= '0' && *src_ptr <= '9' ) {
|
||||
if ( (dest_ptr-link_id_str) < (unsigned int)(sizeof(link_id_str)-1) ) {
|
||||
if ( (unsigned int)(dest_ptr-link_id_str) < (unsigned int)(sizeof(link_id_str)-1) ) {
|
||||
*dest_ptr++ = *src_ptr++;
|
||||
} else {
|
||||
break;
|
||||
|
@ -2585,7 +2549,6 @@ int Monitor::Capture() {
|
|||
|
||||
// Will only be queued if there are iterators allocated in the queue.
|
||||
packetqueue.queuePacket(packet);
|
||||
UpdateCaptureFPS();
|
||||
} else { // result == 0
|
||||
// Question is, do we update last_write_index etc?
|
||||
return 0;
|
||||
|
@ -2625,7 +2588,7 @@ bool Monitor::Decode() {
|
|||
//
|
||||
//capture_image = packet->image = new Image(width, height, camera->Colours(), camera->SubpixelOrder());
|
||||
int ret = packet->decode(camera->getVideoCodecContext());
|
||||
if (ret > 0) {
|
||||
if (ret > 0 and !zm_terminate) {
|
||||
if (packet->in_frame and !packet->image) {
|
||||
packet->image = new Image(camera_width, camera_height, camera->Colours(), camera->SubpixelOrder());
|
||||
AVFrame *input_frame = packet->in_frame;
|
||||
|
@ -2795,7 +2758,7 @@ void Monitor::TimestampImage(Image *ts_image, SystemTimePoint ts_time) const {
|
|||
const char *s_ptr = label_time_text;
|
||||
char *d_ptr = label_text;
|
||||
|
||||
while (*s_ptr && ((d_ptr - label_text) < (unsigned int) sizeof(label_text))) {
|
||||
while (*s_ptr && ((unsigned int)(d_ptr - label_text) < (unsigned int) sizeof(label_text))) {
|
||||
if ( *s_ptr == config.timestamp_code_char[0] ) {
|
||||
bool found_macro = false;
|
||||
switch ( *(s_ptr+1) ) {
|
||||
|
@ -2811,7 +2774,7 @@ void Monitor::TimestampImage(Image *ts_image, SystemTimePoint ts_time) const {
|
|||
typedef std::chrono::duration<int64, std::centi> Centiseconds;
|
||||
Centiseconds centi_sec = std::chrono::duration_cast<Centiseconds>(
|
||||
ts_time.time_since_epoch() - std::chrono::duration_cast<Seconds>(ts_time.time_since_epoch()));
|
||||
d_ptr += snprintf(d_ptr, sizeof(label_text) - (d_ptr - label_text), "%02ld", centi_sec.count());
|
||||
d_ptr += snprintf(d_ptr, sizeof(label_text) - (d_ptr - label_text), "%02lld", static_cast<long long int>(centi_sec.count()));
|
||||
found_macro = true;
|
||||
break;
|
||||
}
|
||||
|
@ -2838,7 +2801,18 @@ void Monitor::closeEvent() {
|
|||
Debug(1, "close event thread is not joinable");
|
||||
}
|
||||
Debug(1, "Starting thread to close event");
|
||||
close_event_thread = std::thread([](Event *e){ delete e; }, event);
|
||||
close_event_thread = std::thread([](Event *e, const std::string &command){
|
||||
int64_t event_id = e->Id();
|
||||
delete e;
|
||||
|
||||
if (!command.empty()) {
|
||||
if (fork() == 0) {
|
||||
execlp(command.c_str(), command.c_str(), std::to_string(event_id).c_str(), nullptr);
|
||||
Error("Error execing %s", command.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
}, event, event_end_command);
|
||||
Debug(1, "Nulling event");
|
||||
event = nullptr;
|
||||
if (shared_data) video_store_data->recording = {};
|
||||
|
|
|
@ -100,7 +100,7 @@ public:
|
|||
} Deinterlace;
|
||||
|
||||
typedef enum {
|
||||
UNKNOWN=-1,
|
||||
UNKNOWN,
|
||||
IDLE,
|
||||
PREALARM,
|
||||
ALARM,
|
||||
|
@ -404,6 +404,8 @@ protected:
|
|||
|
||||
int n_linked_monitors;
|
||||
MonitorLink **linked_monitors;
|
||||
std::string event_start_command;
|
||||
std::string event_end_command;
|
||||
|
||||
std::vector<Group *> groups;
|
||||
|
||||
|
@ -546,8 +548,7 @@ public:
|
|||
unsigned int GetLastWriteIndex() const;
|
||||
uint64_t GetLastEventId() const;
|
||||
double GetFPS() const;
|
||||
void UpdateAnalysisFPS();
|
||||
void UpdateCaptureFPS();
|
||||
void UpdateFPS();
|
||||
void ForceAlarmOn( int force_score, const char *force_case, const char *force_text="" );
|
||||
void ForceAlarmOff();
|
||||
void CancelForced();
|
||||
|
|
|
@ -229,6 +229,7 @@ void MonitorStream::processCommand(const CmdMsg *msg) {
|
|||
break;
|
||||
case CMD_QUIT :
|
||||
Info("User initiated exit - CMD_QUIT");
|
||||
zm_terminate = true;
|
||||
break;
|
||||
case CMD_QUERY :
|
||||
Debug(1, "Got QUERY command, sending STATUS");
|
||||
|
@ -315,16 +316,6 @@ void MonitorStream::processCommand(const CmdMsg *msg) {
|
|||
}
|
||||
}
|
||||
Debug(2, "Number of bytes sent to (%s): (%d)", rem_addr.sun_path, nbytes);
|
||||
|
||||
// quit after sending a status, if this was a quit request
|
||||
if ( (MsgCommand)msg->msg_data[0] == CMD_QUIT ) {
|
||||
zm_terminate = true;
|
||||
Debug(2, "Quitting");
|
||||
return;
|
||||
}
|
||||
|
||||
//Debug(2,"Updating framerate");
|
||||
//updateFrameRate(monitor->GetFPS());
|
||||
} // end void MonitorStream::processCommand(const CmdMsg *msg)
|
||||
|
||||
bool MonitorStream::sendFrame(const std::string &filepath, SystemTimePoint timestamp) {
|
||||
|
@ -386,10 +377,10 @@ bool MonitorStream::sendFrame(const std::string &filepath, SystemTimePoint times
|
|||
}
|
||||
|
||||
bool MonitorStream::sendFrame(Image *image, SystemTimePoint timestamp) {
|
||||
Image *send_image = prepareImage(image);
|
||||
if (!config.timestamp_on_capture) {
|
||||
monitor->TimestampImage(send_image, timestamp);
|
||||
monitor->TimestampImage(image, timestamp);
|
||||
}
|
||||
Image *send_image = prepareImage(image);
|
||||
|
||||
fputs("--" BOUNDARY "\r\n", stdout);
|
||||
if ( type == STREAM_MPEG ) {
|
||||
|
@ -863,16 +854,16 @@ void MonitorStream::SingleImage(int scale) {
|
|||
int index = monitor->shared_data->last_write_index % monitor->image_buffer_count;
|
||||
Debug(1, "write index: %d %d", monitor->shared_data->last_write_index, index);
|
||||
Image *snap_image = monitor->image_buffer[index];
|
||||
if (!config.timestamp_on_capture) {
|
||||
monitor->TimestampImage(snap_image,
|
||||
SystemTimePoint(zm::chrono::duration_cast<Microseconds>(monitor->shared_timestamps[index])));
|
||||
}
|
||||
|
||||
if ( scale != ZM_SCALE_BASE ) {
|
||||
scaled_image.Assign(*snap_image);
|
||||
scaled_image.Scale(scale);
|
||||
snap_image = &scaled_image;
|
||||
}
|
||||
if (!config.timestamp_on_capture) {
|
||||
monitor->TimestampImage(snap_image,
|
||||
SystemTimePoint(zm::chrono::duration_cast<Microseconds>(monitor->shared_timestamps[index])));
|
||||
}
|
||||
snap_image->EncodeJpeg(img_buffer, &img_buffer_size);
|
||||
|
||||
fprintf(stdout,
|
||||
|
|
|
@ -118,12 +118,13 @@ bool PacketQueue::queuePacket(std::shared_ptr<ZMPacket> add_packet) {
|
|||
for (
|
||||
auto it = ++pktQueue.begin();
|
||||
it != pktQueue.end() and *it != add_packet;
|
||||
// iterator is incremented by erase
|
||||
) {
|
||||
std::shared_ptr <ZMPacket>zm_packet = *it;
|
||||
|
||||
ZMLockedPacket *lp = new ZMLockedPacket(zm_packet);
|
||||
if (!lp->trylock()) {
|
||||
Debug(1, "Found locked packet when trying to free up video packets. Skipping to next one");
|
||||
Warning("Found locked packet when trying to free up video packets. This basically means that decoding is not keeping up.");
|
||||
delete lp;
|
||||
++it;
|
||||
continue;
|
||||
|
@ -209,7 +210,7 @@ void PacketQueue::clearPackets(const std::shared_ptr<ZMPacket> &add_packet) {
|
|||
--it;
|
||||
}
|
||||
}
|
||||
Debug(1, "Tail count is %d, queue size is %lu", tail_count, pktQueue.size());
|
||||
Debug(1, "Tail count is %d, queue size is %zu", tail_count, pktQueue.size());
|
||||
|
||||
if (!keep_keyframes) {
|
||||
// If not doing passthrough, we don't care about starting with a keyframe so logic is simpler
|
||||
|
@ -312,7 +313,6 @@ void PacketQueue::clearPackets(const std::shared_ptr<ZMPacket> &add_packet) {
|
|||
pktQueue.size());
|
||||
pktQueue.pop_front();
|
||||
packet_counts[zm_packet->packet.stream_index] -= 1;
|
||||
//delete zm_packet;
|
||||
}
|
||||
} // end if have at least max_video_packet_count video packets remaining
|
||||
// We signal on every packet because someday we may analyze sound
|
||||
|
|
|
@ -46,6 +46,7 @@ RETSIGTYPE zm_die_handler(int signal, siginfo_t * info, void *context)
|
|||
RETSIGTYPE zm_die_handler(int signal)
|
||||
#endif
|
||||
{
|
||||
zm_terminate = true;
|
||||
Error("Got signal %d (%s), crashing", signal, strsignal(signal));
|
||||
#if (defined(__i386__) || defined(__x86_64__))
|
||||
// Get more information if available
|
||||
|
|
|
@ -252,8 +252,15 @@ void HwCapsDetect() {
|
|||
#elif defined(__arm__)
|
||||
// ARM processor in 32bit mode
|
||||
// To see if it supports NEON, we need to get that information from the kernel
|
||||
#ifdef __linux__
|
||||
unsigned long auxval = getauxval(AT_HWCAP);
|
||||
if (auxval & HWCAP_ARM_NEON) {
|
||||
#elif defined(__FreeBSD__)
|
||||
unsigned long auxval = 0;
|
||||
elf_aux_info(AT_HWCAP, &auxval, sizeof(auxval));
|
||||
if (auxval & HWCAP_NEON) {
|
||||
#error Unsupported OS.
|
||||
#endif
|
||||
Debug(1,"Detected ARM (AArch32) processor with Neon");
|
||||
neonversion = 1;
|
||||
} else {
|
||||
|
|
|
@ -111,6 +111,13 @@ class VideoStore {
|
|||
int writePacket(const std::shared_ptr<ZMPacket> &pkt);
|
||||
int write_packets(PacketQueue &queue);
|
||||
void flush_codecs();
|
||||
const char *get_codec() {
|
||||
if (chosen_codec_data)
|
||||
return chosen_codec_data->codec_codec;
|
||||
if (video_out_stream)
|
||||
return avcodec_get_name(video_out_stream->codecpar->codec_id);
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
#endif // ZM_VIDEOSTORE_H
|
||||
|
|
|
@ -878,16 +878,23 @@ std::vector<Zone> Zone::Load(Monitor *monitor) {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (polygon.Extent().Lo().x_ < 0 || polygon.Extent().Hi().x_ > static_cast<int32>(monitor->Width())
|
||||
|| polygon.Extent().Lo().y_ < 0 || polygon.Extent().Hi().y_ > static_cast<int32>(monitor->Height())) {
|
||||
Error("Zone %d/%s for monitor %s extends outside of image dimensions, (%d,%d), (%d,%d), fixing",
|
||||
if (polygon.Extent().Lo().x_ < 0
|
||||
||
|
||||
polygon.Extent().Hi().x_ > static_cast<int32>(monitor->Width())
|
||||
||
|
||||
polygon.Extent().Lo().y_ < 0
|
||||
||
|
||||
polygon.Extent().Hi().y_ > static_cast<int32>(monitor->Height())) {
|
||||
Error("Zone %d/%s for monitor %s extends outside of image dimensions, (%d,%d), (%d,%d) != (%d,%d), fixing",
|
||||
Id,
|
||||
Name,
|
||||
monitor->Name(),
|
||||
polygon.Extent().Lo().x_,
|
||||
polygon.Extent().Lo().y_,
|
||||
polygon.Extent().Hi().x_,
|
||||
polygon.Extent().Hi().y_);
|
||||
polygon.Extent().Hi().y_,
|
||||
monitor->Width(),
|
||||
monitor->Height());
|
||||
|
||||
polygon.Clip(Box(
|
||||
{0, 0},
|
||||
|
|
15
src/zmc.cpp
15
src/zmc.cpp
|
@ -220,12 +220,13 @@ int main(int argc, char *argv[]) {
|
|||
zmSetDefaultTermHandler();
|
||||
zmSetDefaultDieHandler();
|
||||
|
||||
sigset_t block_set;
|
||||
sigemptyset(&block_set);
|
||||
|
||||
sigaddset(&block_set, SIGHUP);
|
||||
sigaddset(&block_set, SIGUSR1);
|
||||
sigaddset(&block_set, SIGUSR2);
|
||||
struct sigaction sa;
|
||||
sa.sa_handler = SIG_IGN; //handle signal by ignoring
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
if (sigaction(SIGCHLD, &sa, 0) == -1) {
|
||||
Error("Unable to set SIGCHLD to ignore. There may be zombies.");
|
||||
}
|
||||
|
||||
int result = 0;
|
||||
int prime_capture_log_count = 0;
|
||||
|
@ -286,7 +287,6 @@ int main(int argc, char *argv[]) {
|
|||
Microseconds sleep_time = Microseconds(0);
|
||||
|
||||
while (!zm_terminate) {
|
||||
//sigprocmask(SIG_BLOCK, &block_set, 0);
|
||||
for (size_t i = 0; i < monitors.size(); i++) {
|
||||
monitors[i]->CheckAction();
|
||||
|
||||
|
@ -308,6 +308,7 @@ int main(int argc, char *argv[]) {
|
|||
result = -1;
|
||||
break;
|
||||
}
|
||||
monitors[i]->UpdateFPS();
|
||||
|
||||
// capture_delay is the amount of time we should sleep in useconds to achieve the desired framerate.
|
||||
Microseconds delay = (monitors[i]->GetState() == Monitor::ALARM) ? monitors[i]->GetAlarmCaptureDelay()
|
||||
|
|
|
@ -116,6 +116,30 @@ else
|
|||
echo "Defaulting to ZoneMinder upstream git"
|
||||
GITHUB_FORK="ZoneMinder"
|
||||
fi;
|
||||
fi;
|
||||
|
||||
# Instead of cloning from github each time, if we have a fork lying around, update it and pull from there instead.
|
||||
if [ ! -d "${GITHUB_FORK}_zoneminder_release" ]; then
|
||||
if [ -d "${GITHUB_FORK}_ZoneMinder.git" ]; then
|
||||
echo "Using local clone ${GITHUB_FORK}_ZoneMinder.git to pull from."
|
||||
cd "${GITHUB_FORK}_ZoneMinder.git"
|
||||
echo "git fetch..."
|
||||
git fetch
|
||||
cd ../
|
||||
|
||||
echo "git clone ${GITHUB_FORK}_ZoneMinder.git ${GITHUB_FORK}_zoneminder_release"
|
||||
git clone "${GITHUB_FORK}_ZoneMinder.git" "${GITHUB_FORK}_zoneminder_release"
|
||||
else
|
||||
echo "git clone https://github.com/$GITHUB_FORK/ZoneMinder.git ${GITHUB_FORK}_zoneminder_release"
|
||||
git clone "https://github.com/$GITHUB_FORK/ZoneMinder.git" "${GITHUB_FORK}_zoneminder_release"
|
||||
fi
|
||||
else
|
||||
echo "release dir already exists. Please remove it."
|
||||
exit 0;
|
||||
fi;
|
||||
|
||||
cd "${GITHUB_FORK}_zoneminder_release"
|
||||
|
||||
if [ "$SNAPSHOT" == "stable" ]; then
|
||||
if [ "$BRANCH" == "" ]; then
|
||||
#REV=$(git rev-list --tags --max-count=1)
|
||||
|
@ -140,37 +164,17 @@ else
|
|||
SNAPSHOT=`date +%Y%m%d%H%M%S`;
|
||||
else
|
||||
if [ "$SNAPSHOT" == "CURRENT" ]; then
|
||||
# git the latest (short) commit hash of the version file
|
||||
versionhash=$(git log -n1 --pretty=format:%h version)
|
||||
|
||||
# Number of commits since the version file was last changed
|
||||
numcommits=$(git rev-list ${versionhash}..HEAD --count)
|
||||
SNAPSHOT="`date +%Y%m%d.`$(git rev-list ${versionhash}..HEAD --count)"
|
||||
fi;
|
||||
fi;
|
||||
fi;
|
||||
fi
|
||||
|
||||
IFS='.' read -r -a VERSION_PARTS <<< "$RELEASE"
|
||||
if [ "$PPA" == "" ]; then
|
||||
if [ "$RELEASE" != "" ]; then
|
||||
# We need to use our official tarball for the original source, so grab it and overwrite our generated one.
|
||||
if [ "${VERSION_PARTS[0]}.${VERSION_PARTS[1]}" == "1.30" ]; then
|
||||
PPA="ppa:iconnor/zoneminder-stable"
|
||||
else
|
||||
PPA="ppa:iconnor/zoneminder-${VERSION_PARTS[0]}.${VERSION_PARTS[1]}"
|
||||
fi;
|
||||
else
|
||||
if [ "$BRANCH" == "" ]; then
|
||||
PPA="ppa:iconnor/zoneminder-master";
|
||||
else
|
||||
PPA="ppa:iconnor/zoneminder-$BRANCH";
|
||||
fi;
|
||||
fi;
|
||||
fi;
|
||||
|
||||
# Instead of cloning from github each time, if we have a fork lying around, update it and pull from there instead.
|
||||
if [ ! -d "${GITHUB_FORK}_zoneminder_release" ]; then
|
||||
if [ -d "${GITHUB_FORK}_ZoneMinder.git" ]; then
|
||||
echo "Using local clone ${GITHUB_FORK}_ZoneMinder.git to pull from."
|
||||
cd "${GITHUB_FORK}_ZoneMinder.git"
|
||||
echo "git fetch..."
|
||||
git fetch
|
||||
echo "git checkout $BRANCH"
|
||||
git checkout $BRANCH
|
||||
if [ $? -ne 0 ]; then
|
||||
|
@ -179,27 +183,15 @@ if [ ! -d "${GITHUB_FORK}_zoneminder_release" ]; then
|
|||
fi;
|
||||
echo "git pull..."
|
||||
git pull
|
||||
cd ../
|
||||
echo "git clone ${GITHUB_FORK}_ZoneMinder.git ${GITHUB_FORK}_zoneminder_release"
|
||||
git clone "${GITHUB_FORK}_ZoneMinder.git" "${GITHUB_FORK}_zoneminder_release"
|
||||
else
|
||||
echo "git clone https://github.com/$GITHUB_FORK/ZoneMinder.git ${GITHUB_FORK}_zoneminder_release"
|
||||
git clone "https://github.com/$GITHUB_FORK/ZoneMinder.git" "${GITHUB_FORK}_zoneminder_release"
|
||||
fi
|
||||
else
|
||||
echo "release dir already exists. Please remove it."
|
||||
exit 0;
|
||||
fi;
|
||||
|
||||
cd "${GITHUB_FORK}_zoneminder_release"
|
||||
git checkout $BRANCH
|
||||
cd ../
|
||||
|
||||
VERSION=`cat ${GITHUB_FORK}_zoneminder_release/version`
|
||||
|
||||
# Grab the ZoneMinder version from the contents of the version file
|
||||
VERSION=$(cat version)
|
||||
if [ -z "$VERSION" ]; then
|
||||
exit 1;
|
||||
fi;
|
||||
IFS='.' read -r -a VERSION_PARTS <<< "$VERSION"
|
||||
|
||||
cd ../
|
||||
|
||||
if [ "$SNAPSHOT" != "stable" ] && [ "$SNAPSHOT" != "" ]; then
|
||||
VERSION="$VERSION~$SNAPSHOT";
|
||||
fi;
|
||||
|
@ -232,8 +224,7 @@ cd ../
|
|||
|
||||
if [ ! -e "$DIRECTORY.orig.tar.gz" ]; then
|
||||
read -p "$DIRECTORY.orig.tar.gz does not exist, create it? [Y/n]"
|
||||
if [[ $REPLY == [yY] ]]; then
|
||||
|
||||
if [[ "$REPLY" == "" || "$REPLY" == [yY] ]]; then
|
||||
tar zcf $DIRECTORY.orig.tar.gz $DIRECTORY.orig
|
||||
fi;
|
||||
fi;
|
||||
|
@ -358,6 +349,22 @@ EOF
|
|||
fi;
|
||||
else
|
||||
SC="zoneminder_${VERSION}-${DISTRO}${PACKAGE_VERSION}_source.changes";
|
||||
if [ "$PPA" == "" ]; then
|
||||
if [ "$RELEASE" != "" ]; then
|
||||
# We need to use our official tarball for the original source, so grab it and overwrite our generated one.
|
||||
if [ "${VERSION_PARTS[0]}.${VERSION_PARTS[1]}" == "1.30" ]; then
|
||||
PPA="ppa:iconnor/zoneminder-stable"
|
||||
else
|
||||
PPA="ppa:iconnor/zoneminder-${VERSION_PARTS[0]}.${VERSION_PARTS[1]}"
|
||||
fi;
|
||||
else
|
||||
if [ "$BRANCH" == "" ]; then
|
||||
PPA="ppa:iconnor/zoneminder-master";
|
||||
else
|
||||
PPA="ppa:iconnor/zoneminder-$BRANCH";
|
||||
fi;
|
||||
fi;
|
||||
fi;
|
||||
|
||||
dput="Y";
|
||||
if [ "$INTERACTIVE" != "no" ]; then
|
||||
|
|
|
@ -93,7 +93,7 @@ if ( canView('Events') or canView('Snapshots') ) {
|
|||
$exportFormat,
|
||||
$exportCompress,
|
||||
$exportStructure,
|
||||
(!empty($_REQUEST['exportFile'])?$_REQUEST['exportFile']:'zmExport'),
|
||||
(!empty($_REQUEST['exportFile'])?$_REQUEST['exportFile']:'zmExport')
|
||||
)) {
|
||||
ajaxResponse(array('exportFile'=>$exportFile));
|
||||
} else {
|
||||
|
|
|
@ -75,7 +75,6 @@ if ( isset($_REQUEST['offset']) ) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Limit specifies the number of rows to return
|
||||
// Set the default to 0 for events view, to prevent an issue with ALL pagination
|
||||
$limit = 0;
|
||||
|
@ -108,7 +107,6 @@ switch ( $task ) {
|
|||
ajaxError('Insufficient permissions for user '.$user['Username']);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($eids as $eid) $data[] = deleteRequest($eid);
|
||||
break;
|
||||
case 'query' :
|
||||
|
@ -139,6 +137,8 @@ function deleteRequest($eid) {
|
|||
$message[] = array($eid=>'Event not found.');
|
||||
} else if ( $event->Archived() ) {
|
||||
$message[] = array($eid=>'Event is archived, cannot delete it.');
|
||||
} else if (!$event->canEdit()) {
|
||||
$message[] = array($eid=>'You do not have permission to delete event '.$event->Id());
|
||||
} else {
|
||||
$event->delete();
|
||||
}
|
||||
|
@ -147,7 +147,6 @@ function deleteRequest($eid) {
|
|||
}
|
||||
|
||||
function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $limit) {
|
||||
|
||||
$data = array(
|
||||
'total' => 0,
|
||||
'totalNotFiltered' => 0,
|
||||
|
@ -195,7 +194,10 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim
|
|||
|
||||
ZM\Debug('Calling the following sql query: ' .$sql);
|
||||
$query = dbQuery($sql, $values);
|
||||
if ( $query ) {
|
||||
if (!$query) {
|
||||
ajaxError(dbError($sql));
|
||||
return;
|
||||
}
|
||||
while ($row = dbFetchNext($query)) {
|
||||
$event = new ZM\Event($row);
|
||||
$event->remove_from_cache();
|
||||
|
@ -205,7 +207,6 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim
|
|||
$event_ids[] = $event->Id();
|
||||
$unfiltered_rows[] = $row;
|
||||
} # end foreach row
|
||||
}
|
||||
|
||||
ZM\Debug('Have ' . count($unfiltered_rows) . ' events matching base filter.');
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ if ($zmuOutput) {
|
|||
$ctls = shell_exec('v4l2-ctl -d '.$monitor->Device().' --list-ctrls');
|
||||
|
||||
if (!$ctls) {
|
||||
ZM\Warning("Guessing v4l ctrls. We need v4l2-ctl please install it");
|
||||
ZM\Warning('Guessing v4l ctrls. We need v4l2-ctl please install it');
|
||||
$ctls = '
|
||||
brightness 0x00980900 (int) : min=-10 max=10 step=1 default=0 value=8
|
||||
contrast 0x00980901 (int) : min=0 max=20 step=1 default=10 value=12
|
||||
|
@ -83,10 +83,15 @@ foreach ($ctls as $line) {
|
|||
}
|
||||
}
|
||||
|
||||
$label = translate($setting_uc);
|
||||
if ($label == $setting_uc) {
|
||||
$label = ucwords(str_replace('_', ' ', $label));
|
||||
}
|
||||
|
||||
if ($setting == 'brightness' or $setting == 'colour' or $setting == 'contrast' or $setting == 'hue') {
|
||||
echo '
|
||||
<tr>
|
||||
<th scope="row">'.translate($setting_uc).'</th>
|
||||
<th scope="row">'.$label.'</th>
|
||||
<td>'.$min.'</td><td><input type="range" title="'.$value.'" min="'.$min.'" max="'.$max.'" step="'.$step.'" default="'.$default.'" value="'.$value.'" id="new'.$setting_uc.'" name="new'.$setting_uc.'" '.(canEdit('Control') ? '' : 'disabled="disabled"') .'/></td><td>'.$max.'</td>
|
||||
</tr>
|
||||
';
|
||||
|
@ -94,7 +99,7 @@ foreach ($ctls as $line) {
|
|||
if ($type == '(bool)') {
|
||||
echo '
|
||||
<tr>
|
||||
<th scope="row">'.translate($setting_uc).'</th>
|
||||
<th scope="row">'.$label.'</th>
|
||||
<td></td><td>'.html_radio('new'.$setting_uc, array('0'=>translate('True'), '1', translate('False')), $value, array('disabled'=>'disabled')).'
|
||||
</td><td></td>
|
||||
</tr>
|
||||
|
@ -102,14 +107,14 @@ foreach ($ctls as $line) {
|
|||
} else if ($type == '(int)') {
|
||||
echo '
|
||||
<tr>
|
||||
<th scope="row">'.translate($setting_uc).'</th>
|
||||
<th scope="row">'.$label.'</th>
|
||||
<td></td><td><input type="range" '.$ctl[1].' disabled="disabled"/></td><td></td>
|
||||
</tr>
|
||||
';
|
||||
} else {
|
||||
echo '
|
||||
<tr>
|
||||
<th scope="row">'.translate($setting_uc).'</th>
|
||||
<th scope="row">'.$label.'</th>
|
||||
<td></td><td>'.$value.'</td><td></td>
|
||||
</tr>
|
||||
';
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
// At the moment this can only return the list of available models given the manufacturer id
|
||||
|
||||
$message = '';
|
||||
|
||||
//
|
||||
// INITIALIZE AND CHECK SANITY
|
||||
//
|
||||
|
||||
if (!canView('Monitors')) {
|
||||
$message = 'Insufficient permissions to view model entries for user '.$user['Username'];
|
||||
} else if (!isset($_REQUEST['ManufacturerId'])) {
|
||||
$message = 'This request requires a ManufacturerId to be set';
|
||||
}
|
||||
|
||||
if ($message) {
|
||||
ajaxError($message);
|
||||
return;
|
||||
}
|
||||
|
||||
require_once('includes/Model.php');
|
||||
$models = ZM\Model::find(array('ManufacturerId'=>$_REQUEST['ManufacturerId']), array('order'=>'lower(Name)'));
|
||||
ajaxResponse(array('models'=>$models));
|
||||
?>
|
|
@ -23,8 +23,6 @@
|
|||
/**
|
||||
* Load the API / REST routes
|
||||
*/
|
||||
/* Add new API to retrieve camera controls - for PTZ */
|
||||
/* refer to https://github.com/ZoneMinder/ZoneMinder/issues/799#issuecomment-105233112 */
|
||||
Router::mapResources('configs');
|
||||
Router::mapResources('controls');
|
||||
Router::mapResources('events');
|
||||
|
@ -32,7 +30,11 @@
|
|||
Router::mapResources('groups');
|
||||
Router::mapResources('host');
|
||||
Router::mapResources('logs');
|
||||
Router::mapResources('manufacturers');
|
||||
Router::mapResources('models');
|
||||
Router::mapResources('cameramodels');
|
||||
Router::mapResources('monitors');
|
||||
Router::mapResources('servers');
|
||||
Router::mapResources('states');
|
||||
Router::mapResources('users');
|
||||
Router::mapResources('zonepresets');
|
||||
|
|
|
@ -0,0 +1,156 @@
|
|||
<?php
|
||||
App::uses('AppController', 'Controller');
|
||||
/**
|
||||
* Models Controller
|
||||
*
|
||||
* @property Model $Model
|
||||
* @property PaginatorComponent $Paginator
|
||||
*/
|
||||
class CameraModelsController extends AppController {
|
||||
|
||||
/**
|
||||
* Components
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $components = array('Paginator', 'RequestHandler');
|
||||
|
||||
public function beforeFilter() {
|
||||
parent::beforeFilter();
|
||||
/*
|
||||
* A user needs the model data to calculate how to view a monitor, and there really isn't anything sensitive in this data.
|
||||
* So it has been decided for now to just let everyone read it.
|
||||
|
||||
global $user;
|
||||
$canView = (!$user) || ($user['System'] != 'None');
|
||||
if ( !$canView ) {
|
||||
throw new UnauthorizedException(__('Insufficient Privileges'));
|
||||
return;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* index method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function index() {
|
||||
$this->CameraModel->recursive = 0;
|
||||
|
||||
$options = '';
|
||||
$models = $this->CameraModel->find('all', $options);
|
||||
$this->set(array(
|
||||
'models' => $models,
|
||||
'_serialize' => array('models')
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* view method
|
||||
*
|
||||
* @throws NotFoundException
|
||||
* @param string $id
|
||||
* @return void
|
||||
*/
|
||||
public function view($id = null) {
|
||||
$this->CameraModel->recursive = 0;
|
||||
if ( !$this->CameraModel->exists($id) ) {
|
||||
throw new NotFoundException(__('Invalid model'));
|
||||
}
|
||||
$restricted = '';
|
||||
|
||||
$options = array('conditions' => array(
|
||||
array('CameraModel.'.$this->CameraModel->primaryKey => $id),
|
||||
$restricted
|
||||
)
|
||||
);
|
||||
$model = $this->CameraModel->find('first', $options);
|
||||
$this->set(array(
|
||||
'model' => $model,
|
||||
'_serialize' => array('model')
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* add method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add() {
|
||||
if ($this->request->is('post')) {
|
||||
|
||||
global $user;
|
||||
$canEdit = (!$user) || ($user['System'] == 'Edit');
|
||||
if (!$canEdit) {
|
||||
throw new UnauthorizedException(__('Insufficient privileges'));
|
||||
return;
|
||||
}
|
||||
|
||||
$this->CameraModel->create();
|
||||
if ($this->CameraModel->save($this->request->data)) {
|
||||
return $this->flash(__('The model has been saved.'), array('action' => 'index'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* edit method
|
||||
*
|
||||
* @throws NotFoundException
|
||||
* @param string $id
|
||||
* @return void
|
||||
*/
|
||||
public function edit($id = null) {
|
||||
$this->CameraModel->id = $id;
|
||||
|
||||
global $user;
|
||||
$canEdit = (!$user) || ($user['System'] == 'Edit');
|
||||
if (!$canEdit) {
|
||||
throw new UnauthorizedException(__('Insufficient privileges'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$this->CameraModel->exists($id)) {
|
||||
throw new NotFoundException(__('Invalid model'));
|
||||
}
|
||||
if ($this->CameraModel->save($this->request->data)) {
|
||||
$message = 'Saved';
|
||||
} else {
|
||||
$message = 'Error';
|
||||
}
|
||||
|
||||
$this->set(array(
|
||||
'message' => $message,
|
||||
'_serialize' => array('message')
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* delete method
|
||||
*
|
||||
* @throws NotFoundException
|
||||
* @param string $id
|
||||
* @return void
|
||||
*/
|
||||
public function delete($id = null) {
|
||||
global $user;
|
||||
$canEdit = (!$user) || ($user['System'] == 'Edit');
|
||||
if (!$canEdit) {
|
||||
throw new UnauthorizedException(__('Insufficient privileges'));
|
||||
return;
|
||||
}
|
||||
|
||||
$this->CameraModel->id = $id;
|
||||
if (!$this->CameraModel->exists()) {
|
||||
throw new NotFoundException(__('Invalid model'));
|
||||
}
|
||||
$this->request->allowMethod('post', 'delete');
|
||||
|
||||
if ($this->CameraModel->delete()) {
|
||||
return $this->flash(__('The model has been deleted.'), array('action' => 'index'));
|
||||
} else {
|
||||
return $this->flash(__('The model could not be deleted. Please, try again.'), array('action' => 'index'));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
<?php
|
||||
App::uses('AppController', 'Controller');
|
||||
/**
|
||||
* Manufacturers Controller
|
||||
*
|
||||
* @property Manufacturer $Manufacturer
|
||||
* @property PaginatorComponent $Paginator
|
||||
*/
|
||||
class ManufacturersController extends AppController {
|
||||
|
||||
/**
|
||||
* Components
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $components = array('Paginator', 'RequestHandler');
|
||||
|
||||
public function beforeFilter() {
|
||||
parent::beforeFilter();
|
||||
/*
|
||||
* A user needs the manufacturer data to calculate how to view a monitor, and there really isn't anything sensitive in this data.
|
||||
* So it has been decided for now to just let everyone read it.
|
||||
|
||||
global $user;
|
||||
$canView = (!$user) || ($user['System'] != 'None');
|
||||
if ( !$canView ) {
|
||||
throw new UnauthorizedException(__('Insufficient Privileges'));
|
||||
return;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* index method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function index() {
|
||||
$this->Manufacturer->recursive = 0;
|
||||
|
||||
$options = '';
|
||||
$manufacturers = $this->Manufacturer->find('all', $options);
|
||||
$this->set(array(
|
||||
'manufacturers' => $manufacturers,
|
||||
'_serialize' => array('manufacturers')
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* view method
|
||||
*
|
||||
* @throws NotFoundException
|
||||
* @param string $id
|
||||
* @return void
|
||||
*/
|
||||
public function view($id = null) {
|
||||
$this->Manufacturer->recursive = 0;
|
||||
if ( !$this->Manufacturer->exists($id) ) {
|
||||
throw new NotFoundException(__('Invalid manufacturer'));
|
||||
}
|
||||
$restricted = '';
|
||||
|
||||
$options = array('conditions' => array(
|
||||
array('Manufacturer.'.$this->Manufacturer->primaryKey => $id),
|
||||
$restricted
|
||||
)
|
||||
);
|
||||
$manufacturer = $this->Manufacturer->find('first', $options);
|
||||
$this->set(array(
|
||||
'manufacturer' => $manufacturer,
|
||||
'_serialize' => array('manufacturer')
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* add method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add() {
|
||||
if ( $this->request->is('post') ) {
|
||||
|
||||
global $user;
|
||||
$canEdit = (!$user) || ($user['System'] == 'Edit');
|
||||
if ( !$canEdit ) {
|
||||
throw new UnauthorizedException(__('Insufficient privileges'));
|
||||
return;
|
||||
}
|
||||
|
||||
$this->Manufacturer->create();
|
||||
if ( $this->Manufacturer->save($this->request->data) ) {
|
||||
# Might be nice to send it a start request
|
||||
#$this->daemonControl($this->Manufacturer->id, 'start', $this->request->data);
|
||||
return $this->flash(__('The manufacturer has been saved.'), array('action' => 'index'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* edit method
|
||||
*
|
||||
* @throws NotFoundException
|
||||
* @param string $id
|
||||
* @return void
|
||||
*/
|
||||
public function edit($id = null) {
|
||||
$this->Manufacturer->id = $id;
|
||||
|
||||
global $user;
|
||||
$canEdit = (!$user) || ($user['System'] == 'Edit');
|
||||
if ( !$canEdit ) {
|
||||
throw new UnauthorizedException(__('Insufficient privileges'));
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !$this->Manufacturer->exists($id) ) {
|
||||
throw new NotFoundException(__('Invalid manufacturer'));
|
||||
}
|
||||
if ( $this->Manufacturer->save($this->request->data) ) {
|
||||
$message = 'Saved';
|
||||
} else {
|
||||
$message = 'Error';
|
||||
}
|
||||
|
||||
$this->set(array(
|
||||
'message' => $message,
|
||||
'_serialize' => array('message')
|
||||
));
|
||||
// - restart this manufacturer after change
|
||||
#$this->daemonControl($this->Manufacturer->id, 'restart', $this->request->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* delete method
|
||||
*
|
||||
* @throws NotFoundException
|
||||
* @param string $id
|
||||
* @return void
|
||||
*/
|
||||
public function delete($id = null) {
|
||||
global $user;
|
||||
$canEdit = (!$user) || ($user['System'] == 'Edit');
|
||||
if ( !$canEdit ) {
|
||||
throw new UnauthorizedException(__('Insufficient privileges'));
|
||||
return;
|
||||
}
|
||||
|
||||
$this->Manufacturer->id = $id;
|
||||
if ( !$this->Manufacturer->exists() ) {
|
||||
throw new NotFoundException(__('Invalid manufacturer'));
|
||||
}
|
||||
$this->request->allowMethod('post', 'delete');
|
||||
|
||||
#$this->daemonControl($this->Manufacturer->id, 'stop');
|
||||
|
||||
if ( $this->Manufacturer->delete() ) {
|
||||
return $this->flash(__('The manufacturer has been deleted.'), array('action' => 'index'));
|
||||
} else {
|
||||
return $this->flash(__('The manufacturer could not be deleted. Please, try again.'), array('action' => 'index'));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -89,8 +89,6 @@ class ServersController extends AppController {
|
|||
|
||||
$this->Server->create();
|
||||
if ( $this->Server->save($this->request->data) ) {
|
||||
# Might be nice to send it a start request
|
||||
#$this->daemonControl($this->Server->id, 'start', $this->request->data);
|
||||
return $this->flash(__('The server has been saved.'), array('action' => 'index'));
|
||||
}
|
||||
}
|
||||
|
@ -126,8 +124,6 @@ class ServersController extends AppController {
|
|||
'message' => $message,
|
||||
'_serialize' => array('message')
|
||||
));
|
||||
// - restart this server after change
|
||||
#$this->daemonControl($this->Server->id, 'restart', $this->request->data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -151,8 +147,6 @@ class ServersController extends AppController {
|
|||
}
|
||||
$this->request->allowMethod('post', 'delete');
|
||||
|
||||
#$this->daemonControl($this->Server->id, 'stop');
|
||||
|
||||
if ( $this->Server->delete() ) {
|
||||
return $this->flash(__('The server has been deleted.'), array('action' => 'index'));
|
||||
} else {
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
App::uses('AppModel', 'CameraModel');
|
||||
/**
|
||||
* Model CameraModel
|
||||
*
|
||||
* @property Name $Name
|
||||
* @property ManufacturerId $ManufacturerId
|
||||
*/
|
||||
class CameraModel extends AppModel {
|
||||
|
||||
/**
|
||||
* Use table
|
||||
*
|
||||
* @var mixed False or table name
|
||||
*/
|
||||
public $useTable = 'Models';
|
||||
|
||||
/**
|
||||
* Primary key field
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $primaryKey = 'Id';
|
||||
|
||||
/**
|
||||
* Display field
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $displayField = 'Name';
|
||||
|
||||
public $recursive = -1;
|
||||
|
||||
/**
|
||||
* Validation rules
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $validate = array(
|
||||
'Name' => array(
|
||||
'notBlank' => array(
|
||||
'rule' => array('notBlank'))),
|
||||
'Id' => array(
|
||||
'numeric' => array(
|
||||
'rule' => array('numeric'),
|
||||
//'message' => 'Your custom message here',
|
||||
//'allowEmpty' => false,
|
||||
//'required' => false,
|
||||
//'last' => false, // Stop validation after this rule
|
||||
//'on' => 'create', // Limit validation to 'create' or 'update' operations
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
//The Associations below have been created with all possible keys, those that are not needed can be removed
|
||||
|
||||
/**
|
||||
* hasMany associations
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $hasOne = array(
|
||||
'Manufacturer' => array(
|
||||
'className' => 'Manufacturer',
|
||||
'joinTable' => 'Manufacturers',
|
||||
'foreignKey' => 'Id',
|
||||
),
|
||||
);
|
||||
//var $actsAs = array( 'Containable' );
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
App::uses('AppModel', 'Model');
|
||||
/**
|
||||
* Manufacturer Model
|
||||
*
|
||||
* @property Event $Event
|
||||
* @property Zone $Zone
|
||||
*/
|
||||
class Manufacturer extends AppModel {
|
||||
|
||||
/**
|
||||
* Use table
|
||||
*
|
||||
* @var mixed False or table name
|
||||
*/
|
||||
public $useTable = 'Manufacturers';
|
||||
|
||||
/**
|
||||
* Primary key field
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $primaryKey = 'Id';
|
||||
|
||||
/**
|
||||
* Display field
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $displayField = 'Name';
|
||||
|
||||
public $recursive = -1;
|
||||
|
||||
/**
|
||||
* Validation rules
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $validate = array(
|
||||
'Id' => array(
|
||||
'numeric' => array(
|
||||
'rule' => array('numeric'),
|
||||
//'message' => 'Your custom message here',
|
||||
//'allowEmpty' => false,
|
||||
//'required' => false,
|
||||
//'last' => false, // Stop validation after this rule
|
||||
//'on' => 'create', // Limit validation to 'create' or 'update' operations
|
||||
),
|
||||
),
|
||||
'Name' => array(
|
||||
'notBlank' => array(
|
||||
'rule' => array('notBlank'))),
|
||||
);
|
||||
|
||||
//The Associations below have been created with all possible keys, those that are not needed can be removed
|
||||
|
||||
/**
|
||||
* hasMany associations
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $hasMany = array(
|
||||
'Model' => array(
|
||||
'className' => 'Model',
|
||||
'foreignKey' => 'ManufacturerId',
|
||||
'dependent' => false,
|
||||
'conditions' => '',
|
||||
'fields' => '',
|
||||
'order' => '',
|
||||
'limit' => '',
|
||||
'offset' => '',
|
||||
'exclusive' => '',
|
||||
'finderQuery' => '',
|
||||
'counterQuery' => ''
|
||||
)
|
||||
);
|
||||
}
|
|
@ -139,6 +139,16 @@ class Monitor extends AppModel {
|
|||
'className' => 'Event_Summary',
|
||||
'foreignKey' => 'MonitorId',
|
||||
'joinTable' => 'Event_Summaries',
|
||||
),
|
||||
'Manufacturer' => array(
|
||||
'className' => 'Manufacturer',
|
||||
'foreignKey' => 'Id',
|
||||
'joinTable' => 'Manufacturers',
|
||||
),
|
||||
'CameraModel' => array(
|
||||
'className' => 'CameraModel',
|
||||
'foreignKey' => 'Id',
|
||||
'joinTable' => 'Models',
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
echo json_encode($message);
|
||||
echo json_encode($manufacturer);
|
|
@ -0,0 +1 @@
|
|||
echo json_encode($manufacturers);
|
|
@ -0,0 +1 @@
|
|||
echo json_encode($manufacturer);
|
|
@ -0,0 +1,2 @@
|
|||
$xml = Xml::fromArray(array('response' => $message));
|
||||
echo $xml->asXML();
|
|
@ -0,0 +1,2 @@
|
|||
$xml = Xml::fromArray(array('response' => $servers));
|
||||
echo $xml->asXML();
|
|
@ -0,0 +1,2 @@
|
|||
$xml = Xml::fromArray(array('response' => $server));
|
||||
echo $xml->asXML();
|
|
@ -650,6 +650,23 @@ class Event extends ZM_Object {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
function canEdit($u=null) {
|
||||
global $user;
|
||||
if (!$u) $u=$user;
|
||||
if (!$u) {
|
||||
# auth turned on and not logged in
|
||||
return false;
|
||||
}
|
||||
if (!empty($u['MonitorIds']) ) {
|
||||
if (!in_array($this->{'MonitorId'}, explode(',', $u['MonitorIds']))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ($u['Events'] != 'Edit') {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} # end class
|
||||
|
||||
?>
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
namespace ZM;
|
||||
require_once('database.php');
|
||||
require_once('Object.php');
|
||||
|
||||
|
||||
class Manufacturer extends ZM_Object {
|
||||
protected static $table = 'Manufacturers';
|
||||
|
||||
protected $defaults = array(
|
||||
'Id' => null,
|
||||
'Name' => '',
|
||||
);
|
||||
|
||||
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 Manufacturer
|
||||
?>
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
namespace ZM;
|
||||
require_once('database.php');
|
||||
require_once('Object.php');
|
||||
|
||||
class Model extends ZM_Object {
|
||||
protected static $table = 'Models';
|
||||
|
||||
protected $defaults = array(
|
||||
'Id' => null,
|
||||
'Name' => '',
|
||||
'ManufacturerId' => null,
|
||||
);
|
||||
|
||||
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 Model
|
||||
?>
|
|
@ -1,11 +1,13 @@
|
|||
<?php
|
||||
namespace ZM;
|
||||
require_once('database.php');
|
||||
require_once('Server.php');
|
||||
require_once('Object.php');
|
||||
require_once('Control.php');
|
||||
require_once('Storage.php');
|
||||
require_once('Group.php');
|
||||
require_once('Manufacturer.php');
|
||||
require_once('Model.php');
|
||||
require_once('Server.php');
|
||||
require_once('Storage.php');
|
||||
|
||||
$FunctionTypes = null;
|
||||
|
||||
|
@ -47,12 +49,16 @@ class Monitor extends ZM_Object {
|
|||
'Notes' => '',
|
||||
'ServerId' => 0,
|
||||
'StorageId' => 0,
|
||||
'ManufacturerId' => null,
|
||||
'ModelId' => null,
|
||||
'Type' => 'Ffmpeg',
|
||||
'Function' => 'Mocord',
|
||||
'Enabled' => array('type'=>'boolean','default'=>1),
|
||||
'DecodingEnabled' => array('type'=>'boolean','default'=>1),
|
||||
'LinkedMonitors' => array('type'=>'set', 'default'=>null),
|
||||
'Triggers' => array('type'=>'set','default'=>''),
|
||||
'EventStartCommand' => '',
|
||||
'EventEndCommand' => '',
|
||||
'ONVIF_URL' => '',
|
||||
'ONVIF_Username' => '',
|
||||
'ONVIF_Password' => '',
|
||||
|
@ -495,6 +501,10 @@ class Monitor extends ZM_Object {
|
|||
return $this->Server()->UrlToIndex($port);
|
||||
}
|
||||
|
||||
public function UrlToZMS($port=null) {
|
||||
return $this->Server()->UrlToZMS($port).'?mid='.$this->Id();
|
||||
}
|
||||
|
||||
public function sendControlCommand($command) {
|
||||
// command is generally a command option list like --command=blah but might be just the word quit
|
||||
|
||||
|
@ -682,5 +692,29 @@ class Monitor extends ZM_Object {
|
|||
function DisableAlarms() {
|
||||
$output = $this->AlarmCommand('disable');
|
||||
}
|
||||
function Model() {
|
||||
if (!property_exists($this, 'Model')) {
|
||||
if ($this->{'ModelId'}) {
|
||||
$this->{'Model'} = Model::find_one(array('Id'=>$this->ModelId()));
|
||||
if (!$this->{'Model'})
|
||||
$this->{'Model'} = new Model();
|
||||
} else {
|
||||
$this->{'Model'} = new Model();
|
||||
}
|
||||
}
|
||||
return $this->{'Model'};
|
||||
}
|
||||
function Manufacturer() {
|
||||
if (!property_exists($this, 'Manufacturer')) {
|
||||
if ($this->{'ManufacturerId'}) {
|
||||
$this->{'Manufacturer'} = Manufacturer::find_one(array('Id'=>$this->ManufacturerId()));
|
||||
if (!$this->{'Manufacturer'})
|
||||
$this->{'Manufacturer'} = new Manufacturer();
|
||||
} else {
|
||||
$this->{'Manufacturer'} = new Manufacturer();
|
||||
}
|
||||
}
|
||||
return $this->{'Manufacturer'};
|
||||
}
|
||||
} // end class Monitor
|
||||
?>
|
||||
|
|
|
@ -24,6 +24,8 @@ if ( !canEdit('Monitors') ) {
|
|||
return;
|
||||
}
|
||||
|
||||
global $error_message;
|
||||
|
||||
if ($action == 'save') {
|
||||
$mid = 0;
|
||||
if (!empty($_REQUEST['mid'])) {
|
||||
|
@ -46,6 +48,37 @@ if ( $action == 'save' ) {
|
|||
}
|
||||
}
|
||||
|
||||
# For convenience
|
||||
$newMonitor = $_REQUEST['newMonitor'];
|
||||
ZM\Debug("newMonitor: ". print_r($newMonitor, true));
|
||||
|
||||
if (!$newMonitor['ManufacturerId'] and ($newMonitor['Manufacturer'] != '')) {
|
||||
# Need to add a new Manufacturer entry
|
||||
$newManufacturer = ZM\Manufacturer::find_one(array('Name'=>$newMonitor['Manufacturer']));
|
||||
if (!$newManufacturer) {
|
||||
$newManufacturer = new ZM\Manufacturer();
|
||||
if (!$newManufacturer->save(array('Name'=>$newMonitor['Manufacturer']))) {
|
||||
$error_message .= "Error saving new Manufacturer: " . $newManufacturer->get_last_error().'</br>';
|
||||
}
|
||||
}
|
||||
$newMonitor['ManufacturerId'] = $newManufacturer->Id();
|
||||
}
|
||||
|
||||
if (!$newMonitor['ModelId'] and ($newMonitor['Model'] != '')) {
|
||||
# Need to add a new Model entry
|
||||
$newModel = ZM\Model::find_one(array('Name'=>$newMonitor['Model']));
|
||||
if (!$newModel) {
|
||||
$newModel = new ZM\Model();
|
||||
if (!$newModel->save(array(
|
||||
'Name'=>$newMonitor['Model'],
|
||||
'ManufacturerId'=>$newMonitor['ManufacturerId']
|
||||
))) {
|
||||
$error_message .= "Error saving new Model: " . $newModel->get_last_error().'</br>';
|
||||
}
|
||||
}
|
||||
$newMonitor['ModelId'] = $newModel->Id();
|
||||
}
|
||||
|
||||
$monitor = new ZM\Monitor($mid);
|
||||
|
||||
// Define a field type for anything that's not simple text equivalent
|
||||
|
@ -69,22 +102,24 @@ if ( $action == 'save' ) {
|
|||
# Checkboxes don't return an element in the POST data, so won't be present in newMonitor.
|
||||
# So force a value for these fields
|
||||
foreach ($types as $field => $value) {
|
||||
if ( ! isset($_REQUEST['newMonitor'][$field] ) ) {
|
||||
$_REQUEST['newMonitor'][$field] = $value;
|
||||
if (!isset($newMonitor[$field])) {
|
||||
$newMonitor[$field] = $value;
|
||||
}
|
||||
} # end foreach type
|
||||
|
||||
if ( $_REQUEST['newMonitor']['ServerId'] == 'auto' ) {
|
||||
$_REQUEST['newMonitor']['ServerId'] = dbFetchOne(
|
||||
if ($newMonitor['ServerId'] == 'auto') {
|
||||
$newMonitor['ServerId'] = dbFetchOne(
|
||||
'SELECT Id FROM Servers WHERE Status=\'Running\' ORDER BY FreeMem DESC, CpuLoad ASC LIMIT 1', 'Id');
|
||||
ZM\Debug('Auto selecting server: Got ' . $_REQUEST['newMonitor']['ServerId']);
|
||||
if ( ( !$_REQUEST['newMonitor'] ) and defined('ZM_SERVER_ID') ) {
|
||||
$_REQUEST['newMonitor']['ServerId'] = ZM_SERVER_ID;
|
||||
ZM\Debug('Auto selecting server: Got ' . $newMonitor['ServerId']);
|
||||
if ((!$newMonitor['ServerId']) and defined('ZM_SERVER_ID')) {
|
||||
$newMonitor['ServerId'] = ZM_SERVER_ID;
|
||||
ZM\Debug('Auto selecting server to ' . ZM_SERVER_ID);
|
||||
}
|
||||
}
|
||||
|
||||
$changes = $monitor->changes($_REQUEST['newMonitor']);
|
||||
ZM\Debug("newMonitor: ". print_r($newMonitor, true));
|
||||
$changes = $monitor->changes($newMonitor);
|
||||
ZM\Debug("Changes: ". print_r($changes, true));
|
||||
$restart = false;
|
||||
|
||||
if (count($changes)) {
|
||||
|
@ -104,7 +139,6 @@ if ( $action == 'save' ) {
|
|||
$oldH = $monitor->Height();
|
||||
|
||||
if ($monitor->save($changes)) {
|
||||
|
||||
// Groups will be added below
|
||||
if ( isset($changes['Name']) or isset($changes['StorageId']) ) {
|
||||
// creating symlinks when symlink already exists reports errors, but is perfectly ok
|
||||
|
@ -115,13 +149,13 @@ if ( $action == 'save' ) {
|
|||
if (file_exists($OldStorage->Path().'/'.$saferOldName))
|
||||
unlink($OldStorage->Path().'/'.$saferOldName);
|
||||
|
||||
$NewStorage = new ZM\Storage($_REQUEST['newMonitor']['StorageId']);
|
||||
$NewStorage = new ZM\Storage($newMonitor['StorageId']);
|
||||
if (!file_exists($NewStorage->Path().'/'.$mid)) {
|
||||
if (!mkdir($NewStorage->Path().'/'.$mid, 0755)) {
|
||||
ZM\Error('Unable to mkdir '.$NewStorage->Path().'/'.$mid);
|
||||
}
|
||||
}
|
||||
$saferNewName = basename($_REQUEST['newMonitor']['Name']);
|
||||
$saferNewName = basename($newMonitor['Name']);
|
||||
$link_path = $NewStorage->Path().'/'.$saferNewName;
|
||||
// Use a relative path for the target so the link continues to work from backups or directory changes.
|
||||
if (!symlink($mid, $link_path)) {
|
||||
|
@ -132,8 +166,8 @@ if ( $action == 'save' ) {
|
|||
} // end if Name or Storage Area Change
|
||||
|
||||
if (isset($changes['Width']) || isset($changes['Height'])) {
|
||||
$newW = $_REQUEST['newMonitor']['Width'];
|
||||
$newH = $_REQUEST['newMonitor']['Height'];
|
||||
$newW = $newMonitor['Width'];
|
||||
$newH = $newMonitor['Height'];
|
||||
|
||||
$zones = dbFetchAll('SELECT * FROM Zones WHERE MonitorId=?', NULL, array($mid));
|
||||
|
||||
|
@ -204,8 +238,7 @@ if ( $action == 'save' ) {
|
|||
} // end if rotation or just size change
|
||||
} // end if changes in width or height
|
||||
} else {
|
||||
global $error_message;
|
||||
$error_message = dbError('unknown');
|
||||
$error_message .= $monitor->get_last_error();
|
||||
} // end if successful save
|
||||
$restart = true;
|
||||
} else { // new monitor
|
||||
|
@ -217,14 +250,27 @@ if ( $action == 'save' ) {
|
|||
|
||||
if ( $monitor->insert($changes) ) {
|
||||
$mid = $monitor->Id();
|
||||
$zoneArea = $_REQUEST['newMonitor']['Width'] * $_REQUEST['newMonitor']['Height'];
|
||||
dbQuery("INSERT INTO Zones SET MonitorId = ?, Name = 'All', Type = 'Active', Units = 'Percent', NumCoords = 4, Coords = ?, Area=?, AlarmRGB = 0xff0000, CheckMethod = 'Blobs', MinPixelThreshold = 25, MinAlarmPixels=?, MaxAlarmPixels=?, FilterX = 3, FilterY = 3, MinFilterPixels=?, MaxFilterPixels=?, MinBlobPixels=?, MinBlobs = 1", array( $mid, sprintf( "%d,%d %d,%d %d,%d %d,%d", 0, 0, $_REQUEST['newMonitor']['Width']-1, 0, $_REQUEST['newMonitor']['Width']-1, $_REQUEST['newMonitor']['Height']-1, 0, $_REQUEST['newMonitor']['Height']-1 ), $zoneArea, intval(($zoneArea*3)/100), intval(($zoneArea*75)/100), intval(($zoneArea*3)/100), intval(($zoneArea*75)/100), intval(($zoneArea*2)/100) ) );
|
||||
//$view = 'none';
|
||||
$zoneArea = $newMonitor['Width'] * $newMonitor['Height'];
|
||||
dbQuery("INSERT INTO Zones SET MonitorId = ?, Name = 'All', Type = 'Active', Units = 'Percent', NumCoords = 4, Coords = ?, Area=?, AlarmRGB = 0xff0000, CheckMethod = 'Blobs', MinPixelThreshold = 25, MinAlarmPixels=?, MaxAlarmPixels=?, FilterX = 3, FilterY = 3, MinFilterPixels=?, MaxFilterPixels=?, MinBlobPixels=?, MinBlobs = 1", array( $mid,
|
||||
sprintf( '%d,%d %d,%d %d,%d %d,%d', 0, 0,
|
||||
$newMonitor['Width']-1,
|
||||
0,
|
||||
$newMonitor['Width']-1,
|
||||
$newMonitor['Height']-1,
|
||||
0,
|
||||
$newMonitor['Height']-1),
|
||||
$zoneArea,
|
||||
intval(($zoneArea*3)/100),
|
||||
intval(($zoneArea*75)/100),
|
||||
intval(($zoneArea*3)/100),
|
||||
intval(($zoneArea*75)/100),
|
||||
intval(($zoneArea*2)/100)
|
||||
));
|
||||
$Storage = $monitor->Storage();
|
||||
|
||||
error_reporting(0);
|
||||
mkdir($Storage->Path().'/'.$mid, 0755);
|
||||
$saferName = basename($_REQUEST['newMonitor']['Name']);
|
||||
$saferName = basename($newMonitor['Name']);
|
||||
symlink($mid, $Storage->Path().'/'.$saferName);
|
||||
|
||||
} else {
|
||||
|
|
|
@ -28,14 +28,17 @@ if ( $action == 'save' ) {
|
|||
foreach ($_REQUEST['mids'] as $mid) {
|
||||
$mid = ValidInt($mid);
|
||||
if (!canEdit('Monitors', $mid)) {
|
||||
ZM\Warning("Cannot edit monitor $mid");
|
||||
ZM\Warning('Cannot edit monitor '.$mid);
|
||||
continue;
|
||||
}
|
||||
$Monitor = new ZM\Monitor($mid);
|
||||
if ($Monitor->Type() != 'WebSite') {
|
||||
$Monitor->zmcControl('stop');
|
||||
}
|
||||
$Monitor->save($_REQUEST['newMonitor']);
|
||||
if (!$Monitor->save($_REQUEST['newMonitor'])) {
|
||||
global $error_message;
|
||||
$error_message .= 'Error saving monitor: ' . $Monitor->get_last_error().'<br/>';
|
||||
}
|
||||
if ($Monitor->Function() != 'None' && $Monitor->Type() != 'WebSite') {
|
||||
$Monitor->zmcControl('start');
|
||||
}
|
||||
|
|
|
@ -3,8 +3,10 @@ function MonitorStream(monitorData) {
|
|||
this.id = monitorData.id;
|
||||
this.connKey = monitorData.connKey;
|
||||
this.url = monitorData.url;
|
||||
this.url_to_zms = monitorData.url_to_zms;
|
||||
this.width = monitorData.width;
|
||||
this.height = monitorData.height;
|
||||
this.scale = 100;
|
||||
this.status = null;
|
||||
this.alarmState = STATE_IDLE;
|
||||
this.lastAlarmState = STATE_IDLE;
|
||||
|
@ -15,18 +17,67 @@ function MonitorStream(monitorData) {
|
|||
};
|
||||
this.type = monitorData.type;
|
||||
this.refresh = monitorData.refresh;
|
||||
this.element = null;
|
||||
this.getElement = function() {
|
||||
if (this.element) return this.element;
|
||||
this.element = document.getElementById('liveStream'+this.id);
|
||||
if (!this.element) {
|
||||
console.error("No img for #liveStream"+this.id);
|
||||
}
|
||||
return this.element;
|
||||
};
|
||||
|
||||
/* if the img element didn't have a src, this would fill it in, causing it to show. */
|
||||
this.show = function() {
|
||||
const stream = this.getElement();
|
||||
if (!stream.src) {
|
||||
stream.src = this.url_to_zms+"&mode=single&scale=100&connkey="+this.connKey;
|
||||
}
|
||||
};
|
||||
|
||||
this.setScale = function(newscale) {
|
||||
const img = this.getElement();
|
||||
if (!img) return;
|
||||
|
||||
this.scale = newscale;
|
||||
|
||||
const oldSrc = img.getAttribute('src');
|
||||
let newSrc = '';
|
||||
|
||||
img.setAttribute('src', '');
|
||||
console.log("Scaling to: " + newscale);
|
||||
|
||||
if (newscale == '0' || newscale == 'auto') {
|
||||
let bottomElement = document.getElementById('replayStatus');
|
||||
if (!bottomElement) {
|
||||
bottomElement = document.getElementById('monitorState');
|
||||
}
|
||||
var newSize = scaleToFit(this.width, this.height, $j(img), $j(bottomElement));
|
||||
|
||||
console.log(newSize);
|
||||
newWidth = newSize.width;
|
||||
newHeight = newSize.height;
|
||||
autoScale = parseInt(newSize.autoScale);
|
||||
// This is so that we don't waste bandwidth and let the browser do all the scaling.
|
||||
if (autoScale > 100) autoScale = 100;
|
||||
if (autoScale) {
|
||||
newSrc = oldSrc.replace(/scale=\d+/i, 'scale='+autoScale);
|
||||
}
|
||||
} else {
|
||||
newWidth = this.width * newscale / SCALE_BASE;
|
||||
newHeight = this.height * newscale / SCALE_BASE;
|
||||
img.width(newWidth);
|
||||
img.height(newHeight);
|
||||
if (newscale > 100) newscale = 100;
|
||||
newSrc = oldSrc.replace(/scale=\d+/i, 'scale='+newscale);
|
||||
}
|
||||
img.setAttribute('src', newSrc);
|
||||
};
|
||||
this.start = function(delay) {
|
||||
// Step 1 make sure we are streaming instead of a static image
|
||||
var stream = $j('#liveStream'+this.id);
|
||||
if (!stream.length) {
|
||||
console.log('No live stream');
|
||||
return;
|
||||
}
|
||||
stream = stream[0];
|
||||
if ( !stream ) {
|
||||
console.log('No live stream');
|
||||
return;
|
||||
}
|
||||
const stream = this.getElement();
|
||||
if (!stream) return;
|
||||
|
||||
if (!stream.src) {
|
||||
// Website Monitors won't have an img tag
|
||||
console.log('No src for #liveStream'+this.id);
|
||||
|
@ -38,7 +89,7 @@ function MonitorStream(monitorData) {
|
|||
src += '&connkey='+this.connKey;
|
||||
}
|
||||
if ( stream.src != src ) {
|
||||
console.log("Setting to streaming");
|
||||
console.log("Setting to streaming: " + src);
|
||||
stream.src = '';
|
||||
stream.src = src;
|
||||
}
|
||||
|
|
|
@ -663,8 +663,33 @@ $SLANG = array(
|
|||
'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.',
|
||||
'PrivacyTelemetry' => 'Telemetry',
|
||||
'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are out there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.',
|
||||
'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:<ul><li>A unique identifier (UUID) <li>City based location is gathered by querying <a href="https://ipinfo.io/geo">ipinfo.io</a>. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!<li>Current time<li>Total number of monitors<li>Total number of events<li>System architecture<li>Operating system kernel, distro, and distro version<li>Version of ZoneMinder<li>Total amount of memory<li>Number of cpu cores</ul>',
|
||||
'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:<ul><li>Id<li>Name<li>Type<li>Function<li>Width<li>Height<li>Colours<li>MaxFPS<li>AlarmMaxFPS</ul>',
|
||||
'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
|
||||
<ul>
|
||||
<li>A unique identifier (UUID)</li>
|
||||
<li>City based location is gathered by querying <a href="https://ipinfo.io/geo">ipinfo.io</a>. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!</li>
|
||||
<li>Current time</li>
|
||||
<li>Total number of monitors</li>
|
||||
<li>Total number of events</li>
|
||||
<li>System architecture</li>
|
||||
<li>Operating system kernel, distro, and distro version</li>
|
||||
<li>Version of ZoneMinder</li>
|
||||
<li>Total amount of memory</li>
|
||||
<li>Number of cpu cores</li>
|
||||
</ul>',
|
||||
'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
|
||||
<ul>
|
||||
<li>Id</li>
|
||||
<li>Name</li>
|
||||
<li>Manufacturer</li>
|
||||
<li>Model</li>
|
||||
<li>Type</li>
|
||||
<li>Function</li>
|
||||
<li>Width</li>
|
||||
<li>Height</li>
|
||||
<li>Colours</li>
|
||||
<li>MaxFPS</li>
|
||||
<li>AlarmMaxFPS</li>
|
||||
</ul>',
|
||||
'PrivacyConclusionText' => 'We are <u>NOT</u> collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.',
|
||||
'Probe' => 'Probe',
|
||||
'ProfileProbe' => 'Stream Probe',
|
||||
|
|
|
@ -786,7 +786,7 @@ function exportFileList(
|
|||
}
|
||||
closedir($dir);
|
||||
}
|
||||
ZM\Debug(print_r($files, true));
|
||||
ZM\Debug('All available files: '.print_r($files, true));
|
||||
|
||||
$exportFileList = array();
|
||||
|
||||
|
@ -843,6 +843,18 @@ function exportFileList(
|
|||
ZM\Debug('Not including frame images');
|
||||
} # end if exportImages
|
||||
|
||||
if ($exportVideo) {
|
||||
$filesLeft = array();
|
||||
foreach ($files as $file) {
|
||||
if (preg_match('/\.(?:mpg|mpeg|mov|swf|mp4|mkv|avi|asf|3gp)$/', $file)) {
|
||||
$exportFileList[$file] = $file;
|
||||
} else {
|
||||
$filesLeft[$file] = $file;
|
||||
}
|
||||
}
|
||||
$files = $filesLeft;
|
||||
}
|
||||
|
||||
if ($exportMisc) {
|
||||
foreach ($files as $file) {
|
||||
$exportFileList[$file] = $file;
|
||||
|
|
|
@ -584,10 +584,21 @@ function scaleToFit(baseWidth, baseHeight, scaleEl, bottomEl) {
|
|||
$j(window).on('resize', endOfResize); //set delayed scaling when Scale to Fit is selected
|
||||
var ratio = baseWidth / baseHeight;
|
||||
var container = $j('#content');
|
||||
if (!container) {
|
||||
console.error("No container found");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bottomEl || !bottomEl.length) {
|
||||
bottomEl = $j(container[0].lastElementChild);
|
||||
}
|
||||
//console.log(bottomEl);
|
||||
var viewPort = $j(window);
|
||||
// jquery does not provide a bottom offet, and offset dows not include margins. outerHeight true minus false gives total vertical margins.
|
||||
// jquery does not provide a bottom offset, and offset does not include margins. outerHeight true minus false gives total vertical margins.
|
||||
var bottomLoc = bottomEl.offset().top + (bottomEl.outerHeight(true) - bottomEl.outerHeight()) + bottomEl.outerHeight(true);
|
||||
//console.log("bottomLoc: " + bottomEl.offset().top + " + (" + bottomEl.outerHeight(true) + ' - ' + bottomEl.outerHeight() +') + '+bottomEl.outerHeight(true));
|
||||
var newHeight = viewPort.height() - (bottomLoc - scaleEl.outerHeight(true));
|
||||
//console.log("newHeight = " + viewPort.height() +" - " + bottomLoc + ' - ' + scaleEl.outerHeight(true));
|
||||
var newWidth = ratio * newHeight;
|
||||
if (newWidth > container.innerWidth()) {
|
||||
newWidth = container.innerWidth();
|
||||
|
@ -598,13 +609,15 @@ function scaleToFit(baseWidth, baseHeight, scaleEl, bottomEl) {
|
|||
return parseInt($j(this).val());
|
||||
}).get();
|
||||
scales.shift();
|
||||
var closest;
|
||||
var closest = null;
|
||||
$j(scales).each(function() { //Set zms scale to nearest regular scale. Zoom does not like arbitrary scale values.
|
||||
if (closest == null || Math.abs(this - autoScale) < Math.abs(closest - autoScale)) {
|
||||
closest = this.valueOf();
|
||||
}
|
||||
});
|
||||
if (closest) {
|
||||
autoScale = closest;
|
||||
}
|
||||
return {width: Math.floor(newWidth), height: Math.floor(newHeight), autoScale: autoScale};
|
||||
}
|
||||
|
||||
|
@ -947,3 +960,29 @@ function initThumbAnimation() {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
/* View in fullscreen */
|
||||
function openFullscreen(elem) {
|
||||
if (elem.requestFullscreen) {
|
||||
elem.requestFullscreen();
|
||||
} else if (elem.webkitRequestFullscreen) {
|
||||
/* Safari */
|
||||
elem.webkitRequestFullscreen();
|
||||
} else if (elem.msRequestFullscreen) {
|
||||
/* IE11 */
|
||||
elem.msRequestFullscreen();
|
||||
}
|
||||
}
|
||||
|
||||
/* Close fullscreen */
|
||||
function closeFullscreen() {
|
||||
if (document.exitFullscreen) {
|
||||
document.exitFullscreen();
|
||||
} else if (document.webkitExitFullscreen) {
|
||||
/* Safari */
|
||||
document.webkitExitFullscreen();
|
||||
} else if (document.msExitFullscreen) {
|
||||
/* IE11 */
|
||||
document.msExitFullscreen();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ foreach ( $perms as $perm ) {
|
|||
?>
|
||||
|
||||
var ANIMATE_THUMBS = <?php echo ZM_WEB_ANIMATE_THUMBS?'true':'false' ?>;
|
||||
var SCALE_BASE = <?php echo SCALE_BASE ?>;
|
||||
|
||||
var refreshParent = <?php
|
||||
if ( ! empty($refreshParent) ) {
|
||||
|
|
|
@ -178,7 +178,6 @@ $html .= '</span>
|
|||
' .
|
||||
( count($conditions) ? ' WHERE ' . implode(' AND ', $conditions) : '' ).' ORDER BY Sequence ASC';
|
||||
$monitors = dbFetchAll($sql, null, $values);
|
||||
ZM\Debug(print_r($monitors, true));
|
||||
$displayMonitors = array();
|
||||
$monitors_dropdown = array();
|
||||
|
||||
|
|
|
@ -150,6 +150,7 @@ if ( $Event->Id() and !file_exists($Event->Path()) )
|
|||
<button id="editBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Edit') ?>" disabled><i class="fa fa-pencil"></i></button>
|
||||
<button id="exportBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Export') ?>"><i class="fa fa-external-link"></i></button>
|
||||
<a id="downloadBtn" class="btn btn-normal" href="<?php echo $Event->getStreamSrc(array('mode'=>'mp4'),'&')?>"
|
||||
title="<?php echo translate('Download'). ' ' . $Event->DefaultVideo() ?>"
|
||||
download
|
||||
<?php echo $Event->DefaultVideo() ? '' : 'style="display:none;"' ?>
|
||||
><i class="fa fa-download"></i></a>
|
||||
|
|
|
@ -152,7 +152,7 @@ $booleanValues = array(
|
|||
|
||||
$focusWindow = true;
|
||||
|
||||
$storageareas = array('' => 'All') + ZM\ZM_Object::Objects_Indexed_By_Id('ZM\Storage');
|
||||
$storageareas = array('' => array('Name'=>'NULL Unspecified'), '0' => array('Name'=>'Zero')) + ZM\ZM_Object::Objects_Indexed_By_Id('ZM\Storage');
|
||||
|
||||
$weekdays = array();
|
||||
for ( $i = 0; $i < 7; $i++ ) {
|
||||
|
|
|
@ -657,6 +657,7 @@ function getFrameResponse(respObj, respText) {
|
|||
|
||||
function frameQuery(eventId, frameId, loadImage) {
|
||||
var data = {};
|
||||
if (auth_hash) data.auth = auth_hash;
|
||||
data.loopback = loadImage;
|
||||
data.id = {eventId, frameId};
|
||||
|
||||
|
@ -772,8 +773,9 @@ function manageDelConfirmModalBtns() {
|
|||
return;
|
||||
}
|
||||
|
||||
pauseClicked();
|
||||
evt.preventDefault();
|
||||
$j.getJSON(thisUrl + '?request=event&task=delete&id='+eventData.Id)
|
||||
$j.getJSON(thisUrl + '?request=event&action=delete&id='+eventData.Id)
|
||||
.done(function(data) {
|
||||
$j('#deleteConfirm').modal('hide');
|
||||
streamNext(true);
|
||||
|
|
|
@ -41,6 +41,10 @@ function ajaxRequest(params) {
|
|||
}
|
||||
$j.getJSON(thisUrl + '?view=request&request=events&task=query'+filterQuery, params.data)
|
||||
.done(function(data) {
|
||||
if (data.result == 'Error') {
|
||||
alert(data.message);
|
||||
return;
|
||||
}
|
||||
var rows = processRows(data.rows);
|
||||
// rearrange the result into what bootstrap-table expects
|
||||
params.success({total: data.total, totalNotFiltered: data.totalNotFiltered, rows: rows});
|
||||
|
@ -59,13 +63,13 @@ function processRows(rows) {
|
|||
|
||||
row.Id = '<a href="?view=event&eid=' + eid + filterQuery + sortQuery + '&page=1">' + eid + '</a>';
|
||||
row.Name = '<a href="?view=event&eid=' + eid + filterQuery + sortQuery + '&page=1">' + row.Name + '</a>' +
|
||||
'<br/><div class="small text-nowrap text-muted">' + archived + emailed + '</div>';
|
||||
'<br/><div class="small text-muted">' + archived + emailed + '</div>';
|
||||
if ( canEdit.Monitors ) row.Monitor = '<a href="?view=event&eid=' + eid + '">' + row.Monitor + '</a>';
|
||||
if ( canEdit.Events ) row.Cause = '<a href="#" title="' + row.Notes + '" class="eDetailLink" data-eid="' + eid + '">' + row.Cause + '</a>';
|
||||
if ( row.Notes.indexOf('detected:') >= 0 ) {
|
||||
row.Cause = row.Cause + '<a href="#" class="objDetectLink" data-eid=' +eid+ '><div class="small text-nowrap text-muted"><u>' + row.Notes + '</u></div></div></a>';
|
||||
row.Cause = row.Cause + '<a href="#" class="objDetectLink" data-eid=' +eid+ '><div class="small text-muted"><u>' + row.Notes + '</u></div></div></a>';
|
||||
} else if ( row.Notes != 'Forced Web: ' ) {
|
||||
row.Cause = row.Cause + '<br/><div class="small text-nowrap text-muted">' + row.Notes + '</div>';
|
||||
row.Cause = row.Cause + '<br/><div class="small text-muted">' + row.Notes + '</div>';
|
||||
}
|
||||
row.Frames = '<a href="?view=frames&eid=' + eid + '">' + row.Frames + '</a>';
|
||||
row.AlarmFrames = '<a href="?view=frames&eid=' + eid + '">' + row.AlarmFrames + '</a>';
|
||||
|
|
|
@ -324,7 +324,6 @@ function update_estimated_ram_use() {
|
|||
var max_buffer_count = parseInt(document.querySelectorAll('input[name="newMonitor[MaxImageBufferCount]"]')[0].value);
|
||||
if (max_buffer_count) {
|
||||
var max_buffer_size = (min_buffer_count + max_buffer_count) * width * height * colours;
|
||||
console.log(max_buffer_size);
|
||||
document.getElementById('estimated_ram_use').innerHTML += ' Max: ' + human_filesize(max_buffer_size);
|
||||
} else {
|
||||
document.getElementById('estimated_ram_use').innerHTML += ' Max: Unlimited';
|
||||
|
@ -346,4 +345,85 @@ function getLocation() {
|
|||
}
|
||||
}
|
||||
|
||||
function populate_models(ManufacturerId) {
|
||||
const dropdown = $j('[name="newMonitor[ModelId]"]');
|
||||
if (!dropdown.length) {
|
||||
console.log("No element found for ModelId");
|
||||
return;
|
||||
}
|
||||
|
||||
dropdown.empty();
|
||||
dropdown.append('<option value="" selected="true">Unknown</option>');
|
||||
dropdown.prop('selectedIndex', 0);
|
||||
|
||||
if (ManufacturerId) {
|
||||
// Populate dropdown with list of provinces
|
||||
$j.getJSON(thisUrl+'?request=models&ManufacturerId='+ManufacturerId, function(data) {
|
||||
if (data.result == 'Ok') {
|
||||
$j.each(data.models, function(key, entry) {
|
||||
dropdown.append($j('<option></option>').attr('value', entry.Id).text(entry.Name));
|
||||
});
|
||||
dropdown.chosen("destroy");
|
||||
dropdown.chosen();
|
||||
} else {
|
||||
alert(data.result);
|
||||
}
|
||||
});
|
||||
}
|
||||
dropdown.chosen("destroy");
|
||||
dropdown.chosen();
|
||||
}
|
||||
|
||||
function ManufacturerId_onchange(ManufacturerId_select) {
|
||||
if (ManufacturerId_select.value) {
|
||||
ManufacturerId_select.form.elements['newMonitor[Manufacturer]'].style['display'] = 'none';
|
||||
populate_models(ManufacturerId_select.value);
|
||||
} else {
|
||||
ManufacturerId_select.form.elements['newMonitor[Manufacturer]'].style['display'] = 'inline';
|
||||
// Set models dropdown to Unknown, text area visible
|
||||
const ModelId_dropdown = $j('[name="newMonitor[ModelId]"]');
|
||||
ModelId_dropdown.empty();
|
||||
ModelId_dropdown.append('<option selected="true">Unknown</option>');
|
||||
ModelId_dropdown.prop('selectedIndex', 0);
|
||||
$j('[name="newMonitor[Model]"]').show();
|
||||
}
|
||||
}
|
||||
|
||||
function select_by_value_case_insensitive(dropdown, value) {
|
||||
const test_value = value.toLowerCase();
|
||||
for (i=1; i < dropdown.options.length; i++) {
|
||||
if (dropdown.options[i].text.toLowerCase() == test_value) {
|
||||
dropdown.selectedIndex = i;
|
||||
dropdown.options[i].selected = true;
|
||||
$j(dropdown).chosen("destroy").chosen();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (dropdown.selectedIndex != 0) {
|
||||
dropdown.selectedIndex = 0;
|
||||
$j(dropdown).chosen("destroy").chosen();
|
||||
}
|
||||
}
|
||||
|
||||
function Manufacturer_onchange(input) {
|
||||
if (!input.value) {
|
||||
return;
|
||||
}
|
||||
ManufacturerId_select = input.form.elements['newMonitor[ManufacturerId]'];
|
||||
select_by_value_case_insensitive(ManufacturerId_select, input.value);
|
||||
populate_models(ManufacturerId_select.value);
|
||||
}
|
||||
|
||||
function ModelId_onchange(ModelId_select) {
|
||||
if (parseInt(ModelId_select.value)) {
|
||||
$j('[name="newMonitor[Model]"]').hide();
|
||||
} else {
|
||||
$j('[name="newMonitor[Model]"]').show();
|
||||
}
|
||||
}
|
||||
|
||||
function Model_onchange(input) {
|
||||
select_by_value_case_insensitive(input.form.elements['newMonitor[ModelId]'], input.value);
|
||||
}
|
||||
|
||||
window.addEventListener('DOMContentLoaded', initPage);
|
||||
|
|
|
@ -317,5 +317,10 @@ function initPage() {
|
|||
}
|
||||
selectLayout('#zmMontageLayout');
|
||||
}
|
||||
|
||||
function watchFullscreen() {
|
||||
const content = document.getElementById('content');
|
||||
openFullscreen(content);
|
||||
}
|
||||
// Kick everything off
|
||||
$j(document).ready(initPage);
|
||||
|
|
|
@ -57,7 +57,7 @@ function getFrame(monId, time, last_Frame) {
|
|||
|
||||
var events_for_monitor = events_by_monitor_id[monId];
|
||||
if ( !events_for_monitor ) {
|
||||
console.log("No events for monitor " + monId);
|
||||
//console.log("No events for monitor " + monId);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -648,8 +648,11 @@ function setSpeed(speed_index) {
|
|||
}
|
||||
|
||||
function setLive(value) {
|
||||
// When we submit the context etc goes away but we may still be trying to update
|
||||
// So kill the timer.
|
||||
clearInterval(timerObj);
|
||||
liveMode = value;
|
||||
var form = $j('#montagereview_form')[0];
|
||||
var form = document.getElementById('montagereview_form');
|
||||
form.elements['live'].value = value;
|
||||
form.submit();
|
||||
return false;
|
||||
|
@ -985,6 +988,19 @@ function initPage() {
|
|||
});
|
||||
});
|
||||
|
||||
if ( !liveMode ) {
|
||||
canvas = document.getElementById('timeline');
|
||||
|
||||
canvas.addEventListener('mousemove', mmove, false);
|
||||
canvas.addEventListener('touchmove', tmove, false);
|
||||
canvas.addEventListener('mousedown', mdown, false);
|
||||
canvas.addEventListener('mouseup', mup, false);
|
||||
canvas.addEventListener('mouseout', mout, false);
|
||||
|
||||
ctx = canvas.getContext('2d');
|
||||
drawGraph();
|
||||
}
|
||||
|
||||
for ( var i = 0, len = monitorPtr.length; i < len; i += 1 ) {
|
||||
var monId = monitorPtr[i];
|
||||
if ( !monId ) continue;
|
||||
|
@ -1006,18 +1022,6 @@ function initPage() {
|
|||
}
|
||||
} // end foreach monitor
|
||||
|
||||
if ( !liveMode ) {
|
||||
canvas = document.getElementById('timeline');
|
||||
|
||||
canvas.addEventListener('mousemove', mmove, false);
|
||||
canvas.addEventListener('touchmove', tmove, false);
|
||||
canvas.addEventListener('mousedown', mdown, false);
|
||||
canvas.addEventListener('mouseup', mup, false);
|
||||
canvas.addEventListener('mouseout', mout, false);
|
||||
|
||||
ctx = canvas.getContext('2d');
|
||||
drawGraph();
|
||||
}
|
||||
setSpeed(speedIndex);
|
||||
//setFit(fitMode); // will redraw
|
||||
//setLive(liveMode); // will redraw
|
||||
|
|
|
@ -239,6 +239,6 @@ echo "];\n";
|
|||
var cWidth; // save canvas width
|
||||
var cHeight; // save canvas height
|
||||
var canvas; // global canvas definition so we don't have to keep looking it up
|
||||
var ctx;
|
||||
var ctx = null;
|
||||
var underSlider; // use this to hold what is hidden by the slider
|
||||
var underSliderX; // Where the above was taken from (left side, Y is zero)
|
||||
|
|
|
@ -16,6 +16,9 @@ function generateVideoResponse( data, responseText ) {
|
|||
}
|
||||
|
||||
function generateVideo() {
|
||||
$j.ajaxSetup({
|
||||
timeout: 0
|
||||
});
|
||||
var form = $j('#videoForm').serialize();
|
||||
$j.getJSON(thisUrl + '?view=request&request=event&action=video', form)
|
||||
.done(generateVideoResponse)
|
||||
|
|
|
@ -970,5 +970,20 @@ function initPage() {
|
|||
});
|
||||
} // initPage
|
||||
|
||||
function watchFullscreen() {
|
||||
const btn = document.getElementById('fullscreenBtn');
|
||||
console.log(btn);
|
||||
if (btn.firstElementChild.innerHTML=='fullscreen') {
|
||||
const content = document.getElementById('content');
|
||||
openFullscreen(content);
|
||||
btn.firstElementChild.innerHTML='fullscreen_exit';
|
||||
btn.setAttribute('title', translate["Exit Fullscreen"]);
|
||||
} else {
|
||||
closeFullscreen();
|
||||
btn.firstElementChild.innerHTML='fullscreen';
|
||||
btn.setAttribute('title', translate["Fullscreen"]);
|
||||
}
|
||||
}
|
||||
|
||||
// Kick everything off
|
||||
$j(document).ready(initPage);
|
||||
|
|
|
@ -103,3 +103,7 @@ labels[<?php echo validInt($index) ?>] = '<?php echo validJsStr($label) ?>';
|
|||
<?php
|
||||
}
|
||||
?>
|
||||
var translate = {
|
||||
"Fullscreen": "<?php echo translate('Fullscreen') ?>",
|
||||
"Exit Fullscreen": "<?php echo translate('Exit Fullscreen') ?>",
|
||||
};
|
||||
|
|
|
@ -661,6 +661,7 @@ function initPage() {
|
|||
|
||||
// Start the fps and status updates. give a random delay so that we don't assault the server
|
||||
var delay = Math.round( (Math.random()+0.5)*statusRefreshTimeout );
|
||||
monitors[i].setScale('auto');
|
||||
monitors[i].start(delay);
|
||||
}
|
||||
|
||||
|
|
|
@ -66,6 +66,7 @@ monitorData[monitorData.length] = {
|
|||
'width': <?php echo $monitor->ViewWidth() ?>,
|
||||
'height':<?php echo $monitor->ViewHeight() ?>,
|
||||
'url': '<?php echo $monitor->UrlToIndex( ZM_MIN_STREAMING_PORT ? ($monitor->Id() + ZM_MIN_STREAMING_PORT) : '') ?>',
|
||||
'url_to_zms': '<?php echo $monitor->UrlToZMS( ZM_MIN_STREAMING_PORT ? ($monitor->Id() + ZM_MIN_STREAMING_PORT) : '') ?>',
|
||||
'type': '<?php echo $monitor->Type() ?>',
|
||||
'refresh': '<?php echo $monitor->Refresh() ?>'
|
||||
};
|
||||
|
|
|
@ -12,6 +12,7 @@ function initPage() {
|
|||
|
||||
// Start the fps and status updates. give a random delay so that we don't assault the server
|
||||
var delay = Math.round( (Math.random()+0.5)*statusRefreshTimeout );
|
||||
monitors[i].setScale('auto');
|
||||
monitors[i].start(delay);
|
||||
}
|
||||
|
||||
|
@ -31,5 +32,12 @@ function initPage() {
|
|||
});
|
||||
}
|
||||
|
||||
function streamCmdQuit() {
|
||||
for ( var i = 0, length = monitorData.length; i < length; i++ ) {
|
||||
monitors[i] = new MonitorStream(monitorData[i]);
|
||||
monitors[i].stop();
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('DOMContentLoaded', initPage);
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ monitorData[monitorData.length] = {
|
|||
'width': <?php echo $monitor->ViewWidth() ?>,
|
||||
'height':<?php echo $monitor->ViewHeight() ?>,
|
||||
'url': '<?php echo $monitor->UrlToIndex( ZM_MIN_STREAMING_PORT ? ($monitor->Id() + ZM_MIN_STREAMING_PORT) : '') ?>',
|
||||
'url_to_zms': '<?php echo $monitor->UrlToZMS( ZM_MIN_STREAMING_PORT ? ($monitor->Id() + ZM_MIN_STREAMING_PORT) : '') ?>',
|
||||
'type': '<?php echo $monitor->Type() ?>',
|
||||
'refresh': '<?php echo $monitor->Refresh() ?>'
|
||||
};
|
||||
|
@ -24,7 +25,7 @@ var STATE_TAPE = <?php echo STATE_TAPE ?>;
|
|||
|
||||
var stateStrings = new Array();
|
||||
stateStrings[STATE_IDLE] = "<?php echo translate('Idle') ?>";
|
||||
stateStrings[STATE_PREALARM] = "<?php echo translate('Idle') ?>";
|
||||
stateStrings[STATE_PREALARM] = "<?php echo translate('PreAlarm') ?>";
|
||||
stateStrings[STATE_ALARM] = "<?php echo translate('Alarm') ?>";
|
||||
stateStrings[STATE_ALERT] = "<?php echo translate('Alert') ?>";
|
||||
stateStrings[STATE_TAPE] = "<?php echo translate('Record') ?>";
|
||||
|
|
|
@ -453,7 +453,7 @@ foreach ( $tabs as $name=>$value ) {
|
|||
switch ( $name ) {
|
||||
case 'general' :
|
||||
{
|
||||
if (!$monitor->Id()) {
|
||||
if (!$monitor->Id() and count($monitors)) {
|
||||
$monitor_ids = array();
|
||||
foreach ($monitors as $m) { $monitor_ids[] = $m['Id']; }
|
||||
$available_monitor_ids = array_diff(range(min($monitor_ids),max($monitor_ids)), $monitor_ids);
|
||||
|
@ -461,13 +461,16 @@ switch ( $name ) {
|
|||
<tr class="Id">
|
||||
<td class="text-right pr-3"><?php echo translate('Id') ?></td>
|
||||
<td><input type="number" step="1" min="1" name="newMonitor[Id]" placeholder="leave blank for auto"/><br/>
|
||||
10 Available Ids:
|
||||
<?php echo implode(', ', array_slice($available_monitor_ids, 0, 10)); ?>
|
||||
<?php
|
||||
if (count($available_monitor_ids)) {
|
||||
echo 'Some available ids: '.implode(', ', array_slice($available_monitor_ids, 0, 10));
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
|
||||
} # end if ! $monitor->Id()
|
||||
} # end if ! $monitor->Id() and count($monitors)
|
||||
?>
|
||||
<tr class="Name">
|
||||
<td class="text-right pr-3"><?php echo translate('Name') ?></td>
|
||||
|
@ -477,6 +480,44 @@ switch ( $name ) {
|
|||
<td class="text-right pr-3"><?php echo translate('Notes') ?></td>
|
||||
<td><textarea name="newMonitor[Notes]" rows="4"><?php echo validHtmlStr($monitor->Notes()) ?></textarea></td>
|
||||
</tr>
|
||||
<tr class="Manufacturer">
|
||||
<td class="text-right pr-3"><?php echo translate('Manufacturer') ?></td>
|
||||
<td>
|
||||
<?php
|
||||
require_once('includes/Manufacturer.php');
|
||||
$manufacturers = array(''=>translate('Unknown'));
|
||||
foreach ( ZM\Manufacturer::find( null, array('order'=>'lower(Name)')) as $Manufacturer ) {
|
||||
$manufacturers[$Manufacturer->Id()] = $Manufacturer->Name();
|
||||
}
|
||||
echo htmlSelect('newMonitor[ManufacturerId]', $manufacturers, $monitor->ManufacturerId(),
|
||||
array('class'=>'chosen','data-on-change-this'=>'ManufacturerId_onchange'));
|
||||
?>
|
||||
<input type="text" name="newMonitor[Manufacturer]"
|
||||
placeholder="enter new manufacturer name"
|
||||
value="<?php echo $monitor->Manufacturer()->Name() ?>"<?php echo $monitor->ManufacturerId() ? ' style="display:none"' : '' ?>
|
||||
data-on-input-this="Manufacturer_onchange"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="Model">
|
||||
<td class="text-right pr-3"><?php echo translate('Model') ?></td>
|
||||
<td>
|
||||
<?php
|
||||
require_once('includes/Model.php');
|
||||
$models = array(''=>translate('Unknown'));
|
||||
foreach ( ZM\Model::find(array('ManufacturerId'=>$monitor->ManufacturerId()), array('order'=>'lower(Name)')) as $Model ) {
|
||||
$models[$Model->Id()] = $Model->Name();
|
||||
}
|
||||
echo htmlSelect('newMonitor[ModelId]', $models, $monitor->ModelId(),
|
||||
array('class'=>'chosen', 'data-on-change-this'=>'ModelId_onchange'));
|
||||
?>
|
||||
<input type="text" name="newMonitor[Model]"
|
||||
placeholder="enter new model name"
|
||||
value="<?php echo $monitor->Model()->Name() ?>"<?php echo $monitor->ModelId() ? ' style="display:none"':'' ?>
|
||||
data-on-input-this="Model_onchange"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-right pr-3"><?php echo translate('Server') ?></td><td>
|
||||
<?php
|
||||
|
@ -634,6 +675,14 @@ switch ( $name ) {
|
|||
}
|
||||
?>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td class="text-right pr-3"><?php echo translate('Event Start Command') ?></td>
|
||||
<td><input type="text" name="newMonitor[EventStartCommand]" value="<?php echo validHtmlStr($monitor->EventStartCommand()) ?>" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-right pr-3"><?php echo translate('Event End Command') ?></td>
|
||||
<td><input type="text" name="newMonitor[EventEndCommand]" value="<?php echo validHtmlStr($monitor->EventEndCommand()) ?>" /></td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -206,6 +206,9 @@ if ( canView('System') ) {
|
|||
<?php echo translate('Snapshot') ?>
|
||||
</button>
|
||||
<?php } ?>
|
||||
<button type="button" id="fullscreenBtn" title="<?php echo translate('Fullscreen') ?>" class="avail" data-on-click="watchFullscreen">
|
||||
<i class="material-icons md-18">fullscreen</i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -44,6 +44,7 @@ $tabs['medband'] = translate('MediumBW');
|
|||
$tabs['lowband'] = translate('LowBW');
|
||||
$tabs['users'] = translate('Users');
|
||||
$tabs['control'] = translate('Control');
|
||||
$tabs['privacy'] = translate('Privacy');
|
||||
|
||||
if (isset($_REQUEST['tab']))
|
||||
$tab = validHtmlStr($_REQUEST['tab']);
|
||||
|
@ -53,7 +54,6 @@ else
|
|||
$focusWindow = true;
|
||||
|
||||
xhtmlHeaders(__FILE__, translate('Options'));
|
||||
|
||||
?>
|
||||
<body>
|
||||
<?php echo getNavBarHTML(); ?>
|
||||
|
@ -194,6 +194,14 @@ foreach ( array_map('basename', glob('skins/'.$skin.'/css/*', GLOB_ONLYDIR)) as
|
|||
}
|
||||
// Have to do this
|
||||
header('Location: '.$redirect);
|
||||
} else if ($tab == 'privacy') {
|
||||
if (canView('System')) {
|
||||
$redirect = '?view=privacy';
|
||||
} else {
|
||||
$redirect = '?view=error';
|
||||
}
|
||||
// Have to do this
|
||||
header('Location: '.$redirect);
|
||||
} else if ( $tab == 'servers' ) {
|
||||
?>
|
||||
<form name="serversForm" method="post" action="?">
|
||||
|
|
|
@ -142,6 +142,9 @@ if ( $streamMode == 'jpeg' ) {
|
|||
<button type="button" id="zoomOutBtn" title="<?php echo translate('ZoomOut') ?>" class="avail" data-on-click="streamCmdZoomOut">
|
||||
<i class="material-icons md-18">zoom_out</i>
|
||||
</button>
|
||||
<button type="button" id="fullscreenBtn" title="<?php echo translate('Fullscreen') ?>" class="avail" data-on-click="watchFullscreen">
|
||||
<i class="material-icons md-18">fullscreen</i>
|
||||
</button>
|
||||
<?php
|
||||
} // end if streamMode==jpeg
|
||||
?>
|
||||
|
|
|
@ -84,7 +84,6 @@ xhtmlHeaders(__FILE__, translate('Zones'));
|
|||
?>
|
||||
<polygon points="<?php echo $zone['AreaCoords'] ?>"
|
||||
class="zmlink <?php echo $zone['Type']?>"
|
||||
data-on-click-true="streamCmdQuit"
|
||||
data-url="?view=zone&mid=<?php echo $mid ?>&zid=<?php echo $zone['Id'] ?>"
|
||||
/>
|
||||
<?php
|
||||
|
|
Loading…
Reference in New Issue