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

This commit is contained in:
Isaac Connor 2018-02-02 12:09:03 -05:00
commit f702b37445
74 changed files with 1450 additions and 1694 deletions

View File

@ -5,6 +5,8 @@ You should only file an issue if you found a bug. Feature and enhancement reque
**Do not post feature or enhancement requests, general discussions or support questions here.** **Do not post feature or enhancement requests, general discussions or support questions here.**
Docker related issues should be posted here: https://github.com/ZoneMinder/zmdockerfiles
Make sure you are running the latest version of ZoneMinder before reporting an issue. Make sure you are running the latest version of ZoneMinder before reporting an issue.
**ZoneMinder Version (`zmaudit.pl -v`):** **ZoneMinder Version (`zmaudit.pl -v`):**

2
.gitmodules vendored
View File

@ -4,4 +4,4 @@
branch = 3.0 branch = 3.0
[submodule "web/api/app/Plugin/CakePHP-Enum-Behavior"] [submodule "web/api/app/Plugin/CakePHP-Enum-Behavior"]
path = web/api/app/Plugin/CakePHP-Enum-Behavior path = web/api/app/Plugin/CakePHP-Enum-Behavior
url = https://github.com/asper/CakePHP-Enum-Behavior.git url = https://github.com/connortechnology/CakePHP-Enum-Behavior.git

View File

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

View File

@ -1,111 +0,0 @@
# ZoneMinder, you need the GIT repository code and submodules (git submodule update --init --recursive)
FROM ubuntu:xenial
MAINTAINER Markos Vakondios <mvakondios@gmail.com>
# Resynchronize the package index files
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
apache2 \
build-essential \
cmake \
dh-autoreconf \
dpatch \
libapache2-mod-php \
libarchive-zip-perl \
libavcodec-dev \
libavdevice-dev \
libavfilter-dev \
libavformat-dev \
libavresample-dev \
libav-tools \
libavutil-dev \
libbz2-dev \
libcurl4-openssl-dev \
libdate-manip-perl \
libdbd-mysql-perl \
libdbi-perl \
libdevice-serialport-perl \
libjpeg-turbo8 \
libjpeg-turbo8-dev \
libmime-lite-perl \
libmime-perl \
libmp4v2-dev \
libmysqlclient-dev \
libnetpbm10-dev \
libpcre3 \
libpcre3-dev \
libpolkit-gobject-1-dev \
libpostproc-dev \
libssl-dev \
libswscale-dev \
libsys-mmap-perl \
libtheora-dev \
libtool \
libv4l-dev \
libvlc5 \
libvlccore8 \
libvlccore-dev \
libvlc-dev \
libvorbis-dev \
libvpx-dev \
libwww-perl \
libx264-dev \
mysql-client \
mysql-server \
php \
php-cli \
php-mysql \
vlc-data \
yasm \
zip \
&& rm -rf /var/lib/apt/lists/*
# Copy local code into our container
ADD cmake /ZoneMinder/cmake/
ADD db /ZoneMinder/db/
ADD misc /ZoneMinder/misc/
ADD onvif /ZoneMinder/onvif/
ADD scripts /ZoneMinder/scripts/
ADD src /ZoneMinder/src/
ADD umutils /ZoneMinder/umutils/
ADD web /ZoneMinder/web/
ADD cmakecacheimport.sh CMakeLists.txt version zm.conf.in zmconfgen.pl.in zmlinkcontent.sh.in zoneminder-config.cmake /ZoneMinder/
ADD conf.d /ZoneMinder/conf.d
# Change into the ZoneMinder directory
WORKDIR /ZoneMinder
# Setup the ZoneMinder build environment
#RUN aclocal && autoheader && automake --force-missing --add-missing && autoconf
# Configure ZoneMinder
#RUN ./configure --with-libarch=lib/$DEB_HOST_GNU_TYPE --disable-debug --host=$DEB_HOST_GNU_TYPE --build=$DEB_BUILD_GNU_TYPE --with-mysql=/usr --with-webdir=/var/www/zm --with-ffmpeg=/usr --with-cgidir=/usr/lib/cgi-bin --with-webuser=www-data --with-webgroup=www-data --enable-mmap=yes --enable-onvif ZM_SSL_LIB=openssl ZM_DB_USER=zm ZM_DB_PASS=zm
RUN cmake .
# Build & install ZoneMinder
RUN make && make install
# ensure writable folders
RUN ./zmlinkcontent.sh
# Adding the start script
ADD utils/docker/start.sh /tmp/start.sh
# Settings rights for /usr/local/share/zoneminder/
RUN chown -R www-data:www-data /usr/local/share/zoneminder/
# Adding apache virtual hosts file
RUN cp misc/apache.conf /etc/apache2/sites-available/000-default.conf
# Expose http port
EXPOSE 80
VOLUME /var/lib/zoneminder/images /var/lib/zoneminder/events /var/lib/mysql /var/log/zm
# To speed up configuration testing, we put it here
ADD utils/docker /ZoneMinder/utils/docker/
CMD /ZoneMinder/utils/docker/setup.sh && /ZoneMinder/utils/docker/start.sh >/var/log/start.log 2>&1 & /bin/bash
# Run example docker run -it -p 1080:80 -e PHP_TIMEZONE='Europe/Paris' -v /disk/zoneminder/events:/var/lib/zoneminder/events -v /disk/zoneminder/images:/var/lib/zoneminder/images -v /disk/zoneminder/mysql:/var/lib/mysql -v /disk/zoneminder/logs:/var/log/zm --name zoneminder zoneminder/zoneminder

View File

@ -13,6 +13,10 @@ ZoneMinder is an integrated set of applications which provide a complete surveil
Before creating an issue in our github forum, please read our posting rules: Before creating an issue in our github forum, please read our posting rules:
https://github.com/ZoneMinder/ZoneMinder/wiki/Github-Posting-Rules https://github.com/ZoneMinder/ZoneMinder/wiki/Github-Posting-Rules
## Our Dockerfile has moved
Please file issues against the ZoneMinder Dockerfile here:
https://github.com/ZoneMinder/zmdockerfiles
## Installation Methods ## Installation Methods
### Building from Source is Discouraged ### Building from Source is Discouraged

View File

@ -273,10 +273,26 @@ CREATE TABLE `Events_Archived` (
) ENGINE=@ZM_MYSQL_ENGINE@; ) ENGINE=@ZM_MYSQL_ENGINE@;
drop trigger if exists event_update_trigger; drop procedure if exists update_storage_stats;
delimiter // delimiter //
create procedure update_storage_stats(IN StorageId smallint(5), IN space BIGINT)
sql security invoker
deterministic
begin
update Storage set DiskSpace = DiskSpace + space where Id = StorageId;
end;
//
drop trigger if exists event_update_trigger//
CREATE TRIGGER event_update_trigger AFTER UPDATE ON Events CREATE TRIGGER event_update_trigger AFTER UPDATE ON Events
FOR EACH ROW FOR EACH ROW
BEGIN BEGIN
@ -504,7 +520,7 @@ CREATE TABLE `MonitorPresets` (
`Name` varchar(64) NOT NULL default '', `Name` varchar(64) NOT NULL default '',
`Type` enum('Local','Remote','File','Ffmpeg','Libvlc','cURL','NVSocket') NOT NULL default 'Local', `Type` enum('Local','Remote','File','Ffmpeg','Libvlc','cURL','NVSocket') NOT NULL default 'Local',
`Device` tinytext, `Device` tinytext,
`Channel` tinytext, `Channel` tinyint(3) unsigned default NULL,
`Format` int(10) unsigned default NULL, `Format` int(10) unsigned default NULL,
`Protocol` varchar(16) default NULL, `Protocol` varchar(16) default NULL,
`Method` varchar(16) default NULL, `Method` varchar(16) default NULL,
@ -546,7 +562,7 @@ CREATE TABLE `Monitors` (
`V4LMultiBuffer` tinyint(1) unsigned, `V4LMultiBuffer` tinyint(1) unsigned,
`V4LCapturesPerFrame` tinyint(3) unsigned, `V4LCapturesPerFrame` tinyint(3) unsigned,
`Protocol` varchar(16), `Protocol` varchar(16),
`Method` varchar(16) NOT NULL default '', `Method` varchar(16) default '',
`Host` varchar(64), `Host` varchar(64),
`Port` varchar(8) NOT NULL default '', `Port` varchar(8) NOT NULL default '',
`SubPath` varchar(64) NOT NULL default '', `SubPath` varchar(64) NOT NULL default '',
@ -628,11 +644,11 @@ CREATE INDEX `Monitors_ServerId_idx` ON `Monitors` (`ServerId`);
DROP TABLE IF EXISTS `Monitor_Status`; DROP TABLE IF EXISTS `Monitor_Status`;
CREATE TABLE `Monitor_Status` ( CREATE TABLE `Monitor_Status` (
`Id` int(10) unsigned NOT NULL, `MonitorId` int(10) unsigned NOT NULL,
`Status` enum('Unknown','NotRunning','Running','NoSignal','Signal') NOT NULL default 'Unknown', `Status` enum('Unknown','NotRunning','Running','Connected','Signal') NOT NULL default 'Unknown',
`CaptureFPS` DECIMAL(10,2) NOT NULL default 0, `CaptureFPS` DECIMAL(10,2) NOT NULL default 0,
`AnalysisFPS` DECIMAL(5,2) NOT NULL default 0, `AnalysisFPS` DECIMAL(5,2) NOT NULL default 0,
PRIMARY KEY (`Id`) PRIMARY KEY (`MonitorId`)
) ENGINE=MEMORY; ) ENGINE=MEMORY;
-- --
-- Table structure for table `States` -- Table structure for table `States`
@ -825,7 +841,7 @@ CREATE TABLE `Storage` (
`Path` varchar(64) NOT NULL default '', `Path` varchar(64) NOT NULL default '',
`Name` varchar(64) NOT NULL default '', `Name` varchar(64) NOT NULL default '',
`Type` enum('local','s3fs') NOT NULL default 'local', `Type` enum('local','s3fs') NOT NULL default 'local',
`DiskSpace` bigint unsigned default NULL, `DiskSpace` bigint default NULL,
`Scheme` enum('Deep','Medium','Shallow') NOT NULL default 'Medium', `Scheme` enum('Deep','Medium','Shallow') NOT NULL default 'Medium',
`ServerId` int(10) unsigned, `ServerId` int(10) unsigned,
PRIMARY KEY (`Id`) PRIMARY KEY (`Id`)
@ -885,7 +901,7 @@ INSERT INTO `Controls` VALUES (NULL,'Foscam 9831W','Ffmpeg','FI9831W',0,0,1,0,0,
INSERT INTO `Controls` VALUES (NULL,'Foscam FI8918W','Ffmpeg','FI8918W',0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,8,0,1,1,1,0,0,0,1,1,0,360,0,360,1,0,4,0,0,1,0,90,0,90,1,0,4,0,0,0,0); INSERT INTO `Controls` VALUES (NULL,'Foscam FI8918W','Ffmpeg','FI8918W',0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,8,0,1,1,1,0,0,0,1,1,0,360,0,360,1,0,4,0,0,1,0,90,0,90,1,0,4,0,0,0,0);
INSERT INTO `Controls` VALUES (NULL,'SunEyes SP-P1802SWPTZ','Libvlc','SPP1802SWPTZ',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,8,0,1,1,0,0,0,0,1,1,0,0,0,0,1,0,64,0,0,1,0,0,0,0,1,0,64,0,0,0,0); INSERT INTO `Controls` VALUES (NULL,'SunEyes SP-P1802SWPTZ','Libvlc','SPP1802SWPTZ',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,8,0,1,1,0,0,0,0,1,1,0,0,0,0,1,0,64,0,0,1,0,0,0,0,1,0,64,0,0,0,0);
INSERT INTO `Controls` VALUES (NULL,'Wanscam HW0025','Libvlc','WanscamHW0025', 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 16, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 350, 0, 0, 1, 0, 10, 0, 0, 1, 0, 0, 0, 0, 1, 0, 10, 0, 0, 0, 0); INSERT INTO `Controls` VALUES (NULL,'Wanscam HW0025','Libvlc','WanscamHW0025', 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 16, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 350, 0, 0, 1, 0, 10, 0, 0, 1, 0, 0, 0, 0, 1, 0, 10, 0, 0, 0, 0);
INSERT INTO `Controls` VALUES (NULL,'IPCC 7210W','Libvlc','IPCC7210W', 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 16, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 350, 0, 0, 1, 0, 10, 0, 0, 1, 0, 0, 0, 0, 1, 0, 10, 0, 0, 0, 0); INSERT INTO `Controls` VALUES (NULL,'IPCC 7210W','Remote','IPCC7210W', 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 16, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
INSERT INTO `Controls` VALUES (NULL,'Vivotek ePTZ','Remote','Vivotek_ePTZ',0,0,1,1,0,0,0,1,0,0,0,0,1,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,1,0,5,0,0,1,0,0,0,0,1,0,5,0,0,0,0); INSERT INTO `Controls` VALUES (NULL,'Vivotek ePTZ','Remote','Vivotek_ePTZ',0,0,1,1,0,0,0,1,0,0,0,0,1,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,1,0,5,0,0,1,0,0,0,0,1,0,5,0,0,0,0);
INSERT INTO `Controls` VALUES (NULL,'Netcat ONVIF','Ffmpeg','Netcat',0,0,1,1,0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,100,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,100,5,5,0,0,0,1,255,1,1,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0); INSERT INTO `Controls` VALUES (NULL,'Netcat ONVIF','Ffmpeg','Netcat',0,0,1,1,0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,100,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,100,5,5,0,0,0,1,255,1,1,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0);
INSERT INTO `Controls` VALUES (NULL,'Keekoon','Remote','Keekoon', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); INSERT INTO `Controls` VALUES (NULL,'Keekoon','Remote','Keekoon', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@ -896,67 +912,67 @@ INSERT INTO `Controls` VALUES (NULL,'Floureon 1080P','Ffmpeg','Floureon',0,0,0,1
-- --
-- Add some monitor preset values -- Add some monitor preset values
-- --
INSERT INTO MonitorPresets VALUES (NULL,'Axis IP, 320x240, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'<ip-address>',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100); INSERT INTO MonitorPresets VALUES (NULL,'Axis IP, 320x240, mpjpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100);
INSERT INTO MonitorPresets VALUES (NULL,'Axis IP, 320x240, mpjpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'<ip-address>',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240&req_fps=5',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100); INSERT INTO MonitorPresets VALUES (NULL,'Axis IP, 320x240, mpjpeg, max 5 FPS','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240&req_fps=5',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100);
INSERT INTO MonitorPresets VALUES (NULL,'Axis IP, 320x240, jpeg','Remote','http','simple',NULL,NULL,NULL,'<ip-address>',80,'/axis-cgi/jpg/image.cgi?resolution=320x240',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100); INSERT INTO MonitorPresets VALUES (NULL,'Axis IP, 320x240, jpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/axis-cgi/jpg/image.cgi?resolution=320x240',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100);
INSERT INTO MonitorPresets VALUES (NULL,'Axis IP, 320x240, jpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'<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, 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','simple',NULL,NULL,NULL,'<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','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','simple',NULL,NULL,NULL,'<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, 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','simple',NULL,NULL,NULL,'<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','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','simple',NULL,NULL,NULL,'<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, 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','simple',NULL,NULL,NULL,'<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, 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','simple',NULL,NULL,NULL,'<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, 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','simple',NULL,NULL,NULL,'<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','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','simple',NULL,NULL,NULL,'<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, 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','simple',NULL,NULL,NULL,'<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','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','simple',NULL,NULL,NULL,'<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, 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','simple',NULL,NULL,NULL,'<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','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','simple',NULL,NULL,NULL,'<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, 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','simple',NULL,NULL,NULL,'<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','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','simple',NULL,NULL,NULL,'<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 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','rtpUni',NULL,NULL,NULL,'<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, 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','rtpMulti',NULL,NULL,NULL,'<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','rtpRtsp',NULL,NULL,NULL,'<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,'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,'Panasonic IP, 320x240, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'<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, 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','simple',NULL,NULL,NULL,'<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','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','simple',NULL,NULL,NULL,'<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, 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','simple',NULL,NULL,NULL,'<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, 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','simple',NULL,NULL,NULL,'<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','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','simple',NULL,NULL,NULL,'<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, 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','simple',NULL,NULL,NULL,'<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, 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','simple',NULL,NULL,NULL,'<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','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','simple',NULL,NULL,NULL,'<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, 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','simple',NULL,NULL,NULL,'<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, 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','simple',NULL,NULL,NULL,'<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','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','simple',NULL,NULL,NULL,'<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,'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','simple',NULL,NULL,NULL,'<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','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','simple',NULL,NULL,NULL,'<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, 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','simple',NULL,NULL,NULL,'<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,'/GetData.cgi',NULL,NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100);
INSERT INTO MonitorPresets VALUES (NULL,'Gadspot IP, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'<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,'/Jpeg/CamImg.jpg',NULL,NULL,NULL,3,5.0,0,NULL,NULL,NULL,100,100);
INSERT INTO MonitorPresets VALUES (NULL,'VEO Observer, jpeg','Remote','http','simple',NULL,NULL,NULL,'<ip-address>',80,'/Jpeg/CamImg.jpg',NULL,NULL,NULL,3,NULL,0,NULL,NULL,NULL,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','simple',NULL,NULL,NULL,'<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,'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,'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,'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,'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,'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,'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<?>','<?>',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','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<?>','<?>',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, 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<?>','<?>',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','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<?>','<?>',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), 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<?>','<?>',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','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<?>','<?>',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, 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<?>','<?>',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','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<?>','<?>',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 (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,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','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,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, 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,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','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,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), 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<?>','<?>',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','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<?>','<?>',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, 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<?>','<?>',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','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<?>','<?>',1,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, 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,'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 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 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);
@ -964,8 +980,8 @@ INSERT INTO MonitorPresets VALUES (NULL,'Foscam FI9821W FFMPEG H.264','Ffmpeg',N
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,'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,'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,'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','rtpRtsp',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, 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','rtpRtsp',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,'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 -- Add some zone preset values

8
db/zm_update-1.31.29.sql Normal file
View File

@ -0,0 +1,8 @@
DROP TABLE IF EXISTS `Monitor_Status`;
CREATE TABLE `Monitor_Status` (
`MonitorId` int(10) unsigned NOT NULL,
`Status` enum('Unknown','NotRunning','Running','NoSignal','Signal') NOT NULL default 'Unknown',
`CaptureFPS` DECIMAL(10,2) NOT NULL default 0,
`AnalysisFPS` DECIMAL(5,2) NOT NULL default 0,
PRIMARY KEY (`MonitorId`)
) ENGINE=MEMORY;

20
db/zm_update-1.31.30.sql Normal file
View File

@ -0,0 +1,20 @@
DROP TABLE IF EXISTS `Monitor_Status`;
CREATE TABLE `Monitor_Status` (
`MonitorId` int(10) unsigned NOT NULL,
`Status` enum('Unknown','NotRunning','Running','Connected','Signal') NOT NULL default 'Unknown',
`CaptureFPS` DECIMAL(10,2) NOT NULL default 0,
`AnalysisFPS` DECIMAL(5,2) NOT NULL default 0,
PRIMARY KEY (`MonitorId`)
) ENGINE=MEMORY;
SET SESSION sql_mode='NO_AUTO_VALUE_ON_ZERO';
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM Storage WHERE Name = 'Default' AND Id=0 AND Path='/var/cache/zoneminder/events'
) > 0,
"SELECT 'Default Storage Area already exists.'",
"INSERT INTO Storage (Id,Name,Path,Scheme,ServerId) VALUES (0,'Default','/var/cache/zoneminder/events','Medium',NULL)"
));
PREPARE stmt FROM @s;
EXECUTE stmt;

1
db/zm_update-1.31.31.sql Normal file
View File

@ -0,0 +1 @@
ALTER TABLE Storage MODIFY DiskSpace BIGINT default NULL;

3
db/zm_update-1.31.32.sql Normal file
View File

@ -0,0 +1,3 @@
ALTER TABLE Monitors MODIFY TotalEventDiskSpace BIGINT default NULL;
ALTER TABLE Monitors MODIFY Method VARCHAR(16) default NULL;

View File

@ -110,6 +110,7 @@ Requires: perl(Net::SMTP)
Requires: perl(Net::FTP) Requires: perl(Net::FTP)
Requires: perl(LWP::Protocol::https) Requires: perl(LWP::Protocol::https)
Requires: ca-certificates Requires: ca-certificates
Requires: zip
%{?with_init_systemd:Requires(post): systemd} %{?with_init_systemd:Requires(post): systemd}
%{?with_init_systemd:Requires(post): systemd-sysv} %{?with_init_systemd:Requires(post): systemd-sysv}

View File

@ -31,9 +31,9 @@ if [ "$1" = "configure" ]; then
if ! $(echo quit | mysql --defaults-file=/etc/mysql/debian.cnf zm > /dev/null 2> /dev/null) ; then if ! $(echo quit | mysql --defaults-file=/etc/mysql/debian.cnf zm > /dev/null 2> /dev/null) ; then
cat /usr/share/zoneminder/db/zm_create.sql | mysql --defaults-file=/etc/mysql/debian.cnf cat /usr/share/zoneminder/db/zm_create.sql | mysql --defaults-file=/etc/mysql/debian.cnf
# This creates the user. # This creates the user.
echo "grant lock tables, alter,select,insert,update,delete,create,index,alter routine,create routine, trigger,execute on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost identified by \"${ZM_DB_PASS}\";" | mysql --defaults-file=/etc/mysql/debian.cnf mysql echo "grant lock tables, alter,drop,select,insert,update,delete,create,index,alter routine,create routine, trigger,execute on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost identified by \"${ZM_DB_PASS}\";" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
else else
echo "grant lock tables, alter,select,insert,update,delete,create,index,alter routine,create routine, trigger,execute on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost;" | mysql --defaults-file=/etc/mysql/debian.cnf mysql echo "grant lock tables, alter,drop,select,insert,update,delete,create,index,alter routine,create routine, trigger,execute on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost;" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
fi fi
zmupdate.pl --nointeractive zmupdate.pl --nointeractive

View File

@ -33,9 +33,9 @@ if [ "$1" = "configure" ]; then
if ! $(echo quit | mysql --defaults-file=/etc/mysql/debian.cnf zm > /dev/null 2> /dev/null) ; then if ! $(echo quit | mysql --defaults-file=/etc/mysql/debian.cnf zm > /dev/null 2> /dev/null) ; then
cat /usr/share/zoneminder/db/zm_create.sql | mysql --defaults-file=/etc/mysql/debian.cnf cat /usr/share/zoneminder/db/zm_create.sql | mysql --defaults-file=/etc/mysql/debian.cnf
# This creates the user. # This creates the user.
echo "grant lock tables,alter,select,insert,update,delete,create,index,alter routine,create routine, trigger,execute on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost identified by \"${ZM_DB_PASS}\";" | mysql --defaults-file=/etc/mysql/debian.cnf mysql echo "grant lock tables,alter,drop,select,insert,update,delete,create,index,alter routine,create routine, trigger,execute on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost identified by \"${ZM_DB_PASS}\";" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
else else
echo "grant lock tables,alter,select,insert,update,delete,create,index,alter routine,create routine, trigger,execute on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost;" | mysql --defaults-file=/etc/mysql/debian.cnf mysql echo "grant lock tables,alter,drop,select,insert,update,delete,create,index,alter routine,create routine, trigger,execute on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost;" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
fi fi
zmupdate.pl --nointeractive zmupdate.pl --nointeractive

View File

@ -44,7 +44,7 @@ Clone the ZoneMinder project if you have not done so already.
:: ::
git clone ZoneMinder git clone https://ZoneMinder/ZoneMinder
cd ZoneMinder cd ZoneMinder
Alternatively, if you have already cloned the repo and wish to update it, do the following. Alternatively, if you have already cloned the repo and wish to update it, do the following.

View File

@ -30,9 +30,14 @@ guide you with a quick search.
.. topic :: Latest Release .. topic :: Latest Release
ZoneMinder 1.29.0 is now part of the current standard Ubuntu repository. But ZoneMinder is now part of the current standard Ubuntu repository, but
if you wish to install the later releases of ZoneMinder you will need sometimes the official repository can lag behind. To find out check our
to add the iconnor/zoneminder PPA. `releases page <https://github.com/ZoneMinder/zoneminder/releases>`_ for
the latest release.
Alternatively, the ZoneMinder project team maintains a ppa, which is updated immediately
following a new release of ZoneMinder. To use this repository instead of the
official Ubuntu repository, enter the following from the command line:
:: ::

View File

@ -8,7 +8,7 @@
ServerAdmin webmaster@localhost ServerAdmin webmaster@localhost
DocumentRoot "@WEB_PREFIX@" DocumentRoot "@WEB_PREFIX@"
Alias /zm/ "@WEB_PREFIX@/" Alias /zm "@WEB_PREFIX@"
<Directory "@WEB_PREFIX@"> <Directory "@WEB_PREFIX@">
Options -Indexes +FollowSymLinks Options -Indexes +FollowSymLinks
AllowOverride All AllowOverride All

View File

@ -3,5 +3,3 @@
# Process the perl modules subdirectory # Process the perl modules subdirectory
add_subdirectory(proxy) add_subdirectory(proxy)
add_subdirectory(modules) add_subdirectory(modules)
add_subdirectory(scripts)

View File

@ -1,9 +0,0 @@
# CMakeLists.txt for the ZoneMinder perl scripts.
# If this is an out-of-source build, copy the files we need to the binary directory
if(NOT (CMAKE_BINARY_DIR STREQUAL CMAKE_SOURCE_DIR))
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/zmonvif-probe.pl" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
endif(NOT (CMAKE_BINARY_DIR STREQUAL CMAKE_SOURCE_DIR))
# Install the perl scripts
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/zmonvif-probe.pl" DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)

View File

@ -1,405 +0,0 @@
#!/usr/bin/perl -w
use strict;
#
# ==========================================================================
#
# ZoneMinder ONVIF Control Protocol Module
# Copyright (C) 2014 Jan M. Hochstein
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# ==========================================================================
#
# This module contains the implementation of the ONVIF capability prober
#
use Getopt::Std;
use Data::UUID;
require ONVIF::Client;
require WSDiscovery10::Interfaces::WSDiscovery::WSDiscoveryPort;
require WSDiscovery10::Elements::Header;
require WSDiscovery10::Elements::Types;
require WSDiscovery10::Elements::Scopes;
require WSDiscovery::TransportUDP;
#
# ========================================================================
# Globals
my $verbose = 0;
my $soap_version = undef;
my $client;
# =========================================================================
# internal functions
sub deserialize_message
{
my ($wsdl_client, $response) = @_;
# copied and adapted from SOAP::WSDL::Client
# get deserializer
my $deserializer = $wsdl_client->get_deserializer();
if(! $deserializer) {
$deserializer = SOAP::WSDL::Factory::Deserializer->get_deserializer({
soap_version => $wsdl_client->get_soap_version(),
%{ $wsdl_client->get_deserializer_args() },
});
}
# set class resolver if serializer supports it
$deserializer->set_class_resolver( $wsdl_client->get_class_resolver() )
if ( $deserializer->can('set_class_resolver') );
# Try deserializing response - there may be some,
# even if transport did not succeed (got a 500 response)
if ( $response ) {
# as our faults are false, returning a success marker is the only
# reliable way of determining whether the deserializer succeeded.
# Custom deserializers may return an empty list, or undef,
# and $@ is not guaranteed to be undefined.
my ($success, $result_body, $result_header) = eval {
(1, $deserializer->deserialize( $response ));
};
if (defined $success) {
return wantarray
? ($result_body, $result_header)
: $result_body;
}
elsif (blessed $@) { #}&& $@->isa('SOAP::WSDL::SOAP::Typelib::Fault11')) {
return $@;
}
else {
return $deserializer->generate_fault({
code => 'soap:Server',
role => 'urn:localhost',
message => "Error deserializing message: $@. \n"
. "Message was: \n$response"
});
}
};
}
sub interpret_messages
{
my ($svc_discover, $services, @responses ) = @_;
foreach my $response ( @responses ) {
if($verbose) {
print "Received message:\n" . $response . "\n";
}
my $result = deserialize_message($svc_discover, $response);
if(not $result) {
if($verbose) {
print "Error deserializing message. No message returned from deserializer.\n";
}
next;
}
my $xaddr;
foreach my $l_xaddr (split ' ', $result->get_ProbeMatch()->get_XAddrs()) {
# find IPv4 address
if($verbose) {
print "l_xaddr = $l_xaddr\n";
}
if($l_xaddr =~ m|//[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+[:/]|) {
$xaddr = $l_xaddr;
last;
} else {
print STDERR "Unable to find IPv4 address from xaddr $l_xaddr\n";
}
}
# No usable address found
next if not $xaddr;
# ignore multiple responses from one service
next if defined $services->{$xaddr};
$services->{$xaddr} = 1;
print "$xaddr, " . $svc_discover->get_soap_version() . ", ";
print "(";
my $scopes = $result->get_ProbeMatch()->get_Scopes();
my $count = 0;
foreach my $scope(split ' ', $scopes) {
if($scope =~ m|onvif://www\.onvif\.org/(.+)/(.*)|) {
my ($attr, $value) = ($1,$2);
if( 0 < $count ++) {
print ", ";
}
print $attr . "=\'" . $value . "\'";
}
}
print ")\n";
}
}
# =========================================================================
# functions
sub discover
{
## collect all responses
my @responses = ();
no warnings 'redefine';
*WSDiscovery::TransportUDP::_notify_response = sub {
my ($transport, $response) = @_;
push @responses, $response;
};
## try both soap versions
my %services;
my $uuid_gen = Data::UUID->new();
if ( ( ! $soap_version ) or ( $soap_version eq '1.1' ) ) {
if($verbose) {
print "Probing for SOAP 1.1\n"
}
my $svc_discover = WSDiscovery10::Interfaces::WSDiscovery::WSDiscoveryPort->new({
# no_dispatch => '1',
});
$svc_discover->set_soap_version('1.1');
my $uuid = $uuid_gen->create_str();
my $result = $svc_discover->ProbeOp(
{ # WSDiscovery::Types::ProbeType
Types => 'http://www.onvif.org/ver10/network/wsdl:NetworkVideoTransmitter http://www.onvif.org/ver10/device/wsdl:Device', # QNameListType
Scopes => { value => '' },
},
WSDiscovery10::Elements::Header->new({
Action => { value => 'http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe' },
MessageID => { value => "urn:uuid:$uuid" },
To => { value => 'urn:schemas-xmlsoap-org:ws:2005:04:discovery' },
})
);
print $result . "\n" if $verbose;
interpret_messages($svc_discover, \%services, @responses);
@responses = ();
} # end if doing soap 1.1
if ( ( ! $soap_version ) or ( $soap_version eq '1.2' ) ) {
if($verbose) {
print "Probing for SOAP 1.2\n"
}
my $svc_discover = WSDiscovery10::Interfaces::WSDiscovery::WSDiscoveryPort->new({
# no_dispatch => '1',
});
$svc_discover->set_soap_version('1.2');
# copies of the same Probe message must have the same MessageID.
# This is not a copy. So we generate a new uuid.
my $uuid = $uuid_gen->create_str();
# Everyone else, like the nodejs onvif code and odm only ask for NetworkVideoTransmitter
my $result = $svc_discover->ProbeOp(
{ # WSDiscovery::Types::ProbeType
xmlattr => { 'xmlns:dn' => 'http://www.onvif.org/ver10/network/wsdl', },
Types => 'dn:NetworkVideoTransmitter', # QNameListType
Scopes => { value => '' },
},
WSDiscovery10::Elements::Header->new({
Action => { value => 'http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe' },
MessageID => { value => "urn:uuid:$uuid" },
To => { value => 'urn:schemas-xmlsoap-org:ws:2005:04:discovery' },
})
);
print $result . "\n" if $verbose;
interpret_messages($svc_discover, \%services, @responses);
} # end if doing soap 1.2
}
sub profiles
{
# my $result = $services{media}{ep}->GetVideoSources( { } ,, );
# die $result if not $result;
# print $result . "\n";
my $result = $client->get_endpoint('media')->GetProfiles( { } ,, );
die $result if not $result;
if($verbose) {
print "Received message:\n" . $result . "\n";
}
my $profiles = $result->get_Profiles();
foreach my $profile ( @{ $profiles } ) {
my $token = $profile->attr()->get_token() ;
# Specification gives conflicting values for unicast stream types, try both.
# http://www.onvif.org/onvif/ver10/media/wsdl/media.wsdl#op.GetStreamUri
foreach my $streamtype ( 'RTP_unicast', 'RTP-Unicast' ) {
$result = $client->get_endpoint('media')->GetStreamUri( {
StreamSetup => { # ONVIF::Media::Types::StreamSetup
Stream => $streamtype, # StreamType
Transport => { # ONVIF::Media::Types::Transport
Protocol => 'RTSP', # TransportProtocol
},
},
ProfileToken => $token, # ReferenceToken
} ,, );
last if $result;
}
die $result if not $result;
# print $result . "\n";
my $VideoEncoderConfiguration = $profile->get_VideoEncoderConfiguration();
print join(', ', $token,
$profile->get_Name(),
( $VideoEncoderConfiguration ? (
$VideoEncoderConfiguration->get_Encoding(),
$VideoEncoderConfiguration->get_Resolution()->get_Width(),
$VideoEncoderConfiguration->get_Resolution()->get_Height(),
$VideoEncoderConfiguration->get_RateControl()->get_FrameRateLimit(),
) : () ),
$result->get_MediaUri()->get_Uri() ,
). "\n";
} # end foreach profile
#
# use message parser without schema validation ???
#
}
sub move
{
my ($dir) = @_;
my $result = $client->get_endpoint('ptz')->GetNodes( { } ,, );
die $result if not $result;
print $result . "\n";
}
sub metadata
{
my $result = $client->get_endpoint('media')->GetMetadataConfigurations( { } ,, );
die $result if not $result;
print $result . "\n";
$result = $client->get_endpoint('media')->GetVideoAnalyticsConfigurations( { } ,, );
die $result if not $result;
print $result . "\n";
# $result = $client->get_endpoint('analytics')->GetServiceCapabilities( { } ,, );
# die $result if not $result;
# print $result . "\n";
}
# ========================================================================
# options processing
$Getopt::Std::STANDARD_HELP_VERSION = 1;
our ($opt_v);
my $OPTIONS = "v";
sub HELP_MESSAGE
{
my ($fh, $pkg, $ver, $opts) = @_;
print $fh "Usage: " . __FILE__ . " [-v] probe <soap version>\n";
print $fh " " . __FILE__ . " [-v] <command> <device URI> <soap version> <user> <password>\n";
print $fh <<EOF
Commands are:
probe - scan for devices on the local network and list them
profiles - print the device's supported stream configurations
metadata - print some of the device's configuration settings
move - move the device (only ptz cameras)
Common parameters:
-v - increase verbosity
Device access parameters (for all commands but 'probe'):
device URL - the ONVIF Device service URL
soap version - SOAP version (1.1 or 1.2)
user - username of a user with access to the device
password - password for the user
EOF
}
# ========================================================================
# MAIN
if(!getopts($OPTIONS)) {
HELP_MESSAGE(\*STDOUT);
exit(1);
}
if(defined $opt_v) {
$verbose = 1;
}
my $action = shift;
if(!defined $action) {
HELP_MESSAGE(\*STDOUT);
exit(1);
}
if($action eq "probe") {
$soap_version = shift;
discover();
}
else {
# all other actions need URI and credentials
my $url_svc_device = shift @ARGV;
$soap_version = shift @ARGV;
my $username = @ARGV ? shift @ARGV : '';
my $password = @ARGV ? shift @ARGV: '';
$client = ONVIF::Client->new( {
'url_svc_device' => $url_svc_device,
'soap_version' => $soap_version } );
$client->set_credentials($username, $password, 1);
$client->create_services();
if($action eq "profiles") {
profiles();
}
elsif($action eq "move") {
my $dir = shift;
move($dir);
}
elsif($action eq "metadata") {
metadata();
}
else {
print("Error: Unknown command\"$action\"");
exit(1);
}
}

View File

@ -8,6 +8,7 @@ configure_file(zmaudit.pl.in "${CMAKE_CURRENT_BINARY_DIR}/zmaudit.pl" @ONLY)
configure_file(zmcontrol.pl.in "${CMAKE_CURRENT_BINARY_DIR}/zmcontrol.pl" @ONLY) configure_file(zmcontrol.pl.in "${CMAKE_CURRENT_BINARY_DIR}/zmcontrol.pl" @ONLY)
configure_file(zmdc.pl.in "${CMAKE_CURRENT_BINARY_DIR}/zmdc.pl" @ONLY) configure_file(zmdc.pl.in "${CMAKE_CURRENT_BINARY_DIR}/zmdc.pl" @ONLY)
configure_file(zmfilter.pl.in "${CMAKE_CURRENT_BINARY_DIR}/zmfilter.pl" @ONLY) configure_file(zmfilter.pl.in "${CMAKE_CURRENT_BINARY_DIR}/zmfilter.pl" @ONLY)
configure_file(zmonvif-probe.pl.in "${CMAKE_CURRENT_BINARY_DIR}/zmonvif-probe.pl" @ONLY)
configure_file(zmpkg.pl.in "${CMAKE_CURRENT_BINARY_DIR}/zmpkg.pl" @ONLY) configure_file(zmpkg.pl.in "${CMAKE_CURRENT_BINARY_DIR}/zmpkg.pl" @ONLY)
configure_file(zmtrack.pl.in "${CMAKE_CURRENT_BINARY_DIR}/zmtrack.pl" @ONLY) configure_file(zmtrack.pl.in "${CMAKE_CURRENT_BINARY_DIR}/zmtrack.pl" @ONLY)
configure_file(zmtrigger.pl.in "${CMAKE_CURRENT_BINARY_DIR}/zmtrigger.pl" @ONLY) configure_file(zmtrigger.pl.in "${CMAKE_CURRENT_BINARY_DIR}/zmtrigger.pl" @ONLY)
@ -34,7 +35,7 @@ FOREACH(PERLSCRIPT ${perlscripts})
ENDFOREACH(PERLSCRIPT ${perlscripts}) ENDFOREACH(PERLSCRIPT ${perlscripts})
# Install the perl scripts # Install the perl scripts
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/zmaudit.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmcontrol.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmdc.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmfilter.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmpkg.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmtrack.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmtrigger.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmupdate.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmvideo.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmwatch.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmcamtool.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmtelemetry.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmstats.pl" DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/zmaudit.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmcontrol.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmdc.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmfilter.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmonvif-probe.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmpkg.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmtrack.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmtrigger.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmupdate.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmvideo.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmwatch.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmcamtool.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmtelemetry.pl" "${CMAKE_CURRENT_BINARY_DIR}/zmstats.pl" DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
if(NOT ZM_NO_X10) if(NOT ZM_NO_X10)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/zmx10.pl" DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/zmx10.pl" DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
endif(NOT ZM_NO_X10) endif(NOT ZM_NO_X10)

View File

@ -139,7 +139,7 @@ sub moveConUp
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
Debug( "Move Up" ); Debug( "Move Up" );
my $cmd = "decoder_control.cgi?command=0&onestep=1&"; my $cmd = "decoder_control.cgi?command=2&onestep=1&";
$self->sendCmd( $cmd ); $self->sendCmd( $cmd );
my $autostop = $self->getParam( $params, 'autostop', 0 ); my $autostop = $self->getParam( $params, 'autostop', 0 );
if ( $autostop && $self->{Monitor}->{AutoStopTimeout} ) if ( $autostop && $self->{Monitor}->{AutoStopTimeout} )
@ -155,7 +155,7 @@ sub moveConDown
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
Debug( "Move Down" ); Debug( "Move Down" );
my $cmd = "decoder_control.cgi?command=2&onestep=1&"; my $cmd = "decoder_control.cgi?command=0&onestep=1&";
$self->sendCmd( $cmd ); $self->sendCmd( $cmd );
my $autostop = $self->getParam( $params, 'autostop', 0 ); my $autostop = $self->getParam( $params, 'autostop', 0 );
if ( $autostop && $self->{Monitor}->{AutoStopTimeout} ) if ( $autostop && $self->{Monitor}->{AutoStopTimeout} )
@ -203,7 +203,7 @@ sub moveConUpRight
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
Debug( "Move Diagonally Up Right" ); Debug( "Move Diagonally Up Right" );
my $cmd = "decoder_control.cgi?command=91&onestep=1&"; my $cmd = "decoder_control.cgi?command=93&onestep=1&";
$self->sendCmd( $cmd ); $self->sendCmd( $cmd );
my $autostop = $self->getParam( $params, 'autostop', 0 ); my $autostop = $self->getParam( $params, 'autostop', 0 );
if ( $autostop && $self->{Monitor}->{AutoStopTimeout} ) if ( $autostop && $self->{Monitor}->{AutoStopTimeout} )
@ -219,7 +219,7 @@ sub moveConDownRight
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
Debug( "Move Diagonally Down Right" ); Debug( "Move Diagonally Down Right" );
my $cmd = "decoder_control.cgi?command=93&onestep=1&"; my $cmd = "decoder_control.cgi?command=91&onestep=1&";
$self->sendCmd( $cmd ); $self->sendCmd( $cmd );
my $autostop = $self->getParam( $params, 'autostop', 0 ); my $autostop = $self->getParam( $params, 'autostop', 0 );
if ( $autostop && $self->{Monitor}->{AutoStopTimeout} ) if ( $autostop && $self->{Monitor}->{AutoStopTimeout} )
@ -235,7 +235,7 @@ sub moveConUpLeft
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
Debug( "Move Diagonally Up Left" ); Debug( "Move Diagonally Up Left" );
my $cmd = "decoder_control.cgi?command=90&onestep=1&"; my $cmd = "decoder_control.cgi?command=92&onestep=1&";
$self->sendCmd( $cmd ); $self->sendCmd( $cmd );
my $autostop = $self->getParam( $params, 'autostop', 0 ); my $autostop = $self->getParam( $params, 'autostop', 0 );
if ( $autostop && $self->{Monitor}->{AutoStopTimeout} ) if ( $autostop && $self->{Monitor}->{AutoStopTimeout} )
@ -251,7 +251,7 @@ sub moveConDownLeft
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
Debug( "Move Diagonally Down Left" ); Debug( "Move Diagonally Down Left" );
my $cmd = "decoder_control.cgi?command=92&onestep=1&"; my $cmd = "decoder_control.cgi?command=90&onestep=1&";
$self->sendCmd( $cmd ); $self->sendCmd( $cmd );
my $autostop = $self->getParam( $params, 'autostop', 0 ); my $autostop = $self->getParam( $params, 'autostop', 0 );
if ( $autostop && $self->{Monitor}->{AutoStopTimeout} ) if ( $autostop && $self->{Monitor}->{AutoStopTimeout} )
@ -275,7 +275,7 @@ sub presetHome
{ {
my $self = shift; my $self = shift;
Debug( "Home Preset" ); Debug( "Home Preset" );
my $cmd = "decoder_control.cgi?command=25&onestep=0&"; my $cmd = "decoder_control.cgi?command=4&onestep=0&";
$self->sendCmd( $cmd ); $self->sendCmd( $cmd );
} }

View File

@ -173,8 +173,7 @@ sub runCommand {
chomp( $output ); chomp( $output );
if ( $status || logDebugging() ) { if ( $status || logDebugging() ) {
if ( $status ) { if ( $status ) {
Error( "Unable to run \"$command\", output is \"$output\"\n" ); Error( "Unable to run \"$command\", output is \"$output\", status is $status\n" );
exit( -1 );
} else { } else {
Debug( "Output: $output\n" ); Debug( "Output: $output\n" );
} }

View File

@ -45,7 +45,6 @@ our @EXPORT = qw();
our $VERSION = $ZoneMinder::Base::VERSION; our $VERSION = $ZoneMinder::Base::VERSION;
use Getopt::Std;
use Data::UUID; use Data::UUID;
use vars qw( $verbose $soap_version ); use vars qw( $verbose $soap_version );
@ -185,11 +184,11 @@ sub discover {
}; };
## try both soap versions ## try both soap versions
my %services;
my $uuid_gen = Data::UUID->new(); my $uuid_gen = Data::UUID->new();
if ( ( ! $soap_version ) or ( $soap_version eq '1.1' ) ) { if ( ( ! $soap_version ) or ( $soap_version eq '1.1' ) ) {
my %services;
if($verbose) { if($verbose) {
print "Probing for SOAP 1.1\n" print "Probing for SOAP 1.1\n"
@ -219,6 +218,7 @@ sub discover {
} # end if doing soap 1.1 } # end if doing soap 1.1
if ( ( ! $soap_version ) or ( $soap_version eq '1.2' ) ) { if ( ( ! $soap_version ) or ( $soap_version eq '1.2' ) ) {
my %services;
if($verbose) { if($verbose) {
print "Probing for SOAP 1.2\n" print "Probing for SOAP 1.2\n"
} }
@ -253,8 +253,17 @@ sub discover {
sub profiles { sub profiles {
my ( $client ) = @_; my ( $client ) = @_;
my $result = $client->get_endpoint('media')->GetProfiles( { } ,, ); my $endpoint = $client->get_endpoint('media');
die $result if not $result; if ( ! $endpoint ) {
print "No media enpoint for client.\n";
return;
}
my $result = $endpoint->GetProfiles( { } ,, );
if ( ! $result ) {
print "No result from GetProfiles\n";
return;
}
if($verbose) { if($verbose) {
print "Received message:\n" . $result . "\n"; print "Received message:\n" . $result . "\n";
} }

View File

@ -180,6 +180,9 @@ MAIN: while( $loop ) {
Info("Auditing Storage Area $Storage_Areas[0]{Id} $Storage_Areas[0]{Name} at $Storage_Areas[0]{Path}"); Info("Auditing Storage Area $Storage_Areas[0]{Id} $Storage_Areas[0]{Name} at $Storage_Areas[0]{Path}");
} elsif ( $Config{ZM_SERVER_ID} ) { } elsif ( $Config{ZM_SERVER_ID} ) {
@Storage_Areas = ZoneMinder::Storage->find( ServerId => $Config{ZM_SERVER_ID} ); @Storage_Areas = ZoneMinder::Storage->find( ServerId => $Config{ZM_SERVER_ID} );
if ( ! @Storage_Areas ) {
Fatal("No Storage Area found with ServerId =" . $Config{ZM_SERVER_ID});
}
Info("Auditing All Storage Areas on Server " . $Storage_Areas[0]->Server()->Name()); Info("Auditing All Storage Areas on Server " . $Storage_Areas[0]->Server()->Name());
} else { } else {
@Storage_Areas = ZoneMinder::Storage->find(); @Storage_Areas = ZoneMinder::Storage->find();
@ -210,11 +213,10 @@ MAIN: while( $loop ) {
$db_events->{$event->{Id}} = $event->{Age}; $db_events->{$event->{Id}} = $event->{Age};
} }
Debug( 'Got '.int(keys(%$db_events))." events for monitor $monitor->{Id}" ); Debug( 'Got '.int(keys(%$db_events))." events for monitor $monitor->{Id}" );
} } # end while monitors
my $fs_monitors; my $fs_monitors;
foreach my $Storage ( @Storage_Areas ) { foreach my $Storage ( @Storage_Areas ) {
Debug('Checking events in ' . $Storage->Path() ); Debug('Checking events in ' . $Storage->Path() );
if ( ! chdir( $Storage->Path() ) ) { if ( ! chdir( $Storage->Path() ) ) {
@ -224,7 +226,14 @@ MAIN: while( $loop ) {
# Please note that this glob will take all files beginning with a digit. # Please note that this glob will take all files beginning with a digit.
foreach my $monitor ( glob('[0-9]*') ) { foreach my $monitor ( glob('[0-9]*') ) {
next if $monitor =~ /\D/; if ( $monitor =~ /\D/ ) {
Debug("Weird non digit characters in $monitor");
next;
}
if ( $monitor_id and ( $monitor_id != $monitor ) ) {
Debug("Skipping monitor $monitor because we are only interested in monitor $monitor_id");
next;
}
Debug( "Found filesystem monitor '$monitor'" ); Debug( "Found filesystem monitor '$monitor'" );
$fs_monitors->{$monitor} = {} if ! $fs_monitors->{$monitor}; $fs_monitors->{$monitor} = {} if ! $fs_monitors->{$monitor};
@ -233,8 +242,10 @@ MAIN: while( $loop ) {
# De-taint # De-taint
( my $monitor_dir ) = ( $monitor =~ /^(.*)$/ ); ( my $monitor_dir ) = ( $monitor =~ /^(.*)$/ );
#if ( $$Storage{Scheme} eq 'Deep' ) { {
foreach my $day_dir ( glob("$monitor_dir/[0-9][0-9]/[0-9][0-9]/[0-9][0-9]") ) { my @day_dirs = glob("$monitor_dir/[0-9][0-9]/[0-9][0-9]/[0-9][0-9]");
Debug(qq`Checking for Deep Events under using glob("$monitor_dir/[0-9][0-9]/[0-9][0-9]/[0-9][0-9]") returned `. scalar @day_dirs . " events");
foreach my $day_dir ( @day_dirs ) {
Debug( "Checking day dir $day_dir" ); Debug( "Checking day dir $day_dir" );
( $day_dir ) = ( $day_dir =~ /^(.*)$/ ); # De-taint ( $day_dir ) = ( $day_dir =~ /^(.*)$/ ); # De-taint
if ( ! chdir( $day_dir ) ) { if ( ! chdir( $day_dir ) ) {
@ -258,7 +269,7 @@ MAIN: while( $loop ) {
#Event path is hour/minute/sec #Event path is hour/minute/sec
my $event_path = readlink( $event_link ); my $event_path = readlink( $event_link );
if ( !-e $event_path ) { if ( !($event_path and -e $event_path) ) {
aud_print( "Event link $day_dir/$event_link does not point to valid target" ); aud_print( "Event link $day_dir/$event_link does not point to valid target" );
if ( confirm() ) { if ( confirm() ) {
( $event_link ) = ( $event_link =~ /^(.*)$/ ); # De-taint ( $event_link ) = ( $event_link =~ /^(.*)$/ ); # De-taint
@ -279,9 +290,17 @@ MAIN: while( $loop ) {
} # end foreach event_link } # end foreach event_link
chdir( $Storage->Path() ); chdir( $Storage->Path() );
} # end foreach day dir } # end foreach day dir
}
foreach my $event_dir ( glob("$monitor_dir/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]/*") ) { Debug("Checking for Medium Scheme Events under $monitor_dir");
next if ! -d $event_dir; {
my @event_dirs = glob("$monitor_dir/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]/*");
Debug(qq`glob("$monitor_dir/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]/*") returned ` . scalar @event_dirs . " entries." );
foreach my $event_dir ( @event_dirs ) {
if ( ! -d $event_dir ) {
Debug( "$event_dir is not a dir. Skipping" );
next;
}
my ( $date, $event_id ) = $event_dir =~ /^$monitor_dir\/(\d{4}\-\d{2}\-\d{2})\/(\d+)$/; my ( $date, $event_id ) = $event_dir =~ /^$monitor_dir\/(\d{4}\-\d{2}\-\d{2})\/(\d+)$/;
if ( ! $event_id ) { if ( ! $event_id ) {
Debug("Unable to parse date/event_id from $event_dir"); Debug("Unable to parse date/event_id from $event_dir");
@ -290,13 +309,16 @@ MAIN: while( $loop ) {
my $Event = $fs_events->{$event_id} = new ZoneMinder::Event(); my $Event = $fs_events->{$event_id} = new ZoneMinder::Event();
$$Event{Id} = $event_id; $$Event{Id} = $event_id;
$$Event{Path} = join('/', $Storage->Path(), $event_dir ); $$Event{Path} = join('/', $Storage->Path(), $event_dir );
Debug("Have event $$Event{Id} at $$Event{Path}");
$$Event{Scheme} = 'Medium'; $$Event{Scheme} = 'Medium';
$$Event{RelativePath} = $event_dir; $$Event{RelativePath} = $event_dir;
$Event->MonitorId( $monitor_dir ); $Event->MonitorId( $monitor_dir );
$Event->StorageId( $Storage->Id() ); $Event->StorageId( $Storage->Id() );
} # end foreach event } # end foreach event
}
if ( ! $$Storage{Scheme} ) { if ( ! $$Storage{Scheme} ) {
Debug("Storage Scheme not set on $$Storage{Name}");
if ( ! chdir( $monitor_dir ) ) { if ( ! chdir( $monitor_dir ) ) {
Error( "Can't chdir directory '$$Storage{Path}/$monitor_dir': $!" ); Error( "Can't chdir directory '$$Storage{Path}/$monitor_dir': $!" );
next; next;
@ -321,12 +343,21 @@ MAIN: while( $loop ) {
#delete_empty_directories( $monitor_dir ); #delete_empty_directories( $monitor_dir );
} # end foreach monitor } # end foreach monitor
redo MAIN if ( $cleaned );
if ( $cleaned ) {
Debug("First stage cleaning done. Restarting.");
redo MAIN;
}
$cleaned = 0; $cleaned = 0;
while ( my ( $monitor_id, $fs_events ) = each(%$fs_monitors) ) { while ( my ( $monitor_id, $fs_events ) = each(%$fs_monitors) ) {
if ( my $db_events = $db_monitors->{$monitor_id} ) { if ( my $db_events = $db_monitors->{$monitor_id} ) {
next if ! $fs_events; if ( ! $fs_events ) {
Debug("No fs_events for database monitor $monitor_id");
next;
}
my @event_ids = keys %$fs_events;
Debug("Have " .scalar @event_ids . " events for monitor $monitor_id");
foreach my $fs_event_id ( sort { $a <=> $b } keys %$fs_events ) { foreach my $fs_event_id ( sort { $a <=> $b } keys %$fs_events ) {
@ -347,6 +378,7 @@ MAIN: while( $loop ) {
} # end foreach fs event } # end foreach fs event
} else { } else {
aud_print( "Filesystem monitor '$monitor_id' in $$Storage{Path} does not exist in database" ); aud_print( "Filesystem monitor '$monitor_id' in $$Storage{Path} does not exist in database" );
if ( confirm() ) { if ( confirm() ) {
my $command = "rm -rf $monitor_id"; my $command = "rm -rf $monitor_id";
executeShellCommand( $command ); executeShellCommand( $command );
@ -477,7 +509,7 @@ MAIN: while( $loop ) {
$res = $selectEmptyEventsSth->execute() $res = $selectEmptyEventsSth->execute()
or Fatal( "Can't execute: ".$selectEmptyEventsSth->errstr() ); or Fatal( "Can't execute: ".$selectEmptyEventsSth->errstr() );
while( my $event = $selectEmptyEventsSth->fetchrow_hashref() ) { while( my $event = $selectEmptyEventsSth->fetchrow_hashref() ) {
aud_print( "Found empty event with no frame records '$event->{Id}'" ); aud_print( "Found empty event with no frame records '$event->{Id}' at $$event{StartTime}" );
if ( confirm() ) { if ( confirm() ) {
$res = $deleteEventSth->execute( $event->{Id} ) $res = $deleteEventSth->execute( $event->{Id} )
or Fatal( "Can't execute: ".$deleteEventSth->errstr() ); or Fatal( "Can't execute: ".$deleteEventSth->errstr() );
@ -689,7 +721,7 @@ sub confirm {
if ( $report ) { if ( $report ) {
print( "\n" ); print( "\n" );
} elsif ( $interactive ) { } elsif ( $interactive ) {
print( ", $prompt y/n: " ); print( ", $prompt Y/n/q: " );
my $char = <>; my $char = <>;
chomp( $char ); chomp( $char );
if ( $char eq 'q' ) { if ( $char eq 'q' ) {
@ -784,6 +816,7 @@ yet.
-c, --continuous - Run continuously -c, --continuous - Run continuously
-f, --force - Run even if pid file exists -f, --force - Run even if pid file exists
-i, --interactive - Ask before applying any changes -i, --interactive - Ask before applying any changes
-m, --monitor_id - Only consider the given monitor
-r, --report - Just report don't actually do anything -r, --report - Just report don't actually do anything
-s, --storage_id - Specify a storage area to audit instead of all -s, --storage_id - Specify a storage area to audit instead of all
-v, --version - Print the installed version of ZoneMinder -v, --version - Print the installed version of ZoneMinder

View File

@ -183,39 +183,39 @@ use Sys::CpuLoad;
socket( CLIENT, PF_UNIX, SOCK_STREAM, 0 ) or Fatal( "Can't open socket: $!" ); socket( CLIENT, PF_UNIX, SOCK_STREAM, 0 ) or Fatal( "Can't open socket: $!" );
my $attempts = 0; my $attempts = 0;
while( !connect( CLIENT, $saddr ) ) { while( !connect(CLIENT, $saddr) ) {
$attempts++; $attempts++;
Debug("Waiting for zmdc.pl server process at ".SOCK_FILE.", attempt $attempts" ); Debug("Waiting for zmdc.pl server process at ".SOCK_FILE.", attempt $attempts");
Fatal( "Can't connect: $!" ) if ($attempts > MAX_CONNECT_DELAY); Fatal("Can't connect: $!") if $attempts > MAX_CONNECT_DELAY;
usleep(200000); usleep(200000);
} # end while } # end while
} elsif ( defined($cpid) ) { } elsif ( defined($cpid) ) {
ZMServer::run(); ZMServer::run();
} else { } else {
Fatal( "Can't fork: $!" ); Fatal("Can't fork: $!");
} }
} # end if ! server is up } # end if ! server is up
if ( $command eq 'check' && ! $daemon ) { if ( ($command eq 'check') && !$daemon ) {
print( "running\n" ); print("running\n");
exit(); exit();
} elsif ( $command eq 'startup' ) { } elsif ( $command eq 'startup' ) {
# Our work here is done # Our work here is done
exit() if ( !$server_up ); exit() if !$server_up;
} }
# The server is there, connect to it # The server is there, connect to it
#print( "Writing commands\n" ); #print( "Writing commands\n" );
CLIENT->autoflush(); CLIENT->autoflush();
my $message = join(';', $command, ( $daemon ? $daemon : () ), @args ); my $message = join(';', $command, ( $daemon ? $daemon : () ), @args );
print( CLIENT $message ); print(CLIENT $message);
shutdown( CLIENT, 1 ); shutdown(CLIENT, 1);
while( my $line = <CLIENT> ) { while( my $line = <CLIENT> ) {
chomp( $line ); chomp($line);
print( "$line\n" ); print("$line\n");
} }
# And we're done! # And we're done!
close( CLIENT ); close(CLIENT);
#print( "Finished writing, bye\n" ); #print( "Finished writing, bye\n" );
exit; exit;
@ -344,9 +344,9 @@ sub run {
} else { } else {
dPrint( ZoneMinder::Logger::ERROR, "Invalid command '$command'\n" ); dPrint( ZoneMinder::Logger::ERROR, "Invalid command '$command'\n" );
} }
close( CLIENT ); close(CLIENT);
} else { } else {
Fatal( 'Bogus descriptor' ); Fatal('Bogus descriptor');
} }
} elsif ( $nfound < 0 ) { } elsif ( $nfound < 0 ) {
if ( $! == EINTR ) { if ( $! == EINTR ) {
@ -355,9 +355,9 @@ sub run {
# See if it needs to start up again # See if it needs to start up again
restartPending(); restartPending();
} elsif ( $! == EPIPE ) { } elsif ( $! == EPIPE ) {
Error( "Can't select: $!" ); Error("Can't select: $!");
} else { } else {
Fatal( "Can't select: $!" ); Fatal("Can't select: $!");
} }
} else { } else {
#print( "Select timed out\n" ); #print( "Select timed out\n" );
@ -566,19 +566,19 @@ sub restart {
my $command = $daemon; my $command = $daemon;
$command .= ' '.join( ' ', ( @args ) ) if @args; $command .= ' '.join( ' ', ( @args ) ) if @args;
dPrint ( ZoneMinder::Logger::WARNING, "Restarting $command\n"); dPrint ( ZoneMinder::Logger::DEBUG, "Restarting $command\n");
my $process = $cmd_hash{$command}; my $process = $cmd_hash{$command};
if ( $process ) { if ( $process ) {
dPrint ( ZoneMinder::Logger::WARNING, "Have process" ); dPrint( ZoneMinder::Logger::DEBUG, "Have process" );
if ( $process->{pid} ) { if ( $process->{pid} ) {
dPrint ( ZoneMinder::Logger::WARNING, "Have process pid " .$process->{pid} ); dPrint( ZoneMinder::Logger::DEBUG, "Have process pid " .$process->{pid} );
my $cpid = $process->{pid}; my $cpid = $process->{pid};
if ( defined($pid_hash{$cpid}) ) { if ( defined($pid_hash{$cpid}) ) {
dPrint ( ZoneMinder::Logger::WARNING, "Have process pid hash " .$process->{pid} ); dPrint( ZoneMinder::Logger::DEBUG, "Have process pid hash " .$process->{pid} );
_stop( 0, $process ); _stop( 0, $process );
return; return;
} else { } else {
dPrint ( ZoneMinder::Logger::WARNING, "Not sending stop" ); dPrint( ZoneMinder::Logger::DEBUG, "Not sending stop" );
} }
} }
} }

View File

@ -73,6 +73,7 @@ use autouse 'Data::Dumper'=>qw(Dumper);
my $filter_name = ''; my $filter_name = '';
my $filter_id; my $filter_id;
my $version = 0; my $version = 0;
my $zm_terminate = 0;
GetOptions( GetOptions(
'filter=s' =>\$filter_name, 'filter=s' =>\$filter_name,
@ -94,7 +95,20 @@ use constant EVENT_PATH => ($Config{ZM_DIR_EVENTS}=~m|/|)
; ;
logInit(); logInit();
logSetSignal(); sub HupHandler {
Info("Received HUP, reloading");
&ZoneMinder::Logger::logHupHandler();
}
sub TermHandler {
Info("Received TERM, exiting");
$zm_terminate = 1;
}
sub Term {
exit( 0 );
}
$SIG{HUP} = \&HupHandler;
$SIG{TERM} = \&TermHandler;
$SIG{INT} = \&TermHandler;
if ( $Config{ZM_OPT_UPLOAD} ) { if ( $Config{ZM_OPT_UPLOAD} ) {
# Comment these out if you don't have them and don't want to upload # Comment these out if you don't have them and don't want to upload
@ -166,7 +180,7 @@ if ( ! ( $filter_name or $filter_id ) ) {
my @filters; my @filters;
my $last_action = 0; my $last_action = 0;
while( 1 ) { while( ! $zm_terminate ) {
my $now = time; my $now = time;
if ( ($now - $last_action) > $Config{ZM_FILTER_RELOAD_DELAY} ) { if ( ($now - $last_action) > $Config{ZM_FILTER_RELOAD_DELAY} ) {
Debug( "Reloading filters\n" ); Debug( "Reloading filters\n" );
@ -175,6 +189,7 @@ while( 1 ) {
} }
foreach my $filter ( @filters ) { foreach my $filter ( @filters ) {
last if $zm_terminate;
if ( $$filter{Concurrent} and ! ( $filter_id or $filter_name ) ) { if ( $$filter{Concurrent} and ! ( $filter_id or $filter_name ) ) {
my ( $proc ) = $0 =~ /(\S+)/; my ( $proc ) = $0 =~ /(\S+)/;
my ( $id ) = $$filter{Id} =~ /(\d+)/; my ( $id ) = $$filter{Id} =~ /(\d+)/;
@ -186,7 +201,7 @@ while( 1 ) {
} }
} }
last if ( $filter_name or $filter_id ); last if $filter_name or $filter_id or $zm_terminate;
Debug( "Sleeping for $delay seconds\n" ); Debug( "Sleeping for $delay seconds\n" );
sleep( $delay ); sleep( $delay );
@ -266,6 +281,7 @@ sub checkFilter {
) ); ) );
foreach my $event ( @Events ) { foreach my $event ( @Events ) {
last if $zm_terminate;
Debug( "Checking event $event->{Id}" ); Debug( "Checking event $event->{Id}" );
my $delete_ok = !undef; my $delete_ok = !undef;
$dbh->ping(); $dbh->ping();

155
scripts/zmonvif-probe.pl.in Executable file
View File

@ -0,0 +1,155 @@
#!/usr/bin/perl -w
use strict;
#
# ==========================================================================
#
# ZoneMinder ONVIF Control Protocol Module
# Copyright (C) 2014 Jan M. Hochstein
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# ==========================================================================
#
# This module contains the implementation of the ONVIF capability prober
#
use Getopt::Std;
require ONVIF::Client;
# ========================================================================
# options processing
$Getopt::Std::STANDARD_HELP_VERSION = 1;
our ($opt_v);
my $OPTIONS = "v";
sub HELP_MESSAGE
{
my ($fh, $pkg, $ver, $opts) = @_;
print $fh "Usage: " . __FILE__ . " [-v] probe <soap version>\n";
print $fh " " . __FILE__ . " [-v] <command> <device URI> <soap version> <user> <password>\n";
print $fh <<EOF
Commands are:
probe - scan for devices on the local network and list them
profiles - print the device's supported stream configurations
metadata - print some of the device's configuration settings
move - move the device (only ptz cameras)
Common parameters:
-v - increase verbosity
Device access parameters (for all commands but 'probe'):
device URL - the ONVIF Device service URL
soap version - SOAP version (1.1 or 1.2)
user - username of a user with access to the device
password - password for the user
EOF
}
# ========================================================================
# MAIN
if ( !getopts($OPTIONS) ) {
HELP_MESSAGE(\*STDOUT);
exit(1);
}
my $action = shift;
if(!defined $action) {
HELP_MESSAGE(\*STDOUT);
exit(1);
}
@EXTRA_PERL_LIB@
require ZoneMinder::ONVIF;
if ( defined $opt_v ) {
$ZoneMinder::ONVIF::verbose = 1;
}
if ( $action eq "probe" ) {
my $soap_version = shift;
ZoneMinder::ONVIF::discover($soap_version);
} else {
# all other actions need URI and credentials
my $url_svc_device = shift @ARGV;
my $soap_version = shift @ARGV;
my $username = @ARGV ? shift @ARGV : '';
my $password = @ARGV ? shift @ARGV: '';
my $client = ONVIF::Client->new( {
'url_svc_device' => $url_svc_device,
'soap_version' => $soap_version } );
$client->set_credentials($username, $password, 1);
$client->create_services();
if ( $action eq "profiles" ) {
ZoneMinder::ONVIF::profiles($client);
} elsif( $action eq "move" ) {
my $dir = shift;
ZoneMinder::ONVIF::move($client, $dir);
} elsif ( $action eq "metadata" ) {
ZoneMinder::ONVIF::metadata($client);
} else {
print("Error: Unknown command\"$action\"");
exit(1);
}
}
1;
__END__
=head1 NAME
zmonvif-probe.pl - ZoneMinder ONVIF probing tool
=head1 SYNOPSIS
zmonfig-probe.pl [-v] probe <soap version>
[-v] <command> <device URI> <soap version> <user> <password>\n";
Commands are:
probe - scan for devices on the local network and list them
profiles - print the device's supported stream configurations
metadata - print some of the device's configuration settings
move - move the device (only ptz cameras)
Common parameters:
-v - increase verbosity
Device access parameters (for all commands but 'probe'):
device URL - the ONVIF Device service URL
soap version - SOAP version (1.1 or 1.2)
user - username of a user with access to the device
password - password for the user
=head1 DESCRIPTION
=head1 OPTIONS
-c, --continuous - Run continuously
-f, --force - Run even if pid file exists
-i, --interactive - Ask before applying any changes
-m, --monitor_id - Only consider the given monitor
-r, --report - Just report don't actually do anything
-s, --storage_id - Specify a storage area to audit instead of all
-v, --version - Print the installed version of ZoneMinder
=cut

View File

@ -43,7 +43,12 @@ int Event::pre_alarm_count = 0;
Event::PreAlarmData Event::pre_alarm_data[MAX_PRE_ALARM_FRAMES] = { { 0 } }; Event::PreAlarmData Event::pre_alarm_data[MAX_PRE_ALARM_FRAMES] = { { 0 } };
Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string &p_cause, const StringSetMap &p_noteSetMap, bool p_videoEvent ) : Event::Event(
Monitor *p_monitor,
struct timeval p_start_time,
const std::string &p_cause,
const StringSetMap &p_noteSetMap,
bool p_videoEvent ) :
monitor( p_monitor ), monitor( p_monitor ),
start_time( p_start_time ), start_time( p_start_time ),
cause( p_cause ), cause( p_cause ),
@ -53,12 +58,18 @@ Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string
{ {
std::string notes; std::string notes;
createNotes( notes ); createNotes(notes);
struct timeval now;
gettimeofday(&now, 0);
bool untimedEvent = false; bool untimedEvent = false;
if ( !start_time.tv_sec ) { if ( !start_time.tv_sec ) {
untimedEvent = true; untimedEvent = true;
gettimeofday( &start_time, 0 ); start_time = now;
} else if ( start_time.tv_sec > now.tv_sec ) {
Error("StartTime in the future");
start_time = now;
} }
Storage * storage = monitor->getStorage(); Storage * storage = monitor->getStorage();
@ -216,7 +227,8 @@ Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string
Event::~Event() { Event::~Event() {
static char sql[ZM_SQL_MED_BUFSIZ]; static char sql[ZM_SQL_MED_BUFSIZ];
struct DeltaTimeval delta_time; struct DeltaTimeval delta_time;
DELTA_TIMEVAL( delta_time, end_time, start_time, DT_PREC_2 ); DELTA_TIMEVAL(delta_time, end_time, start_time, DT_PREC_2);
Debug(2, "start_time:%d.%d end_time%d.%d", start_time.tv_sec, start_time.tv_usec, end_time.tv_sec, end_time.tv_usec );
if ( frames > last_db_frame ) { if ( frames > last_db_frame ) {
@ -462,6 +474,12 @@ void Event::AddFramesInternal( int n_frames, int start_frame, Image **images, st
struct DeltaTimeval delta_time; struct DeltaTimeval delta_time;
DELTA_TIMEVAL( delta_time, *(timestamps[i]), start_time, DT_PREC_2 ); DELTA_TIMEVAL( delta_time, *(timestamps[i]), start_time, DT_PREC_2 );
// Delta is Decimal(8,2) so 6 integer digits and 2 decimal digits
if ( delta_time.sec > 999999 ) {
Warning("Invalid delta_time from_unixtime(%ld), %s%ld.%02ld",
timestamps[i]->tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec );
delta_time.sec = 0;
}
int sql_len = strlen(sql); int sql_len = strlen(sql);
snprintf( sql+sql_len, sizeof(sql)-sql_len, "( %d, %d, from_unixtime(%ld), %s%ld.%02ld ), ", id, frames, timestamps[i]->tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec ); snprintf( sql+sql_len, sizeof(sql)-sql_len, "( %d, %d, from_unixtime(%ld), %s%ld.%02ld ), ", id, frames, timestamps[i]->tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec );
@ -474,7 +492,6 @@ void Event::AddFramesInternal( int n_frames, int start_frame, Image **images, st
*(sql+strlen(sql)-2) = '\0'; *(sql+strlen(sql)-2) = '\0';
if ( mysql_query( &dbconn, sql ) ) { if ( mysql_query( &dbconn, sql ) ) {
Error( "Can't insert frames: %s, sql was (%s)", mysql_error( &dbconn ), sql ); Error( "Can't insert frames: %s, sql was (%s)", mysql_error( &dbconn ), sql );
exit( mysql_errno( &dbconn ) );
} }
last_db_frame = frames; last_db_frame = frames;
} else { } else {

View File

@ -458,5 +458,5 @@ void dumpPacket(AVPacket *pkt, const char *text) {
pkt->flags & AV_PKT_FLAG_KEY, pkt->flags & AV_PKT_FLAG_KEY,
pkt->pos, pkt->pos,
pkt->duration); pkt->duration);
Debug(1, "%s:%d:%s: %s", __FILE__, __LINE__, text, b); Debug(2, "%s:%d:%s: %s", __FILE__, __LINE__, text, b);
} }

View File

@ -111,7 +111,6 @@ FfmpegCamera::FfmpegCamera( int p_id, const std::string &p_path, const std::stri
mIsOpening = false; mIsOpening = false;
mCanCapture = false; mCanCapture = false;
mOpenStart = 0; mOpenStart = 0;
mReopenThread = 0;
videoStore = NULL; videoStore = NULL;
video_last_pts = 0; video_last_pts = 0;
have_video_keyframe = false; have_video_keyframe = false;
@ -162,21 +161,18 @@ void FfmpegCamera::Terminate() {
} }
int FfmpegCamera::PrimeCapture() { int FfmpegCamera::PrimeCapture() {
if ( mCanCapture ) {
CloseFfmpeg();
}
mVideoStreamId = -1; mVideoStreamId = -1;
mAudioStreamId = -1; mAudioStreamId = -1;
Info( "Priming capture from %s", mPath.c_str() ); Info( "Priming capture from %s", mPath.c_str() );
#if THREAD
if ( OpenFfmpeg() != 0 ) {
ReopenFfmpeg();
}
return 0;
#else
return OpenFfmpeg(); return OpenFfmpeg();
#endif
} }
int FfmpegCamera::PreCapture() { int FfmpegCamera::PreCapture() {
Debug(1, "PreCapture");
// If Reopen was called, then ffmpeg is closed and we need to reopen it. // If Reopen was called, then ffmpeg is closed and we need to reopen it.
if ( ! mCanCapture ) if ( ! mCanCapture )
return OpenFfmpeg(); return OpenFfmpeg();
@ -190,18 +186,6 @@ int FfmpegCamera::Capture( Image &image ) {
} }
// If the reopen thread has a value, but mCanCapture != 0, then we have just reopened the connection to the ffmpeg device, and we can clean up the thread. // If the reopen thread has a value, but mCanCapture != 0, then we have just reopened the connection to the ffmpeg device, and we can clean up the thread.
if ( mReopenThread != 0 ) {
void *retval = 0;
int ret;
ret = pthread_join(mReopenThread, &retval);
if ( ret != 0 ) {
Error("Could not join reopen thread.");
}
Info( "Successfully reopened stream." );
mReopenThread = 0;
}
int frameComplete = false; int frameComplete = false;
while ( !frameComplete ) { while ( !frameComplete ) {
@ -217,6 +201,7 @@ int FfmpegCamera::Capture( Image &image ) {
) { ) {
Info( "av_read_frame returned \"%s\". Reopening stream.", errbuf ); Info( "av_read_frame returned \"%s\". Reopening stream.", errbuf );
ReopenFfmpeg(); ReopenFfmpeg();
continue;
} }
Error( "Unable to read packet from stream %d: error %d \"%s\".", packet.stream_index, avResult, errbuf ); Error( "Unable to read packet from stream %d: error %d \"%s\".", packet.stream_index, avResult, errbuf );
@ -292,7 +277,7 @@ int FfmpegCamera::Capture( Image &image ) {
directbuffer = image.WriteBuffer(width, height, colours, subpixelorder); directbuffer = image.WriteBuffer(width, height, colours, subpixelorder);
if ( directbuffer == NULL ) { if ( directbuffer == NULL ) {
Error("Failed requesting writeable buffer for the captured image."); Error("Failed requesting writeable buffer for the captured image.");
return (-1); return -1;
} }
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0) #if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
@ -304,8 +289,10 @@ int FfmpegCamera::Capture( Image &image ) {
#endif #endif
#if HAVE_LIBSWSCALE #if HAVE_LIBSWSCALE
if ( sws_scale(mConvertContext, mRawFrame->data, mRawFrame->linesize, 0, mVideoCodecContext->height, mFrame->data, mFrame->linesize) < 0 ) if ( sws_scale(mConvertContext, mRawFrame->data, mRawFrame->linesize, 0, mVideoCodecContext->height, mFrame->data, mFrame->linesize) < 0 ) {
Fatal("Unable to convert raw format %u to target format %u at frame %d", mVideoCodecContext->pix_fmt, imagePixFormat, frameCount); Error("Unable to convert raw format %u to target format %u at frame %d", mVideoCodecContext->pix_fmt, imagePixFormat, frameCount);
return -1;
}
#else // HAVE_LIBSWSCALE #else // HAVE_LIBSWSCALE
Fatal("You must compile ffmpeg with the --enable-swscale option to use ffmpeg cameras"); Fatal("You must compile ffmpeg with the --enable-swscale option to use ffmpeg cameras");
#endif // HAVE_LIBSWSCALE #endif // HAVE_LIBSWSCALE
@ -327,10 +314,10 @@ int FfmpegCamera::PostCapture() {
int FfmpegCamera::OpenFfmpeg() { int FfmpegCamera::OpenFfmpeg() {
Debug ( 2, "OpenFfmpeg called." ); Debug(2, "OpenFfmpeg called.");
uint32_t last_event_id = monitor->GetLastEventId() ; uint32_t last_event_id = monitor->GetLastEventId() ;
uint32_t video_writer_event_id = monitor->GetVideoWriterEventId(); uint32_t video_writer_event_id = monitor->GetVideoWriterEventId();
Debug(2, "last_event(%d), our current (%d)", last_event_id, video_writer_event_id ); Debug(2, "last_event(%d), our current (%d)", last_event_id, video_writer_event_id);
int ret; int ret;
@ -369,8 +356,6 @@ int FfmpegCamera::OpenFfmpeg() {
Debug ( 1, "Calling avformat_open_input for %s", mPath.c_str() ); Debug ( 1, "Calling avformat_open_input for %s", mPath.c_str() );
mFormatContext = avformat_alloc_context( ); mFormatContext = avformat_alloc_context( );
//mFormatContext->interrupt_callback.callback = FfmpegInterruptCallback;
//mFormatContext->interrupt_callback.opaque = this;
// Speed up find_stream_info // Speed up find_stream_info
//FIXME can speed up initial analysis but need sensible parameters... //FIXME can speed up initial analysis but need sensible parameters...
//mFormatContext->probesize = 32; //mFormatContext->probesize = 32;
@ -380,7 +365,7 @@ int FfmpegCamera::OpenFfmpeg() {
#endif #endif
{ {
mIsOpening = false; mIsOpening = false;
Error( "Unable to open input %s due to: %s", mPath.c_str(), strerror(errno) ); Error("Unable to open input %s due to: %s", mPath.c_str(), strerror(errno));
return -1; return -1;
} }
AVDictionaryEntry *e=NULL; AVDictionaryEntry *e=NULL;
@ -391,19 +376,19 @@ int FfmpegCamera::OpenFfmpeg() {
mIsOpening = false; mIsOpening = false;
Debug ( 1, "Opened input" ); Debug ( 1, "Opened input" );
Info( "Stream open %s", mPath.c_str() ); Info( "Stream open %s, parsing streams...", mPath.c_str() );
#if !LIBAVFORMAT_VERSION_CHECK(53, 6, 0, 6, 0) #if !LIBAVFORMAT_VERSION_CHECK(53, 6, 0, 6, 0)
Debug ( 1, "Calling av_find_stream_info" ); Debug(4, "Calling av_find_stream_info");
if ( av_find_stream_info( mFormatContext ) < 0 ) if ( av_find_stream_info( mFormatContext ) < 0 )
#else #else
Debug ( 1, "Calling avformat_find_stream_info" ); Debug(4, "Calling avformat_find_stream_info");
if ( avformat_find_stream_info( mFormatContext, 0 ) < 0 ) if ( avformat_find_stream_info( mFormatContext, 0 ) < 0 )
#endif #endif
Fatal( "Unable to find stream info from %s due to: %s", mPath.c_str(), strerror(errno) ); Fatal("Unable to find stream info from %s due to: %s", mPath.c_str(), strerror(errno));
startTime = av_gettime();//FIXME here or after find_Stream_info startTime = av_gettime();//FIXME here or after find_Stream_info
Debug ( 1, "Got stream info" ); Debug(4, "Got stream info");
// Find first video stream present // Find first video stream present
// The one we want Might not be the first // The one we want Might not be the first
@ -448,11 +433,11 @@ int FfmpegCamera::OpenFfmpeg() {
if ( mAudioStreamId == -1 ) if ( mAudioStreamId == -1 )
Debug( 3, "Unable to locate audio stream in %s", mPath.c_str() ); Debug( 3, "Unable to locate audio stream in %s", mPath.c_str() );
Debug ( 3, "Found video stream at index %d", mVideoStreamId ); Debug(3, "Found video stream at index %d", mVideoStreamId);
Debug ( 3, "Found audio stream at index %d", mAudioStreamId ); Debug(3, "Found audio stream at index %d", mAudioStreamId);
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
mVideoCodecContext = avcodec_alloc_context3( NULL ); mVideoCodecContext = avcodec_alloc_context3(NULL);
avcodec_parameters_to_context( mVideoCodecContext, mFormatContext->streams[mVideoStreamId]->codecpar ); avcodec_parameters_to_context( mVideoCodecContext, mFormatContext->streams[mVideoStreamId]->codecpar );
#else #else
mVideoCodecContext = mFormatContext->streams[mVideoStreamId]->codec; mVideoCodecContext = mFormatContext->streams[mVideoStreamId]->codec;
@ -505,7 +490,7 @@ int FfmpegCamera::OpenFfmpeg() {
Debug( 1, "Input stream appears to be h265. The stored event file may not be viewable in browser." ); Debug( 1, "Input stream appears to be h265. The stored event file may not be viewable in browser." );
} else { } else {
#endif #endif
Error( "Input stream is not h264. The stored event file may not be viewable in browser." ); Warning( "Input stream is not h264. The stored event file may not be viewable in browser." );
#ifdef AV_CODEC_ID_H265 #ifdef AV_CODEC_ID_H265
} }
#endif #endif
@ -514,7 +499,8 @@ int FfmpegCamera::OpenFfmpeg() {
if ( (!mVideoCodec) and ( (mVideoCodec = avcodec_find_decoder(mVideoCodecContext->codec_id)) == NULL ) ) { if ( (!mVideoCodec) and ( (mVideoCodec = avcodec_find_decoder(mVideoCodecContext->codec_id)) == NULL ) ) {
// Try and get the codec from the codec context // Try and get the codec from the codec context
Fatal("Can't find codec for video stream from %s", mPath.c_str()); Error("Can't find codec for video stream from %s", mPath.c_str());
return -1;
} else { } else {
Debug(1, "Video Found decoder"); Debug(1, "Video Found decoder");
zm_dump_stream_format(mFormatContext, mVideoStreamId, 0, 0); zm_dump_stream_format(mFormatContext, mVideoStreamId, 0, 0);
@ -530,7 +516,8 @@ int FfmpegCamera::OpenFfmpeg() {
while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) { while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
Warning( "Option %s not recognized by ffmpeg", e->key); Warning( "Option %s not recognized by ffmpeg", e->key);
} }
Fatal( "Unable to open codec for video stream from %s", mPath.c_str() ); Error( "Unable to open codec for video stream from %s", mPath.c_str() );
return -1;
} else { } else {
AVDictionaryEntry *e = NULL; AVDictionaryEntry *e = NULL;
@ -557,18 +544,20 @@ int FfmpegCamera::OpenFfmpeg() {
} else { } else {
Debug(1, "Audio Found decoder"); Debug(1, "Audio Found decoder");
zm_dump_stream_format(mFormatContext, mAudioStreamId, 0, 0); zm_dump_stream_format(mFormatContext, mAudioStreamId, 0, 0);
// Open the codec // Open the codec
#if !LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 8, 0) #if !LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 8, 0)
Debug ( 1, "Calling avcodec_open" ); Debug ( 1, "Calling avcodec_open" );
if ( avcodec_open(mAudioCodecContext, mAudioCodec) < 0 ) if ( avcodec_open(mAudioCodecContext, mAudioCodec) < 0 ) {
#else #else
Debug ( 1, "Calling avcodec_open2" ); Debug ( 1, "Calling avcodec_open2" );
if ( avcodec_open2(mAudioCodecContext, mAudioCodec, 0) < 0 ) if ( avcodec_open2(mAudioCodecContext, mAudioCodec, 0) < 0 ) {
#endif #endif
Fatal( "Unable to open codec for video stream from %s", mPath.c_str() ); Error( "Unable to open codec for video stream from %s", mPath.c_str() );
} return -1;
Debug ( 1, "Opened audio codec" ); }
} Debug(2, "Opened audio codec");
} // end if find decoder
} // end if have audio_context
// Allocate space for the native video frame // Allocate space for the native video frame
mRawFrame = zm_av_frame_alloc(); mRawFrame = zm_av_frame_alloc();
@ -576,10 +565,12 @@ int FfmpegCamera::OpenFfmpeg() {
// Allocate space for the converted video frame // Allocate space for the converted video frame
mFrame = zm_av_frame_alloc(); mFrame = zm_av_frame_alloc();
if ( mRawFrame == NULL || mFrame == NULL ) if ( mRawFrame == NULL || mFrame == NULL ) {
Fatal( "Unable to allocate frame for %s", mPath.c_str() ); Error("Unable to allocate frame for %s", mPath.c_str());
return -1;
}
Debug ( 1, "Allocated frames" ); Debug( 3, "Allocated frames");
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0) #if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
int pSize = av_image_get_buffer_size( imagePixFormat, width, height,1 ); int pSize = av_image_get_buffer_size( imagePixFormat, width, height,1 );
@ -588,19 +579,22 @@ int FfmpegCamera::OpenFfmpeg() {
#endif #endif
if ( (unsigned int)pSize != imagesize ) { if ( (unsigned int)pSize != imagesize ) {
Fatal("Image size mismatch. Required: %d Available: %d",pSize,imagesize); Error("Image size mismatch. Required: %d Available: %d",pSize,imagesize);
return -1;
} }
Debug ( 1, "Validated imagesize" ); Debug(4, "Validated imagesize");
#if HAVE_LIBSWSCALE #if HAVE_LIBSWSCALE
Debug ( 1, "Calling sws_isSupportedInput" ); Debug(1, "Calling sws_isSupportedInput");
if ( !sws_isSupportedInput(mVideoCodecContext->pix_fmt) ) { if ( !sws_isSupportedInput(mVideoCodecContext->pix_fmt) ) {
Fatal("swscale does not support the codec format: %c%c%c%c", (mVideoCodecContext->pix_fmt)&0xff, ((mVideoCodecContext->pix_fmt >> 8)&0xff), ((mVideoCodecContext->pix_fmt >> 16)&0xff), ((mVideoCodecContext->pix_fmt >> 24)&0xff)); Error("swscale does not support the codec format: %c%c%c%c", (mVideoCodecContext->pix_fmt)&0xff, ((mVideoCodecContext->pix_fmt >> 8)&0xff), ((mVideoCodecContext->pix_fmt >> 16)&0xff), ((mVideoCodecContext->pix_fmt >> 24)&0xff));
return -1;
} }
if ( !sws_isSupportedOutput(imagePixFormat) ) { if ( !sws_isSupportedOutput(imagePixFormat) ) {
Fatal("swscale does not support the target format: %c%c%c%c",(imagePixFormat)&0xff,((imagePixFormat>>8)&0xff),((imagePixFormat>>16)&0xff),((imagePixFormat>>24)&0xff)); Error("swscale does not support the target format: %c%c%c%c",(imagePixFormat)&0xff,((imagePixFormat>>8)&0xff),((imagePixFormat>>16)&0xff),((imagePixFormat>>24)&0xff));
return -1;
} }
mConvertContext = sws_getContext(mVideoCodecContext->width, mConvertContext = sws_getContext(mVideoCodecContext->width,
@ -609,8 +603,10 @@ int FfmpegCamera::OpenFfmpeg() {
width, height, width, height,
imagePixFormat, SWS_BICUBIC, NULL, imagePixFormat, SWS_BICUBIC, NULL,
NULL, NULL); NULL, NULL);
if ( mConvertContext == NULL ) if ( mConvertContext == NULL ) {
Fatal( "Unable to create conversion context for %s", mPath.c_str() ); Error( "Unable to create conversion context for %s", mPath.c_str() );
return -1;
}
#else // HAVE_LIBSWSCALE #else // HAVE_LIBSWSCALE
Fatal( "You must compile ffmpeg with the --enable-swscale option to use ffmpeg cameras" ); Fatal( "You must compile ffmpeg with the --enable-swscale option to use ffmpeg cameras" );
#endif // HAVE_LIBSWSCALE #endif // HAVE_LIBSWSCALE
@ -628,19 +624,8 @@ int FfmpegCamera::ReopenFfmpeg() {
Debug(2, "ReopenFfmpeg called."); Debug(2, "ReopenFfmpeg called.");
#if THREAD
mCanCapture = false;
if ( pthread_create( &mReopenThread, NULL, ReopenFfmpegThreadCallback, (void*) this) != 0 ) {
// Log a fatal error and exit the process.
Fatal( "ReopenFfmpeg failed to create worker thread." );
}
#else
CloseFfmpeg(); CloseFfmpeg();
OpenFfmpeg(); return OpenFfmpeg();
#endif
return 0;
} }
int FfmpegCamera::CloseFfmpeg() { int FfmpegCamera::CloseFfmpeg() {
@ -690,45 +675,7 @@ int FfmpegCamera::CloseFfmpeg() {
} }
return 0; return 0;
} } // end FfmpegCamera::Close
int FfmpegCamera::FfmpegInterruptCallback(void *ctx) {
Debug(3,"FfmpegInteruptCallback");
FfmpegCamera* camera = reinterpret_cast<FfmpegCamera*>(ctx);
if ( camera->mIsOpening ) {
int now = time(NULL);
if ( (now - camera->mOpenStart) > config.ffmpeg_open_timeout ) {
Error( "Open video took more than %d seconds.", config.ffmpeg_open_timeout );
return 1;
}
}
return 0;
}
void *FfmpegCamera::ReopenFfmpegThreadCallback(void *ctx){
Debug(3,"FfmpegReopenThreadtCallback");
if ( ctx == NULL ) return NULL;
FfmpegCamera* camera = reinterpret_cast<FfmpegCamera*>(ctx);
while (1) {
// Close current stream.
camera->CloseFfmpeg();
// Sleep if necessary to not reconnect too fast.
int wait = config.ffmpeg_open_timeout - (time(NULL) - camera->mOpenStart);
wait = wait < 0 ? 0 : wait;
if ( wait > 0 ) {
Debug( 1, "Sleeping %d seconds before reopening stream.", wait );
sleep(wait);
}
if ( camera->OpenFfmpeg() == 0 ) {
return NULL;
}
}
}
//Function to handle capture and store //Function to handle capture and store
int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event_file ) { int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event_file ) {
@ -738,20 +685,6 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
int ret; int ret;
static char errbuf[AV_ERROR_MAX_STRING_SIZE]; static char errbuf[AV_ERROR_MAX_STRING_SIZE];
// If the reopen thread has a value, but mCanCapture != 0, then we have just reopened
// the connection to the ffmpeg device, and we can clean up the thread.
if ( mReopenThread != 0 ) {
void *retval = 0;
ret = pthread_join(mReopenThread, &retval);
if (ret != 0){
Error("Could not join reopen thread.");
}
Info( "Successfully reopened stream." );
mReopenThread = 0;
}
int frameComplete = false; int frameComplete = false;
while ( ! frameComplete ) { while ( ! frameComplete ) {
av_init_packet( &packet ); av_init_packet( &packet );
@ -995,8 +928,9 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
if (sws_scale(mConvertContext, mRawFrame->data, mRawFrame->linesize, if (sws_scale(mConvertContext, mRawFrame->data, mRawFrame->linesize,
0, mVideoCodecContext->height, mFrame->data, mFrame->linesize) < 0) { 0, mVideoCodecContext->height, mFrame->data, mFrame->linesize) < 0) {
Fatal("Unable to convert raw format %u to target format %u at frame %d", Error("Unable to convert raw format %u to target format %u at frame %d",
mVideoCodecContext->pix_fmt, imagePixFormat, frameCount); mVideoCodecContext->pix_fmt, imagePixFormat, frameCount);
return -1;
} }
frameCount++; frameCount++;

View File

@ -76,12 +76,9 @@ class FfmpegCamera : public Camera {
int OpenFfmpeg(); int OpenFfmpeg();
int ReopenFfmpeg(); int ReopenFfmpeg();
int CloseFfmpeg(); int CloseFfmpeg();
static int FfmpegInterruptCallback(void *ctx);
static void* ReopenFfmpegThreadCallback(void *ctx);
bool mIsOpening; bool mIsOpening;
bool mCanCapture; bool mCanCapture;
int mOpenStart; int mOpenStart;
pthread_t mReopenThread;
#endif // HAVE_LIBAVFORMAT #endif // HAVE_LIBAVFORMAT
VideoStore *videoStore; VideoStore *videoStore;

View File

@ -479,12 +479,12 @@ Debug(2,"last_write_index(%d), last_write_time(%d)", shared_data->last_write_ind
while( while(
( shared_data->last_write_index == (unsigned int)image_buffer_count ) ( shared_data->last_write_index == (unsigned int)image_buffer_count )
&& &&
( shared_data->last_write_time == 0) ( shared_data->last_write_time == 0 )
&& &&
( !zm_terminate ) ( !zm_terminate )
) { ) {
Warning( "Waiting for capture daemon" ); Debug(1, "Waiting for capture daemon");
sleep( 1 ); sleep(1);
} }
ref_image.Assign( width, height, camera->Colours(), camera->SubpixelOrder(), image_buffer[shared_data->last_write_index].image->Buffer(), camera->ImageSize()); ref_image.Assign( width, height, camera->Colours(), camera->SubpixelOrder(), image_buffer[shared_data->last_write_index].image->Buffer(), camera->ImageSize());
adaptive_skip = true; adaptive_skip = true;
@ -1205,7 +1205,7 @@ bool Monitor::Analyse() {
fps = double(fps_report_interval)/(now.tv_sec - last_fps_time); fps = double(fps_report_interval)/(now.tv_sec - last_fps_time);
Info( "%s: %d - Analysing at %.2f fps", name, image_count, fps ); Info( "%s: %d - Analysing at %.2f fps", name, image_count, fps );
static char sql[ZM_SQL_SML_BUFSIZ]; static char sql[ZM_SQL_SML_BUFSIZ];
snprintf( sql, sizeof(sql), "INSERT INTO Monitor_Status (Id,AnalysisFPS) VALUES (%d, %.2lf) ON DUPLICATE KEY UPDATE AnalysisFPS = %.2lf", id, fps, fps ); snprintf( sql, sizeof(sql), "INSERT INTO Monitor_Status (MonitorId,AnalysisFPS) VALUES (%d, %.2lf) ON DUPLICATE KEY UPDATE AnalysisFPS = %.2lf", id, fps, fps );
if ( mysql_query( &dbconn, sql ) ) { if ( mysql_query( &dbconn, sql ) ) {
Error( "Can't run query: %s", mysql_error( &dbconn ) ); Error( "Can't run query: %s", mysql_error( &dbconn ) );
} }
@ -1937,7 +1937,7 @@ int Monitor::LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose
} }
Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame ); Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
col++; col++;
const char *method = dbrow[col]; col++; const char *method = dbrow[col] ? dbrow[col] : ""; col++;
int width = atoi(dbrow[col]); col++; int width = atoi(dbrow[col]); col++;
int height = atoi(dbrow[col]); col++; int height = atoi(dbrow[col]); col++;
@ -2438,7 +2438,7 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose
const char *linked_monitors = dbrow[col] ? dbrow[col] : ""; col++; const char *linked_monitors = dbrow[col] ? dbrow[col] : ""; col++;
const char *path = dbrow[col]; col++; const char *path = dbrow[col]; col++;
const char *method = dbrow[col]; col++; const char *method = dbrow[col] ? dbrow[col] : ""; col++;
const char *options = dbrow[col] ? dbrow[col] : ""; col++; const char *options = dbrow[col] ? dbrow[col] : ""; col++;
int width = atoi(dbrow[col]); col++; int width = atoi(dbrow[col]); col++;
@ -3022,7 +3022,7 @@ Debug(4, "Return from Capture (%d)", captureResult);
Info( "%s: images:%d - Capturing at %.2lf fps", name, image_count, fps ); Info( "%s: images:%d - Capturing at %.2lf fps", name, image_count, fps );
last_fps_time = now; last_fps_time = now;
static char sql[ZM_SQL_SML_BUFSIZ]; static char sql[ZM_SQL_SML_BUFSIZ];
snprintf( sql, sizeof(sql), "INSERT INTO Monitor_Status (Id,CaptureFPS) VALUES (%d, %.2lf) ON DUPLICATE KEY UPDATE CaptureFPS = %.2lf", id, fps, fps ); snprintf( sql, sizeof(sql), "INSERT INTO Monitor_Status (MonitorId,CaptureFPS) VALUES (%d, %.2lf) ON DUPLICATE KEY UPDATE CaptureFPS = %.2lf", id, fps, fps );
if ( mysql_query( &dbconn, sql ) ) { if ( mysql_query( &dbconn, sql ) ) {
Error( "Can't run query: %s", mysql_error( &dbconn ) ); Error( "Can't run query: %s", mysql_error( &dbconn ) );
} }

View File

@ -338,7 +338,7 @@ void MonitorStream::processCommand( const CmdMsg *msg ) {
//exit( -1 ); //exit( -1 );
} }
} }
Debug(2, "NUmber of bytes sent: (%d)", nbytes ); 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 // quit after sending a status, if this was a quit request
if ( (MsgCommand)msg->msg_data[0]==CMD_QUIT ) { if ( (MsgCommand)msg->msg_data[0]==CMD_QUIT ) {
@ -396,7 +396,7 @@ bool MonitorStream::sendFrame( const char *filepath, struct timeval *timestamp )
int frameSendTime = tvDiffMsec( frameStartTime, frameEndTime ); int frameSendTime = tvDiffMsec( frameStartTime, frameEndTime );
if ( frameSendTime > 1000/maxfps ) { if ( frameSendTime > 1000/maxfps ) {
maxfps /= 2; maxfps /= 2;
Error( "Frame send time %d msec too slow, throttling maxfps to %.2f", frameSendTime, maxfps ); Info( "Frame send time %d msec too slow, throttling maxfps to %.2f", frameSendTime, maxfps );
} }
last_frame_sent = TV_2_FLOAT( now ); last_frame_sent = TV_2_FLOAT( now );
@ -579,7 +579,6 @@ void MonitorStream::runStream() {
gettimeofday( &now, NULL ); gettimeofday( &now, NULL );
if ( connkey ) { if ( connkey ) {
Debug(2, "checking command Queue for connkey: %d", connkey );
while(checkCommandQueue()) { while(checkCommandQueue()) {
Debug(2, "Have checking command Queue for connkey: %d", connkey ); Debug(2, "Have checking command Queue for connkey: %d", connkey );
got_command = true; got_command = true;
@ -664,7 +663,7 @@ Debug(2, "Have checking command Queue for connkey: %d", connkey );
if ( last_read_index != monitor->shared_data->last_write_index ) { if ( last_read_index != monitor->shared_data->last_write_index ) {
int index = monitor->shared_data->last_write_index % monitor->image_buffer_count; // % shouldn't be neccessary int index = monitor->shared_data->last_write_index % monitor->image_buffer_count; // % shouldn't be neccessary
last_read_index = monitor->shared_data->last_write_index; last_read_index = monitor->shared_data->last_write_index;
Debug( 1, "index: %d: frame_mod: %d frame count: %d", index, frame_mod, frame_count ); Debug( 3, "index: %d: frame_mod: %d frame count: %d", index, frame_mod, frame_count );
if ( (frame_mod == 1) || ((frame_count%frame_mod) == 0) ) { if ( (frame_mod == 1) || ((frame_count%frame_mod) == 0) ) {
if ( !paused && !delayed ) { if ( !paused && !delayed ) {
// Send the next frame // Send the next frame
@ -713,11 +712,11 @@ Debug(2, "Have checking command Queue for connkey: %d", connkey );
} // end if buffered playback } // end if buffered playback
frame_count++; frame_count++;
} else { } else {
Debug(2,"Waiting for capture"); Debug(5,"Waiting for capture");
} // end if ( (unsigned int)last_read_index != monitor->shared_data->last_write_index ) } // end if ( (unsigned int)last_read_index != monitor->shared_data->last_write_index )
unsigned long sleep_time = (unsigned long)((1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2))); unsigned long sleep_time = (unsigned long)((1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2)));
Debug(2, "Sleeping for (%d)", sleep_time); Debug(4, "Sleeping for (%d)", sleep_time);
usleep( sleep_time ); usleep( sleep_time );
if ( ttl ) { if ( ttl ) {
if ( (now.tv_sec - stream_start_time) > ttl ) { if ( (now.tv_sec - stream_start_time) > ttl ) {

View File

@ -99,6 +99,7 @@ void VideoStream::SetupFormat( ) {
} }
#endif #endif
} else { } else {
Debug(1,"No allocating priv_data");
s->priv_data = NULL; s->priv_data = NULL;
} }
@ -120,7 +121,6 @@ void VideoStream::SetupCodec( int colours, int subpixelorder, int width, int hei
/* ffmpeg format matching */ /* ffmpeg format matching */
switch(colours) { switch(colours) {
case ZM_COLOUR_RGB24: case ZM_COLOUR_RGB24:
{
if(subpixelorder == ZM_SUBPIX_ORDER_BGR) { if(subpixelorder == ZM_SUBPIX_ORDER_BGR) {
/* BGR subpixel order */ /* BGR subpixel order */
pf = AV_PIX_FMT_BGR24; pf = AV_PIX_FMT_BGR24;
@ -129,9 +129,7 @@ void VideoStream::SetupCodec( int colours, int subpixelorder, int width, int hei
pf = AV_PIX_FMT_RGB24; pf = AV_PIX_FMT_RGB24;
} }
break; break;
}
case ZM_COLOUR_RGB32: case ZM_COLOUR_RGB32:
{
if(subpixelorder == ZM_SUBPIX_ORDER_ARGB) { if(subpixelorder == ZM_SUBPIX_ORDER_ARGB) {
/* ARGB subpixel order */ /* ARGB subpixel order */
pf = AV_PIX_FMT_ARGB; pf = AV_PIX_FMT_ARGB;
@ -146,7 +144,6 @@ void VideoStream::SetupCodec( int colours, int subpixelorder, int width, int hei
pf = AV_PIX_FMT_RGBA; pf = AV_PIX_FMT_RGBA;
} }
break; break;
}
case ZM_COLOUR_GRAY8: case ZM_COLOUR_GRAY8:
pf = AV_PIX_FMT_GRAY8; pf = AV_PIX_FMT_GRAY8;
break; break;
@ -159,6 +156,7 @@ void VideoStream::SetupCodec( int colours, int subpixelorder, int width, int hei
// RTP must have a packet_size. // RTP must have a packet_size.
// Not sure what this value should be really... // Not sure what this value should be really...
ofc->packet_size = width*height; ofc->packet_size = width*height;
Debug(1,"Setting packet_size to %d", ofc->packet_size);
if ( of->video_codec == AV_CODEC_ID_NONE ) { if ( of->video_codec == AV_CODEC_ID_NONE ) {
// RTP does not have a default codec in ffmpeg <= 0.8. // RTP does not have a default codec in ffmpeg <= 0.8.
@ -171,6 +169,7 @@ void VideoStream::SetupCodec( int colours, int subpixelorder, int width, int hei
AVCodec *a = avcodec_find_encoder_by_name(codec_name); AVCodec *a = avcodec_find_encoder_by_name(codec_name);
if ( a ) { if ( a ) {
codec_id = a->id; codec_id = a->id;
Debug( 1, "Using codec \"%s\"", codec_name );
} else { } else {
#if (LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 11, 0) && (LIBAVFORMAT_VERSION_MICRO >= 100)) #if (LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 11, 0) && (LIBAVFORMAT_VERSION_MICRO >= 100))
Debug( 1, "Could not find codec \"%s\". Using default \"%s\"", codec_name, avcodec_get_name( codec_id ) ); Debug( 1, "Could not find codec \"%s\". Using default \"%s\"", codec_name, avcodec_get_name( codec_id ) );
@ -209,13 +208,13 @@ void VideoStream::SetupCodec( int colours, int subpixelorder, int width, int hei
Fatal( "Could not alloc stream" ); Fatal( "Could not alloc stream" );
return; return;
} }
Debug( 1, "Allocated stream (%d) !=? (%d)", ost->id , ofc->nb_streams - 1 );
ost->id = ofc->nb_streams - 1; ost->id = ofc->nb_streams - 1;
Debug( 1, "Allocated stream" );
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
codec_context = avcodec_alloc_context3(NULL);
avcodec_parameters_to_context(codec_context, ost->codecpar); codec_context = avcodec_alloc_context3(NULL);
//avcodec_parameters_to_context(codec_context, ost->codecpar);
#else #else
codec_context = ost->codec; codec_context = ost->codec;
#endif #endif
@ -223,7 +222,7 @@ void VideoStream::SetupCodec( int colours, int subpixelorder, int width, int hei
codec_context->codec_id = codec->id; codec_context->codec_id = codec->id;
codec_context->codec_type = codec->type; codec_context->codec_type = codec->type;
codec_context->pix_fmt = strcmp( "mjpeg", ofc->oformat->name ) == 0 ? AV_PIX_FMT_YUVJ422P : AV_PIX_FMT_YUV420P; codec_context->pix_fmt = strcmp("mjpeg", ofc->oformat->name) == 0 ? AV_PIX_FMT_YUVJ422P : AV_PIX_FMT_YUV420P;
if ( bitrate <= 100 ) { if ( bitrate <= 100 ) {
// Quality based bitrate control (VBR). Scale is 1..31 where 1 is best. // Quality based bitrate control (VBR). Scale is 1..31 where 1 is best.
// This gets rid of artifacts in the beginning of the movie; and well, even quality. // This gets rid of artifacts in the beginning of the movie; and well, even quality.
@ -246,8 +245,11 @@ void VideoStream::SetupCodec( int colours, int subpixelorder, int width, int hei
identically 1. */ identically 1. */
codec_context->time_base.den = frame_rate; codec_context->time_base.den = frame_rate;
codec_context->time_base.num = 1; codec_context->time_base.num = 1;
ost->time_base.den = frame_rate;
ost->time_base.num = 1;
Debug( 1, "Will encode in %d fps.", codec_context->time_base.den ); Debug( 1, "Will encode in %d fps. %dx%d", codec_context->time_base.den, width, height );
/* emit one intra frame every second */ /* emit one intra frame every second */
codec_context->gop_size = frame_rate; codec_context->gop_size = frame_rate;
@ -258,6 +260,10 @@ void VideoStream::SetupCodec( int colours, int subpixelorder, int width, int hei
codec_context->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; codec_context->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
#else #else
codec_context->flags |= CODEC_FLAG_GLOBAL_HEADER; codec_context->flags |= CODEC_FLAG_GLOBAL_HEADER;
#endif
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
avcodec_parameters_from_context(ost->codecpar, codec_context);
zm_dump_codecpar(ost->codecpar);
#endif #endif
} else { } else {
Fatal( "of->video_codec == AV_CODEC_ID_NONE" ); Fatal( "of->video_codec == AV_CODEC_ID_NONE" );
@ -271,7 +277,7 @@ const char *VideoStream::MimeType( ) const {
for ( unsigned int i = 0; i < sizeof (mime_data) / sizeof (*mime_data); i++ ) { for ( unsigned int i = 0; i < sizeof (mime_data) / sizeof (*mime_data); i++ ) {
if ( strcmp( format, mime_data[i].format ) == 0 ) { if ( strcmp( format, mime_data[i].format ) == 0 ) {
Debug( 1, "MimeType is \"%s\"", mime_data[i].mime_type ); Debug( 1, "MimeType is \"%s\"", mime_data[i].mime_type );
return ( mime_data[i].mime_type); return mime_data[i].mime_type;
} }
} }
const char *mime_type = of->mime_type; const char *mime_type = of->mime_type;
@ -282,9 +288,9 @@ const char *VideoStream::MimeType( ) const {
Warning( "Unable to determine mime type for '%s' format, using '%s' as default", format, mime_type ); Warning( "Unable to determine mime type for '%s' format, using '%s' as default", format, mime_type );
} }
Debug( 1, "MimeType is \"%s\"", mime_type ); Debug(1, "MimeType is \"%s\"", mime_type );
return ( mime_type); return mime_type;
} }
void VideoStream::OpenStream( ) { void VideoStream::OpenStream( ) {
@ -293,11 +299,13 @@ void VideoStream::OpenStream( ) {
/* now that all the parameters are set, we can open the /* now that all the parameters are set, we can open the
video codecs and allocate the necessary encode buffers */ video codecs and allocate the necessary encode buffers */
if ( ost ) { if ( ost ) {
Debug(1,"Opening codec");
/* open the codec */ /* open the codec */
#if !LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 8, 0) #if !LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 8, 0)
if ( (ret = avcodec_open( codec_context, codec )) < 0 ) if ( (ret = avcodec_open(codec_context, codec)) < 0 )
#else #else
if ( (ret = avcodec_open2( codec_context, codec, 0 )) < 0 ) if ( (ret = avcodec_open2(codec_context, codec, 0)) < 0 )
#endif #endif
{ {
Fatal( "Could not open codec. Error code %d \"%s\"", ret, av_err2str(ret) ); Fatal( "Could not open codec. Error code %d \"%s\"", ret, av_err2str(ret) );
@ -310,6 +318,9 @@ void VideoStream::OpenStream( ) {
if ( !opicture ) { if ( !opicture ) {
Panic( "Could not allocate opicture" ); Panic( "Could not allocate opicture" );
} }
opicture->width = codec_context->width;
opicture->height = codec_context->height;
opicture->format = codec_context->pix_fmt;
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0) #if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
int size = av_image_get_buffer_size( codec_context->pix_fmt, codec_context->width, codec_context->height, 1 ); int size = av_image_get_buffer_size( codec_context->pix_fmt, codec_context->width, codec_context->height, 1 );
@ -362,7 +373,7 @@ void VideoStream::OpenStream( ) {
tmp_opicture_buf, pf, codec_context->width, codec_context->height ); tmp_opicture_buf, pf, codec_context->width, codec_context->height );
#endif #endif
} }
} } // end if ost
/* open the output file, if needed */ /* open the output file, if needed */
if ( !(of->flags & AVFMT_NOFILE) ) { if ( !(of->flags & AVFMT_NOFILE) ) {
@ -384,8 +395,8 @@ void VideoStream::OpenStream( ) {
video_outbuf = NULL; video_outbuf = NULL;
#if LIBAVFORMAT_VERSION_CHECK(57, 0, 0, 0, 0) #if LIBAVFORMAT_VERSION_CHECK(57, 0, 0, 0, 0)
if (codec_context->codec_type == AVMEDIA_TYPE_VIDEO && if (codec_context->codec_type == AVMEDIA_TYPE_VIDEO &&
codec_context->codec_id == AV_CODEC_ID_RAWVIDEO) { codec_context->codec_id == AV_CODEC_ID_RAWVIDEO) {
#else #else
if ( !(of->flags & AVFMT_RAWPICTURE) ) { if ( !(of->flags & AVFMT_RAWPICTURE) ) {
#endif #endif
@ -408,7 +419,7 @@ void VideoStream::OpenStream( ) {
#if !LIBAVFORMAT_VERSION_CHECK(53, 2, 0, 4, 0) #if !LIBAVFORMAT_VERSION_CHECK(53, 2, 0, 4, 0)
ret = av_write_header( ofc ); ret = av_write_header( ofc );
#else #else
ret = avformat_write_header( ofc, NULL ); ret = avformat_write_header(ofc, NULL);
#endif #endif
if ( ret < 0 ) { if ( ret < 0 ) {
@ -451,6 +462,7 @@ VideoStream::VideoStream( const char *in_filename, const char *in_format, int bi
} }
} }
codec_context = NULL;
SetupFormat( ); SetupFormat( );
SetupCodec( colours, subpixelorder, width, height, bitrate, frame_rate ); SetupCodec( colours, subpixelorder, width, height, bitrate, frame_rate );
SetParameters( ); SetParameters( );
@ -466,7 +478,6 @@ VideoStream::VideoStream( const char *in_filename, const char *in_format, int bi
Fatal("pthread_mutex_init failed"); Fatal("pthread_mutex_init failed");
} }
codec_context = NULL;
} }
VideoStream::~VideoStream( ) { VideoStream::~VideoStream( ) {
@ -627,7 +638,6 @@ double VideoStream::ActuallyEncodeFrame( const uint8_t *buffer, int buffer_size,
opicture_ptr->quality = codec_context->global_quality; opicture_ptr->quality = codec_context->global_quality;
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
// Put encoder into flushing mode
avcodec_send_frame(codec_context, opicture_ptr); avcodec_send_frame(codec_context, opicture_ptr);
int ret = avcodec_receive_packet(codec_context, pkt); int ret = avcodec_receive_packet(codec_context, pkt);
if ( ret < 0 ) { if ( ret < 0 ) {

View File

@ -75,7 +75,6 @@ void StreamBase::updateFrameRate( double fps ) {
bool StreamBase::checkCommandQueue() { bool StreamBase::checkCommandQueue() {
if ( sd >= 0 ) { if ( sd >= 0 ) {
Debug(2, "sd is (%d)", sd );
CmdMsg msg; CmdMsg msg;
memset( &msg, 0, sizeof(msg) ); memset( &msg, 0, sizeof(msg) );
int nbytes = recvfrom( sd, &msg, sizeof(msg), MSG_DONTWAIT, 0, 0 ); int nbytes = recvfrom( sd, &msg, sizeof(msg), MSG_DONTWAIT, 0, 0 );

View File

@ -235,7 +235,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
#else #else
avformat_new_stream(oc, (AVCodec *)audio_in_ctx->codec); avformat_new_stream(oc, (AVCodec *)audio_in_ctx->codec);
#endif #endif
if (!audio_out_stream) { if ( !audio_out_stream ) {
Error("Unable to create audio out stream\n"); Error("Unable to create audio out stream\n");
audio_out_stream = NULL; audio_out_stream = NULL;
} else { } else {

View File

@ -223,7 +223,7 @@ int main(int argc, char *argv[]) {
Info("Starting Capture version %s", ZM_VERSION); Info("Starting Capture version %s", ZM_VERSION);
static char sql[ZM_SQL_SML_BUFSIZ]; static char sql[ZM_SQL_SML_BUFSIZ];
for ( int i = 0; i < n_monitors; i ++ ) { for ( int i = 0; i < n_monitors; i ++ ) {
snprintf( sql, sizeof(sql), "REPLACE INTO Monitor_Status (Id, Status ) VALUES ('%d','Running')", monitors[i]->Id() ); snprintf( sql, sizeof(sql), "REPLACE INTO Monitor_Status (MonitorId, Status) VALUES ('%d','Running')", monitors[i]->Id() );
if ( mysql_query( &dbconn, sql ) ) { if ( mysql_query( &dbconn, sql ) ) {
Error( "Can't run query: %s", mysql_error( &dbconn ) ); Error( "Can't run query: %s", mysql_error( &dbconn ) );
} }
@ -238,102 +238,119 @@ int main(int argc, char *argv[]) {
sigaddset(&block_set, SIGUSR1); sigaddset(&block_set, SIGUSR1);
sigaddset(&block_set, SIGUSR2); sigaddset(&block_set, SIGUSR2);
monitors[0]->setStartupTime((time_t)time(NULL));
if ( monitors[0]->PrimeCapture() < 0 ) {
Error("Failed to prime capture of initial monitor");
exit(-1);
}
long *capture_delays = new long[n_monitors];
long *alarm_capture_delays = new long[n_monitors];
long *next_delays = new long[n_monitors];
struct timeval * last_capture_times = new struct timeval[n_monitors];
for ( int i = 0; i < n_monitors; i++ ) {
last_capture_times[i].tv_sec = last_capture_times[i].tv_usec = 0;
capture_delays[i] = monitors[i]->GetCaptureDelay();
alarm_capture_delays[i] = monitors[i]->GetAlarmCaptureDelay();
}
int result = 0; int result = 0;
struct timeval now;
struct DeltaTimeval delta_time;
while ( !zm_terminate ) {
sigprocmask(SIG_BLOCK, &block_set, 0);
for ( int i = 0; i < n_monitors; i++ ) {
long min_delay = MAXINT;
gettimeofday(&now, NULL); while( ! zm_terminate ) {
for ( int j = 0; j < n_monitors; j++ ) { for ( int i = 0; i < n_monitors; i ++ ) {
if ( last_capture_times[j].tv_sec ) { time_t now = (time_t)time(NULL);
DELTA_TIMEVAL(delta_time, now, last_capture_times[j], DT_PREC_3); monitors[i]->setStartupTime(now);
if ( monitors[i]->GetState() == Monitor::ALARM )
next_delays[j] = alarm_capture_delays[j]-delta_time.delta;
else
next_delays[j] = capture_delays[j]-delta_time.delta;
if ( next_delays[j] < 0 )
next_delays[j] = 0;
} else {
next_delays[j] = 0;
}
if ( next_delays[j] <= min_delay ) {
min_delay = next_delays[j];
}
}
if ( next_delays[i] <= min_delay || next_delays[i] <= 0 ) {
if ( monitors[i]->PreCapture() < 0 ) {
Error("Failed to pre-capture monitor %d %d (%d/%d)", monitors[i]->Id(), monitors[i]->Name(), i+1, n_monitors);
zm_terminate = true;
result = -1;
break;
}
if ( monitors[i]->Capture() < 0 ) {
Error("Failed to capture image from monitor %d %s (%d/%d)", monitors[i]->Id(), monitors[i]->Name(), i+1, n_monitors);
zm_terminate = true;
result = -1;
break;
}
if ( monitors[i]->PostCapture() < 0 ) {
Error("Failed to post-capture monitor %d %s (%d/%d)", monitors[i]->Id(), monitors[i]->Name(), i+1, n_monitors);
zm_terminate = true;
result = -1;
break;
}
if ( next_delays[i] > 0 ) {
gettimeofday(&now, NULL);
DELTA_TIMEVAL(delta_time, now, last_capture_times[i], DT_PREC_3);
long sleep_time = next_delays[i]-delta_time.delta;
if ( sleep_time > 0 ) {
usleep(sleep_time*(DT_MAXGRAN/DT_PREC_3));
}
}
gettimeofday(&(last_capture_times[i]), NULL);
} // end if next_delay <= min_delay || next_delays[i] <= 0 )
} // end foreach n_monitors
sigprocmask(SIG_UNBLOCK, &block_set, 0);
if ( zm_reload ) {
for ( int i = 0; i < n_monitors; i++ ) {
monitors[i]->Reload();
}
logTerm();
logInit( log_id_string );
zm_reload = false;
} }
} // end while ! zm_terminate // Outer primary loop, handles connection to camera
if ( monitors[0]->PrimeCapture() < 0 ) {
Error("Failed to prime capture of initial monitor");
sleep(10);
continue;
}
static char sql[ZM_SQL_SML_BUFSIZ];
for ( int i = 0; i < n_monitors; i ++ ) {
snprintf( sql, sizeof(sql), "REPLACE INTO Monitor_Status (MonitorId, Status) VALUES ('%d','Connected')", monitors[i]->Id() );
if ( mysql_query( &dbconn, sql ) ) {
Error( "Can't run query: %s", mysql_error( &dbconn ) );
}
}
long *capture_delays = new long[n_monitors];
long *alarm_capture_delays = new long[n_monitors];
long *next_delays = new long[n_monitors];
struct timeval * last_capture_times = new struct timeval[n_monitors];
for ( int i = 0; i < n_monitors; i++ ) {
last_capture_times[i].tv_sec = last_capture_times[i].tv_usec = 0;
capture_delays[i] = monitors[i]->GetCaptureDelay();
alarm_capture_delays[i] = monitors[i]->GetAlarmCaptureDelay();
}
struct timeval now;
struct DeltaTimeval delta_time;
while ( !zm_terminate ) {
sigprocmask(SIG_BLOCK, &block_set, 0);
for ( int i = 0; i < n_monitors; i++ ) {
long min_delay = MAXINT;
gettimeofday(&now, NULL);
for ( int j = 0; j < n_monitors; j++ ) {
if ( last_capture_times[j].tv_sec ) {
DELTA_TIMEVAL(delta_time, now, last_capture_times[j], DT_PREC_3);
if ( monitors[i]->GetState() == Monitor::ALARM )
next_delays[j] = alarm_capture_delays[j]-delta_time.delta;
else
next_delays[j] = capture_delays[j]-delta_time.delta;
if ( next_delays[j] < 0 )
next_delays[j] = 0;
} else {
next_delays[j] = 0;
}
if ( next_delays[j] <= min_delay ) {
min_delay = next_delays[j];
}
} // end foreach monitor
if ( next_delays[i] <= min_delay || next_delays[i] <= 0 ) {
if ( monitors[i]->PreCapture() < 0 ) {
Error("Failed to pre-capture monitor %d %d (%d/%d)", monitors[i]->Id(), monitors[i]->Name(), i+1, n_monitors);
result = -1;
break;
}
if ( monitors[i]->Capture() < 0 ) {
Error("Failed to capture image from monitor %d %s (%d/%d)", monitors[i]->Id(), monitors[i]->Name(), i+1, n_monitors);
result = -1;
break;
}
if ( monitors[i]->PostCapture() < 0 ) {
Error("Failed to post-capture monitor %d %s (%d/%d)", monitors[i]->Id(), monitors[i]->Name(), i+1, n_monitors);
result = -1;
break;
}
if ( next_delays[i] > 0 ) {
gettimeofday(&now, NULL);
DELTA_TIMEVAL(delta_time, now, last_capture_times[i], DT_PREC_3);
long sleep_time = next_delays[i]-delta_time.delta;
if ( sleep_time > 0 ) {
usleep(sleep_time*(DT_MAXGRAN/DT_PREC_3));
}
}
gettimeofday(&(last_capture_times[i]), NULL);
} // end if next_delay <= min_delay || next_delays[i] <= 0 )
} // end foreach n_monitors
sigprocmask(SIG_UNBLOCK, &block_set, 0);
if ( zm_reload ) {
for ( int i = 0; i < n_monitors; i++ ) {
monitors[i]->Reload();
}
logTerm();
logInit( log_id_string );
zm_reload = false;
}
if ( result < 0 ) {
// Failure, try reconnecting
break;
}
} // end while ! zm_terminate
delete [] alarm_capture_delays;
delete [] capture_delays;
delete [] next_delays;
delete [] last_capture_times;
} // end while ! zm_terminate outer connection loop
for ( int i = 0; i < n_monitors; i++ ) { for ( int i = 0; i < n_monitors; i++ ) {
delete monitors[i]; delete monitors[i];
} }
delete [] monitors; delete [] monitors;
delete [] alarm_capture_delays;
delete [] capture_delays;
delete [] next_delays;
delete [] last_capture_times;
Image::Deinitialise(); Image::Deinitialise();
logTerm(); logTerm();
zmDbClose(); zmDbClose();
return( result ); return result;
} }

View File

@ -1,47 +1,4 @@
# Overview ## Docker Support Files
[Docker](https://www.docker.io/) allows you to quickly spin up application containers, Docker support files have been moved to the zmdockerfiles repo:
which are similar to very lightweight virtual machines. The ZoneMinder Dockerfile will https://github.com/ZoneMinder/zmdockerfiles
start an Ubuntu 12.04 container with MySql, Apache, and PHP properly configured, and
will then compile and install ZoneMinder.
It will also start an SSH server that you can use to log into the container.
This is still a bit of a work in progress.
## How To Use
1. Install [Docker](https://www.docker.io/)
2. Build ZoneMinder container
```sudo docker build -t yourname/zoneminder github.com/ZoneMinder/ZoneMinder```
3. Run it
```CID=$(sudo docker run -d -p 222:22 -p 8080:80 --name zoneminder yourname/zoneminder)```
4. Use it -- you can now SSH to port 222 on your host as user root with password root.
You can also browse to your host on port 8080 to access the zoneminder web interface
## Developing With Docker
If you wish to contribute to ZoneMinder, Docker can be helpful. By re-running
```docker build``` in your working directory, any code modifications you have
made will be pulled into a new container, compiled, and started, all without
modifying your base system.
Development is not totally without annoyances, as any change
to the project will require a full rebuild of all C++. Docker notices that the
directory which has been ADD'ed is now different, and therefore all steps after
the ADD command must be recomputed. A fix for this is to update the Dockerfile to
move the configure and make commands into start.sh, and then use a volume mount
to cache the build directory (I think it's ```/tmp```) on your host filesystem.
This would be really useful for a developer, and would remove the annoying build
problem, but some of the Docker push/pull benefits would be lost.
Docker containers can be both CPU and memory limited, so this can be a practical
method to compile or run multiple development builds of ZoneFinder simultaneously
without taxing your host system.
## Use Cases
## TODO
- Describe how to connect to monitors by mounting devices
- Create a 'development' dockerfile to remove the need to rebuild the entire project
after each small change

View File

@ -1,5 +0,0 @@
[Date]
; Defines the default timezone used by the date functions
; http://php.net/date.timezone
date.timezone = GMT

View File

@ -1,75 +0,0 @@
#!/bin/bash
setup_mysql_first_time(){
if [ "$(ls /var/lib/mysql)" ]; then
return
fi
# Set MySQL in the volume
rm -rf /var/lib/mysql/*
chown -R mysql:mysql /var/lib/mysql
mysqld --initialize-insecure
# Start MySQL
# For Xenial the following won't start mysqld
#/usr/bin/mysqld_safe &
# Use this instead:
service mysql start
# Give MySQL time to wake up
SECONDS_LEFT=120
while true; do
sleep 1
mysqladmin ping
if [ $? -eq 0 ];then
break; # Success
fi
let SECONDS_LEFT=SECONDS_LEFT-1
# If we have waited >120 seconds, give up
# ZM should never have a database that large!
# if $COUNTER -lt 120
if [ $SECONDS_LEFT -eq 0 ];then
return -1;
fi
done
# Create the ZoneMinder database
mysql -u root < db/zm_create.sql
# Add the ZoneMinder DB user
mysql -u root -e "grant insert,select,update,delete,lock tables,alter on zm.* to 'zmuser'@'localhost' identified by 'zmpass';"
# Shut down mysql cleanly:
kill $(cat /var/run/mysqld/mysqld.pid)
sleep 5
}
setup_mysql() {
# To configure MySQL if no container did it before
setup_mysql_first_time
# Add configuration to avoid SQL error when adding monitor
echo "sql_mode=NO_ENGINE_SUBSTITUTION" >> /etc/mysql/mysql.conf.d/mysqld.cnf
}
setup_php() {
# Activate CGI
a2enmod cgi
# Activate modrewrite
a2enmod rewrite
# Setting timezone
sed -i "s#;date.timezone =#date.timezone = $PHP_TIMEZONE#" /etc/php/7.0/apache2/php.ini
# Settings rights for volume
chown -R www-data:www-data /var/lib/zoneminder/events
chown -R www-data:www-data /var/lib/zoneminder/images
}
setup_mysql
setup_php
exit 0

View File

@ -1,48 +0,0 @@
#!/bin/bash
# Prepare proper amount of shared memory
# For H.264 cameras it may be necessary to increase the amount of shared memory
# to 2048 megabytes.
umount /dev/shm
mount -t tmpfs -o rw,nosuid,nodev,noexec,relatime,size=512M tmpfs /dev/shm
# Start MySQL
test -e /var/run/mysqld || install -m 755 -o mysql -g root -d /var/run/mysqld
su - mysql -s /bin/sh -c "/usr/bin/mysqld_safe > /dev/null 2>&1 &"
# Ensure we shut down mysql cleanly later:
trap close_mysql SIGTERM
# Give MySQL time to wake up
SECONDS_LEFT=120
while true; do
sleep 1
mysqladmin ping
if [ $? -eq 0 ];then
break; # Success
fi
let SECONDS_LEFT=SECONDS_LEFT-1
# If we have waited >120 seconds, give up
# ZM should never have a database that large!
# if $COUNTER -lt 120
if [ $SECONDS_LEFT -eq 0 ];then
return -1;
fi
done
# Restart apache
service apache2 restart
# Start ZoneMinder
/usr/local/bin/zmpkg.pl start && echo "Zone Minder started"
while :
do
sleep 3600
done
function close_mysql {
kill $(cat /var/run/mysqld/mysqld.pid)
sleep 5
}

View File

@ -1 +1 @@
1.31.28 1.31.32

View File

@ -12,9 +12,33 @@ $defaultMonitor->set(array(
) ); ) );
function probe( &$url_bits ) { function probe( &$url_bits ) {
error_reporting(0);
global $defaultMonitor; global $defaultMonitor;
$available_streams = array(); $available_streams = array();
if ( ! isset($url_bits['port']) ) { if ( ! isset($url_bits['port']) ) {
$cam_list_html = file_get_contents('http://'.$url_bits['host'].':5000/monitoring/');
if ( $cam_list_html ) {
Logger::Debug("Have content at port 5000/monitoring");
$matches_count = preg_match_all(
'/<a href="http:\/\/([.[:digit:]]+):([[:digit:]]+)\/\?action=stream" target="_blank">([^<]+)<\/a>/',
$cam_list_html, $cam_list );
Logger::Debug(print_r($cam_list,true));
}
if ( $matches_count ) {
for( $index = 0; $index < $matches_count; $index ++ ) {
$new_stream = $url_bits; // make a copy
$new_stream['port'] = $cam_list[2][$index];
$new_stream['Name'] = trim($cam_list[3][$index]);
if ( ! isset($new_stream['scheme'] ) )
$new_stream['scheme'] = 'http';
$available_streams[] = $new_stream;
Logger::Debug("Have new stream " . print_r($new_stream,true) );
}
} else {
Info('No matches');
}
if ( 0 ) {
// No port given, do a port scan // No port given, do a port scan
foreach ( range( 2000, 2007 ) as $port ) { foreach ( range( 2000, 2007 ) as $port ) {
$socket = socket_create( AF_INET, SOCK_STREAM, SOL_TCP ); $socket = socket_create( AF_INET, SOCK_STREAM, SOL_TCP );
@ -61,15 +85,17 @@ Info("Testing connection to " . $url_bits['host'].':'.$port);
$available_streams[] = $new_stream; $available_streams[] = $new_stream;
} // end if new_Stream } // end if new_Stream
} // end foreach port to scan } // end foreach port to scan
} # end if 0
} else { } else {
// A port was specified, so don't need to port scan. // A port was specified, so don't need to port scan.
$available_streams[] = $url_bits; $available_streams[] = $url_bits;
} }
foreach ( $available_streams as &$stream ) { foreach ( $available_streams as &$stream ) {
# check for existence in db. # check for existence in db.
$stream['url'] = unparse_url( $stream, array( 'path'=>'/','query'=>'action=stream' ) ); $stream['url'] = unparse_url( $stream, array('path'=>'/','query'=>'action=stream') );
$monitors = Monitor::find_all( array( 'Path'=>$stream['url'] ) ); $monitors = Monitor::find_all( array('Path'=>$stream['url']) );
if ( count($monitors ) ) { if ( count($monitors) ) {
Info("Found monitors matching " . $stream['url'] );
$stream['Monitor'] = $monitors[0]; $stream['Monitor'] = $monitors[0];
if ( isset( $stream['Width'] ) and ( $stream['Monitor']->Width() != $stream['Width'] ) ) { if ( isset( $stream['Width'] ) and ( $stream['Monitor']->Width() != $stream['Width'] ) ) {
$stream['Warning'] .= 'Monitor width ('.$stream['Monitor']->Width().') and stream width ('.$stream['Width'].") do not match!\n"; $stream['Warning'] .= 'Monitor width ('.$stream['Monitor']->Width().') and stream width ('.$stream['Width'].") do not match!\n";
@ -78,11 +104,14 @@ Info("Testing connection to " . $url_bits['host'].':'.$port);
$stream['Warning'] .= 'Monitor height ('.$stream['Monitor']->Height().') and stream width ('.$stream['Height'].") do not match!\n"; $stream['Warning'] .= 'Monitor height ('.$stream['Monitor']->Height().') and stream width ('.$stream['Height'].") do not match!\n";
} }
} else { } else {
$stream['Monitor'] = $defaultMonitor; $stream['Monitor'] = clone $defaultMonitor;
if ( isset($stream['Width']) ) { if ( isset($stream['Width']) ) {
$stream['Monitor']->Width( $stream['Width'] ); $stream['Monitor']->Width( $stream['Width'] );
$stream['Monitor']->Height( $stream['Height'] ); $stream['Monitor']->Height( $stream['Height'] );
} }
if ( isset($stream['Name']) ) {
$stream['Monitor']->Name( $stream['Name'] );
}
} // Monitor found or not } // Monitor found or not
} // end foreach Stream } // end foreach Stream

View File

@ -382,6 +382,11 @@ function getNearEvents() {
else else
$midSql = ''; $midSql = '';
# When listing, it may make sense to list them in descending order. But when viewing Prev should timewise earlier and Next should be after.
if ( $sortColumn == 'E.Id' or $sortColumn == 'E.StartTime' ) {
$sortOrder = 'asc';
}
$sql = "SELECT E.Id AS Id, E.StartTime AS StartTime FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE $sortColumn ".($sortOrder=='asc'?'<=':'>=')." '".$event[$_REQUEST['sort_field']]."'".$_REQUEST['filter']['sql'].$midSql." ORDER BY $sortColumn ".($sortOrder=='asc'?'desc':'asc') . ' LIMIT 2'; $sql = "SELECT E.Id AS Id, E.StartTime AS StartTime FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE $sortColumn ".($sortOrder=='asc'?'<=':'>=')." '".$event[$_REQUEST['sort_field']]."'".$_REQUEST['filter']['sql'].$midSql." ORDER BY $sortColumn ".($sortOrder=='asc'?'desc':'asc') . ' LIMIT 2';
$result = dbQuery( $sql ); $result = dbQuery( $sql );
while ( $id = dbFetchNext( $result, 'Id' ) ) { while ( $id = dbFetchNext( $result, 'Id' ) ) {

View File

@ -1,31 +1,36 @@
<?php <?php
error_reporting(0);
$start_time = time(); $start_time = time();
define( "MSG_TIMEOUT", ZM_WEB_AJAX_TIMEOUT ); define( 'MSG_TIMEOUT', ZM_WEB_AJAX_TIMEOUT/2 );
define( "MSG_DATA_SIZE", 4+256 ); define( 'MSG_DATA_SIZE', 4+256 );
if ( !($_REQUEST['connkey'] && $_REQUEST['command']) ) { if ( !($_REQUEST['connkey'] && $_REQUEST['command']) ) {
ajaxError( "Unexpected received message type '$type'" ); ajaxError( "Unexpected received message type '$type'" );
} }
if ( !($socket = @socket_create( AF_UNIX, SOCK_DGRAM, 0 )) ) { $key = ftok(ZM_PATH_SOCKS.'/zms-'.sprintf("%06d",$_REQUEST['connkey']).'w.lock', 'Z');
ajaxError( "socket_create() failed: ".socket_strerror(socket_last_error()) ); $semaphore = sem_get($key,1);
} if ( sem_acquire($semaphore,1) !== false ) {
$locSockFile = ZM_PATH_SOCKS.'/zms-'.sprintf("%06d",$_REQUEST['connkey']).'w.sock'; if ( !($socket = @socket_create( AF_UNIX, SOCK_DGRAM, 0 )) ) {
if ( file_exists( $locSockFile ) ) { ajaxError( 'socket_create() failed: '.socket_strerror(socket_last_error()) );
Warning("sock file $locSockFile already exists?! Is someone else talking to zms?"); }
// They could be. We can maybe have concurrent requests from a browser.
} else {
Logger::Debug("socket file does not exist, we should be good to connect.");
}
if ( !@socket_bind( $socket, $locSockFile ) ) {
ajaxError( "socket_bind( $locSockFile ) failed: ".socket_strerror(socket_last_error()) );
} else {
Logger::Debug("Bound to $locSockFile");
}
switch ( $_REQUEST['command'] ) { $localSocketFile = ZM_PATH_SOCKS.'/zms-'.sprintf('%06d',$_REQUEST['connkey']).'w.sock';
if ( file_exists( $localSocketFile ) ) {
Warning("sock file $localSocketFile already exists?! Is someone else talking to zms?");
// They could be. We can maybe have concurrent requests from a browser.
} else {
Logger::Debug("socket file does not exist, we should be good to connect.");
}
if ( ! socket_bind( $socket, $localSocketFile ) ) {
ajaxError( "socket_bind( $localSocketFile ) failed: ".socket_strerror(socket_last_error()) );
} else {
Logger::Debug("Bound to $localSocketFile");
}
switch ( $_REQUEST['command'] ) {
case CMD_VARPLAY : case CMD_VARPLAY :
Logger::Debug( 'Varplaying to '.$_REQUEST['rate'] ); Logger::Debug( 'Varplaying to '.$_REQUEST['rate'] );
$msg = pack( 'lcn', MSG_CMD, $_REQUEST['command'], $_REQUEST['rate']+32768 ); $msg = pack( 'lcn', MSG_CMD, $_REQUEST['command'], $_REQUEST['rate']+32768 );
@ -49,50 +54,54 @@ switch ( $_REQUEST['command'] ) {
default : default :
$msg = pack( 'lc', MSG_CMD, $_REQUEST['command'] ); $msg = pack( 'lc', MSG_CMD, $_REQUEST['command'] );
break; break;
}
$remSockFile = ZM_PATH_SOCKS.'/zms-'.sprintf('%06d',$_REQUEST['connkey']).'s.sock';
$max_socket_tries = 10;
// FIXME This should not exceed web_ajax_timeout
while ( !file_exists($remSockFile) && $max_socket_tries-- ) { //sometimes we are too fast for our own good, if it hasn't been setup yet give it a second.
//Logger::Debug("$remSockFile does not exist, waiting, current " . (time() - $start_time) . ' seconds' );
usleep(200000);
}
if ( !file_exists($remSockFile) ) {
ajaxError("Socket $remSockFile does not exist. This file is created by zms, and since it does not exist, either zms did not run, or zms exited early. Please check your zms logs and ensure that CGI is enabled in apache and check that the PATH_ZMS is set correctly. Make sure that ZM is actually recording. If you are trying to view a live stream and the capture process (zmc) is not running then zms will exit. Please go to http://zoneminder.readthedocs.io/en/latest/faq.html#why-can-t-i-see-streamed-images-when-i-can-see-stills-in-the-zone-window-etc for more information.");
} else {
if ( !@socket_sendto( $socket, $msg, strlen($msg), 0, $remSockFile ) ) {
ajaxError( "socket_sendto( $remSockFile ) failed: ".socket_strerror(socket_last_error()) );
} }
}
$rSockets = array( $socket ); $remSockFile = ZM_PATH_SOCKS.'/zms-'.sprintf('%06d',$_REQUEST['connkey']).'s.sock';
$wSockets = NULL; $max_socket_tries = 10;
$eSockets = NULL; // FIXME This should not exceed web_ajax_timeout
while ( !file_exists($remSockFile) && $max_socket_tries-- ) { //sometimes we are too fast for our own good, if it hasn't been setup yet give it a second.
// WHY? We will just send another one...
// ANSWER: Because otherwise we get a log of errors logged
$timeout = MSG_TIMEOUT - ( time() - $start_time ); //Logger::Debug("$remSockFile does not exist, waiting, current " . (time() - $start_time) . ' seconds' );
Logger::Debug("TImeout is: $timeout " ); usleep(1000);
$numSockets = @socket_select( $rSockets, $wSockets, $eSockets, intval($timeout/1000), ($timeout%1000)*1000 );
if ( $numSockets === false ) {
Error("socket_select failed: " . socket_strerror(socket_last_error()) );
ajaxError( "socket_select failed: ".socket_strerror(socket_last_error()) );
} else if ( $numSockets < 0 ) {
Error( "Socket closed $remSockFile" );
ajaxError( "Socket closed $remSockFile" );
} else if ( $numSockets == 0 ) {
Error( "Timed out waiting for msg $remSockFile" );
ajaxError( "Timed out waiting for msg $remSockFile" );
} else if ( $numSockets > 0 ) {
if ( count($rSockets) != 1 ) {
Error( "Bogus return from select, ".count($rSockets).' sockets available' );
ajaxError( "Bogus return from select, ".count($rSockets).' sockets available' );
} }
}
switch( $nbytes = @socket_recvfrom( $socket, $msg, MSG_DATA_SIZE, 0, $remSockFile ) ) { if ( !file_exists($remSockFile) ) {
ajaxError("Socket $remSockFile does not exist. This file is created by zms, and since it does not exist, either zms did not run, or zms exited early. Please check your zms logs and ensure that CGI is enabled in apache and check that the PATH_ZMS is set correctly. Make sure that ZM is actually recording. If you are trying to view a live stream and the capture process (zmc) is not running then zms will exit. Please go to http://zoneminder.readthedocs.io/en/latest/faq.html#why-can-t-i-see-streamed-images-when-i-can-see-stills-in-the-zone-window-etc for more information.");
} else {
if ( !@socket_sendto( $socket, $msg, strlen($msg), 0, $remSockFile ) ) {
ajaxError( "socket_sendto( $remSockFile ) failed: ".socket_strerror(socket_last_error()) );
}
}
$rSockets = array( $socket );
$wSockets = NULL;
$eSockets = NULL;
$timeout = MSG_TIMEOUT - ( time() - $start_time );
Logger::Debug("TImeout is: $timeout/1000 seconds. " );
$numSockets = socket_select( $rSockets, $wSockets, $eSockets, intval($timeout/1000), ($timeout%1000)*1000 );
if ( $numSockets === false ) {
Error('socket_select failed: ' . socket_strerror(socket_last_error()) );
ajaxError( 'socket_select failed: '.socket_strerror(socket_last_error()) );
} else if ( $numSockets < 0 ) {
Error( "Socket closed $remSockFile" );
ajaxError( "Socket closed $remSockFile" );
} else if ( $numSockets == 0 ) {
Error( "Timed out waiting for msg $remSockFile" );
socket_Set_nonblock($socket);
#ajaxError( "Timed out waiting for msg $remSockFile" );
} else if ( $numSockets > 0 ) {
if ( count($rSockets) != 1 ) {
Error( 'Bogus return from select, '.count($rSockets).' sockets available' );
ajaxError( 'Bogus return from select, '.count($rSockets).' sockets available' );
}
}
switch( $nbytes = @socket_recvfrom( $socket, $msg, MSG_DATA_SIZE, 0, $remSockFile ) ) {
case -1 : case -1 :
{ {
ajaxError( "socket_recvfrom( $remSockFile ) failed: ".socket_strerror(socket_last_error()) ); ajaxError( "socket_recvfrom( $remSockFile ) failed: ".socket_strerror(socket_last_error()) );
@ -109,10 +118,11 @@ switch( $nbytes = @socket_recvfrom( $socket, $msg, MSG_DATA_SIZE, 0, $remSockFil
ajaxError( "Got unexpected message size, got $nbytes, expected ".MSG_DATA_SIZE ); ajaxError( "Got unexpected message size, got $nbytes, expected ".MSG_DATA_SIZE );
break; break;
} }
} }
$data = unpack( 'ltype', $msg );
switch ( $data['type'] ) { $data = unpack( 'ltype', $msg );
switch ( $data['type'] ) {
case MSG_DATA_WATCH : case MSG_DATA_WATCH :
{ {
$data = unpack( "ltype/imonitor/istate/dfps/ilevel/irate/ddelay/izoom/Cdelayed/Cpaused/Cenabled/Cforced", $msg ); $data = unpack( "ltype/imonitor/istate/dfps/ilevel/irate/ddelay/izoom/Cdelayed/Cpaused/Cenabled/Cforced", $msg );
@ -156,15 +166,20 @@ switch ( $data['type'] ) {
{ {
ajaxError( "Unexpected received message type '$type'" ); ajaxError( "Unexpected received message type '$type'" );
} }
}
sem_release($semaphore);
} else {
Logger::Debug("Couldn't get semaphore");
ajaxResponse( array() );
} }
ajaxError( 'Unrecognised action or insufficient permissions' ); ajaxError('Unrecognised action or insufficient permissions in ajax/stream');
function ajaxCleanup() { function ajaxCleanup() {
global $socket, $locSockFile; global $socket, $localSocketFile;
if ( !empty( $socket ) ) if ( !empty( $socket ) )
@socket_close( $socket ); @socket_close( $socket );
if ( !empty( $locSockFile ) ) if ( !empty( $localSocketFile ) )
@unlink( $locSockFile ); @unlink( $localSocketFile );
} }
?> ?>

View File

@ -148,13 +148,27 @@ class MonitorsController extends AppController {
throw new NotFoundException(__('Invalid monitor')); throw new NotFoundException(__('Invalid monitor'));
} }
if ($this->Session->Read('monitorPermission') != 'Edit') { if ($this->Session->Read('monitorPermission') != 'Edit') {
throw new UnauthorizedException(__('Insufficient privileges')); throw new UnauthorizedException(__('Insufficient privileges'));
return; return;
} }
if ($this->Monitor->save($this->request->data)) {
$message = '';
if ( $this->Monitor->save($this->request->data) ) {
$message = 'Saved'; $message = 'Saved';
$Monitor = $this->Monitor->find('first', array(
'fields' => array('Function','ServerId'),
'conditions' => array('Id' => $id)
))['Monitor'];
// - restart or stop this monitor after change
$func = $Monitor['Function'];
// We don't pass the request data as the monitor object because it may be a subset of the full monitor array
$this->daemonControl( $this->Monitor->id, 'stop' );
if ( ( $func != 'None' ) and ( (!defined('ZM_SERVER_ID')) or ($Monitor['ServerId']==ZM_SERVER_ID) ) ) {
$this->daemonControl( $this->Monitor->id, 'start' );
}
} else { } else {
$message = 'Error'; $message = 'Error ' . print_r($this->Monitor->invalidFields(), true);
} }
$this->set(array( $this->set(array(
@ -162,18 +176,6 @@ class MonitorsController extends AppController {
'_serialize' => array('message') '_serialize' => array('message')
)); ));
$Monitor = $this->Monitor->find('first', array(
'fields' => array('Function','ServerId'),
'conditions' => array('Id' => $id)
))['Monitor'];
// - restart or stop this monitor after change
$func = $Monitor['Function'];
// We don't pass the request data as the monitor object because it may be a subset of the full monitor array
$this->daemonControl( $this->Monitor->id, 'stop' );
if ( ( $func != 'None' ) and ( (!defined('ZM_SERVER_ID')) or ($Monitor['ServerId']==ZM_SERVER_ID) ) ) {
$this->daemonControl( $this->Monitor->id, 'start' );
}
} // end function edit } // end function edit
/** /**

View File

@ -110,13 +110,13 @@ class Monitor extends AppModel {
); );
public $actsAs = array( public $actsAs = array(
'CakePHP-Enum-Behavior.Enum' => array( 'CakePHP-Enum-Behavior.Enum' => array(
'Type' => array('Local','Remote','File','Ffmpeg','Libvlc','cURL'), 'Type' => array('Local','Remote','File','Ffmpeg','Libvlc','cURL'),
'Function' => array('None','Monitor','Modect','Record','Mocord','Nodect'), 'Function' => array('None','Monitor','Modect','Record','Mocord','Nodect'),
'Orientation' => array('0','90','180','270','hori','vert'), 'Orientation' => array('0','90','180','270','hori','vert'),
'OutputCodec' => array('h264','mjpeg','mpeg1','mpeg2'), 'OutputCodec' => array('h264','mjpeg','mpeg1','mpeg2'),
'OutputContainer' => array('auto','mp4','mkv'), 'OutputContainer' => array('auto','mp4','mkv'),
'DefaultView' => array('Events','Control'), 'DefaultView' => array('Events','Control'),
'Status' => array('Unknown','NotRunning','Running','NoSignal','Signal'), 'Status' => array('Unknown','NotRunning','Running','NoSignal','Signal'),
) )
); );

@ -1 +1 @@
Subproject commit 7108489f218c54d36d235d3af91d6da2f8311237 Subproject commit ca91b87fda8e006e4fca2ed870f24f9a29c2905d

View File

@ -249,7 +249,7 @@ $group_options[$Group->Id()] = str_repeat( '&nbsp;', $depth ) . $Group->Name();
$MonitorIds = array_merge( $MonitorIds, dbFetchAll( 'SELECT MonitorId FROM Groups_Monitors WHERE GroupId IN (SELECT Id FROM Groups WHERE ParentId = ?)', 'MonitorId', array($group_id) ) ); $MonitorIds = array_merge( $MonitorIds, dbFetchAll( 'SELECT MonitorId FROM Groups_Monitors WHERE GroupId IN (SELECT Id FROM Groups WHERE ParentId = ?)', 'MonitorId', array($group_id) ) );
} }
$groupSql = " find_in_set( Id, '".implode( ',', $MonitorIds )."' )"; $groupSql = " find_in_set( M.Id, '".implode( ',', $MonitorIds )."' )";
} }
return $groupSql; return $groupSql;
} # end public static function get_group_sql( $group_id ) } # end public static function get_group_sql( $group_id )

View File

@ -5,20 +5,22 @@ require_once( 'Server.php' );
class Monitor { class Monitor {
private $defaults = array( private $defaults = array(
'Id' => null, 'Id' => null,
'Name' => '', 'Name' => '',
'StorageId' => 0, 'StorageId' => 0,
'ServerId' => 0, 'ServerId' => 0,
'Function' => 'None', 'Function' => 'None',
'Enabled' => 1, 'Enabled' => 1,
'Width' => null, 'Width' => null,
'Height' => null, 'Height' => null,
'Orientation' => null, 'Orientation' => null,
'AnalysisFPSLimit' => null, 'AnalysisFPSLimit' => null,
'AnalysisFPS' => null, 'ZoneCount' => 0,
'CaptureFPS' => null, 'Triggers' => null,
'ZoneCount' => 0, );
'Triggers' => null, private $status_fields = array(
'AnalysisFPS' => null,
'CaptureFPS' => null,
); );
private $control_fields = array( private $control_fields = array(
'Name' => '', 'Name' => '',
@ -312,7 +314,7 @@ private $control_fields = array(
} // end function save } // end function save
function zmcControl( $mode=false ) { function zmcControl( $mode=false ) {
if ( (!defined('ZM_SERVER_ID')) or ( ZM_SERVER_ID==$this->{'ServerId'} ) ) { if ( (!defined('ZM_SERVER_ID')) or ( array_key_exists('ServerId', $this) and (ZM_SERVER_ID==$this->{'ServerId'}) ) ) {
if ( $this->{'Type'} == 'Local' ) { if ( $this->{'Type'} == 'Local' ) {
$zmcArgs = '-d '.$this->{'Device'}; $zmcArgs = '-d '.$this->{'Device'};
} else { } else {
@ -329,7 +331,7 @@ private $control_fields = array(
daemonControl( 'start', 'zmc', $zmcArgs ); daemonControl( 'start', 'zmc', $zmcArgs );
} }
} }
} else { } else if ( $this->ServerId() ) {
$Server = $this->Server(); $Server = $this->Server();
$url = $Server->Url() . '/zm/api/monitors/'.$this->{'Id'}.'.json'; $url = $Server->Url() . '/zm/api/monitors/'.$this->{'Id'}.'.json';
@ -367,7 +369,7 @@ Logger::Debug("sending command to $url");
} // end function zmcControl } // end function zmcControl
function zmaControl( $mode=false ) { function zmaControl( $mode=false ) {
if ( (!defined('ZM_SERVER_ID')) or ( ZM_SERVER_ID==$this->{'ServerId'} ) ) { if ( (!defined('ZM_SERVER_ID')) or ( array_key_exists('ServerId', $this) and (ZM_SERVER_ID==$this->{'ServerId'}) ) ) {
if ( $this->{'Function'} == 'None' || $this->{'Function'} == 'Monitor' || $mode == 'stop' ) { if ( $this->{'Function'} == 'None' || $this->{'Function'} == 'Monitor' || $mode == 'stop' ) {
if ( ZM_OPT_CONTROL ) { if ( ZM_OPT_CONTROL ) {
daemonControl( 'stop', 'zmtrack.pl', '-m '.$this->{'Id'} ); daemonControl( 'stop', 'zmtrack.pl', '-m '.$this->{'Id'} );

View File

@ -126,7 +126,7 @@ if ( $action == 'login' && isset($_REQUEST['username']) && ( ZM_AUTH_TYPE == 're
userLogin( $username, $password ); userLogin( $username, $password );
$refreshParent = true; $refreshParent = true;
$view = 'console'; $view = 'console';
$redirect = true; $redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=console';
} else if ( $action == 'logout' ) { } else if ( $action == 'logout' ) {
userLogout(); userLogout();
$refreshParent = true; $refreshParent = true;
@ -483,6 +483,18 @@ if ( canEdit( 'Monitors' ) ) {
'RecordAudio' => 'toggle', 'RecordAudio' => 'toggle',
); );
if ( $_REQUEST['newMonitor']['ServerId'] == 'auto' ) {
Logger::Debug("Auto selecting server");
$_REQUEST['newMonitor']['ServerId'] = dbFetchOne( 'SELECT Id FROM Servers WHERE Status=\'Running\' ORDER BY FreeMem ASC, CpuLoad ASC LIMIT 1', 'Id' );
Logger::Debug("Auto selecting server: Got " . $_REQUEST['newMonitor']['ServerId'] );
if ( ( ! $_REQUEST['newMonitor'] ) and defined('ZM_SERVER_ID') ) {
$_REQUEST['newMonitor']['ServerId'] = ZM_SERVER_ID;
Logger::Debug("Auto selecting server to " . ZM_SERVER_ID);
}
} else {
Logger::Debug("NOT Auto selecting server" . $_REQUEST['newMonitor']['ServerId']);
}
$columns = getTableColumns( 'Monitors' ); $columns = getTableColumns( 'Monitors' );
$changes = getFormChanges( $monitor, $_REQUEST['newMonitor'], $types, $columns ); $changes = getFormChanges( $monitor, $_REQUEST['newMonitor'], $types, $columns );
@ -538,22 +550,26 @@ if ( canEdit( 'Monitors' ) ) {
} }
} }
$restart = true; $restart = true;
} elseif ( ! $user['MonitorIds'] ) { // Can only create new monitors if we are not restricted to specific monitors } else if ( ! $user['MonitorIds'] ) { // Can only create new monitors if we are not restricted to specific monitors
# FIXME This is actually a race condition. Should lock the table. # FIXME This is actually a race condition. Should lock the table.
$maxSeq = dbFetchOne( 'SELECT max(Sequence) AS MaxSequence FROM Monitors', 'MaxSequence' ); $maxSeq = dbFetchOne('SELECT MAX(Sequence) AS MaxSequence FROM Monitors', 'MaxSequence');
$changes[] = 'Sequence = '.($maxSeq+1); $changes[] = 'Sequence = '.($maxSeq+1);
dbQuery( 'INSERT INTO Monitors SET '.implode( ', ', $changes ) ); if ( dbQuery( 'INSERT INTO Monitors SET '.implode( ', ', $changes ) ) ) {
$mid = dbInsertId(); $mid = dbInsertId();
$zoneArea = $_REQUEST['newMonitor']['Width'] * $_REQUEST['newMonitor']['Height']; $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) ) ); 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'; //$view = 'none';
$Storage = new Storage( $_REQUEST['newMonitor']['StorageId'] ); $Storage = new Storage( $_REQUEST['newMonitor']['StorageId'] );
mkdir( $Storage->Path().'/'.$mid, 0755 ); mkdir( $Storage->Path().'/'.$mid, 0755 );
$saferName = basename($_REQUEST['newMonitor']['Name']); $saferName = basename($_REQUEST['newMonitor']['Name']);
symlink( $mid, $Storage->Path().'/'.$saferName ); symlink( $mid, $Storage->Path().'/'.$saferName );
if ( isset($_COOKIE['zmGroup']) ) { if ( isset($_COOKIE['zmGroup']) ) {
dbQuery( 'INSERT INTO Groups_Monitors (GroupId,MonitorId) VALUES (?,?)', array($_COOKIE['zmGroup'],$mid) ); dbQuery( 'INSERT INTO Groups_Monitors (GroupId,MonitorId) VALUES (?,?)', array($_COOKIE['zmGroup'],$mid) );
}
} else {
Error("Error saving new Monitor.");
return;
} }
} else { } else {
Error("Users with Monitors restrictions cannot create new monitors."); Error("Users with Monitors restrictions cannot create new monitors.");
@ -726,7 +742,7 @@ if ( canEdit( 'System' ) ) {
$_SESSION['zmMontageLayout'] = $Layout->Id(); $_SESSION['zmMontageLayout'] = $Layout->Id();
setcookie('zmMontageLayout', $Layout->Id(), 1 ); setcookie('zmMontageLayout', $Layout->Id(), 1 );
session_write_close(); session_write_close();
$redirect = true; $redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=montagereview';
} // end if save } // end if save
} else if ( $_REQUEST['object'] == 'server' ) { } else if ( $_REQUEST['object'] == 'server' ) {
@ -893,6 +909,7 @@ if ( canEdit( 'System' ) ) {
case 'lowband' : case 'lowband' :
break; break;
} }
$redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=options&tab='.$_REQUEST['tab'];
} }
loadConfig( false ); loadConfig( false );
} elseif ( $action == 'user' ) { } elseif ( $action == 'user' ) {

View File

@ -98,7 +98,7 @@ function dbLog( $sql, $update=false ) {
} }
function dbError( $sql ) { function dbError( $sql ) {
Fatal( "SQL-ERR '".$dbConn->errorInfo()."', statement was '".$sql."'" ); Error( "SQL-ERR '".$dbConn->errorInfo()."', statement was '".$sql."'" );
} }
function dbEscape( $string ) { function dbEscape( $string ) {
@ -142,21 +142,26 @@ function dbQuery( $sql, $params=NULL ) {
} }
} catch(PDOException $e) { } catch(PDOException $e) {
Error( "SQL-ERR '".$e->getMessage()."', statement was '".$sql."' params:" . ($params?implode(',',$params):'') ); Error( "SQL-ERR '".$e->getMessage()."', statement was '".$sql."' params:" . ($params?implode(',',$params):'') );
return NULL;
} }
return( $result ); return $result;
} }
function dbFetchOne( $sql, $col=false, $params=NULL ) { function dbFetchOne( $sql, $col=false, $params=NULL ) {
$result = dbQuery( $sql, $params ); $result = dbQuery( $sql, $params );
if ( ! $result ) { if ( ! $result ) {
Fatal( "SQL-ERR dbFetchOne no result, statement was '".$sql."'" . ( $params ? 'params: ' . join(',',$params) : '' ) ); Error( "SQL-ERR dbFetchOne no result, statement was '".$sql."'" . ( $params ? 'params: ' . join(',',$params) : '' ) );
return false;
}
if ( ! $result->rowCount() ) {
# No rows is not an error
return false; return false;
} }
if ( $result && $dbRow = $result->fetch( PDO::FETCH_ASSOC ) ) { if ( $result && $dbRow = $result->fetch( PDO::FETCH_ASSOC ) ) {
if ( $col ) { if ( $col ) {
if ( ! isset( $dbRow[$col] ) ) { if ( ! isset( $dbRow[$col] ) ) {
Warning( "$col does not exist in the returned row" ); Warning( "$col does not exist in the returned row " . print_r($dbRow, true) );
} }
return $dbRow[$col]; return $dbRow[$col];
} }
@ -168,7 +173,7 @@ function dbFetchOne( $sql, $col=false, $params=NULL ) {
function dbFetchAll( $sql, $col=false, $params=NULL ) { function dbFetchAll( $sql, $col=false, $params=NULL ) {
$result = dbQuery( $sql, $params ); $result = dbQuery( $sql, $params );
if ( ! $result ) { if ( ! $result ) {
Fatal( "SQL-ERR dbFetchAll no result, statement was '".$sql."'" . ( $params ? 'params: ' .join(',', $params) : '' ) ); Error( "SQL-ERR dbFetchAll no result, statement was '".$sql."'" . ( $params ? 'params: ' .join(',', $params) : '' ) );
return false; return false;
} }

View File

@ -269,14 +269,14 @@ function getVideoStreamHTML( $id, $src, $width, $height, $format, $title='' ) {
if ( isWindows() ) { if ( isWindows() ) {
return '<object id="'.$id.'" width="'.$width.'" height="'.$height.' return '<object id="'.$id.'" width="'.$width.'" height="'.$height.'
classid="CLSID:22D6F312-B0F6-11D0-94AB-0080C74C7E95" classid="CLSID:22D6F312-B0F6-11D0-94AB-0080C74C7E95"
codebase="http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=6,0,02,902" codebase="'.ZM_BASE_PROTOCOL.'://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=6,0,02,902"
standby="Loading Microsoft Windows Media Player components..." standby="Loading Microsoft Windows Media Player components..."
type="'.$mimeType.'"> type="'.$mimeType.'">
<param name="FileName" value="'.$src.'"/> <param name="FileName" value="'.$src.'"/>
<param name="autoStart" value="1"/> <param name="autoStart" value="1"/>
<param name="showControls" value="0"/> <param name="showControls" value="0"/>
<embed type="'.$mimeType.'" <embed type="'.$mimeType.'"
pluginspage="http://www.microsoft.com/Windows/MediaPlayer/" pluginspage="'.ZM_BASE_PROTOCOL.'://www.microsoft.com/Windows/MediaPlayer/"
src="'.$src.'" src="'.$src.'"
name="'.$title.'" name="'.$title.'"
width="'.$width.'" width="'.$width.'"
@ -291,14 +291,14 @@ function getVideoStreamHTML( $id, $src, $width, $height, $format, $title='' ) {
{ {
return '<object id="'.$id.'" width="'.$width.'" height="'.$height.'" return '<object id="'.$id.'" width="'.$width.'" height="'.$height.'"
classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"
codebase="http://www.apple.com/qtactivex/qtplugin.cab" codebase="'.ZM_BASE_PROTOCOL.'://www.apple.com/qtactivex/qtplugin.cab"
type="'.$mimeType.'"> type="'.$mimeType.'">
<param name="src" value="'.$src.'"/> <param name="src" value="'.$src.'"/>
<param name="autoplay" VALUE="true"/> <param name="autoplay" VALUE="true"/>
<param name="controller" VALUE="false"/> <param name="controller" VALUE="false"/>
<embed type="'.$mimeType.'" <embed type="'.$mimeType.'"
src="'.$src.'" src="'.$src.'"
pluginspage="http://www.apple.com/quicktime/download/" pluginspage="'.ZM_BASE_PROTOCOL.'://www.apple.com/quicktime/download/"
name="'.$title.'" width="'.$width.'" height="'.$height.'" name="'.$title.'" width="'.$width.'" height="'.$height.'"
autoplay="true" autoplay="true"
controller="true"> controller="true">
@ -309,13 +309,13 @@ function getVideoStreamHTML( $id, $src, $width, $height, $format, $title='' ) {
{ {
return '<object id="'.$id.'" width="'.$width.'" height="'.$height.'" return '<object id="'.$id.'" width="'.$width.'" height="'.$height.'"
classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" codebase="'.ZM_BASE_PROTOCOL.'://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"
type="'.$mimeType.'"> type="'.$mimeType.'">
<param name="movie" value="'.$src.'"/> <param name="movie" value="'.$src.'"/>
<param name="quality" value="high"/> <param name="quality" value="high"/>
<param name="bgcolor" value="#ffffff"/> <param name="bgcolor" value="#ffffff"/>
<embed type="'.$mimeType.'" <embed type="'.$mimeType.'"
pluginspage="http://www.macromedia.com/go/getflashplayer" pluginspage="'.ZM_BASE_PROTOCOL.'://www.macromedia.com/go/getflashplayer"
src="'.$src.'" src="'.$src.'"
name="'.$title.'" name="'.$title.'"
width="'.$width.'" width="'.$width.'"
@ -2132,10 +2132,11 @@ function ajaxResponse( $result=false ) {
if ( function_exists( 'ajaxCleanup' ) ) if ( function_exists( 'ajaxCleanup' ) )
ajaxCleanup(); ajaxCleanup();
$response = array( 'result'=>'Ok' ); $response = array( 'result'=>'Ok' );
if ( is_array( $result ) ) if ( is_array( $result ) ) {
$response = array_merge( $response, $result ); $response = array_merge( $response, $result );
elseif ( !empty($result) ) } elseif ( !empty($result) ) {
$response['message'] = $result; $response['message'] = $result;
}
header( 'Content-type: text/plain' ); header( 'Content-type: text/plain' );
exit( jsonEncode( $response ) ); exit( jsonEncode( $response ) );
} }

View File

@ -173,18 +173,17 @@ if ( isset($_REQUEST['request']) )
foreach ( getSkinIncludes( 'skin.php' ) as $includeFile ) foreach ( getSkinIncludes( 'skin.php' ) as $includeFile )
require_once $includeFile; require_once $includeFile;
if ( ZM_OPT_USE_AUTH && ZM_AUTH_HASH_LOGINS ) { if ( ZM_OPT_USE_AUTH ) {
Logger::Debug("Useing hash"); if ( ZM_AUTH_HASH_LOGINS ) {
if ( empty($user) && ! empty($_REQUEST['auth']) ) { if ( empty($user) && ! empty($_REQUEST['auth']) ) {
if ( $authUser = getAuthUser( $_REQUEST['auth'] ) ) { if ( $authUser = getAuthUser( $_REQUEST['auth'] ) ) {
userLogin( $authUser['Username'], $authUser['Password'], true ); userLogin( $authUser['Username'], $authUser['Password'], true );
} }
} else if ( ! empty($user) ) { }
Logger::Debug("generating hash"); }
if ( ! empty($user) ) {
// generate it once here, while session is open. Value will be cached in session and return when called later on // generate it once here, while session is open. Value will be cached in session and return when called later on
generateAuthHash( ZM_AUTH_HASH_IPS ); generateAuthHash( ZM_AUTH_HASH_IPS );
} else {
Logger::Debug(" not generating hash");
} }
} }
@ -218,11 +217,11 @@ if ( ZM_OPT_USE_AUTH and ! isset($user) ) {
session_write_close(); session_write_close();
if ( $redirect ) { if ( $redirect ) {
header('Location: '.ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view='.$view); header('Location: '.$redirect);
return; return;
} }
if ( isset( $_REQUEST['request'] ) ) { if ( $request ) {
foreach ( getSkinIncludes( 'ajax/'.$request.'.php', true, true ) as $includeFile ) { foreach ( getSkinIncludes( 'ajax/'.$request.'.php', true, true ) as $includeFile ) {
if ( !file_exists( $includeFile ) ) if ( !file_exists( $includeFile ) )
Fatal( "Request '$request' does not exist" ); Fatal( "Request '$request' does not exist" );

View File

@ -71,7 +71,9 @@ html ul.tabs li.active, html ul.tabs li.active a:hover {
} }
--> -->
</style> </style>
<script type="text/javascript" src="<?php echo ZM_SKIN_PATH; ?>/js/jquery.js"></script> <script type="text/javascript">
<?php include(ZM_SKIN_PATH.'/js/jquery.js'
</script>
<script type="text/javascript" language="javascript" charset="utf-8"> <script type="text/javascript" language="javascript" charset="utf-8">
/*==========[tab code]==========*/ /*==========[tab code]==========*/
@ -579,14 +581,9 @@ else if (document.layers) window.onload=start_slider;
return( ob_get_clean() ); return( ob_get_clean() );
} }
function exportEventImagesMaster( $eids ) {
ob_start();
exportHeader( translate('Images').' Master' );
function exportEventImagesMaster( $eids )
{
ob_start();
exportHeader( translate('Images').' Master' );
?> ?>
<body> <body>
<h2><?php echo translate('Images') ?> Master</h2> <h2><?php echo translate('Images') ?> Master</h2>
@ -611,32 +608,27 @@ function exportEventImagesMaster( $eids )
//trigger_error(print_r($monitorNames,1)); //trigger_error(print_r($monitorNames,1));
?> ?>
<div id= 'tabs'> <div id="tabs">
<ul class= 'tabs'> <ul class="tabs">
<li class = 'active' ><a href='#all' > All </a></li> <li class="active"><a href="#all"> All </a></li>
<?php <?php
foreach ($monitors as $monitor) { foreach ($monitors as $monitor) {
# code... # code...
echo "<li><a href='#tab$monitor'>" . $monitorNames[$monitor] . "</a></li>"; echo "<li><a href='#tab$monitor'>" . $monitorNames[$monitor] . '</a></li>';
} }
?> ?>
</ul> </ul>
</div> </div>
<table width="100%" height="100%" ><tr> <table width="100%" height="100%" ><tr>
<td valign="top" bgcolor="#dddddd" style="padding:10px;"> <td valign="top" bgcolor="#dddddd" style="padding:10px;">
<div class='tab_content' id='all'> <div class='tab_content' id='all'>
<h2> All </h2> <h2> All </h2>
<?php <?php
if (!is_array($eids)) if (!is_array($eids)) {
{
echo "<div><a href=\"javascript:switchevent('$eids/zm/EventImages.html');\"> $eids </div>"; echo "<div><a href=\"javascript:switchevent('$eids/zm/EventImages.html');\"> $eids </div>";
} }
?> ?>
<?php foreach($eids as $eid) <?php foreach($eids as $eid) {
{
?> ?>
<div><a href="javascript:switchevent('<?php echo $eventPath[$eid]; ?>/zmEventImages.html');"><?php echo$eid?></a></div> <div><a href="javascript:switchevent('<?php echo $eventPath[$eid]; ?>/zmEventImages.html');"><?php echo$eid?></a></div>
<?php <?php
@ -644,15 +636,11 @@ function exportEventImagesMaster( $eids )
?> ?>
</div> </div>
<?php <?php
foreach ($monitors as $monitor) {
foreach ($monitors as $monitor)
{
echo "<div class='tab_content' id='tab$monitor'>"; echo "<div class='tab_content' id='tab$monitor'>";
echo "<h2>Monitor: " . $monitorNames[$monitor] . " </h2>"; echo "<h2>Monitor: " . $monitorNames[$monitor] . " </h2>";
foreach ($eids as $eid) foreach ($eids as $eid) {
{ if ($eventMonitorId[$eid] == $monitor) {
if ($eventMonitorId[$eid] == $monitor)
{
?> ?>
<div><a href="javascript:switchevent('<?php echo $eventPath[$eid]; ?>/zmEventImages.html');"><?php echo$eid?></a></div> <div><a href="javascript:switchevent('<?php echo $eventPath[$eid]; ?>/zmEventImages.html');"><?php echo$eid?></a></div>
<?php <?php
@ -660,7 +648,6 @@ function exportEventImagesMaster( $eids )
} }
echo'</div>'; echo'</div>';
} }
?> ?>
</td><td> </td><td>
@ -750,204 +737,168 @@ function loadintoIframe(iframeid, url){
function exportFileList( $eid, $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc ) function exportFileList( $eid, $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc ) {
{
if ( canView( 'Events' ) && $eid ) if ( (!canView('Events')) or ! $eid ) {
{ return;
$event = new Event( $eid ); }
$eventPath = $event->Path();
$files = array();
if ( $dir = opendir( $eventPath ) )
{
while ( ($file = readdir( $dir )) !== false )
{
if ( is_file( $eventPath."/".$file ) )
{
$files[$file] = $file;
}
}
closedir( $dir );
}
$exportFileList = array(); $event = new Event($eid);
$eventPath = $event->Path();
if ( $exportDetail ) $files = array();
{ if ( $dir = opendir($eventPath) ) {
$file = "zmEventDetail.html"; while ( ($file = readdir($dir)) !== false ) {
if ( !($fp = fopen( $eventPath."/".$file, "w" )) ) if ( is_file($eventPath.'/'.$file) ) {
{ $files[$file] = $file;
Fatal( "Can't open event detail export file '$file'" ); }
}
fwrite( $fp, exportEventDetail( $event, $exportFrames, $exportImages ) );
fclose( $fp );
$exportFileList[$file] = $eventPath."/".$file;
}
if ( $exportFrames )
{
$file = "zmEventFrames.html";
if ( !($fp = fopen( $eventPath."/".$file, "w" )) )
{
Fatal( "Can't open event frames export file '$file'" );
}
fwrite( $fp, exportEventFrames( $event, $exportDetail, $exportImages ) );
fclose( $fp );
$exportFileList[$file] = $eventPath."/".$file;
}
if ( $exportImages )
{
$filesLeft = array();
$myfilelist = array();
foreach ( $files as $file )
{
if ( preg_match( "/-(?:capture|analyse).jpg$/", $file ) )
{
$exportFileList[$file] = $eventPath."/".$file;
$myfilelist[$file] = $eventPath."/".$file;
}
else
{
$filesLeft[$file] = $file;
}
}
$files = $filesLeft;
// create an image slider
if(!empty($myfilelist)) {
$file = "zmEventImages.html";
if ( !($fp = fopen( $eventPath."/".$file, "w" )) ) Fatal( "Can't open event images export file '$file'" );
fwrite( $fp, exportEventImages( $event, $exportDetail, $exportFrames, $myfilelist ) );
fclose( $fp );
$exportFileList[$file] = $eventPath."/".$file;
}
}
if ( $exportVideo )
{
$filesLeft = array();
foreach ( $files as $file )
{
if ( preg_match( "/\.(?:mpg|mpeg|mp4|avi|asf|3gp)$/", $file ) )
{
$exportFileList[$file] = $eventPath."/".$file;
}
else
{
$filesLeft[$file] = $file;
}
}
$files = $filesLeft;
}
if ( $exportMisc )
{
foreach ( $files as $file )
{
$exportFileList[$file] = $eventPath."/".$file;
}
$files = array();
}
} }
return( array_values( $exportFileList ) ); closedir($dir);
}
$exportFileList = array();
if ( $exportDetail ) {
$file = 'zmEventDetail.html';
if ( !($fp = fopen( $eventPath.'/'.$file, 'w' )) ) {
Fatal( "Can't open event detail export file '$file'" );
}
fwrite( $fp, exportEventDetail( $event, $exportFrames, $exportImages ) );
fclose( $fp );
$exportFileList[$file] = $eventPath."/".$file;
}
if ( $exportFrames ) {
$file = 'zmEventFrames.html';
if ( !($fp = fopen( $eventPath.'/'.$file, 'w' )) ) {
Fatal( "Can't open event frames export file '$file'" );
}
fwrite( $fp, exportEventFrames( $event, $exportDetail, $exportImages ) );
fclose( $fp );
$exportFileList[$file] = $eventPath."/".$file;
}
if ( $exportImages ) {
$filesLeft = array();
$myfilelist = array();
foreach ( $files as $file ) {
if ( preg_match( '/-(?:capture|analyse).jpg$/', $file ) ) {
$exportFileList[$file] = $eventPath."/".$file;
$myfilelist[$file] = $eventPath."/".$file;
} else {
$filesLeft[$file] = $file;
}
}
$files = $filesLeft;
// create an image slider
if ( !empty($myfilelist) ) {
$file = 'zmEventImages.html';
if ( !($fp = fopen($eventPath.'/'.$file, 'w')) ) Fatal( "Can't open event images export file '$file'" );
fwrite( $fp, exportEventImages( $event, $exportDetail, $exportFrames, $myfilelist ) );
fclose( $fp );
$exportFileList[$file] = $eventPath."/".$file;
}
} # 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] = $eventPath.'/'.$file;
} else {
$filesLeft[$file] = $file;
}
}
$files = $filesLeft;
} # end if exportVideo
if ( $exportMisc ) {
foreach ( $files as $file ) {
$exportFileList[$file] = $eventPath.'/'.$file;
}
$files = array();
}
return( array_values( $exportFileList ) );
} }
function exportEvents( $eids, $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc, $exportFormat, $exportStructure = false ) function exportEvents( $eids, $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc, $exportFormat, $exportStructure = false ) {
{
if ( canView( 'Events' ) && !empty($eids) )
{
$export_root = "zmExport";
$export_listFile = "zmFileList.txt";
$exportFileList = array();
$html_eventMaster = '';
if ( is_array( $eids ) ) if ( (!canView('Events')) || empty($eids) ) {
{ return false;
foreach ( $eids as $eid ) }
{ $export_root = 'zmExport';
$exportFileList = array_merge( $exportFileList, exportFileList( $eid , $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc ) ); $export_listFile = 'zmFileList.txt';
} $exportFileList = array();
$html_eventMaster = '';
}
else
{
$eid = $eids;
$exportFileList = exportFileList( $eid, $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc );
}
// create an master image slider
if($exportImages)
{
if ( !is_array($eids) )
{
$eids = array($eids);
}
$monitorPath = ZM_DIR_EVENTS."/";
$html_eventMaster = 'zmEventImagesMaster_'.date('Ymd_His'). '.html';
if ( !($fp = fopen( $monitorPath."/".$html_eventMaster, "w" )) ) Fatal( "Can't open event images export file '$html_eventMaster'" );
fwrite( $fp, exportEventImagesMaster( $eids ) );
fclose( $fp );
$exportFileList[] = $monitorPath."/".$html_eventMaster;
}
$listFile = ZM_DIR_EXPORTS."/".$export_listFile;
if ( !($fp = fopen( $listFile, "w" )) )
{
Fatal( "Can't open event export list file '$listFile'" );
}
foreach ( $exportFileList as $exportFile )
{
fwrite( $fp, "$exportFile\n" );
}
fclose( $fp );
$archive = "";
if ( $exportFormat == "tar" )
{
$archive = ZM_DIR_EXPORTS."/".$export_root.".tar.gz";
@unlink( $archive );
if ($exportStructure == 'flat') { //strip file paths if we choose
$command = "nice -10 tar --create --gzip --file=".escapeshellarg($archive)." --files-from=".escapeshellarg($listFile)." --xform='s#^.+/##x'";
} else {
$command = "nice -10 tar --create --gzip --file=".escapeshellarg($archive)." --files-from=".escapeshellarg($listFile);
}
exec( $command, $output, $status );
if ( $status )
{
Error( "Command '$command' returned with status $status" );
if ( $output[0] )
Error( "First line of output is '".$output[0]."'" );
return( false );
}
}
elseif ( $exportFormat == "zip" )
{
$archive = ZM_DIR_EXPORTS."/".$export_root.".zip";
@unlink( $archive );
if ($exportStructure == 'flat') {
$command = "cat ".escapeshellarg($listFile)." | nice -10 zip -q -j ".escapeshellarg($archive)." -@";
} else {
$command = "cat ".escapeshellarg($listFile)." | nice -10 zip -q ".escapeshellarg($archive)." -@";
}
//cat zmFileList.txt | zip -q zm_export.zip -@
//-bash: zip: command not found
exec( $command, $output, $status );
if ( $status )
{
Error( "Command '$command' returned with status $status" );
if ( $output[0] )
Error( "First line of output is '".$output[0]."'" );
return( false );
}
}
//clean up temporary files
if(!empty($html_eventMaster)) {
unlink($monitorPath.'/'.$html_eventMaster);
}
if ( is_array($eids) ) {
foreach ( $eids as $eid ) {
$exportFileList = array_merge( $exportFileList, exportFileList( $eid , $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc ) );
} }
return( '?view=archive%26type='.$exportFormat ); } else {
$eid = $eids;
$exportFileList = exportFileList( $eid, $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc );
}
// create an master image slider
if ( $exportImages ) {
if ( !is_array($eids) ) {
$eids = array($eids);
}
$monitorPath = ZM_DIR_EVENTS.'/';
$html_eventMaster = 'zmEventImagesMaster_'.date('Ymd_His'). '.html';
if ( !($fp = fopen( $monitorPath.'/'.$html_eventMaster, 'w' )) ) Fatal( "Can't open event images export file '$html_eventMaster'" );
fwrite($fp, exportEventImagesMaster($eids));
fclose($fp);
$exportFileList[] = $monitorPath.'/'.$html_eventMaster;
}
$listFile = ZM_DIR_EXPORTS.'/'.$export_listFile;
if ( !($fp = fopen($listFile, 'w')) ) {
Fatal( "Can't open event export list file '$listFile'" );
}
foreach ( $exportFileList as $exportFile ) {
fwrite( $fp, "$exportFile\n" );
}
fclose( $fp );
$archive = '';
if ( $exportFormat == 'tar' ) {
$archive = ZM_DIR_EXPORTS.'/'.$export_root.'.tar.gz';
@unlink( $archive );
if ( $exportStructure == 'flat' ) { //strip file paths if we choose
$command = "nice -10 tar --create --gzip --file=".escapeshellarg($archive)." --files-from=".escapeshellarg($listFile)." --xform='s#^.+/##x'";
} else {
$command = "nice -10 tar --create --gzip --file=".escapeshellarg($archive)." --files-from=".escapeshellarg($listFile);
}
exec( $command, $output, $status );
if ( $status ) {
Error( "Command '$command' returned with status $status" );
if ( $output[0] )
Error( "First line of output is '".$output[0]."'" );
return( false );
}
} elseif ( $exportFormat == 'zip' ) {
$archive = ZM_DIR_EXPORTS.'/'.$export_root.'.zip';
@unlink( $archive );
if ($exportStructure == 'flat') {
$command = "cat ".escapeshellarg($listFile)." | nice -10 zip -q -j ".escapeshellarg($archive)." -@";
} else {
$command = "cat ".escapeshellarg($listFile)." | nice -10 zip -q ".escapeshellarg($archive)." -@";
}
//cat zmFileList.txt | zip -q zm_export.zip -@
//-bash: zip: command not found
exec( $command, $output, $status );
if ( $status ) {
Error("Command '$command' returned with status $status");
if ( $output[0] )
Error("First line of output is '".$output[0]."'");
return false;
}
}
//clean up temporary files
if ( !empty($html_eventMaster) ) {
unlink($monitorPath.'/'.$html_eventMaster);
}
return( '?view=archive%26type='.$exportFormat );
} }

View File

@ -85,11 +85,11 @@ if ( ! is_array( $selected_monitor_ids ) ) {
} # end foreach filter } # end foreach filter
if ( ! empty( $user['MonitorIds'] ) ) { if ( ! empty( $user['MonitorIds'] ) ) {
$ids = explode(',', $user['MonitorIds'] ); $ids = explode(',', $user['MonitorIds'] );
$conditions[] = 'Id IN ('.implode(',',array_map( function(){return '?';}, $ids) ).')'; $conditions[] = 'M.Id IN ('.implode(',',array_map( function(){return '?';}, $ids) ).')';
$values += $ids; $values += $ids;
} }
$sql = 'SELECT *,S.Status AS Status, S.CaptureFPS AS CaptureFPS FROM Monitors AS M LEFT JOIN Monitor_Status AS S ON S.Id=M.Id ' . ( count($conditions) ? ' WHERE ' . implode(' AND ', $conditions ) : '' ).' ORDER BY Sequence ASC'; $sql = 'SELECT *,S.Status AS Status, S.CaptureFPS AS CaptureFPS FROM Monitors AS M LEFT JOIN Monitor_Status AS S ON MonitorId=Id ' . ( count($conditions) ? ' WHERE ' . implode(' AND ', $conditions ) : '' ).' ORDER BY Sequence ASC';
$monitors = dbFetchAll( $sql, null, $values ); $monitors = dbFetchAll( $sql, null, $values );
$displayMonitors = array(); $displayMonitors = array();
$monitors_dropdown = array(); $monitors_dropdown = array();

View File

@ -44,6 +44,11 @@ xhtmlHeaders(__FILE__, translate('AddMonitors'));
</div> </div>
<div style="width:50%;position: absolute; top:0; left: 0;height: 100%;"> <div style="width:50%;position: absolute; top:0; left: 0;height: 100%;">
<fieldset><legend>Enter by IP or URL</legend> <fieldset><legend>Enter by IP or URL</legend>
<p>
Simply enter the ip address or full url to the stream.
It will be probed for available streams, or checked to see if it has already been entered.
If streams are found, they will be listed in the results column. Click Add to add them.
</p>
<!--<input type="text" name="newMonitor[Name]" />--> <!--<input type="text" name="newMonitor[Name]" />-->
<input type="text" name="newMonitor[Url]" oninput="probe(this);"/> <input type="text" name="newMonitor[Url]" oninput="probe(this);"/>
</fieldset> </fieldset>
@ -61,7 +66,9 @@ xhtmlHeaders(__FILE__, translate('AddMonitors'));
<td>MN1</td> <td>MN1</td>
</tr> </tr>
</table> </table>
<p>
Defaults to apply to each monitor:<br/> Defaults to apply to each monitor:<br/>
</p>
<table><tr><th>Setting</th><th>Value</th></tr> <table><tr><th>Setting</th><th>Value</th></tr>
<tr><td><?php echo translate('Function') ?></td><td> <tr><td><?php echo translate('Function') ?></td><td>
<?php <?php
@ -69,7 +76,7 @@ xhtmlHeaders(__FILE__, translate('AddMonitors'));
foreach ( getEnumValues('Monitors', 'Function') as $opt ) { foreach ( getEnumValues('Monitors', 'Function') as $opt ) {
$options[$opt] = translate('Fn'.$opt); $options[$opt] = translate('Fn'.$opt);
} }
echo htmlSelect( 'newMonitor[Function]', $options, 'Record' ); echo htmlSelect( 'newMonitor[Function]', $options, 'Mocord' );
?> ?>
</td></tr> </td></tr>
<?php <?php
@ -100,7 +107,7 @@ xhtmlHeaders(__FILE__, translate('AddMonitors'));
?> ?>
</td></tr> </td></tr>
</table> </table>
<br/>
<input type="file" name="import_file" id="import_file"/> <input type="file" name="import_file" id="import_file"/>
<input type="button" value="Import" onclick="import_csv(this.form);"/> <input type="button" value="Import" onclick="import_csv(this.form);"/>
</div> </div>

View File

@ -238,12 +238,21 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
$source = $monitor['Device'].' ('.$monitor['Channel'].')'; $source = $monitor['Device'].' ('.$monitor['Channel'].')';
} elseif ( $monitor['Type'] == 'Remote' ) { } elseif ( $monitor['Type'] == 'Remote' ) {
$source = preg_replace( '/^.*@/', '', $monitor['Host'] ); $source = preg_replace( '/^.*@/', '', $monitor['Host'] );
if ( $monitor['Port'] != '80' and $monitor['Port'] != '554' ) {
$source .= ':'.$monitor['Port'];
}
} elseif ( $monitor['Type'] == 'File' || $monitor['Type'] == 'cURL' ) { } elseif ( $monitor['Type'] == 'File' || $monitor['Type'] == 'cURL' ) {
$source = preg_replace( '/^.*\//', '', $monitor['Path'] ); $source = preg_replace( '/^.*\//', '', $monitor['Path'] );
} elseif ( $monitor['Type'] == 'Ffmpeg' || $monitor['Type'] == 'Libvlc' ) { } elseif ( $monitor['Type'] == 'Ffmpeg' || $monitor['Type'] == 'Libvlc' ) {
$url_parts = parse_url( $monitor['Path'] ); $url_parts = parse_url( $monitor['Path'] );
$source = $url_parts['host']. ( unset($url_parts['user']);
( isset($url_parts['port']) and ( $url_parts['port'] != '554' and $url_parts['port'] != '80' ) ) ? ':'.$url_parts['port'] : '' ); unset($url_parts['pass']);
unset($url_parts['scheme']);
unset($url_parts['query']);
unset($url_parts['path']);
if ( isset($url_parts['port']) and ( $url_parts['port'] == '80' or $url_parts['port'] == '554' ) )
unset($url_parts['port']);
$source = unparse_url( $url_parts );
} }
if ( $source == '' ) { if ( $source == '' ) {
$source = 'Monitor ' . $monitor['Id']; $source = 'Monitor ' . $monitor['Id'];
@ -283,8 +292,10 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
<td class="colId"><?php echo count($displayMonitors) ?></td> <td class="colId"><?php echo count($displayMonitors) ?></td>
<td class="colLeftButtons" colspan="<?php echo $left_columns -1?>"> <td class="colLeftButtons" colspan="<?php echo $left_columns -1?>">
<input type="button" value="<?php echo translate('Refresh') ?>" onclick="location.reload(true);"/> <input type="button" value="<?php echo translate('Refresh') ?>" onclick="location.reload(true);"/>
<input type="button" name="addBtn" value="<?php echo translate('AddNewMonitor') ?>" onclick="addMonitor(this);"/> <!--<input type="button" name="addBtn" value="<?php echo translate('AddNewMonitor') ?>" onclick="addMonitor(this);"
<!-- <?php echo makePopupButton( '?view=monitor', 'zmMonitor0', 'monitor', translate('AddNewMonitor'), (canEdit( 'Monitors' ) && !$user['MonitorIds']) ) ?> --> <?php echo (canEdit( 'Monitors' ) && !$user['MonitorIds']) ? '' : ' disabled="disabled"' ?>
/>-->
<?php echo makePopupButton( '?view=monitor', 'zmMonitor0', 'monitor', translate('AddNewMonitor'), (canEdit( 'Monitors' ) && !$user['MonitorIds']) ) ?>
<input type="button" name="editBtn" value="<?php echo translate('Edit') ?>" onclick="editMonitor( this )" disabled="disabled"/> <input type="button" name="editBtn" value="<?php echo translate('Edit') ?>" onclick="editMonitor( this )" disabled="disabled"/>
<input type="button" name="deleteBtn" value="<?php echo translate('Delete') ?>" onclick="deleteMonitor( this )" disabled="disabled"/> <input type="button" name="deleteBtn" value="<?php echo translate('Delete') ?>" onclick="deleteMonitor( this )" disabled="disabled"/>
</td> </td>

View File

@ -43,6 +43,8 @@ $filterQuery = $_REQUEST['filter']['query'];
if ( $_REQUEST['filter']['sql'] ) { if ( $_REQUEST['filter']['sql'] ) {
$countSql .= $_REQUEST['filter']['sql']; $countSql .= $_REQUEST['filter']['sql'];
$eventsSql .= $_REQUEST['filter']['sql']; $eventsSql .= $_REQUEST['filter']['sql'];
} else {
Error("No filtering in events, will load ALL!");
} }
$eventsSql .= " ORDER BY $sortColumn $sortOrder"; $eventsSql .= " ORDER BY $sortColumn $sortOrder";
@ -141,6 +143,7 @@ if ( $pages > 1 ) {
$count = 0; $count = 0;
$disk_space_total = 0; $disk_space_total = 0;
Logger::Debug("EventSql: $eventsSql");
$results = dbQuery( $eventsSql ); $results = dbQuery( $eventsSql );
while ( $event_row = dbFetchNext( $results ) ) { while ( $event_row = dbFetchNext( $results ) ) {
$event = new Event( $event_row ); $event = new Event( $event_row );

View File

@ -24,18 +24,18 @@ if ( !canView( 'Events' ) ) {
} }
if ( isset($_SESSION['export']) ) { if ( isset($_SESSION['export']) ) {
if ( isset($_SESSION['export']['detail']) ) if ( isset($_SESSION['export']['detail']) )
$_REQUEST['exportDetail'] = $_SESSION['export']['detail']; $_REQUEST['exportDetail'] = $_SESSION['export']['detail'];
if ( isset($_SESSION['export']['frames']) ) if ( isset($_SESSION['export']['frames']) )
$_REQUEST['exportFrames'] = $_SESSION['export']['frames']; $_REQUEST['exportFrames'] = $_SESSION['export']['frames'];
if ( isset($_SESSION['export']['images']) ) if ( isset($_SESSION['export']['images']) )
$_REQUEST['exportImages'] = $_SESSION['export']['images']; $_REQUEST['exportImages'] = $_SESSION['export']['images'];
if ( isset($_SESSION['export']['video']) ) if ( isset($_SESSION['export']['video']) )
$_REQUEST['exportVideo'] = $_SESSION['export']['video']; $_REQUEST['exportVideo'] = $_SESSION['export']['video'];
if ( isset($_SESSION['export']['misc']) ) if ( isset($_SESSION['export']['misc']) )
$_REQUEST['exportMisc'] = $_SESSION['export']['misc']; $_REQUEST['exportMisc'] = $_SESSION['export']['misc'];
if ( isset($_SESSION['export']['format']) ) if ( isset($_SESSION['export']['format']) )
$_REQUEST['exportFormat'] = $_SESSION['export']['format']; $_REQUEST['exportFormat'] = $_SESSION['export']['format'];
} }
$focusWindow = true; $focusWindow = true;
@ -101,24 +101,20 @@ elseif ( !empty($_REQUEST['eids']) )
</tr> </tr>
</tbody> </tbody>
</table> </table>
<input type="button" id="exportButton" name="exportButton" value="<?php echo translate('Export') ?>" onclick="exportEvent( this.form );" disabled="disabled"/> <button id="exportButton" name="exportButton" value="Export" onclick="exportEvent(this.form);" disabled="disabled"><?php echo translate('Export') ?></button>
</form> </form>
</div> </div>
<?php <?php
if ( isset($_REQUEST['generated']) ) if ( isset($_REQUEST['generated']) ) {
{
?> ?>
<h2 id="exportProgress" class="<?php echo $_REQUEST['generated']?'infoText':'errorText' ?>"><span id="exportProgressText"><?php echo $_REQUEST['generated']?translate('ExportSucceeded'):translate('ExportFailed') ?></span><span id="exportProgressTicker"></span></h2> <h2 id="exportProgress" class="<?php echo $_REQUEST['generated']?'infoText':'errorText' ?>"><span id="exportProgressText"><?php echo $_REQUEST['generated']?translate('ExportSucceeded'):translate('ExportFailed') ?></span><span id="exportProgressTicker"></span></h2>
<?php <?php
} } else {
else
{
?> ?>
<h2 id="exportProgress" class="hidden warnText"><span id="exportProgressText"><?php echo translate('Exporting') ?></span><span id="exportProgressTicker"></span></h2> <h2 id="exportProgress" class="hidden warnText"><span id="exportProgressText"><?php echo translate('Exporting') ?></span><span id="exportProgressTicker"></span></h2>
<?php <?php
} }
if ( !empty($_REQUEST['generated']) ) if ( !empty($_REQUEST['generated']) ) {
{
?> ?>
<h3 id="downloadLink"><a href="<?php echo validHtmlStr($_REQUEST['exportFile']) ?>"><?php echo translate('Download') ?></a></h3> <h3 id="downloadLink"><a href="<?php echo validHtmlStr($_REQUEST['exportFile']) ?>"><?php echo translate('Download') ?></a></h3>
<?php <?php

View File

@ -102,7 +102,7 @@ echo htmlSelect( 'newGroup[ParentId]', $options, $newGroup->ParentId(), array('o
<tr> <tr>
<th scope="row"><?php echo translate('Monitor') ?></th> <th scope="row"><?php echo translate('Monitor') ?></th>
<td> <td>
<select name="newGroup[MonitorIds][]" size="4" multiple="multiple" onchange="configureButtons(this);"> <select name="newGroup[MonitorIds][]" class="chosen" multiple="multiple" onchange="configureButtons(this);">
<?php <?php
$monitors = dbFetchAll( 'SELECT Id,Name FROM Monitors ORDER BY Sequence ASC' ); $monitors = dbFetchAll( 'SELECT Id,Name FROM Monitors ORDER BY Sequence ASC' );
$monitorIds = $newGroup->MonitorIds(); $monitorIds = $newGroup->MonitorIds();
@ -127,4 +127,7 @@ echo htmlSelect( 'newGroup[ParentId]', $options, $newGroup->ParentId(), array('o
</div> </div>
</div> </div>
</body> </body>
<script type="text/javascript">
$j('.chosen').chosen();
</script>
</html> </html>

View File

@ -8,21 +8,22 @@ function probe( url_e ) {
var ProbeResults; var ProbeResults;
function getProbeResponse( respObj, respText ) { function getProbeResponse( respObj, respText ) {
if ( checkStreamForErrors( "getProbeResponse", respObj ) ) if ( checkStreamForErrors( "getProbeResponse", respObj ) ) {
console.log(respText);
return; return;
//alert(respText); }
if ( respObj.Streams ) { if ( respObj.Streams && respObj.Streams.length ) {
parseStreams( respObj.Streams ); parseStreams( respObj.Streams );
} else { //} else {
alert("No Streams"); //console.log("No streams: " + respText);
} }
} // end function getProbeResponse } // end function getProbeResponse
function parseStreams( Streams ) { function parseStreams( Streams ) {
ProbeResults = Array(); ProbeResults = Array();
var results_div = $j('#url_results')[0]; var results_div = $j('#results')[0];
if ( ! results_div ) { if ( ! results_div ) {
console.log("No results div found."); console.log("No results div found.");
return; return;
@ -33,7 +34,7 @@ function parseStreams( Streams ) {
for( i in Streams ) { for( i in Streams ) {
var stream = Streams[i]; var stream = Streams[i];
if ( stream.url ) { if ( stream.url ) {
html += '<p>'+stream.url; html += '<p>'+stream.Monitor.Name + ' at ' + stream.url;
if ( stream.Monitor.Id ) { if ( stream.Monitor.Id ) {
html += ' is already entered into the system by Monitor ' + stream.Monitor.Id + ' ' + stream.Monitor.Name + '<br/>'; html += ' is already entered into the system by Monitor ' + stream.Monitor.Id + ' ' + stream.Monitor.Name + '<br/>';
html += '<input type="button" value="Edit" onclick="addMonitor(\''+stream.url+'\');"/>'; html += '<input type="button" value="Edit" onclick="addMonitor(\''+stream.url+'\');"/>';

View File

@ -34,8 +34,11 @@ function addMonitor(element) {
} }
} }
} }
dupParam = (monitorId == -1 ) ? '': '&dupId='+monitorId; if ( monitorId != -1 ) {
createPopup( '?view=monitor'+dupParam, 'zmMonitor0', 'monitor' ); createPopup( '?view=monitor&dupId='+monitorId, 'zmMonitor0', 'monitor' );
} else {
window.location = '?view=add_monitors';
}
} }
function editMonitor( element ) { function editMonitor( element ) {

View File

@ -56,64 +56,66 @@ function Monitor( monitorData ) {
var stream = $j('#liveStream'+this.id)[0]; var stream = $j('#liveStream'+this.id)[0];
if ( respObj.result == 'Ok' ) { if ( respObj.result == 'Ok' ) {
this.status = respObj.status; if ( respObj.status ) {
this.alarmState = this.status.state; this.status = respObj.status;
this.alarmState = this.status.state;
var stateClass = ""; var stateClass = "";
if ( this.alarmState == STATE_ALARM ) if ( this.alarmState == STATE_ALARM )
stateClass = "alarm"; stateClass = "alarm";
else if ( this.alarmState == STATE_ALERT ) else if ( this.alarmState == STATE_ALERT )
stateClass = "alert"; stateClass = "alert";
else else
stateClass = "idle"; stateClass = "idle";
if ( !COMPACT_MONTAGE ) { if ( !COMPACT_MONTAGE ) {
$('fpsValue'+this.id).set( 'text', this.status.fps ); $('fpsValue'+this.id).set( 'text', this.status.fps );
$('stateValue'+this.id).set( 'text', stateStrings[this.alarmState] ); $('stateValue'+this.id).set( 'text', stateStrings[this.alarmState] );
this.setStateClass( $('monitorState'+this.id), stateClass ); this.setStateClass( $('monitorState'+this.id), stateClass );
} }
this.setStateClass( $('monitor'+this.id), stateClass ); this.setStateClass( $('monitor'+this.id), stateClass );
/*Stream could be an applet so can't use moo tools*/ /*Stream could be an applet so can't use moo tools*/
stream.className = stateClass; stream.className = stateClass;
var isAlarmed = ( this.alarmState == STATE_ALARM || this.alarmState == STATE_ALERT ); var isAlarmed = ( this.alarmState == STATE_ALARM || this.alarmState == STATE_ALERT );
var wasAlarmed = ( this.lastAlarmState == STATE_ALARM || this.lastAlarmState == STATE_ALERT ); var wasAlarmed = ( this.lastAlarmState == STATE_ALARM || this.lastAlarmState == STATE_ALERT );
var newAlarm = ( isAlarmed && !wasAlarmed ); var newAlarm = ( isAlarmed && !wasAlarmed );
var oldAlarm = ( !isAlarmed && wasAlarmed ); var oldAlarm = ( !isAlarmed && wasAlarmed );
if ( newAlarm ) { if ( newAlarm ) {
if ( false && SOUND_ON_ALARM ) {
// Enable the alarm sound
$('alarmSound').removeClass( 'hidden' );
}
if ( POPUP_ON_ALARM ) {
windowToFront();
}
}
if ( false && SOUND_ON_ALARM ) { if ( false && SOUND_ON_ALARM ) {
// Enable the alarm sound if ( oldAlarm ) {
$('alarmSound').removeClass( 'hidden' ); // Disable alarm sound
$('alarmSound').addClass( 'hidden' );
}
} }
if ( POPUP_ON_ALARM ) { if ( this.status.auth ) {
windowToFront(); if ( this.status.auth != auth_hash ) {
} // Try to reload the image stream.
} if ( stream )
if ( false && SOUND_ON_ALARM ) { stream.src = stream.src.replace( /auth=\w+/i, 'auth='+this.status.auth );
if ( oldAlarm ) { console.log("Changed auth from " + auth_hash + " to " + this.status.auth );
// Disable alarm sound auth_hash = this.status.auth;
$('alarmSound').addClass( 'hidden' ); }
} } // end if have a new auth hash
} } // end if has state
if ( this.status.auth ) {
if ( this.status.auth != auth_hash ) {
// Try to reload the image stream.
if ( stream )
stream.src = stream.src.replace( /auth=\w+/i, 'auth='+this.status.auth );
console.log("Changed auth from " + auth_hash + " to " + this.status.auth );
auth_hash = this.status.auth;
}
} // end if have a new auth hash
} else { } else {
console.error( respObj.message ); console.error( respObj.message );
// Try to reload the image stream. // Try to reload the image stream.
if ( stream ) { if ( stream ) {
if ( stream.src ) { if ( stream.src ) {
console.log('Reloading stream: ' + stream.src ); console.log('Reloading stream: ' + stream.src );
stream.src = stream.src.replace(/rand=\d+/i, 'rand='+Math.floor((Math.random() * 1000000) )); stream.src = stream.src.replace(/rand=\d+/i, 'rand='+Math.floor((Math.random() * 1000000) ));
} else { } else {
} }
} else { } else {

View File

@ -35,7 +35,7 @@ monitorData[monitorData.length] = {
'connKey': <?php echo $monitor->connKey() ?>, 'connKey': <?php echo $monitor->connKey() ?>,
'width': <?php echo $monitor->Width() ?>, 'width': <?php echo $monitor->Width() ?>,
'height':<?php echo $monitor->Height() ?>, 'height':<?php echo $monitor->Height() ?>,
'server_url': '<?php echo $monitor->Server()->Url().(ZM_MIN_STREAMING_PORT?':'.(ZM_MIN_STREAMING_PORT+$monitor->Id()):'').$_SERVER['PHP_SELF'] ?>', 'server_url': '<?php echo $monitor->Server()->Url().$_SERVER['PHP_SELF'] ?>',
'onclick': function(){createPopup( '?view=watch&mid=<?php echo $monitor->Id() ?>', 'zmWatch<?php echo $monitor->Id() ?>', 'watch', <?php echo reScale( $monitor->Width(), $monitor->PopupScale() ); ?>, <?php echo reScale( $monitor->Height(), $monitor->PopupScale() ); ?> );} 'onclick': function(){createPopup( '?view=watch&mid=<?php echo $monitor->Id() ?>', 'zmWatch<?php echo $monitor->Id() ?>', 'watch', <?php echo reScale( $monitor->Width(), $monitor->PopupScale() ); ?>, <?php echo reScale( $monitor->Height(), $monitor->PopupScale() ); ?> );}
}; };
<?php <?php

View File

@ -38,7 +38,6 @@ function changeScale() {
newHeight = monitorHeight * scale / SCALE_BASE; newHeight = monitorHeight * scale / SCALE_BASE;
} }
Cookie.write( 'zmWatchScale'+monitorId, scale, { duration: 10*365 } ); Cookie.write( 'zmWatchScale'+monitorId, scale, { duration: 10*365 } );
/*Stream could be an applet so can't use moo tools*/ /*Stream could be an applet so can't use moo tools*/
@ -107,101 +106,112 @@ function setAlarmState( currentAlarmState ) {
var streamCmdParms = "view=request&request=stream&connkey="+connKey; var streamCmdParms = "view=request&request=stream&connkey="+connKey;
if ( auth_hash ) if ( auth_hash )
streamCmdParms += '&auth='+auth_hash; streamCmdParms += '&auth='+auth_hash;
var streamCmdReq = new Request.JSON( {
var streamCmdReq = new Request.JSON( { url: monitorUrl+thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getStreamCmdResponse } ); url: monitorUrl+thisUrl,
method: 'get',
timeout: AJAX_TIMEOUT,
link: 'chain',
onSuccess: getStreamCmdResponse,
onFailure: getStreamCmdFailure
} );
var streamCmdTimer = null; var streamCmdTimer = null;
var streamStatus; var streamStatus;
function getStreamCmdFailure(xhr) {
console.log(xhr);
}
function getStreamCmdResponse( respObj, respText ) { function getStreamCmdResponse( respObj, respText ) {
watchdogOk("stream"); watchdogOk("stream");
if ( streamCmdTimer ) if ( streamCmdTimer )
streamCmdTimer = clearTimeout( streamCmdTimer ); streamCmdTimer = clearTimeout( streamCmdTimer );
if ( respObj.result == 'Ok' ) { if ( respObj.result == 'Ok' ) {
streamStatus = respObj.status; // The get status command can get backed up, in which case we won't be able to get the semaphore and will exit.
$('fpsValue').set( 'text', streamStatus.fps ); if ( respObj.status ) {
streamStatus = respObj.status;
$('fpsValue').set( 'text', streamStatus.fps );
setAlarmState( streamStatus.state ); setAlarmState( streamStatus.state );
$('levelValue').set( 'text', streamStatus.level ); $('levelValue').set( 'text', streamStatus.level );
if ( streamStatus.level > 95 ) if ( streamStatus.level > 95 )
$('levelValue').className = "alarm"; $('levelValue').className = "alarm";
else if ( streamStatus.level > 80 ) else if ( streamStatus.level > 80 )
$('levelValue').className = "alert"; $('levelValue').className = "alert";
else else
$('levelValue').className = "ok"; $('levelValue').className = "ok";
var delayString = secsToTime( streamStatus.delay ); var delayString = secsToTime( streamStatus.delay );
if ( streamStatus.paused == true ) { if ( streamStatus.paused == true ) {
$('modeValue').set( 'text', "Paused" ); $('modeValue').set( 'text', "Paused" );
$('rate').addClass( 'hidden' ); $('rate').addClass( 'hidden' );
$('delayValue').set( 'text', delayString ); $('delayValue').set( 'text', delayString );
$('delay').removeClass( 'hidden' ); $('delay').removeClass( 'hidden' );
$('level').removeClass( 'hidden' ); $('level').removeClass( 'hidden' );
streamCmdPause( false ); streamCmdPause( false );
} else if ( streamStatus.delayed == true ) { } else if ( streamStatus.delayed == true ) {
$('modeValue').set( 'text', "Replay" ); $('modeValue').set( 'text', "Replay" );
$('rateValue').set( 'text', streamStatus.rate ); $('rateValue').set( 'text', streamStatus.rate );
$('rate').removeClass( 'hidden' ); $('rate').removeClass( 'hidden' );
$('delayValue').set( 'text', delayString ); $('delayValue').set( 'text', delayString );
$('delay').removeClass( 'hidden' ); $('delay').removeClass( 'hidden' );
$('level').removeClass( 'hidden' ); $('level').removeClass( 'hidden' );
if ( streamStatus.rate == 1 ) { if ( streamStatus.rate == 1 ) {
streamCmdPlay( false ); streamCmdPlay( false );
} else if ( streamStatus.rate > 0 ) { } else if ( streamStatus.rate > 0 ) {
if ( streamStatus.rate < 1 ) if ( streamStatus.rate < 1 )
streamCmdSlowFwd( false ); streamCmdSlowFwd( false );
else else
streamCmdFastFwd( false ); streamCmdFastFwd( false );
} else {
if ( streamStatus.rate > -1 )
streamCmdSlowRev( false );
else
streamCmdFastRev( false );
} // rate
} else {
$('modeValue').set( 'text', "Live" );
$('rate').addClass( 'hidden' );
$('delay').addClass( 'hidden' );
$('level').addClass( 'hidden' );
streamCmdPlay( false );
} // end if paused or delayed
$('zoomValue').set( 'text', streamStatus.zoom );
if ( streamStatus.zoom == "1.0" )
setButtonState( $('zoomOutBtn'), 'unavail' );
else
setButtonState( $('zoomOutBtn'), 'inactive' );
if ( canEditMonitors ) {
if ( streamStatus.enabled ) {
$('enableAlarmsLink').addClass( 'hidden' );
$('disableAlarmsLink').removeClass( 'hidden' );
if ( streamStatus.forced ) {
$('forceAlarmLink').addClass( 'hidden' );
$('cancelAlarmLink').removeClass( 'hidden' );
} else { } else {
$('forceAlarmLink').removeClass( 'hidden' ); if ( streamStatus.rate > -1 )
$('cancelAlarmLink').addClass( 'hidden' ); streamCmdSlowRev( false );
} else
$('forceCancelAlarm').removeClass( 'hidden' ); streamCmdFastRev( false );
} // rate
} else { } else {
$('enableAlarmsLink').removeClass( 'hidden' ); $('modeValue').set( 'text', "Live" );
$('disableAlarmsLink').addClass( 'hidden' ); $('rate').addClass( 'hidden' );
$('forceCancelAlarm').addClass( 'hidden' ); $('delay').addClass( 'hidden' );
} $('level').addClass( 'hidden' );
$('enableDisableAlarms').removeClass( 'hidden' ); streamCmdPlay( false );
} // end if canEditMonitors } // end if paused or delayed
if ( streamStatus.auth ) { $('zoomValue').set( 'text', streamStatus.zoom );
console.log("Haev a new auth hash" + streamStatus.auth); if ( streamStatus.zoom == "1.0" )
// Try to reload the image stream. setButtonState( $('zoomOutBtn'), 'unavail' );
var streamImg = $('liveStream'); else
if ( streamImg ) setButtonState( $('zoomOutBtn'), 'inactive' );
streamImg.src = streamImg.src.replace( /auth=\w+/i, 'auth='+streamStatus.auth );
} // end if haev a new auth hash if ( canEditMonitors ) {
if ( streamStatus.enabled ) {
$('enableAlarmsLink').addClass( 'hidden' );
$('disableAlarmsLink').removeClass( 'hidden' );
if ( streamStatus.forced ) {
$('forceAlarmLink').addClass( 'hidden' );
$('cancelAlarmLink').removeClass( 'hidden' );
} else {
$('forceAlarmLink').removeClass( 'hidden' );
$('cancelAlarmLink').addClass( 'hidden' );
}
$('forceCancelAlarm').removeClass( 'hidden' );
} else {
$('enableAlarmsLink').removeClass( 'hidden' );
$('disableAlarmsLink').addClass( 'hidden' );
$('forceCancelAlarm').addClass( 'hidden' );
}
$('enableDisableAlarms').removeClass( 'hidden' );
} // end if canEditMonitors
if ( streamStatus.auth ) {
console.log("Haev a new auth hash" + streamStatus.auth);
// Try to reload the image stream.
var streamImg = $('liveStream');
if ( streamImg )
streamImg.src = streamImg.src.replace( /auth=\w+/i, 'auth='+streamStatus.auth );
} // end if haev a new auth hash
} // end if respObj.status
} else { } else {
checkStreamForErrors("getStreamCmdResponse",respObj);//log them checkStreamForErrors("getStreamCmdResponse",respObj);//log them
// Try to reload the image stream. // Try to reload the image stream.

View File

@ -48,7 +48,7 @@ var maxDisplayEvents = <?php echo 2 * MAX_EVENTS ?>;
var monitorId = <?php echo $monitor->Id() ?>; var monitorId = <?php echo $monitor->Id() ?>;
var monitorWidth = <?php echo $monitor->Width() ?>; var monitorWidth = <?php echo $monitor->Width() ?>;
var monitorHeight = <?php echo $monitor->Height() ?>; var monitorHeight = <?php echo $monitor->Height() ?>;
var monitorUrl = '<?php echo ( $monitor->Server()->Url() ) ?>'; var monitorUrl = '<?php echo ( $monitor->Server()->Url() . ( ZM_MIN_STREAMING_PORT ? ':'. (ZM_MIN_STREAMING_PORT+$monitor->Id()) : '' ) ) ?>';
var scale = '<?php echo $scale ?>'; var scale = '<?php echo $scale ?>';

View File

@ -72,11 +72,11 @@ if ( ! $monitor ) {
$monitor->set( array( $monitor->set( array(
'Id' => 0, 'Id' => 0,
'Name' => translate('Monitor').'-'.$nextId, 'Name' => translate('Monitor').'-'.$nextId,
'Function' => 'Monitor', 'Function' => 'Mocord',
'Enabled' => true, 'Enabled' => true,
'LinkedMonitors' => '', 'LinkedMonitors' => '',
'Type' => '', 'Type' => 'Ffmpeg',
'Device' => "/dev/video0", 'Device' => '/dev/video0',
'Channel' => '0', 'Channel' => '0',
'Format' => 0x000000ff, 'Format' => 0x000000ff,
'Protocol' => '', 'Protocol' => '',
@ -87,26 +87,26 @@ if ( ! $monitor ) {
'Port' => '80', 'Port' => '80',
'User' => '', 'User' => '',
'Pass' => '', 'Pass' => '',
'Colours' => 3, 'Colours' => 4,
'Palette' => 0, 'Palette' => 0,
'Width' => '320', 'Width' => '1280',
'Height' => '240', 'Height' => '962',
'Orientation' => '0', 'Orientation' => '0',
'Deinterlacing' => 0, 'Deinterlacing' => 0,
'RTSPDescribe' => 0, 'RTSPDescribe' => 0,
'SaveJPEGs' => '3', 'SaveJPEGs' => '4',
'VideoWriter' => '0', 'VideoWriter' => '1',
'EncoderParameters' => "# Lines beginning with # are a comment \n# For changing quality, use the crf option\n# 1 is best, 51 is worst quality\n#crf=23\n", 'EncoderParameters' => "# Lines beginning with # are a comment \n# For changing quality, use the crf option\n# 1 is best, 51 is worst quality\n#crf=23\n",
'RecordAudio' => '0', 'RecordAudio' => '0',
'LabelFormat' => '%N - %d/%m/%y %H:%M:%S', 'LabelFormat' => '%N - %d/%m/%y %H:%M:%S',
'LabelX' => 0, 'LabelX' => 0,
'LabelY' => 0, 'LabelY' => 0,
'LabelSize' => 1, 'LabelSize' => 1,
'ImageBufferCount' => 50, 'ImageBufferCount' => 40,
'WarmupCount' => 25, 'WarmupCount' => 1,
'PreEventCount' => 25, 'PreEventCount' => 1,
'PostEventCount' => 25, 'PostEventCount' => 5,
'StreamReplayBuffer' => 1000, 'StreamReplayBuffer' => 0,
'AlarmFrameCount' => 1, 'AlarmFrameCount' => 1,
'Controllable' => 0, 'Controllable' => 0,
'ControlId' => '', 'ControlId' => '',
@ -124,9 +124,9 @@ if ( ! $monitor ) {
'EventPrefix' => 'Event-', 'EventPrefix' => 'Event-',
'AnalysisFPSLimit' => '', 'AnalysisFPSLimit' => '',
'AnalysisUpdateDelay' => 0, 'AnalysisUpdateDelay' => 0,
'MaxFPS' => '', 'MaxFPS' => '30',
'AlarmMaxFPS' => '', 'AlarmMaxFPS' => '30',
'FPSReportInterval' => 1000, 'FPSReportInterval' => 100,
'RefBlendPerc' => 6, 'RefBlendPerc' => 6,
'AlarmRefBlendPerc' => 6, 'AlarmRefBlendPerc' => 6,
'DefaultView' => 'Events', 'DefaultView' => 'Events',
@ -138,8 +138,8 @@ if ( ! $monitor ) {
'Triggers' => '', 'Triggers' => '',
'V4LMultiBuffer' => '', 'V4LMultiBuffer' => '',
'V4LCapturesPerFrame' => 1, 'V4LCapturesPerFrame' => 1,
'ServerId' => $Server['Id'], 'ServerId' => 'auto',
'StorageId' => '0', 'StorageId' => '1',
) ); ) );
} # end if $_REQUEST['dupID'] } # end if $_REQUEST['dupID']
} # end if $_REQUEST['mid'] } # end if $_REQUEST['mid']
@ -674,7 +674,7 @@ switch ( $tab ) {
<tr class="Name"><td><?php echo translate('Name') ?></td><td><input type="text" name="newMonitor[Name]" value="<?php echo validHtmlStr($monitor->Name()) ?>" /></td></tr> <tr class="Name"><td><?php echo translate('Name') ?></td><td><input type="text" name="newMonitor[Name]" value="<?php echo validHtmlStr($monitor->Name()) ?>" /></td></tr>
<tr><td><?php echo translate('Server') ?></td><td> <tr><td><?php echo translate('Server') ?></td><td>
<?php <?php
$servers = array(''=>'None'); $servers = array(''=>'None','auto'=>'Auto');
$result = dbQuery( 'SELECT * FROM Servers ORDER BY Name'); $result = dbQuery( 'SELECT * FROM Servers ORDER BY Name');
$results = $result->fetchALL(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'Server' ); $results = $result->fetchALL(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'Server' );
foreach ( $results as $row => $server_obj ) { foreach ( $results as $row => $server_obj ) {

View File

@ -158,7 +158,7 @@ if( !isset($_REQUEST['step']) || ($_REQUEST['step'] == "1")) {
*/ */
// $sourceDesc = htmlspecialchars(serialize($camera['monitor'])); // $sourceDesc = htmlspecialchars(serialize($camera['monitor']));
$sourceDesc = base64_encode(serialize($camera['monitor'])); $sourceDesc = base64_encode(serialize($camera['monitor']));
$sourceString = $camera['model'].' @ '.$host; $sourceString = $camera['model'].' @ '.$host . ' using version ' . $camera['monitor']['SOAP'] ;
$cameras[$sourceDesc] = $sourceString; $cameras[$sourceDesc] = $sourceString;
} }

View File

@ -23,7 +23,7 @@ xhtmlHeaders(__FILE__, translate('LoggingIn') );
<body> <body>
<div id="page"> <div id="page">
<div id="header"> <div id="header">
<h1>ZoneMinder <?php echo translate('Login') ?></h1> <h1><?php echo ZM_WEB_TITLE . ' ' . translate('Login') ?></h1>
</div> </div>
<div id="content"> <div id="content">
<h2><?php echo translate('LoggingIn') ?></h2> <h2><?php echo translate('LoggingIn') ?></h2>

View File

@ -32,6 +32,9 @@ if ( $_REQUEST['id'] ) {
$newServer = array(); $newServer = array();
$newServer['Name'] = translate('NewServer'); $newServer['Name'] = translate('NewServer');
$newServer['Hostname'] = ''; $newServer['Hostname'] = '';
$newServer['zmstats'] = '';
$newServer['zmaudit'] = '';
$newServer['zmtrigger'] = '';
} }
$focusWindow = true; $focusWindow = true;

View File

@ -36,6 +36,7 @@ if ( $_REQUEST['id'] ) {
$newStorage['Type'] = 'local'; $newStorage['Type'] = 'local';
$newStorage['Scheme'] = 'Medium'; $newStorage['Scheme'] = 'Medium';
$newStorage['StorageId'] = ''; $newStorage['StorageId'] = '';
$newStorage['ServerId'] = '';
} }
$type_options = array( 'local' => translate('Local'), 's3fs' => translate('s3fs') ); $type_options = array( 'local' => translate('Local'), 's3fs' => translate('s3fs') );

View File

@ -18,45 +18,44 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
// //
if ( !canView( 'Events' ) ) if ( !canView( 'Events' ) ) {
{ $view = 'error';
$view = "error"; return;
return;
} }
$archivetype = $_REQUEST['type']; $archivetype = $_REQUEST['type'];
if ( $archivetype ) { if ( $archivetype ) {
switch ($archivetype) { switch ($archivetype) {
case "tar": case 'tar':
$mimetype = "gzip"; $mimetype = 'gzip';
$file_ext = "tar.gz"; $file_ext = 'tar.gz';
break; break;
case "zip": case 'zip':
$mimetype = "zip"; $mimetype = 'zip';
$file_ext = "zip"; $file_ext = 'zip';
break; break;
default: default:
$mimetype = NULL; $mimetype = NULL;
$file_ext = NULL; $file_ext = NULL;
} }
if ( $mimetype ) { if ( $mimetype ) {
$filename = "zmExport.$file_ext"; $filename = "zmExport.$file_ext";
$filename_path = ZM_DIR_TEMP."/".$filename; $filename_path = ZM_DIR_EXPORTS.'/'.$filename;
if ( is_readable($filename_path) ) { if ( is_readable($filename_path) ) {
header( "Content-type: application/$mimetype" ); header( "Content-type: application/$mimetype" );
header( "Content-Disposition: attachment; filename=$filename"); header( "Content-Disposition: attachment; filename=$filename");
set_time_limit(0); set_time_limit(0);
readfile( $filename_path ); readfile( $filename_path );
} else {
Error("$filename_path does not exist or is not readable.");
}
} else { } else {
Error("Unsupported archive type specified. Supported archives are tar and zip"); Error("$filename_path does not exist or is not readable.");
} }
} else {
Error("Unsupported archive type specified. Supported archives are tar and zip");
}
} else { } else {
Error("No archive type given to archive.php. Please specify a tar or zip archive."); Error("No archive type given to archive.php. Please specify a tar or zip archive.");
} }
?> ?>

View File

@ -1,25 +1,37 @@
#!/bin/bash #!/bin/bash
# The purpose of this file is to create the symlinks in the web folder to the content folder. It can use an existing content folder or create a new one. # This tool is used to verify folders critical to ZoneMinder exist and have the right permissions.
# It will also create symlinks when necessary. It can use an existing content folder or create a new one.
# Set the content dir default to be the one supplied to cmake # Set the content dir default to be the one supplied to cmake
ZM_PATH_CONTENT="@ZM_CONTENTDIR@" ZM_PATH_CONTENT="@ZM_CONTENTDIR@"
# Set the zoneminder log dir default to be the one supplied to cmake
ZM_LOGDIR="@ZM_LOGDIR@"
# Set the zoneminder temp dir default to be the one supplied to cmake
ZM_TMPDIR="@ZM_TMPDIR@"
echo "*** This bash script creates the nessecary symlinks for the zoneminder content" echo "*** This bash script creates the nessecary symlinks for the zoneminder content"
echo "*** It can use an existing content folder or create a new one" echo "*** It can use an existing content folder or create a new one"
echo "*** For usage: use -h" echo "*** For usage: use -h"
echo "*** The default content directory is: $ZM_PATH_CONTENT" echo "*** The default content directory is: $ZM_PATH_CONTENT"
echo "*** The default log directory is: $ZM_LOGDIR"
echo "*** The default temp directory is: $ZM_TMPDIR"
echo "" echo ""
usage() usage()
{ {
cat <<EOF cat <<EOF
Usage: $0 [-q] [-z zm.conf] [-w WEB DIRECTORY] [CONTENT DIRECTORY] Usage: $0 [-q] [-o] [-z zm.conf] [-w WEB DIRECTORY] [-l LOG DIRECTORY] [-t TMP DIRECTORY] [CONTENT DIRECTORY]
OPTIONS: OPTIONS:
-h Show this message and quit -h Show this message and quit
-z ZoneMinder configuration file -z ZoneMinder configuration file
-w Override the web directory from zm.conf -w Override the web directory from zm.conf
-q Quick mode. Do not change ownership recursively. -q Quick mode. Do not change ownership recursively.
-l Override the zm log folder location
-t Override the zm temp folder location
-o Enable old legacy symlinks inside ZoneMinder's webroot folder
If the -w option is not used to specify the path to the web directory, If the -w option is not used to specify the path to the web directory,
the script will use the path from zoneminder's configuration file. the script will use the path from zoneminder's configuration file.
@ -27,10 +39,14 @@ If the -z option is used, the argument will be used instead of zm.conf
Otherwise, it will attempt to read zm.conf from the local directory. Otherwise, it will attempt to read zm.conf from the local directory.
If that fails, it will try from /etc/zm.conf If that fails, it will try from /etc/zm.conf
Newer versions of ZoneMinder no longer require symlinks to the events and
images folders inside the zm webroot. Indeed this is a security risk, and
$0 will no longer create these unless the -o option is specified.
EOF EOF
} }
while getopts "hz:w:q" OPTION while getopts "hz:w:q:l:t:o" OPTION
do do
case $OPTION in case $OPTION in
h) h)
@ -46,6 +62,15 @@ do
q) q)
QUICK=1 QUICK=1
;; ;;
l)
ZM_LOGDIR_FORCE=$OPTARG
;;
t)
ZM_TMPDIR_FORCE=$OPTARG
;;
o)
LEGACY=1
;;
esac esac
done done
shift $(( OPTIND - 1 )) shift $(( OPTIND - 1 ))
@ -73,7 +98,7 @@ elif [ -f "/etc/zm.conf" ]; then
echo "Using system zm.conf" echo "Using system zm.conf"
source "/etc/zm.conf" source "/etc/zm.conf"
else else
echo "Failed locating zoneminder configuration file (zm.conf)\nUse the -z option to specify the full path to the zoneminder configuration file" echo -e "Failed locating zoneminder configuration file (zm.conf)\nUse the -z option to specify the full path to the zoneminder configuration file"
exit 45 exit 45
fi fi
@ -82,6 +107,16 @@ if [ -n "$ZM_PATH_WEB_FORCE" ]; then
ZM_PATH_WEB="$(readlink -f $ZM_PATH_WEB_FORCE)" ZM_PATH_WEB="$(readlink -f $ZM_PATH_WEB_FORCE)"
fi fi
# Override the log directory path
if [ -n "$ZM_LOGDIR_FORCE" ]; then
ZM_LOGDIR="$(readlink -f $ZM_LOGDIR_FORCE)"
fi
# Override the tmp directory path
if [ -n "$ZM_TMPDIR_FORCE" ]; then
ZM_TMPDIR="$(readlink -f $ZM_TMPDIR_FORCE)"
fi
# Override the default content path # Override the default content path
if [[ -n "$@" ]]; then if [[ -n "$@" ]]; then
ZM_PATH_CONTENT="$(readlink -f $@)" ZM_PATH_CONTENT="$(readlink -f $@)"
@ -90,6 +125,8 @@ fi
# Print some information # Print some information
echo "Web folder : $ZM_PATH_WEB" echo "Web folder : $ZM_PATH_WEB"
echo "Content folder : $ZM_PATH_CONTENT" echo "Content folder : $ZM_PATH_CONTENT"
echo "Log folder : $ZM_LOGDIR"
echo "Temp folder : $ZM_TMPDIR"
echo "" echo ""
# Verify the web folder is a real directory # Verify the web folder is a real directory
@ -98,7 +135,7 @@ if [ -d "$ZM_PATH_WEB" ]; then
echo "OK" echo "OK"
else else
echo "Failed" echo "Failed"
exit 3 exit 2
fi fi
# Check if the content folder exists, and if not, create it # Check if the content folder exists, and if not, create it
@ -109,6 +146,22 @@ else
echo "No" echo "No"
echo -n "Creating the content folder... " echo -n "Creating the content folder... "
mkdir "$ZM_PATH_CONTENT" mkdir "$ZM_PATH_CONTENT"
if [ "$?" = "0" ]; then
echo "OK"
else
echo "Failed"
exit 3
fi
fi
# Check if the log folder exists, and if not, create the entire folder including its parents
echo -n "Checking if the log folder exists... "
if [ -d "$ZM_LOGDIR" ]; then
echo "Yes"
else
echo "No"
echo -n "Creating the log folder... "
mkdir -p "$ZM_LOGDIR"
if [ "$?" = "0" ]; then if [ "$?" = "0" ]; then
echo "OK" echo "OK"
else else
@ -116,6 +169,23 @@ else
exit 4 exit 4
fi fi
fi fi
# Check if the temp folder exists, and if not, create the entire folder including its parents
echo -n "Checking if the temp folder exists... "
if [ -d "$ZM_TMPDIR" ]; then
echo "Yes"
else
echo "No"
echo -n "Creating the temp folder... "
mkdir -p "$ZM_TMPDIR"
if [ "$?" = "0" ]; then
echo "OK"
else
echo "Failed"
exit 5
fi
fi
# Check if the content/images folder exists, and if not, create it # Check if the content/images folder exists, and if not, create it
echo -n "Checking if the images folder exists inside the content folder... " echo -n "Checking if the images folder exists inside the content folder... "
if [ -d "$ZM_PATH_CONTENT/images" ]; then if [ -d "$ZM_PATH_CONTENT/images" ]; then
@ -131,6 +201,7 @@ else
exit 6 exit 6
fi fi
fi fi
# Check if the content/events folder exists, and if not, create it # Check if the content/events folder exists, and if not, create it
echo -n "Checking if the events folder exists inside the content folder... " echo -n "Checking if the events folder exists inside the content folder... "
if [ -d "$ZM_PATH_CONTENT/events" ]; then if [ -d "$ZM_PATH_CONTENT/events" ]; then
@ -179,24 +250,26 @@ if [ -d "$ZM_PATH_WEB/events" ]; then
fi fi
fi fi
# Create the symlink for the images folder if [ -n "$LEGACY" ]; then
echo -n "Creating the symlink for the images folder... " # Create the symlink for the images folder
ln -s -f "$ZM_PATH_CONTENT/images" "$ZM_PATH_WEB/images" echo -n "Creating the symlink for the images folder... "
if [ "$?" = "0" ]; then ln -s -f "$ZM_PATH_CONTENT/images" "$ZM_PATH_WEB/images"
echo "OK" if [ "$?" = "0" ]; then
else echo "OK"
echo "Failed" else
exit 15 echo "Failed"
fi exit 15
fi
# Create the symlink for the events folder
echo -n "Creating the symlink for the events folder... " # Create the symlink for the events folder
ln -s -f "$ZM_PATH_CONTENT/events" "$ZM_PATH_WEB/events" echo -n "Creating the symlink for the events folder... "
if [ "$?" = "0" ]; then ln -s -f "$ZM_PATH_CONTENT/events" "$ZM_PATH_WEB/events"
echo "OK" if [ "$?" = "0" ]; then
else echo "OK"
echo "Failed" else
exit 16 echo "Failed"
exit 16
fi
fi fi
# change ownership for the images folder. do it recursively unless -q is used # change ownership for the images folder. do it recursively unless -q is used
@ -228,11 +301,32 @@ if [ -n "$QUICK" ]; then
echo "OK" echo "OK"
else else
echo "Failed" echo "Failed"
exit 25 exit 23
fi fi
else else
echo -n "Changing ownership of the events folder recursively to ${ZM_WEB_USER} ${ZM_WEB_GROUP}... " echo -n "Changing ownership of the events folder recursively to ${ZM_WEB_USER} ${ZM_WEB_GROUP}... "
chown -R ${ZM_WEB_USER}:${ZM_WEB_GROUP} "$ZM_PATH_CONTENT/events" chown -R ${ZM_WEB_USER}:${ZM_WEB_GROUP} "$ZM_PATH_CONTENT/events"
if [ "$?" = "0" ]; then
echo "OK"
else
echo "Failed"
exit 24
fi
fi
# change ownership for the log folder. do it recursively unless -q is used
if [ -n "$QUICK" ]; then
echo -n "Changing ownership of the log folder to ${ZM_WEB_USER} ${ZM_WEB_GROUP}... "
chown ${ZM_WEB_USER}:${ZM_WEB_GROUP} "$ZM_LOGDIR"
if [ "$?" = "0" ]; then
echo "OK"
else
echo "Failed"
exit 25
fi
else
echo -n "Changing ownership of the log folder recursively to ${ZM_WEB_USER} ${ZM_WEB_GROUP}... "
chown -R ${ZM_WEB_USER}:${ZM_WEB_GROUP} "$ZM_LOGDIR"
if [ "$?" = "0" ]; then if [ "$?" = "0" ]; then
echo "OK" echo "OK"
else else
@ -241,6 +335,27 @@ else
fi fi
fi fi
# change ownership for the temp folder. do it recursively unless -q is used
if [ -n "$QUICK" ]; then
echo -n "Changing ownership of the temp folder to ${ZM_WEB_USER} ${ZM_WEB_GROUP}... "
chown ${ZM_WEB_USER}:${ZM_WEB_GROUP} "$ZM_TMPDIR"
if [ "$?" = "0" ]; then
echo "OK"
else
echo "Failed"
exit 27
fi
else
echo -n "Changing ownership of the temp folder recursively to ${ZM_WEB_USER} ${ZM_WEB_GROUP}... "
chown -R ${ZM_WEB_USER}:${ZM_WEB_GROUP} "$ZM_TMPDIR"
if [ "$?" = "0" ]; then
echo "OK"
else
echo "Failed"
exit 28
fi
fi
# Change directory permissions for the images folder # Change directory permissions for the images folder
echo -n "Changing permissions of the images folder to 775... " echo -n "Changing permissions of the images folder to 775... "
chmod 775 "$ZM_PATH_CONTENT/images" chmod 775 "$ZM_PATH_CONTENT/images"
@ -251,7 +366,6 @@ else
exit 30 exit 30
fi fi
# Change directory permissions for the events folder # Change directory permissions for the events folder
echo -n "Changing permissions of the events folder to 775... " echo -n "Changing permissions of the events folder to 775... "
chmod 775 "$ZM_PATH_CONTENT/events" chmod 775 "$ZM_PATH_CONTENT/events"
@ -262,5 +376,35 @@ else
exit 31 exit 31
fi fi
# Change directory permissions for the log folder
echo -n "Changing permissions of the log folder to 775... "
chmod 775 "$ZM_LOGDIR"
if [ "$?" = "0" ]; then
echo "OK"
else
echo "Failed"
exit 32
fi
# Change directory permissions for the temp folder
echo -n "Changing permissions of the temp folder to 775... "
chmod 775 "$ZM_TMPDIR"
if [ "$?" = "0" ]; then
echo "OK"
else
echo "Failed"
exit 33
fi
# Link the CakePHP tmp folder to the zoneminder temp folder
echo -n "Linking CakePHP tmp folder to ${ZM_TMPDIR}... "
ln -sfT "$ZM_TMPDIR" "$ZM_PATH_WEB/api/app/tmp"
if [ "$?" = "0" ]; then
echo "OK"
else
echo "Failed"
exit 40
fi
echo "" echo ""
echo "All done" echo "All done"