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

This commit is contained in:
Isaac Connor 2017-05-26 22:20:50 -04:00
commit 2e673e49c8
22 changed files with 1149 additions and 1273 deletions

View File

@ -1,20 +1,7 @@
ZoneMinder H264 Patch ZoneMinder
==========
[![Build Status](https://travis-ci.org/ZoneMinder/ZoneMinder.png?branch=feature-h264-videostorage)](https://travis-ci.org/ZoneMinder/ZoneMinder) [![Bountysource](https://api.bountysource.com/badge/team?team_id=204&style=bounties_received)](https://www.bountysource.com/teams/zoneminder/issues?utm_source=ZoneMinder&utm_medium=shield&utm_campaign=bounties_received) [![Build Status](https://travis-ci.org/ZoneMinder/ZoneMinder.png)](https://travis-ci.org/ZoneMinder/ZoneMinder) [![Bountysource](https://api.bountysource.com/badge/team?team_id=204&style=bounties_received)](https://www.bountysource.com/teams/zoneminder/issues?utm_source=ZoneMinder&utm_medium=shield&utm_campaign=bounties_received)
##Feature-h264-videostorage Branch Details
This branch supports direct recording of h264 cameras into MP4 format uisng the h264 Passthrough option, but only with FFMPEG Monitors currently. It also provides h264 encoding for any other monitor type. If you encounter any issues, please open an issue on GitHub and attach it to the h264 milestone. But do remember this is bleeding edge so it will have problems.
Thanks to @chriswiggins and @mastertheknife for their work, @SteveGilvarry is now maintaining this branch and welcomes any assistance.
**The following SQL changes are required, these will be merged to zmupdate once we are ready to merge this branch to master.**
```
ALTER TABLE `Monitors` ADD `SaveJPEGs` TINYINT NOT NULL DEFAULT '3' AFTER `Deinterlacing` ,
ADD `VideoWriter` TINYINT NOT NULL DEFAULT '0' AFTER `SaveJPEGs` ,
ADD `EncoderParameters` TEXT NOT NULL AFTER `VideoWriter` ,
ADD `RecordAudio` TINYINT NOT NULL DEFAULT '0' AFTER `EncoderParameters` ;
ALTER TABLE `Events` ADD `DefaultVideo` VARCHAR( 64 ) NOT NULL AFTER `AlarmFrames` ;
```
All documentation for ZoneMinder is now online at https://zoneminder.readthedocs.org All documentation for ZoneMinder is now online at https://zoneminder.readthedocs.org

View File

@ -354,7 +354,7 @@ CREATE TABLE `Monitors` (
`Deinterlacing` int(10) unsigned NOT NULL default '0', `Deinterlacing` int(10) unsigned NOT NULL default '0',
`SaveJPEGs` TINYINT NOT NULL DEFAULT '3' , `SaveJPEGs` TINYINT NOT NULL DEFAULT '3' ,
`VideoWriter` TINYINT NOT NULL DEFAULT '0', `VideoWriter` TINYINT NOT NULL DEFAULT '0',
`EncoderParameters` TEXT NOT NULL, `EncoderParameters` TEXT,
`RecordAudio` TINYINT NOT NULL DEFAULT '0', `RecordAudio` TINYINT NOT NULL DEFAULT '0',
`RTSPDescribe` tinyint(1) unsigned, `RTSPDescribe` tinyint(1) unsigned,
`Brightness` mediumint(7) NOT NULL default '-1', `Brightness` mediumint(7) NOT NULL default '-1',

View File

@ -71,3 +71,27 @@ SET @s = (SELECT IF(
PREPARE stmt FROM @s; PREPARE stmt FROM @s;
EXECUTE stmt; EXECUTE stmt;
--
-- The following alters various columns to allow NULLs
--
ALTER TABLE Monitors MODIFY Host varchar(64);
ALTER TABLE Monitors MODIFY LabelFormat varchar(64);
ALTER TABLE Monitors MODIFY LinkedMonitors varchar(255);
ALTER TABLE Monitors MODIFY Options varchar(255);
ALTER TABLE Monitors MODIFY Protocol varchar(16);
ALTER TABLE Monitors MODIFY User varchar(64);
ALTER TABLE Monitors MODIFY Pass varchar(64);
ALTER TABLE Monitors MODIFY RTSPDescribe tinyint(1) unsigned;
ALTER TABLE Monitors MODIFY ControlId int(10) unsigned;
ALTER TABLE Monitors MODIFY TrackDelay smallint(5) unsigned;
ALTER TABLE Monitors MODIFY ReturnDelay smallint(5) unsigned;
ALTER TABLE Monitors MODIFY EncoderParameters TEXT;
ALTER TABLE Monitors MODIFY Path varchar(255);
ALTER TABLE Monitors MODIFY V4LMultiBuffer tinyint(1) unsigned;
ALTER TABLE Users MODIFY MonitorIds tinytext;
ALTER TABLE Users MODIFY Language varchar(8);
ALTER TABLE Users MODIFY MaxBandwidth varchar(16);

View File

@ -6,7 +6,7 @@ Build-Depends: debhelper (>= 9), cmake
, libphp-serialization-perl , libphp-serialization-perl
, libgnutls28-dev | libgnutls-dev , libgnutls28-dev | libgnutls-dev
, libmysqlclient-dev | libmariadbclient-dev , libmysqlclient-dev | libmariadbclient-dev
, libjpeg-dev , libjpeg8-dev | libjpeg-dev
, libpcre3-dev , libpcre3-dev
, libavcodec-dev, libavformat-dev (>= 3:0.svn20090204), libswscale-dev (>= 3:0.svn20090204), libavutil-dev , libavcodec-dev, libavformat-dev (>= 3:0.svn20090204), libswscale-dev (>= 3:0.svn20090204), libavutil-dev
, libavdevice-dev , libavdevice-dev

View File

@ -5,10 +5,19 @@ Maintainer: Dmitry Smirnov <onlyjob@debian.org>
Uploaders: Vagrant Cascadian <vagrant@debian.org> Uploaders: Vagrant Cascadian <vagrant@debian.org>
Build-Depends: debhelper (>= 9), dh-systemd, python-sphinx | python3-sphinx, apache2-dev, dh-linktree Build-Depends: debhelper (>= 9), dh-systemd, python-sphinx | python3-sphinx, apache2-dev, dh-linktree
,cmake ,cmake
<<<<<<< HEAD
,libx264-dev, libmp4v2-dev ,libx264-dev, libmp4v2-dev
,libavcodec-dev, libavformat-dev, libswscale-dev ,libavcodec-dev, libavformat-dev, libswscale-dev
,libavutil-dev, libavdevice-dev, libavresample-dev ,libavutil-dev, libavdevice-dev, libavresample-dev
,libboost-dev ,libboost-dev
=======
,libboost-dev
,libavdevice-dev (>= 6:10~)
,libavcodec-dev (>= 6:10~)
,libavformat-dev (>= 6:10~)
,libavutil-dev (>= 6:10~)
,libswscale-dev (>= 6:10~)
>>>>>>> dragndrop_monitor_sorting
,libbz2-dev ,libbz2-dev
,libgcrypt-dev ,libgcrypt-dev
,libcurl4-gnutls-dev ,libcurl4-gnutls-dev

View File

@ -1,83 +0,0 @@
AUTOMAKE_OPTIONS = gnu
# Ack! Nasty hack to get modules Makefile regenerated if wiped with make clean
all-local: ZoneMinder/Makefile
ZoneMinder/Makefile: ZoneMinder/Makefile.PL
( cd ZoneMinder; perl Makefile.PL )
bin_SCRIPTS = \
zmdc.pl \
zmaudit.pl \
zmfilter.pl \
zmtrigger.pl \
zmx10.pl \
zmwatch.pl \
zmpkg.pl \
zmupdate.pl \
zmvideo.pl \
zmcontrol.pl \
zmtrack.pl \
zmcamtool.pl \
zmsystemctl.pl \
zmtelemetry.pl
SUBDIRS = \
. \
ZoneMinder
EXTRA_DIST = \
zmdc.pl.in \
zmaudit.pl.in \
zmfilter.pl.in \
zmtrigger.pl.in \
zmx10.pl.in \
zmwatch.pl.in \
zmpkg.pl.in \
zmupdate.pl.in \
zmvideo.pl.in \
zmcontrol.pl.in \
zmtrack.pl.in \
zmcamtool.pl.in \
zmsystemctl.pl.in \
zmtelemtry.pl.in \
ZoneMinder/Makefile.PL \
ZoneMinder/README \
ZoneMinder/Changes \
ZoneMinder/META.yml \
ZoneMinder/MANIFEST \
ZoneMinder/t/ZoneMinder.t \
ZoneMinder/lib/ZoneMinder.pm \
ZoneMinder/lib/ZoneMinder/Base.pm.in \
ZoneMinder/lib/ZoneMinder/Config.pm.in \
ZoneMinder/lib/ZoneMinder/Event.pm \
ZoneMinder/lib/ZoneMinder/Filter.pm \
ZoneMinder/lib/ZoneMinder/Monitor.pm \
ZoneMinder/lib/ZoneMinder/Object.pm \
ZoneMinder/lib/ZoneMinder/Server.pm \
ZoneMinder/lib/ZoneMinder/Storage.pm \
ZoneMinder/lib/ZoneMinder/Logger.pm \
ZoneMinder/lib/ZoneMinder/General.pm \
ZoneMinder/lib/ZoneMinder/Database.pm \
ZoneMinder/lib/ZoneMinder/Memory.pm.in \
ZoneMinder/lib/ZoneMinder/Memory/Shared.pm \
ZoneMinder/lib/ZoneMinder/Memory/Mapped.pm \
ZoneMinder/lib/ZoneMinder/ConfigAdmin.pm \
ZoneMinder/lib/ZoneMinder/ConfigData.pm.in \
ZoneMinder/lib/ZoneMinder/Control.pm \
ZoneMinder/lib/ZoneMinder/Control \
ZoneMinder/lib/ZoneMinder/Trigger/Channel.pm \
ZoneMinder/lib/ZoneMinder/Trigger/Channel/Handle.pm \
ZoneMinder/lib/ZoneMinder/Trigger/Channel/Spawning.pm \
ZoneMinder/lib/ZoneMinder/Trigger/Channel/Inet.pm \
ZoneMinder/lib/ZoneMinder/Trigger/Channel/Unix.pm \
ZoneMinder/lib/ZoneMinder/Trigger/Channel/File.pm \
ZoneMinder/lib/ZoneMinder/Trigger/Channel/Serial.pm \
ZoneMinder/lib/ZoneMinder/Trigger/Connection.pm \
ZoneMinder/lib/ZoneMinder/Trigger/Connection/Example.pm \
zm.in \
zmdbbackup.in \
zmdbrestore.in \
zmeventdump.in \
zmlogrotate.conf.in

View File

@ -187,7 +187,7 @@ Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string
snprintf( video_file, sizeof(video_file), video_file_format, path, video_name ); snprintf( video_file, sizeof(video_file), video_file_format, path, video_name );
/* X264 MP4 video writer */ /* X264 MP4 video writer */
if(monitor->GetOptVideoWriter() == 1) { if ( monitor->GetOptVideoWriter() == Monitor::X264ENCODE ) {
#if ZM_HAVE_VIDEOWRITER_X264MP4 #if ZM_HAVE_VIDEOWRITER_X264MP4
videowriter = new X264MP4Writer(video_file, monitor->Width(), monitor->Height(), monitor->Colours(), monitor->SubpixelOrder(), monitor->GetOptEncoderParams()); videowriter = new X264MP4Writer(video_file, monitor->Width(), monitor->Height(), monitor->Colours(), monitor->SubpixelOrder(), monitor->GetOptEncoderParams());
#else #else
@ -195,8 +195,7 @@ Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string
#endif #endif
} }
if(videowriter != NULL) { if ( videowriter != NULL ) {
/* Open the video stream */ /* Open the video stream */
int nRet = videowriter->Open(); int nRet = videowriter->Open();
if(nRet != 0) { if(nRet != 0) {
@ -207,9 +206,10 @@ Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string
snprintf( timecodes_name, sizeof(timecodes_name), "%d-%s", id, "video.timecodes" ); snprintf( timecodes_name, sizeof(timecodes_name), "%d-%s", id, "video.timecodes" );
snprintf( timecodes_file, sizeof(timecodes_file), video_file_format, path, timecodes_name ); snprintf( timecodes_file, sizeof(timecodes_file), video_file_format, path, timecodes_name );
/* Create timecodes file */ /* Create timecodes file */
timecodes_fd = fopen(timecodes_file, "wb"); timecodes_fd = fopen(timecodes_file, "wb");
if(timecodes_fd == NULL) { if ( timecodes_fd == NULL ) {
Error("Failed creating timecodes file"); Error("Failed creating timecodes file");
} }
} }
@ -353,12 +353,12 @@ void Event::updateNotes( const StringSetMap &newNoteSetMap ) {
noteSet.insert( newNote ); noteSet.insert( newNote );
update = true; update = true;
} }
}
}
}
} // end for } // end for
} // end if ( noteSetMap.size() == 0 } // end if ( noteSetMap.size() == 0
} // end if newNoteSetupMap.size() > 0 } // end if newNoteSetupMap.size() > 0
} // end foreach newNoteSetMap
} // end if have old notes
} // end if have new notes
if ( update ) { if ( update ) {
std::string notes; std::string notes;

View File

@ -61,7 +61,6 @@
#define MAP_LOCKED 0 #define MAP_LOCKED 0
#endif #endif
//=============================================================================
std::vector<std::string> split(const std::string &s, char delim) { std::vector<std::string> split(const std::string &s, char delim) {
std::vector<std::string> elems; std::vector<std::string> elems;
std::stringstream ss(s); std::stringstream ss(s);
@ -71,7 +70,6 @@ std::vector<std::string> split(const std::string &s, char delim) {
} }
return elems; return elems;
} }
//=============================================================================
Monitor::MonitorLink::MonitorLink( int p_id, const char *p_name ) : id( p_id ) { Monitor::MonitorLink::MonitorLink( int p_id, const char *p_name ) : id( p_id ) {
strncpy( name, p_name, sizeof(name) ); strncpy( name, p_name, sizeof(name) );
@ -1228,7 +1226,7 @@ bool Monitor::Analyse() {
} }
shared_data->action &= ~RESUME; shared_data->action &= ~RESUME;
} }
} // end ifshared_data->action } // end if shared_data->action
if ( auto_resume_time && (now.tv_sec >= auto_resume_time) ) { if ( auto_resume_time && (now.tv_sec >= auto_resume_time) ) {
Info( "Auto resuming at count %d", image_count ); Info( "Auto resuming at count %d", image_count );

View File

@ -48,16 +48,14 @@ RemoteCamera::RemoteCamera(
path = '/'+path; path = '/'+path;
} }
RemoteCamera::~RemoteCamera() RemoteCamera::~RemoteCamera() {
{ if ( hp != NULL ) {
if(hp != NULL) {
freeaddrinfo(hp); freeaddrinfo(hp);
hp = NULL; hp = NULL;
} }
} }
void RemoteCamera::Initialise() void RemoteCamera::Initialise() {
{
if( protocol.empty() ) if( protocol.empty() )
Fatal( "No protocol specified for remote camera" ); Fatal( "No protocol specified for remote camera" );
@ -73,8 +71,7 @@ void RemoteCamera::Initialise()
// Cache as much as we can to speed things up // Cache as much as we can to speed things up
std::string::size_type authIndex = host.rfind( '@' ); std::string::size_type authIndex = host.rfind( '@' );
if ( authIndex != std::string::npos ) if ( authIndex != std::string::npos ) {
{
auth = host.substr( 0, authIndex ); auth = host.substr( 0, authIndex );
host.erase( 0, authIndex+1 ); host.erase( 0, authIndex+1 );
auth64 = base64Encode( auth ); auth64 = base64Encode( auth );
@ -82,7 +79,6 @@ void RemoteCamera::Initialise()
authIndex = auth.rfind( ':' ); authIndex = auth.rfind( ':' );
username = auth.substr(0,authIndex); username = auth.substr(0,authIndex);
password = auth.substr( authIndex+1, auth.length() ); password = auth.substr( authIndex+1, auth.length() );
} }
mNeedAuth = false; mNeedAuth = false;
@ -94,9 +90,7 @@ void RemoteCamera::Initialise()
hints.ai_socktype = SOCK_STREAM; hints.ai_socktype = SOCK_STREAM;
int ret = getaddrinfo(host.c_str(), port.c_str(), &hints, &hp); int ret = getaddrinfo(host.c_str(), port.c_str(), &hints, &hp);
if ( ret != 0 ) if ( ret != 0 ) {
{
Fatal( "Can't getaddrinfo(%s port %s): %s", host.c_str(), port.c_str(), gai_strerror(ret) ); Fatal( "Can't getaddrinfo(%s port %s): %s", host.c_str(), port.c_str(), gai_strerror(ret) );
} }
} }

View File

@ -23,8 +23,28 @@
#include "zm_image.h" #include "zm_image.h"
#include "zm_monitor.h" #include "zm_monitor.h"
void Zone::Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_type, const Polygon &p_polygon, const Rgb p_alarm_rgb, CheckMethod p_check_method, int p_min_pixel_threshold, int p_max_pixel_threshold, int p_min_alarm_pixels, int p_max_alarm_pixels, const Coord &p_filter_box, int p_min_filter_pixels, int p_max_filter_pixels, int p_min_blob_pixels, int p_max_blob_pixels, int p_min_blobs, int p_max_blobs, int p_overload_frames, int p_extend_alarm_frames ) void Zone::Setup(
{ Monitor *p_monitor,
int p_id,
const char *p_label,
ZoneType p_type,
const Polygon &p_polygon,
const Rgb p_alarm_rgb,
CheckMethod p_check_method,
int p_min_pixel_threshold,
int p_max_pixel_threshold,
int p_min_alarm_pixels,
int p_max_alarm_pixels,
const Coord &p_filter_box,
int p_min_filter_pixels,
int p_max_filter_pixels,
int p_min_blob_pixels,
int p_max_blob_pixels,
int p_min_blobs,
int p_max_blobs,
int p_overload_frames,
int p_extend_alarm_frames
) {
monitor = p_monitor; monitor = p_monitor;
id = p_id; id = p_id;
@ -48,10 +68,7 @@ void Zone::Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_
overload_frames = p_overload_frames; overload_frames = p_overload_frames;
extend_alarm_frames = p_extend_alarm_frames; extend_alarm_frames = p_extend_alarm_frames;
//Debug( 1, "Initialised zone %d/%s - %d - %dx%d - Rgb:%06x, CM:%d, MnAT:%d, MxAT:%d, MnAP:%d, MxAP:%d, FB:%dx%d, MnFP:%d, MxFP:%d, MnBS:%d, MxBS:%d, MnB:%d, MxB:%d, OF: %d, AF: %d", id, label, type, polygon.Width(), polygon.Height(), alarm_rgb, check_method, min_pixel_threshold, max_pixel_threshold, min_alarm_pixels, max_alarm_pixels, filter_box.X(), filter_box.Y(), min_filter_pixels, max_filter_pixels, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs, overload_frames, extend_alarm_frames ); Debug( 1, "Initialised zone %d/%s - %d - %dx%d - Rgb:%06x, CM:%d, MnAT:%d, MxAT:%d, MnAP:%d, MxAP:%d, FB:%dx%d, MnFP:%d, MxFP:%d, MnBS:%d, MxBS:%d, MnB:%d, MxB:%d, OF: %d, AF: %d", id, label, type, polygon.Width(), polygon.Height(), alarm_rgb, check_method, min_pixel_threshold, max_pixel_threshold, min_alarm_pixels, max_alarm_pixels, filter_box.X(), filter_box.Y(), min_filter_pixels, max_filter_pixels, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs, overload_frames, extend_alarm_frames );
//Debug( 1, "Initialised zone %d/%s - %d - %dx%d - Rgb:%06x, CM:%d, MnAT:%d, MxAT:%d, MnAP:%d, MxAP:%d, FB:%dx%d, MnFP:%d, MxFP:%d, MnBS:%d, MxBS:%d, MnB:%d, MxB:%d, OF: %d", id, label, type, polygon.Width(), polygon.Height(), alarm_rgb, check_method, min_pixel_threshold, max_pixel_threshold, min_alarm_pixels, max_alarm_pixels, filter_box.X(), filter_box.Y(), min_filter_pixels, max_filter_pixels, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs, overload_frames );
//Debug( 1, "Initialised zone %d/%s - %d - %dx%d - Rgb:%06x, CM:%d", id, label, type, polygon.Width(), polygon.Height(), alarm_rgb, check_method );
Debug( 1, "Initialised zone %d/%s - %d - %dx%d", id, label, type, polygon.Width(), polygon.Height() );
alarmed = false; alarmed = false;
pixel_diff = 0; pixel_diff = 0;
@ -67,144 +84,113 @@ void Zone::Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_
overload_count = 0; overload_count = 0;
extend_alarm_count = 0; extend_alarm_count = 0;
pg_image = new Image( monitor->Width(), monitor->Height(), 1, ZM_SUBPIX_ORDER_NONE); pg_image = new Image( monitor->Width(), monitor->Height(), 1, ZM_SUBPIX_ORDER_NONE );
pg_image->Clear(); pg_image->Clear();
pg_image->Fill( 0xff, polygon ); pg_image->Fill( 0xff, polygon );
pg_image->Outline( 0xff, polygon ); pg_image->Outline( 0xff, polygon );
ranges = new Range[monitor->Height()]; ranges = new Range[monitor->Height()];
for ( unsigned int y = 0; y < monitor->Height(); y++) for ( unsigned int y = 0; y < monitor->Height(); y++ ) {
{
ranges[y].lo_x = -1; ranges[y].lo_x = -1;
ranges[y].hi_x = 0; ranges[y].hi_x = 0;
ranges[y].off_x = 0; ranges[y].off_x = 0;
const uint8_t *ppoly = pg_image->Buffer( 0, y ); const uint8_t *ppoly = pg_image->Buffer( 0, y );
for ( unsigned int x = 0; x < monitor->Width(); x++, ppoly++ ) for ( unsigned int x = 0; x < monitor->Width(); x++, ppoly++ ) {
{ if ( *ppoly ) {
if ( *ppoly ) if ( ranges[y].lo_x == -1 ) {
{
if ( ranges[y].lo_x == -1 )
{
ranges[y].lo_x = x; ranges[y].lo_x = x;
} }
if ( (unsigned int)ranges[y].hi_x < x ) if ( (unsigned int)ranges[y].hi_x < x ) {
{
ranges[y].hi_x = x; ranges[y].hi_x = x;
} }
} }
} }
} }
if ( config.record_diag_images ) // FIXME: Is this not a problem? If you had two zones for a monitor.. then these would conflict. You would only get 1 dump file
{ if ( config.record_diag_images ) {
static char diag_path[PATH_MAX] = ""; static char diag_path[PATH_MAX] = "";
if ( !diag_path[0] ) if ( ! diag_path[0] ) {
{ snprintf( diag_path, sizeof(diag_path), "%s/%s/diag-%d-poly.jpg", config.dir_events, monitor->Name(), id);
snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-poly.jpg", monitor->getStorage()->Path(), monitor->Id(), id);
} }
pg_image->WriteJpeg( diag_path ); pg_image->WriteJpeg( diag_path );
} }
} } // end Zone::Setup
Zone::~Zone() Zone::~Zone() {
{
delete[] label; delete[] label;
delete image; delete image;
delete pg_image; delete pg_image;
delete[] ranges; delete[] ranges;
} }
void Zone::RecordStats( const Event *event ) void Zone::RecordStats( const Event *event ) {
{
static char sql[ZM_SQL_MED_BUFSIZ]; static char sql[ZM_SQL_MED_BUFSIZ];
snprintf( sql, sizeof(sql), "insert into Stats set MonitorId=%d, ZoneId=%d, EventId=%d, FrameId=%d, PixelDiff=%d, AlarmPixels=%d, FilterPixels=%d, BlobPixels=%d, Blobs=%d, MinBlobSize=%d, MaxBlobSize=%d, MinX=%d, MinY=%d, MaxX=%d, MaxY=%d, Score=%d", monitor->Id(), id, event->Id(), event->Frames()+1, pixel_diff, alarm_pixels, alarm_filter_pixels, alarm_blob_pixels, alarm_blobs, min_blob_size, max_blob_size, alarm_box.LoX(), alarm_box.LoY(), alarm_box.HiX(), alarm_box.HiY(), score ); snprintf( sql, sizeof(sql), "insert into Stats set MonitorId=%d, ZoneId=%d, EventId=%d, FrameId=%d, PixelDiff=%d, AlarmPixels=%d, FilterPixels=%d, BlobPixels=%d, Blobs=%d, MinBlobSize=%d, MaxBlobSize=%d, MinX=%d, MinY=%d, MaxX=%d, MaxY=%d, Score=%d", monitor->Id(), id, event->Id(), event->Frames()+1, pixel_diff, alarm_pixels, alarm_filter_pixels, alarm_blob_pixels, alarm_blobs, min_blob_size, max_blob_size, alarm_box.LoX(), alarm_box.LoY(), alarm_box.HiX(), alarm_box.HiY(), score );
if ( mysql_query( &dbconn, sql ) ) if ( mysql_query( &dbconn, sql ) ) {
{
Error( "Can't insert event stats: %s", mysql_error( &dbconn ) ); Error( "Can't insert event stats: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) ); exit( mysql_errno( &dbconn ) );
} }
} } // end void Zone::RecordStats( const Event *event )
bool Zone::CheckOverloadCount() {
//=============================================================================
bool Zone::CheckOverloadCount()
{
Info("Overloaded count: %d, Overloaded frames: %d", overload_count, overload_frames); Info("Overloaded count: %d, Overloaded frames: %d", overload_count, overload_frames);
if ( overload_count ) if ( overload_count ) {
{
Info( "In overload mode, %d frames of %d remaining", overload_count, overload_frames ); Info( "In overload mode, %d frames of %d remaining", overload_count, overload_frames );
Debug( 4, "In overload mode, %d frames of %d remaining", overload_count, overload_frames ); Debug( 4, "In overload mode, %d frames of %d remaining", overload_count, overload_frames );
overload_count--; overload_count--;
return( false ); return( false );
} }
return true; return true;
} } // end bool Zone::CheckOverloadCount()
void Zone::SetScore(unsigned int nScore) void Zone::SetScore(unsigned int nScore) {
{
score = nScore; score = nScore;
} } // end void Zone::SetScore(unsigned int nScore)
void Zone::SetAlarmImage(const Image* srcImage) {
void Zone::SetAlarmImage(const Image* srcImage)
{
delete image; delete image;
image = new Image(*srcImage); image = new Image(*srcImage);
} } // end void Zone::SetAlarmImage( const Image* srcImage )
int Zone::GetOverloadCount() int Zone::GetOverloadCount() {
{
return overload_count; return overload_count;
} } // end int Zone::GetOverloadCount()
void Zone::SetOverloadCount(int nOverCount) void Zone::SetOverloadCount(int nOverCount) {
{
overload_count = nOverCount; overload_count = nOverCount;
} } // end void Zone::SetOverloadCount(int nOverCount )
int Zone::GetOverloadFrames() int Zone::GetOverloadFrames() {
{
return overload_frames; return overload_frames;
} } // end int Zone::GetOverloadFrames
int Zone::GetExtendAlarmCount() int Zone::GetExtendAlarmCount() {
{
return extend_alarm_count; return extend_alarm_count;
} } // end int Zone::GetExtendAlarmCount()
void Zone::SetExtendAlarmCount(int nExtendAlarmCount) void Zone::SetExtendAlarmCount(int nExtendAlarmCount) {
{
extend_alarm_count = nExtendAlarmCount; extend_alarm_count = nExtendAlarmCount;
} } // end void Zone::SetExtendAlarmCount( int nExtendAlarmCount )
int Zone::GetExtendAlarmFrames() int Zone::GetExtendAlarmFrames() {
{
return extend_alarm_frames; return extend_alarm_frames;
} } // end int Zone::GetExtendAlarmFrames()
bool Zone::CheckExtendAlarmCount() bool Zone::CheckExtendAlarmCount() {
{ Info( "ExtendAlarm count: %d, ExtendAlarm frames: %d", extend_alarm_count, extend_alarm_frames );
Info("ExtendAlarm count: %d, ExtendAlarm frames: %d", extend_alarm_count, extend_alarm_frames); if ( extend_alarm_count ) {
if ( extend_alarm_count )
{
Debug( 3, "In extend mode, %d frames of %d remaining", extend_alarm_count, extend_alarm_frames ); Debug( 3, "In extend mode, %d frames of %d remaining", extend_alarm_count, extend_alarm_frames );
extend_alarm_count--; extend_alarm_count--;
return( true ); return( true );
} }
return false; return false;
} } // end bool Zone::CheckExtendAlarmCount
bool Zone::CheckAlarms( const Image *delta_image ) {
//===========================================================================
bool Zone::CheckAlarms( const Image *delta_image )
{
ResetStats(); ResetStats();
if ( overload_count ) if ( overload_count ) {
{
Info( "In overload mode, %d frames of %d remaining", overload_count, overload_frames ); Info( "In overload mode, %d frames of %d remaining", overload_count, overload_frames );
Debug( 4, "In overload mode, %d frames of %d remaining", overload_count, overload_frames ); Debug( 4, "In overload mode, %d frames of %d remaining", overload_count, overload_frames );
overload_count--; overload_count--;
@ -236,9 +222,6 @@ bool Zone::CheckAlarms( const Image *delta_image )
Debug( 4, "Checking alarms for zone %d/%s in lines %d -> %d", id, label, lo_y, hi_y ); Debug( 4, "Checking alarms for zone %d/%s in lines %d -> %d", id, label, lo_y, hi_y );
Storage *storage = monitor->getStorage();
Debug( 5, "Checking for alarmed pixels" );
/* if(config.cpu_extensions && sseversion >= 20) { /* if(config.cpu_extensions && sseversion >= 20) {
sse2_alarmedpixels(diff_image, pg_image, &alarm_pixels, &pixel_diff_count); sse2_alarmedpixels(diff_image, pg_image, &alarm_pixels, &pixel_diff_count);
} else { } else {
@ -246,12 +229,10 @@ bool Zone::CheckAlarms( const Image *delta_image )
} */ } */
std_alarmedpixels(diff_image, pg_image, &alarm_pixels, &pixel_diff_count); std_alarmedpixels(diff_image, pg_image, &alarm_pixels, &pixel_diff_count);
if ( config.record_diag_images ) if ( config.record_diag_images ) {
{
static char diag_path[PATH_MAX] = ""; static char diag_path[PATH_MAX] = "";
if ( !diag_path[0] ) if ( ! diag_path[0] ) {
{ snprintf( diag_path, sizeof(diag_path), "%s/%s/diag-%d-%d.jpg", config.dir_events, monitor->Name(), id, 1 );
snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", storage->Path(), monitor->Id(), id, 1 );
} }
diff_image->WriteJpeg( diag_path ); diff_image->WriteJpeg( diag_path );
} }
@ -275,61 +256,50 @@ bool Zone::CheckAlarms( const Image *delta_image )
} }
score = (100*alarm_pixels)/polygon.Area(); score = (100*alarm_pixels)/polygon.Area();
if(score < 1) if ( score < 1 )
score = 1; /* Fix for score of 0 when frame meets thresholds but alarmed area is not big enough */ score = 1; /* Fix for score of 0 when frame meets thresholds but alarmed area is not big enough */
Debug( 5, "Current score is %d", score ); Debug( 5, "Current score is %d", score );
if ( check_method >= FILTERED_PIXELS ) if ( check_method >= FILTERED_PIXELS ) {
{
int bx = filter_box.X(); int bx = filter_box.X();
int by = filter_box.Y(); int by = filter_box.Y();
int bx1 = bx-1; int bx1 = bx-1;
int by1 = by-1; int by1 = by-1;
Debug( 5, "Checking for filtered pixels" ); Debug( 5, "Checking for filtered pixels" );
if ( bx > 1 || by > 1 ) if ( bx > 1 || by > 1 ) {
{
// Now remove any pixels smaller than our filter size // Now remove any pixels smaller than our filter size
unsigned char *cpdiff; unsigned char *cpdiff;
int ldx, hdx, ldy, hdy; int ldx, hdx, ldy, hdy;
bool block; bool block;
for ( unsigned int y = lo_y; y <= hi_y; y++ ) for ( unsigned int y = lo_y; y <= hi_y; y++ ) {
{
int lo_x = ranges[y].lo_x; int lo_x = ranges[y].lo_x;
int hi_x = ranges[y].hi_x; int hi_x = ranges[y].hi_x;
pdiff = (uint8_t*)diff_image->Buffer( lo_x, y ); pdiff = (uint8_t*)diff_image->Buffer( lo_x, y );
for ( int x = lo_x; x <= hi_x; x++, pdiff++ ) for ( int x = lo_x; x <= hi_x; x++, pdiff++ ) {
{ if ( *pdiff == WHITE ) {
if ( *pdiff == WHITE )
{
// Check participation in an X block // Check participation in an X block
ldx = (x>=(lo_x+bx1))?-bx1:lo_x-x; ldx = (x>=(lo_x+bx1))?-bx1:lo_x-x;
hdx = (x<=(hi_x-bx1))?0:((hi_x-x)-bx1); hdx = (x<=(hi_x-bx1))?0:((hi_x-x)-bx1);
ldy = (y>=(lo_y+by1))?-by1:lo_y-y; ldy = (y>=(lo_y+by1))?-by1:lo_y-y;
hdy = (y<=(hi_y-by1))?0:((hi_y-y)-by1); hdy = (y<=(hi_y-by1))?0:((hi_y-y)-by1);
block = false; block = false;
for ( int dy = ldy; !block && dy <= hdy; dy++ ) for ( int dy = ldy; !block && dy <= hdy; dy++ ) {
{ for ( int dx = ldx; !block && dx <= hdx; dx++ ) {
for ( int dx = ldx; !block && dx <= hdx; dx++ )
{
block = true; block = true;
for ( int dy2 = 0; block && dy2 < by; dy2++ ) for ( int dy2 = 0; block && dy2 < by; dy2++ ) {
{ for ( int dx2 = 0; block && dx2 < bx; dx2++ ) {
for ( int dx2 = 0; block && dx2 < bx; dx2++ )
{
cpdiff = diff_buff + (((y+dy+dy2)*diff_width) + (x+dx+dx2)); cpdiff = diff_buff + (((y+dy+dy2)*diff_width) + (x+dx+dx2));
if ( !*cpdiff ) if ( !*cpdiff ) {
{
block = false; block = false;
} }
} }
} }
} }
} }
if ( !block ) if ( !block ) {
{
*pdiff = BLACK; *pdiff = BLACK;
continue; continue;
} }
@ -337,18 +307,14 @@ bool Zone::CheckAlarms( const Image *delta_image )
} }
} }
} }
} } else {
else
{
alarm_filter_pixels = alarm_pixels; alarm_filter_pixels = alarm_pixels;
} }
if ( config.record_diag_images ) if ( config.record_diag_images ) {
{
static char diag_path[PATH_MAX] = ""; static char diag_path[PATH_MAX] = "";
if ( !diag_path[0] ) if ( !diag_path[0] ) {
{ snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 2 );
snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", storage->Path(), monitor->Id(), id, 2 );
} }
diff_image->WriteJpeg( diag_path ); diff_image->WriteJpeg( diag_path );
} }
@ -370,12 +336,11 @@ bool Zone::CheckAlarms( const Image *delta_image )
} }
score = (100*alarm_filter_pixels)/(polygon.Area()); score = (100*alarm_filter_pixels)/(polygon.Area());
if(score < 1) if ( score < 1 )
score = 1; /* Fix for score of 0 when frame meets thresholds but alarmed area is not big enough */ score = 1; /* Fix for score of 0 when frame meets thresholds but alarmed area is not big enough */
Debug( 5, "Current score is %d", score ); Debug( 5, "Current score is %d", score );
if ( check_method >= BLOBS ) if ( check_method >= BLOBS ) {
{
Debug( 5, "Checking for blob pixels" ); Debug( 5, "Checking for blob pixels" );
typedef struct { unsigned char tag; int count; int lo_x; int hi_x; int lo_y; int hi_y; } BlobStats; typedef struct { unsigned char tag; int count; int lo_x; int hi_x; int lo_y; int hi_y; } BlobStats;
BlobStats blob_stats[256]; BlobStats blob_stats[256];
@ -384,16 +349,13 @@ bool Zone::CheckAlarms( const Image *delta_image )
uint8_t last_x, last_y; uint8_t last_x, last_y;
BlobStats *bsx, *bsy; BlobStats *bsx, *bsy;
BlobStats *bsm, *bss; BlobStats *bsm, *bss;
for ( unsigned int y = lo_y; y <= hi_y; y++ ) for ( unsigned int y = lo_y; y <= hi_y; y++ ) {
{
int lo_x = ranges[y].lo_x; int lo_x = ranges[y].lo_x;
int hi_x = ranges[y].hi_x; int hi_x = ranges[y].hi_x;
pdiff = (uint8_t*)diff_image->Buffer( lo_x, y ); pdiff = (uint8_t*)diff_image->Buffer( lo_x, y );
for ( int x = lo_x; x <= hi_x; x++, pdiff++ ) for ( int x = lo_x; x <= hi_x; x++, pdiff++ ) {
{ if ( *pdiff == WHITE ) {
if ( *pdiff == WHITE )
{
Debug( 9, "Got white pixel at %d,%d (%p)", x, y, pdiff ); Debug( 9, "Got white pixel at %d,%d (%p)", x, y, pdiff );
//last_x = (x>lo_x)?*(pdiff-1):0; //last_x = (x>lo_x)?*(pdiff-1):0;
//last_y = (y>lo_y&&x>=last_lo_x&&x<=last_hi_x)?*(pdiff-diff_width):0; //last_y = (y>lo_y&&x>=last_lo_x&&x<=last_hi_x)?*(pdiff-diff_width):0;
@ -412,16 +374,13 @@ bool Zone::CheckAlarms( const Image *delta_image )
} }
} }
if ( last_x ) if ( last_x ) {
{
Debug( 9, "Left neighbour is %d", last_x ); Debug( 9, "Left neighbour is %d", last_x );
bsx = &blob_stats[last_x]; bsx = &blob_stats[last_x];
if ( last_y ) if ( last_y ) {
{
Debug( 9, "Top neighbour is %d", last_y ); Debug( 9, "Top neighbour is %d", last_y );
bsy = &blob_stats[last_y]; bsy = &blob_stats[last_y];
if ( last_x == last_y ) if ( last_x == last_y ) {
{
Debug( 9, "Matching neighbours, setting to %d", last_x ); Debug( 9, "Matching neighbours, setting to %d", last_x );
// Add to the blob from the x side (either side really) // Add to the blob from the x side (either side really)
*pdiff = last_x; *pdiff = last_x;
@ -429,9 +388,7 @@ bool Zone::CheckAlarms( const Image *delta_image )
bsx->count++; bsx->count++;
if ( x > bsx->hi_x ) bsx->hi_x = x; if ( x > bsx->hi_x ) bsx->hi_x = x;
if ( (int)y > bsx->hi_y ) bsx->hi_y = y; if ( (int)y > bsx->hi_y ) bsx->hi_y = y;
} } else {
else
{
// Aggregate blobs // Aggregate blobs
bsm = bsx->count>=bsy->count?bsx:bsy; bsm = bsx->count>=bsy->count?bsx:bsy;
bss = bsm==bsx?bsy:bsx; bss = bsm==bsx?bsy:bsx;
@ -441,19 +398,16 @@ bool Zone::CheckAlarms( const Image *delta_image )
Debug( 9, "Slave blob t:%d, c:%d, lx:%d, hx:%d, ly:%d, hy:%d", bss->tag, bss->count, bss->lo_x, bss->hi_x, bss->lo_y, bss->hi_y ); Debug( 9, "Slave blob t:%d, c:%d, lx:%d, hx:%d, ly:%d, hy:%d", bss->tag, bss->count, bss->lo_x, bss->hi_x, bss->lo_y, bss->hi_y );
// Now change all those pixels to the other setting // Now change all those pixels to the other setting
int changed = 0; int changed = 0;
for ( int sy = bss->lo_y; sy <= bss->hi_y; sy++) for ( int sy = bss->lo_y; sy <= bss->hi_y; sy++) {
{
int lo_sx = bss->lo_x>=ranges[sy].lo_x?bss->lo_x:ranges[sy].lo_x; int lo_sx = bss->lo_x>=ranges[sy].lo_x?bss->lo_x:ranges[sy].lo_x;
int hi_sx = bss->hi_x<=ranges[sy].hi_x?bss->hi_x:ranges[sy].hi_x; int hi_sx = bss->hi_x<=ranges[sy].hi_x?bss->hi_x:ranges[sy].hi_x;
Debug( 9, "Changing %d, %d->%d", sy, lo_sx, hi_sx ); Debug( 9, "Changing %d, %d->%d", sy, lo_sx, hi_sx );
Debug( 9, "Range %d, %d->%d", sy, ranges[sy].lo_x, ranges[sy].hi_x ); Debug( 9, "Range %d, %d->%d", sy, ranges[sy].lo_x, ranges[sy].hi_x );
spdiff = diff_buff + ((diff_width * sy) + lo_sx); spdiff = diff_buff + ((diff_width * sy) + lo_sx);
for ( int sx = lo_sx; sx <= hi_sx; sx++, spdiff++ ) for ( int sx = lo_sx; sx <= hi_sx; sx++, spdiff++ ) {
{
Debug( 9, "Pixel at %d,%d (%p) is %d", sx, sy, spdiff, *spdiff ); Debug( 9, "Pixel at %d,%d (%p) is %d", sx, sy, spdiff, *spdiff );
if ( *spdiff == bss->tag ) if ( *spdiff == bss->tag ) {
{
Debug( 9, "Setting pixel" ); Debug( 9, "Setting pixel" );
*spdiff = bsm->tag; *spdiff = bsm->tag;
changed++; changed++;
@ -462,8 +416,7 @@ bool Zone::CheckAlarms( const Image *delta_image )
} }
*pdiff = bsm->tag; *pdiff = bsm->tag;
alarm_blob_pixels++; alarm_blob_pixels++;
if ( !changed ) if ( !changed ) {
{
Info( "Master blob t:%d, c:%d, lx:%d, hx:%d, ly:%d, hy:%d", bsm->tag, bsm->count, bsm->lo_x, bsm->hi_x, bsm->lo_y, bsm->hi_y ); Info( "Master blob t:%d, c:%d, lx:%d, hx:%d, ly:%d, hy:%d", bsm->tag, bsm->count, bsm->lo_x, bsm->hi_x, bsm->lo_y, bsm->hi_y );
Info( "Slave blob t:%d, c:%d, lx:%d, hx:%d, ly:%d, hy:%d", bss->tag, bss->count, bss->lo_x, bss->hi_x, bss->lo_y, bss->hi_y ); Info( "Slave blob t:%d, c:%d, lx:%d, hx:%d, ly:%d, hy:%d", bss->tag, bss->count, bss->lo_x, bss->hi_x, bss->lo_y, bss->hi_y );
Error( "No pixels changed, exiting" ); Error( "No pixels changed, exiting" );
@ -491,9 +444,7 @@ bool Zone::CheckAlarms( const Image *delta_image )
bss->hi_x = 0; bss->hi_x = 0;
bss->hi_y = 0; bss->hi_y = 0;
} }
} } else {
else
{
Debug( 9, "Setting to left neighbour %d", last_x ); Debug( 9, "Setting to left neighbour %d", last_x );
// Add to the blob from the x side // Add to the blob from the x side
*pdiff = last_x; *pdiff = last_x;
@ -502,11 +453,8 @@ bool Zone::CheckAlarms( const Image *delta_image )
if ( x > bsx->hi_x ) bsx->hi_x = x; if ( x > bsx->hi_x ) bsx->hi_x = x;
if ( (int)y > bsx->hi_y ) bsx->hi_y = y; if ( (int)y > bsx->hi_y ) bsx->hi_y = y;
} }
} } else {
else if ( last_y ) {
{
if ( last_y )
{
Debug( 9, "Top neighbour is %d", last_y ); Debug( 9, "Top neighbour is %d", last_y );
Debug( 9, "Setting to top neighbour %d", last_y ); Debug( 9, "Setting to top neighbour %d", last_y );
@ -518,28 +466,19 @@ bool Zone::CheckAlarms( const Image *delta_image )
bsy->count++; bsy->count++;
if ( x > bsy->hi_x ) bsy->hi_x = x; if ( x > bsy->hi_x ) bsy->hi_x = x;
if ( (int)y > bsy->hi_y ) bsy->hi_y = y; if ( (int)y > bsy->hi_y ) bsy->hi_y = y;
} } else {
else
{
// Create a new blob // Create a new blob
int i; int i;
for ( i = (WHITE-1); i > 0; i-- ) for ( i = (WHITE-1); i > 0; i-- ) {
{
BlobStats *bs = &blob_stats[i]; BlobStats *bs = &blob_stats[i];
// See if we can recycle one first, only if it's at least two rows up // See if we can recycle one first, only if it's at least two rows up
if ( bs->count && bs->hi_y < (int)(y-1) ) if ( bs->count && bs->hi_y < (int)(y-1) ) {
{ if ( (min_blob_pixels && bs->count < min_blob_pixels) || (max_blob_pixels && bs->count > max_blob_pixels) ) {
if ( (min_blob_pixels && bs->count < min_blob_pixels) || (max_blob_pixels && bs->count > max_blob_pixels) ) if ( config.create_analysis_images || config.record_diag_images ) {
{ for ( int sy = bs->lo_y; sy <= bs->hi_y; sy++ ) {
if ( config.create_analysis_images || config.record_diag_images )
{
for ( int sy = bs->lo_y; sy <= bs->hi_y; sy++ )
{
spdiff = diff_buff + ((diff_width * sy) + bs->lo_x); spdiff = diff_buff + ((diff_width * sy) + bs->lo_x);
for ( int sx = bs->lo_x; sx <= bs->hi_x; sx++, spdiff++ ) for ( int sx = bs->lo_x; sx <= bs->hi_x; sx++, spdiff++ ) {
{ if ( *spdiff == bs->tag ) {
if ( *spdiff == bs->tag )
{
*spdiff = BLACK; *spdiff = BLACK;
} }
} }
@ -558,8 +497,7 @@ bool Zone::CheckAlarms( const Image *delta_image )
bs->hi_y = 0; bs->hi_y = 0;
} }
} }
if ( !bs->count ) if ( !bs->count ) {
{
Debug( 9, "Creating new blob %d", i ); Debug( 9, "Creating new blob %d", i );
*pdiff = i; *pdiff = i;
alarm_blob_pixels++; alarm_blob_pixels++;
@ -573,8 +511,7 @@ bool Zone::CheckAlarms( const Image *delta_image )
break; break;
} }
} }
if ( i == 0 ) if ( i == 0 ) {
{
Warning( "Max blob count reached. Unable to allocate new blobs so terminating. Zone settings may be too sensitive." ); Warning( "Max blob count reached. Unable to allocate new blobs so terminating. Zone settings may be too sensitive." );
x = hi_x+1; x = hi_x+1;
y = hi_y+1; y = hi_y+1;
@ -584,40 +521,30 @@ bool Zone::CheckAlarms( const Image *delta_image )
} }
} }
} }
if ( config.record_diag_images ) if ( config.record_diag_images ) {
{
static char diag_path[PATH_MAX] = ""; static char diag_path[PATH_MAX] = "";
if ( !diag_path[0] ) if ( !diag_path[0] ) {
{ snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 3 );
snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", storage->Path(), monitor->Id(), id, 3 );
} }
diff_image->WriteJpeg( diag_path ); diff_image->WriteJpeg( diag_path );
} }
if ( !alarm_blobs ) if ( !alarm_blobs ) {
{
return( false ); return( false );
} }
Debug( 5, "Got %d raw blob pixels, %d raw blobs, need %d -> %d, %d -> %d", alarm_blob_pixels, alarm_blobs, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs ); Debug( 5, "Got %d raw blob pixels, %d raw blobs, need %d -> %d, %d -> %d", alarm_blob_pixels, alarm_blobs, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs );
// Now eliminate blobs under the threshold // Now eliminate blobs under the threshold
for ( int i = 1; i < WHITE; i++ ) for ( int i = 1; i < WHITE; i++ ) {
{
BlobStats *bs = &blob_stats[i]; BlobStats *bs = &blob_stats[i];
if ( bs->count ) if ( bs->count ) {
{ if ( (min_blob_pixels && bs->count < min_blob_pixels) || (max_blob_pixels && bs->count > max_blob_pixels) ) {
if ( (min_blob_pixels && bs->count < min_blob_pixels) || (max_blob_pixels && bs->count > max_blob_pixels) ) if ( config.create_analysis_images || config.record_diag_images ) {
{ for ( int sy = bs->lo_y; sy <= bs->hi_y; sy++ ) {
if ( config.create_analysis_images || config.record_diag_images )
{
for ( int sy = bs->lo_y; sy <= bs->hi_y; sy++ )
{
spdiff = diff_buff + ((diff_width * sy) + bs->lo_x); spdiff = diff_buff + ((diff_width * sy) + bs->lo_x);
for ( int sx = bs->lo_x; sx <= bs->hi_x; sx++, spdiff++ ) for ( int sx = bs->lo_x; sx <= bs->hi_x; sx++, spdiff++ ) {
{ if ( *spdiff == bs->tag ) {
if ( *spdiff == bs->tag )
{
*spdiff = BLACK; *spdiff = BLACK;
} }
} }
@ -634,21 +561,17 @@ bool Zone::CheckAlarms( const Image *delta_image )
bs->lo_y = 0; bs->lo_y = 0;
bs->hi_x = 0; bs->hi_x = 0;
bs->hi_y = 0; bs->hi_y = 0;
} } else {
else
{
Debug( 6, "Preserved blob %d, %d pixels (%d,%d - %d,%d), %d current blobs", i, bs->count, bs->lo_x, bs->lo_y, bs->hi_x, bs->hi_y, alarm_blobs ); Debug( 6, "Preserved blob %d, %d pixels (%d,%d - %d,%d), %d current blobs", i, bs->count, bs->lo_x, bs->lo_y, bs->hi_x, bs->hi_y, alarm_blobs );
if ( !min_blob_size || bs->count < min_blob_size ) min_blob_size = bs->count; if ( !min_blob_size || bs->count < min_blob_size ) min_blob_size = bs->count;
if ( !max_blob_size || bs->count > max_blob_size ) max_blob_size = bs->count; if ( !max_blob_size || bs->count > max_blob_size ) max_blob_size = bs->count;
} }
} }
} }
if ( config.record_diag_images ) if ( config.record_diag_images ) {
{
static char diag_path[PATH_MAX] = ""; static char diag_path[PATH_MAX] = "";
if ( !diag_path[0] ) if ( !diag_path[0] ) {
{ snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 4 );
snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", storage->Path(), monitor->Id(), id, 4 );
} }
diff_image->WriteJpeg( diag_path ); diff_image->WriteJpeg( diag_path );
} }
@ -669,7 +592,7 @@ bool Zone::CheckAlarms( const Image *delta_image )
} }
score = (100*alarm_blob_pixels)/(polygon.Area()); score = (100*alarm_blob_pixels)/(polygon.Area());
if(score < 1) if ( score < 1 )
score = 1; /* Fix for score of 0 when frame meets thresholds but alarmed area is not big enough */ score = 1; /* Fix for score of 0 when frame meets thresholds but alarmed area is not big enough */
Debug( 5, "Current score is %d", score ); Debug( 5, "Current score is %d", score );
@ -677,25 +600,19 @@ bool Zone::CheckAlarms( const Image *delta_image )
alarm_hi_x = polygon.LoX()-1; alarm_hi_x = polygon.LoX()-1;
alarm_lo_y = polygon.HiY()+1; alarm_lo_y = polygon.HiY()+1;
alarm_hi_y = polygon.LoY()-1; alarm_hi_y = polygon.LoY()-1;
for ( int i = 1; i < WHITE; i++ )
{ for ( int i = 1; i < WHITE; i++ ) {
BlobStats *bs = &blob_stats[i]; BlobStats *bs = &blob_stats[i];
if ( bs->count ) if ( bs->count ) {
{ if ( bs->count == max_blob_size ) {
if ( bs->count == max_blob_size ) if ( config.weighted_alarm_centres ) {
{
if ( config.weighted_alarm_centres )
{
unsigned long x_total = 0; unsigned long x_total = 0;
unsigned long y_total = 0; unsigned long y_total = 0;
for ( int sy = bs->lo_y; sy <= bs->hi_y; sy++ ) for ( int sy = bs->lo_y; sy <= bs->hi_y; sy++ ) {
{
spdiff = diff_buff + ((diff_width * sy) + bs->lo_x); spdiff = diff_buff + ((diff_width * sy) + bs->lo_x);
for ( int sx = bs->lo_x; sx <= bs->hi_x; sx++, spdiff++ ) for ( int sx = bs->lo_x; sx <= bs->hi_x; sx++, spdiff++ ) {
{ if ( *spdiff == bs->tag ) {
if ( *spdiff == bs->tag )
{
x_total += sx; x_total += sx;
y_total += sy; y_total += sy;
} }
@ -703,9 +620,7 @@ bool Zone::CheckAlarms( const Image *delta_image )
} }
alarm_mid_x = int(round(x_total/bs->count)); alarm_mid_x = int(round(x_total/bs->count));
alarm_mid_y = int(round(y_total/bs->count)); alarm_mid_y = int(round(y_total/bs->count));
} } else {
else
{
alarm_mid_x = int((bs->hi_x+bs->lo_x+1)/2); alarm_mid_x = int((bs->hi_x+bs->lo_x+1)/2);
alarm_mid_y = int((bs->hi_y+bs->lo_y+1)/2); alarm_mid_y = int((bs->hi_y+bs->lo_y+1)/2);
} }
@ -715,94 +630,72 @@ bool Zone::CheckAlarms( const Image *delta_image )
if ( alarm_lo_y > bs->lo_y ) alarm_lo_y = bs->lo_y; if ( alarm_lo_y > bs->lo_y ) alarm_lo_y = bs->lo_y;
if ( alarm_hi_x < bs->hi_x ) alarm_hi_x = bs->hi_x; if ( alarm_hi_x < bs->hi_x ) alarm_hi_x = bs->hi_x;
if ( alarm_hi_y < bs->hi_y ) alarm_hi_y = bs->hi_y; if ( alarm_hi_y < bs->hi_y ) alarm_hi_y = bs->hi_y;
} } // end if bs->count
} } // end for i < WHITE
} } else {
else
{
alarm_mid_x = int((alarm_hi_x+alarm_lo_x+1)/2); alarm_mid_x = int((alarm_hi_x+alarm_lo_x+1)/2);
alarm_mid_y = int((alarm_hi_y+alarm_lo_y+1)/2); alarm_mid_y = int((alarm_hi_y+alarm_lo_y+1)/2);
} }
} }
if ( type == INCLUSIVE ) if ( type == INCLUSIVE ) {
{
// score >>= 1; // score >>= 1;
score /= 2; score /= 2;
} } else if ( type == EXCLUSIVE ) {
else if ( type == EXCLUSIVE )
{
// score <<= 1; // score <<= 1;
score *= 2; score *= 2;
} }
Debug( 5, "Adjusted score is %d", score ); Debug( 5, "Adjusted score is %d", score );
// Now outline the changed region // Now outline the changed region
if ( score ) if ( score ) {
{
alarm_box = Box( Coord( alarm_lo_x, alarm_lo_y ), Coord( alarm_hi_x, alarm_hi_y ) ); alarm_box = Box( Coord( alarm_lo_x, alarm_lo_y ), Coord( alarm_hi_x, alarm_hi_y ) );
//if ( monitor->followMotion() ) //if ( monitor->followMotion() )
if ( true ) if ( true ) {
{
alarm_centre = Coord( alarm_mid_x, alarm_mid_y ); alarm_centre = Coord( alarm_mid_x, alarm_mid_y );
} } else {
else
{
alarm_centre = alarm_box.Centre(); alarm_centre = alarm_box.Centre();
} }
if ( (type < PRECLUSIVE) && check_method >= BLOBS && config.create_analysis_images ) if ( (type < PRECLUSIVE) && check_method >= BLOBS && config.create_analysis_images ) {
{
// First mask out anything we don't want // First mask out anything we don't want
for ( unsigned int y = lo_y; y <= hi_y; y++ ) for ( unsigned int y = lo_y; y <= hi_y; y++ ) {
{
pdiff = diff_buff + ((diff_width * y) + lo_x); pdiff = diff_buff + ((diff_width * y) + lo_x);
int lo_x2 = ranges[y].lo_x; int lo_x2 = ranges[y].lo_x;
int hi_x2 = ranges[y].hi_x; int hi_x2 = ranges[y].hi_x;
int lo_gap = lo_x2-lo_x; int lo_gap = lo_x2-lo_x;
if ( lo_gap > 0 ) if ( lo_gap > 0 ) {
{ if ( lo_gap == 1 ) {
if ( lo_gap == 1 )
{
*pdiff++ = BLACK; *pdiff++ = BLACK;
} } else {
else
{
memset( pdiff, BLACK, lo_gap ); memset( pdiff, BLACK, lo_gap );
pdiff += lo_gap; pdiff += lo_gap;
} }
} }
ppoly = pg_image->Buffer( lo_x2, y ); ppoly = pg_image->Buffer( lo_x2, y );
for ( int x = lo_x2; x <= hi_x2; x++, pdiff++, ppoly++ ) for ( int x = lo_x2; x <= hi_x2; x++, pdiff++, ppoly++ ) {
{ if ( !*ppoly ) {
if ( !*ppoly )
{
*pdiff = BLACK; *pdiff = BLACK;
} }
} }
int hi_gap = hi_x-hi_x2; int hi_gap = hi_x-hi_x2;
if ( hi_gap > 0 ) if ( hi_gap > 0 ) {
{ if ( hi_gap == 1 ) {
if ( hi_gap == 1 )
{
*pdiff = BLACK; *pdiff = BLACK;
} } else {
else
{
memset( pdiff, BLACK, hi_gap ); memset( pdiff, BLACK, hi_gap );
} }
} }
} }
if( monitor->Colours() == ZM_COLOUR_GRAY8 ) { if ( monitor->Colours() == ZM_COLOUR_GRAY8 ) {
image = diff_image->HighlightEdges( alarm_rgb, ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB, &polygon.Extent() ); image = diff_image->HighlightEdges( alarm_rgb, ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB, &polygon.Extent() );
} else { } else {
image = diff_image->HighlightEdges( alarm_rgb, monitor->Colours(), monitor->SubpixelOrder(), &polygon.Extent() ); image = diff_image->HighlightEdges( alarm_rgb, monitor->Colours(), monitor->SubpixelOrder(), &polygon.Extent() );
@ -810,20 +703,18 @@ bool Zone::CheckAlarms( const Image *delta_image )
// Only need to delete this when 'image' becomes detached and points somewhere else // Only need to delete this when 'image' becomes detached and points somewhere else
delete diff_image; delete diff_image;
} } else {
else
{
delete image; delete image;
image = 0; image = 0;
} }
Debug( 3, "%s: Pixel Diff: %d, Alarm Pixels: %d, Filter Pixels: %d, Blob Pixels: %d, Blobs: %d, Score: %d", Label(), pixel_diff, alarm_pixels, alarm_filter_pixels, alarm_blob_pixels, alarm_blobs, score ); Debug( 1, "%s: Pixel Diff: %d, Alarm Pixels: %d, Filter Pixels: %d, Blob Pixels: %d, Blobs: %d, Score: %d",
Label(), pixel_diff, alarm_pixels, alarm_filter_pixels, alarm_blob_pixels, alarm_blobs, score );
} }
return( true ); return( true );
} }
bool Zone::ParsePolygonString( const char *poly_string, Polygon &polygon ) bool Zone::ParsePolygonString( const char *poly_string, Polygon &polygon ) {
{
Debug( 3, "Parsing polygon string '%s'", poly_string ); Debug( 3, "Parsing polygon string '%s'", poly_string );
char *str_ptr = new char[strlen(poly_string)+1]; char *str_ptr = new char[strlen(poly_string)+1];
@ -834,27 +725,21 @@ bool Zone::ParsePolygonString( const char *poly_string, Polygon &polygon )
int n_coords = 0; int n_coords = 0;
int max_n_coords = strlen(str)/4; int max_n_coords = strlen(str)/4;
Coord *coords = new Coord[max_n_coords]; Coord *coords = new Coord[max_n_coords];
while( true ) while( true ) {
{ if ( *str == '\0' ) {
if ( *str == '\0' )
{
break; break;
} }
ws = strchr( str, ' ' ); ws = strchr( str, ' ' );
if ( ws ) if ( ws ) {
{
*ws = '\0'; *ws = '\0';
} }
char *cp = strchr( str, ',' ); char *cp = strchr( str, ',' );
if ( !cp ) if ( !cp ) {
{
Error( "Bogus coordinate %s found in polygon string", str ); Error( "Bogus coordinate %s found in polygon string", str );
delete[] coords; delete[] coords;
delete[] str_ptr; delete[] str_ptr;
return( false ); return( false );
} } else {
else
{
*cp = '\0'; *cp = '\0';
char *xp = str; char *xp = str;
char *yp = cp+1; char *yp = cp+1;
@ -892,8 +777,7 @@ bool Zone::ParsePolygonString( const char *poly_string, Polygon &polygon )
return( true ); return( true );
} }
bool Zone::ParseZoneString( const char *zone_string, int &zone_id, int &colour, Polygon &polygon ) bool Zone::ParseZoneString( const char *zone_string, int &zone_id, int &colour, Polygon &polygon ) {
{
Debug( 3, "Parsing zone string '%s'", zone_string ); Debug( 3, "Parsing zone string '%s'", zone_string );
char *str_ptr = new char[strlen(zone_string)+1]; char *str_ptr = new char[strlen(zone_string)+1];
@ -901,14 +785,12 @@ bool Zone::ParseZoneString( const char *zone_string, int &zone_id, int &colour,
strcpy( str, zone_string ); strcpy( str, zone_string );
char *ws = strchr( str, ' ' ); char *ws = strchr( str, ' ' );
if ( !ws ) if ( !ws ) {
{
Debug( 3, "No initial whitespace found in zone string '%s', finishing", str ); Debug( 3, "No initial whitespace found in zone string '%s', finishing", str );
} }
zone_id = strtol( str, 0, 10 ); zone_id = strtol( str, 0, 10 );
Debug( 3, "Got zone %d from zone string", zone_id ); Debug( 3, "Got zone %d from zone string", zone_id );
if ( !ws ) if ( !ws ) {
{
delete str_ptr; delete str_ptr;
return( true ); return( true );
} }
@ -917,14 +799,12 @@ bool Zone::ParseZoneString( const char *zone_string, int &zone_id, int &colour,
str = ws+1; str = ws+1;
ws = strchr( str, ' ' ); ws = strchr( str, ' ' );
if ( !ws ) if ( !ws ) {
{
Debug( 3, "No secondary whitespace found in zone string '%s', finishing", zone_string ); Debug( 3, "No secondary whitespace found in zone string '%s', finishing", zone_string );
} }
colour = strtol( str, 0, 16 ); colour = strtol( str, 0, 16 );
Debug( 3, "Got colour %06x from zone string", colour ); Debug( 3, "Got colour %06x from zone string", colour );
if ( !ws ) if ( !ws ) {
{
delete str_ptr; delete str_ptr;
return( true ); return( true );
} }
@ -941,8 +821,7 @@ bool Zone::ParseZoneString( const char *zone_string, int &zone_id, int &colour,
return( result ); return( result );
} }
int Zone::Load( Monitor *monitor, Zone **&zones ) int Zone::Load( Monitor *monitor, Zone **&zones ) {
{
static char sql[ZM_SQL_MED_BUFSIZ]; static char sql[ZM_SQL_MED_BUFSIZ];
snprintf( sql, sizeof(sql), "select Id,Name,Type+0,Units,Coords,AlarmRGB,CheckMethod+0,MinPixelThreshold,MaxPixelThreshold,MinAlarmPixels,MaxAlarmPixels,FilterX,FilterY,MinFilterPixels,MaxFilterPixels,MinBlobPixels,MaxBlobPixels,MinBlobs,MaxBlobs,OverloadFrames,ExtendAlarmFrames from Zones where MonitorId = %d order by Type, Id", monitor->Id() ); snprintf( sql, sizeof(sql), "select Id,Name,Type+0,Units,Coords,AlarmRGB,CheckMethod+0,MinPixelThreshold,MaxPixelThreshold,MinAlarmPixels,MaxAlarmPixels,FilterX,FilterY,MinFilterPixels,MaxFilterPixels,MinBlobPixels,MaxBlobPixels,MinBlobs,MaxBlobs,OverloadFrames,ExtendAlarmFrames from Zones where MonitorId = %d order by Type, Id", monitor->Id() );
if ( mysql_query( &dbconn, sql ) ) { if ( mysql_query( &dbconn, sql ) ) {
@ -960,12 +839,11 @@ int Zone::Load( Monitor *monitor, Zone **&zones )
delete[] zones; delete[] zones;
zones = new Zone *[n_zones]; zones = new Zone *[n_zones];
for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) { for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) {
zones[i] = NULL;
int col = 0; int col = 0;
int Id = atoi(dbrow[col++]); int Id = atoi(dbrow[col++]);
const char *Name = dbrow[col++]; const char *Name = dbrow[col++];
ZoneType Type = (ZoneType) atoi(dbrow[col++]); int Type = atoi(dbrow[col++]);
const char *Units = dbrow[col++]; const char *Units = dbrow[col++];
const char *Coords = dbrow[col++]; const char *Coords = dbrow[col++];
int AlarmRGB = dbrow[col]?atoi(dbrow[col]):0; col++; int AlarmRGB = dbrow[col]?atoi(dbrow[col]):0; col++;
@ -1012,25 +890,22 @@ int Zone::Load( Monitor *monitor, Zone **&zones )
MaxBlobPixels = (MaxBlobPixels*polygon.Area())/100; MaxBlobPixels = (MaxBlobPixels*polygon.Area())/100;
} }
if ( Type == INACTIVE ) { if ( atoi(dbrow[2]) == Zone::INACTIVE ) {
zones[i] = new Zone( monitor, Id, Name, polygon ); zones[i] = new Zone( monitor, Id, Name, polygon );
} else if ( Type == PRIVACY ) { } else if ( atoi(dbrow[2]) == Zone::PRIVACY ) {
zones[i] = new Zone( monitor, Id, Name, Type, polygon ); zones[i] = new Zone( monitor, Id, Name, (Zone::ZoneType)Type, polygon );
} else { }
zones[i] = new Zone( monitor, Id, Name, Type, polygon, AlarmRGB, (Zone::CheckMethod)CheckMethod, MinPixelThreshold, MaxPixelThreshold, MinAlarmPixels, MaxAlarmPixels, Coord( FilterX, FilterY ), MinFilterPixels, MaxFilterPixels, MinBlobPixels, MaxBlobPixels, MinBlobs, MaxBlobs, OverloadFrames, ExtendAlarmFrames ); zones[i] = new Zone( monitor, Id, Name, (Zone::ZoneType)Type, polygon, AlarmRGB, (Zone::CheckMethod)CheckMethod, MinPixelThreshold, MaxPixelThreshold, MinAlarmPixels, MaxAlarmPixels, Coord( FilterX, FilterY ), MinFilterPixels, MaxFilterPixels, MinBlobPixels, MaxBlobPixels, MinBlobs, MaxBlobs, OverloadFrames, ExtendAlarmFrames );
} }
} // end foreach row in zones table
if ( mysql_errno( &dbconn ) ) { if ( mysql_errno( &dbconn ) ) {
Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); Error( "Can't fetch row: %s", mysql_error( &dbconn ) );
exit( mysql_errno( &dbconn ) ); exit( mysql_errno( &dbconn ) );
} }
// Yadda yadda
mysql_free_result( result ); mysql_free_result( result );
return( n_zones ); return( n_zones );
} }
bool Zone::DumpSettings( char *output, bool /*verbose*/ ) bool Zone::DumpSettings( char *output, bool /*verbose*/ ) {
{
output[0] = 0; output[0] = 0;
sprintf( output+strlen(output), " Id : %d\n", id ); sprintf( output+strlen(output), " Id : %d\n", id );
@ -1044,8 +919,7 @@ bool Zone::DumpSettings( char *output, bool /*verbose*/ )
type==PRIVACY?"Privacy":"Unknown" type==PRIVACY?"Privacy":"Unknown"
)))))); ))))));
sprintf( output+strlen(output), " Shape : %d points\n", polygon.getNumCoords() ); sprintf( output+strlen(output), " Shape : %d points\n", polygon.getNumCoords() );
for ( int i = 0; i < polygon.getNumCoords(); i++ ) for ( int i = 0; i < polygon.getNumCoords(); i++ ) {
{
sprintf( output+strlen(output), " %i: %d,%d\n", i, polygon.getCoord( i ).X(), polygon.getCoord( i ).Y() ); sprintf( output+strlen(output), " %i: %d,%d\n", i, polygon.getCoord( i ).X(), polygon.getCoord( i ).Y() );
} }
sprintf( output+strlen(output), " Alarm RGB : %06x\n", alarm_rgb ); sprintf( output+strlen(output), " Alarm RGB : %06x\n", alarm_rgb );
@ -1084,8 +958,7 @@ void Zone::std_alarmedpixels(Image* pdiff_image, const Image* ppoly_image, unsig
lo_y = polygon.LoY(); lo_y = polygon.LoY();
hi_y = polygon.HiY(); hi_y = polygon.HiY();
for ( unsigned int y = lo_y; y <= hi_y; y++ ) for ( unsigned int y = lo_y; y <= hi_y; y++ ) {
{
lo_x = ranges[y].lo_x; lo_x = ranges[y].lo_x;
hi_x = ranges[y].hi_x; hi_x = ranges[y].hi_x;
@ -1093,16 +966,12 @@ void Zone::std_alarmedpixels(Image* pdiff_image, const Image* ppoly_image, unsig
pdiff = (uint8_t*)pdiff_image->Buffer( lo_x, y ); pdiff = (uint8_t*)pdiff_image->Buffer( lo_x, y );
ppoly = ppoly_image->Buffer( lo_x, y ); ppoly = ppoly_image->Buffer( lo_x, y );
for ( unsigned int x = lo_x; x <= hi_x; x++, pdiff++, ppoly++ ) for ( unsigned int x = lo_x; x <= hi_x; x++, pdiff++, ppoly++ ) {
{ if ( *ppoly && (*pdiff > min_pixel_threshold) && (*pdiff <= calc_max_pixel_threshold) ) {
if ( *ppoly && (*pdiff > min_pixel_threshold) && (*pdiff <= calc_max_pixel_threshold) )
{
pixelsalarmed++; pixelsalarmed++;
pixelsdifference += *pdiff; pixelsdifference += *pdiff;
*pdiff = WHITE; *pdiff = WHITE;
} } else {
else
{
*pdiff = BLACK; *pdiff = BLACK;
} }
} }

View File

@ -94,7 +94,10 @@ class ImageComponent extends Component {
// Take the StartTime of an Event and return // Take the StartTime of an Event and return
// the path to its location on the filesystem // the path to its location on the filesystem
public function getEventPath( $event ) { public function getEventPath( $event ) {
if ( $config['ZM_USE_DEEP_STORAGE'] == 1 )
return $event['Event']['MonitorId'].'/'.strftime( "%y/%m/%d/%H/%M/%S", strtotime($event['Event']['StartTime']) ); return $event['Event']['MonitorId'].'/'.strftime( "%y/%m/%d/%H/%M/%S", strtotime($event['Event']['StartTime']) );
else
return $event['Event']['MonitorId'].'/'.$event['Event']['Id'];
} }
} }
?> ?>

View File

@ -1,9 +0,0 @@
AUTOMAKE_OPTIONS = gnu
webdir = @WEB_PREFIX@/css
dist_web_DATA = \
bootstrap.min.css \
reset.css \
spinner.css \
overlay.css

View File

@ -61,12 +61,8 @@
text-align: left; text-align: left;
} }
#consoleTable .colOrder {
text-align: center;
}
#consoleTable .colMark { #consoleTable .colMark {
width: 32px; width: 62px;
text-align: center; text-align: center;
} }
@ -85,13 +81,3 @@
#consoleTable .colLeftButtons input { #consoleTable .colLeftButtons input {
margin-right: 24px; margin-right: 24px;
} }
#consoleTable .colRightButtons {
text-align: right;
padding-right: 8px;
}
#consoleTable .colRightButtons input {
margin: 0 8px;
}

View File

@ -61,12 +61,8 @@
text-align: left; text-align: left;
} }
#consoleTable .colOrder {
text-align: center;
}
#consoleTable .colMark { #consoleTable .colMark {
width: 32px; width: 62px;
text-align: center; text-align: center;
} }
@ -85,13 +81,3 @@
#consoleTable .colLeftButtons input { #consoleTable .colLeftButtons input {
margin-right: 24px; margin-right: 24px;
} }
#consoleTable .colRightButtons {
text-align: right;
padding-right: 8px;
}
#consoleTable .colRightButtons input {
margin: 0 8px;
}

View File

@ -61,12 +61,8 @@
text-align: left; text-align: left;
} }
#consoleTable .colOrder {
text-align: center;
}
#consoleTable .colMark { #consoleTable .colMark {
width: 32px; width: 62px;
text-align: center; text-align: center;
} }
@ -85,12 +81,3 @@
#consoleTable .colLeftButtons input { #consoleTable .colLeftButtons input {
margin-right: 24px; margin-right: 24px;
} }
#consoleTable .colRightButtons {
text-align: right;
padding-right: 8px;
}
#consoleTable .colRightButtons input {
margin: 0 8px;
}

View File

@ -74,8 +74,6 @@ function xhtmlHeaders( $file, $title ) {
<script type="text/javascript" src="tools/mootools/mootools-core.js"></script> <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="tools/mootools/mootools-more.js"></script>
<script type="text/javascript" src="js/mootools.ext.js"></script> <script type="text/javascript" src="js/mootools.ext.js"></script>
<?php if ( !in_array($basename, $bad_views) ) { ?>
<!--<script type="text/javascript" src="js/overlay.js"></script>-->
<script type="text/javascript" src="skins/<?php echo $skin; ?>/js/jquery-1.11.3.js"></script> <script type="text/javascript" src="skins/<?php echo $skin; ?>/js/jquery-1.11.3.js"></script>
<script type="text/javascript" src="skins/<?php echo $skin; ?>/js/jquery-ui-1.11.3.js"></script> <script type="text/javascript" src="skins/<?php echo $skin; ?>/js/jquery-ui-1.11.3.js"></script>
<script type="text/javascript" src="skins/<?php echo $skin; ?>/js/bootstrap.min.js"></script> <script type="text/javascript" src="skins/<?php echo $skin; ?>/js/bootstrap.min.js"></script>
@ -90,7 +88,6 @@ var $j = jQuery.noConflict();
//]]> //]]>
</script> </script>
<script type="text/javascript" src="skins/<?php echo $skin; ?>/views/js/state.js"></script> <script type="text/javascript" src="skins/<?php echo $skin; ?>/views/js/state.js"></script>
<?php } ?>
<?php if ( $title == 'Login' && (defined('ZM_OPT_USE_GOOG_RECAPTCHA') && ZM_OPT_USE_GOOG_RECAPTCHA) ) { ?> <?php if ( $title == 'Login' && (defined('ZM_OPT_USE_GOOG_RECAPTCHA') && ZM_OPT_USE_GOOG_RECAPTCHA) ) { ?>
<script src='https://www.google.com/recaptcha/api.js'></script> <script src='https://www.google.com/recaptcha/api.js'></script>
<?php } else if ( $title == 'Event' ) { <?php } else if ( $title == 'Event' ) {

View File

@ -83,6 +83,7 @@ $eventCounts = array(
$displayMonitors = NULL; $displayMonitors = NULL;
<<<<<<< HEAD
# Also populates displayMonitors # Also populates displayMonitors
$navbar = getNavBarHTML(); $navbar = getNavBarHTML();
$zoneCount = 0; $zoneCount = 0;
@ -107,12 +108,76 @@ for( $i = 0; $i < count($displayMonitors); $i += 1 ) {
$eventCounts[$j]['total'] += $monitor['EventCount'.$j]; $eventCounts[$j]['total'] += $monitor['EventCount'.$j];
} }
$zoneCount += $monitor['ZoneCount']; $zoneCount += $monitor['ZoneCount'];
=======
$group = NULL;
if ( ! empty($_COOKIE['zmGroup']) ) {
if ( $group = dbFetchOne( 'select * from Groups where Id = ?', NULL, array($_COOKIE['zmGroup'])) )
$groupIds = array_flip(explode( ',', $group['MonitorIds'] ));
}
noCacheHeaders();
$maxWidth = 0;
$maxHeight = 0;
$cycleCount = 0;
$minSequence = 0;
$maxSequence = 1;
$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;
$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 );
$displayMonitors[] = $monitors[$i];
>>>>>>> dragndrop_monitor_sorting
} }
noCacheHeaders(); noCacheHeaders();
$eventsView = ZM_WEB_EVENTS_VIEW; $eventsView = ZM_WEB_EVENTS_VIEW;
$eventsWindow = 'zm'.ucfirst(ZM_WEB_EVENTS_VIEW); $eventsWindow = 'zm'.ucfirst(ZM_WEB_EVENTS_VIEW);
<<<<<<< HEAD
=======
$eventCount = 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'];
}
$versionClass = (ZM_DYN_DB_VERSION&&(ZM_DYN_DB_VERSION!=ZM_VERSION))?'errorText':'';
>>>>>>> dragndrop_monitor_sorting
$left_columns = 3; $left_columns = 3;
if ( count($servers) ) $left_columns += 1; if ( count($servers) ) $left_columns += 1;
if ( ZM_WEB_ID_ON_CONSOLE ) $left_columns += 1; if ( ZM_WEB_ID_ON_CONSOLE ) $left_columns += 1;
@ -124,11 +189,56 @@ xhtmlHeaders( __FILE__, translate('Console') );
<form name="monitorForm" method="get" action="<?php echo $_SERVER['PHP_SELF'] ?>"> <form name="monitorForm" method="get" action="<?php echo $_SERVER['PHP_SELF'] ?>">
<input type="hidden" name="view" value="<?php echo $view ?>"/> <input type="hidden" name="view" value="<?php echo $view ?>"/>
<input type="hidden" name="action" value=""/> <input type="hidden" name="action" value=""/>
<<<<<<< HEAD
<?php echo $navbar ?> <?php echo $navbar ?>
<div class="container-fluid"> <div class="container-fluid">
<table class="table table-striped table-hover table-condensed"> <table class="table table-striped table-hover table-condensed">
=======
<div id="header">
<h3 id="systemTime"><?php echo preg_match( '/%/', DATE_FMT_CONSOLE_LONG )?strftime( DATE_FMT_CONSOLE_LONG ):date( DATE_FMT_CONSOLE_LONG ) ?></h3>
<h3 id="systemStats"><?php echo translate('Load') ?>: <?php echo getLoad() ?> - <?php echo translate('Disk') ?>: <?php echo getDiskPercent() ?>% - <?php echo ZM_PATH_MAP ?>: <?php echo getDiskPercent(ZM_PATH_MAP) ?>%</h3>
<h2 id="title"><a href="http://www.zoneminder.com" target="ZoneMinder">ZoneMinder</a> <?php echo translate('Console') ?> - <?php echo makePopupLink( '?view=state', 'zmState', 'state', $status, canEdit( 'System' ) ) ?> - <?php echo $run_state ?> <?php echo makePopupLink( '?view=version', 'zmVersion', 'version', '<span class="'.$versionClass.'">v'.ZM_VERSION.'</span>', canEdit( 'System' ) ) ?></h2>
<div class="clear"></div>
<h3 id="development"><center><?php echo ZM_WEB_CONSOLE_BANNER ?></center></h3>
<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' ) ) {
?>
<div id="devices"><?php echo makePopupLink( '?view=devices', 'zmDevices', 'devices', translate('Devices') ) ?></div>
<?php
}
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 ) {
$cycleGroup = isset($_COOKIE['zmGroup'])?$_COOKIE['zmGroup']:0;
?>
<div id="cycleMontage">
<?php echo makePopupLink( '?view=cycle&amp;group='.$cycleGroup, 'zmCycle'.$cycleGroup, array( 'cycle', $cycleWidth, $cycleHeight ), translate('Cycle'), $running ) ?>&nbsp;/&nbsp;
<?php echo makePopupLink( '?view=montage&amp;group='.$cycleGroup, 'zmMontage'.$cycleGroup, 'montage', translate('Montage'), $running ) ?>&nbsp;/&nbsp;
<?php echo makePopupLink( '?view=montagereview&amp;group='.$cycleGroup, 'zmMontage'.$cycleGroup, 'montagereview', translate('Montage Review'), $running ) ?>
</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 {
?><?php echo translate('ConfiguredFor') ?><?php
}
?>&nbsp;<?php echo makePopupLink( '?view=bandwidth', 'zmBandwidth', 'bandwidth', $bwArray[$_COOKIE['zmBandwidth']], ($user && $user['MaxBandwidth'] != 'low' ) ) ?> <?php echo translate('BandwidthHead') ?></h3>
</div>
<div id="content">
<table id="consoleTable" cellspacing="0">
>>>>>>> dragndrop_monitor_sorting
<thead> <thead>
<tr> <tr>
<?php if ( ZM_WEB_ID_ON_CONSOLE ) { ?> <?php if ( ZM_WEB_ID_ON_CONSOLE ) { ?>
@ -140,6 +250,7 @@ xhtmlHeaders( __FILE__, translate('Console') );
<th class="colServer"><?php echo translate('Server') ?></th> <th class="colServer"><?php echo translate('Server') ?></th>
<?php } ?> <?php } ?>
<th class="colSource"><?php echo translate('Source') ?></th> <th class="colSource"><?php echo translate('Source') ?></th>
<<<<<<< HEAD
<?php if ( $show_storage_areas ) { ?> <?php if ( $show_storage_areas ) { ?>
<th class="colStorage"><?php echo translate('Storage') ?></th> <th class="colStorage"><?php echo translate('Storage') ?></th>
<?php } ?> <?php } ?>
@ -148,6 +259,16 @@ xhtmlHeaders( __FILE__, translate('Console') );
<?php } ?> <?php } ?>
<th class="colZones"><a href="<?php echo $_SERVER['PHP_SELF'] ?>?view=zones_overview"><?php echo translate('Zones') ?></a></th> <th class="colZones"><a href="<?php echo $_SERVER['PHP_SELF'] ?>?view=zones_overview"><?php echo translate('Zones') ?></a></th>
<?php if ( canEdit('Monitors') ) { ?> <?php if ( canEdit('Monitors') ) { ?>
=======
<?php
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>
>>>>>>> dragndrop_monitor_sorting
<th class="colMark"><?php echo translate('Mark') ?></th> <th class="colMark"><?php echo translate('Mark') ?></th>
<?php } ?> <?php } ?>
</tr> </tr>
@ -155,6 +276,7 @@ xhtmlHeaders( __FILE__, translate('Console') );
<tfoot> <tfoot>
<tr> <tr>
<td class="colLeftButtons" colspan="<?php echo $left_columns ?>"> <td class="colLeftButtons" colspan="<?php echo $left_columns ?>">
<<<<<<< HEAD
<input type="button" class="btn btn-primary" value="<?php echo translate('Refresh') ?>" onclick="location.reload(true);"/> <input type="button" class="btn btn-primary" value="<?php echo translate('Refresh') ?>" onclick="location.reload(true);"/>
<input type="button" class="btn btn-primary" name="addBtn" value="<?php echo translate('AddNewMonitor') ?>" onclick="addMonitor( this )"/> <input type="button" class="btn btn-primary" 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=monitor', 'zmMonitor0', 'monitor', translate('AddNewMonitor'), (canEdit( 'Monitors' ) && !$user['MonitorIds']) ) ?> -->
@ -164,28 +286,49 @@ xhtmlHeaders( __FILE__, translate('Console') );
</td> </td>
<?php for ( $i = 0; $i < count($eventCounts); $i++ ) { <?php for ( $i = 0; $i < count($eventCounts); $i++ ) {
parseFilter( $eventCounts[$i]['filter'] ); parseFilter( $eventCounts[$i]['filter'] );
=======
<input type="button" value="<?php echo translate('Refresh') ?>" onclick="location.reload(true);"/>
<input type="button" name="addBtn" value="<?php echo translate('AddNewMonitor') ?>" onclick="addMonitor( this )"/>
<!-- <?php echo makePopupButton( '?view=monitor', 'zmMonitor0', 'monitor', translate('AddNewMonitor'), (canEdit( 'Monitors' ) && !$user['MonitorIds']) ) ?> -->
<?php echo makePopupButton( '?view=filter&amp;filter[terms][0][attr]=DateTime&amp;filter[terms][0][op]=%3c&amp;filter[terms][0][val]=now', 'zmFilter', 'filter', translate('Filters'), canView( 'Events' ) ) ?>
<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>
<?php
for ( $i = 0; $i < count($eventCounts); $i++ ) {
parseFilter( $eventCounts[$i]['filter'] );
>>>>>>> dragndrop_monitor_sorting
?> ?>
<td class="colEvents"><?php echo makePopupLink( '?view='.$eventsView.'&amp;page=1'.$eventCounts[$i]['filter']['query'], $eventsWindow, $eventsView, $eventCounts[$i]['total'], canView( 'Events' ) ) ?></td> <td class="colEvents"><?php echo makePopupLink( '?view='.$eventsView.'&amp;page=1'.$eventCounts[$i]['filter']['query'], $eventsWindow, $eventsView, $eventCounts[$i]['total'], canView( 'Events' ) ) ?></td>
<?php <?php
} }
?> ?>
<td class="colZones"><?php echo $zoneCount ?></td> <td class="colZones"><?php echo $zoneCount ?></td>
<<<<<<< HEAD
<?php if ( canEdit('Monitors') ) { ?> <?php if ( canEdit('Monitors') ) { ?>
<td class="colMark"></td> <td class="colMark"></td>
<?php } ?> <?php } ?>
=======
<td class="colMark"></td>
>>>>>>> dragndrop_monitor_sorting
</tr> </tr>
</tfoot> </tfoot>
<tbody id="consoleTableBody"> <tbody id="consoleTableBody">
<?php <?php
<<<<<<< HEAD
for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) { for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
$monitor = $displayMonitors[$monitor_i]; $monitor = $displayMonitors[$monitor_i];
?> ?>
<tr id="<?php echo 'monitor_id-'.$monitor['Id'] ?>" title="<?php echo $monitor['Id'] ?>"> <tr id="<?php echo 'monitor_id-'.$monitor['Id'] ?>" title="<?php echo $monitor['Id'] ?>">
=======
foreach( $displayMonitors as $monitor ) {
?>
<tr id="<?php echo 'monitor_id-'.$monitor['Id'] ?>">
>>>>>>> dragndrop_monitor_sorting
<?php <?php
if ( !$monitor['zmc'] ) if ( !$monitor['zmc'] ) {
$dclass = "errorText"; $dclass = "errorText";
else } else {
{
// https://github.com/ZoneMinder/ZoneMinder/issues/1082 // https://github.com/ZoneMinder/ZoneMinder/issues/1082
if ( !$monitor['zma'] && $monitor['Function']!='Monitor' ) if ( !$monitor['zma'] && $monitor['Function']!='Monitor' )
$dclass = "warnText"; $dclass = "warnText";
@ -262,13 +405,4 @@ if ( canEdit('System') ) {
} }
?> ?>
</body> </body>
<script>
$j( function() {
$j( "#consoleTableBody" ).sortable({
handle: ".glyphicon-sort",
update: applySort,
axis:'Y' } );
$j( "#consoleTableBody" ).disableSelection();
} );
</script>
</html> </html>

View File

@ -74,6 +74,15 @@ function initPage() {
createPopup( '?view=version', 'zmVersion', 'version' ); createPopup( '?view=version', 'zmVersion', 'version' );
if ( showDonatePopup ) if ( showDonatePopup )
createPopup( '?view=donate', 'zmDonate', 'donate' ); createPopup( '?view=donate', 'zmDonate', 'donate' );
// Makes table sortable
$j( function() {
$j( "#consoleTableBody" ).sortable({
handle: ".glyphicon-sort",
update: applySort,
axis:'Y' } );
$j( "#consoleTableBody" ).disableSelection();
} );
} }
function applySort(event, ui) { function applySort(event, ui) {

View File

@ -19,7 +19,6 @@
// //
require_once( 'includes/Server.php'); require_once( 'includes/Server.php');
require_once( 'includes/Storage.php');
if ( !canView( 'Monitors' ) ) { if ( !canView( 'Monitors' ) ) {
$view = "error"; $view = "error";
@ -29,7 +28,6 @@ if ( !canView( 'Monitors' ) ) {
$tabs = array(); $tabs = array();
$tabs["general"] = translate('General'); $tabs["general"] = translate('General');
$tabs["source"] = translate('Source'); $tabs["source"] = translate('Source');
$tabs["storage"] = translate('Storage');
$tabs["timestamp"] = translate('Timestamp'); $tabs["timestamp"] = translate('Timestamp');
$tabs["buffers"] = translate('Buffers'); $tabs["buffers"] = translate('Buffers');
if ( ZM_OPT_CONTROL && canView( 'Control' ) ) if ( ZM_OPT_CONTROL && canView( 'Control' ) )
@ -137,7 +135,6 @@ if ( ! empty($_REQUEST['mid']) ) {
'V4LMultiBuffer' => '', 'V4LMultiBuffer' => '',
'V4LCapturesPerFrame' => 1, 'V4LCapturesPerFrame' => 1,
'ServerId' => $Server['Id'], 'ServerId' => $Server['Id'],
'StorageId' => '0',
) ); ) );
} # end if $_REQUEST['dupID'] } # end if $_REQUEST['dupID']
} # end if $_REQUEST['mid'] } # end if $_REQUEST['mid']
@ -519,7 +516,6 @@ if ( $tab != 'general' ) {
?> ?>
<input type="hidden" name="newMonitor[Name]" value="<?php echo validHtmlStr($monitor->Name) ?>"/> <input type="hidden" name="newMonitor[Name]" value="<?php echo validHtmlStr($monitor->Name) ?>"/>
<input type="hidden" name="newMonitor[ServerId]" value="<?php echo validHtmlStr($monitor->ServerId() ) ?>"/> <input type="hidden" name="newMonitor[ServerId]" value="<?php echo validHtmlStr($monitor->ServerId() ) ?>"/>
<input type="hidden" name="newMonitor[StorageId]" value="<?= validHtmlStr($monitor->StorageId() ) ?>"/>
<input type="hidden" name="newMonitor[Type]" value="<?php echo validHtmlStr($monitor->Type) ?>"/> <input type="hidden" name="newMonitor[Type]" value="<?php echo validHtmlStr($monitor->Type) ?>"/>
<input type="hidden" name="newMonitor[Function]" value="<?php echo validHtmlStr($monitor->Function) ?>"/> <input type="hidden" name="newMonitor[Function]" value="<?php echo validHtmlStr($monitor->Function) ?>"/>
<input type="hidden" name="newMonitor[Enabled]" value="<?php echo validHtmlStr($monitor->Enabled) ?>"/> <input type="hidden" name="newMonitor[Enabled]" value="<?php echo validHtmlStr($monitor->Enabled) ?>"/>
@ -682,17 +678,6 @@ switch ( $tab )
$servers[$server_obj->Id()] = $server_obj->Name(); $servers[$server_obj->Id()] = $server_obj->Name();
} }
echo htmlSelect( "newMonitor[ServerId]", $servers, $monitor->ServerId() ); echo htmlSelect( "newMonitor[ServerId]", $servers, $monitor->ServerId() );
?>
</td></tr>
<tr><td><?php echo translate('StorageArea') ?></td><td>
<?php
$storage_areas = array(0=>'Default');
$result = dbQuery( 'SELECT * FROM Storage ORDER BY Name');
$results = $result->fetchALL(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'Storage' );
foreach ( $results as $row => $storage_obj ) {
$storage_areas[$storage_obj->Id] = $storage_obj->Name();
}
echo htmlSelect( "newMonitor[StorageId]", $storage_areas, $monitor->StorageId() );
?> ?>
</td></tr> </td></tr>
<tr><td><?php echo translate('SourceType') ?></td><td><?php echo htmlSelect( "newMonitor[Type]", $sourceTypes, $monitor->Type() ); ?></td></tr> <tr><td><?php echo translate('SourceType') ?></td><td><?php echo htmlSelect( "newMonitor[Type]", $sourceTypes, $monitor->Type() ); ?></td></tr>