Merge branch 'master' of github.com:ConnorTechnology/ZoneMinder

This commit is contained in:
Isaac Connor 2017-06-05 16:29:35 -04:00
commit 523f3f4fca
39 changed files with 3722 additions and 3162 deletions

View File

@ -20,6 +20,7 @@ addons:
- git - git
- curl - curl
- sshfs - sshfs
- sed
env: env:
matrix: matrix:
- OS=el DIST=6 - OS=el DIST=6

View File

@ -0,0 +1,573 @@
zoneminder (1.28.1+1-vivid-SNAPSHOT2015081701) vivid; urgency=medium
* include api, switch to cmake build
-- Isaac Connor <iconnor@connortechnology.com> Mon, 17 Aug 2015 10:29:23 -0400
zoneminder (1.28.1-8) unstable; urgency=medium
* Patchworks:
+ New upstream "980-fix-image-size.patch".
+ New "default_cgi-path.patch" to correct default ZM_PATH_ZMS.
* postinst: set "root" as group owner for "/var/log/zm" to silence
logrotate warnings.
* Minor correction to README.Debian.
-- Dmitry Smirnov <onlyjob@debian.org> Sun, 16 Aug 2015 19:19:50 +1000
zoneminder (1.28.1-7) unstable; urgency=medium
* Build-Depends += "cakephp (<< 3.0.0~)";
Zoneminder is not compatible with latest CakePHP.
* Handle conffile removal from maintscript.
* rules: build man pages reproducibly.
* gbp.conf: renamed old style config section [git-dch] to [dch].
* README
+ added instructions to update owner of the "/etc/zm/zm.conf"
(Closes: #789327).
+ zmupdate.pl needs CREATE rights.
+ added note about required number of "fcgiwrap" workers.
* New upstream patch: "zmtrigger-plus.patch".
-- Dmitry Smirnov <onlyjob@debian.org> Mon, 20 Jul 2015 16:30:15 +1000
zoneminder (1.28.1-6) unstable; urgency=low
* New "zoneminder-doc" and "zoneminder-dbg" packages.
-- Dmitry Smirnov <onlyjob@debian.org> Sun, 19 Apr 2015 14:50:41 +1000
zoneminder (1.28.1-5) unstable; urgency=low
* Move handling of "/var/run/zm" and "/tmp/zm" from .service into .tmpfile.
Let dh_installinit do the job. Thanks, Andrew Bauer.
* Use dh_apache2 to install Apache conf file; remove old conf and symlink.
* Promote "libapache2-mod-php5 | php5-fpm" to Recommends.
* Build-Depends:
+ dh-linktree
+ cakephp (>= 2.6.3)
+ libjs-jquery
+ libjs-mootools
* Depends:
- libjs-jquery
- libjs-mootools
* Build-time replace bundled CakePHP with system one using "dh-linktree".
* Use "dh-linktree" to handle mootools and jquery symlinks.
-- Dmitry Smirnov <onlyjob@debian.org> Sun, 19 Apr 2015 11:45:01 +1000
zoneminder (1.28.1-4) unstable; urgency=low
* New patch to fix HTML export with USE_DEEP_STORAGE (closes: #723706).
* New "783.patch" to describe potential data loss in ZM_USE_DEEP_STORAGE.
* New patch to change default date format to region-neutral ISO notation
with time zone.
* Build sphinx documentation:
+ Install "zoneminder.1" man page.
+ Build-Depends += "python-sphinx | python3-sphinx"
+ Added commented "zoneminder-doc" package.
+ Added "docs.patch" to unlink distro-specific installation docs.
* rules:
+ set ZM_CONTENTDIR, ZM_SOCKDIR and ZM_TMPDIR.
+ remove mistakengly installed Perl module templates.
* Updated startup scripts to create ZM_TMPDIR.
* Hurd improvements:
+ New patch to add PATH_MAX definitions.
+ Build without MMAP support on Hurd.
+ libsys-mmap-perl [!hurd-any].
-- Dmitry Smirnov <onlyjob@debian.org> Mon, 06 Apr 2015 18:18:55 +1000
zoneminder (1.28.1-3) unstable; urgency=low
* Updated Apache2 and nginx configuration templates to support CGI.
* Updated README.Debian to document cgi-bin setup.
* Removed "/usr/share/zoneminder/www/cgi-bin" symlink.
* Added "apache2.patch" to correct Apache2 site configuration example.
* control: Suggests += "fcgiwrap".
* rules: added dh_systemd overrides to prevent automatic service
activation and start.
* Added note about manual service activation to README.Debian
(Closes: #781733).
-- Dmitry Smirnov <onlyjob@debian.org> Thu, 02 Apr 2015 23:20:20 +1100
zoneminder (1.28.1-2) unstable; urgency=low
* Removed word "Linux" from short package description.
* Build-Depends: do not require "libv4l-dev" on Hurd i.e. [!hurd-any].
* Added run-time Perl Depends:
+ libdbd-mysql-perl
+ libimage-info-perl
+ libmodule-load-conditional-perl
+ libnet-sftp-foreign-perl
+ liburi-encode-perl
* Prepare for package split: added commented "libzoneminder-perl"
and "zoneminder-dbg" packages to "debian/control".
* rules: do not install worthless ".packlist" file.
* Updated "libv4l1-videodev.h.patch" to fix v4lv1 detection in CMake.
-- Dmitry Smirnov <onlyjob@debian.org> Thu, 02 Apr 2015 13:25:19 +1100
zoneminder (1.28.1-1) unstable; urgency=low
[ Dmitry Smirnov <onlyjob@debian.org> ]
* New upstream release [February 2015].
* Upload to unstable.
* Disabled automatic database upgrades: post(inst|rm) scripts no longer
touch database or do unexpected stuff (Closes: #779254).
See README.Debian for details.
* Updated installation paths:
+ /usr/share/zoneminder --> /usr/share/zoneminder/www
+ /usr/lib/cgi-bin --> /usr/lib/zoneminder/cgi-bin
* Added logrotate config (Closes: #544826).
Thanks, Alberto Reyes.
* Native systemd service; "--with systemd" added to dh.
* Build with CMake instead of autoconf; rules clean-up.
* Build with all hardening.
* Build and install "zmupdate.pl.1" man page.
* Added nginx/php5-fpm configuration example.
* Install upstream "apache.conf" example.
* Described setup of Zoneminer web site and database in README.Debian.
* Install "/etc/zm/zm.conf" with tighter permissions.
* Added TODO.Debian.
* Added "debian/clean"; "debian/gbp.conf"; bug-presubj.
* Remove bundled Cake tests to take ~5 MB off big-usr-share.
* Standards-Version: 3.9.6; compat/debhelper to version 9.
* Vcs links to new git repository at collab-maint.
* Build-Depends:
+ dh-systemd
+ libgcrypt11-dev --> libgcrypt-dev
+ libcurl4-gnutls-dev
+ libvlc-dev
+ policykit-1 (required by "zmsystemctl.pl")
- dh-autoreconf, autoconf, automake
* Depends:
- apache2
- libapache2-mod-php5 (moved to Suggests)
- libpcre3 (invalid)
- libmodule-load-perl (obsolete; replaced with perl-modules)
- libarchive-tar-perl (obsolete; replaced with perl-modules)
- mysql-server (moved to Recommends, Closes: #759504).
- php5
+ libav-tools
+ libjs-jquery (replaces bundled component)
+ libjs-mootool (replaces bundled component)
+ libjson-any-perl (Closes: #690803).
+ perl-modules (Closes: #745819).
* Recommends:
+ apache2 | httpd
+ mysql-server | virtual-mysql-server (Closes: #732874).
* Suggests:
+ libapache2-mod-php5 | php5-fpm
+ logrotate
* Refreshed, renamed and re-ordered patches; added DEP-3 headers.
* Removed "vendor_perl" patch (applied-upstream).
* New patches:
+ cmake-fix-confpath.patch
+ cmake-gnutls.patch
+ cmake-nossl.patch
+ cmake.patch
+ format-hardening.patch
+ pod_man_fixes.patch
+ pod_name_fixes.patch
+ pod_zmupdate-to-pod2usage.patch
* Lintianisation (incomplete):
- extra-license-file
- init.d-script-missing-lsb-description
- init.d-script-does-not-source-init-functions
- privacy-breach-generic
- package-contains-empty-directory
- manpage-has-errors-from-pod2man
- manpage-has-bad-whatis-entry
- quilt-patch-missing-description
- no-dep5-copyright
* Lintian-overrides:
+ unusual-interpreter usr/bin/zmsystemctl.pl #!/usr/bin/pkexec
+ script-not-executable usr/share/zoneminder/www/api/*
+ script-with-language-extension usr/bin/*.pl
+ source-is-missing web/tools/mootools/mootools-*-yc.js
+ source-is-missing web/skins/*/js/jquery-1.4.2.min.js
+ source-contains-prebuilt-javascript-object
* Renamed files in "debian".
* watch: dfsg repacksuffix and dversionmangle.
* "debian/copyright" to Copyright-Format-1.0.
* Set myself as new Maintainer (Closes: #760314).
[ Vagrant Cascadian <vagrant@debian.org> ]
* Removed obsolete DM-Upload-Allowed flag.
* Update debian/watch to use tarballs from github.
* Add Build-Depends on libgcrypt11-dev (Closes: #745819).
* Use canonical alioth Vcs-Hg URL.
* debian/control: Add Build-Depends: libpolkit-gobject-1-dev.
* Removed configure flag "--enable-crashtrace=no", which is no longer
present upstream.
-- Dmitry Smirnov <onlyjob@debian.org> Tue, 31 Mar 2015 15:11:13 +1100
zoneminder (1.26.5-3.1) experimental; urgency=low
* Non-maintainer upload.
* Add libav10.patch and compile against libav10 (Closes: #739461)
-- Reinhard Tartler <siretart@tauware.de> Wed, 19 Mar 2014 00:31:22 +0000
zoneminder (1.26.5-3) unstable; urgency=low
* Previous release still didn't build on PPC - this has been corrected.
(Closes: #736516)
-- Peter Howard <pjh@northern-ridge.com.au> Tue, 4 Feb 2014 02:02:10 +1000
zoneminder (1.26.5-2) unstable; urgency=low
* Remove dependency on ffmpeg
(Closes: #721161)
* Builds again on non-x86 target architectures.
-- Peter Howard <pjh@northern-ridge.com.au> Thu, 23 Jan 2014 01:02:10 +1000
zoneminder (1.26.5-1) unstable; urgency=low
* New upstream version
(Closes: #694131)
* Change Build-Depends on libgnutls-dev to libgnutls-openssl-dev
(Closes: #731560)
-- Peter Howard <pjh@northern-ridge.com.au> Tue, 17 Dec 2013 01:02:10 +1000
zoneminder (1.25.0-4) unstable; urgency=high
* Add CVE-2013-0232 patch
[SECURITY] CVE-2013-0232: Shell escape commands with untrusted content.
Thanks to James McCoy <jamessan@debian.org> (Closes: #698910)
Thanks also to Salvatore Bonaccorso <carnil@debian.org>
-- Peter Howard <pjh@northern-ridge.com.au> Tue, 12 Jun 2013 12:02:10 +1000
zoneminder (1.25.0-3) unstable; urgency=low
* debian/rules: Export CFLAGS, CPPFLAGS, CXXFLAGS and LDFLAGS, to ensure
hardening build flags are enabled.
-- Vagrant Cascadian <vagrant@debian.org> Tue, 28 Aug 2012 12:10:03 -0700
zoneminder (1.25.0-2) unstable; urgency=low
[ Vagrant Cascadian ]
* Add a patch to disable checking for updated versions by default, as
upgrades should happen through package management.
* Use dpkg-buildflags in debian/rules to set default compiler flags.
* Ensure zoneminder is stopped before starting (Closes: #657407).
[ Peter Howard ]
* Fix postinst to add permission for table creation during upgrade
(Closes: #657407).
-- Vagrant Cascadian <vagrant@debian.org> Thu, 23 Aug 2012 12:40:34 -0700
zoneminder (1.25.0-1.1) unstable; urgency=low
* Non-maintainer upload.
* Fix "ftbfs with GCC-4.7": add patch Fix-FTBFS-with-gcc-4.7 from Cyril
Brulebois: fix missing <unistd.h> includes.
(Closes: #667428)
-- gregor herrmann <gregoa@debian.org> Sun, 13 May 2012 17:02:21 +0200
zoneminder (1.25.0-1) unstable; urgency=low
* Fix typo in libv4l1-videodev.h patch that caused v4l1 support to be
dropped.
* Fail to build if version in postinst doesn't match upstream version.
* Add Build-Depends: libavdevice-dev to fix MPEG streaming (Closes: #515558).
* debian/rules: Convert to using debhelper overrides.
* Set debian/compat to 7.
* Simplify debian/watch file.
* Refresh debian/patches/use_libjs-mootools.
* Refresh debian/patches/libv4l1-videodev.h.
* Remove dependencies on php4 and related packages.
* Remove build-dependencies on libmysqlclient14-dev and
libmysqlclient15-dev.
* Update Build-Depends to use libjpeg-dev instead of libjpeg62-dev
(Closes: #647114).
* Add patch to fix build by testing for C headers rather than C++ headers.
Thanks to Ryan Niebur. (Closes: #654230)
* Add a patch to fix build problems caused by API changes in libav 0.8.
Thanks again to Ryan Niebur. (Closes: #654230)
-- Vagrant Cascadian <vagrant@debian.org> Mon, 16 Jan 2012 11:58:05 -0800
zoneminder (1.24.4-1) unstable; urgency=low
[ Peter Howard ]
* Initial release of 1.24.4 (Closes: #634985).
- Fix 32/64-bit type declarations (Closes: #614404).
* Update patches.
[ Vagrant Cascadian ]
* Add patch to fix FTBFS by using libv4l1-videodev.h from libv4l-dev.
Thanks to Andreas Metzler for reporting the issue.
(Closes: #619813).
* Document adding the www-data user to the video group in README.Debian.
(Closes: #611324)
* Depend on libsys-mmap-perl to enable mapped memory support.
(Closes: #607331)
* Update libjs-mootools patch to use -nc variants (Closes: #635075).
* Depend on javascript-common, to ensure that /javascript is available in
the web server.
* Set the upstream version in postinst at build time.
* Use dh-autoreconf to properly clean up autogenerated files during build.
* Add Vcs-HG to debian/control.
* Add Build-Depends: libv4l-dev, libbz2-dev, dh-autoreconf, libsys-mmap-perl.
-- Vagrant Cascadian <vagrant@debian.org> Sun, 24 Jul 2011 16:44:30 +0200
zoneminder (1.24.2-9) unstable; urgency=low
* Apply patch from Ubuntu to fix FTBFS with ffmpeg 0.6:
- Add -D__STDC_CONSTANT_MACROS to CPPFLAGS (closes: 614080).
* Update Standards-Version to 3.9.1, no changes necessary.
-- Vagrant Cascadian <vagrant@debian.org> Sun, 20 Feb 2011 23:43:02 -0800
zoneminder (1.24.2-8) unstable; urgency=medium
[ Vagrant Cascadian ]
* Apply patch to fix V4L2 cameras without crop support (closes: #608790).
Thanks to piratebab.
* Add preinst script which aborts if dangerous symlinks exist.
(closes: #608793)
[ Peter Howard ]
* Added to README.Debian with info about images and events directories.
(closes: #608793)
-- Vagrant Cascadian <vagrant@debian.org> Sat, 15 Jan 2011 19:39:26 -0800
zoneminder (1.24.2-7) unstable; urgency=medium
* Do not set ownership of /var/cache/zoneminder when upgrading, which fixes a
regression causing upgrades to take inordinately long with large
installations (closes: #597040).
-- Vagrant Cascadian <vagrant@debian.org> Fri, 17 Sep 2010 11:24:41 -0700
zoneminder (1.24.2-6) unstable; urgency=low
* Only remove database on purge. This requires only creating the database if
it doesn't already exist, and upgrading the database only if the database
is an older version (closes: #497107).
* Do not prompt the user on database upgrades by using the --nointeractive
flag when calling zmupdate.pl from postinst (closes: #595902).
-- Vagrant Cascadian <vagrant@debian.org> Fri, 10 Sep 2010 10:06:06 -0700
zoneminder (1.24.2-5) unstable; urgency=low
[ Peter Howard ]
* Add zip dependency
(closes: #494261)
* Add debian/watch file
(closes: #545552)
* Use packaged libjs-mootools
(closes: #585590)
* Miscellaneous cleanups
[ Vagrant Cascadian ]
* Add vagrant@debian.org as uploader
* Update Standards-Version to 3.9.0, no changes necessary.
-- Vagrant Cascadian <vagrant@debian.org> Fri, 23 Jul 2010 18:12:50 -0500
zoneminder (1.24.2-4.1) unstable; urgency=low
* Non-maintainer upload.
* Fix "package removed, processes still running": apply patch to
debian/postinst by Vagrant Cascadian: use invoke-rc.d and run
mysql-related actions only when mysql is running (closes: #583648).
-- gregor herrmann <gregoa@debian.org> Thu, 01 Jul 2010 19:47:10 +0200
zoneminder (1.24.2-4) unstable; urgency=high
* Update init.d to list mysql dependency
(closes: #583505)
* Change dependency from libmime-perl to libmime-tools-perl
(closes: #585589)
* Problems in changelog format fixed
(closes: #585592)
* Fix debian-rules-ignores-make-clean-error
(closes: #585593)
-- Peter Howard <pjh@northern-ridge.com.au> Mon, 14 jun 2010 15:02:10 +1000
zoneminder (1.24.2-3) unstable; urgency=high
* Changes symbols to build with libjpeg8
(closes: #565326, #568327)
* Note: location of all perl files should have been fixed in previous release
(closes: #553096)
-- Peter Howard <pjh@northern-ridge.com.au> Mon, 26 apr 2010 15:02:10 +1000
zoneminder (1.24.2-2) unstable; urgency=high
* Remove custom perl parth from zmpkg.pl, fix location of manpages.
(closes: #551746, #553092)
* Fix GCC4.4 bug
(closes: #531717)
* Fix potential bug in postinst script
-- Peter Howard <pjh@northern-ridge.com.au> Sat, 14 Nov 2009 15:02:10 +1000
zoneminder (1.24.2-1) unstable; urgency=high
* Initial release of zoneminder 1.24.2
-- Peter Howard <pjh@northern-ridge.com.au> Fri, 11 Sep 2009 07:02:50 +1000
zoneminder (1.24.1-1) unstable; urgency=high
* Initial release of zoneminder 1.24.1, closing CVE-2008-3882,
CVE-2008-3881, CVE-2008-3880
(closes: #497640)
* Change syslog dependency to rsyslog.
(closes: #526918)
* Add missing perl dependency.
* Restore patch to disable "check for updates" by default.
* Removed spurious '$' in init script.
(closes: #486064)
* Change permission of zm.conf from 0600 to 0400 for CVE-2008-6755
(closes: #528252)
-- Peter Howard <pjh@northern-ridge.com.au> Sat, 16 May 2009 07:02:50 +1000
zoneminder (1.23.3-4) unstable; urgency=high
* update to get it building with latest unstable. Thanks to waldi@debian.org
(closes: #517569)
-- Peter Howard <pjh@northern-ridge.com.au> Thu, 16 Apr 2009 01:02:50 +1000
zoneminder (1.23.3-3) unstable; urgency=high
* ffmpeg confirmed working
(closes: #475145)
* Fix upgrade problem intrudouced in 1.23.3-1
(closes: #481637)
* Include libmime-lite-perl in dependencies
(closes: #486312)
-- Peter Howard <pjh@northern-ridge.com.au> Thu, 18 Sep 2008 01:02:50 +1000
zoneminder (1.23.3-2) unstable; urgency=high
* ffmpeg finally working?
-- Peter Howard <pjh@northern-ridge.com.au> Wed, 13 Aug 2008 01:02:50 +1000
zoneminder (1.23.3-1) unstable; urgency=high
* Initial version for 1.23.3 - security fix.
(closes: #479034)
-- Peter Howard <pjh@northern-ridge.com.au> Wed, 19 Mar 2008 01:02:50 +1000
zoneminder (1.23.2-2) unstable; urgency=low
* Update to init.d
(closes: #468856)
* Add dependency on logging daemon
(closes: #471277)
-- Peter Howard <pjh@northern-ridge.com.au> Wed, 19 Mar 2008 01:02:50 +1000
zoneminder (1.23.2-1) unstable; urgency=low
* Initial version for 1.23.2
(closes: #464152)
* Zoneminder 1.23.2 upstream includes fix for GCC 4.3
(closes: #454980)
* Includes ffmpeg patch by Alexander Kushnirenko <kushnir@uni-protvino.ru>
-- Peter Howard <pjh@northern-ridge.com.au> Sat, 01 Mar 2008 16:02:50 +1000
zoneminder (1.22.3-10) unstable; urgency=low
* Fix bug introduced in -9 where perl is put under /usr/local
(closes: #457507)
-- Peter Howard <pjh@northern-ridge.com.au> Mon, 24 Dec 2007 16:02:50 +1000
zoneminder (1.22.3-9) unstable; urgency=low
* Starting zoneminder via init script now invokes "zmfix -a"
(closes: #481637)
* Change apache2-mpm-prefork dependency to apache2
* Temp dir for export under /var/cache/zoneminder (but linked back to
/usr/share/zoneminder for now)
* Redo use of gnutls rather than openssl for md5 hashes
-- Peter Howard <pjh@northern-ridge.com.au> Mon, 10 Dec 2007 16:02:50 +1000
zoneminder (1.22.3-8) unstable; urgency=low
* Build now includes libpcre3
(closes: #437533)
* "Monitor Presets" patch now applied to package during build.
-- Peter Howard <pjh@northern-ridge.com.au> Sat, 18 Aug 2007 14:35:23 +1000
zoneminder (1.22.3-7) unstable; urgency=low
* Turn off debug trace and crash dump on build
(closes:#414857,#414891)
* Additional perl libraries added in dependencies
(closes:#416291)
* Change preferred PHP version from 4 to 5
-- Peter Howard <pjh@northern-ridge.com.au> Sun, 29 Jul 2007 15:11:13 +1000
zoneminder (1.22.3-6) unstable; urgency=low
* Removed a similar bash only statement from zmpkg.pl
(closes:414882)
-- Peter Howard <pjh@northern-ridge.com.au> Sat, 14 Apr 2007 11:46:56 +1000
zoneminder (1.22.3-5) unstable; urgency=low
* Installs with "phone home" feature turned off by default, and permissions
on /etc/zm/zm.conf fixed (now the 0600 it s hould be)
(closes:415349)
* Removed "stupid bash-ism" on mysqld check in postinst file.
-- Peter Howard <pjh@northern-ridge.com.au> Fri, 6 Apr 2007 15:50:00 +1000
zoneminder (1.22.3-4) unstable; urgency=low
* Put libmysqlclient-15-dev in front of -14-dev so sbuild works
(closes: #414410)
-- Peter Howard <pjh@northern-ridge.com.au> Mon, 12 Mar 2007 11:38:56 +1100
zoneminder (1.22.3-3) unstable; urgency=low
* Clean up of postinstall, postrm ; user "zm" definitely was a mistake
* Also in postinstall: check and start MySQL if it's not running.
* init.d script now checks if zoneminder isn't running and still returns 0
(which helps uninstalling)
* Addition of php5 dependency options as well as php4.
-- Peter Howard <pjh@northern-ridge.com.au> Mon, 26 Feb 2007 10:40:52 +1100
zoneminder (1.22.3-2) unstable; urgency=low
* Added zmuser in the mysql creation; this should fix the install problem
for people, but needs to be cleaned up (in -3)
-- Peter Howard <pjh@northern-ridge.com.au> Fri, 16 Feb 2007 14:16:03 +1100
zoneminder (1.22.3-1) unstable; urgency=low
* Initial Version. (closes: #248393)
* Patched out use of openssl; uses gnutls instead for MD5 hashes.
* Removed MakeMaker-inserted Perl licensing (with authors permission) in
various scripts; replaced with GPL.
-- Peter Howard <pjh@northern-ridge.com.au> Wed, 7 Feb 2007 14:09:01 +1100

View File

@ -397,7 +397,6 @@ our @options = (
type => $types{boolean}, type => $types{boolean},
category => 'system', category => 'system',
}, },
{ {
name => 'ZM_OPT_GOOG_RECAPTCHA_SITEKEY', name => 'ZM_OPT_GOOG_RECAPTCHA_SITEKEY',
default => '...Insert your recaptcha site-key here...', default => '...Insert your recaptcha site-key here...',
@ -428,8 +427,6 @@ our @options = (
type => $types{string}, type => $types{string},
category => 'system', category => 'system',
}, },
{ {
name => 'ZM_DIR_EVENTS', name => 'ZM_DIR_EVENTS',
default => 'events', default => 'events',
@ -1580,7 +1577,7 @@ our @options = (
}, },
{ {
name => 'ZM_WEB_EVENT_DISK_SPACE', name => 'ZM_WEB_EVENT_DISK_SPACE',
default => '', default => 'no',
description => 'Whether to show disk space used by each event.', description => 'Whether to show disk space used by each event.',
help => q`Adds another column to the listing of events help => q`Adds another column to the listing of events
showing the disk space used by the event. This will impart a small showing the disk space used by the event. This will impart a small
@ -1815,7 +1812,7 @@ our @options = (
ZM_CAPTURES_PER_FRAME option and you should normally change the ZM_CAPTURES_PER_FRAME option and you should normally change the
value of only one of the options at a time. If you have value of only one of the options at a time. If you have
different capture cards that need different values you can different capture cards that need different values you can
ovveride them in each individual monitor on the source page. override them in each individual monitor on the source page.
`, `,
type => $types{boolean}, type => $types{boolean},
category => 'config', category => 'config',
@ -1839,7 +1836,7 @@ our @options = (
ZM_V4L_MULTI_BUFFER option and you should normally change the ZM_V4L_MULTI_BUFFER option and you should normally change the
value of only one of the options at a time. If you have value of only one of the options at a time. If you have
different capture cards that need different values you can different capture cards that need different values you can
ovveride them in each individual monitor on the source page. override them in each individual monitor on the source page.
`, `,
type => $types{integer}, type => $types{integer},
category => 'config', category => 'config',
@ -2498,7 +2495,6 @@ our @options = (
category => 'system', category => 'system',
}, },
{ {
name => 'ZM_RUN_AUDIT', name => 'ZM_RUN_AUDIT',
default => 'yes', default => 'yes',
description => 'Run zmaudit to check data consistency', description => 'Run zmaudit to check data consistency',
@ -3370,7 +3366,7 @@ our @options = (
{ {
name => 'ZM_WEB_M_DEFAULT_SCALE', name => 'ZM_WEB_M_DEFAULT_SCALE',
default => '100', default => '100',
description => 'What the default scaling factor applied to \'live\' or \'event\' views is (%)', description => q`'What the default scaling factor applied to 'live' or 'event' views is (%)`,
help => q` help => q`
Normally ZoneMinder will display 'live' or 'event' streams in Normally ZoneMinder will display 'live' or 'event' streams in
their native size. However if you have monitors with large their native size. However if you have monitors with large
@ -3633,7 +3629,7 @@ our @options = (
{ {
name => 'ZM_WEB_L_DEFAULT_SCALE', name => 'ZM_WEB_L_DEFAULT_SCALE',
default => '100', default => '100',
description => 'What the default scaling factor applied to \'live\' or \'event\' views is (%)', description => q`What the default scaling factor applied to 'live' or 'event' views is (%)`,
help => q` help => q`
Normally ZoneMinder will display 'live' or 'event' streams in Normally ZoneMinder will display 'live' or 'event' streams in
their native size. However if you have monitors with large their native size. However if you have monitors with large
@ -3654,7 +3650,7 @@ our @options = (
{ {
name => 'ZM_WEB_L_DEFAULT_RATE', name => 'ZM_WEB_L_DEFAULT_RATE',
default => '100', default => '100',
description => 'What the default replay rate factor applied to \'event\' views is (%)', description => q`What the default replay rate factor applied to 'event' views is (%)`,
help => q` help => q`
Normally ZoneMinder will display 'event' streams at their Normally ZoneMinder will display 'event' streams at their
native rate, i.e. as close to real-time as possible. However if native rate, i.e. as close to real-time as possible. However if

View File

@ -45,8 +45,7 @@ use ZoneMinder::Config qw(:all);
use Time::HiRes qw( usleep ); use Time::HiRes qw( usleep );
sub new sub new {
{
my $class = shift; my $class = shift;
my $id = shift; my $id = shift;
my $self = ZoneMinder::Control->new( $id ); my $self = ZoneMinder::Control->new( $id );
@ -57,21 +56,18 @@ sub new
our $AUTOLOAD; our $AUTOLOAD;
sub AUTOLOAD sub AUTOLOAD {
{
my $self = shift; my $self = shift;
my $class = ref($self) || croak( "$self not object" ); my $class = ref($self) || croak( "$self not object" );
my $name = $AUTOLOAD; my $name = $AUTOLOAD;
$name =~ s/.*://; $name =~ s/.*://;
if ( exists($self->{$name}) ) if ( exists($self->{$name}) ) {
{
return( $self->{$name} ); return( $self->{$name} );
} }
Fatal( "Can't access $name member of object of class $class" ); Fatal( "Can't access $name member of object of class $class" );
} }
sub open sub open {
{
my $self = shift; my $self = shift;
$self->loadMonitor(); $self->loadMonitor();
@ -83,14 +79,12 @@ sub open
$self->{state} = 'open'; $self->{state} = 'open';
} }
sub close sub close {
{
my $self = shift; my $self = shift;
$self->{state} = 'closed'; $self->{state} = 'closed';
} }
sub printMsg sub printMsg {
{
my $self = shift; my $self = shift;
my $msg = shift; my $msg = shift;
my $msg_len = length($msg); my $msg_len = length($msg);
@ -98,8 +92,7 @@ sub printMsg
Debug( $msg."[".$msg_len."]" ); Debug( $msg."[".$msg_len."]" );
} }
sub sendCmd sub sendCmd {
{
my $self = shift; my $self = shift;
my $cmd = shift; my $cmd = shift;
@ -117,28 +110,23 @@ sub sendCmd
my $res = $self->{ua}->request($req); my $res = $self->{ua}->request($req);
if ( $res->is_success ) if ( $res->is_success ) {
{
$result = !undef; $result = !undef;
} } else {
else
{
Error( "Error check failed: '".$res->status_line()."'" ); Error( "Error check failed: '".$res->status_line()."'" );
} }
return( $result ); return( $result );
} }
sub reset sub reset {
{
my $self = shift; my $self = shift;
Debug( "Camera Reset" ); Debug( "Camera Reset" );
my $cmd = "/admin/ptctl.cgi?move=reset"; my $cmd = "/admin/ptctl.cgi?move=reset";
$self->sendCmd( $cmd ); $self->sendCmd( $cmd );
} }
sub moveMap sub moveMap {
{
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
my $xcoord = $self->getParam( $params, 'xcoord' ); my $xcoord = $self->getParam( $params, 'xcoord' );
@ -155,26 +143,26 @@ sub moveMap
my $horSteps = 0; my $horSteps = 0;
my $verSteps = 0; my $verSteps = 0;
# Horizontal movement # Horizontal movement
if ($hor < 50) { if ( $hor < 50 ) {
# left # left
$horSteps = ((50 - $hor) / 50) * $maxhor; $horSteps = ((50 - $hor) / 50) * $maxhor;
$horDir = "left"; $horDir = "left";
} }
elsif ($hor > 50) { elsif ( $hor > 50 ) {
# right # right
$horSteps = (($hor - 50) / 50) * $maxhor; $horSteps = (($hor - 50) / 50) * $maxhor;
$horDir = "right"; $horDir = "right";
} }
# Vertical movement # Vertical movement
if ($ver < 50) { if ( $ver < 50 ) {
# up # up
$verSteps = ((50 - $ver) / 50) * $maxver; $verSteps = ((50 - $ver) / 50) * $maxver;
$verDir = "up"; $verDir = "up";
} }
elsif ($ver > 50) { elsif ( $ver > 50 ) {
# down # down
$verSteps = (($ver - 50) / 50) * $maxver; $verSteps = (($ver - 50) / 50) * $maxver;
$verDir = "down"; $verDir = "down";
} }
@ -189,8 +177,7 @@ sub moveMap
$self->sendCmd( $cmd ); $self->sendCmd( $cmd );
} }
sub moveRelUp sub moveRelUp {
{
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
my $step = $self->getParam( $params, 'tiltstep' ); my $step = $self->getParam( $params, 'tiltstep' );
@ -199,8 +186,7 @@ sub moveRelUp
$self->sendCmd( $cmd ); $self->sendCmd( $cmd );
} }
sub moveRelDown sub moveRelDown {
{
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
my $step = $self->getParam( $params, 'tiltstep' ); my $step = $self->getParam( $params, 'tiltstep' );
@ -209,38 +195,43 @@ sub moveRelDown
$self->sendCmd( $cmd ); $self->sendCmd( $cmd );
} }
sub moveRelLeft sub moveRelLeft {
{
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
my $step = $self->getParam( $params, 'panstep' ); my $step = $self->getParam( $params, 'panstep' );
Debug( "Step Left $step" );
my $cmd = "/admin/ptctl.cgi?move=left"; if ( $self->{Monitor}->{Orientation} eq "hori" ) {
$self->sendCmd( $cmd ); Debug( "Stepping Right because flipped horizontally " );
$self->sendCmd( "/admin/ptctl.cgi?move=right" );
} else {
Debug( "Step Left" );
$self->sendCmd( "/admin/ptctl.cgi?move=left" );
}
} }
sub moveRelRight sub moveRelRight {
{
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
my $step = $self->getParam( $params, 'panstep' ); my $step = $self->getParam( $params, 'panstep' );
Debug( "Step Right $step" ); if ( $self->{Monitor}->{Orientation} eq "hori" ) {
my $cmd = "/admin/ptctl.cgi?move=right"; Debug( "Stepping Left because flipped horizontally " );
$self->sendCmd( $cmd ); $self->sendCmd( "/admin/ptctl.cgi?move=left" );
} else {
Debug( "Step Right" );
$self->sendCmd( "/admin/ptctl.cgi?move=right" );
}
} }
sub presetClear sub presetClear {
{
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
my $preset = $self->getParam( $params, 'preset' ); my $preset = $self->getParam( $params, 'preset' );
Debug( "Clear Preset $preset" ); Debug( "Clear Preset $preset" );
#my $cmd = "/axis-cgi/com/ptz.cgi?removeserverpresetno=$preset"; #my $cmd = "/axis-cgi/com/ptz.cgi?removeserverpresetno=$preset";
#$self->sendCmd( $cmd ); #$self->sendCmd( $cmd );
} }
sub presetSet sub presetSet {
{
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
my $preset = $self->getParam( $params, 'preset' ); my $preset = $self->getParam( $params, 'preset' );
@ -249,8 +240,7 @@ sub presetSet
$self->sendCmd( $cmd ); $self->sendCmd( $cmd );
} }
sub presetGoto sub presetGoto {
{
my $self = shift; my $self = shift;
my $params = shift; my $params = shift;
my $preset = $self->getParam( $params, 'preset' ); my $preset = $self->getParam( $params, 'preset' );
@ -259,8 +249,7 @@ sub presetGoto
$self->sendCmd( $cmd ); $self->sendCmd( $cmd );
} }
sub presetHome sub presetHome {
{
my $self = shift; my $self = shift;
Debug( "Home Preset" ); Debug( "Home Preset" );
my $cmd = "/admin/ptctl.cgi?move=h"; my $cmd = "/admin/ptctl.cgi?move=h";
@ -269,41 +258,26 @@ sub presetHome
1; 1;
__END__ __END__
# Below is stub documentation for your module. You'd better edit it!
=head1 NAME =head1 NAME
ZoneMinder::Database - Perl extension for blah blah blah ZoneMinder::Control::SkyIPCam7xx.pm - Module for controlling AirLink101 SkyIPams
=head1 SYNOPSIS =head1 SYNOPSIS
use ZoneMinder::Database; use ZoneMinder::Control::SkyIPCam7xx;
blah blah blah
=head1 DESCRIPTION =head1 DESCRIPTION
Stub documentation for ZoneMinder, created by h2xs. It looks like the Module for controlling AirLink101 Cameras.
author of the extension was negligent enough to leave the stub
unedited.
Blah blah blah.
=head2 EXPORT =head2 EXPORT
None by default. None by default.
=head1 SEE ALSO =head1 SEE ALSO
Mention other useful documentation such as the documentation of ZoneMinder::Control
related modules or operating system documentation (such as man pages
in UNIX), or any relevant external documentation such as RFCs or
standards.
If you have a mailing list set up for your module, mention it here.
If you have a web site set up for your module, mention it here.
=head1 AUTHOR =head1 AUTHOR
@ -318,5 +292,4 @@ This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.3 or, it under the same terms as Perl itself, either Perl version 5.8.3 or,
at your option, any later version of Perl 5 you may have available. at your option, any later version of Perl 5 you may have available.
=cut =cut

View File

@ -28,30 +28,12 @@ use 5.006;
use strict; use strict;
use warnings; use warnings;
require Exporter;
require ZoneMinder::Base; require ZoneMinder::Base;
require ZoneMinder::Object;
require Date::Manip; require Date::Manip;
our @ISA = qw(Exporter ZoneMinder::Base); #our @ISA = qw(ZoneMinder::Object);
use parent qw(ZoneMinder::Object);
# Items to export into callers namespace by default. Note: do not export
# names by default without a very good reason. Use EXPORT_OK instead.
# Do not simply export all your public functions/methods/constants.
# This allows declaration use ZoneMinder ':all';
# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
# will save memory.
our %EXPORT_TAGS = (
'functions' => [ qw(
) ]
);
push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS;
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw();
our $VERSION = $ZoneMinder::Base::VERSION;
# ========================================================================== # ==========================================================================
# #
@ -62,39 +44,24 @@ our $VERSION = $ZoneMinder::Base::VERSION;
use ZoneMinder::Config qw(:all); use ZoneMinder::Config qw(:all);
use ZoneMinder::Logger qw(:all); use ZoneMinder::Logger qw(:all);
use ZoneMinder::Database qw(:all); use ZoneMinder::Database qw(:all);
require Date::Parse;
use vars qw/ $table $primary_key /;
$table = 'Events';
$primary_key = 'Id';
use POSIX; use POSIX;
sub new { sub Time {
my ( $parent, $id, $data ) = @_; if ( @_ > 1 ) {
$_[0]{Time} = $_[1];
my $self = {};
bless $self, $parent;
$$self{dbh} = $ZoneMinder::Database::dbh;
#zmDbConnect();
if ( ( $$self{Id} = $id ) or $data ) {
#$log->debug("loading $parent $id") if $debug or DEBUG_ALL;
$self->load( $data );
} }
return $self; if ( ! defined $_[0]{Time} ) {
} # end sub new
sub load { $_[0]{Time} = Date::Parse::str2time( $_[0]{StartTime} );
my ( $self, $data ) = @_; }
my $type = ref $self; return $_[0]{Time};
if ( ! $data ) { }
#$log->debug("Object::load Loading from db $type");
$data = $$self{dbh}->selectrow_hashref( 'SELECT * FROM Events WHERE Id=?', {}, $$self{Id} );
if ( ! $data ) {
Error( "Failure to load Event record for $$self{Id}: Reason: " . $$self{dbh}->errstr );
} else {
Debug( 3, "Loaded Event $$self{Id}" );
} # end if
} # end if ! $data
if ( $data and %$data ) {
@$self{keys %$data} = values %$data;
} # end if
} # end sub load
sub Name { sub Name {
if ( @_ > 1 ) { if ( @_ > 1 ) {
@ -130,6 +97,7 @@ sub find {
my $filter = new ZoneMinder::Event( $$db_filter{Id}, $db_filter ); my $filter = new ZoneMinder::Event( $$db_filter{Id}, $db_filter );
push @results, $filter; push @results, $filter;
} # end while } # end while
$sth->finish();
return @results; return @results;
} }
@ -138,36 +106,51 @@ sub find_one {
return $results[0] if @results; return $results[0] if @results;
} }
sub getEventPath { sub getPath {
return Path( @_ );
}
sub Path {
my $event = shift; my $event = shift;
my $event_path = ""; if ( @_ > 1 ) {
if ( $Config{ZM_USE_DEEP_STORAGE} ) { $$event{Path} = $_[1];
$event_path = $Config{ZM_DIR_EVENTS} if ( ! -e $$event{Path} ) {
.'/'.$event->{MonitorId} Error("Setting path for event $$event{Id} to $_[1] but does not exist!");
.'/'.strftime( "%y/%m/%d/%H/%M/%S", }
localtime($event->{Time})
)
;
} else {
$event_path = $Config{ZM_DIR_EVENTS}
.'/'.$event->{MonitorId}
.'/'.$event->{Id}
;
} }
if ( index($Config{ZM_DIR_EVENTS},'/') != 0 ){ if ( ! $$event{Path} ) {
$event_path = $Config{ZM_PATH_WEB} my $path = ($Config{ZM_DIR_EVENTS}=~/^\//) ? $Config{ZM_DIR_EVENTS} : $Config{ZM_PATH_WEB}.'/'.$Config{ZM_DIR_EVENTS};
.'/'.$event_path
; if ( $Config{ZM_USE_DEEP_STORAGE} ) {
if ( $event->Time() ) {
$$event{Path} = join('/',
$path,
$event->{MonitorId},
strftime( "%y/%m/%d/%H/%M/%S",
localtime($event->Time())
),
);
} else {
Error("Event $$event{Id} has no value for Time(), unable to determine path");
$$event{Path} = '';
} }
return( $event_path ); } else {
$$event{Path} = join('/',
$path,
$event->{MonitorId},
$event->{Id},
);
}
} # end if
return $$event{Path};
} }
sub GenerateVideo { sub GenerateVideo {
my ( $self, $rate, $fps, $scale, $size, $overwrite, $format ) = @_; my ( $self, $rate, $fps, $scale, $size, $overwrite, $format ) = @_;
my $event_path = getEventPath( $self ); my $event_path = $self->getPath( );
chdir( $event_path ); chdir( $event_path );
( my $video_name = $self->{Name} ) =~ s/\s/_/g; ( my $video_name = $self->{Name} ) =~ s/\s/_/g;
@ -228,9 +211,7 @@ sub GenerateVideo {
my $command = $Config{ZM_PATH_FFMPEG} my $command = $Config{ZM_PATH_FFMPEG}
." -y -r $frame_rate " ." -y -r $frame_rate "
.$Config{ZM_FFMPEG_INPUT_OPTIONS} .$Config{ZM_FFMPEG_INPUT_OPTIONS}
." -i %0" .' -i ' . ( $$self{DefaultVideo} ? $$self{DefaultVideo} : '%0'.$Config{ZM_EVENT_IMAGE_DIGITS} .'d-capture.jpg' )
.$Config{ZM_EVENT_IMAGE_DIGITS}
."d-capture.jpg -s $video_size "
#. " -f concat -i /tmp/event_files.txt" #. " -f concat -i /tmp/event_files.txt"
." -s $video_size " ." -s $video_size "
.$Config{ZM_FFMPEG_OUTPUT_OPTIONS} .$Config{ZM_FFMPEG_OUTPUT_OPTIONS}
@ -256,51 +237,140 @@ sub GenerateVideo {
return; return;
} # end sub GenerateVideo } # end sub GenerateVideo
sub delete {
my $event = $_[0];
Info( "Deleting event $event->{Id} from Monitor $event->{MonitorId} $event->{StartTime}\n" );
$ZoneMinder::Database::dbh->ping();
# Do it individually to avoid locking up the table for new events
my $sql = 'delete from Events where Id = ?';
my $sth = $ZoneMinder::Database::dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$ZoneMinder::Database::dbh->errstr() );
my $res = $sth->execute( $event->{Id} )
or Fatal( "Can't execute '$sql': ".$sth->errstr() );
$sth->finish();
if ( ! $Config{ZM_OPT_FAST_DELETE} ) {
my $sql = 'delete from Frames where EventId = ?';
my $sth = $ZoneMinder::Database::dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$ZoneMinder::Database::dbh->errstr() );
my $res = $sth->execute( $event->{Id} )
or Fatal( "Can't execute '$sql': ".$sth->errstr() );
$sth->finish();
$sql = 'delete from Stats where EventId = ?';
$sth = $ZoneMinder::Database::dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$ZoneMinder::Database::dbh->errstr() );
$res = $sth->execute( $event->{Id} )
or Fatal( "Can't execute '$sql': ".$sth->errstr() );
$sth->finish();
$event->delete_files( );
} else {
Debug('Not deleting frames, stats and files for speed.');
}
} # end sub delete
sub delete_files {
my $storage_path = ($Config{ZM_DIR_EVENTS}=~/^\//) ? $Config{ZM_DIR_EVENTS} : $Config{ZM_PATH_WEB}.'/'.$Config{ZM_DIR_EVENTS};
if ( ! $storage_path ) {
Fatal("Empty path when deleting files for event $_[0]{Id} ");
return;
}
chdir ( $storage_path );
if ( $Config{ZM_USE_DEEP_STORAGE} ) {
if ( ! $_[0]{MonitorId} ) {
Error("No monitor id assigned to event $_[0]{Id}");
return;
}
Debug("Deleting files for Event $_[0]{Id} from $storage_path.");
my $link_path = $_[0]{MonitorId}.'/*/*/*/.'.$_[0]{Id};
#Debug( "LP1:$link_path" );
my @links = glob($link_path);
#Debug( "L:".$links[0].": $!" );
if ( @links ) {
( $link_path ) = ( $links[0] =~ /^(.*)$/ ); # De-taint
#Debug( "LP2:$link_path" );
( my $day_path = $link_path ) =~ s/\.\d+//;
#Debug( "DP:$day_path" );
my $event_path = $day_path.readlink( $link_path );
( $event_path ) = ( $event_path =~ /^(.*)$/ ); # De-taint
#Debug( "EP:$event_path" );
my $command = "/bin/rm -rf $event_path";
#Debug( "C:$command" );
ZoneMinder::General::executeShellCommand( $command );
unlink( $link_path ) or Error( "Unable to unlink '$link_path': $!" );
my @path_parts = split( /\//, $event_path );
for ( my $i = int(@path_parts)-2; $i >= 1; $i-- ) {
my $delete_path = join( '/', @path_parts[0..$i] );
#Debug( "DP$i:$delete_path" );
my @has_files = glob( join('/', $storage_path,$delete_path,'*' ) );
#Debug( "HF1:".$has_files[0] ) if ( @has_files );
last if ( @has_files );
@has_files = glob( join('/', $storage_path, $delete_path, '.[0-9]*' ) );
#Debug( "HF2:".$has_files[0] ) if ( @has_files );
last if ( @has_files );
my $command = "/bin/rm -rf $storage_path/$delete_path";
ZoneMinder::General::executeShellCommand( $command );
}
}
} else {
my $command = "/bin/rm -rf $storage_path/$_[0]{MonitorId}/$_[0]{Id}";
ZoneMinder::General::executeShellCommand( $command );
}
} # end sub delete_files
sub Storage {
return new ZoneMinder::Storage( $_[0]{StorageId} );
}
sub check_for_in_filesystem {
my $path = $_[0]->Path();
if ( $path ) {
my @files = glob( $path . '/*' );
Debug("Checking for files for event $_[0]{Id} at $path using glob $path/* found " . scalar @files . " files");
return 1 if @files;
}
Debug("Checking for files for event $_[0]{Id} at $path using glob $path/* found no files");
return 0;
}
sub age {
if ( ! $_[0]{age} ) {
$_[0]{age} = (time() - ($^T - ((-M $_[0]->Path() ) * 24*60*60)));
}
return $_[0]{age};
}
1; 1;
__END__ __END__
# Below is stub documentation for your module. You'd better edit it!
=head1 NAME =head1 NAME
ZoneMinder::Database - Perl extension for blah blah blah ZoneMinder::Event - Perl Class for events
=head1 SYNOPSIS =head1 SYNOPSIS
use ZoneMinder::Event; use ZoneMinder::Event;
blah blah blah
=head1 DESCRIPTION =head1 DESCRIPTION
Stub documentation for ZoneMinder, created by h2xs. It looks like the The Event class has everything you need to deal with events from Perl.
author of the extension was negligent enough to leave the stub
unedited.
Blah blah blah.
=head2 EXPORT
None by default.
=head1 SEE ALSO
Mention other useful documentation such as the documentation of
related modules or operating system documentation (such as man pages
in UNIX), or any relevant external documentation such as RFCs or
standards.
If you have a mailing list set up for your module, mention it here.
If you have a web site set up for your module, mention it here.
=head1 AUTHOR =head1 AUTHOR
Philip Coombes, E<lt>philip.coombes@zoneminder.comE<gt> Isaac Connor, E<lt>isaac@zoneminder.comE<gt>
=head1 COPYRIGHT AND LICENSE =head1 COPYRIGHT AND LICENSE
Copyright (C) 2001-2008 Philip Coombes Copyright (C) 2001-2017 ZoneMinder LLC
This library is free software; you can redistribute it and/or modify This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.3 or, it under the same terms as Perl itself, either Perl version 5.8.3 or,

View File

@ -41,7 +41,7 @@ our @ISA = qw(Exporter ZoneMinder::Base);
# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
# will save memory. # will save memory.
our %EXPORT_TAGS = ( our %EXPORT_TAGS = (
'constants' => [ qw( constants => [ qw(
STATE_IDLE STATE_IDLE
STATE_PREALARM STATE_PREALARM
STATE_ALARM STATE_ALARM
@ -56,7 +56,7 @@ our %EXPORT_TAGS = (
TRIGGER_ON TRIGGER_ON
TRIGGER_OFF TRIGGER_OFF
) ], ) ],
'functions' => [ qw( functions => [ qw(
zmMemVerify zmMemVerify
zmMemInvalidate zmMemInvalidate
zmMemRead zmMemRead
@ -82,7 +82,7 @@ our %EXPORT_TAGS = (
); );
push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS; push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS;
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{all} } );
our @EXPORT = qw(); our @EXPORT = qw();
@ -115,7 +115,7 @@ use constant TRIGGER_OFF => 2;
use Storable qw( freeze thaw ); use Storable qw( freeze thaw );
if ( "@ENABLE_MMAP@" eq 'yes' ) { if ( '@ENABLE_MMAP@' eq 'yes' ) {
# 'yes' if memory is mmapped # 'yes' if memory is mmapped
require ZoneMinder::Memory::Mapped; require ZoneMinder::Memory::Mapped;
ZoneMinder::Memory::Mapped->import(); ZoneMinder::Memory::Mapped->import();
@ -141,42 +141,42 @@ our $native = $arch/8;
our $mem_seq = 0; our $mem_seq = 0;
our $mem_data = { our $mem_data = {
"shared_data" => { "type"=>"SharedData", "seq"=>$mem_seq++, "contents"=> { shared_data => { type=>'SharedData', seq=>$mem_seq++, contents=> {
"size" => { "type"=>"uint32", "seq"=>$mem_seq++ }, size => { type=>'uint32', seq=>$mem_seq++ },
"last_write_index" => { "type"=>"uint32", "seq"=>$mem_seq++ }, last_write_index => { type=>'uint32', seq=>$mem_seq++ },
"last_read_index" => { "type"=>"uint32", "seq"=>$mem_seq++ }, last_read_index => { type=>'uint32', seq=>$mem_seq++ },
"state" => { "type"=>"uint32", "seq"=>$mem_seq++ }, state => { type=>'uint32', seq=>$mem_seq++ },
"last_event" => { "type"=>"uint32", "seq"=>$mem_seq++ }, last_event => { type=>'uint32', seq=>$mem_seq++ },
"action" => { "type"=>"uint32", "seq"=>$mem_seq++ }, action => { type=>'uint32', seq=>$mem_seq++ },
"brightness" => { "type"=>"int32", "seq"=>$mem_seq++ }, brightness => { type=>'int32', seq=>$mem_seq++ },
"hue" => { "type"=>"int32", "seq"=>$mem_seq++ }, hue => { type=>'int32', seq=>$mem_seq++ },
"colour" => { "type"=>"int32", "seq"=>$mem_seq++ }, colour => { type=>'int32', seq=>$mem_seq++ },
"contrast" => { "type"=>"int32", "seq"=>$mem_seq++ }, contrast => { type=>'int32', seq=>$mem_seq++ },
"alarm_x" => { "type"=>"int32", "seq"=>$mem_seq++ }, alarm_x => { type=>'int32', seq=>$mem_seq++ },
"alarm_y" => { "type"=>"int32", "seq"=>$mem_seq++ }, alarm_y => { type=>'int32', seq=>$mem_seq++ },
"valid" => { "type"=>"uint8", "seq"=>$mem_seq++ }, valid => { type=>'uint8', seq=>$mem_seq++ },
"active" => { "type"=>"uint8", "seq"=>$mem_seq++ }, active => { type=>'uint8', seq=>$mem_seq++ },
"signal" => { "type"=>"uint8", "seq"=>$mem_seq++ }, signal => { type=>'uint8', seq=>$mem_seq++ },
"format" => { "type"=>"uint8", "seq"=>$mem_seq++ }, format => { type=>'uint8', seq=>$mem_seq++ },
"imagesize" => { "type"=>"uint32", "seq"=>$mem_seq++ }, imagesize => { type=>'uint32', seq=>$mem_seq++ },
"epadding1" => { "type"=>"uint32", "seq"=>$mem_seq++ }, epadding1 => { type=>'uint32', seq=>$mem_seq++ },
"epadding2" => { "type"=>"uint32", "seq"=>$mem_seq++ }, epadding2 => { type=>'uint32', seq=>$mem_seq++ },
"last_write_time" => { "type"=>"time_t64", "seq"=>$mem_seq++ }, last_write_time => { type=>'time_t64', seq=>$mem_seq++ },
"last_read_time" => { "type"=>"time_t64", "seq"=>$mem_seq++ }, last_read_time => { type=>'time_t64', seq=>$mem_seq++ },
"control_state" => { "type"=>"uint8[256]", "seq"=>$mem_seq++ }, control_state => { type=>'uint8[256]', seq=>$mem_seq++ },
} }
}, },
"trigger_data" => { "type"=>"TriggerData", "seq"=>$mem_seq++, "contents"=> { trigger_data => { type=>'TriggerData', seq=>$mem_seq++, 'contents'=> {
"size" => { "type"=>"uint32", "seq"=>$mem_seq++ }, size => { type=>'uint32', seq=>$mem_seq++ },
"trigger_state" => { "type"=>"uint32", "seq"=>$mem_seq++ }, trigger_state => { type=>'uint32', seq=>$mem_seq++ },
"trigger_score" => { "type"=>"uint32", "seq"=>$mem_seq++ }, trigger_score => { type=>'uint32', seq=>$mem_seq++ },
"padding" => { "type"=>"uint32", "seq"=>$mem_seq++ }, padding => { type=>'uint32', seq=>$mem_seq++ },
"trigger_cause" => { "type"=>"int8[32]", "seq"=>$mem_seq++ }, trigger_cause => { type=>'int8[32]', seq=>$mem_seq++ },
"trigger_text" => { "type"=>"int8[256]", "seq"=>$mem_seq++ }, trigger_text => { type=>'int8[256]', seq=>$mem_seq++ },
"trigger_showtext" => { "type"=>"int8[256]", "seq"=>$mem_seq++ }, trigger_showtext => { type=>'int8[256]', seq=>$mem_seq++ },
} }
}, },
"end" => { "seq"=>$mem_seq++, "size"=> 0 } end => { seq=>$mem_seq++, size=>0 }
}; };
our $mem_size = 0; our $mem_size = 0;
@ -195,28 +195,28 @@ sub zmMemInit {
} }
} }
foreach my $member_data ( sort { $a->{seq} <=> $b->{seq} } values( %{$section_data->{contents}} ) ) { foreach my $member_data ( sort { $a->{seq} <=> $b->{seq} } values( %{$section_data->{contents}} ) ) {
if ( $member_data->{type} eq "long" if ( $member_data->{type} eq 'long'
|| $member_data->{type} eq "ulong" || $member_data->{type} eq 'ulong'
|| $member_data->{type} eq "size_t" || $member_data->{type} eq 'size_t'
) { ) {
$member_data->{size} = $member_data->{align} = $native; $member_data->{size} = $member_data->{align} = $native;
} elsif ( $member_data->{type} eq "int64" } elsif ( $member_data->{type} eq 'int64'
|| $member_data->{type} eq "uint64" || $member_data->{type} eq 'uint64'
|| $member_data->{type} eq "time_t64" || $member_data->{type} eq 'time_t64'
) { ) {
$member_data->{size} = $member_data->{align} = 8; $member_data->{size} = $member_data->{align} = 8;
} elsif ( $member_data->{type} eq "int32" } elsif ( $member_data->{type} eq 'int32'
|| $member_data->{type} eq "uint32" || $member_data->{type} eq 'uint32'
|| $member_data->{type} eq "bool4" || $member_data->{type} eq 'bool4'
) { ) {
$member_data->{size} = $member_data->{align} = 4; $member_data->{size} = $member_data->{align} = 4;
} elsif ($member_data->{type} eq "int16" } elsif ($member_data->{type} eq 'int16'
|| $member_data->{type} eq "uint16" || $member_data->{type} eq 'uint16'
) { ) {
$member_data->{size} = $member_data->{align} = 2; $member_data->{size} = $member_data->{align} = 2;
} elsif ( $member_data->{type} eq "int8" } elsif ( $member_data->{type} eq 'int8'
|| $member_data->{type} eq "uint8" || $member_data->{type} eq 'uint8'
|| $member_data->{type} eq "bool1" || $member_data->{type} eq 'bool1'
) { ) {
$member_data->{size} = $member_data->{align} = 1; $member_data->{size} = $member_data->{align} = 1;
} elsif ( $member_data->{type} =~ /^u?int8\[(\d+)\]$/ ) { } elsif ( $member_data->{type} =~ /^u?int8\[(\d+)\]$/ ) {
@ -248,7 +248,7 @@ sub zmMemVerify {
return( undef ); return( undef );
} }
my $sd_size = zmMemRead( $monitor, "shared_data:size", 1 ); my $sd_size = zmMemRead( $monitor, 'shared_data:size', 1 );
if ( $sd_size != $mem_data->{shared_data}->{size} ) { if ( $sd_size != $mem_data->{shared_data}->{size} ) {
if ( $sd_size ) { if ( $sd_size ) {
Error( "Shared data size conflict in shared_data for monitor " Error( "Shared data size conflict in shared_data for monitor "
@ -268,7 +268,7 @@ sub zmMemVerify {
} }
return( undef ); return( undef );
} }
my $td_size = zmMemRead( $monitor, "trigger_data:size", 1 ); my $td_size = zmMemRead( $monitor, 'trigger_data:size', 1 );
if ( $td_size != $mem_data->{trigger_data}->{size} ) { if ( $td_size != $mem_data->{trigger_data}->{size} ) {
if ( $td_size ) { if ( $td_size ) {
Error( "Shared data size conflict in trigger_data for monitor " Error( "Shared data size conflict in trigger_data for monitor "
@ -289,7 +289,7 @@ sub zmMemVerify {
} }
return( undef ); return( undef );
} }
if ( !zmMemRead($monitor, "shared_data:valid",1) ) { if ( !zmMemRead($monitor, 'shared_data:valid',1) ) {
Error( "Shared data not valid for monitor $$monitor{Id}" ); Error( "Shared data not valid for monitor $$monitor{Id}" );
return( undef ); return( undef );
} }
@ -325,32 +325,32 @@ sub zmMemRead {
return( undef ); return( undef );
} }
my $value; my $value;
if ( $type eq "long" ) { if ( $type eq 'long' ) {
( $value ) = unpack( "l!", $data ); ( $value ) = unpack( 'l!', $data );
} elsif ( $type eq "ulong" || $type eq "size_t" ) { } elsif ( $type eq 'ulong' || $type eq 'size_t' ) {
( $value ) = unpack( "L!", $data ); ( $value ) = unpack( 'L!', $data );
} elsif ( $type eq "int64" || $type eq "time_t64" ) { } elsif ( $type eq 'int64' || $type eq 'time_t64' ) {
# The "q" type is only available on 64bit platforms, so use native. # The 'q' type is only available on 64bit platforms, so use native.
( $value ) = unpack( "l!", $data ); ( $value ) = unpack( 'l!', $data );
} elsif ( $type eq "uint64" ) { } elsif ( $type eq 'uint64' ) {
# The "q" type is only available on 64bit platforms, so use native. # The 'q' type is only available on 64bit platforms, so use native.
( $value ) = unpack( "L!", $data ); ( $value ) = unpack( 'L!', $data );
} elsif ( $type eq "int32" ) { } elsif ( $type eq 'int32' ) {
( $value ) = unpack( "l", $data ); ( $value ) = unpack( 'l', $data );
} elsif ( $type eq "uint32" || $type eq "bool4" ) { } elsif ( $type eq 'uint32' || $type eq 'bool4' ) {
( $value ) = unpack( "L", $data ); ( $value ) = unpack( 'L', $data );
} elsif ( $type eq "int16" ) { } elsif ( $type eq 'int16' ) {
( $value ) = unpack( "s", $data ); ( $value ) = unpack( 's', $data );
} elsif ( $type eq "uint16" ) { } elsif ( $type eq 'uint16' ) {
( $value ) = unpack( "S", $data ); ( $value ) = unpack( 'S', $data );
} elsif ( $type eq "int8" ) { } elsif ( $type eq 'int8' ) {
( $value ) = unpack( "c", $data ); ( $value ) = unpack( 'c', $data );
} elsif ( $type eq "uint8" || $type eq "bool1" ) { } elsif ( $type eq 'uint8' || $type eq 'bool1' ) {
( $value ) = unpack( "C", $data ); ( $value ) = unpack( 'C', $data );
} elsif ( $type =~ /^int8\[\d+\]$/ ) { } elsif ( $type =~ /^int8\[\d+\]$/ ) {
( $value ) = unpack( "Z".$size, $data ); ( $value ) = unpack( 'Z'.$size, $data );
} elsif ( $type =~ /^uint8\[\d+\]$/ ) { } elsif ( $type =~ /^uint8\[\d+\]$/ ) {
( $value ) = unpack( "C".$size, $data ); ( $value ) = unpack( 'C'.$size, $data );
} else { } else {
Fatal( "Unexpected type '".$type."' found for '".$field."'" ); Fatal( "Unexpected type '".$type."' found for '".$field."'" );
} }
@ -394,34 +394,34 @@ sub zmMemWrite {
my $size = $mem_data->{$section}->{contents}->{$element}->{size}; my $size = $mem_data->{$section}->{contents}->{$element}->{size};
my $data; my $data;
if ( $type eq "long" ) { if ( $type eq 'long' ) {
$data = pack( "l!", $value ); $data = pack( 'l!', $value );
} elsif ( $type eq "ulong" || $type eq "size_t" ) { } elsif ( $type eq 'ulong' || $type eq 'size_t' ) {
$data = pack( "L!", $value ); $data = pack( 'L!', $value );
} elsif ( $type eq "int64" || $type eq "time_t64" ) { } elsif ( $type eq 'int64' || $type eq 'time_t64' ) {
# The "q" type is only available on 64bit platforms, so use native. # The 'q' type is only available on 64bit platforms, so use native.
$data = pack( "l!", $value ); $data = pack( 'l!', $value );
} elsif ( $type eq "uint64" ) { } elsif ( $type eq 'uint64' ) {
# The "q" type is only available on 64bit platforms, so use native. # The 'q' type is only available on 64bit platforms, so use native.
$data = pack( "L!", $value ); $data = pack( 'L!', $value );
} elsif ( $type eq "int32" ) { } elsif ( $type eq 'int32' ) {
$data = pack( "l", $value ); $data = pack( 'l', $value );
} elsif ( $type eq "uint32" || $type eq "bool4" ) { } elsif ( $type eq 'uint32' || $type eq 'bool4' ) {
$data = pack( "L", $value ); $data = pack( 'L', $value );
} elsif ( $type eq "int16" ) { } elsif ( $type eq 'int16' ) {
$data = pack( "s", $value ); $data = pack( 's', $value );
} elsif ( $type eq "uint16" ) { } elsif ( $type eq 'uint16' ) {
$data = pack( "S", $value ); $data = pack( 'S', $value );
} elsif ( $type eq "int8" ) { } elsif ( $type eq 'int8' ) {
$data = pack( "c", $value ); $data = pack( 'c', $value );
} elsif ( $type eq "uint8" || $type eq "bool1" ) { } elsif ( $type eq 'uint8' || $type eq 'bool1' ) {
$data = pack( "C", $value ); $data = pack( 'C', $value );
} elsif ( $type =~ /^int8\[\d+\]$/ ) { } elsif ( $type =~ /^int8\[\d+\]$/ ) {
$data = pack( "Z".$size, $value ); $data = pack( 'Z'.$size, $value );
} elsif ( $type =~ /^uint8\[\d+\]$/ ) { } elsif ( $type =~ /^uint8\[\d+\]$/ ) {
$data = pack( "C".$size, $value ); $data = pack( 'C'.$size, $value );
} else { } else {
Fatal( "Unexpected type '".$type."' found for '".$field."'" ); Fatal( "Unexpected type \"$type\" found for \"$field\"" );
} }
if ( !zmMemPut( $monitor, $offset, $size, $data ) ) { if ( !zmMemPut( $monitor, $offset, $size, $data ) ) {
@ -438,26 +438,26 @@ sub zmMemWrite {
sub zmGetMonitorState { sub zmGetMonitorState {
my $monitor = shift; my $monitor = shift;
return( zmMemRead( $monitor, "shared_data:state" ) ); return( zmMemRead( $monitor, 'shared_data:state' ) );
} }
sub zmGetAlarmLocation { sub zmGetAlarmLocation {
my $monitor = shift; my $monitor = shift;
return( zmMemRead( $monitor, [ "shared_data:alarm_x", "shared_data:alarm_y" ] ) ); return( zmMemRead( $monitor, [ 'shared_data:alarm_x', 'shared_data:alarm_y' ] ) );
} }
sub zmSetControlState { sub zmSetControlState {
my $monitor = shift; my $monitor = shift;
my $control_state = shift; my $control_state = shift;
zmMemWrite( $monitor, { "shared_data:control_state" => $control_state } ); zmMemWrite( $monitor, { 'shared_data:control_state' => $control_state } );
} }
sub zmGetControlState { sub zmGetControlState {
my $monitor = shift; my $monitor = shift;
return( zmMemRead( $monitor, "shared_data:control_state" ) ); return( zmMemRead( $monitor, 'shared_data:control_state' ) );
} }
sub zmSaveControlState { sub zmSaveControlState {
@ -493,8 +493,8 @@ sub zmHasAlarmed {
my $monitor = shift; my $monitor = shift;
my $last_event_id = shift; my $last_event_id = shift;
my ( $state, $last_event ) = zmMemRead( $monitor, [ "shared_data:state" my ( $state, $last_event ) = zmMemRead( $monitor, [ 'shared_data:state'
,"shared_data:last_event" ,'shared_data:last_event'
] ]
); );
@ -509,63 +509,63 @@ sub zmHasAlarmed {
sub zmGetLastEvent { sub zmGetLastEvent {
my $monitor = shift; my $monitor = shift;
return( zmMemRead( $monitor, "shared_data:last_event" ) ); return( zmMemRead( $monitor, 'shared_data:last_event' ) );
} }
sub zmGetLastWriteTime { sub zmGetLastWriteTime {
my $monitor = shift; my $monitor = shift;
return( zmMemRead( $monitor, "shared_data:last_write_time" ) ); return( zmMemRead( $monitor, 'shared_data:last_write_time' ) );
} }
sub zmGetLastReadTime { sub zmGetLastReadTime {
my $monitor = shift; my $monitor = shift;
return( zmMemRead( $monitor, "shared_data:last_read_time" ) ); return( zmMemRead( $monitor, 'shared_data:last_read_time' ) );
} }
sub zmGetMonitorActions { sub zmGetMonitorActions {
my $monitor = shift; my $monitor = shift;
return( zmMemRead( $monitor, "shared_data:action" ) ); return( zmMemRead( $monitor, 'shared_data:action' ) );
} }
sub zmMonitorEnable { sub zmMonitorEnable {
my $monitor = shift; my $monitor = shift;
my $action = zmMemRead( $monitor, "shared_data:action" ); my $action = zmMemRead( $monitor, 'shared_data:action' );
$action |= ACTION_SUSPEND; $action |= ACTION_SUSPEND;
zmMemWrite( $monitor, { "shared_data:action" => $action } ); zmMemWrite( $monitor, { 'shared_data:action' => $action } );
} }
sub zmMonitorDisable { sub zmMonitorDisable {
my $monitor = shift; my $monitor = shift;
my $action = zmMemRead( $monitor, "shared_data:action" ); my $action = zmMemRead( $monitor, 'shared_data:action' );
$action |= ACTION_RESUME; $action |= ACTION_RESUME;
zmMemWrite( $monitor, { "shared_data:action" => $action } ); zmMemWrite( $monitor, { 'shared_data:action' => $action } );
} }
sub zmMonitorSuspend { sub zmMonitorSuspend {
my $monitor = shift; my $monitor = shift;
my $action = zmMemRead( $monitor, "shared_data:action" ); my $action = zmMemRead( $monitor, 'shared_data:action' );
$action |= ACTION_SUSPEND; $action |= ACTION_SUSPEND;
zmMemWrite( $monitor, { "shared_data:action" => $action } ); zmMemWrite( $monitor, { 'shared_data:action' => $action } );
} }
sub zmMonitorResume { sub zmMonitorResume {
my $monitor = shift; my $monitor = shift;
my $action = zmMemRead( $monitor, "shared_data:action" ); my $action = zmMemRead( $monitor, 'shared_data:action' );
$action |= ACTION_RESUME; $action |= ACTION_RESUME;
zmMemWrite( $monitor, { "shared_data:action" => $action } ); zmMemWrite( $monitor, { 'shared_data:action' => $action } );
} }
sub zmGetTriggerState { sub zmGetTriggerState {
my $monitor = shift; my $monitor = shift;
return( zmMemRead( $monitor, "trigger_data:trigger_state" ) ); return( zmMemRead( $monitor, 'trigger_data:trigger_state' ) );
} }
sub zmTriggerEventOn { sub zmTriggerEventOn {
@ -576,12 +576,12 @@ sub zmTriggerEventOn {
my $showtext = shift; my $showtext = shift;
my $values = { my $values = {
"trigger_data:trigger_score" => $score, 'trigger_data:trigger_score' => $score,
"trigger_data:trigger_cause" => $cause, 'trigger_data:trigger_cause' => $cause,
}; };
$values->{"trigger_data:trigger_text"} = $text if ( defined($text) ); $values->{'trigger_data:trigger_text'} = $text if ( defined($text) );
$values->{"trigger_data:trigger_showtext"} = $showtext if ( defined($showtext) ); $values->{'trigger_data:trigger_showtext'} = $showtext if ( defined($showtext) );
$values->{"trigger_data:trigger_state"} = TRIGGER_ON; # Write state last so event not read incomplete $values->{'trigger_data:trigger_state'} = TRIGGER_ON; # Write state last so event not read incomplete
zmMemWrite( $monitor, $values ); zmMemWrite( $monitor, $values );
} }
@ -590,11 +590,11 @@ sub zmTriggerEventOff {
my $monitor = shift; my $monitor = shift;
my $values = { my $values = {
"trigger_data:trigger_state" => TRIGGER_OFF, 'trigger_data:trigger_state' => TRIGGER_OFF,
"trigger_data:trigger_score" => 0, 'trigger_data:trigger_score' => 0,
"trigger_data:trigger_cause" => "", 'trigger_data:trigger_cause' => '',
"trigger_data:trigger_text" => "", 'trigger_data:trigger_text' => '',
"trigger_data:trigger_showtext" => "", 'trigger_data:trigger_showtext' => '',
}; };
zmMemWrite( $monitor, $values ); zmMemWrite( $monitor, $values );
@ -604,11 +604,11 @@ sub zmTriggerEventCancel {
my $monitor = shift; my $monitor = shift;
my $values = { my $values = {
"trigger_data:trigger_state" => TRIGGER_CANCEL, 'trigger_data:trigger_state' => TRIGGER_CANCEL,
"trigger_data:trigger_score" => 0, 'trigger_data:trigger_score' => 0,
"trigger_data:trigger_cause" => "", 'trigger_data:trigger_cause' => '',
"trigger_data:trigger_text" => "", 'trigger_data:trigger_text' => '',
"trigger_data:trigger_showtext" => "", 'trigger_data:trigger_showtext' => '',
}; };
zmMemWrite( $monitor, $values ); zmMemWrite( $monitor, $values );
@ -619,7 +619,7 @@ sub zmTriggerShowtext {
my $showtext = shift; my $showtext = shift;
my $values = { my $values = {
"trigger_data:trigger_showtext" => $showtext, 'trigger_data:trigger_showtext' => $showtext,
}; };
zmMemWrite( $monitor, $values ); zmMemWrite( $monitor, $values );
@ -648,7 +648,7 @@ if ( zmMemVerify( $monitor ) ) {
"shared_data:last_write_index" "shared_data:last_write_index"
] ]
); );
zmMemWrite( $monitor, { "trigger_data:trigger_showtext" => "Some Text" } ); zmMemWrite( $monitor, { 'trigger_data:trigger_showtext' => "Some Text" } );
=head1 DESCRIPTION =head1 DESCRIPTION

View File

@ -40,7 +40,7 @@ our @ISA = qw(Exporter ZoneMinder::Base);
# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
# will save memory. # will save memory.
our %EXPORT_TAGS = ( our %EXPORT_TAGS = (
'functions' => [ qw( functions => [ qw(
zmMemKey zmMemKey
zmMemAttach zmMemAttach
zmMemDetach zmMemDetach
@ -48,7 +48,7 @@ our %EXPORT_TAGS = (
zmMemPut zmMemPut
zmMemClean zmMemClean
) ], ) ],
); );
push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS; push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS;
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
@ -68,21 +68,18 @@ use ZoneMinder::Logger qw(:all);
use Sys::Mmap; use Sys::Mmap;
sub zmMemKey sub zmMemKey {
{
my $monitor = shift; my $monitor = shift;
return( defined($monitor->{MMapAddr})?$monitor->{MMapAddr}:undef ); return( defined($monitor->{MMapAddr})?$monitor->{MMapAddr}:undef );
} }
sub zmMemAttach sub zmMemAttach {
{
my ( $monitor, $size ) = @_; my ( $monitor, $size ) = @_;
if ( ! $size ) { if ( ! $size ) {
Error( "No size passed to zmMemAttach for monitor $$monitor{Id}\n" ); Error( "No size passed to zmMemAttach for monitor $$monitor{Id}\n" );
return( undef ); return( undef );
} }
if ( !defined($monitor->{MMapAddr}) ) if ( !defined($monitor->{MMapAddr}) ) {
{
my $mmap_file = $Config{ZM_PATH_MAP}."/zm.mmap.".$monitor->{Id}; my $mmap_file = $Config{ZM_PATH_MAP}."/zm.mmap.".$monitor->{Id};
if ( ! -e $mmap_file ) { if ( ! -e $mmap_file ) {
@ -105,15 +102,13 @@ sub zmMemAttach
return ( undef ); return ( undef );
} }
my $MMAP; my $MMAP;
if ( !open( $MMAP, "+<", $mmap_file ) ) if ( !open( $MMAP, '+<', $mmap_file ) ) {
{
Error( sprintf( "Can't open memory map file '%s': $!\n", $mmap_file ) ); Error( sprintf( "Can't open memory map file '%s': $!\n", $mmap_file ) );
return( undef ); return( undef );
} }
my $mmap = undef; my $mmap = undef;
my $mmap_addr = mmap( $mmap, $size, PROT_READ|PROT_WRITE, MAP_SHARED, $MMAP ); my $mmap_addr = mmap( $mmap, $size, PROT_READ|PROT_WRITE, MAP_SHARED, $MMAP );
if ( !$mmap_addr || !$mmap ) if ( !$mmap_addr || !$mmap ) {
{
Error( sprintf( "Can't mmap to file '%s': $!\n", $mmap_file ) ); Error( sprintf( "Can't mmap to file '%s': $!\n", $mmap_file ) );
close( $MMAP ); close( $MMAP );
return( undef ); return( undef );
@ -125,37 +120,31 @@ sub zmMemAttach
return( !undef ); return( !undef );
} }
sub zmMemDetach sub zmMemDetach {
{
my $monitor = shift; my $monitor = shift;
if ( $monitor->{MMap} ) if ( $monitor->{MMap} ) {
{
if ( ! munmap( ${$monitor->{MMap}} ) ) { if ( ! munmap( ${$monitor->{MMap}} ) ) {
Warn( "Unable to munmap for monitor $$monitor{Id}\n"); Warn( "Unable to munmap for monitor $$monitor{Id}\n");
} }
delete $monitor->{MMap}; delete $monitor->{MMap};
} }
if ( $monitor->{MMapAddr} ) if ( $monitor->{MMapAddr} ) {
{
delete $monitor->{MMapAddr}; delete $monitor->{MMapAddr};
} }
if ( $monitor->{MMapHandle} ) if ( $monitor->{MMapHandle} ) {
{
close( $monitor->{MMapHandle} ); close( $monitor->{MMapHandle} );
delete $monitor->{MMapHandle}; delete $monitor->{MMapHandle};
} }
} }
sub zmMemGet sub zmMemGet {
{
my $monitor = shift; my $monitor = shift;
my $offset = shift; my $offset = shift;
my $size = shift; my $size = shift;
my $mmap = $monitor->{MMap}; my $mmap = $monitor->{MMap};
if ( !$mmap || !$$mmap ) if ( !$mmap || !$$mmap ) {
{
Error( sprintf( "Can't read from mapped memory for monitor '%d', gone away?" Error( sprintf( "Can't read from mapped memory for monitor '%d', gone away?"
, $monitor->{Id} , $monitor->{Id}
) )
@ -166,16 +155,14 @@ sub zmMemGet
return( $data ); return( $data );
} }
sub zmMemPut sub zmMemPut {
{
my $monitor = shift; my $monitor = shift;
my $offset = shift; my $offset = shift;
my $size = shift; my $size = shift;
my $data = shift; my $data = shift;
my $mmap = $monitor->{MMap}; my $mmap = $monitor->{MMap};
if ( !$mmap || !$$mmap ) if ( !$mmap || !$$mmap ) {
{
Error( sprintf( "Can't write mapped memory for monitor '%d', gone away?" Error( sprintf( "Can't write mapped memory for monitor '%d', gone away?"
, $monitor->{Id} , $monitor->{Id}
) )
@ -186,12 +173,10 @@ sub zmMemPut
return( !undef ); return( !undef );
} }
sub zmMemClean sub zmMemClean {
{
Debug( "Removing memory map files\n" ); Debug( "Removing memory map files\n" );
my $mapPath = $Config{ZM_PATH_MAP}."/zm.mmap.*"; my $mapPath = $Config{ZM_PATH_MAP}.'/zm.mmap.*';
foreach my $mapFile( glob( $mapPath ) ) foreach my $mapFile( glob( $mapPath ) ) {
{
( $mapFile ) = $mapFile =~ /^(.+)$/; ( $mapFile ) = $mapFile =~ /^(.+)$/;
Debug( "Removing memory map file '$mapFile'\n" ); Debug( "Removing memory map file '$mapFile'\n" );
unlink( $mapFile ); unlink( $mapFile );

View File

@ -0,0 +1,85 @@
# ==========================================================================
#
# ZoneMinder Monitor Module, $Date$, $Revision$
# Copyright (C) 2001-2008 Philip Coombes
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ==========================================================================
#
# This module contains the common definitions and functions used by the rest
# of the ZoneMinder scripts
#
package ZoneMinder::Monitor;
use 5.006;
use strict;
use warnings;
require ZoneMinder::Base;
require ZoneMinder::Object;
require ZoneMinder::Server;
#our @ISA = qw(Exporter ZoneMinder::Base);
use parent qw(ZoneMinder::Object);
# ==========================================================================
#
# General Utility Functions
#
# ==========================================================================
use ZoneMinder::Config qw(:all);
use ZoneMinder::Logger qw(:all);
use ZoneMinder::Database qw(:all);
use POSIX;
use vars qw/ $table $primary_key /;
$table = 'Monitors';
$primary_key = 'Id';
sub Server {
return new ZoneMinder::Server( $_[0]{ServerId} );
} # end sub Server
1;
__END__
=head1 NAME
ZoneMinder::Monitor - Perl Class for Monitors
=head1 SYNOPSIS
use ZoneMinder::Monitor;
=head1 DESCRIPTION
=head1 AUTHOR
Isaac Connor, E<lt>isaac@zoneminder.comE<gt>
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2001-2017 ZoneMinder LLC
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.3 or,
at your option, any later version of Perl 5 you may have available.
=cut

View File

@ -41,9 +41,9 @@ yet.
=head1 OPTIONS =head1 OPTIONS
-r, --report - Just report don't actually do anything
-i, --interactive - Ask before applying any changes
-c, --continuous - Run continuously -c, --continuous - Run continuously
-i, --interactive - Ask before applying any changes
-r, --report - Just report don't actually do anything
-v, --version - Print the installed version of ZoneMinder -v, --version - Print the installed version of ZoneMinder
=cut =cut
@ -57,8 +57,8 @@ use bytes;
# ========================================================================== # ==========================================================================
use constant MAX_AGED_DIRS => 10; # Number of event dirs to check age on use constant MAX_AGED_DIRS => 10; # Number of event dirs to check age on
use constant RECOVER_TAG => "(r)"; # Tag to append to event name when recovered use constant RECOVER_TAG => '(r)'; # Tag to append to event name when recovered
use constant RECOVER_TEXT => "Recovered."; # Text to append to event notes when recovered use constant RECOVER_TEXT => 'Recovered.'; # Text to append to event notes when recovered
# ========================================================================== # ==========================================================================
# #
@ -96,10 +96,10 @@ logInit();
logSetSignal(); logSetSignal();
GetOptions( GetOptions(
'report' =>\$report, continuous =>\$continuous,
'interactive' =>\$interactive, interactive =>\$interactive,
'continuous' =>\$continuous, report =>\$report,
'version' =>\$version version =>\$version
) or pod2usage(-exitstatus => -1); ) or pod2usage(-exitstatus => -1);
if ( $version ) { if ( $version ) {
@ -111,6 +111,10 @@ if ( ($report + $interactive + $continuous) > 1 ) {
pod2usage(-exitstatus => -1); pod2usage(-exitstatus => -1);
} }
if ( ! exists $Config{ZM_AUDIT_MIN_AGE} ) {
Fatal('ZM_AUDIT_MIN_AGE is not set in config.');
}
my $dbh = zmDbConnect(); my $dbh = zmDbConnect();
chdir( EVENT_PATH ); chdir( EVENT_PATH );
@ -126,13 +130,13 @@ MAIN: while( $loop ) {
$dbh = zmDbConnect(); $dbh = zmDbConnect();
if ( $continuous ) { if ( $continuous ) {
Error("Unable to connect to database"); Error('Unable to connect to database');
# if we are running continuously, then just skip to the next # if we are running continuously, then just skip to the next
# interval, otherwise we are a one off run, so wait a second and # interval, otherwise we are a one off run, so wait a second and
# retry until someone kills us. # retry until someone kills us.
sleep( $Config{ZM_AUDIT_CHECK_INTERVAL} ); sleep( $Config{ZM_AUDIT_CHECK_INTERVAL} );
} else { } else {
Fatal("Unable to connect to database"); Fatal('Unable to connect to database');
} # end if } # end if
} # end while can't connect to the db } # end while can't connect to the db
@ -145,16 +149,12 @@ MAIN: while( $loop ) {
sleep 1; sleep 1;
} # end if } # end if
if ( ! exists $Config{ZM_AUDIT_MIN_AGE} ) {
Fatal("ZM_AUDIT_MIN_AGE is not set in config.");
}
my $db_monitors; my $db_monitors;
my $monitorSelectSql = "select Id from Monitors order by Id"; my $monitorSelectSql = 'select Id from Monitors order by Id';
my $monitorSelectSth = $dbh->prepare_cached( $monitorSelectSql ) my $monitorSelectSth = $dbh->prepare_cached( $monitorSelectSql )
or Fatal( "Can't prepare '$monitorSelectSql': ".$dbh->errstr() ); or Fatal( "Can't prepare '$monitorSelectSql': ".$dbh->errstr() );
my $eventSelectSql = "SELECT Id, (unix_timestamp() - unix_timestamp(StartTime)) as Age my $eventSelectSql = 'SELECT Id, (unix_timestamp() - unix_timestamp(StartTime)) as Age
FROM Events WHERE MonitorId = ? ORDER BY Id"; FROM Events WHERE MonitorId = ? ORDER BY Id';
my $eventSelectSth = $dbh->prepare_cached( $eventSelectSql ) my $eventSelectSth = $dbh->prepare_cached( $eventSelectSql )
or Fatal( "Can't prepare '$eventSelectSql': ".$dbh->errstr() ); or Fatal( "Can't prepare '$eventSelectSql': ".$dbh->errstr() );
@ -169,11 +169,11 @@ MAIN: while( $loop ) {
while ( my $event = $eventSelectSth->fetchrow_hashref() ) { while ( my $event = $eventSelectSth->fetchrow_hashref() ) {
$db_events->{$event->{Id}} = $event->{Age}; $db_events->{$event->{Id}} = $event->{Age};
} }
Debug( "Got ".int(keys(%$db_events))." events\n" ); Debug( 'Got '.int(keys(%$db_events))." events\n" );
} }
my $fs_monitors; my $fs_monitors;
foreach my $monitor ( glob("[0-9]*") ) { foreach my $monitor ( glob('[0-9]*') ) {
# Thie glob above gives all files starting with a digit. So a monitor with a name starting with a digit will be in this list. # Thie glob above gives all files starting with a digit. So a monitor with a name starting with a digit will be in this list.
next if $monitor =~ /\D/; next if $monitor =~ /\D/;
Debug( "Found filesystem monitor '$monitor'" ); Debug( "Found filesystem monitor '$monitor'" );
@ -182,11 +182,17 @@ MAIN: while( $loop ) {
if ( $Config{ZM_USE_DEEP_STORAGE} ) { if ( $Config{ZM_USE_DEEP_STORAGE} ) {
foreach my $day_dir ( glob("$monitor_dir/*/*/*") ) { foreach my $day_dir ( glob("$monitor_dir/*/*/*") ) {
Debug( "Checking $day_dir" ); Debug( "Checking day dir $day_dir" );
( $day_dir ) = ( $day_dir =~ /^(.*)$/ ); # De-taint ( $day_dir ) = ( $day_dir =~ /^(.*)$/ ); # De-taint
chdir( $day_dir ); if ( ! chdir( $day_dir ) ) {
opendir( DIR, "." ) Error( "Can't chdir to '$day_dir': $!" );
or Fatal( "Can't open directory '$day_dir': $!" ); next;
}
if ( ! opendir( DIR, '.' ) ) {
Error( "Can't open directory '$day_dir': $!" );
next;
}
my @event_links = sort { $b <=> $a } grep { -l $_ } readdir( DIR ); my @event_links = sort { $b <=> $a } grep { -l $_ } readdir( DIR );
closedir( DIR ); closedir( DIR );
my $count = 0; my $count = 0;
@ -226,7 +232,7 @@ MAIN: while( $loop ) {
} }
chdir( EVENT_PATH ); chdir( EVENT_PATH );
} }
Debug( "Got ".int(keys(%$fs_events))." events\n" ); Debug( 'Got '.int(keys(%$fs_events))." events\n" );
} # end foreach monitor Id } # end foreach monitor Id
redo MAIN if ( $cleaned ); redo MAIN if ( $cleaned );
@ -255,7 +261,7 @@ MAIN: while( $loop ) {
} }
my $monitor_links; my $monitor_links;
foreach my $link ( glob("*") ) { foreach my $link ( glob('*') ) {
next if ( !-l $link ); next if ( !-l $link );
next if ( -e $link ); next if ( -e $link );
@ -270,16 +276,16 @@ MAIN: while( $loop ) {
redo MAIN if ( $cleaned ); redo MAIN if ( $cleaned );
$cleaned = 0; $cleaned = 0;
my $deleteMonitorSql = "delete low_priority from Monitors where Id = ?"; my $deleteMonitorSql = 'delete low_priority from Monitors where Id = ?';
my $deleteMonitorSth = $dbh->prepare_cached( $deleteMonitorSql ) my $deleteMonitorSth = $dbh->prepare_cached( $deleteMonitorSql )
or Fatal( "Can't prepare '$deleteMonitorSql': ".$dbh->errstr() ); or Fatal( "Can't prepare '$deleteMonitorSql': ".$dbh->errstr() );
my $deleteEventSql = "delete low_priority from Events where Id = ?"; my $deleteEventSql = 'delete low_priority from Events where Id = ?';
my $deleteEventSth = $dbh->prepare_cached( $deleteEventSql ) my $deleteEventSth = $dbh->prepare_cached( $deleteEventSql )
or Fatal( "Can't prepare '$deleteEventSql': ".$dbh->errstr() ); or Fatal( "Can't prepare '$deleteEventSql': ".$dbh->errstr() );
my $deleteFramesSql = "delete low_priority from Frames where EventId = ?"; my $deleteFramesSql = 'delete low_priority from Frames where EventId = ?';
my $deleteFramesSth = $dbh->prepare_cached( $deleteFramesSql ) my $deleteFramesSth = $dbh->prepare_cached( $deleteFramesSql )
or Fatal( "Can't prepare '$deleteFramesSql': ".$dbh->errstr() ); or Fatal( "Can't prepare '$deleteFramesSql': ".$dbh->errstr() );
my $deleteStatsSql = "delete low_priority from Stats where EventId = ?"; my $deleteStatsSql = 'delete low_priority from Stats where EventId = ?';
my $deleteStatsSth = $dbh->prepare_cached( $deleteStatsSql ) my $deleteStatsSth = $dbh->prepare_cached( $deleteStatsSql )
or Fatal( "Can't prepare '$deleteStatsSql': ".$dbh->errstr() ); or Fatal( "Can't prepare '$deleteStatsSql': ".$dbh->errstr() );
while ( my ( $db_monitor, $db_events ) = each(%$db_monitors) ) { while ( my ( $db_monitor, $db_events ) = each(%$db_monitors) ) {
@ -319,9 +325,9 @@ MAIN: while( $loop ) {
# Remove orphaned events (with no monitor) # Remove orphaned events (with no monitor)
$cleaned = 0; $cleaned = 0;
my $selectOrphanedEventsSql = "SELECT Events.Id, Events.Name my $selectOrphanedEventsSql = 'SELECT Events.Id, Events.Name
FROM Events LEFT JOIN Monitors ON (Events.MonitorId = Monitors.Id) FROM Events LEFT JOIN Monitors ON (Events.MonitorId = Monitors.Id)
WHERE isnull(Monitors.Id)"; WHERE isnull(Monitors.Id)';
my $selectOrphanedEventsSth = $dbh->prepare_cached( $selectOrphanedEventsSql ) my $selectOrphanedEventsSth = $dbh->prepare_cached( $selectOrphanedEventsSql )
or Fatal( "Can't prepare '$selectOrphanedEventsSql': ".$dbh->errstr() ); or Fatal( "Can't prepare '$selectOrphanedEventsSql': ".$dbh->errstr() );
$res = $selectOrphanedEventsSth->execute() $res = $selectOrphanedEventsSth->execute()
@ -356,8 +362,8 @@ MAIN: while( $loop ) {
# Remove orphaned frame records # Remove orphaned frame records
$cleaned = 0; $cleaned = 0;
my $selectOrphanedFramesSql = "SELECT DISTINCT EventId FROM Frames my $selectOrphanedFramesSql = 'SELECT DISTINCT EventId FROM Frames
WHERE EventId NOT IN (SELECT Id FROM Events)"; WHERE EventId NOT IN (SELECT Id FROM Events)';
my $selectOrphanedFramesSth = $dbh->prepare_cached( $selectOrphanedFramesSql ) my $selectOrphanedFramesSth = $dbh->prepare_cached( $selectOrphanedFramesSql )
or Fatal( "Can't prepare '$selectOrphanedFramesSql': ".$dbh->errstr() ); or Fatal( "Can't prepare '$selectOrphanedFramesSql': ".$dbh->errstr() );
$res = $selectOrphanedFramesSth->execute() $res = $selectOrphanedFramesSth->execute()
@ -374,8 +380,8 @@ MAIN: while( $loop ) {
# Remove orphaned stats records # Remove orphaned stats records
$cleaned = 0; $cleaned = 0;
my $selectOrphanedStatsSql = "SELECT DISTINCT EventId FROM Stats my $selectOrphanedStatsSql = 'SELECT DISTINCT EventId FROM Stats
WHERE EventId NOT IN (SELECT Id FROM Events)"; WHERE EventId NOT IN (SELECT Id FROM Events)';
my $selectOrphanedStatsSth = $dbh->prepare_cached( $selectOrphanedStatsSql ) my $selectOrphanedStatsSth = $dbh->prepare_cached( $selectOrphanedStatsSql )
or Fatal( "Can't prepare '$selectOrphanedStatsSql': ".$dbh->errstr() ); or Fatal( "Can't prepare '$selectOrphanedStatsSql': ".$dbh->errstr() );
$res = $selectOrphanedStatsSth->execute() $res = $selectOrphanedStatsSth->execute()
@ -429,20 +435,13 @@ MAIN: while( $loop ) {
aud_print( "Found open event '$event->{Id}'" ); aud_print( "Found open event '$event->{Id}'" );
if ( confirm( 'close', 'closing' ) ) { if ( confirm( 'close', 'closing' ) ) {
$res = $updateUnclosedEventsSth->execute( $res = $updateUnclosedEventsSth->execute(
sprintf("%s%d%s", sprintf('%s%d%s', $event->{Prefix}, $event->{Id}, RECOVER_TAG),
$event->{Prefix},
$event->{Id},
RECOVER_TAG
),
$event->{EndTime}, $event->{EndTime},
$event->{Length}, $event->{Length},
$event->{Frames}, $event->{Frames},
$event->{AlarmFrames}, $event->{AlarmFrames},
$event->{TotScore}, $event->{TotScore},
$event->{AlarmFrames} $event->{AlarmFrames} ? int($event->{TotScore} / $event->{AlarmFrames}) : 0,
? int($event->{TotScore} / $event->{AlarmFrames})
: 0
,
$event->{MaxScore}, $event->{MaxScore},
RECOVER_TEXT, RECOVER_TEXT,
$event->{Id} $event->{Id}
@ -453,8 +452,8 @@ MAIN: while( $loop ) {
# Now delete any old image files # Now delete any old image files
my @old_files = grep { -M > $max_image_age } <$image_path/*.{jpg,gif,wbmp}>; my @old_files = grep { -M > $max_image_age } <$image_path/*.{jpg,gif,wbmp}>;
if ( @old_files ) { if ( @old_files ) {
aud_print( "Deleting ".int(@old_files)." old images\n" ); aud_print( 'Deleting '.( scalar @old_files )." old images\n" );
my $untainted_old_files = join( ";", @old_files ); my $untainted_old_files = join( ';', @old_files );
( $untainted_old_files ) = ( $untainted_old_files =~ /^(.*)$/ ); ( $untainted_old_files ) = ( $untainted_old_files =~ /^(.*)$/ );
unlink( split( /;/, $untainted_old_files ) ); unlink( split( /;/, $untainted_old_files ) );
} }
@ -467,7 +466,7 @@ MAIN: while( $loop ) {
if ( $Config{ZM_LOG_DATABASE_LIMIT} ) { if ( $Config{ZM_LOG_DATABASE_LIMIT} ) {
if ( $Config{ZM_LOG_DATABASE_LIMIT} =~ /^\d+$/ ) { if ( $Config{ZM_LOG_DATABASE_LIMIT} =~ /^\d+$/ ) {
# Number of rows # Number of rows
my $selectLogRowCountSql = "SELECT count(*) as Rows from Logs"; my $selectLogRowCountSql = 'SELECT count(*) AS Rows FROM Logs';
my $selectLogRowCountSth = $dbh->prepare_cached( $selectLogRowCountSql ) my $selectLogRowCountSth = $dbh->prepare_cached( $selectLogRowCountSql )
or Fatal( "Can't prepare '$selectLogRowCountSql': ".$dbh->errstr() ); or Fatal( "Can't prepare '$selectLogRowCountSql': ".$dbh->errstr() );
$res = $selectLogRowCountSth->execute() $res = $selectLogRowCountSth->execute()
@ -475,20 +474,20 @@ MAIN: while( $loop ) {
my $row = $selectLogRowCountSth->fetchrow_hashref(); my $row = $selectLogRowCountSth->fetchrow_hashref();
my $logRows = $row->{Rows}; my $logRows = $row->{Rows};
if ( $logRows > $Config{ZM_LOG_DATABASE_LIMIT} ) { if ( $logRows > $Config{ZM_LOG_DATABASE_LIMIT} ) {
my $deleteLogByRowsSql = "DELETE low_priority FROM Logs ORDER BY TimeKey ASC LIMIT ?"; my $deleteLogByRowsSql = 'DELETE low_priority FROM Logs ORDER BY TimeKey ASC LIMIT ?';
my $deleteLogByRowsSth = $dbh->prepare_cached( $deleteLogByRowsSql ) my $deleteLogByRowsSth = $dbh->prepare_cached( $deleteLogByRowsSql )
or Fatal( "Can't prepare '$deleteLogByRowsSql': ".$dbh->errstr() ); or Fatal( "Can't prepare '$deleteLogByRowsSql': ".$dbh->errstr() );
$res = $deleteLogByRowsSth->execute( $logRows - $Config{ZM_LOG_DATABASE_LIMIT} ) $res = $deleteLogByRowsSth->execute( $logRows - $Config{ZM_LOG_DATABASE_LIMIT} )
or Fatal( "Can't execute: ".$deleteLogByRowsSth->errstr() ); or Fatal( "Can't execute: ".$deleteLogByRowsSth->errstr() );
if ( $deleteLogByRowsSth->rows() ) { if ( $deleteLogByRowsSth->rows() ) {
aud_print( "Deleted ".$deleteLogByRowsSth->rows() ." log table entries by count\n" ); aud_print( 'Deleted '.$deleteLogByRowsSth->rows() ." log table entries by count\n" );
} }
} }
} else { } else {
# Time of record # Time of record
my $deleteLogByTimeSql = my $deleteLogByTimeSql =
"DELETE low_priority FROM Logs 'DELETE low_priority FROM Logs
WHERE TimeKey < unix_timestamp(now() - interval ".$Config{ZM_LOG_DATABASE_LIMIT}.")"; WHERE TimeKey < unix_timestamp(now() - interval '.$Config{ZM_LOG_DATABASE_LIMIT}.')';
my $deleteLogByTimeSth = $dbh->prepare_cached( $deleteLogByTimeSql ) my $deleteLogByTimeSth = $dbh->prepare_cached( $deleteLogByTimeSql )
or Fatal( "Can't prepare '$deleteLogByTimeSql': ".$dbh->errstr() ); or Fatal( "Can't prepare '$deleteLogByTimeSql': ".$dbh->errstr() );
$res = $deleteLogByTimeSth->execute() $res = $deleteLogByTimeSth->execute()
@ -515,8 +514,8 @@ sub aud_print {
} }
sub confirm { sub confirm {
my $prompt = shift || "delete"; my $prompt = shift || 'delete';
my $action = shift || "deleting"; my $action = shift || 'deleting';
my $yesno = 0; my $yesno = 0;
if ( $report ) { if ( $report ) {

File diff suppressed because it is too large Load Diff

View File

@ -167,11 +167,8 @@ int FfmpegCamera::Capture( Image &image )
Debug( 5, "Got packet from stream %d dts (%d) pts(%d)", packet.stream_index, packet.pts, packet.dts ); Debug( 5, "Got packet from stream %d dts (%d) pts(%d)", packet.stream_index, packet.pts, packet.dts );
// What about audio stream? Maybe someday we could do sound detection... // What about audio stream? Maybe someday we could do sound detection...
if ( packet.stream_index == mVideoStreamId ) { if ( packet.stream_index == mVideoStreamId ) {
#if LIBAVCODEC_VERSION_CHECK(52, 23, 0, 23, 0) int ret = zm_avcodec_decode_video( mVideoCodecContext, mRawFrame, &frameComplete, &packet );
if (avcodec_decode_video2(mVideoCodecContext, mRawFrame, &frameComplete, &packet) < 0) if ( ret < 0 )
#else
if (avcodec_decode_video(mVideoCodecContext, mRawFrame, &frameComplete, packet.data, packet.size) < 0)
#endif
Fatal( "Unable to decode frame at frame %d", frameCount ); Fatal( "Unable to decode frame at frame %d", frameCount );
Debug( 4, "Decoded video packet at frame %d", frameCount ); Debug( 4, "Decoded video packet at frame %d", frameCount );
@ -364,7 +361,7 @@ int FfmpegCamera::OpenFfmpeg() {
Fatal( "Unable to open codec for video stream from %s", mPath.c_str() ); Fatal( "Unable to open codec for video stream from %s", mPath.c_str() );
} }
if (mAudioStreamId >= 0) { if ( mAudioStreamId >= 0 ) {
mAudioCodecContext = mFormatContext->streams[mAudioStreamId]->codec; mAudioCodecContext = mFormatContext->streams[mAudioStreamId]->codec;
if ((mAudioCodec = avcodec_find_decoder(mAudioCodecContext->codec_id)) == NULL) { if ((mAudioCodec = avcodec_find_decoder(mAudioCodecContext->codec_id)) == NULL) {
Debug(1, "Can't find codec for audio stream from %s", mPath.c_str()); Debug(1, "Can't find codec for audio stream from %s", mPath.c_str());
@ -437,7 +434,7 @@ int FfmpegCamera::OpenFfmpeg() {
mCanCapture = true; mCanCapture = true;
return 0; return 0;
} } // int FfmpegCamera::OpenFfmpeg()
int FfmpegCamera::ReopenFfmpeg() { int FfmpegCamera::ReopenFfmpeg() {
@ -639,6 +636,7 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
unsigned int packet_count = 0; unsigned int packet_count = 0;
ZMPacket *queued_packet; ZMPacket *queued_packet;
// Clear all packets that predate the moment when the recording began
packetqueue.clear_unwanted_packets( &recording, mVideoStreamId ); packetqueue.clear_unwanted_packets( &recording, mVideoStreamId );
while ( ( queued_packet = packetqueue.popPacket() ) ) { while ( ( queued_packet = packetqueue.popPacket() ) ) {
@ -673,7 +671,7 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
// Buffer video packets, since we are not recording. // Buffer video packets, since we are not recording.
// All audio packets are keyframes, so only if it's a video keyframe // All audio packets are keyframes, so only if it's a video keyframe
if ( packet.stream_index == mVideoStreamId) { if ( packet.stream_index == mVideoStreamId ) {
if ( key_frame ) { if ( key_frame ) {
Debug(3, "Clearing queue"); Debug(3, "Clearing queue");
packetqueue.clearQueue( monitor->GetPreEventCount(), mVideoStreamId ); packetqueue.clearQueue( monitor->GetPreEventCount(), mVideoStreamId );
@ -689,11 +687,15 @@ else if ( packet.pts && video_last_pts > packet.pts ) {
#endif #endif
} }
if ( // The following lines should ensure that the queue always begins with a video keyframe
( packet.stream_index != mAudioStreamId || record_audio ) if ( packet.stream_index == mAudioStreamId ) {
&& Debug(2, "Have audio packet, reocrd_audio is (%d) and packetqueue.size is (%d)", record_audio, packetqueue.size() );
( key_frame || packetqueue.size() ) if ( record_audio && packetqueue.size() ) {
) { // if it's audio, and we are doing audio, and there is already something in the queue
packetqueue.queuePacket( &packet );
}
} else if ( packet.stream_index == mVideoStreamId ) {
if ( key_frame || packetqueue.size() ) // it's a keyframe or we already have something in the queue
packetqueue.queuePacket( &packet ); packetqueue.queuePacket( &packet );
} }
} // end if recording or not } // end if recording or not

View File

@ -60,14 +60,12 @@ ZMPacket* zm_packetqueue::popPacket( ) {
unsigned int zm_packetqueue::clearQueue( unsigned int frames_to_keep, int stream_id ) { unsigned int zm_packetqueue::clearQueue( unsigned int frames_to_keep, int stream_id ) {
Debug(3, "Clearing all but %d frames", frames_to_keep ); Debug(3, "Clearing all but %d frames, queue has %d", frames_to_keep, pktQueue.size() );
frames_to_keep += 1; frames_to_keep += 1;
if ( pktQueue.empty() ) { if ( pktQueue.empty() ) {
Debug(3, "Queue is empty"); Debug(3, "Queue is empty");
return 0; return 0;
} else {
Debug(3, "Queue has (%d)", pktQueue.size() );
} }
list<ZMPacket *>::reverse_iterator it; list<ZMPacket *>::reverse_iterator it;
@ -77,18 +75,19 @@ unsigned int zm_packetqueue::clearQueue( unsigned int frames_to_keep, int stream
ZMPacket *zm_packet = *it; ZMPacket *zm_packet = *it;
AVPacket *av_packet = &(zm_packet->packet); AVPacket *av_packet = &(zm_packet->packet);
Debug(3, "Looking at packet with stream index (%d) with keyframe (%d), frames_to_keep is (%d)", av_packet->stream_index, ( av_packet->flags & AV_PKT_FLAG_KEY ), frames_to_keep ); Debug(4, "Looking at packet with stream index (%d) with keyframe (%d), frames_to_keep is (%d)", av_packet->stream_index, ( av_packet->flags & AV_PKT_FLAG_KEY ), frames_to_keep );
// Want frames_to_keep video keyframes. Otherwise, we may not have enough // Want frames_to_keep video keyframes. Otherwise, we may not have enough
if ( ( av_packet->stream_index == stream_id) && ( av_packet->flags & AV_PKT_FLAG_KEY ) ) { if ( ( av_packet->stream_index == stream_id) && ( av_packet->flags & AV_PKT_FLAG_KEY ) ) {
if (!frames_to_keep)
break;
frames_to_keep --; frames_to_keep --;
} }
} }
if ( frames_to_keep ) {
Debug(3, "Hit end of queue, still need (%d) video keyframes", frames_to_keep );
}
unsigned int delete_count = 0; unsigned int delete_count = 0;
while ( it != pktQueue.rend() ) { while ( it != pktQueue.rend() ) {
Debug(3, "Deleting a packet from the front, count is (%d)", delete_count ); Debug(4, "Deleting a packet from the front, count is (%d)", delete_count );
packet = pktQueue.front(); packet = pktQueue.front();
pktQueue.pop_front(); pktQueue.pop_front();
@ -96,6 +95,7 @@ unsigned int zm_packetqueue::clearQueue( unsigned int frames_to_keep, int stream
delete_count += 1; delete_count += 1;
} }
Debug(3, "Deleted (%d) packets", delete_count );
return delete_count; return delete_count;
} // end unsigned int zm_packetqueue::clearQueue( unsigned int frames_to_keep, int stream_id ) } // end unsigned int zm_packetqueue::clearQueue( unsigned int frames_to_keep, int stream_id )
@ -123,10 +123,10 @@ void zm_packetqueue::clear_unwanted_packets( timeval *recording_started, int mVi
// Step 2 - pop packets until we get to the packet in step 2 // Step 2 - pop packets until we get to the packet in step 2
list<ZMPacket *>::reverse_iterator it; list<ZMPacket *>::reverse_iterator it;
Debug(3, "Looking for keyframe after start recording stream id (%d)", mVideoStreamId );
for ( it = pktQueue.rbegin(); it != pktQueue.rend(); ++ it ) { for ( it = pktQueue.rbegin(); it != pktQueue.rend(); ++ it ) {
ZMPacket *zm_packet = *it; ZMPacket *zm_packet = *it;
AVPacket *av_packet = &(zm_packet->packet); AVPacket *av_packet = &(zm_packet->packet);
Debug(1, "Looking for keyframe after start" );
if ( if (
( av_packet->flags & AV_PKT_FLAG_KEY ) ( av_packet->flags & AV_PKT_FLAG_KEY )
&& &&
@ -134,7 +134,7 @@ Debug(1, "Looking for keyframe after start" );
&& &&
timercmp( &(zm_packet->timestamp), recording_started, < ) timercmp( &(zm_packet->timestamp), recording_started, < )
) { ) {
Debug(1, "Found keyframe before start" ); Debug(3, "Found keyframe before start with stream index (%d) with keyframe (%d)", av_packet->stream_index, ( av_packet->flags & AV_PKT_FLAG_KEY ) );
break; break;
} }
} }
@ -143,10 +143,29 @@ Debug(1, "Found keyframe before start" );
return; return;
} }
ZMPacket *zm_packet = *it;
AVPacket *av_packet = &(zm_packet->packet);
Debug(3, "Found packet before start with stream index (%d) with keyframe (%d), distance(%d), size(%d)",
av_packet->stream_index,
( av_packet->flags & AV_PKT_FLAG_KEY ),
distance( it, pktQueue.rend() ),
pktQueue.size() );
unsigned int deleted_frames = 0;
ZMPacket *packet = NULL; ZMPacket *packet = NULL;
while ( pktQueue.rend() != it ) { while ( distance( it, pktQueue.rend() ) > 1 ) {
//while ( pktQueue.rend() != it ) {
packet = pktQueue.front(); packet = pktQueue.front();
pktQueue.pop_front(); pktQueue.pop_front();
delete packet; delete packet;
deleted_frames += 1;
}
zm_packet = pktQueue.front();
av_packet = &(zm_packet->packet);
if ( ( ! ( av_packet->flags & AV_PKT_FLAG_KEY ) ) || ( av_packet->stream_index != mVideoStreamId ) ) {
Error( "Done looking for keyframe. Deleted %d frames. Remaining frames in queue: %d stream of head packet is (%d), keyframe (%d), distance(%d), packets(%d)", deleted_frames, pktQueue.size(), av_packet->stream_index, ( av_packet->flags & AV_PKT_FLAG_KEY ), distance( it, pktQueue.rend() ), pktQueue.size() );
} else {
Debug(1, "Done looking for keyframe. Deleted %d frames. Remaining frames in queue: %d stream of head packet is (%d), keyframe (%d), distance(%d), packets(%d)", deleted_frames, pktQueue.size(), av_packet->stream_index, ( av_packet->flags & AV_PKT_FLAG_KEY ), distance( it, pktQueue.rend() ), pktQueue.size() );
} }
} }

View File

@ -82,28 +82,36 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
if (dsr < 0) Warning("%s:%d: title set failed", __FILE__, __LINE__ ); if (dsr < 0) Warning("%s:%d: title set failed", __FILE__, __LINE__ );
oc->metadata = pmetadata; oc->metadata = pmetadata;
output_format = oc->oformat; output_format = oc->oformat;
Debug(2, "setting parameters");
#if LIBAVCODEC_VERSION_CHECK(58, 0, 0, 0, 0)
AVCodec *codec = avcodec_find_decoder( video_input_stream->codecpar->codec_id );
video_output_context = avcodec_alloc_context3( codec );
ret = avcodec_parameters_to_context( video_output_context, video_input_stream->codecpar );
if ( ret < 0 ) {
Error( "Could not initialize stream parameteres");
return;
} else {
Debug(2, "Success setting parameters");
}
if ( avcodec_open2( video_output_context, codec, NULL ) < 0 ) {
Fatal("Unable to open video out codec\n");
}
video_output_stream = avformat_new_stream( oc, codec );
if (!video_output_stream) {
Fatal("Unable to create video out stream\n");
} else {
Debug(2, "Success creating video out stream" );
}
#else
video_output_stream = avformat_new_stream(oc, (AVCodec*)video_input_context->codec); video_output_stream = avformat_new_stream(oc, (AVCodec*)video_input_context->codec);
if (!video_output_stream) { if (!video_output_stream) {
Fatal("Unable to create video out stream\n"); Fatal("Unable to create video out stream\n");
} else { } else {
Debug(2, "Success creating video out stream" ); Debug(2, "Success creating video out stream" );
} }
video_output_context = video_output_stream->codec; video_output_context = video_output_stream->codec;
#if LIBAVCODEC_VERSION_CHECK(58, 0, 0, 0, 0)
Debug(2, "setting parameters");
ret = avcodec_parameters_to_context( video_output_context, video_input_stream->codecpar );
if ( ret < 0 ) {
Error( "Could not initialize stream parameteres");
return;
} else {
Debug(2, "Success getting parameters");
}
#else
ret = avcodec_copy_context(video_output_context, video_input_context ); ret = avcodec_copy_context(video_output_context, video_input_context );
if (ret < 0) { if (ret < 0) {
Fatal("Unable to copy input video context to output video context %s\n", Fatal("Unable to copy input video context to output video context %s\n",
@ -145,6 +153,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
} }
Monitor::Orientation orientation = monitor->getOrientation(); Monitor::Orientation orientation = monitor->getOrientation();
Debug(3, "Have orientation" );
if ( orientation ) { if ( orientation ) {
if ( orientation == Monitor::ROTATE_0 ) { if ( orientation == Monitor::ROTATE_0 ) {
@ -170,6 +179,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
#endif #endif
if (audio_input_stream) { if (audio_input_stream) {
Debug(3, "Have audio stream" );
audio_input_context = audio_input_stream->codec; audio_input_context = audio_input_stream->codec;
if ( audio_input_context->codec_id != AV_CODEC_ID_AAC ) { if ( audio_input_context->codec_id != AV_CODEC_ID_AAC ) {
@ -187,9 +197,13 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
Error("Unable to create audio out stream\n"); Error("Unable to create audio out stream\n");
audio_output_stream = NULL; audio_output_stream = NULL;
} else { } else {
Debug(2, "setting parameters");
audio_output_context = audio_output_stream->codec; audio_output_context = audio_output_stream->codec;
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
ret = avcodec_parameters_to_context( audio_output_context, audio_input_stream->codecpar );
#else
ret = avcodec_copy_context(audio_output_context, audio_input_context); ret = avcodec_copy_context(audio_output_context, audio_input_context);
#endif
if (ret < 0) { if (ret < 0) {
Error("Unable to copy audio context %s\n", av_make_error_string(ret).c_str()); Error("Unable to copy audio context %s\n", av_make_error_string(ret).c_str());
audio_output_stream = NULL; audio_output_stream = NULL;
@ -233,7 +247,8 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
//av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0); //av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0);
//av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0); //av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0);
//av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov+default_base_moof", 0); //av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov+default_base_moof", 0);
if ((ret = avformat_write_header(oc, &opts)) < 0) { if ((ret = avformat_write_header(oc, NULL)) < 0) {
//if ((ret = avformat_write_header(oc, &opts)) < 0) {
Warning("Unable to set movflags to frag_custom+dash+delay_moov"); Warning("Unable to set movflags to frag_custom+dash+delay_moov");
/* Write the stream header, if any. */ /* Write the stream header, if any. */
ret = avformat_write_header(oc, NULL); ret = avformat_write_header(oc, NULL);
@ -262,14 +277,14 @@ VideoStore::~VideoStore(){
if ( audio_output_codec ) { if ( audio_output_codec ) {
// Do we need to flush the outputs? I have no idea. // Do we need to flush the outputs? I have no idea.
AVPacket pkt; AVPacket pkt;
int got_packet; int got_packet = 0;
av_init_packet(&pkt); av_init_packet(&pkt);
pkt.data = NULL; pkt.data = NULL;
pkt.size = 0; pkt.size = 0;
int64_t size; int64_t size;
while(1) { while(1) {
#if LIBAVCODEC_VERSION_CHECK(58, 0, 0, 0, 0) #if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
ret = avcodec_receive_packet( audio_output_context, &pkt ); ret = avcodec_receive_packet( audio_output_context, &pkt );
#else #else
ret = avcodec_encode_audio2( audio_output_context, &pkt, NULL, &got_packet ); ret = avcodec_encode_audio2( audio_output_context, &pkt, NULL, &got_packet );
@ -677,7 +692,7 @@ int VideoStore::writeAudioFramePacket( AVPacket *ipkt ) {
if ( audio_output_codec ) { if ( audio_output_codec ) {
#ifdef HAVE_LIBAVRESAMPLE #ifdef HAVE_LIBAVRESAMPLE
#if 0 #if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
ret = avcodec_send_packet( audio_input_context, ipkt ); ret = avcodec_send_packet( audio_input_context, ipkt );
if ( ret < 0 ) { if ( ret < 0 ) {
Error("avcodec_send_packet fail %s", av_make_error_string(ret).c_str()); Error("avcodec_send_packet fail %s", av_make_error_string(ret).c_str());
@ -696,26 +711,7 @@ int VideoStore::writeAudioFramePacket( AVPacket *ipkt ) {
input_frame->channel_layout, input_frame->channel_layout,
audio_output_context->refcounted_frames audio_output_context->refcounted_frames
); );
ret = avcodec_send_frame( audio_output_context, input_frame );
if ( ret < 0 ) {
av_frame_unref( input_frame );
Error("avcodec_send_frame fail(%d), %s codec is open(%d) is_encoder(%d)", ret, av_make_error_string(ret).c_str(),
avcodec_is_open( audio_output_context ),
av_codec_is_encoder( audio_output_context->codec)
);
return 0;
}
ret = avcodec_receive_packet( audio_output_context, &opkt );
if ( ret < 0 ) {
av_frame_unref( input_frame );
Error("avcodec_receive_packet fail %s", av_make_error_string(ret).c_str());
return 0;
}
av_frame_unref( input_frame );
#else #else
/** /**
* Decode the audio frame stored in the packet. * Decode the audio frame stored in the packet.
* The input audio stream decoder is used to do this. * The input audio stream decoder is used to do this.
@ -736,7 +732,7 @@ int VideoStore::writeAudioFramePacket( AVPacket *ipkt ) {
zm_av_packet_unref(&opkt); zm_av_packet_unref(&opkt);
return 0; return 0;
} }
#endif
int frame_size = input_frame->nb_samples; int frame_size = input_frame->nb_samples;
Debug(4, "Frame size: %d", frame_size ); Debug(4, "Frame size: %d", frame_size );
@ -778,7 +774,7 @@ int VideoStore::writeAudioFramePacket( AVPacket *ipkt ) {
* Encode the audio frame and store it in the temporary packet. * Encode the audio frame and store it in the temporary packet.
* The output audio stream encoder is used to do this. * The output audio stream encoder is used to do this.
*/ */
#if LIBAVCODEC_VERSION_CHECK(58, 0, 0, 0, 0) #if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
if (( ret = avcodec_receive_packet( audio_output_context, &opkt )) < 0 ) { if (( ret = avcodec_receive_packet( audio_output_context, &opkt )) < 0 ) {
#else #else
if (( ret = avcodec_encode_audio2( audio_output_context, &opkt, output_frame, &data_present )) < 0) { if (( ret = avcodec_encode_audio2( audio_output_context, &opkt, output_frame, &data_present )) < 0) {
@ -794,7 +790,6 @@ int VideoStore::writeAudioFramePacket( AVPacket *ipkt ) {
return 0; return 0;
} }
#endif
#endif #endif
} else { } else {
av_init_packet(&opkt); av_init_packet(&opkt);

View File

@ -163,7 +163,7 @@ int main( int argc, char *argv[] )
if ( analysis_update_delay ) if ( analysis_update_delay )
{ {
cur_time = time( 0 ); cur_time = time( 0 );
if ( ( cur_time - last_analysis_update_time ) > analysis_update_delay ) if ( (unsigned int)( cur_time - last_analysis_update_time ) > analysis_update_delay )
{ {
analysis_rate = monitor->GetAnalysisRate(); analysis_rate = monitor->GetAnalysisRate();
monitor->UpdateAdaptiveSkip(); monitor->UpdateAdaptiveSkip();

View File

@ -95,8 +95,7 @@ Options for use with monitors:
#include "zm_monitor.h" #include "zm_monitor.h"
#include "zm_local_camera.h" #include "zm_local_camera.h"
void Usage( int status=-1 ) void Usage( int status=-1 ) {
{
fprintf( stderr, "zmu <-d device_path> [-v] [function] [-U<username> -P<password>]\n" ); fprintf( stderr, "zmu <-d device_path> [-v] [function] [-U<username> -P<password>]\n" );
fprintf( stderr, "zmu <-m monitor_id> [-v] [function] [-U<username> -P<password>]\n" ); fprintf( stderr, "zmu <-m monitor_id> [-v] [function] [-U<username> -P<password>]\n" );
fprintf( stderr, "General options:\n" ); fprintf( stderr, "General options:\n" );
@ -167,48 +166,38 @@ typedef enum {
ZMU_LIST = 0x10000000, ZMU_LIST = 0x10000000,
} Function; } Function;
bool ValidateAccess( User *user, int mon_id, int function ) bool ValidateAccess( User *user, int mon_id, int function ) {
{
bool allowed = true; bool allowed = true;
if ( function & (ZMU_STATE|ZMU_IMAGE|ZMU_TIME|ZMU_READ_IDX|ZMU_WRITE_IDX|ZMU_FPS) ) if ( function & (ZMU_STATE|ZMU_IMAGE|ZMU_TIME|ZMU_READ_IDX|ZMU_WRITE_IDX|ZMU_FPS) ) {
{
if ( user->getStream() < User::PERM_VIEW ) if ( user->getStream() < User::PERM_VIEW )
allowed = false; allowed = false;
} }
if ( function & ZMU_EVENT ) if ( function & ZMU_EVENT ) {
{
if ( user->getEvents() < User::PERM_VIEW ) if ( user->getEvents() < User::PERM_VIEW )
allowed = false; allowed = false;
} }
if ( function & (ZMU_ZONES|ZMU_QUERY|ZMU_LIST) ) if ( function & (ZMU_ZONES|ZMU_QUERY|ZMU_LIST) ) {
{
if ( user->getMonitors() < User::PERM_VIEW ) if ( user->getMonitors() < User::PERM_VIEW )
allowed = false; allowed = false;
} }
if ( function & (ZMU_ALARM|ZMU_NOALARM|ZMU_CANCEL|ZMU_RELOAD|ZMU_ENABLE|ZMU_DISABLE|ZMU_SUSPEND|ZMU_RESUME|ZMU_BRIGHTNESS|ZMU_CONTRAST|ZMU_HUE|ZMU_COLOUR) ) if ( function & (ZMU_ALARM|ZMU_NOALARM|ZMU_CANCEL|ZMU_RELOAD|ZMU_ENABLE|ZMU_DISABLE|ZMU_SUSPEND|ZMU_RESUME|ZMU_BRIGHTNESS|ZMU_CONTRAST|ZMU_HUE|ZMU_COLOUR) ) {
{
if ( user->getMonitors() < User::PERM_EDIT ) if ( user->getMonitors() < User::PERM_EDIT )
allowed = false; allowed = false;
} }
if ( mon_id > 0 ) if ( mon_id > 0 ) {
{ if ( !user->canAccess( mon_id ) ) {
if ( !user->canAccess( mon_id ) )
{
allowed = false; allowed = false;
} }
} }
if ( !allowed ) if ( !allowed ) {
{
fprintf( stderr, "Error, insufficient privileges for requested action\n" ); fprintf( stderr, "Error, insufficient privileges for requested action\n" );
exit( -1 ); exit( -1 );
} }
return( allowed ); return( allowed );
} }
int main( int argc, char *argv[] ) int main( int argc, char *argv[] ) {
{ if ( access(ZM_CONFIG, R_OK) != 0 ) {
if ( access(ZM_CONFIG, R_OK) != 0 )
{
fprintf( stderr, "Can't open %s: %s\n", ZM_CONFIG, strerror(errno) ); fprintf( stderr, "Can't open %s: %s\n", ZM_CONFIG, strerror(errno) );
exit( -1 ); exit( -1 );
} }
@ -274,18 +263,15 @@ int main( int argc, char *argv[] )
int v4lVersion = 1; int v4lVersion = 1;
#endif // ZM_HAS_V4L2/1 #endif // ZM_HAS_V4L2/1
#endif // ZM_HAS_V4L #endif // ZM_HAS_V4L
while (1) while (1) {
{
int option_index = 0; int option_index = 0;
int c = getopt_long (argc, argv, "d:m:vsEDLurwei::S:t::fz::ancqhlB::C::H::O::U:P:A:V:", long_options, &option_index); int c = getopt_long (argc, argv, "d:m:vsEDLurwei::S:t::fz::ancqhlB::C::H::O::U:P:A:V:", long_options, &option_index);
if (c == -1) if (c == -1) {
{
break; break;
} }
switch (c) switch (c) {
{
case 'd': case 'd':
if ( optarg ) if ( optarg )
device = optarg; device = optarg;
@ -405,8 +391,7 @@ int main( int argc, char *argv[] )
} }
} }
if (optind < argc) if (optind < argc) {
{
fprintf( stderr, "Extraneous options, " ); fprintf( stderr, "Extraneous options, " );
while (optind < argc) while (optind < argc)
fprintf( stderr, "%s ", argv[optind++]); fprintf( stderr, "%s ", argv[optind++]);
@ -414,13 +399,11 @@ int main( int argc, char *argv[] )
Usage(); Usage();
} }
if ( device && !(function&ZMU_QUERY) ) if ( device && !(function&ZMU_QUERY) ) {
{
fprintf( stderr, "Error, -d option cannot be used with this option\n" ); fprintf( stderr, "Error, -d option cannot be used with this option\n" );
Usage(); Usage();
} }
if ( scale != -1 && !(function&ZMU_IMAGE) ) if ( scale != -1 && !(function&ZMU_IMAGE) ) {
{
fprintf( stderr, "Error, -S option cannot be used with this option\n" ); fprintf( stderr, "Error, -S option cannot be used with this option\n" );
Usage(); Usage();
} }
@ -435,46 +418,36 @@ int main( int argc, char *argv[] )
User *user = 0; User *user = 0;
if ( config.opt_use_auth ) if ( config.opt_use_auth ) {
{ if ( strcmp( config.auth_relay, "none" ) == 0 ) {
if ( strcmp( config.auth_relay, "none" ) == 0 ) if ( !username ) {
{
if ( !username )
{
fprintf( stderr, "Error, username must be supplied\n" ); fprintf( stderr, "Error, username must be supplied\n" );
exit( -1 ); exit( -1 );
} }
if ( username ) if ( username ) {
{
user = zmLoadUser( username ); user = zmLoadUser( username );
} }
} } else {
else if ( !(username && password) && !auth ) {
{
if ( !(username && password) && !auth )
{
fprintf( stderr, "Error, username and password or auth string must be supplied\n" ); fprintf( stderr, "Error, username and password or auth string must be supplied\n" );
exit( -1 ); exit( -1 );
} }
//if ( strcmp( config.auth_relay, "hashed" ) == 0 ) //if ( strcmp( config.auth_relay, "hashed" ) == 0 )
{ {
if ( auth ) if ( auth ) {
{
user = zmLoadAuthUser( auth, false ); user = zmLoadAuthUser( auth, false );
} }
} }
//else if ( strcmp( config.auth_relay, "plain" ) == 0 ) //else if ( strcmp( config.auth_relay, "plain" ) == 0 )
{ {
if ( username && password ) if ( username && password ) {
{
user = zmLoadUser( username, password ); user = zmLoadUser( username, password );
} }
} }
} }
if ( !user ) if ( !user ) {
{
fprintf( stderr, "Error, unable to authenticate user\n" ); fprintf( stderr, "Error, unable to authenticate user\n" );
exit( -1 ); exit( -1 );
} }
@ -482,13 +455,10 @@ int main( int argc, char *argv[] )
} }
if ( mon_id > 0 ) if ( mon_id > 0 ) {
{
Monitor *monitor = Monitor::Load( mon_id, function&(ZMU_QUERY|ZMU_ZONES), Monitor::QUERY ); Monitor *monitor = Monitor::Load( mon_id, function&(ZMU_QUERY|ZMU_ZONES), Monitor::QUERY );
if ( monitor ) if ( monitor ) {
{ if ( verbose ) {
if ( verbose )
{
printf( "Monitor %d(%s)\n", monitor->Id(), monitor->Name() ); printf( "Monitor %d(%s)\n", monitor->Id(), monitor->Name() );
} }
if ( ! monitor->connect() ) { if ( ! monitor->connect() ) {
@ -498,23 +468,19 @@ int main( int argc, char *argv[] )
char separator = ' '; char separator = ' ';
bool have_output = false; bool have_output = false;
if ( function & ZMU_STATE ) if ( function & ZMU_STATE ) {
{
Monitor::State state = monitor->GetState(); Monitor::State state = monitor->GetState();
if ( verbose ) if ( verbose )
printf( "Current state: %s\n", state==Monitor::ALARM?"Alarm":(state==Monitor::ALERT?"Alert":"Idle") ); printf( "Current state: %s\n", state==Monitor::ALARM?"Alarm":(state==Monitor::ALERT?"Alert":"Idle") );
else else {
{
if ( have_output ) printf( "%c", separator ); if ( have_output ) printf( "%c", separator );
printf( "%d", state ); printf( "%d", state );
have_output = true; have_output = true;
} }
} }
if ( function & ZMU_TIME ) if ( function & ZMU_TIME ) {
{
struct timeval timestamp = monitor->GetTimestamp( image_idx ); struct timeval timestamp = monitor->GetTimestamp( image_idx );
if ( verbose ) if ( verbose ) {
{
char timestamp_str[64] = "None"; char timestamp_str[64] = "None";
if ( timestamp.tv_sec ) if ( timestamp.tv_sec )
strftime( timestamp_str, sizeof(timestamp_str), "%Y-%m-%d %H:%M:%S", localtime( &timestamp.tv_sec ) ); strftime( timestamp_str, sizeof(timestamp_str), "%Y-%m-%d %H:%M:%S", localtime( &timestamp.tv_sec ) );
@ -522,62 +488,50 @@ int main( int argc, char *argv[] )
printf( "Time of last image capture: %s.%02ld\n", timestamp_str, timestamp.tv_usec/10000 ); printf( "Time of last image capture: %s.%02ld\n", timestamp_str, timestamp.tv_usec/10000 );
else else
printf( "Time of image %d capture: %s.%02ld\n", image_idx, timestamp_str, timestamp.tv_usec/10000 ); printf( "Time of image %d capture: %s.%02ld\n", image_idx, timestamp_str, timestamp.tv_usec/10000 );
} } else {
else
{
if ( have_output ) printf( "%c", separator ); if ( have_output ) printf( "%c", separator );
printf( "%ld.%02ld", timestamp.tv_sec, timestamp.tv_usec/10000 ); printf( "%ld.%02ld", timestamp.tv_sec, timestamp.tv_usec/10000 );
have_output = true; have_output = true;
} }
} }
if ( function & ZMU_READ_IDX ) if ( function & ZMU_READ_IDX ) {
{
if ( verbose ) if ( verbose )
printf( "Last read index: %d\n", monitor->GetLastReadIndex() ); printf( "Last read index: %d\n", monitor->GetLastReadIndex() );
else else {
{
if ( have_output ) printf( "%c", separator ); if ( have_output ) printf( "%c", separator );
printf( "%d", monitor->GetLastReadIndex() ); printf( "%d", monitor->GetLastReadIndex() );
have_output = true; have_output = true;
} }
} }
if ( function & ZMU_WRITE_IDX ) if ( function & ZMU_WRITE_IDX ) {
{
if ( verbose ) if ( verbose )
printf( "Last write index: %d\n", monitor->GetLastWriteIndex() ); printf( "Last write index: %d\n", monitor->GetLastWriteIndex() );
else else {
{
if ( have_output ) printf( "%c", separator ); if ( have_output ) printf( "%c", separator );
printf( "%d", monitor->GetLastWriteIndex() ); printf( "%d", monitor->GetLastWriteIndex() );
have_output = true; have_output = true;
} }
} }
if ( function & ZMU_EVENT ) if ( function & ZMU_EVENT ) {
{
if ( verbose ) if ( verbose )
printf( "Last event id: %d\n", monitor->GetLastEvent() ); printf( "Last event id: %d\n", monitor->GetLastEvent() );
else else {
{
if ( have_output ) printf( "%c", separator ); if ( have_output ) printf( "%c", separator );
printf( "%d", monitor->GetLastEvent() ); printf( "%d", monitor->GetLastEvent() );
have_output = true; have_output = true;
} }
} }
if ( function & ZMU_FPS ) if ( function & ZMU_FPS ) {
{
if ( verbose ) if ( verbose )
printf( "Current capture rate: %.2f frames per second\n", monitor->GetFPS() ); printf( "Current capture rate: %.2f frames per second\n", monitor->GetFPS() );
else else {
{
if ( have_output ) printf( "%c", separator ); if ( have_output ) printf( "%c", separator );
printf( "%.2f", monitor->GetFPS() ); printf( "%.2f", monitor->GetFPS() );
have_output = true; have_output = true;
} }
} }
if ( function & ZMU_IMAGE ) if ( function & ZMU_IMAGE ) {
{ if ( verbose ) {
if ( verbose )
{
if ( image_idx == -1 ) if ( image_idx == -1 )
printf( "Dumping last image captured to Monitor%d.jpg", monitor->Id() ); printf( "Dumping last image captured to Monitor%d.jpg", monitor->Id() );
else else
@ -588,77 +542,63 @@ int main( int argc, char *argv[] )
} }
monitor->GetImage( image_idx, scale>0?scale:100 ); monitor->GetImage( image_idx, scale>0?scale:100 );
} }
if ( function & ZMU_ZONES ) if ( function & ZMU_ZONES ) {
{
if ( verbose ) if ( verbose )
printf( "Dumping zone image to Zones%d.jpg\n", monitor->Id() ); printf( "Dumping zone image to Zones%d.jpg\n", monitor->Id() );
monitor->DumpZoneImage( zoneString ); monitor->DumpZoneImage( zoneString );
} }
if ( function & ZMU_ALARM ) if ( function & ZMU_ALARM ) {
{
if ( verbose ) if ( verbose )
printf( "Forcing alarm on\n" ); printf( "Forcing alarm on\n" );
monitor->ForceAlarmOn( config.forced_alarm_score, "Forced Web" ); monitor->ForceAlarmOn( config.forced_alarm_score, "Forced Web" );
} }
if ( function & ZMU_NOALARM ) if ( function & ZMU_NOALARM ) {
{
if ( verbose ) if ( verbose )
printf( "Forcing alarm off\n" ); printf( "Forcing alarm off\n" );
monitor->ForceAlarmOff(); monitor->ForceAlarmOff();
} }
if ( function & ZMU_CANCEL ) if ( function & ZMU_CANCEL ) {
{
if ( verbose ) if ( verbose )
printf( "Cancelling forced alarm on/off\n" ); printf( "Cancelling forced alarm on/off\n" );
monitor->CancelForced(); monitor->CancelForced();
} }
if ( function & ZMU_RELOAD ) if ( function & ZMU_RELOAD ) {
{
if ( verbose ) if ( verbose )
printf( "Reloading monitor settings\n" ); printf( "Reloading monitor settings\n" );
monitor->actionReload(); monitor->actionReload();
} }
if ( function & ZMU_ENABLE ) if ( function & ZMU_ENABLE ) {
{
if ( verbose ) if ( verbose )
printf( "Enabling event generation\n" ); printf( "Enabling event generation\n" );
monitor->actionEnable(); monitor->actionEnable();
} }
if ( function & ZMU_DISABLE ) if ( function & ZMU_DISABLE ) {
{
if ( verbose ) if ( verbose )
printf( "Disabling event generation\n" ); printf( "Disabling event generation\n" );
monitor->actionDisable(); monitor->actionDisable();
} }
if ( function & ZMU_SUSPEND ) if ( function & ZMU_SUSPEND ) {
{
if ( verbose ) if ( verbose )
printf( "Suspending event generation\n" ); printf( "Suspending event generation\n" );
monitor->actionSuspend(); monitor->actionSuspend();
} }
if ( function & ZMU_RESUME ) if ( function & ZMU_RESUME ) {
{
if ( verbose ) if ( verbose )
printf( "Resuming event generation\n" ); printf( "Resuming event generation\n" );
monitor->actionResume(); monitor->actionResume();
} }
if ( function & ZMU_QUERY ) if ( function & ZMU_QUERY ) {
{
char monString[16382] = ""; char monString[16382] = "";
monitor->DumpSettings( monString, verbose ); monitor->DumpSettings( monString, verbose );
printf( "%s\n", monString ); printf( "%s\n", monString );
} }
if ( function & ZMU_BRIGHTNESS ) if ( function & ZMU_BRIGHTNESS ) {
{ if ( verbose ) {
if ( verbose )
{
if ( brightness >= 0 ) if ( brightness >= 0 )
printf( "New brightness: %d\n", monitor->actionBrightness( brightness ) ); printf( "New brightness: %d\n", monitor->actionBrightness( brightness ) );
else else
printf( "Current brightness: %d\n", monitor->actionBrightness() ); printf( "Current brightness: %d\n", monitor->actionBrightness() );
} } else {
else
{
if ( have_output ) printf( "%c", separator ); if ( have_output ) printf( "%c", separator );
if ( brightness >= 0 ) if ( brightness >= 0 )
printf( "%d", monitor->actionBrightness( brightness ) ); printf( "%d", monitor->actionBrightness( brightness ) );
@ -667,17 +607,13 @@ int main( int argc, char *argv[] )
have_output = true; have_output = true;
} }
} }
if ( function & ZMU_CONTRAST ) if ( function & ZMU_CONTRAST ) {
{ if ( verbose ) {
if ( verbose )
{
if ( contrast >= 0 ) if ( contrast >= 0 )
printf( "New brightness: %d\n", monitor->actionContrast( contrast ) ); printf( "New brightness: %d\n", monitor->actionContrast( contrast ) );
else else
printf( "Current contrast: %d\n", monitor->actionContrast() ); printf( "Current contrast: %d\n", monitor->actionContrast() );
} } else {
else
{
if ( have_output ) printf( "%c", separator ); if ( have_output ) printf( "%c", separator );
if ( contrast >= 0 ) if ( contrast >= 0 )
printf( "%d", monitor->actionContrast( contrast ) ); printf( "%d", monitor->actionContrast( contrast ) );
@ -686,17 +622,13 @@ int main( int argc, char *argv[] )
have_output = true; have_output = true;
} }
} }
if ( function & ZMU_HUE ) if ( function & ZMU_HUE ) {
{ if ( verbose ) {
if ( verbose )
{
if ( hue >= 0 ) if ( hue >= 0 )
printf( "New hue: %d\n", monitor->actionHue( hue ) ); printf( "New hue: %d\n", monitor->actionHue( hue ) );
else else
printf( "Current hue: %d\n", monitor->actionHue() ); printf( "Current hue: %d\n", monitor->actionHue() );
} } else {
else
{
if ( have_output ) printf( "%c", separator ); if ( have_output ) printf( "%c", separator );
if ( hue >= 0 ) if ( hue >= 0 )
printf( "%d", monitor->actionHue( hue ) ); printf( "%d", monitor->actionHue( hue ) );
@ -705,17 +637,13 @@ int main( int argc, char *argv[] )
have_output = true; have_output = true;
} }
} }
if ( function & ZMU_COLOUR ) if ( function & ZMU_COLOUR ) {
{ if ( verbose ) {
if ( verbose )
{
if ( colour >= 0 ) if ( colour >= 0 )
printf( "New colour: %d\n", monitor->actionColour( colour ) ); printf( "New colour: %d\n", monitor->actionColour( colour ) );
else else
printf( "Current colour: %d\n", monitor->actionColour() ); printf( "Current colour: %d\n", monitor->actionColour() );
} } else {
else
{
if ( have_output ) printf( "%c", separator ); if ( have_output ) printf( "%c", separator );
if ( colour >= 0 ) if ( colour >= 0 )
printf( "%d", monitor->actionColour( colour ) ); printf( "%d", monitor->actionColour( colour ) );
@ -724,26 +652,19 @@ int main( int argc, char *argv[] )
have_output = true; have_output = true;
} }
} }
if ( have_output ) if ( have_output ) {
{
printf( "\n" ); printf( "\n" );
} }
if ( !function ) if ( !function ) {
{
Usage(); Usage();
} }
delete monitor; delete monitor;
} } else {
else
{
fprintf( stderr, "Error, invalid monitor id %d\n", mon_id ); fprintf( stderr, "Error, invalid monitor id %d\n", mon_id );
exit( -1 ); exit( -1 );
} }
} } else {
else if ( function & ZMU_QUERY ) {
{
if ( function & ZMU_QUERY )
{
#if ZM_HAS_V4L #if ZM_HAS_V4L
char vidString[0x10000] = ""; char vidString[0x10000] = "";
bool ok = LocalCamera::GetCurrentSettings( device, vidString, v4lVersion, verbose ); bool ok = LocalCamera::GetCurrentSettings( device, vidString, v4lVersion, verbose );
@ -755,24 +676,20 @@ int main( int argc, char *argv[] )
#endif // ZM_HAS_V4L #endif // ZM_HAS_V4L
} }
if ( function & ZMU_LIST ) if ( function & ZMU_LIST ) {
{
std::string sql = "select Id, Function+0 from Monitors"; std::string sql = "select Id, Function+0 from Monitors";
if ( !verbose ) if ( !verbose ) {
{
sql += "where Function != 'None'"; sql += "where Function != 'None'";
} }
sql += " order by Id asc"; sql += " order by Id asc";
if ( mysql_query( &dbconn, sql.c_str() ) ) if ( mysql_query( &dbconn, sql.c_str() ) ) {
{
Error( "Can't run query: %s", mysql_error( &dbconn ) ); Error( "Can't run query: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) ); exit( mysql_errno( &dbconn ) );
} }
MYSQL_RES *result = mysql_store_result( &dbconn ); MYSQL_RES *result = mysql_store_result( &dbconn );
if ( !result ) if ( !result ) {
{
Error( "Can't use query result: %s", mysql_error( &dbconn ) ); Error( "Can't use query result: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) ); exit( mysql_errno( &dbconn ) );
} }
@ -780,17 +697,13 @@ int main( int argc, char *argv[] )
Debug( 1, "Got %d monitors", n_monitors ); Debug( 1, "Got %d monitors", n_monitors );
printf( "%4s%5s%6s%9s%14s%6s%6s%8s%8s\n", "Id", "Func", "State", "TrgState", "LastImgTim", "RdIdx", "WrIdx", "LastEvt", "FrmRate" ); printf( "%4s%5s%6s%9s%14s%6s%6s%8s%8s\n", "Id", "Func", "State", "TrgState", "LastImgTim", "RdIdx", "WrIdx", "LastEvt", "FrmRate" );
for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) {
{
int mon_id = atoi(dbrow[0]); int mon_id = atoi(dbrow[0]);
int function = atoi(dbrow[1]); int function = atoi(dbrow[1]);
if ( !user || user->canAccess( mon_id ) ) if ( !user || user->canAccess( mon_id ) ) {
{ if ( function > 1 ) {
if ( function > 1 )
{
Monitor *monitor = Monitor::Load( mon_id, false, Monitor::QUERY ); Monitor *monitor = Monitor::Load( mon_id, false, Monitor::QUERY );
if ( monitor && monitor->connect() ) if ( monitor && monitor->connect() ) {
{
struct timeval tv = monitor->GetTimestamp(); struct timeval tv = monitor->GetTimestamp();
printf( "%4d%5d%6d%9d%11ld.%02ld%6d%6d%8d%8.2f\n", printf( "%4d%5d%6d%9d%11ld.%02ld%6d%6d%8d%8.2f\n",
monitor->Id(), monitor->Id(),
@ -805,9 +718,7 @@ int main( int argc, char *argv[] )
); );
delete monitor; delete monitor;
} }
} } else {
else
{
struct timeval tv = { 0, 0 }; struct timeval tv = { 0, 0 };
printf( "%4d%5d%6d%9d%11ld.%02ld%6d%6d%8d%8.2f\n", printf( "%4d%5d%6d%9d%11ld.%02ld%6d%6d%8d%8.2f\n",
mon_id, mon_id,

View File

@ -46,7 +46,7 @@ commonprep () {
echo "Checking packpack github repo for changes..." echo "Checking packpack github repo for changes..."
git -C packpack pull origin master git -C packpack pull origin master
else else
echo "Cloning pakcpack github repo..." echo "Cloning packpack github repo..."
git clone https://github.com/packpack/packpack.git packpack git clone https://github.com/packpack/packpack.git packpack
fi fi
@ -117,6 +117,11 @@ installtrusty () {
# This sets the naming convention for the deb packages # This sets the naming convention for the deb packages
setdebpkgver () { setdebpkgver () {
# DEBUG
git describe --long --always
git describe --long --always | sed -n 's/^\([0-9\.]*\)-\([0-9]*\)-\([a-z0-9]*\)/\1/p'
git describe --long --always | sed -n 's/^\([0-9\.]*\)-\([0-9]*\)-\([a-z0-9]*\)/\2/p'
# Set VERSION to x.xx.x+x e.g. 1.30.2+15 # Set VERSION to x.xx.x+x e.g. 1.30.2+15
# the last x is number of commits since release # the last x is number of commits since release
# Creates zoneminder packages in the format: zoneminder-{version}-{release} # Creates zoneminder packages in the format: zoneminder-{version}-{release}

View File

@ -1 +1 @@
1.30.4 1.31.0

View File

@ -100,12 +100,12 @@ App::uses('CakeLog', 'Log');
CakeLog::config('debug', array( CakeLog::config('debug', array(
'engine' => 'File', 'engine' => 'File',
'types' => array('notice', 'info', 'debug'), 'types' => array('notice', 'info', 'debug'),
'file' => 'cake_debug', 'file' => '@ZM_LOGDIR@/cake_debug',
)); ));
CakeLog::config('error', array( CakeLog::config('error', array(
'engine' => 'File', 'engine' => 'File',
'types' => array('warning', 'error', 'critical', 'alert', 'emergency'), 'types' => array('warning', 'error', 'critical', 'alert', 'emergency'),
'file' => 'cake_error', 'file' => '@ZM_LOGDIR@/cake_error',
)); ));
CakeLog::config('custom_path', array( CakeLog::config('custom_path', array(
'engine' => 'File', 'engine' => 'File',

View File

@ -29,12 +29,15 @@ class Event {
Error('No row for Event ' . $IdOrRow ); Error('No row for Event ' . $IdOrRow );
} }
} // end function __construct } // end function __construct
public function Storage() { public function Storage() {
return new Storage( isset($this->{'StorageId'}) ? $this->{'StorageId'} : NULL ); return new Storage( isset($this->{'StorageId'}) ? $this->{'StorageId'} : NULL );
} }
public function Monitor() { public function Monitor() {
return new Monitor( isset($this->{'MonitorId'}) ? $this->{'MonitorId'} : NULL ); return new Monitor( isset($this->{'MonitorId'}) ? $this->{'MonitorId'} : NULL );
} }
public function __call( $fn, array $args){ public function __call( $fn, array $args){
if ( array_key_exists( $fn, $this ) ) { if ( array_key_exists( $fn, $this ) ) {
return $this->{$fn}; return $this->{$fn};
@ -54,6 +57,7 @@ class Event {
$Storage = $this->Storage(); $Storage = $this->Storage();
return $Storage->Path().'/'.$this->Relative_Path(); return $Storage->Path().'/'.$this->Relative_Path();
} }
public function Relative_Path() { public function Relative_Path() {
$event_path = ''; $event_path = '';
@ -197,16 +201,22 @@ class Event {
return( $thumbData ); return( $thumbData );
} // end function createListThumbnail } // end function createListThumbnail
// frame is an array representing the db row for a frame.
function getImageSrc( $frame, $scale=SCALE_BASE, $captureOnly=false, $overwrite=false ) { function getImageSrc( $frame, $scale=SCALE_BASE, $captureOnly=false, $overwrite=false ) {
$Storage = new Storage( isset($this->{'StorageId'}) ? $this->{'StorageId'} : NULL ); $Storage = new Storage( isset($this->{'StorageId'}) ? $this->{'StorageId'} : NULL );
$Event = $this; $Event = $this;
$eventPath = $Event->Path(); $eventPath = $Event->Path();
if ( !is_array($frame) ) if ( $frame and ! is_array($frame) ) {
# Must be an Id
Debug("Assuming that $frame is an Id");
$frame = array( 'FrameId'=>$frame, 'Type'=>'' ); $frame = array( 'FrameId'=>$frame, 'Type'=>'' );
}
if ( file_exists( $eventPath.'/snapshot.jpg' ) ) { if ( ( ! $frame ) and file_exists( $eventPath.'/snapshot.jpg' ) ) {
$captImage = "snapshot.jpg"; # No frame specified, so look for a snapshot to use
$captImage = 'snapshot.jpg';
Debug("Frame not specified, using snapshot");
} else { } else {
$captImage = sprintf( '%0'.ZM_EVENT_IMAGE_DIGITS.'d-capture.jpg', $frame['FrameId'] ); $captImage = sprintf( '%0'.ZM_EVENT_IMAGE_DIGITS.'d-capture.jpg', $frame['FrameId'] );
if ( ! file_exists( $eventPath.'/'.$captImage ) ) { if ( ! file_exists( $eventPath.'/'.$captImage ) ) {
@ -275,8 +285,7 @@ class Event {
} }
$thumbFile = $thumbPath; $thumbFile = $thumbPath;
if ( $overwrite || !file_exists( $thumbFile ) || !filesize( $thumbFile ) ) if ( $overwrite || ! file_exists( $thumbFile ) || ! filesize( $thumbFile ) ) {
{
// Get new dimensions // Get new dimensions
list( $imageWidth, $imageHeight ) = getimagesize( $imagePath ); list( $imageWidth, $imageHeight ) = getimagesize( $imagePath );
$thumbWidth = $imageWidth * $fraction; $thumbWidth = $imageWidth * $fraction;
@ -290,7 +299,7 @@ class Event {
if ( !imagejpeg( $thumbImage, $thumbPath ) ) if ( !imagejpeg( $thumbImage, $thumbPath ) )
Error( "Can't create thumbnail '$thumbPath'" ); Error( "Can't create thumbnail '$thumbPath'" );
} }
} } # Create thumbnails
$imageData = array( $imageData = array(
'eventPath' => $eventPath, 'eventPath' => $eventPath,
@ -298,7 +307,7 @@ class Event {
'thumbPath' => $thumbPath, 'thumbPath' => $thumbPath,
'imageFile' => $imagePath, 'imageFile' => $imagePath,
'thumbFile' => $thumbFile, 'thumbFile' => $thumbFile,
'imageClass' => $alarmFrame?"alarm":"normal", 'imageClass' => $alarmFrame?'alarm':'normal',
'isAnalImage' => $isAnalImage, 'isAnalImage' => $isAnalImage,
'hasAnalImage' => $hasAnalImage, 'hasAnalImage' => $hasAnalImage,
); );

View File

@ -27,9 +27,11 @@ class Frame {
Error("No row for Frame " . $IdOrRow ); Error("No row for Frame " . $IdOrRow );
} }
} // end function __construct } // end function __construct
public function Storage() { public function Storage() {
return $this->Event()->Storage(); return $this->Event()->Storage();
} }
public function Event() { public function Event() {
return new Event( $this->{'EventId'} ); return new Event( $this->{'EventId'} );
} }
@ -70,7 +72,9 @@ class Frame {
} }
public function getImageSrc( $show='capture' ) { public function getImageSrc( $show='capture' ) {
return $_SERVER['PHP_SELF'].'?view=image&fid='.$this->{'Id'}.'&show='.$show.'&filename='.$this->Event()->MonitorId().'_'.$this->{'EventId'}.'_'.$this->{'FrameId'}.'.jpg';
return $_SERVER['PHP_SELF'].'?view=image&fid='.$this->{'FrameId'}.'&eid='.$this->{'EventId'}.'&show='.$show;
#return $_SERVER['PHP_SELF'].'?view=image&fid='.$this->{'Id'}.'&show='.$show.'&filename='.$this->Event()->MonitorId().'_'.$this->{'EventId'}.'_'.$this->{'FrameId'}.'.jpg';
} // end function getImageSrc } // end function getImageSrc
public static function find( $parameters = array(), $limit = NULL ) { public static function find( $parameters = array(), $limit = NULL ) {

View File

@ -27,13 +27,14 @@ if ( version_compare( phpversion(), '4.3.0', '<') ) {
} }
} }
# We are requiring these because this file is getting included from the api, which hasn't already included them.
require_once( 'logger.php' ); require_once( 'logger.php' );
require_once( 'database.php' ); require_once( 'database.php' );
function userLogin( $username, $password='', $passwordHashed=false ) { function userLogin( $username, $password='', $passwordHashed=false ) {
global $user, $cookies; global $user, $cookies;
$sql = 'select * from Users where Enabled = 1'; $sql = 'SELECT * FROM Users WHERE Enabled = 1';
$sql_values = NULL; $sql_values = NULL;
if ( ZM_AUTH_TYPE == 'builtin' ) { if ( ZM_AUTH_TYPE == 'builtin' ) {
if ( $passwordHashed ) { if ( $passwordHashed ) {
@ -323,9 +324,9 @@ function outputImageStream( $id, $src, $width, $height, $title='' ) {
function getImageStream( $id, $src, $width, $height, $title='' ) { function getImageStream( $id, $src, $width, $height, $title='' ) {
if ( canStreamIframe() ) { if ( canStreamIframe() ) {
return '<iframe id="'.$id.'" src="'.$src.'" alt="'. validHtmlStr($title) .'" width="'. validInt($width)." height=".validInt($height).'"/>'; return '<iframe id="'.$id.'" src="'.$src.'" alt="'. validHtmlStr($title) .'" '.($width? ' width="'. validInt($width).'"' : '').($height?' height="'.validInt($height).'"' : '' ).'/>';
} else { } else {
return '<img id="'.$id.'" src="'.$src.'" alt="'. validHtmlStr($title) .'" width="'. validInt($width) .'" height="'. validInt( $height ).'"/>'; return '<img id="'.$id.'" src="'.$src.'" alt="'. validHtmlStr($title) .'" style="'.($width? ' width:'. validInt($width) .'px;': '').($height ? ' height:'. validInt( $height ).'px;':'').'"/>';
} }
} }
@ -357,17 +358,18 @@ function outputControlStream( $src, $width, $height, $monitor, $scale, $target )
} }
function outputHelperStream( $id, $src, $width, $height, $title='' ) { function outputHelperStream( $id, $src, $width, $height, $title='' ) {
?> echo getHelperStream( $id, $src, $width, $height, $title );
<applet id="<?php echo $id ?>" code="com.charliemouse.cambozola.Viewer" }
archive="<?php echo ZM_PATH_CAMBOZOLA ?>" function getHelperStream( $id, $src, $width, $height, $title='' ) {
return '<applet id="'.$id.'" code="com.charliemouse.cambozola.Viewer"
archive="'. ZM_PATH_CAMBOZOLA .'"
align="middle" align="middle"
width="<?php echo $width ?>" width="'. $width .'"
height="<?php echo $height ?>" height="'. $height .'"
title="<?php echo $title ?>"> title="'. $title .'">
<param name="accessories" value="none"/> <param name="accessories" value="none"/>
<param name="url" value="<?php echo $src ?>"/> <param name="url" value="'. $src .'"/>
</applet> </applet>';
<?php
} }
function outputImageStill( $id, $src, $width, $height, $title='' ) { function outputImageStill( $id, $src, $width, $height, $title='' ) {
@ -536,11 +538,11 @@ function makePopupLink( $url, $winName, $winSize, $label, $condition=1, $options
$popupParms = "'".$url."', '".$winName."', '".$winSize."'"; $popupParms = "'".$url."', '".$winName."', '".$winSize."'";
$string .= '<a href="'.$url.'" onclick="createPopup( '.$popupParms.' ); return( false );"'.($options?(' '.$options):'').'>'; $string .= '<a href="'.$url.'" onclick="createPopup( '.$popupParms.' ); return( false );"'.($options?(' '.$options):'').'>';
} else {
$string .= '<a>';
} }
$string .= $label; $string .= $label;
if ( $condition ) {
$string .= '</a>'; $string .= '</a>';
}
return( $string ); return( $string );
} }
@ -703,8 +705,12 @@ function getFormChanges( $values, $newValues, $types=false, $columns=false ) {
default : default :
{ {
if ( !isset($values[$key]) || ($values[$key] != $value) ) { if ( !isset($values[$key]) || ($values[$key] != $value) ) {
if ( ! isset($value) || $value == '' ) {
$changes[$key] = "$key = NULL";
} else {
$changes[$key] = $key . ' = '.dbEscape(trim($value)); $changes[$key] = $key . ' = '.dbEscape(trim($value));
} }
}
break; break;
} }
} }
@ -852,15 +858,15 @@ function zmcControl( $monitor, $mode=false ) {
if ( (!defined('ZM_SERVER_ID')) or ( ZM_SERVER_ID==$monitor['ServerId'] ) ) { if ( (!defined('ZM_SERVER_ID')) or ( ZM_SERVER_ID==$monitor['ServerId'] ) ) {
$row = NULL; $row = NULL;
if ( $monitor['Type'] == 'Local' ) { if ( $monitor['Type'] == 'Local' ) {
$row = dbFetchOne( "select count(if(Function!='None',1,NULL)) as ActiveCount from Monitors where Device = ?", NULL, array($monitor['Device']) ); $row = dbFetchOne( "SELECT count(if(Function!='None',1,NULL)) AS ActiveCount FROM Monitors WHERE Device = ?", NULL, array($monitor['Device']) );
$zmcArgs = '-d '.$monitor['Device']; $zmcArgs = '-d '.$monitor['Device'];
} else { } else {
$row = dbFetchOne( "select count(if(Function!='None',1,NULL)) as ActiveCount from Monitors where Id = ?", NULL, array($monitor['Id']) ); $row = dbFetchOne( "SELECT count(if(Function!='None',1,NULL)) AS ActiveCount FROM Monitors WHERE Id = ?", NULL, array($monitor['Id']) );
$zmcArgs = '-m '.$monitor['Id']; $zmcArgs = '-m '.$monitor['Id'];
} }
$activeCount = $row['ActiveCount']; $activeCount = $row['ActiveCount'];
if ( !$activeCount || $mode == 'stop' ) { if ( (!$activeCount) || ($mode == 'stop') ) {
daemonControl( 'stop', 'zmc', $zmcArgs ); daemonControl( 'stop', 'zmc', $zmcArgs );
} else { } else {
if ( $mode == 'restart' ) { if ( $mode == 'restart' ) {
@ -868,6 +874,24 @@ function zmcControl( $monitor, $mode=false ) {
} }
daemonControl( 'start', 'zmc', $zmcArgs ); daemonControl( 'start', 'zmc', $zmcArgs );
} }
} else {
$Server = new Server( $monitor['ServerId'] );
#$url = $Server->Url() . '/zm/api/monitors.json?auth='.generateAuthHash( $_SESSION['remoteAddr'] );
$url = $Server->Url() . '/zm/api/monitors.json?user='.$_SESSION['username'].'&pass='.$_SESSION['passwordHash'];
$data = array('Monitor[Function]' => $monitor['Function'] );
// use key 'http' even if you send the request to https://...
$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($data)
)
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
if ($result === FALSE) { /* Handle error */ }
} }
} }
@ -917,9 +941,9 @@ function daemonStatus( $daemon, $args=false ) {
initDaemonStatus(); initDaemonStatus();
$string = "$daemon"; $string = $daemon;
if ( $args ) if ( $args )
$string .= " $args"; $string .= ' ' . $args;
return( strpos( $daemon_status, "'$string' running" ) !== false ); return( strpos( $daemon_status, "'$string' running" ) !== false );
} }
@ -1066,6 +1090,7 @@ function viewImagePath( $path, $querySep='&amp;' ) {
} }
function createListThumbnail( $event, $overwrite=false ) { function createListThumbnail( $event, $overwrite=false ) {
# Load the frame with the highest score to use as a thumbnail
if ( !($frame = dbFetchOne( "SELECT * FROM Frames WHERE EventId=? AND Score=? ORDER BY FrameId LIMIT 1", NULL, array( $event['Id'], $event['MaxScore'] ) )) ) if ( !($frame = dbFetchOne( "SELECT * FROM Frames WHERE EventId=? AND Score=? ORDER BY FrameId LIMIT 1", NULL, array( $event['Id'], $event['MaxScore'] ) )) )
return( false ); return( false );
@ -1084,6 +1109,10 @@ function createListThumbnail( $event, $overwrite=false ) {
} }
$imageData = getImageSrc( $event, $frame, $scale, false, $overwrite ); $imageData = getImageSrc( $event, $frame, $scale, false, $overwrite );
if ( ! $imageData ) {
return ( false );
}
$thumbData = $frame; $thumbData = $frame;
$thumbData['Path'] = $imageData['thumbPath']; $thumbData['Path'] = $imageData['thumbPath'];
$thumbData['Width'] = (int)$thumbWidth; $thumbData['Width'] = (int)$thumbWidth;
@ -1212,17 +1241,17 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&amp;' ) {
if ( isset($filter['terms']) && count($filter['terms']) ) { if ( isset($filter['terms']) && count($filter['terms']) ) {
for ( $i = 0; $i < count($filter['terms']); $i++ ) { for ( $i = 0; $i < count($filter['terms']); $i++ ) {
if ( isset($filter['terms'][$i]['cnj']) ) { if ( isset($filter['terms'][$i]['cnj']) ) {
$filter['query'] .= $querySep."filter[terms][$i][cnj]=".urlencode($filter['terms'][$i]['cnj']); $filter['query'] .= $querySep.urlencode("filter[terms][$i][cnj]").'='.urlencode($filter['terms'][$i]['cnj']);
$filter['sql'] .= " ".$filter['terms'][$i]['cnj']." "; $filter['sql'] .= ' '.$filter['terms'][$i]['cnj'].' ';
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[terms][$i][cnj]\" value=\"".htmlspecialchars($filter['terms'][$i]['cnj'])."\"/>\n"; $filter['fields'] .= "<input type=\"hidden\" name=\"filter[terms][$i][cnj]\" value=\"".htmlspecialchars($filter['terms'][$i]['cnj'])."\"/>\n";
} }
if ( isset($filter['terms'][$i]['obr']) ) { if ( isset($filter['terms'][$i]['obr']) ) {
$filter['query'] .= $querySep."filter[terms][$i][obr]=".urlencode($filter['terms'][$i]['obr']); $filter['query'] .= $querySep.urlencode("filter[terms][$i][obr]").'='.urlencode($filter['terms'][$i]['obr']);
$filter['sql'] .= " ".str_repeat( "(", $filter['terms'][$i]['obr'] )." "; $filter['sql'] .= ' '.str_repeat( '(', $filter['terms'][$i]['obr'] ).' ';
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[terms][$i][obr]\" value=\"".htmlspecialchars($filter['terms'][$i]['obr'])."\"/>\n"; $filter['fields'] .= "<input type=\"hidden\" name=\"filter[terms][$i][obr]\" value=\"".htmlspecialchars($filter['terms'][$i]['obr'])."\"/>\n";
} }
if ( isset($filter['terms'][$i]['attr']) ) { if ( isset($filter['terms'][$i]['attr']) ) {
$filter['query'] .= $querySep."filter[terms][$i][attr]=".urlencode($filter['terms'][$i]['attr']); $filter['query'] .= $querySep.urlencode("filter[terms][$i][attr]").'='.urlencode($filter['terms'][$i]['attr']);
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[terms][$i][attr]\" value=\"".htmlspecialchars($filter['terms'][$i]['attr'])."\"/>\n"; $filter['fields'] .= "<input type=\"hidden\" name=\"filter[terms][$i][attr]\" value=\"".htmlspecialchars($filter['terms'][$i]['attr'])."\"/>\n";
switch ( $filter['terms'][$i]['attr'] ) { switch ( $filter['terms'][$i]['attr'] ) {
case 'MonitorName': case 'MonitorName':
@ -1306,7 +1335,7 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&amp;' ) {
case '>' : case '>' :
case '<' : case '<' :
case '<=' : case '<=' :
$filter['sql'] .= ' '.$filter['terms'][$i]['op']." $value"; $filter['sql'] .= ' '.$filter['terms'][$i]['op'].' '. $value;
break; break;
case '=~' : case '=~' :
$filter['sql'] .= ' regexp '.$value; $filter['sql'] .= ' regexp '.$value;
@ -1315,20 +1344,20 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&amp;' ) {
$filter['sql'] .= ' not regexp '.$value; $filter['sql'] .= ' not regexp '.$value;
break; break;
case '=[]' : case '=[]' :
$filter['sql'] .= ' in ('.join( ",", $valueList ).')'; $filter['sql'] .= ' in ('.join( ',', $valueList ).')';
break; break;
case '![]' : case '![]' :
$filter['sql'] .= ' not in ('.join( ',', $valueList ).')'; $filter['sql'] .= ' not in ('.join( ',', $valueList ).')';
break; break;
} }
$filter['query'] .= $querySep."filter[terms][$i][op]=".urlencode($filter['terms'][$i]['op']); $filter['query'] .= $querySep.urlencode("filter[terms][$i][op]").'='.urlencode($filter['terms'][$i]['op']);
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[terms][$i][op]\" value=\"".htmlspecialchars($filter['terms'][$i]['op'])."\"/>\n"; $filter['fields'] .= "<input type=\"hidden\" name=\"filter[terms][$i][op]\" value=\"".htmlspecialchars($filter['terms'][$i]['op'])."\"/>\n";
$filter['query'] .= $querySep."filter[terms][$i][val]=".urlencode($filter['terms'][$i]['val']); $filter['query'] .= $querySep.urlencode("filter[terms][$i][val]").'='.urlencode($filter['terms'][$i]['val']);
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[terms][$i][val]\" value=\"".htmlspecialchars($filter['terms'][$i]['val'])."\"/>\n"; $filter['fields'] .= "<input type=\"hidden\" name=\"filter[terms][$i][val]\" value=\"".htmlspecialchars($filter['terms'][$i]['val'])."\"/>\n";
} }
if ( isset($filter['terms'][$i]['cbr']) ) { if ( isset($filter['terms'][$i]['cbr']) ) {
$filter['query'] .= $querySep."filter[terms][$i][cbr]=".urlencode($filter['terms'][$i]['cbr']); $filter['query'] .= $querySep.urlencode("filter[terms][$i][cbr]").'='.urlencode($filter['terms'][$i]['cbr']);
$filter['sql'] .= ' '.str_repeat( ')', $filter['terms'][$i]['cbr'] ).' '; $filter['sql'] .= ' '.str_repeat( ')', $filter['terms'][$i]['cbr'] ).' ';
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[terms][$i][cbr]\" value=\"".htmlspecialchars($filter['terms'][$i]['cbr'])."\"/>\n"; $filter['fields'] .= "<input type=\"hidden\" name=\"filter[terms][$i][cbr]\" value=\"".htmlspecialchars($filter['terms'][$i]['cbr'])."\"/>\n";
} }
@ -1788,6 +1817,33 @@ function coordsToPoints( $coords ) {
return( $points ); return( $points );
} }
function limitPoints( &$points, $min_x, $min_y, $max_x, $max_y ) {
foreach ( $points as &$point ) {
if ( $point['x'] < $min_x ) {
Logger::Debug('Limiting point x'.$point['x'].' to min_x ' . $min_x );
$point['x'] = $min_x;
} else if ( $point['x'] > $max_x ) {
Logger::Debug('Limiting point x'.$point['x'].' to max_x ' . $max_x );
$point['x'] = $max_x;
}
if ( $point['y'] < $min_y ) {
Logger::Debug('Limiting point y'.$point['y'].' to min_y ' . $min_y );
$point['y'] = $min_y;
} else if ( $point['y'] > $max_y ) {
Logger::Debug('Limiting point y'.$point['y'].' to max_y ' . $max_y );
$point['y'] = $max_y;
}
} // end foreach point
} // end function limitPoints( $points, $min_x, $min_y, $max_x, $max_y )
function scalePoints( &$points, $scale ) {
foreach ( $points as &$point ) {
$point['x'] = reScale( $point['x'], $scale );
$point['y'] = reScale( $point['y'], $scale );
}
}
function getLanguages() { function getLanguages() {
$langs = array(); $langs = array();
foreach ( glob('lang/*_*.php') as $file ) { foreach ( glob('lang/*_*.php') as $file ) {
@ -2133,25 +2189,64 @@ function validHtmlStr( $input ) {
return( htmlspecialchars( $input, ENT_QUOTES ) ); return( htmlspecialchars( $input, ENT_QUOTES ) );
} }
function getStreamHTML( $monitor, $scale=100 ) { function getStreamHTML( $monitor, $options = array() ) {
if ( isset($options['scale']) ) {
$options['width'] = reScale( $monitor->Width(), $options['scale'] );
$options['height'] = reScale( $monitor->Height(), $options['scale'] );
}
if ( ! isset($options['mode'] ) ) {
$options['mode'] = 'stream';
}
$options['maxfps'] = ZM_WEB_VIDEO_MAXFPS;
if ( $monitor->StreamReplayBuffer() )
$options['buffer'] = $monitor->StreamReplayBuffer();
//FIXME, the width and height of the image need to be scaled. //FIXME, the width and height of the image need to be scaled.
if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT ) { if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT ) {
$streamSrc = $monitor->getStreamSrc( array( 'mode=mpeg', 'scale='.$scale, 'bitrate='.ZM_WEB_VIDEO_BITRATE, 'maxfps='.ZM_WEB_VIDEO_MAXFPS, 'format='.ZM_MPEG_LIVE_FORMAT ) ); $streamSrc = $monitor->getStreamSrc( array( 'mode'=>'mpeg', 'scale'=>$options['scale'], 'bitrate'=>ZM_WEB_VIDEO_BITRATE, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'format'=>ZM_MPEG_LIVE_FORMAT ) );
return getVideoStream( 'liveStream', $streamSrc, reScale( $monitor->Width(), $scale ), reScale( $monitor->Height(), $scale ), ZM_MPEG_LIVE_FORMAT, $monitor->Name() ); return getVideoStream( 'liveStream'.$monitor->Id(), $streamSrc, $options, ZM_MPEG_LIVE_FORMAT, $monitor->Name() );
} else if ( canStream() ) { } else if ( $options['mode'] == 'stream' and canStream() ) {
$streamSrc = $monitor->getStreamSrc( array( 'mode=jpeg', 'scale='.$scale, 'maxfps='.ZM_WEB_VIDEO_MAXFPS, 'buffer='.$monitor->StreamReplayBuffer() ) ); $options['mode'] = 'jpeg';
if ( canStreamNative() ) { $streamSrc = $monitor->getStreamSrc( $options );
return getImageStream( 'liveStream', $streamSrc, reScale( $monitor->Width(), $scale ), reScale( $monitor->Height(), $scale ), $monitor->Name() );
} elseif ( canStreamApplet() ) { if ( canStreamNative() )
return getHelperStream( 'liveStream', $streamSrc, reScale( $monitor->Width(), $scale ), reScale( $monitor->Height(), $scale ), $monitor->Name() ); return getImageStream( 'liveStream'.$monitor->Id(), $streamSrc,
} ( isset($options['width']) ? $options['width'] : NULL ),
( isset($options['height']) ? $options['height'] : NULL ),
$monitor->Name()
);
elseif ( canStreamApplet() )
return getHelperStream( 'liveStream'.$monitor->Id(), $streamSrc,
( isset($options['width']) ? $options['width'] : NULL ),
( isset($options['height']) ? $options['height'] : NULL ),
$monitor->Name()
);
} else { } else {
$streamSrc = $monitor->getStreamSrc( array( 'mode=single', 'scale='.$scale ) ); $streamSrc = $monitor->getStreamSrc( $options );
Info( 'The system has fallen back to single jpeg mode for streaming. Consider enabling Cambozola or upgrading the client browser.'); if ( $mode == 'stream' ) {
return getImageStill( 'liveStream', $streamSrc, reScale( $monitor->Width(), $scale ), reScale( $monitor->Height(), $scale ), $monitor->Name() ); Info( 'The system has fallen back to single jpeg mode for streaming. Consider enabling Cambozola or upgrading the client browser.' );
}
return getImageStill( 'liveStream'.$monitor->Id(), $streamSrc,
( isset($options['width']) ? $options['width'] : NULL ),
( isset($options['height']) ? $options['height'] : NULL ),
$monitor->Name()
);
} }
} // end function getStreamHTML } // end function getStreamHTML
function getStreamMode( ) {
$streamMode = '';
if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT ) {
$streamMode = 'mpeg';
} elseif ( canStream() ) {
$streamMode = 'jpeg';
} else {
$streamMode = 'single';
Info( 'The system has fallen back to single jpeg mode for streaming. Consider enabling Cambozola or upgrading the client browser.' );
}
} // end function getStreamMode
function folder_size($dir) { function folder_size($dir) {
$size = 0; $size = 0;
foreach (glob(rtrim($dir, '/').'/*', GLOB_NOSORT) as $each) { foreach (glob(rtrim($dir, '/').'/*', GLOB_NOSORT) as $each) {
@ -2160,6 +2255,12 @@ function folder_size($dir) {
return $size; return $size;
} // end function folder_size } // end function folder_size
function human_filesize($bytes, $decimals = 2) {
$sz = 'BKMGTP';
$factor = floor((strlen($bytes) - 1) / 3);
return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . @$sz[$factor];
}
function csrf_startup() { function csrf_startup() {
csrf_conf('rewrite-js', 'includes/csrf/csrf-magic.js'); csrf_conf('rewrite-js', 'includes/csrf/csrf-magic.js');
} }

View File

@ -177,7 +177,7 @@ isset($view) || $view = NULL;
isset($request) || $request = NULL; isset($request) || $request = NULL;
isset($action) || $action = NULL; isset($action) || $action = NULL;
if ( ZM_ENABLE_CSRF_MAGIC ) { if ( ZM_ENABLE_CSRF_MAGIC && $action != 'login' ) {
Logger::Debug("Calling csrf_check with the following values: \$request = \"$request\", \$view = \"$view\", \$action = \"$action\""); Logger::Debug("Calling csrf_check with the following values: \$request = \"$request\", \$view = \"$view\", \$action = \"$action\"");
csrf_check(); csrf_check();
} }

View File

@ -1,7 +1,3 @@
#header {
width: 99%;
}
#layout { #layout {
margin-right: 10px; margin-right: 10px;
} }

View File

@ -1,7 +1,3 @@
#header {
width: 99%;
}
#layout { #layout {
margin-right: 10px; margin-right: 10px;
} }

View File

@ -21,8 +21,7 @@
// Only load new js & css in these views // Only load new js & css in these views
$new_views = array('login'); $new_views = array('login');
function xhtmlHeaders( $file, $title ) function xhtmlHeaders( $file, $title ) {
{
global $css; global $css;
global $skin; global $skin;
$skinCssFile = getSkinFile( 'css/'.$css.'/skin.css' ); $skinCssFile = getSkinFile( 'css/'.$css.'/skin.css' );
@ -56,14 +55,12 @@ function xhtmlHeaders( $file, $title )
<?php } ?> <?php } ?>
<link rel="stylesheet" href="<?php echo $skinCssFile ?>" type="text/css" media="screen"/> <link rel="stylesheet" href="<?php echo $skinCssFile ?>" type="text/css" media="screen"/>
<?php <?php
if ( $viewCssFile ) if ( $viewCssFile ) {
{
?> ?>
<link rel="stylesheet" href="<?php echo $viewCssFile ?>" type="text/css" media="screen"/> <link rel="stylesheet" href="<?php echo $viewCssFile ?>" type="text/css" media="screen"/>
<?php <?php
} }
if ( $viewCssPhpFile ) if ( $viewCssPhpFile ) {
{
?> ?>
<style type="text/css"> <style type="text/css">
/*<![CDATA[*/ /*<![CDATA[*/
@ -88,9 +85,9 @@ function xhtmlHeaders( $file, $title )
<script src="skins/<?php echo $skin ?>/js/video.js"></script> <script src="skins/<?php echo $skin ?>/js/video.js"></script>
<script src="./js/videojs.zoomrotate.js"></script> <script src="./js/videojs.zoomrotate.js"></script>
<script src="skins/<?php echo $skin ?>/js/moment.min.js"></script> <script src="skins/<?php echo $skin ?>/js/moment.min.js"></script>
<?php } <?php
if ( $skinJsPhpFile ) }
{ if ( $skinJsPhpFile ) {
?> ?>
<script type="text/javascript"> <script type="text/javascript">
//<![CDATA[ //<![CDATA[
@ -103,8 +100,7 @@ function xhtmlHeaders( $file, $title )
</script> </script>
<?php <?php
} }
if ( $viewJsPhpFile ) if ( $viewJsPhpFile ) {
{
?> ?>
<script type="text/javascript"> <script type="text/javascript">
//<![CDATA[ //<![CDATA[
@ -123,8 +119,7 @@ function xhtmlHeaders( $file, $title )
<?php } ?> <?php } ?>
<script type="text/javascript" src="<?php echo $skinJsFile ?>"></script> <script type="text/javascript" src="<?php echo $skinJsFile ?>"></script>
<?php <?php
if ( $viewJsFile ) if ( $viewJsFile ) {
{
?> ?>
<script type="text/javascript" src="<?php echo $viewJsFile ?>"></script> <script type="text/javascript" src="<?php echo $viewJsFile ?>"></script>
<?php <?php

View File

@ -23,49 +23,49 @@ $servers = Server::find_all();
$eventCounts = array( $eventCounts = array(
array( array(
"title" => translate('Events'), 'title' => translate('Events'),
"filter" => array( 'filter' => array(
"terms" => array( 'terms' => array(
) )
), ),
), ),
array( array(
"title" => translate('Hour'), 'title' => translate('Hour'),
"filter" => array( 'filter' => array(
"terms" => array( 'terms' => array(
array( "attr" => "DateTime", "op" => ">=", "val" => "-1 hour" ), array( 'attr' => "DateTime", 'op' => ">=", 'val' => "-1 hour" ),
) )
), ),
), ),
array( array(
"title" => translate('Day'), 'title' => translate('Day'),
"filter" => array( 'filter' => array(
"terms" => array( 'terms' => array(
array( "attr" => "DateTime", "op" => ">=", "val" => "-1 day" ), array( 'attr' => "DateTime", 'op' => ">=", 'val' => "-1 day" ),
) )
), ),
), ),
array( array(
"title" => translate('Week'), 'title' => translate('Week'),
"filter" => array( 'filter' => array(
"terms" => array( 'terms' => array(
array( "attr" => "DateTime", "op" => ">=", "val" => "-7 day" ), array( 'attr' => "DateTime", 'op' => ">=", 'val' => "-7 day" ),
) )
), ),
), ),
array( array(
"title" => translate('Month'), 'title' => translate('Month'),
"filter" => array( 'filter' => array(
"terms" => array( 'terms' => array(
array( "attr" => "DateTime", "op" => ">=", "val" => "-1 month" ), array( 'attr' => "DateTime", 'op' => ">=", 'val' => "-1 month" ),
) )
), ),
), ),
array( array(
"title" => translate('Archived'), 'title' => translate('Archived'),
"filter" => array( 'filter' => array(
"terms" => array( 'terms' => array(
array( "attr" => "Archived", "op" => "=", "val" => "1" ), array( 'attr' => "Archived", 'op' => "=", 'val' => "1" ),
) )
), ),
), ),
@ -110,12 +110,12 @@ for ( $i = 0; $i < count($monitors); $i++ ) {
$monitors[$i]['ZoneCount'] = dbFetchOne( 'select count(Id) as ZoneCount from Zones where MonitorId = ?', 'ZoneCount', array($monitors[$i]['Id']) ); $monitors[$i]['ZoneCount'] = dbFetchOne( 'select count(Id) as ZoneCount from Zones where MonitorId = ?', 'ZoneCount', array($monitors[$i]['Id']) );
$counts = array(); $counts = array();
for ( $j = 0; $j < count($eventCounts); $j++ ) { for ( $j = 0; $j < count($eventCounts); $j++ ) {
$filter = addFilterTerm( $eventCounts[$j]['filter'], count($eventCounts[$j]['filter']['terms']), array( "cnj" => "and", "attr" => "MonitorId", "op" => "=", "val" => $monitors[$i]['Id'] ) ); $filter = addFilterTerm( $eventCounts[$j]['filter'], count($eventCounts[$j]['filter']['terms']), array( 'cnj' => 'and', 'attr' => 'MonitorId', 'op' => '=', 'val' => $monitors[$i]['Id'] ) );
parseFilter( $filter ); parseFilter( $filter );
$counts[] = "count(if(1".$filter['sql'].",1,NULL)) as EventCount$j"; $counts[] = 'count(if(1'.$filter['sql'].",1,NULL)) as EventCount$j";
$monitors[$i]['eventCounts'][$j]['filter'] = $filter; $monitors[$i]['eventCounts'][$j]['filter'] = $filter;
} }
$sql = "select ".join($counts,", ")." from Events as E where MonitorId = ?"; $sql = 'select '.join($counts,", ").' from Events as E where MonitorId = ?';
$counts = dbFetchOne( $sql, NULL, array($monitors[$i]['Id']) ); $counts = dbFetchOne( $sql, NULL, array($monitors[$i]['Id']) );
if ( $monitors[$i]['Function'] != 'None' ) { if ( $monitors[$i]['Function'] != 'None' ) {
$cycleCount++; $cycleCount++;
@ -186,7 +186,7 @@ xhtmlHeaders( __FILE__, translate('Console') );
<h3 id="systemStats"><?php echo translate('Load') ?>: <?php echo getLoad() ?> - <?php echo translate('Disk') ?>: <?php echo getDiskPercent() ?>% - <?php echo ZM_PATH_MAP ?>: <?php echo getDiskPercent(ZM_PATH_MAP) ?>%</h3> <h3 id="systemStats"><?php echo translate('Load') ?>: <?php echo getLoad() ?> - <?php echo translate('Disk') ?>: <?php echo getDiskPercent() ?>% - <?php echo ZM_PATH_MAP ?>: <?php echo getDiskPercent(ZM_PATH_MAP) ?>%</h3>
<h2 id="title"><a href="http://www.zoneminder.com" target="ZoneMinder">ZoneMinder</a> <?php echo translate('Console') ?> - <?php echo makePopupLink( '?view=state', 'zmState', 'state', $status, canEdit( 'System' ) ) ?> - <?php echo $run_state ?> <?php echo makePopupLink( '?view=version', 'zmVersion', 'version', '<span class="'.$versionClass.'">v'.ZM_VERSION.'</span>', canEdit( 'System' ) ) ?></h2> <h2 id="title"><a href="http://www.zoneminder.com" target="ZoneMinder">ZoneMinder</a> <?php echo translate('Console') ?> - <?php echo makePopupLink( '?view=state', 'zmState', 'state', $status, canEdit( 'System' ) ) ?> - <?php echo $run_state ?> <?php echo makePopupLink( '?view=version', 'zmVersion', 'version', '<span class="'.$versionClass.'">v'.ZM_VERSION.'</span>', canEdit( 'System' ) ) ?></h2>
<div class="clear"></div> <div class="clear"></div>
<h3 id="development"><center><?php echo ZM_WEB_CONSOLE_BANNER ?></center></h3> <?php if ( ZM_WEB_CONSOLE_BANNER ) { ?><h3 id="development"><?php echo ZM_WEB_CONSOLE_BANNER ?></h3><?php } ?>
<div id="monitorSummary"><?php echo makePopupLink( '?view=groups', 'zmGroups', 'groups', sprintf( $CLANG['MonitorCount'], count($displayMonitors), zmVlang( $VLANG['Monitor'], count($displayMonitors) ) ).($group?' ('.$group['Name'].')':''), canView( 'Groups' ) ); ?></div> <div id="monitorSummary"><?php echo makePopupLink( '?view=groups', 'zmGroups', 'groups', sprintf( $CLANG['MonitorCount'], count($displayMonitors), zmVlang( $VLANG['Monitor'], count($displayMonitors) ) ).($group?' ('.$group['Name'].')':''), canView( 'Groups' ) ); ?></div>
<?php <?php
if ( ZM_OPT_X10 && canView( 'Devices' ) ) { if ( ZM_OPT_X10 && canView( 'Devices' ) ) {
@ -208,21 +208,18 @@ if ( canView( 'Stream' ) && $cycleCount > 1 ) {
<?php echo makePopupLink( '?view=montagereview&amp;group='.$cycleGroup, 'zmMontage'.$cycleGroup, 'montagereview', translate('Montage Review'), $running ) ?> <?php echo makePopupLink( '?view=montagereview&amp;group='.$cycleGroup, 'zmMontage'.$cycleGroup, 'montagereview', translate('Montage Review'), $running ) ?>
</div> </div>
<?php <?php
} else {
?>
<?php
} }
?> ?>
<h3 id="loginBandwidth"><?php <h3 id="loginBandwidth"><?php
if ( ZM_OPT_USE_AUTH ) { if ( ZM_OPT_USE_AUTH ) {
?><?php echo translate('LoggedInAs') ?> <?php echo makePopupLink( '?view=logout', 'zmLogout', 'logout', $user['Username'], (ZM_AUTH_TYPE == "builtin") ) ?>, <?php echo strtolower( translate('ConfiguredFor') ) ?><?php ?><?php echo translate('LoggedInAs') ?> <?php echo makePopupLink( '?view=logout', 'zmLogout', 'logout', $user['Username'], (ZM_AUTH_TYPE == 'builtin') ) ?>, <?php echo strtolower( translate('ConfiguredFor') ) ?><?php
} else { } else {
?><?php echo translate('ConfiguredFor') ?><?php ?><?php echo translate('ConfiguredFor') ?><?php
} }
?>&nbsp;<?php echo makePopupLink( '?view=bandwidth', 'zmBandwidth', 'bandwidth', $bwArray[$_COOKIE['zmBandwidth']], ($user && $user['MaxBandwidth'] != 'low' ) ) ?> <?php echo translate('BandwidthHead') ?></h3> ?>&nbsp;<?php echo makePopupLink( '?view=bandwidth', 'zmBandwidth', 'bandwidth', $bwArray[$_COOKIE['zmBandwidth']], ($user && $user['MaxBandwidth'] != 'low' ) ) ?> <?php echo translate('BandwidthHead') ?></h3>
</div> </div>
<div id="content"> <div id="content">
<table id="consoleTable" cellspacing="0"> <table id="consoleTable">
<thead> <thead>
<tr> <tr>
<?php if ( ZM_WEB_ID_ON_CONSOLE ) { ?> <?php if ( ZM_WEB_ID_ON_CONSOLE ) { ?>
@ -235,43 +232,23 @@ if ( ZM_OPT_USE_AUTH ) {
<?php } ?> <?php } ?>
<th class="colSource"><?php echo translate('Source') ?></th> <th class="colSource"><?php echo translate('Source') ?></th>
<?php <?php
for ( $i = 0; $i < count($eventCounts); $i++ ) { for ( $i = 0; $i < count($eventCounts); $i++ ) {
?> ?>
<th class="colEvents"><?php echo $eventCounts[$i]['title'] ?></th> <th class="colEvents"><?php echo $eventCounts[$i]['title'] ?></th>
<?php <?php
} }
?> ?>
<th class="colZones"><?php echo translate('Zones') ?></th> <th class="colZones"><?php echo translate('Zones') ?></th>
<?php <?php
if ( canEdit('Monitors') ) { if ( canEdit('Monitors') ) {
?> ?>
<th class="colOrder"><?php echo translate('Order') ?></th> <th class="colOrder"><?php echo translate('Order') ?></th>
<?php <?php
} }
?> ?>
<th class="colMark"><?php echo translate('Mark') ?></th> <th class="colMark"><?php echo translate('Mark') ?></th>
</tr> </tr>
</thead> </thead>
<tfoot>
<tr>
<td class="colLeftButtons" colspan="<?php echo $left_columns ?>">
<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 )"/>
<!-- <?php echo makePopupButton( '?view=monitor', 'zmMonitor0', 'monitor', translate('AddNewMonitor'), (canEdit( 'Monitors' ) && !$user['MonitorIds']) ) ?> -->
<?php echo makePopupButton( '?view=filter&amp;filter[terms][0][attr]=DateTime&amp;filter[terms][0][op]=%3c&amp;filter[terms][0][val]=now', 'zmFilter', 'filter', translate('Filters'), canView( 'Events' ) ) ?>
</td>
<?php
for ( $i = 0; $i < count($eventCounts); $i++ ) {
parseFilter( $eventCounts[$i]['filter'] );
?>
<td class="colEvents"><?php echo makePopupLink( '?view='.$eventsView.'&amp;page=1'.$eventCounts[$i]['filter']['query'], $eventsWindow, $eventsView, $eventCounts[$i]['total'], canView( 'Events' ) ) ?></td>
<?php
}
?>
<td class="colZones"><?php echo $zoneCount ?></td>
<td class="colRightButtons" colspan="<?php echo canEdit('Monitors')?2:1 ?>"><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"/></td>
</tr>
</tfoot>
<tbody> <tbody>
<?php <?php
foreach( $displayMonitors as $monitor ) { foreach( $displayMonitors as $monitor ) {
@ -279,22 +256,22 @@ foreach( $displayMonitors as $monitor ) {
<tr> <tr>
<?php <?php
if ( !$monitor['zmc'] ) { if ( !$monitor['zmc'] ) {
$dclass = "errorText"; $dclass = 'errorText';
} else { } else {
// https://github.com/ZoneMinder/ZoneMinder/issues/1082 // https://github.com/ZoneMinder/ZoneMinder/issues/1082
if ( !$monitor['zma'] && $monitor['Function']!='Monitor' ) if ( !$monitor['zma'] && $monitor['Function']!='Monitor' )
$dclass = "warnText"; $dclass = 'warnText';
else else
$dclass = "infoText"; $dclass = 'infoText';
} }
if ( $monitor['Function'] == 'None' ) if ( $monitor['Function'] == 'None' )
$fclass = "errorText"; $fclass = 'errorText';
//elseif ( $monitor['Function'] == 'Monitor' ) //elseif ( $monitor['Function'] == 'Monitor' )
// $fclass = "warnText"; // $fclass = 'warnText';
else else
$fclass = "infoText"; $fclass = 'infoText';
if ( !$monitor['Enabled'] ) if ( !$monitor['Enabled'] )
$fclass .= " disabledText"; $fclass .= ' disabledText';
$scale = max( reScale( SCALE_BASE, $monitor['DefaultScale'], ZM_WEB_DEFAULT_SCALE ), SCALE_BASE ); $scale = max( reScale( SCALE_BASE, $monitor['DefaultScale'], ZM_WEB_DEFAULT_SCALE ), SCALE_BASE );
?> ?>
<?php if ( ZM_WEB_ID_ON_CONSOLE ) { ?> <?php if ( ZM_WEB_ID_ON_CONSOLE ) { ?>
@ -348,6 +325,29 @@ echo $Server->Name();
} }
?> ?>
</tbody> </tbody>
<tfoot>
<tr>
<td class="colLeftButtons" colspan="<?php echo $left_columns ?>">
<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 )"/>
<!-- <?php echo makePopupButton( '?view=monitor', 'zmMonitor0', 'monitor', translate('AddNewMonitor'), (canEdit( 'Monitors' ) && !$user['MonitorIds']) ) ?> -->
<?php echo makePopupButton( '?view=filter&filter[terms][0][attr]=DateTime&filter[terms][0][op]=%3c&filter[terms][0][val]=now', 'zmFilter', 'filter', translate('Filters'), canView( 'Events' ) ) ?>
</td>
<?php
for ( $i = 0; $i < count($eventCounts); $i++ ) {
parseFilter( $eventCounts[$i]['filter'] );
?>
<td class="colEvents"><?php echo makePopupLink( '?view='.$eventsView.'&amp;page=1'.$eventCounts[$i]['filter']['query'], $eventsWindow, $eventsView, $eventCounts[$i]['total'], canView( 'Events' ) ) ?></td>
<?php
}
?>
<td class="colZones"><?php echo $zoneCount ?></td>
<td class="colRightButtons" colspan="<?php echo canEdit('Monitors')?2:1 ?>">
<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"/>
</td>
</tr>
</tfoot>
</table> </table>
</div> </div>
</form> </form>

View File

@ -18,26 +18,23 @@
// 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( 'Control' ) ) if ( !canView( 'Control' ) ) {
{ $view = 'error';
$view = "error";
return; return;
} }
$groupSql = ""; $groupSql = '';
if ( !empty($_REQUEST['group']) ) { if ( !empty($_REQUEST['group']) ) {
$row = dbFetchOne( 'SELECT * FROM Groups WHERE Id = ?', NULL, array($_REQUEST['group']) ); $row = dbFetchOne( 'SELECT * FROM Groups WHERE Id = ?', NULL, array($_REQUEST['group']) );
$groupSql = " and find_in_set( Id, '".$row['MonitorIds']."' )"; $groupSql = " and find_in_set( Id, '".$row['MonitorIds']."' )";
} }
$mid = validInt($_REQUEST['mid']); $mid = !empty($_REQUEST['mid']) ? validInt($_REQUEST['mid']) : 0;
$sql = "SELECT * FROM Monitors WHERE Function != 'None' AND Controllable = 1$groupSql ORDER BY Sequence"; $sql = "SELECT * FROM Monitors WHERE Function != 'None' AND Controllable = 1$groupSql ORDER BY Sequence";
$mids = array(); $mids = array();
foreach( dbFetchAll( $sql ) as $row ) foreach( dbFetchAll( $sql ) as $row ) {
{ if ( !visibleMonitor( $row['Id'] ) ) {
if ( !visibleMonitor( $row['Id'] ) )
{
continue; continue;
} }
if ( empty($mid) ) if ( empty($mid) )
@ -70,7 +67,7 @@ xhtmlHeaders(__FILE__, translate('Control') );
</div> </div>
<div id="content"> <div id="content">
<div id="ptzControls" class="ptzControls"> <div id="ptzControls" class="ptzControls">
<?php echo ptzControls( $monitor ) ?> <?php echo ptzControls( $monitor ) ?>
</div> </div>
</div> </div>
</div> </div>

View File

@ -18,28 +18,23 @@
// 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( 'Stream' ) ) if ( !canView( 'Stream' ) ) {
{ $view = 'error';
$view = "error";
return; return;
} }
if ( empty($_REQUEST['mode']) ) if ( empty($_REQUEST['mode']) ) {
{
if ( canStream() ) if ( canStream() )
$mode = "stream"; $mode = 'stream';
else else
$mode = "still"; $mode = 'still';
} } else {
else
{
$mode = validHtmlStr($_REQUEST['mode']); $mode = validHtmlStr($_REQUEST['mode']);
} }
$group = ''; $group = '';
$groupSql = ''; $groupSql = '';
if ( !empty($_REQUEST['group']) ) if ( !empty($_REQUEST['group']) ) {
{
$group = validInt($_REQUEST['group']); $group = validInt($_REQUEST['group']);
$row = dbFetchOne( 'SELECT * FROM Groups WHERE Id = ?', NULL, array($group) ); $row = dbFetchOne( 'SELECT * FROM Groups WHERE Id = ?', NULL, array($group) );
$groupSql = " and find_in_set( Id, '".$row['MonitorIds']."' )"; $groupSql = " and find_in_set( Id, '".$row['MonitorIds']."' )";
@ -48,41 +43,24 @@ if ( !empty($_REQUEST['group']) )
$sql = "SELECT * FROM Monitors WHERE Function != 'None'$groupSql ORDER BY Sequence"; $sql = "SELECT * FROM Monitors WHERE Function != 'None'$groupSql ORDER BY Sequence";
$monitors = array(); $monitors = array();
$monIdx = 0; $monIdx = 0;
foreach( dbFetchAll( $sql ) as $row ) foreach( dbFetchAll( $sql ) as $row ) {
{
if ( !visibleMonitor( $row['Id'] ) ) if ( !visibleMonitor( $row['Id'] ) )
continue; continue;
if ( isset($_REQUEST['mid']) && $row['Id'] == $_REQUEST['mid'] ) if ( isset($_REQUEST['mid']) && $row['Id'] == $_REQUEST['mid'] )
$monIdx = count($monitors); $monIdx = count($monitors);
$row['ScaledWidth'] = reScale( $row['Width'], $row['DefaultScale'], ZM_WEB_DEFAULT_SCALE ); $row['ScaledWidth'] = reScale( $row['Width'], $row['DefaultScale'], ZM_WEB_DEFAULT_SCALE );
$row['ScaledHeight'] = reScale( $row['Height'], $row['DefaultScale'], ZM_WEB_DEFAULT_SCALE ); $row['ScaledHeight'] = reScale( $row['Height'], $row['DefaultScale'], ZM_WEB_DEFAULT_SCALE );
$monitors[] = $row; $monitors[] = new Monitor( $row );
} }
$monitor = $monitors[$monIdx]; $monitor = $monitors[$monIdx];
$nextMid = $monIdx==(count($monitors)-1)?$monitors[0]['Id']:$monitors[$monIdx+1]['Id']; $nextMid = $monIdx==(count($monitors)-1)?$monitors[0]->Id():$monitors[$monIdx+1]->Id();
$montageWidth = $monitor['ScaledWidth']; $montageWidth = $monitor->ScaledWidth();
$montageHeight = $monitor['ScaledHeight']; $montageHeight = $monitor->ScaledHeight();
$widthScale = ($montageWidth*SCALE_BASE)/$monitor['Width']; $widthScale = ($montageWidth*SCALE_BASE)/$monitor->Width();
$heightScale = ($montageHeight*SCALE_BASE)/$monitor['Height']; $heightScale = ($montageHeight*SCALE_BASE)/$monitor->Height();
$scale = (int)(($widthScale<$heightScale)?$widthScale:$heightScale); $scale = (int)(($widthScale<$heightScale)?$widthScale:$heightScale);
if ( false && (ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT) )
{
$streamMode = "mpeg";
$streamSrc = getStreamSrc( array( "mode=".$streamMode, "monitor=".$monitor['Id'], "scale=".$scale, "bitrate=".ZM_WEB_VIDEO_BITRATE, "maxfps=".ZM_WEB_VIDEO_MAXFPS, "format=".ZM_MPEG_LIVE_FORMAT ) );
}
elseif ( $mode == 'stream' && canStream() )
{
$streamMode = "jpeg";
$streamSrc = getStreamSrc( array( "mode=".$streamMode, "monitor=".$monitor['Id'], "scale=".$scale, "maxfps=".ZM_WEB_VIDEO_MAXFPS ) );
}
else
{
$streamMode = "single";
$streamSrc = getStreamSrc( array( "mode=".$streamMode, "monitor=".$monitor['Id'], "scale=".$scale ) );
}
noCacheHeaders(); noCacheHeaders();
$focusWindow = true; $focusWindow = true;
@ -94,33 +72,17 @@ xhtmlHeaders(__FILE__, translate('CycleWatch') );
<div id="header"> <div id="header">
<div id="headerButtons"> <div id="headerButtons">
<?php if ( $mode == "stream" ) { ?> <?php if ( $mode == "stream" ) { ?>
<a href="?view=<?php echo $view ?>&amp;mode=still&amp;group=<?php echo $group ?>&amp;mid=<?php echo $monitor['Id'] ?>"><?php echo translate('Stills') ?></a> <a href="?view=<?php echo $view ?>&amp;mode=still&amp;group=<?php echo $group ?>&amp;mid=<?php echo $monitor->Id() ?>"><?php echo translate('Stills') ?></a>
<?php } else { ?> <?php } else { ?>
<a href="?view=<?php echo $view ?>&amp;mode=stream&amp;group=<?php echo $group ?>&amp;mid=<?php echo $monitor['Id'] ?>"><?php echo translate('Stream') ?></a> <a href="?view=<?php echo $view ?>&amp;mode=stream&amp;group=<?php echo $group ?>&amp;mid=<?php echo $monitor->Id() ?>"><?php echo translate('Stream') ?></a>
<?php } ?> <?php } ?>
<a href="#" onclick="closeWindow(); return( false );"><?php echo translate('Close') ?></a> <a href="#" onclick="closeWindow(); return( false );"><?php echo translate('Close') ?></a>
</div> </div>
<h2><?php echo translate('Cycle') ?> - <?php echo validHtmlStr($monitor['Name']) ?></h2> <h2><?php echo translate('Cycle') ?> - <?php echo validHtmlStr($monitor->Name()) ?></h2>
</div> </div>
<div id="content"> <div id="content">
<div id="imageFeed"> <div id="imageFeed">
<?php <?php echo getStreamHTML( $monitor, array( 'scale'=>$scale, 'mode'=>$mode ) ); ?>
if ( $streamMode == "mpeg" )
{
outputVideoStream( "liveStream", $streamSrc, reScale( $monitor['Width'], $scale ), reScale( $monitor['Height'], $scale ), ZM_MPEG_LIVE_FORMAT, validHtmlStr($monitor['Name']) );
}
elseif ( $streamMode == "jpeg" )
{
if ( canStreamNative() )
outputImageStream( "liveStream", $streamSrc, reScale( $monitor['Width'], $scale ), reScale( $monitor['Height'], $scale ), validHtmlStr($monitor['Name']) );
elseif ( canStreamApplet() )
outputHelperStream( "liveStream", $streamSrc, reScale( $monitor['Width'], $scale ), reScale( $monitor['Height'], $scale ), validHtmlStr($monitor['Name']) );
}
else
{
outputImageStill( "liveStream", $streamSrc, reScale( $monitor['Width'], $scale ), reScale( $monitor['Height'], $scale ), validHtmlStr($monitor['Name']) );
}
?>
</div> </div>
</div> </div>
</div> </div>

View File

@ -18,21 +18,19 @@
// 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' ) || (!empty($_REQUEST['execute']) && !canEdit('Events')) ) if ( !canView( 'Events' ) || (!empty($_REQUEST['execute']) && !canEdit('Events')) ) {
{ $view = 'error';
$view = "error";
return; return;
} }
require_once( 'includes/Event.php' ); require_once( 'includes/Event.php' );
if ( !empty($_REQUEST['execute']) ) if ( !empty($_REQUEST['execute']) ) {
{
executeFilter( $tempFilterName ); executeFilter( $tempFilterName );
} }
$countSql = 'SELECT count(E.Id) AS EventCount FROM Monitors AS M INNER JOIN Events AS E ON (M.Id = E.MonitorId) WHERE'; $countSql = 'SELECT count(E.Id) AS EventCount FROM Monitors AS M INNER JOIN Events AS E ON (M.Id = E.MonitorId) WHERE';
$eventsSql = 'SELECT E.*,M.Name AS MonitorName FROM Monitors AS M INNER JOIN Events AS E on (M.Id = E.MonitorId) WHERE'; $eventsSql = 'SELECT E.*,M.Name AS MonitorName,M.DefaultScale FROM Monitors AS M INNER JOIN Events AS E on (M.Id = E.MonitorId) WHERE';
if ( $user['MonitorIds'] ) { if ( $user['MonitorIds'] ) {
$user_monitor_ids = ' M.Id in ('.$user['MonitorIds'].')'; $user_monitor_ids = ' M.Id in ('.$user['MonitorIds'].')';
$countSql .= $user_monitor_ids; $countSql .= $user_monitor_ids;
@ -46,8 +44,7 @@ parseSort();
parseFilter( $_REQUEST['filter'] ); parseFilter( $_REQUEST['filter'] );
$filterQuery = $_REQUEST['filter']['query']; $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'];
} }
@ -63,31 +60,28 @@ else
$limit = 0; $limit = 0;
$nEvents = dbFetchOne( $countSql, 'EventCount' ); $nEvents = dbFetchOne( $countSql, 'EventCount' );
if ( !empty($limit) && $nEvents > $limit ) if ( !empty($limit) && $nEvents > $limit ) {
{
$nEvents = $limit; $nEvents = $limit;
} }
$pages = (int)ceil($nEvents/ZM_WEB_EVENTS_PER_PAGE); $pages = (int)ceil($nEvents/ZM_WEB_EVENTS_PER_PAGE);
if ( !empty($page) ) { if ( !empty($page) ) {
if ( $page < 0 ) if ( $page < 0 )
$page = 1; $page = 1;
if ( $page > $pages ) else if ( $page > $pages )
$page = $pages; $page = $pages;
} }
if ( !empty($page) ) { if ( !empty($page) ) {
$limitStart = (($page-1)*ZM_WEB_EVENTS_PER_PAGE); $limitStart = (($page-1)*ZM_WEB_EVENTS_PER_PAGE);
if ( empty( $limit ) ) if ( empty( $limit ) ) {
{
$limitAmount = ZM_WEB_EVENTS_PER_PAGE; $limitAmount = ZM_WEB_EVENTS_PER_PAGE;
} } else {
else
{
$limitLeft = $limit - $limitStart; $limitLeft = $limit - $limitStart;
$limitAmount = ($limitLeft>ZM_WEB_EVENTS_PER_PAGE)?ZM_WEB_EVENTS_PER_PAGE:$limitLeft; $limitAmount = ($limitLeft>ZM_WEB_EVENTS_PER_PAGE)?ZM_WEB_EVENTS_PER_PAGE:$limitLeft;
} }
$eventsSql .= " limit $limitStart, $limitAmount"; $eventsSql .= " limit $limitStart, $limitAmount";
} elseif ( !empty( $limit ) ) { } elseif ( !empty( $limit ) ) {
$eventsSql .= " limit 0, ".$limit; $eventsSql .= ' limit 0, '.$limit;
} }
$maxWidth = 0; $maxWidth = 0;
@ -95,11 +89,10 @@ $maxHeight = 0;
$archived = false; $archived = false;
$unarchived = false; $unarchived = false;
$events = array(); $events = array();
foreach ( dbFetchAll( $eventsSql ) as $event_row ) foreach ( dbFetchAll( $eventsSql ) as $event_row ) {
{
$events[] = $event = new Event( $event_row ); $events[] = $event = new Event( $event_row );
# Doesn this code do anything? # Doesn this code do anything?
$scale = max( reScale( SCALE_BASE, $event->DefaultScale(), ZM_WEB_DEFAULT_SCALE ), SCALE_BASE ); $scale = max( reScale( SCALE_BASE, $event->DefaultScale(), ZM_WEB_DEFAULT_SCALE ), SCALE_BASE );
$eventWidth = reScale( $event_row['Width'], $scale ); $eventWidth = reScale( $event_row['Width'], $scale );
$eventHeight = reScale( $event_row['Height'], $scale ); $eventHeight = reScale( $event_row['Height'], $scale );
@ -124,16 +117,12 @@ xhtmlHeaders(__FILE__, translate('Events') );
<div id="header"> <div id="header">
<div id="headerButtons"> <div id="headerButtons">
<?php <?php
if ( $pages > 1 ) if ( $pages > 1 ) {
{ if ( !empty($page) ) {
if ( !empty($page) )
{
?> ?>
<a href="?view=<?php echo $view ?>&amp;page=0<?php echo $filterQuery ?><?php echo $sortQuery ?>&amp;limit=<?php echo $limit ?>"><?php echo translate('ViewAll') ?></a> <a href="?view=<?php echo $view ?>&amp;page=0<?php echo $filterQuery ?><?php echo $sortQuery ?>&amp;limit=<?php echo $limit ?>"><?php echo translate('ViewAll') ?></a>
<?php <?php
} } else {
else
{
?> ?>
<a href="?view=<?php echo $view ?>&amp;page=1<?php echo $filterQuery ?><?php echo $sortQuery ?>&amp;limit=<?php echo $limit ?>"><?php echo translate('ViewPaged') ?></a> <a href="?view=<?php echo $view ?>&amp;page=1<?php echo $filterQuery ?><?php echo $sortQuery ?>&amp;limit=<?php echo $limit ?>"><?php echo translate('ViewPaged') ?></a>
<?php <?php
@ -154,8 +143,7 @@ if ( $pages > 1 )
<input type="hidden" name="sort_asc" value="<?php echo validHtmlStr($_REQUEST['sort_asc']) ?>"/> <input type="hidden" name="sort_asc" value="<?php echo validHtmlStr($_REQUEST['sort_asc']) ?>"/>
<input type="hidden" name="limit" value="<?php echo $limit ?>"/> <input type="hidden" name="limit" value="<?php echo $limit ?>"/>
<?php <?php
if ( $pagination ) if ( $pagination ) {
{
?> ?>
<h3 class="pagination"><?php echo $pagination ?></h3> <h3 class="pagination"><?php echo $pagination ?></h3>
<?php <?php
@ -170,10 +158,8 @@ if ( $pagination )
<tbody> <tbody>
<?php <?php
$count = 0; $count = 0;
foreach ( $events as $event ) foreach ( $events as $event ) {
{ if ( ($count++%ZM_WEB_EVENTS_PER_PAGE) == 0 ) {
if ( ($count++%ZM_WEB_EVENTS_PER_PAGE) == 0 )
{
?> ?>
<tr> <tr>
<th class="colId"><a href="<?php echo sortHeader( 'Id' ) ?>"><?php echo translate('Id') ?><?php echo sortTag( 'Id' ) ?></a></th> <th class="colId"><a href="<?php echo sortHeader( 'Id' ) ?>"><?php echo translate('Id') ?><?php echo sortTag( 'Id' ) ?></a></th>
@ -187,12 +173,12 @@ foreach ( $events as $event )
<th class="colTotScore"><a href="<?php echo sortHeader( 'TotScore' ) ?>"><?php echo translate('TotalBrScore') ?><?php echo sortTag( 'TotScore' ) ?></a></th> <th class="colTotScore"><a href="<?php echo sortHeader( 'TotScore' ) ?>"><?php echo translate('TotalBrScore') ?><?php echo sortTag( 'TotScore' ) ?></a></th>
<th class="colAvgScore"><a href="<?php echo sortHeader( 'AvgScore' ) ?>"><?php echo translate('AvgBrScore') ?><?php echo sortTag( 'AvgScore' ) ?></a></th> <th class="colAvgScore"><a href="<?php echo sortHeader( 'AvgScore' ) ?>"><?php echo translate('AvgBrScore') ?><?php echo sortTag( 'AvgScore' ) ?></a></th>
<th class="colMaxScore"><a href="<?php echo sortHeader( 'MaxScore' ) ?>"><?php echo translate('MaxBrScore') ?><?php echo sortTag( 'MaxScore' ) ?></a></th> <th class="colMaxScore"><a href="<?php echo sortHeader( 'MaxScore' ) ?>"><?php echo translate('MaxBrScore') ?><?php echo sortTag( 'MaxScore' ) ?></a></th>
<?php if ( ZM_WEB_EVENT_DISK_SPACE ) { ?> <?php
if ( ZM_WEB_EVENT_DISK_SPACE ) { ?>
<th class="colDiskSpace"><a href="<?php echo sortHeader( 'DiskSpace' ) ?>"><?php echo translate('DiskSpace') ?><?php echo sortTag( 'DiskSpace' ) ?></a></th> <th class="colDiskSpace"><a href="<?php echo sortHeader( 'DiskSpace' ) ?>"><?php echo translate('DiskSpace') ?><?php echo sortTag( 'DiskSpace' ) ?></a></th>
<?php <?php
} }
if ( ZM_WEB_LIST_THUMBS ) if ( ZM_WEB_LIST_THUMBS ) {
{
?> ?>
<th class="colThumbnail"><?php echo translate('Thumbnail') ?></th> <th class="colThumbnail"><?php echo translate('Thumbnail') ?></th>
<?php <?php
@ -216,25 +202,37 @@ foreach ( $events as $event )
<td class="colTotScore"><?php echo $event->TotScore() ?></td> <td class="colTotScore"><?php echo $event->TotScore() ?></td>
<td class="colAvgScore"><?php echo $event->AvgScore() ?></td> <td class="colAvgScore"><?php echo $event->AvgScore() ?></td>
<td class="colMaxScore"><?php echo makePopupLink( '?view=frame&amp;eid='.$event->Id().'&amp;fid=0', 'zmImage', array( 'image', reScale( $event->Width(), $scale ), reScale( $event->Height(), $scale ) ), $event->MaxScore() ) ?></td> <td class="colMaxScore"><?php echo makePopupLink( '?view=frame&amp;eid='.$event->Id().'&amp;fid=0', 'zmImage', array( 'image', reScale( $event->Width(), $scale ), reScale( $event->Height(), $scale ) ), $event->MaxScore() ) ?></td>
<?php if ( ZM_WEB_EVENT_DISK_SPACE ) { ?>
<td class="colDiskSpace"><?php echo $event->DiskSpace() ?></td>
<?php <?php
} if ( ZM_WEB_EVENT_DISK_SPACE ) {
if ( ZM_WEB_LIST_THUMBS )
{
if ( $thumbData = $event->createListThumbnail() )
{
?> ?>
<td class="colThumbnail"><?php echo makePopupLink( '?view=frame&amp;eid='.$event->Id().'&amp;fid='.$thumbData['FrameId'], 'zmImage', array( 'image', reScale( $event->Width(), $scale ), reScale( $event->Height(), $scale ) ), '<img src="?view=image&amp;eid='.$event->Id().'&amp;fid='.$thumbData['FrameId'].'&amp;width='.$thumbData['Width'].'&amp;height='.$thumbData['Height'].'" width="'.$thumbData['Width'].'" height="'.$thumbData['Height'].'" alt="'.$thumbData['FrameId'].'/'.$event->MaxScore().'"/>' ) ?></td> <td class="colDiskSpace"><?php echo human_filesize( $event->DiskSpace() ) ?></td>
<?php <?php
} }
else if ( ZM_WEB_LIST_THUMBS ) {
{ if ( $thumbData = $event->createListThumbnail() ) {
?>
<td class="colThumbnail">
<?php
$imgSrc = '?view=image&amp;eid='.$event->Id().'&amp;fid='.$thumbData['FrameId'].'&amp;width='.$thumbData['Width'].'&amp;height='.$thumbData['Height'];
$streamSrc = getStreamSrc( array( "source=event", "mode=jpeg", "event=".$event->Id(), "scale=".$scale, "maxfps=".ZM_WEB_VIDEO_MAXFPS, "replay=single") );
$imgHtml = '<img id="thumbnail'.$event->id().'" src="'.$imgSrc.'" alt="'. validHtmlStr('Event '.$event->Id()) .'" style="width:'. validInt($thumbData['Width']) .'px;height:'. validInt( $thumbData['Height'] ).'px;" onmouseover="this.src=\''.$streamSrc.'\';" onmouseout="this.src=\''.$imgSrc.'\';"/>';
echo makePopupLink(
'?view=frame&amp;eid='.$event->Id().'&amp;fid='.$thumbData['FrameId'],
'zmImage',
array( 'image', reScale( $event->Width(), $scale ), reScale( $event->Height(), $scale ) ),
$imgHtml
);
?>
</td>
<?php
} else {
?> ?>
<td class="colThumbnail">&nbsp;</td> <td class="colThumbnail">&nbsp;</td>
<?php <?php
} }
} } // end if ZM_WEB_LIST_THUMBS
?> ?>
<td class="colMark"><input type="checkbox" name="markEids[]" value="<?php echo $event->Id() ?>" onclick="configureButton( this, 'markEids' );"<?php if ( !canEdit( 'Events' ) ) { ?> disabled="disabled"<?php } ?>/></td> <td class="colMark"><input type="checkbox" name="markEids[]" value="<?php echo $event->Id() ?>" onclick="configureButton( this, 'markEids' );"<?php if ( !canEdit( 'Events' ) ) { ?> disabled="disabled"<?php } ?>/></td>
</tr> </tr>
@ -244,14 +242,12 @@ foreach ( $events as $event )
</tbody> </tbody>
</table> </table>
<?php <?php
if ( $pagination ) if ( $pagination ) {
{
?> ?>
<h3 class="pagination"><?php echo $pagination ?></h3> <h3 class="pagination"><?php echo $pagination ?></h3>
<?php <?php
} }
if ( true || canEdit( 'Events' ) ) if ( true || canEdit( 'Events' ) ) {
{
?> ?>
<div id="contentButtons"> <div id="contentButtons">
<input type="button" name="viewBtn" value="<?php echo translate('View') ?>" onclick="viewEvents( this, 'markEids' );" disabled="disabled"/> <input type="button" name="viewBtn" value="<?php echo translate('View') ?>" onclick="viewEvents( this, 'markEids' );" disabled="disabled"/>

View File

@ -18,25 +18,22 @@
// 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;
} }
$selectName = "filterName"; $selectName = 'filterName';
$filterNames = array( ''=>translate('ChooseFilter') ); $filterNames = array( ''=>translate('ChooseFilter') );
foreach ( dbFetchAll( "select * from Filters order by Name" ) as $row ) foreach ( dbFetchAll( 'select * from Filters order by Name' ) as $row ) {
{
$filterNames[$row['Name']] = $row['Name']; $filterNames[$row['Name']] = $row['Name'];
if ( $row['Background'] ) if ( $row['Background'] )
$filterNames[$row['Name']] .= "*"; $filterNames[$row['Name']] .= '*';
if ( !empty($_REQUEST['reload']) && isset($_REQUEST['filterName']) && $_REQUEST['filterName'] == $row['Name'] ) if ( !empty($_REQUEST['reload']) && isset($_REQUEST['filterName']) && $_REQUEST['filterName'] == $row['Name'] )
$dbFilter = $row; $dbFilter = $row;
} }
$backgroundStr = ""; $backgroundStr = '';
if ( isset($dbFilter) ) if ( isset($dbFilter) ) {
{
if ( $dbFilter['Background'] ) if ( $dbFilter['Background'] )
$backgroundStr = '['.strtolower(translate('Background')).']'; $backgroundStr = '['.strtolower(translate('Background')).']';
$_REQUEST['filter'] = jsonDecode( $dbFilter['Query'] ); $_REQUEST['filter'] = jsonDecode( $dbFilter['Query'] );
@ -64,13 +61,11 @@ if ( isset( $_REQUEST['reload'] ) and ! $_REQUEST['reload'] ) {
$conjunctionTypes = array( $conjunctionTypes = array(
'and' => translate('ConjAnd'), 'and' => translate('ConjAnd'),
'or' => translate('ConjOr') 'or' => translate('ConjOr')
); );
$obracketTypes = array(); $obracketTypes = array();
$cbracketTypes = array(); $cbracketTypes = array();
if ( isset($_REQUEST['filter']['terms']) ) if ( isset($_REQUEST['filter']['terms']) ) {
{ for ( $i = 0; $i <= count($_REQUEST['filter']['terms'])-2; $i++ ) {
for ( $i = 0; $i <= count($_REQUEST['filter']['terms'])-2; $i++ )
{
$obracketTypes[$i] = str_repeat( "(", $i ); $obracketTypes[$i] = str_repeat( "(", $i );
$cbracketTypes[$i] = str_repeat( ")", $i ); $cbracketTypes[$i] = str_repeat( ")", $i );
} }
@ -98,7 +93,7 @@ $attrTypes = array(
'DiskBlocks' => translate('AttrDiskBlocks'), 'DiskBlocks' => translate('AttrDiskBlocks'),
'SystemLoad' => translate('AttrSystemLoad'), 'SystemLoad' => translate('AttrSystemLoad'),
'ServerId' => translate('AttrServer'), 'ServerId' => translate('AttrServer'),
); );
$opTypes = array( $opTypes = array(
'=' => translate('OpEq'), '=' => translate('OpEq'),
'!=' => translate('OpNe'), '!=' => translate('OpNe'),
@ -110,15 +105,14 @@ $opTypes = array(
'!~' => translate('OpNotMatches'), '!~' => translate('OpNotMatches'),
'=[]' => translate('OpIn'), '=[]' => translate('OpIn'),
'![]' => translate('OpNotIn'), '![]' => translate('OpNotIn'),
); );
$archiveTypes = array( $archiveTypes = array(
'0' => translate('ArchUnarchived'), '0' => translate('ArchUnarchived'),
'1' => translate('ArchArchived') '1' => translate('ArchArchived')
); );
$weekdays = array(); $weekdays = array();
for ( $i = 0; $i < 7; $i++ ) for ( $i = 0; $i < 7; $i++ ) {
{ $weekdays[$i] = strftime( '%A', mktime( 12, 0, 0, 1, $i+1, 2001 ) );
$weekdays[$i] = strftime( "%A", mktime( 12, 0, 0, 1, $i+1, 2001 ) );
} }
$sort_fields = array( $sort_fields = array(
'Id' => translate('AttrId'), 'Id' => translate('AttrId'),
@ -133,13 +127,12 @@ $sort_fields = array(
'TotScore' => translate('AttrTotalScore'), 'TotScore' => translate('AttrTotalScore'),
'AvgScore' => translate('AttrAvgScore'), 'AvgScore' => translate('AttrAvgScore'),
'MaxScore' => translate('AttrMaxScore'), 'MaxScore' => translate('AttrMaxScore'),
); );
$sort_dirns = array( $sort_dirns = array(
'1' => translate('SortAsc'), '1' => translate('SortAsc'),
'0' => translate('SortDesc') '0' => translate('SortDesc')
); );
if ( empty($_REQUEST['sort_field']) ) if ( empty($_REQUEST['sort_field']) ) {
{
$_REQUEST['sort_field'] = ZM_WEB_EVENT_SORT_FIELD; $_REQUEST['sort_field'] = ZM_WEB_EVENT_SORT_FIELD;
$_REQUEST['sort_asc'] = (ZM_WEB_EVENT_SORT_ORDER == "asc"); $_REQUEST['sort_asc'] = (ZM_WEB_EVENT_SORT_ORDER == "asc");
} }
@ -174,19 +167,15 @@ xhtmlHeaders(__FILE__, translate('EventFilter') );
<table id="fieldsTable" class="filterTable" cellspacing="0"> <table id="fieldsTable" class="filterTable" cellspacing="0">
<tbody> <tbody>
<?php <?php
for ( $i = 0; isset($_REQUEST['filter']) && $i < count($_REQUEST['filter']['terms']); $i++ ) for ( $i = 0; isset($_REQUEST['filter']) && $i < count($_REQUEST['filter']['terms']); $i++ ) {
{
?> ?>
<tr> <tr>
<?php <?php
if ( $i == 0 ) if ( $i == 0 ) {
{
?> ?>
<td>&nbsp;</td> <td>&nbsp;</td>
<?php <?php
} } else {
else
{
?> ?>
<td><?php echo buildSelect( "filter[terms][$i][cnj]", $conjunctionTypes ); ?></td> <td><?php echo buildSelect( "filter[terms][$i][cnj]", $conjunctionTypes ); ?></td>
<?php <?php
@ -195,43 +184,41 @@ for ( $i = 0; isset($_REQUEST['filter']) && $i < count($_REQUEST['filter']['term
<td><?php if ( count($_REQUEST['filter']['terms']) > 2 ) { echo buildSelect( "filter[terms][$i][obr]", $obracketTypes ); } else { ?>&nbsp;<?php } ?></td> <td><?php if ( count($_REQUEST['filter']['terms']) > 2 ) { echo buildSelect( "filter[terms][$i][obr]", $obracketTypes ); } else { ?>&nbsp;<?php } ?></td>
<td><?php echo buildSelect( "filter[terms][$i][attr]", $attrTypes, "clearValue( this, $i ); submitToFilter( this, 0 );" ); ?></td> <td><?php echo buildSelect( "filter[terms][$i][attr]", $attrTypes, "clearValue( this, $i ); submitToFilter( this, 0 );" ); ?></td>
<?php <?php
if ( isset($_REQUEST['filter']['terms'][$i]['attr']) ) if ( isset($_REQUEST['filter']['terms'][$i]['attr']) ) {
{ if ( $_REQUEST['filter']['terms'][$i]['attr'] == 'Archived' ) {
if ( $_REQUEST['filter']['terms'][$i]['attr'] == "Archived" )
{
?> ?>
<td><?php echo translate('OpEq') ?><input type="hidden" name="filter[terms][<?php echo $i ?>][op]" value="="/></td> <td><?php echo translate('OpEq') ?><input type="hidden" name="filter[terms][<?php echo $i ?>][op]" value="="/></td>
<td><?php echo buildSelect( "filter[terms][$i][val]", $archiveTypes ); ?></td> <td><?php echo buildSelect( "filter[terms][$i][val]", $archiveTypes ); ?></td>
<?php <?php
} } elseif ( $_REQUEST['filter']['terms'][$i]['attr'] == 'DateTime' ) {
elseif ( $_REQUEST['filter']['terms'][$i]['attr'] == "DateTime" )
{
?> ?>
<td><?php echo buildSelect( "filter[terms][$i][op]", $opTypes ); ?></td> <td><?php echo buildSelect( "filter[terms][$i][op]", $opTypes ); ?></td>
<td><input name="filter[terms][<?php echo $i ?>][val]" id="filter[terms][<?php echo $i ?>][val]" value="<?php echo isset($_REQUEST['filter']['terms'][$i]['val'])?validHtmlStr($_REQUEST['filter']['terms'][$i]['val']):'' ?>"/><?php if ( $hasCal ) { ?><script type="text/javascript">Calendar.setup( { inputField: "filter[terms][<?php echo $i ?>][val]", ifFormat: "%Y-%m-%d %H:%M", showsTime: true, timeFormat: "24", showOthers: true, weekNumbers: false });</script><?php } ?></td> <td>
<input name="filter[terms][<?php echo $i ?>][val]" id="filter[terms][<?php echo $i ?>][val]" value="<?php echo isset($_REQUEST['filter']['terms'][$i]['val'])?validHtmlStr($_REQUEST['filter']['terms'][$i]['val']):'' ?>"/>
<?php if ( $hasCal ) { ?>
<script type="text/javascript">Calendar.setup( { inputField: "filter[terms][<?php echo $i ?>][val]", ifFormat: "%Y-%m-%d %H:%M", showsTime: true, timeFormat: "24", showOthers: true, weekNumbers: false });</script>
<?php } ?>
</td>
<?php <?php
} } elseif ( $_REQUEST['filter']['terms'][$i]['attr'] == 'Date' ) {
elseif ( $_REQUEST['filter']['terms'][$i]['attr'] == "Date" )
{
?> ?>
<td><?php echo buildSelect( "filter[terms][$i][op]", $opTypes ); ?></td> <td><?php echo buildSelect( "filter[terms][$i][op]", $opTypes ); ?></td>
<td><input name="filter[terms][<?php echo $i ?>][val]" id="filter[terms][<?php echo $i ?>][val]" value="<?php echo isset($_REQUEST['filter']['terms'][$i]['val'])?validHtmlStr($_REQUEST['filter']['terms'][$i]['val']):'' ?>"/><?php if ( $hasCal ) { ?><script type="text/javascript">Calendar.setup( { inputField: "filter[terms][<?php echo $i ?>][val]", ifFormat: "%Y-%m-%d", showOthers: true, weekNumbers: false });</script><?php } ?></td> <td>
<input name="filter[terms][<?php echo $i ?>][val]" id="filter[terms][<?php echo $i ?>][val]" value="<?php echo isset($_REQUEST['filter']['terms'][$i]['val'])?validHtmlStr($_REQUEST['filter']['terms'][$i]['val']):'' ?>"/>
<?php if ( $hasCal ) { ?>
<script type="text/javascript">Calendar.setup( { inputField: "filter[terms][<?php echo $i ?>][val]", ifFormat: "%Y-%m-%d", showOthers: true, weekNumbers: false });</script>
<?php } ?>
</td>
<?php <?php
} } elseif ( $_REQUEST['filter']['terms'][$i]['attr'] == 'Weekday' ) {
elseif ( $_REQUEST['filter']['terms'][$i]['attr'] == "Weekday" )
{
?> ?>
<td><?php echo buildSelect( "filter[terms][$i][op]", $opTypes ); ?></td> <td><?php echo buildSelect( "filter[terms][$i][op]", $opTypes ); ?></td>
<td><?php echo buildSelect( "filter[terms][$i][val]", $weekdays ); ?></td> <td><?php echo buildSelect( "filter[terms][$i][val]", $weekdays ); ?></td>
<?php <?php
} } elseif ( false && $_REQUEST['filter']['terms'][$i]['attr'] == 'MonitorName' ) {
elseif ( false && $_REQUEST['filter']['terms'][$i]['attr'] == "MonitorName" )
{
$monitors = array(); $monitors = array();
foreach ( dbFetchAll( "select Id,Name from Monitors order by Sequence asc" ) as $monitor ) foreach ( dbFetchAll( "select Id,Name from Monitors order by Sequence asc" ) as $monitor ) {
{ if ( visibleMonitor( $monitor['Id'] ) ) {
if ( visibleMonitor( $monitor['Id'] ) )
{
$monitors[$monitor['Name']] = $monitor['Name']; $monitors[$monitor['Name']] = $monitor['Name'];
} }
} }
@ -239,29 +226,23 @@ for ( $i = 0; isset($_REQUEST['filter']) && $i < count($_REQUEST['filter']['term
<td><?php echo buildSelect( "filter[terms][$i][op]", $opTypes ); ?></td> <td><?php echo buildSelect( "filter[terms][$i][op]", $opTypes ); ?></td>
<td><?php echo buildSelect( "filter[terms][$i][val]", $monitors ); ?></td> <td><?php echo buildSelect( "filter[terms][$i][val]", $monitors ); ?></td>
<?php <?php
} } elseif ( $_REQUEST['filter']['terms'][$i]['attr'] == 'ServerId' ) {
elseif ( $_REQUEST['filter']['terms'][$i]['attr'] == "ServerId" )
{
$servers = array(); $servers = array();
$servers['ZM_SERVER_ID'] = 'Current Server'; $servers['ZM_SERVER_ID'] = 'Current Server';
foreach ( dbFetchAll( "SELECT Id,Name FROM Servers ORDER BY lower(Name) ASC" ) as $server ) { foreach ( dbFetchAll( 'SELECT Id,Name FROM Servers ORDER BY lower(Name) ASC' ) as $server ) {
$servers[$server['Id']] = $server['Name']; $servers[$server['Id']] = $server['Name'];
} }
?> ?>
<td><?php echo buildSelect( "filter[terms][$i][op]", $opTypes ); ?></td> <td><?php echo buildSelect( "filter[terms][$i][op]", $opTypes ); ?></td>
<td><?php echo buildSelect( "filter[terms][$i][val]", $servers ); ?></td> <td><?php echo buildSelect( "filter[terms][$i][val]", $servers ); ?></td>
<?php <?php
} } else {
else
{
?> ?>
<td><?php echo buildSelect( "filter[terms][$i][op]", $opTypes ); ?></td> <td><?php echo buildSelect( "filter[terms][$i][op]", $opTypes ); ?></td>
<td><input name="filter[terms][<?php echo $i ?>][val]" value="<?php echo $_REQUEST['filter']['terms'][$i]['val'] ?>"/></td> <td><input name="filter[terms][<?php echo $i ?>][val]" value="<?php echo $_REQUEST['filter']['terms'][$i]['val'] ?>"/></td>
<?php <?php
} }
} } else {
else
{
?> ?>
<td><?php echo buildSelect( "filter[terms][$i][op]", $opTypes ); ?></td> <td><?php echo buildSelect( "filter[terms][$i][op]", $opTypes ); ?></td>
<td><input name="filter[terms][<?php echo $i ?>][val]" value="<?php echo isset($_REQUEST['filter']['terms'][$i]['val'])?$_REQUEST['filter']['terms'][$i]['val']:'' ?>"/></td> <td><input name="filter[terms][<?php echo $i ?>][val]" value="<?php echo isset($_REQUEST['filter']['terms'][$i]['val'])?$_REQUEST['filter']['terms'][$i]['val']:'' ?>"/></td>
@ -272,7 +253,7 @@ for ( $i = 0; isset($_REQUEST['filter']) && $i < count($_REQUEST['filter']['term
<td><input type="button" onclick="addTerm( this, <?php echo $i+1 ?> )" value="+"/><?php if ( $_REQUEST['filter']['terms'] > 1 ) { ?><input type="button" onclick="delTerm( this, <?php echo $i ?> )" value="-"/><?php } ?></td> <td><input type="button" onclick="addTerm( this, <?php echo $i+1 ?> )" value="+"/><?php if ( $_REQUEST['filter']['terms'] > 1 ) { ?><input type="button" onclick="delTerm( this, <?php echo $i ?> )" value="-"/><?php } ?></td>
</tr> </tr>
<?php <?php
} } # end foreach filter
?> ?>
</tbody> </tbody>
</table> </table>
@ -346,9 +327,9 @@ if ( ZM_OPT_MESSAGE )
<input type="button" name="executeButton" id="executeButton" value="<?php echo translate('Execute') ?>" onclick="executeFilter( this );"/> <input type="button" name="executeButton" id="executeButton" value="<?php echo translate('Execute') ?>" onclick="executeFilter( this );"/>
<?php if ( canEdit( 'Events' ) ) { ?> <?php if ( canEdit( 'Events' ) ) { ?>
<input type="button" value="<?php echo translate('Save') ?>" onclick="saveFilter( this );"/> <input type="button" value="<?php echo translate('Save') ?>" onclick="saveFilter( this );"/>
<?php } ?> <?php if ( isset($dbFilter) && $dbFilter['Name'] ) { ?>
<?php if ( canEdit( 'Events' ) && isset($dbFilter) && $dbFilter['Name'] ) { ?>
<input type="button" value="<?php echo translate('Delete') ?>" onclick="deleteFilter( this, '<?php echo $dbFilter['Name'] ?>' );"/> <input type="button" value="<?php echo translate('Delete') ?>" onclick="deleteFilter( this, '<?php echo $dbFilter['Name'] ?>' );"/>
<?php } ?>
<?php } ?> <?php } ?>
<input type="button" value="<?php echo translate('Reset') ?>" onclick="submitToFilter( this, 1 );"/> <input type="button" value="<?php echo translate('Reset') ?>" onclick="submitToFilter( this, 1 );"/>
</div> </div>

View File

@ -19,7 +19,7 @@
// //
if ( !canView( 'Events' ) ) { if ( !canView( 'Events' ) ) {
$view = "error"; $view = 'error';
return; return;
} }
@ -60,16 +60,27 @@ if ( isset( $_REQUEST['scale'] ) ) {
$scale = max( reScale( SCALE_BASE, $Monitor->DefaultScale(), ZM_WEB_DEFAULT_SCALE ), SCALE_BASE ); $scale = max( reScale( SCALE_BASE, $Monitor->DefaultScale(), ZM_WEB_DEFAULT_SCALE ), SCALE_BASE );
} }
$imageData = $Event->getImageSrc( $frame, $scale, (isset($_REQUEST['show']) && $_REQUEST['show']=="capt") ); $imageData = $Event->getImageSrc( $frame, $scale, 0 );
if ( ! $imageData ) {
Error("No data found for Event $eid frame $fid");
$imageData = array();
}
$show = 'capt';
if ( isset($_REQUEST['show']) ) {
$show = $_REQUEST['show'];
} else if ( $imageData['hasAnalImage'] ) {
$show = 'anal';
}
$imagePath = $imageData['thumbPath']; $imagePath = $imageData['thumbPath'];
$eventPath = $imageData['eventPath']; $eventPath = $imageData['eventPath'];
$dImagePath = sprintf( "%s/%0".ZM_EVENT_IMAGE_DIGITS."d-diag-d.jpg", $eventPath, $Frame->FrameId() ); $dImagePath = sprintf( '%s/%0'.ZM_EVENT_IMAGE_DIGITS.'d-diag-d.jpg', $eventPath, $Frame->FrameId() );
$rImagePath = sprintf( "%s/%0".ZM_EVENT_IMAGE_DIGITS."d-diag-r.jpg", $eventPath, $Frame->FrameId() ); $rImagePath = sprintf( '%s/%0'.ZM_EVENT_IMAGE_DIGITS.'d-diag-r.jpg', $eventPath, $Frame->FrameId() );
$focusWindow = true; $focusWindow = true;
xhtmlHeaders(__FILE__, translate('Frame')." - ".$Event->Id()." - ".$Frame->FrameId() ); xhtmlHeaders(__FILE__, translate('Frame').' - '.$Event->Id()." - ".$Frame->FrameId() );
?> ?>
<body> <body>
<div id="page"> <div id="page">
@ -88,33 +99,29 @@ xhtmlHeaders(__FILE__, translate('Frame')." - ".$Event->Id()." - ".$Frame->Frame
</div> </div>
<div id="content"> <div id="content">
<p id="image"> <p id="image">
<?php if ( in_array($event['VideoWriter'],array("1","2")) ) { ?>
<img src="?view=image-ffmpeg&eid=<?php echo $event['Id'] ?>&fid=<?php echo $frame['FrameId'] ?>&scale=<?php echo $event['DefaultScale'] ?>" class="<?php echo $imageData['imageClass'] ?>"> <?php if ( $imageData['hasAnalImage'] ) {
<?php } else { echo sprintf('<a href="?view=frame&amp;eid=%d&amp;fid=%d&scale=%d&amp;show=%s">', $Event->Id(), $Frame->FrameId(), $scale, ( $show=='anal'?'capt':'anal' ) );
if ( $imageData['hasAnalImage'] ) { ?> } ?>
<a href="?view=frame&amp;eid=<?php echo $Event->Id() ?>&amp;fid=<?php echo $Frame->FrameId() ?>&amp;scale=<?php echo $scale ?>&amp;show=<?php echo $imageData['isAnalImage']?"capt":"anal" ?>"> <img id="frameImg" src="<?php echo $Frame->getImageSrc($show=='anal'?'analyse':'capture') ?>" width="<?php echo reScale( $Event->Width(), $Event->DefaultScale(), $scale ) ?>" height="<?php echo reScale( $Event->Height(), $Event->DefaultScale(), $scale ) ?>" alt="<?php echo $Frame->EventId()."-".$Frame->FrameId() ?>" class="<?php echo $imageData['imageClass'] ?>"/>
<?php } ?>
<img id="frameImg" src="<?php echo $Frame->getImageSrc($imageData['isAnalImage']?'analyse':'capture') ?>" width="<?php echo reScale( $Event->Width(), $Event->DefaultScale(), $scale ) ?>" height="<?php echo reScale( $Event->Height(), $Event->DefaultScale(), $scale ) ?>" alt="<?php echo $Frame->EventId()."-".$Frame->FrameId() ?>" class="<?php echo $imageData['imageClass'] ?>"/>
<?php if ( $imageData['hasAnalImage'] ) { ?></a><?php } ?> <?php if ( $imageData['hasAnalImage'] ) { ?></a><?php } ?>
<?php } ?>
</p> </p>
<p id="controls"> <p id="controls">
<?php if ( $Frame->FrameId() > 1 ) { ?> <?php if ( $Frame->FrameId() > 1 ) { ?>
<a id="firstLink" href="?view=frame&amp;eid=<?php echo $Event->Id() ?>&amp;fid=<?php echo $firstFid ?>&amp;scale=<?php echo $scale ?>"><?php echo translate('First') ?></a> <a id="firstLink" href="?view=frame&amp;eid=<?php echo $Event->Id() ?>&amp;fid=<?php echo $firstFid ?>&amp;scale=<?php echo $scale ?>&amp;show=<?php echo $show ?>"><?php echo translate('First') ?></a>
<?php } if ( $Frame->FrameId() > 1 ) { ?> <a id="prevLink" href="?view=frame&amp;eid=<?php echo $Event->Id() ?>&amp;fid=<?php echo $prevFid ?>&amp;scale=<?php echo $scale ?>&amp;show=<?php echo $show ?>"><?php echo translate('Prev') ?></a>
<a id="prevLink" href="?view=frame&amp;eid=<?php echo $Event->Id() ?>&amp;fid=<?php echo $prevFid ?>&amp;scale=<?php echo $scale ?>"><?php echo translate('Prev') ?></a>
<?php } if ( $Frame->FrameId() < $maxFid ) { ?> <?php } if ( $Frame->FrameId() < $maxFid ) { ?>
<a id="nextLink" href="?view=frame&amp;eid=<?php echo $Event->Id() ?>&amp;fid=<?php echo $nextFid ?>&amp;scale=<?php echo $scale ?>"><?php echo translate('Next') ?></a> <a id="nextLink" href="?view=frame&amp;eid=<?php echo $Event->Id() ?>&amp;fid=<?php echo $nextFid ?>&amp;scale=<?php echo $scale ?>&amp;show=<?php echo $show ?>"><?php echo translate('Next') ?></a>
<?php } if ( $Frame->FrameId() < $maxFid ) { ?> <a id="lastLink" href="?view=frame&amp;eid=<?php echo $Event->Id() ?>&amp;fid=<?php echo $lastFid ?>&amp;scale=<?php echo $scale ?>&amp;show=<?php echo $show ?>"><?php echo translate('Last') ?></a>
<a id="lastLink" href="?view=frame&amp;eid=<?php echo $Event->Id() ?>&amp;fid=<?php echo $lastFid ?>&amp;scale=<?php echo $scale ?>"><?php echo translate('Last') ?></a>
<?php } ?> <?php } ?>
</p> </p>
<?php if (file_exists ($dImagePath)) { ?> <?php if (file_exists ($dImagePath)) { ?>
<p id="diagImagePath"><?php echo $dImagePath ?></p> <p id="diagImagePath"><?php echo $dImagePath ?></p>
<p id="diagImage"><img src=?"<?php echo viewImagePath( $dImagePath ) ?>" width="<?php echo reScale( $Event->Width(), $Event->DefaultScale(), $scale ) ?>" height="<?php echo reScale( $Event->Height(), $Event->DefaultScale(), $scale ) ?>" class="<?php echo $imageData['imageClass'] ?>"/></p> <p id="diagImage"><img src="<?php echo viewImagePath( $dImagePath ) ?>" width="<?php echo reScale( $Event->Width(), $Monitor->DefaultScale(), $scale ) ?>" height="<?php echo reScale( $Event->Height(), $Monitor->DefaultScale(), $scale ) ?>" class="<?php echo $imageData['imageClass'] ?>"/></p>
<?php } if (file_exists ($rImagePath)) { ?> <?php } if (file_exists ($rImagePath)) { ?>
<p id="refImagePath"><?php echo $rImagePath ?></p> <p id="refImagePath"><?php echo $rImagePath ?></p>
<p id="refImage"><img src="<?php echo viewImagePath( $rImagePath ) ?>" width="<?php echo reScale( $Event->Width(), $Event->DefaultScale(), $scale ) ?>" height="<?php echo reScale( $Event->Height(), $Event->DefaultScale(), $scale ) ?>" class="<?php echo $imageData['imageClass'] ?>"/></p> <p id="refImage"><img src="<?php echo viewImagePath( $rImagePath ) ?>" width="<?php echo reScale( $Event->Width(), $Monitor->DefaultScale(), $scale ) ?>" height="<?php echo reScale( $Event->Height(), $Monitor->DefaultScale(), $scale ) ?>" class="<?php echo $imageData['imageClass'] ?>"/></p>
<?php } ?> <?php } ?>
</div> </div>
</div> </div>

View File

@ -7,13 +7,13 @@ function updateButtons( element ) {
var canExecute = false; var canExecute = false;
if ( form.elements['AutoArchive'].checked ) if ( form.elements['AutoArchive'].checked )
canExecute = true; canExecute = true;
else if ( typeof ZM_OPT_FFMPEG !== "undefined" && form.elements['AutoVideo'].checked ) else if ( form.elements['AutoVideo'] && form.elements['AutoVideo'].checked )
canExecute = true; canExecute = true;
else if ( typeof ZM_OPT_UPLOAD !== "undefined" && form.elements['AutoUpload'].checked ) else if ( form.elements['AutoUpload'] && form.elements['AutoUpload'].checked )
canExecute = true; canExecute = true;
else if ( typeof ZM_OPT_EMAIL !== "undefined" && form.elements['AutoEmail'].checked ) else if ( form.elements['AutoEmail'] && form.elements['AutoEmail'].checked )
canExecute = true; canExecute = true;
else if ( typeof ZM_OPT_MESSAGE !== "undefined" && form.elements['AutoMessage'].checked ) else if ( form.elements['AutoMessage'] && form.elements['AutoMessage'].checked )
canExecute = true; canExecute = true;
else if ( form.elements['AutoExecute'].checked && form.elements['AutoExecuteCmd'].value != '' ) else if ( form.elements['AutoExecute'].checked && form.elements['AutoExecuteCmd'].value != '' )
canExecute = true; canExecute = true;

View File

@ -94,7 +94,7 @@ function previewEvent( eventId, frameId ) {
if ( event['frames'] ) { if ( event['frames'] ) {
if ( event['frames'][frameId] ) { if ( event['frames'][frameId] ) {
showEventDetail( event['frames'][frameId]['html'] ); showEventDetail( event['frames'][frameId]['html'] );
var imagePath = event.frames[frameId].Image.imagePath; var imagePath = '/index.php?view=image&eid='+eventId+'&fid='+frameId;
var videoName = event.DefaultVideo; var videoName = event.DefaultVideo;
loadEventImage( imagePath, eventId, frameId, event.Width, event.Height, event.Frames/event.Length, videoName, event.Length, event.StartTime, monitors[event.MonitorId]); loadEventImage( imagePath, eventId, frameId, event.Width, event.Height, event.Frames/event.Length, videoName, event.Length, event.StartTime, monitors[event.MonitorId]);
return; return;
@ -107,13 +107,13 @@ function previewEvent( eventId, frameId ) {
function loadEventImage( imagePath, eid, fid, width, height, fps, videoName, duration, startTime, Monitor ) { function loadEventImage( imagePath, eid, fid, width, height, fps, videoName, duration, startTime, Monitor ) {
var vid= $('preview'); var vid= $('preview');
var imageSrc = $('imageSrc'); var imageSrc = $('imageSrc');
if(videoName) { if ( videoName && vid ) {
vid.show(); vid.show();
imageSrc.hide(); imageSrc.hide();
var newsource=imagePrefix+imagePath.slice(0,imagePath.lastIndexOf('/'))+"/"+videoName; var newsource=imagePath.slice(0,imagePath.lastIndexOf('/'))+"/"+videoName;
//console.log(newsource); //console.log(newsource);
//console.log(sources[0].src.slice(-newsource.length)); //console.log(sources[0].src.slice(-newsource.length));
if(newsource!=vid.currentSrc.slice(-newsource.length) || vid.readyState==0) { if ( newsource != vid.currentSrc.slice(-newsource.length) || vid.readyState == 0 ) {
//console.log("loading new"); //console.log("loading new");
//it is possible to set a long source list here will that be unworkable? //it is possible to set a long source list here will that be unworkable?
var sources = vid.getElementsByTagName('source'); var sources = vid.getElementsByTagName('source');
@ -126,13 +126,13 @@ function loadEventImage( imagePath, eid, fid, width, height, fps, videoName, dur
addVideoTimingTrack(vid, Monitor.LabelFormat, Monitor.Name, duration, startTime) addVideoTimingTrack(vid, Monitor.LabelFormat, Monitor.Name, duration, startTime)
vid.currentTime = fid/fps; vid.currentTime = fid/fps;
} else { } else {
if(!vid.seeking) if ( ! vid.seeking )
vid.currentTime=fid/fps; vid.currentTime=fid/fps;
} }
} else { } else {
vid.hide(); if ( vid ) vid.hide();
imageSrc.show(); imageSrc.show();
imageSrc.setProperty( 'src', imagePrefix+imagePath ); imageSrc.setProperty( 'src', imagePath );
imageSrc.removeEvent( 'click' ); imageSrc.removeEvent( 'click' );
imageSrc.addEvent( 'click', showEvent.pass( [ eid, fid, width, height ] ) ); imageSrc.addEvent( 'click', showEvent.pass( [ eid, fid, width, height ] ) );
} }

View File

@ -31,7 +31,7 @@ function changeScale() {
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*/
var streamImg = document.getElementById('liveStream'); var streamImg = document.getElementById('liveStream'+monitorId);
if ( streamImg ) { if ( streamImg ) {
streamImg.style.width = newWidth + "px"; streamImg.style.width = newWidth + "px";
streamImg.style.height = newHeight + "px"; streamImg.style.height = newHeight + "px";
@ -146,14 +146,14 @@ function getStreamCmdResponse( respObj, respText ) {
streamCmdSlowRev( false ); streamCmdSlowRev( false );
else else
streamCmdFastRev( false ); streamCmdFastRev( false );
} } // rate
} else { } else {
$('modeValue').set( 'text', "Live" ); $('modeValue').set( 'text', "Live" );
$('rate').addClass( 'hidden' ); $('rate').addClass( 'hidden' );
$('delay').addClass( 'hidden' ); $('delay').addClass( 'hidden' );
$('level').addClass( 'hidden' ); $('level').addClass( 'hidden' );
streamCmdPlay( false ); streamCmdPlay( false );
} } // end if paused or delayed
$('zoomValue').set( 'text', streamStatus.zoom ); $('zoomValue').set( 'text', streamStatus.zoom );
if ( streamStatus.zoom == "1.0" ) if ( streamStatus.zoom == "1.0" )
setButtonState( $('zoomOutBtn'), 'unavail' ); setButtonState( $('zoomOutBtn'), 'unavail' );
@ -538,13 +538,8 @@ function controlCmdImage( x, y ) {
fetchImage.pass( $('imageFeed').getElement('img') ).delay( 1000 ); fetchImage.pass( $('imageFeed').getElement('img') ).delay( 1000 );
} }
var tempImage = null;
function fetchImage( streamImage ) { function fetchImage( streamImage ) {
var now = new Date(); streamImage.src = streamImage.src.replace(/rand=\d+/i,'rand='+Math.floor((Math.random() * 1000000) ));
if ( !tempImage )
tempImage = new Element( 'img' );
tempImage.setProperty( 'src', streamSrc+'&'+now.getTime() );
$(streamImage).setProperty( 'src', tempImage.getProperty( 'src' ) );
} }
function handleClick( event ) { function handleClick( event ) {

View File

@ -52,8 +52,6 @@ var monitorUrl = '<?php echo ( $monitor->Server()->Url() ) ?>';
var scale = <?php echo $scale ?>; var scale = <?php echo $scale ?>;
var streamSrc = "<?php echo preg_replace( '/&amp;/', '&', $streamSrc ) ?>";
var statusRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_STATUS ?>; var statusRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_STATUS ?>;
var eventsRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_EVENTS ?>; var eventsRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_EVENTS ?>;
var imageRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_IMAGE ?>; var imageRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_IMAGE ?>;

File diff suppressed because it is too large Load Diff

View File

@ -18,9 +18,8 @@
// 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( 'Monitors' ) ) if ( !canView( 'Monitors' ) ) {
{ $view = 'error';
$view = "error";
return; return;
} }
@ -34,28 +33,24 @@ $hicolor = '0x00ff00'; // Green
$presets = array(); $presets = array();
$presetNames = array(); $presetNames = array();
$presetNames[0] = translate('ChoosePreset'); $presetNames[0] = translate('ChoosePreset');
$sql = "select *, Units-1 as UnitsIndex, CheckMethod-1 as CheckMethodIndex from ZonePresets order by Id asc"; $sql = 'SELECT *, Units-1 AS UnitsIndex, CheckMethod-1 AS CheckMethodIndex FROM ZonePresets ORDER BY Id ASC';
foreach( dbFetchAll( $sql ) as $preset ) foreach( dbFetchAll( $sql ) as $preset ) {
{
$presetNames[$preset['Id']] = $preset['Name']; $presetNames[$preset['Id']] = $preset['Name'];
$presets[] = $preset; $presets[] = $preset;
} }
$optTypes = array(); $optTypes = array();
foreach ( getEnumValues( 'Zones', 'Type' ) as $optType ) foreach ( getEnumValues( 'Zones', 'Type' ) as $optType ) {
{
$optTypes[$optType] = $optType; $optTypes[$optType] = $optType;
} }
$optUnits = array(); $optUnits = array();
foreach ( getEnumValues( 'Zones', 'Units' ) as $optUnit ) foreach ( getEnumValues( 'Zones', 'Units' ) as $optUnit ) {
{
$optUnits[$optUnit] = $optUnit; $optUnits[$optUnit] = $optUnit;
} }
$optCheckMethods = array(); $optCheckMethods = array();
foreach ( getEnumValues( 'Zones', 'CheckMethod' ) as $optCheckMethod ) foreach ( getEnumValues( 'Zones', 'CheckMethod' ) as $optCheckMethod ) {
{
$optCheckMethods[$optCheckMethod] = $optCheckMethod; $optCheckMethods[$optCheckMethod] = $optCheckMethod;
} }
@ -66,14 +61,10 @@ $maxX = $monitor->Width()-1;
$minY = 0; $minY = 0;
$maxY = $monitor->Height()-1; $maxY = $monitor->Height()-1;
if ( !isset($newZone) ) if ( !isset($newZone) ) {
{ if ( $zid > 0 ) {
if ( $zid > 0 )
{
$zone = dbFetchOne( 'SELECT * FROM Zones WHERE MonitorId = ? AND Id=?', NULL, array( $monitor->Id(), $zid ) ); $zone = dbFetchOne( 'SELECT * FROM Zones WHERE MonitorId = ? AND Id=?', NULL, array( $monitor->Id(), $zid ) );
} } else {
else
{
$zone = array( $zone = array(
'Id' => 0, 'Id' => 0,
'Name' => translate('New'), 'Name' => translate('New'),
@ -104,17 +95,16 @@ if ( !isset($newZone) )
$zone['AreaCoords'] = preg_replace( '/\s+/', ',', $zone['Coords'] ); $zone['AreaCoords'] = preg_replace( '/\s+/', ',', $zone['Coords'] );
$newZone = $zone; $newZone = $zone;
} } # end if new Zone
//if ( !$points ) # Ensure Zone fits within the limits of the Monitor
//{ limitPoints( $newZone['Points'], $minX, $minY, $maxX, $maxY );
//$points = $zone['Points'];
//}
ksort( $newZone['Points'], SORT_NUMERIC ); ksort( $newZone['Points'], SORT_NUMERIC );
$newZone['Coords'] = pointsToCoords( $newZone['Points'] ); $newZone['Coords'] = pointsToCoords( $newZone['Points'] );
$newZone['Area'] = getPolyArea( $newZone['Points'] ); $newZone['Area'] = getPolyArea( $newZone['Points'] );
$newZone['AreaCoords'] = preg_replace( '/\s+/', ',', $newZone['Coords'] );
$selfIntersecting = isSelfIntersecting( $newZone['Points'] ); $selfIntersecting = isSelfIntersecting( $newZone['Points'] );
$focusWindow = true; $focusWindow = true;
@ -122,7 +112,7 @@ $connkey = generateConnKey();
$streamSrc = ''; $streamSrc = '';
$streamMode = ''; $streamMode = '';
# Have to do this here, because the .js.php references somethings figured out when generating the streamHTML # Have to do this here, because the .js.php references somethings figured out when generating the streamHTML
$StreamHTML = getStreamHTML( $monitor, $scale ); $StreamHTML = getStreamHTML( $monitor, array('scale'=>$scale) );
xhtmlHeaders(__FILE__, translate('Zone') ); xhtmlHeaders(__FILE__, translate('Zone') );
?> ?>
@ -162,7 +152,13 @@ xhtmlHeaders(__FILE__, translate('Zone') );
</tr> </tr>
<tr> <tr>
<th scope="row"><?php echo translate('ZoneAlarmColour') ?></th> <th scope="row"><?php echo translate('ZoneAlarmColour') ?></th>
<td colspan="2"><input type="text" name="newAlarmRgbR" value="<?php echo ($newZone['AlarmRGB']>>16)&0xff ?>" size="3" onchange="limitRange( this, 0, 255 )"/>&nbsp;/&nbsp;<input type="text" name="newAlarmRgbG" value="<?php echo ($newZone['AlarmRGB']>>8)&0xff ?>" size="3" onchange="limitRange( this, 0, 255 )"/>&nbsp;/&nbsp;<input type="text" name="newAlarmRgbB" value="<?php echo $newZone['AlarmRGB']&0xff ?>" size="3" onchange="limitRange( this, 0, 255 )"/></td> <td colspan="2">
<input type="text" name="newAlarmRgbR" value="<?php echo ($newZone['AlarmRGB']>>16)&0xff ?>" size="3" onchange="limitRange( this, 0, 255 )"/>
/
<input type="text" name="newAlarmRgbG" value="<?php echo ($newZone['AlarmRGB']>>8)&0xff ?>" size="3" onchange="limitRange( this, 0, 255 )"/>
/
<input type="text" name="newAlarmRgbB" value="<?php echo $newZone['AlarmRGB']&0xff ?>" size="3" onchange="limitRange( this, 0, 255 )"/>
</td>
</tr> </tr>
<tr> <tr>
<th scope="row"><?php echo translate('CheckMethod') ?></th> <th scope="row"><?php echo translate('CheckMethod') ?></th>

View File

@ -18,23 +18,27 @@
// 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( 'Monitors' ) ) if ( !canView( 'Monitors' ) ) {
{ $view = 'error';
$view = "error";
return; return;
} }
$mid = validInt($_REQUEST['mid']); $mid = validInt($_REQUEST['mid']);
$monitor = new Monitor( $mid ); $monitor = new Monitor( $mid );
# Width() and Height() are already rotated
$minX = 0;
$maxX = $monitor->Width()-1;
$minY = 0;
$maxY = $monitor->Height()-1;
$zones = array(); $zones = array();
foreach( dbFetchAll( 'select * from Zones where MonitorId = ? order by Area desc', NULL, array($mid) ) as $row ) foreach( dbFetchAll( 'SELECT * FROM Zones WHERE MonitorId=? ORDER BY Area DESC', NULL, array($mid) ) as $row ) {
{ $row['Points'] = coordsToPoints( $row['Coords'] );
if ( $row['Points'] = coordsToPoints( $row['Coords'] ) )
{ limitPoints( $row['Points'], $minX, $minY, $maxX, $maxY );
$row['Coords'] = pointsToCoords( $row['Points'] );
$row['AreaCoords'] = preg_replace( '/\s+/', ',', $row['Coords'] ); $row['AreaCoords'] = preg_replace( '/\s+/', ',', $row['Coords'] );
$zones[] = $row; $zones[] = $row;
}
} }
$connkey = generateConnKey(); $connkey = generateConnKey();
@ -48,21 +52,14 @@ xhtmlHeaders(__FILE__, translate('Zones') );
<h2><?php echo translate('Zones') ?></h2> <h2><?php echo translate('Zones') ?></h2>
</div> </div>
<div id="content" style="width:<?php echo $monitor->Width() ?>px; height:<?php echo $monitor->Height() ?>px; position:relative; margin: 0 auto;"> <div id="content" style="width:<?php echo $monitor->Width() ?>px; height:<?php echo $monitor->Height() ?>px; position:relative; margin: 0 auto;">
<?php echo getStreamHTML( $monitor ); ?>
<svg class="zones" width="<?php echo $monitor->Width() ?>" height="<?php echo $monitor->Height() ?>" style="position:absolute; top: 0; left: 0; background: none;">
<?php
foreach( array_reverse($zones) as $zone ) {
?>
<polygon points="<?php echo $zone['AreaCoords'] ?>" class="<?php echo $zone['Type']?>" onclick="streamCmdQuit( true ); createPopup( '?view=zone&amp;mid=<?php echo $mid ?>&amp;zid=<?php echo $zone['Id'] ?>', 'zmZone', 'zone', <?php echo $monitor->Width ?>, <?php echo $monitor->Height ?> ); return( false );"/>
<?php
} // end foreach zone
?>
Sorry, your browser does not support inline SVG
</svg>
<form name="contentForm" id="contentForm" method="get" action="<?php echo $_SERVER['PHP_SELF'] ?>"> <form name="contentForm" id="contentForm" method="get" action="<?php echo $_SERVER['PHP_SELF'] ?>">
<input type="hidden" name="view" value="<?php echo $view ?>"/> <input type="hidden" name="view" value="<?php echo $view ?>"/>
<input type="hidden" name="action" value="delete"/> <input type="hidden" name="action" value="delete"/>
<input type="hidden" name="mid" value="<?php echo $mid ?>"/> <input type="hidden" name="mid" value="<?php echo $mid ?>"/>
<div id="contentButtons">
<input type="button" value="<?php echo translate('AddNewZone') ?>" onclick="createPopup( '?view=zone&amp;mid=<?php echo $mid ?>&amp;zid=0', 'zmZone', 'zone', <?php echo $monitor->Width() ?>, <?php echo $monitor->Height() ?> );"<?php if ( !canEdit( 'Monitors' ) ) { ?> disabled="disabled"<?php } ?>/>
<input type="submit" name="deleteBtn" value="<?php echo translate('Delete') ?>" disabled="disabled"/>
</div>
<table id="contentTable" class="major" cellspacing="0"> <table id="contentTable" class="major" cellspacing="0">
<thead> <thead>
<tr> <tr>
@ -88,9 +85,18 @@ foreach( $zones as $zone )
?> ?>
</tbody> </tbody>
</table> </table>
<div id="contentButtons"> <div class="ZonesImage" style="position:relative; clear:both;">
<input type="button" value="<?php echo translate('AddNewZone') ?>" onclick="createPopup( '?view=zone&amp;mid=<?php echo $mid ?>&amp;zid=0', 'zmZone', 'zone', <?php echo $monitor->Width() ?>, <?php echo $monitor->Height() ?> );"<?php if ( !canEdit( 'Monitors' ) ) { ?> disabled="disabled"<?php } ?>/> <?php echo getStreamHTML( $monitor ); ?>
<input type="submit" name="deleteBtn" value="<?php echo translate('Delete') ?>" disabled="disabled"/> <svg class="zones" width="<?php echo $monitor->Width() ?>" height="<?php echo $monitor->Height() ?>" style="position:absolute; top: 0; left: 0; background: none;">
<?php
foreach( array_reverse($zones) as $zone ) {
?>
<polygon points="<?php echo $zone['AreaCoords'] ?>" class="<?php echo $zone['Type']?>" onclick="streamCmdQuit( true ); createPopup( '?view=zone&amp;mid=<?php echo $mid ?>&amp;zid=<?php echo $zone['Id'] ?>', 'zmZone', 'zone', <?php echo $monitor->Width ?>, <?php echo $monitor->Height ?> ); return( false );"/>
<?php
} // end foreach zone
?>
Sorry, your browser does not support inline SVG
</svg>
</div> </div>
</form> </form>
</div> </div>

View File

@ -32,21 +32,16 @@
// If both scale and either width or height are specified, scale is ignored // If both scale and either width or height are specified, scale is ignored
// //
if ( !canView( 'Events' ) ) if ( !canView( 'Events' ) ) {
{ $view = 'error';
$view = "error";
return; return;
} }
require_once('includes/Event.php'); require_once('includes/Event.php');
require_once('includes/Frame.php'); require_once('includes/Frame.php');
header( 'Content-type: image/jpeg' );
// Compatibility for PHP 5.4 // Compatibility for PHP 5.4
if (!function_exists('imagescale')) if (!function_exists('imagescale')) {
{ function imagescale($image, $new_width, $new_height = -1, $mode = 0) {
function imagescale($image, $new_width, $new_height = -1, $mode = 0)
{
$mode; // Not supported $mode; // Not supported
$new_height = ($new_height == -1) ? imagesy($image) : $new_height; $new_height = ($new_height == -1) ? imagesy($image) : $new_height;
@ -58,35 +53,66 @@ if (!function_exists('imagescale'))
} }
$errorText = false; $errorText = false;
if ( empty($_REQUEST['path']) ) $filename = '';
{ $Frame = null;
$Event = null;
$path = null;
if ( empty($_REQUEST['path']) ) {
if ( ! empty($_REQUEST['fid']) ) { if ( ! empty($_REQUEST['fid']) ) {
$show = empty($_REQUEST['show']) ? 'capture' : $_REQUEST['show']; $show = empty($_REQUEST['show']) ? 'capture' : $_REQUEST['show'];
if ( ! empty($_REQUEST['eid'] ) ) { if ( ! empty($_REQUEST['eid'] ) ) {
$Event = new Event( $_REQUEST['eid'] ); $Event = new Event( $_REQUEST['eid'] );
$Frame = Frame::find_one( array( 'EventId' => $_REQUEST['eid'], 'FrameId' => $_REQUEST['fid'] ) ); $Frame = Frame::find_one( array( 'EventId' => $_REQUEST['eid'], 'FrameId' => $_REQUEST['fid'] ) );
if ( ! $Frame ) { if ( ! $Frame ) {
Fatal("No Frame found for event(".$_REQUEST['eid'].") and frame id(".$_REQUEST['fid'].")"); Fatal("No Frame found for event(".$_REQUEST['eid'].") and frame id(".$_REQUEST['fid'].")");
} }
$path = $Event->Path().'/'.sprintf("%'.0".ZM_EVENT_IMAGE_DIGITS.'d',$_REQUEST['fid']).'-'.$show.'.jpg';
} else { } else {
# If we are only specifying fid, then the fid must be the primary key into the frames table. But when the event is specified, then it is the frame # # If we are only specifying fid, then the fid must be the primary key into the frames table. But when the event is specified, then it is the frame #
$Frame = new Frame( $_REQUEST['fid'] ); $Frame = new Frame( $_REQUEST['fid'] );
$Event = new Event( $Frame->EventId() ); $Event = new Event( $Frame->EventId() );
$path = $Event->Path().'/'.sprintf("%'.0".ZM_EVENT_IMAGE_DIGITS.'d',$Frame->FrameId()).'-'.$show.'.jpg'; }
$path = $Event->Path().'/'.sprintf('%0'.ZM_EVENT_IMAGE_DIGITS.'d',$Frame->FrameId()).'-'.$show.'.jpg';
} else {
Fatal("No Frame ID specified");
header("HTTP/1.0 404 Not Found");
return;
}
if ( ! file_exists( $path ) ) {
Logger::Debug( "$path does not exist");
# Generate the frame JPG
if ( $show == 'capture' and $Event->DefaultVideo() ) {
$command ='ffmpeg -ss '. $Frame->Delta() .' -i '.$Event->Path().'/'.$Event->DefaultVideo().' -frames:v 1 '.$path;
#$command ='ffmpeg -ss '. $Frame->Delta() .' -i '.$Event->Path().'/'.$Event->DefaultVideo().' -vf "select=gte(n\\,'.$Frame->FrameId().'),setpts=PTS-STARTPTS" '.$path;
#$command ='ffmpeg -v 0 -i '.$Storage->Path().'/'.$Event->Path().'/'.$Event->DefaultVideo().' -vf "select=gte(n\\,'.$Frame->FrameId().'),setpts=PTS-STARTPTS" '.$path;
Logger::Debug( "Running $command" );
$output = array();
$retval = 0;
exec( $command, $output, $retval );
Logger::Debug("Command: $command, retval: $retval, output: " . implode("\n", $output));
if ( ! file_exists( $path ) ) {
header('HTTP/1.0 404 Not Found');
Fatal("Can't create frame images from video for this event (".$Event->DefaultVideo() );
} }
} else { } else {
$errorText = "No image path"; header('HTTP/1.0 404 Not Found');
Fatal("Can't create frame images from video becuase there is no video file for this event (".$Event->DefaultVideo() );
} }
}
} else { } else {
Warning('Loading images by path is deprecated');
$dir_events = realpath(ZM_DIR_EVENTS); $dir_events = realpath(ZM_DIR_EVENTS);
$path = realpath($dir_events . '/' . $_REQUEST['path']); $path = realpath($dir_events . '/' . $_REQUEST['path']);
$pos = strpos($path, $dir_events); $pos = strpos($path, $dir_events);
if($pos == 0 && $pos !== false) { if ( $pos == 0 && $pos !== false ) {
if ( !empty($user['MonitorIds']) ) { if ( ! empty( $user['MonitorIds'] ) ) {
$imageOk = false; $imageOk = false;
$pathMonId = substr( $path, 0, strspn( $path, "1234567890" ) ); $pathMonId = substr( $path, 0, strspn( $path, '1234567890' ) );
foreach ( preg_split( '/["\'\s]*,["\'\s]*/', $user['MonitorIds'] ) as $monId ) { foreach ( preg_split( '/["\'\s]*,["\'\s]*/', $user['MonitorIds'] ) as $monId ) {
if ( $pathMonId == $monId ) { if ( $pathMonId == $monId ) {
$imageOk = true; $imageOk = true;
@ -94,74 +120,95 @@ if ( empty($_REQUEST['path']) )
} }
} }
if ( !$imageOk ) if ( !$imageOk )
$errorText = "No image permissions"; $errorText = 'No image permissions';
} }
} else { } else {
$errorText = "Invalid image path"; $errorText = 'Invalid image path';
}
if ( ! file_exists( $path ) ) {
header('HTTP/1.0 404 Not Found');
Fatal("Image not found at $path");
} }
} }
$scale=0; $scale=0;
if( !empty($_REQUEST['scale']) ) if( !empty($_REQUEST['scale']) ) {
if (is_numeric($_REQUEST['scale'])) if (is_numeric($_REQUEST['scale'])) {
{
$x = $_REQUEST['scale']; $x = $_REQUEST['scale'];
if($x >= 1 and $x <= 400) if($x >= 1 and $x <= 400)
$scale=$x; $scale=$x;
} }
}
$width=0; $width=0;
if( !empty($_REQUEST['width']) ) if ( !empty($_REQUEST['width']) ) {
if (is_numeric($_REQUEST['width'])) if (is_numeric($_REQUEST['width'])) {
{
$x = $_REQUEST['width']; $x = $_REQUEST['width'];
if($x >= 10 and $x <= 8000) if($x >= 10 and $x <= 8000)
$width=$x; $width=$x;
} }
}
$height=0; $height=0;
if( !empty($_REQUEST['height']) ) if( !empty($_REQUEST['height']) ) {
if (is_numeric($_REQUEST['height'])) if (is_numeric($_REQUEST['height'])) {
{
$x = $_REQUEST['height']; $x = $_REQUEST['height'];
if($x >= 10 and $x <= 8000) if($x >= 10 and $x <= 8000)
$height=$x; $height=$x;
} }
}
header( 'Content-type: image/jpeg' );
if ( $errorText ) # This is so that Save Image As give a useful filename
if ( $Event ) {
$filename = $Event->MonitorId().'_'.$Event->Id().'_'.$Frame->FrameId().'.jpg';
header('Content-Disposition: inline; filename="' . $filename . '"');
}
ob_clean();
flush();
if ( $errorText ) {
Error( $errorText ); Error( $errorText );
else } else {
if( ($scale==0 || $scale==100) && $width==0 && $height==0 ) if ( ( $scale==0 || $scale==100 ) && $width==0 && $height==0 ) {
readfile( $path ); if ( ! readfile( $path ) ) {
else Error("No bytes read from ". $path );
{ }
$i = imagecreatefromjpeg ( $path ); } else {
$oldWidth=imagesx($i); Logger::Debug("Doing a scaled image: scale($scale) width($width) height($height)");
$oldHeight=imagesy($i); $i = 0;
if($width==0 && $height==0) // scale has to be set to get here with both zero if ( ! ( $width && $height ) ) {
{ $i = imagecreatefromjpeg( $path );
$oldWidth = imagesx( $i );
$oldHeight = imagesy( $i );
if ( $width == 0 && $height == 0 ) { // scale has to be set to get here with both zero
$width = $oldWidth * $scale / 100.0; $width = $oldWidth * $scale / 100.0;
$height= $oldHeight * $scale / 100.0; $height= $oldHeight * $scale / 100.0;
} } elseif ( $width == 0 && $height != 0 ) {
elseif ($width==0 && $height!=0)
{
$width = ($height * $oldWidth) / $oldHeight; $width = ($height * $oldWidth) / $oldHeight;
} } elseif ( $width != 0 && $height == 0 ) {
elseif ($width!=0 && $height==0)
{
$height = ($width * $oldHeight) / $oldWidth; $height = ($width * $oldHeight) / $oldWidth;
} }
if($width==$oldWidth && $height==$oldHeight) // See if we really need to scale if ( $width == $oldWidth && $height == $oldHeight) {
{ Warning( 'No change to width despite scaling.' );
imagejpeg($i);
imagedestroy($i);
}
else // we do need to scale
{
$iScale = imagescale($i, $width, $height);
imagejpeg($iScale);
imagedestroy($i);
imagedestroy($iScale);
} }
} }
?>
# Slight optimisation, thumbnails always specify width and height, so we can cache them.
$scaled_path = preg_replace('/\.jpg$/', "-${width}x${height}.jpg", $path );
if ( ! file_exists( $scaled_path ) or ! readfile( $scaled_path ) ) {
Logger::Debug( "Cached scaled image does not exist at $scaled_path or is no good.. Creating it");
ob_start();
if ( ! $i )
$i = imagecreatefromjpeg( $path );
$iScale = imagescale( $i, $width, $height );
imagejpeg( $iScale );
imagedestroy( $i );
imagedestroy( $iScale );
$scaled_jpeg_data = ob_get_contents();
file_put_contents( $scaled_path, $scaled_jpeg_data );
ob_end_clean();
echo $scaled_jpeg_data;
}
}
}