From b12d72c68f2d580f014a764de8655f799f1a5957 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 9 Jul 2015 11:44:27 -0400 Subject: [PATCH 001/362] fix monitor popup size --- web/skins/classic/js/flat.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/js/flat.js b/web/skins/classic/js/flat.js index 4e43ce170..7a6947d60 100644 --- a/web/skins/classic/js/flat.js +++ b/web/skins/classic/js/flat.js @@ -48,7 +48,7 @@ var popupSizes = { 'log': { 'width': 1080, 'height': 720 }, 'login': { 'width': 720, 'height': 480 }, 'logout': { 'width': 260, 'height': 100 }, - 'monitor': { 'width': 450, 'height': 440 }, + 'monitor': { 'width': 550, 'height': 630 }, 'monitorpreset':{ 'width': 440, 'height': 200 }, 'monitorprobe': { 'width': 500, 'height': 240 }, 'monitorselect':{ 'width': 160, 'height': 200 }, From 69e1fd8b182f0ffc1b3af8d049ac50738b216758 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 9 Jul 2015 11:45:19 -0400 Subject: [PATCH 002/362] add code to convert the human readable config entry ZM_SERVER_NAME into ZM_SERVER_ID --- web/includes/config.php.in | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/web/includes/config.php.in b/web/includes/config.php.in index fbcb0e7b3..7fdba34a7 100644 --- a/web/includes/config.php.in +++ b/web/includes/config.php.in @@ -166,4 +166,15 @@ function loadConfig( $defineConsts=true ) //print_r( $configCats ); } +// For Human-readability, user ZM_SERVER in zm.conf, and convert it here to a ZM_SERVER_ID +if ( ! defined(ZM_SERVER_ID) and defined(ZM_SERVER) ) { + $server_id = dbFetchOne('SELECT Id FROM Servers WHERE Name=?', 'Id', array(ZM_SERVER_NAME)); + if ( ! $server_id ) { + Error("ZM_SERVER_NAME set in config, but not found in Servers table."); + } else { + define( ZM_SERVER_ID, $server_id ); + } +} + + ?> From 7fa2d51277d5ff7582161e9cf3f7b5ff5a951575 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 15 Jul 2015 09:42:29 -0400 Subject: [PATCH 003/362] snapshot releases --- distros/ubuntu1504/changelog | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/distros/ubuntu1504/changelog b/distros/ubuntu1504/changelog index 2dfc8b63c..e53dd0203 100644 --- a/distros/ubuntu1504/changelog +++ b/distros/ubuntu1504/changelog @@ -1,3 +1,21 @@ +zoneminder (1.28.1+1-vivid-SNAPSHOT2015070402) vivid; urgency=medium + + * Correct PRIMARY KEY update code on States table + + -- Isaac Connor Tue, 07 Jul 2015 15:40:21 -0400 + +zoneminder (1.28.1+1-vivid-SNAPSHOT2015070401) vivid; urgency=medium + + * Bump actual version # so that db upgrade scripts run + + -- Isaac Connor Tue, 07 Jul 2015 12:44:55 -0400 + +zoneminder (1.28.1+1-vivid-SNAPSHOT2015070301) vivid; urgency=medium + + * initial merge of api. Various other small fixes/improvements. + + -- Isaac Connor Mon, 06 Jul 2015 15:59:08 -0400 + zoneminder (1.28.1+1-trusty-SNAPSHOT2015030201) trusty; urgency=medium * maybe fix for RTSP Basic Auth From e318c3bf3746e7cca71a8ed8decd6e95cb63864c Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 15 Jul 2015 16:12:35 -0400 Subject: [PATCH 004/362] Add ServerId as a filter option --- scripts/zmfilter.pl.in | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/scripts/zmfilter.pl.in b/scripts/zmfilter.pl.in index 54f372262..4280f4e48 100755 --- a/scripts/zmfilter.pl.in +++ b/scripts/zmfilter.pl.in @@ -349,6 +349,10 @@ sub getFilters my ( $temp_attr_name ) = $filter_expr->{terms}[$i]->{attr} =~ /^Monitor(.+)$/; $db_filter->{Sql} .= "M.".$temp_attr_name; } + elsif ( $filter_expr->{terms}[$i]->{attr} eq 'ServerId' ) + { + $db_filter->{Sql} .= "M.ServerId"; + } elsif ( $filter_expr->{terms}[$i]->{attr} eq 'DateTime' ) { $db_filter->{Sql} .= "E.StartTime"; @@ -392,6 +396,13 @@ sub getFilters { $value = "'$temp_value'"; } + elsif ( $filter_expr->{terms}[$i]->{attr} eq 'ServerId' ) { + if ( $temp_value eq 'ZM_SERVER_ID' ) { + $value = "'$Config{ZM_SERVER_ID}'"; + } else { + $value = "'$temp_value'"; + } + } elsif ( $filter_expr->{terms}[$i]->{attr} eq 'Name' || $filter_expr->{terms}[$i]->{attr} eq 'Cause' || $filter_expr->{terms}[$i]->{attr} eq 'Notes' From 51af432468c278a667652352a3ad57fa76e08b23 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 15 Jul 2015 16:18:05 -0400 Subject: [PATCH 005/362] Only load monitors for our server if ZM_SERVER_ID is specified --- scripts/zmpkg.pl.in | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/zmpkg.pl.in b/scripts/zmpkg.pl.in index 46ea825c4..c5a1d489d 100644 --- a/scripts/zmpkg.pl.in +++ b/scripts/zmpkg.pl.in @@ -119,10 +119,10 @@ my $retval = 0; if ( $command eq "state" ) { Info( "Updating DB: $state->{Name}\n" ); - my $sql = "select * from Monitors order by Id asc"; + my $sql = $Config{ZM_SERVER_ID} ? 'SELECT * FROM Monitors WHERE ServerId=? ORDER BY Id ASC' : 'SELECT * FROM Monitors ORDER BY Id ASC'; my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); - my $res = $sth->execute() + my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID}: () ) or Fatal( "Can't execute: ".$sth->errstr() ); while( my $monitor = $sth->fetchrow_hashref() ) { @@ -228,10 +228,10 @@ if ( $command =~ /^(?:start|restart)$/ ) zmMemTidy(); runCommand( "zmdc.pl startup" ); - my $sql = "select * from Monitors"; + my $sql = $Config{ZM_SERVER_ID} ? 'SELECT * FROM Monitors WHERE ServerId=?' : 'SELECT * FROM Monitors'; my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); - my $res = $sth->execute() + my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID} : () ) or Fatal( "Can't execute: ".$sth->errstr() ); while( my $monitor = $sth->fetchrow_hashref() ) { From b8888b9d5536b51e66331ec49c60ce1d6b40ad74 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 15 Jul 2015 16:22:43 -0400 Subject: [PATCH 006/362] Only load triggers for our Server if ZM_SERVER_ID is set --- scripts/zmtrigger.pl.in | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/zmtrigger.pl.in b/scripts/zmtrigger.pl.in index e43b00bbb..0dc18562d 100644 --- a/scripts/zmtrigger.pl.in +++ b/scripts/zmtrigger.pl.in @@ -358,11 +358,12 @@ sub loadMonitors my %new_monitors = (); my $sql = "SELECT * FROM Monitors - WHERE find_in_set( Function, 'Modect,Mocord,Nodect' )" + WHERE find_in_set( Function, 'Modect,Mocord,Nodect' )". + ( $Config{ZM_SERVER_ID} ? 'AND ServerId=?' : '' ) ; my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); - my $res = $sth->execute() + my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID} : () ) or Fatal( "Can't execute: ".$sth->errstr() ); while( my $monitor = $sth->fetchrow_hashref() ) { From ca9a391d6216cc17b48298af7d1d78b661357a11 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 15 Jul 2015 16:24:01 -0400 Subject: [PATCH 007/362] Only load the monitors for our server --- scripts/zmwatch.pl.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/zmwatch.pl.in b/scripts/zmwatch.pl.in index 01d15e815..3e97733a1 100644 --- a/scripts/zmwatch.pl.in +++ b/scripts/zmwatch.pl.in @@ -74,14 +74,14 @@ sleep( START_DELAY ); my $dbh = zmDbConnect(); -my $sql = "select * from Monitors"; +my $sql = $Config{ZM_SERVER_ID} ? 'SELECT * FROM Monitors WHERE ServerId=?' : 'SELECT * FROM Monitors'; my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); while( 1 ) { my $now = time(); - my $res = $sth->execute() + my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID} : () ) or Fatal( "Can't execute: ".$sth->errstr() ); while( my $monitor = $sth->fetchrow_hashref() ) { From 34813685742ed08aa918ac1f42363ba0985d470e Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 15 Jul 2015 16:44:16 -0400 Subject: [PATCH 008/362] given SERVER_NAME populate SERVER_ID and vice versa --- src/zm_config.cpp | 69 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/src/zm_config.cpp b/src/zm_config.cpp index a25f7a39a..27a8365e4 100644 --- a/src/zm_config.cpp +++ b/src/zm_config.cpp @@ -91,17 +91,82 @@ void zmLoadConfig() staticConfig.DB_PASS = std::string(val_ptr); else if ( strcasecmp( name_ptr, "ZM_PATH_WEB" ) == 0 ) staticConfig.PATH_WEB = std::string(val_ptr); + else if ( strcasecmp( name_ptr, "ZM_SERVER_HOST" ) == 0 ) + staticConfig.SERVER_NAME = std::string(val_ptr); + else if ( strcasecmp( name_ptr, "ZM_SERVER_NAME" ) == 0 ) + staticConfig.SERVER_NAME = std::string(val_ptr); + else if ( strcasecmp( name_ptr, "ZM_SERVER_ID" ) == 0 ) + staticConfig.SERVER_ID = atoi(val_ptr); else { // We ignore this now as there may be more parameters than the // c/c++ binaries are bothered about // Warning( "Invalid parameter '%s' in %s", name_ptr, ZM_CONFIG ); } - } - fclose( cfg); + } // end foreach line of the config + fclose( cfg ); zmDbConnect(); config.Load(); config.Assign(); + + // Populate the server config entries + if ( ! staticConfig.SERVER_ID ) { + if ( staticConfig.SERVER_NAME && ! staticConfig.SERVER_NAME.empty() ) { + + std::string sql = stringtf("SELECT Id FROM Servers WHERE Name='%s'", staticConfig.SERVER_NAME ); + if ( mysql_query( &dbconn, sql.c_str() ) ) + { + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + Fatal("Can't get ServerId for Server %s", staticConfig.SERVER_NAME ); + } + MYSQL_RES *result = mysql_store_result( &dbconn ); + if ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + Fatal("Can't get ServerId for Server %s", staticConfig.SERVER_NAME ); + } + int n_rows = mysql_num_rows( result ); + if ( n_rows != 1 ) + { + Error( "Bogus number of lines return from Server lookup, %d, returned. Can't reload", n_rows ); + Fatal("Can't get ServerId for Server %s", staticConfig.SERVER_NAME ); + } + + if ( MYSQL_ROW dbrow = mysql_fetch_row( result ) ) + { + staticConfig.SERVER_ID = atoi(dbrow[0]); + } + mysql_free_result( result ); + + } // end if has SERVER_NAME + } else if ( ! staticConfig.SERVER_NAME ) { + std::string sql = stringtf("SELECT Name FROM Servers WHERE Id='%d'", staticConfig.SERVER_ID ); + if ( mysql_query( &dbconn, sql.c_str() ) ) + { + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + Fatal("Can't get ServerName for Server ID %d", staticConfig.SERVER_ID ); + } + + MYSQL_RES *result = mysql_store_result( &dbconn ); + if ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + Fatal("Can't get ServerName for Server ID %d", staticConfig.SERVER_ID ); + } + int n_rows = mysql_num_rows( result ); + if ( n_rows != 1 ) + { + Error( "Bogus number of lines return from Server lookup, %d, returned. Can't reload", n_rows ); + Fatal("Can't get ServerName for Server ID %d", staticConfig.SERVER_ID ); + } + + if ( MYSQL_ROW dbrow = mysql_fetch_row( result ) ) + { + staticConfig.SERVER_NAME = std::string(dbrow[0]); + } + mysql_free_result( result ); + + } } StaticConfig staticConfig; From 50b333fb28321fca9e2cba017294f5380622b25c Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 16 Jul 2015 10:04:56 -0400 Subject: [PATCH 009/362] Add SERVER_NAME and SERVER_ID loading to config --- src/zm_config.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/zm_config.cpp b/src/zm_config.cpp index 27a8365e4..f8ae0c271 100644 --- a/src/zm_config.cpp +++ b/src/zm_config.cpp @@ -25,6 +25,8 @@ #include #include +#include "zm_utils.h" + void zmLoadConfig() { FILE *cfg; @@ -111,25 +113,25 @@ void zmLoadConfig() // Populate the server config entries if ( ! staticConfig.SERVER_ID ) { - if ( staticConfig.SERVER_NAME && ! staticConfig.SERVER_NAME.empty() ) { + if ( ! staticConfig.SERVER_NAME.empty() ) { - std::string sql = stringtf("SELECT Id FROM Servers WHERE Name='%s'", staticConfig.SERVER_NAME ); + std::string sql = stringtf("SELECT Id FROM Servers WHERE Name='%s'", staticConfig.SERVER_NAME.c_str() ); if ( mysql_query( &dbconn, sql.c_str() ) ) { Error( "Can't run query: %s", mysql_error( &dbconn ) ); - Fatal("Can't get ServerId for Server %s", staticConfig.SERVER_NAME ); + Fatal("Can't get ServerId for Server %s", staticConfig.SERVER_NAME.c_str() ); } MYSQL_RES *result = mysql_store_result( &dbconn ); if ( !result ) { Error( "Can't use query result: %s", mysql_error( &dbconn ) ); - Fatal("Can't get ServerId for Server %s", staticConfig.SERVER_NAME ); + Fatal("Can't get ServerId for Server %s", staticConfig.SERVER_NAME.c_str() ); } int n_rows = mysql_num_rows( result ); if ( n_rows != 1 ) { Error( "Bogus number of lines return from Server lookup, %d, returned. Can't reload", n_rows ); - Fatal("Can't get ServerId for Server %s", staticConfig.SERVER_NAME ); + Fatal("Can't get ServerId for Server %s", staticConfig.SERVER_NAME.c_str() ); } if ( MYSQL_ROW dbrow = mysql_fetch_row( result ) ) @@ -139,7 +141,7 @@ void zmLoadConfig() mysql_free_result( result ); } // end if has SERVER_NAME - } else if ( ! staticConfig.SERVER_NAME ) { + } else if ( staticConfig.SERVER_NAME.empty() ) { std::string sql = stringtf("SELECT Name FROM Servers WHERE Id='%d'", staticConfig.SERVER_ID ); if ( mysql_query( &dbconn, sql.c_str() ) ) { From 4ed248e5a5d00fad62fb43ead3e297a9c0bd165c Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 16 Jul 2015 10:05:21 -0400 Subject: [PATCH 010/362] Add SERVER_NAME and SERVER_ID loading to config --- src/zm_config.h.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/zm_config.h.in b/src/zm_config.h.in index 1df1edf16..83aa19210 100644 --- a/src/zm_config.h.in +++ b/src/zm_config.h.in @@ -65,6 +65,8 @@ struct StaticConfig std::string DB_USER; std::string DB_PASS; std::string PATH_WEB; + std::string SERVER_NAME; + unsigned int SERVER_ID; }; extern StaticConfig staticConfig; From 60410c98d6c20988a012da7f68995be7889f3b2c Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 16 Jul 2015 16:44:09 -0400 Subject: [PATCH 011/362] use new db functions in zm_config.cpp --- src/zm_config.cpp | 25 ++++--------------------- src/zm_db.cpp | 3 ++- src/zm_db.h | 2 +- 3 files changed, 7 insertions(+), 23 deletions(-) diff --git a/src/zm_config.cpp b/src/zm_config.cpp index f8ae0c271..e9c54b943 100644 --- a/src/zm_config.cpp +++ b/src/zm_config.cpp @@ -115,30 +115,13 @@ void zmLoadConfig() if ( ! staticConfig.SERVER_ID ) { if ( ! staticConfig.SERVER_NAME.empty() ) { + std::string sql = stringtf("SELECT Id FROM Servers WHERE Name='%s'", staticConfig.SERVER_NAME.c_str() ); - if ( mysql_query( &dbconn, sql.c_str() ) ) - { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - Fatal("Can't get ServerId for Server %s", staticConfig.SERVER_NAME.c_str() ); - } - MYSQL_RES *result = mysql_store_result( &dbconn ); - if ( !result ) - { - Error( "Can't use query result: %s", mysql_error( &dbconn ) ); - Fatal("Can't get ServerId for Server %s", staticConfig.SERVER_NAME.c_str() ); - } - int n_rows = mysql_num_rows( result ); - if ( n_rows != 1 ) - { - Error( "Bogus number of lines return from Server lookup, %d, returned. Can't reload", n_rows ); - Fatal("Can't get ServerId for Server %s", staticConfig.SERVER_NAME.c_str() ); - } - - if ( MYSQL_ROW dbrow = mysql_fetch_row( result ) ) - { + if ( MYSQL_ROW dbrow = zmDbFetchOne( sql.c_str() ) ) { staticConfig.SERVER_ID = atoi(dbrow[0]); + } else { + Fatal("Can't get ServerId for Server %s", staticConfig.SERVER_NAME.c_str() ); } - mysql_free_result( result ); } // end if has SERVER_NAME } else if ( staticConfig.SERVER_NAME.empty() ) { diff --git a/src/zm_db.cpp b/src/zm_db.cpp index 0065488f5..a342ca14b 100644 --- a/src/zm_db.cpp +++ b/src/zm_db.cpp @@ -95,7 +95,7 @@ MYSQL_RES * zmDbFetch( const char * query ) { return result; } // end MYSQL_RES * zmDbFetch( const char * query ); -MYSQL_ROW zmDBFetchOne( const char *query ) { +MYSQL_ROW zmDbFetchOne( const char *query ) { MYSQL_RES *result = zmDbFetch( query ); int n_rows = mysql_num_rows( result ); if ( n_rows != 1 ) { @@ -104,6 +104,7 @@ MYSQL_ROW zmDBFetchOne( const char *query ) { } MYSQL_ROW dbrow = mysql_fetch_row( result ); + mysql_free_result( result ); if ( ! dbrow ) { Error("Error getting row from query %s. Error is %s", query, mysql_error( &dbconn ) ); return NULL; diff --git a/src/zm_db.h b/src/zm_db.h index de1a81340..6ec1b5e4e 100644 --- a/src/zm_db.h +++ b/src/zm_db.h @@ -33,7 +33,7 @@ void zmDbConnect(); void zmDbClose(); MYSQL_RES * zmDbFetch( const char *query ); -MYSQL_ROW zmDBFetchOne( const char *query ); +MYSQL_ROW zmDbFetchOne( const char *query ); #ifdef __cplusplus } /* extern "C" */ From 633a6e2df9fbdfee6768c53784df441b7191a080 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 16 Jul 2015 16:53:30 -0400 Subject: [PATCH 012/362] use zmDbFetchOne more --- src/zm_config.cpp | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/src/zm_config.cpp b/src/zm_config.cpp index e9c54b943..5521b5a14 100644 --- a/src/zm_config.cpp +++ b/src/zm_config.cpp @@ -115,7 +115,6 @@ void zmLoadConfig() if ( ! staticConfig.SERVER_ID ) { if ( ! staticConfig.SERVER_NAME.empty() ) { - std::string sql = stringtf("SELECT Id FROM Servers WHERE Name='%s'", staticConfig.SERVER_NAME.c_str() ); if ( MYSQL_ROW dbrow = zmDbFetchOne( sql.c_str() ) ) { staticConfig.SERVER_ID = atoi(dbrow[0]); @@ -126,30 +125,12 @@ void zmLoadConfig() } // end if has SERVER_NAME } else if ( staticConfig.SERVER_NAME.empty() ) { std::string sql = stringtf("SELECT Name FROM Servers WHERE Id='%d'", staticConfig.SERVER_ID ); - if ( mysql_query( &dbconn, sql.c_str() ) ) - { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - Fatal("Can't get ServerName for Server ID %d", staticConfig.SERVER_ID ); - } - MYSQL_RES *result = mysql_store_result( &dbconn ); - if ( !result ) - { - Error( "Can't use query result: %s", mysql_error( &dbconn ) ); - Fatal("Can't get ServerName for Server ID %d", staticConfig.SERVER_ID ); - } - int n_rows = mysql_num_rows( result ); - if ( n_rows != 1 ) - { - Error( "Bogus number of lines return from Server lookup, %d, returned. Can't reload", n_rows ); - Fatal("Can't get ServerName for Server ID %d", staticConfig.SERVER_ID ); - } - - if ( MYSQL_ROW dbrow = mysql_fetch_row( result ) ) - { + if ( MYSQL_ROW dbrow = zmDbFetchOne( sql.c_str() ) ) { staticConfig.SERVER_NAME = std::string(dbrow[0]); + } else { + Fatal("Can't get ServerName for Server ID %d", staticConfig.SERVER_ID ); } - mysql_free_result( result ); } } From 441a82e611e73c4e5da899093a0fee1e85772550 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 17 Jul 2015 10:12:44 -0400 Subject: [PATCH 013/362] fixup loading SERVER_ID from SERVER_NAME --- web/includes/config.php.in | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/web/includes/config.php.in b/web/includes/config.php.in index 7fdba34a7..efe9d2bce 100644 --- a/web/includes/config.php.in +++ b/web/includes/config.php.in @@ -167,13 +167,22 @@ function loadConfig( $defineConsts=true ) } // For Human-readability, user ZM_SERVER in zm.conf, and convert it here to a ZM_SERVER_ID -if ( ! defined(ZM_SERVER_ID) and defined(ZM_SERVER) ) { - $server_id = dbFetchOne('SELECT Id FROM Servers WHERE Name=?', 'Id', array(ZM_SERVER_NAME)); - if ( ! $server_id ) { - Error("ZM_SERVER_NAME set in config, but not found in Servers table."); - } else { - define( ZM_SERVER_ID, $server_id ); - } +if ( ! defined('ZM_SERVER_ID') ) { + if ( defined('ZM_SERVER_NAME') ) { + $server_id = dbFetchOne('SELECT Id FROM Servers WHERE Name=?', 'Id', array(ZM_SERVER_NAME)); + if ( ! $server_id ) { + Error("ZM_SERVER_NAME set in config, but not found in Servers table."); + } else { + define( 'ZM_SERVER_ID', $server_id ); + } + } else if ( defined('ZM_SERVER_HOST') ) { + $server_id = dbFetchOne('SELECT Id FROM Servers WHERE Name=?', 'Id', array(ZM_SERVER_HOST)); + if ( ! $server_id ) { + Error("ZM_SERVER_HOST set in config, but not found in Servers table."); + } else { + define( 'ZM_SERVER_ID', $server_id ); + } + } } From dfd3d2c4cde6a2867b4b53983811d9d7d5d424ba Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 20 Jul 2015 16:28:21 -0400 Subject: [PATCH 014/362] use std::string to build sql for loading monitors. ALso use new ZmDbFetch functions --- src/zm_monitor.cpp | 660 ++++++++++++++++++++++----------------------- src/zm_monitor.h | 5 +- 2 files changed, 321 insertions(+), 344 deletions(-) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 906ca68f6..e233b0790 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -263,6 +263,7 @@ bool Monitor::MonitorLink::hasAlarmed() Monitor::Monitor( int p_id, const char *p_name, + const unsigned int p_server_id, int p_function, bool p_enabled, const char *p_linked_monitors, @@ -292,6 +293,7 @@ Monitor::Monitor( int p_n_zones, Zone *p_zones[] ) : id( p_id ), + server_id( p_server_id ), function( (Function)p_function ), enabled( p_enabled ), width( (p_orientation==ROTATE_90||p_orientation==ROTATE_270)?p_camera->Height():p_camera->Width() ), @@ -1860,25 +1862,22 @@ void Monitor::ReloadLinkedMonitors( const char *p_linked_monitors ) #if ZM_HAS_V4L int Monitor::LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose purpose ) { - static char sql[ZM_SQL_MED_BUFSIZ]; - if ( !device[0] ) - { - strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, Method, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Function != 'None' and Type = 'Local' order by Device, Channel", sizeof(sql) ); - } - else - { - snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, Method, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Function != 'None' and Type = 'Local' and Device = '%s' order by Channel", device ); - } - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } + std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, Method, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Function != 'None' and Type = 'Local'"; +; + if ( device[0] ) { + sql += " AND Device='"; + sql += device; + sql += "'"; + } + if ( staticConfig.SERVER_ID ) { + sql += " AND ServerId='"; + sql += staticConfig.SERVER_ID; + sql += "'"; + } - MYSQL_RES *result = mysql_store_result( &dbconn ); - if ( !result ) - { - Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + MYSQL_RES *result = zmDbFetch( sql.c_str() ); + if ( !result ) { + Error( "Can't load local monitors: %s", mysql_error( &dbconn ) ); exit( mysql_errno( &dbconn ) ); } int n_monitors = mysql_num_rows( result ); @@ -1891,6 +1890,7 @@ int Monitor::LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose int id = atoi(dbrow[col]); col++; const char *name = dbrow[col]; col++; + unsigned int server_id = atoi(dbrow[col]); col++; int function = atoi(dbrow[col]); col++; int enabled = atoi(dbrow[col]); col++; const char *linked_monitors = dbrow[col]; col++; @@ -1988,6 +1988,7 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame ); monitors[i] = new Monitor( id, name, + server_id, function, enabled, linked_monitors, @@ -2036,24 +2037,19 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame ); int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const char *port, const char *path, Monitor **&monitors, Purpose purpose ) { - static char sql[ZM_SQL_MED_BUFSIZ]; - if ( !protocol ) - { - strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Remote'", sizeof(sql) ); - } - else - { - snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Remote' and Protocol = '%s' and Host = '%s' and Port = '%s' and Path = '%s'", protocol, host, port, path ); - } - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); + std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Remote'"; + if ( staticConfig.SERVER_ID ) { + sql += " AND ServerId='"; + sql += staticConfig.SERVER_ID; + sql += "'"; } - MYSQL_RES *result = mysql_store_result( &dbconn ); - if ( !result ) - { + if ( protocol ) { + sql += stringtf(" AND Protocol = '%s' and Host = '%s' and Port = '%s' and Path = '%s'", protocol, host, port, path ); + } + + MYSQL_RES *result = zmDbFetch( sql.c_str() ); + if ( !result ) { Error( "Can't use query result: %s", mysql_error( &dbconn ) ); exit( mysql_errno( &dbconn ) ); } @@ -2067,6 +2063,7 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c int id = atoi(dbrow[col]); col++; std::string name = dbrow[col]; col++; + unsigned int server_id = atoi(dbrow[col]); col++; int function = atoi(dbrow[col]); col++; int enabled = atoi(dbrow[col]); col++; const char *linked_monitors = dbrow[col]; col++; @@ -2161,6 +2158,7 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c monitors[i] = new Monitor( id, name.c_str(), + server_id, function, enabled, linked_monitors, @@ -2209,22 +2207,18 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose purpose ) { - static char sql[ZM_SQL_MED_BUFSIZ]; - if ( !file[0] ) - { - strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'File'", sizeof(sql) ); + std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'File'"; + if ( file[0] ) { + sql += " AND Path='"; + sql += file; + sql += "'"; } - else - { - snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'File' and Path = '%s'", file ); + if ( staticConfig.SERVER_ID ) { + sql += " AND ServerId='"; + sql += staticConfig.SERVER_ID; + sql += "'"; } - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - - MYSQL_RES *result = mysql_store_result( &dbconn ); + MYSQL_RES *result = zmDbFetch( sql.c_str() ); if ( !result ) { Error( "Can't use query result: %s", mysql_error( &dbconn ) ); @@ -2240,6 +2234,7 @@ int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose pu int id = atoi(dbrow[col]); col++; const char *name = dbrow[col]; col++; + unsigned int server_id = atoi(dbrow[col]); col++; int function = atoi(dbrow[col]); col++; int enabled = atoi(dbrow[col]); col++; const char *linked_monitors = dbrow[col]; col++; @@ -2298,6 +2293,7 @@ int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose pu monitors[i] = new Monitor( id, name, + server_id, function, enabled, linked_monitors, @@ -2346,27 +2342,23 @@ int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose pu #if HAVE_LIBAVFORMAT int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose purpose ) { - static char sql[ZM_SQL_MED_BUFSIZ]; - if ( !file[0] ) - { - strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Method, Options, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Ffmpeg'", sizeof(sql) ); + std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Path, Method, Options, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Ffmpeg'"; + if ( file[0] ) { + sql += " AND Path = '"; + sql += file; + sql += "'"; } - else - { - snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Method, Options, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Ffmpeg' and Path = '%s'", file ); + if ( staticConfig.SERVER_ID ) { + sql += " AND ServerId='"; + sql += staticConfig.SERVER_ID; + sql += "'"; } - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); + MYSQL_RES *result = zmDbFetch( sql.c_str() ); + if ( ! result ) { + Error( "Cannot load FfmpegMonitors" ); exit( mysql_errno( &dbconn ) ); } - MYSQL_RES *result = mysql_store_result( &dbconn ); - if ( !result ) - { - Error( "Can't use query result: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } int n_monitors = mysql_num_rows( result ); Debug( 1, "Got %d monitors", n_monitors ); delete[] monitors; @@ -2377,6 +2369,7 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose int id = atoi(dbrow[col]); col++; const char *name = dbrow[col]; col++; + unsigned int server_id = atoi(dbrow[col]); col++; int function = atoi(dbrow[col]); col++; int enabled = atoi(dbrow[col]); col++; const char *linked_monitors = dbrow[col]; col++; @@ -2439,6 +2432,7 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose monitors[i] = new Monitor( id, name, + server_id, function, enabled, linked_monitors, @@ -2485,321 +2479,303 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose } #endif // HAVE_LIBAVFORMAT -Monitor *Monitor::Load( int id, bool load_zones, Purpose purpose ) +Monitor *Monitor::Load( unsigned int p_id, bool load_zones, Purpose purpose ) { - static char sql[ZM_SQL_MED_BUFSIZ]; - snprintf( sql, sizeof(sql), "select Id, Name, Type, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, Protocol, Method, Host, Port, Path, Options, User, Pass, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Id = %d", id ); - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } + std::string sql = stringtf( "select Id, Name, ServerId, Type, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, Protocol, Method, Host, Port, Path, Options, User, Pass, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Id = %d", p_id ); - MYSQL_RES *result = mysql_store_result( &dbconn ); - if ( !result ) - { + MYSQL_ROW dbrow = zmDbFetchOne( sql.c_str() ); + if ( ! dbrow ) { Error( "Can't use query result: %s", mysql_error( &dbconn ) ); exit( mysql_errno( &dbconn ) ); } - int n_monitors = mysql_num_rows( result ); - Debug( 1, "Got %d monitors", n_monitors ); Monitor *monitor = 0; - for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) - { - int col = 0; + unsigned int col = 0; - int id = atoi(dbrow[col]); col++; - std::string name = dbrow[col]; col++; - std::string type = dbrow[col]; col++; - int function = atoi(dbrow[col]); col++; - int enabled = atoi(dbrow[col]); col++; - std::string linked_monitors = dbrow[col]; col++; + unsigned int id = atoi(dbrow[col]); col++; + std::string name = dbrow[col]; col++; + unsigned int server_id = atoi(dbrow[col]); col++; + std::string type = dbrow[col]; col++; + int function = atoi(dbrow[col]); col++; + int enabled = atoi(dbrow[col]); col++; + std::string linked_monitors = dbrow[col]; col++; - std::string device = dbrow[col]; col++; - int channel = atoi(dbrow[col]); col++; - int format = atoi(dbrow[col]); col++; + std::string device = dbrow[col]; col++; + int channel = atoi(dbrow[col]); col++; + int format = atoi(dbrow[col]); col++; - bool v4l_multi_buffer; - if ( dbrow[col] ) { - if (*dbrow[col] == '0' ) { - v4l_multi_buffer = false; - } else if ( *dbrow[col] == '1' ) { - v4l_multi_buffer = true; - } - } else { - v4l_multi_buffer = config.v4l_multi_buffer; - } - col++; + bool v4l_multi_buffer; + if ( dbrow[col] ) { + if (*dbrow[col] == '0' ) { + v4l_multi_buffer = false; + } else if ( *dbrow[col] == '1' ) { + v4l_multi_buffer = true; + } + } else { + v4l_multi_buffer = config.v4l_multi_buffer; + } + col++; - int v4l_captures_per_frame = 0; - if ( dbrow[col] ) { - v4l_captures_per_frame = atoi(dbrow[col]); - } else { - v4l_captures_per_frame = config.captures_per_frame; - } + int v4l_captures_per_frame = 0; + if ( dbrow[col] ) { + v4l_captures_per_frame = atoi(dbrow[col]); + } else { + v4l_captures_per_frame = config.captures_per_frame; + } Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame ); - col++; + col++; - std::string protocol = dbrow[col]; col++; - std::string method = dbrow[col]; col++; - std::string host = dbrow[col]; col++; - std::string port = dbrow[col]; col++; - std::string path = dbrow[col]; col++; - std::string options = dbrow[col]; col++; - std::string user = dbrow[col]; col++; - std::string pass = dbrow[col]; col++; + std::string protocol = dbrow[col]; col++; + std::string method = dbrow[col]; col++; + std::string host = dbrow[col]; col++; + std::string port = dbrow[col]; col++; + std::string path = dbrow[col]; col++; + std::string options = dbrow[col]; col++; + std::string user = dbrow[col]; col++; + std::string pass = dbrow[col]; col++; - int width = atoi(dbrow[col]); col++; - int height = atoi(dbrow[col]); col++; - int colours = atoi(dbrow[col]); col++; - int palette = atoi(dbrow[col]); col++; - Orientation orientation = (Orientation)atoi(dbrow[col]); col++; - unsigned int deinterlacing = atoi(dbrow[col]); col++; - int brightness = atoi(dbrow[col]); col++; - int contrast = atoi(dbrow[col]); col++; - int hue = atoi(dbrow[col]); col++; - int colour = atoi(dbrow[col]); col++; + int width = atoi(dbrow[col]); col++; + int height = atoi(dbrow[col]); col++; + int colours = atoi(dbrow[col]); col++; + int palette = atoi(dbrow[col]); col++; + Orientation orientation = (Orientation)atoi(dbrow[col]); col++; + unsigned int deinterlacing = atoi(dbrow[col]); col++; + int brightness = atoi(dbrow[col]); col++; + int contrast = atoi(dbrow[col]); col++; + int hue = atoi(dbrow[col]); col++; + int colour = atoi(dbrow[col]); col++; - std::string event_prefix = dbrow[col]; col++; - std::string label_format = dbrow[col]; col++; + std::string event_prefix = dbrow[col]; col++; + std::string label_format = dbrow[col]; col++; - int label_x = atoi(dbrow[col]); col++; - int label_y = atoi(dbrow[col]); col++; + int label_x = atoi(dbrow[col]); col++; + int label_y = atoi(dbrow[col]); col++; - int image_buffer_count = atoi(dbrow[col]); col++; - int warmup_count = atoi(dbrow[col]); col++; - int pre_event_count = atoi(dbrow[col]); col++; - int post_event_count = atoi(dbrow[col]); col++; - int stream_replay_buffer = atoi(dbrow[col]); col++; - int alarm_frame_count = atoi(dbrow[col]); col++; - int section_length = atoi(dbrow[col]); col++; - int frame_skip = atoi(dbrow[col]); col++; - int motion_frame_skip = atoi(dbrow[col]); col++; - int capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; - int alarm_capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; - int fps_report_interval = atoi(dbrow[col]); col++; - int ref_blend_perc = atoi(dbrow[col]); col++; - int alarm_ref_blend_perc = atoi(dbrow[col]); col++; - int track_motion = atoi(dbrow[col]); col++; + int image_buffer_count = atoi(dbrow[col]); col++; + int warmup_count = atoi(dbrow[col]); col++; + int pre_event_count = atoi(dbrow[col]); col++; + int post_event_count = atoi(dbrow[col]); col++; + int stream_replay_buffer = atoi(dbrow[col]); col++; + int alarm_frame_count = atoi(dbrow[col]); col++; + int section_length = atoi(dbrow[col]); col++; + int frame_skip = atoi(dbrow[col]); col++; + int motion_frame_skip = atoi(dbrow[col]); col++; + int capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; + int alarm_capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; + int fps_report_interval = atoi(dbrow[col]); col++; + int ref_blend_perc = atoi(dbrow[col]); col++; + int alarm_ref_blend_perc = atoi(dbrow[col]); col++; + int track_motion = atoi(dbrow[col]); col++; - int signal_check_colour; - if ( dbrow[col][0] == '#' ) - signal_check_colour = strtol(dbrow[col]+1,0,16); - else - signal_check_colour = strtol(dbrow[col],0,16); + int signal_check_colour; + if ( dbrow[col][0] == '#' ) + signal_check_colour = strtol(dbrow[col]+1,0,16); + else + signal_check_colour = strtol(dbrow[col],0,16); - int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); - int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); + int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); + int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); - int extras = (deinterlacing>>24)&0xff; + int extras = (deinterlacing>>24)&0xff; - Camera *camera = 0; - if ( type == "Local" ) - { + Camera *camera = 0; + if ( type == "Local" ) + { #if ZM_HAS_V4L - camera = new LocalCamera( - id, - device.c_str(), - channel, - format, - v4l_multi_buffer, - v4l_captures_per_frame, - method, - cam_width, - cam_height, - colours, - palette, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE, - extras - ); + camera = new LocalCamera( + id, + device.c_str(), + channel, + format, + v4l_multi_buffer, + v4l_captures_per_frame, + method, + cam_width, + cam_height, + colours, + palette, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE, + extras + ); #else // ZM_HAS_V4L - Fatal( "You must have video4linux libraries and headers installed to use local analog or USB cameras for monitor %d", id ); + Fatal( "You must have video4linux libraries and headers installed to use local analog or USB cameras for monitor %d", id ); #endif // ZM_HAS_V4L - } - else if ( type == "Remote" ) - { - if ( protocol == "http" ) - { - camera = new RemoteCameraHttp( - id, - method.c_str(), - host.c_str(), - port.c_str(), - path.c_str(), - cam_width, - cam_height, - colours, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE - ); - } - else if ( protocol == "rtsp" ) - { + } + else if ( type == "Remote" ) + { + if ( protocol == "http" ) + { + camera = new RemoteCameraHttp( + id, + method.c_str(), + host.c_str(), + port.c_str(), + path.c_str(), + cam_width, + cam_height, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE + ); + } + else if ( protocol == "rtsp" ) + { #if HAVE_LIBAVFORMAT - camera = new RemoteCameraRtsp( - id, - method.c_str(), - host.c_str(), - port.c_str(), - path.c_str(), - cam_width, - cam_height, - colours, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE - ); + camera = new RemoteCameraRtsp( + id, + method.c_str(), + host.c_str(), + port.c_str(), + path.c_str(), + cam_width, + cam_height, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE + ); #else // HAVE_LIBAVFORMAT - Fatal( "You must have ffmpeg libraries installed to use remote camera protocol '%s' for monitor %d", protocol.c_str(), id ); + Fatal( "You must have ffmpeg libraries installed to use remote camera protocol '%s' for monitor %d", protocol.c_str(), id ); #endif // HAVE_LIBAVFORMAT - } - else - { - Fatal( "Unexpected remote camera protocol '%s' for monitor %d", protocol.c_str(), id ); - } - } - else if ( type == "File" ) - { - camera = new FileCamera( - id, - path.c_str(), - cam_width, - cam_height, - colours, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE - ); - } - else if ( type == "Ffmpeg" ) - { + } + else + { + Fatal( "Unexpected remote camera protocol '%s' for monitor %d", protocol.c_str(), id ); + } + } + else if ( type == "File" ) + { + camera = new FileCamera( + id, + path.c_str(), + cam_width, + cam_height, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE + ); + } + else if ( type == "Ffmpeg" ) + { #if HAVE_LIBAVFORMAT - camera = new FfmpegCamera( - id, - path.c_str(), - method, - options, - cam_width, - cam_height, - colours, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE - ); + camera = new FfmpegCamera( + id, + path.c_str(), + method, + options, + cam_width, + cam_height, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE + ); #else // HAVE_LIBAVFORMAT - Fatal( "You must have ffmpeg libraries installed to use ffmpeg cameras for monitor %d", id ); + Fatal( "You must have ffmpeg libraries installed to use ffmpeg cameras for monitor %d", id ); #endif // HAVE_LIBAVFORMAT - } - else if (type == "Libvlc") - { + } + else if (type == "Libvlc") + { #if HAVE_LIBVLC - camera = new LibvlcCamera( - id, - path.c_str(), - method, - options, - cam_width, - cam_height, - colours, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE - ); + camera = new LibvlcCamera( + id, + path.c_str(), + method, + options, + cam_width, + cam_height, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE + ); #else // HAVE_LIBVLC - Fatal( "You must have vlc libraries installed to use vlc cameras for monitor %d", id ); + Fatal( "You must have vlc libraries installed to use vlc cameras for monitor %d", id ); #endif // HAVE_LIBVLC - } - else if ( type == "cURL" ) - { + } + else if ( type == "cURL" ) + { #if HAVE_LIBCURL - camera = new cURLCamera( - id, - path.c_str(), - user.c_str(), - pass.c_str(), - cam_width, - cam_height, - colours, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE - ); + camera = new cURLCamera( + id, + path.c_str(), + user.c_str(), + pass.c_str(), + cam_width, + cam_height, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE + ); #else // HAVE_LIBCURL - Fatal( "You must have libcurl installed to use ffmpeg cameras for monitor %d", id ); + Fatal( "You must have libcurl installed to use ffmpeg cameras for monitor %d", id ); #endif // HAVE_LIBCURL - } - else - { - Fatal( "Bogus monitor type '%s' for monitor %d", type.c_str(), id ); - } - monitor = new Monitor( - id, - name.c_str(), - function, - enabled, - linked_monitors.c_str(), - camera, - orientation, - deinterlacing, - event_prefix.c_str(), - label_format.c_str(), - Coord( label_x, label_y ), - image_buffer_count, - warmup_count, - pre_event_count, - post_event_count, - stream_replay_buffer, - alarm_frame_count, - section_length, - frame_skip, - motion_frame_skip, - capture_delay, - alarm_capture_delay, - fps_report_interval, - ref_blend_perc, - alarm_ref_blend_perc, - track_motion, - signal_check_colour, - purpose, - 0, - 0 + } + else + { + Fatal( "Bogus monitor type '%s' for monitor %d", type.c_str(), id ); + } + monitor = new Monitor( + id, + name.c_str(), + server_id, + function, + enabled, + linked_monitors.c_str(), + camera, + orientation, + deinterlacing, + event_prefix.c_str(), + label_format.c_str(), + Coord( label_x, label_y ), + image_buffer_count, + warmup_count, + pre_event_count, + post_event_count, + stream_replay_buffer, + alarm_frame_count, + section_length, + frame_skip, + motion_frame_skip, + capture_delay, + alarm_capture_delay, + fps_report_interval, + ref_blend_perc, + alarm_ref_blend_perc, + track_motion, + signal_check_colour, + purpose, + 0, + 0 - ); - - int n_zones = 0; - if ( load_zones ) - { - Zone **zones = 0; - n_zones = Zone::Load( monitor, zones ); - monitor->AddZones( n_zones, zones ); - } - Debug( 1, "Loaded monitor %d(%s), %d zones", id, name.c_str(), n_zones ); - } - if ( mysql_errno( &dbconn ) ) - { - Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - // Yadda yadda - mysql_free_result( result ); + ); + int n_zones = 0; + if ( load_zones ) + { + Zone **zones = 0; + n_zones = Zone::Load( monitor, zones ); + monitor->AddZones( n_zones, zones ); + } + Debug( 1, "Loaded monitor %d(%s), %d zones", id, name.c_str(), n_zones ); return( monitor ); } diff --git a/src/zm_monitor.h b/src/zm_monitor.h index b8326a1c4..8cf5ece36 100644 --- a/src/zm_monitor.h +++ b/src/zm_monitor.h @@ -211,6 +211,7 @@ protected: // These are read from the DB and thereafter remain unchanged unsigned int id; char name[64]; + unsigned int server_id; Function function; // What the monitor is doing bool enabled; // Whether the monitor is enabled or asleep unsigned int width; // Normally the same as the camera, but not if partly rotated @@ -298,7 +299,7 @@ protected: public: // OurCheckAlarms seems to be unused. Check it on zm_monitor.cpp for more info. //bool OurCheckAlarms( Zone *zone, const Image *pImage ); - Monitor( int p_id, const char *p_name, int p_function, bool p_enabled, const char *p_linked_monitors, Camera *p_camera, int p_orientation, unsigned int p_deinterlacing, const char *p_event_prefix, const char *p_label_format, const Coord &p_label_coord, int p_image_buffer_count, int p_warmup_count, int p_pre_event_count, int p_post_event_count, int p_stream_replay_buffer, int p_alarm_frame_count, int p_section_length, int p_frame_skip, int p_motion_frame_skip, int p_capture_delay, int p_alarm_capture_delay, int p_fps_report_interval, int p_ref_blend_perc, int p_alarm_ref_blend_perc, bool p_track_motion, Rgb p_signal_check_colour, Purpose p_purpose, int p_n_zones=0, Zone *p_zones[]=0 ); + Monitor( int p_id, const char *p_name, unsigned int p_server_id, int p_function, bool p_enabled, const char *p_linked_monitors, Camera *p_camera, int p_orientation, unsigned int p_deinterlacing, const char *p_event_prefix, const char *p_label_format, const Coord &p_label_coord, int p_image_buffer_count, int p_warmup_count, int p_pre_event_count, int p_post_event_count, int p_stream_replay_buffer, int p_alarm_frame_count, int p_section_length, int p_frame_skip, int p_motion_frame_skip, int p_capture_delay, int p_alarm_capture_delay, int p_fps_report_interval, int p_ref_blend_perc, int p_alarm_ref_blend_perc, bool p_track_motion, Rgb p_signal_check_colour, Purpose p_purpose, int p_n_zones=0, Zone *p_zones[]=0 ); ~Monitor(); void AddZones( int p_n_zones, Zone *p_zones[] ); @@ -413,7 +414,7 @@ public: #if HAVE_LIBAVFORMAT static int LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose purpose ); #endif // HAVE_LIBAVFORMAT - static Monitor *Load( int id, bool load_zones, Purpose purpose ); + static Monitor *Load( unsigned int id, bool load_zones, Purpose purpose ); //void writeStreamImage( Image *image, struct timeval *timestamp, int scale, int mag, int x, int y ); //void StreamImages( int scale=100, int maxfps=10, time_t ttl=0, int msq_id=0 ); //void StreamImagesRaw( int scale=100, int maxfps=10, time_t ttl=0 ); From 84ed491765a89ff7de47e993f33a9d5a2dff455c Mon Sep 17 00:00:00 2001 From: Linwood-F Date: Wed, 22 Jul 2015 13:51:31 -0400 Subject: [PATCH 015/362] Initial Montage Review for people to take a look at --- web/skins/classic/views/console.php | 6 +- web/skins/classic/views/montagereview.php | 688 ++++++++++++++++++++++ 2 files changed, 693 insertions(+), 1 deletion(-) create mode 100644 web/skins/classic/views/montagereview.php diff --git a/web/skins/classic/views/console.php b/web/skins/classic/views/console.php index 5930ebe95..f7724d6e7 100644 --- a/web/skins/classic/views/console.php +++ b/web/skins/classic/views/console.php @@ -210,7 +210,11 @@ if ( canView( 'Stream' ) && $cycleCount > 1 ) { $cycleGroup = isset($_COOKIE['zmGroup'])?$_COOKIE['zmGroup']:0; ?> -
 / 
+
+  /  +  /  + +
0 "; + +// This program only calls itself with the time range involved -- it does all monitors (the user can see) all the time + +if ( !empty($user['MonitorIds']) ) +{ + $monFilterSql = ' AND M.Id IN ('.$user['MonitorIds'].')'; + + $eventsSql .= $monFilterSql; + $monitorsSQL .= $monFilterSql; + $frameSql .= $monFilterSql; +} + +// Parse input parameters -- note for future, validate/clean up better in case we don't get called from self. + +if ( isset($_REQUEST['minTime']) ) + $minTime = validHtmlStr($_REQUEST['minTime']); + +if ( isset($_REQUEST['maxTime']) ) + $maxTime = validHtmlStr($_REQUEST['maxTime']); + +if ( isset($_REQUEST['scale']) ) + $defaultScale=validHtmlStr($_REQUEST['scale']); +else + $defaultScale=0.3; + +if (isset($_REQUEST['speed']) ) + $defaultSpeed=validHtmlStr($_REQUEST['speed']); +else + $defaultSpeed=1; + +if (isset($_REQUEST['current']) ) + $defaultCurrentTime=validHtmlStr($_REQUEST['current']); + +$archive=1; +if (isset($_REQUEST['archive']) ) + $archive=validHtmlStr($_REQUEST['archive']); + +if ($archive==0) +{ + $eventsSql .= " and E.Archived=0 "; +} $frameSql .= " and E.Archived=0 "; + +$eventsSql .= "group by E.Id,E.Name,E.StartTime,E.Length,E.Frames,E.MaxScore,E.Cause,E.Notes,E.Archived,E.MonitorId "; + +if( isset($minTime) && isset($maxTime) ) +{ + $eventsSql .= "having CalcEndTime > '" . $minTime . "' and StartTime < '" . $maxTime . "'"; + $frameSql .= " + and TimeStamp > '" . $minTime . "' and TimeStamp < '" . $maxTime . "'"; +} +$frameSql .= "group by E.Id, E.MonitorId, F.TimeStamp order by E.MonitorId, F.TimeStamp asc"; + +xhtmlHeaders(__FILE__, translate('montagereview') ); +?> + + + +
+ + +
+ + step=0.10 width=20% onchange='changescale(this.value)'/> + x +
+
+ + step=1 wdth=20% onchange='changespeed(this.value)'/> + x +
+
+ + + + + + + +
+ +
+ + + + +
+ + +\n"; +echo "var eventMonitorId = [];\n"; +echo "var eventId = [];\n"; +echo "var eventStartTimeSecs = [];\n"; +echo "var eventEndTimeSecs = [];\n"; +echo "var eventPath = [];\n"; +echo "var eventFrames = [];\n"; // this is going to presume all frames equal durationlength + +// Because we might not have time as the criteria, figure out the min/max time when we run the query + +$minTimeSecs = strtotime("2036-01-01 01:01:01"); +$maxTimeSecs = strtotime("1950-01-01 01:01:01"); + +$index=0; +$anyAlarms=false; +$eventsMonitorsFound = array(); // this will just flag which ones found + +foreach( dbFetchAll( $eventsSql ) as $event ) +{ + if( $minTimeSecs > strtotime($event['StartTime'])) $minTimeSecs=strtotime($event['StartTime']); + if( $maxTimeSecs < strtotime($event['CalcEndTime'])) $maxTimeSecs=strtotime($event['CalcEndTime']); + echo "eventMonitorId[$index]=" . $event['MonitorId'] . "; eventId[$index]=" . $event['Id'] . "; "; + echo "eventStartTimeSecs[$index]=" . strtotime($event['StartTime']) . "; eventEndTimeSecs[$index]=" . strtotime($event['CalcEndTime']) . "; "; + echo "eventFrames[$index]=" . $event['Frames'] . "; "; + + if ( ZM_USE_DEEP_STORAGE ) + echo "eventPath[$index] = \"events/" . $event['MonitorId'] . "/" . strftime("%y/%m/%d/%H/%M/%S", strtotime($event['StartTime'])) . "/\";" ; + else + echo "eventPath[$index] = \"events/" . $event['MonitorId'] . "/" . $event['Id'] . "/\";" ; + $eventsMonitorsFound[$event['MonitorId']] = true; + $index=$index+1; + if($event['MaxScore']>0) + $anyAlarms=true; + echo "\n"; +} + +if($index == 0) // if there is no data set the min/max to the passed in values +{ + if(isset($minTime) && isset($maxTime)) + { + $minTimeSecs = strtotime($minTime); + $maxTimeSecs = strtotime($maxTime); + } + else // this is the case of no passed in times AND no data -- just set something arbitrary + { + $minTimeSecs=strtotime('1950-06-01 01:01:01'); // random time so there's something to display + $maxTimeSecs=strtotime('2020-06-02 02:02:02'); + } +} + +// We only reset the calling time if there was no calling time +if(!isset($minTime) || !isset($maxTime)) +{ + $maxTime = strftime($maxTimeSecs); + $minTime = strftime($minTimeSecs); +} +else +{ + $minTimeSecs = strtotime($minTime); + $maxTimeSecs = strtotime($maxTime); +} + +// If we had any alarms in those events, this builds the list of all alarm frames (thought for later - should these be ranges, so as to minimize list if very long?) + +echo "var frameMonitorId = [];\n"; +echo "var frameTimeStampSecs = [];\n"; +echo "var frameScore = [];\n"; +$maxScore=0; +$index=0; + +if($anyAlarms) + foreach( dbFetchAll ($frameSql) as $frame ) + { + echo " frameMonitorId[$index]=" . $frame['MonitorId'] . ";"; + echo " frameTimeStampSecs[$index]=" . strtotime($frame['TimeStamp']) . ";"; + echo " frameScore[$index]=" . $frame['Score'] . ";\n"; + if($maxScore <= $frame['Score']) + $maxScore=$frame['Score']; + $index += 1; + } + +// This is where we have to display the canvases -- AFTER determining which monitors we use (above in events) and BEFORE we loop through them to cache the objects +// This splits up the javascript and html a bit, but it's a lot simpler than trying in php to cache one while completing the other + +// Monitor images - these had to be loaded after the monitors used were determined (after loading events) + +echo "\n"; + +foreach ($monitors as $m) +{ + if(!empty($eventsMonitorsFound[$m['Id']])) // only save the monitor if it's part of these events + { + echo "No Canvas Support!!\n"; + } +} +echo " + +
+ + + + From b88403cd416cbbd20dbee93efc3f763baa96841c Mon Sep 17 00:00:00 2001 From: Linwood-F Date: Thu, 23 Jul 2015 15:01:53 -0400 Subject: [PATCH 016/362] Minor corrections based on feedback to date --- src/zm_event.cpp | 56 ++++++++++----- src/zm_event.h | 6 ++ src/zm_image.cpp | 42 ++++++++++- src/zm_image.h | 7 +- web/api/app/Config/core.php | 4 +- web/graphics/NoDataImage.gif | Bin 0 -> 7002 bytes web/skins/classic/views/montagereview.php | 81 +++++++++++++++------- 7 files changed, 149 insertions(+), 47 deletions(-) create mode 100644 web/graphics/NoDataImage.gif diff --git a/src/zm_event.cpp b/src/zm_event.cpp index 3e723fa48..b173d9e0c 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -67,6 +67,14 @@ Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string if ( !initialised ) Initialise(); +// >>> Real time image extrat settings <<< these need to go in conf options + + UpldCount=0; + strcpy(UpldPath,"/home/ferguson/ToUpload"); + UpldWriteEvery=600; + UpldWriteEveryAlarm=2; + + std::string notes; createNotes( notes ); @@ -349,28 +357,42 @@ bool Event::SendFrameImage( const Image *image, bool alarm_frame ) bool Event::WriteFrameImage( Image *image, struct timeval timestamp, const char *event_file, bool alarm_frame ) { - if ( config.timestamp_on_capture ) + bool toUpld=false; + char UpldFile[PATH_MAX]; + char UpldFileRename[PATH_MAX]; + if( ( UpldCount++ % (alarm_frame ? UpldWriteEveryAlarm : UpldWriteEvery) ) == 0) // notice this grabs frame #1 so it gets the first of every event (zero count = frame 1) { - if ( !config.opt_frame_server || !SendFrameImage( image, alarm_frame) ) - { - if ( alarm_frame && (config.jpeg_alarm_file_quality > config.jpeg_file_quality) ) - image->WriteJpeg( event_file, config.jpeg_alarm_file_quality ); - else - image->WriteJpeg( event_file ); - } + toUpld=true; + char tmbuf[64], buf[64]; + strftime(tmbuf, sizeof tmbuf, "%Y-%m-%d-%H-%M-%S", localtime(&(timestamp.tv_sec))); + snprintf(buf, sizeof buf, "%s-%06d", tmbuf,(int)(timestamp.tv_usec)); + snprintf(UpldFile, sizeof(UpldFile),"%s/%s-%06d_%s_%s.jpg_saving",UpldPath, tmbuf,(int)(timestamp.tv_usec),this->monitor->Name(),alarm_frame?"Alarm":"Periodic"); + snprintf(UpldFileRename, sizeof(UpldFile),"%s/%s-%06d_%s_%s.jpg", UpldPath, tmbuf,(int)(timestamp.tv_usec),this->monitor->Name(),alarm_frame?"Alarm":"Periodic"); + } + + Image* ImgToWrite; + Image ts_image( *image ); + + if ( config.timestamp_on_capture ) // stash the image we plan to use in another pointer regardless if timestamped. + { + monitor->TimestampImage( &ts_image, ×tamp ); + ImgToWrite=&ts_image; } else + ImgToWrite=image; + + if ( !config.opt_frame_server || !SendFrameImage( ImgToWrite, alarm_frame) ) { - Image ts_image( *image ); - monitor->TimestampImage( &ts_image, ×tamp ); - if ( !config.opt_frame_server || !SendFrameImage( &ts_image, alarm_frame) ) - { - if ( alarm_frame && (config.jpeg_alarm_file_quality > config.jpeg_file_quality) ) - ts_image.WriteJpeg( event_file, config.jpeg_alarm_file_quality ); - else - ts_image.WriteJpeg( event_file ); + int thisquality = ( alarm_frame && (config.jpeg_alarm_file_quality > config.jpeg_file_quality) ) ? config.jpeg_alarm_file_quality : 0 ; // quality to use + ImgToWrite->WriteJpeg( event_file, thisquality, timestamp ); + if(toUpld) + { // Because these are for real-time use and may be grabbed as they are being written, write under one name then rename + ImgToWrite->WriteJpeg(UpldFile, thisquality, timestamp); + if(rename(UpldFile, UpldFileRename)!=0) + Error ("Failure to rename real time capture file %s to %s, ignored",UpldFile, UpldFileRename); } } + return( true ); } @@ -885,7 +907,7 @@ void EventStream::processCommand( const CmdMsg *msg ) } // If we are in single event mode and at the last frame, replay the current event - if ( (mode == MODE_SINGLE) && (curr_frame_id == event_data->frame_count) ) + if ( (mode == MODE_SINGLE) && ((unsigned int)curr_frame_id == event_data->frame_count) ) curr_frame_id = 1; replay_rate = ZM_RATE_BASE; diff --git a/src/zm_event.h b/src/zm_event.h index f50a5bf06..412baa0bb 100644 --- a/src/zm_event.h +++ b/src/zm_event.h @@ -59,6 +59,12 @@ protected: protected: static int sd; +private: + int UpldCount; + char UpldPath[PATH_MAX]; + int UpldWriteEvery; + int UpldWriteEveryAlarm; + public: typedef std::set StringSet; typedef std::map StringSetMap; diff --git a/src/zm_image.cpp b/src/zm_image.cpp index 8f91ab28b..c1e91a00d 100644 --- a/src/zm_image.cpp +++ b/src/zm_image.cpp @@ -787,7 +787,22 @@ bool Image::ReadJpeg( const char *filename, unsigned int p_colours, unsigned int return( true ); } -bool Image::WriteJpeg( const char *filename, int quality_override ) const +// Multiple calling formats to permit inclusion (or not) of both quality_override and timestamp (exif), with suitable defaults. + +bool Image::WriteJpeg( const char *filename, int quality_override) const +{ + return Image::WriteJpeg(filename, quality_override, (timeval){0,0}); +} +bool Image::WriteJpeg( const char *filename) const +{ + return Image::WriteJpeg(filename, 0, (timeval){0,0}); +} +bool Image::WriteJpeg( const char *filename, struct timeval timestamp ) const +{ + return Image::WriteJpeg(filename,0,timestamp); +} + +bool Image::WriteJpeg( const char *filename, int quality_override, struct timeval timestamp ) const { if ( config.colour_jpeg_files && colours == ZM_COLOUR_GRAY8 ) { @@ -795,7 +810,6 @@ bool Image::WriteJpeg( const char *filename, int quality_override ) const temp_image.Colourise( ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB ); return( temp_image.WriteJpeg( filename, quality_override ) ); } - int quality = quality_override?quality_override:config.jpeg_file_quality; struct jpeg_compress_struct *cinfo = jpg_ccinfo[quality]; @@ -887,6 +901,30 @@ bool Image::WriteJpeg( const char *filename, int quality_override ) const jpeg_write_marker( cinfo, JPEG_COM, (const JOCTET *)text, strlen(text) ); } + if(timestamp.tv_sec) + { + #define EXIFTIMES_MS_OFFSET 0x36 // three decimal digits for milliseconds + #define EXIFTIMES_MS_LEN 0x03 + #define EXIFTIMES_OFFSET 0x3E // 19 characters format '2015:07:21 13:14:45' not including quotes + #define EXIFTIMES_LEN 0x13 // = 19 + #define EXIF_CODE 0xE1 + + char timebuf[64], msbuf[64]; + strftime(timebuf, sizeof timebuf, "%Y:%m:%d %H:%M:%S", localtime(&(timestamp.tv_sec))); + snprintf(msbuf, sizeof msbuf, "%06d",(int)(timestamp.tv_usec)); // we only use milliseconds because that's all defined in exif, but this is the whole microseconds because we have it + unsigned char exiftimes[82] = { + 0x45, 0x78, 0x69, 0x66, 0x00, 0x00, 0x49, 0x49, 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x69, 0x87, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x03, 0x90, 0x02, 0x00, 0x14, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x91, 0x92, + 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00 }; + memcpy(&exiftimes[EXIFTIMES_OFFSET], timebuf,EXIFTIMES_LEN); + memcpy(&exiftimes[EXIFTIMES_MS_OFFSET],msbuf ,EXIFTIMES_MS_LEN); // first character after the decimal point + jpeg_write_marker (cinfo, EXIF_CODE, (const JOCTET *)exiftimes, sizeof(exiftimes) ); + + } + JSAMPROW row_pointer; /* pointer to a single row */ int row_stride = cinfo->image_width * colours; /* physical row width in buffer */ while ( cinfo->next_scanline < cinfo->image_height ) diff --git a/src/zm_image.h b/src/zm_image.h index 46c7a031b..a48fafacc 100644 --- a/src/zm_image.h +++ b/src/zm_image.h @@ -204,7 +204,12 @@ public: bool WriteRaw( const char *filename ) const; bool ReadJpeg( const char *filename, unsigned int p_colours, unsigned int p_subpixelorder); - bool WriteJpeg( const char *filename, int quality_override=0 ) const; + + bool WriteJpeg ( const char *filename) const; + bool WriteJpeg ( const char *filename, int quality_override ) const; + bool WriteJpeg ( const char *filename, struct timeval timestamp ) const; + bool WriteJpeg ( const char *filename, int quality_override, struct timeval timestamp ) const; + bool DecodeJpeg( const JOCTET *inbuffer, int inbuffer_size, unsigned int p_colours, unsigned int p_subpixelorder); bool EncodeJpeg( JOCTET *outbuffer, int *outbuffer_size, int quality_override=0 ) const; diff --git a/web/api/app/Config/core.php b/web/api/app/Config/core.php index 436cf8d60..59d72162c 100644 --- a/web/api/app/Config/core.php +++ b/web/api/app/Config/core.php @@ -222,12 +222,12 @@ /** * A random string used in security hashing methods. */ - Configure::write('Security.salt', 'Q0MjGG2xRQEhJVQR85WhFJKI7f2St8RYMlVR7GNQ'); + Configure::write('Security.salt', 'olX2TOlboOnC474y3Tk4W4JOyuirw1EaadeHCcr4'); /** * A random numeric string (digits only) used to encrypt/decrypt strings. */ - Configure::write('Security.cipherSeed', '02670120062639232092038865362'); + Configure::write('Security.cipherSeed', '84684583012508019120061282965'); /** * Apply timestamps with the last modified time to static assets (js, css, images). diff --git a/web/graphics/NoDataImage.gif b/web/graphics/NoDataImage.gif new file mode 100644 index 0000000000000000000000000000000000000000..ff97eb1a96f13e5caaba7a7707bea402a1be4e5a GIT binary patch literal 7002 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 sJRu5GsKOPpu!SysAq-
- + step=0.10 width=20% onchange='changescale(this.value)'/> x
- + step=1 wdth=20% onchange='changespeed(this.value)'/> x
- - - - - - - + + + + + + +
@@ -166,6 +186,7 @@ foreach( dbFetchAll( $monitorsSql ) as $row ) // This builds the list of events that are eligible from this range echo " From 3544fbd0a8ed6b7c14ed2e214aa15262674fcaf0 Mon Sep 17 00:00:00 2001 From: Linwood-F Date: Thu, 23 Jul 2015 15:15:57 -0400 Subject: [PATCH 017/362] Remove unexpected files that were added --- src/zm_event.cpp | 62 ++++++++++++++++-------------------------------- src/zm_event.h | 6 ----- src/zm_image.cpp | 42 ++------------------------------ src/zm_image.h | 7 +----- 4 files changed, 23 insertions(+), 94 deletions(-) diff --git a/src/zm_event.cpp b/src/zm_event.cpp index b173d9e0c..3e723fa48 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -67,14 +67,6 @@ Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string if ( !initialised ) Initialise(); -// >>> Real time image extrat settings <<< these need to go in conf options - - UpldCount=0; - strcpy(UpldPath,"/home/ferguson/ToUpload"); - UpldWriteEvery=600; - UpldWriteEveryAlarm=2; - - std::string notes; createNotes( notes ); @@ -357,42 +349,28 @@ bool Event::SendFrameImage( const Image *image, bool alarm_frame ) bool Event::WriteFrameImage( Image *image, struct timeval timestamp, const char *event_file, bool alarm_frame ) { - bool toUpld=false; - char UpldFile[PATH_MAX]; - char UpldFileRename[PATH_MAX]; - if( ( UpldCount++ % (alarm_frame ? UpldWriteEveryAlarm : UpldWriteEvery) ) == 0) // notice this grabs frame #1 so it gets the first of every event (zero count = frame 1) + if ( config.timestamp_on_capture ) { - toUpld=true; - char tmbuf[64], buf[64]; - strftime(tmbuf, sizeof tmbuf, "%Y-%m-%d-%H-%M-%S", localtime(&(timestamp.tv_sec))); - snprintf(buf, sizeof buf, "%s-%06d", tmbuf,(int)(timestamp.tv_usec)); - snprintf(UpldFile, sizeof(UpldFile),"%s/%s-%06d_%s_%s.jpg_saving",UpldPath, tmbuf,(int)(timestamp.tv_usec),this->monitor->Name(),alarm_frame?"Alarm":"Periodic"); - snprintf(UpldFileRename, sizeof(UpldFile),"%s/%s-%06d_%s_%s.jpg", UpldPath, tmbuf,(int)(timestamp.tv_usec),this->monitor->Name(),alarm_frame?"Alarm":"Periodic"); - } - - Image* ImgToWrite; - Image ts_image( *image ); - - if ( config.timestamp_on_capture ) // stash the image we plan to use in another pointer regardless if timestamped. - { - monitor->TimestampImage( &ts_image, ×tamp ); - ImgToWrite=&ts_image; - } - else - ImgToWrite=image; - - if ( !config.opt_frame_server || !SendFrameImage( ImgToWrite, alarm_frame) ) - { - int thisquality = ( alarm_frame && (config.jpeg_alarm_file_quality > config.jpeg_file_quality) ) ? config.jpeg_alarm_file_quality : 0 ; // quality to use - ImgToWrite->WriteJpeg( event_file, thisquality, timestamp ); - if(toUpld) - { // Because these are for real-time use and may be grabbed as they are being written, write under one name then rename - ImgToWrite->WriteJpeg(UpldFile, thisquality, timestamp); - if(rename(UpldFile, UpldFileRename)!=0) - Error ("Failure to rename real time capture file %s to %s, ignored",UpldFile, UpldFileRename); + if ( !config.opt_frame_server || !SendFrameImage( image, alarm_frame) ) + { + if ( alarm_frame && (config.jpeg_alarm_file_quality > config.jpeg_file_quality) ) + image->WriteJpeg( event_file, config.jpeg_alarm_file_quality ); + else + image->WriteJpeg( event_file ); + } + } + else + { + Image ts_image( *image ); + monitor->TimestampImage( &ts_image, ×tamp ); + if ( !config.opt_frame_server || !SendFrameImage( &ts_image, alarm_frame) ) + { + if ( alarm_frame && (config.jpeg_alarm_file_quality > config.jpeg_file_quality) ) + ts_image.WriteJpeg( event_file, config.jpeg_alarm_file_quality ); + else + ts_image.WriteJpeg( event_file ); } } - return( true ); } @@ -907,7 +885,7 @@ void EventStream::processCommand( const CmdMsg *msg ) } // If we are in single event mode and at the last frame, replay the current event - if ( (mode == MODE_SINGLE) && ((unsigned int)curr_frame_id == event_data->frame_count) ) + if ( (mode == MODE_SINGLE) && (curr_frame_id == event_data->frame_count) ) curr_frame_id = 1; replay_rate = ZM_RATE_BASE; diff --git a/src/zm_event.h b/src/zm_event.h index 412baa0bb..f50a5bf06 100644 --- a/src/zm_event.h +++ b/src/zm_event.h @@ -59,12 +59,6 @@ protected: protected: static int sd; -private: - int UpldCount; - char UpldPath[PATH_MAX]; - int UpldWriteEvery; - int UpldWriteEveryAlarm; - public: typedef std::set StringSet; typedef std::map StringSetMap; diff --git a/src/zm_image.cpp b/src/zm_image.cpp index c1e91a00d..8f91ab28b 100644 --- a/src/zm_image.cpp +++ b/src/zm_image.cpp @@ -787,22 +787,7 @@ bool Image::ReadJpeg( const char *filename, unsigned int p_colours, unsigned int return( true ); } -// Multiple calling formats to permit inclusion (or not) of both quality_override and timestamp (exif), with suitable defaults. - -bool Image::WriteJpeg( const char *filename, int quality_override) const -{ - return Image::WriteJpeg(filename, quality_override, (timeval){0,0}); -} -bool Image::WriteJpeg( const char *filename) const -{ - return Image::WriteJpeg(filename, 0, (timeval){0,0}); -} -bool Image::WriteJpeg( const char *filename, struct timeval timestamp ) const -{ - return Image::WriteJpeg(filename,0,timestamp); -} - -bool Image::WriteJpeg( const char *filename, int quality_override, struct timeval timestamp ) const +bool Image::WriteJpeg( const char *filename, int quality_override ) const { if ( config.colour_jpeg_files && colours == ZM_COLOUR_GRAY8 ) { @@ -810,6 +795,7 @@ bool Image::WriteJpeg( const char *filename, int quality_override, struct timeva temp_image.Colourise( ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB ); return( temp_image.WriteJpeg( filename, quality_override ) ); } + int quality = quality_override?quality_override:config.jpeg_file_quality; struct jpeg_compress_struct *cinfo = jpg_ccinfo[quality]; @@ -901,30 +887,6 @@ bool Image::WriteJpeg( const char *filename, int quality_override, struct timeva jpeg_write_marker( cinfo, JPEG_COM, (const JOCTET *)text, strlen(text) ); } - if(timestamp.tv_sec) - { - #define EXIFTIMES_MS_OFFSET 0x36 // three decimal digits for milliseconds - #define EXIFTIMES_MS_LEN 0x03 - #define EXIFTIMES_OFFSET 0x3E // 19 characters format '2015:07:21 13:14:45' not including quotes - #define EXIFTIMES_LEN 0x13 // = 19 - #define EXIF_CODE 0xE1 - - char timebuf[64], msbuf[64]; - strftime(timebuf, sizeof timebuf, "%Y:%m:%d %H:%M:%S", localtime(&(timestamp.tv_sec))); - snprintf(msbuf, sizeof msbuf, "%06d",(int)(timestamp.tv_usec)); // we only use milliseconds because that's all defined in exif, but this is the whole microseconds because we have it - unsigned char exiftimes[82] = { - 0x45, 0x78, 0x69, 0x66, 0x00, 0x00, 0x49, 0x49, 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x69, 0x87, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x03, 0x90, 0x02, 0x00, 0x14, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x91, 0x92, - 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x00 }; - memcpy(&exiftimes[EXIFTIMES_OFFSET], timebuf,EXIFTIMES_LEN); - memcpy(&exiftimes[EXIFTIMES_MS_OFFSET],msbuf ,EXIFTIMES_MS_LEN); // first character after the decimal point - jpeg_write_marker (cinfo, EXIF_CODE, (const JOCTET *)exiftimes, sizeof(exiftimes) ); - - } - JSAMPROW row_pointer; /* pointer to a single row */ int row_stride = cinfo->image_width * colours; /* physical row width in buffer */ while ( cinfo->next_scanline < cinfo->image_height ) diff --git a/src/zm_image.h b/src/zm_image.h index a48fafacc..46c7a031b 100644 --- a/src/zm_image.h +++ b/src/zm_image.h @@ -204,12 +204,7 @@ public: bool WriteRaw( const char *filename ) const; bool ReadJpeg( const char *filename, unsigned int p_colours, unsigned int p_subpixelorder); - - bool WriteJpeg ( const char *filename) const; - bool WriteJpeg ( const char *filename, int quality_override ) const; - bool WriteJpeg ( const char *filename, struct timeval timestamp ) const; - bool WriteJpeg ( const char *filename, int quality_override, struct timeval timestamp ) const; - + bool WriteJpeg( const char *filename, int quality_override=0 ) const; bool DecodeJpeg( const JOCTET *inbuffer, int inbuffer_size, unsigned int p_colours, unsigned int p_subpixelorder); bool EncodeJpeg( JOCTET *outbuffer, int *outbuffer_size, int quality_override=0 ) const; From 9e81eaa0f9fe35ffc89ea0cbbb0751f92c23e304 Mon Sep 17 00:00:00 2001 From: Linwood-F Date: Thu, 23 Jul 2015 15:19:40 -0400 Subject: [PATCH 018/362] Remove unexpected files that were added - 3 --- web/api/app/Config/core.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/api/app/Config/core.php b/web/api/app/Config/core.php index 59d72162c..93dcff772 100644 --- a/web/api/app/Config/core.php +++ b/web/api/app/Config/core.php @@ -222,12 +222,12 @@ /** * A random string used in security hashing methods. */ - Configure::write('Security.salt', 'olX2TOlboOnC474y3Tk4W4JOyuirw1EaadeHCcr4'); + Configure::write('Security.salt', '02670120062639232092038865362'); /** * A random numeric string (digits only) used to encrypt/decrypt strings. */ - Configure::write('Security.cipherSeed', '84684583012508019120061282965'); + Configure::write('Security.cipherSeed', '02670120062639232092038865362'); /** * Apply timestamps with the last modified time to static assets (js, css, images). From e967e3de6efacb4e8ec84abba87c2aac349198c7 Mon Sep 17 00:00:00 2001 From: Linwood-F Date: Thu, 23 Jul 2015 15:20:40 -0400 Subject: [PATCH 019/362] Remove unexpected files that were added - 4 --- web/api/app/Config/core.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/api/app/Config/core.php b/web/api/app/Config/core.php index 93dcff772..436cf8d60 100644 --- a/web/api/app/Config/core.php +++ b/web/api/app/Config/core.php @@ -222,7 +222,7 @@ /** * A random string used in security hashing methods. */ - Configure::write('Security.salt', '02670120062639232092038865362'); + Configure::write('Security.salt', 'Q0MjGG2xRQEhJVQR85WhFJKI7f2St8RYMlVR7GNQ'); /** * A random numeric string (digits only) used to encrypt/decrypt strings. From a091ad16f30ed2401c65d620d45abc0d4705aba1 Mon Sep 17 00:00:00 2001 From: Linwood-F Date: Thu, 23 Jul 2015 15:36:21 -0400 Subject: [PATCH 020/362] Final cleanup before pull request --- web/skins/classic/views/montagereview.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/web/skins/classic/views/montagereview.php b/web/skins/classic/views/montagereview.php index d243c3949..210ccc668 100644 --- a/web/skins/classic/views/montagereview.php +++ b/web/skins/classic/views/montagereview.php @@ -21,11 +21,10 @@ // Montage Review -- show all (visible) monitors, and allow to review time ranges easily for all monitors. // -// This is similar to the timeline view, but is NOT linked to events directly, and shows all monitors +// This is similar to the timeline view, but is NOT linked to events directly, and shows all monitors' images. // It also will do a pseudo play function (one second or more at a time, not less than 1 second resolution) // -// This is very much a preliminary version, very lightly tested, mostly on Firefox, but should work on IE and Chrome (at least) // It takes very high bandwidth to the server, and a pretty fast client to keep up with the image rate. To reduce the rate // change the playback slider to 0 and then it does not try to play at the same time it is scrubbing. // @@ -58,7 +57,7 @@ else } // Note that this finds incomplete events as well, and any frame records written, but still cannot "see" to the end frame -// if the bulk record has not been written - to get more current reduce bulk frame sizes +// if the bulk record has not been written - to be able to include more current frames reduce bulk frame sizes (event size can be large) $eventsSql = " select E.Id,E.Name,E.StartTime,max(F.TimeStamp) as CalcEndTime,E.Length,max(F.FrameId) as Frames,E.MaxScore,E.Cause,E.Notes,E.Archived,E.MonitorId @@ -73,7 +72,7 @@ $frameSql = " inner join Frames as F on (F.EventId = E.Id) where not isnull(StartTime) and F.Score>0 "; -// This program only calls itself with the time range involved -- it does all monitors (the user can see) all the time +// This program only calls itself with the time range involved -- it does all monitors (the user can see, in the called group) all the time if ( !empty($user['MonitorIds']) ) { @@ -248,7 +247,8 @@ else $maxTimeSecs = strtotime($maxTime); } -// If we had any alarms in those events, this builds the list of all alarm frames (thought for later - should these be ranges, so as to minimize list if very long?) +// If we had any alarms in those events, this builds the list of all alarm frames +// thought for later in case people have a LOT of alarms - change these to ranges, built as it loads, so as to minimize list length echo "var frameMonitorId = [];\n"; echo "var frameTimeStampSecs = [];\n"; From 3e85d57710440729a830b20cc9fd663aaa0a2cd5 Mon Sep 17 00:00:00 2001 From: Linwood-F Date: Thu, 30 Jul 2015 12:06:52 -0400 Subject: [PATCH 021/362] New version with added live view --- web/skins/classic/views/montagereview.php | 356 +++++++++++++++------- 1 file changed, 251 insertions(+), 105 deletions(-) diff --git a/web/skins/classic/views/montagereview.php b/web/skins/classic/views/montagereview.php index 210ccc668..92c15e43c 100644 --- a/web/skins/classic/views/montagereview.php +++ b/web/skins/classic/views/montagereview.php @@ -17,12 +17,13 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // + // --------------------- // Montage Review -- show all (visible) monitors, and allow to review time ranges easily for all monitors. // // This is similar to the timeline view, but is NOT linked to events directly, and shows all monitors' images. -// It also will do a pseudo play function (one second or more at a time, not less than 1 second resolution) +// It also will do a pseudo play function from history, as well as a live display of images. // // It takes very high bandwidth to the server, and a pretty fast client to keep up with the image rate. To reduce the rate @@ -38,6 +39,13 @@ // - Removed range from/to labels on very small graphs to keep from overlapping slider // - Changed initial (from other page) position of slider to be in the middle to be more obvious // +// Jul 29 2015 update +// - Add live mode shots from cameras via single frame pull mode +// - Added dynamic refresh rate based on how fast we can upload images +// - Closed some gaps in playback frames due to time rounding in retrieval. +// - Consolidated frame in-memory records to contiguous time rather than individual frame-seconds (still requires a good deal of browser memory) +// - Took out a lot of the integral second rounding so that it works better at subsequent replay speeds +// if ( !canView( 'Events' ) ) { $view = "error"; @@ -60,14 +68,15 @@ else // if the bulk record has not been written - to be able to include more current frames reduce bulk frame sizes (event size can be large) $eventsSql = " - select E.Id,E.Name,E.StartTime,max(F.TimeStamp) as CalcEndTime,E.Length,max(F.FrameId) as Frames,E.MaxScore,E.Cause,E.Notes,E.Archived,E.MonitorId + select E.Id,E.Name,UNIX_TIMESTAMP(E.StartTime) as StartTimeSecs,UNIX_TIMESTAMP(max(DATE_ADD(E.StartTime, Interval Delta Second))) as CalcEndTimeSecs, E.Length,max(F.FrameId) as Frames,E.MaxScore,E.Cause,E.Notes,E.Archived,E.MonitorId from Events as E inner join Monitors as M on (E.MonitorId = M.Id) inner join Frames F on F.EventId=E.Id where not isnull(E.Frames) and not isnull(StartTime) "; +// Note that the delta value seems more accurate than the time stamp for some reason. $frameSql = " - select E.Id as EventId, E.MonitorId, F.TimeStamp, max(F.Score) as Score + select E.Id as EventId, E.MonitorId, UNIX_TIMESTAMP(DATE_ADD(E.StartTime, Interval Delta Second)) as TimeStampSecs, max(F.Score) as Score from Events as E inner join Frames as F on (F.EventId = E.Id) where not isnull(StartTime) and F.Score>0 "; @@ -84,6 +93,7 @@ if ( !empty($user['MonitorIds']) ) } // Parse input parameters -- note for future, validate/clean up better in case we don't get called from self. +// Live overrides all the min/max stuff but it is still processed if ( isset($_REQUEST['minTime']) ) $minTime = validHtmlStr($_REQUEST['minTime']); @@ -104,6 +114,10 @@ else if (isset($_REQUEST['current']) ) $defaultCurrentTime=validHtmlStr($_REQUEST['current']); +$initialModeIsLive=0; +if(isset($_REQUEST['live']) ) + $initialModeIsLive=1; + $archive=1; if (isset($_REQUEST['archive']) ) $archive=validHtmlStr($_REQUEST['archive']); @@ -117,9 +131,10 @@ $eventsSql .= "group by E.Id,E.Name,E.StartTime,E.Length,E.Frames,E.MaxScore,E.C if( isset($minTime) && isset($maxTime) ) { - $eventsSql .= "having CalcEndTime > '" . $minTime . "' and StartTime < '" . $maxTime . "'"; - $frameSql .= " - and TimeStamp > '" . $minTime . "' and TimeStamp < '" . $maxTime . "'"; + $minTimeSecs = strtotime($minTime); + $maxTimeSecs = strtotime($maxTime); + $eventsSql .= "having CalcEndTimeSecs > '" . $minTimeSecs . "' and StartTimeSecs < '" . $maxTimeSecs . "'"; + $frameSql .= "and TimeStamp > '" . $minTime . "' and TimeStamp < '" . $maxTime . "'"; } $frameSql .= "group by E.Id, E.MonitorId, F.TimeStamp order by E.MonitorId, F.TimeStamp asc"; @@ -146,19 +161,20 @@ input[type=range]::-ms-tooltip { step=0.10 width=20% onchange='changescale(this.value)'/> x
-
+
step=1 wdth=20% onchange='changespeed(this.value)'/> - x + fps
- - - - - - - + + + + + + + +
@@ -168,9 +184,34 @@ input[type=range]::-ms-tooltip {
- + + +\n"; - +echo "
\n"; foreach ($monitors as $m) { if(!empty($eventsMonitorsFound[$m['Id']])) // only save the monitor if it's part of these events @@ -337,6 +360,8 @@ foreach ($monitors as $m) echo "No Canvas Support!!\n"; } } +echo "
\n"; +echo "

evaluating fps

\n"; echo "\n"; -echo "
\n"; -foreach ($monitors as $m) -{ - if(!empty($eventsMonitorsFound[$m['Id']])) // only save the monitor if it's part of these events - { - echo "No Canvas Support!!\n"; - } -} -echo "
\n"; -echo "

evaluating fps

\n"; -echo "
- - From e7264a8167059bee96f2e700403e0aa95ff57fcb Mon Sep 17 00:00:00 2001 From: Linwood-F Date: Mon, 3 Aug 2015 15:31:13 -0400 Subject: [PATCH 024/362] Minox fixes, make live mode default, 1 hour default --- web/skins/classic/views/montagereview.php | 45 +++++++++++++++++++---- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/web/skins/classic/views/montagereview.php b/web/skins/classic/views/montagereview.php index eb9760c02..2ee386428 100644 --- a/web/skins/classic/views/montagereview.php +++ b/web/skins/classic/views/montagereview.php @@ -26,6 +26,25 @@ // It also will do a pseudo play function from history, as well as a live display of images. // +// Valid query string: +// +// &maxTime, minTime = string formats (locale) of starting and ending time for history (pass both or none), default = last hour +// +// ¤t = string format of time, where the slider is positioned first in history mode (normally only used in reloads, default = half scale) +// +// &speed = one of the valid speeds below (see $speeds in php section, default = 1.0) +// +// &scale = image sie scale (.1 to 1.0, or 1.1 = fit, default = fit) +// +// &live=1 whether to start in live mode, 1 = yes, 0 = no +// +// &archive = if "1" then include archive frames, if "0" do not, default "1" +// +// &z1, &z2, etc. = initial monitor specific zoom, numeral is a monitor id, default = 1.0, used in page reloads normally +// +// &group = group number of monitors to display, comes from console if set, default is none (i.e. not limited by group) +// + // It takes very high bandwidth to the server, and a pretty fast client to keep up with the image rate. To reduce the rate // change the playback slider to 0 and then it does not try to play at the same time it is scrubbing. // @@ -56,6 +75,8 @@ // - Add max fit, make it default // - Remove timeline in live mode, and restore when switched back (live button becomes toggle) // - Add +/- zooms to individual monitors so you can adjust size, persist across reload buttons (only) +// - Change default to 1 hour and live mode (reduce workload on initial load, let people ask for huge history amounts) +// - Since this may be run as a standalone window for shortcuts, etc., add a "console" link to get back to the console // if ( !canView( 'Events' ) ) { @@ -107,12 +128,21 @@ if ( !empty($user['MonitorIds']) ) // Parse input parameters -- note for future, validate/clean up better in case we don't get called from self. // Live overrides all the min/max stuff but it is still processed +// The default (nothing at all specified) is for 1 hour so we do not read the whole database + + +if ( !isset($_REQUEST['minTime']) && !isset($_REQUEST['maxTime']) ) +{ + $maxTime=strftime("%c",time()); + $minTime=strftime("%c",time() - 3600); +} if ( isset($_REQUEST['minTime']) ) $minTime = validHtmlStr($_REQUEST['minTime']); if ( isset($_REQUEST['maxTime']) ) $maxTime = validHtmlStr($_REQUEST['maxTime']); + if ( isset($_REQUEST['scale']) ) $defaultScale=validHtmlStr($_REQUEST['scale']); else @@ -137,9 +167,9 @@ if (isset($_REQUEST['current']) ) $defaultCurrentTime=validHtmlStr($_REQUEST['current']); -$initialModeIsLive=0; -if(isset($_REQUEST['live']) ) - $initialModeIsLive=1; +$initialModeIsLive=1; +if(isset($_REQUEST['live']) && $_REQUEST['live']=='0' ) + $initialModeIsLive=0; $initialDisplayInterval=1000; if(isset($_REQUEST['displayinterval'])) @@ -192,6 +222,7 @@ input[type=range]::-ms-tooltip {