Merge branch 'master' into add_was_alarmed
This commit is contained in:
commit
f8cb0a5e21
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
91
Dockerfile
91
Dockerfile
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
@ -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=
|
||||
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -1,2 +0,0 @@
|
|||
default_cgi-path.patch
|
||||
use_libjs-mootools.patch
|
|
@ -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 )
|
|
@ -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" \
|
||||
|
|
|
@ -1 +1 @@
|
|||
3.0 (native)
|
||||
3.0 (quilt)
|
||||
|
|
|
@ -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...
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
default_cgi-path.patch
|
||||
use_libjs-mootools.patch
|
|
@ -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
|
||||
|
|
|
@ -1 +1 @@
|
|||
3.0 (native)
|
||||
3.0 (quilt)
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
missingok
|
||||
notifempty
|
||||
sharedscripts
|
||||
delaycompress
|
||||
compress
|
||||
postrotate
|
||||
/usr/bin/zmpkg.pl logrot >>/dev/null 2>&1 || :
|
||||
endscript
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
@ -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
|
||||
|
|
|
@ -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}
|
||||
);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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 ) {
|
||||
|
|
|
@ -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
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ) );
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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() );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
249
src/zmu.cpp
249
src/zmu.cpp
|
@ -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( ×tamp.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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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' );
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
@ -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();
|
||||
}
|
||||
|
|
1441
web/lang/dk_dk.php
1441
web/lang/dk_dk.php
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,3 @@
|
|||
#header {
|
||||
width: 99%;
|
||||
}
|
||||
|
||||
#layout {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
#header {
|
||||
width: 99%;
|
||||
}
|
||||
|
||||
#layout {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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&group='.$cycleGroup, 'zmCycle'.$cycleGroup, array( 'cycle', $cycleWidth, $cycleHeight ), translate('Cycle'), $running ) ?> /
|
||||
<?php echo makePopupLink( '?view=montage&group='.$cycleGroup, 'zmMontage'.$cycleGroup, 'montage', translate('Montage'), $running ) ?> /
|
||||
<?php echo makePopupLink( '?view=montagereview&group='.$cycleGroup, 'zmMontage'.$cycleGroup, 'montagereview', translate('Montage Review'), $running ) ?>
|
||||
<?php echo makePopupLink( '?view=cycle&group='.$cycleGroup, 'zmCycle'.$cycleGroup, array( 'cycle', $cycleWidth, $cycleHeight ), translate('Cycle'), $running ) ?> /
|
||||
<?php echo makePopupLink( '?view=montage&group='.$cycleGroup, 'zmMontage'.$cycleGroup, 'montage', translate('Montage'), $running ) ?> /
|
||||
<?php echo makePopupLink( '?view=montagereview&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
|
||||
}
|
||||
?> <?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&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.'&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&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"> </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.'&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&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.'&action=sequence&mid='.$monitor['Id'].'&smid='.$seqIdUpList[$monitor['Id']], '<img src="'.$seqUpFile.'" alt="Up"/>', $monitor['Sequence']>$minSequence ) ?><?php echo makeLink( '?view='.$view.'&action=sequence&mid='.$monitor['Id'].'&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.'&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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 ?>&mode=still&group=<?php echo $group ?>&mid=<?php echo $monitor['Id'] ?>"><?php echo translate('Stills') ?></a>
|
||||
<a href="?view=<?php echo $view ?>&mode=still&group=<?php echo $group ?>&mid=<?php echo $monitor->Id() ?>"><?php echo translate('Stills') ?></a>
|
||||
<?php } else { ?>
|
||||
<a href="?view=<?php echo $view ?>&mode=stream&group=<?php echo $group ?>&mid=<?php echo $monitor['Id'] ?>"><?php echo translate('Stream') ?></a>
|
||||
<a href="?view=<?php echo $view ?>&mode=stream&group=<?php echo $group ?>&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>
|
||||
|
|
|
@ -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-->
|
||||
|
|
|
@ -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 ?>&page=0<?php echo $filterQuery ?><?php echo $sortQuery ?>&limit=<?php echo $limit ?>"><?php echo translate('ViewAll') ?></a>
|
||||
<?php
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
?>
|
||||
<a href="?view=<?php echo $view ?>&page=1<?php echo $filterQuery ?><?php echo $sortQuery ?>&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&eid='.$event->Id().$filterQuery.$sortQuery.'&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&eid='.$event->Id().'&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&eid='.$event->Id().'&fid='.$thumbData['FrameId'], 'zmImage', array( 'image', reScale( $event->Width(), $scale ), reScale( $event->Height(), $scale ) ), '<img src="?view=image&eid='.$event->Id().'&fid='.$thumbData['FrameId'].'&width='.$thumbData['Width'].'&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&eid='.$event->Id().'&fid='.$thumbData['FrameId'].'&width='.$thumbData['Width'].'&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&eid='.$event->Id().'&fid='.$thumbData['FrameId'],
|
||||
'zmImage',
|
||||
array( 'image', reScale( $event->Width(), $scale ), reScale( $event->Height(), $scale ) ),
|
||||
$imgHtml
|
||||
);
|
||||
?>
|
||||
</td>
|
||||
<?php
|
||||
} else {
|
||||
?>
|
||||
<td class="colThumbnail"> </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"/>
|
||||
|
|
|
@ -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> </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 { ?> <?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 { ?> <?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>
|
||||
|
|
|
@ -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&eid=<?php echo $Event->Id() ?>&fid=<?php echo $Frame->FrameId() ?>&scale=<?php echo $scale ?>&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&eid=%d&fid=%d&scale=%d&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&eid=<?php echo $Event->Id() ?>&fid=<?php echo $firstFid ?>&scale=<?php echo $scale ?>"><?php echo translate('First') ?></a>
|
||||
<?php } if ( $Frame->FrameId() > 1 ) { ?>
|
||||
<a id="prevLink" href="?view=frame&eid=<?php echo $Event->Id() ?>&fid=<?php echo $prevFid ?>&scale=<?php echo $scale ?>"><?php echo translate('Prev') ?></a>
|
||||
<a id="firstLink" href="?view=frame&eid=<?php echo $Event->Id() ?>&fid=<?php echo $firstFid ?>&scale=<?php echo $scale ?>&show=<?php echo $show ?>"><?php echo translate('First') ?></a>
|
||||
<a id="prevLink" href="?view=frame&eid=<?php echo $Event->Id() ?>&fid=<?php echo $prevFid ?>&scale=<?php echo $scale ?>&show=<?php echo $show ?>"><?php echo translate('Prev') ?></a>
|
||||
<?php } if ( $Frame->FrameId() < $maxFid ) { ?>
|
||||
<a id="nextLink" href="?view=frame&eid=<?php echo $Event->Id() ?>&fid=<?php echo $nextFid ?>&scale=<?php echo $scale ?>"><?php echo translate('Next') ?></a>
|
||||
<?php } if ( $Frame->FrameId() < $maxFid ) { ?>
|
||||
<a id="lastLink" href="?view=frame&eid=<?php echo $Event->Id() ?>&fid=<?php echo $lastFid ?>&scale=<?php echo $scale ?>"><?php echo translate('Last') ?></a>
|
||||
<a id="nextLink" href="?view=frame&eid=<?php echo $Event->Id() ?>&fid=<?php echo $nextFid ?>&scale=<?php echo $scale ?>&show=<?php echo $show ?>"><?php echo translate('Next') ?></a>
|
||||
<a id="lastLink" href="?view=frame&eid=<?php echo $Event->Id() ?>&fid=<?php echo $lastFid ?>&scale=<?php echo $scale ?>&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>
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ] ) );
|
||||
}
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -52,8 +52,6 @@ var monitorUrl = '<?php echo ( $monitor->Server()->Url() ) ?>';
|
|||
|
||||
var scale = <?php echo $scale ?>;
|
||||
|
||||
var streamSrc = "<?php echo preg_replace( '/&/', '&', $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
|
@ -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 )"/> / <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>
|
||||
<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>
|
||||
|
|
|
@ -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&mid=<?php echo $mid ?>&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&mid=<?php echo $mid ?>&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&mid=<?php echo $mid ?>&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&mid=<?php echo $mid ?>&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>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
17
zm.conf.in
17
zm.conf.in
|
@ -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=
|
||||
|
|
Loading…
Reference in New Issue