Merge branch 'master' into add_was_alarmed

This commit is contained in:
Isaac Connor 2017-06-09 10:46:01 -04:00
commit f8cb0a5e21
81 changed files with 7804 additions and 7427 deletions

View File

@ -1,6 +1,8 @@
language: cpp
sudo: required
dist: trusty
git:
depth: 9999999
notifications:
irc: chat.freenode.net#zoneminder-dev
branches:
@ -20,6 +22,7 @@ addons:
- git
- curl
- sshfs
- sed
env:
matrix:
- OS=el DIST=6

View File

@ -104,6 +104,7 @@ mark_as_advanced(
ZM_PERL_SEARCH_PATH
ZM_TARGET_DISTRO
ZM_CONFIG_DIR
ZM_CONFIG_SUBDIR
ZM_SYSTEMD)
set(ZM_RUNDIR "/var/run/zm" CACHE PATH
@ -137,6 +138,8 @@ set(ZM_WEB_GROUP "" CACHE STRING
# Advanced
set(ZM_CONFIG_DIR "/${CMAKE_INSTALL_SYSCONFDIR}" CACHE PATH
"Location of ZoneMinder configuration, default system config directory")
set(ZM_CONFIG_SUBDIR "${ZM_CONFIG_DIR}/conf.d" CACHE PATH
"Location of ZoneMinder configuration subfolder, default: ZM_CONFIG_DIR/conf.d")
set(ZM_EXTRA_LIBS "" CACHE STRING
"A list of optional libraries, separated by semicolons, e.g. ssl;theora")
set(ZM_MYSQL_ENGINE "InnoDB" CACHE STRING
@ -171,28 +174,13 @@ set(ZM_SYSTEMD "OFF" CACHE BOOL
"Set to ON to force building ZM with systemd support. default: OFF")
# Reassign some variables if a target distro has been specified
if((ZM_TARGET_DISTRO STREQUAL "fc24") OR (ZM_TARGET_DISTRO STREQUAL "fc25"))
set(ZM_RUNDIR "/var/run/zoneminder")
set(ZM_SOCKDIR "/var/lib/zoneminder/sock")
set(ZM_TMPDIR "/var/lib/zoneminder/temp")
set(ZM_LOGDIR "/var/log/zoneminder")
set(ZM_CONFIG_DIR "/etc/zm")
set(ZM_WEBDIR "/usr/share/zoneminder/www")
set(ZM_CGIDIR "/usr/libexec/zoneminder/cgi-bin")
elseif(ZM_TARGET_DISTRO STREQUAL "el6")
set(ZM_RUNDIR "/var/run/zoneminder")
set(ZM_SOCKDIR "/var/lib/zoneminder/sock")
set(ZM_TMPDIR "/var/lib/zoneminder/temp")
set(ZM_LOGDIR "/var/log/zoneminder")
set(ZM_CONFIG_DIR "/etc/zm")
set(ZM_WEBDIR "/usr/share/zoneminder/www")
set(ZM_CGIDIR "/usr/libexec/zoneminder/cgi-bin")
elseif(ZM_TARGET_DISTRO STREQUAL "el7")
if((ZM_TARGET_DISTRO MATCHES "^el") OR (ZM_TARGET_DISTRO MATCHES "^fc"))
set(ZM_RUNDIR "/var/run/zoneminder")
set(ZM_SOCKDIR "/var/lib/zoneminder/sock")
set(ZM_TMPDIR "/var/lib/zoneminder/temp")
set(ZM_LOGDIR "/var/log/zoneminder")
set(ZM_CONFIG_DIR "/etc/zm")
set(ZM_CONFIG_SUBDIR "/etc/zm/conf.d")
set(ZM_WEBDIR "/usr/share/zoneminder/www")
set(ZM_CGIDIR "/usr/libexec/zoneminder/cgi-bin")
elseif(ZM_TARGET_DISTRO STREQUAL "OS13")
@ -212,10 +200,11 @@ elseif(ZM_TARGET_DISTRO STREQUAL "FreeBSD")
set(ZM_WEB_USER "www")
set(ZM_WEB_GROUP "www")
set(ZM_CONFIG_DIR "/usr/local/etc/zm")
set(ZM_CONFIG_SUBDIR "/usr/local/etc/zm/conf.d")
set(ZM_WEBDIR "/usr/local/share/zoneminder/www")
set(ZM_CGIDIR "/usr/local/libexec/zoneminder/cgi-bin")
set(ZM_PERL_MM_PARMS "INSTALLDIRS=site")
endif((ZM_TARGET_DISTRO STREQUAL "fc24") OR (ZM_TARGET_DISTRO STREQUAL "fc25"))
endif((ZM_TARGET_DISTRO MATCHES "^el") OR (ZM_TARGET_DISTRO MATCHES "^fc"))
# Required for certain checks to work
set(CMAKE_EXTRA_INCLUDE_FILES
@ -791,6 +780,11 @@ else(ZM_PERL_SEARCH_PATH)
set(EXTRA_PERL_LIB "# Include from system perl paths only")
endif(ZM_PERL_SEARCH_PATH)
# If this is an out-of-source build, copy the files we need to the binary directory
if(NOT (CMAKE_BINARY_DIR STREQUAL CMAKE_SOURCE_DIR))
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/conf.d" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/conf.d")
endif(NOT (CMAKE_BINARY_DIR STREQUAL CMAKE_SOURCE_DIR))
# Generate files from the .in files
configure_file(zm.conf.in "${CMAKE_CURRENT_BINARY_DIR}/zm.conf" @ONLY)
configure_file(zoneminder-config.cmake "${CMAKE_CURRENT_BINARY_DIR}/config.h" @ONLY)
@ -814,13 +808,11 @@ if(ZM_ONVIF)
endif(ZM_ONVIF)
# Process distro subdirectories
if((ZM_TARGET_DISTRO STREQUAL "fc24") OR (ZM_TARGET_DISTRO STREQUAL "fc25"))
add_subdirectory(distros/redhat)
elseif((ZM_TARGET_DISTRO STREQUAL "el6") OR (ZM_TARGET_DISTRO STREQUAL "el7"))
if((ZM_TARGET_DISTRO MATCHES "^el") OR (ZM_TARGET_DISTRO MATCHES "^fc"))
add_subdirectory(distros/redhat)
elseif(ZM_TARGET_DISTRO STREQUAL "OS13")
add_subdirectory(distros/opensuse)
endif((ZM_TARGET_DISTRO STREQUAL "fc24") OR (ZM_TARGET_DISTRO STREQUAL "fc25"))
endif((ZM_TARGET_DISTRO MATCHES "^el") OR (ZM_TARGET_DISTRO MATCHES "^fc"))
# Print optional libraries detection status
message(STATUS "Optional libraries found:${optlibsfound}")
@ -837,8 +829,9 @@ else(zmconfgen_result EQUAL 0)
"ZoneMinder configuration generator failed. Exit code: ${zmconfgen_result}")
endif(zmconfgen_result EQUAL 0)
# Install zm.conf
# Install zm.conf and conf.d subfolder
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/zm.conf" DESTINATION "${ZM_CONFIG_DIR}")
install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/conf.d/" DESTINATION "${ZM_CONFIG_SUBDIR}")
# Uninstall target
configure_file(

View File

@ -1,24 +1,75 @@
# ZoneMinder
# ZoneMinder, you need the GIT repository code and submodules (git submodule update --init --recursive)
FROM ubuntu:xenial
MAINTAINER Markos Vakondios <mvakondios@gmail.com>
# Resynchronize the package index files
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y \
libpolkit-gobject-1-dev build-essential libmysqlclient-dev libssl-dev libbz2-dev libpcre3-dev \
libdbi-perl libarchive-zip-perl libdate-manip-perl libdevice-serialport-perl libmime-perl libpcre3 \
libwww-perl libdbd-mysql-perl libsys-mmap-perl yasm cmake libjpeg-turbo8-dev \
libjpeg-turbo8 libtheora-dev libvorbis-dev libvpx-dev libx264-dev libmp4v2-dev libav-tools mysql-client \
apache2 php php-mysql libapache2-mod-php php-cli \
mysql-server libvlc-dev libvlc5 libvlccore-dev libvlccore8 vlc-data libcurl4-openssl-dev \
libavformat-dev libswscale-dev libavutil-dev libavcodec-dev libavfilter-dev \
libavresample-dev libavdevice-dev libpostproc-dev libv4l-dev libtool libnetpbm10-dev \
libmime-lite-perl dh-autoreconf dpatch \
&& apt-get clean
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
apache2 \
build-essential \
cmake \
dh-autoreconf \
dpatch \
libapache2-mod-php \
libarchive-zip-perl \
libavcodec-dev \
libavdevice-dev \
libavfilter-dev \
libavformat-dev \
libavresample-dev \
libav-tools \
libavutil-dev \
libbz2-dev \
libcurl4-openssl-dev \
libdate-manip-perl \
libdbd-mysql-perl \
libdbi-perl \
libdevice-serialport-perl \
libjpeg-turbo8 \
libjpeg-turbo8-dev \
libmime-lite-perl \
libmime-perl \
libmp4v2-dev \
libmysqlclient-dev \
libnetpbm10-dev \
libpcre3 \
libpcre3-dev \
libpolkit-gobject-1-dev \
libpostproc-dev \
libssl-dev \
libswscale-dev \
libsys-mmap-perl \
libtheora-dev \
libtool \
libv4l-dev \
libvlc5 \
libvlccore8 \
libvlccore-dev \
libvlc-dev \
libvorbis-dev \
libvpx-dev \
libwww-perl \
libx264-dev \
mysql-client \
mysql-server \
php \
php-cli \
php-mysql \
vlc-data \
yasm \
&& rm -rf /var/lib/apt/lists/*
# Copy local code into our container
ADD . /ZoneMinder
ADD cmake /ZoneMinder/cmake/
ADD db /ZoneMinder/db/
ADD misc /ZoneMinder/misc/
ADD onvif /ZoneMinder/onvif/
ADD scripts /ZoneMinder/scripts/
ADD src /ZoneMinder/src/
ADD umutils /ZoneMinder/umutils/
ADD web /ZoneMinder/web/
ADD cmakecacheimport.sh CMakeLists.txt version zm.conf.in zmconfgen.pl.in zmlinkcontent.sh.in zoneminder-config.cmake /ZoneMinder/
# Change into the ZoneMinder directory
WORKDIR /ZoneMinder
@ -39,18 +90,20 @@ RUN ./zmlinkcontent.sh
# Adding the start script
ADD utils/docker/start.sh /tmp/start.sh
# give files in /usr/local/share/zoneminder/
# Settings rights for /usr/local/share/zoneminder/
RUN chown -R www-data:www-data /usr/local/share/zoneminder/
# Adding apache virtual hosts file
RUN cp misc/apache.conf /etc/apache2/sites-available/000-default.conf
ADD utils/docker/phpdate.ini /etc/php5/apache2/conf.d/25-phpdate.ini
# Expose http port
EXPOSE 80
# Initial database and apache setup:
RUN "/ZoneMinder/utils/docker/setup.sh"
VOLUME /var/lib/zoneminder/images /var/lib/zoneminder/events /var/lib/mysql /var/log/zm
CMD ["/ZoneMinder/utils/docker/start.sh"]
# To speed up configuration testing, we put it here
ADD utils/docker /ZoneMinder/utils/docker/
CMD /ZoneMinder/utils/docker/setup.sh && /ZoneMinder/utils/docker/start.sh >/var/log/start.log 2>&1 & /bin/bash
# Run example docker run -it -p 1080:80 -e PHP_TIMEZONE='Europe/Paris' -v /disk/zoneminder/events:/var/lib/zoneminder/events -v /disk/zoneminder/images:/var/lib/zoneminder/images -v /disk/zoneminder/mysql:/var/lib/mysql -v /disk/zoneminder/logs:/var/log/zm --name zoneminder zoneminder/zoneminder

View File

@ -55,7 +55,7 @@ further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at [INSERT EMAIL ADDRESS]. All
reported by contacting the project team at abuse@zoneminder.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.

19
conf.d/README Normal file
View File

@ -0,0 +1,19 @@
conf.d/README
Any changes to ZoneMinder's configuration should be made here in this folder,
rather than directly editing the default zm.conf file.
ZoneMinder will process each file in this folder with a ".conf" extension.
Each "Var = Value" pair, in each config file, will be loaded into ZoneMinder's
running configuration, overriding any variables with the same name found in the
default zm.conf file.
After creating a custom config file, don't forget to set the proper file and
owner permission on it. For example, this is typically what you should do after
saving the config file to disk:
sudo chown root:apache *.conf
sudo chmod 640 *.conf
Substitute "apache" with the name of the web server user account on your system.

View File

@ -0,0 +1,7 @@
# Do NOT set ZM_SERVER_HOST if you are not using Multi-Server
# You have been warned
#
# The name specified here must have a corresponding entry
# in the Servers tab under Options
ZM_SERVER_HOST=

View File

@ -2,7 +2,7 @@ Alias /zm /usr/share/zoneminder/www
<IfModule mod_fcgid.c>
<Directory /usr/share/zoneminder/www>
Options +ExecCGI
Options -Indexes +ExecCGI
AllowOverride All
AddHandler fcgid-script .php
FCGIWrapper /usr/bin/php5-cgi
@ -12,7 +12,7 @@ Alias /zm /usr/share/zoneminder/www
</IfModule>
<IfModule mod_php5.c>
<Directory /usr/share/zoneminder/www>
Options Indexes FollowSymLinks
Options -Indexes +FollowSymLinks
<IfModule mod_dir.c>
DirectoryIndex index.php
</IfModule>

View File

@ -22,7 +22,8 @@ override_dh_auto_configure:
-DZM_CGIDIR=/usr/lib/zoneminder/cgi-bin \
-DZM_WEB_USER=www-data \
-DZM_WEB_GROUP=www-data \
-DCMAKE_INSTALL_SYSCONFDIR=etc/zm
-DZM_CONFIG_SUBDIR="/etc/zm/conf.d" \
-DZM_CONFIG_DIR="/etc/zm"
override_dh_auto_install:
dh_auto_install --buildsystem=cmake

View File

@ -1,7 +1,16 @@
What's New
==========
1. The Apache ScriptAlias has been changed from "/cgi-bin/zm/zms" to
1. ZoneMinder now uses a conf.d subfolder to process custom changes to
variables found in zm.conf. Changes to zm.conf will be overwritten
during an upgrade. Instead, create a file with a ".conf" extension under
the conf.d folder and make your changes there.
2. ZoneMinder now supports recording directly to video container! This feature
is new and should be treated as experimental. Refer to the documentation
regarding how to use this feature.
3. The Apache ScriptAlias has been changed from "/cgi-bin/zm/zms" to
"/cgi-bin-zm/zms". This has been to done to avoid this bug:
https://bugzilla.redhat.com/show_bug.cgi?id=973067
@ -9,16 +18,10 @@ What's New
and verify it is set to "/cgi-bin-zm/nph-zms". Failure to do so will result
in a broken system. You have been warned.
2. Due to the active state of the ZoneMinder project, we now recommend granting
ALL permission to the ZoneMinder mysql account. This change must be done
manually before ZoneMinder will run. See the installation steps below.
3. This package uses the HTTPS protocol by default to access the web portal.
4. This package uses the HTTPS protocol by default to access the web portal.
Requests using HTTP will auto-redirect to HTTPS. See README.https for
more information.
4. This package ships with the new ZoneMinder API enabled.
New installs
============
@ -43,13 +46,17 @@ New installs
anything that suits your environment.
3. If you have chosen to change the zoneminder database account credentials to
something other than zmuser/zmpass, you must now edit /etc/zm/zm.conf.
Change ZM_DB_USER and ZM_DB_PASS to the values you created in the previous
step.
something other than zmuser/zmpass, you must now create a config file under
/etc/zm/conf.d and set your credentials there. For example, create the file
/etc/zm/conf.d/zm-db-user.conf and add the following content to it:
ZM_DB_USER = {username of the sql account you want to use}
ZM_DB_PASS = {password of the sql account you want to use}
This version of zoneminder no longer requires you to make a similar change
to the credentials in /usr/share/zoneminder/www/api/app/Config/database.php
This now happens dynamically. Do *not* make any changes to this file.
Once the file has been saved, set proper file & ownership permissions on it:
sudo chown root:apache *.conf
sudo chmod 640 *.conf
4. Edit /etc/php.ini, uncomment the date.timezone line, and add your local
timezone. PHP will complain loudly if this is not set, or if it is set
@ -107,21 +114,11 @@ New installs
Upgrades
========
1. Verify /etc/zm/zm.conf.
If zm.conf was manually edited before running the upgrade, the installation
may not overwrite it. In this case, it will create the file
/etc/zm/zm.conf.rpmnew.
For example, this will happen if you are using database account credentials
other than zmuser/zmpass.
Compare /etc/zm/zm.conf to /etc/zm/zm.conf.rpmnew. Verify that zm.conf
contains any new config settings that may be in zm.conf.rpmnew.
This version of zoneminder no longer requires you to make a similar change
to the credentials in /usr/share/zoneminder/www/api/app/Config/database.php
This now happens dynamically. Do *not* make any changes to this file.
1. Conf.d folder support has been added to ZoneMinder 1.31.0. Any custom
changes previously made to zm.conf must now be made in one or more custom
config files, created under the conf.d folder. Do this now. See
/etc/zm/conf.d/README for details. Once you recreate any custom config changes
under the conf.d folder, they will remain in place indefinitely.
2. Verify permissions of the zmuser account.

View File

@ -11,7 +11,16 @@ What's New
replacing core packages, such as php, will not be supported by us. You are
on your own should you choose to go down that path.
2. The Apache ScriptAlias has been changed from "/cgi-bin/zm/zms" to
2. ZoneMinder now uses a conf.d subfolder to process custom changes to
variables found in zm.conf. Changes to zm.conf will be overwritten
during an upgrade. Instead, create a file with a ".conf" extension under
th2 conf.d folder and make your changes there.
3. ZoneMinder now supports recording directly to video container! This feature
is new and should be treated as experimental. Refer to the documentation
regarding how to use this feature.
4. The Apache ScriptAlias has been changed from "/cgi-bin/zm/zms" to
"/cgi-bin-zm/zms". This has been to done match the configuration of
CentOS7/Fedora and simplify the build process.
@ -19,14 +28,6 @@ What's New
Make sure it is set to "/cgi-bin-zm/nph-zms". Failure to do so will result
in a broken system. You have been warned.
3. The ZoneMinder configuration file, zm.conf, has been moved to /etc/zm/.
This has been to done match the configuration of CentOS7/Fedora and
simplify the build process.
4. Due to the active state of the ZoneMinder project, we now recommend granting
ALL permission to the ZoneMinder mysql account. This change must be done
manually before ZoneMinder will run. See the installation steps below.
5. This package uses the HTTPS protocol by default to access the web portal.
Requests using HTTP will auto-redirect to HTTPS. See README.https for
more information.
@ -59,9 +60,18 @@ New installs
The database account credentials, zmuser/zmpass, are arbitrary. Set them to
anything that suits your environment.
3. If you have chosen to change the zoneminder mysql credentials to something
other than zmuser/zmpass then you must now edit /etc/zm/zm.conf. Change
ZM_DB_USER and ZM_DB_PASS to the values you created in the previous step.
3. If you have chosen to change the zoneminder database account credentials to
something other than zmuser/zmpass, you must now create a config file under
/etc/zm/conf.d and set your credentials there. For example, create the file
/etc/zm/conf.d/zm-db-user.conf and add the following content to it:
ZM_DB_USER = {username of the sql account you want to use}
ZM_DB_PASS = {password of the sql account you want to use}
Once the file has been saved, set proper file & ownership permissions on it:
sudo chown root:apache *.conf
sudo chmod 640 *.conf
4. Edit /etc/php.ini, uncomment the date.timezone line, and add your local
timezone. PHP will complain loudly if this is not set, or if it is set
@ -110,17 +120,11 @@ New installs
Upgrades
========
1. Verify /etc/zm/zm.conf.
If zm.conf was manually edited before running the upgrade, the installation
may not overwrite it. In this case, it will create the file
/etc/zm/zm.conf.rpmnew.
For example, this will happen if you are using database account credentials
other than zmuser/zmpass.
Compare /etc/zm/zm.conf to /etc/zm/zm.conf.rpmnew. Verify that zm.conf
contains any new config settings that may be in zm.conf.rpmnew.
1. Conf.d folder support has been added to ZoneMinder 1.31.0. Any custom
changes previously made to zm.conf must now be made in one or more custom
config files, created under the conf.d folder. Do this now. See
/etc/zm/conf.d/README for details. Once you recreate any custom config changes
under the conf.d folder, they will remain in place indefinitely.
2. Verify permissions of the zmuser account.

View File

@ -1,23 +1,26 @@
What's New
==========
1. The Apache ScriptAlias has been changed from "/cgi-bin/zm/zms" to
1. ZoneMinder now uses a conf.d subfolder to process custom changes to
variables found in zm.conf. Changes to zm.conf will be overwritten
during an upgrade. Instead, create a file with a ".conf" extension under
the conf.d folder and make your changes there.
2. ZoneMinder now supports recording directly to video container! This feature
is new and should be treated as experimental. Refer to the documentation
regarding how to use this feature.
3. The Apache ScriptAlias has been changed from "/cgi-bin/zm/zms" to
"/cgi-bin-zm/zms". This has been to done to avoid this bug:
https://bugzilla.redhat.com/show_bug.cgi?id=973067
IMPORTANT: You must manually verify the value of PATH_ZMS under Options.
Make sure it is set to "/cgi-bin-zm/nph-zms". Failure to do so will result
IMPORTANT: You must manually inspect the value for PATH_ZMS under Options
and verify it is set to "/cgi-bin-zm/nph-zms". Failure to do so will result
in a broken system. You have been warned.
2. Due to the active state of the ZoneMinder project, we now recommend granting
ALL permission to the ZoneMinder mysql account. This change must be done
manually before ZoneMinder will run. See the installation steps below.
3. This package uses the HTTPS protocol by default to access the web portal.
4. This package uses the HTTPS protocol by default to access the web portal.
Requests using HTTP will auto-redirect to HTTPS. See README.https for
more information.
4. This package ships with the new ZoneMinder API enabled.
New installs
============
@ -43,13 +46,17 @@ New installs
anything that suits your environment.
3. If you have chosen to change the zoneminder database account credentials to
something other than zmuser/zmpass, you must now edit /etc/zm/zm.conf.
Change ZM_DB_USER and ZM_DB_PASS to the values you created in the previous
step.
something other than zmuser/zmpass, you must now create a config file under
/etc/zm/conf.d and set your credentials there. For example, create the file
/etc/zm/conf.d/zm-db-user.conf and add the following content to it:
ZM_DB_USER = {username of the sql account you want to use}
ZM_DB_PASS = {password of the sql account you want to use}
This version of zoneminder no longer requires you to make a similar change
to the credentials in /usr/share/zoneminder/www/api/app/Config/database.php
This now happens dynamically. Do *not* make any changes to this file.
Once the file has been saved, set proper file & ownership permissions on it:
sudo chown root:apache *.conf
sudo chmod 640 *.conf
4. Edit /etc/php.ini, uncomment the date.timezone line, and add your local
timezone. PHP will complain loudly if this is not set, or if it is set
@ -98,21 +105,11 @@ New installs
Upgrades
========
1. Verify /etc/zm/zm.conf.
If zm.conf was manually edited before running the upgrade, the installation
may not overwrite it. In this case, it will create the file
/etc/zm/zm.conf.rpmnew.
For example, this will happen if you are using database account credentials
other than zmuser/zmpass.
Compare /etc/zm/zm.conf to /etc/zm/zm.conf.rpmnew. Verify that zm.conf
contains any new config settings that may be in zm.conf.rpmnew.
This version of zoneminder no longer requires you to make a similar change
to the credentials in /usr/share/zoneminder/www/api/app/Config/database.php
This now happens dynamically. Do *not* make any changes to this file.
1. Conf.d folder support has been added to ZoneMinder 1.31.0. Any custom
changes previously made to zm.conf must now be made in one or more custom
config files, created under the conf.d folder. Do this now. See
/etc/zm/conf.d/README for details. Once you recreate any custom config changes
under the conf.d folder, they will remain in place indefinitely.
2. Verify permissions of the zmuser account.

View File

@ -280,7 +280,13 @@ rm -rf %{_docdir}/%{name}-%{version}
%files
%license COPYING
%doc AUTHORS README.md distros/redhat/readme/README.%{readme_suffix} distros/redhat/readme/README.https distros/redhat/jscalendar-doc
%config(noreplace) %attr(640,root,%{zmgid_final}) %{_sysconfdir}/zm/zm.conf
%dir %{_sysconfdir}/zm
%dir %{_sysconfdir}/zm/conf.d
%{_sysconfdir}/zm/conf.d/README
# Always overwrite zm.conf now that ZoneMinder supports conf.d folder
%attr(640,root,%{zmgid_final}) %{_sysconfdir}/zm/zm.conf
%config(noreplace) %attr(640,root,%{zmgid_final}) %{_sysconfdir}/zm/conf.d/*.conf
%config(noreplace) %attr(644,root,root) %{wwwconfdir}/zoneminder.conf
%config(noreplace) %{_sysconfdir}/logrotate.d/zoneminder

View File

@ -1,10 +0,0 @@
zoneminder (1.28.1-1) unstable; urgency=low
This version is no longer automatically initialize or upgrade database.
See README.Debian for details.
Changed installation paths (please correct your web server configuration):
/usr/share/zoneminder --> /usr/share/zoneminder/www
/usr/lib/cgi-bin --> /usr/lib/zoneminder/cgi-bin
-- Dmitry Smirnov <onlyjob@debian.org> Tue, 31 Mar 2015 15:12:17 +1100

View File

View File

@ -1,16 +0,0 @@
Last-Update: 2015-08-16
Forwarded: no
Author: Dmitry Smirnov <onlyjob@member.fsf.org>
Description: correct path to CGI app according to default web server configuration.
--- a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in
+++ b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in
@@ -428,7 +428,7 @@ our @options =
},
{
name => "ZM_PATH_ZMS",
- default => "/cgi-bin/nph-zms",
+ default => "/zm/cgi-bin/nph-zms",
description => "Web path to zms streaming server",
help => qqq("
The ZoneMinder streaming server is required to send streamed

View File

@ -1,2 +0,0 @@
default_cgi-path.patch
use_libjs-mootools.patch

View File

@ -1,18 +0,0 @@
Last-Update: 2015-03-29
Forwarded: no
Bug-Debian: http://bugs.debian.org/585590
Reviewed-By: Dmitry Smirnov <onlyjob@member.fsf.org>
Description: use mootools shipped by debian, rather than the zoneminder included mootools.
--- a/web/skins/classic/includes/functions.php
+++ b/web/skins/classic/includes/functions.php
@@ -63,9 +63,8 @@
}
?>
<script type="text/javascript" src="tools/mootools/mootools-core.js"></script>
<script type="text/javascript" src="tools/mootools/mootools-more.js"></script>
- <script type="text/javascript" src="js/mootools.ext.js"></script>
<script type="text/javascript" src="js/logger.js"></script>
<script type="text/javascript" src="js/overlay.js"></script>
<?php
if ( $skinJsPhpFile )

View File

@ -20,6 +20,7 @@ override_dh_auto_configure:
-DCMAKE_VERBOSE_MAKEFILE=ON \
-DCMAKE_BUILD_TYPE=Release \
-DZM_CONFIG_DIR="/etc/zm" \
-DZM_CONFIG_SUBDIR="/etc/zm/conf.d" \
-DZM_RUNDIR="/var/run/zm" \
-DZM_SOCKDIR="/var/run/zm" \
-DZM_TMPDIR="/tmp/zm" \

View File

@ -1 +1 @@
3.0 (native)
3.0 (quilt)

View File

@ -62,7 +62,9 @@ override_dh_auto_configure:
-DZM_CGIDIR=/usr/lib/cgi-bin \
-DZM_WEB_USER=www-data \
-DZM_WEB_GROUP=www-data \
-DCMAKE_INSTALL_SYSCONFDIR=etc/zm
-DZM_CONFIG_SUBDIR="/etc/zm/conf.d" \
-DZM_CONFIG_DIR="/etc/zm"
override_dh_auto_test:
# do not run tests...

View File

@ -5,6 +5,7 @@ Maintainer: Dmitry Smirnov <onlyjob@debian.org>
Uploaders: Vagrant Cascadian <vagrant@debian.org>
Build-Depends: debhelper (>= 9), dh-systemd, python-sphinx | python3-sphinx, apache2-dev, dh-linktree
,cmake
,libx264-dev, libmp4v2-dev
,libboost-dev
,libavdevice-dev (>= 6:10~)
,libavcodec-dev (>= 6:10~)
@ -15,7 +16,7 @@ Build-Depends: debhelper (>= 9), dh-systemd, python-sphinx | python3-sphinx, apa
,libgcrypt-dev
,libcurl4-gnutls-dev
,libgnutls-openssl-dev
,libjpeg-dev
,libjpeg8-dev | libjpeg9-dev | libjpeg62-turbo-dev
,libmysqlclient-dev
,libpcre3-dev
,libpolkit-gobject-1-dev
@ -27,12 +28,10 @@ Build-Depends: debhelper (>= 9), dh-systemd, python-sphinx | python3-sphinx, apa
,libsys-mmap-perl [!hurd-any]
,libwww-perl
,libdata-uuid-perl
,libx264-dev
,libmp4v2-dev
# Unbundled (dh_linktree):
,libjs-jquery
,libjs-mootools
Standards-Version: 3.9.6
Standards-Version: 3.9.8
Homepage: http://www.zoneminder.com/
Vcs-Browser: http://anonscm.debian.org/cgit/collab-maint/zoneminder.git
Vcs-Git: git://anonscm.debian.org/collab-maint/zoneminder.git
@ -41,11 +40,10 @@ Package: zoneminder
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
,javascript-common
,libmp4v2-2, libx264-142|libx264-148, libswscale-ffmpeg3|libswscale4|libswscale3
,ffmpeg | libav-tools
,libdate-manip-perl
,libdate-manip-perl, libmime-lite-perl, libmime-tools-perl
,libdbd-mysql-perl
,libmime-lite-perl
,libmime-tools-perl
,libphp-serialization-perl
,libmodule-load-conditional-perl
,libnet-sftp-foreign-perl
@ -66,10 +64,11 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
,libdata-uuid-perl
,mysql-client | virtual-mysql-client
,perl-modules
,php5-mysql | php-mysql, php5-gd | php-gd, php-apcu, php-apcu-bc | php-gd
,php5-mysql | php-mysql, php5-gd | php-gd , php5-apcu | php-apcu , php-apc | php-apcu-bc
,policykit-1
,rsyslog | system-log-daemon
,zip
,libpcre3
Recommends: ${misc:Recommends}
,libapache2-mod-php5 | libapache2-mod-php | php5-fpm | php-fpm
,mysql-server | virtual-mysql-server

View File

@ -1,2 +0,0 @@
default_cgi-path.patch
use_libjs-mootools.patch

View File

@ -20,6 +20,7 @@ override_dh_auto_configure:
-DCMAKE_VERBOSE_MAKEFILE=ON \
-DCMAKE_BUILD_TYPE=Release \
-DZM_CONFIG_DIR="/etc/zm" \
-DZM_CONFIG_SUBDIR="/etc/zm/conf.d" \
-DZM_RUNDIR="/var/run/zm" \
-DZM_SOCKDIR="/var/run/zm" \
-DZM_TMPDIR="/tmp/zm" \
@ -28,7 +29,7 @@ override_dh_auto_configure:
override_dh_clean:
dh_clean $(MANPAGES1)
$(RM) -r docs/_build docs/installationguide
$(RM) -r docs/_build
build-indep:
#$(MAKE) -C docs text

View File

@ -1 +1 @@
3.0 (native)
3.0 (quilt)

View File

@ -2,6 +2,8 @@
missingok
notifempty
sharedscripts
delaycompress
compress
postrotate
/usr/bin/zmpkg.pl logrot >>/dev/null 2>&1 || :
endscript

View File

@ -12,6 +12,10 @@ if [ "$1" = "configure" ]; then
if [ -z "$2" ]; then
chown www-data:www-data /var/cache/zoneminder /var/cache/zoneminder/*
fi
if [ ! -e "/etc/apache2/mods-enabled/cgi.load" ]; then
echo "The cgi module is not enabled in apache2. I am enabling it using a2enmod cgi."
a2enmod cgi
fi
# Do this every time the package is installed or upgraded

View File

@ -65,26 +65,28 @@ our $VERSION = $ZoneMinder::Base::VERSION;
use constant ZM_PID => "@ZM_PID@"; # Path to the ZoneMinder run pid file
use constant ZM_CONFIG => "@ZM_CONFIG@"; # Path to the ZoneMinder config file
use constant ZM_CONFIG_SUBDIR => "@ZM_CONFIG_SUBDIR@"; # Path to the ZoneMinder config subfolder
use Carp;
# Load the config from the database into the symbol table
BEGIN {
# Process name, value pairs from the main config file first
my $config_file = ZM_CONFIG;
open( my $CONFIG, "<", $config_file )
or croak( "Can't open config file '$config_file': $!" );
foreach my $str ( <$CONFIG> ) {
next if ( $str =~ /^\s*$/ );
next if ( $str =~ /^\s*#/ );
my ( $name, $value ) = $str =~ /^\s*([^=\s]+)\s*=\s*(.*?)\s*$/;
if ( ! $name ) {
print( STDERR "Warning, bad line in $config_file: $str\n" );
next;
} # end if
$name =~ tr/a-z/A-Z/;
$Config{$name} = $value;
process_configfile($config_file);
# Search for user created config files. If one or more are found then
# update the Config hash with those values
if ( -d ZM_CONFIG_SUBDIR ) {
if ( -R ZM_CONFIG_SUBDIR ) {
foreach my $filename ( glob ZM_CONFIG_SUBDIR."/*.conf" ) {
process_configfile($filename);
}
} else {
print( STDERR "WARNING: ZoneMinder configuration subfolder found but is not readable. Check folder permissions on ".ZM_CONFIG_SUBDIR.".\n" );
}
}
close( $CONFIG );
use DBI;
my $socket;
@ -126,6 +128,31 @@ BEGIN {
}
$sth->finish();
}
# This subroutine must be inside the BEGIN block
sub process_configfile {
my $config_file = shift;
if ( -R $config_file ) {
open( my $CONFIG, "<", $config_file )
or croak( "Can't open config file '$config_file': $!" );
foreach my $str ( <$CONFIG> ) {
next if ( $str =~ /^\s*$/ );
next if ( $str =~ /^\s*#/ );
my ( $name, $value ) = $str =~ /^\s*([^=\s]+)\s*=\s*(.*?)\s*$/;
if ( ! $name ) {
print( STDERR "Warning, bad line in $config_file: $str\n" );
next;
} # end if
$name =~ tr/a-z/A-Z/;
$Config{$name} = $value;
}
close( $CONFIG );
} else {
print( STDERR "WARNING: ZoneMinder configuration file found but is not readable. Check file permissions on $config_file\n" );
}
}
} # end BEGIN
sub loadConfigFromDB {

File diff suppressed because it is too large Load Diff

View File

@ -45,265 +45,239 @@ use ZoneMinder::Config qw(:all);
use Time::HiRes qw( usleep );
sub new
{
my $class = shift;
my $id = shift;
my $self = ZoneMinder::Control->new( $id );
bless( $self, $class );
srand( time() );
return $self;
sub new {
my $class = shift;
my $id = shift;
my $self = ZoneMinder::Control->new( $id );
bless( $self, $class );
srand( time() );
return $self;
}
our $AUTOLOAD;
sub AUTOLOAD
{
my $self = shift;
my $class = ref($self) || croak( "$self not object" );
my $name = $AUTOLOAD;
$name =~ s/.*://;
if ( exists($self->{$name}) )
{
return( $self->{$name} );
}
Fatal( "Can't access $name member of object of class $class" );
sub AUTOLOAD {
my $self = shift;
my $class = ref($self) || croak( "$self not object" );
my $name = $AUTOLOAD;
$name =~ s/.*://;
if ( exists($self->{$name}) ) {
return( $self->{$name} );
}
Fatal( "Can't access $name member of object of class $class" );
}
sub open
{
my $self = shift;
sub open {
my $self = shift;
$self->loadMonitor();
$self->loadMonitor();
use LWP::UserAgent;
$self->{ua} = LWP::UserAgent->new;
$self->{ua}->agent( "ZoneMinder Control Agent/".ZoneMinder::Base::ZM_VERSION );
use LWP::UserAgent;
$self->{ua} = LWP::UserAgent->new;
$self->{ua}->agent( "ZoneMinder Control Agent/".ZoneMinder::Base::ZM_VERSION );
$self->{state} = 'open';
$self->{state} = 'open';
}
sub close
{
my $self = shift;
$self->{state} = 'closed';
sub close {
my $self = shift;
$self->{state} = 'closed';
}
sub printMsg
{
my $self = shift;
my $msg = shift;
my $msg_len = length($msg);
sub printMsg {
my $self = shift;
my $msg = shift;
my $msg_len = length($msg);
Debug( $msg."[".$msg_len."]" );
Debug( $msg."[".$msg_len."]" );
}
sub sendCmd
{
my $self = shift;
my $cmd = shift;
sub sendCmd {
my $self = shift;
my $cmd = shift;
my $result = undef;
my $result = undef;
printMsg( $cmd, "Tx" );
printMsg( $cmd, "Tx" );
my $url;
if ( $self->{Monitor}->{ControlAddress} =~ /^http/ ) {
$url = $self->{Monitor}->{ControlAddress}.$cmd;
} else {
$url = 'http://'.$self->{Monitor}->{ControlAddress}.$cmd;
} # en dif
my $req = HTTP::Request->new( GET=>$url );
my $url;
if ( $self->{Monitor}->{ControlAddress} =~ /^http/ ) {
$url = $self->{Monitor}->{ControlAddress}.$cmd;
} else {
$url = 'http://'.$self->{Monitor}->{ControlAddress}.$cmd;
} # en dif
my $req = HTTP::Request->new( GET=>$url );
my $res = $self->{ua}->request($req);
my $res = $self->{ua}->request($req);
if ( $res->is_success )
{
$result = !undef;
}
else
{
Error( "Error check failed: '".$res->status_line()."'" );
}
if ( $res->is_success ) {
$result = !undef;
} else {
Error( "Error check failed: '".$res->status_line()."'" );
}
return( $result );
return( $result );
}
sub reset
{
my $self = shift;
Debug( "Camera Reset" );
my $cmd = "/admin/ptctl.cgi?move=reset";
$self->sendCmd( $cmd );
sub reset {
my $self = shift;
Debug( "Camera Reset" );
my $cmd = "/admin/ptctl.cgi?move=reset";
$self->sendCmd( $cmd );
}
sub moveMap
{
my $self = shift;
my $params = shift;
my $xcoord = $self->getParam( $params, 'xcoord' );
my $ycoord = $self->getParam( $params, 'ycoord' );
sub moveMap {
my $self = shift;
my $params = shift;
my $xcoord = $self->getParam( $params, 'xcoord' );
my $ycoord = $self->getParam( $params, 'ycoord' );
my $hor = $xcoord * 100 / $self->{Monitor}->{Width};
my $ver = $ycoord * 100 / $self->{Monitor}->{Height};
my $hor = $xcoord * 100 / $self->{Monitor}->{Width};
my $ver = $ycoord * 100 / $self->{Monitor}->{Height};
my $maxver = 8;
my $maxhor = 30;
my $horDir = "right";
my $verDir = "up";
my $horSteps = 0;
my $verSteps = 0;
my $maxver = 8;
my $maxhor = 30;
# Horizontal movement
if ($hor < 50) {
# left
$horSteps = ((50 - $hor) / 50) * $maxhor;
$horDir = "left";
}
elsif ($hor > 50) {
# right
$horSteps = (($hor - 50) / 50) * $maxhor;
$horDir = "right";
}
# Vertical movement
if ($ver < 50) {
# up
$verSteps = ((50 - $ver) / 50) * $maxver;
$verDir = "up";
}
elsif ($ver > 50) {
# down
$verSteps = (($ver - 50) / 50) * $maxver;
$verDir = "down";
}
my $horDir = "right";
my $verDir = "up";
my $horSteps = 0;
my $verSteps = 0;
my $v = int($verSteps);
my $h = int($horSteps);
# Horizontal movement
if ( $hor < 50 ) {
# left
$horSteps = ((50 - $hor) / 50) * $maxhor;
$horDir = "left";
}
elsif ( $hor > 50 ) {
# right
$horSteps = (($hor - 50) / 50) * $maxhor;
$horDir = "right";
}
Debug( "Move Map to $xcoord,$ycoord, hor=$h $horDir, ver=$v $verDir");
my $cmd = "/cgi/admin/ptctrl.cgi?action=movedegree&Cmd=$horDir&Degree=$h";
$self->sendCmd( $cmd );
$cmd = "/cgi/admin/ptctrl.cgi?action=movedegree&Cmd=$verDir&Degree=$v";
$self->sendCmd( $cmd );
# Vertical movement
if ( $ver < 50 ) {
# up
$verSteps = ((50 - $ver) / 50) * $maxver;
$verDir = "up";
}
elsif ( $ver > 50 ) {
# down
$verSteps = (($ver - 50) / 50) * $maxver;
$verDir = "down";
}
my $v = int($verSteps);
my $h = int($horSteps);
Debug( "Move Map to $xcoord,$ycoord, hor=$h $horDir, ver=$v $verDir");
my $cmd = "/cgi/admin/ptctrl.cgi?action=movedegree&Cmd=$horDir&Degree=$h";
$self->sendCmd( $cmd );
$cmd = "/cgi/admin/ptctrl.cgi?action=movedegree&Cmd=$verDir&Degree=$v";
$self->sendCmd( $cmd );
}
sub moveRelUp
{
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'tiltstep' );
Debug( "Step Up $step" );
my $cmd = "/admin/ptctl.cgi?move=up";
$self->sendCmd( $cmd );
sub moveRelUp {
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'tiltstep' );
Debug( "Step Up $step" );
my $cmd = "/admin/ptctl.cgi?move=up";
$self->sendCmd( $cmd );
}
sub moveRelDown
{
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'tiltstep' );
Debug( "Step Down $step" );
my $cmd = "/admin/ptctl.cgi?move=down";
$self->sendCmd( $cmd );
sub moveRelDown {
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'tiltstep' );
Debug( "Step Down $step" );
my $cmd = "/admin/ptctl.cgi?move=down";
$self->sendCmd( $cmd );
}
sub moveRelLeft
{
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'panstep' );
Debug( "Step Left $step" );
my $cmd = "/admin/ptctl.cgi?move=left";
$self->sendCmd( $cmd );
sub moveRelLeft {
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'panstep' );
if ( $self->{Monitor}->{Orientation} eq "hori" ) {
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
{
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'panstep' );
Debug( "Step Right $step" );
my $cmd = "/admin/ptctl.cgi?move=right";
$self->sendCmd( $cmd );
sub moveRelRight {
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'panstep' );
if ( $self->{Monitor}->{Orientation} eq "hori" ) {
Debug( "Stepping Left because flipped horizontally " );
$self->sendCmd( "/admin/ptctl.cgi?move=left" );
} else {
Debug( "Step Right" );
$self->sendCmd( "/admin/ptctl.cgi?move=right" );
}
}
sub presetClear
{
my $self = shift;
my $params = shift;
my $preset = $self->getParam( $params, 'preset' );
Debug( "Clear Preset $preset" );
#my $cmd = "/axis-cgi/com/ptz.cgi?removeserverpresetno=$preset";
#$self->sendCmd( $cmd );
sub presetClear {
my $self = shift;
my $params = shift;
my $preset = $self->getParam( $params, 'preset' );
Debug( "Clear Preset $preset" );
#my $cmd = "/axis-cgi/com/ptz.cgi?removeserverpresetno=$preset";
#$self->sendCmd( $cmd );
}
sub presetSet
{
my $self = shift;
my $params = shift;
my $preset = $self->getParam( $params, 'preset' );
Debug( "Set Preset $preset" );
my $cmd = "/admin/ptctl.cgi?position=" . ($preset - 1) . "&positionname=zm$preset";
$self->sendCmd( $cmd );
sub presetSet {
my $self = shift;
my $params = shift;
my $preset = $self->getParam( $params, 'preset' );
Debug( "Set Preset $preset" );
my $cmd = "/admin/ptctl.cgi?position=" . ($preset - 1) . "&positionname=zm$preset";
$self->sendCmd( $cmd );
}
sub presetGoto
{
my $self = shift;
my $params = shift;
my $preset = $self->getParam( $params, 'preset' );
Debug( "Goto Preset $preset" );
my $cmd = "/admin/ptctl.cgi?move=p" . ($preset - 1);
$self->sendCmd( $cmd );
sub presetGoto {
my $self = shift;
my $params = shift;
my $preset = $self->getParam( $params, 'preset' );
Debug( "Goto Preset $preset" );
my $cmd = "/admin/ptctl.cgi?move=p" . ($preset - 1);
$self->sendCmd( $cmd );
}
sub presetHome
{
my $self = shift;
Debug( "Home Preset" );
my $cmd = "/admin/ptctl.cgi?move=h";
$self->sendCmd( $cmd );
sub presetHome {
my $self = shift;
Debug( "Home Preset" );
my $cmd = "/admin/ptctl.cgi?move=h";
$self->sendCmd( $cmd );
}
1;
__END__
# Below is stub documentation for your module. You'd better edit it!
=head1 NAME
ZoneMinder::Database - Perl extension for blah blah blah
ZoneMinder::Control::SkyIPCam7xx.pm - Module for controlling AirLink101 SkyIPams
=head1 SYNOPSIS
use ZoneMinder::Database;
blah blah blah
use ZoneMinder::Control::SkyIPCam7xx;
=head1 DESCRIPTION
Stub documentation for ZoneMinder, created by h2xs. It looks like the
author of the extension was negligent enough to leave the stub
unedited.
Blah blah blah.
Module for controlling AirLink101 Cameras.
=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.
ZoneMinder::Control
=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,
at your option, any later version of Perl 5 you may have available.
=cut

View File

@ -75,9 +75,11 @@ sub zmDbConnect {
if ( $force ) {
zmDbDisconnect();
}
if ( !defined( $dbh ) ) {
my $options = shift;
if ( ( ! defined( $dbh ) ) or ! $dbh->ping() ) {
my ( $host, $portOrSocket ) = ( $ZoneMinder::Config::Config{ZM_DB_HOST} =~ /^([^:]+)(?::(.+))?$/ );
my $socket;
my ( $host, $portOrSocket ) = ( $Config{ZM_DB_HOST} =~ /^([^:]+)(?::(.+))?$/ );
if ( defined($portOrSocket) ) {
if ( $portOrSocket =~ /^\// ) {
@ -89,7 +91,7 @@ sub zmDbConnect {
$socket = ";host=".$Config{ZM_DB_HOST};
}
$dbh = DBI->connect( "DBI:mysql:database=".$Config{ZM_DB_NAME}
.$socket
.$socket . ($options?';'.join(';', map { $_.'='.$$options{$_} } keys %{$options} ) : '' )
, $Config{ZM_DB_USER}
, $Config{ZM_DB_PASS}
);

View File

@ -28,30 +28,12 @@ use 5.006;
use strict;
use warnings;
require Exporter;
require ZoneMinder::Base;
require ZoneMinder::Object;
require Date::Manip;
our @ISA = qw(Exporter ZoneMinder::Base);
# 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;
#our @ISA = qw(ZoneMinder::Object);
use parent qw(ZoneMinder::Object);
# ==========================================================================
#
@ -62,39 +44,24 @@ our $VERSION = $ZoneMinder::Base::VERSION;
use ZoneMinder::Config qw(:all);
use ZoneMinder::Logger qw(:all);
use ZoneMinder::Database qw(:all);
require Date::Parse;
use vars qw/ $table $primary_key /;
$table = 'Events';
$primary_key = 'Id';
use POSIX;
sub new {
my ( $parent, $id, $data ) = @_;
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 );
sub Time {
if ( @_ > 1 ) {
$_[0]{Time} = $_[1];
}
return $self;
} # end sub new
if ( ! defined $_[0]{Time} ) {
sub load {
my ( $self, $data ) = @_;
my $type = ref $self;
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
$_[0]{Time} = Date::Parse::str2time( $_[0]{StartTime} );
}
return $_[0]{Time};
}
sub Name {
if ( @_ > 1 ) {
@ -130,6 +97,7 @@ sub find {
my $filter = new ZoneMinder::Event( $$db_filter{Id}, $db_filter );
push @results, $filter;
} # end while
$sth->finish();
return @results;
}
@ -138,36 +106,51 @@ sub find_one {
return $results[0] if @results;
}
sub getEventPath {
sub getPath {
return Path( @_ );
}
sub Path {
my $event = shift;
my $event_path = "";
if ( $Config{ZM_USE_DEEP_STORAGE} ) {
$event_path = $Config{ZM_DIR_EVENTS}
.'/'.$event->{MonitorId}
.'/'.strftime( "%y/%m/%d/%H/%M/%S",
localtime($event->{Time})
)
;
} else {
$event_path = $Config{ZM_DIR_EVENTS}
.'/'.$event->{MonitorId}
.'/'.$event->{Id}
;
if ( @_ > 1 ) {
$$event{Path} = $_[1];
if ( ! -e $$event{Path} ) {
Error("Setting path for event $$event{Id} to $_[1] but does not exist!");
}
}
if ( index($Config{ZM_DIR_EVENTS},'/') != 0 ){
$event_path = $Config{ZM_PATH_WEB}
.'/'.$event_path
;
}
return( $event_path );
if ( ! $$event{Path} ) {
my $path = ($Config{ZM_DIR_EVENTS}=~/^\//) ? $Config{ZM_DIR_EVENTS} : $Config{ZM_PATH_WEB}.'/'.$Config{ZM_DIR_EVENTS};
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} = '';
}
} else {
$$event{Path} = join('/',
$path,
$event->{MonitorId},
$event->{Id},
);
}
} # end if
return $$event{Path};
}
sub GenerateVideo {
my ( $self, $rate, $fps, $scale, $size, $overwrite, $format ) = @_;
my $event_path = getEventPath( $self );
my $event_path = $self->getPath( );
chdir( $event_path );
( my $video_name = $self->{Name} ) =~ s/\s/_/g;
@ -228,9 +211,7 @@ sub GenerateVideo {
my $command = $Config{ZM_PATH_FFMPEG}
." -y -r $frame_rate "
.$Config{ZM_FFMPEG_INPUT_OPTIONS}
." -i %0"
.$Config{ZM_EVENT_IMAGE_DIGITS}
."d-capture.jpg -s $video_size "
.' -i ' . ( $$self{DefaultVideo} ? $$self{DefaultVideo} : '%0'.$Config{ZM_EVENT_IMAGE_DIGITS} .'d-capture.jpg' )
#. " -f concat -i /tmp/event_files.txt"
." -s $video_size "
.$Config{ZM_FFMPEG_OUTPUT_OPTIONS}
@ -253,54 +234,143 @@ sub GenerateVideo {
Info( "Video file $video_file already exists for event $self->{Id}\n" );
return $event_path.'/'.$video_file;
}
return;
return;
} # 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;
__END__
# Below is stub documentation for your module. You'd better edit it!
=head1 NAME
ZoneMinder::Database - Perl extension for blah blah blah
ZoneMinder::Event - Perl Class for events
=head1 SYNOPSIS
use ZoneMinder::Event;
blah blah blah
=head1 DESCRIPTION
Stub documentation for ZoneMinder, created by h2xs. It looks like the
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.
The Event class has everything you need to deal with events from Perl.
=head1 AUTHOR
Philip Coombes, E<lt>philip.coombes@zoneminder.comE<gt>
Isaac Connor, E<lt>isaac@zoneminder.comE<gt>
=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
it under the same terms as Perl itself, either Perl version 5.8.3 or,

View File

@ -28,31 +28,14 @@ use 5.006;
use strict;
use warnings;
require Exporter;
require ZoneMinder::Base;
require Date::Manip;
our @ISA = qw(Exporter ZoneMinder::Base);
# 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;
use parent qw(ZoneMinder::Object);
use vars qw/ $table $primary_key /;
$table = 'Filters';
$primary_key = 'Id';
# ==========================================================================
#
# General Utility Functions
@ -62,40 +45,10 @@ our $VERSION = $ZoneMinder::Base::VERSION;
use ZoneMinder::Config qw(:all);
use ZoneMinder::Logger qw(:all);
use ZoneMinder::Database qw(:all);
require ZoneMinder::Server;
use POSIX;
sub new {
my ( $parent, $id, $data ) = @_;
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;
} # end sub new
sub load {
my ( $self, $data ) = @_;
my $type = ref $self;
if ( ! $data ) {
#$log->debug("Object::load Loading from db $type");
$data = $$self{dbh}->selectrow_hashref( 'SELECT * FROM Filter WHERE Id=?', {}, $$self{Id} );
if ( ! $data ) {
Error( "Failure to load Filter record for $$self{Id}: Reason: " . $$self{dbh}->errstr );
} else {
Debug( 3, "Loaded Filter $$self{Id}" );
} # end if
} # end if ! $data
if ( $data and %$data ) {
@$self{keys %$data} = values %$data;
} # end if
} # end sub load
sub Name {
if ( @_ > 1 ) {
$_[0]{Name} = $_[1];
@ -142,7 +95,6 @@ sub find_one {
sub Execute {
my $self = $_[0];
my $sql = $self->Sql();
if ( $self->{HasDiskPercent} ) {
@ -158,8 +110,9 @@ sub Execute {
$sql =~ s/zmSystemLoad/$load/g;
}
my $sth = $$self{dbh}->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$$self{dbh}->errstr() );
Debug("Filter::Execute SQL ($sql)");
my $sth = $ZoneMinder::Database::dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$ZoneMinder::Database::dbh->errstr() );
my $res = $sth->execute();
if ( !$res ) {
Error( "Can't execute filter '$sql', ignoring: ".$sth->errstr() );
@ -171,6 +124,7 @@ sub Execute {
push @results, $event;
}
$sth->finish();
Debug("Loaded " . @results . " events for filter $_[0]{Name} using query ($sql)");
return @results;
}
@ -308,6 +262,8 @@ sub Sql {
if ( $self->{AutoArchive} ) {
push @auto_terms, "E.Archived = 0";
}
# Don't do this, it prevents re-generation and concatenation.
# If the file already exists, then the video won't be re-recreated
if ( $self->{AutoVideo} ) {
push @auto_terms, "E.Videoed = 0";
}
@ -359,14 +315,13 @@ sub Sql {
if ( $filter_expr->{limit} ) {
$sql .= " limit 0,".$filter_expr->{limit};
}
Debug( "SQL:$sql\n" );
$self->{Sql} = $sql;
} # end if has Sql
return $self->{Sql};
} # end sub Sql
sub getDiskPercent {
my $command = "df .";
my $command = "df " . ($_[0] ? $_[0] : '.');
my $df = qx( $command );
my $space = -1;
if ( $df =~ /\s(\d+)%/ms ) {

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

View File

@ -40,15 +40,15 @@ our @ISA = qw(Exporter ZoneMinder::Base);
# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
# will save memory.
our %EXPORT_TAGS = (
'functions' => [ qw(
zmMemKey
zmMemAttach
zmMemDetach
zmMemGet
zmMemPut
zmMemClean
) ],
);
functions => [ qw(
zmMemKey
zmMemAttach
zmMemDetach
zmMemGet
zmMemPut
zmMemClean
) ],
);
push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS;
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
@ -68,134 +68,119 @@ use ZoneMinder::Logger qw(:all);
use Sys::Mmap;
sub zmMemKey
{
my $monitor = shift;
return( defined($monitor->{MMapAddr})?$monitor->{MMapAddr}:undef );
sub zmMemKey {
my $monitor = shift;
return( defined($monitor->{MMapAddr})?$monitor->{MMapAddr}:undef );
}
sub zmMemAttach
{
my ( $monitor, $size ) = @_;
if ( ! $size ) {
Error( "No size passed to zmMemAttach for monitor $$monitor{Id}\n" );
return( undef );
sub zmMemAttach {
my ( $monitor, $size ) = @_;
if ( ! $size ) {
Error( "No size passed to zmMemAttach for monitor $$monitor{Id}\n" );
return( undef );
}
if ( !defined($monitor->{MMapAddr}) ) {
my $mmap_file = $Config{ZM_PATH_MAP}."/zm.mmap.".$monitor->{Id};
if ( ! -e $mmap_file ) {
Error( sprintf( "Memory map file '%s' does not exist. zmc might not be running."
, $mmap_file
)
);
return ( undef );
}
if ( !defined($monitor->{MMapAddr}) )
{
my $mmap_file = $Config{ZM_PATH_MAP}."/zm.mmap.".$monitor->{Id};
if ( ! -e $mmap_file ) {
Error( sprintf( "Memory map file '%s' does not exist. zmc might not be running."
, $mmap_file
)
);
return ( undef );
}
my $mmap_file_size = -s $mmap_file;
my $mmap_file_size = -s $mmap_file;
if ( $mmap_file_size < $size ) {
Error( sprintf( "Memory map file '%s' should have been %d but was instead %d"
, $mmap_file
, $size
, $mmap_file_size
)
);
return ( undef );
}
my $MMAP;
if ( !open( $MMAP, "+<", $mmap_file ) )
{
Error( sprintf( "Can't open memory map file '%s': $!\n", $mmap_file ) );
return( undef );
}
my $mmap = undef;
my $mmap_addr = mmap( $mmap, $size, PROT_READ|PROT_WRITE, MAP_SHARED, $MMAP );
if ( !$mmap_addr || !$mmap )
{
Error( sprintf( "Can't mmap to file '%s': $!\n", $mmap_file ) );
close( $MMAP );
return( undef );
}
$monitor->{MMapHandle} = $MMAP;
$monitor->{MMapAddr} = $mmap_addr;
$monitor->{MMap} = \$mmap;
if ( $mmap_file_size < $size ) {
Error( sprintf( "Memory map file '%s' should have been %d but was instead %d"
, $mmap_file
, $size
, $mmap_file_size
)
);
return ( undef );
}
return( !undef );
my $MMAP;
if ( !open( $MMAP, '+<', $mmap_file ) ) {
Error( sprintf( "Can't open memory map file '%s': $!\n", $mmap_file ) );
return( undef );
}
my $mmap = undef;
my $mmap_addr = mmap( $mmap, $size, PROT_READ|PROT_WRITE, MAP_SHARED, $MMAP );
if ( !$mmap_addr || !$mmap ) {
Error( sprintf( "Can't mmap to file '%s': $!\n", $mmap_file ) );
close( $MMAP );
return( undef );
}
$monitor->{MMapHandle} = $MMAP;
$monitor->{MMapAddr} = $mmap_addr;
$monitor->{MMap} = \$mmap;
}
return( !undef );
}
sub zmMemDetach
{
my $monitor = shift;
sub zmMemDetach {
my $monitor = shift;
if ( $monitor->{MMap} )
{
if ( ! munmap( ${$monitor->{MMap}} ) ) {
Warn( "Unable to munmap for monitor $$monitor{Id}\n");
}
delete $monitor->{MMap};
}
if ( $monitor->{MMapAddr} )
{
delete $monitor->{MMapAddr};
}
if ( $monitor->{MMapHandle} )
{
close( $monitor->{MMapHandle} );
delete $monitor->{MMapHandle};
if ( $monitor->{MMap} ) {
if ( ! munmap( ${$monitor->{MMap}} ) ) {
Warn( "Unable to munmap for monitor $$monitor{Id}\n");
}
delete $monitor->{MMap};
}
if ( $monitor->{MMapAddr} ) {
delete $monitor->{MMapAddr};
}
if ( $monitor->{MMapHandle} ) {
close( $monitor->{MMapHandle} );
delete $monitor->{MMapHandle};
}
}
sub zmMemGet
{
my $monitor = shift;
my $offset = shift;
my $size = shift;
sub zmMemGet {
my $monitor = shift;
my $offset = shift;
my $size = shift;
my $mmap = $monitor->{MMap};
if ( !$mmap || !$$mmap )
{
Error( sprintf( "Can't read from mapped memory for monitor '%d', gone away?"
, $monitor->{Id}
)
my $mmap = $monitor->{MMap};
if ( !$mmap || !$$mmap ) {
Error( sprintf( "Can't read from mapped memory for monitor '%d', gone away?"
, $monitor->{Id}
)
);
return( undef );
}
my $data = substr( $$mmap, $offset, $size );
return( $data );
return( undef );
}
my $data = substr( $$mmap, $offset, $size );
return( $data );
}
sub zmMemPut
{
my $monitor = shift;
my $offset = shift;
my $size = shift;
my $data = shift;
sub zmMemPut {
my $monitor = shift;
my $offset = shift;
my $size = shift;
my $data = shift;
my $mmap = $monitor->{MMap};
if ( !$mmap || !$$mmap )
{
Error( sprintf( "Can't write mapped memory for monitor '%d', gone away?"
, $monitor->{Id}
)
my $mmap = $monitor->{MMap};
if ( !$mmap || !$$mmap ) {
Error( sprintf( "Can't write mapped memory for monitor '%d', gone away?"
, $monitor->{Id}
)
);
return( undef );
}
substr( $$mmap, $offset, $size ) = $data;
return( !undef );
return( undef );
}
substr( $$mmap, $offset, $size ) = $data;
return( !undef );
}
sub zmMemClean
{
Debug( "Removing memory map files\n" );
my $mapPath = $Config{ZM_PATH_MAP}."/zm.mmap.*";
foreach my $mapFile( glob( $mapPath ) )
{
( $mapFile ) = $mapFile =~ /^(.+)$/;
Debug( "Removing memory map file '$mapFile'\n" );
unlink( $mapFile );
}
sub zmMemClean {
Debug( "Removing memory map files\n" );
my $mapPath = $Config{ZM_PATH_MAP}.'/zm.mmap.*';
foreach my $mapFile( glob( $mapPath ) ) {
( $mapFile ) = $mapFile =~ /^(.+)$/;
Debug( "Removing memory map file '$mapFile'\n" );
unlink( $mapFile );
}
}
1;

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

@ -0,0 +1,150 @@
# ==========================================================================
#
# ZoneMinder Object Module, $Date$, $Revision$
# Copyright (C) 2001-2017 ZoneMinder LLC
#
# 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::Object;
use 5.006;
use strict;
use warnings;
require ZoneMinder::Base;
our @ISA = qw(ZoneMinder::Base);
# ==========================================================================
#
# General Utility Functions
#
# ==========================================================================
use ZoneMinder::Config qw(:all);
use ZoneMinder::Logger qw(:all);
use ZoneMinder::Database qw(:all);
use vars qw/ $AUTOLOAD /;
sub new {
my ( $parent, $id, $data ) = @_;
my $self = {};
bless $self, $parent;
no strict 'refs';
my $primary_key = ${$parent.'::primary_key'};
if ( ! $primary_key ) {
Error( 'NO primary_key for type ' . $parent );
return;
} # end if
if ( ( $$self{$primary_key} = $id ) or $data ) {
#$log->debug("loading $parent $id") if $debug or DEBUG_ALL;
$self->load( $data );
}
return $self;
} # end sub new
sub load {
my ( $self, $data ) = @_;
my $type = ref $self;
if ( ! $data ) {
no strict 'refs';
my $table = ${$type.'::table'};
if ( ! $table ) {
Error( 'NO table for type ' . $type );
return;
} # end if
my $primary_key = ${$type.'::primary_key'};
if ( ! $primary_key ) {
Error( 'NO primary_key for type ' . $type );
return;
} # end if
if ( ! $$self{$primary_key} ) {
my ( $caller, undef, $line ) = caller;
Error( (ref $self) . "::load called without $primary_key from $caller:$line");
} else {
#$log->debug("Object::load Loading from db $type");
Debug("Loading $type from $table WHERE $primary_key = $$self{$primary_key}");
$data = $ZoneMinder::Database::dbh->selectrow_hashref( "SELECT * FROM $table WHERE $primary_key=?", {}, $$self{$primary_key} );
if ( ! $data ) {
if ( $ZoneMinder::Database::dbh->errstr ) {
Error( "Failure to load Object record for $$self{$primary_key}: Reason: " . $ZoneMinder::Database::dbh->errstr );
} else {
Debug("No Results Loading $type from $table WHERE $primary_key = $$self{$primary_key}");
} # end if
} # end if
} # end if
} # end if ! $data
if ( $data and %$data ) {
@$self{keys %$data} = values %$data;
} # end if
} # end sub load
sub AUTOLOAD {
my ( $self, $newvalue ) = @_;
my $type = ref($_[0]);
my $name = $AUTOLOAD;
$name =~ s/.*://;
if ( @_ > 1 ) {
return $_[0]{$name} = $_[1];
}
return $_[0]{$name};
}
1;
__END__
# Below is stub documentation for your module. You'd better edit it!
=head1 NAME
ZoneMinder::Object
=head1 SYNOPSIS
use parent ZoneMinder::Object;
This package should likely not be used directly, as it is meant mainly to be a parent for all other ZoneMinder classes.
=head1 DESCRIPTION
A base Object to act as parent for other ZoneMinder Objects.
=head2 EXPORT
None by default.
=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
-r, --report - Just report don't actually do anything
-i, --interactive - Ask before applying any changes
-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
=cut
@ -57,8 +57,8 @@ use bytes;
# ==========================================================================
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_TEXT => "Recovered."; # Text to append to event notes 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
# ==========================================================================
#
@ -96,10 +96,10 @@ logInit();
logSetSignal();
GetOptions(
'report' =>\$report,
'interactive' =>\$interactive,
'continuous' =>\$continuous,
'version' =>\$version
continuous =>\$continuous,
interactive =>\$interactive,
report =>\$report,
version =>\$version
) or pod2usage(-exitstatus => -1);
if ( $version ) {
@ -111,6 +111,10 @@ if ( ($report + $interactive + $continuous) > 1 ) {
pod2usage(-exitstatus => -1);
}
if ( ! exists $Config{ZM_AUDIT_MIN_AGE} ) {
Fatal('ZM_AUDIT_MIN_AGE is not set in config.');
}
my $dbh = zmDbConnect();
chdir( EVENT_PATH );
@ -126,13 +130,13 @@ MAIN: while( $loop ) {
$dbh = zmDbConnect();
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
# interval, otherwise we are a one off run, so wait a second and
# retry until someone kills us.
sleep( $Config{ZM_AUDIT_CHECK_INTERVAL} );
} else {
Fatal("Unable to connect to database");
Fatal('Unable to connect to database');
} # end if
} # end while can't connect to the db
@ -145,16 +149,12 @@ MAIN: while( $loop ) {
sleep 1;
} # end if
if ( ! exists $Config{ZM_AUDIT_MIN_AGE} ) {
Fatal("ZM_AUDIT_MIN_AGE is not set in config.");
}
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 )
or Fatal( "Can't prepare '$monitorSelectSql': ".$dbh->errstr() );
my $eventSelectSql = "SELECT Id, (unix_timestamp() - unix_timestamp(StartTime)) as Age
FROM Events WHERE MonitorId = ? ORDER BY Id";
my $eventSelectSql = 'SELECT Id, (unix_timestamp() - unix_timestamp(StartTime)) as Age
FROM Events WHERE MonitorId = ? ORDER BY Id';
my $eventSelectSth = $dbh->prepare_cached( $eventSelectSql )
or Fatal( "Can't prepare '$eventSelectSql': ".$dbh->errstr() );
@ -169,11 +169,11 @@ MAIN: while( $loop ) {
while ( my $event = $eventSelectSth->fetchrow_hashref() ) {
$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;
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.
next if $monitor =~ /\D/;
Debug( "Found filesystem monitor '$monitor'" );
@ -182,11 +182,17 @@ MAIN: while( $loop ) {
if ( $Config{ZM_USE_DEEP_STORAGE} ) {
foreach my $day_dir ( glob("$monitor_dir/*/*/*") ) {
Debug( "Checking $day_dir" );
Debug( "Checking day dir $day_dir" );
( $day_dir ) = ( $day_dir =~ /^(.*)$/ ); # De-taint
chdir( $day_dir );
opendir( DIR, "." )
or Fatal( "Can't open directory '$day_dir': $!" );
if ( ! chdir( $day_dir ) ) {
Error( "Can't chdir to '$day_dir': $!" );
next;
}
if ( ! opendir( DIR, '.' ) ) {
Error( "Can't open directory '$day_dir': $!" );
next;
}
my @event_links = sort { $b <=> $a } grep { -l $_ } readdir( DIR );
closedir( DIR );
my $count = 0;
@ -226,7 +232,7 @@ MAIN: while( $loop ) {
}
chdir( EVENT_PATH );
}
Debug( "Got ".int(keys(%$fs_events))." events\n" );
Debug( 'Got '.int(keys(%$fs_events))." events\n" );
} # end foreach monitor Id
redo MAIN if ( $cleaned );
@ -255,7 +261,7 @@ MAIN: while( $loop ) {
}
my $monitor_links;
foreach my $link ( glob("*") ) {
foreach my $link ( glob('*') ) {
next if ( !-l $link );
next if ( -e $link );
@ -270,16 +276,16 @@ MAIN: while( $loop ) {
redo MAIN if ( $cleaned );
$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 )
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 )
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 )
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 )
or Fatal( "Can't prepare '$deleteStatsSql': ".$dbh->errstr() );
while ( my ( $db_monitor, $db_events ) = each(%$db_monitors) ) {
@ -319,9 +325,9 @@ MAIN: while( $loop ) {
# Remove orphaned events (with no monitor)
$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)
WHERE isnull(Monitors.Id)";
WHERE isnull(Monitors.Id)';
my $selectOrphanedEventsSth = $dbh->prepare_cached( $selectOrphanedEventsSql )
or Fatal( "Can't prepare '$selectOrphanedEventsSql': ".$dbh->errstr() );
$res = $selectOrphanedEventsSth->execute()
@ -356,8 +362,8 @@ MAIN: while( $loop ) {
# Remove orphaned frame records
$cleaned = 0;
my $selectOrphanedFramesSql = "SELECT DISTINCT EventId FROM Frames
WHERE EventId NOT IN (SELECT Id FROM Events)";
my $selectOrphanedFramesSql = 'SELECT DISTINCT EventId FROM Frames
WHERE EventId NOT IN (SELECT Id FROM Events)';
my $selectOrphanedFramesSth = $dbh->prepare_cached( $selectOrphanedFramesSql )
or Fatal( "Can't prepare '$selectOrphanedFramesSql': ".$dbh->errstr() );
$res = $selectOrphanedFramesSth->execute()
@ -374,8 +380,8 @@ MAIN: while( $loop ) {
# Remove orphaned stats records
$cleaned = 0;
my $selectOrphanedStatsSql = "SELECT DISTINCT EventId FROM Stats
WHERE EventId NOT IN (SELECT Id FROM Events)";
my $selectOrphanedStatsSql = 'SELECT DISTINCT EventId FROM Stats
WHERE EventId NOT IN (SELECT Id FROM Events)';
my $selectOrphanedStatsSth = $dbh->prepare_cached( $selectOrphanedStatsSql )
or Fatal( "Can't prepare '$selectOrphanedStatsSql': ".$dbh->errstr() );
$res = $selectOrphanedStatsSth->execute()
@ -429,20 +435,13 @@ MAIN: while( $loop ) {
aud_print( "Found open event '$event->{Id}'" );
if ( confirm( 'close', 'closing' ) ) {
$res = $updateUnclosedEventsSth->execute(
sprintf("%s%d%s",
$event->{Prefix},
$event->{Id},
RECOVER_TAG
),
sprintf('%s%d%s', $event->{Prefix}, $event->{Id}, RECOVER_TAG),
$event->{EndTime},
$event->{Length},
$event->{Frames},
$event->{AlarmFrames},
$event->{TotScore},
$event->{AlarmFrames}
? int($event->{TotScore} / $event->{AlarmFrames})
: 0
,
$event->{AlarmFrames} ? int($event->{TotScore} / $event->{AlarmFrames}) : 0,
$event->{MaxScore},
RECOVER_TEXT,
$event->{Id}
@ -453,8 +452,8 @@ MAIN: while( $loop ) {
# Now delete any old image files
my @old_files = grep { -M > $max_image_age } <$image_path/*.{jpg,gif,wbmp}>;
if ( @old_files ) {
aud_print( "Deleting ".int(@old_files)." old images\n" );
my $untainted_old_files = join( ";", @old_files );
aud_print( 'Deleting '.( scalar @old_files )." old images\n" );
my $untainted_old_files = join( ';', @old_files );
( $untainted_old_files ) = ( $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} =~ /^\d+$/ ) {
# 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 )
or Fatal( "Can't prepare '$selectLogRowCountSql': ".$dbh->errstr() );
$res = $selectLogRowCountSth->execute()
@ -475,20 +474,20 @@ MAIN: while( $loop ) {
my $row = $selectLogRowCountSth->fetchrow_hashref();
my $logRows = $row->{Rows};
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 )
or Fatal( "Can't prepare '$deleteLogByRowsSql': ".$dbh->errstr() );
$res = $deleteLogByRowsSth->execute( $logRows - $Config{ZM_LOG_DATABASE_LIMIT} )
or Fatal( "Can't execute: ".$deleteLogByRowsSth->errstr() );
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 {
# Time of record
my $deleteLogByTimeSql =
"DELETE low_priority FROM Logs
WHERE TimeKey < unix_timestamp(now() - interval ".$Config{ZM_LOG_DATABASE_LIMIT}.")";
'DELETE low_priority FROM Logs
WHERE TimeKey < unix_timestamp(now() - interval '.$Config{ZM_LOG_DATABASE_LIMIT}.')';
my $deleteLogByTimeSth = $dbh->prepare_cached( $deleteLogByTimeSql )
or Fatal( "Can't prepare '$deleteLogByTimeSql': ".$dbh->errstr() );
$res = $deleteLogByTimeSth->execute()
@ -515,8 +514,8 @@ sub aud_print {
}
sub confirm {
my $prompt = shift || "delete";
my $action = shift || "deleting";
my $prompt = shift || 'delete';
my $action = shift || 'deleting';
my $yesno = 0;
if ( $report ) {

View File

@ -55,6 +55,7 @@ a sql file, which can then be easily imported to another zoneminder system.
--help - Print usage information.
--user=<dbuser> - Alternate dB user with privileges to alter dB.
--pass=<dbpass> - Password of alternate dB user with privileges to alter dB.
--version - Print version.
=cut
use strict;
@ -105,43 +106,43 @@ $Config{ZM_DB_USER} = $dbUser;
$Config{ZM_DB_PASS} = $dbPass;
if ( $version ) {
print( ZoneMinder::Base::ZM_VERSION . "\n");
exit(0);
print( ZoneMinder::Base::ZM_VERSION . "\n");
exit(0);
}
# Check to make sure commandline params make sense
if ( ((!$help) && ($import + $export + $topreset) != 1 )) {
print( STDERR qq/Please give only one of the following: "import", "export", or "topreset".\n/ );
pod2usage(-exitstatus => -1);
print( STDERR qq/Please give only one of the following: "import", "export", or "topreset".\n/ );
pod2usage(-exitstatus => -1);
}
if ( ($export)&&($overwrite) ) {
print( "Warning: Overwrite parameter ignored during an export.\n");
print( "Warning: Overwrite parameter ignored during an export.\n");
}
if ( ($noregex)&&(!$topreset) ) {
print( qq/Warning: Noregex parameter only applies when "topreset" parameter is also set. Ignoring.\n/);
print( qq/Warning: Noregex parameter only applies when "topreset" parameter is also set. Ignoring.\n/);
}
if ( ($topreset)&&($ARGV[0] !~ /\d\d*/) ) {
print( STDERR qq/Parameter "topreset" requires a valid monitor ID.\n/ );
pod2usage(-exitstatus => -1);
print( STDERR qq/Parameter "topreset" requires a valid monitor ID.\n/ );
pod2usage(-exitstatus => -1);
}
# Call the appropriate subroutine based on the params given on the commandline
if ($help) {
pod2usage(-exitstatus => -1);
pod2usage(-exitstatus => -1);
}
if ($export) {
exportsql();
exportsql();
}
if ($import) {
importsql();
importsql();
}
if ($topreset) {
toPreset();
toPreset();
}
###############
@ -149,299 +150,293 @@ if ($topreset) {
###############
# Execute a pre-built sql select query
sub selectQuery
{
my $dbh = shift;
my $sql = shift;
my $monitorid = shift;
sub selectQuery {
my $dbh = shift;
my $sql = shift;
my $monitorid = shift;
my $sth = $dbh->prepare_cached( $sql )
or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute($monitorid)
or die( "Can't execute: ".$sth->errstr() );
my $sth = $dbh->prepare_cached( $sql )
or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute($monitorid)
or die( "Can't execute: ".$sth->errstr() );
my @data = $sth->fetchrow_array();
$sth->finish();
my @data = $sth->fetchrow_array();
$sth->finish();
return @data;
return @data;
}
# Exectute a pre-built sql query
sub runQuery
{
my $dbh = shift;
my $sql = shift;
my $sth = $dbh->prepare_cached( $sql )
or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute()
or die( "Can't execute: ".$sth->errstr() );
$sth->finish();
sub runQuery {
my $dbh = shift;
my $sql = shift;
my $sth = $dbh->prepare_cached( $sql )
or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute()
or die( "Can't execute: ".$sth->errstr() );
$sth->finish();
return $res;
return $res;
}
# Build and execute a sql insert query
sub insertQuery
{
my $dbh = shift;
my $tablename = shift;
my @data = @_;
sub insertQuery {
my $dbh = shift;
my $tablename = shift;
my @data = @_;
my $sql = "INSERT INTO $tablename VALUES (NULL,"
.(join ", ", ("?") x @data).")"; # Add "?" for each array element
my $sql = "INSERT INTO $tablename VALUES (NULL,"
.(join ', ', ('?') x @data).')'; # Add "?" for each array element
my $sth = $dbh->prepare_cached( $sql )
or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute(@data)
or die( "Can't execute: ".$sth->errstr() );
$sth->finish();
or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute(@data)
or die( "Can't execute: ".$sth->errstr() );
$sth->finish();
return $res;
return $res;
}
# Build and execute a sql delete query
sub deleteQuery
{
my $dbh = shift;
my $sqltable = shift;
my $sqlname = shift;
sub deleteQuery {
my $dbh = shift;
my $sqltable = shift;
my $sqlname = shift;
my $sql = "DELETE FROM $sqltable WHERE Name = ?";
my $sth = $dbh->prepare_cached( $sql )
or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute($sqlname)
or die( "Can't execute: ".$sth->errstr() );
$sth->finish();
my $sql = "DELETE FROM $sqltable WHERE Name = ?";
my $sth = $dbh->prepare_cached( $sql )
or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute($sqlname)
or die( "Can't execute: ".$sth->errstr() );
$sth->finish();
return $res;
return $res;
}
# Build and execute a sql select count query
sub checkExists
{
my $dbh = shift;
my $sqltable = shift;
my $sqlname = shift;
my $result = 0;
sub checkExists {
my $dbh = shift;
my $sqltable = shift;
my $sqlname = shift;
my $result = 0;
my $sql = "SELECT count(*) FROM $sqltable WHERE Name = ?";
my $sth = $dbh->prepare_cached( $sql )
or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute($sqlname)
or die( "Can't execute: ".$sth->errstr() );
my $sql = "SELECT count(*) FROM $sqltable WHERE Name = ?";
my $sth = $dbh->prepare_cached( $sql )
or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute($sqlname)
or die( "Can't execute: ".$sth->errstr() );
my $rows = $sth->fetchrow_arrayref();
$sth->finish();
my $rows = $sth->fetchrow_arrayref();
$sth->finish();
if ($rows->[0] > 0) {
$result = 1;
}
if ($rows->[0] > 0) {
$result = 1;
}
return $result;
return $result;
}
# Import camera control & presets into the zoneminder dB
sub importsql
{
my @newcontrols;
my @overwritecontrols;
my @skippedcontrols;
my @newpresets;
my @overwritepresets;
my @skippedpresets;
my %controls;
my %monitorpresets;
sub importsql {
my @newcontrols;
my @overwritecontrols;
my @skippedcontrols;
my @newpresets;
my @overwritepresets;
my @skippedpresets;
my %controls;
my %monitorpresets;
if ($ARGV[0]) {
$sqlfile = $ARGV[0];
if ($ARGV[0]) {
$sqlfile = $ARGV[0];
} else {
$sqlfile = $Config{ZM_PATH_DATA}.'/db/zm_create.sql';
}
open(my $SQLFILE,'<',$sqlfile)
or die( "Can't Open file: $!\n" );
# Find and extract ptz control and monitor preset records
while (<$SQLFILE>) {
# Our regex replaces the primary key with NULL
if (s/^(INSERT INTO .*?Controls.*? VALUES \().*?(,')(.*?)(',.*)/$1NULL$2$3$4/i) {
$controls{$3} = $_;
} elsif (s/^(INSERT INTO .*?MonitorPresets.*? VALUES \().*?(,')(.*?)(',.*)/$1NULL$2$3$4/i) {
$monitorpresets{$3} = $_;
}
}
close $SQLFILE;
if ( ! (%controls || %monitorpresets) ) {
die( "Error: No relevant data found in $sqlfile.\n" );
}
# Now that we've got what we were looking for,
# compare to what is already in the dB
my $dbh = zmDbConnect();
foreach (keys %controls) {
if (!checkExists($dbh,'Controls',$_)) {
# No existing Control was found. Add new control to dB.
runQuery($dbh,$controls{$_});
push @newcontrols, $_;
} elsif ($overwrite) {
# An existing Control was found and the overwrite flag is set.
# Overwrite the control.
deleteQuery($dbh,'Controls',$_);
runQuery($dbh,$controls{$_});
push @overwritecontrols, $_;
} else {
$sqlfile = $Config{ZM_PATH_DATA}.'/db/zm_create.sql';
}
# An existing Control was found and the overwrite flag was not set.
# Do nothing.
push @skippedcontrols, $_;
}
}
open(my $SQLFILE,"<",$sqlfile)
or die( "Can't Open file: $!\n" );
foreach (keys %monitorpresets) {
if (!checkExists($dbh,'MonitorPresets',$_)) {
# No existing MonitorPreset was found. Add new MonitorPreset to dB.
runQuery($dbh,$monitorpresets{$_});
push @newpresets, $_;
} elsif ($overwrite) {
# An existing MonitorPreset was found and the overwrite flag is set.
# Overwrite the MonitorPreset.
deleteQuery($dbh,'MonitorPresets',$_);
runQuery($dbh,$monitorpresets{$_});
push @overwritepresets, $_;
} else {
# An existing MonitorPreset was found and the overwrite flag was
# not set. Do nothing.
push @skippedpresets, $_;
}
}
# Find and extract ptz control and monitor preset records
while (<$SQLFILE>) {
# Our regex replaces the primary key with NULL
if (s/^(INSERT INTO .*?Controls.*? VALUES \().*?(,')(.*?)(',.*)/$1NULL$2$3$4/i) {
$controls{$3} = $_;
} elsif (s/^(INSERT INTO .*?MonitorPresets.*? VALUES \().*?(,')(.*?)(',.*)/$1NULL$2$3$4/i) {
$monitorpresets{$3} = $_;
}
}
close $SQLFILE;
if (@newcontrols) {
print 'Number of ptz camera controls added: '
.scalar(@newcontrols)."\n";
}
if (@overwritecontrols) {
print 'Number of existing ptz camera controls overwritten: '
.scalar(@overwritecontrols)."\n";
}
if (@skippedcontrols) {
print 'Number of existing ptz camera controls skipped: '
.scalar(@skippedcontrols)."\n";
}
if ( ! (%controls || %monitorpresets) ) {
die( "Error: No relevant data found in $sqlfile.\n" );
}
# Now that we've got what we were looking for,
# compare to what is already in the dB
my $dbh = zmDbConnect();
foreach (keys %controls) {
if (!checkExists($dbh,"Controls",$_)) {
# No existing Control was found. Add new control to dB.
runQuery($dbh,$controls{$_});
push @newcontrols, $_;
} elsif ($overwrite) {
# An existing Control was found and the overwrite flag is set.
# Overwrite the control.
deleteQuery($dbh,"Controls",$_);
runQuery($dbh,$controls{$_});
push @overwritecontrols, $_;
} else {
# An existing Control was found and the overwrite flag was not set.
# Do nothing.
push @skippedcontrols, $_;
}
}
foreach (keys %monitorpresets) {
if (!checkExists($dbh,"MonitorPresets",$_)) {
# No existing MonitorPreset was found. Add new MonitorPreset to dB.
runQuery($dbh,$monitorpresets{$_});
push @newpresets, $_;
} elsif ($overwrite) {
# An existing MonitorPreset was found and the overwrite flag is set.
# Overwrite the MonitorPreset.
deleteQuery($dbh,"MonitorPresets",$_);
runQuery($dbh,$monitorpresets{$_});
push @overwritepresets, $_;
} else {
# An existing MonitorPreset was found and the overwrite flag was
# not set. Do nothing.
push @skippedpresets, $_;
}
}
if (@newcontrols) {
print "Number of ptz camera controls added: "
.scalar(@newcontrols)."\n";
}
if (@overwritecontrols) {
print "Number of existing ptz camera controls overwritten: "
.scalar(@overwritecontrols)."\n";
}
if (@skippedcontrols) {
print "Number of existing ptz camera controls skipped: "
.scalar(@skippedcontrols)."\n";
}
if (@newpresets) {
print "Number of monitor presets added: "
.scalar(@newpresets)."\n";
}
if (@overwritepresets) {
print "Number of existing monitor presets overwritten: "
.scalar(@overwritepresets)."\n";
}
if (@skippedpresets) {
print "Number of existing presets skipped: "
.scalar(@skippedpresets)."\n";
}
if (@newpresets) {
print 'Number of monitor presets added: '
.scalar(@newpresets)."\n";
}
if (@overwritepresets) {
print 'Number of existing monitor presets overwritten: '
.scalar(@overwritepresets)."\n";
}
if (@skippedpresets) {
print 'Number of existing presets skipped: '
.scalar(@skippedpresets)."\n";
}
}
# Export camera controls & presets from the zoneminder dB to STDOUT
sub exportsql
{
sub exportsql {
my ( $host, $port ) = ( $Config{ZM_DB_HOST} =~ /^([^:]+)(?::(.+))?$/ );
my $command = "mysqldump -t --skip-opt --compact -h".$host;
$command .= " -P".$port if defined($port);
if ( $dbUser ) {
$command .= " -u".$dbUser;
my ( $host, $port ) = ( $Config{ZM_DB_HOST} =~ /^([^:]+)(?::(.+))?$/ );
my $command = 'mysqldump -t --skip-opt --compact -h'.$host;
$command .= ' -P'.$port if defined($port);
if ( $dbUser ) {
$command .= ' -u'.$dbUser;
if ( $dbPass ) {
$command .= " -p".$dbPass;
}
$command .= ' -p'.$dbPass;
}
}
if ($ARGV[0]) {
if ($ARGV[0]) {
$command .= qq( --where="Name = '$ARGV[0]'");
}
}
$command .= " zm Controls MonitorPresets";
$command .= " zm Controls MonitorPresets";
my $output = qx($command);
my $status = $? >> 8;
if ( $status || logDebugging() ) {
my $output = qx($command);
my $status = $? >> 8;
if ( $status || logDebugging() ) {
chomp( $output );
print( "Output: $output\n" );
}
if ( $status ) {
}
if ( $status ) {
die( "Command '$command' exited with status: $status\n" );
} else {
# NULLify the primary keys before printing the output to STDOUT
} else {
# NULLify the primary keys before printing the output to STDOUT
$output =~ s/VALUES \((.*?),'/VALUES \(NULL,'/ig;
print $output;
}
}
}
sub toPreset
{
my $dbh = zmDbConnect();
my $monitorid = $ARGV[0];
sub toPreset {
my $dbh = zmDbConnect();
my $monitorid = $ARGV[0];
# Grap the following fields from the Monitors table
my $sql = "SELECT
Name,
Type,
Device,
Channel,
Format,
Protocol,
Method,
Host,
Port,
Path,
SubPath,
Width,
Height,
Palette,
MaxFPS,
Controllable,
ControlId,
ControlDevice,
ControlAddress,
DefaultRate,
DefaultScale
FROM Monitors WHERE Id = ?";
my @data = selectQuery($dbh,$sql,$monitorid);
# Grap the following fields from the Monitors table
my $sql = 'SELECT
Name,
Type,
Device,
Channel,
Format,
Protocol,
Method,
Host,
Port,
Path,
SubPath,
Width,
Height,
Palette,
MaxFPS,
Controllable,
ControlId,
ControlDevice,
ControlAddress,
DefaultRate,
DefaultScale
FROM Monitors WHERE Id = ?';
my @data = selectQuery($dbh,$sql,$monitorid);
if (!@data) {
die( "Error: Monitor Id $monitorid does not appear to exist in the database.\n" );
if (!@data) {
die( "Error: Monitor Id $monitorid does not appear to exist in the database.\n" );
}
# Attempt to search for and replace system specific values such as
# ip addresses, ports, usernames, etc. with generic placeholders
if (!$noregex) {
foreach (@data) {
next if ! $_;
s/\b(?:\d{1,3}\.){3}\d{1,3}\b/<ip-address>/; # ip address
s/<ip-address>:(6553[0-5]|655[0-2]\d|65[0-4]\d\d|6[0-4]\d{3}|[1-5]\d{4}|[1-9]\d{0,3}|0)$/<ip-address>:<port>/; # tcpip port
s/\/\/.*:.*@/\/\/<username>:<pwd>@/; # user & pwd preceding an ip address
s/(&|\?)(user|username)=\w\w*(&|\?)/$1$2=<username>$3/i; # username embedded in url
s/(&|\?)(pwd|password)=\w\w*(&|\?)/$1$2=<pwd>$3/i; # password embedded in url
s/\w\w*:\w\w*/<username>:<pwd>/; # user & pwd in their own field
s/\/dev\/video\d\d*/\/dev\/video<?>/; # local video devices
}
}
# Attempt to search for and replace system specific values such as
# ip addresses, ports, usernames, etc. with generic placeholders
if (!$noregex) {
foreach (@data) {
next if ! $_;
s/\b(?:\d{1,3}\.){3}\d{1,3}\b/<ip-address>/; # ip address
s/<ip-address>:(6553[0-5]|655[0-2]\d|65[0-4]\d\d|6[0-4]\d{3}|[1-5]\d{4}|[1-9]\d{0,3}|0)$/<ip-address>:<port>/; # tcpip port
s/\/\/.*:.*@/\/\/<username>:<pwd>@/; # user & pwd preceding an ip address
s/(&|\?)(user|username)=\w\w*(&|\?)/$1$2=<username>$3/i; # username embedded in url
s/(&|\?)(pwd|password)=\w\w*(&|\?)/$1$2=<pwd>$3/i; # password embedded in url
s/\w\w*:\w\w*/<username>:<pwd>/; # user & pwd in their own field
s/\/dev\/video\d\d*/\/dev\/video<?>/; # local video devices
}
}
if (!checkExists($dbh,"MonitorPresets",$data[0])) {
# No existing Preset was found. Add new Preset to dB.
print "Adding new preset: $data[0]\n";
insertQuery($dbh,"MonitorPresets",@data);
} elsif ($overwrite) {
# An existing Control was found and the overwrite flag is set.
# Overwrite the control.
print "Existing preset $data[0] detected.\nOverwriting...\n";
deleteQuery($dbh,"MonitorPresets",$data[0]);
insertQuery($dbh,"MonitorPresets",@data);
} else {
# An existing Control was found and the overwrite flag was not set.
# Do nothing.
print "Existing preset $data[0] detected and overwrite flag not set.\nSkipping...\n";
}
if (!checkExists($dbh,"MonitorPresets",$data[0])) {
# No existing Preset was found. Add new Preset to dB.
print "Adding new preset: $data[0]\n";
insertQuery($dbh,'MonitorPresets',@data);
} elsif ($overwrite) {
# An existing Control was found and the overwrite flag is set.
# Overwrite the control.
print "Existing preset $data[0] detected.\nOverwriting...\n";
deleteQuery($dbh,'MonitorPresets',$data[0]);
insertQuery($dbh,'MonitorPresets',@data);
} else {
# An existing Control was found and the overwrite flag was not set.
# Do nothing.
print "Existing preset $data[0] detected and overwrite flag not set.\nSkipping...\n";
}
}
1;
__END__

File diff suppressed because it is too large Load Diff

View File

@ -24,14 +24,80 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <dirent.h>
#include <glob.h>
#include "zm_utils.h"
void zmLoadConfig() {
// Process name, value pairs from the main config file first
char configFile[PATH_MAX] = ZM_CONFIG;
process_configfile(configFile);
// Search for user created config files. If one or more are found then
// update the Config hash with those values
DIR* configSubFolder = opendir(ZM_CONFIG_SUBDIR);
if ( configSubFolder ) { // subfolder exists and is readable
char glob_pattern[PATH_MAX] = "";
snprintf( glob_pattern, sizeof(glob_pattern), "%s/*.conf", ZM_CONFIG_SUBDIR );
glob_t pglob;
int glob_status = glob( glob_pattern, 0, 0, &pglob );
if ( glob_status != 0 ) {
if ( glob_status < 0 ) {
Error( "Can't glob '%s': %s", glob_pattern, strerror(errno) );
} else {
Debug( 1, "Can't glob '%s': %d", glob_pattern, glob_status );
}
} else {
for ( unsigned int i = 0; i < pglob.gl_pathc; i++ ) {
process_configfile(pglob.gl_pathv[i]);
}
closedir(configSubFolder);
}
globfree( &pglob );
}
zmDbConnect();
config.Load();
config.Assign();
// Populate the server config entries
if ( ! staticConfig.SERVER_ID ) {
if ( ! staticConfig.SERVER_NAME.empty() ) {
Debug( 1, "Fetching ZM_SERVER_ID For Name = %s", staticConfig.SERVER_NAME.c_str() );
std::string sql = stringtf("SELECT Id FROM Servers WHERE Name='%s'", staticConfig.SERVER_NAME.c_str() );
if ( MYSQL_ROW dbrow = zmDbFetchOne( sql.c_str() ) ) {
staticConfig.SERVER_ID = atoi(dbrow[0]);
} else {
Fatal("Can't get ServerId for Server %s", staticConfig.SERVER_NAME.c_str() );
}
} // end if has SERVER_NAME
} else if ( staticConfig.SERVER_NAME.empty() ) {
Debug( 1, "Fetching ZM_SERVER_NAME For Id = %d", staticConfig.SERVER_ID );
std::string sql = stringtf("SELECT Name FROM Servers WHERE Id='%d'", staticConfig.SERVER_ID );
if ( MYSQL_ROW dbrow = zmDbFetchOne( sql.c_str() ) ) {
staticConfig.SERVER_NAME = std::string(dbrow[0]);
} else {
Fatal("Can't get ServerName for Server ID %d", staticConfig.SERVER_ID );
}
if ( staticConfig.SERVER_ID ) {
Debug( 3, "Multi-server configuration detected. Server is %d.", staticConfig.SERVER_ID );
} else {
Debug( 3, "Single server configuration assumed because no Server ID or Name was specified." );
}
}
}
void process_configfile( char* configFile) {
FILE *cfg;
char line[512];
if ( (cfg = fopen( ZM_CONFIG, "r")) == NULL ) {
Fatal( "Can't open %s: %s", ZM_CONFIG, strerror(errno) );
if ( (cfg = fopen( configFile, "r")) == NULL ) {
Fatal( "Can't open %s: %s", configFile, strerror(errno) );
}
while ( fgets( line, sizeof(line), cfg ) != NULL ) {
char *line_ptr = line;
@ -58,7 +124,7 @@ void zmLoadConfig() {
// Now look for the '=' in the middle of the line
temp_ptr = strchr( line_ptr, '=' );
if ( !temp_ptr ) {
Warning( "Invalid data in %s: '%s'", ZM_CONFIG, line );
Warning( "Invalid data in %s: '%s'", configFile, line );
continue;
}
@ -99,38 +165,6 @@ void zmLoadConfig() {
}
} // end foreach line of the config
fclose( cfg );
zmDbConnect();
config.Load();
config.Assign();
// Populate the server config entries
if ( ! staticConfig.SERVER_ID ) {
if ( ! staticConfig.SERVER_NAME.empty() ) {
Debug( 1, "Fetching ZM_SERVER_ID For Name = %s", staticConfig.SERVER_NAME.c_str() );
std::string sql = stringtf("SELECT Id FROM Servers WHERE Name='%s'", staticConfig.SERVER_NAME.c_str() );
if ( MYSQL_ROW dbrow = zmDbFetchOne( sql.c_str() ) ) {
staticConfig.SERVER_ID = atoi(dbrow[0]);
} else {
Fatal("Can't get ServerId for Server %s", staticConfig.SERVER_NAME.c_str() );
}
} // end if has SERVER_NAME
} else if ( staticConfig.SERVER_NAME.empty() ) {
Debug( 1, "Fetching ZM_SERVER_NAME For Id = %d", staticConfig.SERVER_ID );
std::string sql = stringtf("SELECT Name FROM Servers WHERE Id='%d'", staticConfig.SERVER_ID );
if ( MYSQL_ROW dbrow = zmDbFetchOne( sql.c_str() ) ) {
staticConfig.SERVER_NAME = std::string(dbrow[0]);
} else {
Fatal("Can't get ServerName for Server ID %d", staticConfig.SERVER_ID );
}
if ( staticConfig.SERVER_ID ) {
Debug( 3, "Multi-server configuration detected. Server is %d.", staticConfig.SERVER_ID );
} else {
Debug( 3, "Single server configuration assumed because no Server ID or Name was specified." );
}
}
}
StaticConfig staticConfig;

View File

@ -26,6 +26,7 @@
#include <string>
#define ZM_CONFIG "@ZM_CONFIG@" // Path to config file
#define ZM_CONFIG_SUBDIR "@ZM_CONFIG_SUBDIR@" // Path to the ZoneMinder config subfolder
#define ZM_VERSION "@VERSION@" // ZoneMinder Version
#define ZM_HAS_V4L1 @ZM_HAS_V4L1@
@ -58,6 +59,8 @@
extern void zmLoadConfig();
extern void process_configfile( char* configFile );
struct StaticConfig
{
std::string DB_HOST;

View File

@ -643,7 +643,7 @@ bool EventStream::loadInitialEventData( int init_event_id, unsigned int init_fra
bool EventStream::loadEventData( int event_id ) {
static char sql[ZM_SQL_MED_BUFSIZ];
snprintf( sql, sizeof(sql), "select MonitorId, Frames, unix_timestamp( StartTime ) as StartTimestamp, (SELECT max(Delta)-min(Delta) FROM Frames WHERE EventId=Events.Id) as Duration, DefaultVideo from Events Id = %d", event_id );
snprintf( sql, sizeof(sql), "SELECT MonitorId, Frames, unix_timestamp( StartTime ) AS StartTimestamp, (SELECT max(Delta)-min(Delta) FROM Frames WHERE EventId=Events.Id) AS Duration, DefaultVideo FROM Events WHERE Id = %d", event_id );
if ( mysql_query( &dbconn, sql ) ) {
Error( "Can't run query: %s", mysql_error( &dbconn ) );

View File

@ -23,7 +23,7 @@
#include "zm_ffmpeg_camera.h"
extern "C"{
extern "C" {
#include "libavutil/time.h"
}
#ifndef AV_ERROR_MAX_STRING_SIZE
@ -125,8 +125,7 @@ int FfmpegCamera::PreCapture()
return( 0 );
}
int FfmpegCamera::Capture( Image &image )
{
int FfmpegCamera::Capture( Image &image ) {
if (!mCanCapture){
return -1;
}
@ -167,11 +166,8 @@ int FfmpegCamera::Capture( Image &image )
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...
if ( packet.stream_index == mVideoStreamId ) {
#if LIBAVCODEC_VERSION_CHECK(52, 23, 0, 23, 0)
if (avcodec_decode_video2(mVideoCodecContext, mRawFrame, &frameComplete, &packet) < 0)
#else
if (avcodec_decode_video(mVideoCodecContext, mRawFrame, &frameComplete, packet.data, packet.size) < 0)
#endif
int ret = zm_avcodec_decode_video( mVideoCodecContext, mRawFrame, &frameComplete, &packet );
if ( ret < 0 )
Fatal( "Unable to decode frame at frame %d", frameCount );
Debug( 4, "Decoded video packet at frame %d", frameCount );
@ -364,7 +360,7 @@ int FfmpegCamera::OpenFfmpeg() {
Fatal( "Unable to open codec for video stream from %s", mPath.c_str() );
}
if (mAudioStreamId >= 0) {
if ( mAudioStreamId >= 0 ) {
mAudioCodecContext = mFormatContext->streams[mAudioStreamId]->codec;
if ((mAudioCodec = avcodec_find_decoder(mAudioCodecContext->codec_id)) == NULL) {
Debug(1, "Can't find codec for audio stream from %s", mPath.c_str());
@ -437,7 +433,7 @@ int FfmpegCamera::OpenFfmpeg() {
mCanCapture = true;
return 0;
}
} // int FfmpegCamera::OpenFfmpeg()
int FfmpegCamera::ReopenFfmpeg() {
@ -462,8 +458,7 @@ int FfmpegCamera::CloseFfmpeg(){
av_frame_free( &mRawFrame );
#if HAVE_LIBSWSCALE
if ( mConvertContext )
{
if ( mConvertContext ) {
sws_freeContext( mConvertContext );
mConvertContext = NULL;
}
@ -490,8 +485,7 @@ int FfmpegCamera::CloseFfmpeg(){
return 0;
}
int FfmpegCamera::FfmpegInterruptCallback(void *ctx)
{
int FfmpegCamera::FfmpegInterruptCallback(void *ctx) {
FfmpegCamera* camera = reinterpret_cast<FfmpegCamera*>(ctx);
if (camera->mIsOpening){
int now = time(NULL);
@ -529,14 +523,14 @@ void *FfmpegCamera::ReopenFfmpegThreadCallback(void *ctx){
//Function to handle capture and store
int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event_file ) {
if (!mCanCapture){
if ( ! mCanCapture ) {
return -1;
}
int ret;
static char errbuf[AV_ERROR_MAX_STRING_SIZE];
// If the reopen thread has a value, but mCanCapture != 0, then we have just reopened the connection to the ffmpeg device, and we can clean up the thread.
if (mReopenThread != 0) {
if ( mReopenThread != 0 ) {
void *retval = 0;
ret = pthread_join(mReopenThread, &retval);
@ -548,7 +542,7 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
mReopenThread = 0;
}
if (mVideoCodecContext->codec_id != AV_CODEC_ID_H264) {
if ( mVideoCodecContext->codec_id != AV_CODEC_ID_H264 ) {
Error( "Input stream is not h264. The stored event file may not be viewable in browser." );
}
@ -639,6 +633,7 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
unsigned int packet_count = 0;
ZMPacket *queued_packet;
// Clear all packets that predate the moment when the recording began
packetqueue.clear_unwanted_packets( &recording, mVideoStreamId );
while ( ( queued_packet = packetqueue.popPacket() ) ) {
@ -673,7 +668,7 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
// Buffer video packets, since we are not recording.
// 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 ) {
Debug(3, "Clearing queue");
packetqueue.clearQueue( monitor->GetPreEventCount(), mVideoStreamId );
@ -688,18 +683,22 @@ else if ( packet.pts && video_last_pts > packet.pts ) {
}
#endif
}
if (
( packet.stream_index != mAudioStreamId || record_audio )
&&
( key_frame || packetqueue.size() )
) {
packetqueue.queuePacket( &packet );
// The following lines should ensure that the queue always begins with a video keyframe
if ( packet.stream_index == mAudioStreamId ) {
//Debug(2, "Have audio packet, reocrd_audio is (%d) and packetqueue.size is (%d)", record_audio, 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 );
}
} // end if recording or not
if ( packet.stream_index == mVideoStreamId ) {
if ( videoStore ) {
if ( videoStore ) {
//Write the packet to our video store
int ret = videoStore->writeVideoFramePacket( &packet );
if ( ret < 0 ) { //Less than zero and we skipped a frame
@ -779,8 +778,10 @@ else if ( packet.pts && video_last_pts > packet.pts ) {
return 0;
}
} else {
Debug(4, "Not recording audio packet" );
Debug(4, "Not doing recording of audio packet" );
}
} else {
Debug(4, "Have audio packet, but not recording atm" );
}
} else {
#if LIBAVUTIL_VERSION_CHECK(56, 23, 0, 23, 0)

View File

@ -60,14 +60,12 @@ ZMPacket* zm_packetqueue::popPacket( ) {
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;
if ( pktQueue.empty() ) {
Debug(3, "Queue is empty");
return 0;
} else {
Debug(3, "Queue has (%d)", pktQueue.size() );
}
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;
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
if ( ( av_packet->stream_index == stream_id) && ( av_packet->flags & AV_PKT_FLAG_KEY ) ) {
if (!frames_to_keep)
break;
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;
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();
pktQueue.pop_front();
@ -96,6 +95,7 @@ unsigned int zm_packetqueue::clearQueue( unsigned int frames_to_keep, int stream
delete_count += 1;
}
Debug(3, "Deleted (%d) packets", delete_count );
return delete_count;
} // 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
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 ) {
ZMPacket *zm_packet = *it;
AVPacket *av_packet = &(zm_packet->packet);
Debug(1, "Looking for keyframe after start" );
if (
( av_packet->flags & AV_PKT_FLAG_KEY )
&&
@ -134,7 +134,7 @@ Debug(1, "Looking for keyframe after start" );
&&
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;
}
}
@ -143,10 +143,29 @@ Debug(1, "Found keyframe before start" );
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;
while ( pktQueue.rend() != it ) {
while ( distance( it, pktQueue.rend() ) > 1 ) {
//while ( pktQueue.rend() != it ) {
packet = pktQueue.front();
pktQueue.pop_front();
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

@ -171,7 +171,7 @@ User *zmLoadAuthUser( const char *auth, bool use_remote_addr )
Debug( 1, "Attempting to authenticate user from auth string '%s'", auth );
char sql[ZM_SQL_SML_BUFSIZ] = "";
snprintf( sql, sizeof(sql), "select Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds from Users where Enabled = 1" );
snprintf( sql, sizeof(sql), "SELECT Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds FROM Users WHERE Enabled = 1" );
if ( mysql_query( &dbconn, sql ) )
{
@ -232,7 +232,7 @@ User *zmLoadAuthUser( const char *auth, bool use_remote_addr )
{
sprintf( &auth_md5[2*j], "%02x", md5sum[j] );
}
Debug( 1, "Checking auth_key '%s' -> auth_md5 '%s'", auth_key, auth_md5 );
Debug( 1, "Checking auth_key '%s' -> auth_md5 '%s' == '%s'", auth_key, auth_md5, auth );
if ( !strcmp( auth, auth_md5 ) )
{
@ -246,5 +246,6 @@ User *zmLoadAuthUser( const char *auth, bool use_remote_addr )
#else // HAVE_DECL_MD5
Error( "You need to build with gnutls or openssl installed to use hash based authentication" );
#endif // HAVE_DECL_MD5
Debug(1, "No user found for auth_key %s", auth );
return( 0 );
}

View File

@ -27,7 +27,7 @@
#include "zm.h"
#include "zm_videostore.h"
extern "C"{
extern "C" {
#include "libavutil/time.h"
}
@ -37,23 +37,23 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
int64_t nStartTime,
Monitor * monitor
) {
video_input_stream = p_video_input_stream;
audio_input_stream = p_audio_input_stream;
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
video_input_context = avcodec_alloc_context3( NULL );
avcodec_parameters_to_context( video_input_context, video_input_stream->codecpar );
#else
video_input_context = video_input_stream->codec;
#endif
//store inputs in variables local to class
filename = filename_in;
format = format_in;
keyframeMessage = false;
keyframeSkipNumber = 0;
Info("Opening video storage stream %s format: %s\n", filename, format);
//Init everything we need, shouldn't have to do this, ffmpeg_camera or something else will call it.
//av_register_all();
ret = avformat_alloc_output_context2(&oc, NULL, NULL, filename);
if ( ret < 0 ) {
Warning("Could not create video storage stream %s as no output context"
@ -62,11 +62,11 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
av_make_error_string(ret).c_str()
);
} else {
Debug(2, "Success alocateing output context");
Debug(2, "Success allocating output context");
}
//Couldn't deduce format from filename, trying from format name
if (!oc) {
if ( ! oc ) {
avformat_alloc_output_context2(&oc, NULL, format, filename);
if (!oc) {
Fatal("Could not create video storage stream %s as no output context"
@ -82,29 +82,47 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
if (dsr < 0) Warning("%s:%d: title set failed", __FILE__, __LINE__ );
oc->metadata = pmetadata;
output_format = oc->oformat;
video_output_stream = avformat_new_stream(oc, (AVCodec*)video_input_context->codec);
if (!video_output_stream) {
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
// Since we are not re-encoding, all we have to do is copy the parameters
video_output_context = avcodec_alloc_context3( NULL );
// Copy params from inputstream to context
ret = avcodec_parameters_to_context( video_output_context, video_input_stream->codecpar );
if ( ret < 0 ) {
Error( "Could not initialize context parameteres");
return;
} else {
Debug( 2, "Success getting parameters");
}
video_output_stream = avformat_new_stream( oc, NULL );
if ( ! video_output_stream ) {
Fatal("Unable to create video out stream\n");
} else {
Debug(2, "Success creating video out stream" );
}
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 );
// Now copy them to the output stream
ret = avcodec_parameters_from_context( video_output_stream->codecpar, video_output_context );
if ( ret < 0 ) {
Error( "Could not initialize stream parameteres");
return;
} else {
Debug(2, "Success getting parameters");
Debug(2, "Success setting parameters");
}
zm_dump_stream_format( oc, 0, 0, 1 );
#else
ret = avcodec_copy_context(video_output_context, video_input_context );
video_output_stream = avformat_new_stream(oc, (AVCodec*)video_input_context->codec );
if ( ! video_output_stream ) {
Fatal("Unable to create video out stream\n");
} else {
Debug(2, "Success creating video out stream" );
}
video_output_context = video_output_stream->codec;
ret = avcodec_copy_context( video_output_context, video_input_context );
if (ret < 0) {
Fatal("Unable to copy input video context to output video context %s\n",
av_make_error_string(ret).c_str());
@ -130,7 +148,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
// WHY?
//video_output_context->codec_tag = 0;
if (!video_output_context->codec_tag) {
if ( ! video_output_context->codec_tag ) {
Debug(2, "No codec_tag");
if (! oc->oformat->codec_tag
|| av_codec_get_id (oc->oformat->codec_tag, video_input_context->codec_tag) == video_output_context->codec_id
@ -145,6 +163,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
}
Monitor::Orientation orientation = monitor->getOrientation();
Debug(3, "Have orientation" );
if ( orientation ) {
if ( orientation == Monitor::ROTATE_0 ) {
@ -169,13 +188,22 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
resample_context = NULL;
#endif
if (audio_input_stream) {
if ( audio_input_stream ) {
Debug(3, "Have audio stream" );
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
audio_input_context = avcodec_alloc_context3( NULL );
ret = avcodec_parameters_to_context( audio_input_context, audio_input_stream->codecpar );
#else
audio_input_context = audio_input_stream->codec;
#endif
if ( audio_input_context->codec_id != AV_CODEC_ID_AAC ) {
static char error_buffer[256];
avcodec_string(error_buffer, sizeof(error_buffer), audio_input_context, 0 );
Debug(3, "Got something other than AAC (%s)", error_buffer );
Debug(2, "Got something other than AAC (%s)", error_buffer );
if ( ! setup_resampler() ) {
return;
}
@ -187,9 +215,16 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
Error("Unable to create audio out stream\n");
audio_output_stream = NULL;
} else {
audio_output_context = audio_output_stream->codec;
Debug(2, "setting parameters");
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
audio_output_context = avcodec_alloc_context3( NULL );
// Copy params from inputstream to context
ret = avcodec_parameters_to_context( audio_output_context, audio_input_stream->codecpar );
#else
audio_output_context = audio_output_stream->codec;
ret = avcodec_copy_context(audio_output_context, audio_input_context);
#endif
if (ret < 0) {
Error("Unable to copy audio context %s\n", av_make_error_string(ret).c_str());
audio_output_stream = NULL;
@ -233,7 +268,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_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");
/* Write the stream header, if any. */
ret = avformat_write_header(oc, NULL);
@ -252,8 +288,10 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
video_last_dts = 0;
audio_last_pts = 0;
audio_last_dts = 0;
previous_pts = 0;
previous_dts = 0;
video_previous_pts = 0;
video_previous_dts = 0;
audio_previous_pts = 0;
audio_previous_dts = 0;
} // VideoStore::VideoStore
@ -262,14 +300,14 @@ VideoStore::~VideoStore(){
if ( audio_output_codec ) {
// Do we need to flush the outputs? I have no idea.
AVPacket pkt;
int got_packet;
int got_packet = 0;
av_init_packet(&pkt);
pkt.data = NULL;
pkt.size = 0;
int64_t size;
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 );
#else
ret = avcodec_encode_audio2( audio_output_context, &pkt, NULL, &got_packet );
@ -341,6 +379,18 @@ bool VideoStore::setup_resampler() {
#ifdef HAVE_LIBAVRESAMPLE
static char error_buffer[256];
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
// Newer ffmpeg wants to keep everything separate... so have to lookup our own decoder, can't reuse the one from the camera.
AVCodec *audio_input_codec = avcodec_find_decoder(audio_input_stream->codecpar->codec_id);
#else
AVCodec *audio_input_codec = avcodec_find_decoder(audio_input_context->codec_id);
#endif
ret = avcodec_open2( audio_input_context, audio_input_codec, NULL );
if ( ret < 0 ) {
Error("Can't open input codec!");
return false;
}
audio_output_codec = avcodec_find_encoder(AV_CODEC_ID_AAC);
if ( ! audio_output_codec ) {
Error("Could not find codec for AAC");
@ -348,8 +398,8 @@ bool VideoStore::setup_resampler() {
}
Debug(2, "Have audio output codec");
audio_output_stream = avformat_new_stream( oc, audio_output_codec );
audio_output_context = audio_output_stream->codec;
//audio_output_context = audio_output_stream->codec;
audio_output_context = avcodec_alloc_context3( audio_output_codec );
if ( ! audio_output_context ) {
Error( "could not allocate codec context for AAC\n");
@ -359,18 +409,15 @@ bool VideoStore::setup_resampler() {
Debug(2, "Have audio_output_context");
AVDictionary *opts = NULL;
av_dict_set(&opts, "strict", "experimental", 0);
/* put sample parameters */
audio_output_context->bit_rate = audio_input_context->bit_rate;
audio_output_context->sample_rate = audio_input_context->sample_rate;
audio_output_context->channels = audio_input_context->channels;
audio_output_context->channel_layout = audio_input_context->channel_layout;
audio_output_context->sample_fmt = audio_input_context->sample_fmt;
//audio_output_context->refcounted_frames = 1;
audio_output_context->refcounted_frames = 1;
if (audio_output_codec->supported_samplerates) {
if ( audio_output_codec->supported_samplerates ) {
int found = 0;
for ( unsigned int i = 0; audio_output_codec->supported_samplerates[i]; i++) {
if ( audio_output_context->sample_rate == audio_output_codec->supported_samplerates[i] ) {
@ -387,36 +434,14 @@ bool VideoStore::setup_resampler() {
}
/* check that the encoder supports s16 pcm input */
if (!check_sample_fmt( audio_output_codec, audio_output_context->sample_fmt)) {
if ( ! check_sample_fmt( audio_output_codec, audio_output_context->sample_fmt ) ) {
Debug( 3, "Encoder does not support sample format %s, setting to FLTP",
av_get_sample_fmt_name( audio_output_context->sample_fmt));
audio_output_context->sample_fmt = AV_SAMPLE_FMT_FLTP;
}
//audio_output_stream->time_base = audio_input_stream->time_base;
audio_output_context->time_base = (AVRational){ 1, audio_output_context->sample_rate };
Debug(3, "Audio Time bases input stream (%d/%d) input codec: (%d/%d) output_stream (%d/%d) output codec (%d/%d)",
audio_input_stream->time_base.num,
audio_input_stream->time_base.den,
audio_input_context->time_base.num,
audio_input_context->time_base.den,
audio_output_stream->time_base.num,
audio_output_stream->time_base.den,
audio_output_context->time_base.num,
audio_output_context->time_base.den
);
ret = avcodec_open2(audio_output_context, audio_output_codec, &opts );
av_dict_free(&opts);
if ( ret < 0 ) {
av_strerror(ret, error_buffer, sizeof(error_buffer));
Fatal( "could not open codec (%d) (%s)\n", ret, error_buffer );
audio_output_codec = NULL;
audio_output_context = NULL;
audio_output_stream = NULL;
return false;
}
Debug(1, "Audio output bit_rate (%d) sample_rate(%d) channels(%d) fmt(%d) layout(%d) frame_size(%d)",
audio_output_context->bit_rate,
@ -427,7 +452,30 @@ bool VideoStore::setup_resampler() {
audio_output_context->frame_size
);
output_frame_size = audio_output_context->frame_size;
// Now copy them to the output stream
audio_output_stream = avformat_new_stream( oc, audio_output_codec );
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
ret = avcodec_parameters_from_context( audio_output_stream->codecpar, audio_output_context );
if ( ret < 0 ) {
Error( "Could not initialize stream parameteres");
return false;
}
#endif
AVDictionary *opts = NULL;
av_dict_set( &opts, "strict", "experimental", 0);
ret = avcodec_open2( audio_output_context, audio_output_codec, &opts );
av_dict_free(&opts);
if ( ret < 0 ) {
av_strerror(ret, error_buffer, sizeof(error_buffer));
Fatal( "could not open codec (%d) (%s)\n", ret, error_buffer );
audio_output_codec = NULL;
audio_output_context = NULL;
audio_output_stream = NULL;
return false;
}
/** Create a new frame to store the audio samples. */
if (!(input_frame = zm_av_frame_alloc())) {
Error("Could not allocate input frame");
@ -562,9 +610,9 @@ int VideoStore::writeVideoFramePacket( AVPacket *ipkt ) {
if ( ipkt->pts < video_last_pts ) {
Debug(1, "Resetting video_last_pts from (%d) to (%d)", video_last_pts, ipkt->pts );
// wrap around, need to figure out the distance FIXME having this wrong should cause a jump, but then play ok?
opkt.pts = previous_pts + av_rescale_q( ipkt->pts, video_input_stream->time_base, video_output_stream->time_base);
opkt.pts = video_previous_pts + av_rescale_q( ipkt->pts, video_input_stream->time_base, video_output_stream->time_base);
} else {
opkt.pts = previous_pts + av_rescale_q( ipkt->pts - video_last_pts, video_input_stream->time_base, video_output_stream->time_base);
opkt.pts = video_previous_pts + av_rescale_q( ipkt->pts - video_last_pts, video_input_stream->time_base, video_output_stream->time_base);
}
}
Debug(3, "opkt.pts = %d from ipkt->pts(%d) - last_pts(%d)", opkt.pts, ipkt->pts, video_last_pts );
@ -588,24 +636,20 @@ int VideoStore::writeVideoFramePacket( AVPacket *ipkt ) {
// why are we using cur_dts instead of packet.dts? I think cur_dts is in AV_TIME_BASE_Q, but ipkt.dts is in video_input_stream->time_base
if ( video_input_stream->cur_dts < video_last_dts ) {
Debug(1, "Resetting video_last_dts from (%d) to (%d) p.dts was (%d)", video_last_dts, video_input_stream->cur_dts, ipkt->dts );
opkt.dts = previous_dts + av_rescale_q(video_input_stream->cur_dts, AV_TIME_BASE_Q, video_output_stream->time_base);
opkt.dts = video_previous_dts + av_rescale_q(video_input_stream->cur_dts, AV_TIME_BASE_Q, video_output_stream->time_base);
} else {
opkt.dts = previous_dts + av_rescale_q(video_input_stream->cur_dts - video_last_dts, AV_TIME_BASE_Q, video_output_stream->time_base);
opkt.dts = video_previous_dts + av_rescale_q(video_input_stream->cur_dts - video_last_dts, AV_TIME_BASE_Q, video_output_stream->time_base);
}
Debug(3, "opkt.dts = %d from video_input_stream->cur_dts(%d) - previus_dts(%d)",
opkt.dts, video_input_stream->cur_dts, video_last_dts
);
Debug(3, "opkt.dts = %d from video_input_stream->cur_dts(%d) - previus_dts(%d)", opkt.dts, video_input_stream->cur_dts, video_last_dts );
video_last_dts = video_input_stream->cur_dts;
} else {
if ( ipkt->dts < video_last_dts ) {
Debug(1, "Resetting video_last_dts from (%d) to (%d)", video_last_dts, ipkt->dts );
opkt.dts = previous_dts + av_rescale_q( ipkt->dts, video_input_stream->time_base, video_output_stream->time_base);
opkt.dts = video_previous_dts + av_rescale_q( ipkt->dts, video_input_stream->time_base, video_output_stream->time_base);
} else {
opkt.dts = previous_dts + av_rescale_q( ipkt->dts - video_last_dts, video_input_stream->time_base, video_output_stream->time_base);
opkt.dts = video_previous_dts + av_rescale_q( ipkt->dts - video_last_dts, video_input_stream->time_base, video_output_stream->time_base);
}
Debug(3, "opkt.dts = %d from ipkt.dts(%d) - previus_dts(%d)",
opkt.dts, ipkt->dts, video_last_dts
);
Debug(3, "opkt.dts = %d from ipkt.dts(%d) - previus_dts(%d)", opkt.dts, ipkt->dts, video_last_dts );
video_last_dts = ipkt->dts;
}
}
@ -642,15 +686,15 @@ Debug(1, "writing video packet pts(%d) dts(%d) duration(%d)", opkt.pts, opkt.dts
dumpPacket( ipkt);
dumpPacket(&opkt);
} else if ((previous_dts > 0) && (previous_dts > opkt.dts)) {
Warning("%s:%d: DTS out of order: %lld \u226E %lld; discarding frame", __FILE__, __LINE__, previous_dts, opkt.dts);
previous_dts = opkt.dts;
} else if ((video_previous_dts > 0) && (video_previous_dts > opkt.dts)) {
Warning("%s:%d: DTS out of order: %lld \u226E %lld; discarding frame", __FILE__, __LINE__, video_previous_dts, opkt.dts);
video_previous_dts = opkt.dts;
dumpPacket(&opkt);
} else {
previous_dts = opkt.dts; // Unsure if av_interleaved_write_frame() clobbers opkt.dts when out of order, so storing in advance
previous_pts = opkt.pts;
video_previous_dts = opkt.dts; // Unsure if av_interleaved_write_frame() clobbers opkt.dts when out of order, so storing in advance
video_previous_pts = opkt.pts;
ret = av_interleaved_write_frame(oc, &opkt);
if(ret<0){
// There's nothing we can really do if the frame is rejected, just drop it and get on with the next
@ -663,21 +707,20 @@ Debug(1, "writing video packet pts(%d) dts(%d) duration(%d)", opkt.pts, opkt.dts
return 0;
}
} // end int VideoStore::writeVideoFramePacket( AVPacket *ipkt )
int VideoStore::writeAudioFramePacket( AVPacket *ipkt ) {
Debug(4, "writeAudioFrame");
if(!audio_output_stream) {
if ( ! audio_output_stream ) {
Debug(1, "Called writeAudioFramePacket when no audio_output_stream");
return 0;//FIXME -ve return codes do not free packet in ffmpeg_camera at the moment
}
if ( audio_output_codec ) {
#ifdef HAVE_LIBAVRESAMPLE
#if 0
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
ret = avcodec_send_packet( audio_input_context, ipkt );
if ( ret < 0 ) {
Error("avcodec_send_packet fail %s", av_make_error_string(ret).c_str());
@ -696,26 +739,7 @@ int VideoStore::writeAudioFramePacket( AVPacket *ipkt ) {
input_frame->channel_layout,
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
/**
* Decode the audio frame stored in the packet.
* The input audio stream decoder is used to do this.
@ -728,15 +752,13 @@ int VideoStore::writeAudioFramePacket( AVPacket *ipkt ) {
av_make_error_string(ret).c_str());
dumpPacket( ipkt );
av_frame_free( &input_frame );
zm_av_packet_unref( &opkt );
return 0;
}
if ( ! data_present ) {
Debug(2, "Not ready to transcode a frame yet.");
zm_av_packet_unref(&opkt);
return 0;
}
#endif
int frame_size = input_frame->nb_samples;
Debug(4, "Frame size: %d", frame_size );
@ -778,11 +800,22 @@ int VideoStore::writeAudioFramePacket( AVPacket *ipkt ) {
* Encode the audio frame and store it in the temporary packet.
* 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_send_frame( audio_output_context, output_frame ) ) < 0 ) {
Error( "Could not send frame (error '%s')",
av_make_error_string(ret).c_str());
zm_av_packet_unref(&opkt);
return 0;
}
if (( ret = avcodec_receive_packet( audio_output_context, &opkt )) < 0 ) {
Error( "Could not recieve packet (error '%s')",
av_make_error_string(ret).c_str());
zm_av_packet_unref(&opkt);
return 0;
}
#else
if (( ret = avcodec_encode_audio2( audio_output_context, &opkt, output_frame, &data_present )) < 0) {
#endif
Error( "Could not encode frame (error '%s')",
av_make_error_string(ret).c_str());
zm_av_packet_unref(&opkt);
@ -793,8 +826,8 @@ int VideoStore::writeAudioFramePacket( AVPacket *ipkt ) {
zm_av_packet_unref(&opkt);
return 0;
}
#endif
#endif
} else {
av_init_packet(&opkt);
@ -807,14 +840,17 @@ int VideoStore::writeAudioFramePacket( AVPacket *ipkt ) {
//Scale the PTS of the outgoing packet to be the correct time base
if ( ipkt->pts != AV_NOPTS_VALUE ) {
if ( !audio_last_pts ) {
if ( ! audio_last_pts ) {
opkt.pts = 0;
Debug(1, "No audio_last_pts");
} else {
if ( audio_last_pts > ipkt->pts ) {
Debug(1, "Resetting audeo_start_pts from (%d) to (%d)", audio_last_pts, ipkt->pts );
opkt.pts = audio_previous_pts + av_rescale_q(ipkt->pts, audio_input_stream->time_base, audio_output_stream->time_base);
} else {
opkt.pts = audio_previous_pts + av_rescale_q(ipkt->pts - audio_last_pts, audio_input_stream->time_base, audio_output_stream->time_base);
}
opkt.pts = previous_pts + av_rescale_q(ipkt->pts - audio_last_pts, audio_input_stream->time_base, audio_output_stream->time_base);
Debug(2, "opkt.pts = %d from ipkt->pts(%d) - last_pts(%d)", opkt.pts, ipkt->pts, audio_last_pts );
Debug(2, "audio opkt.pts = %d from ipkt->pts(%d) - last_pts(%d)", opkt.pts, ipkt->pts, audio_last_pts );
}
audio_last_pts = ipkt->pts;
} else {
@ -825,28 +861,30 @@ int VideoStore::writeAudioFramePacket( AVPacket *ipkt ) {
//Scale the DTS of the outgoing packet to be the correct time base
if ( ! audio_last_dts ) {
opkt.dts = 0;
} else {
if( ipkt->dts == AV_NOPTS_VALUE ) {
// So if the input has no dts assigned... still need an output dts... so we use cur_dts?
if ( audio_last_dts > audio_input_stream->cur_dts ) {
Debug(1, "Resetting audio_last_pts from (%d) to cur_dts (%d)", audio_last_dts, audio_input_stream->cur_dts );
opkt.dts = previous_dts + av_rescale_q( audio_input_stream->cur_dts, AV_TIME_BASE_Q, audio_output_stream->time_base);
Debug(1, "Resetting audio_last_dts from (%d) to cur_dts (%d)", audio_last_dts, audio_input_stream->cur_dts );
opkt.dts = audio_previous_dts + av_rescale_q( audio_input_stream->cur_dts, AV_TIME_BASE_Q, audio_output_stream->time_base);
} else {
opkt.dts = previous_dts + av_rescale_q( audio_input_stream->cur_dts - audio_last_dts, AV_TIME_BASE_Q, audio_output_stream->time_base);
opkt.dts = audio_previous_dts + av_rescale_q( audio_input_stream->cur_dts - audio_last_dts, AV_TIME_BASE_Q, audio_output_stream->time_base);
}
audio_last_dts = audio_input_stream->cur_dts;
Debug(2, "opkt.dts = %d from video_input_stream->cur_dts(%d) - last_dts(%d)", opkt.dts, audio_input_stream->cur_dts, audio_last_dts );
} else {
if ( audio_last_dts > ipkt->dts ) {
Debug(1, "Resetting audio_last_dts from (%d) to (%d)", audio_last_dts, ipkt->dts );
opkt.dts = previous_dts + av_rescale_q(ipkt->dts, audio_input_stream->time_base, audio_output_stream->time_base);
opkt.dts = audio_previous_dts + av_rescale_q(ipkt->dts, audio_input_stream->time_base, audio_output_stream->time_base);
} else {
opkt.dts = previous_dts + av_rescale_q(ipkt->dts - audio_last_dts, audio_input_stream->time_base, audio_output_stream->time_base);
opkt.dts = audio_previous_dts + av_rescale_q(ipkt->dts - audio_last_dts, audio_input_stream->time_base, audio_output_stream->time_base);
}
Debug(2, "opkt.dts = %d from ipkt->dts(%d) - last_dts(%d)", opkt.dts, ipkt->dts, audio_last_dts );
}
}
audio_last_dts = ipkt->dts;
if ( opkt.dts > opkt.pts ) {
Debug(1,"opkt.dts(%d) must be <= opkt.pts(%d). Decompression must happen before presentation.", opkt.dts, opkt.pts );
opkt.dts = opkt.pts;
@ -854,15 +892,17 @@ int VideoStore::writeAudioFramePacket( AVPacket *ipkt ) {
// I wonder if we could just use duration instead of all the hoop jumping above?
opkt.duration = av_rescale_q(ipkt->duration, audio_input_stream->time_base, audio_output_stream->time_base);
Debug( 2, "opkt.pts (%d), opkt.dts(%d) opkt.duration = (%d)", opkt.pts, opkt.dts, opkt.duration );
// pkt.pos: byte position in stream, -1 if unknown
opkt.pos = -1;
opkt.flags = ipkt->flags;
opkt.stream_index = ipkt->stream_index;
Debug(2, "Stream index is %d", opkt.stream_index );
AVPacket safepkt;
memcpy(&safepkt, &opkt, sizeof(AVPacket));
audio_previous_dts = opkt.dts; // Unsure if av_interleaved_write_frame() clobbers opkt.dts when out of order, so storing in advance
audio_previous_pts = opkt.pts;
ret = av_interleaved_write_frame(oc, &opkt);
if(ret!=0){
Error("Error writing audio frame packet: %s\n", av_make_error_string(ret).c_str());

View File

@ -46,7 +46,7 @@ private:
#ifdef HAVE_LIBAVRESAMPLE
AVAudioResampleContext* resample_context;
#endif
uint8_t *converted_input_samples = NULL;
uint8_t *converted_input_samples;
const char *filename;
const char *format;
@ -61,8 +61,10 @@ AVAudioResampleContext* resample_context;
int64_t audio_last_dts;
// These are for output, should start at zero. We assume they do not wrap because we just aren't going to save files that big.
int64_t previous_pts;
int64_t previous_dts;
int64_t video_previous_pts;
int64_t video_previous_dts;
int64_t audio_previous_pts;
int64_t audio_previous_dts;
int64_t filter_in_rescale_delta_last;

View File

@ -163,7 +163,7 @@ int main( int argc, char *argv[] )
if ( analysis_update_delay )
{
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();
monitor->UpdateAdaptiveSkip();

View File

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

View File

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

View File

@ -35,7 +35,7 @@ done
service apache2 restart
# Start ZoneMinder
/usr/local/bin/zmpkg.pl start
/usr/local/bin/zmpkg.pl start && echo "Zone Minder started"
while :
do

View File

@ -36,7 +36,46 @@ checksanity () {
echo
exit 1
fi
}
# Create key variables used to assemble the package name
createvars () {
# We need today's date in year/month/day format
thedate=$(date +%Y%m%d)
# We need the (short) commit hash of the latest commit (rpm packaging only)
shorthash=$(git describe --long --always | awk -F - '{print $3}')
# Grab the ZoneMinder version from the contents of the version file
versionfile=$(cat version)
# git the latest (short) commit hash of the version file
versionhash=$(git log -n1 --pretty=format:%h version)
# Number of commits since the version file was last changed
numcommits=$(git rev-list ${versionhash}..HEAD --count)
}
# Check key variables before calling packpack
checkvars () {
for var in $thedate $shorthash $versionfile $versionhash $numcommits; do
if [ -z ${var} ]; then
echo
echo "FATAL: This script was unable to determine one or more key variables. Cannot continue."
echo
echo "VARIABLE DUMP"
echo "-------------"
echo
echo "thedate: ${thedate}"
echo "shorthash: ${shorthash}"
echo "versionfile: ${versionfile}"
echo "versionhash: ${versionhash}"
echo "numcommits: ${numcommits}"
echo
exit 98
fi
done
}
# Steps common to all builds
@ -46,7 +85,7 @@ commonprep () {
echo "Checking packpack github repo for changes..."
git -C packpack pull origin master
else
echo "Cloning pakcpack github repo..."
echo "Cloning packpack github repo..."
git clone https://github.com/packpack/packpack.git packpack
fi
@ -114,17 +153,18 @@ installtrusty () {
fi
}
# This sets the naming convention for the deb packages
setdebpkgver () {
# This sets the naming convention for the rpm packages
setrpmpkgname () {
# Set VERSION to x.xx.x+x e.g. 1.30.2+15
# the last x is number of commits since release
# Creates zoneminder packages in the format: zoneminder-{version}-{release}
zmver=$(git describe --long --always | sed -n 's/^\([0-9\.]*\)-\([0-9]*\)-\([a-z0-9]*\)/\1/p')
commitnum=$(git describe --long --always | sed -n 's/^\([0-9\.]*\)-\([0-9]*\)-\([a-z0-9]*\)/\2/p')
export VERSION="$zmver+$commitnum"
export RELEASE="${DIST}"
createvars
# Set VERSION to the contents of the version file e.g. 1.31.0
# Set RELEASE to 1.{number of commits}.{today's date}git{short hash of HEAD} e.g. 1.82.20170605gitg7ae0b4a
export VERSION="$versionfile"
export RELEASE="1.${numcommits}.${thedate}git${shorthash}"
checkvars
echo
echo "Packpack VERSION has been set to: ${VERSION}"
echo "Packpack RELEASE has been set to: ${RELEASE}"
@ -132,6 +172,45 @@ setdebpkgver () {
}
# This sets the naming convention for the deb packages
setdebpkgname () {
createvars
# Set VERSION to {zm version}~{today's date}.{number of commits} e.g. 1.31.0~20170605.82
# Set RELEASE to the packpack DIST variable e.g. Trusty
export VERSION="${versionfile}~${thedate}.${numcommits}"
export RELEASE="${DIST}"
checkvars
echo
echo "Packpack VERSION has been set to: ${VERSION}"
echo "Packpack RELEASE has been set to: ${RELEASE}"
echo
}
# This adds an entry to the rpm specfile changelog
setrpmchangelog () {
export CHANGELOG_NAME="Andrew Bauer"
export CHANGELOG_EMAIL="zonexpertconsulting@outlook.com"
export CHANGELOG_TEXT="Automated, development snapshot of git ${shorthash}"
}
# This adds an entry to the debian changelog
setdebchangelog () {
DATE=`date -R`
cat <<EOF > debian/changelog
zoneminder ($VERSION-${DIST}-1) unstable; urgency=low
*
-- Isaac Connor <iconnor@connortechnology.com> $DATE
EOF
}
################
# MAIN PROGRAM #
################
@ -148,16 +227,7 @@ if [ "${TRAVIS_EVENT_TYPE}" == "cron" ] || [ "${TRAVIS}" != "true" ]; then
if [ "${OS}" == "el" ] || [ "${OS}" == "fedora" ]; then
echo "Begin Redhat build..."
# Set VERSION to x.xx.x e.g. 1.30.2
# Set RELEASE to x where x is number of commits since release
# Creates zoneminder packages in the format: zoneminder-{version}-{release}
export VERSION=$(git describe --long --always | sed -n 's/^\([0-9\.]*\)-\([0-9]*\)-\([a-z0-9]*\)/\1/p')
export RELEASE=$(git describe --long --always | sed -n 's/^\([0-9\.]*\)-\([0-9]*\)-\([a-z0-9]*\)/\2/p')
echo
echo "Packpack VERSION has been set to: ${VERSION}"
echo "Packpack RELEASE has been set to: ${RELEASE}"
echo
setrpmpkgname
ln -sfT distros/redhat rpm
@ -182,6 +252,8 @@ if [ "${TRAVIS_EVENT_TYPE}" == "cron" ] || [ "${TRAVIS}" != "true" ]; then
exit 1
fi
setrpmchangelog
echo "Starting packpack..."
packpack/packpack -f utils/packpack/redhat_package.mk redhat_package
@ -189,7 +261,7 @@ if [ "${TRAVIS_EVENT_TYPE}" == "cron" ] || [ "${TRAVIS}" != "true" ]; then
elif [ "${OS}" == "debian" ] || [ "${OS}" == "ubuntu" ]; then
echo "Begin ${OS} ${DIST} build..."
setdebpkgver
setdebpkgname
movecrud
if [ "${DIST}" == "trusty" ] || [ "${DIST}" == "precise" ]; then
@ -199,7 +271,9 @@ if [ "${TRAVIS_EVENT_TYPE}" == "cron" ] || [ "${TRAVIS}" != "true" ]; then
else
ln -sfT distros/ubuntu1604 debian
fi
setdebchangelog
echo "Starting packpack..."
packpack/packpack
@ -213,11 +287,13 @@ elif [ "${OS}" == "ubuntu" ] && [ "${DIST}" == "trusty" ] && [ "${ARCH}" == "x86
echo "Begin Ubuntu Trusty build..."
commonprep
setdebpkgver
setdebpkgname
movecrud
ln -sfT distros/ubuntu1204 debian
setdebchangelog
echo "Starting packpack..."
packpack/packpack

View File

@ -1 +1 @@
1.30.4
1.31.0

View File

@ -1,119 +1,120 @@
<?php
if ( empty($_REQUEST['id']) && empty($_REQUEST['eids']) ) {
ajaxError( "No event id(s) supplied" );
ajaxError( 'No event id(s) supplied' );
}
if ( canView( 'Events' ) ) {
switch ( $_REQUEST['action'] ) {
case 'video' : {
if ( empty($_REQUEST['videoFormat']) ) {
ajaxError( "Video Generation Failure, no format given" );
} elseif ( empty($_REQUEST['rate']) ) {
ajaxError( "Video Generation Failure, no rate given" );
} elseif ( empty($_REQUEST['scale']) ) {
ajaxError( "Video Generation Failure, no scale given" );
} else {
$sql = 'SELECT E.*,M.Name AS MonitorName,M.DefaultRate,M.DefaultScale FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE E.Id = ?'.monitorLimitSql();
if ( !($event = dbFetchOne( $sql, NULL, array( $_REQUEST['id'] ) )) )
ajaxError( "Video Generation Failure, can't load event" );
else
if ( $videoFile = createVideo( $event, $_REQUEST['videoFormat'], $_REQUEST['rate'], $_REQUEST['scale'], !empty($_REQUEST['overwrite']) ) )
ajaxResponse( array( 'response'=>$videoFile ) );
else
ajaxError( "Video Generation Failed" );
}
$ok = true;
break;
switch ( $_REQUEST['action'] ) {
case 'video' :
{
if ( empty($_REQUEST['videoFormat']) ) {
ajaxError( 'Video Generation Failure, no format given' );
} elseif ( empty($_REQUEST['rate']) ) {
ajaxError( 'Video Generation Failure, no rate given' );
} elseif ( empty($_REQUEST['scale']) ) {
ajaxError( 'Video Generation Failure, no scale given' );
} else {
$sql = 'SELECT E.*,M.Name AS MonitorName,M.DefaultRate,M.DefaultScale FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE E.Id = ?'.monitorLimitSql();
if ( !($event = dbFetchOne( $sql, NULL, array( $_REQUEST['id'] ) )) )
ajaxError( "Video Generation Failure, can't load event" );
else
if ( $videoFile = createVideo( $event, $_REQUEST['videoFormat'], $_REQUEST['rate'], $_REQUEST['scale'], !empty($_REQUEST['overwrite']) ) )
ajaxResponse( array( 'response'=>$videoFile ) );
else
ajaxError( "Video Generation Failed" );
}
case 'deleteVideo' :
{
unlink( $videoFiles[$_REQUEST['id']] );
unset( $videoFiles[$_REQUEST['id']] );
ajaxResponse();
break;
}
case "export" :
{
require_once( ZM_SKIN_PATH.'/includes/export_functions.php' );
$ok = true;
break;
}
case 'deleteVideo' :
{
unlink( $videoFiles[$_REQUEST['id']] );
unset( $videoFiles[$_REQUEST['id']] );
ajaxResponse();
break;
}
case 'export' :
{
require_once( ZM_SKIN_PATH.'/includes/export_functions.php' );
# We use session vars in here, so we need to restart the session because we stopped it in index.php to improve concurrency.
session_start();
# We use session vars in here, so we need to restart the session because we stopped it in index.php to improve concurrency.
session_start();
if ( !empty($_REQUEST['exportDetail']) )
$exportDetail = $_SESSION['export']['detail'] = $_REQUEST['exportDetail'];
else
$exportDetail = false;
if ( !empty($_REQUEST['exportFrames']) )
$exportFrames = $_SESSION['export']['frames'] = $_REQUEST['exportFrames'];
else
$exportFrames = false;
if ( !empty($_REQUEST['exportImages']) )
$exportImages = $_SESSION['export']['images'] = $_REQUEST['exportImages'];
else
$exportImages = false;
if ( !empty($_REQUEST['exportVideo']) )
$exportVideo = $_SESSION['export']['video'] = $_REQUEST['exportVideo'];
else
$exportVideo = false;
if ( !empty($_REQUEST['exportMisc']) )
$exportMisc = $_SESSION['export']['misc'] = $_REQUEST['exportMisc'];
else
$exportMisc = false;
if ( !empty($_REQUEST['exportFormat']) )
$exportFormat = $_SESSION['export']['format'] = $_REQUEST['exportFormat'];
else
$exportFormat = '';
if ( !empty($_REQUEST['exportDetail']) )
$exportDetail = $_SESSION['export']['detail'] = $_REQUEST['exportDetail'];
else
$exportDetail = false;
if ( !empty($_REQUEST['exportFrames']) )
$exportFrames = $_SESSION['export']['frames'] = $_REQUEST['exportFrames'];
else
$exportFrames = false;
if ( !empty($_REQUEST['exportImages']) )
$exportImages = $_SESSION['export']['images'] = $_REQUEST['exportImages'];
else
$exportImages = false;
if ( !empty($_REQUEST['exportVideo']) )
$exportVideo = $_SESSION['export']['video'] = $_REQUEST['exportVideo'];
else
$exportVideo = false;
if ( !empty($_REQUEST['exportMisc']) )
$exportMisc = $_SESSION['export']['misc'] = $_REQUEST['exportMisc'];
else
$exportMisc = false;
if ( !empty($_REQUEST['exportFormat']) )
$exportFormat = $_SESSION['export']['format'] = $_REQUEST['exportFormat'];
else
$exportFormat = '';
session_write_close();
session_write_close();
$exportIds = !empty($_REQUEST['eids'])?$_REQUEST['eids']:$_REQUEST['id'];
if ( $exportFile = exportEvents( $exportIds, $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc, $exportFormat ) )
ajaxResponse( array( 'exportFile'=>$exportFile ) );
else
ajaxError( "Export Failed" );
break;
}
}
$exportIds = !empty($_REQUEST['eids'])?$_REQUEST['eids']:$_REQUEST['id'];
if ( $exportFile = exportEvents( $exportIds, $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc, $exportFormat ) )
ajaxResponse( array( 'exportFile'=>$exportFile ) );
else
ajaxError( 'Export Failed' );
break;
}
}
}
if ( canEdit( 'Events' ) ) {
switch ( $_REQUEST['action'] ) {
case 'rename' :
{
if ( !empty($_REQUEST['eventName']) )
dbQuery( 'UPDATE Events SET Name = ? WHERE Id = ?', array( $_REQUEST['eventName'], $_REQUEST['id'] ) );
else
ajaxError( "No new event name supplied" );
ajaxResponse( array( 'refreshEvent'=>true, 'refreshParent'=>true ) );
break;
switch ( $_REQUEST['action'] ) {
case 'rename' :
{
if ( !empty($_REQUEST['eventName']) )
dbQuery( 'UPDATE Events SET Name = ? WHERE Id = ?', array( $_REQUEST['eventName'], $_REQUEST['id'] ) );
else
ajaxError( "No new event name supplied" );
ajaxResponse( array( 'refreshEvent'=>true, 'refreshParent'=>true ) );
break;
}
case 'eventdetail' :
{
dbQuery( 'UPDATE Events SET Cause = ?, Notes = ? WHERE Id = ?', array( $_REQUEST['newEvent']['Cause'], $_REQUEST['newEvent']['Notes'], $_REQUEST['id'] ) );
ajaxResponse( array( 'refreshEvent'=>true, 'refreshParent'=>true ) );
break;
}
case 'archive' :
case 'unarchive' :
{
$archiveVal = ($_REQUEST['action'] == 'archive')?1:0;
dbQuery( 'UPDATE Events SET Archived = ? WHERE Id = ?', array( $archiveVal, $_REQUEST['id']) );
ajaxResponse( array( 'refreshEvent'=>true, 'refreshParent'=>false ) );
break;
}
case 'delete' :
{
$Event = new Event( $_REQUEST['id'] );
if ( ! $Event->Id() ) {
ajaxResponse( array( 'refreshEvent'=>false, 'refreshParent'=>true, 'message'=> 'Event not found.' ) );
} else {
$Event->delete();
ajaxResponse( array( 'refreshEvent'=>false, 'refreshParent'=>true ) );
}
case 'eventdetail' :
{
dbQuery( 'UPDATE Events SET Cause = ?, Notes = ? WHERE Id = ?', array( $_REQUEST['newEvent']['Cause'], $_REQUEST['newEvent']['Notes'], $_REQUEST['id'] ) );
ajaxResponse( array( 'refreshEvent'=>true, 'refreshParent'=>true ) );
break;
}
case 'archive' :
case 'unarchive' :
{
$archiveVal = ($_REQUEST['action'] == "archive")?1:0;
dbQuery( 'UPDATE Events SET Archived = ? WHERE Id = ?', array( $archiveVal, $_REQUEST['id']) );
ajaxResponse( array( 'refreshEvent'=>true, 'refreshParent'=>false ) );
break;
}
case 'delete' :
{
$Event = new Event( $_REQUEST['id'] );
if ( ! $Event->Id() ) {
ajaxResponse( array( 'refreshEvent'=>false, 'refreshParent'=>true, 'message'=> 'Event not found.' ) );
} else {
$Event->delete();
ajaxResponse( array( 'refreshEvent'=>false, 'refreshParent'=>true ) );
}
break;
}
}
break;
}
}
}
ajaxError( 'Unrecognised action or insufficient permissions' );

View File

@ -29,12 +29,15 @@ class Event {
Error('No row for Event ' . $IdOrRow );
}
} // end function __construct
public function Storage() {
return new Storage( isset($this->{'StorageId'}) ? $this->{'StorageId'} : NULL );
}
public function Monitor() {
return new Monitor( isset($this->{'MonitorId'}) ? $this->{'MonitorId'} : NULL );
}
public function __call( $fn, array $args){
if ( array_key_exists( $fn, $this ) ) {
return $this->{$fn};
@ -54,6 +57,7 @@ class Event {
$Storage = $this->Storage();
return $Storage->Path().'/'.$this->Relative_Path();
}
public function Relative_Path() {
$event_path = '';
@ -133,28 +137,27 @@ class Event {
$streamSrc = ZM_BASE_URL.ZM_PATH_ZMS;
$args[] = 'source=event&event='.$this->{'Id'};
$args['source'] = 'event';
$args['event'] = $this->{'Id'};
if ( ZM_OPT_USE_AUTH ) {
if ( ZM_AUTH_RELAY == 'hashed' ) {
$args[] = 'auth='.generateAuthHash( ZM_AUTH_HASH_IPS );
$args['auth'] = generateAuthHash( ZM_AUTH_HASH_IPS );
} elseif ( ZM_AUTH_RELAY == 'plain' ) {
$args[] = 'user='.$_SESSION['username'];
$args[] = 'pass='.$_SESSION['password'];
$args['user'] = $_SESSION['username'];
$args['pass'] = $_SESSION['password'];
} elseif ( ZM_AUTH_RELAY == "none" ) {
$args[] = 'user='.$_SESSION['username'];
$args['user'] = $_SESSION['username'];
}
}
if ( !in_array( 'mode=single', $args ) && !empty($GLOBALS['connkey']) ) {
$args[] = 'connkey='.$GLOBALS['connkey'];
if ( ( (!isset($args['mode'])) or ( $args['mode'] != 'single' ) ) && !empty($GLOBALS['connkey']) ) {
$args['connkey'] = $GLOBALS['connkey'];
}
if ( ZM_RAND_STREAM ) {
$args[] = 'rand='.time();
$args['rand'] = time();
}
if ( count($args) ) {
$streamSrc .= '?'.join( $querySep, $args );
}
$streamSrc .= '?'.http_build_query( $args,'', $querySep );
return( $streamSrc );
} // end function getStreamSrc
@ -197,20 +200,26 @@ class Event {
return( $thumbData );
} // end function createListThumbnail
// frame is an array representing the db row for a frame.
function getImageSrc( $frame, $scale=SCALE_BASE, $captureOnly=false, $overwrite=false ) {
$Storage = new Storage( isset($this->{'StorageId'}) ? $this->{'StorageId'} : NULL );
$Event = $this;
$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'=>'' );
}
if ( file_exists( $eventPath.'/snapshot.jpg' ) ) {
$captImage = "snapshot.jpg";
if ( ( ! $frame ) and file_exists( $eventPath.'/snapshot.jpg' ) ) {
# No frame specified, so look for a snapshot to use
$captImage = 'snapshot.jpg';
Debug("Frame not specified, using snapshot");
} else {
$captImage = sprintf( '%0'.ZM_EVENT_IMAGE_DIGITS.'d-capture.jpg', $frame['FrameId'] );
if ( ! file_exists( $eventPath.'/'.$captImage ) ) {
# Generate the frame JPG
# Generate the frame JPG
if ( $Event->DefaultVideo() ) {
$videoPath = $eventPath.'/'.$Event->DefaultVideo();
@ -275,8 +284,7 @@ class Event {
}
$thumbFile = $thumbPath;
if ( $overwrite || !file_exists( $thumbFile ) || !filesize( $thumbFile ) )
{
if ( $overwrite || ! file_exists( $thumbFile ) || ! filesize( $thumbFile ) ) {
// Get new dimensions
list( $imageWidth, $imageHeight ) = getimagesize( $imagePath );
$thumbWidth = $imageWidth * $fraction;
@ -290,7 +298,7 @@ class Event {
if ( !imagejpeg( $thumbImage, $thumbPath ) )
Error( "Can't create thumbnail '$thumbPath'" );
}
}
} # Create thumbnails
$imageData = array(
'eventPath' => $eventPath,
@ -298,7 +306,7 @@ class Event {
'thumbPath' => $thumbPath,
'imageFile' => $imagePath,
'thumbFile' => $thumbFile,
'imageClass' => $alarmFrame?"alarm":"normal",
'imageClass' => $alarmFrame?'alarm':'normal',
'isAnalImage' => $isAnalImage,
'hasAnalImage' => $hasAnalImage,
);

View File

@ -27,9 +27,11 @@ class Frame {
Error("No row for Frame " . $IdOrRow );
}
} // end function __construct
public function Storage() {
return $this->Event()->Storage();
}
public function Event() {
return new Event( $this->{'EventId'} );
}
@ -70,7 +72,9 @@ class Frame {
}
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
public static function find( $parameters = array(), $limit = NULL ) {

View File

@ -198,9 +198,7 @@ private $control_fields = array(
$args['rand'] = time();
}
if ( count($args) ) {
$streamSrc .= '?'.http_build_query( $args,'', $querySep );
}
$streamSrc .= '?'.http_build_query( $args,'', $querySep );
return( $streamSrc );
} // end function getStreamSrc

View File

@ -22,6 +22,7 @@
// This section contains options substituted by the zmconfig.pl utility, do not edit these directly
//
define( "ZM_CONFIG", "@ZM_CONFIG@" ); // Path to config file
define( "ZM_CONFIG_SUBDIR", "@ZM_CONFIG_SUBDIR@" ); // Path to config subfolder
// Define, and override any given in config file
define( "ZM_VERSION", "@VERSION@" ); // Version
define( "ZM_DIR_TEMP", "@ZM_TMPDIR@" );
@ -36,19 +37,28 @@ if ( file_exists( $localConfigFile ) && filesize( $localConfigFile ) > 0 )
error_log( "Warning, overriding installed $localConfigFile file with local copy" );
$configFile = $localConfigFile;
}
$cfg = fopen( $configFile, "r") or die("Could not open config file.");
while ( !feof($cfg) )
{
$str = fgets( $cfg, 256 );
if ( preg_match( '/^\s*$/', $str ))
continue;
elseif ( preg_match( '/^\s*#/', $str ))
continue;
elseif ( preg_match( '/^\s*([^=\s]+)\s*=\s*(.*?)\s*$/', $str, $matches ))
define( $matches[1], $matches[2] );
# Process name, value pairs from the main config file first
$configvals = process_configfile($configFile);
# Search for user created config files. If one or more are found then
# update our config value array with those values
$configSubFolder = ZM_CONFIG_SUBDIR;
if ( is_dir($configSubFolder) ) {
if ( is_readable($configSubFolder) ) {
foreach ( glob("$configSubFolder/*.conf") as $filename ) {
$configvals = array_replace($configvals, process_configfile($filename) );
}
} else {
error_log( "WARNING: ZoneMinder configuration subfolder found but is not readable. Check folder permissions on $configSubFolder." );
}
}
# Now that our array our finalized, define each key => value
# pair in the array as a constant
foreach( $configvals as $key => $value) {
define( $key, $value );
}
fclose( $cfg );
//
// This section is options normally derived from other options or configuration
@ -189,5 +199,27 @@ if ( ! defined('ZM_SERVER_ID') ) {
}
}
function process_configfile($configFile) {
if ( is_readable( $configFile ) ) {
$configvals = array();
$cfg = fopen( $configFile, "r") or die("Could not open config file.");
while ( !feof($cfg) )
{
$str = fgets( $cfg, 256 );
if ( preg_match( '/^\s*$/', $str ))
continue;
elseif ( preg_match( '/^\s*#/', $str ))
continue;
elseif ( preg_match( '/^\s*([^=\s]+)\s*=\s*(.*?)\s*$/', $str, $matches ))
$configvals[$matches[1]] = $matches[2];
}
fclose( $cfg );
return( $configvals );
} else {
error_log( "WARNING: ZoneMinder configuration file found but is not readable. Check file permissions on $configFile." );
return( false );
}
}
?>

File diff suppressed because it is too large Load Diff

View File

@ -177,7 +177,7 @@ isset($view) || $view = NULL;
isset($request) || $request = 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\"");
csrf_check();
}

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

@ -21,31 +21,29 @@
// Only load new js & css in these views
$new_views = array('login');
function xhtmlHeaders( $file, $title )
{
global $css;
global $skin;
$skinCssFile = getSkinFile( 'css/'.$css.'/skin.css' );
$skinCssPhpFile = getSkinFile( 'css/'.$css.'/skin.css.php' );
function xhtmlHeaders( $file, $title ) {
global $css;
global $skin;
$skinCssFile = getSkinFile( 'css/'.$css.'/skin.css' );
$skinCssPhpFile = getSkinFile( 'css/'.$css.'/skin.css.php' );
$skinJsFile = getSkinFile( 'js/skin.js' );
$skinJsPhpFile = getSkinFile( 'js/skin.js.php' );
$cssJsFile = getSkinFile( 'js/'.$css.'.js' );
$skinJsFile = getSkinFile( 'js/skin.js' );
$skinJsPhpFile = getSkinFile( 'js/skin.js.php' );
$cssJsFile = getSkinFile( 'js/'.$css.'.js' );
$basename = basename( $file, '.php' );
$viewCssFile = getSkinFile( '/css/'.$css.'/views/'.$basename.'.css' );
$viewCssPhpFile = getSkinFile( '/css/'.$css.'/views/'.$basename.'.css.php' );
$viewJsFile = getSkinFile( 'views/js/'.$basename.'.js' );
$viewJsPhpFile = getSkinFile( 'views/js/'.$basename.'.js.php' );
$basename = basename( $file, '.php' );
$viewCssFile = getSkinFile( '/css/'.$css.'/views/'.$basename.'.css' );
$viewCssPhpFile = getSkinFile( '/css/'.$css.'/views/'.$basename.'.css.php' );
$viewJsFile = getSkinFile( 'views/js/'.$basename.'.js' );
$viewJsPhpFile = getSkinFile( 'views/js/'.$basename.'.js.php' );
extract( $GLOBALS, EXTR_OVERWRITE );
extract( $GLOBALS, EXTR_OVERWRITE );
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
<title><?php echo ZM_WEB_TITLE_PREFIX ?> - <?php echo validHtmlStr($title) ?></title>
<link rel="icon" type="image/ico" href="graphics/favicon.ico"/>
<link rel="shortcut icon" href="graphics/favicon.ico"/>
@ -56,19 +54,17 @@ function xhtmlHeaders( $file, $title )
<?php } ?>
<link rel="stylesheet" href="<?php echo $skinCssFile ?>" type="text/css" media="screen"/>
<?php
if ( $viewCssFile )
{
if ( $viewCssFile ) {
?>
<link rel="stylesheet" href="<?php echo $viewCssFile ?>" type="text/css" media="screen"/>
<?php
}
if ( $viewCssPhpFile )
{
}
if ( $viewCssPhpFile ) {
?>
<style type="text/css">
/*<![CDATA[*/
<?php
require_once( $viewCssPhpFile );
require_once( $viewCssPhpFile );
?>
/*]]>*/
</style>
@ -88,9 +84,9 @@ function xhtmlHeaders( $file, $title )
<script src="skins/<?php echo $skin ?>/js/video.js"></script>
<script src="./js/videojs.zoomrotate.js"></script>
<script src="skins/<?php echo $skin ?>/js/moment.min.js"></script>
<?php }
if ( $skinJsPhpFile )
{
<?php
}
if ( $skinJsPhpFile ) {
?>
<script type="text/javascript">
//<![CDATA[
@ -102,33 +98,31 @@ function xhtmlHeaders( $file, $title )
//]]>
</script>
<?php
}
if ( $viewJsPhpFile )
{
}
if ( $viewJsPhpFile ) {
?>
<script type="text/javascript">
//<![CDATA[
<!--
<?php
require_once( $viewJsPhpFile );
require_once( $viewJsPhpFile );
?>
//-->
//]]>
</script>
<?php
}
}
if ( $cssJsFile ) {
?>
<script type="text/javascript" src="<?php echo $cssJsFile ?>"></script>
<?php } ?>
<script type="text/javascript" src="<?php echo $skinJsFile ?>"></script>
<?php
if ( $viewJsFile )
{
if ( $viewJsFile ) {
?>
<script type="text/javascript" src="<?php echo $viewJsFile ?>"></script>
<?php
}
}
?>
</head>
<?php

View File

@ -23,49 +23,49 @@ $servers = Server::find_all();
$eventCounts = array(
array(
"title" => translate('Events'),
"filter" => array(
"terms" => array(
'title' => translate('Events'),
'filter' => array(
'terms' => array(
)
),
),
array(
"title" => translate('Hour'),
"filter" => array(
"terms" => array(
array( "attr" => "DateTime", "op" => ">=", "val" => "-1 hour" ),
'title' => translate('Hour'),
'filter' => array(
'terms' => array(
array( 'attr' => 'DateTime', 'op' => '>=', 'val' => '-1 hour' ),
)
),
),
array(
"title" => translate('Day'),
"filter" => array(
"terms" => array(
array( "attr" => "DateTime", "op" => ">=", "val" => "-1 day" ),
'title' => translate('Day'),
'filter' => array(
'terms' => array(
array( 'attr' => "DateTime", 'op' => '>=', 'val' => '-1 day' ),
)
),
),
array(
"title" => translate('Week'),
"filter" => array(
"terms" => array(
array( "attr" => "DateTime", "op" => ">=", "val" => "-7 day" ),
'title' => translate('Week'),
'filter' => array(
'terms' => array(
array( 'attr' => "DateTime", 'op' => '>=', 'val' => '-7 day' ),
)
),
),
array(
"title" => translate('Month'),
"filter" => array(
"terms" => array(
array( "attr" => "DateTime", "op" => ">=", "val" => "-1 month" ),
'title' => translate('Month'),
'filter' => array(
'terms' => array(
array( 'attr' => "DateTime", 'op' => '>=', 'val' => '-1 month' ),
)
),
),
array(
"title" => translate('Archived'),
"filter" => array(
"terms" => array(
array( "attr" => "Archived", "op" => "=", "val" => "1" ),
'title' => translate('Archived'),
'filter' => array(
'terms' => array(
array( 'attr' => "Archived", 'op' => '=', 'val' => '1' ),
)
),
),
@ -77,8 +77,8 @@ $run_state = dbFetchOne('select Name from States where IsActive = 1', 'Name' );
$group = NULL;
if ( ! empty($_COOKIE['zmGroup']) ) {
if ( $group = dbFetchOne( 'select * from Groups where Id = ?', NULL, array($_COOKIE['zmGroup'])) )
$groupIds = array_flip(explode( ',', $group['MonitorIds'] ));
if ( $group = dbFetchOne( 'select * from Groups where Id = ?', NULL, array($_COOKIE['zmGroup'])) )
$groupIds = array_flip(explode( ',', $group['MonitorIds'] ));
}
noCacheHeaders();
@ -91,69 +91,60 @@ $maxSequence = 1;
$seqIdList = array();
$monitors = dbFetchAll( "select * from Monitors order by Sequence asc" );
$displayMonitors = array();
for ( $i = 0; $i < count($monitors); $i++ )
{
if ( !visibleMonitor( $monitors[$i]['Id'] ) )
{
continue;
}
if ( $group && !empty($groupIds) && !array_key_exists( $monitors[$i]['Id'], $groupIds ) )
{
continue;
}
$monitors[$i]['Show'] = true;
if ( empty($minSequence) || ($monitors[$i]['Sequence'] < $minSequence) )
{
$minSequence = $monitors[$i]['Sequence'];
}
if ( $monitors[$i]['Sequence'] > $maxSequence )
{
$maxSequence = $monitors[$i]['Sequence'];
}
$monitors[$i]['zmc'] = zmcStatus( $monitors[$i] );
$monitors[$i]['zma'] = zmaStatus( $monitors[$i] );
$monitors[$i]['ZoneCount'] = dbFetchOne( 'select count(Id) as ZoneCount from Zones where MonitorId = ?', 'ZoneCount', array($monitors[$i]['Id']) );
$counts = array();
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'] ) );
parseFilter( $filter );
$counts[] = "count(if(1".$filter['sql'].",1,NULL)) as EventCount$j";
$monitors[$i]['eventCounts'][$j]['filter'] = $filter;
}
$sql = "select ".join($counts,", ")." from Events as E where MonitorId = ?";
$counts = dbFetchOne( $sql, NULL, array($monitors[$i]['Id']) );
if ( $monitors[$i]['Function'] != 'None' )
{
$cycleCount++;
$scaleWidth = reScale( $monitors[$i]['Width'], $monitors[$i]['DefaultScale'], ZM_WEB_DEFAULT_SCALE );
$scaleHeight = reScale( $monitors[$i]['Height'], $monitors[$i]['DefaultScale'], ZM_WEB_DEFAULT_SCALE );
if ( $maxWidth < $scaleWidth ) $maxWidth = $scaleWidth;
if ( $maxHeight < $scaleHeight ) $maxHeight = $scaleHeight;
}
if ( $counts ) $monitors[$i] = array_merge( $monitors[$i], $counts );
$seqIdList[] = $monitors[$i]['Id'];
$displayMonitors[] = $monitors[$i];
for ( $i = 0; $i < count($monitors); $i++ ) {
if ( !visibleMonitor( $monitors[$i]['Id'] ) ) {
continue;
}
if ( $group && !empty($groupIds) && !array_key_exists( $monitors[$i]['Id'], $groupIds ) ) {
continue;
}
$monitors[$i]['Show'] = true;
if ( empty($minSequence) || ($monitors[$i]['Sequence'] < $minSequence) ) {
$minSequence = $monitors[$i]['Sequence'];
}
if ( $monitors[$i]['Sequence'] > $maxSequence ) {
$maxSequence = $monitors[$i]['Sequence'];
}
$monitors[$i]['zmc'] = zmcStatus( $monitors[$i] );
$monitors[$i]['zma'] = zmaStatus( $monitors[$i] );
$monitors[$i]['ZoneCount'] = dbFetchOne( 'select count(Id) as ZoneCount from Zones where MonitorId = ?', 'ZoneCount', array($monitors[$i]['Id']) );
$counts = array();
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'] ) );
parseFilter( $filter );
$counts[] = 'count(if(1'.$filter['sql'].",1,NULL)) as EventCount$j";
$monitors[$i]['eventCounts'][$j]['filter'] = $filter;
}
$sql = 'SELECT '.join($counts,', ').' FROM Events AS E WHERE MonitorId = ?';
$counts = dbFetchOne( $sql, NULL, array($monitors[$i]['Id']) );
if ( $monitors[$i]['Function'] != 'None' ) {
$cycleCount++;
$scaleWidth = reScale( $monitors[$i]['Width'], $monitors[$i]['DefaultScale'], ZM_WEB_DEFAULT_SCALE );
$scaleHeight = reScale( $monitors[$i]['Height'], $monitors[$i]['DefaultScale'], ZM_WEB_DEFAULT_SCALE );
if ( $maxWidth < $scaleWidth ) $maxWidth = $scaleWidth;
if ( $maxHeight < $scaleHeight ) $maxHeight = $scaleHeight;
}
if ( $counts ) $monitors[$i] = array_merge( $monitors[$i], $counts );
$seqIdList[] = $monitors[$i]['Id'];
$displayMonitors[] = $monitors[$i];
}
$lastId = 0;
$seqIdUpList = array();
foreach ( $seqIdList as $seqId )
{
if ( !empty($lastId) )
$seqIdUpList[$seqId] = $lastId;
else
$seqIdUpList[$seqId] = $seqId;
$lastId = $seqId;
foreach ( $seqIdList as $seqId ) {
if ( !empty($lastId) )
$seqIdUpList[$seqId] = $lastId;
else
$seqIdUpList[$seqId] = $seqId;
$lastId = $seqId;
}
$lastId = 0;
$seqIdDownList = array();
foreach ( array_reverse($seqIdList) as $seqId )
{
if ( !empty($lastId) )
$seqIdDownList[$seqId] = $lastId;
else
$seqIdDownList[$seqId] = $seqId;
$lastId = $seqId;
foreach ( array_reverse($seqIdList) as $seqId ) {
if ( !empty($lastId) )
$seqIdDownList[$seqId] = $lastId;
else
$seqIdDownList[$seqId] = $seqId;
$lastId = $seqId;
}
$cycleWidth = $maxWidth;
@ -163,18 +154,15 @@ $eventsView = ZM_WEB_EVENTS_VIEW;
$eventsWindow = 'zm'.ucfirst(ZM_WEB_EVENTS_VIEW);
$eventCount = 0;
for ( $i = 0; $i < count($eventCounts); $i++ )
{
$eventCounts[$i]['total'] = 0;
for ( $i = 0; $i < count($eventCounts); $i++ ) {
$eventCounts[$i]['total'] = 0;
}
$zoneCount = 0;
foreach( $displayMonitors as $monitor )
{
for ( $i = 0; $i < count($eventCounts); $i++ )
{
$eventCounts[$i]['total'] += $monitor['EventCount'.$i];
}
$zoneCount += $monitor['ZoneCount'];
foreach( $displayMonitors as $monitor ) {
for ( $i = 0; $i < count($eventCounts); $i++ ) {
$eventCounts[$i]['total'] += $monitor['EventCount'.$i];
}
$zoneCount += $monitor['ZoneCount'];
}
$seqUpFile = getSkinFile( 'graphics/seq-u.png' );
@ -198,51 +186,40 @@ 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>
<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>
<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>
<?php
if ( ZM_OPT_X10 && canView( 'Devices' ) )
{
if ( ZM_OPT_X10 && canView( 'Devices' ) ) {
?>
<div id="devices"><?php echo makePopupLink( '?view=devices', 'zmDevices', 'devices', translate('Devices') ) ?></div>
<?php
}
if ( canView( 'System' ) )
{
if ( canView( 'System' ) ) {
?>
<div id="options"><?php echo makePopupLink( '?view=options', 'zmOptions', 'options', translate('Options') ) ?><?php if ( logToDatabase() > Logger::NOLOG ) { ?> / <?php echo makePopupLink( '?view=log', 'zmLog', 'log', '<span class="'.logState().'">'.translate('Log').'</span>' ) ?><?php } ?></div>
<?php
}
if ( canView( 'Stream' ) && $cycleCount > 1 )
{
if ( canView( 'Stream' ) && $cycleCount > 1 ) {
$cycleGroup = isset($_COOKIE['zmGroup'])?$_COOKIE['zmGroup']:0;
?>
<div id="cycleMontage">
<?php echo makePopupLink( '?view=cycle&amp;group='.$cycleGroup, 'zmCycle'.$cycleGroup, array( 'cycle', $cycleWidth, $cycleHeight ), translate('Cycle'), $running ) ?>&nbsp;/&nbsp;
<?php echo makePopupLink( '?view=montage&amp;group='.$cycleGroup, 'zmMontage'.$cycleGroup, 'montage', translate('Montage'), $running ) ?>&nbsp;/&nbsp;
<?php echo makePopupLink( '?view=montagereview&amp;group='.$cycleGroup, 'zmMontage'.$cycleGroup, 'montagereview', translate('Montage Review'), $running ) ?>
<?php echo makePopupLink( '?view=cycle&amp;group='.$cycleGroup, 'zmCycle'.$cycleGroup, array( 'cycle', $cycleWidth, $cycleHeight ), translate('Cycle'), $running ) ?>&nbsp;/&nbsp;
<?php echo makePopupLink( '?view=montage&amp;group='.$cycleGroup, 'zmMontage'.$cycleGroup, 'montage', translate('Montage'), $running ) ?>&nbsp;/&nbsp;
<?php echo makePopupLink( '?view=montagereview&amp;group='.$cycleGroup, 'zmMontage'.$cycleGroup, 'montagereview', translate('Montage Review'), $running ) ?>
</div>
<?php
}
else
{
?>
<?php
}
?>
<h3 id="loginBandwidth"><?php
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
}
else
{
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
} else {
?><?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>
</div>
<div id="content">
<table id="consoleTable" cellspacing="0">
<table id="consoleTable">
<thead>
<tr>
<?php if ( ZM_WEB_ID_ON_CONSOLE ) { ?>
@ -255,71 +232,46 @@ else
<?php } ?>
<th class="colSource"><?php echo translate('Source') ?></th>
<?php
for ( $i = 0; $i < count($eventCounts); $i++ )
{
for ( $i = 0; $i < count($eventCounts); $i++ ) {
?>
<th class="colEvents"><?php echo $eventCounts[$i]['title'] ?></th>
<?php
}
}
?>
<th class="colZones"><?php echo translate('Zones') ?></th>
<?php
if ( canEdit('Monitors') )
{
if ( canEdit('Monitors') ) {
?>
<th class="colOrder"><?php echo translate('Order') ?></th>
<?php
}
}
?>
<th class="colMark"><?php echo translate('Mark') ?></th>
</tr>
</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>
<?php
foreach( $displayMonitors as $monitor )
{
foreach( $displayMonitors as $monitor ) {
?>
<tr>
<?php
if ( !$monitor['zmc'] )
$dclass = "errorText";
else
{
if ( !$monitor['zmc'] ) {
$dclass = 'errorText';
} else {
// https://github.com/ZoneMinder/ZoneMinder/issues/1082
if ( !$monitor['zma'] && $monitor['Function']!='Monitor' )
$dclass = "warnText";
else
$dclass = "infoText";
if ( !$monitor['zma'] && $monitor['Function']!='Monitor' )
$dclass = 'warnText';
else
$dclass = 'infoText';
}
if ( $monitor['Function'] == 'None' )
$fclass = "errorText";
$fclass = 'errorText';
//elseif ( $monitor['Function'] == 'Monitor' )
// $fclass = "warnText";
// $fclass = 'warnText';
else
$fclass = "infoText";
$fclass = 'infoText';
if ( !$monitor['Enabled'] )
$fclass .= " disabledText";
$fclass .= ' disabledText';
$scale = max( reScale( SCALE_BASE, $monitor['DefaultScale'], ZM_WEB_DEFAULT_SCALE ), SCALE_BASE );
?>
<?php if ( ZM_WEB_ID_ON_CONSOLE ) { ?>
@ -343,7 +295,7 @@ echo $Server->Name();
$domain = parse_url( $monitor['Path'], PHP_URL_HOST );
$shortpath = $domain ? $domain : preg_replace( '/^.*\//', '', $monitor['Path'] );
if ( $shortpath == '' ) {
$shortpath = 'Monitor ' . $monitor['Id'];
$shortpath = 'Monitor ' . $monitor['Id'];
}
?>
<td class="colSource"><?php echo makePopupLink( '?view=monitor&amp;mid='.$monitor['Id'], 'zmMonitor'.$monitor['Id'], 'monitor', '<span class="'.$dclass.'">'.$shortpath.'</span>', canEdit( 'Monitors' ) ) ?></td>
@ -353,8 +305,7 @@ echo $Server->Name();
<td class="colSource">&nbsp;</td>
<?php } ?>
<?php
for ( $i = 0; $i < count($eventCounts); $i++ )
{
for ( $i = 0; $i < count($eventCounts); $i++ ) {
?>
<td class="colEvents"><?php echo makePopupLink( '?view='.$eventsView.'&amp;page=1'.$monitor['eventCounts'][$i]['filter']['query'], $eventsWindow, $eventsView, $monitor['EventCount'.$i], canView( 'Events' ) ) ?></td>
<?php
@ -362,8 +313,7 @@ echo $Server->Name();
?>
<td class="colZones"><?php echo makePopupLink( '?view=zones&amp;mid='.$monitor['Id'], 'zmZones', array( 'zones', $monitor['Width'], $monitor['Height'] ), $monitor['ZoneCount'], $running && canView( 'Monitors' ) ) ?></td>
<?php
if ( canEdit('Monitors') )
{
if ( canEdit('Monitors') ) {
?>
<td class="colOrder"><?php echo makeLink( '?view='.$view.'&amp;action=sequence&amp;mid='.$monitor['Id'].'&amp;smid='.$seqIdUpList[$monitor['Id']], '<img src="'.$seqUpFile.'" alt="Up"/>', $monitor['Sequence']>$minSequence ) ?><?php echo makeLink( '?view='.$view.'&amp;action=sequence&amp;mid='.$monitor['Id'].'&amp;smid='.$seqIdDownList[$monitor['Id']], '<img src="'.$seqDownFile.'" alt="Down"/>', $monitor['Sequence']<$maxSequence ) ?></td>
<?php
@ -375,6 +325,29 @@ echo $Server->Name();
}
?>
</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>
</div>
</form>

View File

@ -18,35 +18,32 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
if ( !canView( 'Control' ) )
{
$view = "error";
return;
if ( !canView( 'Control' ) ) {
$view = 'error';
return;
}
$groupSql = "";
$groupSql = '';
if ( !empty($_REQUEST['group']) ) {
$row = dbFetchOne( 'SELECT * FROM Groups WHERE Id = ?', NULL, array($_REQUEST['group']) );
$groupSql = " and find_in_set( Id, '".$row['MonitorIds']."' )";
$row = dbFetchOne( 'SELECT * FROM Groups WHERE Id = ?', NULL, array($_REQUEST['group']) );
$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";
$mids = array();
foreach( dbFetchAll( $sql ) as $row )
{
if ( !visibleMonitor( $row['Id'] ) )
{
continue;
}
if ( empty($mid) )
$mid = $row['Id'];
$mids[$row['Id']] = $row['Name'];
foreach( dbFetchAll( $sql ) as $row ) {
if ( !visibleMonitor( $row['Id'] ) ) {
continue;
}
if ( empty($mid) )
$mid = $row['Id'];
$mids[$row['Id']] = $row['Name'];
}
foreach ( getSkinIncludes( 'includes/control_functions.php' ) as $includeFile )
require_once $includeFile;
require_once $includeFile;
$monitor = new Monitor( $mid );
@ -70,7 +67,7 @@ xhtmlHeaders(__FILE__, translate('Control') );
</div>
<div id="content">
<div id="ptzControls" class="ptzControls">
<?php echo ptzControls( $monitor ) ?>
<?php echo ptzControls( $monitor ) ?>
</div>
</div>
</div>

View File

@ -18,71 +18,49 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
if ( !canView( 'Stream' ) )
{
$view = "error";
return;
if ( !canView( 'Stream' ) ) {
$view = 'error';
return;
}
if ( empty($_REQUEST['mode']) )
{
if ( canStream() )
$mode = "stream";
else
$mode = "still";
}
else
{
$mode = validHtmlStr($_REQUEST['mode']);
if ( empty($_REQUEST['mode']) ) {
if ( canStream() )
$mode = 'stream';
else
$mode = 'still';
} else {
$mode = validHtmlStr($_REQUEST['mode']);
}
$group = '';
$groupSql = '';
if ( !empty($_REQUEST['group']) )
{
$group = validInt($_REQUEST['group']);
$row = dbFetchOne( 'SELECT * FROM Groups WHERE Id = ?', NULL, array($group) );
$groupSql = " and find_in_set( Id, '".$row['MonitorIds']."' )";
if ( !empty($_REQUEST['group']) ) {
$group = validInt($_REQUEST['group']);
$row = dbFetchOne( 'SELECT * FROM Groups WHERE Id = ?', NULL, array($group) );
$groupSql = " and find_in_set( Id, '".$row['MonitorIds']."' )";
}
$sql = "SELECT * FROM Monitors WHERE Function != 'None'$groupSql ORDER BY Sequence";
$monitors = array();
$monIdx = 0;
foreach( dbFetchAll( $sql ) as $row )
{
if ( !visibleMonitor( $row['Id'] ) )
continue;
if ( isset($_REQUEST['mid']) && $row['Id'] == $_REQUEST['mid'] )
$monIdx = count($monitors);
$row['ScaledWidth'] = reScale( $row['Width'], $row['DefaultScale'], ZM_WEB_DEFAULT_SCALE );
$row['ScaledHeight'] = reScale( $row['Height'], $row['DefaultScale'], ZM_WEB_DEFAULT_SCALE );
$monitors[] = $row;
foreach( dbFetchAll( $sql ) as $row ) {
if ( !visibleMonitor( $row['Id'] ) )
continue;
if ( isset($_REQUEST['mid']) && $row['Id'] == $_REQUEST['mid'] )
$monIdx = count($monitors);
$row['ScaledWidth'] = reScale( $row['Width'], $row['DefaultScale'], ZM_WEB_DEFAULT_SCALE );
$row['ScaledHeight'] = reScale( $row['Height'], $row['DefaultScale'], ZM_WEB_DEFAULT_SCALE );
$monitors[] = new Monitor( $row );
}
$monitor = $monitors[$monIdx];
$nextMid = $monIdx==(count($monitors)-1)?$monitors[0]['Id']:$monitors[$monIdx+1]['Id'];
$montageWidth = $monitor['ScaledWidth'];
$montageHeight = $monitor['ScaledHeight'];
$widthScale = ($montageWidth*SCALE_BASE)/$monitor['Width'];
$heightScale = ($montageHeight*SCALE_BASE)/$monitor['Height'];
$nextMid = $monIdx==(count($monitors)-1)?$monitors[0]->Id():$monitors[$monIdx+1]->Id();
$montageWidth = $monitor->ScaledWidth();
$montageHeight = $monitor->ScaledHeight();
$widthScale = ($montageWidth*SCALE_BASE)/$monitor->Width();
$heightScale = ($montageHeight*SCALE_BASE)/$monitor->Height();
$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();
$focusWindow = true;
@ -94,33 +72,17 @@ xhtmlHeaders(__FILE__, translate('CycleWatch') );
<div id="header">
<div id="headerButtons">
<?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 { ?>
<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 } ?>
<a href="#" onclick="closeWindow(); return( false );"><?php echo translate('Close') ?></a>
</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 id="content">
<div id="imageFeed">
<?php
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']) );
}
?>
<?php echo getStreamHTML( $monitor, array( 'scale'=>$scale, 'mode'=>$mode ) ); ?>
</div>
</div>
</div>

View File

@ -128,12 +128,11 @@ if ( canEdit( 'Events' ) ) {
<div id="archiveEvent" class="hidden"><a href="#" onclick="archiveEvent()"><?php echo translate('Archive') ?></a></div>
<div id="unarchiveEvent" class="hidden"><a href="#" onclick="unarchiveEvent()"><?php echo translate('Unarchive') ?></a></div>
<?php
} // end if can edit Events
if ( $Event->DefaultVideo() ) { ?>
<div id="downloadEventFile"><a href="<?php echo $Event->getStreamSrc()?>">Download MP4</a></div>
<?php
} // end if Event->DefaultVideo
} // end if can edit Events
if ( canView( 'Events' ) ) {
?>
<div id="framesEvent"><a href="#" onclick="showEventFrames()"><?php echo translate('Frames') ?></a></div>
<?php
@ -170,14 +169,14 @@ if ( $Event->DefaultVideo() ) {
<div id="imageFeed" <?php if ( $Event->DefaultVideo() ) { ?>class="hidden"<?php } ?> >
<?php
if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT ) {
$streamSrc = getStreamSrc( array( "source=event", "mode=mpeg", "event=".$eid, "frame=".$fid, "scale=".$scale, "rate=".$rate, "bitrate=".ZM_WEB_VIDEO_BITRATE, "maxfps=".ZM_WEB_VIDEO_MAXFPS, "format=".ZM_MPEG_REPLAY_FORMAT, "replay=".$replayMode ) );
$streamSrc = $Event->getStreamSrc( array( 'mode'=>'mpeg', 'scale'=>$scale, 'rate'=>$rate, 'bitrate'=>ZM_WEB_VIDEO_BITRATE, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'format'=>ZM_MPEG_REPLAY_FORMAT, 'replay'=>$replayMode ) );
outputVideoStream( "evtStream", $streamSrc, reScale( $Event->Width(), $scale ), reScale( $Event->Height(), $scale ), ZM_MPEG_LIVE_FORMAT );
} else {
$streamSrc = getStreamSrc( array( "source=event", "mode=jpeg", "event=".$eid, "frame=".$fid, "scale=".$scale, "rate=".$rate, "maxfps=".ZM_WEB_VIDEO_MAXFPS, "replay=".$replayMode) );
$streamSrc = $Event->getStreamSrc( array( 'mode'=>'jpeg', 'frame'=>$fid, 'scale'=>$scale, 'rate'=>$rate, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'replay'=>$replayMode) );
if ( canStreamNative() ) {
outputImageStream( "evtStream", $streamSrc, reScale( $Event->Width(), $scale ), reScale( $Event->Height(), $scale ), validHtmlStr($Event->Name()) );
outputImageStream( 'evtStream', $streamSrc, reScale( $Event->Width(), $scale ), reScale( $Event->Height(), $scale ), validHtmlStr($Event->Name()) );
} else {
outputHelperStream( "evtStream", $streamSrc, reScale( $Event->Width(), $scale ), reScale( $Event->Height(), $scale ) );
outputHelperStream( 'evtStream', $streamSrc, reScale( $Event->Width(), $scale ), reScale( $Event->Height(), $scale ) );
}
} // end if stream method
?>
@ -244,8 +243,7 @@ if ($Event->SaveJPEGs() & 3) { // frames or analysis
</div>
</div>
<?php
} // end if SaveJPEGs() & 3 Analysis or Jpegs
} // end if canView
} // end if SaveJPEGs() & 3 Analysis or Jpegs
} // end if Event exists
?>
</div><!--page-->

View File

@ -18,76 +18,70 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
if ( !canView( 'Events' ) || (!empty($_REQUEST['execute']) && !canEdit('Events')) )
{
$view = "error";
return;
if ( !canView( 'Events' ) || (!empty($_REQUEST['execute']) && !canEdit('Events')) ) {
$view = 'error';
return;
}
require_once( 'includes/Event.php' );
if ( !empty($_REQUEST['execute']) )
{
executeFilter( $tempFilterName );
if ( !empty($_REQUEST['execute']) ) {
executeFilter( $tempFilterName );
}
$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'] ) {
$user_monitor_ids = ' M.Id in ('.$user['MonitorIds'].')';
$countSql .= $user_monitor_ids;
$eventsSql .= $user_monitor_ids;
} else {
$countSql .= " 1";
$eventsSql .= " 1";
$countSql .= " 1";
$eventsSql .= " 1";
}
parseSort();
parseFilter( $_REQUEST['filter'] );
$filterQuery = $_REQUEST['filter']['query'];
if ( $_REQUEST['filter']['sql'] )
{
$countSql .= $_REQUEST['filter']['sql'];
$eventsSql .= $_REQUEST['filter']['sql'];
if ( $_REQUEST['filter']['sql'] ) {
$countSql .= $_REQUEST['filter']['sql'];
$eventsSql .= $_REQUEST['filter']['sql'];
}
$eventsSql .= " ORDER BY $sortColumn $sortOrder";
if ( isset($_REQUEST['page']) )
$page = validInt($_REQUEST['page']);
$page = validInt($_REQUEST['page']);
else
$page = 0;
$page = 0;
if ( isset($_REQUEST['limit']) )
$limit = validInt($_REQUEST['limit']);
$limit = validInt($_REQUEST['limit']);
else
$limit = 0;
$limit = 0;
$nEvents = dbFetchOne( $countSql, 'EventCount' );
if ( !empty($limit) && $nEvents > $limit )
{
$nEvents = $limit;
if ( !empty($limit) && $nEvents > $limit ) {
$nEvents = $limit;
}
$pages = (int)ceil($nEvents/ZM_WEB_EVENTS_PER_PAGE);
if ( !empty($page) ) {
if ( $page < 0 )
$page = 1;
if ( $page > $pages )
$page = $pages;
if ( $page < 0 )
$page = 1;
else if ( $page > $pages )
$page = $pages;
}
if ( !empty($page) ) {
$limitStart = (($page-1)*ZM_WEB_EVENTS_PER_PAGE);
if ( empty( $limit ) )
{
$limitAmount = ZM_WEB_EVENTS_PER_PAGE;
}
else
{
$limitLeft = $limit - $limitStart;
$limitAmount = ($limitLeft>ZM_WEB_EVENTS_PER_PAGE)?ZM_WEB_EVENTS_PER_PAGE:$limitLeft;
}
$eventsSql .= " limit $limitStart, $limitAmount";
$limitStart = (($page-1)*ZM_WEB_EVENTS_PER_PAGE);
if ( empty( $limit ) ) {
$limitAmount = ZM_WEB_EVENTS_PER_PAGE;
} else {
$limitLeft = $limit - $limitStart;
$limitAmount = ($limitLeft>ZM_WEB_EVENTS_PER_PAGE)?ZM_WEB_EVENTS_PER_PAGE:$limitLeft;
}
$eventsSql .= " limit $limitStart, $limitAmount";
} elseif ( !empty( $limit ) ) {
$eventsSql .= " limit 0, ".$limit;
$eventsSql .= ' limit 0, '.$limit;
}
$maxWidth = 0;
@ -95,20 +89,19 @@ $maxHeight = 0;
$archived = false;
$unarchived = false;
$events = array();
foreach ( dbFetchAll( $eventsSql ) as $event_row )
{
$events[] = $event = new Event( $event_row );
foreach ( dbFetchAll( $eventsSql ) as $event_row ) {
$events[] = $event = new Event( $event_row );
# Doesn this code do anything?
$scale = max( reScale( SCALE_BASE, $event->DefaultScale(), ZM_WEB_DEFAULT_SCALE ), SCALE_BASE );
$eventWidth = reScale( $event_row['Width'], $scale );
$eventHeight = reScale( $event_row['Height'], $scale );
if ( $maxWidth < $eventWidth ) $maxWidth = $eventWidth;
if ( $maxHeight < $eventHeight ) $maxHeight = $eventHeight;
if ( $event_row['Archived'] )
$archived = true;
else
$unarchived = true;
# Doesn this code do anything?
$scale = max( reScale( SCALE_BASE, $event->DefaultScale(), ZM_WEB_DEFAULT_SCALE ), SCALE_BASE );
$eventWidth = reScale( $event_row['Width'], $scale );
$eventHeight = reScale( $event_row['Height'], $scale );
if ( $maxWidth < $eventWidth ) $maxWidth = $eventWidth;
if ( $maxHeight < $eventHeight ) $maxHeight = $eventHeight;
if ( $event_row['Archived'] )
$archived = true;
else
$unarchived = true;
}
$maxShortcuts = 5;
@ -124,20 +117,16 @@ xhtmlHeaders(__FILE__, translate('Events') );
<div id="header">
<div id="headerButtons">
<?php
if ( $pages > 1 )
{
if ( !empty($page) )
{
if ( $pages > 1 ) {
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>
<?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>
<?php
}
}
}
?>
<a href="#" onclick="closeWindows();"><?php echo translate('Close') ?></a>
@ -154,8 +143,7 @@ if ( $pages > 1 )
<input type="hidden" name="sort_asc" value="<?php echo validHtmlStr($_REQUEST['sort_asc']) ?>"/>
<input type="hidden" name="limit" value="<?php echo $limit ?>"/>
<?php
if ( $pagination )
{
if ( $pagination ) {
?>
<h3 class="pagination"><?php echo $pagination ?></h3>
<?php
@ -170,10 +158,8 @@ if ( $pagination )
<tbody>
<?php
$count = 0;
foreach ( $events as $event )
{
if ( ($count++%ZM_WEB_EVENTS_PER_PAGE) == 0 )
{
foreach ( $events as $event ) {
if ( ($count++%ZM_WEB_EVENTS_PER_PAGE) == 0 ) {
?>
<tr>
<th class="colId"><a href="<?php echo sortHeader( 'Id' ) ?>"><?php echo translate('Id') ?><?php echo sortTag( 'Id' ) ?></a></th>
@ -187,22 +173,22 @@ 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="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>
<?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>
<?php
}
if ( ZM_WEB_LIST_THUMBS )
{
}
if ( ZM_WEB_LIST_THUMBS ) {
?>
<th class="colThumbnail"><?php echo translate('Thumbnail') ?></th>
<?php
}
}
?>
<th class="colMark"><input type="checkbox" name="toggleCheck" value="1" onclick="toggleCheckbox( this, 'markEids' );"<?php if ( !canEdit( 'Events' ) ) { ?> disabled="disabled"<?php } ?>/></th>
</tr>
<?php
}
$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 );
?>
<tr>
<td class="colId"><?php echo makePopupLink( '?view=event&amp;eid='.$event->Id().$filterQuery.$sortQuery.'&amp;page=1', 'zmEvent', array( 'event', reScale( $event->Width(), $scale ), reScale( $event->Height(), $scale ) ), $event->Id().($event->Archived()?'*':'') ) ?></td>
@ -216,25 +202,37 @@ foreach ( $events as $event )
<td class="colTotScore"><?php echo $event->TotScore() ?></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>
<?php if ( ZM_WEB_EVENT_DISK_SPACE ) { ?>
<td class="colDiskSpace"><?php echo $event->DiskSpace() ?></td>
<?php
}
if ( ZM_WEB_LIST_THUMBS )
{
if ( $thumbData = $event->createListThumbnail() )
{
if ( ZM_WEB_EVENT_DISK_SPACE ) {
?>
<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
}
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>
<?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>
</tr>
@ -244,14 +242,12 @@ foreach ( $events as $event )
</tbody>
</table>
<?php
if ( $pagination )
{
if ( $pagination ) {
?>
<h3 class="pagination"><?php echo $pagination ?></h3>
<?php
}
if ( true || canEdit( 'Events' ) )
{
if ( true || canEdit( 'Events' ) ) {
?>
<div id="contentButtons">
<input type="button" name="viewBtn" value="<?php echo translate('View') ?>" onclick="viewEvents( this, 'markEids' );" disabled="disabled"/>

View File

@ -18,34 +18,31 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
if ( !canView( 'Events' ) )
{
$view = "error";
return;
if ( !canView( 'Events' ) ) {
$view = 'error';
return;
}
$selectName = "filterName";
$selectName = 'filterName';
$filterNames = array( ''=>translate('ChooseFilter') );
foreach ( dbFetchAll( "select * from Filters order by Name" ) as $row )
{
$filterNames[$row['Name']] = $row['Name'];
if ( $row['Background'] )
$filterNames[$row['Name']] .= "*";
if ( !empty($_REQUEST['reload']) && isset($_REQUEST['filterName']) && $_REQUEST['filterName'] == $row['Name'] )
$dbFilter = $row;
foreach ( dbFetchAll( 'select * from Filters order by Name' ) as $row ) {
$filterNames[$row['Name']] = $row['Name'];
if ( $row['Background'] )
$filterNames[$row['Name']] .= '*';
if ( !empty($_REQUEST['reload']) && isset($_REQUEST['filterName']) && $_REQUEST['filterName'] == $row['Name'] )
$dbFilter = $row;
}
$backgroundStr = "";
if ( isset($dbFilter) )
{
if ( $dbFilter['Background'] )
$backgroundStr = '['.strtolower(translate('Background')).']';
$_REQUEST['filter'] = jsonDecode( $dbFilter['Query'] );
$_REQUEST['sort_field'] = isset($_REQUEST['filter']['sort_field'])?$_REQUEST['filter']['sort_field']:"DateTime";
$_REQUEST['sort_asc'] = isset($_REQUEST['filter']['sort_asc'])?$_REQUEST['filter']['sort_asc']:"1";
$_REQUEST['limit'] = isset($_REQUEST['filter']['limit'])?$_REQUEST['filter']['limit']:"";
unset( $_REQUEST['filter']['sort_field'] );
unset( $_REQUEST['filter']['sort_asc'] );
unset( $_REQUEST['filter']['limit'] );
$backgroundStr = '';
if ( isset($dbFilter) ) {
if ( $dbFilter['Background'] )
$backgroundStr = '['.strtolower(translate('Background')).']';
$_REQUEST['filter'] = jsonDecode( $dbFilter['Query'] );
$_REQUEST['sort_field'] = isset($_REQUEST['filter']['sort_field'])?$_REQUEST['filter']['sort_field']:"DateTime";
$_REQUEST['sort_asc'] = isset($_REQUEST['filter']['sort_asc'])?$_REQUEST['filter']['sort_asc']:"1";
$_REQUEST['limit'] = isset($_REQUEST['filter']['limit'])?$_REQUEST['filter']['limit']:"";
unset( $_REQUEST['filter']['sort_field'] );
unset( $_REQUEST['filter']['sort_asc'] );
unset( $_REQUEST['filter']['limit'] );
}
# reload is set when the dropdown is changed.
@ -64,16 +61,14 @@ if ( isset( $_REQUEST['reload'] ) and ! $_REQUEST['reload'] ) {
$conjunctionTypes = array(
'and' => translate('ConjAnd'),
'or' => translate('ConjOr')
);
);
$obracketTypes = array();
$cbracketTypes = array();
if ( isset($_REQUEST['filter']['terms']) )
{
for ( $i = 0; $i <= count($_REQUEST['filter']['terms'])-2; $i++ )
{
$obracketTypes[$i] = str_repeat( "(", $i );
$cbracketTypes[$i] = str_repeat( ")", $i );
}
if ( isset($_REQUEST['filter']['terms']) ) {
for ( $i = 0; $i <= count($_REQUEST['filter']['terms'])-2; $i++ ) {
$obracketTypes[$i] = str_repeat( "(", $i );
$cbracketTypes[$i] = str_repeat( ")", $i );
}
}
$attrTypes = array(
@ -98,7 +93,7 @@ $attrTypes = array(
'DiskBlocks' => translate('AttrDiskBlocks'),
'SystemLoad' => translate('AttrSystemLoad'),
'ServerId' => translate('AttrServer'),
);
);
$opTypes = array(
'=' => translate('OpEq'),
'!=' => translate('OpNe'),
@ -110,15 +105,14 @@ $opTypes = array(
'!~' => translate('OpNotMatches'),
'=[]' => translate('OpIn'),
'![]' => translate('OpNotIn'),
);
);
$archiveTypes = array(
'0' => translate('ArchUnarchived'),
'1' => translate('ArchArchived')
);
);
$weekdays = array();
for ( $i = 0; $i < 7; $i++ )
{
$weekdays[$i] = strftime( "%A", mktime( 12, 0, 0, 1, $i+1, 2001 ) );
for ( $i = 0; $i < 7; $i++ ) {
$weekdays[$i] = strftime( '%A', mktime( 12, 0, 0, 1, $i+1, 2001 ) );
}
$sort_fields = array(
'Id' => translate('AttrId'),
@ -133,13 +127,12 @@ $sort_fields = array(
'TotScore' => translate('AttrTotalScore'),
'AvgScore' => translate('AttrAvgScore'),
'MaxScore' => translate('AttrMaxScore'),
);
);
$sort_dirns = array(
'1' => translate('SortAsc'),
'0' => translate('SortDesc')
);
if ( empty($_REQUEST['sort_field']) )
{
);
if ( empty($_REQUEST['sort_field']) ) {
$_REQUEST['sort_field'] = ZM_WEB_EVENT_SORT_FIELD;
$_REQUEST['sort_asc'] = (ZM_WEB_EVENT_SORT_ORDER == "asc");
}
@ -174,105 +167,93 @@ xhtmlHeaders(__FILE__, translate('EventFilter') );
<table id="fieldsTable" class="filterTable" cellspacing="0">
<tbody>
<?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>
<?php
if ( $i == 0 )
{
if ( $i == 0 ) {
?>
<td>&nbsp;</td>
<?php
}
else
{
} else {
?>
<td><?php echo buildSelect( "filter[terms][$i][cnj]", $conjunctionTypes ); ?></td>
<?php
}
}
?>
<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>
<?php
if ( isset($_REQUEST['filter']['terms'][$i]['attr']) )
{
if ( $_REQUEST['filter']['terms'][$i]['attr'] == "Archived" )
{
if ( isset($_REQUEST['filter']['terms'][$i]['attr']) ) {
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 buildSelect( "filter[terms][$i][val]", $archiveTypes ); ?></td>
<?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><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
}
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><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
}
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][val]", $weekdays ); ?></td>
<?php
} elseif ( false && $_REQUEST['filter']['terms'][$i]['attr'] == 'MonitorName' ) {
$monitors = array();
foreach ( dbFetchAll( "select Id,Name from Monitors order by Sequence asc" ) as $monitor ) {
if ( visibleMonitor( $monitor['Id'] ) ) {
$monitors[$monitor['Name']] = $monitor['Name'];
}
elseif ( false && $_REQUEST['filter']['terms'][$i]['attr'] == "MonitorName" )
{
$monitors = array();
foreach ( dbFetchAll( "select Id,Name from Monitors order by Sequence asc" ) as $monitor )
{
if ( visibleMonitor( $monitor['Id'] ) )
{
$monitors[$monitor['Name']] = $monitor['Name'];
}
}
}
?>
<td><?php echo buildSelect( "filter[terms][$i][op]", $opTypes ); ?></td>
<td><?php echo buildSelect( "filter[terms][$i][val]", $monitors ); ?></td>
<?php
}
elseif ( $_REQUEST['filter']['terms'][$i]['attr'] == "ServerId" )
{
$servers = array();
$servers['ZM_SERVER_ID'] = 'Current Server';
foreach ( dbFetchAll( "SELECT Id,Name FROM Servers ORDER BY lower(Name) ASC" ) as $server ) {
$servers[$server['Id']] = $server['Name'];
}
} elseif ( $_REQUEST['filter']['terms'][$i]['attr'] == 'ServerId' ) {
$servers = array();
$servers['ZM_SERVER_ID'] = 'Current Server';
foreach ( dbFetchAll( 'SELECT Id,Name FROM Servers ORDER BY lower(Name) ASC' ) as $server ) {
$servers[$server['Id']] = $server['Name'];
}
?>
<td><?php echo buildSelect( "filter[terms][$i][op]", $opTypes ); ?></td>
<td><?php echo buildSelect( "filter[terms][$i][val]", $servers ); ?></td>
<?php
}
else
{
} else {
?>
<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>
<?php
}
}
else
{
} else {
?>
<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>
<?php
}
}
?>
<td><?php if ( count($_REQUEST['filter']['terms']) > 2 ) { echo buildSelect( "filter[terms][$i][cbr]", $cbracketTypes ); } else { ?>&nbsp;<?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>
<?php
}
} # end foreach filter
?>
</tbody>
</table>
@ -346,9 +327,9 @@ if ( ZM_OPT_MESSAGE )
<input type="button" name="executeButton" id="executeButton" value="<?php echo translate('Execute') ?>" onclick="executeFilter( this );"/>
<?php if ( canEdit( 'Events' ) ) { ?>
<input type="button" value="<?php echo translate('Save') ?>" onclick="saveFilter( this );"/>
<?php } ?>
<?php if ( canEdit( 'Events' ) && isset($dbFilter) && $dbFilter['Name'] ) { ?>
<?php if ( isset($dbFilter) && $dbFilter['Name'] ) { ?>
<input type="button" value="<?php echo translate('Delete') ?>" onclick="deleteFilter( this, '<?php echo $dbFilter['Name'] ?>' );"/>
<?php } ?>
<?php } ?>
<input type="button" value="<?php echo translate('Reset') ?>" onclick="submitToFilter( this, 1 );"/>
</div>

View File

@ -19,15 +19,15 @@
//
if ( !canView( 'Events' ) ) {
$view = "error";
return;
$view = 'error';
return;
}
require_once('includes/Frame.php');
$eid = validInt($_REQUEST['eid']);
if ( !empty($_REQUEST['fid']) )
$fid = validInt($_REQUEST['fid']);
$fid = validInt($_REQUEST['fid']);
$Event = new Event( $eid );
$Monitor = $Event->Monitor();
@ -37,7 +37,7 @@ if ( !empty($fid) ) {
if ( !($frame = dbFetchOne( $sql, NULL, array($eid, $fid) )) )
$frame = array( 'FrameId'=>$fid, 'Type'=>'Normal', 'Score'=>0 );
} else {
$frame = dbFetchOne( 'SELECT * FROM Frames WHERE EventId = ? AND Score = ?', NULL, array( $eid, $Event->MaxScore() ) );
$frame = dbFetchOne( 'SELECT * FROM Frames WHERE EventId = ? AND Score = ?', NULL, array( $eid, $Event->MaxScore() ) );
}
$Frame = new Frame( $frame );
@ -60,16 +60,27 @@ if ( isset( $_REQUEST['scale'] ) ) {
$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'];
$eventPath = $imageData['eventPath'];
$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() );
$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() );
$focusWindow = true;
xhtmlHeaders(__FILE__, translate('Frame')." - ".$Event->Id()." - ".$Frame->FrameId() );
xhtmlHeaders(__FILE__, translate('Frame').' - '.$Event->Id()." - ".$Frame->FrameId() );
?>
<body>
<div id="page">
@ -88,33 +99,29 @@ xhtmlHeaders(__FILE__, translate('Frame')." - ".$Event->Id()." - ".$Frame->Frame
</div>
<div id="content">
<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 } else {
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" ?>">
<?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'] ) {
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' ) );
} ?>
<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 if ( $imageData['hasAnalImage'] ) { ?></a><?php } ?>
<?php } ?>
</p>
</p>
<p id="controls">
<?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>
<?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 ?>"><?php echo translate('Prev') ?></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>
<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>
<?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>
<?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 ?>"><?php echo translate('Last') ?></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>
<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>
<?php } ?>
</p>
<?php if (file_exists ($dImagePath)) { ?>
<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)) { ?>
<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 } ?>
</div>
</div>

View File

@ -628,17 +628,16 @@ function drawProgressBar() {
var cells = $('progressBar').getElements( 'div' );
var cellWidth = parseInt( eventData.Width/$$(cells).length );
$$(cells).forEach(
function( cell, index )
{
function( cell, index ) {
if ( index == 0 )
$(cell).setStyles( { 'left': barWidth, 'width': cellWidth, 'borderLeft': 0 } );
$(cell).setStyles( { 'left': barWidth, 'width': cellWidth, 'borderLeft': 0 } );
else
$(cell).setStyles( { 'left': barWidth, 'width': cellWidth } );
var offset = parseInt((index*eventData.Length)/$$(cells).length);
$(cell).setProperty( 'title', '+'+secsToTime(offset)+'s' );
$(cell).removeEvent( 'click' );
$(cell).addEvent( 'click', function() { streamSeek( offset ); } );
barWidth += $(cell).getCoordinates().width;
$(cell).setStyles( { 'left': barWidth, 'width': cellWidth } );
var offset = parseInt((index*eventData.Length)/$$(cells).length);
$(cell).setProperty( 'title', '+'+secsToTime(offset)+'s' );
$(cell).removeEvent( 'click' );
$(cell).addEvent( 'click', function() { streamSeek( offset ); } );
barWidth += $(cell).getCoordinates().width;
}
);
$('progressBar').setStyle( 'width', barWidth );
@ -662,7 +661,7 @@ function updateProgressBar() {
} // end if
} // end function
);
$('progressBar').setStyle( 'width', barWidth );
//$('progressBar').setStyle( 'width', barWidth );
$('progressBar').removeClass( 'invisible' );
} // end if eventData && streamStatus
} // end function updateProgressBar()

View File

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

View File

@ -94,7 +94,7 @@ function previewEvent( eventId, frameId ) {
if ( event['frames'] ) {
if ( event['frames'][frameId] ) {
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;
loadEventImage( imagePath, eventId, frameId, event.Width, event.Height, event.Frames/event.Length, videoName, event.Length, event.StartTime, monitors[event.MonitorId]);
return;
@ -107,13 +107,13 @@ function previewEvent( eventId, frameId ) {
function loadEventImage( imagePath, eid, fid, width, height, fps, videoName, duration, startTime, Monitor ) {
var vid= $('preview');
var imageSrc = $('imageSrc');
if(videoName) {
if ( videoName && vid ) {
vid.show();
imageSrc.hide();
var newsource=imagePrefix+imagePath.slice(0,imagePath.lastIndexOf('/'))+"/"+videoName;
var newsource=imagePath.slice(0,imagePath.lastIndexOf('/'))+"/"+videoName;
//console.log(newsource);
//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");
//it is possible to set a long source list here will that be unworkable?
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)
vid.currentTime = fid/fps;
} else {
if(!vid.seeking)
if ( ! vid.seeking )
vid.currentTime=fid/fps;
}
} else {
vid.hide();
if ( vid ) vid.hide();
imageSrc.show();
imageSrc.setProperty( 'src', imagePrefix+imagePath );
imageSrc.setProperty( 'src', imagePath );
imageSrc.removeEvent( 'click' );
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 } );
/*Stream could be an applet so can't use moo tools*/
var streamImg = document.getElementById('liveStream');
var streamImg = document.getElementById('liveStream'+monitorId);
if ( streamImg ) {
streamImg.style.width = newWidth + "px";
streamImg.style.height = newHeight + "px";
@ -146,14 +146,14 @@ function getStreamCmdResponse( respObj, respText ) {
streamCmdSlowRev( false );
else
streamCmdFastRev( false );
}
} // rate
} else {
$('modeValue').set( 'text', "Live" );
$('rate').addClass( 'hidden' );
$('delay').addClass( 'hidden' );
$('level').addClass( 'hidden' );
streamCmdPlay( false );
}
} // end if paused or delayed
$('zoomValue').set( 'text', streamStatus.zoom );
if ( streamStatus.zoom == "1.0" )
setButtonState( $('zoomOutBtn'), 'unavail' );
@ -538,13 +538,8 @@ function controlCmdImage( x, y ) {
fetchImage.pass( $('imageFeed').getElement('img') ).delay( 1000 );
}
var tempImage = null;
function fetchImage( streamImage ) {
var now = new Date();
if ( !tempImage )
tempImage = new Element( 'img' );
tempImage.setProperty( 'src', streamSrc+'&'+now.getTime() );
$(streamImage).setProperty( 'src', tempImage.getProperty( 'src' ) );
streamImage.src = streamImage.src.replace(/rand=\d+/i,'rand='+Math.floor((Math.random() * 1000000) ));
}
function handleClick( event ) {

View File

@ -52,8 +52,6 @@ var monitorUrl = '<?php echo ( $monitor->Server()->Url() ) ?>';
var scale = <?php echo $scale ?>;
var streamSrc = "<?php echo preg_replace( '/&amp;/', '&', $streamSrc ) ?>";
var statusRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_STATUS ?>;
var eventsRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_EVENTS ?>;
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.
//
if ( !canView( 'Monitors' ) )
{
$view = "error";
if ( !canView( 'Monitors' ) ) {
$view = 'error';
return;
}
@ -34,29 +33,25 @@ $hicolor = '0x00ff00'; // Green
$presets = array();
$presetNames = array();
$presetNames[0] = translate('ChoosePreset');
$sql = "select *, Units-1 as UnitsIndex, CheckMethod-1 as CheckMethodIndex from ZonePresets order by Id asc";
foreach( dbFetchAll( $sql ) as $preset )
{
$presetNames[$preset['Id']] = $preset['Name'];
$presets[] = $preset;
$sql = 'SELECT *, Units-1 AS UnitsIndex, CheckMethod-1 AS CheckMethodIndex FROM ZonePresets ORDER BY Id ASC';
foreach( dbFetchAll( $sql ) as $preset ) {
$presetNames[$preset['Id']] = $preset['Name'];
$presets[] = $preset;
}
$optTypes = array();
foreach ( getEnumValues( 'Zones', 'Type' ) as $optType )
{
$optTypes[$optType] = $optType;
foreach ( getEnumValues( 'Zones', 'Type' ) as $optType ) {
$optTypes[$optType] = $optType;
}
$optUnits = array();
foreach ( getEnumValues( 'Zones', 'Units' ) as $optUnit )
{
$optUnits[$optUnit] = $optUnit;
foreach ( getEnumValues( 'Zones', 'Units' ) as $optUnit ) {
$optUnits[$optUnit] = $optUnit;
}
$optCheckMethods = array();
foreach ( getEnumValues( 'Zones', 'CheckMethod' ) as $optCheckMethod )
{
$optCheckMethods[$optCheckMethod] = $optCheckMethod;
foreach ( getEnumValues( 'Zones', 'CheckMethod' ) as $optCheckMethod ) {
$optCheckMethods[$optCheckMethod] = $optCheckMethod;
}
$monitor = new Monitor( $mid );
@ -66,14 +61,10 @@ $maxX = $monitor->Width()-1;
$minY = 0;
$maxY = $monitor->Height()-1;
if ( !isset($newZone) )
{
if ( $zid > 0 )
{
if ( !isset($newZone) ) {
if ( $zid > 0 ) {
$zone = dbFetchOne( 'SELECT * FROM Zones WHERE MonitorId = ? AND Id=?', NULL, array( $monitor->Id(), $zid ) );
}
else
{
} else {
$zone = array(
'Id' => 0,
'Name' => translate('New'),
@ -104,17 +95,16 @@ if ( !isset($newZone) )
$zone['AreaCoords'] = preg_replace( '/\s+/', ',', $zone['Coords'] );
$newZone = $zone;
}
} # end if new Zone
//if ( !$points )
//{
//$points = $zone['Points'];
//}
# Ensure Zone fits within the limits of the Monitor
limitPoints( $newZone['Points'], $minX, $minY, $maxX, $maxY );
ksort( $newZone['Points'], SORT_NUMERIC );
$newZone['Coords'] = pointsToCoords( $newZone['Points'] );
$newZone['Area'] = getPolyArea( $newZone['Points'] );
$newZone['AreaCoords'] = preg_replace( '/\s+/', ',', $newZone['Coords'] );
$selfIntersecting = isSelfIntersecting( $newZone['Points'] );
$focusWindow = true;
@ -122,7 +112,7 @@ $connkey = generateConnKey();
$streamSrc = '';
$streamMode = '';
# 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') );
?>
@ -162,7 +152,13 @@ xhtmlHeaders(__FILE__, translate('Zone') );
</tr>
<tr>
<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>
<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.
//
if ( !canView( 'Monitors' ) )
{
$view = "error";
return;
if ( !canView( 'Monitors' ) ) {
$view = 'error';
return;
}
$mid = validInt($_REQUEST['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();
foreach( dbFetchAll( 'select * from Zones where MonitorId = ? order by Area desc', NULL, array($mid) ) as $row )
{
if ( $row['Points'] = coordsToPoints( $row['Coords'] ) )
{
$row['AreaCoords'] = preg_replace( '/\s+/', ',', $row['Coords'] );
$zones[] = $row;
}
foreach( dbFetchAll( 'SELECT * FROM Zones WHERE MonitorId=? ORDER BY Area DESC', NULL, array($mid) ) as $row ) {
$row['Points'] = coordsToPoints( $row['Coords'] );
limitPoints( $row['Points'], $minX, $minY, $maxX, $maxY );
$row['Coords'] = pointsToCoords( $row['Points'] );
$row['AreaCoords'] = preg_replace( '/\s+/', ',', $row['Coords'] );
$zones[] = $row;
}
$connkey = generateConnKey();
@ -48,21 +52,14 @@ xhtmlHeaders(__FILE__, translate('Zones') );
<h2><?php echo translate('Zones') ?></h2>
</div>
<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'] ?>">
<input type="hidden" name="view" value="<?php echo $view ?>"/>
<input type="hidden" name="action" value="delete"/>
<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">
<thead>
<tr>
@ -88,9 +85,18 @@ foreach( $zones as $zone )
?>
</tbody>
</table>
<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 class="ZonesImage" style="position:relative; clear:both;">
<?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>
</div>
</form>
</div>

View File

@ -32,136 +32,183 @@
// If both scale and either width or height are specified, scale is ignored
//
if ( !canView( 'Events' ) )
{
$view = "error";
return;
if ( !canView( 'Events' ) ) {
$view = 'error';
return;
}
require_once('includes/Event.php');
require_once('includes/Frame.php');
header( 'Content-type: image/jpeg' );
// Compatibility for PHP 5.4
if (!function_exists('imagescale'))
{
function imagescale($image, $new_width, $new_height = -1, $mode = 0)
{
$mode; // Not supported
if (!function_exists('imagescale')) {
function imagescale($image, $new_width, $new_height = -1, $mode = 0) {
$mode; // Not supported
$new_height = ($new_height == -1) ? imagesy($image) : $new_height;
$imageNew = imagecreatetruecolor($new_width, $new_height);
imagecopyresampled($imageNew, $image, 0, 0, 0, 0, (int)$new_width, (int)$new_height, imagesx($image), imagesy($image));
return $imageNew;
}
$new_height = ($new_height == -1) ? imagesy($image) : $new_height;
$imageNew = imagecreatetruecolor($new_width, $new_height);
imagecopyresampled($imageNew, $image, 0, 0, 0, 0, (int)$new_width, (int)$new_height, imagesx($image), imagesy($image));
return $imageNew;
}
}
$errorText = false;
if ( empty($_REQUEST['path']) )
{
$filename = '';
$Frame = null;
$Event = null;
$path = null;
if ( empty($_REQUEST['path']) ) {
if ( ! empty($_REQUEST['fid']) ) {
$show = empty($_REQUEST['show']) ? 'capture' : $_REQUEST['show'];
if ( ! empty($_REQUEST['eid'] ) ) {
$Event = new Event( $_REQUEST['eid'] );
$Frame = Frame::find_one( array( 'EventId' => $_REQUEST['eid'], 'FrameId' => $_REQUEST['fid'] ) );
if ( ! $Frame ) {
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 {
# 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'] );
$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 {
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 {
Warning('Loading images by path is deprecated');
$dir_events = realpath(ZM_DIR_EVENTS);
$path = realpath($dir_events . '/' . $_REQUEST['path']);
$pos = strpos($path, $dir_events);
if ( $pos == 0 && $pos !== false ) {
if ( ! empty( $user['MonitorIds'] ) ) {
$imageOk = false;
$pathMonId = substr( $path, 0, strspn( $path, '1234567890' ) );
foreach ( preg_split( '/["\'\s]*,["\'\s]*/', $user['MonitorIds'] ) as $monId ) {
if ( $pathMonId == $monId ) {
$imageOk = true;
break;
}
}
if ( !$imageOk )
$errorText = 'No image permissions';
}
} else {
$errorText = "No image path";
$errorText = 'Invalid image path';
}
if ( ! file_exists( $path ) ) {
header('HTTP/1.0 404 Not Found');
Fatal("Image not found at $path");
}
} else {
$dir_events = realpath(ZM_DIR_EVENTS);
$path = realpath($dir_events . '/' . $_REQUEST['path']);
$pos = strpos($path, $dir_events);
if($pos == 0 && $pos !== false) {
if ( !empty($user['MonitorIds']) ) {
$imageOk = false;
$pathMonId = substr( $path, 0, strspn( $path, "1234567890" ) );
foreach ( preg_split( '/["\'\s]*,["\'\s]*/', $user['MonitorIds'] ) as $monId ) {
if ( $pathMonId == $monId ) {
$imageOk = true;
break;
}
}
if ( !$imageOk )
$errorText = "No image permissions";
}
} else {
$errorText = "Invalid image path";
}
}
$scale=0;
if( !empty($_REQUEST['scale']) )
if (is_numeric($_REQUEST['scale']))
{
$x = $_REQUEST['scale'];
if($x >= 1 and $x <= 400)
$scale=$x;
}
if( !empty($_REQUEST['scale']) ) {
if (is_numeric($_REQUEST['scale'])) {
$x = $_REQUEST['scale'];
if($x >= 1 and $x <= 400)
$scale=$x;
}
}
$width=0;
if( !empty($_REQUEST['width']) )
if (is_numeric($_REQUEST['width']))
{
$x = $_REQUEST['width'];
if($x >= 10 and $x <= 8000)
$width=$x;
}
if ( !empty($_REQUEST['width']) ) {
if (is_numeric($_REQUEST['width'])) {
$x = $_REQUEST['width'];
if($x >= 10 and $x <= 8000)
$width=$x;
}
}
$height=0;
if( !empty($_REQUEST['height']) )
if (is_numeric($_REQUEST['height']))
{
$x = $_REQUEST['height'];
if($x >= 10 and $x <= 8000)
$height=$x;
}
if( !empty($_REQUEST['height']) ) {
if (is_numeric($_REQUEST['height'])) {
$x = $_REQUEST['height'];
if($x >= 10 and $x <= 8000)
$height=$x;
}
}
header( 'Content-type: image/jpeg' );
if ( $errorText )
Error( $errorText );
else
if( ($scale==0 || $scale==100) && $width==0 && $height==0 )
readfile( $path );
else
{
$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;
$height= $oldHeight * $scale / 100.0;
}
elseif ($width==0 && $height!=0)
{
$width = ($height * $oldWidth) / $oldHeight;
}
elseif ($width!=0 && $height==0)
{
$height = ($width * $oldHeight) / $oldWidth;
}
if($width==$oldWidth && $height==$oldHeight) // See if we really need to scale
{
imagejpeg($i);
imagedestroy($i);
}
else // we do need to scale
{
$iScale = imagescale($i, $width, $height);
imagejpeg($iScale);
imagedestroy($i);
imagedestroy($iScale);
}
# 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 );
} else {
if ( ( $scale==0 || $scale==100 ) && $width==0 && $height==0 ) {
if ( ! readfile( $path ) ) {
Error("No bytes read from ". $path );
}
?>
} else {
Logger::Debug("Doing a scaled image: scale($scale) width($width) height($height)");
$i = 0;
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;
$height= $oldHeight * $scale / 100.0;
} elseif ( $width == 0 && $height != 0 ) {
$width = ($height * $oldWidth) / $oldHeight;
} elseif ( $width != 0 && $height == 0 ) {
$height = ($width * $oldHeight) / $oldWidth;
}
if ( $width == $oldWidth && $height == $oldHeight) {
Warning( 'No change to width despite scaling.' );
}
}
# 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;
}
}
}

View File

@ -1,13 +1,16 @@
# ==========================================================================
#
# ZoneMinder Base Configuration, $Date$, $Revision$
# ZoneMinder Base Configuration File
#
# ==========================================================================
#
# This file is generated by 'configure'. Care should be taken if manually
# editing this file as an changes may be overwritten by subsequent configuration
# or installations.
# *** DO NOT EDIT THIS FILE ***
# Changes made directly to this configuration file are no longer supported.
# They will be overwritten during an upgrade.
#
# Instead, create a custom configuration file, with an extention of ".conf"
# under the @ZM_CONFIG_SUBDIR@ subfolder containing your desired modifications.
#
# Path to installed data directory, used mostly for finding DB upgrade scripts
ZM_PATH_DATA=@PKGDATADIR@
@ -47,9 +50,3 @@ ZM_DB_USER=@ZM_DB_USER@
# ZoneMinder database password
ZM_DB_PASS=@ZM_DB_PASS@
# Do NOT set ZM_SERVER_HOST if you are not using Multi-Server
# You have been warned
#
# The name specified here must have a corresponding entry
# in the Servers tab under Options
ZM_SERVER_HOST=