Merge branch 'storageareas' of github.com:connortechnology/ZoneMinder into storageareas
This commit is contained in:
commit
878e9e4cde
|
@ -634,7 +634,7 @@ insert into Users VALUES (NULL,'admin',password('admin'),'',1,'View','Edit','Edi
|
|||
--
|
||||
-- Add a sample filter to purge the oldest 100 events when the disk is 95% full
|
||||
--
|
||||
insert into Filters values (NULL,'PurgeWhenFull','{"sort_field":"Id","terms":[{"val":0,"attr":"Archived","op":"="},{"cnj":"and","val":95,"attr":"DiskPercent","op":">="}],"limit":100,"sort_asc":1}',0,0,0,0,0,0,'',1,1,0);
|
||||
insert into Filters values (NULL,'PurgeWhenFull','{"sort_field":"Id","terms":[{"val":0,"attr":"Archived","op":"="},{"cnj":"and","val":95,"attr":"DiskPercent","op":">="}],"limit":100,"sort_asc":1}',0,0,0,0,0,0,'',1,0,1,0);
|
||||
|
||||
--
|
||||
-- Add in some sample control protocol definitions
|
||||
|
@ -762,6 +762,21 @@ CREATE TABLE Maps (
|
|||
`ParentId` int(1) unsigned,
|
||||
PRIMARY KEY (`Id`)
|
||||
);
|
||||
|
||||
CREATE TABLE MontageLayouts (
|
||||
`Id` int(10) unsigned NOT NULL auto_increment,
|
||||
`Name` TEXT NOT NULL,
|
||||
`Positions` LONGTEXT,
|
||||
/*`Positions` JSON,*/
|
||||
PRIMARY KEY (`Id`)
|
||||
);
|
||||
|
||||
INSERT INTO MontageLayouts (`Name`,`Positions`) VALUES ('Freeform', '{ "default":{"float":"left","left":"0px","right":"0px","top":"0px","bottom":"0px"} }' );
|
||||
INSERT INTO MontageLayouts (`Name`,`Positions`) VALUES ('2 Wide', '{ "default":{"float":"left", "width":"49%","left":"0px","right":"0px","top":"0px","bottom":"0px"} }' );
|
||||
INSERT INTO MontageLayouts (`Name`,`Positions`) VALUES ('3 Wide', '{ "default":{"float":"left", "width":"33%","left":"0px","right":"0px","top":"0px","bottom":"0px"} }' );
|
||||
INSERT INTO MontageLayouts (`Name`,`Positions`) VALUES ('4 Wide', '{ "default":{"float":"left", "width":"24.5%","left":"0px","right":"0px","top":"0px","bottom":"0px"} }' );
|
||||
INSERT INTO MontageLayouts (`Name`,`Positions`) VALUES ('5 Wide', '{ "default":{"float":"left", "width":"19%","left":"0px","right":"0px","top":"0px","bottom":"0px"} }' );
|
||||
|
||||
--
|
||||
-- Apply the initial configuration
|
||||
--
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
--
|
||||
-- Add UpdateDiskSpace action to Filters
|
||||
--
|
||||
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
|
||||
AND table_name = 'Filters'
|
||||
AND column_name = 'UpdateDiskSpace'
|
||||
) > 0,
|
||||
"SELECT 'Column UpdateDiskSpace already exists in Filters'",
|
||||
"ALTER TABLE Filters ADD `UpdateDiskSpace` tinyint(3) unsigned NOT NULL default '0' AFTER `AutoDelete`"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
--
|
||||
-- Update Logs table to have some Indexes
|
||||
--
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE table_name = 'Logs'
|
||||
AND table_schema = DATABASE()
|
||||
AND index_name = 'Logs_TimeKey_idx'
|
||||
) > 0,
|
||||
"SELECT 'Logs_TimeKey_idx already exists on Logs table'",
|
||||
"CREATE INDEX `Logs_TimeKey_idx` ON `Logs` (`TimeKey`)"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE table_name = 'Logs'
|
||||
AND table_schema = DATABASE()
|
||||
AND index_name = 'Logs_Level_idx'
|
||||
) > 0,
|
||||
"SELECT 'Logs_Level_idx already exists on Logs table'",
|
||||
"CREATE INDEX `Logs_Level_idx` ON `Logs` (`Level`)"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
|
||||
AND table_name = 'Monitors'
|
||||
AND column_name = 'OutputCodec'
|
||||
) > 0,
|
||||
"SELECT 'Column OutputCodec already exists in Monitors'",
|
||||
"ALTER TABLE `Monitors` ADD `OutputCodec` enum('h264','mjpeg') AFTER `VideoWriter`"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
|
||||
AND table_name = 'Monitors'
|
||||
AND column_name = 'OutputContainer'
|
||||
) > 0,
|
||||
"SELECT 'Column OutputContainer already exists in Monitors'",
|
||||
"ALTER TABLE `Monitors` ADD `OutputContainer` enum('mp4','mkv') AFTER `OutputCodec`"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
|
@ -0,0 +1,67 @@
|
|||
--
|
||||
-- This adds Manufacturers and Models
|
||||
--
|
||||
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.TABLES
|
||||
WHERE table_name = 'MontageLayouts'
|
||||
AND table_schema = DATABASE()
|
||||
) > 0,
|
||||
"SELECT 'MontageLayouts table exists'",
|
||||
"
|
||||
CREATE TABLE MontageLayouts (
|
||||
`Id` int(10) unsigned NOT NULL auto_increment,
|
||||
`Name` TEXT NOT NULL,
|
||||
`Positions` LONGTEXT,
|
||||
PRIMARY KEY (`Id`)
|
||||
);
|
||||
"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
|
||||
DELETE FROM MontageLayouts WHERE Name IN ('Freeform','2 Wide','3 Wide','4 Wide','5 Wide');
|
||||
|
||||
SET @s = ( SELECT IF(
|
||||
(SELECT COUNT(*) FROM MontageLayouts WHERE Name='Freeform') > 0,
|
||||
"SELECT 'Freeform already in layouts'",
|
||||
'INSERT INTO MontageLayouts (`Name`,`Positions`) VALUES (\'Freeform\', \'{"default":{"float":"left","position":"relative","left":"0px","right":"0px","top":"0px","bottom":"0px"}}\');'
|
||||
) );
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
|
||||
SET @s = ( SELECT IF(
|
||||
(SELECT COUNT(*) FROM MontageLayouts WHERE Name='2 Wide') > 0,
|
||||
"SELECT '2 Wide already in layouts'",
|
||||
'INSERT INTO MontageLayouts (`Name`,`Positions`) VALUES (\'2 Wide\', \'{"default":{"float":"left","position":"relative","width":"49%","left":"0px","right":"0px","top":"0px","bottom":"0px"}}\');'
|
||||
) );
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
|
||||
SET @s = ( SELECT IF(
|
||||
(SELECT COUNT(*) FROM MontageLayouts WHERE Name='3 Wide') > 0,
|
||||
"SELECT '3 Wide already in layouts'",
|
||||
'INSERT INTO MontageLayouts (`Name`,`Positions`) VALUES (\'3 Wide\', \'{"default":{"float":"left","position":"relative","width":"33%","left":"0px","right":"0px","top":"0px","bottom":"0px"}}\');'
|
||||
) );
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
|
||||
SET @s = ( SELECT IF(
|
||||
(SELECT COUNT(*) FROM MontageLayouts WHERE Name='4 Wide') > 0,
|
||||
"SELECT '4 Wide already in layouts'",
|
||||
'INSERT INTO MontageLayouts (`Name`,`Positions`) VALUES (\'4 Wide\', \'{"default":{"float":"left","position":"relative","width":"24.5%","left":"0px","right":"0px","top":"0px","bottom":"0px"}}\');'
|
||||
) );
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
|
||||
SET @s = ( SELECT IF(
|
||||
(SELECT COUNT(*) FROM MontageLayouts WHERE Name='5 Wide') > 0,
|
||||
"SELECT '5 Wide already in layouts'",
|
||||
'INSERT INTO MontageLayouts (`Name`,`Positions`) VALUES (\'5 Wide\', \'{"default":{"float":"left","position":"relative","width":"19%"}}\' );'
|
||||
) );
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
|
@ -27,9 +27,7 @@ override_dh_auto_configure:
|
|||
-DZM_CGIDIR="/usr/lib/zoneminder/cgi-bin" \
|
||||
-DZM_DIR_EVENTS="/var/cache/zoneminder/events" \
|
||||
-DZM_DIR_IMAGES="/var/cache/zoneminder/images" \
|
||||
-DZM_PATH_ZMS="/zm/cgi-bin/nph-zms" \
|
||||
-DZM_NO_CURL=1 \
|
||||
-DZM_NO_LIBVLC=1
|
||||
-DZM_PATH_ZMS="/zm/cgi-bin/nph-zms"
|
||||
|
||||
override_dh_clean:
|
||||
dh_clean $(MANPAGES1)
|
||||
|
|
|
@ -4,5 +4,6 @@ var/cache/zoneminder/events
|
|||
var/cache/zoneminder/images
|
||||
var/cache/zoneminder/temp
|
||||
usr/share/zoneminder/db
|
||||
usr/share/zoneminder/www/cache
|
||||
etc/zm/
|
||||
etc/zm/conf.d
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
d /var/run/zm 0755 www-data www-data
|
||||
d /tmp/zm 0755 www-data www-data
|
||||
d /var/tmp/zm 0755 www-data www-data
|
||||
d /usr/share/zoneminder/www/cache 0755 www-data www-data
|
||||
|
|
|
@ -205,6 +205,30 @@ sub zmDbGetMonitorAndControl {
|
|||
return( $monitor );
|
||||
}
|
||||
|
||||
sub start_transaction {
|
||||
#my ( $caller, undef, $line ) = caller;
|
||||
#$openprint::log->debug("Called start_transaction from $caller : $line");
|
||||
my $d = shift;
|
||||
$d = $dbh if ! $d;
|
||||
my $ac = $d->{AutoCommit};
|
||||
$d->{AutoCommit} = 0;
|
||||
return $ac;
|
||||
} # end sub start_transaction
|
||||
|
||||
sub end_transaction {
|
||||
#my ( $caller, undef, $line ) = caller;
|
||||
#$openprint::log->debug("Called end_transaction from $caller : $line");
|
||||
my ( $d, $ac ) = @_;
|
||||
if ( ! defined $ac ) {
|
||||
Error("Undefined ac");
|
||||
}
|
||||
$d = $dbh if ! $d;
|
||||
if ( $ac ) {
|
||||
#$log->debug("Committing");
|
||||
$d->commit();
|
||||
} # end if
|
||||
$d->{AutoCommit} = $ac;
|
||||
} # end sub end_transaction
|
||||
1;
|
||||
__END__
|
||||
# Below is stub documentation for your module. You'd better edit it!
|
||||
|
|
|
@ -48,9 +48,38 @@ use ZoneMinder::Logger qw(:all);
|
|||
use ZoneMinder::Database qw(:all);
|
||||
require Date::Parse;
|
||||
|
||||
use vars qw/ $table $primary_key /;
|
||||
use vars qw/ $table $primary_key %fields $serial @identified_by/;
|
||||
$table = 'Events';
|
||||
$primary_key = 'Id';
|
||||
@identified_by = ('Id');
|
||||
$serial = $primary_key = 'Id';
|
||||
%fields = map { $_, $_ } qw(
|
||||
Id
|
||||
MonitorId
|
||||
StorageId
|
||||
Name
|
||||
Cause
|
||||
StartTime
|
||||
EndTime
|
||||
Width
|
||||
Height
|
||||
Length
|
||||
Frames
|
||||
AlarmFrames
|
||||
DefaultVideo
|
||||
TotScore
|
||||
AvgScore
|
||||
MaxScore
|
||||
Archived
|
||||
Videoed
|
||||
Uploaded
|
||||
Emailed
|
||||
Messaged
|
||||
Executed
|
||||
Notes
|
||||
StateId
|
||||
Orientation
|
||||
DiskSpace
|
||||
);
|
||||
|
||||
use POSIX;
|
||||
|
||||
|
@ -359,14 +388,16 @@ sub age {
|
|||
return $_[0]{age};
|
||||
}
|
||||
|
||||
sub DiskUsage {
|
||||
sub DiskSpace {
|
||||
if ( @_ > 1 ) {
|
||||
$_[0]{DiskUsage} = $_[1];
|
||||
Debug("Cleared DiskSpace, was $_[0]{DiskSpace}");
|
||||
$_[0]{DiskSpace} = $_[1];
|
||||
}
|
||||
if ( ! defined $_[0]{DiskUsage} ) {
|
||||
if ( ! defined $_[0]{DiskSpace} ) {
|
||||
my $size = 0;
|
||||
File::Find::find( { wanted=>sub { $size += -f $_ ? -s _ : 0 }, untaint=>1 }, $_[0]->Path() );
|
||||
$_[0]{DiskUsage} = $size;
|
||||
$_[0]{DiskSpace} = $size;
|
||||
Debug("DiskSpace for event $_[0]{Id} at $_[0]{Path} Updated to $size bytes");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -224,7 +224,7 @@ sub Sql {
|
|||
|| $term->{attr} eq 'Notes'
|
||||
) {
|
||||
$value = "'$temp_value'";
|
||||
} elsif ( $term->{attr} eq 'DateTime' ) {
|
||||
} elsif ( $term->{attr} eq 'DateTime' or $term->{attr} eq 'StartDateTime' or $term->{attr} eq 'EndDateTime' ) {
|
||||
$value = DateTimeToSQL( $temp_value );
|
||||
if ( !$value ) {
|
||||
Error( "Error parsing date/time '$temp_value', "
|
||||
|
@ -232,7 +232,7 @@ sub Sql {
|
|||
return;
|
||||
}
|
||||
$value = "'$value'";
|
||||
} elsif ( $term->{attr} eq 'Date' ) {
|
||||
} elsif ( $term->{attr} eq 'Date' or $term->{attr} eq 'StartDate' or $term->{attr} eq 'EndDate' ) {
|
||||
$value = DateTimeToSQL( $temp_value );
|
||||
if ( !$value ) {
|
||||
Error( "Error parsing date/time '$temp_value', "
|
||||
|
@ -240,7 +240,7 @@ sub Sql {
|
|||
return;
|
||||
}
|
||||
$value = "to_days( '$value' )";
|
||||
} elsif ( $term->{attr} eq 'Time' ) {
|
||||
} elsif ( $term->{attr} eq 'Time' or $term->{attr} eq 'StartTime' or $term->{attr} eq 'EndTime' ) {
|
||||
$value = DateTimeToSQL( $temp_value );
|
||||
if ( !$value ) {
|
||||
Error( "Error parsing date/time '$temp_value', "
|
||||
|
@ -259,6 +259,10 @@ sub Sql {
|
|||
$self->{Sql} .= " regexp $value";
|
||||
} elsif ( $term->{op} eq '!~' ) {
|
||||
$self->{Sql} .= " not regexp $value";
|
||||
} elsif ( $term->{op} eq 'IS' ) {
|
||||
$self->{Sql} .= " IS $value";
|
||||
} elsif ( $term->{op} eq 'IS NOT' ) {
|
||||
$self->{Sql} .= " IS NOT $value";
|
||||
} elsif ( $term->{op} eq '=[]' ) {
|
||||
$self->{Sql} .= " in (".join( ",", @value_list ).")";
|
||||
} elsif ( $term->{op} eq '!~' ) {
|
||||
|
@ -277,15 +281,15 @@ sub Sql {
|
|||
if ( $self->{AutoMessage} ) {
|
||||
# Include all events, including events that are still ongoing
|
||||
# and have no EndTime yet
|
||||
$sql .= " and ( ".$self->{Sql}." )";
|
||||
$sql .= ' AND ( '.$self->{Sql}.' )';
|
||||
} else {
|
||||
# Only include closed events (events with valid EndTime)
|
||||
$sql .= " where not isnull(E.EndTime) and ( ".$self->{Sql}." )";
|
||||
$sql .= ' WHERE (E.EndTime IS NOT NULL) AND ( '.$self->{Sql}.' )';
|
||||
}
|
||||
}
|
||||
my @auto_terms;
|
||||
if ( $self->{AutoArchive} ) {
|
||||
push @auto_terms, "E.Archived = 0";
|
||||
push @auto_terms, 'E.Archived = 0';
|
||||
}
|
||||
# Don't do this, it prevents re-generation and concatenation.
|
||||
# If the file already exists, then the video won't be re-recreated
|
||||
|
|
|
@ -678,6 +678,11 @@ sub Dump {
|
|||
fetch()->logPrint( DEBUG, Data::Dumper->Dump( [ $var ], [ $label ] ) );
|
||||
}
|
||||
|
||||
sub debug {
|
||||
my $log = shift;
|
||||
$log->logPrint( DEBUG, @_ );
|
||||
}
|
||||
|
||||
sub Debug( @ ) {
|
||||
fetch()->logPrint( DEBUG, @_ );
|
||||
}
|
||||
|
@ -685,14 +690,27 @@ sub Debug( @ ) {
|
|||
sub Info( @ ) {
|
||||
fetch()->logPrint( INFO, @_ );
|
||||
}
|
||||
sub info {
|
||||
my $log = shift;
|
||||
$log->logPrint( INFO, @_ );
|
||||
}
|
||||
|
||||
|
||||
sub Warning( @ ) {
|
||||
fetch()->logPrint( WARNING, @_ );
|
||||
}
|
||||
sub warn {
|
||||
my $log = shift;
|
||||
$log->logPrint( WARNING, @_ );
|
||||
}
|
||||
|
||||
sub Error( @ ) {
|
||||
fetch()->logPrint( ERROR, @_ );
|
||||
}
|
||||
sub error {
|
||||
my $log = shift;
|
||||
$log->logPrint( ERROR, @_ );
|
||||
}
|
||||
|
||||
sub Fatal( @ ) {
|
||||
fetch()->logPrint( FATAL, @_ );
|
||||
|
|
|
@ -42,7 +42,13 @@ use ZoneMinder::Config qw(:all);
|
|||
use ZoneMinder::Logger qw(:all);
|
||||
use ZoneMinder::Database qw(:all);
|
||||
|
||||
use vars qw/ $AUTOLOAD /;
|
||||
use vars qw/ $AUTOLOAD $log $dbh/;
|
||||
|
||||
*log = \$ZoneMinder::Logger::logger;
|
||||
*dbh = \$ZoneMinder::Database::dbh;
|
||||
|
||||
my $debug = 1;
|
||||
use constant DEBUG_ALL=>1;
|
||||
|
||||
sub new {
|
||||
my ( $parent, $id, $data ) = @_;
|
||||
|
@ -110,7 +116,282 @@ sub AUTOLOAD {
|
|||
return $_[0]{$name};
|
||||
}
|
||||
|
||||
sub save {
|
||||
my ( $self, $data, $force_insert ) = @_;
|
||||
|
||||
my $type = ref $self;
|
||||
if ( ! $type ) {
|
||||
my ( $caller, undef, $line ) = caller;
|
||||
$log->error("No type in Object::save. self:$self from $caller:$line");
|
||||
}
|
||||
my $local_dbh = eval '$'.$type.'::dbh';
|
||||
$local_dbh = $ZoneMinder::Database::dbh if ! $local_dbh;
|
||||
$self->set( $data ? $data : {} );
|
||||
if ( $debug or DEBUG_ALL ) {
|
||||
if ( $data ) {
|
||||
foreach my $k ( keys %$data ) {
|
||||
$log->debug("Object::save after set $k => $$data{$k} $$self{$k}");
|
||||
}
|
||||
} else {
|
||||
$log->debug("No data after set");
|
||||
}
|
||||
}
|
||||
#$debug = 0;
|
||||
|
||||
my $table = eval '$'.$type.'::table';
|
||||
my $fields = eval '\%'.$type.'::fields';
|
||||
my $debug = eval '$'.$type.'::debug';
|
||||
#$debug = DEBUG_ALL if ! $debug;
|
||||
|
||||
my %sql;
|
||||
foreach my $k ( keys %$fields ) {
|
||||
$sql{$$fields{$k}} = $$self{$k} if defined $$fields{$k};
|
||||
} # end foreach
|
||||
if ( ! $force_insert ) {
|
||||
$sql{$$fields{updated_on}} = 'NOW()' if exists $$fields{updated_on};
|
||||
} # end if
|
||||
my $serial = eval '$'.$type.'::serial';
|
||||
my @identified_by = eval '@'.$type.'::identified_by';
|
||||
|
||||
my $ac = ZoneMinder::Database::start_transaction( $local_dbh );
|
||||
if ( ! $serial ) {
|
||||
my $insert = $force_insert;
|
||||
my %serial = eval '%'.$type.'::serial';
|
||||
if ( ! %serial ) {
|
||||
$log->debug("No serial") if $debug;
|
||||
# No serial columns defined, which means that we will do saving by delete/insert instead of insert/update
|
||||
if ( @identified_by ) {
|
||||
my $where = join(' AND ', map { $$fields{$_}.'=?' } @identified_by );
|
||||
if ( $debug ) {
|
||||
$log->debug("DELETE FROM $table WHERE $where");
|
||||
} # end if
|
||||
|
||||
if ( ! ( ( $_ = $local_dbh->prepare("DELETE FROM $table WHERE $where") ) and $_->execute( @$self{@identified_by} ) ) ) {
|
||||
$where =~ s/\?/\%s/g;
|
||||
$log->error("Error deleting: DELETE FROM $table WHERE " . sprintf($where, map { defined $_ ? $_ : 'undef' } ( @$self{@identified_by}) ).'):' . $local_dbh->errstr);
|
||||
$local_dbh->rollback();
|
||||
ZoneMinder::Database::end_transaction( $local_dbh, $ac );
|
||||
return $local_dbh->errstr;
|
||||
} elsif ( $debug ) {
|
||||
$log->debug("SQL succesful DELETE FROM $table WHERE $where");
|
||||
} # end if
|
||||
} # end if
|
||||
$insert = 1;
|
||||
} else {
|
||||
foreach my $id ( @identified_by ) {
|
||||
if ( ! $serial{$id} ) {
|
||||
my ( $caller, undef, $line ) = caller;
|
||||
$log->error("$id nor in serial for $type from $caller:$line") if $debug;
|
||||
next;
|
||||
}
|
||||
if ( ! $$self{$id} ) {
|
||||
my $s = qq{SELECT `auto_increment` FROM INFORMATION_SCHEMA.TABLES WHERE table_name = '$table'};
|
||||
|
||||
($$self{$id}) = ($sql{$$fields{$id}}) = $local_dbh->selectrow_array( $s );
|
||||
#($$self{$id}) = ($sql{$$fields{$id}}) = $local_dbh->selectrow_array( q{SELECT nextval('} . $serial{$id} . q{')} );
|
||||
$log->debug("SQL statement execution SELECT $s returned $$self{$id}") if $debug or DEBUG_ALL;
|
||||
$insert = 1;
|
||||
} # end if
|
||||
} # end foreach
|
||||
} # end if ! %serial
|
||||
|
||||
if ( $insert ) {
|
||||
my @keys = keys %sql;
|
||||
my $command = "INSERT INTO $table (" . join(',', @keys ) . ') VALUES (' . join(',', map { '?' } @sql{@keys} ) . ')';
|
||||
if ( ! ( ( $_ = $local_dbh->prepare($command) ) and $_->execute( @sql{@keys} ) ) ) {
|
||||
my $error = $local_dbh->errstr;
|
||||
$command =~ s/\?/\%s/g;
|
||||
$log->error('SQL statement execution failed: ('.sprintf($command, , map { defined $_ ? $_ : 'undef' } ( @sql{@keys}) ).'):' . $local_dbh->errstr);
|
||||
$local_dbh->rollback();
|
||||
ZoneMinder::Database::end_transaction( $local_dbh, $ac );
|
||||
return $error;
|
||||
} # end if
|
||||
if ( $debug or DEBUG_ALL ) {
|
||||
$command =~ s/\?/\%s/g;
|
||||
$log->debug('SQL statement execution: ('.sprintf($command, , map { defined $_ ? $_ : 'undef' } ( @sql{@keys} ) ).'):' );
|
||||
} # end if
|
||||
} else {
|
||||
my @keys = keys %sql;
|
||||
my $command = "UPDATE $table SET " . join(',', map { $_ . ' = ?' } @keys ) . ' WHERE ' . join(' AND ', map { $_ . ' = ?' } @$fields{@identified_by} );
|
||||
if ( ! ( $_ = $local_dbh->prepare($command) and $_->execute( @sql{@keys,@$fields{@identified_by}} ) ) ) {
|
||||
my $error = $local_dbh->errstr;
|
||||
$command =~ s/\?/\%s/g;
|
||||
$log->error('SQL failed: ('.sprintf($command, , map { defined $_ ? $_ : 'undef' } ( @sql{@keys, @$fields{@identified_by}}) ).'):' . $local_dbh->errstr);
|
||||
$local_dbh->rollback();
|
||||
ZoneMinder::Database::end_transaction( $local_dbh, $ac );
|
||||
return $error;
|
||||
} # end if
|
||||
if ( $debug or DEBUG_ALL ) {
|
||||
$command =~ s/\?/\%s/g;
|
||||
$log->debug('SQL DEBUG: ('.sprintf($command, map { defined $_ ? $_ : 'undef' } ( @sql{@keys,@$fields{@identified_by}} ) ).'):' );
|
||||
} # end if
|
||||
} # end if
|
||||
} else { # not identified_by
|
||||
@identified_by = ('Id') if ! @identified_by;
|
||||
|
||||
# If the size of the arrays are not equal which means one or more are missing
|
||||
my @identified_by_without_values = map { $$self{$_} ? () : $_ } @identified_by;
|
||||
my $need_serial = @identified_by_without_values > 0;
|
||||
|
||||
if ( $force_insert or $need_serial ) {
|
||||
|
||||
if ( $need_serial ) {
|
||||
if ( $serial ) {
|
||||
my $s = qq{SELECT `auto_increment` FROM INFORMATION_SCHEMA.TABLES WHERE table_name = '$table'};
|
||||
@$self{@identified_by} = @sql{@$fields{@identified_by}} = $local_dbh->selectrow_array( $s );
|
||||
#@$self{@identified_by} = @sql{@$fields{@identified_by}} = $local_dbh->selectrow_array( q{SELECT nextval('} . $serial . q{')} );
|
||||
if ( $local_dbh->errstr() ) {
|
||||
$log->error("Error getting next id. " . $local_dbh->errstr() );
|
||||
$log->error("SQL statement execution $s returned ".join(',',@$self{@identified_by}));
|
||||
} elsif ( $debug or DEBUG_ALL ) {
|
||||
$log->debug("SQL statement execution $s returned ".join(',',@$self{@identified_by}));
|
||||
} # end if
|
||||
} # end if
|
||||
} # end if
|
||||
|
||||
my @keys = keys %sql;
|
||||
my $command = "INSERT INTO $table (" . join(',', @keys ) . ') VALUES (' . join(',', map { '?' } @sql{@keys} ) . ')';
|
||||
if ( ! ( $_ = $local_dbh->prepare($command) and $_->execute( @sql{@keys} ) ) ) {
|
||||
$command =~ s/\?/\%s/g;
|
||||
my $error = $local_dbh->errstr;
|
||||
$log->error('SQL failed: ('.sprintf($command, map { defined $_ ? $_ : 'undef' } ( @sql{@keys}) ).'):' . $error);
|
||||
$local_dbh->rollback();
|
||||
ZoneMinder::Database::end_transaction( $local_dbh, $ac );
|
||||
return $error;
|
||||
} # end if
|
||||
if ( $debug or DEBUG_ALL ) {
|
||||
$command =~ s/\?/\%s/g;
|
||||
$log->debug('SQL DEBUG: ('.sprintf($command, map { defined $_ ? $_ : 'undef' } ( @sql{@keys} ) ).'):' );
|
||||
} # end if
|
||||
} else {
|
||||
delete $sql{created_on};
|
||||
my @keys = keys %sql;
|
||||
my %identified_by = map { $_, $_ } @identified_by;
|
||||
|
||||
@keys = map { $identified_by{$_} ? () : $$fields{$_} } @keys;
|
||||
my $command = "UPDATE $table SET " . join(',', map { $_ . ' = ?' } @keys ) . ' WHERE ' . join(' AND ', map { $$fields{$_} .'= ?' } @identified_by );
|
||||
if ( ! ( $_ = $local_dbh->prepare($command) and $_->execute( @sql{@keys}, @sql{@$fields{@identified_by}} ) ) ) {
|
||||
my $error = $local_dbh->errstr;
|
||||
$command =~ s/\?/\%s/g;
|
||||
$log->error('SQL failed: ('.sprintf($command, map { defined $_ ? $_ : 'undef' } ( @sql{@keys}, @sql{@$fields{@identified_by}} ) ).'):' . $error) if $log;
|
||||
$local_dbh->rollback();
|
||||
ZoneMinder::Database::end_transaction( $local_dbh, $ac );
|
||||
return $error;
|
||||
} # end if
|
||||
if ( $debug or DEBUG_ALL ) {
|
||||
$command =~ s/\?/\%s/g;
|
||||
$log->debug('SQL DEBUG: ('.sprintf($command, map { defined $_ ? ( ref $_ eq 'ARRAY' ? join(',',@{$_}) : $_ ) : 'undef' } ( @sql{@keys}, @$self{@identified_by} ) ).'):' );
|
||||
} # end if
|
||||
} # end if
|
||||
} # end if
|
||||
ZoneMinder::Database::end_transaction( $local_dbh, $ac );
|
||||
$self->load();
|
||||
#if ( $$fields{id} ) {
|
||||
#if ( ! $ZoneMinder::Object::cache{$type}{$$self{id}} ) {
|
||||
#$ZoneMinder::Object::cache{$type}{$$self{id}} = $self;
|
||||
#} # end if
|
||||
#delete $ZoneMinder::Object::cache{$config{db_name}}{$type}{$$self{id}};
|
||||
#} # end if
|
||||
#$log->debug("after delete");
|
||||
#eval 'if ( %'.$type.'::find_cache ) { %'.$type.'::find_cache = (); }';
|
||||
#$log->debug("after clear cache");
|
||||
return '';
|
||||
} # end sub save
|
||||
|
||||
sub set {
|
||||
my ( $self, $params ) = @_;
|
||||
my @set_fields = ();
|
||||
|
||||
my $type = ref $self;
|
||||
my %fields = eval ('%'.$type.'::fields');
|
||||
if ( ! %fields ) {
|
||||
$log->warn("ZoneMinder::Object::set called on an object ($type) with no fields".$@);
|
||||
} # end if
|
||||
my %defaults = eval('%'.$type.'::defaults');
|
||||
if ( ref $params ne 'HASH' ) {
|
||||
my ( $caller, undef, $line ) = caller;
|
||||
$log->error("$type -> set called with non-hash params from $caller $line");
|
||||
}
|
||||
|
||||
foreach my $field ( keys %fields ) {
|
||||
if ( $params ) {
|
||||
$log->debug("field: $field, param: ".$$params{$field}) if $debug;
|
||||
if ( exists $$params{$field} ) {
|
||||
$log->debug("field: $field, $$self{$field} =? param: ".$$params{$field}) if $debug;
|
||||
if ( ( ! defined $$self{$field} ) or ($$self{$field} ne $params->{$field}) ) {
|
||||
# Only make changes to fields that have changed
|
||||
if ( defined $fields{$field} ) {
|
||||
$$self{$field} = $$params{$field} if defined $fields{$field};
|
||||
push @set_fields, $fields{$field}, $$params{$field}; #mark for sql updating
|
||||
} # end if
|
||||
$log->debug("Running $field with $$params{$field}") if $debug;
|
||||
if ( my $func = $self->can( $field ) ) {
|
||||
$func->( $self, $$params{$field} );
|
||||
} # end if
|
||||
} # end if
|
||||
} # end if
|
||||
} # end if $params
|
||||
|
||||
if ( defined $fields{$field} ) {
|
||||
if ( $$self{$field} ) {
|
||||
$$self{$field} = transform( $type, $field, $$self{$field} );
|
||||
} # end if $$self{field}
|
||||
}
|
||||
} # end foreach field
|
||||
|
||||
foreach my $field ( keys %defaults ) {
|
||||
|
||||
if ( ( ! exists $$self{$field} ) or (!defined $$self{$field}) or ( $$self{$field} eq '' ) ) {
|
||||
$log->debug("Setting default ($field) ($$self{$field}) ($defaults{$field}) ") if $debug;
|
||||
if ( defined $defaults{$field} ) {
|
||||
$log->debug("Default $field is defined: $defaults{$field}") if $debug;
|
||||
if ( $defaults{$field} eq 'NOW()' ) {
|
||||
$$self{$field} = 'NOW()';
|
||||
} else {
|
||||
$$self{$field} = eval($defaults{$field});
|
||||
$log->error( "Eval error of object default $field default ($defaults{$field}) Reason: " . $@ ) if $@;
|
||||
} # end if
|
||||
} else {
|
||||
$$self{$field} = $defaults{$field};
|
||||
} # end if
|
||||
#$$self{$field} = ( defined $defaults{$field} ) ? eval($defaults{$field}) : $defaults{$field};
|
||||
$log->debug("Setting default for ($field) using ($defaults{$field}) to ($$self{$field}) ") if $debug;
|
||||
} # end if
|
||||
} # end foreach default
|
||||
return @set_fields;
|
||||
} # end sub set
|
||||
|
||||
sub transform {
|
||||
my $type = ref $_[0];
|
||||
$type = $_[0] if ! $type;
|
||||
my $fields = eval '\%'.$type.'::fields';
|
||||
my $value = $_[2];
|
||||
|
||||
if ( defined $$fields{$_[1]} ) {
|
||||
my @transforms = eval('@{$'.$type.'::transforms{$_[1]}}');
|
||||
$log->debug("Transforms for $_[1] before $_[2]: @transforms") if $debug;
|
||||
if ( @transforms ) {
|
||||
foreach my $transform ( @transforms ) {
|
||||
if ( $transform =~ /^s\// or $transform =~ /^tr\// ) {
|
||||
eval '$value =~ ' . $transform;
|
||||
} elsif ( $transform =~ /^<(\d+)/ ) {
|
||||
if ( $value > $1 ) {
|
||||
$value = undef;
|
||||
} # end if
|
||||
} else {
|
||||
$log->debug("evalling $value ".$transform . " Now value is $value" );
|
||||
eval '$value '.$transform;
|
||||
$log->error("Eval error $@") if $@;
|
||||
}
|
||||
$log->debug("After $transform: $value") if $debug;
|
||||
} # end foreach
|
||||
} # end if
|
||||
} else {
|
||||
$log->error("Object::transform ($_[1]) not in fields for $type");
|
||||
} # end if
|
||||
return $value;
|
||||
|
||||
} # end sub transform
|
||||
1;
|
||||
__END__
|
||||
|
||||
|
|
|
@ -246,7 +246,7 @@ MAIN: while( $loop ) {
|
|||
$$Event{Path} = join('/', $Storage->Path(), $day_dir,$event_path);
|
||||
$Event->MonitorId( $monitor_dir );
|
||||
$Event->StorageId( $Storage->Id() );
|
||||
$Event->DiskUsage( undef );
|
||||
$Event->DiskSpace( undef );
|
||||
} # event path exists
|
||||
} # end foreach event_link
|
||||
chdir( $Storage->Path() );
|
||||
|
|
|
@ -251,15 +251,21 @@ sub checkFilter {
|
|||
my $filter = shift;
|
||||
|
||||
my @Events = $filter->Execute();
|
||||
Info( join( "Checking filter '$filter->{Name}'",
|
||||
($filter->{AutoDelete}?', delete':''),
|
||||
($filter->{AutoArchive}?', archive':''),
|
||||
($filter->{AutoVideo}?', video':''),
|
||||
($filter->{AutoUpload}?', upload':''),
|
||||
($filter->{AutoEmail}?', email':''),
|
||||
($filter->{AutoMessage}?', message':''),
|
||||
($filter->{AutoExecute}?', execute':''),
|
||||
' returned ' , scalar @Events , ' events',
|
||||
Info(
|
||||
join(' ',
|
||||
'Checking filter', $filter->{Name},
|
||||
join( ', ',
|
||||
|
||||
($filter->{AutoDelete}?'delete':()),
|
||||
($filter->{AutoArchive}?'archive':()),
|
||||
($filter->{AutoVideo}?'video':()),
|
||||
($filter->{AutoUpload}?'upload':()),
|
||||
($filter->{AutoEmail}?'email':()),
|
||||
($filter->{AutoMessage}?'message':()),
|
||||
($filter->{AutoExecute}?'execute':()),
|
||||
($filter->{UpdateDiskSpace}?'update disk space':()),
|
||||
),
|
||||
'returned' , scalar @Events , 'events',
|
||||
"\n",
|
||||
) );
|
||||
|
||||
|
@ -309,6 +315,12 @@ sub checkFilter {
|
|||
Error( "Unable toto delete event $event->{Id} as previous operations failed\n" );
|
||||
}
|
||||
} # end if AutoDelete
|
||||
if ( $filter->{UpdateDiskSpace} ) {
|
||||
my $Event = new ZoneMinder::Event( $$event{Id}, $event );
|
||||
$Event->DiskSpace(undef);
|
||||
$Event->save();
|
||||
|
||||
} # end if UpdateDiskSpace
|
||||
} # end foreach event
|
||||
}
|
||||
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
snprintf( swap_path, sizeof(swap_path), "%s/zmswap-m%d/zmswap-q%06d", staticConfig.PATH_SWAP.c_str(), monitor->Id(), connkey );
|
||||
|
||||
int len = snprintf(NULL, 0, "/zmswap-m%d", monitor->Id());
|
||||
|
||||
|
||||
int swap_path_length = strlen(staticConfig.PATH_SWAP.c_str()) + snprintf(NULL, 0, "/zmswap-m%d", monitor->Id() ) + snprintf(NULL, 0, "/zmswap-q%06d", connkey ) + 1; // +1 for NULL terminator
|
||||
|
||||
if ( connkey && playback_buffer > 0 ) {
|
||||
|
||||
if ( swap_path_length + max_swap_len_suffix > PATH_MAX ) {
|
||||
Error( "Swap Path is too long. %d > %d ", swap_path_length+max_swap_len_suffix, PATH_MAX );
|
||||
} else {
|
||||
swap_path = (char *)malloc( swap_path_length+max_swap_len_suffix );
|
||||
Debug( 3, "Checking swap image path %s", staticConfig.PATH_SWAP.c_str() );
|
||||
strncpy( swap_path, staticConfig.PATH_SWAP.c_str(), swap_path_length );
|
||||
if ( checkSwapPath( swap_path, false ) ) {
|
||||
snprintf( &(swap_path[swap_path_length]), max_swap_len_suffix, "/zmswap-m%d", monitor->Id() );
|
||||
if ( checkSwapPath( swap_path, true ) ) {
|
||||
snprintf( &(swap_path[swap_path_length]), max_swap_len_suffix, "/zmswap-q%06d", connkey );
|
||||
if ( checkSwapPath( swap_path, true ) ) {
|
||||
buffered_playback = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -215,6 +215,18 @@ ConfigItem::ConfigItem( const char *p_name, const char *p_value, const char *con
|
|||
|
||||
accessed = false;
|
||||
}
|
||||
ConfigItem::ConfigItem( const ConfigItem &item ) {
|
||||
name = new char[strlen(item.name)+1];
|
||||
strcpy( name, item.name );
|
||||
value = new char[strlen(item.value)+1];
|
||||
strcpy( value, item.value );
|
||||
type = new char[strlen(item.type)+1];
|
||||
strcpy( type, item.type );
|
||||
|
||||
//Info( "Created new config item %s = %s (%s)\n", name, value, type );
|
||||
|
||||
accessed = false;
|
||||
}
|
||||
|
||||
ConfigItem::~ConfigItem() {
|
||||
delete[] name;
|
||||
|
|
|
@ -107,7 +107,8 @@ private:
|
|||
mutable bool accessed;
|
||||
|
||||
public:
|
||||
ConfigItem( const char *p_name, const char *p_value, const char *const p_type );
|
||||
ConfigItem(const char *p_name, const char *p_value, const char *const p_type);
|
||||
ConfigItem(const ConfigItem &);
|
||||
~ConfigItem();
|
||||
void ConvertValue() const;
|
||||
bool BooleanValue() const;
|
||||
|
@ -116,16 +117,16 @@ public:
|
|||
const char *StringValue() const;
|
||||
|
||||
inline operator bool() const {
|
||||
return( BooleanValue() );
|
||||
return BooleanValue();
|
||||
}
|
||||
inline operator int() const {
|
||||
return( IntegerValue() );
|
||||
return IntegerValue();
|
||||
}
|
||||
inline operator double() const {
|
||||
return( DecimalValue() );
|
||||
return DecimalValue();
|
||||
}
|
||||
inline operator const char *() const {
|
||||
return( StringValue() );
|
||||
return StringValue();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -128,10 +128,10 @@ int cURLCamera::Capture( Image &image ) {
|
|||
/* Grab the mutex to ensure exclusive access to the shared data */
|
||||
lock();
|
||||
|
||||
while (!frameComplete) {
|
||||
while ( !frameComplete ) {
|
||||
|
||||
/* If the work thread did a reset, reset our local variables */
|
||||
if(bReset) {
|
||||
if ( bReset ) {
|
||||
SubHeadersParsingComplete = false;
|
||||
frame_content_length = 0;
|
||||
frame_content_type.clear();
|
||||
|
@ -139,25 +139,25 @@ int cURLCamera::Capture( Image &image ) {
|
|||
bReset = false;
|
||||
}
|
||||
|
||||
if(mode == MODE_UNSET) {
|
||||
if ( mode == MODE_UNSET ) {
|
||||
/* Don't have a mode yet. Sleep while waiting for data */
|
||||
nRet = pthread_cond_wait(&data_available_cond,&shareddata_mutex);
|
||||
if(nRet != 0) {
|
||||
if ( nRet != 0 ) {
|
||||
Error("Failed waiting for available data condition variable: %s",strerror(nRet));
|
||||
return -20;
|
||||
}
|
||||
}
|
||||
|
||||
if(mode == MODE_STREAM) {
|
||||
if ( mode == MODE_STREAM ) {
|
||||
|
||||
/* Subheader parsing */
|
||||
while(!SubHeadersParsingComplete && !need_more_data) {
|
||||
while( !SubHeadersParsingComplete && !need_more_data ) {
|
||||
|
||||
size_t crlf_start, crlf_end, crlf_size;
|
||||
std::string subheader;
|
||||
|
||||
/* Check if the buffer contains something */
|
||||
if(databuffer.empty()) {
|
||||
if ( databuffer.empty() ) {
|
||||
/* Empty buffer, wait for data */
|
||||
need_more_data = true;
|
||||
break;
|
||||
|
@ -165,14 +165,14 @@ int cURLCamera::Capture( Image &image ) {
|
|||
|
||||
/* Find crlf start */
|
||||
crlf_start = memcspn(databuffer,"\r\n",databuffer.size());
|
||||
if(crlf_start == databuffer.size()) {
|
||||
if ( crlf_start == databuffer.size() ) {
|
||||
/* Not found, wait for more data */
|
||||
need_more_data = true;
|
||||
break;
|
||||
}
|
||||
|
||||
/* See if we have enough data for determining crlf length */
|
||||
if(databuffer.size() < crlf_start+5) {
|
||||
if ( databuffer.size() < crlf_start+5 ) {
|
||||
/* Need more data */
|
||||
need_more_data = true;
|
||||
break;
|
||||
|
@ -183,13 +183,13 @@ int cURLCamera::Capture( Image &image ) {
|
|||
crlf_size = (crlf_start + crlf_end) - crlf_start;
|
||||
|
||||
/* Is this the end of a previous stream? (This is just before the boundary) */
|
||||
if(crlf_start == 0) {
|
||||
if ( crlf_start == 0 ) {
|
||||
databuffer.consume(crlf_size);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check for invalid CRLF size */
|
||||
if(crlf_size > 4) {
|
||||
if ( crlf_size > 4 ) {
|
||||
Error("Invalid CRLF length");
|
||||
}
|
||||
|
||||
|
@ -209,7 +209,7 @@ int cURLCamera::Capture( Image &image ) {
|
|||
|
||||
/* Find where the data in this header starts */
|
||||
size_t subheader_data_start = subheader.rfind(' ');
|
||||
if(subheader_data_start == std::string::npos) {
|
||||
if ( subheader_data_start == std::string::npos ) {
|
||||
subheader_data_start = subheader.find(':');
|
||||
}
|
||||
|
||||
|
|
|
@ -593,6 +593,7 @@ bool EventStream::sendFrame( int delta_us ) {
|
|||
FILE *fdj = NULL;
|
||||
|
||||
// This needs to be abstracted. If we are saving jpgs, then load the capture file. If we are only saving analysis frames, then send that.
|
||||
// // This is also wrong, need to have this info stored in the event! FIXME
|
||||
if ( monitor->GetOptSaveJPEGs() & 1 ) {
|
||||
snprintf( filepath, sizeof(filepath), staticConfig.capture_file_format, event_data->path, curr_frame_id );
|
||||
} else if ( monitor->GetOptSaveJPEGs() & 2 ) {
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "zm_stream.h"
|
||||
#include "zm_video.h"
|
||||
#include "zm_ffmpeg_input.h"
|
||||
#include "zm_monitor.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -108,11 +109,17 @@ class EventStream : public StreamBase {
|
|||
}
|
||||
void setStreamStart( int init_event_id, unsigned int init_frame_id=0 ) {
|
||||
loadInitialEventData( init_event_id, init_frame_id );
|
||||
loadMonitor( event_data->monitor_id );
|
||||
if ( !(monitor = Monitor::Load( event_data->monitor_id, false, Monitor::QUERY )) ) {
|
||||
Fatal( "Unable to load monitor id %d for streaming", event_data->monitor_id );
|
||||
return;
|
||||
}
|
||||
}
|
||||
void setStreamStart( int monitor_id, time_t event_time ) {
|
||||
loadInitialEventData( monitor_id, event_time );
|
||||
loadMonitor( monitor_id );
|
||||
if ( !(monitor = Monitor::Load( event_data->monitor_id, false, Monitor::QUERY )) ) {
|
||||
Fatal( "Unable to load monitor id %d for streaming", monitor_id );
|
||||
return;
|
||||
}
|
||||
}
|
||||
void setStreamMode( StreamMode p_mode ) {
|
||||
mode = p_mode;
|
||||
|
|
|
@ -317,7 +317,7 @@ int FfmpegCamera::Capture( Image &image ) {
|
|||
} // end if packet.stream_index == mVideoStreamId
|
||||
zm_av_packet_unref( &packet );
|
||||
} // end while ! frameComplete
|
||||
return (0);
|
||||
return 1;
|
||||
} // FfmpegCamera::Capture
|
||||
|
||||
int FfmpegCamera::PostCapture() {
|
||||
|
@ -495,7 +495,16 @@ int FfmpegCamera::OpenFfmpeg() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
#ifdef AV_CODEC_ID_H265
|
||||
if ( mVideoCodecContext->codec_id == AV_CODEC_ID_H265 ) {
|
||||
Debug( 1, "Input stream appears to be h265. The stored event file may not be viewable in browser." );
|
||||
} else {
|
||||
#endif
|
||||
Error( "Input stream is not h264. The stored event file may not be viewable in browser." );
|
||||
#ifdef AV_CODEC_ID_H265
|
||||
}
|
||||
#endif
|
||||
} // end if h264
|
||||
#endif
|
||||
|
||||
|
@ -735,22 +744,12 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
|
|||
mReopenThread = 0;
|
||||
}
|
||||
|
||||
if ( mVideoCodecContext->codec_id != AV_CODEC_ID_H264 ) {
|
||||
#ifdef AV_CODEC_ID_H265
|
||||
if ( mVideoCodecContext->codec_id == AV_CODEC_ID_H265 ) {
|
||||
Debug( 1, "Input stream appears to be h265. The stored event file may not be viewable in browser." );
|
||||
} else {
|
||||
#endif
|
||||
Error( "Input stream is not h264. The stored event file may not be viewable in browser." );
|
||||
#ifdef AV_CODEC_ID_H265
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int frameComplete = false;
|
||||
while ( ! frameComplete ) {
|
||||
av_init_packet( &packet );
|
||||
|
||||
Debug(4,"before read frame");
|
||||
ret = av_read_frame( mFormatContext, &packet );
|
||||
if ( ret < 0 ) {
|
||||
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
|
||||
|
@ -960,7 +959,7 @@ else if ( packet.pts && video_last_pts > packet.pts ) {
|
|||
ret = avcodec_receive_frame( mVideoCodecContext, mRawFrame );
|
||||
if ( ret < 0 ) {
|
||||
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
|
||||
Error( "Unable to send packet at frame %d: %s, continuing", frameCount, errbuf );
|
||||
Warning( "Unable to receive frame %d: %s, continuing", frameCount, errbuf );
|
||||
zm_av_packet_unref( &packet );
|
||||
continue;
|
||||
}
|
||||
|
@ -980,8 +979,6 @@ else if ( packet.pts && video_last_pts > packet.pts ) {
|
|||
}
|
||||
#endif
|
||||
|
||||
Debug( 4, "Decoded video packet at frame %d", frameCount );
|
||||
|
||||
if ( frameComplete ) {
|
||||
Debug( 4, "Got frame %d", frameCount );
|
||||
|
||||
|
@ -1012,6 +1009,7 @@ else if ( packet.pts && video_last_pts > packet.pts ) {
|
|||
Debug( 3, "Not framecomplete after av_read_frame" );
|
||||
} // end if frameComplete
|
||||
} else if ( packet.stream_index == mAudioStreamId ) { //FIXME best way to copy all other streams
|
||||
frameComplete = 1;
|
||||
if ( videoStore ) {
|
||||
if ( record_audio ) {
|
||||
if ( have_video_keyframe ) {
|
||||
|
@ -1033,6 +1031,8 @@ else if ( packet.pts && video_last_pts > packet.pts ) {
|
|||
} else {
|
||||
Debug(4, "Have audio packet, but not recording atm" );
|
||||
}
|
||||
zm_av_packet_unref( &packet );
|
||||
return 0;
|
||||
} else {
|
||||
#if LIBAVUTIL_VERSION_CHECK(56, 23, 0, 23, 0)
|
||||
Debug( 3, "Some other stream index %d, %s", packet.stream_index, av_get_media_type_string( mFormatContext->streams[packet.stream_index]->codecpar->codec_type) );
|
||||
|
@ -1044,7 +1044,7 @@ else if ( packet.pts && video_last_pts > packet.pts ) {
|
|||
// the packet contents are ref counted... when queuing, we allocate another packet and reference it with that one, so we should always need to unref here, which should not affect the queued version.
|
||||
zm_av_packet_unref( &packet );
|
||||
} // end while ! frameComplete
|
||||
return (frameCount);
|
||||
return frameCount;
|
||||
} // end FfmpegCamera::CaptureAndRecord
|
||||
|
||||
|
||||
|
|
|
@ -23,8 +23,7 @@
|
|||
#if HAVE_LIBVLC
|
||||
|
||||
// Do all the buffer checking work here to avoid unnecessary locking
|
||||
void* LibvlcLockBuffer(void* opaque, void** planes)
|
||||
{
|
||||
void* LibvlcLockBuffer(void* opaque, void** planes) {
|
||||
LibvlcPrivateData* data = (LibvlcPrivateData*)opaque;
|
||||
data->mutex.lock();
|
||||
|
||||
|
@ -36,15 +35,12 @@ void* LibvlcLockBuffer(void* opaque, void** planes)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void LibvlcUnlockBuffer(void* opaque, void* picture, void *const *planes)
|
||||
{
|
||||
void LibvlcUnlockBuffer(void* opaque, void* picture, void *const *planes) {
|
||||
LibvlcPrivateData* data = (LibvlcPrivateData*)opaque;
|
||||
|
||||
bool newFrame = false;
|
||||
for(uint32_t i = 0; i < data->bufferSize; i++)
|
||||
{
|
||||
if(data->buffer[i] != data->prevBuffer[i])
|
||||
{
|
||||
for( uint32_t i = 0; i < data->bufferSize; i++ ) {
|
||||
if ( data->buffer[i] != data->prevBuffer[i] ) {
|
||||
newFrame = true;
|
||||
break;
|
||||
}
|
||||
|
@ -54,8 +50,7 @@ void LibvlcUnlockBuffer(void* opaque, void* picture, void *const *planes)
|
|||
time_t now;
|
||||
time(&now);
|
||||
// Return frames slightly faster than 1fps (if time() supports greater than one second resolution)
|
||||
if(newFrame || difftime(now, data->prevTime) >= 0.8)
|
||||
{
|
||||
if ( newFrame || difftime(now, data->prevTime) >= 0.8 ) {
|
||||
data->prevTime = now;
|
||||
data->newImage.updateValueSignal(true);
|
||||
}
|
||||
|
@ -90,58 +85,46 @@ LibvlcCamera::LibvlcCamera( int p_id, const std::string &p_path, const std::stri
|
|||
Panic("Unexpected colours: %d",colours);
|
||||
}
|
||||
|
||||
if ( capture )
|
||||
{
|
||||
if ( capture ) {
|
||||
Initialise();
|
||||
}
|
||||
}
|
||||
|
||||
LibvlcCamera::~LibvlcCamera()
|
||||
{
|
||||
if ( capture )
|
||||
{
|
||||
LibvlcCamera::~LibvlcCamera() {
|
||||
if ( capture ) {
|
||||
Terminate();
|
||||
}
|
||||
if(mLibvlcMediaPlayer != NULL)
|
||||
{
|
||||
if ( mLibvlcMediaPlayer != NULL ) {
|
||||
libvlc_media_player_release(mLibvlcMediaPlayer);
|
||||
mLibvlcMediaPlayer = NULL;
|
||||
}
|
||||
if(mLibvlcMedia != NULL)
|
||||
{
|
||||
if ( mLibvlcMedia != NULL ) {
|
||||
libvlc_media_release(mLibvlcMedia);
|
||||
mLibvlcMedia = NULL;
|
||||
}
|
||||
if(mLibvlcInstance != NULL)
|
||||
{
|
||||
if ( mLibvlcInstance != NULL ) {
|
||||
libvlc_release(mLibvlcInstance);
|
||||
mLibvlcInstance = NULL;
|
||||
}
|
||||
if (mOptArgV != NULL)
|
||||
{
|
||||
if ( mOptArgV != NULL ) {
|
||||
delete[] mOptArgV;
|
||||
}
|
||||
}
|
||||
|
||||
void LibvlcCamera::Initialise()
|
||||
{
|
||||
void LibvlcCamera::Initialise() {
|
||||
}
|
||||
|
||||
void LibvlcCamera::Terminate()
|
||||
{
|
||||
void LibvlcCamera::Terminate() {
|
||||
libvlc_media_player_stop(mLibvlcMediaPlayer);
|
||||
if(mLibvlcData.buffer != NULL)
|
||||
{
|
||||
if(mLibvlcData.buffer != NULL) {
|
||||
zm_freealigned(mLibvlcData.buffer);
|
||||
}
|
||||
if(mLibvlcData.prevBuffer != NULL)
|
||||
{
|
||||
if(mLibvlcData.prevBuffer != NULL) {
|
||||
zm_freealigned(mLibvlcData.prevBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
int LibvlcCamera::PrimeCapture()
|
||||
{
|
||||
int LibvlcCamera::PrimeCapture() {
|
||||
Info("Priming capture from %s", mPath.c_str());
|
||||
|
||||
StringVector opVect = split(Options(), ",");
|
||||
|
@ -154,8 +137,7 @@ int LibvlcCamera::PrimeCapture()
|
|||
else if ( Method() == "rtpRtspHttp" )
|
||||
opVect.push_back("--rtsp-http");
|
||||
|
||||
if (opVect.size() > 0)
|
||||
{
|
||||
if ( opVect.size() > 0 ) {
|
||||
mOptArgV = new char*[opVect.size()];
|
||||
Debug(2, "Number of Options: %d",opVect.size());
|
||||
for (size_t i=0; i< opVect.size(); i++) {
|
||||
|
@ -166,7 +148,7 @@ int LibvlcCamera::PrimeCapture()
|
|||
}
|
||||
|
||||
mLibvlcInstance = libvlc_new (opVect.size(), (const char* const*)mOptArgV);
|
||||
if(mLibvlcInstance == NULL)
|
||||
if ( mLibvlcInstance == NULL )
|
||||
Fatal("Unable to create libvlc instance due to: %s", libvlc_errmsg());
|
||||
|
||||
mLibvlcMedia = libvlc_media_new_location(mLibvlcInstance, mPath.c_str());
|
||||
|
@ -189,17 +171,15 @@ int LibvlcCamera::PrimeCapture()
|
|||
|
||||
libvlc_media_player_play(mLibvlcMediaPlayer);
|
||||
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LibvlcCamera::PreCapture()
|
||||
{
|
||||
int LibvlcCamera::PreCapture() {
|
||||
return(0);
|
||||
}
|
||||
|
||||
// Should not return -1 as cancels capture. Always wait for image if available.
|
||||
int LibvlcCamera::Capture( Image &image )
|
||||
{
|
||||
int LibvlcCamera::Capture( Image &image ) {
|
||||
while(!mLibvlcData.newImage.getValueImmediate())
|
||||
mLibvlcData.newImage.getUpdatedValue(1);
|
||||
|
||||
|
@ -208,25 +188,15 @@ int LibvlcCamera::Capture( Image &image )
|
|||
mLibvlcData.newImage.setValueImmediate(false);
|
||||
mLibvlcData.mutex.unlock();
|
||||
|
||||
return (0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Should not return -1 as cancels capture. Always wait for image if available.
|
||||
int LibvlcCamera::CaptureAndRecord(Image &image, timeval recording, char* event_directory)
|
||||
{
|
||||
while(!mLibvlcData.newImage.getValueImmediate())
|
||||
mLibvlcData.newImage.getUpdatedValue(1);
|
||||
|
||||
mLibvlcData.mutex.lock();
|
||||
image.Assign(width, height, colours, subpixelorder, mLibvlcData.buffer, width * height * mBpp);
|
||||
mLibvlcData.newImage.setValueImmediate(false);
|
||||
mLibvlcData.mutex.unlock();
|
||||
|
||||
int LibvlcCamera::CaptureAndRecord(Image &image, timeval recording, char* event_directory) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
int LibvlcCamera::PostCapture()
|
||||
{
|
||||
int LibvlcCamera::PostCapture() {
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
|
|
@ -1534,34 +1534,28 @@ bool LocalCamera::GetCurrentSettings( const char *device, char *output, int vers
|
|||
return( false );
|
||||
}
|
||||
|
||||
if ( verbose )
|
||||
{
|
||||
if ( verbose ) {
|
||||
sprintf( output+strlen(output), " Input %d\n", input.index );
|
||||
sprintf( output+strlen(output), " Name: %s\n", input.name );
|
||||
sprintf( output+strlen(output), " Type: %s\n", input.type==V4L2_INPUT_TYPE_TUNER?"Tuner":(input.type==V4L2_INPUT_TYPE_CAMERA?"Camera":"Unknown") );
|
||||
sprintf( output+strlen(output), " Audioset: %08x\n", input.audioset );
|
||||
sprintf( output+strlen(output), " Standards: 0x%llx\n", input.std );
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
sprintf( output+strlen(output), "i%d:%s|", input.index, input.name );
|
||||
sprintf( output+strlen(output), "i%dT:%s|", input.index, input.type==V4L2_INPUT_TYPE_TUNER?"Tuner":(input.type==V4L2_INPUT_TYPE_CAMERA?"Camera":"Unknown") );
|
||||
sprintf( output+strlen(output), "i%dS:%llx|", input.index, input.std );
|
||||
}
|
||||
|
||||
if ( verbose )
|
||||
{
|
||||
if ( verbose ) {
|
||||
sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_POWER, "Power ", "off", "on", " (X)" ) );
|
||||
sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_SIGNAL, "Signal ", "not detected", "detected", " (X)" ) );
|
||||
sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_COLOR, "Colour Signal ", "not detected", "detected", "" ) );
|
||||
sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_H_LOCK, "Horizontal Lock ", "not detected", "detected", "" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf( output+strlen(output), "i%dSP:%d|", input.index, input.status&V4L2_IN_ST_NO_POWER?0:1 );
|
||||
sprintf( output+strlen(output), "i%dSS:%d|", input.index, input.status&V4L2_IN_ST_NO_SIGNAL?0:1 );
|
||||
sprintf( output+strlen(output), "i%dSC:%d|", input.index, input.status&V4L2_IN_ST_NO_COLOR?0:1 );
|
||||
sprintf( output+strlen(output), "i%dHP:%d|", input.index, input.status&V4L2_IN_ST_NO_H_LOCK?0:1 );
|
||||
} else {
|
||||
sprintf( output+strlen(output), "i%dSP:%d|", input.index, (input.status&V4L2_IN_ST_NO_POWER)?0:1 );
|
||||
sprintf( output+strlen(output), "i%dSS:%d|", input.index, (input.status&V4L2_IN_ST_NO_SIGNAL)?0:1 );
|
||||
sprintf( output+strlen(output), "i%dSC:%d|", input.index, (input.status&V4L2_IN_ST_NO_COLOR)?0:1 );
|
||||
sprintf( output+strlen(output), "i%dHP:%d|", input.index, (input.status&V4L2_IN_ST_NO_H_LOCK)?0:1 );
|
||||
}
|
||||
}
|
||||
while ( inputIndex++ >= 0 );
|
||||
|
@ -1570,12 +1564,10 @@ bool LocalCamera::GetCurrentSettings( const char *device, char *output, int vers
|
|||
}
|
||||
#endif // ZM_HAS_V4L2
|
||||
#if ZM_HAS_V4L1
|
||||
if ( version == 1 )
|
||||
{
|
||||
if ( version == 1 ) {
|
||||
struct video_capability vid_cap;
|
||||
memset( &vid_cap, 0, sizeof(video_capability) );
|
||||
if ( ioctl( vid_fd, VIDIOCGCAP, &vid_cap ) < 0 )
|
||||
{
|
||||
if ( ioctl( vid_fd, VIDIOCGCAP, &vid_cap ) < 0 ) {
|
||||
Error( "Failed to get video capabilities: %s", strerror(errno) );
|
||||
if ( verbose )
|
||||
sprintf( output, "Error, failed to get video capabilities %s: %s\n", queryDevice, strerror(errno) );
|
||||
|
@ -1583,8 +1575,7 @@ bool LocalCamera::GetCurrentSettings( const char *device, char *output, int vers
|
|||
sprintf( output, "error%d\n", errno );
|
||||
return( false );
|
||||
}
|
||||
if ( verbose )
|
||||
{
|
||||
if ( verbose ) {
|
||||
sprintf( output+strlen(output), "Video Capabilities\n" );
|
||||
sprintf( output+strlen(output), " Name: %s\n", vid_cap.name );
|
||||
sprintf( output+strlen(output), " Type: %d\n%s%s%s%s%s%s%s%s%s%s%s%s%s%s", vid_cap.type,
|
||||
|
@ -1995,17 +1986,14 @@ int LocalCamera::Contrast( int p_contrast )
|
|||
return( -1 );
|
||||
}
|
||||
|
||||
int LocalCamera::PrimeCapture()
|
||||
{
|
||||
int LocalCamera::PrimeCapture() {
|
||||
Initialise();
|
||||
|
||||
Debug( 2, "Priming capture" );
|
||||
#if ZM_HAS_V4L2
|
||||
if ( v4l_version == 2 )
|
||||
{
|
||||
if ( v4l_version == 2 ) {
|
||||
Debug( 3, "Queueing buffers" );
|
||||
for ( unsigned int frame = 0; frame < v4l2_data.reqbufs.count; frame++ )
|
||||
{
|
||||
for ( unsigned int frame = 0; frame < v4l2_data.reqbufs.count; frame++ ) {
|
||||
struct v4l2_buffer vid_buf;
|
||||
|
||||
memset( &vid_buf, 0, sizeof(vid_buf) );
|
||||
|
@ -2028,13 +2016,10 @@ int LocalCamera::PrimeCapture()
|
|||
}
|
||||
#endif // ZM_HAS_V4L2
|
||||
#if ZM_HAS_V4L1
|
||||
if ( v4l_version == 1 )
|
||||
{
|
||||
for ( int frame = 0; frame < v4l1_data.frames.frames; frame++ )
|
||||
{
|
||||
if ( v4l_version == 1 ) {
|
||||
for ( int frame = 0; frame < v4l1_data.frames.frames; frame++ ) {
|
||||
Debug( 3, "Queueing frame %d", frame );
|
||||
if ( ioctl( vid_fd, VIDIOCMCAPTURE, &v4l1_data.buffers[frame] ) < 0 )
|
||||
{
|
||||
if ( ioctl( vid_fd, VIDIOCMCAPTURE, &v4l1_data.buffers[frame] ) < 0 ) {
|
||||
Error( "Capture failure for frame %d: %s", frame, strerror(errno) );
|
||||
return( -1 );
|
||||
}
|
||||
|
@ -2045,19 +2030,16 @@ int LocalCamera::PrimeCapture()
|
|||
return( 0 );
|
||||
}
|
||||
|
||||
int LocalCamera::PreCapture()
|
||||
{
|
||||
Debug( 2, "Pre-capturing" );
|
||||
int LocalCamera::PreCapture() {
|
||||
Debug( 5, "Pre-capturing" );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int LocalCamera::Capture( Image &image )
|
||||
{
|
||||
int LocalCamera::Capture( Image &image ) {
|
||||
Debug( 3, "Capturing" );
|
||||
static uint8_t* buffer = NULL;
|
||||
static uint8_t* directbuffer = NULL;
|
||||
static int capture_frame = -1;
|
||||
int buffer_bytesused = 0;
|
||||
int capture_frame = -1;
|
||||
|
||||
int captures_per_frame = 1;
|
||||
if ( channel_count > 1 )
|
||||
|
@ -2067,13 +2049,10 @@ int LocalCamera::Capture( Image &image )
|
|||
Warning( "Invalid Captures Per Frame setting: %d", captures_per_frame );
|
||||
}
|
||||
|
||||
|
||||
// Do the capture, unless we are the second or subsequent camera on a channel, in which case just reuse the buffer
|
||||
if ( channel_prime )
|
||||
{
|
||||
if ( channel_prime ) {
|
||||
#if ZM_HAS_V4L2
|
||||
if ( v4l_version == 2 )
|
||||
{
|
||||
if ( v4l_version == 2 ) {
|
||||
static struct v4l2_buffer vid_buf;
|
||||
|
||||
memset( &vid_buf, 0, sizeof(vid_buf) );
|
||||
|
@ -2083,10 +2062,8 @@ int LocalCamera::Capture( Image &image )
|
|||
vid_buf.memory = v4l2_data.reqbufs.memory;
|
||||
|
||||
Debug( 3, "Capturing %d frames", captures_per_frame );
|
||||
while ( captures_per_frame )
|
||||
{
|
||||
if ( vidioctl( vid_fd, VIDIOC_DQBUF, &vid_buf ) < 0 )
|
||||
{
|
||||
while ( captures_per_frame ) {
|
||||
if ( vidioctl( vid_fd, VIDIOC_DQBUF, &vid_buf ) < 0 ) {
|
||||
if ( errno == EIO )
|
||||
Warning( "Capture failure, possible signal loss?: %s", strerror(errno) )
|
||||
else
|
||||
|
@ -2096,15 +2073,13 @@ int LocalCamera::Capture( Image &image )
|
|||
|
||||
v4l2_data.bufptr = &vid_buf;
|
||||
capture_frame = v4l2_data.bufptr->index;
|
||||
if ( --captures_per_frame )
|
||||
{
|
||||
if ( vidioctl( vid_fd, VIDIOC_QBUF, &vid_buf ) < 0 )
|
||||
{
|
||||
if ( --captures_per_frame ) {
|
||||
if ( vidioctl( vid_fd, VIDIOC_QBUF, &vid_buf ) < 0 ) {
|
||||
Error( "Unable to requeue buffer %d: %s", vid_buf.index, strerror(errno) );
|
||||
return( -1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
} // while captures_per_frame
|
||||
|
||||
Debug( 3, "Captured frame %d/%d from channel %d", capture_frame, v4l2_data.bufptr->sequence, channel );
|
||||
|
||||
|
@ -2115,23 +2090,19 @@ int LocalCamera::Capture( Image &image )
|
|||
Fatal("Captured image dimensions differ: V4L2: %dx%d monitor: %dx%d",v4l2_data.fmt.fmt.pix.width,v4l2_data.fmt.fmt.pix.height,width,height);
|
||||
}
|
||||
|
||||
}
|
||||
} // end if v4l2
|
||||
#endif // ZM_HAS_V4L2
|
||||
#if ZM_HAS_V4L1
|
||||
if ( v4l_version == 1 )
|
||||
{
|
||||
if ( v4l_version == 1 ) {
|
||||
Debug( 3, "Capturing %d frames", captures_per_frame );
|
||||
while ( captures_per_frame )
|
||||
{
|
||||
while ( captures_per_frame ) {
|
||||
Debug( 3, "Syncing frame %d", v4l1_data.active_frame );
|
||||
if ( ioctl( vid_fd, VIDIOCSYNC, &v4l1_data.active_frame ) < 0 )
|
||||
{
|
||||
if ( ioctl( vid_fd, VIDIOCSYNC, &v4l1_data.active_frame ) < 0 ) {
|
||||
Error( "Sync failure for frame %d buffer %d: %s", v4l1_data.active_frame, captures_per_frame, strerror(errno) );
|
||||
return( -1 );
|
||||
}
|
||||
captures_per_frame--;
|
||||
if ( captures_per_frame )
|
||||
{
|
||||
if ( captures_per_frame ) {
|
||||
Debug( 3, "Capturing frame %d", v4l1_data.active_frame );
|
||||
if ( ioctl( vid_fd, VIDIOCMCAPTURE, &v4l1_data.buffers[v4l1_data.active_frame] ) < 0 )
|
||||
{
|
||||
|
@ -2148,18 +2119,18 @@ int LocalCamera::Capture( Image &image )
|
|||
#endif // ZM_HAS_V4L1
|
||||
} /* prime capture */
|
||||
|
||||
if(conversion_type != 0) {
|
||||
if ( conversion_type != 0 ) {
|
||||
|
||||
Debug( 3, "Performing format conversion" );
|
||||
|
||||
/* Request a writeable buffer of the target image */
|
||||
directbuffer = image.WriteBuffer(width, height, colours, subpixelorder);
|
||||
if(directbuffer == NULL) {
|
||||
uint8_t* directbuffer = image.WriteBuffer(width, height, colours, subpixelorder);
|
||||
if ( directbuffer == NULL ) {
|
||||
Error("Failed requesting writeable buffer for the captured image.");
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
#if HAVE_LIBSWSCALE
|
||||
if(conversion_type == 1) {
|
||||
if ( conversion_type == 1 ) {
|
||||
|
||||
Debug( 9, "Calling sws_scale to perform the conversion" );
|
||||
/* Use swscale to convert the image directly into the shared memory */
|
||||
|
@ -2171,17 +2142,20 @@ int LocalCamera::Capture( Image &image )
|
|||
avpicture_fill( (AVPicture *)tmpPicture, directbuffer,
|
||||
imagePixFormat, width, height );
|
||||
#endif
|
||||
sws_scale( imgConversionContext, capturePictures[capture_frame]->data, capturePictures[capture_frame]->linesize, 0, height, tmpPicture->data, tmpPicture->linesize );
|
||||
sws_scale( imgConversionContext,
|
||||
capturePictures[capture_frame]->data,
|
||||
capturePictures[capture_frame]->linesize,
|
||||
0,
|
||||
height,
|
||||
tmpPicture->data,
|
||||
tmpPicture->linesize );
|
||||
}
|
||||
#endif
|
||||
if(conversion_type == 2) {
|
||||
|
||||
if ( conversion_type == 2 ) {
|
||||
Debug( 9, "Calling the conversion function" );
|
||||
/* Call the image conversion function and convert directly into the shared memory */
|
||||
(*conversion_fptr)(buffer, directbuffer, pixels);
|
||||
}
|
||||
else if(conversion_type == 3) {
|
||||
|
||||
} else if ( conversion_type == 3 ) {
|
||||
Debug( 9, "Decoding the JPEG image" );
|
||||
/* JPEG decoding */
|
||||
image.DecodeJpeg(buffer, buffer_bytesused, colours, subpixelorder);
|
||||
|
@ -2192,11 +2166,10 @@ int LocalCamera::Capture( Image &image )
|
|||
|
||||
/* No conversion was performed, the image is in the V4L buffers and needs to be copied into the shared memory */
|
||||
image.Assign( width, height, colours, subpixelorder, buffer, imagesize);
|
||||
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
return 1;
|
||||
} // end int LocalCamera::Capture()
|
||||
|
||||
int LocalCamera::PostCapture()
|
||||
{
|
||||
|
|
|
@ -1178,7 +1178,7 @@ bool Monitor::Analyse() {
|
|||
gettimeofday( &now, NULL );
|
||||
|
||||
if ( image_count && fps_report_interval && !(image_count%fps_report_interval) ) {
|
||||
fps = double(fps_report_interval)/(now.tv_sec-last_fps_time);
|
||||
fps = double(fps_report_interval)/(now.tv_sec - last_fps_time);
|
||||
Info( "%s: %d - Analysing at %.2f fps", name, image_count, fps );
|
||||
static char sql[ZM_SQL_SML_BUFSIZ];
|
||||
snprintf( sql, sizeof(sql), "UPDATE Monitors SET AnalysisFPS = '%.2lf' WHERE Id = '%d'", fps, id );
|
||||
|
@ -2889,33 +2889,27 @@ int Monitor::Capture() {
|
|||
|
||||
} else {
|
||||
//Check if FFMPEG camera
|
||||
if ( (videowriter == H264PASSTHROUGH ) && camera->SupportsNativeVideo() ) {
|
||||
if ( (videowriter == H264PASSTHROUGH) && camera->SupportsNativeVideo() ) {
|
||||
//Warning("ZMC: Recording: %d", video_store_data->recording);
|
||||
captureResult = camera->CaptureAndRecord(*capture_image, video_store_data->recording, video_store_data->event_file);
|
||||
}else{
|
||||
// Should return -1 on error, like loss of signal. Should return 0 if ok but no video frame. > 0 for received a frame.
|
||||
captureResult = camera->CaptureAndRecord(
|
||||
*capture_image,
|
||||
video_store_data->recording,
|
||||
video_store_data->event_file
|
||||
);
|
||||
} else {
|
||||
/* Capture directly into image buffer, avoiding the need to memcpy() */
|
||||
captureResult = camera->Capture(*capture_image);
|
||||
}
|
||||
}
|
||||
|
||||
// CaptureAndRecord returns # of frames captured I think
|
||||
if ( ( videowriter == H264PASSTHROUGH ) && ( captureResult > 0 ) ) {
|
||||
//video_store_data->frameNumber = captureResult;
|
||||
captureResult = 0;
|
||||
}
|
||||
|
||||
if ( captureResult != 0 ) {
|
||||
Debug(4, "Return from Capture (%d)", captureResult);
|
||||
if ( captureResult < 0 ) {
|
||||
// Unable to capture image for temporary reason
|
||||
// Fake a signal loss image
|
||||
Rgb signalcolor;
|
||||
signalcolor = rgb_convert(signal_check_colour, ZM_SUBPIX_ORDER_BGR); /* HTML colour code is actually BGR in memory, we want RGB */
|
||||
capture_image->Fill(signalcolor);
|
||||
captureResult = 0;
|
||||
} else {
|
||||
captureResult = 1;
|
||||
}
|
||||
|
||||
if ( captureResult == 1 ) {
|
||||
} else if ( captureResult > 0 ) {
|
||||
|
||||
/* Deinterlacing */
|
||||
if ( deinterlacing_value == 1 ) {
|
||||
|
@ -2969,29 +2963,41 @@ int Monitor::Capture() {
|
|||
if ( privacy_bitmask )
|
||||
capture_image->MaskPrivacy( privacy_bitmask );
|
||||
|
||||
// Might be able to remove this call, when we start passing around ZMPackets, which will already have a timestamp
|
||||
gettimeofday( image_buffer[index].timestamp, NULL );
|
||||
if ( config.timestamp_on_capture ) {
|
||||
TimestampImage( capture_image, image_buffer[index].timestamp );
|
||||
}
|
||||
// Maybe we don't need to do this on all camera types
|
||||
shared_data->signal = CheckSignal(capture_image);
|
||||
shared_data->last_write_index = index;
|
||||
shared_data->last_write_time = image_buffer[index].timestamp->tv_sec;
|
||||
|
||||
image_count++;
|
||||
} // end if captureResult
|
||||
|
||||
if ( image_count && fps_report_interval && !(image_count%fps_report_interval) ) {
|
||||
time_t now = image_buffer[index].timestamp->tv_sec;
|
||||
fps = double(fps_report_interval)/(now-last_fps_time);
|
||||
//Info( "%d -> %d -> %d", fps_report_interval, now, last_fps_time );
|
||||
|
||||
struct timeval now;
|
||||
if ( !captureResult ) {
|
||||
gettimeofday( &now, NULL );
|
||||
} else {
|
||||
now.tv_sec = image_buffer[index].timestamp->tv_sec;
|
||||
}
|
||||
// If we are too fast, we get div by zero. This seems to happen in the case of audio packets.
|
||||
if ( now.tv_sec != last_fps_time ) {
|
||||
fps = double(fps_report_interval)/(now.tv_sec-last_fps_time);
|
||||
Info( "%d -> %d -> %d", fps_report_interval, now.tv_sec, last_fps_time );
|
||||
//Info( "%d -> %d -> %lf -> %lf", now-last_fps_time, fps_report_interval/(now-last_fps_time), double(fps_report_interval)/(now-last_fps_time), fps );
|
||||
Info( "%s: %d - Capturing at %.2lf fps", name, image_count, fps );
|
||||
last_fps_time = now;
|
||||
last_fps_time = now.tv_sec;
|
||||
static char sql[ZM_SQL_SML_BUFSIZ];
|
||||
snprintf( sql, sizeof(sql), "UPDATE Monitors SET CaptureFPS = '%.2lf' WHERE Id = '%d'", fps, id );
|
||||
snprintf( sql, sizeof(sql), "UPDATE Monitors SET CaptureFPS='%.2lf' WHERE Id=%d", fps, id );
|
||||
if ( mysql_query( &dbconn, sql ) ) {
|
||||
Error( "Can't run query: %s", mysql_error( &dbconn ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Icon: I'm not sure these should be here. They have nothing to do with capturing
|
||||
if ( shared_data->action & GET_SETTINGS ) {
|
||||
|
@ -3008,10 +3014,7 @@ int Monitor::Capture() {
|
|||
camera->Contrast( shared_data->contrast );
|
||||
shared_data->action &= ~SET_SETTINGS;
|
||||
}
|
||||
return( 0 );
|
||||
} // end if captureResults == 1 which is success I think
|
||||
shared_data->signal = false;
|
||||
return( -1 );
|
||||
return captureResult;
|
||||
}
|
||||
|
||||
void Monitor::TimestampImage( Image *ts_image, const struct timeval *ts_time ) const {
|
||||
|
|
|
@ -316,7 +316,7 @@ void MonitorStream::processCommand( const CmdMsg *msg ) {
|
|||
//status_data.enabled = monitor->shared_data->active;
|
||||
status_data.enabled = monitor->trigger_data->trigger_state!=Monitor::TRIGGER_OFF;
|
||||
status_data.forced = monitor->trigger_data->trigger_state==Monitor::TRIGGER_ON;
|
||||
Debug( 2, "L:%d, D:%d, P:%d, R:%d, d:%.3f, Z:%d, E:%d F:%d",
|
||||
Debug( 2, "Buffer Level:%d, Delayed:%d, Paused:%d, Rate:%d, delay:%.3f, Zoom:%d, Enabled:%d Forced:%d",
|
||||
status_data.buffer_level,
|
||||
status_data.delayed,
|
||||
status_data.paused,
|
||||
|
@ -338,11 +338,15 @@ void MonitorStream::processCommand( const CmdMsg *msg ) {
|
|||
//exit( -1 );
|
||||
}
|
||||
}
|
||||
Debug(2, "NUmber of bytes sent: (%d)", nbytes );
|
||||
|
||||
// quit after sending a status, if this was a quit request
|
||||
if ((MsgCommand)msg->msg_data[0]==CMD_QUIT)
|
||||
if ( (MsgCommand)msg->msg_data[0]==CMD_QUIT ) {
|
||||
Debug(2,"Quitting");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
Debug(2,"Updating framrate");
|
||||
updateFrameRate( monitor->GetFPS() );
|
||||
} // end void MonitorStream::processCommand( const CmdMsg *msg )
|
||||
|
||||
|
@ -553,20 +557,28 @@ void MonitorStream::runStream() {
|
|||
Debug( 2, "Assigned temporary buffer" );
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end if connkey & playback_buffer
|
||||
|
||||
float max_secs_since_last_sent_frame = 10.0; //should be > keep alive amount (5 secs)
|
||||
while ( !zm_terminate ) {
|
||||
bool got_command = false;
|
||||
if ( feof( stdout ) || ferror( stdout ) || !monitor->ShmValid() ) {
|
||||
if ( feof( stdout ) ) {
|
||||
Debug(2,"feof stdout");
|
||||
} else if ( ferror( stdout ) ) {
|
||||
Debug(2,"ferror stdout");
|
||||
} else if ( !monitor->ShmValid() ) {
|
||||
Debug(2,"monitor not valid.... maybe we should wait until it comes back.");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
gettimeofday( &now, NULL );
|
||||
|
||||
if ( connkey ) {
|
||||
Debug(2, "checking command Queue");
|
||||
//Debug(2, "checking command Queue for connkey: %d", connkey );
|
||||
while(checkCommandQueue()) {
|
||||
Debug(2, "Have checking command Queue for connkey: %d", connkey );
|
||||
got_command = true;
|
||||
}
|
||||
}
|
||||
|
@ -655,8 +667,10 @@ Debug(2, "checking command Queue");
|
|||
// Send the next frame
|
||||
Monitor::Snapshot *snap = &monitor->image_buffer[index];
|
||||
|
||||
if ( !sendFrame( snap->image, snap->timestamp ) )
|
||||
if ( !sendFrame( snap->image, snap->timestamp ) ) {
|
||||
Debug(2, "sendFrame failed, quiting.");
|
||||
zm_terminate = true;
|
||||
}
|
||||
memcpy( &last_frame_timestamp, snap->timestamp, sizeof(last_frame_timestamp) );
|
||||
//frame_sent = true;
|
||||
|
||||
|
@ -693,9 +707,12 @@ Debug(2, "checking command Queue");
|
|||
} // end if buffered playback
|
||||
frame_count++;
|
||||
}
|
||||
unsigned long sleep_time = (unsigned long)((1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2)));
|
||||
Debug(2, "Sleeping for (%d)", sleep_time);
|
||||
usleep( (unsigned long)((1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2))) );
|
||||
if ( ttl ) {
|
||||
if ( (now.tv_sec - stream_start_time) > ttl ) {
|
||||
Debug(2, "now(%d) - start(%d) > ttl(%d) break", now.tv_sec, stream_start_time, ttl);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1063,23 +1063,18 @@ int RemoteCameraHttp::GetResponse()
|
|||
return( 0 );
|
||||
}
|
||||
|
||||
int RemoteCameraHttp::PreCapture()
|
||||
{
|
||||
if ( sd < 0 )
|
||||
{
|
||||
int RemoteCameraHttp::PreCapture() {
|
||||
if ( sd < 0 ) {
|
||||
Connect();
|
||||
if ( sd < 0 )
|
||||
{
|
||||
if ( sd < 0 ) {
|
||||
Error( "Unable to connect to camera" );
|
||||
return( -1 );
|
||||
}
|
||||
mode = SINGLE_IMAGE;
|
||||
buffer.clear();
|
||||
}
|
||||
if ( mode == SINGLE_IMAGE )
|
||||
{
|
||||
if ( SendRequest() < 0 )
|
||||
{
|
||||
if ( mode == SINGLE_IMAGE ) {
|
||||
if ( SendRequest() < 0 ) {
|
||||
Error( "Unable to send request" );
|
||||
Disconnect();
|
||||
return( -1 );
|
||||
|
@ -1088,50 +1083,43 @@ int RemoteCameraHttp::PreCapture()
|
|||
return( 0 );
|
||||
}
|
||||
|
||||
int RemoteCameraHttp::Capture( Image &image )
|
||||
{
|
||||
int RemoteCameraHttp::Capture( Image &image ) {
|
||||
int content_length = GetResponse();
|
||||
if ( content_length == 0 )
|
||||
{
|
||||
if ( content_length == 0 ) {
|
||||
Warning( "Unable to capture image, retrying" );
|
||||
return( 1 );
|
||||
return 0;
|
||||
}
|
||||
if ( content_length < 0 )
|
||||
{
|
||||
if ( content_length < 0 ) {
|
||||
Error( "Unable to get response, disconnecting" );
|
||||
Disconnect();
|
||||
return( -1 );
|
||||
return -1;
|
||||
}
|
||||
switch( format )
|
||||
{
|
||||
switch( format ) {
|
||||
case JPEG :
|
||||
{
|
||||
if ( !image.DecodeJpeg( buffer.extract( content_length ), content_length, colours, subpixelorder ) )
|
||||
{
|
||||
if ( !image.DecodeJpeg( buffer.extract( content_length ), content_length, colours, subpixelorder ) ) {
|
||||
Error( "Unable to decode jpeg" );
|
||||
Disconnect();
|
||||
return( -1 );
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case X_RGB :
|
||||
{
|
||||
if ( content_length != (long)image.Size() )
|
||||
{
|
||||
if ( content_length != (long)image.Size() ) {
|
||||
Error( "Image length mismatch, expected %d bytes, content length was %d", image.Size(), content_length );
|
||||
Disconnect();
|
||||
return( -1 );
|
||||
return -1;
|
||||
}
|
||||
image.Assign( width, height, colours, subpixelorder, buffer, imagesize );
|
||||
break;
|
||||
}
|
||||
case X_RGBZ :
|
||||
{
|
||||
if ( !image.Unzip( buffer.extract( content_length ), content_length ) )
|
||||
{
|
||||
if ( !image.Unzip( buffer.extract( content_length ), content_length ) ) {
|
||||
Error( "Unable to unzip RGB image" );
|
||||
Disconnect();
|
||||
return( -1 );
|
||||
return -1;
|
||||
}
|
||||
image.Assign( width, height, colours, subpixelorder, buffer, imagesize );
|
||||
break;
|
||||
|
@ -1140,13 +1128,12 @@ int RemoteCameraHttp::Capture( Image &image )
|
|||
{
|
||||
Error( "Unexpected image format encountered" );
|
||||
Disconnect();
|
||||
return( -1 );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return( 0 );
|
||||
return 1;
|
||||
}
|
||||
|
||||
int RemoteCameraHttp::PostCapture()
|
||||
{
|
||||
return( 0 );
|
||||
int RemoteCameraHttp::PostCapture() {
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -266,15 +266,15 @@ int RemoteCameraRtsp::Capture( Image &image ) {
|
|||
|
||||
/* Request a writeable buffer of the target image */
|
||||
directbuffer = image.WriteBuffer(width, height, colours, subpixelorder);
|
||||
if(directbuffer == NULL) {
|
||||
if ( directbuffer == NULL ) {
|
||||
Error("Failed requesting writeable buffer for the captured image.");
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ( true ) {
|
||||
buffer.clear();
|
||||
if ( !rtspThread->isRunning() )
|
||||
return (-1);
|
||||
return -1;
|
||||
|
||||
if ( rtspThread->getFrame( buffer ) ) {
|
||||
Debug( 3, "Read frame %d bytes", buffer.size() );
|
||||
|
@ -282,21 +282,21 @@ int RemoteCameraRtsp::Capture( Image &image ) {
|
|||
Hexdump( 4, buffer.head(), 16 );
|
||||
|
||||
if ( !buffer.size() )
|
||||
return( -1 );
|
||||
return -1;
|
||||
|
||||
if(mCodecContext->codec_id == AV_CODEC_ID_H264) {
|
||||
if ( mCodecContext->codec_id == AV_CODEC_ID_H264 ) {
|
||||
// SPS and PPS frames should be saved and appended to IDR frames
|
||||
int nalType = (buffer.head()[3] & 0x1f);
|
||||
|
||||
// SPS The SPS NAL unit contains parameters that apply to a series of consecutive coded video pictures
|
||||
if(nalType == 7) {
|
||||
if ( nalType == 7 ) {
|
||||
lastSps = buffer;
|
||||
continue;
|
||||
} else if(nalType == 8) {
|
||||
} else if ( nalType == 8 ) {
|
||||
// PPS The PPS NAL unit contains parameters that apply to the decoding of one or more individual pictures inside a coded video sequence
|
||||
lastPps = buffer;
|
||||
continue;
|
||||
} else if(nalType == 5) {
|
||||
} else if ( nalType == 5 ) {
|
||||
// IDR
|
||||
buffer += lastSps;
|
||||
buffer += lastPps;
|
||||
|
@ -357,13 +357,13 @@ int RemoteCameraRtsp::Capture( Image &image ) {
|
|||
zm_av_packet_unref( &packet );
|
||||
} /* getFrame() */
|
||||
|
||||
if(frameComplete)
|
||||
return (0);
|
||||
if ( frameComplete )
|
||||
return 1;
|
||||
|
||||
} // end while true
|
||||
|
||||
// can never get here.
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Function to handle capture and store
|
||||
|
|
|
@ -311,7 +311,7 @@ void StreamBase::openComms() {
|
|||
strncpy( rem_addr.sun_path, rem_sock_path, sizeof(rem_addr.sun_path) );
|
||||
rem_addr.sun_family = AF_UNIX;
|
||||
} // end if connKey > 0
|
||||
Debug(3, "comms open" );
|
||||
Debug(2, "comms open" );
|
||||
}
|
||||
|
||||
void StreamBase::closeComms() {
|
||||
|
|
|
@ -90,12 +90,12 @@ bool User::canAccess( int monitor_id ) {
|
|||
User *zmLoadUser( const char *username, const char *password ) {
|
||||
char sql[ZM_SQL_SML_BUFSIZ] = "";
|
||||
char safer_username[65]; // current db username size is 32
|
||||
char safer_password[129]; // current db password size is 64
|
||||
|
||||
// According to docs, size of safer_whatever must be 2*length+1 due to unicode conversions + null terminator.
|
||||
mysql_real_escape_string(&dbconn, safer_username, username, strlen( username ) );
|
||||
|
||||
if ( password ) {
|
||||
char safer_password[129]; // current db password size is 64
|
||||
mysql_real_escape_string(&dbconn, safer_password, password, strlen( password ) );
|
||||
snprintf( sql, sizeof(sql), "select Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds from Users where Username = '%s' and Password = password('%s') and Enabled = 1", safer_username, safer_password );
|
||||
} else {
|
||||
|
|
|
@ -80,7 +80,7 @@ const std::string stringtf( const char *format, ... )
|
|||
return( tempString );
|
||||
}
|
||||
|
||||
const std::string stringtf( const std::string &format, ... )
|
||||
const std::string stringtf( const std::string format, ... )
|
||||
{
|
||||
va_list ap;
|
||||
char tempBuffer[8192];
|
||||
|
@ -100,7 +100,7 @@ bool startsWith( const std::string &haystack, const std::string &needle )
|
|||
return( haystack.substr( 0, needle.length() ) == needle );
|
||||
}
|
||||
|
||||
StringVector split( const std::string &string, const std::string chars, int limit )
|
||||
StringVector split( const std::string &string, const std::string &chars, int limit )
|
||||
{
|
||||
StringVector stringVector;
|
||||
std::string tempString = string;
|
||||
|
@ -134,7 +134,7 @@ StringVector split( const std::string &string, const std::string chars, int limi
|
|||
return( stringVector );
|
||||
}
|
||||
|
||||
const std::string join(const StringVector v, const char * delim ) {
|
||||
const std::string join(const StringVector &v, const char * delim ) {
|
||||
std::stringstream ss;
|
||||
|
||||
for(size_t i = 0; i < v.size(); ++i) {
|
||||
|
|
|
@ -33,11 +33,11 @@ std::string trimSet(std::string str, std::string trimset);
|
|||
std::string replaceAll(std::string str, std::string from, std::string to);
|
||||
|
||||
const std::string stringtf( const char *format, ... );
|
||||
const std::string stringtf( const std::string &format, ... );
|
||||
const std::string stringtf( const std::string format, ... );
|
||||
|
||||
bool startsWith( const std::string &haystack, const std::string &needle );
|
||||
StringVector split( const std::string &string, const std::string chars, int limit=0 );
|
||||
const std::string join( const StringVector, const char * );
|
||||
StringVector split( const std::string &string, const std::string &chars, int limit=0 );
|
||||
const std::string join( const StringVector &, const char * );
|
||||
|
||||
const std::string base64Encode( const std::string &inString );
|
||||
|
||||
|
|
|
@ -823,19 +823,19 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
|
|||
int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
|
||||
Debug(4, "writeAudioFrame");
|
||||
|
||||
if (!audio_out_stream) {
|
||||
if ( !audio_out_stream ) {
|
||||
Debug(1, "Called writeAudioFramePacket when no audio_out_stream");
|
||||
return 0; // FIXME -ve return codes do not free packet in ffmpeg_camera at
|
||||
// the moment
|
||||
}
|
||||
|
||||
if (audio_out_codec) {
|
||||
if ( audio_out_codec ) {
|
||||
Debug(3, "Have audio codec");
|
||||
#ifdef HAVE_LIBAVRESAMPLE
|
||||
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||
ret = avcodec_send_packet(audio_in_ctx, ipkt);
|
||||
if (ret < 0) {
|
||||
if ( ret < 0 ) {
|
||||
Error("avcodec_send_packet fail %s", av_make_error_string(ret).c_str());
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -204,7 +204,6 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
|
|||
int diff_width = diff_image->Width();
|
||||
uint8_t* diff_buff = (uint8_t*)diff_image->Buffer();
|
||||
uint8_t* pdiff;
|
||||
const uint8_t* ppoly;
|
||||
|
||||
unsigned int pixel_diff_count = 0;
|
||||
|
||||
|
@ -267,6 +266,7 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
|
|||
int bx1 = bx-1;
|
||||
int by1 = by-1;
|
||||
|
||||
|
||||
Debug( 5, "Checking for filtered pixels" );
|
||||
if ( bx > 1 || by > 1 ) {
|
||||
// Now remove any pixels smaller than our filter size
|
||||
|
@ -679,7 +679,7 @@ bool Zone::CheckAlarms( const Image *delta_image ) {
|
|||
}
|
||||
}
|
||||
|
||||
ppoly = pg_image->Buffer( lo_x2, y );
|
||||
const uint8_t* ppoly = pg_image->Buffer( lo_x2, y );
|
||||
for ( int x = lo_x2; x <= hi_x2; x++, pdiff++, ppoly++ ) {
|
||||
if ( !*ppoly ) {
|
||||
*pdiff = BLACK;
|
||||
|
|
|
@ -161,7 +161,7 @@ int main(int argc, char *argv[]) {
|
|||
Usage();
|
||||
}
|
||||
|
||||
int modes = (device[0]?1:0 + host[0]?1:0 + file[0]?1:0 + (monitor_id > 0 ? 1 : 0));
|
||||
int modes = ( (device[0]?1:0) + (host[0]?1:0) + (file[0]?1:0) + (monitor_id > 0 ? 1 : 0));
|
||||
if ( modes > 1 ) {
|
||||
fprintf(stderr, "Only one of device, host/port/path, file or monitor id allowed\n");
|
||||
Usage();
|
||||
|
|
353
src/zmf.cpp
353
src/zmf.cpp
|
@ -1,353 +0,0 @@
|
|||
//
|
||||
// ZoneMinder Image File Writer Implementation, $Date$, $Revision$
|
||||
// Copyright (C) 2001-2008 Philip Coombes
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
//
|
||||
|
||||
/*
|
||||
|
||||
=head1 NAME
|
||||
|
||||
zmf - The ZoneMinder Frame daemon
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
zmf -m <monitor_id>
|
||||
zmf --monitor <monitor_id>
|
||||
zmf -h
|
||||
zmf --help
|
||||
zmf -v
|
||||
zmf --version
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is an optional daemon that can run in concert with the Analysis daemon and
|
||||
whose function it is to actually write captured frames to disk. This frees up
|
||||
the Analysis daemon to do more analysis (!) and so keep up with the Capture
|
||||
daemon better. If it isn't running or dies then the Analysis daemon just writes
|
||||
them itself.
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
-m, --monitor_id - ID of the monitor to use
|
||||
-h, --help - Display usage information
|
||||
-v, --version - Print the installed version of ZoneMinder
|
||||
|
||||
=cut
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <getopt.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "zm.h"
|
||||
#include "zm_db.h"
|
||||
#include "zm_signal.h"
|
||||
#include "zm_monitor.h"
|
||||
|
||||
#include "zmf.h"
|
||||
|
||||
int OpenSocket( int monitor_id )
|
||||
{
|
||||
int sd = socket( AF_UNIX, SOCK_STREAM, 0);
|
||||
if ( sd < 0 )
|
||||
{
|
||||
Error( "Can't create socket: %s", strerror(errno) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
char sock_path[PATH_MAX] = "";
|
||||
snprintf( sock_path, sizeof(sock_path), "%s/zmf-%d.sock", config.path_socks, monitor_id );
|
||||
if ( unlink( sock_path ) < 0 )
|
||||
{
|
||||
Warning( "Can't unlink '%s': %s", sock_path, strerror(errno) );
|
||||
}
|
||||
|
||||
struct sockaddr_un addr;
|
||||
|
||||
strncpy( addr.sun_path, sock_path, sizeof(addr.sun_path) );
|
||||
addr.sun_family = AF_UNIX;
|
||||
|
||||
if ( bind( sd, (struct sockaddr *)&addr, strlen(addr.sun_path)+sizeof(addr.sun_family)) < 0 )
|
||||
{
|
||||
Error( "Can't bind: %s", strerror(errno) );
|
||||
exit( -1 );
|
||||
}
|
||||
|
||||
if ( listen( sd, SOMAXCONN ) < 0 )
|
||||
{
|
||||
Error( "Can't listen: %s", strerror(errno) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
struct sockaddr_un rem_addr;
|
||||
socklen_t rem_addr_len = sizeof(rem_addr);
|
||||
int new_sd = -1;
|
||||
if ( (new_sd = accept( sd, (struct sockaddr *)&rem_addr, &rem_addr_len )) < 0 )
|
||||
{
|
||||
Error( "Can't accept: %s", strerror(errno) );
|
||||
exit( -1 );
|
||||
}
|
||||
close( sd );
|
||||
|
||||
sd = new_sd;
|
||||
|
||||
Info( "Frame server socket open, awaiting images" );
|
||||
return( sd );
|
||||
}
|
||||
|
||||
int ReopenSocket( int &sd, int monitor_id )
|
||||
{
|
||||
close( sd );
|
||||
return( sd = OpenSocket( monitor_id ) );
|
||||
}
|
||||
|
||||
void Usage()
|
||||
{
|
||||
fprintf( stderr, "zmf -m <monitor_id>\n" );
|
||||
fprintf( stderr, "Options:\n" );
|
||||
fprintf( stderr, " -m, --monitor <monitor_id> : Specify which monitor to use\n" );
|
||||
fprintf( stderr, " -h, --help : This screen\n" );
|
||||
fprintf( stderr, " -v, --version : Report the installed version of ZoneMinder\n" );
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
int main( int argc, char *argv[] )
|
||||
{
|
||||
self = argv[0];
|
||||
|
||||
srand( getpid() * time( 0 ) );
|
||||
|
||||
int id = -1;
|
||||
|
||||
static struct option long_options[] = {
|
||||
{"monitor", 1, 0, 'm'},
|
||||
{"help", 0, 0, 'h'},
|
||||
{"version", 0, 0, 'v'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
while (1)
|
||||
{
|
||||
int option_index = 0;
|
||||
|
||||
int c = getopt_long (argc, argv, "m:h:v", long_options, &option_index);
|
||||
if (c == -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 'm':
|
||||
id = atoi(optarg);
|
||||
break;
|
||||
case 'h':
|
||||
case '?':
|
||||
Usage();
|
||||
break;
|
||||
case 'v':
|
||||
std::cout << ZM_VERSION << "\n";
|
||||
exit(0);
|
||||
default:
|
||||
//fprintf( stderr, "?? getopt returned character code 0%o ??\n", c );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (optind < argc)
|
||||
{
|
||||
fprintf( stderr, "Extraneous options, " );
|
||||
while (optind < argc)
|
||||
printf ("%s ", argv[optind++]);
|
||||
printf ("\n");
|
||||
Usage();
|
||||
}
|
||||
|
||||
if ( id < 0 )
|
||||
{
|
||||
fprintf( stderr, "Bogus monitor %d\n", id );
|
||||
Usage();
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
char log_id_string[16];
|
||||
snprintf( log_id_string, sizeof(log_id_string), "m%d", id );
|
||||
|
||||
zmLoadConfig();
|
||||
|
||||
logInit( "zmf" );
|
||||
|
||||
hwcaps_detect();
|
||||
|
||||
Monitor *monitor = Monitor::Load( id, false, Monitor::QUERY );
|
||||
|
||||
if ( !monitor )
|
||||
{
|
||||
fprintf( stderr, "Can't find monitor with id of %d\n", id );
|
||||
exit( -1 );
|
||||
}
|
||||
|
||||
Storage *Storage = monitor->getStorage();
|
||||
|
||||
char capt_path[PATH_MAX];
|
||||
char anal_path[PATH_MAX];
|
||||
snprintf( capt_path, sizeof(capt_path), "%s/%d/%%s/%%0%dd-capture.jpg", Storage->Path(), monitor->Id(), config.event_image_digits );
|
||||
snprintf( anal_path, sizeof(anal_path), "%s/%d/%%s/%%0%dd-analyse.jpg", Storage->Path(), monitor->Id(), config.event_image_digits );
|
||||
zmSetDefaultTermHandler();
|
||||
zmSetDefaultDieHandler();
|
||||
|
||||
sigset_t block_set;
|
||||
sigemptyset( &block_set );
|
||||
|
||||
int sd = OpenSocket( monitor->Id() );
|
||||
|
||||
FrameHeader frame_header = { 0, 0, false, 0 };
|
||||
//unsigned char *image_data = 0;
|
||||
|
||||
fd_set rfds;
|
||||
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = 1;
|
||||
timeout.tv_usec = 0;
|
||||
while( 1 )
|
||||
{
|
||||
struct timeval temp_timeout = timeout;
|
||||
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(sd, &rfds);
|
||||
int n_found = select( sd+1, &rfds, NULL, NULL, &temp_timeout );
|
||||
if( n_found == 0 )
|
||||
{
|
||||
Debug( 1, "Select timed out" );
|
||||
continue;
|
||||
}
|
||||
else if ( n_found < 0)
|
||||
{
|
||||
Error( "Select error: %s", strerror(errno) );
|
||||
ReopenSocket( sd, monitor->Id() );
|
||||
continue;
|
||||
}
|
||||
|
||||
sigprocmask( SIG_BLOCK, &block_set, 0 );
|
||||
|
||||
int n_bytes = read( sd, &frame_header, sizeof(frame_header) );
|
||||
if ( n_bytes != sizeof(frame_header) )
|
||||
{
|
||||
if ( n_bytes < 0 )
|
||||
{
|
||||
Error( "Can't read frame header: %s", strerror(errno) );
|
||||
}
|
||||
else if ( n_bytes > 0 )
|
||||
{
|
||||
Error( "Incomplete read of frame header, %d bytes only", n_bytes );
|
||||
}
|
||||
else
|
||||
{
|
||||
Warning( "Socket closed at remote end" );
|
||||
}
|
||||
ReopenSocket( sd, monitor->Id() );
|
||||
continue;
|
||||
}
|
||||
Debug( 1, "Read frame header, expecting %ld bytes of image", frame_header.image_length );
|
||||
static unsigned char image_data[ZM_MAX_IMAGE_SIZE];
|
||||
|
||||
// Read for pipe and loop until bytes expected have been read or an error occurs
|
||||
int bytes_read = 0;
|
||||
do
|
||||
{
|
||||
n_bytes = read( sd, image_data+bytes_read, frame_header.image_length-bytes_read );
|
||||
if (n_bytes < 0) break; // break on error
|
||||
if (n_bytes < (int)frame_header.image_length)
|
||||
{
|
||||
// print some informational messages
|
||||
if (bytes_read == 0)
|
||||
{
|
||||
Debug(4,"Image read : Short read %d bytes of %d expected bytes",n_bytes,frame_header.image_length);
|
||||
}
|
||||
else if (bytes_read+n_bytes == (int)frame_header.image_length)
|
||||
{
|
||||
Debug(5,"Image read : Read rest of short read: %d bytes read total of %d bytes",n_bytes,frame_header.image_length);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug(6,"Image read : continuing, read %d bytes (%d so far)", n_bytes, bytes_read+n_bytes);
|
||||
}
|
||||
}
|
||||
bytes_read+= n_bytes;
|
||||
} while (n_bytes>0 && (bytes_read < (ssize_t)frame_header.image_length) );
|
||||
|
||||
// Print errors if there was a problem
|
||||
if ( n_bytes < 1 )
|
||||
{
|
||||
|
||||
Error( "Only read %d bytes of %d\n", bytes_read, frame_header.image_length);
|
||||
if ( n_bytes < 0 )
|
||||
{
|
||||
Error( "Can't read frame image data: %s", strerror(errno) );
|
||||
}
|
||||
else
|
||||
{
|
||||
Warning( "Socket closed at remote end" );
|
||||
}
|
||||
ReopenSocket( sd, monitor->Id() );
|
||||
continue;
|
||||
}
|
||||
|
||||
static char subpath[PATH_MAX] = "";
|
||||
if ( config.use_deep_storage )
|
||||
{
|
||||
struct tm *time = localtime( &frame_header.event_time );
|
||||
snprintf( subpath, sizeof(subpath), "%02d/%02d/%02d/%02d/%02d/%02d", time->tm_year-100, time->tm_mon+1, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec );
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf( subpath, sizeof(subpath), "%ld", frame_header.event_id );
|
||||
}
|
||||
|
||||
static char path[PATH_MAX] = "";
|
||||
snprintf( path, sizeof(path), frame_header.alarm_frame?anal_path:capt_path, subpath, frame_header.frame_id );
|
||||
Debug( 1, "Got image, writing to %s", path );
|
||||
|
||||
FILE *fd = 0;
|
||||
if ( (fd = fopen( path, "w" )) < 0 )
|
||||
{
|
||||
Error( "Can't fopen '%s': %s", path, strerror(errno) );
|
||||
exit( -1 );
|
||||
}
|
||||
if ( 0 == fwrite( image_data, frame_header.image_length, 1, fd ) )
|
||||
{
|
||||
Error( "Can't fwrite image data: %s", strerror(errno) );
|
||||
exit( -1 );
|
||||
}
|
||||
fclose( fd );
|
||||
|
||||
sigprocmask( SIG_UNBLOCK, &block_set, 0 );
|
||||
}
|
||||
logTerm();
|
||||
zmDbClose();
|
||||
}
|
|
@ -37,6 +37,8 @@ if ( $$opts{protocol} eq 'https' ) {
|
|||
die "https requires a server_name";
|
||||
}
|
||||
$VirtualHostPorts = ' *:443';
|
||||
} else {
|
||||
$VirtualHostPorts = ' *:80';
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,209 @@
|
|||
<?php
|
||||
function unparse_url($parsed_url, $substitutions = array() ) {
|
||||
$fields = array('scheme','host','port','user','pass','path','query','fragment');
|
||||
|
||||
foreach ( $fields as $field ) {
|
||||
if ( isset( $substitutions[$field] ) ) {
|
||||
$parsed_url[$field] = $substitutions[$field];
|
||||
}
|
||||
}
|
||||
$scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : '';
|
||||
$host = isset($parsed_url['host']) ? $parsed_url['host'] : '';
|
||||
$port = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : '';
|
||||
$user = isset($parsed_url['user']) ? $parsed_url['user'] : '';
|
||||
$pass = isset($parsed_url['pass']) ? ':' . $parsed_url['pass'] : '';
|
||||
$pass = ($user || $pass) ? "$pass@" : '';
|
||||
$path = isset($parsed_url['path']) ? $parsed_url['path'] : '';
|
||||
$query = isset($parsed_url['query']) ? '?' . $parsed_url['query'] : '';
|
||||
$fragment = isset($parsed_url['fragment']) ? '#' . $parsed_url['fragment'] : '';
|
||||
return "$scheme$user$pass$host$port$path$query$fragment";
|
||||
}
|
||||
|
||||
$defaultMonitor = new Monitor();
|
||||
$defaultMonitor->set(array(
|
||||
'StorageId' => 1,
|
||||
'ServerId' => 'auto',
|
||||
'Function' => 'Record',
|
||||
'Type' => 'Ffmpeg',
|
||||
'Enabled' => '1',
|
||||
'Colour' => '4', // 32bit
|
||||
'PreEventCount' => 0,
|
||||
) );
|
||||
|
||||
function probe( &$url_bits ) {
|
||||
global $defaultMonitor;
|
||||
$available_streams = array();
|
||||
if ( ! isset($url_bits['port']) ) {
|
||||
// No port given, do a port scan
|
||||
foreach ( range( 2000, 2007 ) as $port ) {
|
||||
$socket = socket_create( AF_INET, SOCK_STREAM, SOL_TCP );
|
||||
socket_set_option( $socket,
|
||||
SOL_SOCKET, // socket level
|
||||
SO_SNDTIMEO, // timeout option
|
||||
array(
|
||||
"sec"=>0, // Timeout in seconds
|
||||
"usec"=>500 // I assume timeout in microseconds
|
||||
)
|
||||
);
|
||||
$new_stream = null;
|
||||
Info("Testing connection to " . $url_bits['host'].':'.$port);
|
||||
if ( socket_connect( $socket, $url_bits['host'], $port ) ) {
|
||||
$new_stream = $url_bits; // make a copy
|
||||
$new_stream['port'] = $port;
|
||||
} else {
|
||||
socket_close($socket);
|
||||
Info("No connection to ".$url_bits['host'] . " on port $port");
|
||||
continue;
|
||||
}
|
||||
if ( $new_stream ) {
|
||||
if ( ! isset($new_stream['scheme'] ) )
|
||||
$new_stream['scheme'] = 'http';
|
||||
$url = unparse_url($new_stream, array('path'=>'/', 'query'=>'action=snapshot'));
|
||||
list($width, $height, $type, $attr) = getimagesize( $url );
|
||||
Info("Got $width x $height from $url");
|
||||
$new_stream['Width'] = $width;
|
||||
$new_stream['Height'] = $height;
|
||||
|
||||
//try {
|
||||
//if ( $response = do_request( 'GET', $url ) ) {
|
||||
//$new_stream['path'] = '/';
|
||||
//$new_stream['query'] = '?action=stream';
|
||||
//$image = imagecreatefromstring($response);
|
||||
////$size = getimagesize( $image );
|
||||
//
|
||||
//} else {
|
||||
//Info("No response from $url");
|
||||
//}
|
||||
//} catch ( EXception $e ) {
|
||||
//Info("No response from $url");
|
||||
//}
|
||||
$available_streams[] = $new_stream;
|
||||
} // end if new_Stream
|
||||
} // end foreach port to scan
|
||||
} else {
|
||||
// A port was specified, so don't need to port scan.
|
||||
$available_streams[] = $url_bits;
|
||||
}
|
||||
foreach ( $available_streams as &$stream ) {
|
||||
# check for existence in db.
|
||||
$stream['url'] = unparse_url( $stream, array( 'path'=>'/','query'=>'action=stream' ) );
|
||||
$monitors = Monitor::find_all( array( 'Path'=>$stream['url'] ) );
|
||||
if ( count($monitors ) ) {
|
||||
$stream['Monitor'] = $monitors[0];
|
||||
if ( isset( $stream['Width'] ) and ( $stream['Monitor']->Width() != $stream['Width'] ) ) {
|
||||
$stream['Warning'] .= 'Monitor width ('.$stream['Monitor']->Width().') and stream width ('.$stream['Width'].") do not match!\n";
|
||||
}
|
||||
if ( isset( $stream['Height'] ) and ( $stream['Monitor']->Height() != $stream['Height'] ) ) {
|
||||
$stream['Warning'] .= 'Monitor height ('.$stream['Monitor']->Height().') and stream width ('.$stream['Height'].") do not match!\n";
|
||||
}
|
||||
} else {
|
||||
$stream['Monitor'] = $defaultMonitor;
|
||||
if ( isset($stream['Width']) ) {
|
||||
$stream['Monitor']->Width( $stream['Width'] );
|
||||
$stream['Monitor']->Height( $stream['Height'] );
|
||||
}
|
||||
} // Monitor found or not
|
||||
} // end foreach Stream
|
||||
|
||||
#$macCommandString = 'arp ' . $url_bits['host'] . " | awk 'BEGIN{ i=1; } { i++; if(i==3) print $3 }'";
|
||||
#$mac = exec($macCommandString);
|
||||
#Info("Mac $mac");
|
||||
return $available_streams;
|
||||
} // end function probe
|
||||
|
||||
if ( canEdit( 'Monitors' ) ) {
|
||||
switch ( $_REQUEST['action'] ) {
|
||||
case 'probe' :
|
||||
{
|
||||
$available_streams = array();
|
||||
$url_bits = null;
|
||||
if ( preg_match('/(\d+)\.(\d+)\.(\d+)\.(\d+)/', $_REQUEST['url'] ) ) {
|
||||
$url_bits = array( 'host'=>$_REQUEST['url'] );
|
||||
} else {
|
||||
$url_bits = parse_url( $_REQUEST['url'] );
|
||||
}
|
||||
|
||||
if ( 0 ) {
|
||||
// Shortcut test
|
||||
$monitors = Monitor::find_all( array( 'Path'=>$_REQUEST['url'] ) );
|
||||
if ( count( $monitors ) ) {
|
||||
Info("Monitor found for " . $_REQUEST['url']);
|
||||
$url_bits['url'] = $_REQUEST['url'];
|
||||
$url_bits['Monitor'] = $monitors[0];
|
||||
$available_stream[] = $url_bits;
|
||||
ajaxResponse( array ( 'Streams'=>$available_streams) );
|
||||
return;
|
||||
} # end url already has a monitor
|
||||
}
|
||||
|
||||
if ( ! $url_bits ) {
|
||||
ajaxError("The given URL was too malformed to parse.");
|
||||
return;
|
||||
}
|
||||
|
||||
$available_streams = probe( $url_bits );
|
||||
|
||||
ajaxResponse( array('Streams'=>$available_streams) );
|
||||
return;
|
||||
} // end case url_probe
|
||||
case 'import':
|
||||
{
|
||||
|
||||
$file = $_FILES['import_file'];
|
||||
|
||||
if ($file["error"] > 0) {
|
||||
ajaxError($file["error"]);
|
||||
return;
|
||||
} else {
|
||||
$filename = $file["name"];
|
||||
|
||||
$available_streams = array();
|
||||
$row = 1;
|
||||
if (($handle = fopen($file['tmp_name'], 'r')) !== FALSE) {
|
||||
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
|
||||
$name = $data[0];
|
||||
$url = $data[1];
|
||||
$group = $data[2];
|
||||
Info("Have the following line data $name $url $group");
|
||||
|
||||
$url_bits = null;
|
||||
if ( preg_match('/(\d+)\.(\d+)\.(\d+)\.(\d+)/', $url) ) {
|
||||
$url_bits = array( 'host'=>$url, 'scheme'=>'http' );
|
||||
} else {
|
||||
$url_bits = parse_url( $url );
|
||||
}
|
||||
if ( ! $url_bits ) {
|
||||
Info("Bad url, skipping line $name $url $group");
|
||||
continue;
|
||||
}
|
||||
|
||||
$available_streams += probe( $url_bits );
|
||||
|
||||
//$url_bits['url'] = unparse_url( $url_bits );
|
||||
//$url_bits['Monitor'] = $defaultMonitor;
|
||||
//$url_bits['Monitor']->Name( $name );
|
||||
//$url_bits['Monitor']->merge( $_POST['newMonitor'] );
|
||||
//$available_streams[] = $url_bits;
|
||||
|
||||
} // end while rows
|
||||
fclose($handle);
|
||||
ajaxResponse( array('Streams'=>$available_streams) );
|
||||
} else {
|
||||
ajaxError("Uploaded file does not exist");
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
} // end case import
|
||||
default:
|
||||
{
|
||||
Warning("unknown action " . $_REQUEST['action'] );
|
||||
} // end ddcase default
|
||||
}
|
||||
} else {
|
||||
Warning("Cannot edit monitors" );
|
||||
}
|
||||
|
||||
ajaxError( 'Unrecognised action or insufficient permissions' );
|
||||
|
||||
?>
|
|
@ -1,170 +1,170 @@
|
|||
<?php
|
||||
|
||||
$statusData = array(
|
||||
"system" => array(
|
||||
"permission" => "System",
|
||||
"table" => "Monitors",
|
||||
"limit" => 1,
|
||||
"elements" => array(
|
||||
"MonitorCount" => array( "sql" => "count(*)" ),
|
||||
"ActiveMonitorCount" => array( "sql" => "count(if(Function != 'None',1,NULL))" ),
|
||||
"State" => array( "func" => "daemonCheck()?".translate('Running').":".translate('Stopped') ),
|
||||
"Load" => array( "func" => "getLoad()" ),
|
||||
"Disk" => array( "func" => "getDiskPercent()" ),
|
||||
'system' => array(
|
||||
'permission' => 'System',
|
||||
'table' => 'Monitors',
|
||||
'limit' => 1,
|
||||
'elements' => array(
|
||||
'MonitorCount' => array( 'sql' => "count(*)" ),
|
||||
'ActiveMonitorCount' => array( 'sql' => "count(if(Function != 'None',1,NULL))" ),
|
||||
'State' => array( 'func' => "daemonCheck()?".translate('Running').":".translate('Stopped') ),
|
||||
'Load' => array( 'func' => "getLoad()" ),
|
||||
'Disk' => array( 'func' => "getDiskPercent()" ),
|
||||
),
|
||||
),
|
||||
"monitor" => array(
|
||||
"permission" => "Monitors",
|
||||
"table" => "Monitors",
|
||||
"limit" => 1,
|
||||
"selector" => "Monitors.Id",
|
||||
"elements" => array(
|
||||
"Id" => array( "sql" => "Monitors.Id" ),
|
||||
"Name" => array( "sql" => "Monitors.Name" ),
|
||||
"Type" => true,
|
||||
"Function" => true,
|
||||
"Enabled" => true,
|
||||
"LinkedMonitors" => true,
|
||||
"Triggers" => true,
|
||||
"Device" => true,
|
||||
"Channel" => true,
|
||||
"Format" => true,
|
||||
"Host" => true,
|
||||
"Port" => true,
|
||||
"Path" => true,
|
||||
"Width" => array( "sql" => "Monitors.Width" ),
|
||||
"Height" => array( "sql" => "Monitors.Height" ),
|
||||
"Palette" => true,
|
||||
"Orientation" => true,
|
||||
"Brightness" => true,
|
||||
"Contrast" => true,
|
||||
"Hue" => true,
|
||||
"Colour" => true,
|
||||
"EventPrefix" => true,
|
||||
"LabelFormat" => true,
|
||||
"LabelX" => true,
|
||||
"LabelY" => true,
|
||||
"LabelSize" => true,
|
||||
"ImageBufferCount" => true,
|
||||
"WarmupCount" => true,
|
||||
"PreEventCount" => true,
|
||||
"PostEventCount" => true,
|
||||
"AlarmFrameCount" => true,
|
||||
"SectionLength" => true,
|
||||
"FrameSkip" => true,
|
||||
"MotionFrameSkip" => true,
|
||||
"MaxFPS" => true,
|
||||
"AlarmMaxFPS" => true,
|
||||
"FPSReportInterval" => true,
|
||||
"RefBlendPerc" => true,
|
||||
"Controllable" => true,
|
||||
"ControlId" => true,
|
||||
"ControlDevice" => true,
|
||||
"ControlAddress" => true,
|
||||
"AutoStopTimeout" => true,
|
||||
"TrackMotion" => true,
|
||||
"TrackDelay" => true,
|
||||
"ReturnLocation" => true,
|
||||
"ReturnDelay" => true,
|
||||
"DefaultView" => true,
|
||||
"DefaultRate" => true,
|
||||
"DefaultScale" => true,
|
||||
"WebColour" => true,
|
||||
"Sequence" => true,
|
||||
"MinEventId" => array( "sql" => "(SELECT min(Events.Id) FROM Events WHERE Events.MonitorId = Monitors.Id" ),
|
||||
"MaxEventId" => array( "sql" => "(SELECT max(Events.Id) FROM Events WHERE Events.MonitorId = Monitors.Id" ),
|
||||
"TotalEvents" => array( "sql" => "(SELECT count(Events.Id) FROM Events WHERE Events.MonitorId = Monitors.Id" ),
|
||||
"Status" => array( "zmu" => "-m ".escapeshellarg($_REQUEST['id'][0])." -s" ),
|
||||
"FrameRate" => array( "zmu" => "-m ".escapeshellarg($_REQUEST['id'][0])." -f" ),
|
||||
'monitor' => array(
|
||||
'permission' => 'Monitors',
|
||||
'table' => 'Monitors',
|
||||
'limit' => 1,
|
||||
'selector' => "Monitors.Id",
|
||||
'elements' => array(
|
||||
'Id' => array( 'sql' => "Monitors.Id" ),
|
||||
'Name' => array( 'sql' => "Monitors.Name" ),
|
||||
'Type' => true,
|
||||
'Function' => true,
|
||||
'Enabled' => true,
|
||||
'LinkedMonitors' => true,
|
||||
'Triggers' => true,
|
||||
'Device' => true,
|
||||
'Channel' => true,
|
||||
'Format' => true,
|
||||
'Host' => true,
|
||||
'Port' => true,
|
||||
'Path' => true,
|
||||
'Width' => array( 'sql' => "Monitors.Width" ),
|
||||
'Height' => array( 'sql' => "Monitors.Height" ),
|
||||
'Palette' => true,
|
||||
'Orientation' => true,
|
||||
'Brightness' => true,
|
||||
'Contrast' => true,
|
||||
'Hue' => true,
|
||||
'Colour' => true,
|
||||
'EventPrefix' => true,
|
||||
'LabelFormat' => true,
|
||||
'LabelX' => true,
|
||||
'LabelY' => true,
|
||||
'LabelSize' => true,
|
||||
'ImageBufferCount' => true,
|
||||
'WarmupCount' => true,
|
||||
'PreEventCount' => true,
|
||||
'PostEventCount' => true,
|
||||
'AlarmFrameCount' => true,
|
||||
'SectionLength' => true,
|
||||
'FrameSkip' => true,
|
||||
'MotionFrameSkip' => true,
|
||||
'MaxFPS' => true,
|
||||
'AlarmMaxFPS' => true,
|
||||
'FPSReportInterval' => true,
|
||||
'RefBlendPerc' => true,
|
||||
'Controllable' => true,
|
||||
'ControlId' => true,
|
||||
'ControlDevice' => true,
|
||||
'ControlAddress' => true,
|
||||
'AutoStopTimeout' => true,
|
||||
'TrackMotion' => true,
|
||||
'TrackDelay' => true,
|
||||
'ReturnLocation' => true,
|
||||
'ReturnDelay' => true,
|
||||
'DefaultView' => true,
|
||||
'DefaultRate' => true,
|
||||
'DefaultScale' => true,
|
||||
'WebColour' => true,
|
||||
'Sequence' => true,
|
||||
'MinEventId' => array( 'sql' => "(SELECT min(Events.Id) FROM Events WHERE Events.MonitorId = Monitors.Id" ),
|
||||
'MaxEventId' => array( 'sql' => "(SELECT max(Events.Id) FROM Events WHERE Events.MonitorId = Monitors.Id" ),
|
||||
'TotalEvents' => array( 'sql' => "(SELECT count(Events.Id) FROM Events WHERE Events.MonitorId = Monitors.Id" ),
|
||||
'Status' => array( 'zmu' => "-m ".escapeshellarg($_REQUEST['id'][0])." -s" ),
|
||||
'FrameRate' => array( 'zmu' => "-m ".escapeshellarg($_REQUEST['id'][0])." -f" ),
|
||||
),
|
||||
),
|
||||
"events" => array(
|
||||
"permission" => "Events",
|
||||
"table" => "Events",
|
||||
"selector" => "Events.MonitorId",
|
||||
"elements" => array(
|
||||
"Id" => true,
|
||||
"Name" => true,
|
||||
"Cause" => true,
|
||||
"Notes" => true,
|
||||
"StartTime" => true,
|
||||
"StartTimeShort" => array( "sql" => "date_format( StartTime, '".MYSQL_FMT_DATETIME_SHORT."' )" ),
|
||||
"EndTime" => true,
|
||||
"Width" => true,
|
||||
"Height" => true,
|
||||
"Length" => true,
|
||||
"Frames" => true,
|
||||
"AlarmFrames" => true,
|
||||
"TotScore" => true,
|
||||
"AvgScore" => true,
|
||||
"MaxScore" => true,
|
||||
'events' => array(
|
||||
'permission' => 'Events',
|
||||
'table' => 'Events',
|
||||
'selector' => "Events.MonitorId",
|
||||
'elements' => array(
|
||||
'Id' => true,
|
||||
'Name' => true,
|
||||
'Cause' => true,
|
||||
'Notes' => true,
|
||||
'StartTime' => true,
|
||||
'StartTimeShort' => array( 'sql' => "date_format( StartTime, '".MYSQL_FMT_DATETIME_SHORT."' )" ),
|
||||
'EndTime' => true,
|
||||
'Width' => true,
|
||||
'Height' => true,
|
||||
'Length' => true,
|
||||
'Frames' => true,
|
||||
'AlarmFrames' => true,
|
||||
'TotScore' => true,
|
||||
'AvgScore' => true,
|
||||
'MaxScore' => true,
|
||||
),
|
||||
),
|
||||
"event" => array(
|
||||
"permission" => "Events",
|
||||
"table" => "Events",
|
||||
"limit" => 1,
|
||||
"selector" => "Events.Id",
|
||||
"elements" => array(
|
||||
"Id" => array( "sql" => "Events.Id" ),
|
||||
"MonitorId" => true,
|
||||
"MonitorName" => array("sql" => "(SELECT Monitors.Name FROM Monitors WHERE Monitors.Id = Events.MonitorId)"),
|
||||
"Name" => true,
|
||||
"Cause" => true,
|
||||
"StartTime" => true,
|
||||
"StartTimeShort" => array( "sql" => "date_format( StartTime, '".MYSQL_FMT_DATETIME_SHORT."' )" ),
|
||||
"EndTime" => true,
|
||||
"Width" => true,
|
||||
"Height" => true,
|
||||
"Length" => true,
|
||||
"Frames" => true,
|
||||
"DefaultVideo" => true,
|
||||
"AlarmFrames" => true,
|
||||
"TotScore" => true,
|
||||
"AvgScore" => true,
|
||||
"MaxScore" => true,
|
||||
"Archived" => true,
|
||||
"Videoed" => true,
|
||||
"Uploaded" => true,
|
||||
"Emailed" => true,
|
||||
"Messaged" => true,
|
||||
"Executed" => true,
|
||||
"Notes" => true,
|
||||
"MinFrameId" => array( "sql" => "(SELECT min(Frames.FrameId) FROM Frames WHERE EventId=Events.Id)" ),
|
||||
"MaxFrameId" => array( "sql" => "(SELECT max(Frames.FrameId) FROM Frames WHERE Events.Id = Frames.EventId)" ),
|
||||
"MinFrameDelta" => array( "sql" => "(SELECT min(Frames.Delta) FROM Frames WHERE Events.Id = Frames.EventId)" ),
|
||||
"MaxFrameDelta" => array( "sql" => "(SELECT max(Frames.Delta) FROM Frames WHERE Events.Id = Frames.EventId)" ),
|
||||
//"Path" => array( "postFunc" => "getEventPath" ),
|
||||
'event' => array(
|
||||
'permission' => 'Events',
|
||||
'table' => 'Events',
|
||||
'limit' => 1,
|
||||
'selector' => "Events.Id",
|
||||
'elements' => array(
|
||||
'Id' => array( 'sql' => "Events.Id" ),
|
||||
'MonitorId' => true,
|
||||
'MonitorName' => array('sql' => "(SELECT Monitors.Name FROM Monitors WHERE Monitors.Id = Events.MonitorId)"),
|
||||
'Name' => true,
|
||||
'Cause' => true,
|
||||
'StartTime' => true,
|
||||
'StartTimeShort' => array( 'sql' => "date_format( StartTime, '".MYSQL_FMT_DATETIME_SHORT."' )" ),
|
||||
'EndTime' => true,
|
||||
'Width' => true,
|
||||
'Height' => true,
|
||||
'Length' => true,
|
||||
'Frames' => true,
|
||||
'DefaultVideo' => true,
|
||||
'AlarmFrames' => true,
|
||||
'TotScore' => true,
|
||||
'AvgScore' => true,
|
||||
'MaxScore' => true,
|
||||
'Archived' => true,
|
||||
'Videoed' => true,
|
||||
'Uploaded' => true,
|
||||
'Emailed' => true,
|
||||
'Messaged' => true,
|
||||
'Executed' => true,
|
||||
'Notes' => true,
|
||||
'MinFrameId' => array( 'sql' => "(SELECT min(Frames.FrameId) FROM Frames WHERE EventId=Events.Id)" ),
|
||||
'MaxFrameId' => array( 'sql' => "(SELECT max(Frames.FrameId) FROM Frames WHERE Events.Id = Frames.EventId)" ),
|
||||
'MinFrameDelta' => array( 'sql' => "(SELECT min(Frames.Delta) FROM Frames WHERE Events.Id = Frames.EventId)" ),
|
||||
'MaxFrameDelta' => array( 'sql' => "(SELECT max(Frames.Delta) FROM Frames WHERE Events.Id = Frames.EventId)" ),
|
||||
//'Path' => array( 'postFunc' => 'getEventPath' ),
|
||||
),
|
||||
),
|
||||
"frame" => array(
|
||||
"permission" => "Events",
|
||||
"table" => "Frames",
|
||||
"limit" => 1,
|
||||
"selector" => array( array( "table" => "Events", "join" => "Events.Id = Frames.EventId", "selector"=>"Events.Id" ), "Frames.FrameId" ),
|
||||
"elements" => array(
|
||||
//"Id" => array( "sql" => "Frames.FrameId" ),
|
||||
"FrameId" => true,
|
||||
"EventId" => true,
|
||||
"Type" => true,
|
||||
"TimeStamp" => true,
|
||||
"TimeStampShort" => array( "sql" => "date_format( StartTime, '".MYSQL_FMT_DATETIME_SHORT."' )" ),
|
||||
"Delta" => true,
|
||||
"Score" => true,
|
||||
//"Image" => array( "postFunc" => "getFrameImage" ),
|
||||
'frame' => array(
|
||||
'permission' => 'Events',
|
||||
'table' => 'Frames',
|
||||
'limit' => 1,
|
||||
'selector' => array( array( 'table' => 'Events', 'join' => "Events.Id = Frames.EventId", 'selector'=>"Events.Id" ), "Frames.FrameId" ),
|
||||
'elements' => array(
|
||||
//'Id' => array( 'sql' => "Frames.FrameId" ),
|
||||
'FrameId' => true,
|
||||
'EventId' => true,
|
||||
'Type' => true,
|
||||
'TimeStamp' => true,
|
||||
'TimeStampShort' => array( 'sql' => "date_format( StartTime, '".MYSQL_FMT_DATETIME_SHORT."' )" ),
|
||||
'Delta' => true,
|
||||
'Score' => true,
|
||||
//'Image' => array( 'postFunc' => 'getFrameImage' ),
|
||||
),
|
||||
),
|
||||
"frameimage" => array(
|
||||
"permission" => "Events",
|
||||
"func" => "getFrameImage()"
|
||||
'frameimage' => array(
|
||||
'permission' => 'Events',
|
||||
'func' => "getFrameImage()"
|
||||
),
|
||||
"nearframe" => array(
|
||||
"permission" => "Events",
|
||||
"func" => "getNearFrame()"
|
||||
'nearframe' => array(
|
||||
'permission' => 'Events',
|
||||
'func' => "getNearFrame()"
|
||||
),
|
||||
"nearevents" => array(
|
||||
"permission" => "Events",
|
||||
"func" => "getNearEvents()"
|
||||
'nearevents' => array(
|
||||
'permission' => 'Events',
|
||||
'func' => "getNearEvents()"
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -290,7 +290,7 @@ function collectData() {
|
|||
$data = collectData();
|
||||
|
||||
if ( !isset($_REQUEST['layout']) ) {
|
||||
$_REQUEST['layout'] = "json";
|
||||
$_REQUEST['layout'] = 'json';
|
||||
}
|
||||
|
||||
switch( $_REQUEST['layout'] ) {
|
||||
|
@ -331,7 +331,7 @@ function getFrameImage() {
|
|||
$frame = array();
|
||||
$frame['EventId'] = $eventId;
|
||||
$frame['FrameId'] = $frameId;
|
||||
$frame['Type'] = "Virtual";
|
||||
$frame['Type'] = 'Virtual';
|
||||
}
|
||||
$event = dbFetchOne( 'select * from Events where Id = ?', NULL, array( $frame['EventId'] ) );
|
||||
$frame['Image'] = getImageSrc( $event, $frame, SCALE_BASE );
|
||||
|
@ -349,7 +349,7 @@ function getNearFrame() {
|
|||
return( array() );
|
||||
}
|
||||
}
|
||||
$_REQUEST['entity'] = "frame";
|
||||
$_REQUEST['entity'] = 'frame';
|
||||
$_REQUEST['id'][1] = $nearFrameId;
|
||||
return( collectData() );
|
||||
}
|
||||
|
@ -358,7 +358,7 @@ function getNearEvents() {
|
|||
global $user, $sortColumn, $sortOrder;
|
||||
|
||||
$eventId = $_REQUEST['id'];
|
||||
$event = dbFetchOne( 'select * from Events where Id = ?', NULL, array( $eventId ) );
|
||||
$event = dbFetchOne( 'SELECT * FROM Events WHERE Id=?', NULL, array( $eventId ) );
|
||||
|
||||
parseFilter( $_REQUEST['filter'] );
|
||||
parseSort();
|
||||
|
@ -368,7 +368,7 @@ function getNearEvents() {
|
|||
else
|
||||
$midSql = '';
|
||||
|
||||
$sql = "select E.Id as Id, E.StartTime as StartTime from Events as E inner join Monitors as M on E.MonitorId = M.Id where $sortColumn ".($sortOrder=='asc'?'<=':'>=')." '".$event[$_REQUEST['sort_field']]."'".$_REQUEST['filter']['sql'].$midSql." order by $sortColumn ".($sortOrder=='asc'?'desc':'asc');
|
||||
$sql = "SELECT E.Id AS Id, E.StartTime AS StartTime FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE $sortColumn ".($sortOrder=='asc'?'<=':'>=')." '".$event[$_REQUEST['sort_field']]."'".$_REQUEST['filter']['sql'].$midSql." ORDER BY $sortColumn ".($sortOrder=='asc'?'desc':'asc') . ' LIMIT 2';
|
||||
$result = dbQuery( $sql );
|
||||
while ( $id = dbFetchNext( $result, 'Id' ) ) {
|
||||
if ( $id == $eventId ) {
|
||||
|
@ -377,7 +377,7 @@ function getNearEvents() {
|
|||
}
|
||||
}
|
||||
|
||||
$sql = "select E.Id as Id, E.StartTime as StartTime from Events as E inner join Monitors as M on E.MonitorId = M.Id where $sortColumn ".($sortOrder=='asc'?'>=':'<=')." '".$event[$_REQUEST['sort_field']]."'".$_REQUEST['filter']['sql'].$midSql." order by $sortColumn $sortOrder";
|
||||
$sql = "SELECT E.Id AS Id, E.StartTime AS StartTime FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE $sortColumn ".($sortOrder=='asc'?'>=':'<=')." '".$event[$_REQUEST['sort_field']]."'".$_REQUEST['filter']['sql'].$midSql." ORDER BY $sortColumn $sortOrder LIMIT 2";
|
||||
$result = dbQuery( $sql );
|
||||
while ( $id = dbFetchNext( $result, 'Id' ) ) {
|
||||
if ( $id == $eventId ) {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
$start_time = time();
|
||||
|
||||
define( "MSG_TIMEOUT", ZM_WEB_AJAX_TIMEOUT );
|
||||
define( "MSG_DATA_SIZE", 4+256 );
|
||||
|
||||
|
@ -11,39 +13,48 @@ if ( !($socket = @socket_create( AF_UNIX, SOCK_DGRAM, 0 )) ) {
|
|||
ajaxError( "socket_create() failed: ".socket_strerror(socket_last_error()) );
|
||||
}
|
||||
$locSockFile = ZM_PATH_SOCKS.'/zms-'.sprintf("%06d",$_REQUEST['connkey']).'w.sock';
|
||||
if ( file_exists( $locSockFile ) ) {
|
||||
Warning("sock file $locSockFile already exists?! Is someone else talking to zms?");
|
||||
} else {
|
||||
Logger::Debug("socket file does not exist, we should be good to connect.");
|
||||
}
|
||||
if ( !@socket_bind( $socket, $locSockFile ) ) {
|
||||
ajaxError( "socket_bind( $locSockFile ) failed: ".socket_strerror(socket_last_error()) );
|
||||
} else {
|
||||
Logger::Debug("Bound to $locSockFile");
|
||||
}
|
||||
|
||||
switch ( $_REQUEST['command'] ) {
|
||||
case CMD_VARPLAY :
|
||||
Logger::Debug( "Varplaying to ".$_REQUEST['rate'] );
|
||||
$msg = pack( "lcn", MSG_CMD, $_REQUEST['command'], $_REQUEST['rate']+32768 );
|
||||
Logger::Debug( 'Varplaying to '.$_REQUEST['rate'] );
|
||||
$msg = pack( 'lcn', MSG_CMD, $_REQUEST['command'], $_REQUEST['rate']+32768 );
|
||||
break;
|
||||
case CMD_ZOOMIN :
|
||||
Logger::Debug( "Zooming to ".$_REQUEST['x'].",".$_REQUEST['y'] );
|
||||
$msg = pack( "lcnn", MSG_CMD, $_REQUEST['command'], $_REQUEST['x'], $_REQUEST['y'] );
|
||||
Logger::Debug( 'Zooming to '.$_REQUEST['x'].",".$_REQUEST['y'] );
|
||||
$msg = pack( 'lcnn', MSG_CMD, $_REQUEST['command'], $_REQUEST['x'], $_REQUEST['y'] );
|
||||
break;
|
||||
case CMD_PAN :
|
||||
Logger::Debug( "Panning to ".$_REQUEST['x'].",".$_REQUEST['y'] );
|
||||
$msg = pack( "lcnn", MSG_CMD, $_REQUEST['command'], $_REQUEST['x'], $_REQUEST['y'] );
|
||||
Logger::Debug( 'Panning to '.$_REQUEST['x'].",".$_REQUEST['y'] );
|
||||
$msg = pack( 'lcnn', MSG_CMD, $_REQUEST['command'], $_REQUEST['x'], $_REQUEST['y'] );
|
||||
break;
|
||||
case CMD_SCALE :
|
||||
Logger::Debug( "Scaling to ".$_REQUEST['scale'] );
|
||||
$msg = pack( "lcn", MSG_CMD, $_REQUEST['command'], $_REQUEST['scale'] );
|
||||
Logger::Debug( 'Scaling to '.$_REQUEST['scale'] );
|
||||
$msg = pack( 'lcn', MSG_CMD, $_REQUEST['command'], $_REQUEST['scale'] );
|
||||
break;
|
||||
case CMD_SEEK :
|
||||
Logger::Debug( "Seeking to ".$_REQUEST['offset'] );
|
||||
$msg = pack( "lcN", MSG_CMD, $_REQUEST['command'], $_REQUEST['offset'] );
|
||||
Logger::Debug( 'Seeking to '.$_REQUEST['offset'] );
|
||||
$msg = pack( 'lcN', MSG_CMD, $_REQUEST['command'], $_REQUEST['offset'] );
|
||||
break;
|
||||
default :
|
||||
$msg = pack( "lc", MSG_CMD, $_REQUEST['command'] );
|
||||
$msg = pack( 'lc', MSG_CMD, $_REQUEST['command'] );
|
||||
break;
|
||||
}
|
||||
|
||||
$remSockFile = ZM_PATH_SOCKS.'/zms-'.sprintf("%06d",$_REQUEST['connkey']).'s.sock';
|
||||
$remSockFile = ZM_PATH_SOCKS.'/zms-'.sprintf('%06d',$_REQUEST['connkey']).'s.sock';
|
||||
$max_socket_tries = 10;
|
||||
// FIXME This should not exceed web_ajax_timeout
|
||||
while ( !file_exists($remSockFile) && $max_socket_tries-- ) { //sometimes we are too fast for our own good, if it hasn't been setup yet give it a second.
|
||||
Logger::Debug("$remSockFile does not exist, waiting, current " . (time() - $start_time) . ' seconds' );
|
||||
usleep(200000);
|
||||
}
|
||||
|
||||
|
@ -58,17 +69,26 @@ if ( !file_exists($remSockFile) ) {
|
|||
$rSockets = array( $socket );
|
||||
$wSockets = NULL;
|
||||
$eSockets = NULL;
|
||||
$numSockets = @socket_select( $rSockets, $wSockets, $eSockets, intval(MSG_TIMEOUT/1000), (MSG_TIMEOUT%1000)*1000 );
|
||||
|
||||
$timeout = MSG_TIMEOUT - ( time() - $start_time );
|
||||
Logger::Debug("TImeout is: $timeout " );
|
||||
|
||||
$numSockets = @socket_select( $rSockets, $wSockets, $eSockets, intval($timeout/1000), ($timeout%1000)*1000 );
|
||||
|
||||
if ( $numSockets === false ) {
|
||||
Error("socket_select failed: " . socket_strerror(socket_last_error()) );
|
||||
ajaxError( "socket_select failed: ".socket_strerror(socket_last_error()) );
|
||||
} else if ( $numSockets < 0 ) {
|
||||
Error( "Socket closed $remSockFile" );
|
||||
ajaxError( "Socket closed $remSockFile" );
|
||||
} else if ( $numSockets == 0 ) {
|
||||
Error( "Timed out waiting for msg $remSockFile" );
|
||||
ajaxError( "Timed out waiting for msg $remSockFile" );
|
||||
} else if ( $numSockets > 0 ) {
|
||||
if ( count($rSockets) != 1 )
|
||||
ajaxError( "Bogus return from select, ".count($rSockets)." sockets available" );
|
||||
if ( count($rSockets) != 1 ) {
|
||||
Error( "Bogus return from select, ".count($rSockets).' sockets available' );
|
||||
ajaxError( "Bogus return from select, ".count($rSockets).' sockets available' );
|
||||
}
|
||||
}
|
||||
|
||||
switch( $nbytes = @socket_recvfrom( $socket, $msg, MSG_DATA_SIZE, 0, $remSockFile ) ) {
|
||||
|
@ -79,7 +99,7 @@ switch( $nbytes = @socket_recvfrom( $socket, $msg, MSG_DATA_SIZE, 0, $remSockFil
|
|||
}
|
||||
case 0 :
|
||||
{
|
||||
ajaxError( "No data to read from socket" );
|
||||
ajaxError( 'No data to read from socket' );
|
||||
break;
|
||||
}
|
||||
default :
|
||||
|
@ -90,7 +110,7 @@ switch( $nbytes = @socket_recvfrom( $socket, $msg, MSG_DATA_SIZE, 0, $remSockFil
|
|||
}
|
||||
}
|
||||
|
||||
$data = unpack( "ltype", $msg );
|
||||
$data = unpack( 'ltype', $msg );
|
||||
switch ( $data['type'] ) {
|
||||
case MSG_DATA_WATCH :
|
||||
{
|
||||
|
@ -99,7 +119,7 @@ switch ( $data['type'] ) {
|
|||
$data['rate'] /= RATE_BASE;
|
||||
$data['delay'] = round( $data['delay'], 2 );
|
||||
$data['zoom'] = round( $data['zoom']/SCALE_BASE, 1 );
|
||||
if ( ZM_OPT_USE_AUTH && ZM_AUTH_RELAY == "hashed" ) {
|
||||
if ( ZM_OPT_USE_AUTH && ZM_AUTH_RELAY == 'hashed' ) {
|
||||
session_start();
|
||||
$time = time();
|
||||
// Regenerate auth hash after half the lifetime of the hash
|
||||
|
@ -117,7 +137,7 @@ switch ( $data['type'] ) {
|
|||
//$data['progress'] = sprintf( "%.2f", $data['progress'] );
|
||||
$data['rate'] /= RATE_BASE;
|
||||
$data['zoom'] = round( $data['zoom']/SCALE_BASE, 1 );
|
||||
if ( ZM_OPT_USE_AUTH && ZM_AUTH_RELAY == "hashed" ) {
|
||||
if ( ZM_OPT_USE_AUTH && ZM_AUTH_RELAY == 'hashed' ) {
|
||||
session_start();
|
||||
$time = time();
|
||||
// Regenerate auth hash after half the lifetime of the hash
|
||||
|
|
|
@ -4,13 +4,17 @@ require_once( 'Server.php' );
|
|||
|
||||
class Monitor {
|
||||
|
||||
private $fields = array(
|
||||
'Id',
|
||||
'Name',
|
||||
'StorageId',
|
||||
'ServerId',
|
||||
'Function',
|
||||
'Enabled',
|
||||
private $defaults = array(
|
||||
'Id' => null,
|
||||
'Name' => '',
|
||||
'StorageId' => 0,
|
||||
'ServerId' => 0,
|
||||
'Function' => 'None',
|
||||
'Enabled' => 1,
|
||||
'Width' => null,
|
||||
'Height' => null,
|
||||
'Orientation' => null,
|
||||
'AnalysisFPSLimit' => null,
|
||||
);
|
||||
private $control_fields = array(
|
||||
'Name' => '',
|
||||
|
@ -158,19 +162,20 @@ private $control_fields = array(
|
|||
public function Server() {
|
||||
return new Server( $this->{'ServerId'} );
|
||||
}
|
||||
public function __call( $fn, array $args){
|
||||
if ( count( $args ) ) {
|
||||
public function __call($fn, array $args){
|
||||
if ( count($args) ) {
|
||||
$this->{$fn} = $args[0];
|
||||
}
|
||||
if ( array_key_exists( $fn, $this ) ) {
|
||||
if ( array_key_exists($fn, $this) ) {
|
||||
return $this->{$fn};
|
||||
#array_unshift($args, $this);
|
||||
#call_user_func_array( $this->{$fn}, $args);
|
||||
} else {
|
||||
if ( array_key_exists( $fn, $this->control_fields ) ) {
|
||||
if ( array_key_exists($fn, $this->control_fields) ) {
|
||||
return $this->control_fields{$fn};
|
||||
} else if ( array_key_exists( $fn, $this->defaults ) ) {
|
||||
return $this->defaults{$fn};
|
||||
} else {
|
||||
|
||||
$backTrace = debug_backtrace();
|
||||
$file = $backTrace[1]['file'];
|
||||
$line = $backTrace[1]['line'];
|
||||
|
@ -214,14 +219,19 @@ private $control_fields = array(
|
|||
return( $streamSrc );
|
||||
} // end function getStreamSrc
|
||||
|
||||
public function Width() {
|
||||
public function Width( $new = null ) {
|
||||
if ( $new )
|
||||
$this->{'Width'} = $new;
|
||||
|
||||
if ( $this->Orientation() == '90' or $this->Orientation() == '270' ) {
|
||||
return $this->{'Height'};
|
||||
}
|
||||
return $this->{'Width'};
|
||||
}
|
||||
|
||||
public function Height() {
|
||||
public function Height( $new=null ) {
|
||||
if ( $new )
|
||||
$this->{'Height'} = $new;
|
||||
if ( $this->Orientation() == '90' or $this->Orientation() == '270' ) {
|
||||
return $this->{'Width'};
|
||||
}
|
||||
|
@ -287,11 +297,12 @@ private $control_fields = array(
|
|||
}
|
||||
}
|
||||
|
||||
$sql = 'UPDATE Monitors SET '.implode(', ', array_map( function($field) {return $field.'=?';}, $this->fields ) ) . ' WHERE Id=?';
|
||||
$sql = 'UPDATE Monitors SET '.implode(', ', array_map( function($field) {return $field.'=?';}, array_keys( $this->defaults ) ) ) . ' WHERE Id=?';
|
||||
$values = array_map( function($field){return $this->{$field};}, $this->fields );
|
||||
$values[] = $this->{'Id'};
|
||||
dbQuery( $sql, $values );
|
||||
} // end function save
|
||||
|
||||
function zmcControl( $mode=false ) {
|
||||
if ( (!defined('ZM_SERVER_ID')) or ( ZM_SERVER_ID==$this->{'ServerId'} ) ) {
|
||||
if ( $this->{'Type'} == 'Local' ) {
|
||||
|
@ -306,6 +317,7 @@ private $control_fields = array(
|
|||
if ( $mode == 'restart' ) {
|
||||
daemonControl( 'stop', 'zmc', $zmcArgs );
|
||||
}
|
||||
if ( $this->{'Function'} != 'None' )
|
||||
daemonControl( 'start', 'zmc', $zmcArgs );
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
<?php
|
||||
|
||||
require_once('database.php');
|
||||
|
||||
class MontageLayout {
|
||||
|
||||
private $defaults = array(
|
||||
'Id' => null,
|
||||
'Name' => '',
|
||||
'Positions' => 0,
|
||||
);
|
||||
|
||||
public function __construct( $IdOrRow = NULL ) {
|
||||
if ( $IdOrRow ) {
|
||||
$row = NULL;
|
||||
if ( is_integer( $IdOrRow ) or is_numeric( $IdOrRow ) ) {
|
||||
$row = dbFetchOne( 'SELECT * FROM MontageLayouts WHERE Id=?', NULL, array( $IdOrRow ) );
|
||||
if ( ! $row ) {
|
||||
Error("Unable to load MontageLayout record for Id=" . $IdOrRow );
|
||||
}
|
||||
} elseif ( is_array( $IdOrRow ) ) {
|
||||
$row = $IdOrRow;
|
||||
} else {
|
||||
Error("Unknown argument passed to MontageLayout Constructor ($IdOrRow)");
|
||||
return;
|
||||
}
|
||||
|
||||
if ( $row ) {
|
||||
foreach ($row as $k => $v) {
|
||||
$this->{$k} = $v;
|
||||
}
|
||||
} else {
|
||||
Error('No row for MontageLayout ' . $IdOrRow );
|
||||
}
|
||||
} # end if isset($IdOrRow)
|
||||
} // end function __construct
|
||||
|
||||
public function __call($fn, array $args){
|
||||
if ( count($args) ) {
|
||||
$this->{$fn} = $args[0];
|
||||
}
|
||||
if ( array_key_exists($fn, $this) ) {
|
||||
return $this->{$fn};
|
||||
} else {
|
||||
if ( array_key_exists( $fn, $this->defaults ) ) {
|
||||
return $this->defaults{$fn};
|
||||
} else {
|
||||
$backTrace = debug_backtrace();
|
||||
$file = $backTrace[1]['file'];
|
||||
$line = $backTrace[1]['line'];
|
||||
Warning( "Unknown function call MontageLayout->$fn from $file:$line" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function set( $data ) {
|
||||
foreach ($data as $k => $v) {
|
||||
if ( is_array( $v ) ) {
|
||||
# perhaps should turn into a comma-separated string
|
||||
$this->{$k} = implode(',',$v);
|
||||
} else if ( is_string( $v ) ) {
|
||||
$this->{$k} = trim( $v );
|
||||
} else if ( is_integer( $v ) ) {
|
||||
$this->{$k} = $v;
|
||||
} else if ( is_bool( $v ) ) {
|
||||
$this->{$k} = $v;
|
||||
} else {
|
||||
Error( "Unknown type $k => $v of var " . gettype( $v ) );
|
||||
$this->{$k} = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
public static function find( $parameters = null, $options = null ) {
|
||||
$filters = array();
|
||||
$sql = 'SELECT * FROM MontageLayouts ';
|
||||
$values = array();
|
||||
|
||||
if ( $parameters ) {
|
||||
$fields = array();
|
||||
$sql .= 'WHERE ';
|
||||
foreach ( $parameters as $field => $value ) {
|
||||
if ( $value == null ) {
|
||||
$fields[] = $field.' IS NULL';
|
||||
} else if ( is_array( $value ) ) {
|
||||
$func = function(){return '?';};
|
||||
$fields[] = $field.' IN ('.implode(',', array_map( $func, $value ) ). ')';
|
||||
$values += $value;
|
||||
|
||||
} else {
|
||||
$fields[] = $field.'=?';
|
||||
$values[] = $value;
|
||||
}
|
||||
}
|
||||
$sql .= implode(' AND ', $fields );
|
||||
}
|
||||
if ( $options and isset($options['order']) ) {
|
||||
$sql .= ' ORDER BY ' . $options['order'];
|
||||
}
|
||||
$result = dbQuery($sql, $values);
|
||||
if ( $result ) {
|
||||
$results = $result->fetchALL(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'MontageLayout');
|
||||
foreach ( $results as $row => $obj ) {
|
||||
$filters[] = $obj;
|
||||
}
|
||||
}
|
||||
return $filters;
|
||||
}
|
||||
public function save( $new_values = null ) {
|
||||
if ( $new_values ) {
|
||||
foreach ( $new_values as $k=>$v ) {
|
||||
$this->{$k} = $v;
|
||||
}
|
||||
}
|
||||
|
||||
$fields = array_values( array_filter( array_keys($this->defaults), function($field){return $field != 'Id';} ) );
|
||||
$values = null;
|
||||
if ( isset($this->{'Id'}) ) {
|
||||
$sql = 'UPDATE MontageLayouts SET '.implode(', ', array_map( function($field) {return $field.'=?';}, $fields ) ) . ' WHERE Id=?';
|
||||
$values = array_map( function($field){return $this->{$field};}, $fields );
|
||||
$values[] = $this->{'Id'};
|
||||
dbQuery( $sql, $values );
|
||||
} else {
|
||||
$sql = 'INSERT INTO MontageLayouts ('.implode( ',', $fields ).') VALUES ('.implode(',',array_map( function(){return '?';}, $fields ) ).')';
|
||||
$values = array_map( function($field){return $this->{$field};}, $fields );
|
||||
dbQuery( $sql, $values );
|
||||
global $dbConn;
|
||||
$this->{Id} = $dbConn->lastInsertId();
|
||||
}
|
||||
} // end function save
|
||||
|
||||
} // end class MontageLayout
|
||||
?>
|
|
@ -18,11 +18,32 @@
|
|||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
//
|
||||
|
||||
|
||||
// PP - POST request handler for PHP which does not need extensions
|
||||
// credit: http://wezfurlong.org/blog/2006/nov/http-post-from-php-without-curl/
|
||||
|
||||
|
||||
function do_request($method, $url, $data=array(), $optional_headers = null) {
|
||||
global $php_errormsg;
|
||||
|
||||
$params = array('http' => array(
|
||||
'method' => $method,
|
||||
'content' => $data
|
||||
));
|
||||
if ($optional_headers !== null) {
|
||||
$params['http']['header'] = $optional_headers;
|
||||
}
|
||||
$ctx = stream_context_create($params);
|
||||
$fp = @fopen($url, 'rb', false, $ctx);
|
||||
if (!$fp) {
|
||||
throw new Exception("Problem with $url, $php_errormsg");
|
||||
}
|
||||
$response = @stream_get_contents($fp);
|
||||
if ($response === false) {
|
||||
throw new Exception("Problem reading data from $url, $php_errormsg");
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
function do_post_request($url, $data, $optional_headers = null) {
|
||||
$params = array('http' => array(
|
||||
'method' => 'POST',
|
||||
|
@ -56,23 +77,25 @@ function getAffectedIds( $name ) {
|
|||
}
|
||||
|
||||
|
||||
if ( !empty($action) ) {
|
||||
if ( $action == 'login' && isset($_REQUEST['username']) && ( ZM_AUTH_TYPE == 'remote' || isset($_REQUEST['password']) ) ) {
|
||||
if ( empty($action) ) {
|
||||
return;
|
||||
}
|
||||
if ( $action == 'login' && isset($_REQUEST['username']) && ( ZM_AUTH_TYPE == 'remote' || isset($_REQUEST['password']) ) ) {
|
||||
// if true, a popup will display after login
|
||||
// PP - lets validate reCaptcha if it exists
|
||||
if ( defined('ZM_OPT_USE_GOOG_RECAPTCHA')
|
||||
&& defined('ZM_OPT_GOOG_RECAPTCHA_SECRETKEY')
|
||||
&& defined('ZM_OPT_GOOG_RECAPTCHA_SITEKEY')
|
||||
&& ZM_OPT_USE_GOOG_RECAPTCHA && ZM_OPT_GOOG_RECAPTCHA_SECRETKEY
|
||||
&& ZM_OPT_GOOG_RECAPTCHA_SITEKEY)
|
||||
&& ZM_OPT_GOOG_RECAPTCHA_SITEKEY )
|
||||
{
|
||||
$url = 'https://www.google.com/recaptcha/api/siteverify';
|
||||
$fields = array (
|
||||
'secret'=> ZM_OPT_GOOG_RECAPTCHA_SECRETKEY,
|
||||
'secret' => ZM_OPT_GOOG_RECAPTCHA_SECRETKEY,
|
||||
'response' => $_REQUEST['g-recaptcha-response'],
|
||||
'remoteip'=> $_SERVER['REMOTE_ADDR']
|
||||
'remoteip' => $_SERVER['REMOTE_ADDR']
|
||||
);
|
||||
$res= do_post_request($url, http_build_query($fields));
|
||||
$res = do_post_request($url, http_build_query($fields));
|
||||
$responseData = json_decode($res,true);
|
||||
// PP - credit: https://github.com/google/recaptcha/blob/master/src/ReCaptcha/Response.php
|
||||
// if recaptcha resulted in error, we might have to deny login
|
||||
|
@ -104,18 +127,18 @@ if ( !empty($action) ) {
|
|||
$refreshParent = true;
|
||||
$view = 'console';
|
||||
$redirect = true;
|
||||
} else if ( $action == 'logout' ) {
|
||||
} else if ( $action == 'logout' ) {
|
||||
userLogout();
|
||||
$refreshParent = true;
|
||||
$view = 'none';
|
||||
} else if ( $action == 'bandwidth' && isset($_REQUEST['newBandwidth']) ) {
|
||||
} else if ( $action == 'bandwidth' && isset($_REQUEST['newBandwidth']) ) {
|
||||
$_COOKIE['zmBandwidth'] = validStr($_REQUEST['newBandwidth']);
|
||||
setcookie( 'zmBandwidth', validStr($_REQUEST['newBandwidth']), time()+3600*24*30*12*10 );
|
||||
$refreshParent = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Event scope actions, view permissions only required
|
||||
if ( canView( 'Events' ) ) {
|
||||
// Event scope actions, view permissions only required
|
||||
if ( canView( 'Events' ) ) {
|
||||
|
||||
if ( isset( $_REQUEST['object'] ) and ( $_REQUEST['object'] == 'filter' ) ) {
|
||||
if ( $action == 'addterm' ) {
|
||||
|
@ -197,10 +220,10 @@ Warning("Addterm");
|
|||
}
|
||||
} // end if canEdit(Events)
|
||||
} // end if filter or something else
|
||||
} // end canView(Events)
|
||||
} // end canView(Events)
|
||||
|
||||
// Monitor control actions, require a monitor id and control view permissions for that monitor
|
||||
if ( !empty($_REQUEST['mid']) && canView( 'Control', $_REQUEST['mid'] ) ) {
|
||||
// Monitor control actions, require a monitor id and control view permissions for that monitor
|
||||
if ( !empty($_REQUEST['mid']) && canView( 'Control', $_REQUEST['mid'] ) ) {
|
||||
require_once( 'control_functions.php' );
|
||||
require_once( 'Monitor.php' );
|
||||
$mid = validInt($_REQUEST['mid']);
|
||||
|
@ -222,10 +245,10 @@ Warning("Addterm");
|
|||
list( $brightness, $contrast, $hue, $colour ) = explode( ' ', $zmuOutput );
|
||||
dbQuery( 'UPDATE Monitors SET Brightness = ?, Contrast = ?, Hue = ?, Colour = ? WHERE Id = ?', array($brightness, $contrast, $hue, $colour, $mid));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Control capability actions, require control edit permissions
|
||||
if ( canEdit( 'Control' ) ) {
|
||||
// Control capability actions, require control edit permissions
|
||||
if ( canEdit( 'Control' ) ) {
|
||||
if ( $action == 'controlcap' ) {
|
||||
if ( !empty($_REQUEST['cid']) ) {
|
||||
$control = dbFetchOne( 'SELECT * FROM Controls WHERE Id = ?', NULL, array($_REQUEST['cid']) );
|
||||
|
@ -265,9 +288,9 @@ Warning("Addterm");
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset($_REQUEST['object']) and $_REQUEST['object'] == 'Monitor' ) {
|
||||
if ( isset($_REQUEST['object']) and $_REQUEST['object'] == 'Monitor' ) {
|
||||
if ( $action == 'save' ) {
|
||||
foreach ( $_REQUEST['mids'] as $mid ) {
|
||||
$mid = ValidInt( $mid );
|
||||
|
@ -289,10 +312,10 @@ Warning("Addterm");
|
|||
} // end foreach mid
|
||||
$refreshParent = true;
|
||||
} // end if action == save
|
||||
} // end if object is Monitor
|
||||
} // end if object is Monitor
|
||||
|
||||
// Monitor edit actions, require a monitor id and edit permissions for that monitor
|
||||
if ( !empty($_REQUEST['mid']) && canEdit( 'Monitors', $_REQUEST['mid'] ) ) {
|
||||
// Monitor edit actions, require a monitor id and edit permissions for that monitor
|
||||
if ( !empty($_REQUEST['mid']) && canEdit( 'Monitors', $_REQUEST['mid'] ) ) {
|
||||
$mid = validInt($_REQUEST['mid']);
|
||||
if ( $action == 'function' ) {
|
||||
$monitor = dbFetchOne( 'SELECT * FROM Monitors WHERE Id=?', NULL, array($mid) );
|
||||
|
@ -417,10 +440,10 @@ Warning("Addterm");
|
|||
} // end if deletedzid
|
||||
} // end if isset($_REQUEST['markZids'])
|
||||
} // end if action
|
||||
} // end if $mid and canEdit($mid)
|
||||
} // end if $mid and canEdit($mid)
|
||||
|
||||
// Monitor edit actions, monitor id derived, require edit permissions for that monitor
|
||||
if ( canEdit( 'Monitors' ) ) {
|
||||
// Monitor edit actions, monitor id derived, require edit permissions for that monitor
|
||||
if ( canEdit( 'Monitors' ) ) {
|
||||
if ( $action == 'monitor' ) {
|
||||
$mid = 0;
|
||||
if ( !empty($_REQUEST['mid']) ) {
|
||||
|
@ -590,10 +613,10 @@ Warning("Addterm");
|
|||
} // end foreach monitor in MarkMid
|
||||
} // markMids is set and we aren't limited to specific monitors
|
||||
} // end if action == Delete
|
||||
}
|
||||
}
|
||||
|
||||
// Device view actions
|
||||
if ( canEdit( 'Devices' ) ) {
|
||||
// Device view actions
|
||||
if ( canEdit( 'Devices' ) ) {
|
||||
if ( $action == 'device' ) {
|
||||
if ( !empty($_REQUEST['command']) ) {
|
||||
setDeviceStatusX10( $_REQUEST['key'], $_REQUEST['command'] );
|
||||
|
@ -614,21 +637,21 @@ Warning("Addterm");
|
|||
}
|
||||
}
|
||||
} // end if action
|
||||
} // end if canedit devices
|
||||
} // end if canedit devices
|
||||
|
||||
// Group view actions
|
||||
if ( canView( 'Groups' ) && $action == 'setgroup' ) {
|
||||
// Group view actions
|
||||
if ( canView( 'Groups' ) && $action == 'setgroup' ) {
|
||||
if ( !empty($_REQUEST['gid']) ) {
|
||||
setcookie( 'zmGroup', validInt($_REQUEST['gid']), time()+3600*24*30*12*10 );
|
||||
} else {
|
||||
setcookie( 'zmGroup', '', time()-3600*24*2 );
|
||||
}
|
||||
$refreshParent = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Group edit actions
|
||||
// Group edit actions
|
||||
# Should probably verify that each monitor id is a valid monitor, that we have access to. However at the moment, you have to have System permissions to do this
|
||||
if ( canEdit( 'Groups' ) ) {
|
||||
if ( canEdit( 'Groups' ) ) {
|
||||
if ( $action == 'group' ) {
|
||||
$monitors = empty( $_POST['newGroup']['MonitorIds'] ) ? '' : implode(',', $_POST['newGroup']['MonitorIds']);
|
||||
if ( !empty($_POST['gid']) ) {
|
||||
|
@ -654,12 +677,31 @@ Warning("Addterm");
|
|||
}
|
||||
$refreshParent = true;
|
||||
} # end if action
|
||||
} // end if can edit groups
|
||||
} // end if can edit groups
|
||||
|
||||
// System edit actions
|
||||
if ( canEdit( 'System' ) ) {
|
||||
// System edit actions
|
||||
if ( canEdit( 'System' ) ) {
|
||||
if ( isset( $_REQUEST['object'] ) ) {
|
||||
if ( $_REQUEST['object'] == 'server' ) {
|
||||
if ( $_REQUEST['object'] == 'MontageLayout' ) {
|
||||
require_once('MontageLayout.php');
|
||||
if ( $action == 'Save' ) {
|
||||
$Layout = null;
|
||||
if ( $_REQUEST['Name'] != '' ) {
|
||||
$Layout = new MontageLayout();
|
||||
$Layout->Name( $_REQUEST['Name'] );
|
||||
} else {
|
||||
$Layout = new MontageLayout( $_REQUEST['zmMontageLayout'] );
|
||||
}
|
||||
$Layout->Positions( $_REQUEST['Positions'] );
|
||||
$Layout->save();
|
||||
session_start();
|
||||
$_SESSION['zmMontageLayout'] = $Layout->Id();
|
||||
setcookie('zmMontageLayout', $Layout->Id(), 1 );
|
||||
session_write_close();
|
||||
$redirect = true;
|
||||
} // end if save
|
||||
|
||||
} else if ( $_REQUEST['object'] == 'server' ) {
|
||||
|
||||
if ( $action == 'Save' ) {
|
||||
if ( !empty($_REQUEST['id']) )
|
||||
|
@ -880,7 +922,7 @@ Warning("Addterm");
|
|||
userLogout();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else {
|
||||
if ( ZM_USER_SELF_EDIT && $action == 'user' ) {
|
||||
$uid = $user['Id'];
|
||||
|
||||
|
@ -899,13 +941,12 @@ Warning("Addterm");
|
|||
}
|
||||
$view = 'none';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $action == 'reset' ) {
|
||||
if ( $action == 'reset' ) {
|
||||
$_SESSION['zmEventResetTime'] = strftime( STRF_FMT_DATETIME_DB );
|
||||
setcookie( 'zmEventResetTime', $_SESSION['zmEventResetTime'], time()+3600*24*30*12*10 );
|
||||
//if ( $cookies ) session_write_close();
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
|
@ -122,17 +122,26 @@ function dbQuery( $sql, $params=NULL ) {
|
|||
$result = NULL;
|
||||
try {
|
||||
if ( isset($params) ) {
|
||||
$result = $dbConn->prepare( $sql );
|
||||
$result->execute( $params );
|
||||
if ( ! $result = $dbConn->prepare( $sql ) ) {
|
||||
Error("SQL: Error preparing $sql: " . $pdo->errorInfo);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( ! $result->execute( $params ) ) {
|
||||
Error("SQL: Error executing $sql: " . implode(',', $result->errorInfo() ) );
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
$result = $dbConn->query( $sql );
|
||||
}
|
||||
if ( 0 ) {
|
||||
if ( $params )
|
||||
Warning("SQL: $sql" . implode(',',$params));
|
||||
Warning("SQL: $sql" . implode(',',$params) . ' rows: '.$result->rowCount() );
|
||||
else
|
||||
Warning("SQL: $sql" );
|
||||
Warning("SQL: $sql: rows:" . $result->rowCount() );
|
||||
}
|
||||
} catch(PDOException $e) {
|
||||
Error( "SQL-ERR '".$e->getMessage()."', statement was '".$sql."' params:" . implode(',',$params) );
|
||||
Error( "SQL-ERR '".$e->getMessage()."', statement was '".$sql."' params:" . ($params?implode(',',$params):'') );
|
||||
}
|
||||
return( $result );
|
||||
}
|
||||
|
|
|
@ -339,11 +339,11 @@ function getVideoStreamHTML( $id, $src, $width, $height, $format, $title='' ) {
|
|||
}
|
||||
|
||||
function outputImageStream( $id, $src, $width, $height, $title='' ) {
|
||||
echo getImageStream( $id, $src, $width, $height, $title );
|
||||
echo getImageStreamHTML( $id, $src, $width, $height, $title );
|
||||
}
|
||||
|
||||
|
||||
function getImageStream( $id, $src, $width, $height, $title='' ) {
|
||||
function getImageStreamHTML( $id, $src, $width, $height, $title='' ) {
|
||||
if ( canStreamIframe() ) {
|
||||
return '<iframe id="'.$id.'" src="'.$src.'" alt="'. validHtmlStr($title) .'" '.($width? ' width="'. validInt($width).'"' : '').($height?' height="'.validInt($height).'"' : '' ).'/>';
|
||||
} else {
|
||||
|
@ -1058,6 +1058,7 @@ function parseSort( $saveToSession=false, $querySep='&' ) {
|
|||
break;
|
||||
case 'DateTime' :
|
||||
$sortColumn = 'E.StartTime';
|
||||
$_REQUEST['sort_field'] = 'StartTime';
|
||||
break;
|
||||
case 'DiskSpace' :
|
||||
$sortColumn = 'E.DiskSpace';
|
||||
|
@ -1238,12 +1239,18 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&' ) {
|
|||
$value = dbEscape($value);
|
||||
break;
|
||||
case 'DateTime':
|
||||
case 'StartDateTime':
|
||||
case 'EndDateTime':
|
||||
$value = "'".strftime( STRF_FMT_DATETIME_DB, strtotime( $value ) )."'";
|
||||
break;
|
||||
case 'Date':
|
||||
case 'StartDate':
|
||||
case 'EndDate':
|
||||
$value = "to_days( '".strftime( STRF_FMT_DATETIME_DB, strtotime( $value ) )."' )";
|
||||
break;
|
||||
case 'Time':
|
||||
case 'StartTime':
|
||||
case 'EndTime':
|
||||
$value = "extract( hour_second from '".strftime( STRF_FMT_DATETIME_DB, strtotime( $value ) )."' )";
|
||||
break;
|
||||
default :
|
||||
|
@ -1274,13 +1281,21 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&' ) {
|
|||
case '![]' :
|
||||
$filter['sql'] .= ' not in ('.join( ',', $valueList ).')';
|
||||
break;
|
||||
case 'IS' :
|
||||
$filter['sql'] .= " IS $value";
|
||||
break;
|
||||
case 'IS NOT' :
|
||||
$filter['sql'] .= " IS NOT $value";
|
||||
break;
|
||||
default:
|
||||
Warning("Invalid operator in filter: " . $terms[$i]['op'] );
|
||||
}
|
||||
|
||||
$filter['query'] .= $querySep.urlencode("filter[Query][terms][$i][op]").'='.urlencode($terms[$i]['op']);
|
||||
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[Query][terms][$i][op]\" value=\"".htmlspecialchars($terms[$i]['op'])."\"/>\n";
|
||||
$filter['query'] .= $querySep.urlencode("filter[Query][terms][$i][val]").'='.urlencode($terms[$i]['val']);
|
||||
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[Query][terms][$i][val]\" value=\"".htmlspecialchars($terms[$i]['val'])."\"/>\n";
|
||||
}
|
||||
} // end foreach term
|
||||
if ( isset($terms[$i]['cbr']) ) {
|
||||
$filter['query'] .= $querySep.urlencode("filter[Query][terms][$i][cbr]").'='.urlencode($terms[$i]['cbr']);
|
||||
$filter['sql'] .= ' '.str_repeat( ')', $terms[$i]['cbr'] ).' ';
|
||||
|
@ -1295,13 +1310,14 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&' ) {
|
|||
}
|
||||
}
|
||||
|
||||
// Please note that the filter is passed in by copy, so you need to use the return value from this function.
|
||||
//
|
||||
function addFilterTerm( $filter, $position, $term=false ) {
|
||||
if ( $position < 0 )
|
||||
$position = 0;
|
||||
|
||||
if ( ! isset( $filter['Query']['terms'] ) )
|
||||
$filter['Query']['terms'] = array();
|
||||
|
||||
elseif( $position > count($filter['Query']['terms']) )
|
||||
$position = count($filter['Query']['terms']);
|
||||
if ( $term && $position == 0 )
|
||||
|
@ -2056,6 +2072,19 @@ function detaintPath( $path ) {
|
|||
return( $path );
|
||||
}
|
||||
|
||||
function cache_bust( $file ) {
|
||||
# Use the last modified timestamp to create a link that gets a different filename
|
||||
# To defeat caching. Should probably use md5 hash
|
||||
$parts = pathinfo($file);
|
||||
$cacheFile = 'cache/'.$parts['filename'].'-'.filemtime($file).'.'.$parts['extension'];
|
||||
if ( file_exists( ZM_PATH_WEB.'/'.$cacheFile ) or symlink( ZM_PATH_WEB.'/'.$file, ZM_PATH_WEB.'/'.$cacheFile ) ) {
|
||||
return $cacheFile;
|
||||
} else {
|
||||
Warning("Failed linking $file to $cacheFile");
|
||||
}
|
||||
return $file;
|
||||
}
|
||||
|
||||
function getSkinFile( $file ) {
|
||||
global $skinBase;
|
||||
$skinFile = false;
|
||||
|
@ -2064,7 +2093,7 @@ function getSkinFile( $file ) {
|
|||
if ( file_exists( $tempSkinFile ) )
|
||||
$skinFile = $tempSkinFile;
|
||||
}
|
||||
return( $skinFile );
|
||||
return $skinFile;
|
||||
}
|
||||
|
||||
function getSkinIncludes( $file, $includeBase=false, $asOverride=false ) {
|
||||
|
@ -2121,37 +2150,43 @@ function validHtmlStr( $input ) {
|
|||
function getStreamHTML( $monitor, $options = array() ) {
|
||||
|
||||
if ( isset($options['scale']) and $options['scale'] and ( $options['scale'] != 100 ) ) {
|
||||
//Warning("Scale to " . $options['scale'] );
|
||||
$options['width'] = reScale( $monitor->Width(), $options['scale'] );
|
||||
$options['height'] = reScale( $monitor->Height(), $options['scale'] );
|
||||
} else {
|
||||
if ( ! isset( $options['width'] ) ) {
|
||||
$options['width'] = NULL;
|
||||
} else if ( $options['width'] == 100 ) {
|
||||
# scale is empty or 100
|
||||
# There may be a fixed width applied though, in which case we need to leave the height empty
|
||||
if ( ! ( isset($options['width']) and $options['width'] ) ) {
|
||||
$options['width'] = $monitor->Width();
|
||||
}
|
||||
if ( ! isset( $options['height'] ) ) {
|
||||
$options['height'] = NULL;
|
||||
} else if ( $options['height'] == 100 ) {
|
||||
if ( ! ( isset($options['height']) and $options['height'] ) ) {
|
||||
$options['height'] = $monitor->Height();
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( ! isset($options['mode'] ) ) {
|
||||
$options['mode'] = 'stream';
|
||||
}
|
||||
$options['maxfps'] = ZM_WEB_VIDEO_MAXFPS;
|
||||
if ( $monitor->StreamReplayBuffer() )
|
||||
$options['buffer'] = $monitor->StreamReplayBuffer();
|
||||
//Warning("width: " . $options['width'] . ' height: ' . $options['height']. ' scale: ' . $options['scale'] );
|
||||
|
||||
//FIXME, the width and height of the image need to be scaled.
|
||||
if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT ) {
|
||||
$streamSrc = $monitor->getStreamSrc( array( 'mode'=>'mpeg', 'scale'=>$options['scale'], 'bitrate'=>ZM_WEB_VIDEO_BITRATE, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'format' => ZM_MPEG_LIVE_FORMAT ) );
|
||||
return getVideoStream( 'liveStream'.$monitor->Id(), $streamSrc, $options, ZM_MPEG_LIVE_FORMAT, $monitor->Name() );
|
||||
$streamSrc = $monitor->getStreamSrc( array(
|
||||
'mode'=>'mpeg',
|
||||
'scale'=>$options['scale'],
|
||||
'bitrate'=>ZM_WEB_VIDEO_BITRATE,
|
||||
'maxfps'=>ZM_WEB_VIDEO_MAXFPS,
|
||||
'format' => ZM_MPEG_LIVE_FORMAT
|
||||
) );
|
||||
return getVideoStreamHTML( 'liveStream'.$monitor->Id(), $streamSrc, $options['width'], $options['height'], ZM_MPEG_LIVE_FORMAT, $monitor->Name() );
|
||||
} else if ( $options['mode'] == 'stream' and canStream() ) {
|
||||
$options['mode'] = 'jpeg';
|
||||
$streamSrc = $monitor->getStreamSrc( $options );
|
||||
|
||||
if ( canStreamNative() )
|
||||
return getImageStream( 'liveStream'.$monitor->Id(), $streamSrc, $options['width'], $options['height'], $monitor->Name());
|
||||
return getImageStreamHTML( 'liveStream'.$monitor->Id(), $streamSrc, $options['width'], $options['height'], $monitor->Name());
|
||||
elseif ( canStreamApplet() )
|
||||
// Helper, empty widths and heights really don't work.
|
||||
return getHelperStream( 'liveStream'.$monitor->Id(), $streamSrc,
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
require_once( 'config.php' );
|
||||
|
||||
class Logger
|
||||
{
|
||||
class Logger {
|
||||
private static $instance;
|
||||
|
||||
const DEBUG = 1;
|
||||
|
@ -61,26 +60,22 @@ class Logger
|
|||
self::PANIC => E_USER_ERROR,
|
||||
);
|
||||
|
||||
private function __construct()
|
||||
{
|
||||
private function __construct() {
|
||||
$this->hasTerm = (php_sapi_name() == 'cli' && empty($_SERVER['REMOTE_ADDR']));
|
||||
$this->logFile = $this->logPath."/".$this->id.".log";
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
public function __destruct() {
|
||||
$this->terminate();
|
||||
}
|
||||
|
||||
public function initialise( $options=array() )
|
||||
{
|
||||
public function initialise( $options=array() ) {
|
||||
if ( !empty($options['id']) )
|
||||
$this->id = $options['id'];
|
||||
|
||||
//if ( isset($options['useErrorLog']) )
|
||||
//$this->useErrorLog = $options['useErrorLog'];
|
||||
if ( isset($options['logPath']) )
|
||||
{
|
||||
if ( isset($options['logPath']) ) {
|
||||
$this->logPath = $options['logPath'];
|
||||
$tempLogFile = $this->logPath."/".$this->id.".log";
|
||||
}
|
||||
|
@ -134,27 +129,21 @@ class Logger
|
|||
if ( !is_null($level = $this->getTargettedEnv('LOG_LEVEL_WEBLOG')) )
|
||||
$tempWeblogLevel = $level;
|
||||
|
||||
if ( ZM_LOG_DEBUG )
|
||||
{
|
||||
foreach ( explode( '|', ZM_LOG_DEBUG_TARGET ) as $target )
|
||||
{
|
||||
if ( $target == $this->id || $target == "_".$this->id || $target == $this->idRoot || $target == "_".$this->idRoot || $target == "" )
|
||||
{
|
||||
if ( ZM_LOG_DEBUG_LEVEL > self::NOLOG )
|
||||
{
|
||||
if ( ZM_LOG_DEBUG ) {
|
||||
foreach ( explode( '|', ZM_LOG_DEBUG_TARGET ) as $target ) {
|
||||
if ( $target == $this->id || $target == '_'.$this->id || $target == $this->idRoot || $target == '_'.$this->idRoot || $target == '' ) {
|
||||
if ( ZM_LOG_DEBUG_LEVEL > self::NOLOG ) {
|
||||
$tempLevel = $this->limit( ZM_LOG_DEBUG_LEVEL );
|
||||
if ( ZM_LOG_DEBUG_FILE != "" )
|
||||
{
|
||||
if ( ZM_LOG_DEBUG_FILE != '' ) {
|
||||
$tempLogFile = ZM_LOG_DEBUG_FILE;
|
||||
$tempFileLevel = $tempLevel;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end foreach target
|
||||
} // end if DEBUG
|
||||
|
||||
$this->logFile( $tempLogFile );
|
||||
|
||||
$this->termLevel( $tempTermLevel );
|
||||
$this->databaseLevel( $tempDatabaseLevel );
|
||||
$this->fileLevel( $tempFileLevel );
|
||||
|
@ -168,10 +157,8 @@ class Logger
|
|||
Logger::Debug( "LogOpts: level=".self::$codes[$this->level]."/".self::$codes[$this->effectiveLevel].", screen=".self::$codes[$this->termLevel].", database=".self::$codes[$this->databaseLevel].", logfile=".self::$codes[$this->fileLevel]."->".$this->logFile.", weblog=".self::$codes[$this->weblogLevel].", syslog=".self::$codes[$this->syslogLevel] );
|
||||
}
|
||||
|
||||
private function terminate()
|
||||
{
|
||||
if ( $this->initialised )
|
||||
{
|
||||
private function terminate() {
|
||||
if ( $this->initialised ) {
|
||||
if ( $this->fileLevel > self::NOLOG )
|
||||
$this->closeFile();
|
||||
if ( $this->syslogLevel > self::NOLOG )
|
||||
|
@ -180,8 +167,7 @@ class Logger
|
|||
$this->initialised = false;
|
||||
}
|
||||
|
||||
private function limit( $level )
|
||||
{
|
||||
private function limit( $level ) {
|
||||
if ( $level > self::DEBUG )
|
||||
return( self::DEBUG );
|
||||
if ( $level < self::NOLOG )
|
||||
|
@ -189,8 +175,7 @@ class Logger
|
|||
return( $level );
|
||||
}
|
||||
|
||||
private function getTargettedEnv( $name )
|
||||
{
|
||||
private function getTargettedEnv( $name ) {
|
||||
$envName = $name."_".$this->id;
|
||||
$value = getenv( $envName );
|
||||
if ( $value === false && $this->id != $this->idRoot )
|
||||
|
@ -200,10 +185,8 @@ class Logger
|
|||
return( $value !== false ? $value : NULL );
|
||||
}
|
||||
|
||||
public static function fetch( $initialise=true )
|
||||
{
|
||||
if ( !isset(self::$instance) )
|
||||
{
|
||||
public static function fetch( $initialise=true ) {
|
||||
if ( !isset(self::$instance) ) {
|
||||
$class = __CLASS__;
|
||||
self::$instance = new $class;
|
||||
if ( $initialise )
|
||||
|
@ -212,25 +195,20 @@ class Logger
|
|||
return self::$instance;
|
||||
}
|
||||
|
||||
public static function Debug( $string )
|
||||
{
|
||||
public static function Debug( $string ) {
|
||||
Logger::fetch()->logPrint( Logger::DEBUG, $string );
|
||||
}
|
||||
|
||||
public function id( $id=NULL )
|
||||
{
|
||||
if ( isset($id) && $this->id != $id )
|
||||
{
|
||||
public function id( $id=NULL ) {
|
||||
if ( isset($id) && $this->id != $id ) {
|
||||
// Remove whitespace
|
||||
$id = preg_replace( '/\S/', '', $id );
|
||||
// Replace non-alphanum with underscore
|
||||
$id = preg_replace( '/[^a-zA-Z_]/', '_', $id );
|
||||
|
||||
if ( $this->id != $id )
|
||||
{
|
||||
if ( $this->id != $id ) {
|
||||
$this->id = $this->idRoot = $id;
|
||||
if ( preg_match( '/^([^_]+)_(.+)$/', $id, $matches ) )
|
||||
{
|
||||
if ( preg_match( '/^([^_]+)_(.+)$/', $id, $matches ) ) {
|
||||
$this->idRoot = $matches[1];
|
||||
$this->idArgs = $matches[2];
|
||||
}
|
||||
|
@ -239,10 +217,8 @@ class Logger
|
|||
return( $this->id );
|
||||
}
|
||||
|
||||
public function level( $level )
|
||||
{
|
||||
if ( isset($level) )
|
||||
{
|
||||
public function level( $level ) {
|
||||
if ( isset($level) ) {
|
||||
$lastLevel = $this->level;
|
||||
$this->level = $this->limit($level);
|
||||
$this->effectiveLevel = self::NOLOG;
|
||||
|
@ -258,15 +234,11 @@ class Logger
|
|||
$this->effectiveLevel = $this->syslogLevel;
|
||||
if ( $this->effectiveLevel > $this->level )
|
||||
$this->effectiveLevel = $this->level;
|
||||
if ( !$this->hasTerm )
|
||||
{
|
||||
if ( $lastLevel < self::DEBUG && $this->level >= self::DEBUG )
|
||||
{
|
||||
if ( !$this->hasTerm ) {
|
||||
if ( $lastLevel < self::DEBUG && $this->level >= self::DEBUG ) {
|
||||
$this->savedErrorReporting = error_reporting( E_ALL );
|
||||
$this->savedDisplayErrors = ini_set( 'display_errors', true );
|
||||
}
|
||||
elseif ( $lastLevel >= self::DEBUG && $this->level < self::DEBUG )
|
||||
{
|
||||
} elseif ( $lastLevel >= self::DEBUG && $this->level < self::DEBUG ) {
|
||||
error_reporting( $this->savedErrorReporting );
|
||||
ini_set( 'display_errors', $this->savedDisplayErrors );
|
||||
}
|
||||
|
@ -275,15 +247,12 @@ class Logger
|
|||
return( $this->level );
|
||||
}
|
||||
|
||||
public function debugOn()
|
||||
{
|
||||
public function debugOn() {
|
||||
return( $this->effectiveLevel >= self::DEBUG );
|
||||
}
|
||||
|
||||
public function termLevel( $termLevel )
|
||||
{
|
||||
if ( isset($termLevel) )
|
||||
{
|
||||
public function termLevel( $termLevel ) {
|
||||
if ( isset($termLevel) ) {
|
||||
$termLevel = $this->limit($termLevel);
|
||||
if ( $this->termLevel != $termLevel )
|
||||
$this->termLevel = $termLevel;
|
||||
|
@ -291,18 +260,13 @@ class Logger
|
|||
return( $this->termLevel );
|
||||
}
|
||||
|
||||
public function databaseLevel( $databaseLevel=NULL )
|
||||
{
|
||||
if ( !is_null($databaseLevel) )
|
||||
{
|
||||
public function databaseLevel( $databaseLevel=NULL ) {
|
||||
if ( !is_null($databaseLevel) ) {
|
||||
$databaseLevel = $this->limit($databaseLevel);
|
||||
if ( $this->databaseLevel != $databaseLevel )
|
||||
{
|
||||
if ( $this->databaseLevel != $databaseLevel ) {
|
||||
$this->databaseLevel = $databaseLevel;
|
||||
if ( $this->databaseLevel > self::NOLOG )
|
||||
{
|
||||
if ( (include_once 'database.php') === FALSE )
|
||||
{
|
||||
if ( $this->databaseLevel > self::NOLOG ) {
|
||||
if ( (include_once 'database.php') === FALSE ) {
|
||||
$this->databaseLevel = self::NOLOG;
|
||||
Warning( "Unable to write log entries to DB, database.php not found" );
|
||||
}
|
||||
|
@ -312,13 +276,10 @@ class Logger
|
|||
return( $this->databaseLevel );
|
||||
}
|
||||
|
||||
public function fileLevel( $fileLevel )
|
||||
{
|
||||
if ( isset($fileLevel) )
|
||||
{
|
||||
public function fileLevel( $fileLevel ) {
|
||||
if ( isset($fileLevel) ) {
|
||||
$fileLevel = $this->limit($fileLevel);
|
||||
if ( $this->fileLevel != $fileLevel )
|
||||
{
|
||||
if ( $this->fileLevel != $fileLevel ) {
|
||||
if ( $this->fileLevel > self::NOLOG )
|
||||
$this->closeFile();
|
||||
$this->fileLevel = $fileLevel;
|
||||
|
@ -329,19 +290,13 @@ class Logger
|
|||
return( $this->fileLevel );
|
||||
}
|
||||
|
||||
public function weblogLevel( $weblogLevel )
|
||||
{
|
||||
if ( isset($weblogLevel) )
|
||||
{
|
||||
public function weblogLevel( $weblogLevel ) {
|
||||
if ( isset($weblogLevel) ) {
|
||||
$weblogLevel = $this->limit($weblogLevel);
|
||||
if ( $this->weblogLevel != $weblogLevel )
|
||||
{
|
||||
if ( $weblogLevel > self::NOLOG && $this->weblogLevel <= self::NOLOG )
|
||||
{
|
||||
if ( $this->weblogLevel != $weblogLevel ) {
|
||||
if ( $weblogLevel > self::NOLOG && $this->weblogLevel <= self::NOLOG ) {
|
||||
$this->savedLogErrors = ini_set( 'log_errors', true );
|
||||
}
|
||||
elseif ( $weblogLevel <= self::NOLOG && $this->weblogLevel > self::NOLOG )
|
||||
{
|
||||
} elseif ( $weblogLevel <= self::NOLOG && $this->weblogLevel > self::NOLOG ) {
|
||||
ini_set( 'log_errors', $this->savedLogErrors );
|
||||
}
|
||||
$this->weblogLevel = $weblogLevel;
|
||||
|
@ -350,13 +305,10 @@ class Logger
|
|||
return( $this->weblogLevel );
|
||||
}
|
||||
|
||||
public function syslogLevel( $syslogLevel )
|
||||
{
|
||||
if ( isset($syslogLevel) )
|
||||
{
|
||||
public function syslogLevel( $syslogLevel ) {
|
||||
if ( isset($syslogLevel) ) {
|
||||
$syslogLevel = $this->limit($syslogLevel);
|
||||
if ( $this->syslogLevel != $syslogLevel )
|
||||
{
|
||||
if ( $this->syslogLevel != $syslogLevel ) {
|
||||
if ( $this->syslogLevel > self::NOLOG )
|
||||
$this->closeSyslog();
|
||||
$this->syslogLevel = $syslogLevel;
|
||||
|
@ -367,60 +319,48 @@ class Logger
|
|||
return( $this->syslogLevel );
|
||||
}
|
||||
|
||||
private function openSyslog()
|
||||
{
|
||||
private function openSyslog() {
|
||||
openlog( $this->id, LOG_PID|LOG_NDELAY, LOG_LOCAL1 );
|
||||
}
|
||||
|
||||
private function closeSyslog()
|
||||
{
|
||||
private function closeSyslog() {
|
||||
closelog();
|
||||
}
|
||||
|
||||
private function logFile( $logFile )
|
||||
{
|
||||
private function logFile( $logFile ) {
|
||||
if ( preg_match( '/^(.+)\+$/', $logFile, $matches ) )
|
||||
$this->logFile = $matches[1].'.'.getmypid();
|
||||
else
|
||||
$this->logFile = $logFile;
|
||||
}
|
||||
|
||||
private function openFile()
|
||||
{
|
||||
if ( !$this->useErrorLog )
|
||||
{
|
||||
if ( $this->logFd = fopen( $this->logFile, "a+" ) )
|
||||
{
|
||||
if ( strnatcmp( phpversion(), '5.2.0' ) >= 0 )
|
||||
{
|
||||
private function openFile() {
|
||||
if ( !$this->useErrorLog ) {
|
||||
if ( $this->logFd = fopen( $this->logFile, 'a+' ) ) {
|
||||
if ( strnatcmp( phpversion(), '5.2.0' ) >= 0 ) {
|
||||
$error = error_get_last();
|
||||
trigger_error( "Can't open log file '$logFile': ".$error['message']." @ ".$error['file']."/".$error['line'], E_USER_ERROR );
|
||||
trigger_error( "Can't open log file '$logFile': ".$error['message'].' @ '.$error['file'].'/'.$error['line'], E_USER_ERROR );
|
||||
}
|
||||
$this->fileLevel = self::NOLOG;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function closeFile()
|
||||
{
|
||||
private function closeFile() {
|
||||
if ( $this->logFd )
|
||||
fclose( $this->logFd );
|
||||
}
|
||||
|
||||
public function logPrint( $level, $string, $file=NULL, $line=NULL )
|
||||
{
|
||||
if ( $level <= $this->effectiveLevel )
|
||||
{
|
||||
public function logPrint( $level, $string, $file=NULL, $line=NULL ) {
|
||||
if ( $level <= $this->effectiveLevel ) {
|
||||
$string = preg_replace( '/[\r\n]+$/', '', $string );
|
||||
$code = self::$codes[$level];
|
||||
|
||||
$time = gettimeofday();
|
||||
$message = sprintf( "%s.%06d %s[%d].%s [%s]", strftime( "%x %H:%M:%S", $time['sec'] ), $time['usec'], $this->id, getmypid(), $code, $string );
|
||||
$message = sprintf( '%s.%06d %s[%d].%s [%s]', strftime( '%x %H:%M:%S', $time['sec'] ), $time['usec'], $this->id, getmypid(), $code, $string );
|
||||
|
||||
if ( is_null( $file) )
|
||||
{
|
||||
if ( $this->useErrorLog || $this->databaseLevel > self::NOLOG )
|
||||
{
|
||||
if ( is_null($file) ) {
|
||||
if ( $this->useErrorLog || $this->databaseLevel > self::NOLOG ) {
|
||||
$backTrace = debug_backtrace();
|
||||
$file = $backTrace[1]['file'];
|
||||
$line = $backTrace[1]['line'];
|
||||
|
@ -441,28 +381,24 @@ class Logger
|
|||
if ( $this->hasTerm )
|
||||
print( $message."\n" );
|
||||
else
|
||||
print( preg_replace( "/\n/", '<br/>', htmlspecialchars($message) )."<br/>" );
|
||||
print( preg_replace( "/\n/", '<br/>', htmlspecialchars($message) ).'<br/>' );
|
||||
|
||||
if ( $level <= $this->fileLevel )
|
||||
if ( $this->useErrorLog )
|
||||
{
|
||||
if ( !error_log( $message."\n", 3, $this->logFile ) )
|
||||
{
|
||||
if ( strnatcmp( phpversion(), '5.2.0' ) >= 0 )
|
||||
{
|
||||
if ( $this->useErrorLog ) {
|
||||
if ( !error_log( $message."\n", 3, $this->logFile ) ) {
|
||||
if ( strnatcmp( phpversion(), '5.2.0' ) >= 0 ) {
|
||||
$error = error_get_last();
|
||||
trigger_error( "Can't write to log file '".$this->logFile."': ".$error['message']." @ ".$error['file']."/".$error['line'], E_USER_ERROR );
|
||||
trigger_error( "Can't write to log file '".$this->logFile."': ".$error['message'].' @ '.$error['file'].'/'.$error['line'], E_USER_ERROR );
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif ( $this->logFd )
|
||||
} elseif ( $this->logFd ) {
|
||||
fprintf( $this->logFd, $message."\n" );
|
||||
}
|
||||
|
||||
$message = $code." [".$string."]";
|
||||
$message = $code.' ['.$string.']';
|
||||
if ( $level <= $this->syslogLevel )
|
||||
syslog( self::$syslogPriorities[$level], $message );
|
||||
if ( $level <= $this->databaseLevel )
|
||||
{
|
||||
if ( $level <= $this->databaseLevel ) {
|
||||
try {
|
||||
global $dbConn;
|
||||
$sql = "INSERT INTO Logs ( TimeKey, Component, Pid, Level, Code, Message, File, Line ) values ( ?, ?, ?, ?, ?, ?, ?, ? )";
|
||||
|
@ -474,8 +410,7 @@ class Logger
|
|||
}
|
||||
}
|
||||
// This has to be last as trigger_error can be fatal
|
||||
if ( $level <= $this->weblogLevel )
|
||||
{
|
||||
if ( $level <= $this->weblogLevel ) {
|
||||
if ( $this->useErrorLog )
|
||||
error_log( $message, 0 );
|
||||
else
|
||||
|
@ -485,68 +420,55 @@ class Logger
|
|||
}
|
||||
};
|
||||
|
||||
function logInit( $options=array() )
|
||||
{
|
||||
function logInit( $options=array() ) {
|
||||
$logger = Logger::fetch();
|
||||
$logger->initialise( $options );
|
||||
set_error_handler( 'ErrorHandler' );
|
||||
}
|
||||
|
||||
function logToDatabase( $level=NULL )
|
||||
{
|
||||
function logToDatabase( $level=NULL ) {
|
||||
return( Logger::fetch()->databaseLevel( $level ) );
|
||||
}
|
||||
|
||||
function Mark( $level=Logger::DEBUG, $tag="Mark" )
|
||||
{
|
||||
function Mark( $level=Logger::DEBUG, $tag='Mark' ) {
|
||||
Logger::fetch()->logPrint( $level, $tag );
|
||||
}
|
||||
|
||||
function Dump( &$var, $label="VAR" )
|
||||
{
|
||||
function Dump( &$var, $label='VAR' ) {
|
||||
ob_start();
|
||||
print( $label." => " );
|
||||
print( $label.' => ' );
|
||||
print_r( $var );
|
||||
Logger::fetch()->logPrint( Logger::DEBUG, ob_get_clean() );
|
||||
}
|
||||
|
||||
function Info( $string )
|
||||
{
|
||||
function Info( $string ) {
|
||||
Logger::fetch()->logPrint( Logger::INFO, $string );
|
||||
}
|
||||
|
||||
function Warning( $string )
|
||||
{
|
||||
function Warning( $string ) {
|
||||
Logger::fetch()->logPrint( Logger::WARNING, $string );
|
||||
}
|
||||
|
||||
function Error( $string )
|
||||
{
|
||||
function Error( $string ) {
|
||||
Logger::fetch()->logPrint( Logger::ERROR, $string );
|
||||
}
|
||||
|
||||
function Fatal( $string )
|
||||
{
|
||||
function Fatal( $string ) {
|
||||
Logger::fetch()->logPrint( Logger::FATAL, $string );
|
||||
die( htmlentities($string) );
|
||||
}
|
||||
|
||||
function Panic( $string )
|
||||
{
|
||||
if ( true )
|
||||
{
|
||||
function Panic( $string ) {
|
||||
if ( true ) {
|
||||
// Use builtin function
|
||||
ob_start();
|
||||
debug_print_backtrace();
|
||||
$backtrace = "\n".ob_get_clean();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// Roll your own
|
||||
$backtrace = '';
|
||||
$frames = debug_backtrace();
|
||||
for ( $i = 0; $i < count($frames); $i++ )
|
||||
{
|
||||
for ( $i = 0; $i < count($frames); $i++ ) {
|
||||
$frame = $frames[$i];
|
||||
$backtrace .= sprintf( "\n#%d %s() at %s/%d", $i, $frame['function'], $frame['file'], $frame['line'] );
|
||||
}
|
||||
|
@ -555,16 +477,13 @@ function Panic( $string )
|
|||
die( $string );
|
||||
}
|
||||
|
||||
function ErrorHandler( $error, $string, $file, $line )
|
||||
{
|
||||
if ( ! (error_reporting() & $error) )
|
||||
{
|
||||
function ErrorHandler( $error, $string, $file, $line ) {
|
||||
if ( ! (error_reporting() & $error) ) {
|
||||
// This error code is not included in error_reporting
|
||||
return( false );
|
||||
}
|
||||
|
||||
switch ( $error )
|
||||
{
|
||||
switch ( $error ) {
|
||||
case E_USER_ERROR:
|
||||
Logger::fetch()->logPrint( Logger::FATAL, $string, $file, $line );
|
||||
break;
|
||||
|
|
|
@ -34,7 +34,7 @@ if ( version_compare( phpversion(), '4.1.0', '<') ) {
|
|||
}
|
||||
|
||||
// Useful debugging lines for mobile devices
|
||||
if ( false ) {
|
||||
if ( true ) {
|
||||
ob_start();
|
||||
phpinfo( INFO_VARIABLES );
|
||||
$fp = fopen( '/tmp/env.html', 'w' );
|
||||
|
@ -113,7 +113,7 @@ if ( !file_exists( ZM_SKIN_PATH ) )
|
|||
$skinBase[] = $skin;
|
||||
|
||||
$currentCookieParams = session_get_cookie_params();
|
||||
Logger::Debug('Setting cookie parameters to lifetime('.$currentCookieParams['lifetime'].') path('.$currentCookieParams['path'].') domain ('.$currentCookieParams['domain'].') secure('.$currentCookieParams['secure'].') httpOnly(1)');
|
||||
//Logger::Debug('Setting cookie parameters to lifetime('.$currentCookieParams['lifetime'].') path('.$currentCookieParams['path'].') domain ('.$currentCookieParams['domain'].') secure('.$currentCookieParams['secure'].') httpOnly(1)');
|
||||
session_set_cookie_params(
|
||||
$currentCookieParams['lifetime'],
|
||||
$currentCookieParams['path'],
|
||||
|
@ -175,9 +175,7 @@ foreach ( getSkinIncludes( 'skin.php' ) as $includeFile )
|
|||
|
||||
if ( ZM_OPT_USE_AUTH && ZM_AUTH_HASH_LOGINS ) {
|
||||
if ( empty($user) && ! empty($_REQUEST['auth']) ) {
|
||||
Logger::Debug("Getting user from auth hash");
|
||||
if ( $authUser = getAuthUser( $_REQUEST['auth'] ) ) {
|
||||
Logger::Debug("Success Getting user from auth hash");
|
||||
userLogin( $authUser['Username'], $authUser['Password'], true );
|
||||
}
|
||||
} else if ( ! empty($user) ) {
|
||||
|
|
|
@ -302,6 +302,7 @@ $SLANG = array(
|
|||
'DuplicateMonitorName' => 'Duplicate Monitor Name',
|
||||
'Duration' => 'Duration',
|
||||
'Edit' => 'Edit',
|
||||
'EditLayout' => 'Edit Layout',
|
||||
'Email' => 'Email',
|
||||
'EnableAlarms' => 'Enable Alarms',
|
||||
'Enabled' => 'Enabled',
|
||||
|
@ -556,6 +557,8 @@ $SLANG = array(
|
|||
'OpNe' => 'not equal to',
|
||||
'OpNotIn' => 'not in set',
|
||||
'OpNotMatches' => 'does not match',
|
||||
'OpIs' => 'is',
|
||||
'OpIsNot' => 'is not',
|
||||
'OptionalEncoderParam' => 'Optional Encoder Parameters',
|
||||
'OptionHelp' => 'Option Help',
|
||||
'OptionRestartWarning' => 'These changes may not come into effect fully\nwhile the system is running. When you have\nfinished making your changes please ensure that\nyou restart ZoneMinder.',
|
||||
|
|
|
@ -68,11 +68,7 @@ th {
|
|||
color: #016A9d;
|
||||
}
|
||||
|
||||
a:link {
|
||||
color: #7f7fb2;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:link,
|
||||
a:visited {
|
||||
color: #7f7fb2;
|
||||
text-decoration: none;
|
||||
|
|
|
@ -6,6 +6,15 @@
|
|||
width: 99%;
|
||||
}
|
||||
|
||||
#monitors:after {
|
||||
content: ".";
|
||||
display: block;
|
||||
height: 0;
|
||||
font-size: 0;
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#monitors .monitor {
|
||||
min-width: 180px;
|
||||
margin: 0;
|
||||
|
|
|
@ -48,8 +48,10 @@ function xhtmlHeaders( $file, $title ) {
|
|||
<title><?php echo ZM_WEB_TITLE_PREFIX ?> - <?php echo validHtmlStr($title) ?></title>
|
||||
<?php
|
||||
if ( file_exists( "skins/$skin/css/$css/graphics/favicon.ico" ) ) {
|
||||
echo "<link rel=\"icon\" type=\"image/ico\" href=\"skins/$skin/css/$css/graphics/favicon.ico\"/>\n";
|
||||
echo "<link rel=\"shortcut icon\" href=\"skins/$skin/css/$css/graphics/favicon.ico\"/>\n";
|
||||
echo "
|
||||
<link rel=\"icon\" type=\"image/ico\" href=\"skins/$skin/css/$css/graphics/favicon.ico\"/>
|
||||
<link rel=\"shortcut icon\" href=\"skins/$skin/css/$css/graphics/favicon.ico\"/>
|
||||
";
|
||||
} else {
|
||||
echo '
|
||||
<link rel="icon" type="image/ico" href="graphics/favicon.ico"/>
|
||||
|
@ -60,11 +62,11 @@ if ( file_exists( "skins/$skin/css/$css/graphics/favicon.ico" ) ) {
|
|||
<link rel="stylesheet" href="css/reset.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="css/overlay.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="css/bootstrap.min.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="<?php echo $skinCssFile ?>" type="text/css" media="screen"/>
|
||||
<link rel="stylesheet" href="<?php echo cache_bust($skinCssFile) ?>" type="text/css" media="screen"/>
|
||||
<?php
|
||||
if ( $viewCssFile ) {
|
||||
?>
|
||||
<link rel="stylesheet" href="<?php echo $viewCssFile ?>" type="text/css" media="screen"/>
|
||||
<link rel="stylesheet" href="<?php echo cache_bust($viewCssFile) ?>" type="text/css" media="screen"/>
|
||||
<?php
|
||||
}
|
||||
if ( $viewCssPhpFile ) {
|
||||
|
@ -138,18 +140,18 @@ if ( file_exists( "skins/$skin/css/$css/graphics/favicon.ico" ) ) {
|
|||
}
|
||||
if ( $cssJsFile ) {
|
||||
?>
|
||||
<script type="text/javascript" src="<?php echo $cssJsFile ?>"></script>
|
||||
<script type="text/javascript" src="<?php echo cache_bust($cssJsFile) ?>"></script>
|
||||
<?php
|
||||
} else {
|
||||
?>
|
||||
<script type="text/javascript" src="skins/classic/js/classic.js"></script>
|
||||
<?php } ?>
|
||||
<script type="text/javascript" src="<?php echo $skinJsFile ?>"></script>
|
||||
<script type="text/javascript" src="<?php echo cache_bust($skinJsFile) ?>"></script>
|
||||
<script type="text/javascript" src="js/logger.js"></script>
|
||||
<?php
|
||||
if ( $viewJsFile ) {
|
||||
?>
|
||||
<script type="text/javascript" src="<?php echo $viewJsFile ?>"></script>
|
||||
<script type="text/javascript" src="<?php echo cache_bust($viewJsFile) ?>"></script>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
var popupOptions = "resizable,scrollbars,status=no,toolbar=yes";
|
||||
|
||||
function checkSize() {
|
||||
if ( 0 ) {
|
||||
if (window.outerHeight) {
|
||||
var w = window.outerWidth;
|
||||
var prevW = w;
|
||||
|
@ -37,6 +38,7 @@ function checkSize() {
|
|||
if (w != prevW || h != prevH)
|
||||
window.resizeTo(w, h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
<?php
|
||||
//
|
||||
// ZoneMinder web console file, $Date$, $Revision$
|
||||
// Copyright (C) 2001-2008 Philip Coombes
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
//
|
||||
|
||||
$servers = Server::find_all();
|
||||
$ServersById = array();
|
||||
foreach ( $servers as $S ) {
|
||||
$ServersById[$S->Id()] = $S;
|
||||
}
|
||||
session_start();
|
||||
foreach ( array('ServerFilter','StorageFilter','StatusFilter','MonitorId') as $var ) {
|
||||
if ( isset( $_REQUEST[$var] ) ) {
|
||||
if ( $_REQUEST[$var] != '' ) {
|
||||
$_SESSION[$var] = $_REQUEST[$var];
|
||||
} else {
|
||||
unset( $_SESSION[$var] );
|
||||
}
|
||||
} else if ( isset( $_COOKIE[$var] ) ) {
|
||||
if ( $_COOKIE[$var] != '' ) {
|
||||
$_SESSION[$var] = $_COOKIE[$var];
|
||||
} else {
|
||||
unset($_SESSION[$var]);
|
||||
}
|
||||
}
|
||||
}
|
||||
session_write_close();
|
||||
|
||||
$storage_areas = Storage::find_all();
|
||||
$StorageById = array();
|
||||
foreach ( $storage_areas as $S ) {
|
||||
$StorageById[$S->Id()] = $S;
|
||||
}
|
||||
|
||||
?>
|
||||
<div class="controlHeader">
|
||||
<span id="groupControl"><label><?php echo translate('Group') ?>:</label>
|
||||
<?php
|
||||
# This will end up with the group_id of the deepest selection
|
||||
$group_id = Group::get_group_dropdowns();
|
||||
$groupSql = Group::get_group_sql( $group_id );
|
||||
?>
|
||||
</span>
|
||||
<span id="monitorControl"><label><?php echo translate('Monitor') ?>:</label>
|
||||
<?php
|
||||
|
||||
$monitor_id = isset($_SESSION['MonitorId']) ? $_SESSION['MonitorId'] : 0;
|
||||
|
||||
# Used to determine if the Cycle button should be made available
|
||||
|
||||
$conditions = array();
|
||||
$values = array();
|
||||
|
||||
if ( $groupSql )
|
||||
$conditions[] = $groupSql;
|
||||
if ( isset($_SESSION['ServerFilter']) ) {
|
||||
$conditions[] = 'ServerId=?';
|
||||
$values[] = $_SESSION['ServerFilter'];
|
||||
}
|
||||
if ( isset($_SESSION['StorageFilter']) ) {
|
||||
$conditions[] = 'StorageId=?';
|
||||
$values[] = $_SESSION['StorageFilter'];
|
||||
}
|
||||
if ( ! empty( $user['MonitorIds'] ) ) {
|
||||
$ids = explode(',', $user['MonitorIds'] );
|
||||
$conditions[] = 'Id IN ('.implode(',',array_map( function(){return '?';}, $ids) ).')';
|
||||
$values += $ids;
|
||||
}
|
||||
|
||||
$sql = 'SELECT * FROM Monitors' . ( count($conditions) ? ' WHERE ' . implode(' AND ', $conditions ) : '' ).' ORDER BY Sequence ASC';
|
||||
$monitors = dbFetchAll( $sql, null, $values );
|
||||
$displayMonitors = array();
|
||||
$monitors_dropdown = array(''=>'All');
|
||||
|
||||
if ( $monitor_id ) {
|
||||
$found_selected_monitor = false;
|
||||
|
||||
for ( $i = 0; $i < count($monitors); $i++ ) {
|
||||
if ( !visibleMonitor( $monitors[$i]['Id'] ) ) {
|
||||
continue;
|
||||
}
|
||||
$monitors_dropdown[$monitors[$i]['Id']] = $monitors[$i]['Name'];
|
||||
if ( $monitors[$i]['Id'] == $monitor_id ) {
|
||||
$found_selected_monitor = true;
|
||||
}
|
||||
}
|
||||
if ( ! $found_selected_monitor ) {
|
||||
$monitor_id = '';
|
||||
}
|
||||
}
|
||||
for ( $i = 0; $i < count($monitors); $i++ ) {
|
||||
if ( !visibleMonitor( $monitors[$i]['Id'] ) ) {
|
||||
continue;
|
||||
}
|
||||
$monitors_dropdown[$monitors[$i]['Id']] = $monitors[$i]['Name'];
|
||||
|
||||
if ( $monitor_id and ( $monitors[$i]['Id'] != $monitor_id ) ) {
|
||||
continue;
|
||||
}
|
||||
$displayMonitors[] = $monitors[$i];
|
||||
}
|
||||
echo htmlSelect( 'MonitorId', $monitors_dropdown, $monitor_id, array('onchange'=>'changeMonitor(this);') );
|
||||
?>
|
||||
</span>
|
||||
<?php
|
||||
if ( count($ServersById) > 1 ) {
|
||||
?>
|
||||
<span class="ServerFilter"><label><?php echo translate('Server')?>:</label>
|
||||
<?php
|
||||
echo htmlSelect( 'ServerFilter', array(''=>'All')+$ServersById, (isset($_SESSION['ServerFilter'])?$_SESSION['ServerFilter']:''), array('onchange'=>'changeFilter(this);') );
|
||||
?>
|
||||
</span>
|
||||
<?php
|
||||
}
|
||||
if ( count($StorageById) > 1 ) { ?>
|
||||
<span class="StorageFilter"><label><?php echo translate('Storage')?>:</label>
|
||||
<?php
|
||||
echo htmlSelect( 'StorageFilter', array(''=>'All')+$StorageById, (isset($_SESSION['StorageFilter'])?$_SESSION['StorageFilter']:''), array('onchange'=>'changeFilter(this);') );
|
||||
?>
|
||||
</span>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<span class="StatusFilter"><label><?php echo translate('Status')?>:</label>
|
||||
<?php
|
||||
$status_options = array(
|
||||
''=>'All',
|
||||
'Unknown' => translate('Unknown'),
|
||||
'NotRunning' => translate('NotRunning'),
|
||||
'Running' => translate('Running'),
|
||||
);
|
||||
echo htmlSelect( 'StatusFilter', $status_options, ( isset($_SESSION['StatusFilter']) ? $_SESSION['StatusFilter'] : '' ), array('onchange'=>'changeFilter(this);') );
|
||||
?>
|
||||
</span>
|
||||
</div>
|
|
@ -0,0 +1,112 @@
|
|||
<?php
|
||||
//
|
||||
// ZoneMinder web function view file, $Date$, $Revision$
|
||||
// Copyright (C) 2017 ZoneMinder LLC
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
//
|
||||
|
||||
if ( !canEdit( 'Monitors' ) ) {
|
||||
$view = 'error';
|
||||
return;
|
||||
}
|
||||
|
||||
$focusWindow = true;
|
||||
$navbar = getNavBarHTML();
|
||||
|
||||
xhtmlHeaders(__FILE__, translate('AddMonitors'));
|
||||
?>
|
||||
<body>
|
||||
<div id="page">
|
||||
<?php echo $navbar ?>
|
||||
<div id="content">
|
||||
|
||||
<form name="contentForm" id="contentForm" method="post" action="<?php echo $_SERVER['PHP_SELF'] ?>">
|
||||
<div style="position:relative;">
|
||||
<div id="results" style="position: absolute; top:0; right: 0; width: 50%; height: 100%;">
|
||||
<fieldset><legend>Results</legend>
|
||||
<div id="url_results">
|
||||
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div style="width:50%;position: absolute; top:0; left: 0;height: 100%;">
|
||||
<fieldset><legend>Enter by IP or URL</legend>
|
||||
<!--<input type="text" name="newMonitor[Name]" />-->
|
||||
<input type="url" name="newMonitor[Url]" oninput="probe(this);"/>
|
||||
</fieldset>
|
||||
<fieldset><legend>Import CSV Spreadsheet</legend>
|
||||
Spreadsheet should have the following format:<br/>
|
||||
<table class="major">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>URL</th>
|
||||
<th>Group</th>
|
||||
</tr>
|
||||
<tr title="Example Data">
|
||||
<td>Example Name MN1-30 INQ37.01</td>
|
||||
<td>http://10.34.152.20:2001/?action=stream</td>
|
||||
<td>MN1</td>
|
||||
</tr>
|
||||
</table>
|
||||
Defaults to apply to each monitor:<br/>
|
||||
<table><tr><th>Setting</th><th>Value</th></tr>
|
||||
<tr><td><?php echo translate('Function') ?></td><td>
|
||||
<?php
|
||||
$options = array();
|
||||
foreach ( getEnumValues('Monitors', 'Function') as $opt ) {
|
||||
$options[$opt] = translate('Fn'.$opt);
|
||||
}
|
||||
echo htmlSelect( 'newMonitor[Function]', $options, 'Record' );
|
||||
?>
|
||||
</td></tr>
|
||||
<?php
|
||||
$servers = Server::find_all();
|
||||
$ServersById = array();
|
||||
foreach ( $servers as $S ) {
|
||||
$ServersById[$S->Id()] = $S;
|
||||
}
|
||||
|
||||
if ( count($ServersById) > 0 ) { ?>
|
||||
<tr class="Server"><td><?php echo translate('Server')?></td><td>
|
||||
<?php echo htmlSelect( 'newMonitor[ServerId]', array(''=>'Auto')+$ServersById, '' ); ?>
|
||||
</td></tr>
|
||||
<?php
|
||||
}
|
||||
$storage_areas = Storage::find_all();
|
||||
$StorageById = array();
|
||||
foreach ( $storage_areas as $S ) {
|
||||
$StorageById[$S->Id()] = $S;
|
||||
}
|
||||
if ( count($StorageById) > 0 ) {
|
||||
?>
|
||||
<tr class="Storage"><td><?php echo translate('Storage')?></td><td>
|
||||
<?php echo htmlSelect( 'newMonitor[StorageId]', array(''=>'All')+$StorageById, 1 ); ?>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</td></tr>
|
||||
</table>
|
||||
|
||||
<input type="file" name="import_file" id="import_file"/>
|
||||
<input type="button" value="Import" onclick="import_csv(this.form);"/>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php xhtmlFooter() ?>
|
|
@ -18,36 +18,6 @@
|
|||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
//
|
||||
|
||||
$servers = Server::find_all();
|
||||
$ServersById = array();
|
||||
foreach ( $servers as $S ) {
|
||||
$ServersById[$S->Id()] = $S;
|
||||
}
|
||||
session_start();
|
||||
foreach ( array('ServerFilter','StorageFilter') as $var ) {
|
||||
if ( isset( $_REQUEST[$var] ) ) {
|
||||
if ( $_REQUEST[$var] != '' ) {
|
||||
$_SESSION[$var] = $_REQUEST[$var];
|
||||
} else {
|
||||
unset( $_SESSION[$var] );
|
||||
}
|
||||
} else if ( isset( $_COOKIE[$var] ) ) {
|
||||
if ( $_COOKIE[$var] != '' ) {
|
||||
$_SESSION[$var] = $_COOKIE[$var];
|
||||
} else {
|
||||
unset($_SESSION[$var]);
|
||||
}
|
||||
}
|
||||
}
|
||||
session_write_close();
|
||||
|
||||
$storage_areas = Storage::find_all();
|
||||
$StorageById = array();
|
||||
foreach ( $storage_areas as $S ) {
|
||||
$StorageById[$S->Id()] = $S;
|
||||
}
|
||||
|
||||
$show_storage_areas = count($storage_areas) > 1 and canEdit( 'System' ) ? 1 : 0;
|
||||
if ( $running == null )
|
||||
$running = daemonCheck();
|
||||
|
||||
|
@ -55,7 +25,7 @@ $eventCounts = array(
|
|||
array(
|
||||
'title' => translate('Events'),
|
||||
'filter' => array(
|
||||
'Query' => array (
|
||||
'Query' => array(
|
||||
'terms' => array()
|
||||
)
|
||||
),
|
||||
|
@ -120,6 +90,50 @@ $eventCounts = array(
|
|||
|
||||
|
||||
$navbar = getNavBarHTML();
|
||||
ob_start();
|
||||
include('_monitor_filters.php');
|
||||
$filterbar = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
$show_storage_areas = count($storage_areas) > 1 and canEdit( 'System' ) ? 1 : 0;
|
||||
$maxWidth = 0;
|
||||
$maxHeight = 0;
|
||||
$zoneCount = 0;
|
||||
for ( $i = 0; $i < count($displayMonitors); $i++ ) {
|
||||
$monitor = &$displayMonitors[$i];
|
||||
if ( $monitor['Function'] != 'None' ) {
|
||||
$scaleWidth = reScale( $monitor['Width'], $monitor['DefaultScale'], ZM_WEB_DEFAULT_SCALE );
|
||||
$scaleHeight = reScale( $monitor['Height'], $monitor['DefaultScale'], ZM_WEB_DEFAULT_SCALE );
|
||||
if ( $maxWidth < $scaleWidth ) $maxWidth = $scaleWidth;
|
||||
if ( $maxHeight < $scaleHeight ) $maxHeight = $scaleHeight;
|
||||
}
|
||||
$monitor['zmc'] = zmcStatus( $monitor );
|
||||
$monitor['zma'] = zmaStatus( $monitor );
|
||||
$monitor['ZoneCount'] = dbFetchOne( 'select count(Id) as ZoneCount from Zones where MonitorId = ?', 'ZoneCount', array($monitor['Id']) );
|
||||
$zoneCount += $monitor['ZoneCount'];
|
||||
|
||||
$counts = array();
|
||||
for ( $j = 0; $j < count($eventCounts); $j += 1 ) {
|
||||
$filter = addFilterTerm(
|
||||
$eventCounts[$j]['filter'],
|
||||
count($eventCounts[$j]['filter']['Query']['terms']),
|
||||
array( 'cnj' => 'and', 'attr' => 'MonitorId', 'op' => '=', 'val' => $monitor['Id'] )
|
||||
);
|
||||
parseFilter( $filter );
|
||||
$counts[] = 'count(if(1'.$filter['sql'].",1,NULL)) AS EventCount$j, SUM(if(1".$filter['sql'].",DiskSpace,NULL)) As DiskSpace$j";
|
||||
$monitor['eventCounts'][$j]['filter'] = $filter;
|
||||
}
|
||||
$sql = 'SELECT '.join($counts,', ').' FROM Events as E where MonitorId = ?';
|
||||
$counts = dbFetchOne( $sql, NULL, array($monitor['Id']) );
|
||||
if ( $counts )
|
||||
$monitor = array_merge( $monitor, $counts );
|
||||
for ( $j = 0; $j < count($eventCounts); $j += 1 ) {
|
||||
$eventCounts[$j]['total'] += $monitor['EventCount'.$j];
|
||||
}
|
||||
unset($monitor);
|
||||
} // end foreach display monitor
|
||||
$cycleWidth = $maxWidth;
|
||||
$cycleHeight = $maxHeight;
|
||||
|
||||
noCacheHeaders();
|
||||
|
||||
|
@ -137,139 +151,7 @@ xhtmlHeaders( __FILE__, translate('Console') );
|
|||
<input type="hidden" name="action" value=""/>
|
||||
|
||||
<?php echo $navbar ?>
|
||||
<div class="controlHeader">
|
||||
<span id="groupControl"><label><?php echo translate('Group') ?>:</label>
|
||||
<?php
|
||||
# This will end up with the group_id of the deepest selection
|
||||
$group_id = Group::get_group_dropdowns();
|
||||
$groupSql = Group::get_group_sql( $group_id );
|
||||
?>
|
||||
</span>
|
||||
<span id="monitorControl"><label><?php echo translate('Monitor') ?>:</label>
|
||||
<?php
|
||||
|
||||
$monitor_id = 0;
|
||||
if ( isset( $_REQUEST['monitor_id'] ) ) {
|
||||
$monitor_id = $_REQUEST['monitor_id'];
|
||||
} else if ( isset($_COOKIE['zmMonitorId']) ) {
|
||||
$monitor_id = $_COOKIE['zmMonitorId'];
|
||||
}
|
||||
|
||||
$maxWidth = 0;
|
||||
$maxHeight = 0;
|
||||
# Used to determine if the Cycle button should be made available
|
||||
|
||||
$conditions = array();
|
||||
$values = array();
|
||||
|
||||
if ( $groupSql )
|
||||
$conditions[] = $groupSql;
|
||||
if ( isset($_SESSION['ServerFilter']) ) {
|
||||
$conditions[] = 'ServerId=?';
|
||||
$values[] = $_SESSION['ServerFilter'];
|
||||
}
|
||||
if ( isset($_SESSION['StorageFilter']) ) {
|
||||
$conditions[] = 'StorageId=?';
|
||||
$values[] = $_SESSION['StorageFilter'];
|
||||
}
|
||||
$sql = 'SELECT * FROM Monitors' . ( count($conditions) ? ' WHERE ' . implode(' AND ', $conditions ) : '' ).' ORDER BY Sequence ASC';
|
||||
$monitors = dbFetchAll( $sql, null, $values );
|
||||
$displayMonitors = array();
|
||||
$monitors_dropdown = array(''=>'All');
|
||||
|
||||
if ( $monitor_id ) {
|
||||
$found_selected_monitor = false;
|
||||
|
||||
for ( $i = 0; $i < count($monitors); $i++ ) {
|
||||
if ( !visibleMonitor( $monitors[$i]['Id'] ) ) {
|
||||
continue;
|
||||
}
|
||||
$monitors_dropdown[$monitors[$i]['Id']] = $monitors[$i]['Name'];
|
||||
if ( $monitors[$i]['Id'] == $monitor_id ) {
|
||||
$found_selected_monitor = true;
|
||||
}
|
||||
}
|
||||
if ( ! $found_selected_monitor ) {
|
||||
$monitor_id = '';
|
||||
}
|
||||
}
|
||||
for ( $i = 0; $i < count($monitors); $i++ ) {
|
||||
if ( !visibleMonitor( $monitors[$i]['Id'] ) ) {
|
||||
continue;
|
||||
}
|
||||
$monitors_dropdown[$monitors[$i]['Id']] = $monitors[$i]['Name'];
|
||||
|
||||
if ( $monitor_id and ( $monitors[$i]['Id'] != $monitor_id ) ) {
|
||||
continue;
|
||||
}
|
||||
if ( $monitors[$i]['Function'] != 'None' ) {
|
||||
$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;
|
||||
}
|
||||
$displayMonitors[] = $monitors[$i];
|
||||
}
|
||||
|
||||
|
||||
echo htmlSelect( 'monitor_id', $monitors_dropdown, $monitor_id, array('onchange'=>'changeMonitor(this);') );
|
||||
|
||||
$cycleWidth = $maxWidth;
|
||||
$cycleHeight = $maxHeight;
|
||||
$zoneCount = 0;
|
||||
|
||||
for( $i = 0; $i < count($displayMonitors); $i += 1 ) {
|
||||
$monitor = $displayMonitors[$i];
|
||||
$monitor['zmc'] = zmcStatus( $monitor );
|
||||
$monitor['zma'] = zmaStatus( $monitor );
|
||||
$monitor['ZoneCount'] = dbFetchOne( 'select count(Id) as ZoneCount from Zones where MonitorId = ?', 'ZoneCount', array($monitor['Id']) );
|
||||
$counts = array();
|
||||
for ( $j = 0; $j < count($eventCounts); $j += 1 ) {
|
||||
$filter = addFilterTerm( $eventCounts[$j]['filter'], count($eventCounts[$j]['filter']['Query']['terms']), array( 'cnj' => 'and', 'attr' => 'MonitorId', 'op' => '=', 'val' => $monitor['Id'] ) );
|
||||
parseFilter( $filter );
|
||||
$counts[] = 'count(if(1'.$filter['sql'].",1,NULL)) AS EventCount$j, SUM(if(1".$filter['sql'].",DiskSpace,NULL)) As DiskSpace$j";
|
||||
$monitor['eventCounts'][$j]['filter'] = $filter;
|
||||
}
|
||||
$sql = 'SELECT '.join($counts,', ').' FROM Events as E where MonitorId = ?';
|
||||
$counts = dbFetchOne( $sql, NULL, array($monitor['Id']) );
|
||||
if ( $counts )
|
||||
$displayMonitors[$i] = $monitor = array_merge( $monitor, $counts );
|
||||
for ( $j = 0; $j < count($eventCounts); $j += 1 ) {
|
||||
$eventCounts[$j]['total'] += $monitor['EventCount'.$j];
|
||||
}
|
||||
$zoneCount += $monitor['ZoneCount'];
|
||||
}
|
||||
?>
|
||||
</span>
|
||||
<?php if ( count($ServersById) > 0 ) { ?>
|
||||
<span class="ServerFilter"><label><?php echo translate('Server')?>:</label>
|
||||
<?php
|
||||
echo htmlSelect( 'ServerFilter', array(''=>'All')+$ServersById, (isset($_SESSION['ServerFilter'])?$_SESSION['ServerFilter']:''), array('onchange'=>'changeFilter(this);') );
|
||||
?>
|
||||
</span>
|
||||
<?php
|
||||
}
|
||||
if ( count($StorageById) > 0 ) { ?>
|
||||
<span class="StorageFilter"><label><?php echo translate('Storage')?>:</label>
|
||||
<?php
|
||||
echo htmlSelect( 'StorageFilter', array(''=>'All')+$StorageById, (isset($_SESSION['StorageFilter'])?$_SESSION['StorageFilter']:''), array('onchange'=>'changeFilter(this);') );
|
||||
?>
|
||||
</span>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<span class="StatusFilter"><label><?php echo translate('Status')?>:</label>
|
||||
<?php
|
||||
$status_options = array(
|
||||
''=>'All',
|
||||
'Unknown' => translate('Unknown'),
|
||||
'NotRunning' => translate('NotRunning'),
|
||||
'Running' => translate('Running'),
|
||||
);
|
||||
echo htmlSelect( 'StatusFilter', $status_options, ( isset($_SESSION['StatusFilter']) ? $_SESSION['StatusFilter'] : '' ), array('onchange'=>'changeFilter(this);') );
|
||||
?>
|
||||
</span>
|
||||
</div>
|
||||
<?php echo $filterbar ?>
|
||||
|
||||
<div class="container-fluid">
|
||||
<table class="table table-striped table-hover table-condensed" id="consoleTable">
|
||||
|
|
|
@ -84,6 +84,7 @@ if ( !empty($page) ) {
|
|||
$eventsSql .= ' limit 0, '.$limit;
|
||||
}
|
||||
|
||||
if ( 0 ) {
|
||||
$maxWidth = 0;
|
||||
$maxHeight = 0;
|
||||
$archived = false;
|
||||
|
@ -103,6 +104,7 @@ foreach ( dbFetchAll( $eventsSql ) as $event_row ) {
|
|||
else
|
||||
$unarchived = true;
|
||||
}
|
||||
}
|
||||
|
||||
$maxShortcuts = 5;
|
||||
$pagination = getPagination( $pages, $page, $maxShortcuts, $filterQuery.$sortQuery.'&limit='.$limit );
|
||||
|
@ -160,7 +162,12 @@ if ( $pagination ) {
|
|||
$count = 0;
|
||||
$disk_space_total = 0;
|
||||
|
||||
foreach ( $events as $event ) {
|
||||
$results = dbQuery( $eventsSql );
|
||||
while ( $event_row = dbFetchNext( $results ) ) {
|
||||
$event = new Event( $event_row );
|
||||
#foreach ( dbFetchAll( $eventsSql ) as $event_row ) {
|
||||
#$events[] = $event = new Event( $event_row );
|
||||
#foreach ( $events as $event ) {
|
||||
if ( ($count++%ZM_WEB_EVENTS_PER_PAGE) == 0 ) {
|
||||
?>
|
||||
<tr>
|
||||
|
|
|
@ -104,6 +104,8 @@ $opTypes = array(
|
|||
'!~' => translate('OpNotMatches'),
|
||||
'=[]' => translate('OpIn'),
|
||||
'![]' => translate('OpNotIn'),
|
||||
'IS' => translate('OpIs'),
|
||||
'IS NOT' => translate('OpIsNot'),
|
||||
);
|
||||
|
||||
$archiveTypes = array(
|
||||
|
|
|
@ -87,9 +87,11 @@ function get_children($Group) {
|
|||
}
|
||||
|
||||
$kids = get_children($newGroup);
|
||||
$kids[] = $newGroup->Id();
|
||||
if ( $newGroup->Id() )
|
||||
$kids[] = $newGroup->Id();
|
||||
$sql = 'SELECT Id,Name from Groups'.(count($kids)?' WHERE Id NOT IN ('.implode(',',array_map(function(){return '?';}, $kids )).')' : '').' ORDER BY Name';
|
||||
$options = array(''=>'None');
|
||||
foreach ( dbFetchAll( 'SELECT Id,Name from Groups WHERE Id NOT IN ('.implode(',',array_map(function(){return '?';}, $kids )).') ORDER BY Name', null, $kids ) as $option ) {
|
||||
foreach ( dbFetchAll( $sql, null, $kids ) as $option ) {
|
||||
$options[$option['Id']] = $option['Name'];
|
||||
}
|
||||
echo htmlSelect( 'newGroup[ParentId]', $options, $newGroup->ParentId(), array('onchange'=>'configureButtons(this);' ));
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
|
||||
var probeReq = new Request.JSON( { url:thisUrl, method: 'get', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getProbeResponse } );
|
||||
|
||||
function probe( url_e ) {
|
||||
probeReq.send( "request=add_monitors&action=probe&url="+url_e.value );
|
||||
}
|
||||
|
||||
var ProbeResults;
|
||||
|
||||
function getProbeResponse( respObj, respText ) {
|
||||
if ( checkStreamForErrors( "getProbeResponse", respObj ) )
|
||||
return;
|
||||
//alert(respText);
|
||||
|
||||
if ( respObj.Streams ) {
|
||||
parseStreams( respObj.Streams );
|
||||
} else {
|
||||
alert("No Streams");
|
||||
}
|
||||
} // end function getProbeResponse
|
||||
|
||||
function parseStreams( Streams ) {
|
||||
ProbeResults = Array();
|
||||
|
||||
var results_div = $j('#url_results')[0];
|
||||
if ( ! results_div ) {
|
||||
console.log("No results div found.");
|
||||
return;
|
||||
}
|
||||
results_div.innerHTML = '';
|
||||
var html = '';
|
||||
|
||||
for( i in Streams ) {
|
||||
var stream = Streams[i];
|
||||
if ( stream.url ) {
|
||||
html += '<p>'+stream.url;
|
||||
if ( stream.Monitor.Id ) {
|
||||
html += ' is already entered into the system by Monitor ' + stream.Monitor.Id + ' ' + stream.Monitor.Name + '<br/>';
|
||||
html += '<input type="button" value="Edit" onclick="addMonitor(\''+stream.url+'\');"/>';
|
||||
} else {
|
||||
html += '<input type="button" value="Add" onclick="addMonitor(\''+stream.url+'\');"/>';
|
||||
}
|
||||
html += '</p>';
|
||||
ProbeResults[stream.url] = stream;
|
||||
} else {
|
||||
//console.log(stream);
|
||||
}
|
||||
} // end for eah Stream
|
||||
|
||||
results_div.innerHTML = html;
|
||||
}
|
||||
|
||||
function addMonitor(url) {
|
||||
if ( ! ProbeResults[url] ) {
|
||||
alert("Monitor for url " + url + " not found in probe results." );
|
||||
return;
|
||||
}
|
||||
var Stream = ProbeResults[url];
|
||||
var Monitor = Stream.Monitor;
|
||||
|
||||
popup_url = '?view=monitor&newMonitor[Path]='+url;
|
||||
keys = Object.keys( Monitor );
|
||||
for ( i in Monitor ) {
|
||||
if ( ! Monitor[i] )
|
||||
continue;
|
||||
if ( Monitor[i] == 'null' )
|
||||
Monitor[i]='';
|
||||
popup_url += '&newMonitor['+i+']='+Monitor[i];
|
||||
}
|
||||
createPopup( popup_url, 'zmMonitor0', 'monitor' );
|
||||
}
|
||||
|
||||
function import_csv( form ) {
|
||||
var formData = new FormData( form );
|
||||
console.log(formData);
|
||||
//formData.append('file', $('#file')[0].files[0]);
|
||||
|
||||
$j.ajax({
|
||||
url : thisUrl+"?request=add_monitors&action=import",
|
||||
type : 'POST',
|
||||
data : formData,
|
||||
processData: false, // tell jQuery not to process the data
|
||||
contentType: false, // tell jQuery not to set contentType
|
||||
success : function(data) {
|
||||
var json = JSON.parse(data);
|
||||
parseStreams( json.Streams );
|
||||
}
|
||||
});
|
||||
}
|
|
@ -19,7 +19,7 @@ function setButtonStates( element ) {
|
|||
form.deleteBtn.disabled = (checked==0);
|
||||
}
|
||||
|
||||
function addMonitor( element) {
|
||||
function addMonitor(element) {
|
||||
var form = element.form;
|
||||
var dupParam;
|
||||
var monitorId=-1;
|
||||
|
|
|
@ -7,11 +7,10 @@ function Monitor( monitorData ) {
|
|||
this.status = null;
|
||||
this.alarmState = STATE_IDLE;
|
||||
this.lastAlarmState = STATE_IDLE;
|
||||
this.streamCmdParms = "view=request&request=stream&connkey="+this.connKey;
|
||||
this.streamCmdParms = 'view=request&request=stream&connkey='+this.connKey;
|
||||
this.onclick = monitorData.onclick;
|
||||
if ( auth_hash )
|
||||
this.streamCmdParms += '&auth='+auth_hash;
|
||||
else
|
||||
console.log("No auth_hash");
|
||||
this.streamCmdTimer = null;
|
||||
|
||||
this.start = function( delay ) {
|
||||
|
@ -34,7 +33,8 @@ function Monitor( monitorData ) {
|
|||
if ( this.streamCmdTimer )
|
||||
this.streamCmdTimer = clearTimeout( this.streamCmdTimer );
|
||||
|
||||
var stream = $j('#liveStream'+this.id )[0];
|
||||
var stream = $j('#liveStream'+this.id)[0];
|
||||
|
||||
if ( respObj.result == 'Ok' ) {
|
||||
this.status = respObj.status;
|
||||
this.alarmState = this.status.state;
|
||||
|
@ -83,42 +83,106 @@ function Monitor( monitorData ) {
|
|||
// Try to reload the image stream.
|
||||
if ( stream )
|
||||
stream.src = stream.src.replace( /auth=\w+/i, 'auth='+this.status.auth );
|
||||
console.log("Changed auth to " + this.status.auth );
|
||||
console.log("Changed auth from " + auth_hash + " to " + this.status.auth );
|
||||
auth_hash = this.status.auth;
|
||||
}
|
||||
} // end if haev a new auth hash
|
||||
} // end if have a new auth hash
|
||||
} else {
|
||||
console.error( respObj.message );
|
||||
// Try to reload the image stream.
|
||||
if ( stream )
|
||||
if ( stream ) {
|
||||
if ( stream.src ) {
|
||||
console.log('Reloading stream: ' + stream.src );
|
||||
stream.src = stream.src.replace(/rand=\d+/i, 'rand='+Math.floor((Math.random() * 1000000) ));
|
||||
} else {
|
||||
}
|
||||
} else {
|
||||
console.log( 'No stream to reload?' );
|
||||
}
|
||||
} // end if Ok or not
|
||||
var streamCmdTimeout = statusRefreshTimeout;
|
||||
if ( this.alarmState == STATE_ALARM || this.alarmState == STATE_ALERT )
|
||||
streamCmdTimeout = streamCmdTimeout/5;
|
||||
// The idea here is if we are alarmed, do updates faster. However, there is a timeout in the php side which isn't getting modified, so this may cause a problem. Also the server may only be able to update so fast.
|
||||
//if ( this.alarmState == STATE_ALARM || this.alarmState == STATE_ALERT ) {
|
||||
//streamCmdTimeout = streamCmdTimeout/5;
|
||||
//}
|
||||
this.streamCmdTimer = this.streamCmdQuery.delay( streamCmdTimeout, this );
|
||||
this.lastAlarmState = this.alarmState;
|
||||
};
|
||||
|
||||
this.streamCmdQuery = function( resent ) {
|
||||
//if ( resent )
|
||||
//console.log( this.connKey+": Resending" );
|
||||
if ( resent )
|
||||
console.log( this.connKey+": Resending" );
|
||||
//this.streamCmdReq.cancel();
|
||||
this.streamCmdReq.send( this.streamCmdParms+"&command="+CMD_QUERY );
|
||||
};
|
||||
this.onError = function( text, error ) {
|
||||
console.log('onerror: ' + text + ' error:'+error);
|
||||
};
|
||||
this.onFailure = function( xhr ) {
|
||||
console.log('onFailure: ' );
|
||||
console.log(xhr );
|
||||
// Requeue
|
||||
var streamCmdTimeout = statusRefreshTimeout;
|
||||
this.streamCmdTimer = this.streamCmdQuery.delay( streamCmdTimeout, this );
|
||||
};
|
||||
|
||||
this.streamCmdReq = new Request.JSON( { url: this.server_url, method: 'get', timeout: AJAX_TIMEOUT, onSuccess: this.getStreamCmdResponse.bind( this ), onTimeout: this.streamCmdQuery.bind( this, true ), link: 'cancel' } );
|
||||
this.streamCmdReq = new Request.JSON( {
|
||||
url: this.server_url,
|
||||
method: 'get',
|
||||
timeout: 1000+AJAX_TIMEOUT,
|
||||
onSuccess: this.getStreamCmdResponse.bind( this ),
|
||||
onTimeout: this.streamCmdQuery.bind( this, true ),
|
||||
onError: this.onError.bind(this),
|
||||
onFailure: this.onFailure.bind(this),
|
||||
link: 'cancel'
|
||||
} );
|
||||
|
||||
requestQueue.addRequest( "cmdReq"+this.id, this.streamCmdReq );
|
||||
}
|
||||
|
||||
function selectLayout( element ) {
|
||||
layout = $(element).get('value')
|
||||
var cssFile = skinPath+'/css/'+Cookie.read('zmCSS')+'/views/'+layout;
|
||||
if ( $('dynamicStyles') )
|
||||
$('dynamicStyles').destroy();
|
||||
new Asset.css( cssFile, { id: 'dynamicStyles' } );
|
||||
Cookie.write( 'zmMontageLayout', layout, { duration: 10*365 } );
|
||||
if ( layout != 'montage_freeform.css' ) {
|
||||
layout = $j(element).val();
|
||||
|
||||
if ( layout_id = parseInt(layout) ) {
|
||||
layout = layouts[layout];
|
||||
console.log(layout);
|
||||
|
||||
for ( var i = 0; i < monitors.length; i++ ) {
|
||||
monitor = monitors[i];
|
||||
// Need to clear the current positioning, and apply the new
|
||||
|
||||
monitor_frame = $j('#monitorFrame'+monitor.id);
|
||||
if ( ! monitor_frame ) {
|
||||
console.log("Error finding frame for " + monitor.id );
|
||||
continue;
|
||||
}
|
||||
|
||||
// Apply default layout options, like float left
|
||||
if ( layout.Positions['default'] ) {
|
||||
styles = layout.Positions['default'];
|
||||
for ( style in styles ) {
|
||||
monitor_frame.css(style, styles[style]);
|
||||
}
|
||||
} else {
|
||||
console.log("No default styles to apply" + layout.Positions);
|
||||
} // end if default styles
|
||||
|
||||
if ( layout.Positions['mId'+monitor.id] ) {
|
||||
styles = layout.Positions['mId'+monitor.id];
|
||||
for ( style in styles ) {
|
||||
monitor_frame.css(style, styles[style]);
|
||||
console.log("Applying " + style + ' : ' + styles[style] );
|
||||
}
|
||||
} else {
|
||||
console.log("No Monitor styles to apply");
|
||||
} // end if specific monitor style
|
||||
} // end foreach monitor
|
||||
} // end if a stored layout
|
||||
if ( ! layout ) {
|
||||
return;
|
||||
}
|
||||
Cookie.write( 'zmMontageLayout', layout_id, { duration: 10*365 } );
|
||||
if ( layouts[layout_id].Name != 'Freeform' ) { // 'montage_freeform.css' ) {
|
||||
Cookie.write( 'zmMontageScale', '', { duration: 10*365 } );
|
||||
$('scale').set('value', '' );
|
||||
$('width').set('value', '');
|
||||
|
@ -152,6 +216,17 @@ function changeSize() {
|
|||
|
||||
for ( var x = 0; x < monitors.length; x++ ) {
|
||||
var monitor = monitors[x];
|
||||
|
||||
// Scale the frame
|
||||
monitor_frame = $j('#monitorFrame'+monitor.id);
|
||||
if ( ! monitor_frame ) {
|
||||
console.log("Error finding frame for " + monitor.id );
|
||||
continue;
|
||||
}
|
||||
if ( width )
|
||||
monitor_frame.css('width',width+'px');
|
||||
if ( height )
|
||||
monitor_frame.css('height',height+'px');
|
||||
/*Stream could be an applet so can't use moo tools*/
|
||||
var streamImg = $( 'liveStream'+monitor.id );
|
||||
if ( streamImg ) {
|
||||
|
@ -177,17 +252,37 @@ function changeSize() {
|
|||
Cookie.write( 'zmMontageScale', '', { duration: 10*365 } );
|
||||
Cookie.write( 'zmMontageWidth', width, { duration: 10*365 } );
|
||||
Cookie.write( 'zmMontageHeight', height, { duration: 10*365 } );
|
||||
selectLayout('#zmMontageLayout');
|
||||
} // end function changeSize()
|
||||
|
||||
function changeScale() {
|
||||
var scale = $('scale').get('value');
|
||||
|
||||
$('width').set('value', '');
|
||||
$('height').set('value', '');
|
||||
Cookie.write( 'zmMontageScale', scale, { duration: 10*365 } );
|
||||
Cookie.write( 'zmMontageWidth', '', { duration: 10*365 } );
|
||||
Cookie.write( 'zmMontageHeight', '', { duration: 10*365 } );
|
||||
if ( ! scale ) {
|
||||
selectLayout('#zmMontageLayout');
|
||||
return;
|
||||
}
|
||||
for ( var x = 0; x < monitors.length; x++ ) {
|
||||
var monitor = monitors[x];
|
||||
var newWidth = ( monitorData[x].width * scale ) / SCALE_BASE;
|
||||
var newHeight = ( monitorData[x].height * scale ) / SCALE_BASE;
|
||||
|
||||
// Scale the frame
|
||||
monitor_frame = $j('#monitorFrame'+monitor.id);
|
||||
if ( ! monitor_frame ) {
|
||||
console.log("Error finding frame for " + monitor.id );
|
||||
continue;
|
||||
}
|
||||
if ( width )
|
||||
monitor_frame.css('width',width+'px');
|
||||
if ( height )
|
||||
monitor_frame.css('height',height+'px');
|
||||
/*Stream could be an applet so can't use moo tools*/
|
||||
var streamImg = document.getElementById( 'liveStream'+monitor.id );
|
||||
var streamImg = $j('#liveStream'+monitor.id )[0];
|
||||
if ( streamImg ) {
|
||||
if ( streamImg.nodeName == 'IMG' ) {
|
||||
var src = streamImg.src;
|
||||
|
@ -208,22 +303,72 @@ function changeScale() {
|
|||
zonesSVG.style.height = newHeight + "px";
|
||||
}
|
||||
}
|
||||
$('width').set('value', '');
|
||||
$('height').set('value', '');
|
||||
Cookie.write( 'zmMontageScale', scale, { duration: 10*365 } );
|
||||
Cookie.write( 'zmMontageWidth', '', { duration: 10*365 } );
|
||||
Cookie.write( 'zmMontageHeight', '', { duration: 10*365 } );
|
||||
}
|
||||
|
||||
function toGrid(value) {
|
||||
return Math.round(value / 80) * 80;
|
||||
}
|
||||
|
||||
// Makes monitorFrames draggable.
|
||||
function edit_layout(button) {
|
||||
|
||||
// Turn off the onclick on the image.
|
||||
|
||||
for ( var i = 0; i < monitors.length; i++ ) {
|
||||
var monitor = monitors[i];
|
||||
monitor_feed = $j('#imageFeed'+monitor.id)[0];
|
||||
monitor_feed.onclick='';
|
||||
};
|
||||
|
||||
$j('#monitors .monitorFrame').draggable({
|
||||
cursor: 'crosshair',
|
||||
//revert: 'invalid'
|
||||
});
|
||||
$j('#SaveLayout').show();
|
||||
$j('#EditLayout').hide();
|
||||
} // end function edit_layout
|
||||
|
||||
function save_layout(button) {
|
||||
var form=button.form;
|
||||
// In fixed positioning, order doesn't matter. In floating positioning, it does.
|
||||
var Positions = {};
|
||||
for ( var i = 0; i < monitors.length; i++ ) {
|
||||
var monitor = monitors[i];
|
||||
monitor_frame = $j('#monitorFrame'+monitor.id);
|
||||
|
||||
Positions['mId'+monitor.id] = {
|
||||
width: monitor_frame.css('width'),
|
||||
height: monitor_frame.css('height'),
|
||||
top: monitor_frame.css('top'),
|
||||
bottom: monitor_frame.css('bottom'),
|
||||
left: monitor_frame.css('left'),
|
||||
right: monitor_frame.css('right'),
|
||||
position: monitor_frame.css('position'),
|
||||
float: monitor_frame.css('float'),
|
||||
};
|
||||
} // end foreach monitor
|
||||
form.Positions.value = JSON.stringify( Positions );
|
||||
form.submit();
|
||||
}
|
||||
function cancel_layout(button) {
|
||||
$j('#SaveLayout').hide();
|
||||
$j('#EditLayout').show();
|
||||
for ( var i = 0; i < monitors.length; i++ ) {
|
||||
var monitor = monitors[i];
|
||||
monitor_feed = $j('#imageFeed'+monitor.id);
|
||||
monitor_feed.click( monitor.onclick );
|
||||
};
|
||||
selectLayout('#zmMontageLayout');
|
||||
}
|
||||
|
||||
var monitors = new Array();
|
||||
function initPage() {
|
||||
for ( var i = 0; i < monitorData.length; i++ ) {
|
||||
monitors[i] = new Monitor( monitorData[i] );
|
||||
var delay = Math.round( (Math.random()+0.5)*statusRefreshTimeout );
|
||||
monitors[i].start( delay );
|
||||
monitors[i] = new Monitor(monitorData[i]);
|
||||
var delay = Math.round( (Math.random()+0.75)*statusRefreshTimeout );
|
||||
monitors[i].start(delay);
|
||||
}
|
||||
selectLayout($('layout'));
|
||||
selectLayout('#zmMontageLayout');
|
||||
}
|
||||
|
||||
// Kick everything off
|
||||
window.addEvent( 'domready', initPage );
|
||||
|
|
|
@ -35,8 +35,18 @@ monitorData[monitorData.length] = {
|
|||
'connKey': <?php echo $monitor->connKey() ?>,
|
||||
'width': <?php echo $monitor->Width() ?>,
|
||||
'height':<?php echo $monitor->Height() ?>,
|
||||
'server_url': '<?php echo $monitor->Server()->Url().(ZM_MIN_STREAMING_PORT?':'.(ZM_MIN_STREAMING_PORT+$monitor->Id()):'').$_SERVER['PHP_SELF'] ?>'
|
||||
'server_url': '<?php echo $monitor->Server()->Url().(ZM_MIN_STREAMING_PORT?':'.(ZM_MIN_STREAMING_PORT+$monitor->Id()):'').$_SERVER['PHP_SELF'] ?>',
|
||||
'onclick': function(){createPopup( '?view=watch&mid=<?php echo $monitor->Id() ?>', 'zmWatch<?php echo $monitor->Id() ?>', 'watch', <?php echo reScale( $monitor->Width(), $monitor->PopupScale() ); ?>, <?php echo reScale( $monitor->Height(), $monitor->PopupScale() ); ?> );}
|
||||
};
|
||||
<?php
|
||||
}
|
||||
} // end foreach monitor
|
||||
?>
|
||||
layouts = new Array();
|
||||
layouts[0] = {}; // reserved, should hold which fields to clear when transitioning
|
||||
<?php
|
||||
foreach ( $layouts as $layout ) {
|
||||
?>
|
||||
layouts[<?php echo $layout->Id() ?>] = {"Name":"<?php echo $layout->Name()?>","Positions":<?php echo $layout->Positions() ?>};
|
||||
<?php
|
||||
} // end foreach layout
|
||||
?>
|
||||
|
|
|
@ -84,7 +84,11 @@ function imagedone( obj, monId, success ) {
|
|||
if ( ! success ) {
|
||||
// if we had a failrue queue up the no-data image
|
||||
//loadImage2Monitor(monId,"no data"); // leave the staged URL if there is one, just ignore it here.
|
||||
loadNoData( monId );
|
||||
if ( liveMode ) {
|
||||
writeText( monId, "Camera Offline" );
|
||||
} else {
|
||||
writeText( monId, "No Data" );
|
||||
}
|
||||
} else {
|
||||
if ( monitorLoadingStageURL[monId] == "" ) {
|
||||
console.log("Not showing image for " + monId );
|
||||
|
|
|
@ -665,7 +665,7 @@ if ( ZM_HAS_V4L && ($tab != 'misc' || $monitor->Type()!= 'Local') ) {
|
|||
<?php
|
||||
}
|
||||
?>
|
||||
<table id="contentTable" class="major" cellspacing="0">
|
||||
<table id="contentTable" class="major">
|
||||
<tbody>
|
||||
<?php
|
||||
switch ( $tab ) {
|
||||
|
|
|
@ -23,6 +23,8 @@ if ( !canView('Stream') ) {
|
|||
return;
|
||||
}
|
||||
|
||||
require_once('includes/MontageLayout.php');
|
||||
|
||||
$showControl = false;
|
||||
$showZones = false;
|
||||
if ( isset( $_REQUEST['showZones'] ) ) {
|
||||
|
@ -57,58 +59,52 @@ if ( isset( $_REQUEST['scale'] ) ) {
|
|||
if ( ! $scale )
|
||||
$scale = 100;
|
||||
|
||||
$focusWindow = true;
|
||||
$layouts = MontageLayout::find(NULL, array('order'=>"lower('Name')"));
|
||||
$layoutsById = array();
|
||||
foreach ( $layouts as $l ) {
|
||||
$layoutsById[$l->Id()] = $l->Name();
|
||||
}
|
||||
|
||||
$layouts = array(
|
||||
'montage_freeform.css' => translate('MtgDefault'),
|
||||
'montage_2wide.css' => translate('Mtg2widgrd'),
|
||||
'montage_3wide.css' => translate('Mtg3widgrd'),
|
||||
'montage_4wide.css' => translate('Mtg4widgrd'),
|
||||
'montage_3wide50enlarge.css' => translate('Mtg3widgrx'),
|
||||
);
|
||||
|
||||
session_start();
|
||||
|
||||
$layout = '';
|
||||
if ( isset($_COOKIE['zmMontageLayout']) )
|
||||
$layout = $_COOKIE['zmMontageLayout'];
|
||||
if ( isset($_COOKIE['zmMontageLayout']) ) {
|
||||
$layout = $_SESSION['zmMontageLayout'] = $_COOKIE['zmMontageLayout'];
|
||||
Warning("Setting layout by cookie");
|
||||
} elseif ( isset($_SESSION['zmMontageLayout']) ) {
|
||||
$layout = $_SESSION['zmMontageLayout'];
|
||||
Warning("Setting layout by session");
|
||||
}
|
||||
|
||||
$options = array();
|
||||
if ( isset($_COOKIE['zmMontageWidth']) and $_COOKIE['zmMontageWidth'] )
|
||||
$options['width'] = $_COOKIE['zmMontageWidth'];
|
||||
else
|
||||
if ( isset($_COOKIE['zmMontageWidth']) and $_COOKIE['zmMontageWidth'] ) {
|
||||
$_SESSION['zmMontageWidth'] = $options['width'] = $_COOKIE['zmMontageWidth'];
|
||||
} elseif ( isset($_SESSION['zmMontageWidth']) and $_SESSION['zmMontageWidth'] ) {
|
||||
$options['width'] = $_SESSION['zmMontageWidth'];
|
||||
} else
|
||||
$options['width'] = '';
|
||||
|
||||
if ( isset($_COOKIE['zmMontageHeight']) and $_COOKIE['zmMontageHeight'] )
|
||||
$options['height'] = $_COOKIE['zmMontageHeight'];
|
||||
$_SESSION['zmMontageHeight'] = $options['height'] = $_COOKIE['zmMontageHeight'];
|
||||
else if ( isset($_SESSION['zmMontageHeight']) and $_SESSION['zmMontageHeight'] )
|
||||
$options['height'] = $_SESSION['zmMontageHeight'];
|
||||
else
|
||||
$options['height'] = '';
|
||||
session_write_close();
|
||||
|
||||
if ( $scale )
|
||||
$options['scale'] = $scale;
|
||||
|
||||
ob_start();
|
||||
# This will end up with the group_id of the deepest selection
|
||||
$group_id = Group::get_group_dropdowns();
|
||||
$group_dropdowns = ob_get_contents();
|
||||
include('_monitor_filters.php');
|
||||
$filterbar = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
$groupSql = Group::get_group_sql( $group_id );
|
||||
|
||||
$monitor_id = 0;
|
||||
if ( isset( $_REQUEST['monitor_id'] ) ) {
|
||||
$monitor_id = $_REQUEST['monitor_id'];
|
||||
} else if ( isset($_COOKIE['zmMonitorId']) ) {
|
||||
$monitor_id = $_COOKIE['zmMonitorId'];
|
||||
}
|
||||
|
||||
$monitors = array();
|
||||
$monitors_dropdown = array( '' => 'All' );
|
||||
$sql = "SELECT * FROM Monitors WHERE Function != 'None'";
|
||||
if ( $groupSql ) { $sql .= ' AND ' . $groupSql; };
|
||||
if ( $monitor_id ) { $sql .= ' AND Id='.$monitor_id; };
|
||||
|
||||
$sql .= ' ORDER BY Sequence';
|
||||
foreach( dbFetchAll( $sql ) as $row ) {
|
||||
if ( !visibleMonitor( $row['Id'] ) ) {
|
||||
foreach( $displayMonitors as &$row ) {
|
||||
if ( $row['Function'] == 'None' )
|
||||
continue;
|
||||
}
|
||||
|
||||
$row['Scale'] = $scale;
|
||||
$row['PopupScale'] = reScale( SCALE_BASE, $row['DefaultScale'], ZM_WEB_DEFAULT_SCALE );
|
||||
|
@ -116,14 +112,13 @@ foreach( dbFetchAll( $sql ) as $row ) {
|
|||
if ( ZM_OPT_CONTROL && $row['ControlId'] && $row['Controllable'] )
|
||||
$showControl = true;
|
||||
$row['connKey'] = generateConnKey();
|
||||
$Monitor = $monitors[] = new Monitor( $row );
|
||||
$monitors_dropdown[$Monitor->Id()] = $Monitor->Name();
|
||||
if ( ! isset( $widths[$row['Width']] ) ) {
|
||||
$widths[$row['Width']] = $row['Width'];
|
||||
}
|
||||
if ( ! isset( $heights[$row['Height']] ) ) {
|
||||
$heights[$row['Height']] = $row['Height'];
|
||||
}
|
||||
$monitors[] = new Monitor( $row );
|
||||
} # end foreach Monitor
|
||||
|
||||
xhtmlHeaders(__FILE__, translate('Montage') );
|
||||
|
@ -141,26 +136,36 @@ if ( $showControl ) {
|
|||
}
|
||||
if ( $showZones ) {
|
||||
?>
|
||||
<a href="<?php echo $_SERVER['PHP_SELF'].'?view=montage&showZones=0'; ?>">Hide Zones</a>
|
||||
<a id="ShowZones" href="<?php echo $_SERVER['PHP_SELF'].'?view=montage&showZones=0'; ?>">Hide Zones</a>
|
||||
<?php
|
||||
} else {
|
||||
?>
|
||||
<a href="<?php echo $_SERVER['PHP_SELF'].'?view=montage&showZones=1'; ?>">Show Zones</a>
|
||||
<a id="ShowZones" href="<?php echo $_SERVER['PHP_SELF'].'?view=montage&showZones=1'; ?>">Show Zones</a>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<div id="headerControl">
|
||||
<span id="groupControl"><label><?php echo translate('Group') ?>:</label>
|
||||
<?php echo $group_dropdowns; ?>
|
||||
</span>
|
||||
<span id="monitorControl"><label><?php echo translate('Monitor') ?>:</label>
|
||||
<?php echo htmlSelect( 'monitor_id', $monitors_dropdown, $monitor_id, array('onchange'=>'changeMonitor(this);') ); ?>
|
||||
</span>
|
||||
<?php echo $filterbar ?>
|
||||
<div id="sizeControl">
|
||||
<form action="index.php?view=montage" method="post">
|
||||
<input type="hidden" name="object" value="MontageLayout"/>
|
||||
<input type="hidden" name="action" value="Save"/>
|
||||
|
||||
<span id="widthControl"><label><?php echo translate('Width') ?>:</label><?php echo htmlSelect( 'width', $widths, $options['width'], 'changeSize(this);' ); ?></span>
|
||||
<span id="heightControl"><label><?php echo translate('Height') ?>:</label><?php echo htmlSelect( 'height', $heights, $options['height'], 'changeSize(this);' ); ?></span>
|
||||
<span id="scaleControl"><label><?php echo translate('Scale') ?>:</label><?php echo htmlSelect( 'scale', $scales, $scale, 'changeScale(this);' ); ?></span>
|
||||
<span id="layoutControl"><label for="layout"><?php echo translate('Layout') ?>:</label><?php echo htmlSelect( 'layout', $layouts, $layout, 'selectLayout(this);' )?></span>
|
||||
<span id="layoutControl">
|
||||
<label for="layout"><?php echo translate('Layout') ?>:</label>
|
||||
<?php echo htmlSelect( 'zmMontageLayout', $layoutsById, $layout, array( 'onchange'=>'selectLayout(this);', 'id'=>'zmMontageLayout') ); ?>
|
||||
</span>
|
||||
<input type="hidden" name="Positions"/>
|
||||
<input type="button" id="EditLayout" value="<?php echo translate('EditLayout') ?>" onclick="edit_layout(this);"/>
|
||||
<span id="SaveLayout" style="display:none;">
|
||||
<input type="text" name="Name" placeholder="Enter new name for layout if desired" />
|
||||
<input type="button" value="<?php echo translate('Save') ?>" onclick="save_layout(this);"/>
|
||||
<input type="button" value="Cancel" onclick="cancel_layout(this);"/>
|
||||
</span>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div id="content">
|
||||
|
@ -169,7 +174,7 @@ if ( $showZones ) {
|
|||
foreach ( $monitors as $monitor ) {
|
||||
$connkey = $monitor->connKey(); // Minor hack
|
||||
?>
|
||||
<div id="monitorFrame<?php echo $monitor->Id() ?>" class="monitorFrame" title="<?php echo $monitor->Id() . ' ' .$monitor->Name() ?>">
|
||||
<div id="monitorFrame<?php echo $monitor->Id() ?>" class="monitorFrame" title="<?php echo $monitor->Id() . ' ' .$monitor->Name() ?>" style="<?php echo $options['width'] ? 'width:'.$options['width'].'px;':''?>">
|
||||
<div id="monitor<?php echo $monitor->Id() ?>" class="monitor idle">
|
||||
<div id="imageFeed<?php echo $monitor->Id() ?>" class="imageFeed" onclick="createPopup( '?view=watch&mid=<?php echo $monitor->Id() ?>', 'zmWatch<?php echo $monitor->Id() ?>', 'watch', <?php echo reScale( $monitor->Width(), $monitor->PopupScale() ); ?>, <?php echo reScale( $monitor->Height(), $monitor->PopupScale() ); ?> );">
|
||||
<?php
|
||||
|
@ -210,16 +215,13 @@ foreach ( $monitors as $monitor ) {
|
|||
$row['Coords'] = pointsToCoords( $row['Points'] );
|
||||
$row['AreaCoords'] = preg_replace( '/\s+/', ',', $row['Coords'] );
|
||||
$zones[] = $row;
|
||||
}
|
||||
|
||||
} // end foreach Zone
|
||||
?>
|
||||
|
||||
<svg class="zones" id="zones<?php echo $monitor->Id() ?>" style="position:absolute; top: 0; left: 0; background: none; width: <?php echo $width ?>px; height: <?php echo $height ?>px;">
|
||||
<?php
|
||||
foreach( array_reverse($zones) as $zone ) {
|
||||
?>
|
||||
<polygon points="<?php echo $zone['AreaCoords'] ?>" class="<?php echo $zone['Type']?>" />
|
||||
<?php
|
||||
echo '<polygon points="'. $zone['AreaCoords'] .'" class="'. $zone['Type'].'" />';
|
||||
} // end foreach zone
|
||||
?>
|
||||
Sorry, your browser does not support inline SVG
|
||||
|
|
|
@ -55,62 +55,10 @@ if ( !canView( 'Events' ) ) {
|
|||
}
|
||||
|
||||
ob_start();
|
||||
# This will end up with the group_id of the deepest selection
|
||||
$group_id = Group::get_group_dropdowns();
|
||||
$group_dropdowns = ob_get_contents();
|
||||
include('_monitor_filters.php');
|
||||
$filter_bar = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
$groupSql = Group::get_group_sql( $group_id );
|
||||
|
||||
$servers = Server::find_all();
|
||||
$ServersById = array();
|
||||
foreach ( $servers as $S ) {
|
||||
$ServersById[$S->Id()] = $S;
|
||||
}
|
||||
$storage_areas = Storage::find_all();
|
||||
$StorageById = array();
|
||||
foreach ( $storage_areas as $S ) {
|
||||
$StorageById[$S->Id()] = $S;
|
||||
}
|
||||
session_start();
|
||||
foreach ( array('minTime','maxTime','ServerFilter','StorageFilter') as $var ) {
|
||||
if ( isset( $_REQUEST[$var] ) ) {
|
||||
if ( $_REQUEST[$var] != '' ) {
|
||||
$_SESSION[$var] = $_REQUEST[$var];
|
||||
} else {
|
||||
unset( $_SESSION[$var] );
|
||||
}
|
||||
} else if ( isset( $_COOKIE[$var] ) ) {
|
||||
if ( $_COOKIE[$var] != '' ) {
|
||||
$_SESSION[$var] = $_COOKIE[$var];
|
||||
} else {
|
||||
unset($_SESSION[$var]);
|
||||
}
|
||||
}
|
||||
}
|
||||
session_write_close();
|
||||
|
||||
$monitor_id = 0;
|
||||
if ( isset( $_REQUEST['monitor_id'] ) ) {
|
||||
$monitor_id = $_REQUEST['monitor_id'];
|
||||
} else if ( isset($_COOKIE['zmMonitorId']) ) {
|
||||
$monitor_id = $_COOKIE['zmMonitorId'];
|
||||
}
|
||||
|
||||
$conditions = array();
|
||||
$values = array();
|
||||
|
||||
if ( $groupSql )
|
||||
$conditions[] = $groupSql;
|
||||
if ( isset($_SESSION['ServerFilter']) ) {
|
||||
$conditions[] = 'ServerId=?';
|
||||
$values[] = $_SESSION['ServerFilter'];
|
||||
}
|
||||
if ( isset($_SESSION['StorageFilter']) ) {
|
||||
$conditions[] = 'StorageId=?';
|
||||
$values[] = $_SESSION['StorageFilter'];
|
||||
}
|
||||
|
||||
// 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 be able to include more current frames reduce bulk frame sizes (event size can be large)
|
||||
// Note we round up just a bit on the end time as otherwise you get gaps, like 59.78 to 00 in the next second, which can give blank frames when moved through slowly.
|
||||
|
@ -142,15 +90,9 @@ $frameSql = '
|
|||
|
||||
if ( ! empty( $user['MonitorIds'] ) ) {
|
||||
$eventsSql .= ' AND M.Id IN ('.$user['MonitorIds'].')';
|
||||
$monitorsSql .= ' AND Id IN ('.$user['MonitorIds'].')';
|
||||
$monitor_ids = explode(',',$user['MonitorIds']);
|
||||
$conditions[] .= 'Id IN ('.array_map( function(){return '?';}, $monitor_ids ) . ')';
|
||||
array_push( $values, $monitor_ids );
|
||||
$frameSql .= ' AND E.MonitorId IN ('.$user['MonitorIds'].')';
|
||||
}
|
||||
if ( $monitor_id ) {
|
||||
$conditions[] = 'Id=?';
|
||||
$values[] = $monitor_id;
|
||||
$eventsSql .= ' AND M.Id='.$monitor_id;
|
||||
$frameSql .= ' AND E.MonitorId='.$monitor_id;
|
||||
}
|
||||
|
@ -160,7 +102,6 @@ if ( $monitor_id ) {
|
|||
|
||||
// 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']) ) {
|
||||
$time = time();
|
||||
$maxTime = strftime("%FT%T",$time);
|
||||
|
@ -180,7 +121,7 @@ if ( (strtotime($maxTime) - strtotime($minTime))/(365*24*3600) > 30 ) {
|
|||
$maxTime = null;
|
||||
}
|
||||
|
||||
$fitMode=1;
|
||||
$fitMode = 1;
|
||||
if (isset($_REQUEST['fit']) && $_REQUEST['fit']=='0' )
|
||||
$fitMode = 0;
|
||||
|
||||
|
@ -196,7 +137,7 @@ if ( isset($_REQUEST['speed']) )
|
|||
else
|
||||
$defaultSpeed = 1;
|
||||
|
||||
$speedIndex=5; // default to 1x
|
||||
$speedIndex = 5; // default to 1x
|
||||
for ( $i = 0; $i < count($speeds); $i++ ) {
|
||||
if ( $speeds[$i] == $defaultSpeed ) {
|
||||
$speedIndex = $i;
|
||||
|
@ -225,10 +166,10 @@ if ( isset($minTime) && isset($maxTime) ) {
|
|||
}
|
||||
$frameSql .= ' GROUP BY E.Id, E.MonitorId, F.TimeStamp, F.Delta ORDER BY E.MonitorId, F.TimeStamp ASC';
|
||||
|
||||
|
||||
$monitors = array();
|
||||
$monitorsSql = 'SELECT * FROM Monitors' . ( count($conditions) ? ' WHERE ' . implode(' AND ', $conditions ) : '' ).' ORDER BY Sequence ASC';
|
||||
foreach( dbFetchAll( $monitorsSql, null, $values ) as $row ) {
|
||||
foreach( $displayMonitors as &$row ) {
|
||||
if ( $row['Function'] == 'None' )
|
||||
continue;
|
||||
$Monitor = new Monitor( $row );
|
||||
$monitors[] = $Monitor;
|
||||
}
|
||||
|
@ -243,32 +184,7 @@ xhtmlHeaders(__FILE__, translate('MontageReview') );
|
|||
<form action="<?php echo $_SERVER['PHP_SELF'] ?>" method="get">
|
||||
<input type="hidden" name="view" value="montagereview"/>
|
||||
<div id="header">
|
||||
<div id="headerControl">
|
||||
<span id="groupControl"><label><?php echo translate('Group') ?>:</label>
|
||||
<?php echo $group_dropdowns; ?>
|
||||
</span>
|
||||
<span id="monitorControl"><label><?php echo translate('Monitor') ?>:</label>
|
||||
<?php Group::get_monitors_dropdown( $groupSql ? array( 'groupSql'=>$groupSql) : null ); ?>
|
||||
</span>
|
||||
<?php
|
||||
if ( count($ServersById) > 0 ) { ?>
|
||||
<span class="ServerFilter"><label><?php echo translate('Server')?>:</label>
|
||||
<?php
|
||||
echo htmlSelect( 'ServerFilter', array(''=>'All')+$ServersById, (isset($_SESSION['ServerFilter'])?$_SESSION['ServerFilter']:''), array('onchange'=>'changeFilter(this);') );
|
||||
?>
|
||||
</span>
|
||||
<?php
|
||||
}
|
||||
if ( count($StorageById) > 0 ) { ?>
|
||||
<span class="StorageFilter"><label><?php echo translate('Storage')?>:</label>
|
||||
<?php
|
||||
echo htmlSelect( 'StorageFilter', array(''=>'All')+$StorageById, (isset($_SESSION['StorageFilter'])?$_SESSION['StorageFilter']:''), array('onchange'=>'changeFilter(this);') );
|
||||
?>
|
||||
</span>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
<?php echo $filter_bar ?>
|
||||
<div id="DateTimeDiv">
|
||||
<input type="datetime-local" name="minTime" id="minTime" value="<?php echo preg_replace('/ /', 'T', $minTime ) ?>" onchange="changeDateTime(this);"> to
|
||||
<input type="datetime-local" name="maxTime" id="maxTime" value="<?php echo preg_replace('/ /', 'T', $maxTime ) ?>" onchange="changeDateTime(this);">
|
||||
|
|
|
@ -25,6 +25,11 @@ if ( !canView( 'Stream' ) ) {
|
|||
return;
|
||||
}
|
||||
|
||||
if ( ! isset($_REQUEST['mid']) ) {
|
||||
$view = 'error';
|
||||
return;
|
||||
}
|
||||
|
||||
// This is for input sanitation
|
||||
$mid = intval( $_REQUEST['mid'] );
|
||||
if ( ! visibleMonitor( $mid ) ) {
|
||||
|
|
Loading…
Reference in New Issue