Merge branch 'master' of https://github.com/ZoneMinder/ZoneMinder into plugin_support

This commit is contained in:
manupap1 2014-11-14 10:55:05 +01:00
commit dac1756d0d
32 changed files with 1380 additions and 200 deletions

View File

@ -224,7 +224,11 @@ else(GCRYPT_LIBRARIES)
endif(GCRYPT_LIBRARIES) endif(GCRYPT_LIBRARIES)
# gnutls (using find_library and find_path) # gnutls (using find_library and find_path)
find_library(GNUTLS_LIBRARIES gnutls) find_library(GNUTLS_LIBRARIES gnutls-openssl)
if(NOT GNUTLS_LIBRARIES)
find_library(GNUTLS_LIBRARIES gnutls)
endif(NOT GNUTLS_LIBRARIES)
if(GNUTLS_LIBRARIES) if(GNUTLS_LIBRARIES)
set(HAVE_LIBGNUTLS 1) set(HAVE_LIBGNUTLS 1)
list(APPEND ZM_BIN_LIBS "${GNUTLS_LIBRARIES}") list(APPEND ZM_BIN_LIBS "${GNUTLS_LIBRARIES}")

View File

@ -577,7 +577,7 @@ INSERT INTO Controls VALUES (NULL,'Foscam FI9821W','Ffmpeg','FI9821W_Y2k',1,0,1,
INSERT INTO Controls VALUES (NULL,'Loftek Sentinel','Remote','LoftekSentinel',0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,255,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,6,1,1,0,0,0,1,10,0,1,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0); INSERT INTO Controls VALUES (NULL,'Loftek Sentinel','Remote','LoftekSentinel',0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,255,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,6,1,1,0,0,0,1,10,0,1,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0);
INSERT INTO Controls VALUES (NULL,'Toshiba IK-WB11A','Remote','Toshiba_IK_WB11A',0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,10,0,1,1,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0); INSERT INTO Controls VALUES (NULL,'Toshiba IK-WB11A','Remote','Toshiba_IK_WB11A',0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,10,0,1,1,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0);
INSERT INTO Controls VALUES (NULL,'WanscamPT','Remote','Wanscam',1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,16,0,0,0,0,0,1,16,1,1,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0); INSERT INTO Controls VALUES (NULL,'WanscamPT','Remote','Wanscam',1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,16,0,0,0,0,0,1,16,1,1,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0);
INSERT INTO Controls VALUES (NULL,'3S Domo N5071', 'Remote', '3S', 0, 0, 1, 1, 0, 1, 1, 0, 0, 9999, 0, 9999, 0, 0, 0, 1, 1, 1, 1, 0, 0, 9999, 20, 9999, 0, 0, 0, 1, 1, 1, 1, 0, 0, 9999, 1, 9999, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 64, 1, 0, 1, 1, 0, 0, 0, 0, 1, -180, 180, 40, 100, 1, 40, 100, 0, 0, 1, -180, 180, 40, 100, 1, 40, 100, 0, 0, 0, 0);
-- --
-- Add some monitor preset values -- Add some monitor preset values
-- --

7
distros/debian/install Normal file
View File

@ -0,0 +1,7 @@
usr/bin
usr/lib/cgi-bin
usr/share/man
usr/share/perl5/ZoneMinder
usr/share/perl5/ZoneMinder.pm
usr/share/zoneminder
etc/zm

4
distros/debian/links Normal file
View File

@ -0,0 +1,4 @@
var/cache/zoneminder/events usr/share/zoneminder/events
var/cache/zoneminder/images usr/share/zoneminder/images
var/cache/zoneminder/temp usr/share/zoneminder/temp
usr/lib/cgi-bin usr/share/zoneminder/cgi-bin

View File

@ -0,0 +1,51 @@
zoneminder for Debian
---------------------
There is one manual step to get the web interface working.
You need to link /etc/zm/apache.conf to /etc/apache2/conf.d/zoneminder.conf,
then reload the apache config (i.e. /etc/init.d/apache2 reload)
Changing the location for images and events
-------------------------------------------
Zoneminder, in its upstream form, stores data in /usr/share/zoneminder/. This
package modifies that by changing /usr/share/zoneminder/images and
/usr/share/zoneminder/events to symlinks to directories under
/var/cache/zoneminder.
There are numerous places these could be put and ways to do it. But, at the
moment, if you change this, an upgrade will fail with a warning about these
locations having changed (the reason for this was that previously, an upgrade
would silently revert the changes and cause event loss - refer
bug #608793).
If you do want to change the location, here are a couple of suggestions.
These lines would mount /dev/sdX1 to /video_storage, and then 'link' /video_storage
to the locations that ZoneMinder expects them to be at.
/dev/sdX1 /video_storage ext4 defaults 0 2
/video_storage/zoneminder/images /var/cache/zoneminder/images none bind 0 2
/video_storage/zoneminder/events /var/cache/zoneminder/events none bind 0 2
or if you have a separate partition for each:
/dev/sdX1 /var/cache/zoneminder/images ext4 defaults 0 2
/dev/sdX2 /var/cache/zoneminder/events ext4 defaults 0 2
-- Peter Howard <pjh@northern-ridge.com.au>, Sun, 16 Jan 2010 01:35:51 +1100
Access to /dev/video*
---------------------
For cameras which require access to /dev/video*, zoneminder may need the
www-data user added to the video group in order to see those cameras:
adduser www-data video
Note that all web applications running on the zoneminder server will then have
access to all video devices on the system.
-- Vagrant Cascadian <vagrant@debian.org> Sun, 27 Mar 2011 13:06:56 -0700

View File

@ -0,0 +1,9 @@
Alias /zm /usr/share/zoneminder
<Directory /usr/share/zoneminder>
php_flag register_globals off
Options Indexes FollowSymLinks
<IfModule mod_dir.c>
DirectoryIndex index.php
</IfModule>
</Directory>

View File

@ -0,0 +1,29 @@
zoneminder (1.28.0-0.1) wheezy; urgency=low
* Use CMake instead of Autotools to simplify
debian/rules and have less build-depends.
* Some lintian love in debian/{control,copyright}
and perl ZoneMinder modules.
* Don't purge database if we use a remote
MySQL server.
-- Cosme Domínguez Díaz <cosme.ddiaz@gmail.com> Sun, 09 Nov 2014 02:20:20 +0100
zoneminder (1.28.0-wheezy) wheezy; urgency=medium
* Release
-- Isaac Connor <iconnor@connortechnology.com> Fri, 17 Oct 2014 09:27:22 -0400
zoneminder (1.27.99+1-testing-SNAPSHOT2014072901) testing; urgency=medium
* improve error messages
* Make zmupdate re-run the most recent patch so that people running the daily builds get their db updates
-- Isaac Connor <iconnor@connortechnology.com> Tue, 29 Jul 2014 14:50:20 -0400
zoneminder (1.27.0+1-testing-v4ltomonitor-1) testing; urgency=high
* Snapshot release -
-- Isaac Connor <iconnor@connortechnology.com> Wed, 09 Jul 2014 21:35:29 -0400

View File

@ -0,0 +1 @@
9

View File

@ -0,0 +1,40 @@
Source: zoneminder
Section: net
Priority: optional
Maintainer: Isaac Connor <iconnor@connortechnology.com>
Build-Depends: debhelper (>= 9), cmake, libphp-serialization-perl, libgnutls-dev, libmysqlclient-dev | libmariadbclient-dev, libdbd-mysql-perl, libdate-manip-perl, libwww-perl, libjpeg8-dev, libpcre3-dev, libavcodec-dev, libavformat-dev (>= 3:0.svn20090204), libswscale-dev (>= 3:0.svn20090204), libavutil-dev, libv4l-dev (>= 0.8.3), libbz2-dev, libsys-mmap-perl, libav-tools, libnetpbm10-dev, libavdevice-dev, libdevice-serialport-perl, libarchive-zip-perl, libmime-lite-perl, libvlccore-dev, libvlc-dev, libcurl4-gnutls-dev | libcurl4-nss-dev | libcurl4-openssl-dev, libgcrypt11-dev, libpolkit-gobject-1-dev
Standards-Version: 3.9.4
Package: zoneminder
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}, apache2 | httpd, libapache2-mod-php5 | libapache2-mod-fcgid | php5-fpm, php5-mysqlnd | php5-mysql, libphp-serialization-perl, libdate-manip-perl, libmime-lite-perl, libmime-tools-perl, mariadb-client | mysql-client, libwww-perl, libarchive-tar-perl, libarchive-zip-perl, libdevice-serialport-perl, libpcre3, libav-tools, rsyslog | system-log-daemon, libmodule-load-perl, libsys-mmap-perl, libjson-any-perl, netpbm, libavdevice53, libjpeg8, zip, libnet-sftp-foreign-perl, libio-pty-perl, libexpect-perl, libvlccore5 | libvlccore7, libvlc5, libcurl4-gnutls-dev | libcurl4-nss-dev | libcurl4-openssl-dev, libpolkit-gobject-1-0
Recommends: mysql-server | mariadb-server
Description: Video camera security and surveillance solution
ZoneMinder is intended for use in single or multi-camera video security
applications, including commercial or home CCTV, theft prevention and child
or family member or home monitoring and other care scenarios. It
supports capture, analysis, recording, and monitoring of video data coming
from one or more video or network cameras attached to a Linux system.
ZoneMinder also support web and semi-automatic control of Pan/Tilt/Zoom
cameras using a variety of protocols. It is suitable for use as a home
video security system and for commercial or professional video security
and surveillance. It can also be integrated into a home automation system
via X.10 or other protocols.
Package: zoneminder-dbg
Architecture: any
Priority: extra
Section: debug
Depends: zoneminder (= ${binary:Version}), ${misc:Depends}
Description: debugging syumbols for zoneminder.
ZoneMinder is a video camera security and surveillance solution.
ZoneMinder is intended for use in single or multi-camera video security
applications, including commercial or home CCTV, theft prevention and child
or family member or home monitoring and other care scenarios. It
supports capture, analysis, recording, and monitoring of video data coming
from one or more video or network cameras attached to a Linux system.
ZoneMinder also support web and semi-automatic control of Pan/Tilt/Zoom
cameras using a variety of protocols. It is suitable for use as a home
video security system and for commercial or professional video security
and surveillance. It can also be integrated into a home automation system
via X.10 or other protocols.

View File

@ -0,0 +1,57 @@
Copyright:
Copyright 2002 Philip Coombes <philip.coombes@zoneminder.com>
License:
This package 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 package 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 package; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
On Debian GNU/Linux systems, the text of the GPL can be found in
/usr/share/common-licenses/GPL.
/usr/share/zoneminder/api/lib/Cake/*:
Copyright:
Copyright (c) 2005-2013, Cake Software Foundation, Inc.
License:
CakePHP(tm) : The Rapid Development PHP Framework (http://cakephp.org)
The MIT License
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
Cake Software Foundation, Inc.
1785 E. Sahara Avenue,
Suite 490-204
Las Vegas, Nevada 89104,
United States of America.

View File

@ -0,0 +1,5 @@
var/log/zm
var/lib/zm
var/cache/zoneminder/events
var/cache/zoneminder/images
var/cache/zoneminder/temp

View File

@ -0,0 +1 @@
README.md

View File

@ -0,0 +1,87 @@
#!/bin/sh
### BEGIN INIT INFO
# Provides: zoneminder
# Required-Start: $network $remote_fs $syslog
# Required-Stop: $network $remote_fs $syslog
# Should-Start: mysql
# Should-Stop: mysql
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Control ZoneMinder as a Service
### END INIT INFO
# description: Control ZoneMinder as a Service
# chkconfig: 2345 20 20
# Source function library.
#. /etc/rc.d/init.d/functions
prog=ZoneMinder
ZM_PATH_BIN="/usr/bin"
RUNDIR=/var/run/zm
TMPDIR=/tmp/zm
command="$ZM_PATH_BIN/zmpkg.pl"
start() {
echo -n "Starting $prog: "
mkdir -p $RUNDIR $TMPDIR && chown www-data:www-data $RUNDIR $TMPDIR
$command start
RETVAL=$?
[ $RETVAL = 0 ] && echo success || echo failure
echo
[ $RETVAL = 0 ] && touch /var/lock/zm
return $RETVAL
}
stop() {
echo -n "Stopping $prog: "
#
# Why is this status check being done?
# as $command stop returns 1 if zoneminder
# is stopped, which will result in
# this returning 1, which will stuff
# dpkg when it tries to stop zoneminder before
# uninstalling . . .
#
result=`$command status`
if [ ! "$result" = "running" ]; then
echo "Zoneminder already stopped"
echo
RETVAL=0
else
$command stop
RETVAL=$?
[ $RETVAL = 0 ] && echo success || echo failure
echo
[ $RETVAL = 0 ] && rm -f /var/lock/zm
fi
}
status() {
result=`$command status`
if [ "$result" = "running" ]; then
echo "ZoneMinder is running"
RETVAL=0
else
echo "ZoneMinder is stopped"
RETVAL=1
fi
}
case "$1" in
'start')
start
;;
'stop')
stop
;;
'restart' | 'force-reload')
stop
start
;;
'status')
status
;;
*)
echo "Usage: $0 { start | stop | restart | status }"
RETVAL=1
;;
esac
exit $RETVAL

View File

@ -0,0 +1,7 @@
usr/bin
usr/lib/cgi-bin
usr/share/man
usr/share/perl5/ZoneMinder
usr/share/perl5/ZoneMinder.pm
usr/share/zoneminder
etc/zm

View File

@ -0,0 +1,4 @@
var/cache/zoneminder/events usr/share/zoneminder/events
var/cache/zoneminder/images usr/share/zoneminder/images
var/cache/zoneminder/temp usr/share/zoneminder/temp
usr/lib/cgi-bin usr/share/zoneminder/cgi-bin

View File

@ -0,0 +1,53 @@
#! /bin/sh
set -e
if [ "$1" = "configure" ]; then
if [ -e "/etc/init.d/mysql" ]; then
#
# Get mysql started if it isn't
#
if ! $(/etc/init.d/mysql status >/dev/null 2>&1); then
invoke-rc.d mysql start
fi
if $(/etc/init.d/mysql status >/dev/null 2>&1); then
mysqladmin --defaults-file=/etc/mysql/debian.cnf -f reload
# test if database if already present...
if ! $(echo quit | mysql --defaults-file=/etc/mysql/debian.cnf zm > /dev/null 2> /dev/null) ; then
cat /usr/share/zoneminder/db/zm_create.sql | mysql --defaults-file=/etc/mysql/debian.cnf
echo 'grant lock tables, alter,select,insert,update,delete on zm.* to 'zmuser'@localhost identified by "zmpass";' | mysql --defaults-file=/etc/mysql/debian.cnf mysql
fi
invoke-rc.d zoneminder stop || true
zmupdate.pl --nointeractive
else
echo 'NOTE: mysql not running, please start mysql and run dpkg-reconfigure zoneminder when it is running.'
fi
else
echo 'mysql not found, assuming remote server.'
fi
chown www-data:www-data /var/log/zm
chown www-data:www-data /var/lib/zm/
if [ -z "$2" ]; then
chown www-data:www-data -R /var/cache/zoneminder
fi
fi
# Ensure zoneminder is stopped...
if [ -x "/etc/init.d/zoneminder" ]; then
if invoke-rc.d zoneminder status ; then
invoke-rc.d zoneminder stop || exit $?
fi
fi
if [ "$1" = "configure" ]; then
if [ -z "$2" ]; then
chown www-data:www-data /var/log/zm
chown www-data:www-data /var/lib/zm/
chown www-data:www-data -R /var/cache/zoneminder
else
chown www-data:www-data /var/log/zm
zmupdate.pl
fi
fi
#DEBHELPER#

View File

@ -0,0 +1,11 @@
#! /bin/sh
set -e
if [ "$1" = "purge" ]; then
if [ -e "/etc/init.d/mysql" ]; then
echo 'delete from user where User="zmuser";' | mysql --defaults-file=/etc/mysql/debian.cnf mysql
echo 'delete from db where User="zmuser";' | mysql --defaults-file=/etc/mysql/debian.cnf mysql
mysqladmin --defaults-file=/etc/mysql/debian.cnf -f drop zm
fi
fi
#DEBHELPER#

View File

@ -0,0 +1,32 @@
#!/bin/sh
set -e
abort=false
if [ -L /usr/share/zoneminder/events ]; then
l=$(readlink /usr/share/zoneminder/events)
if [ "$l" != "/var/cache/zoneminder/events" ]; then
abort=true
fi
fi
if [ -L /usr/share/zoneminder/images ]; then
l=$(readlink /usr/share/zoneminder/images )
if [ "$l" != "/var/cache/zoneminder/images" ]; then
abort=true
fi
fi
if [ "$abort" = "true" ]; then
cat >&2 << EOF
Aborting installation of zoneminder due to non-default symlinks in
/usr/share/zoneminder for the images and/or events directory, which could
result in loss of data. Please move your data in each of these directories to
/var/cache/zoneminder before installing zoneminder from the package.
EOF
exit 1
fi
#DEBHELPER#
exit 0

42
distros/debian_cmake/rules Executable file
View File

@ -0,0 +1,42 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
export CFLAGS = -g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -pipe
export CXXFLAGS = -g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -pipe
INSTDIR = debian/tmp
override_dh_auto_configure:
dh_auto_configure -- \
-DCMAKE_INSTALL_PREFIX=/usr \
-DCMAKE_SKIP_RPATH=ON \
-DCMAKE_VERBOSE_MAKEFILE=OFF \
-DCMAKE_COLOR_MAKEFILE=ON \
-DZM_RUNDIR=/var/run/zm \
-DZM_SOCKDIR=/var/run/zm \
-DZM_TMPDIR=/var/tmp/zm \
-DZM_LOGDIR=/var/log/zm \
-DZM_WEBDIR=/usr/share/zoneminder \
-DZM_CONTENTDIR=/var/cache/zoneminder \
-DZM_CGIDIR=/usr/lib/cgi-bin \
-DZM_WEB_USER=www-data \
-DZM_WEB_GROUP=www-data \
-DZM_PERL_SUBPREFIX=/share/perl5 \
-DCMAKE_INSTALL_SYSCONFDIR=etc/zm
override_dh_auto_install:
dh_auto_install --buildsystem=cmake
install -D -m 0644 debian/apache.conf $(INSTDIR)/etc/zm/apache.conf
rm $(INSTDIR)/usr/share/zoneminder/api/lib/Cake/LICENSE.txt
rm $(INSTDIR)/usr/share/zoneminder/api/.gitignore
rm -r $(INSTDIR)/usr/share/zoneminder/api/lib/Cake/Test
override_dh_auto_test:
# do not run tests...
override_dh_strip:
dh_strip --dbg-package=zoneminder-dbg
%:
dh $@ --buildsystem=cmake --parallel

View File

@ -0,0 +1,3 @@
version=3
http://www.zoneminder.com/downloads.html \
.*/ZoneMinder-(.*).tar.gz

View File

@ -442,6 +442,15 @@ our @options =
type => $types{string}, type => $types{string},
category => "images", category => "images",
}, },
{
name => "ZM_FFMPEG_OPEN_TIMEOUT",
default => "10",
description => "Timeout in seconds when opening a stream.",
help => "When Ffmpeg is opening a stream, it can take a long time before failing; certain circumstances even seem to be able to lock indefinitely. This option allows you to set a maximum time in seconds to pass before closing the stream and trying to reopen it again.",
requires => [ { name=>"ZM_OPT_FFMPEG", value=>"yes" } ],
type => $types{integer},
category => "images",
},
{ {
name => "ZM_LOG_LEVEL_SYSLOG", name => "ZM_LOG_LEVEL_SYSLOG",
default => "0", default => "0",

View File

@ -0,0 +1,606 @@
# ==========================================================================
#
# ZoneMinder 3S API Control Protocol Module, $Date: 2014-11-12 08:00:00 +0300 (Tue, 21 Jun 2011) $, $Revision: 1 $
# Copyright (C) 2014 Juan Manuel Castro
#
# 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 implementation of the 3S camera control
# protocol
#Model: N5071
#Hardware Version: 00
#Firmware Version: V1.03_STD-1
#Firmware Build Time: Jun 19 2012 15:28:17
package ZoneMinder::Control::3S;
use 5.006;
use strict;
use warnings;
require ZoneMinder::Base;
require ZoneMinder::Control;
our @ISA = qw(ZoneMinder::Control);
our $VERSION = $ZoneMinder::Base::VERSION;
# ==========================================================================
#
# 3S Control Protocol
#
# ==========================================================================
use ZoneMinder::Logger qw(:all);
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;
}
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 open
{
my $self = shift;
$self->loadMonitor();
use LWP::UserAgent;
$self->{ua} = LWP::UserAgent->new;
#$self->{ua}->agent( "ZoneMinder Control Agent/".ZM_VERSION );
$self->{ua}->agent( "ZoneMinder Control Agent/" . ZoneMinder::Base::ZM_VERSION );
$self->{state} = 'open';
}
sub close
{
my $self = shift;
$self->{state} = 'closed';
}
sub printMsg
{
my $self = shift;
my $msg = shift;
my $msg_len = length($msg);
Debug( $msg."[".$msg_len."]" );
}
sub sendCmd
{
my $self = shift;
my $cmd = shift;
my $result = undef;
printMsg( $cmd, "Tx" );
#print("http://".$self->{Monitor}->{ControlAddress}."/$cmd");
my $req = HTTP::Request->new( GET=>"http://".$self->{Monitor}->{ControlAddress}."/$cmd" );
my $res = $self->{ua}->request($req);
if ( $res->is_success )
{
$result = !undef;
}
else
{
Error( "Error check failed: '".$res->status_line()."'" );
}
return( $result );
}
sub cameraReset
{
my $self = shift;
Debug( "Camera Reset" );
my $cmd = "/restart.cgi";
$self->sendCmd( $cmd );
}
#Custom#
#Move X or Y Axis
sub Up
{
my $self = shift;
Debug( "Move Up" );
my $cmd = "/ptz.cgi?move=up";
$self->sendCmd( $cmd );
}
sub Down
{
my $self = shift;
Debug( "Move Down" );
my $cmd = "/ptz.cgi?move=down";
$self->sendCmd( $cmd );
}
sub Left
{
my $self = shift;
Debug( "Move Left" );
my $cmd = "/ptz.cgi?move=left";
$self->sendCmd( $cmd );
}
sub Right
{
my $self = shift;
Debug( "Move Right" );
my $cmd = "/ptz.cgi?move=right";
$self->sendCmd( $cmd );
}
##Zoom
sub Tele
{
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'step' );
Debug( "Zoom Tele" );
my $cmd = "/ptz.cgi?rzoom=$step";
$self->sendCmd( $cmd );
}
sub Wide
{
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'step' );
Debug( "Zoom Wide" );
my $cmd = "/ptz.cgi?rzoom=-$step";
$self->sendCmd( $cmd );
}
#Move X and Y Axis
sub UpRight
{
my $self = shift;
Debug( "Move Up/Right" );
my $cmd = "/ptz.cgi?move=upright";
$self->sendCmd( $cmd );
}
sub UpLeft
{
my $self = shift;
Debug( "Move Up/Left" );
my $cmd = "/ptz.cgi?move=upleft";
$self->sendCmd( $cmd );
}
sub DownRight
{
my $self = shift;
Debug( "Move Down/Right" );
my $cmd = "/ptz.cgi?move=downright";
$self->sendCmd( $cmd );
}
sub DownLeft
{
my $self = shift;
Debug( "Move Down/Left" );
my $cmd = "/ptz.cgi?move=downleft";
$self->sendCmd( $cmd );
}
#Foco
sub focusAuto
{
my $self = shift;
Debug( "Focus Auto" );
my $cmd = "/ptz.cgi?Autofocus=on";
$self->sendCmd( $cmd );
}
sub focusMan
{
my $self = shift;
Debug( "Focus Manual" );
my $cmd = "/ptz.cgi?Autofocus=off";
$self->sendCmd( $cmd );
}
sub Near
{
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'step' );
Debug( "Focus Near" );
my $cmd = "/ptz.cgi?rfocus=-$step";
$self->sendCmd( $cmd );
}
sub Far
{
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'step' );
Debug( "Focus Far" );
my $cmd = "/ptz.cgi?rfocus=$step";
$self->sendCmd( $cmd );
}
#Iris
sub Open
{
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'step' );
Debug( "Iris Open" );
my $cmd = "/ptz.cgi?riris=$step";
$self->sendCmd( $cmd );
}
sub Close
{
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'step' );
Debug( "Iris Close" );
my $cmd = "/ptz.cgi?riris=-$step";
$self->sendCmd( $cmd );
}
#Custom#
sub moveConUp
{
my $self = shift;
Debug( "Move Up" );
my $cmd = "/ptz.cgi?move=up";
$self->sendCmd( $cmd );
}
sub moveConDown
{
my $self = shift;
Debug( "Move Down" );
my $cmd = "/ptz.cgi?move=down";
$self->sendCmd( $cmd );
}
sub moveConLeft
{
my $self = shift;
Debug( "Move Left" );
my $cmd = "/ptz.cgi?move=left";
$self->sendCmd( $cmd );
}
sub moveConRight
{
my $self = shift;
Debug( "Move Right" );
my $cmd = "/ptz.cgi?move=right";
$self->sendCmd( $cmd );
}
sub moveConUpRight
{
my $self = shift;
Debug( "Move Up/Right" );
my $cmd = "/ptz.cgi?move=upright";
$self->sendCmd( $cmd );
}
sub moveConUpLeft
{
my $self = shift;
Debug( "Move Up/Left" );
my $cmd = "/ptz.cgi?move=upleft";
$self->sendCmd( $cmd );
}
sub moveConDownRight
{
my $self = shift;
Debug( "Move Down/Right" );
my $cmd = "/ptz.cgi?move=downright";
$self->sendCmd( $cmd );
}
sub moveConDownLeft
{
my $self = shift;
Debug( "Move Down/Left" );
my $cmd = "/ptz.cgi?move=downleft";
$self->sendCmd( $cmd );
}
sub moveRelUp
{
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'tiltstep' );
Debug( "Step Up $step" );
my $cmd = "/ptz.cgi?tilt=$step";
$self->sendCmd( $cmd );
}
sub moveRelDown
{
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'tiltstep' );
Debug( "Step Down $step" );
my $cmd = "/ptz.cgi?tilt=-$step";
$self->sendCmd( $cmd );
}
sub moveRelLeft
{
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'panstep' );
Debug( "Step Left $step" );
my $cmd = "/ptz.cgi?pan=-$step";
$self->sendCmd( $cmd );
}
sub moveRelRight
{
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'panstep' );
Debug( "Step Right $step" );
my $cmd = "/ptz.cgi?pan=$step";
$self->sendCmd( $cmd );
}
sub moveRelUpRight
{
my $self = shift;
my $params = shift;
my $panstep = $self->getParam( $params, 'panstep' );
my $tiltstep = $self->getParam( $params, 'tiltstep' );
Debug( "Step Up/Right $tiltstep/$panstep" );
my $cmd = "/ptz.cgi?pan=$panstep&tilt=$tiltstep";
$self->sendCmd( $cmd );
}
sub moveRelUpLeft
{
my $self = shift;
my $params = shift;
my $panstep = $self->getParam( $params, 'panstep' );
my $tiltstep = $self->getParam( $params, 'tiltstep' );
Debug( "Step Up/Left $tiltstep/$panstep" );
my $cmd = "/ptz.cgi?pan=-$panstep&tilt=$tiltstep";
$self->sendCmd( $cmd );
}
sub moveRelDownRight
{
my $self = shift;
my $params = shift;
my $panstep = $self->getParam( $params, 'panstep' );
my $tiltstep = $self->getParam( $params, 'tiltstep' );
Debug( "Step Down/Right $tiltstep/$panstep" );
my $cmd = "/ptz.cgi?pan=$panstep&tilt=-$tiltstep";
$self->sendCmd( $cmd );
}
sub moveRelDownLeft
{
my $self = shift;
my $params = shift;
my $panstep = $self->getParam( $params, 'panstep' );
my $tiltstep = $self->getParam( $params, 'tiltstep' );
Debug( "Step Down/Left $tiltstep/$panstep" );
my $cmd = "/ptz.cgi?pan=-$panstep&tilt=-$tiltstep";
$self->sendCmd( $cmd );
}
sub zoomRelTele
{
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'step' );
Debug( "Zoom Tele" );
my $cmd = "/ptz.cgi?rzoom=$step";
$self->sendCmd( $cmd );
}
sub zoomRelWide
{
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'step' );
Debug( "Zoom Wide" );
my $cmd = "/ptz.cgi?rzoom=-$step";
$self->sendCmd( $cmd );
}
sub focusRelNear
{
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'step' );
Debug( "Focus Near" );
my $cmd = "/ptz.cgi?rfocus=-$step";
$self->sendCmd( $cmd );
}
sub focusRelFar
{
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'step' );
Debug( "Focus Far" );
my $cmd = "/ptz.cgi?rfocus=$step";
$self->sendCmd( $cmd );
}
sub focusAuto
{
my $self = shift;
Debug( "Focus Auto" );
my $cmd = "/ptz.cgi?Autofocus=on";
$self->sendCmd( $cmd );
}
sub focusMan
{
my $self = shift;
Debug( "Focus Manual" );
my $cmd = "/ptz.cgi?Autofocus=off";
$self->sendCmd( $cmd );
}
sub irisRelOpen
{
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'step' );
Debug( "Iris Open" );
my $cmd = "/ptz.cgi?riris=$step";
$self->sendCmd( $cmd );
}
sub irisRelClose
{
my $self = shift;
my $params = shift;
my $step = $self->getParam( $params, 'step' );
Debug( "Iris Close" );
my $cmd = "/ptz.cgi?riris=-$step";
$self->sendCmd( $cmd );
}
sub irisAuto
{
my $self = shift;
Debug( "Iris Auto" );
my $cmd = "/ptz.cgi?autoiris=on";
$self->sendCmd( $cmd );
}
sub irisMan
{
my $self = shift;
Debug( "Iris Manual" );
my $cmd = "/ptz.cgi?autoiris=off";
$self->sendCmd( $cmd );
}
sub presetClear
{
my $self = shift;
my $params = shift;
my $preset = $self->getParam( $params, 'preset' );
Debug( "Clear Preset $preset" );
my $cmd = "/ptz.cgi?removeserverpresetno=$preset";
$self->sendCmd( $cmd );
}
sub presetGoto
{
my $self = shift;
my $params = shift;
my $preset = $self->getParam( $params, 'preset' );
Debug( "Goto Preset $preset" );
my $cmd = "/ptz.cgi?gotoserverpresetno=$preset";
$self->sendCmd( $cmd );
}
sub presetHome
{
my $self = shift;
Debug( "Home Preset" );
my $cmd = "/ptz.cgi?move=home";
$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
=head1 SYNOPSIS
use ZoneMinder::Database;
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.
=head1 AUTHOR
Juan Manuel Castro, E<lt>juanmanuel.castro@gmail.comE<gt>
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2014 Juan Manuel Castro
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.3 or,
at your option, any later version of Perl 5 you may have available.
=cut

View File

@ -151,7 +151,7 @@ public:
{ {
if ( mSize == 0 ) if ( mSize == 0 )
mHead = mTail = mStorage; mHead = mTail = mStorage;
else if ( level >= 1 ) else if ( level )
{ {
if ( (mHead-mStorage) > mSize ) if ( (mHead-mStorage) > mSize )
{ {
@ -159,12 +159,6 @@ public:
mHead = mStorage; mHead = mStorage;
mTail = mHead + mSize; mTail = mHead + mSize;
} }
else if ( level >= 2 )
{
memmove( mStorage, mHead, mSize );
mHead = mStorage;
mTail = mHead + mSize;
}
} }
} }
} }

View File

@ -23,6 +23,10 @@
#include "zm_ffmpeg_camera.h" #include "zm_ffmpeg_camera.h"
#ifndef AV_ERROR_MAX_STRING_SIZE
#define AV_ERROR_MAX_STRING_SIZE 64
#endif
FfmpegCamera::FfmpegCamera( int p_id, const std::string &p_path, const std::string &p_method, const std::string &p_options, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ) : FfmpegCamera::FfmpegCamera( int p_id, const std::string &p_path, const std::string &p_method, const std::string &p_options, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ) :
Camera( p_id, FFMPEG_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture ), Camera( p_id, FFMPEG_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture ),
mPath( p_path ), mPath( p_path ),
@ -41,6 +45,10 @@ FfmpegCamera::FfmpegCamera( int p_id, const std::string &p_path, const std::stri
mRawFrame = NULL; mRawFrame = NULL;
mFrame = NULL; mFrame = NULL;
frameCount = 0; frameCount = 0;
mIsOpening = false;
mCanCapture = false;
mOpenStart = 0;
mReopenThread = 0;
#if HAVE_LIBSWSCALE #if HAVE_LIBSWSCALE
mConvertContext = NULL; mConvertContext = NULL;
@ -63,31 +71,7 @@ FfmpegCamera::FfmpegCamera( int p_id, const std::string &p_path, const std::stri
FfmpegCamera::~FfmpegCamera() FfmpegCamera::~FfmpegCamera()
{ {
av_freep( &mFrame ); CloseFfmpeg();
av_freep( &mRawFrame );
#if HAVE_LIBSWSCALE
if ( mConvertContext )
{
sws_freeContext( mConvertContext );
mConvertContext = NULL;
}
#endif
if ( mCodecContext )
{
avcodec_close( mCodecContext );
mCodecContext = NULL; // Freed by av_close_input_file
}
if ( mFormatContext )
{
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 17, 0)
avformat_close_input( &mFormatContext );
#else
av_close_input_file( mFormatContext );
#endif
mFormatContext = NULL;
}
if ( capture ) if ( capture )
{ {
@ -113,115 +97,10 @@ int FfmpegCamera::PrimeCapture()
{ {
Info( "Priming capture from %s", mPath.c_str() ); Info( "Priming capture from %s", mPath.c_str() );
if (OpenFfmpeg() != 0){
ReopenFfmpeg();
// Open the input, not necessarily a file
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 4, 0)
if ( av_open_input_file( &mFormatContext, mPath.c_str(), NULL, 0, NULL ) !=0 )
#else
// Handle options
AVDictionary *opts = 0;
StringVector opVect = split(Options(), ",");
// Set transport method as specified by method field, rtpUni is default
if ( Method() == "rtpMulti" )
opVect.push_back("rtsp_transport=udp_multicast");
else if ( Method() == "rtpRtsp" )
opVect.push_back("rtsp_transport=tcp");
else if ( Method() == "rtpRtspHttp" )
opVect.push_back("rtsp_transport=http");
Debug(2, "Number of Options: %d",opVect.size());
for (size_t i=0; i<opVect.size(); i++)
{
StringVector parts = split(opVect[i],"=");
if (parts.size() > 1) {
parts[0] = trimSpaces(parts[0]);
parts[1] = trimSpaces(parts[1]);
if ( av_dict_set(&opts, parts[0].c_str(), parts[1].c_str(), 0) == 0 ) {
Debug(2, "set option %d '%s' to '%s'", i, parts[0].c_str(), parts[1].c_str());
}
else
{
Warning( "Error trying to set option %d '%s' to '%s'", i, parts[0].c_str(), parts[1].c_str() );
}
}
} }
return 0;
if ( avformat_open_input( &mFormatContext, mPath.c_str(), NULL, &opts ) !=0 )
#endif
Fatal( "Unable to open input %s due to: %s", mPath.c_str(), strerror(errno) );
// Locate stream info from input
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 4, 0)
if ( av_find_stream_info( mFormatContext ) < 0 )
#else
if ( avformat_find_stream_info( mFormatContext, 0 ) < 0 )
#endif
Fatal( "Unable to find stream info from %s due to: %s", mPath.c_str(), strerror(errno) );
// Find first video stream present
mVideoStreamId = -1;
for (unsigned int i=0; i < mFormatContext->nb_streams; i++ )
{
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51,2,1)
if ( mFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO )
#else
if ( mFormatContext->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO )
#endif
{
mVideoStreamId = i;
break;
}
}
if ( mVideoStreamId == -1 )
Fatal( "Unable to locate video stream in %s", mPath.c_str() );
mCodecContext = mFormatContext->streams[mVideoStreamId]->codec;
// Try and get the codec from the codec context
if ( (mCodec = avcodec_find_decoder( mCodecContext->codec_id )) == NULL )
Fatal( "Can't find codec for video stream from %s", mPath.c_str() );
// Open the codec
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 7, 0)
if ( avcodec_open( mCodecContext, mCodec ) < 0 )
#else
if ( avcodec_open2( mCodecContext, mCodec, 0 ) < 0 )
#endif
Fatal( "Unable to open codec for video stream from %s", mPath.c_str() );
// Allocate space for the native video frame
mRawFrame = avcodec_alloc_frame();
// Allocate space for the converted video frame
mFrame = avcodec_alloc_frame();
if(mRawFrame == NULL || mFrame == NULL)
Fatal( "Unable to allocate frame for %s", mPath.c_str() );
int pSize = avpicture_get_size( imagePixFormat, width, height );
if( (unsigned int)pSize != imagesize) {
Fatal("Image size mismatch. Required: %d Available: %d",pSize,imagesize);
}
#if HAVE_LIBSWSCALE
#if LIBSWSCALE_VERSION_INT >= AV_VERSION_INT(0, 8, 0)
if(!sws_isSupportedInput(mCodecContext->pix_fmt)) {
Fatal("swscale does not support the codec format: %c%c%c%c",(mCodecContext->pix_fmt)&0xff,((mCodecContext->pix_fmt>>8)&0xff),((mCodecContext->pix_fmt>>16)&0xff),((mCodecContext->pix_fmt>>24)&0xff));
}
if(!sws_isSupportedOutput(imagePixFormat)) {
Fatal("swscale does not support the target format: %c%c%c%c",(imagePixFormat)&0xff,((imagePixFormat>>8)&0xff),((imagePixFormat>>16)&0xff),((imagePixFormat>>24)&0xff));
}
#endif
#else // HAVE_LIBSWSCALE
Fatal( "You must compile ffmpeg with the --enable-swscale option to use ffmpeg cameras" );
#endif // HAVE_LIBSWSCALE
return( 0 );
} }
int FfmpegCamera::PreCapture() int FfmpegCamera::PreCapture()
@ -232,6 +111,24 @@ int FfmpegCamera::PreCapture()
int FfmpegCamera::Capture( Image &image ) int FfmpegCamera::Capture( Image &image )
{ {
if (!mCanCapture){
return -1;
}
// If the reopen thread has a value, but mCanCapture != 0, then we have just reopened the connection to the ffmpeg device, and we can clean up the thread.
if (mReopenThread != 0) {
void *retval = 0;
int ret;
ret = pthread_tryjoin_np(mReopenThread, &retval);
if (ret != 0){
Error("Could not join reopen thread.");
}
Info( "Successfully reopened stream." );
mReopenThread = 0;
}
AVPacket packet; AVPacket packet;
uint8_t* directbuffer; uint8_t* directbuffer;
@ -248,7 +145,20 @@ int FfmpegCamera::Capture( Image &image )
int avResult = av_read_frame( mFormatContext, &packet ); int avResult = av_read_frame( mFormatContext, &packet );
if ( avResult < 0 ) if ( avResult < 0 )
{ {
Error( "Unable to read packet from stream %d: error %d", packet.stream_index, avResult ); char errbuf[AV_ERROR_MAX_STRING_SIZE];
av_strerror(avResult, errbuf, AV_ERROR_MAX_STRING_SIZE);
if (
// Check if EOF.
(avResult == AVERROR_EOF || (mFormatContext->pb && mFormatContext->pb->eof_reached)) ||
// Check for Connection failure.
(avResult == -110)
)
{
Info( "av_read_frame returned \"%s\". Reopening stream.", errbuf);
ReopenFfmpeg();
}
Error( "Unable to read packet from stream %d: error %d \"%s\".", packet.stream_index, avResult, errbuf );
return( -1 ); return( -1 );
} }
Debug( 5, "Got packet from stream %d", packet.stream_index ); Debug( 5, "Got packet from stream %d", packet.stream_index );
@ -300,4 +210,235 @@ int FfmpegCamera::PostCapture()
return( 0 ); return( 0 );
} }
int FfmpegCamera::OpenFfmpeg() {
Debug ( 2, "OpenFfmpeg called." );
mOpenStart = time(NULL);
mIsOpening = true;
// Open the input, not necessarily a file
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 4, 0)
Debug ( 1, "Calling av_open_input_file" );
if ( av_open_input_file( &mFormatContext, mPath.c_str(), NULL, 0, NULL ) !=0 )
#else
// Handle options
AVDictionary *opts = 0;
StringVector opVect = split(Options(), ",");
// Set transport method as specified by method field, rtpUni is default
if ( Method() == "rtpMulti" )
opVect.push_back("rtsp_transport=udp_multicast");
else if ( Method() == "rtpRtsp" )
opVect.push_back("rtsp_transport=tcp");
else if ( Method() == "rtpRtspHttp" )
opVect.push_back("rtsp_transport=http");
Debug(2, "Number of Options: %d",opVect.size());
for (size_t i=0; i<opVect.size(); i++)
{
StringVector parts = split(opVect[i],"=");
if (parts.size() > 1) {
parts[0] = trimSpaces(parts[0]);
parts[1] = trimSpaces(parts[1]);
if ( av_dict_set(&opts, parts[0].c_str(), parts[1].c_str(), 0) == 0 ) {
Debug(2, "set option %d '%s' to '%s'", i, parts[0].c_str(), parts[1].c_str());
}
else
{
Warning( "Error trying to set option %d '%s' to '%s'", i, parts[0].c_str(), parts[1].c_str() );
}
}
}
Debug ( 1, "Calling avformat_open_input" );
mFormatContext = avformat_alloc_context( );
mFormatContext->interrupt_callback.callback = FfmpegInterruptCallback;
mFormatContext->interrupt_callback.opaque = this;
if ( avformat_open_input( &mFormatContext, mPath.c_str(), NULL, &opts ) !=0 )
#endif
{
mIsOpening = false;
Error( "Unable to open input %s due to: %s", mPath.c_str(), strerror(errno) );
return -1;
}
mIsOpening = false;
Debug ( 1, "Opened input" );
// Locate stream info from avformat_open_input
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 4, 0)
Debug ( 1, "Calling av_find_stream_info" );
if ( av_find_stream_info( mFormatContext ) < 0 )
#else
Debug ( 1, "Calling avformat_find_stream_info" );
if ( avformat_find_stream_info( mFormatContext, 0 ) < 0 )
#endif
Fatal( "Unable to find stream info from %s due to: %s", mPath.c_str(), strerror(errno) );
Debug ( 1, "Got stream info" );
// Find first video stream present
mVideoStreamId = -1;
for (unsigned int i=0; i < mFormatContext->nb_streams; i++ )
{
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51,2,1)
if ( mFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO )
#else
if ( mFormatContext->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO )
#endif
{
mVideoStreamId = i;
break;
}
}
if ( mVideoStreamId == -1 )
Fatal( "Unable to locate video stream in %s", mPath.c_str() );
Debug ( 1, "Found video stream" );
mCodecContext = mFormatContext->streams[mVideoStreamId]->codec;
// Try and get the codec from the codec context
if ( (mCodec = avcodec_find_decoder( mCodecContext->codec_id )) == NULL )
Fatal( "Can't find codec for video stream from %s", mPath.c_str() );
Debug ( 1, "Found decoder" );
// Open the codec
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 7, 0)
Debug ( 1, "Calling avcodec_open" );
if ( avcodec_open( mCodecContext, mCodec ) < 0 )
#else
Debug ( 1, "Calling avcodec_open2" );
if ( avcodec_open2( mCodecContext, mCodec, 0 ) < 0 )
#endif
Fatal( "Unable to open codec for video stream from %s", mPath.c_str() );
Debug ( 1, "Opened codec" );
// Allocate space for the native video frame
mRawFrame = avcodec_alloc_frame();
// Allocate space for the converted video frame
mFrame = avcodec_alloc_frame();
if(mRawFrame == NULL || mFrame == NULL)
Fatal( "Unable to allocate frame for %s", mPath.c_str() );
Debug ( 1, "Allocated frames" );
int pSize = avpicture_get_size( imagePixFormat, width, height );
if( (unsigned int)pSize != imagesize) {
Fatal("Image size mismatch. Required: %d Available: %d",pSize,imagesize);
}
Debug ( 1, "Validated imagesize" );
#if HAVE_LIBSWSCALE
Debug ( 1, "Calling sws_isSupportedInput" );
if(!sws_isSupportedInput(mCodecContext->pix_fmt)) {
Fatal("swscale does not support the codec format: %c%c%c%c",(mCodecContext->pix_fmt)&0xff,((mCodecContext->pix_fmt>>8)&0xff),((mCodecContext->pix_fmt>>16)&0xff),((mCodecContext->pix_fmt>>24)&0xff));
}
if(!sws_isSupportedOutput(imagePixFormat)) {
Fatal("swscale does not support the target format: %c%c%c%c",(imagePixFormat)&0xff,((imagePixFormat>>8)&0xff),((imagePixFormat>>16)&0xff),((imagePixFormat>>24)&0xff));
}
#else // HAVE_LIBSWSCALE
Fatal( "You must compile ffmpeg with the --enable-swscale option to use ffmpeg cameras" );
#endif // HAVE_LIBSWSCALE
mCanCapture = true;
return 0;
}
int FfmpegCamera::ReopenFfmpeg() {
Debug(2, "ReopenFfmpeg called.");
mCanCapture = false;
if (pthread_create( &mReopenThread, NULL, ReopenFfmpegThreadCallback, (void*) this) != 0){
// Log a fatal error and exit the process.
Fatal( "ReopenFfmpeg failed to create worker thread." );
}
return 0;
}
int FfmpegCamera::CloseFfmpeg(){
Debug(2, "CloseFfmpeg called.");
mCanCapture = false;
av_freep( &mFrame );
av_freep( &mRawFrame );
#if HAVE_LIBSWSCALE
if ( mConvertContext )
{
sws_freeContext( mConvertContext );
mConvertContext = NULL;
}
#endif
if ( mCodecContext )
{
avcodec_close( mCodecContext );
mCodecContext = NULL; // Freed by av_close_input_file
}
if ( mFormatContext )
{
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 4, 0)
av_close_input_file( mFormatContext );
#else
avformat_close_input( &mFormatContext );
#endif
mFormatContext = NULL;
}
return 0;
}
int FfmpegCamera::FfmpegInterruptCallback(void *ctx)
{
FfmpegCamera* camera = reinterpret_cast<FfmpegCamera*>(ctx);
if (camera->mIsOpening){
int now = time(NULL);
if ((now - camera->mOpenStart) > config.ffmpeg_open_timeout) {
Error ( "Open video took more than %d seconds.", config.ffmpeg_open_timeout );
return 1;
}
}
return 0;
}
void *FfmpegCamera::ReopenFfmpegThreadCallback(void *ctx){
if (ctx == NULL) return NULL;
FfmpegCamera* camera = reinterpret_cast<FfmpegCamera*>(ctx);
while (1){
// Close current stream.
camera->CloseFfmpeg();
// Sleep if neccessary to not reconnect too fast.
int wait = config.ffmpeg_open_timeout - (time(NULL) - camera->mOpenStart);
wait = wait < 0 ? 0 : wait;
if (wait > 0){
Debug( 1, "Sleeping %d seconds before reopening stream.", wait );
sleep(wait);
}
if (camera->OpenFfmpeg() == 0){
return NULL;
}
}
}
#endif // HAVE_LIBAVFORMAT #endif // HAVE_LIBAVFORMAT

View File

@ -47,6 +47,16 @@ protected:
AVFrame *mRawFrame; AVFrame *mRawFrame;
AVFrame *mFrame; AVFrame *mFrame;
PixelFormat imagePixFormat; PixelFormat imagePixFormat;
int OpenFfmpeg();
int ReopenFfmpeg();
int CloseFfmpeg();
static int FfmpegInterruptCallback(void *ctx);
static void* ReopenFfmpegThreadCallback(void *ctx);
bool mIsOpening;
bool mCanCapture;
int mOpenStart;
pthread_t mReopenThread;
#endif // HAVE_LIBAVFORMAT #endif // HAVE_LIBAVFORMAT
#if HAVE_LIBSWSCALE #if HAVE_LIBSWSCALE

View File

@ -10,7 +10,8 @@ switch ( $_REQUEST['task'] )
logInit( array( 'id' => "web_js" ) ); logInit( array( 'id' => "web_js" ) );
$string = $_POST['message']; $string = $_POST['message'];
$file = preg_replace( '/\w+:\/\/\w+\//', '', $_POST['file'] );
$file = !empty($_POST['file']) ? preg_replace( '/\w+:\/\/\w+\//', '', $_POST['file'] ) : '';
if ( !empty( $_POST['line'] ) ) if ( !empty( $_POST['line'] ) )
$line = $_POST['line']; $line = $_POST['line'];
else else

View File

@ -659,21 +659,14 @@ if ( !empty($action) )
} }
// System view actions // System view actions
if ( canView( 'System' ) ) if ( $action == "setgroup" ) {
{ if ( !empty($_REQUEST['gid']) ) {
if ( $action == "setgroup" ) setcookie( "zmGroup", validInt($_REQUEST['gid']), time()+3600*24*30*12*10 );
{ } else {
if ( !empty($_REQUEST['gid']) ) setcookie( "zmGroup", "", time()-3600*24*2 );
{ }
setcookie( "zmGroup", validInt($_REQUEST['gid']), time()+3600*24*30*12*10 ); $refreshParent = true;
} }
else
{
setcookie( "zmGroup", "", time()-3600*24*2 );
}
$refreshParent = true;
}
}
// System edit actions // System edit actions
if ( canEdit( 'System' ) ) if ( canEdit( 'System' ) )
@ -866,13 +859,10 @@ if ( !empty($action) )
} }
elseif ( $action == "group" ) elseif ( $action == "group" )
{ {
if ( !empty($_REQUEST['gid']) ) if ( !empty($_POST['gid']) ) {
{ dbQuery( "UPDATE Groups SET Name=?, MonitorIds=? WHERE Id=?", array($_POST['newGroup']['Name'], $_POST['newGroup']['MonitorIds'], $_POST['gid']) );
dbQuery( "update Groups set Name=?, MonitorIds=? WHERE Id=?", array($_REQUEST['newGroup']['Name'], join(',',$_REQUEST['newGroup']['MonitorIds']), $_REQUEST['gid']) ); } else {
} dbQuery( "INSERT INTO Groups SET Name=?, MonitorIds=?", array( $_POST['newGroup']['Name'], empty($_POST['newGroup']['MonitorIds']) ? array() : $_POST['newGroup']['MonitorIds'] ) );
else
{
dbQuery( "insert into Groups set Name=?, MonitorIds=?", array( $_REQUEST['newGroup']['Name'], join(',',$_REQUEST['newGroup']['MonitorIds'])) );
} }
$refreshParent = true; $refreshParent = true;
$view = 'none'; $view = 'none';

View File

@ -57,8 +57,10 @@ function logReport( level, message, file, line )
requestParms += "&level="+level+"&message="+encodeURIComponent(message); requestParms += "&level="+level+"&message="+encodeURIComponent(message);
if ( file ) if ( file )
requestParms += "&file="+file; requestParms += "&file="+file;
else else if ( location.search ) {
//location.search is the querystring part, so ?blah=blah but there is almost never any value to this
requestParms += "&file="+location.search; requestParms += "&file="+location.search;
}
if ( line ) if ( line )
requestParms += "&line="+line; requestParms += "&line="+line;
debugReq.send( requestParms ); debugReq.send( requestParms );

View File

@ -190,7 +190,7 @@ xhtmlHeaders( __FILE__, $SLANG['Console'] );
<h3 id="systemStats"><?= $SLANG['Load'] ?>: <?= getLoad() ?> / <?= $SLANG['Disk'] ?>: <?= getDiskPercent() ?>%</h3> <h3 id="systemStats"><?= $SLANG['Load'] ?>: <?= getLoad() ?> / <?= $SLANG['Disk'] ?>: <?= getDiskPercent() ?>%</h3>
<h2 id="title"><a href="http://www.zoneminder.com" target="ZoneMinder">ZoneMinder</a> <?= $SLANG['Console'] ?> - <?= makePopupLink( '?view=state', 'zmState', 'state', $status, canEdit( 'System' ) ) ?> - <?= makePopupLink( '?view=version', 'zmVersion', 'version', '<span class="'.$versionClass.'">v'.ZM_VERSION.'</span>', canEdit( 'System' ) ) ?></h2> <h2 id="title"><a href="http://www.zoneminder.com" target="ZoneMinder">ZoneMinder</a> <?= $SLANG['Console'] ?> - <?= makePopupLink( '?view=state', 'zmState', 'state', $status, canEdit( 'System' ) ) ?> - <?= makePopupLink( '?view=version', 'zmVersion', 'version', '<span class="'.$versionClass.'">v'.ZM_VERSION.'</span>', canEdit( 'System' ) ) ?></h2>
<div class="clear"></div> <div class="clear"></div>
<div id="monitorSummary"><?= makePopupLink( '?view=groups', 'zmGroups', 'groups', sprintf( $CLANG['MonitorCount'], count($displayMonitors), zmVlang( $VLANG['Monitor'], count($displayMonitors) ) ).($group?' ('.$group['Name'].')':''), canView( 'System' ) ); ?></div> <div id="monitorSummary"><?= makePopupLink( '?view=groups', 'zmGroups', 'groups', 'Group: ' . ($group?' ('.$group['Name'].')':'All').': '. sprintf( $CLANG['MonitorCount'], count($displayMonitors), zmVlang( $VLANG['Monitor'], count($displayMonitors) ) ) ); ?></div>
<?php <?php
if ( ZM_OPT_X10 && canView( 'Devices' ) ) if ( ZM_OPT_X10 && canView( 'Devices' ) )
{ {

View File

@ -18,11 +18,6 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// //
if ( !canView( 'System' ) )
{
$view = "error";
return;
}
$sql = "select * from Groups order by Name"; $sql = "select * from Groups order by Name";
$groups = array(); $groups = array();
@ -66,18 +61,13 @@ xhtmlHeaders(__FILE__, $SLANG['Groups'] );
<td class="colIds"><?= $SLANG['All'] ?></td> <td class="colIds"><?= $SLANG['All'] ?></td>
<td class="colSelect"><input type="radio" name="gid" value="0"<?= !$selected?' checked="checked"':'' ?> onclick="configureButtons( this );"/></td> <td class="colSelect"><input type="radio" name="gid" value="0"<?= !$selected?' checked="checked"':'' ?> onclick="configureButtons( this );"/></td>
</tr> </tr>
<?php <?php foreach ( $groups as $group ) { ?>
foreach ( $groups as $group )
{
?>
<tr> <tr>
<td class="colName"><?= validHtmlStr($group['Name']) ?></td> <td class="colName"><?= validHtmlStr($group['Name']) ?></td>
<td class="colIds"><?= monitorIdsToNames( $group['MonitorIds'], 30 ) ?></td> <td class="colIds"><?= monitorIdsToNames( $group['MonitorIds'], 30 ) ?></td>
<td class="colSelect"><input type="radio" name="gid" value="<?= $group['Id'] ?>"<?= $group['selected']?' checked="checked"':'' ?> onclick="configureButtons( this );"/></td> <td class="colSelect"><input type="radio" name="gid" value="<?= $group['Id'] ?>"<?= $group['selected']?' checked="checked"':'' ?> onclick="configureButtons( this );"/></td>
</tr> </tr>
<?php <?php } ?>
}
?>
</tbody> </tbody>
</table> </table>
<div id="contentButtons"> <div id="contentButtons">

View File

@ -73,7 +73,7 @@ $status = $running?$SLANG['Running']:$SLANG['Stopped'];
$group = NULL; $group = NULL;
if ( ! empty($_COOKIE['zmGroup']) ) { if ( ! empty($_COOKIE['zmGroup']) ) {
if ( $group = dbFetchOne( 'SELECT * FROM Groups WHERE Id = ?', NULL, array($_COOKIE['zmGroup']) ) ) if ( $group = dbFetchOne( 'select * from Groups where Id = ?', NULL, array($_COOKIE['zmGroup'])) )
$groupIds = array_flip(explode( ',', $group['MonitorIds'] )); $groupIds = array_flip(explode( ',', $group['MonitorIds'] ));
} }
@ -85,7 +85,7 @@ $cycleCount = 0;
$minSequence = 0; $minSequence = 0;
$maxSequence = 1; $maxSequence = 1;
$seqIdList = array(); $seqIdList = array();
$monitors = dbFetchAll( 'SELECT * FROM Monitors ORDER BY Sequence ASC' ); $monitors = dbFetchAll( "select * from Monitors order by Sequence asc" );
$displayMonitors = array(); $displayMonitors = array();
for ( $i = 0; $i < count($monitors); $i++ ) for ( $i = 0; $i < count($monitors); $i++ )
{ {
@ -108,7 +108,7 @@ for ( $i = 0; $i < count($monitors); $i++ )
} }
$monitors[$i]['zmc'] = zmcStatus( $monitors[$i] ); $monitors[$i]['zmc'] = zmcStatus( $monitors[$i] );
$monitors[$i]['zma'] = zmaStatus( $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'] ) ); $monitors[$i]['ZoneCount'] = dbFetchOne( 'select count(Id) as ZoneCount from Zones where MonitorId = ?', 'ZoneCount', array($monitors[$i]['Id']) );
$counts = array(); $counts = array();
for ( $j = 0; $j < count($eventCounts); $j++ ) for ( $j = 0; $j < count($eventCounts); $j++ )
{ {
@ -117,8 +117,8 @@ for ( $i = 0; $i < count($monitors); $i++ )
$counts[] = "count(if(1".$filter['sql'].",1,NULL)) as EventCount$j"; $counts[] = "count(if(1".$filter['sql'].",1,NULL)) as EventCount$j";
$monitors[$i]['eventCounts'][$j]['filter'] = $filter; $monitors[$i]['eventCounts'][$j]['filter'] = $filter;
} }
$sql = 'SELECT '.join($counts,', ').' FROM Events AS E WHERE MonitorId = ?'; $sql = "select ".join($counts,", ")." from Events as E where MonitorId = ?";
$counts = dbFetchOne( $sql, NULL, array( $monitors[$i]['Id'] ) ); $counts = dbFetchOne( $sql, NULL, array($monitors[$i]['Id']) );
if ( $monitors[$i]['Function'] != 'None' ) if ( $monitors[$i]['Function'] != 'None' )
{ {
$cycleCount++; $cycleCount++;
@ -190,7 +190,7 @@ xhtmlHeaders( __FILE__, $SLANG['Console'] );
<h3 id="systemStats"><?= $SLANG['Load'] ?>: <?= getLoad() ?> / <?= $SLANG['Disk'] ?>: <?= getDiskPercent() ?>%</h3> <h3 id="systemStats"><?= $SLANG['Load'] ?>: <?= getLoad() ?> / <?= $SLANG['Disk'] ?>: <?= getDiskPercent() ?>%</h3>
<h2 id="title"><a href="http://www.zoneminder.com" target="ZoneMinder">ZoneMinder</a> <?= $SLANG['Console'] ?> - <?= makePopupLink( '?view=state', 'zmState', 'state', $status, canEdit( 'System' ) ) ?> - <?= makePopupLink( '?view=version', 'zmVersion', 'version', '<span class="'.$versionClass.'">v'.ZM_VERSION.'</span>', canEdit( 'System' ) ) ?></h2> <h2 id="title"><a href="http://www.zoneminder.com" target="ZoneMinder">ZoneMinder</a> <?= $SLANG['Console'] ?> - <?= makePopupLink( '?view=state', 'zmState', 'state', $status, canEdit( 'System' ) ) ?> - <?= makePopupLink( '?view=version', 'zmVersion', 'version', '<span class="'.$versionClass.'">v'.ZM_VERSION.'</span>', canEdit( 'System' ) ) ?></h2>
<div class="clear"></div> <div class="clear"></div>
<div id="monitorSummary"><?= makePopupLink( '?view=groups', 'zmGroups', 'groups', sprintf( $CLANG['MonitorCount'], count($displayMonitors), zmVlang( $VLANG['Monitor'], count($displayMonitors) ) ).($group?' ('.$group['Name'].')':''), canView( 'System' ) ); ?></div> <div id="monitorSummary"><?= makePopupLink( '?view=groups', 'zmGroups', 'groups', 'Group: ' . ($group?' ('.$group['Name'].')':'All').': '. sprintf( $CLANG['MonitorCount'], count($displayMonitors), zmVlang( $VLANG['Monitor'], count($displayMonitors) ) ) ); ?></div>
<?php <?php
if ( ZM_OPT_X10 && canView( 'Devices' ) ) if ( ZM_OPT_X10 && canView( 'Devices' ) )
{ {
@ -226,7 +226,7 @@ else
{ {
?><?= $SLANG['ConfiguredFor'] ?><?php ?><?= $SLANG['ConfiguredFor'] ?><?php
} }
?>&nbsp;<?= makePopupLink( '?view=bandwidth', 'zmBandwidth', 'bandwidth', $bwArray[$_COOKIE['zmBandwidth']], ($user && $user['MaxBandwidth'] != 'low' ) ) ?> <?= $SLANG['Bandwidth'] ?></h3> ?>&nbsp;<?= makePopupLink( '?view=bandwidth', 'zmBandwidth', 'bandwidth', $bwArray[$_COOKIE['zmBandwidth']], ($user && $user['MaxBandwidth'] != 'low' ) ) ?> <?= $SLANG['BandwidthHead'] ?></h3>
</div> </div>
<div id="content"> <div id="content">
<table id="consoleTable" cellspacing="0"> <table id="consoleTable" cellspacing="0">
@ -302,7 +302,7 @@ foreach( $displayMonitors as $monitor )
$scale = max( reScale( SCALE_BASE, $monitor['DefaultScale'], ZM_WEB_DEFAULT_SCALE ), SCALE_BASE ); $scale = max( reScale( SCALE_BASE, $monitor['DefaultScale'], ZM_WEB_DEFAULT_SCALE ), SCALE_BASE );
?> ?>
<td class="colName"><?= makePopupLink( '?view=watch&amp;mid='.$monitor['Id'], 'zmWatch'.$monitor['Id'], array( 'watch', reScale( $monitor['Width'], $scale ), reScale( $monitor['Height'], $scale ) ), $monitor['Name'], $running && ($monitor['Function'] != 'None') && canView( 'Stream' ) ) ?></td> <td class="colName"><?= makePopupLink( '?view=watch&amp;mid='.$monitor['Id'], 'zmWatch'.$monitor['Id'], array( 'watch', reScale( $monitor['Width'], $scale ), reScale( $monitor['Height'], $scale ) ), $monitor['Name'], $running && ($monitor['Function'] != 'None') && canView( 'Stream' ) ) ?></td>
<td class="colFunction"><?= makePopupLink( '?view=function&amp;mid='.$monitor['Id'], 'zmFunction', 'function', '<span class="'.$fclass.'">'.$monitor['Function'].( empty($monitor['Enabled']) ? ', disabled' : '' ).'</span>', canEdit( 'Monitors' ) ) ?></td> <td class="colFunction"><?= makePopupLink( '?view=function&amp;mid='.$monitor['Id'], 'zmFunction', 'function', '<span class="'.$fclass.'">'.$SLANG['Fn'.$monitor['Function']].( empty($monitor['Enabled']) ? ', disabled' : '' ) .'</span>', canEdit( 'Monitors' ) ) ?></td>
<?php if ( $monitor['Type'] == "Local" ) { ?> <?php if ( $monitor['Type'] == "Local" ) { ?>
<td class="colSource"><?= makePopupLink( '?view=monitor&amp;mid='.$monitor['Id'], 'zmMonitor'.$monitor['Id'], 'monitor', '<span class="'.$dclass.'">'.$monitor['Device'].' ('.$monitor['Channel'].')</span>', canEdit( 'Monitors' ) ) ?></td> <td class="colSource"><?= makePopupLink( '?view=monitor&amp;mid='.$monitor['Id'], 'zmMonitor'.$monitor['Id'], 'monitor', '<span class="'.$dclass.'">'.$monitor['Device'].' ('.$monitor['Channel'].')</span>', canEdit( 'Monitors' ) ) ?></td>
<?php } elseif ( $monitor['Type'] == "Remote" ) { ?> <?php } elseif ( $monitor['Type'] == "Remote" ) { ?>

View File

@ -18,11 +18,6 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// //
if ( !canView( 'System' ) )
{
$view = "error";
return;
}
$sql = "select * from Groups order by Name"; $sql = "select * from Groups order by Name";
$groups = array(); $groups = array();
@ -66,18 +61,13 @@ xhtmlHeaders(__FILE__, $SLANG['Groups'] );
<td class="colIds"><?= $SLANG['All'] ?></td> <td class="colIds"><?= $SLANG['All'] ?></td>
<td class="colSelect"><input type="radio" name="gid" value="0"<?= !$selected?' checked="checked"':'' ?> onclick="configureButtons( this );"/></td> <td class="colSelect"><input type="radio" name="gid" value="0"<?= !$selected?' checked="checked"':'' ?> onclick="configureButtons( this );"/></td>
</tr> </tr>
<?php <?php foreach ( $groups as $group ) { ?>
foreach ( $groups as $group )
{
?>
<tr> <tr>
<td class="colName"><?= validHtmlStr($group['Name']) ?></td> <td class="colName"><?= validHtmlStr($group['Name']) ?></td>
<td class="colIds"><?= monitorIdsToNames( $group['MonitorIds'], 30 ) ?></td> <td class="colIds"><?= monitorIdsToNames( $group['MonitorIds'], 30 ) ?></td>
<td class="colSelect"><input type="radio" name="gid" value="<?= $group['Id'] ?>"<?= $group['selected']?' checked="checked"':'' ?> onclick="configureButtons( this );"/></td> <td class="colSelect"><input type="radio" name="gid" value="<?= $group['Id'] ?>"<?= $group['selected']?' checked="checked"':'' ?> onclick="configureButtons( this );"/></td>
</tr> </tr>
<?php <?php } ?>
}
?>
</tbody> </tbody>
</table> </table>
<div id="contentButtons"> <div id="contentButtons">