Merge branch 'storageareas' into ffmpeg_output

Conflicts:
	scripts/ZoneMinder/lib/ZoneMinder/Logger.pm
	scripts/ZoneMinder/lib/ZoneMinder/Object.pm
This commit is contained in:
APHW2 MFGENG 2017-11-07 18:25:33 -08:00
commit 4e080b8a36
63 changed files with 3372 additions and 2496 deletions

View File

@ -636,7 +636,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 -- 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 -- Add in some sample control protocol definitions
@ -764,6 +764,21 @@ CREATE TABLE Maps (
`ParentId` int(1) unsigned, `ParentId` int(1) unsigned,
PRIMARY KEY (`Id`) 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 -- Apply the initial configuration
-- --

69
db/zm_update-1.31.11.sql Normal file
View File

@ -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;

67
db/zm_update-1.31.12.sql Normal file
View File

@ -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;

View File

@ -27,7 +27,8 @@ override_dh_auto_configure:
-DZM_CGIDIR="/usr/lib/zoneminder/cgi-bin" \ -DZM_CGIDIR="/usr/lib/zoneminder/cgi-bin" \
-DZM_DIR_EVENTS="/var/cache/zoneminder/events" \ -DZM_DIR_EVENTS="/var/cache/zoneminder/events" \
-DZM_DIR_IMAGES="/var/cache/zoneminder/images" \ -DZM_DIR_IMAGES="/var/cache/zoneminder/images" \
-DZM_PATH_ZMS="/zm/cgi-bin/nph-zms" -DZM_PATH_ZMS="/zm/cgi-bin/nph-zms" \
-DZM_NO_LIBVLC=1
override_dh_clean: override_dh_clean:
dh_clean $(MANPAGES1) dh_clean $(MANPAGES1)

View File

@ -4,5 +4,6 @@ var/cache/zoneminder/events
var/cache/zoneminder/images var/cache/zoneminder/images
var/cache/zoneminder/temp var/cache/zoneminder/temp
usr/share/zoneminder/db usr/share/zoneminder/db
usr/share/zoneminder/www/cache
etc/zm/ etc/zm/
etc/zm/conf.d etc/zm/conf.d

View File

@ -1,3 +1,4 @@
d /var/run/zm 0755 www-data www-data d /var/run/zm 0755 www-data www-data
d /tmp/zm 0755 www-data www-data d /tmp/zm 0755 www-data www-data
d /var/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

View File

@ -115,7 +115,7 @@ BEGIN {
, $Config{ZM_DB_USER} , $Config{ZM_DB_USER}
, $Config{ZM_DB_PASS} , $Config{ZM_DB_PASS}
) or croak( "Can't connect to db" ); ) or croak( "Can't connect to db" );
my $sql = 'select * from Config'; my $sql = 'SELECT Name,Value FROM Config';
my $sth = $dbh->prepare_cached( $sql ) or croak( "Can't prepare '$sql': ".$dbh->errstr() ); my $sth = $dbh->prepare_cached( $sql ) or croak( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute() or croak( "Can't execute: ".$sth->errstr() ); my $res = $sth->execute() or croak( "Can't execute: ".$sth->errstr() );
while( my $config = $sth->fetchrow_hashref() ) { while( my $config = $sth->fetchrow_hashref() ) {

View File

@ -205,6 +205,30 @@ sub zmDbGetMonitorAndControl {
return( $monitor ); 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; 1;
__END__ __END__
# Below is stub documentation for your module. You'd better edit it! # Below is stub documentation for your module. You'd better edit it!

View File

@ -48,9 +48,38 @@ use ZoneMinder::Logger qw(:all);
use ZoneMinder::Database qw(:all); use ZoneMinder::Database qw(:all);
require Date::Parse; require Date::Parse;
use vars qw/ $table $primary_key /; use vars qw/ $table $primary_key %fields $serial @identified_by/;
$table = 'Events'; $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; use POSIX;
@ -359,14 +388,16 @@ sub age {
return $_[0]{age}; return $_[0]{age};
} }
sub DiskUsage { sub DiskSpace {
if ( @_ > 1 ) { 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; my $size = 0;
File::Find::find( { wanted=>sub { $size += -f $_ ? -s _ : 0 }, untaint=>1 }, $_[0]->Path() ); 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");
} }
} }

View File

@ -224,7 +224,7 @@ sub Sql {
|| $term->{attr} eq 'Notes' || $term->{attr} eq 'Notes'
) { ) {
$value = "'$temp_value'"; $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 ); $value = DateTimeToSQL( $temp_value );
if ( !$value ) { if ( !$value ) {
Error( "Error parsing date/time '$temp_value', " Error( "Error parsing date/time '$temp_value', "
@ -232,7 +232,7 @@ sub Sql {
return; return;
} }
$value = "'$value'"; $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 ); $value = DateTimeToSQL( $temp_value );
if ( !$value ) { if ( !$value ) {
Error( "Error parsing date/time '$temp_value', " Error( "Error parsing date/time '$temp_value', "
@ -240,7 +240,7 @@ sub Sql {
return; return;
} }
$value = "to_days( '$value' )"; $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 ); $value = DateTimeToSQL( $temp_value );
if ( !$value ) { if ( !$value ) {
Error( "Error parsing date/time '$temp_value', " Error( "Error parsing date/time '$temp_value', "
@ -259,6 +259,10 @@ sub Sql {
$self->{Sql} .= " regexp $value"; $self->{Sql} .= " regexp $value";
} elsif ( $term->{op} eq '!~' ) { } elsif ( $term->{op} eq '!~' ) {
$self->{Sql} .= " not regexp $value"; $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 '=[]' ) { } elsif ( $term->{op} eq '=[]' ) {
$self->{Sql} .= " in (".join( ",", @value_list ).")"; $self->{Sql} .= " in (".join( ",", @value_list ).")";
} elsif ( $term->{op} eq '!~' ) { } elsif ( $term->{op} eq '!~' ) {
@ -277,15 +281,15 @@ sub Sql {
if ( $self->{AutoMessage} ) { if ( $self->{AutoMessage} ) {
# Include all events, including events that are still ongoing # Include all events, including events that are still ongoing
# and have no EndTime yet # and have no EndTime yet
$sql .= " and ( ".$self->{Sql}." )"; $sql .= ' AND ( '.$self->{Sql}.' )';
} else { } else {
# Only include closed events (events with valid EndTime) # 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; my @auto_terms;
if ( $self->{AutoArchive} ) { 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. # Don't do this, it prevents re-generation and concatenation.
# If the file already exists, then the video won't be re-recreated # If the file already exists, then the video won't be re-recreated

View File

@ -678,7 +678,10 @@ sub Dump {
fetch()->logPrint( DEBUG, Data::Dumper->Dump( [ $var ], [ $label ] ) ); fetch()->logPrint( DEBUG, Data::Dumper->Dump( [ $var ], [ $label ] ) );
} }
sub debug { fetch()->logPrint( DEBUG, @_ ); } sub debug {
my $log = shift;
$log->logPrint( DEBUG, @_ );
}
sub Debug( @ ) { sub Debug( @ ) {
fetch()->logPrint( DEBUG, @_ ); fetch()->logPrint( DEBUG, @_ );
@ -688,7 +691,8 @@ sub Info( @ ) {
fetch()->logPrint( INFO, @_ ); fetch()->logPrint( INFO, @_ );
} }
sub info { sub info {
fetch()->logPrint( INFO, @_ ); my $log = shift;
$log->logPrint( INFO, @_ );
} }
@ -696,14 +700,16 @@ sub Warning( @ ) {
fetch()->logPrint( WARNING, @_ ); fetch()->logPrint( WARNING, @_ );
} }
sub warn { sub warn {
fetch()->logPrint( WARNING, @_ ); my $log = shift;
$log->logPrint( WARNING, @_ );
} }
sub Error( @ ) { sub Error( @ ) {
fetch()->logPrint( ERROR, @_ ); fetch()->logPrint( ERROR, @_ );
} }
sub error { sub error {
fetch()->logPrint( ERROR, @_ ); my $log = shift;
$log->logPrint( ERROR, @_ );
} }
sub Fatal( @ ) { sub Fatal( @ ) {

View File

@ -153,7 +153,7 @@ sub save {
my $serial = eval '$'.$type.'::serial'; my $serial = eval '$'.$type.'::serial';
my @identified_by = eval '@'.$type.'::identified_by'; my @identified_by = eval '@'.$type.'::identified_by';
my $ac = sql::start_transaction( $local_dbh ); my $ac = ZoneMinder::Database::start_transaction( $local_dbh );
if ( ! $serial ) { if ( ! $serial ) {
my $insert = $force_insert; my $insert = $force_insert;
my %serial = eval '%'.$type.'::serial'; my %serial = eval '%'.$type.'::serial';
@ -170,7 +170,7 @@ $log->debug("No serial") if $debug;
$where =~ s/\?/\%s/g; $where =~ s/\?/\%s/g;
$log->error("Error deleting: DELETE FROM $table WHERE " . sprintf($where, map { defined $_ ? $_ : 'undef' } ( @$self{@identified_by}) ).'):' . $local_dbh->errstr); $log->error("Error deleting: DELETE FROM $table WHERE " . sprintf($where, map { defined $_ ? $_ : 'undef' } ( @$self{@identified_by}) ).'):' . $local_dbh->errstr);
$local_dbh->rollback(); $local_dbh->rollback();
sql::end_transaction( $local_dbh, $ac ); ZoneMinder::Database::end_transaction( $local_dbh, $ac );
return $local_dbh->errstr; return $local_dbh->errstr;
} elsif ( $debug ) { } elsif ( $debug ) {
$log->debug("SQL succesful DELETE FROM $table WHERE $where"); $log->debug("SQL succesful DELETE FROM $table WHERE $where");
@ -185,8 +185,11 @@ $log->debug("No serial") if $debug;
next; next;
} }
if ( ! $$self{$id} ) { if ( ! $$self{$id} ) {
($$self{$id}) = ($sql{$$fields{$id}}) = $local_dbh->selectrow_array( q{SELECT nextval('} . $serial{$id} . q{')} ); my $s = qq{SELECT `auto_increment` FROM INFORMATION_SCHEMA.TABLES WHERE table_name = '$table'};
$log->debug("SQL statement execution SELECT nextval('$serial{$id}') returned $$self{$id}") if $debug or DEBUG_ALL;
($$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; $insert = 1;
} # end if } # end if
} # end foreach } # end foreach
@ -200,7 +203,7 @@ $log->debug("No serial") if $debug;
$command =~ s/\?/\%s/g; $command =~ s/\?/\%s/g;
$log->error('SQL statement execution failed: ('.sprintf($command, , map { defined $_ ? $_ : 'undef' } ( @sql{@keys}) ).'):' . $local_dbh->errstr); $log->error('SQL statement execution failed: ('.sprintf($command, , map { defined $_ ? $_ : 'undef' } ( @sql{@keys}) ).'):' . $local_dbh->errstr);
$local_dbh->rollback(); $local_dbh->rollback();
sql::end_transaction( $local_dbh, $ac ); ZoneMinder::Database::end_transaction( $local_dbh, $ac );
return $error; return $error;
} # end if } # end if
if ( $debug or DEBUG_ALL ) { if ( $debug or DEBUG_ALL ) {
@ -215,7 +218,7 @@ $log->debug("No serial") if $debug;
$command =~ s/\?/\%s/g; $command =~ s/\?/\%s/g;
$log->error('SQL failed: ('.sprintf($command, , map { defined $_ ? $_ : 'undef' } ( @sql{@keys, @$fields{@identified_by}}) ).'):' . $local_dbh->errstr); $log->error('SQL failed: ('.sprintf($command, , map { defined $_ ? $_ : 'undef' } ( @sql{@keys, @$fields{@identified_by}}) ).'):' . $local_dbh->errstr);
$local_dbh->rollback(); $local_dbh->rollback();
sql::end_transaction( $local_dbh, $ac ); ZoneMinder::Database::end_transaction( $local_dbh, $ac );
return $error; return $error;
} # end if } # end if
if ( $debug or DEBUG_ALL ) { if ( $debug or DEBUG_ALL ) {
@ -224,22 +227,28 @@ $log->debug("No serial") if $debug;
} # end if } # end if
} # end if } # end if
} else { # not identified_by } else { # not identified_by
@identified_by = ('id') if ! @identified_by; @identified_by = ('Id') if ! @identified_by;
my $need_serial = ! ( @identified_by == map { $$self{$_} ? $_ : () } @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 ( $force_insert or $need_serial ) {
if ( $need_serial ) { if ( $need_serial ) {
if ( $serial ) { if ( $serial ) {
@$self{@identified_by} = @sql{@$fields{@identified_by}} = $local_dbh->selectrow_array( q{SELECT nextval('} . $serial . q{')} ); 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() ) { if ( $local_dbh->errstr() ) {
$log->error("Error getting next id. " . $local_dbh->errstr() ); $log->error("Error getting next id. " . $local_dbh->errstr() );
$log->error("SQL statement execution SELECT nextval('$serial') returned ".join(',',@$self{@identified_by})); $log->error("SQL statement execution $s returned ".join(',',@$self{@identified_by}));
} elsif ( $debug or DEBUG_ALL ) { } elsif ( $debug or DEBUG_ALL ) {
$log->debug("SQL statement execution SELECT nextval('$serial') returned ".join(',',@$self{@identified_by})); $log->debug("SQL statement execution $s returned ".join(',',@$self{@identified_by}));
} # end if } # end if
} # end if } # end if
} # end if } # end if
my @keys = keys %sql; my @keys = keys %sql;
my $command = "INSERT INTO $table (" . join(',', @keys ) . ') VALUES (' . join(',', map { '?' } @sql{@keys} ) . ')'; my $command = "INSERT INTO $table (" . join(',', @keys ) . ') VALUES (' . join(',', map { '?' } @sql{@keys} ) . ')';
if ( ! ( $_ = $local_dbh->prepare($command) and $_->execute( @sql{@keys} ) ) ) { if ( ! ( $_ = $local_dbh->prepare($command) and $_->execute( @sql{@keys} ) ) ) {
@ -247,7 +256,7 @@ $log->debug("No serial") if $debug;
my $error = $local_dbh->errstr; my $error = $local_dbh->errstr;
$log->error('SQL failed: ('.sprintf($command, map { defined $_ ? $_ : 'undef' } ( @sql{@keys}) ).'):' . $error); $log->error('SQL failed: ('.sprintf($command, map { defined $_ ? $_ : 'undef' } ( @sql{@keys}) ).'):' . $error);
$local_dbh->rollback(); $local_dbh->rollback();
sql::end_transaction( $local_dbh, $ac ); ZoneMinder::Database::end_transaction( $local_dbh, $ac );
return $error; return $error;
} # end if } # end if
if ( $debug or DEBUG_ALL ) { if ( $debug or DEBUG_ALL ) {
@ -257,14 +266,16 @@ $log->debug("No serial") if $debug;
} else { } else {
delete $sql{created_on}; delete $sql{created_on};
my @keys = keys %sql; my @keys = keys %sql;
@keys = sets::exclude( [ @$fields{@identified_by} ], \@keys ); 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 ); 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}} ) ) ) { if ( ! ( $_ = $local_dbh->prepare($command) and $_->execute( @sql{@keys}, @sql{@$fields{@identified_by}} ) ) ) {
my $error = $local_dbh->errstr; my $error = $local_dbh->errstr;
$command =~ s/\?/\%s/g; $command =~ s/\?/\%s/g;
$log->error('SQL failed: ('.sprintf($command, map { defined $_ ? $_ : 'undef' } ( @sql{@keys}, @sql{@$fields{@identified_by}} ) ).'):' . $error) if $log; $log->error('SQL failed: ('.sprintf($command, map { defined $_ ? $_ : 'undef' } ( @sql{@keys}, @sql{@$fields{@identified_by}} ) ).'):' . $error) if $log;
$local_dbh->rollback(); $local_dbh->rollback();
sql::end_transaction( $local_dbh, $ac ); ZoneMinder::Database::end_transaction( $local_dbh, $ac );
return $error; return $error;
} # end if } # end if
if ( $debug or DEBUG_ALL ) { if ( $debug or DEBUG_ALL ) {
@ -273,7 +284,7 @@ $log->debug("No serial") if $debug;
} # end if } # end if
} # end if } # end if
} # end if } # end if
sql::end_transaction( $local_dbh, $ac ); ZoneMinder::Database::end_transaction( $local_dbh, $ac );
$self->load(); $self->load();
#if ( $$fields{id} ) { #if ( $$fields{id} ) {
#if ( ! $ZoneMinder::Object::cache{$type}{$$self{id}} ) { #if ( ! $ZoneMinder::Object::cache{$type}{$$self{id}} ) {
@ -294,30 +305,32 @@ sub set {
my $type = ref $self; my $type = ref $self;
my %fields = eval ('%'.$type.'::fields'); my %fields = eval ('%'.$type.'::fields');
if ( ! %fields ) { if ( ! %fields ) {
$log->warn('ZoneMinder::Object::set called on an object with no fields'); $log->warn("ZoneMinder::Object::set called on an object ($type) with no fields".$@);
} # end if } # end if
my %defaults = eval('%'.$type.'::defaults'); my %defaults = eval('%'.$type.'::defaults');
if ( ref $params ne 'HASH' ) { if ( ref $params ne 'HASH' ) {
my ( $caller, undef, $line ) = caller; my ( $caller, undef, $line ) = caller;
$openprint::log->error("$type -> set called with non-hash params from $caller $line"); $log->error("$type -> set called with non-hash params from $caller $line");
} }
foreach my $field ( keys %fields ) { foreach my $field ( keys %fields ) {
if ( $params ) {
$log->debug("field: $field, param: ".$$params{$field}) if $debug; $log->debug("field: $field, param: ".$$params{$field}) if $debug;
if ( exists $$params{$field} ) { if ( exists $$params{$field} ) {
$openprint::log->debug("field: $field, $$self{$field} =? param: ".$$params{$field}) if $debug; $log->debug("field: $field, $$self{$field} =? param: ".$$params{$field}) if $debug;
if ( ( ! defined $$self{$field} ) or ($$self{$field} ne $params->{$field}) ) { if ( ( ! defined $$self{$field} ) or ($$self{$field} ne $params->{$field}) ) {
# Only make changes to fields that have changed # Only make changes to fields that have changed
if ( defined $fields{$field} ) { if ( defined $fields{$field} ) {
$$self{$field} = $$params{$field} if defined $fields{$field}; $$self{$field} = $$params{$field} if defined $fields{$field};
push @set_fields, $fields{$field}, $$params{$field}; #mark for sql updating push @set_fields, $fields{$field}, $$params{$field}; #mark for sql updating
} # end if } # end if
$openprint::log->debug("Running $field with $$params{$field}") if $debug; $log->debug("Running $field with $$params{$field}") if $debug;
if ( my $func = $self->can( $field ) ) { if ( my $func = $self->can( $field ) ) {
$func->( $self, $$params{$field} ); $func->( $self, $$params{$field} );
} # end if } # end if
} # end if } # end if
} # end if } # end if
} # end if $params
if ( defined $fields{$field} ) { if ( defined $fields{$field} ) {
if ( $$self{$field} ) { if ( $$self{$field} ) {
@ -356,7 +369,7 @@ sub transform {
if ( defined $$fields{$_[1]} ) { if ( defined $$fields{$_[1]} ) {
my @transforms = eval('@{$'.$type.'::transforms{$_[1]}}'); my @transforms = eval('@{$'.$type.'::transforms{$_[1]}}');
$openprint::log->debug("Transforms for $_[1] before $_[2]: @transforms") if $debug; $log->debug("Transforms for $_[1] before $_[2]: @transforms") if $debug;
if ( @transforms ) { if ( @transforms ) {
foreach my $transform ( @transforms ) { foreach my $transform ( @transforms ) {
if ( $transform =~ /^s\// or $transform =~ /^tr\// ) { if ( $transform =~ /^s\// or $transform =~ /^tr\// ) {
@ -366,15 +379,15 @@ sub transform {
$value = undef; $value = undef;
} # end if } # end if
} else { } else {
$openprint::log->debug("evalling $value ".$transform . " Now value is $value" ); $log->debug("evalling $value ".$transform . " Now value is $value" );
eval '$value '.$transform; eval '$value '.$transform;
$openprint::log->error("Eval error $@") if $@; $log->error("Eval error $@") if $@;
} }
$openprint::log->debug("After $transform: $value") if $debug; $log->debug("After $transform: $value") if $debug;
} # end foreach } # end foreach
} # end if } # end if
} else { } else {
$openprint::log->error("Object::transform ($_[1]) not in fields for $type"); $log->error("Object::transform ($_[1]) not in fields for $type");
} # end if } # end if
return $value; return $value;

View File

@ -246,7 +246,7 @@ MAIN: while( $loop ) {
$$Event{Path} = join('/', $Storage->Path(), $day_dir,$event_path); $$Event{Path} = join('/', $Storage->Path(), $day_dir,$event_path);
$Event->MonitorId( $monitor_dir ); $Event->MonitorId( $monitor_dir );
$Event->StorageId( $Storage->Id() ); $Event->StorageId( $Storage->Id() );
$Event->DiskUsage( undef ); $Event->DiskSpace( undef );
} # event path exists } # event path exists
} # end foreach event_link } # end foreach event_link
chdir( $Storage->Path() ); chdir( $Storage->Path() );

View File

@ -251,14 +251,20 @@ sub checkFilter {
my $filter = shift; my $filter = shift;
my @Events = $filter->Execute(); my @Events = $filter->Execute();
Info( join( "Checking filter '$filter->{Name}'", Info(
($filter->{AutoDelete}?', delete':''), join(' ',
($filter->{AutoArchive}?', archive':''), 'Checking filter', $filter->{Name},
($filter->{AutoVideo}?', video':''), join( ', ',
($filter->{AutoUpload}?', upload':''),
($filter->{AutoEmail}?', email':''), ($filter->{AutoDelete}?'delete':()),
($filter->{AutoMessage}?', message':''), ($filter->{AutoArchive}?'archive':()),
($filter->{AutoExecute}?', execute':''), ($filter->{AutoVideo}?'video':()),
($filter->{AutoUpload}?'upload':()),
($filter->{AutoEmail}?'email':()),
($filter->{AutoMessage}?'message':()),
($filter->{AutoExecute}?'execute':()),
($filter->{UpdateDiskSpace}?'update disk space':()),
),
'returned' , scalar @Events , 'events', 'returned' , scalar @Events , 'events',
"\n", "\n",
) ); ) );
@ -309,6 +315,12 @@ sub checkFilter {
Error( "Unable toto delete event $event->{Id} as previous operations failed\n" ); Error( "Unable toto delete event $event->{Id} as previous operations failed\n" );
} }
} # end if AutoDelete } # 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 } # end foreach event
} }

View File

@ -27,6 +27,7 @@
#include "zm_stream.h" #include "zm_stream.h"
#include "zm_video.h" #include "zm_video.h"
#include "zm_ffmpeg_input.h" #include "zm_ffmpeg_input.h"
#include "zm_monitor.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -108,11 +109,17 @@ class EventStream : public StreamBase {
} }
void setStreamStart( int init_event_id, unsigned int init_frame_id=0 ) { void setStreamStart( int init_event_id, unsigned int init_frame_id=0 ) {
loadInitialEventData( init_event_id, init_frame_id ); 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 ) { void setStreamStart( int monitor_id, time_t event_time ) {
loadInitialEventData( monitor_id, 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 ) { void setStreamMode( StreamMode p_mode ) {
mode = p_mode; mode = p_mode;

View File

@ -133,6 +133,7 @@ int av_dict_parse_string(AVDictionary **pm, const char *str,
#endif // HAVE_LIBAVCODEC || HAVE_LIBAVUTIL || HAVE_LIBSWSCALE #endif // HAVE_LIBAVCODEC || HAVE_LIBAVUTIL || HAVE_LIBSWSCALE
#if HAVE_LIBAVUTIL #if HAVE_LIBAVUTIL
#if LIBAVUTIL_VERSION_CHECK(56, 0, 0, 17, 100)
int64_t av_rescale_delta(AVRational in_tb, int64_t in_ts, AVRational fs_tb, int duration, int64_t *last, AVRational out_tb){ int64_t av_rescale_delta(AVRational in_tb, int64_t in_ts, AVRational fs_tb, int duration, int64_t *last, AVRational out_tb){
int64_t a, b, this_thing; int64_t a, b, this_thing;
@ -156,6 +157,7 @@ simple_round:
return av_rescale_q(this_thing, fs_tb, out_tb); return av_rescale_q(this_thing, fs_tb, out_tb);
} }
#endif #endif
#endif
int hacked_up_context2_for_older_ffmpeg(AVFormatContext **avctx, AVOutputFormat *oformat, const char *format, const char *filename) { int hacked_up_context2_for_older_ffmpeg(AVFormatContext **avctx, AVOutputFormat *oformat, const char *format, const char *filename) {
AVFormatContext *s = avformat_alloc_context(); AVFormatContext *s = avformat_alloc_context();

View File

@ -317,7 +317,7 @@ int FfmpegCamera::Capture( Image &image ) {
} // end if packet.stream_index == mVideoStreamId } // end if packet.stream_index == mVideoStreamId
zm_av_packet_unref( &packet ); zm_av_packet_unref( &packet );
} // end while ! frameComplete } // end while ! frameComplete
return (0); return 1;
} // FfmpegCamera::Capture } // FfmpegCamera::Capture
int FfmpegCamera::PostCapture() { int FfmpegCamera::PostCapture() {
@ -458,7 +458,9 @@ int FfmpegCamera::OpenFfmpeg() {
// STolen from ispy // STolen from ispy
//this fixes issues with rtsp streams!! woot. //this fixes issues with rtsp streams!! woot.
//mVideoCodecContext->flags2 |= CODEC_FLAG2_FAST | CODEC_FLAG2_CHUNKS | CODEC_FLAG_LOW_DELAY; // Enable faster H264 decode. //mVideoCodecContext->flags2 |= CODEC_FLAG2_FAST | CODEC_FLAG2_CHUNKS | CODEC_FLAG_LOW_DELAY; // Enable faster H264 decode.
#ifdef CODEC_FLAG2_FAST
mVideoCodecContext->flags2 |= CODEC_FLAG2_FAST | CODEC_FLAG_LOW_DELAY; mVideoCodecContext->flags2 |= CODEC_FLAG2_FAST | CODEC_FLAG_LOW_DELAY;
#endif
#if HAVE_AVUTIL_HWCONTEXT_H #if HAVE_AVUTIL_HWCONTEXT_H
if ( mVideoCodecContext->codec_id == AV_CODEC_ID_H264 ) { if ( mVideoCodecContext->codec_id == AV_CODEC_ID_H264 ) {
@ -495,7 +497,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 } // end if h264
#endif #endif
@ -752,6 +763,7 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
while ( ! frameComplete ) { while ( ! frameComplete ) {
av_init_packet( &packet ); av_init_packet( &packet );
Debug(4,"before read frame");
ret = av_read_frame( mFormatContext, &packet ); ret = av_read_frame( mFormatContext, &packet );
if ( ret < 0 ) { if ( ret < 0 ) {
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE ); av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
@ -961,7 +973,7 @@ else if ( packet.pts && video_last_pts > packet.pts ) {
ret = avcodec_receive_frame( mVideoCodecContext, mRawFrame ); ret = avcodec_receive_frame( mVideoCodecContext, mRawFrame );
if ( ret < 0 ) { if ( ret < 0 ) {
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE ); 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 ); zm_av_packet_unref( &packet );
continue; continue;
} }
@ -981,8 +993,6 @@ else if ( packet.pts && video_last_pts > packet.pts ) {
} }
#endif #endif
Debug( 4, "Decoded video packet at frame %d", frameCount );
if ( frameComplete ) { if ( frameComplete ) {
Debug( 4, "Got frame %d", frameCount ); Debug( 4, "Got frame %d", frameCount );
@ -1013,6 +1023,7 @@ else if ( packet.pts && video_last_pts > packet.pts ) {
Debug( 3, "Not framecomplete after av_read_frame" ); Debug( 3, "Not framecomplete after av_read_frame" );
} // end if frameComplete } // end if frameComplete
} else if ( packet.stream_index == mAudioStreamId ) { //FIXME best way to copy all other streams } else if ( packet.stream_index == mAudioStreamId ) { //FIXME best way to copy all other streams
frameComplete = 1;
if ( videoStore ) { if ( videoStore ) {
if ( record_audio ) { if ( record_audio ) {
if ( have_video_keyframe ) { if ( have_video_keyframe ) {
@ -1034,6 +1045,8 @@ else if ( packet.pts && video_last_pts > packet.pts ) {
} else { } else {
Debug(4, "Have audio packet, but not recording atm" ); Debug(4, "Have audio packet, but not recording atm" );
} }
zm_av_packet_unref( &packet );
return 0;
} else { } else {
#if LIBAVUTIL_VERSION_CHECK(56, 23, 0, 23, 0) #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) ); Debug( 3, "Some other stream index %d, %s", packet.stream_index, av_get_media_type_string( mFormatContext->streams[packet.stream_index]->codecpar->codec_type) );
@ -1045,7 +1058,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. // 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 ); zm_av_packet_unref( &packet );
} // end while ! frameComplete } // end while ! frameComplete
return (frameCount); return frameCount;
} // end FfmpegCamera::CaptureAndRecord } // end FfmpegCamera::CaptureAndRecord

View File

@ -23,8 +23,7 @@
#if HAVE_LIBVLC #if HAVE_LIBVLC
// Do all the buffer checking work here to avoid unnecessary locking // 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; LibvlcPrivateData* data = (LibvlcPrivateData*)opaque;
data->mutex.lock(); data->mutex.lock();
@ -36,15 +35,12 @@ void* LibvlcLockBuffer(void* opaque, void** planes)
return NULL; return NULL;
} }
void LibvlcUnlockBuffer(void* opaque, void* picture, void *const *planes) void LibvlcUnlockBuffer(void* opaque, void* picture, void *const *planes) {
{
LibvlcPrivateData* data = (LibvlcPrivateData*)opaque; LibvlcPrivateData* data = (LibvlcPrivateData*)opaque;
bool newFrame = false; bool newFrame = false;
for(uint32_t i = 0; i < data->bufferSize; i++) for( uint32_t i = 0; i < data->bufferSize; i++ ) {
{ if ( data->buffer[i] != data->prevBuffer[i] ) {
if(data->buffer[i] != data->prevBuffer[i])
{
newFrame = true; newFrame = true;
break; break;
} }
@ -54,8 +50,7 @@ void LibvlcUnlockBuffer(void* opaque, void* picture, void *const *planes)
time_t now; time_t now;
time(&now); time(&now);
// Return frames slightly faster than 1fps (if time() supports greater than one second resolution) // 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->prevTime = now;
data->newImage.updateValueSignal(true); 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); Panic("Unexpected colours: %d",colours);
} }
if ( capture ) if ( capture ) {
{
Initialise(); Initialise();
} }
} }
LibvlcCamera::~LibvlcCamera() LibvlcCamera::~LibvlcCamera() {
{ if ( capture ) {
if ( capture )
{
Terminate(); Terminate();
} }
if(mLibvlcMediaPlayer != NULL) if ( mLibvlcMediaPlayer != NULL ) {
{
libvlc_media_player_release(mLibvlcMediaPlayer); libvlc_media_player_release(mLibvlcMediaPlayer);
mLibvlcMediaPlayer = NULL; mLibvlcMediaPlayer = NULL;
} }
if(mLibvlcMedia != NULL) if ( mLibvlcMedia != NULL ) {
{
libvlc_media_release(mLibvlcMedia); libvlc_media_release(mLibvlcMedia);
mLibvlcMedia = NULL; mLibvlcMedia = NULL;
} }
if(mLibvlcInstance != NULL) if ( mLibvlcInstance != NULL ) {
{
libvlc_release(mLibvlcInstance); libvlc_release(mLibvlcInstance);
mLibvlcInstance = NULL; mLibvlcInstance = NULL;
} }
if (mOptArgV != NULL) if ( mOptArgV != NULL ) {
{
delete[] mOptArgV; delete[] mOptArgV;
} }
} }
void LibvlcCamera::Initialise() void LibvlcCamera::Initialise() {
{
} }
void LibvlcCamera::Terminate() void LibvlcCamera::Terminate() {
{
libvlc_media_player_stop(mLibvlcMediaPlayer); libvlc_media_player_stop(mLibvlcMediaPlayer);
if(mLibvlcData.buffer != NULL) if(mLibvlcData.buffer != NULL) {
{
zm_freealigned(mLibvlcData.buffer); zm_freealigned(mLibvlcData.buffer);
} }
if(mLibvlcData.prevBuffer != NULL) if(mLibvlcData.prevBuffer != NULL) {
{
zm_freealigned(mLibvlcData.prevBuffer); zm_freealigned(mLibvlcData.prevBuffer);
} }
} }
int LibvlcCamera::PrimeCapture() int LibvlcCamera::PrimeCapture() {
{
Info("Priming capture from %s", mPath.c_str()); Info("Priming capture from %s", mPath.c_str());
StringVector opVect = split(Options(), ","); StringVector opVect = split(Options(), ",");
@ -154,8 +137,7 @@ int LibvlcCamera::PrimeCapture()
else if ( Method() == "rtpRtspHttp" ) else if ( Method() == "rtpRtspHttp" )
opVect.push_back("--rtsp-http"); opVect.push_back("--rtsp-http");
if (opVect.size() > 0) if ( opVect.size() > 0 ) {
{
mOptArgV = new char*[opVect.size()]; mOptArgV = new char*[opVect.size()];
Debug(2, "Number of Options: %d",opVect.size()); Debug(2, "Number of Options: %d",opVect.size());
for (size_t i=0; i< opVect.size(); i++) { for (size_t i=0; i< opVect.size(); i++) {
@ -189,17 +171,15 @@ int LibvlcCamera::PrimeCapture()
libvlc_media_player_play(mLibvlcMediaPlayer); libvlc_media_player_play(mLibvlcMediaPlayer);
return(0); return 0;
} }
int LibvlcCamera::PreCapture() int LibvlcCamera::PreCapture() {
{
return(0); return(0);
} }
// Should not return -1 as cancels capture. Always wait for image if available. // 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()) while(!mLibvlcData.newImage.getValueImmediate())
mLibvlcData.newImage.getUpdatedValue(1); mLibvlcData.newImage.getUpdatedValue(1);
@ -208,25 +188,15 @@ int LibvlcCamera::Capture( Image &image )
mLibvlcData.newImage.setValueImmediate(false); mLibvlcData.newImage.setValueImmediate(false);
mLibvlcData.mutex.unlock(); mLibvlcData.mutex.unlock();
return (0); return 1;
} }
// Should not return -1 as cancels capture. Always wait for image if available. // Should not return -1 as cancels capture. Always wait for image if available.
int LibvlcCamera::CaptureAndRecord(Image &image, timeval recording, char* event_directory) 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();
return (0); return (0);
} }
int LibvlcCamera::PostCapture() int LibvlcCamera::PostCapture() {
{
return(0); return(0);
} }

View File

@ -1995,17 +1995,14 @@ int LocalCamera::Contrast( int p_contrast )
return( -1 ); return( -1 );
} }
int LocalCamera::PrimeCapture() int LocalCamera::PrimeCapture() {
{
Initialise(); Initialise();
Debug( 2, "Priming capture" ); Debug( 2, "Priming capture" );
#if ZM_HAS_V4L2 #if ZM_HAS_V4L2
if ( v4l_version == 2 ) if ( v4l_version == 2 ) {
{
Debug( 3, "Queueing buffers" ); 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; struct v4l2_buffer vid_buf;
memset( &vid_buf, 0, sizeof(vid_buf) ); memset( &vid_buf, 0, sizeof(vid_buf) );
@ -2028,13 +2025,10 @@ int LocalCamera::PrimeCapture()
} }
#endif // ZM_HAS_V4L2 #endif // ZM_HAS_V4L2
#if ZM_HAS_V4L1 #if ZM_HAS_V4L1
if ( v4l_version == 1 ) if ( v4l_version == 1 ) {
{ for ( int frame = 0; frame < v4l1_data.frames.frames; frame++ ) {
for ( int frame = 0; frame < v4l1_data.frames.frames; frame++ )
{
Debug( 3, "Queueing frame %d", 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) ); Error( "Capture failure for frame %d: %s", frame, strerror(errno) );
return( -1 ); return( -1 );
} }
@ -2045,14 +2039,12 @@ int LocalCamera::PrimeCapture()
return( 0 ); return( 0 );
} }
int LocalCamera::PreCapture() int LocalCamera::PreCapture() {
{ Debug( 5, "Pre-capturing" );
Debug( 2, "Pre-capturing" );
return( 0 ); return( 0 );
} }
int LocalCamera::Capture( Image &image ) int LocalCamera::Capture( Image &image ) {
{
Debug( 3, "Capturing" ); Debug( 3, "Capturing" );
static uint8_t* buffer = NULL; static uint8_t* buffer = NULL;
static uint8_t* directbuffer = NULL; static uint8_t* directbuffer = NULL;
@ -2069,11 +2061,9 @@ int LocalCamera::Capture( Image &image )
// Do the capture, unless we are the second or subsequent camera on a channel, in which case just reuse the buffer // 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 ZM_HAS_V4L2
if ( v4l_version == 2 ) if ( v4l_version == 2 ) {
{
static struct v4l2_buffer vid_buf; static struct v4l2_buffer vid_buf;
memset( &vid_buf, 0, sizeof(vid_buf) ); memset( &vid_buf, 0, sizeof(vid_buf) );
@ -2083,10 +2073,8 @@ int LocalCamera::Capture( Image &image )
vid_buf.memory = v4l2_data.reqbufs.memory; vid_buf.memory = v4l2_data.reqbufs.memory;
Debug( 3, "Capturing %d frames", captures_per_frame ); Debug( 3, "Capturing %d frames", captures_per_frame );
while ( captures_per_frame ) while ( captures_per_frame ) {
{ if ( vidioctl( vid_fd, VIDIOC_DQBUF, &vid_buf ) < 0 ) {
if ( vidioctl( vid_fd, VIDIOC_DQBUF, &vid_buf ) < 0 )
{
if ( errno == EIO ) if ( errno == EIO )
Warning( "Capture failure, possible signal loss?: %s", strerror(errno) ) Warning( "Capture failure, possible signal loss?: %s", strerror(errno) )
else else
@ -2096,15 +2084,13 @@ int LocalCamera::Capture( Image &image )
v4l2_data.bufptr = &vid_buf; v4l2_data.bufptr = &vid_buf;
capture_frame = v4l2_data.bufptr->index; capture_frame = v4l2_data.bufptr->index;
if ( --captures_per_frame ) if ( --captures_per_frame ) {
{ if ( vidioctl( vid_fd, VIDIOC_QBUF, &vid_buf ) < 0 ) {
if ( vidioctl( vid_fd, VIDIOC_QBUF, &vid_buf ) < 0 )
{
Error( "Unable to requeue buffer %d: %s", vid_buf.index, strerror(errno) ); Error( "Unable to requeue buffer %d: %s", vid_buf.index, strerror(errno) );
return( -1 ); return( -1 );
} }
} }
} } // while captures_per_frame
Debug( 3, "Captured frame %d/%d from channel %d", capture_frame, v4l2_data.bufptr->sequence, channel ); Debug( 3, "Captured frame %d/%d from channel %d", capture_frame, v4l2_data.bufptr->sequence, channel );
@ -2115,23 +2101,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); 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 #endif // ZM_HAS_V4L2
#if ZM_HAS_V4L1 #if ZM_HAS_V4L1
if ( v4l_version == 1 ) if ( v4l_version == 1 ) {
{
Debug( 3, "Capturing %d frames", captures_per_frame ); 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 ); 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) ); Error( "Sync failure for frame %d buffer %d: %s", v4l1_data.active_frame, captures_per_frame, strerror(errno) );
return( -1 ); return( -1 );
} }
captures_per_frame--; captures_per_frame--;
if ( captures_per_frame ) if ( captures_per_frame ) {
{
Debug( 3, "Capturing frame %d", v4l1_data.active_frame ); Debug( 3, "Capturing frame %d", v4l1_data.active_frame );
if ( ioctl( vid_fd, VIDIOCMCAPTURE, &v4l1_data.buffers[v4l1_data.active_frame] ) < 0 ) if ( ioctl( vid_fd, VIDIOCMCAPTURE, &v4l1_data.buffers[v4l1_data.active_frame] ) < 0 )
{ {
@ -2156,7 +2138,7 @@ int LocalCamera::Capture( Image &image )
directbuffer = image.WriteBuffer(width, height, colours, subpixelorder); directbuffer = image.WriteBuffer(width, height, colours, subpixelorder);
if ( directbuffer == NULL ) { if ( directbuffer == NULL ) {
Error("Failed requesting writeable buffer for the captured image."); Error("Failed requesting writeable buffer for the captured image.");
return (-1); return -1;
} }
#if HAVE_LIBSWSCALE #if HAVE_LIBSWSCALE
if ( conversion_type == 1 ) { if ( conversion_type == 1 ) {
@ -2175,13 +2157,10 @@ int LocalCamera::Capture( Image &image )
} }
#endif #endif
if ( conversion_type == 2 ) { if ( conversion_type == 2 ) {
Debug( 9, "Calling the conversion function" ); Debug( 9, "Calling the conversion function" );
/* Call the image conversion function and convert directly into the shared memory */ /* Call the image conversion function and convert directly into the shared memory */
(*conversion_fptr)(buffer, directbuffer, pixels); (*conversion_fptr)(buffer, directbuffer, pixels);
} } else if ( conversion_type == 3 ) {
else if(conversion_type == 3) {
Debug( 9, "Decoding the JPEG image" ); Debug( 9, "Decoding the JPEG image" );
/* JPEG decoding */ /* JPEG decoding */
image.DecodeJpeg(buffer, buffer_bytesused, colours, subpixelorder); image.DecodeJpeg(buffer, buffer_bytesused, colours, subpixelorder);
@ -2192,10 +2171,9 @@ 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 */ /* 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); image.Assign( width, height, colours, subpixelorder, buffer, imagesize);
} }
return( 0 ); return 1;
} }
int LocalCamera::PostCapture() int LocalCamera::PostCapture()

View File

@ -2891,31 +2891,25 @@ int Monitor::Capture() {
//Check if FFMPEG camera //Check if FFMPEG camera
if ( (videowriter == H264PASSTHROUGH) && camera->SupportsNativeVideo() ) { if ( (videowriter == H264PASSTHROUGH) && camera->SupportsNativeVideo() ) {
//Warning("ZMC: Recording: %d", video_store_data->recording); //Warning("ZMC: Recording: %d", video_store_data->recording);
captureResult = camera->CaptureAndRecord(*capture_image, video_store_data->recording, video_store_data->event_file); // 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 { } else {
/* Capture directly into image buffer, avoiding the need to memcpy() */ /* Capture directly into image buffer, avoiding the need to memcpy() */
captureResult = camera->Capture(*capture_image); captureResult = camera->Capture(*capture_image);
} }
} }
Debug(4, "Return from Capture (%d)", captureResult);
// CaptureAndRecord returns # of frames captured I think if ( captureResult < 0 ) {
if ( ( videowriter == H264PASSTHROUGH ) && ( captureResult > 0 ) ) {
//video_store_data->frameNumber = captureResult;
captureResult = 0;
}
if ( captureResult != 0 ) {
// Unable to capture image for temporary reason // Unable to capture image for temporary reason
// Fake a signal loss image // Fake a signal loss image
Rgb signalcolor; Rgb signalcolor;
signalcolor = rgb_convert(signal_check_colour, ZM_SUBPIX_ORDER_BGR); /* HTML colour code is actually BGR in memory, we want RGB */ 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); capture_image->Fill(signalcolor);
captureResult = 0; } else if ( captureResult > 0 ) {
} else {
captureResult = 1;
}
if ( captureResult == 1 ) {
/* Deinterlacing */ /* Deinterlacing */
if ( deinterlacing_value == 1 ) { if ( deinterlacing_value == 1 ) {
@ -2969,29 +2963,41 @@ int Monitor::Capture() {
if ( privacy_bitmask ) if ( privacy_bitmask )
capture_image->MaskPrivacy( 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 ); gettimeofday( image_buffer[index].timestamp, NULL );
if ( config.timestamp_on_capture ) { if ( config.timestamp_on_capture ) {
TimestampImage( capture_image, image_buffer[index].timestamp ); 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->signal = CheckSignal(capture_image);
shared_data->last_write_index = index; shared_data->last_write_index = index;
shared_data->last_write_time = image_buffer[index].timestamp->tv_sec; shared_data->last_write_time = image_buffer[index].timestamp->tv_sec;
image_count++; image_count++;
} // end if captureResult
if ( image_count && fps_report_interval && !(image_count%fps_report_interval) ) { 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); struct timeval now;
//Info( "%d -> %d -> %d", fps_report_interval, now, last_fps_time ); 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( "%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 ); 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]; 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 ) ) { if ( mysql_query( &dbconn, sql ) ) {
Error( "Can't run query: %s", mysql_error( &dbconn ) ); 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 // Icon: I'm not sure these should be here. They have nothing to do with capturing
if ( shared_data->action & GET_SETTINGS ) { if ( shared_data->action & GET_SETTINGS ) {
@ -3008,10 +3014,7 @@ int Monitor::Capture() {
camera->Contrast( shared_data->contrast ); camera->Contrast( shared_data->contrast );
shared_data->action &= ~SET_SETTINGS; shared_data->action &= ~SET_SETTINGS;
} }
return( 0 ); return captureResult;
} // end if captureResults == 1 which is success I think
shared_data->signal = false;
return( -1 );
} }
void Monitor::TimestampImage( Image *ts_image, const struct timeval *ts_time ) const { void Monitor::TimestampImage( Image *ts_image, const struct timeval *ts_time ) const {

View File

@ -316,7 +316,7 @@ void MonitorStream::processCommand( const CmdMsg *msg ) {
//status_data.enabled = monitor->shared_data->active; //status_data.enabled = monitor->shared_data->active;
status_data.enabled = monitor->trigger_data->trigger_state!=Monitor::TRIGGER_OFF; status_data.enabled = monitor->trigger_data->trigger_state!=Monitor::TRIGGER_OFF;
status_data.forced = monitor->trigger_data->trigger_state==Monitor::TRIGGER_ON; 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.buffer_level,
status_data.delayed, status_data.delayed,
status_data.paused, status_data.paused,
@ -338,11 +338,15 @@ void MonitorStream::processCommand( const CmdMsg *msg ) {
//exit( -1 ); //exit( -1 );
} }
} }
Debug(2, "NUmber of bytes sent: (%d)", nbytes );
// quit after sending a status, if this was a quit request // 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); exit(0);
}
Debug(2,"Updating framrate");
updateFrameRate( monitor->GetFPS() ); updateFrameRate( monitor->GetFPS() );
} // end void MonitorStream::processCommand( const CmdMsg *msg ) } // end void MonitorStream::processCommand( const CmdMsg *msg )
@ -553,20 +557,28 @@ void MonitorStream::runStream() {
Debug( 2, "Assigned temporary buffer" ); 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) float max_secs_since_last_sent_frame = 10.0; //should be > keep alive amount (5 secs)
while ( !zm_terminate ) { while ( !zm_terminate ) {
bool got_command = false; bool got_command = false;
if ( feof( stdout ) || ferror( stdout ) || !monitor->ShmValid() ) { 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; break;
} }
gettimeofday( &now, NULL ); gettimeofday( &now, NULL );
if ( connkey ) { if ( connkey ) {
Debug(2, "checking command Queue"); //Debug(2, "checking command Queue for connkey: %d", connkey );
while(checkCommandQueue()) { while(checkCommandQueue()) {
Debug(2, "Have checking command Queue for connkey: %d", connkey );
got_command = true; got_command = true;
} }
} }
@ -655,8 +667,10 @@ Debug(2, "checking command Queue");
// Send the next frame // Send the next frame
Monitor::Snapshot *snap = &monitor->image_buffer[index]; 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; zm_terminate = true;
}
memcpy( &last_frame_timestamp, snap->timestamp, sizeof(last_frame_timestamp) ); memcpy( &last_frame_timestamp, snap->timestamp, sizeof(last_frame_timestamp) );
//frame_sent = true; //frame_sent = true;
@ -693,9 +707,12 @@ Debug(2, "checking command Queue");
} // end if buffered playback } // end if buffered playback
frame_count++; 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))) ); usleep( (unsigned long)((1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2))) );
if ( ttl ) { if ( ttl ) {
if ( (now.tv_sec - stream_start_time) > 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; break;
} }
} }

View File

@ -211,39 +211,52 @@ void VideoStream::SetupCodec( int colours, int subpixelorder, int width, int hei
Debug( 1, "Allocated stream" ); Debug( 1, "Allocated stream" );
AVCodecContext *c = ost->codec; #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
codec_context = avcodec_alloc_context3(NULL);
avcodec_parameters_to_context(codec_context, ost->codecpar);
#else
codec_context = ost->codec;
#endif
c->codec_id = codec->id; codec_context->codec_id = codec->id;
c->codec_type = codec->type; codec_context->codec_type = codec->type;
c->pix_fmt = strcmp( "mjpeg", ofc->oformat->name ) == 0 ? AV_PIX_FMT_YUVJ422P : AV_PIX_FMT_YUV420P; codec_context->pix_fmt = strcmp( "mjpeg", ofc->oformat->name ) == 0 ? AV_PIX_FMT_YUVJ422P : AV_PIX_FMT_YUV420P;
if ( bitrate <= 100 ) { if ( bitrate <= 100 ) {
// Quality based bitrate control (VBR). Scale is 1..31 where 1 is best. // Quality based bitrate control (VBR). Scale is 1..31 where 1 is best.
// This gets rid of artifacts in the beginning of the movie; and well, even quality. // This gets rid of artifacts in the beginning of the movie; and well, even quality.
c->flags |= CODEC_FLAG_QSCALE; #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
c->global_quality = FF_QP2LAMBDA * (31 - (31 * (bitrate / 100.0))); codec_context->flags |= AV_CODEC_FLAG_QSCALE;
#else
codec_context->flags |= CODEC_FLAG_QSCALE;
#endif
codec_context->global_quality = FF_QP2LAMBDA * (31 - (31 * (bitrate / 100.0)));
} else { } else {
c->bit_rate = bitrate; codec_context->bit_rate = bitrate;
} }
/* resolution must be a multiple of two */ /* resolution must be a multiple of two */
c->width = width; codec_context->width = width;
c->height = height; codec_context->height = height;
/* time base: this is the fundamental unit of time (in seconds) in terms /* time base: this is the fundamental unit of time (in seconds) in terms
of which frame timestamps are represented. for fixed-fps content, of which frame timestamps are represented. for fixed-fps content,
timebase should be 1/framerate and timestamp increments should be timebase should be 1/framerate and timestamp increments should be
identically 1. */ identically 1. */
c->time_base.den = frame_rate; codec_context->time_base.den = frame_rate;
c->time_base.num = 1; codec_context->time_base.num = 1;
Debug( 1, "Will encode in %d fps.", c->time_base.den ); Debug( 1, "Will encode in %d fps.", codec_context->time_base.den );
/* emit one intra frame every second */ /* emit one intra frame every second */
c->gop_size = frame_rate; codec_context->gop_size = frame_rate;
// some formats want stream headers to be separate // some formats want stream headers to be separate
if ( of->flags & AVFMT_GLOBALHEADER ) if ( of->flags & AVFMT_GLOBALHEADER )
c->flags |= CODEC_FLAG_GLOBAL_HEADER; #if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0)
codec_context->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
#else
codec_context->flags |= CODEC_FLAG_GLOBAL_HEADER;
#endif
} else { } else {
Fatal( "of->video_codec == AV_CODEC_ID_NONE" ); Fatal( "of->video_codec == AV_CODEC_ID_NONE" );
} }
@ -278,13 +291,11 @@ void VideoStream::OpenStream( ) {
/* now that all the parameters are set, we can open the /* now that all the parameters are set, we can open the
video codecs and allocate the necessary encode buffers */ video codecs and allocate the necessary encode buffers */
if ( ost ) { if ( ost ) {
AVCodecContext *c = ost->codec;
/* open the codec */ /* open the codec */
#if !LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 8, 0) #if !LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 8, 0)
if ( (avRet = avcodec_open( c, codec )) < 0 ) if ( (avRet = avcodec_open( codec_context, codec )) < 0 )
#else #else
if ( (avRet = avcodec_open2( c, codec, 0 )) < 0 ) if ( (avRet = avcodec_open2( codec_context, codec, 0 )) < 0 )
#endif #endif
{ {
Fatal( "Could not open codec. Error code %d \"%s\"", avRet, av_err2str( avRet ) ); Fatal( "Could not open codec. Error code %d \"%s\"", avRet, av_err2str( avRet ) );
@ -293,19 +304,15 @@ void VideoStream::OpenStream( ) {
Debug( 1, "Opened codec" ); Debug( 1, "Opened codec" );
/* allocate the encoded raw picture */ /* allocate the encoded raw picture */
#if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101) opicture = zm_av_frame_alloc( );
opicture = av_frame_alloc( );
#else
opicture = avcodec_alloc_frame( );
#endif
if ( !opicture ) { if ( !opicture ) {
Panic( "Could not allocate opicture" ); Panic( "Could not allocate opicture" );
} }
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0) #if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
int size = av_image_get_buffer_size( c->pix_fmt, c->width, c->height, 1 ); int size = av_image_get_buffer_size( codec_context->pix_fmt, codec_context->width, codec_context->height, 1 );
#else #else
int size = avpicture_get_size( c->pix_fmt, c->width, c->height ); int size = avpicture_get_size( codec_context->pix_fmt, codec_context->width, codec_context->height );
#endif #endif
uint8_t *opicture_buf = (uint8_t *)av_malloc( size ); uint8_t *opicture_buf = (uint8_t *)av_malloc( size );
@ -315,17 +322,17 @@ void VideoStream::OpenStream( ) {
} }
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0) #if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
av_image_fill_arrays(opicture->data, opicture->linesize, av_image_fill_arrays(opicture->data, opicture->linesize,
opicture_buf, c->pix_fmt, c->width, c->height, 1); opicture_buf, codec_context->pix_fmt, codec_context->width, codec_context->height, 1);
#else #else
avpicture_fill( (AVPicture *)opicture, opicture_buf, c->pix_fmt, avpicture_fill( (AVPicture *)opicture, opicture_buf, codec_context->pix_fmt,
c->width, c->height ); codec_context->width, codec_context->height );
#endif #endif
/* if the output format is not identical to the input format, then a temporary /* if the output format is not identical to the input format, then a temporary
picture is needed too. It is then converted to the required picture is needed too. It is then converted to the required
output format */ output format */
tmp_opicture = NULL; tmp_opicture = NULL;
if ( c->pix_fmt != pf ) { if ( codec_context->pix_fmt != pf ) {
#if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101) #if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101)
tmp_opicture = av_frame_alloc( ); tmp_opicture = av_frame_alloc( );
#else #else
@ -335,9 +342,9 @@ void VideoStream::OpenStream( ) {
Panic( "Could not allocate tmp_opicture" ); Panic( "Could not allocate tmp_opicture" );
} }
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0) #if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
int size = av_image_get_buffer_size( pf, c->width, c->height,1 ); int size = av_image_get_buffer_size( pf, codec_context->width, codec_context->height,1 );
#else #else
int size = avpicture_get_size( pf, c->width, c->height ); int size = avpicture_get_size( pf, codec_context->width, codec_context->height );
#endif #endif
uint8_t *tmp_opicture_buf = (uint8_t *)av_malloc( size ); uint8_t *tmp_opicture_buf = (uint8_t *)av_malloc( size );
if ( !tmp_opicture_buf ) { if ( !tmp_opicture_buf ) {
@ -347,10 +354,10 @@ void VideoStream::OpenStream( ) {
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0) #if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
av_image_fill_arrays(tmp_opicture->data, av_image_fill_arrays(tmp_opicture->data,
tmp_opicture->linesize, tmp_opicture_buf, pf, tmp_opicture->linesize, tmp_opicture_buf, pf,
c->width, c->height, 1); codec_context->width, codec_context->height, 1);
#else #else
avpicture_fill( (AVPicture *)tmp_opicture, avpicture_fill( (AVPicture *)tmp_opicture,
tmp_opicture_buf, pf, c->width, c->height ); tmp_opicture_buf, pf, codec_context->width, codec_context->height );
#endif #endif
} }
} }
@ -375,7 +382,12 @@ void VideoStream::OpenStream( ) {
} }
video_outbuf = NULL; video_outbuf = NULL;
#if LIBAVFORMAT_VERSION_CHECK(57, 0, 0, 0, 0)
if (codec_context->codec_type == AVMEDIA_TYPE_VIDEO &&
codec_context->codec_id == AV_CODEC_ID_RAWVIDEO) {
#else
if ( !(of->flags & AVFMT_RAWPICTURE) ) { if ( !(of->flags & AVFMT_RAWPICTURE) ) {
#endif
/* allocate output buffer */ /* allocate output buffer */
/* XXX: API change will be done */ /* XXX: API change will be done */
// TODO: Make buffer dynamic. // TODO: Make buffer dynamic.
@ -446,6 +458,8 @@ VideoStream::VideoStream( const char *in_filename, const char *in_format, int bi
if ( pthread_mutex_init( buffer_copy_lock, NULL ) != 0 ) { if ( pthread_mutex_init( buffer_copy_lock, NULL ) != 0 ) {
Fatal("pthread_mutex_init failed"); Fatal("pthread_mutex_init failed");
} }
codec_context = NULL;
} }
VideoStream::~VideoStream( ) { VideoStream::~VideoStream( ) {
@ -481,7 +495,7 @@ VideoStream::~VideoStream( ) {
/* close each codec */ /* close each codec */
if ( ost ) { if ( ost ) {
avcodec_close( ost->codec ); avcodec_close( codec_context );
av_free( opicture->data[0] ); av_free( opicture->data[0] );
av_frame_free( &opicture ); av_frame_free( &opicture );
if ( tmp_opicture ) { if ( tmp_opicture ) {
@ -564,17 +578,15 @@ double VideoStream::ActuallyEncodeFrame( const uint8_t *buffer, int buffer_size,
static struct SwsContext *img_convert_ctx = 0; static struct SwsContext *img_convert_ctx = 0;
#endif // HAVE_LIBSWSCALE #endif // HAVE_LIBSWSCALE
AVCodecContext *c = ost->codec; if ( codec_context->pix_fmt != pf ) {
if ( c->pix_fmt != pf ) {
memcpy( tmp_opicture->data[0], buffer, buffer_size ); memcpy( tmp_opicture->data[0], buffer, buffer_size );
#ifdef HAVE_LIBSWSCALE #ifdef HAVE_LIBSWSCALE
if ( !img_convert_ctx ) { if ( !img_convert_ctx ) {
img_convert_ctx = sws_getCachedContext( NULL, c->width, c->height, pf, c->width, c->height, c->pix_fmt, SWS_BICUBIC, NULL, NULL, NULL ); img_convert_ctx = sws_getCachedContext( NULL, codec_context->width, codec_context->height, pf, codec_context->width, codec_context->height, codec_context->pix_fmt, SWS_BICUBIC, NULL, NULL, NULL );
if ( !img_convert_ctx ) if ( !img_convert_ctx )
Panic( "Unable to initialise image scaling context" ); Panic( "Unable to initialise image scaling context" );
} }
sws_scale( img_convert_ctx, tmp_opicture->data, tmp_opicture->linesize, 0, c->height, opicture->data, opicture->linesize ); sws_scale( img_convert_ctx, tmp_opicture->data, tmp_opicture->linesize, 0, codec_context->height, opicture->data, opicture->linesize );
#else // HAVE_LIBSWSCALE #else // HAVE_LIBSWSCALE
Fatal( "swscale is required for MPEG mode" ); Fatal( "swscale is required for MPEG mode" );
#endif // HAVE_LIBSWSCALE #endif // HAVE_LIBSWSCALE
@ -586,7 +598,13 @@ double VideoStream::ActuallyEncodeFrame( const uint8_t *buffer, int buffer_size,
AVPacket *pkt = packet_buffers[packet_index]; AVPacket *pkt = packet_buffers[packet_index];
av_init_packet( pkt ); av_init_packet( pkt );
int got_packet = 0; int got_packet = 0;
#if LIBAVFORMAT_VERSION_CHECK(57, 0, 0, 0, 0)
if (codec_context->codec_type == AVMEDIA_TYPE_VIDEO &&
codec_context->codec_id == AV_CODEC_ID_RAWVIDEO) {
#else
if ( of->flags & AVFMT_RAWPICTURE ) { if ( of->flags & AVFMT_RAWPICTURE ) {
#endif
#if LIBAVCODEC_VERSION_CHECK(52, 30, 2, 30, 2) #if LIBAVCODEC_VERSION_CHECK(52, 30, 2, 30, 2)
pkt->flags |= AV_PKT_FLAG_KEY; pkt->flags |= AV_PKT_FLAG_KEY;
#else #else
@ -597,19 +615,34 @@ double VideoStream::ActuallyEncodeFrame( const uint8_t *buffer, int buffer_size,
pkt->size = sizeof (AVPicture); pkt->size = sizeof (AVPicture);
got_packet = 1; got_packet = 1;
} else { } else {
opicture_ptr->pts = c->frame_number; opicture_ptr->pts = codec_context->frame_number;
opicture_ptr->quality = c->global_quality; opicture_ptr->quality = codec_context->global_quality;
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
// Put encoder into flushing mode
avcodec_send_frame(codec_context, opicture_ptr);
int ret = avcodec_receive_packet(codec_context, pkt);
if ( ret < 0 ) {
if ( AVERROR_EOF != ret ) {
Error("ERror encoding video (%d) (%s)", ret,
av_err2str(ret));
}
} else {
got_packet = 1;
}
#else
#if LIBAVFORMAT_VERSION_CHECK(54, 1, 0, 2, 100) #if LIBAVFORMAT_VERSION_CHECK(54, 1, 0, 2, 100)
int ret = avcodec_encode_video2( c, pkt, opicture_ptr, &got_packet ); int ret = avcodec_encode_video2( codec_context, pkt, opicture_ptr, &got_packet );
if ( ret != 0 ) { if ( ret != 0 ) {
Fatal( "avcodec_encode_video2 failed with errorcode %d \"%s\"", ret, av_err2str( ret ) ); Fatal( "avcodec_encode_video2 failed with errorcode %d \"%s\"", ret, av_err2str( ret ) );
} }
#else #else
int out_size = avcodec_encode_video( c, video_outbuf, video_outbuf_size, opicture_ptr ); int out_size = avcodec_encode_video( codec_context, video_outbuf, video_outbuf_size, opicture_ptr );
got_packet = out_size > 0 ? 1 : 0; got_packet = out_size > 0 ? 1 : 0;
pkt->data = got_packet ? video_outbuf : NULL; pkt->data = got_packet ? video_outbuf : NULL;
pkt->size = got_packet ? out_size : 0; pkt->size = got_packet ? out_size : 0;
#endif
#endif #endif
if ( got_packet ) { if ( got_packet ) {
// if ( c->coded_frame->key_frame ) // if ( c->coded_frame->key_frame )
@ -622,12 +655,12 @@ double VideoStream::ActuallyEncodeFrame( const uint8_t *buffer, int buffer_size,
// } // }
if ( pkt->pts != (int64_t)AV_NOPTS_VALUE ) { if ( pkt->pts != (int64_t)AV_NOPTS_VALUE ) {
pkt->pts = av_rescale_q( pkt->pts, c->time_base, ost->time_base ); pkt->pts = av_rescale_q( pkt->pts, codec_context->time_base, ost->time_base );
} }
if ( pkt->dts != (int64_t)AV_NOPTS_VALUE ) { if ( pkt->dts != (int64_t)AV_NOPTS_VALUE ) {
pkt->dts = av_rescale_q( pkt->dts, c->time_base, ost->time_base ); pkt->dts = av_rescale_q( pkt->dts, codec_context->time_base, ost->time_base );
} }
pkt->duration = av_rescale_q( pkt->duration, c->time_base, ost->time_base ); pkt->duration = av_rescale_q( pkt->duration, codec_context->time_base, ost->time_base );
pkt->stream_index = ost->index; pkt->stream_index = ost->index;
} }
} }
@ -659,7 +692,11 @@ void *VideoStream::StreamingThreadCallback(void *ctx){
const uint64_t nanosecond_multiplier = 1000000000; const uint64_t nanosecond_multiplier = 1000000000;
uint64_t target_interval_ns = nanosecond_multiplier * ( ((double)videoStream->ost->codec->time_base.num) / (videoStream->ost->codec->time_base.den) ); #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
uint64_t target_interval_ns = nanosecond_multiplier * ( ((double)videoStream->codec_context->time_base.num) / (videoStream->codec_context->time_base.den) );
#else
uint64_t target_interval_ns = nanosecond_multiplier * ( ((double)videoStream->codec_context->time_base.num) / (videoStream->codec_context->time_base.den) );
#endif
uint64_t frame_count = 0; uint64_t frame_count = 0;
timespec start_time; timespec start_time;
clock_gettime(CLOCK_MONOTONIC, &start_time); clock_gettime(CLOCK_MONOTONIC, &start_time);

View File

@ -46,6 +46,7 @@ protected:
AVOutputFormat *of; AVOutputFormat *of;
AVFormatContext *ofc; AVFormatContext *ofc;
AVStream *ost; AVStream *ost;
AVCodecContext *codec_context;
AVCodec *codec; AVCodec *codec;
AVFrame *opicture; AVFrame *opicture;
AVFrame *tmp_opicture; AVFrame *tmp_opicture;

View File

@ -103,6 +103,7 @@ int RemoteCamera::Read( int fd, char *buf, int size ) {
int bytes_to_recv = size - ReceivedBytes; int bytes_to_recv = size - ReceivedBytes;
if ( SOCKET_BUF_SIZE < bytes_to_recv ) if ( SOCKET_BUF_SIZE < bytes_to_recv )
bytes_to_recv = SOCKET_BUF_SIZE; bytes_to_recv = SOCKET_BUF_SIZE;
//Debug(3, "Aiming to receive %d of %d bytes", bytes_to_recv, size );
bytes = recv(fd, &buf[ReceivedBytes], bytes_to_recv, 0); //socket, buffer, len, flags bytes = recv(fd, &buf[ReceivedBytes], bytes_to_recv, 0); //socket, buffer, len, flags
if ( bytes <= 0 ) { if ( bytes <= 0 ) {
Error("RemoteCamera::Read Recv error. Closing Socket\n"); Error("RemoteCamera::Read Recv error. Closing Socket\n");

View File

@ -87,7 +87,8 @@ public:
virtual void Terminate() = 0; virtual void Terminate() = 0;
virtual int Connect() = 0; virtual int Connect() = 0;
virtual int Disconnect() = 0; virtual int Disconnect() = 0;
virtual int PreCapture() = 0; virtual int PreCapture() { return 0; };
virtual int PrimeCapture() { return 0; };
virtual int Capture( Image &image ) = 0; virtual int Capture( Image &image ) = 0;
virtual int PostCapture() = 0; virtual int PostCapture() = 0;
virtual int CaptureAndRecord( Image &image, timeval recording, char* event_directory )=0; virtual int CaptureAndRecord( Image &image, timeval recording, char* event_directory )=0;

View File

@ -1063,23 +1063,18 @@ int RemoteCameraHttp::GetResponse()
return( 0 ); return( 0 );
} }
int RemoteCameraHttp::PreCapture() int RemoteCameraHttp::PreCapture() {
{ if ( sd < 0 ) {
if ( sd < 0 )
{
Connect(); Connect();
if ( sd < 0 ) if ( sd < 0 ) {
{
Error( "Unable to connect to camera" ); Error( "Unable to connect to camera" );
return( -1 ); return( -1 );
} }
mode = SINGLE_IMAGE; mode = SINGLE_IMAGE;
buffer.clear(); buffer.clear();
} }
if ( mode == SINGLE_IMAGE ) if ( mode == SINGLE_IMAGE ) {
{ if ( SendRequest() < 0 ) {
if ( SendRequest() < 0 )
{
Error( "Unable to send request" ); Error( "Unable to send request" );
Disconnect(); Disconnect();
return( -1 ); return( -1 );
@ -1088,50 +1083,43 @@ int RemoteCameraHttp::PreCapture()
return( 0 ); return( 0 );
} }
int RemoteCameraHttp::Capture( Image &image ) int RemoteCameraHttp::Capture( Image &image ) {
{
int content_length = GetResponse(); int content_length = GetResponse();
if ( content_length == 0 ) if ( content_length == 0 ) {
{
Warning( "Unable to capture image, retrying" ); Warning( "Unable to capture image, retrying" );
return( 1 ); return 0;
} }
if ( content_length < 0 ) if ( content_length < 0 ) {
{
Error( "Unable to get response, disconnecting" ); Error( "Unable to get response, disconnecting" );
Disconnect(); Disconnect();
return( -1 ); return -1;
} }
switch( format ) switch( format ) {
{
case JPEG : 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" ); Error( "Unable to decode jpeg" );
Disconnect(); Disconnect();
return( -1 ); return -1;
} }
break; break;
} }
case X_RGB : 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 ); Error( "Image length mismatch, expected %d bytes, content length was %d", image.Size(), content_length );
Disconnect(); Disconnect();
return( -1 ); return -1;
} }
image.Assign( width, height, colours, subpixelorder, buffer, imagesize ); image.Assign( width, height, colours, subpixelorder, buffer, imagesize );
break; break;
} }
case X_RGBZ : 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" ); Error( "Unable to unzip RGB image" );
Disconnect(); Disconnect();
return( -1 ); return -1;
} }
image.Assign( width, height, colours, subpixelorder, buffer, imagesize ); image.Assign( width, height, colours, subpixelorder, buffer, imagesize );
break; break;
@ -1140,13 +1128,12 @@ int RemoteCameraHttp::Capture( Image &image )
{ {
Error( "Unexpected image format encountered" ); Error( "Unexpected image format encountered" );
Disconnect(); Disconnect();
return( -1 ); return -1;
} }
} }
return( 0 ); return 1;
} }
int RemoteCameraHttp::PostCapture() int RemoteCameraHttp::PostCapture() {
{ return 0;
return( 0 );
} }

View File

@ -67,6 +67,7 @@ RemoteCameraNVSocket::RemoteCameraNVSocket(
timeout.tv_sec = 0; timeout.tv_sec = 0;
timeout.tv_usec = 0; timeout.tv_usec = 0;
subpixelorder = ZM_SUBPIX_ORDER_BGR;
if ( capture ) { if ( capture ) {
Initialise(); Initialise();
@ -97,13 +98,13 @@ void RemoteCameraNVSocket::Initialise() {
} }
int RemoteCameraNVSocket::Connect() { int RemoteCameraNVSocket::Connect() {
int port_num = atoi(port.c_str());
//struct addrinfo *p; //struct addrinfo *p;
struct sockaddr_in servaddr; struct sockaddr_in servaddr;
bzero( &servaddr, sizeof(servaddr)); bzero( &servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET; servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htons(INADDR_ANY); servaddr.sin_addr.s_addr = htons(INADDR_ANY);
servaddr.sin_port = htons(atoi(port.c_str())); servaddr.sin_port = htons(port_num);
sd = socket(AF_INET, SOCK_STREAM, 0); sd = socket(AF_INET, SOCK_STREAM, 0);
//for(p = hp; p != NULL; p = p->ai_next) { //for(p = hp; p != NULL; p = p->ai_next) {
@ -121,10 +122,6 @@ struct sockaddr_in servaddr;
Warning("Can't connect to socket mid: %d : %s", monitor_id, strerror(errno) ); Warning("Can't connect to socket mid: %d : %s", monitor_id, strerror(errno) );
return -1; return -1;
//continue;
//}
/* If we got here, we must have connected successfully */
//break;
} }
//if ( p == NULL ) { //if ( p == NULL ) {
@ -132,8 +129,8 @@ struct sockaddr_in servaddr;
//return( -1 ); //return( -1 );
//} //}
Debug( 3, "Connected to host, socket = %d", sd ); Debug( 3, "Connected to host:%d, socket = %d", port_num, sd );
return( sd ); return sd;
} }
int RemoteCameraNVSocket::Disconnect() { int RemoteCameraNVSocket::Disconnect() {
@ -144,124 +141,25 @@ int RemoteCameraNVSocket::Disconnect() {
} }
int RemoteCameraNVSocket::SendRequest( std::string request ) { int RemoteCameraNVSocket::SendRequest( std::string request ) {
Debug( 2, "Sending request: %s", request.c_str() ); Debug( 4, "Sending request: %s", request.c_str() );
if ( write( sd, request.data(), request.length() ) < 0 ) { if ( write( sd, request.data(), request.length() ) < 0 ) {
Error( "Can't write: %s", strerror(errno) ); Error( "Can't write: %s", strerror(errno) );
Disconnect(); Disconnect();
return( -1 ); return( -1 );
} }
Debug( 3, "Request sent" ); Debug( 4, "Request sent" );
return( 0 ); return( 0 );
} }
/* Return codes are as follows: int RemoteCameraNVSocket::PrimeCapture() {
* -1 means there was an error
* 0 means no bytes were returned but there wasn't actually an error.
* > 0 is the # of bytes read.
*/
int RemoteCameraNVSocket::ReadData( Buffer &buffer, unsigned int bytes_expected ) {
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(sd, &rfds);
struct timeval temp_timeout = timeout;
int n_found = select(sd+1, &rfds, NULL, NULL, &temp_timeout);
if ( n_found == 0 ) {
Debug( 4, "Select timed out timeout was %d secs %d usecs", temp_timeout.tv_sec, temp_timeout.tv_usec );
int error = 0;
socklen_t len = sizeof(error);
int retval = getsockopt(sd, SOL_SOCKET, SO_ERROR, &error, &len);
if ( retval != 0 ) {
Debug(1, "error getting socket error code %s", strerror(retval));
}
if ( error != 0 ) {
return -1;
}
// Why are we disconnecting? It's just a timeout, meaning that data wasn't available.
//Disconnect();
return 0;
} else if ( n_found < 0 ) {
Error("Select error: %s", strerror(errno));
return -1;
}
unsigned int total_bytes_to_read = 0;
if ( bytes_expected ) {
total_bytes_to_read = bytes_expected;
} else {
if ( ioctl( sd, FIONREAD, &total_bytes_to_read ) < 0 ) {
Error( "Can't ioctl(): %s", strerror(errno) );
return( -1 );
}
if ( total_bytes_to_read == 0 ) {
if ( mode == SINGLE_IMAGE ) {
int error = 0;
socklen_t len = sizeof (error);
int retval = getsockopt( sd, SOL_SOCKET, SO_ERROR, &error, &len );
if(retval != 0 ) {
Debug( 1, "error getting socket error code %s", strerror(retval) );
}
if (error != 0) {
return -1;
}
// Case where we are grabbing a single jpg, but no content-length was given, so the expectation is that we read until close.
return( 0 );
}
// If socket is closed locally, then select will fail, but if it is closed remotely
// then we have an exception on our socket.. but no data.
Debug( 3, "Socket closed remotely" );
//Disconnect(); // Disconnect is done outside of ReadData now.
return( -1 );
}
// There can be lots of bytes available. I've seen 4MB or more. This will vastly inflate our buffer size unnecessarily.
if ( total_bytes_to_read > ZM_NETWORK_BUFSIZ ) {
total_bytes_to_read = ZM_NETWORK_BUFSIZ;
Debug(3, "Just getting 32K" );
} else {
Debug(3, "Just getting %d", total_bytes_to_read );
}
} // end if bytes_expected or not
Debug( 3, "Expecting %d bytes", total_bytes_to_read );
int total_bytes_read = 0;
do {
int bytes_read = buffer.read_into( sd, total_bytes_to_read );
if ( bytes_read < 0 ) {
Error( "Read error: %s", strerror(errno) );
return( -1 );
} else if ( bytes_read == 0 ) {
Debug( 2, "Socket closed" );
//Disconnect(); // Disconnect is done outside of ReadData now.
return( -1 );
} else if ( (unsigned int)bytes_read < total_bytes_to_read ) {
Error( "Incomplete read, expected %d, got %d", total_bytes_to_read, bytes_read );
return( -1 );
}
Debug( 3, "Read %d bytes", bytes_read );
total_bytes_read += bytes_read;
total_bytes_to_read -= bytes_read;
} while ( total_bytes_to_read );
Debug( 4, buffer );
return( total_bytes_read );
}
int RemoteCameraNVSocket::PreCapture() {
if ( sd < 0 ) { if ( sd < 0 ) {
Connect(); Connect();
if ( sd < 0 ) { if ( sd < 0 ) {
Error( "Unable to connect to camera" ); Error( "Unable to connect to camera" );
return( -1 ); return( -1 );
} }
mode = SINGLE_IMAGE;
buffer.clear();
} }
buffer.clear();
struct image_def { struct image_def {
uint16_t width; uint16_t width;
uint16_t height; uint16_t height;
@ -269,7 +167,7 @@ struct image_def {
}; };
struct image_def image_def; struct image_def image_def;
if ( SendRequest("GetImageParams") < 0 ) { if ( SendRequest("GetImageParams\n") < 0 ) {
Error( "Unable to send request" ); Error( "Unable to send request" );
Disconnect(); Disconnect();
return -1; return -1;
@ -289,20 +187,28 @@ struct image_def image_def;
} }
int RemoteCameraNVSocket::Capture( Image &image ) { int RemoteCameraNVSocket::Capture( Image &image ) {
if ( SendRequest("GetNextImage") < 0 ) { if ( SendRequest("GetNextImage\n") < 0 ) {
Warning( "Unable to capture image, retrying" ); Warning( "Unable to capture image, retrying" );
return( 1 ); return 0;
} }
if ( Read( sd, buffer, imagesize ) < imagesize ) { if ( Read( sd, buffer, imagesize ) < imagesize ) {
Warning( "Unable to capture image, retrying" ); Warning( "Unable to capture image, retrying" );
return( 1 ); return 0;
}
uint32_t end;
if ( Read(sd, (char *) &end , sizeof(end)) < 0 ) {
Warning( "Unable to capture image, retrying" );
return 0;
}
if ( end != 0xFFFFFFFF) {
Warning("End Bytes Failed\n");
return 0;
} }
image.Assign( width, height, colours, subpixelorder, buffer, imagesize ); image.Assign( width, height, colours, subpixelorder, buffer, imagesize );
return( 0 ); return 1;
} }
int RemoteCameraNVSocket::PostCapture() int RemoteCameraNVSocket::PostCapture() {
{
return( 0 ); return( 0 );
} }

View File

@ -67,7 +67,7 @@ bool p_record_audio );
int SendRequest( std::string ); int SendRequest( std::string );
int ReadData( Buffer &buffer, unsigned int bytes_expected=0 ); int ReadData( Buffer &buffer, unsigned int bytes_expected=0 );
int GetResponse(); int GetResponse();
int PreCapture(); int PrimeCapture();
int Capture( Image &image ); int Capture( Image &image );
int PostCapture(); int PostCapture();
int CaptureAndRecord( Image &image, timeval recording, char* event_directory ) {return(0);}; int CaptureAndRecord( Image &image, timeval recording, char* event_directory ) {return(0);};

View File

@ -268,13 +268,13 @@ int RemoteCameraRtsp::Capture( Image &image ) {
directbuffer = image.WriteBuffer(width, height, colours, subpixelorder); directbuffer = image.WriteBuffer(width, height, colours, subpixelorder);
if ( directbuffer == NULL ) { if ( directbuffer == NULL ) {
Error("Failed requesting writeable buffer for the captured image."); Error("Failed requesting writeable buffer for the captured image.");
return (-1); return -1;
} }
while ( true ) { while ( true ) {
buffer.clear(); buffer.clear();
if ( !rtspThread->isRunning() ) if ( !rtspThread->isRunning() )
return (-1); return -1;
if ( rtspThread->getFrame( buffer ) ) { if ( rtspThread->getFrame( buffer ) ) {
Debug( 3, "Read frame %d bytes", buffer.size() ); Debug( 3, "Read frame %d bytes", buffer.size() );
@ -282,7 +282,7 @@ int RemoteCameraRtsp::Capture( Image &image ) {
Hexdump( 4, buffer.head(), 16 ); Hexdump( 4, buffer.head(), 16 );
if ( !buffer.size() ) 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 // SPS and PPS frames should be saved and appended to IDR frames
@ -358,12 +358,12 @@ int RemoteCameraRtsp::Capture( Image &image ) {
} /* getFrame() */ } /* getFrame() */
if ( frameComplete ) if ( frameComplete )
return (0); return 1;
} // end while true } // end while true
// can never get here. // can never get here.
return (0); return 0;
} }
//Function to handle capture and store //Function to handle capture and store

View File

@ -379,21 +379,31 @@ AVFormatContext *SessionDescriptor::generateFormatContext() const
stream->id = i; stream->id = i;
#endif #endif
AVCodecContext *codec_context = NULL;
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
codec_context = avcodec_alloc_context3(NULL);
avcodec_parameters_to_context(codec_context, stream->codecpar);
#else
codec_context = stream->codec;
#endif
Debug( 1, "Looking for codec for %s payload type %d / %s", mediaDesc->getType().c_str(), mediaDesc->getPayloadType(), mediaDesc->getPayloadDesc().c_str() ); Debug( 1, "Looking for codec for %s payload type %d / %s", mediaDesc->getType().c_str(), mediaDesc->getPayloadType(), mediaDesc->getPayloadDesc().c_str() );
#if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0)) #if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0))
if ( mediaDesc->getType() == "video" ) if ( mediaDesc->getType() == "video" )
stream->codec->codec_type = AVMEDIA_TYPE_VIDEO; codec_context->codec_type = AVMEDIA_TYPE_VIDEO;
else if ( mediaDesc->getType() == "audio" ) else if ( mediaDesc->getType() == "audio" )
stream->codec->codec_type = AVMEDIA_TYPE_AUDIO; codec_context->codec_type = AVMEDIA_TYPE_AUDIO;
else if ( mediaDesc->getType() == "application" ) else if ( mediaDesc->getType() == "application" )
stream->codec->codec_type = AVMEDIA_TYPE_DATA; codec_context->codec_type = AVMEDIA_TYPE_DATA;
#else #else
if ( mediaDesc->getType() == "video" ) if ( mediaDesc->getType() == "video" )
stream->codec->codec_type = CODEC_TYPE_VIDEO; codec_context->codec_type = CODEC_TYPE_VIDEO;
else if ( mediaDesc->getType() == "audio" ) else if ( mediaDesc->getType() == "audio" )
stream->codec->codec_type = CODEC_TYPE_AUDIO; codec_context->codec_type = CODEC_TYPE_AUDIO;
else if ( mediaDesc->getType() == "application" ) else if ( mediaDesc->getType() == "application" )
stream->codec->codec_type = CODEC_TYPE_DATA; codec_context->codec_type = CODEC_TYPE_DATA;
#endif #endif
#if LIBAVCODEC_VERSION_CHECK(55, 50, 3, 60, 103) #if LIBAVCODEC_VERSION_CHECK(55, 50, 3, 60, 103)
@ -410,31 +420,27 @@ AVFormatContext *SessionDescriptor::generateFormatContext() const
#if LIBAVCODEC_VERSION_CHECK(55, 50, 3, 60, 103) #if LIBAVCODEC_VERSION_CHECK(55, 50, 3, 60, 103)
codec_name = std::string( smStaticPayloads[i].payloadName ); codec_name = std::string( smStaticPayloads[i].payloadName );
#else #else
strncpy( stream->codec->codec_name, smStaticPayloads[i].payloadName, sizeof(stream->codec->codec_name) );; strncpy( codec_context->codec_name, smStaticPayloads[i].payloadName, sizeof(codec_context->codec_name) );;
#endif #endif
stream->codec->codec_type = smStaticPayloads[i].codecType; codec_context->codec_type = smStaticPayloads[i].codecType;
stream->codec->codec_id = smStaticPayloads[i].codecId; codec_context->codec_id = smStaticPayloads[i].codecId;
stream->codec->sample_rate = smStaticPayloads[i].clockRate; codec_context->sample_rate = smStaticPayloads[i].clockRate;
break; break;
} }
} }
} } else {
else
{
// Look in dynamic table // Look in dynamic table
for ( unsigned int i = 0; i < (sizeof(smDynamicPayloads)/sizeof(*smDynamicPayloads)); i++ ) for ( unsigned int i = 0; i < (sizeof(smDynamicPayloads)/sizeof(*smDynamicPayloads)); i++ ) {
{ if ( smDynamicPayloads[i].payloadName == mediaDesc->getPayloadDesc() ) {
if ( smDynamicPayloads[i].payloadName == mediaDesc->getPayloadDesc() )
{
Debug( 1, "Got dynamic payload type %d, %s", mediaDesc->getPayloadType(), smDynamicPayloads[i].payloadName ); Debug( 1, "Got dynamic payload type %d, %s", mediaDesc->getPayloadType(), smDynamicPayloads[i].payloadName );
#if LIBAVCODEC_VERSION_CHECK(55, 50, 3, 60, 103) #if LIBAVCODEC_VERSION_CHECK(55, 50, 3, 60, 103)
codec_name = std::string( smStaticPayloads[i].payloadName ); codec_name = std::string( smStaticPayloads[i].payloadName );
#else #else
strncpy( stream->codec->codec_name, smDynamicPayloads[i].payloadName, sizeof(stream->codec->codec_name) );; strncpy( codec_context->codec_name, smDynamicPayloads[i].payloadName, sizeof(codec_context->codec_name) );;
#endif #endif
stream->codec->codec_type = smDynamicPayloads[i].codecType; codec_context->codec_type = smDynamicPayloads[i].codecType;
stream->codec->codec_id = smDynamicPayloads[i].codecId; codec_context->codec_id = smDynamicPayloads[i].codecId;
stream->codec->sample_rate = mediaDesc->getClock(); codec_context->sample_rate = mediaDesc->getClock();
break; break;
} }
} }
@ -450,14 +456,13 @@ AVFormatContext *SessionDescriptor::generateFormatContext() const
//return( 0 ); //return( 0 );
} }
if ( mediaDesc->getWidth() ) if ( mediaDesc->getWidth() )
stream->codec->width = mediaDesc->getWidth(); codec_context->width = mediaDesc->getWidth();
if ( mediaDesc->getHeight() ) if ( mediaDesc->getHeight() )
stream->codec->height = mediaDesc->getHeight(); codec_context->height = mediaDesc->getHeight();
if ( stream->codec->codec_id == AV_CODEC_ID_H264 && mediaDesc->getSprops().size()) if ( codec_context->codec_id == AV_CODEC_ID_H264 && mediaDesc->getSprops().size()) {
{
uint8_t start_sequence[]= { 0, 0, 1 }; uint8_t start_sequence[]= { 0, 0, 1 };
stream->codec->extradata_size= 0; codec_context->extradata_size= 0;
stream->codec->extradata= NULL; codec_context->extradata= NULL;
char pvalue[1024], *value = pvalue; char pvalue[1024], *value = pvalue;
strcpy(pvalue, mediaDesc->getSprops().c_str()); strcpy(pvalue, mediaDesc->getSprops().c_str());
@ -482,22 +487,33 @@ AVFormatContext *SessionDescriptor::generateFormatContext() const
if (packet_size) { if (packet_size) {
uint8_t *dest = uint8_t *dest =
(uint8_t *)av_malloc(packet_size + sizeof(start_sequence) + (uint8_t *)av_malloc(packet_size + sizeof(start_sequence) +
stream->codec->extradata_size + codec_context->extradata_size +
FF_INPUT_BUFFER_PADDING_SIZE); #if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
AV_INPUT_BUFFER_PADDING_SIZE
#else
FF_INPUT_BUFFER_PADDING_SIZE
#endif
);
if(dest) { if(dest) {
if(stream->codec->extradata_size) { if(codec_context->extradata_size) {
// av_realloc? // av_realloc?
memcpy(dest, stream->codec->extradata, stream->codec->extradata_size); memcpy(dest, codec_context->extradata, codec_context->extradata_size);
av_free(stream->codec->extradata); av_free(codec_context->extradata);
} }
memcpy(dest+stream->codec->extradata_size, start_sequence, sizeof(start_sequence)); memcpy(dest+codec_context->extradata_size, start_sequence, sizeof(start_sequence));
memcpy(dest+stream->codec->extradata_size+sizeof(start_sequence), decoded_packet, packet_size); memcpy(dest+codec_context->extradata_size+sizeof(start_sequence), decoded_packet, packet_size);
memset(dest+stream->codec->extradata_size+sizeof(start_sequence)+ memset(dest+codec_context->extradata_size+sizeof(start_sequence)+
packet_size, 0, FF_INPUT_BUFFER_PADDING_SIZE); packet_size, 0,
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
AV_INPUT_BUFFER_PADDING_SIZE
#else
FF_INPUT_BUFFER_PADDING_SIZE
#endif
);
stream->codec->extradata= dest; codec_context->extradata= dest;
stream->codec->extradata_size+= sizeof(start_sequence)+packet_size; codec_context->extradata_size+= sizeof(start_sequence)+packet_size;
// } else { // } else {
// av_log(codec, AV_LOG_ERROR, "Unable to allocate memory for extradata!"); // av_log(codec, AV_LOG_ERROR, "Unable to allocate memory for extradata!");
// return AVERROR(ENOMEM); // return AVERROR(ENOMEM);

View File

@ -31,13 +31,11 @@
#include <string> #include <string>
#include <vector> #include <vector>
class SessionDescriptor class SessionDescriptor {
{
protected: protected:
enum { PAYLOAD_TYPE_DYNAMIC=96 }; enum { PAYLOAD_TYPE_DYNAMIC=96 };
struct StaticPayloadDesc struct StaticPayloadDesc {
{
int payloadType; int payloadType;
const char payloadName[6]; const char payloadName[6];
#if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0)) #if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0))
@ -50,8 +48,7 @@ protected:
int autoChannels; int autoChannels;
}; };
struct DynamicPayloadDesc struct DynamicPayloadDesc {
{
const char payloadName[32]; const char payloadName[32];
#if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0)) #if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0))
AVMediaType codecType; AVMediaType codecType;
@ -65,8 +62,7 @@ protected:
}; };
public: public:
class ConnInfo class ConnInfo {
{
protected: protected:
std::string mNetworkType; std::string mNetworkType;
std::string mAddressType; std::string mAddressType;
@ -78,8 +74,7 @@ public:
ConnInfo( const std::string &connInfo ); ConnInfo( const std::string &connInfo );
}; };
class BandInfo class BandInfo {
{
protected: protected:
std::string mType; std::string mType;
int mValue; int mValue;
@ -88,8 +83,7 @@ public:
BandInfo( const std::string &bandInfo ); BandInfo( const std::string &bandInfo );
}; };
class MediaDescriptor class MediaDescriptor {
{
protected: protected:
std::string mType; std::string mType;
int mPort; int mPort;

View File

@ -311,7 +311,7 @@ void StreamBase::openComms() {
strncpy( rem_addr.sun_path, rem_sock_path, sizeof(rem_addr.sun_path) ); strncpy( rem_addr.sun_path, rem_sock_path, sizeof(rem_addr.sun_path) );
rem_addr.sun_family = AF_UNIX; rem_addr.sun_family = AF_UNIX;
} // end if connKey > 0 } // end if connKey > 0
Debug(3, "comms open" ); Debug(2, "comms open" );
} }
void StreamBase::closeComms() { void StreamBase::closeComms() {

View File

@ -229,7 +229,11 @@ VideoStore::VideoStore(
video_out_ctx->time_base.den); video_out_ctx->time_base.den);
if (oc->oformat->flags & AVFMT_GLOBALHEADER) { if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
#if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0)
video_out_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
#else
video_out_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER; video_out_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
#endif
} }
Monitor::Orientation orientation = monitor->getOrientation(); Monitor::Orientation orientation = monitor->getOrientation();
@ -335,7 +339,11 @@ VideoStore::VideoStore(
if (audio_out_stream) { if (audio_out_stream) {
if (oc->oformat->flags & AVFMT_GLOBALHEADER) { if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
#if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0)
audio_out_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
#else
audio_out_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER; audio_out_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
#endif
} }
} }
} // end if audio_in_stream } // end if audio_in_stream

View File

@ -1 +1 @@
1.31.10 1.31.12

209
web/ajax/add_monitors.php Normal file
View File

@ -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' );
?>

View File

@ -1,170 +1,170 @@
<?php <?php
$statusData = array( $statusData = array(
"system" => array( 'system' => array(
"permission" => "System", 'permission' => 'System',
"table" => "Monitors", 'table' => 'Monitors',
"limit" => 1, 'limit' => 1,
"elements" => array( 'elements' => array(
"MonitorCount" => array( "sql" => "count(*)" ), 'MonitorCount' => array( 'sql' => "count(*)" ),
"ActiveMonitorCount" => array( "sql" => "count(if(Function != 'None',1,NULL))" ), 'ActiveMonitorCount' => array( 'sql' => "count(if(Function != 'None',1,NULL))" ),
"State" => array( "func" => "daemonCheck()?".translate('Running').":".translate('Stopped') ), 'State' => array( 'func' => "daemonCheck()?".translate('Running').":".translate('Stopped') ),
"Load" => array( "func" => "getLoad()" ), 'Load' => array( 'func' => "getLoad()" ),
"Disk" => array( "func" => "getDiskPercent()" ), 'Disk' => array( 'func' => "getDiskPercent()" ),
), ),
), ),
"monitor" => array( 'monitor' => array(
"permission" => "Monitors", 'permission' => 'Monitors',
"table" => "Monitors", 'table' => 'Monitors',
"limit" => 1, 'limit' => 1,
"selector" => "Monitors.Id", 'selector' => "Monitors.Id",
"elements" => array( 'elements' => array(
"Id" => array( "sql" => "Monitors.Id" ), 'Id' => array( 'sql' => "Monitors.Id" ),
"Name" => array( "sql" => "Monitors.Name" ), 'Name' => array( 'sql' => "Monitors.Name" ),
"Type" => true, 'Type' => true,
"Function" => true, 'Function' => true,
"Enabled" => true, 'Enabled' => true,
"LinkedMonitors" => true, 'LinkedMonitors' => true,
"Triggers" => true, 'Triggers' => true,
"Device" => true, 'Device' => true,
"Channel" => true, 'Channel' => true,
"Format" => true, 'Format' => true,
"Host" => true, 'Host' => true,
"Port" => true, 'Port' => true,
"Path" => true, 'Path' => true,
"Width" => array( "sql" => "Monitors.Width" ), 'Width' => array( 'sql' => "Monitors.Width" ),
"Height" => array( "sql" => "Monitors.Height" ), 'Height' => array( 'sql' => "Monitors.Height" ),
"Palette" => true, 'Palette' => true,
"Orientation" => true, 'Orientation' => true,
"Brightness" => true, 'Brightness' => true,
"Contrast" => true, 'Contrast' => true,
"Hue" => true, 'Hue' => true,
"Colour" => true, 'Colour' => true,
"EventPrefix" => true, 'EventPrefix' => true,
"LabelFormat" => true, 'LabelFormat' => true,
"LabelX" => true, 'LabelX' => true,
"LabelY" => true, 'LabelY' => true,
"LabelSize" => true, 'LabelSize' => true,
"ImageBufferCount" => true, 'ImageBufferCount' => true,
"WarmupCount" => true, 'WarmupCount' => true,
"PreEventCount" => true, 'PreEventCount' => true,
"PostEventCount" => true, 'PostEventCount' => true,
"AlarmFrameCount" => true, 'AlarmFrameCount' => true,
"SectionLength" => true, 'SectionLength' => true,
"FrameSkip" => true, 'FrameSkip' => true,
"MotionFrameSkip" => true, 'MotionFrameSkip' => true,
"MaxFPS" => true, 'MaxFPS' => true,
"AlarmMaxFPS" => true, 'AlarmMaxFPS' => true,
"FPSReportInterval" => true, 'FPSReportInterval' => true,
"RefBlendPerc" => true, 'RefBlendPerc' => true,
"Controllable" => true, 'Controllable' => true,
"ControlId" => true, 'ControlId' => true,
"ControlDevice" => true, 'ControlDevice' => true,
"ControlAddress" => true, 'ControlAddress' => true,
"AutoStopTimeout" => true, 'AutoStopTimeout' => true,
"TrackMotion" => true, 'TrackMotion' => true,
"TrackDelay" => true, 'TrackDelay' => true,
"ReturnLocation" => true, 'ReturnLocation' => true,
"ReturnDelay" => true, 'ReturnDelay' => true,
"DefaultView" => true, 'DefaultView' => true,
"DefaultRate" => true, 'DefaultRate' => true,
"DefaultScale" => true, 'DefaultScale' => true,
"WebColour" => true, 'WebColour' => true,
"Sequence" => true, 'Sequence' => true,
"MinEventId" => array( "sql" => "(SELECT min(Events.Id) FROM Events WHERE Events.MonitorId = Monitors.Id" ), '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" ), '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" ), 'TotalEvents' => array( 'sql' => "(SELECT count(Events.Id) FROM Events WHERE Events.MonitorId = Monitors.Id" ),
"Status" => array( "zmu" => "-m ".escapeshellarg($_REQUEST['id'][0])." -s" ), 'Status' => array( 'zmu' => "-m ".escapeshellarg($_REQUEST['id'][0])." -s" ),
"FrameRate" => array( "zmu" => "-m ".escapeshellarg($_REQUEST['id'][0])." -f" ), 'FrameRate' => array( 'zmu' => "-m ".escapeshellarg($_REQUEST['id'][0])." -f" ),
), ),
), ),
"events" => array( 'events' => array(
"permission" => "Events", 'permission' => 'Events',
"table" => "Events", 'table' => 'Events',
"selector" => "Events.MonitorId", 'selector' => "Events.MonitorId",
"elements" => array( 'elements' => array(
"Id" => true, 'Id' => true,
"Name" => true, 'Name' => true,
"Cause" => true, 'Cause' => true,
"Notes" => true, 'Notes' => true,
"StartTime" => true, 'StartTime' => true,
"StartTimeShort" => array( "sql" => "date_format( StartTime, '".MYSQL_FMT_DATETIME_SHORT."' )" ), 'StartTimeShort' => array( 'sql' => "date_format( StartTime, '".MYSQL_FMT_DATETIME_SHORT."' )" ),
"EndTime" => true, 'EndTime' => true,
"Width" => true, 'Width' => true,
"Height" => true, 'Height' => true,
"Length" => true, 'Length' => true,
"Frames" => true, 'Frames' => true,
"AlarmFrames" => true, 'AlarmFrames' => true,
"TotScore" => true, 'TotScore' => true,
"AvgScore" => true, 'AvgScore' => true,
"MaxScore" => true, 'MaxScore' => true,
), ),
), ),
"event" => array( 'event' => array(
"permission" => "Events", 'permission' => 'Events',
"table" => "Events", 'table' => 'Events',
"limit" => 1, 'limit' => 1,
"selector" => "Events.Id", 'selector' => "Events.Id",
"elements" => array( 'elements' => array(
"Id" => array( "sql" => "Events.Id" ), 'Id' => array( 'sql' => "Events.Id" ),
"MonitorId" => true, 'MonitorId' => true,
"MonitorName" => array("sql" => "(SELECT Monitors.Name FROM Monitors WHERE Monitors.Id = Events.MonitorId)"), 'MonitorName' => array('sql' => "(SELECT Monitors.Name FROM Monitors WHERE Monitors.Id = Events.MonitorId)"),
"Name" => true, 'Name' => true,
"Cause" => true, 'Cause' => true,
"StartTime" => true, 'StartTime' => true,
"StartTimeShort" => array( "sql" => "date_format( StartTime, '".MYSQL_FMT_DATETIME_SHORT."' )" ), 'StartTimeShort' => array( 'sql' => "date_format( StartTime, '".MYSQL_FMT_DATETIME_SHORT."' )" ),
"EndTime" => true, 'EndTime' => true,
"Width" => true, 'Width' => true,
"Height" => true, 'Height' => true,
"Length" => true, 'Length' => true,
"Frames" => true, 'Frames' => true,
"DefaultVideo" => true, 'DefaultVideo' => true,
"AlarmFrames" => true, 'AlarmFrames' => true,
"TotScore" => true, 'TotScore' => true,
"AvgScore" => true, 'AvgScore' => true,
"MaxScore" => true, 'MaxScore' => true,
"Archived" => true, 'Archived' => true,
"Videoed" => true, 'Videoed' => true,
"Uploaded" => true, 'Uploaded' => true,
"Emailed" => true, 'Emailed' => true,
"Messaged" => true, 'Messaged' => true,
"Executed" => true, 'Executed' => true,
"Notes" => true, 'Notes' => true,
"MinFrameId" => array( "sql" => "(SELECT min(Frames.FrameId) FROM Frames WHERE EventId=Events.Id)" ), '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)" ), '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)" ), '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)" ), 'MaxFrameDelta' => array( 'sql' => "(SELECT max(Frames.Delta) FROM Frames WHERE Events.Id = Frames.EventId)" ),
//"Path" => array( "postFunc" => "getEventPath" ), //'Path' => array( 'postFunc' => 'getEventPath' ),
), ),
), ),
"frame" => array( 'frame' => array(
"permission" => "Events", 'permission' => 'Events',
"table" => "Frames", 'table' => 'Frames',
"limit" => 1, 'limit' => 1,
"selector" => array( array( "table" => "Events", "join" => "Events.Id = Frames.EventId", "selector"=>"Events.Id" ), "Frames.FrameId" ), 'selector' => array( array( 'table' => 'Events', 'join' => "Events.Id = Frames.EventId", 'selector'=>"Events.Id" ), "Frames.FrameId" ),
"elements" => array( 'elements' => array(
//"Id" => array( "sql" => "Frames.FrameId" ), //'Id' => array( 'sql' => "Frames.FrameId" ),
"FrameId" => true, 'FrameId' => true,
"EventId" => true, 'EventId' => true,
"Type" => true, 'Type' => true,
"TimeStamp" => true, 'TimeStamp' => true,
"TimeStampShort" => array( "sql" => "date_format( StartTime, '".MYSQL_FMT_DATETIME_SHORT."' )" ), 'TimeStampShort' => array( 'sql' => "date_format( StartTime, '".MYSQL_FMT_DATETIME_SHORT."' )" ),
"Delta" => true, 'Delta' => true,
"Score" => true, 'Score' => true,
//"Image" => array( "postFunc" => "getFrameImage" ), //'Image' => array( 'postFunc' => 'getFrameImage' ),
), ),
), ),
"frameimage" => array( 'frameimage' => array(
"permission" => "Events", 'permission' => 'Events',
"func" => "getFrameImage()" 'func' => "getFrameImage()"
), ),
"nearframe" => array( 'nearframe' => array(
"permission" => "Events", 'permission' => 'Events',
"func" => "getNearFrame()" 'func' => "getNearFrame()"
), ),
"nearevents" => array( 'nearevents' => array(
"permission" => "Events", 'permission' => 'Events',
"func" => "getNearEvents()" 'func' => "getNearEvents()"
) )
); );
@ -290,7 +290,7 @@ function collectData() {
$data = collectData(); $data = collectData();
if ( !isset($_REQUEST['layout']) ) { if ( !isset($_REQUEST['layout']) ) {
$_REQUEST['layout'] = "json"; $_REQUEST['layout'] = 'json';
} }
switch( $_REQUEST['layout'] ) { switch( $_REQUEST['layout'] ) {
@ -331,7 +331,7 @@ function getFrameImage() {
$frame = array(); $frame = array();
$frame['EventId'] = $eventId; $frame['EventId'] = $eventId;
$frame['FrameId'] = $frameId; $frame['FrameId'] = $frameId;
$frame['Type'] = "Virtual"; $frame['Type'] = 'Virtual';
} }
$event = dbFetchOne( 'select * from Events where Id = ?', NULL, array( $frame['EventId'] ) ); $event = dbFetchOne( 'select * from Events where Id = ?', NULL, array( $frame['EventId'] ) );
$frame['Image'] = getImageSrc( $event, $frame, SCALE_BASE ); $frame['Image'] = getImageSrc( $event, $frame, SCALE_BASE );
@ -349,7 +349,7 @@ function getNearFrame() {
return( array() ); return( array() );
} }
} }
$_REQUEST['entity'] = "frame"; $_REQUEST['entity'] = 'frame';
$_REQUEST['id'][1] = $nearFrameId; $_REQUEST['id'][1] = $nearFrameId;
return( collectData() ); return( collectData() );
} }
@ -358,7 +358,7 @@ function getNearEvents() {
global $user, $sortColumn, $sortOrder; global $user, $sortColumn, $sortOrder;
$eventId = $_REQUEST['id']; $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'] ); parseFilter( $_REQUEST['filter'] );
parseSort(); parseSort();
@ -368,7 +368,7 @@ function getNearEvents() {
else else
$midSql = ''; $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 ); $result = dbQuery( $sql );
while ( $id = dbFetchNext( $result, 'Id' ) ) { while ( $id = dbFetchNext( $result, 'Id' ) ) {
if ( $id == $eventId ) { 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 ); $result = dbQuery( $sql );
while ( $id = dbFetchNext( $result, 'Id' ) ) { while ( $id = dbFetchNext( $result, 'Id' ) ) {
if ( $id == $eventId ) { if ( $id == $eventId ) {

View File

@ -1,5 +1,7 @@
<?php <?php
$start_time = time();
define( "MSG_TIMEOUT", ZM_WEB_AJAX_TIMEOUT ); define( "MSG_TIMEOUT", ZM_WEB_AJAX_TIMEOUT );
define( "MSG_DATA_SIZE", 4+256 ); 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()) ); ajaxError( "socket_create() failed: ".socket_strerror(socket_last_error()) );
} }
$locSockFile = ZM_PATH_SOCKS.'/zms-'.sprintf("%06d",$_REQUEST['connkey']).'w.sock'; $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 ) ) { if ( !@socket_bind( $socket, $locSockFile ) ) {
ajaxError( "socket_bind( $locSockFile ) failed: ".socket_strerror(socket_last_error()) ); ajaxError( "socket_bind( $locSockFile ) failed: ".socket_strerror(socket_last_error()) );
} else {
Logger::Debug("Bound to $locSockFile");
} }
switch ( $_REQUEST['command'] ) { switch ( $_REQUEST['command'] ) {
case CMD_VARPLAY : case CMD_VARPLAY :
Logger::Debug( "Varplaying to ".$_REQUEST['rate'] ); Logger::Debug( 'Varplaying to '.$_REQUEST['rate'] );
$msg = pack( "lcn", MSG_CMD, $_REQUEST['command'], $_REQUEST['rate']+32768 ); $msg = pack( 'lcn', MSG_CMD, $_REQUEST['command'], $_REQUEST['rate']+32768 );
break; break;
case CMD_ZOOMIN : case CMD_ZOOMIN :
Logger::Debug( "Zooming to ".$_REQUEST['x'].",".$_REQUEST['y'] ); Logger::Debug( 'Zooming to '.$_REQUEST['x'].",".$_REQUEST['y'] );
$msg = pack( "lcnn", MSG_CMD, $_REQUEST['command'], $_REQUEST['x'], $_REQUEST['y'] ); $msg = pack( 'lcnn', MSG_CMD, $_REQUEST['command'], $_REQUEST['x'], $_REQUEST['y'] );
break; break;
case CMD_PAN : case CMD_PAN :
Logger::Debug( "Panning to ".$_REQUEST['x'].",".$_REQUEST['y'] ); Logger::Debug( 'Panning to '.$_REQUEST['x'].",".$_REQUEST['y'] );
$msg = pack( "lcnn", MSG_CMD, $_REQUEST['command'], $_REQUEST['x'], $_REQUEST['y'] ); $msg = pack( 'lcnn', MSG_CMD, $_REQUEST['command'], $_REQUEST['x'], $_REQUEST['y'] );
break; break;
case CMD_SCALE : case CMD_SCALE :
Logger::Debug( "Scaling to ".$_REQUEST['scale'] ); Logger::Debug( 'Scaling to '.$_REQUEST['scale'] );
$msg = pack( "lcn", MSG_CMD, $_REQUEST['command'], $_REQUEST['scale'] ); $msg = pack( 'lcn', MSG_CMD, $_REQUEST['command'], $_REQUEST['scale'] );
break; break;
case CMD_SEEK : case CMD_SEEK :
Logger::Debug( "Seeking to ".$_REQUEST['offset'] ); Logger::Debug( 'Seeking to '.$_REQUEST['offset'] );
$msg = pack( "lcN", MSG_CMD, $_REQUEST['command'], $_REQUEST['offset'] ); $msg = pack( 'lcN', MSG_CMD, $_REQUEST['command'], $_REQUEST['offset'] );
break; break;
default : default :
$msg = pack( "lc", MSG_CMD, $_REQUEST['command'] ); $msg = pack( 'lc', MSG_CMD, $_REQUEST['command'] );
break; 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; $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. 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); usleep(200000);
} }
@ -58,17 +69,26 @@ if ( !file_exists($remSockFile) ) {
$rSockets = array( $socket ); $rSockets = array( $socket );
$wSockets = NULL; $wSockets = NULL;
$eSockets = 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 ) { if ( $numSockets === false ) {
Error("socket_select failed: " . socket_strerror(socket_last_error()) );
ajaxError( "socket_select failed: ".socket_strerror(socket_last_error()) ); ajaxError( "socket_select failed: ".socket_strerror(socket_last_error()) );
} else if ( $numSockets < 0 ) { } else if ( $numSockets < 0 ) {
Error( "Socket closed $remSockFile" );
ajaxError( "Socket closed $remSockFile" ); ajaxError( "Socket closed $remSockFile" );
} else if ( $numSockets == 0 ) { } else if ( $numSockets == 0 ) {
Error( "Timed out waiting for msg $remSockFile" );
ajaxError( "Timed out waiting for msg $remSockFile" ); ajaxError( "Timed out waiting for msg $remSockFile" );
} else if ( $numSockets > 0 ) { } else if ( $numSockets > 0 ) {
if ( count($rSockets) != 1 ) if ( count($rSockets) != 1 ) {
ajaxError( "Bogus return from select, ".count($rSockets)." sockets available" ); 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 ) ) { 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 : case 0 :
{ {
ajaxError( "No data to read from socket" ); ajaxError( 'No data to read from socket' );
break; break;
} }
default : 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'] ) { switch ( $data['type'] ) {
case MSG_DATA_WATCH : case MSG_DATA_WATCH :
{ {
@ -99,7 +119,7 @@ switch ( $data['type'] ) {
$data['rate'] /= RATE_BASE; $data['rate'] /= RATE_BASE;
$data['delay'] = round( $data['delay'], 2 ); $data['delay'] = round( $data['delay'], 2 );
$data['zoom'] = round( $data['zoom']/SCALE_BASE, 1 ); $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(); session_start();
$time = time(); $time = time();
// Regenerate auth hash after half the lifetime of the hash // Regenerate auth hash after half the lifetime of the hash
@ -117,7 +137,7 @@ switch ( $data['type'] ) {
//$data['progress'] = sprintf( "%.2f", $data['progress'] ); //$data['progress'] = sprintf( "%.2f", $data['progress'] );
$data['rate'] /= RATE_BASE; $data['rate'] /= RATE_BASE;
$data['zoom'] = round( $data['zoom']/SCALE_BASE, 1 ); $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(); session_start();
$time = time(); $time = time();
// Regenerate auth hash after half the lifetime of the hash // Regenerate auth hash after half the lifetime of the hash

View File

@ -4,13 +4,16 @@ require_once( 'Server.php' );
class Monitor { class Monitor {
private $fields = array( private $defaults = array(
'Id', 'Id' => null,
'Name', 'Name' => '',
'StorageId', 'StorageId' => 0,
'ServerId', 'ServerId' => 0,
'Function', 'Function' => 'None',
'Enabled', 'Enabled' => 1,
'Width' => null,
'Height' => null,
'Orientation' => null,
); );
private $control_fields = array( private $control_fields = array(
'Name' => '', 'Name' => '',
@ -169,8 +172,9 @@ private $control_fields = array(
} else { } else {
if ( array_key_exists($fn, $this->control_fields) ) { if ( array_key_exists($fn, $this->control_fields) ) {
return $this->control_fields{$fn}; return $this->control_fields{$fn};
} else if ( array_key_exists( $fn, $this->defaults ) ) {
return $this->defaults{$fn};
} else { } else {
$backTrace = debug_backtrace(); $backTrace = debug_backtrace();
$file = $backTrace[1]['file']; $file = $backTrace[1]['file'];
$line = $backTrace[1]['line']; $line = $backTrace[1]['line'];
@ -214,14 +218,19 @@ private $control_fields = array(
return( $streamSrc ); return( $streamSrc );
} // end function getStreamSrc } // end function getStreamSrc
public function Width() { public function Width( $new = null ) {
if ( $new )
$this->{'Width'} = $new;
if ( $this->Orientation() == '90' or $this->Orientation() == '270' ) { if ( $this->Orientation() == '90' or $this->Orientation() == '270' ) {
return $this->{'Height'}; return $this->{'Height'};
} }
return $this->{'Width'}; return $this->{'Width'};
} }
public function Height() { public function Height( $new=null ) {
if ( $new )
$this->{'Height'} = $new;
if ( $this->Orientation() == '90' or $this->Orientation() == '270' ) { if ( $this->Orientation() == '90' or $this->Orientation() == '270' ) {
return $this->{'Width'}; return $this->{'Width'};
} }
@ -287,11 +296,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 = array_map( function($field){return $this->{$field};}, $this->fields );
$values[] = $this->{'Id'}; $values[] = $this->{'Id'};
dbQuery( $sql, $values ); dbQuery( $sql, $values );
} // end function save } // end function save
function zmcControl( $mode=false ) { function zmcControl( $mode=false ) {
if ( (!defined('ZM_SERVER_ID')) or ( ZM_SERVER_ID==$this->{'ServerId'} ) ) { if ( (!defined('ZM_SERVER_ID')) or ( ZM_SERVER_ID==$this->{'ServerId'} ) ) {
if ( $this->{'Type'} == 'Local' ) { if ( $this->{'Type'} == 'Local' ) {
@ -306,6 +316,7 @@ private $control_fields = array(
if ( $mode == 'restart' ) { if ( $mode == 'restart' ) {
daemonControl( 'stop', 'zmc', $zmcArgs ); daemonControl( 'stop', 'zmc', $zmcArgs );
} }
if ( $this->{'Function'} != 'None' )
daemonControl( 'start', 'zmc', $zmcArgs ); daemonControl( 'start', 'zmc', $zmcArgs );
} }
} else { } else {

View File

@ -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
?>

View File

@ -18,11 +18,32 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
// //
// PP - POST request handler for PHP which does not need extensions // PP - POST request handler for PHP which does not need extensions
// credit: http://wezfurlong.org/blog/2006/nov/http-post-from-php-without-curl/ // 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) { function do_post_request($url, $data, $optional_headers = null) {
$params = array('http' => array( $params = array('http' => array(
'method' => 'POST', 'method' => 'POST',
@ -56,7 +77,9 @@ function getAffectedIds( $name ) {
} }
if ( !empty($action) ) { if ( empty($action) ) {
return;
}
if ( $action == 'login' && isset($_REQUEST['username']) && ( ZM_AUTH_TYPE == 'remote' || isset($_REQUEST['password']) ) ) { if ( $action == 'login' && isset($_REQUEST['username']) && ( ZM_AUTH_TYPE == 'remote' || isset($_REQUEST['password']) ) ) {
// if true, a popup will display after login // if true, a popup will display after login
// PP - lets validate reCaptcha if it exists // PP - lets validate reCaptcha if it exists
@ -659,7 +682,26 @@ Warning("Addterm");
// System edit actions // System edit actions
if ( canEdit( 'System' ) ) { if ( canEdit( 'System' ) ) {
if ( isset( $_REQUEST['object'] ) ) { 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 ( $action == 'Save' ) {
if ( !empty($_REQUEST['id']) ) if ( !empty($_REQUEST['id']) )
@ -906,6 +948,5 @@ Warning("Addterm");
setcookie( 'zmEventResetTime', $_SESSION['zmEventResetTime'], time()+3600*24*30*12*10 ); setcookie( 'zmEventResetTime', $_SESSION['zmEventResetTime'], time()+3600*24*30*12*10 );
//if ( $cookies ) session_write_close(); //if ( $cookies ) session_write_close();
} }
}
?> ?>

View File

@ -122,17 +122,26 @@ function dbQuery( $sql, $params=NULL ) {
$result = NULL; $result = NULL;
try { try {
if ( isset($params) ) { if ( isset($params) ) {
$result = $dbConn->prepare( $sql ); if ( ! $result = $dbConn->prepare( $sql ) ) {
$result->execute( $params ); Error("SQL: Error preparing $sql: " . $pdo->errorInfo);
return NULL;
}
if ( ! $result->execute( $params ) ) {
Error("SQL: Error executing $sql: " . implode(',', $result->errorInfo() ) );
return NULL;
}
} else { } else {
$result = $dbConn->query( $sql ); $result = $dbConn->query( $sql );
} }
if ( 0 ) {
if ( $params ) if ( $params )
Warning("SQL: $sql" . implode(',',$params)); Warning("SQL: $sql" . implode(',',$params) . ' rows: '.$result->rowCount() );
else else
Warning("SQL: $sql" ); Warning("SQL: $sql: rows:" . $result->rowCount() );
}
} catch(PDOException $e) { } 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 ); return( $result );
} }

View File

@ -1058,6 +1058,7 @@ function parseSort( $saveToSession=false, $querySep='&amp;' ) {
break; break;
case 'DateTime' : case 'DateTime' :
$sortColumn = 'E.StartTime'; $sortColumn = 'E.StartTime';
$_REQUEST['sort_field'] = 'StartTime';
break; break;
case 'DiskSpace' : case 'DiskSpace' :
$sortColumn = 'E.DiskSpace'; $sortColumn = 'E.DiskSpace';
@ -1274,6 +1275,12 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&amp;' ) {
case '![]' : case '![]' :
$filter['sql'] .= ' not in ('.join( ',', $valueList ).')'; $filter['sql'] .= ' not in ('.join( ',', $valueList ).')';
break; break;
case 'IS' :
$filter['sql'] .= " IS $value";
break;
case 'IS NOT' :
$filter['sql'] .= " IS NOT $value";
break;
} }
$filter['query'] .= $querySep.urlencode("filter[Query][terms][$i][op]").'='.urlencode($terms[$i]['op']); $filter['query'] .= $querySep.urlencode("filter[Query][terms][$i][op]").'='.urlencode($terms[$i]['op']);
@ -2056,6 +2063,19 @@ function detaintPath( $path ) {
return( $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 ) { function getSkinFile( $file ) {
global $skinBase; global $skinBase;
$skinFile = false; $skinFile = false;
@ -2064,7 +2084,7 @@ function getSkinFile( $file ) {
if ( file_exists( $tempSkinFile ) ) if ( file_exists( $tempSkinFile ) )
$skinFile = $tempSkinFile; $skinFile = $tempSkinFile;
} }
return( $skinFile ); return $skinFile;
} }
function getSkinIncludes( $file, $includeBase=false, $asOverride=false ) { function getSkinIncludes( $file, $includeBase=false, $asOverride=false ) {

View File

@ -2,8 +2,7 @@
require_once( 'config.php' ); require_once( 'config.php' );
class Logger class Logger {
{
private static $instance; private static $instance;
const DEBUG = 1; const DEBUG = 1;
@ -61,26 +60,22 @@ class Logger
self::PANIC => E_USER_ERROR, self::PANIC => E_USER_ERROR,
); );
private function __construct() private function __construct() {
{
$this->hasTerm = (php_sapi_name() == 'cli' && empty($_SERVER['REMOTE_ADDR'])); $this->hasTerm = (php_sapi_name() == 'cli' && empty($_SERVER['REMOTE_ADDR']));
$this->logFile = $this->logPath."/".$this->id.".log"; $this->logFile = $this->logPath."/".$this->id.".log";
} }
public function __destruct() public function __destruct() {
{
$this->terminate(); $this->terminate();
} }
public function initialise( $options=array() ) public function initialise( $options=array() ) {
{
if ( !empty($options['id']) ) if ( !empty($options['id']) )
$this->id = $options['id']; $this->id = $options['id'];
//if ( isset($options['useErrorLog']) ) //if ( isset($options['useErrorLog']) )
//$this->useErrorLog = $options['useErrorLog']; //$this->useErrorLog = $options['useErrorLog'];
if ( isset($options['logPath']) ) if ( isset($options['logPath']) ) {
{
$this->logPath = $options['logPath']; $this->logPath = $options['logPath'];
$tempLogFile = $this->logPath."/".$this->id.".log"; $tempLogFile = $this->logPath."/".$this->id.".log";
} }
@ -134,27 +129,21 @@ class Logger
if ( !is_null($level = $this->getTargettedEnv('LOG_LEVEL_WEBLOG')) ) if ( !is_null($level = $this->getTargettedEnv('LOG_LEVEL_WEBLOG')) )
$tempWeblogLevel = $level; $tempWeblogLevel = $level;
if ( ZM_LOG_DEBUG ) if ( ZM_LOG_DEBUG ) {
{ foreach ( explode( '|', ZM_LOG_DEBUG_TARGET ) as $target ) {
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 ( $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 ); $tempLevel = $this->limit( ZM_LOG_DEBUG_LEVEL );
if ( ZM_LOG_DEBUG_FILE != "" ) if ( ZM_LOG_DEBUG_FILE != '' ) {
{
$tempLogFile = ZM_LOG_DEBUG_FILE; $tempLogFile = ZM_LOG_DEBUG_FILE;
$tempFileLevel = $tempLevel; $tempFileLevel = $tempLevel;
} }
} }
} }
} } // end foreach target
} } // end if DEBUG
$this->logFile( $tempLogFile ); $this->logFile( $tempLogFile );
$this->termLevel( $tempTermLevel ); $this->termLevel( $tempTermLevel );
$this->databaseLevel( $tempDatabaseLevel ); $this->databaseLevel( $tempDatabaseLevel );
$this->fileLevel( $tempFileLevel ); $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] ); 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() private function terminate() {
{ if ( $this->initialised ) {
if ( $this->initialised )
{
if ( $this->fileLevel > self::NOLOG ) if ( $this->fileLevel > self::NOLOG )
$this->closeFile(); $this->closeFile();
if ( $this->syslogLevel > self::NOLOG ) if ( $this->syslogLevel > self::NOLOG )
@ -180,8 +167,7 @@ class Logger
$this->initialised = false; $this->initialised = false;
} }
private function limit( $level ) private function limit( $level ) {
{
if ( $level > self::DEBUG ) if ( $level > self::DEBUG )
return( self::DEBUG ); return( self::DEBUG );
if ( $level < self::NOLOG ) if ( $level < self::NOLOG )
@ -189,8 +175,7 @@ class Logger
return( $level ); return( $level );
} }
private function getTargettedEnv( $name ) private function getTargettedEnv( $name ) {
{
$envName = $name."_".$this->id; $envName = $name."_".$this->id;
$value = getenv( $envName ); $value = getenv( $envName );
if ( $value === false && $this->id != $this->idRoot ) if ( $value === false && $this->id != $this->idRoot )
@ -200,10 +185,8 @@ class Logger
return( $value !== false ? $value : NULL ); return( $value !== false ? $value : NULL );
} }
public static function fetch( $initialise=true ) public static function fetch( $initialise=true ) {
{ if ( !isset(self::$instance) ) {
if ( !isset(self::$instance) )
{
$class = __CLASS__; $class = __CLASS__;
self::$instance = new $class; self::$instance = new $class;
if ( $initialise ) if ( $initialise )
@ -212,25 +195,20 @@ class Logger
return self::$instance; return self::$instance;
} }
public static function Debug( $string ) public static function Debug( $string ) {
{
Logger::fetch()->logPrint( Logger::DEBUG, $string ); Logger::fetch()->logPrint( Logger::DEBUG, $string );
} }
public function id( $id=NULL ) public function id( $id=NULL ) {
{ if ( isset($id) && $this->id != $id ) {
if ( isset($id) && $this->id != $id )
{
// Remove whitespace // Remove whitespace
$id = preg_replace( '/\S/', '', $id ); $id = preg_replace( '/\S/', '', $id );
// Replace non-alphanum with underscore // Replace non-alphanum with underscore
$id = preg_replace( '/[^a-zA-Z_]/', '_', $id ); $id = preg_replace( '/[^a-zA-Z_]/', '_', $id );
if ( $this->id != $id ) if ( $this->id != $id ) {
{
$this->id = $this->idRoot = $id; $this->id = $this->idRoot = $id;
if ( preg_match( '/^([^_]+)_(.+)$/', $id, $matches ) ) if ( preg_match( '/^([^_]+)_(.+)$/', $id, $matches ) ) {
{
$this->idRoot = $matches[1]; $this->idRoot = $matches[1];
$this->idArgs = $matches[2]; $this->idArgs = $matches[2];
} }
@ -239,10 +217,8 @@ class Logger
return( $this->id ); return( $this->id );
} }
public function level( $level ) public function level( $level ) {
{ if ( isset($level) ) {
if ( isset($level) )
{
$lastLevel = $this->level; $lastLevel = $this->level;
$this->level = $this->limit($level); $this->level = $this->limit($level);
$this->effectiveLevel = self::NOLOG; $this->effectiveLevel = self::NOLOG;
@ -258,15 +234,11 @@ class Logger
$this->effectiveLevel = $this->syslogLevel; $this->effectiveLevel = $this->syslogLevel;
if ( $this->effectiveLevel > $this->level ) if ( $this->effectiveLevel > $this->level )
$this->effectiveLevel = $this->level; $this->effectiveLevel = $this->level;
if ( !$this->hasTerm ) if ( !$this->hasTerm ) {
{ if ( $lastLevel < self::DEBUG && $this->level >= self::DEBUG ) {
if ( $lastLevel < self::DEBUG && $this->level >= self::DEBUG )
{
$this->savedErrorReporting = error_reporting( E_ALL ); $this->savedErrorReporting = error_reporting( E_ALL );
$this->savedDisplayErrors = ini_set( 'display_errors', true ); $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 ); error_reporting( $this->savedErrorReporting );
ini_set( 'display_errors', $this->savedDisplayErrors ); ini_set( 'display_errors', $this->savedDisplayErrors );
} }
@ -275,15 +247,12 @@ class Logger
return( $this->level ); return( $this->level );
} }
public function debugOn() public function debugOn() {
{
return( $this->effectiveLevel >= self::DEBUG ); return( $this->effectiveLevel >= self::DEBUG );
} }
public function termLevel( $termLevel ) public function termLevel( $termLevel ) {
{ if ( isset($termLevel) ) {
if ( isset($termLevel) )
{
$termLevel = $this->limit($termLevel); $termLevel = $this->limit($termLevel);
if ( $this->termLevel != $termLevel ) if ( $this->termLevel != $termLevel )
$this->termLevel = $termLevel; $this->termLevel = $termLevel;
@ -291,18 +260,13 @@ class Logger
return( $this->termLevel ); return( $this->termLevel );
} }
public function databaseLevel( $databaseLevel=NULL ) public function databaseLevel( $databaseLevel=NULL ) {
{ if ( !is_null($databaseLevel) ) {
if ( !is_null($databaseLevel) )
{
$databaseLevel = $this->limit($databaseLevel); $databaseLevel = $this->limit($databaseLevel);
if ( $this->databaseLevel != $databaseLevel ) if ( $this->databaseLevel != $databaseLevel ) {
{
$this->databaseLevel = $databaseLevel; $this->databaseLevel = $databaseLevel;
if ( $this->databaseLevel > self::NOLOG ) if ( $this->databaseLevel > self::NOLOG ) {
{ if ( (include_once 'database.php') === FALSE ) {
if ( (include_once 'database.php') === FALSE )
{
$this->databaseLevel = self::NOLOG; $this->databaseLevel = self::NOLOG;
Warning( "Unable to write log entries to DB, database.php not found" ); Warning( "Unable to write log entries to DB, database.php not found" );
} }
@ -312,13 +276,10 @@ class Logger
return( $this->databaseLevel ); return( $this->databaseLevel );
} }
public function fileLevel( $fileLevel ) public function fileLevel( $fileLevel ) {
{ if ( isset($fileLevel) ) {
if ( isset($fileLevel) )
{
$fileLevel = $this->limit($fileLevel); $fileLevel = $this->limit($fileLevel);
if ( $this->fileLevel != $fileLevel ) if ( $this->fileLevel != $fileLevel ) {
{
if ( $this->fileLevel > self::NOLOG ) if ( $this->fileLevel > self::NOLOG )
$this->closeFile(); $this->closeFile();
$this->fileLevel = $fileLevel; $this->fileLevel = $fileLevel;
@ -329,19 +290,13 @@ class Logger
return( $this->fileLevel ); return( $this->fileLevel );
} }
public function weblogLevel( $weblogLevel ) public function weblogLevel( $weblogLevel ) {
{ if ( isset($weblogLevel) ) {
if ( isset($weblogLevel) )
{
$weblogLevel = $this->limit($weblogLevel); $weblogLevel = $this->limit($weblogLevel);
if ( $this->weblogLevel != $weblogLevel ) if ( $this->weblogLevel != $weblogLevel ) {
{ if ( $weblogLevel > self::NOLOG && $this->weblogLevel <= self::NOLOG ) {
if ( $weblogLevel > self::NOLOG && $this->weblogLevel <= self::NOLOG )
{
$this->savedLogErrors = ini_set( 'log_errors', true ); $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 ); ini_set( 'log_errors', $this->savedLogErrors );
} }
$this->weblogLevel = $weblogLevel; $this->weblogLevel = $weblogLevel;
@ -350,13 +305,10 @@ class Logger
return( $this->weblogLevel ); return( $this->weblogLevel );
} }
public function syslogLevel( $syslogLevel ) public function syslogLevel( $syslogLevel ) {
{ if ( isset($syslogLevel) ) {
if ( isset($syslogLevel) )
{
$syslogLevel = $this->limit($syslogLevel); $syslogLevel = $this->limit($syslogLevel);
if ( $this->syslogLevel != $syslogLevel ) if ( $this->syslogLevel != $syslogLevel ) {
{
if ( $this->syslogLevel > self::NOLOG ) if ( $this->syslogLevel > self::NOLOG )
$this->closeSyslog(); $this->closeSyslog();
$this->syslogLevel = $syslogLevel; $this->syslogLevel = $syslogLevel;
@ -367,60 +319,48 @@ class Logger
return( $this->syslogLevel ); return( $this->syslogLevel );
} }
private function openSyslog() private function openSyslog() {
{
openlog( $this->id, LOG_PID|LOG_NDELAY, LOG_LOCAL1 ); openlog( $this->id, LOG_PID|LOG_NDELAY, LOG_LOCAL1 );
} }
private function closeSyslog() private function closeSyslog() {
{
closelog(); closelog();
} }
private function logFile( $logFile ) private function logFile( $logFile ) {
{
if ( preg_match( '/^(.+)\+$/', $logFile, $matches ) ) if ( preg_match( '/^(.+)\+$/', $logFile, $matches ) )
$this->logFile = $matches[1].'.'.getmypid(); $this->logFile = $matches[1].'.'.getmypid();
else else
$this->logFile = $logFile; $this->logFile = $logFile;
} }
private function openFile() private function openFile() {
{ if ( !$this->useErrorLog ) {
if ( !$this->useErrorLog ) if ( $this->logFd = fopen( $this->logFile, 'a+' ) ) {
{ if ( strnatcmp( phpversion(), '5.2.0' ) >= 0 ) {
if ( $this->logFd = fopen( $this->logFile, "a+" ) )
{
if ( strnatcmp( phpversion(), '5.2.0' ) >= 0 )
{
$error = error_get_last(); $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; $this->fileLevel = self::NOLOG;
} }
} }
} }
private function closeFile() private function closeFile() {
{
if ( $this->logFd ) if ( $this->logFd )
fclose( $this->logFd ); fclose( $this->logFd );
} }
public function logPrint( $level, $string, $file=NULL, $line=NULL ) public function logPrint( $level, $string, $file=NULL, $line=NULL ) {
{ if ( $level <= $this->effectiveLevel ) {
if ( $level <= $this->effectiveLevel )
{
$string = preg_replace( '/[\r\n]+$/', '', $string ); $string = preg_replace( '/[\r\n]+$/', '', $string );
$code = self::$codes[$level]; $code = self::$codes[$level];
$time = gettimeofday(); $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 ( is_null($file) ) {
{ if ( $this->useErrorLog || $this->databaseLevel > self::NOLOG ) {
if ( $this->useErrorLog || $this->databaseLevel > self::NOLOG )
{
$backTrace = debug_backtrace(); $backTrace = debug_backtrace();
$file = $backTrace[1]['file']; $file = $backTrace[1]['file'];
$line = $backTrace[1]['line']; $line = $backTrace[1]['line'];
@ -441,28 +381,24 @@ class Logger
if ( $this->hasTerm ) if ( $this->hasTerm )
print( $message."\n" ); print( $message."\n" );
else else
print( preg_replace( "/\n/", '<br/>', htmlspecialchars($message) )."<br/>" ); print( preg_replace( "/\n/", '<br/>', htmlspecialchars($message) ).'<br/>' );
if ( $level <= $this->fileLevel ) if ( $level <= $this->fileLevel )
if ( $this->useErrorLog ) if ( $this->useErrorLog ) {
{ if ( !error_log( $message."\n", 3, $this->logFile ) ) {
if ( !error_log( $message."\n", 3, $this->logFile ) ) if ( strnatcmp( phpversion(), '5.2.0' ) >= 0 ) {
{
if ( strnatcmp( phpversion(), '5.2.0' ) >= 0 )
{
$error = error_get_last(); $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" ); fprintf( $this->logFd, $message."\n" );
}
$message = $code." [".$string."]"; $message = $code.' ['.$string.']';
if ( $level <= $this->syslogLevel ) if ( $level <= $this->syslogLevel )
syslog( self::$syslogPriorities[$level], $message ); syslog( self::$syslogPriorities[$level], $message );
if ( $level <= $this->databaseLevel ) if ( $level <= $this->databaseLevel ) {
{
try { try {
global $dbConn; global $dbConn;
$sql = "INSERT INTO Logs ( TimeKey, Component, Pid, Level, Code, Message, File, Line ) values ( ?, ?, ?, ?, ?, ?, ?, ? )"; $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 // This has to be last as trigger_error can be fatal
if ( $level <= $this->weblogLevel ) if ( $level <= $this->weblogLevel ) {
{
if ( $this->useErrorLog ) if ( $this->useErrorLog )
error_log( $message, 0 ); error_log( $message, 0 );
else else
@ -485,68 +420,55 @@ class Logger
} }
}; };
function logInit( $options=array() ) function logInit( $options=array() ) {
{
$logger = Logger::fetch(); $logger = Logger::fetch();
$logger->initialise( $options ); $logger->initialise( $options );
set_error_handler( 'ErrorHandler' ); set_error_handler( 'ErrorHandler' );
} }
function logToDatabase( $level=NULL ) function logToDatabase( $level=NULL ) {
{
return( Logger::fetch()->databaseLevel( $level ) ); return( Logger::fetch()->databaseLevel( $level ) );
} }
function Mark( $level=Logger::DEBUG, $tag="Mark" ) function Mark( $level=Logger::DEBUG, $tag='Mark' ) {
{
Logger::fetch()->logPrint( $level, $tag ); Logger::fetch()->logPrint( $level, $tag );
} }
function Dump( &$var, $label="VAR" ) function Dump( &$var, $label='VAR' ) {
{
ob_start(); ob_start();
print( $label." => " ); print( $label.' => ' );
print_r( $var ); print_r( $var );
Logger::fetch()->logPrint( Logger::DEBUG, ob_get_clean() ); Logger::fetch()->logPrint( Logger::DEBUG, ob_get_clean() );
} }
function Info( $string ) function Info( $string ) {
{
Logger::fetch()->logPrint( Logger::INFO, $string ); Logger::fetch()->logPrint( Logger::INFO, $string );
} }
function Warning( $string ) function Warning( $string ) {
{
Logger::fetch()->logPrint( Logger::WARNING, $string ); Logger::fetch()->logPrint( Logger::WARNING, $string );
} }
function Error( $string ) function Error( $string ) {
{
Logger::fetch()->logPrint( Logger::ERROR, $string ); Logger::fetch()->logPrint( Logger::ERROR, $string );
} }
function Fatal( $string ) function Fatal( $string ) {
{
Logger::fetch()->logPrint( Logger::FATAL, $string ); Logger::fetch()->logPrint( Logger::FATAL, $string );
die( htmlentities($string) ); die( htmlentities($string) );
} }
function Panic( $string ) function Panic( $string ) {
{ if ( true ) {
if ( true )
{
// Use builtin function // Use builtin function
ob_start(); ob_start();
debug_print_backtrace(); debug_print_backtrace();
$backtrace = "\n".ob_get_clean(); $backtrace = "\n".ob_get_clean();
} } else {
else
{
// Roll your own // Roll your own
$backtrace = ''; $backtrace = '';
$frames = debug_backtrace(); $frames = debug_backtrace();
for ( $i = 0; $i < count($frames); $i++ ) for ( $i = 0; $i < count($frames); $i++ ) {
{
$frame = $frames[$i]; $frame = $frames[$i];
$backtrace .= sprintf( "\n#%d %s() at %s/%d", $i, $frame['function'], $frame['file'], $frame['line'] ); $backtrace .= sprintf( "\n#%d %s() at %s/%d", $i, $frame['function'], $frame['file'], $frame['line'] );
} }
@ -555,16 +477,13 @@ function Panic( $string )
die( $string ); die( $string );
} }
function ErrorHandler( $error, $string, $file, $line ) function ErrorHandler( $error, $string, $file, $line ) {
{ if ( ! (error_reporting() & $error) ) {
if ( ! (error_reporting() & $error) )
{
// This error code is not included in error_reporting // This error code is not included in error_reporting
return( false ); return( false );
} }
switch ( $error ) switch ( $error ) {
{
case E_USER_ERROR: case E_USER_ERROR:
Logger::fetch()->logPrint( Logger::FATAL, $string, $file, $line ); Logger::fetch()->logPrint( Logger::FATAL, $string, $file, $line );
break; break;

View File

@ -34,7 +34,7 @@ if ( version_compare( phpversion(), '4.1.0', '<') ) {
} }
// Useful debugging lines for mobile devices // Useful debugging lines for mobile devices
if ( false ) { if ( true ) {
ob_start(); ob_start();
phpinfo( INFO_VARIABLES ); phpinfo( INFO_VARIABLES );
$fp = fopen( '/tmp/env.html', 'w' ); $fp = fopen( '/tmp/env.html', 'w' );
@ -113,7 +113,7 @@ if ( !file_exists( ZM_SKIN_PATH ) )
$skinBase[] = $skin; $skinBase[] = $skin;
$currentCookieParams = session_get_cookie_params(); $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( session_set_cookie_params(
$currentCookieParams['lifetime'], $currentCookieParams['lifetime'],
$currentCookieParams['path'], $currentCookieParams['path'],
@ -175,9 +175,7 @@ foreach ( getSkinIncludes( 'skin.php' ) as $includeFile )
if ( ZM_OPT_USE_AUTH && ZM_AUTH_HASH_LOGINS ) { if ( ZM_OPT_USE_AUTH && ZM_AUTH_HASH_LOGINS ) {
if ( empty($user) && ! empty($_REQUEST['auth']) ) { if ( empty($user) && ! empty($_REQUEST['auth']) ) {
Logger::Debug("Getting user from auth hash");
if ( $authUser = getAuthUser( $_REQUEST['auth'] ) ) { if ( $authUser = getAuthUser( $_REQUEST['auth'] ) ) {
Logger::Debug("Success Getting user from auth hash");
userLogin( $authUser['Username'], $authUser['Password'], true ); userLogin( $authUser['Username'], $authUser['Password'], true );
} }
} else if ( ! empty($user) ) { } else if ( ! empty($user) ) {

View File

@ -302,6 +302,7 @@ $SLANG = array(
'DuplicateMonitorName' => 'Duplicate Monitor Name', 'DuplicateMonitorName' => 'Duplicate Monitor Name',
'Duration' => 'Duration', 'Duration' => 'Duration',
'Edit' => 'Edit', 'Edit' => 'Edit',
'EditLayout' => 'Edit Layout',
'Email' => 'Email', 'Email' => 'Email',
'EnableAlarms' => 'Enable Alarms', 'EnableAlarms' => 'Enable Alarms',
'Enabled' => 'Enabled', 'Enabled' => 'Enabled',
@ -556,6 +557,8 @@ $SLANG = array(
'OpNe' => 'not equal to', 'OpNe' => 'not equal to',
'OpNotIn' => 'not in set', 'OpNotIn' => 'not in set',
'OpNotMatches' => 'does not match', 'OpNotMatches' => 'does not match',
'OpIs' => 'is',
'OpIsNot' => 'is not',
'OptionalEncoderParam' => 'Optional Encoder Parameters', 'OptionalEncoderParam' => 'Optional Encoder Parameters',
'OptionHelp' => 'Option Help', '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.', '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.',

View File

@ -6,6 +6,15 @@
width: 99%; width: 99%;
} }
#monitors:after {
content: ".";
display: block;
height: 0;
font-size: 0;
clear: both;
visibility: hidden;
}
#monitors .monitor { #monitors .monitor {
min-width: 180px; min-width: 180px;
margin: 0; margin: 0;

View File

@ -48,8 +48,10 @@ function xhtmlHeaders( $file, $title ) {
<title><?php echo ZM_WEB_TITLE_PREFIX ?> - <?php echo validHtmlStr($title) ?></title> <title><?php echo ZM_WEB_TITLE_PREFIX ?> - <?php echo validHtmlStr($title) ?></title>
<?php <?php
if ( file_exists( "skins/$skin/css/$css/graphics/favicon.ico" ) ) { 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 "
echo "<link rel=\"shortcut icon\" href=\"skins/$skin/css/$css/graphics/favicon.ico\"/>\n"; <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 { } else {
echo ' echo '
<link rel="icon" type="image/ico" href="graphics/favicon.ico"/> <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/reset.css" type="text/css"/>
<link rel="stylesheet" href="css/overlay.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="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 <?php
if ( $viewCssFile ) { 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 <?php
} }
if ( $viewCssPhpFile ) { if ( $viewCssPhpFile ) {
@ -138,18 +140,18 @@ if ( file_exists( "skins/$skin/css/$css/graphics/favicon.ico" ) ) {
} }
if ( $cssJsFile ) { if ( $cssJsFile ) {
?> ?>
<script type="text/javascript" src="<?php echo $cssJsFile ?>"></script> <script type="text/javascript" src="<?php echo cache_bust($cssJsFile) ?>"></script>
<?php <?php
} else { } else {
?> ?>
<script type="text/javascript" src="skins/classic/js/classic.js"></script> <script type="text/javascript" src="skins/classic/js/classic.js"></script>
<?php } ?> <?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> <script type="text/javascript" src="js/logger.js"></script>
<?php <?php
if ( $viewJsFile ) { if ( $viewJsFile ) {
?> ?>
<script type="text/javascript" src="<?php echo $viewJsFile ?>"></script> <script type="text/javascript" src="<?php echo cache_bust($viewJsFile) ?>"></script>
<?php <?php
} }
?> ?>

View File

@ -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>

View File

@ -0,0 +1,14 @@
<input type="hidden" name="newMonitor[Method]" value="<?php echo validHtmlStr($monitor->Method()) ?>"/>
<tr><td><?php echo translate('HostName') ?></td><td><input type="text" name="newMonitor[Host]" value="<?php echo validHtmlStr($monitor->Host()) ?>" size="36"/></td></tr>
<tr><td><?php echo translate('Port') ?></td><td><input type="number" name="newMonitor[Port]" value="<?php echo validHtmlStr($monitor->Port()) ?>" size="6"/></td></tr>
<tr><td><?php echo translate('Path') ?></td><td><input type="text" name="newMonitor[Path]" value="<?php echo validHtmlStr($monitor->Path()) ?>" size="36"/></td></tr>
<input type="hidden" name="newMonitor[User]" value="<?php echo validHtmlStr($monitor->User()) ?>"/>
<input type="hidden" name="newMonitor[Pass]" value="<?php echo validHtmlStr($monitor->Pass()) ?>"/>
<input type="hidden" name="newMonitor[Options]" value="<?php echo validHtmlStr($monitor->Options()) ?>"/>
<tr><td><?php echo translate('TargetColorspace') ?></td><td><select name="newMonitor[Colours]"><?php foreach ( $Colours as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $monitor->Colours()) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
<tr><td><?php echo translate('CaptureWidth') ?> (<?php echo translate('Pixels') ?>)</td><td><input type="number" name="newMonitor[Width]" value="<?php echo validHtmlStr($monitor->Width()) ?>" size="4" onkeyup="updateMonitorDimensions(this);"/></td></tr>
<tr><td><?php echo translate('CaptureHeight') ?> (<?php echo translate('Pixels') ?>)</td><td><input type="number" name="newMonitor[Height]" value="<?php echo validHtmlStr($monitor->Height()) ?>" size="4" onkeyup="updateMonitorDimensions(this);"/></td></tr>
<tr><td><?php echo translate('PreserveAspect') ?></td><td><input type="checkbox" name="preserveAspectRatio" value="1"/></td></tr>
<tr><td><?php echo translate('Orientation') ?></td><td><?php echo htmlselect( 'newMonitor[Orientation]', $orientations, $monitor->Orientation() );?></td></tr>
<input type="hidden" name="newMonitor[Deinterlacing]" value="<?php echo validHtmlStr($monitor->Deinterlacing()) ?>"/>
<input type="hidden" name="newMonitor[RTSPDescribe]" value="<?php echo validHtmlStr($monitor->RTSPDescribe()) ?>"/>

View File

@ -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() ?>

View File

@ -18,36 +18,6 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // 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 ) if ( $running == null )
$running = daemonCheck(); $running = daemonCheck();
@ -120,6 +90,46 @@ $eventCounts = array(
$navbar = getNavBarHTML(); $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);
}
$cycleWidth = $maxWidth;
$cycleHeight = $maxHeight;
noCacheHeaders(); noCacheHeaders();
@ -137,139 +147,7 @@ xhtmlHeaders( __FILE__, translate('Console') );
<input type="hidden" name="action" value=""/> <input type="hidden" name="action" value=""/>
<?php echo $navbar ?> <?php echo $navbar ?>
<div class="controlHeader"> <?php echo $filterbar ?>
<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>
<div class="container-fluid"> <div class="container-fluid">
<table class="table table-striped table-hover table-condensed" id="consoleTable"> <table class="table table-striped table-hover table-condensed" id="consoleTable">

View File

@ -104,6 +104,8 @@ $opTypes = array(
'!~' => translate('OpNotMatches'), '!~' => translate('OpNotMatches'),
'=[]' => translate('OpIn'), '=[]' => translate('OpIn'),
'![]' => translate('OpNotIn'), '![]' => translate('OpNotIn'),
'IS' => translate('OpIs'),
'IS NOT' => translate('OpIsNot'),
); );
$archiveTypes = array( $archiveTypes = array(

View File

@ -87,9 +87,11 @@ function get_children($Group) {
} }
$kids = get_children($newGroup); $kids = get_children($newGroup);
if ( $newGroup->Id() )
$kids[] = $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'); $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']; $options[$option['Id']] = $option['Name'];
} }
echo htmlSelect( 'newGroup[ParentId]', $options, $newGroup->ParentId(), array('onchange'=>'configureButtons(this);' )); echo htmlSelect( 'newGroup[ParentId]', $options, $newGroup->ParentId(), array('onchange'=>'configureButtons(this);' ));

View File

@ -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 );
}
});
}

View File

@ -97,7 +97,7 @@ function validateForm( form ) {
errors[errors.length] = "<?php echo translate('BadImageBufferCount') ?>"; errors[errors.length] = "<?php echo translate('BadImageBufferCount') ?>";
if ( !form.elements['newMonitor[WarmupCount]'].value || !(parseInt(form.elements['newMonitor[WarmupCount]'].value) >= 0 ) ) if ( !form.elements['newMonitor[WarmupCount]'].value || !(parseInt(form.elements['newMonitor[WarmupCount]'].value) >= 0 ) )
errors[errors.length] = "<?php echo translate('BadWarmupCount') ?>"; errors[errors.length] = "<?php echo translate('BadWarmupCount') ?>";
if ( !form.elements['newMonitor[PreEventCount]'].value || !(parseInt(form.elements['newMonitor[PreEventCount]'].value) > 0 ) || (parseInt(form.elements['newMonitor[PreEventCount]'].value) > parseInt(form.elements['newMonitor[ImageBufferCount]'].value)) ) if ( !form.elements['newMonitor[PreEventCount]'].value || !(parseInt(form.elements['newMonitor[PreEventCount]'].value) >= 0 ) || (parseInt(form.elements['newMonitor[PreEventCount]'].value) > parseInt(form.elements['newMonitor[ImageBufferCount]'].value)) )
errors[errors.length] = "<?php echo translate('BadPreEventCount') ?>"; errors[errors.length] = "<?php echo translate('BadPreEventCount') ?>";
if ( !form.elements['newMonitor[PostEventCount]'].value || !(parseInt(form.elements['newMonitor[PostEventCount]'].value) >= 0 ) ) if ( !form.elements['newMonitor[PostEventCount]'].value || !(parseInt(form.elements['newMonitor[PostEventCount]'].value) >= 0 ) )
errors[errors.length] = "<?php echo translate('BadPostEventCount') ?>"; errors[errors.length] = "<?php echo translate('BadPostEventCount') ?>";

View File

@ -7,11 +7,10 @@ function Monitor( monitorData ) {
this.status = null; this.status = null;
this.alarmState = STATE_IDLE; this.alarmState = STATE_IDLE;
this.lastAlarmState = 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 ) if ( auth_hash )
this.streamCmdParms += '&auth='+auth_hash; this.streamCmdParms += '&auth='+auth_hash;
else
console.log("No auth_hash");
this.streamCmdTimer = null; this.streamCmdTimer = null;
this.start = function( delay ) { this.start = function( delay ) {
@ -35,6 +34,7 @@ function Monitor( monitorData ) {
this.streamCmdTimer = clearTimeout( 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' ) { if ( respObj.result == 'Ok' ) {
this.status = respObj.status; this.status = respObj.status;
this.alarmState = this.status.state; this.alarmState = this.status.state;
@ -83,42 +83,100 @@ function Monitor( monitorData ) {
// Try to reload the image stream. // Try to reload the image stream.
if ( stream ) if ( stream )
stream.src = stream.src.replace( /auth=\w+/i, 'auth='+this.status.auth ); 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 { } else {
console.error( respObj.message ); console.error( respObj.message );
// Try to reload the image stream. // Try to reload the image stream.
if ( stream ) if ( stream ) {
console.log('Reloading stream: ' + stream.src );
stream.src = stream.src.replace(/rand=\d+/i, 'rand='+Math.floor((Math.random() * 1000000) )); stream.src = stream.src.replace(/rand=\d+/i, 'rand='+Math.floor((Math.random() * 1000000) ));
} else {
console.log( 'No stream to reload?' );
} }
} // end if Ok or not
var streamCmdTimeout = statusRefreshTimeout; var streamCmdTimeout = statusRefreshTimeout;
if ( this.alarmState == STATE_ALARM || this.alarmState == STATE_ALERT ) // 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.
streamCmdTimeout = streamCmdTimeout/5; //if ( this.alarmState == STATE_ALARM || this.alarmState == STATE_ALERT ) {
//streamCmdTimeout = streamCmdTimeout/5;
//}
this.streamCmdTimer = this.streamCmdQuery.delay( streamCmdTimeout, this ); this.streamCmdTimer = this.streamCmdQuery.delay( streamCmdTimeout, this );
this.lastAlarmState = this.alarmState; this.lastAlarmState = this.alarmState;
}; };
this.streamCmdQuery = function( resent ) { this.streamCmdQuery = function( resent ) {
//if ( resent ) if ( resent )
//console.log( this.connKey+": Resending" ); console.log( this.connKey+": Resending" );
//this.streamCmdReq.cancel(); //this.streamCmdReq.cancel();
this.streamCmdReq.send( this.streamCmdParms+"&command="+CMD_QUERY ); 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 );
};
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 ); requestQueue.addRequest( "cmdReq"+this.id, this.streamCmdReq );
} }
function selectLayout( element ) { function selectLayout( element ) {
layout = $(element).get('value') layout = $j(element).val();
var cssFile = skinPath+'/css/'+Cookie.read('zmCSS')+'/views/'+layout;
if ( $('dynamicStyles') ) if ( layout_id = parseInt(layout) ) {
$('dynamicStyles').destroy(); layout = layouts[layout];
new Asset.css( cssFile, { id: 'dynamicStyles' } ); console.log(layout);
Cookie.write( 'zmMontageLayout', layout, { duration: 10*365 } );
if ( layout != 'montage_freeform.css' ) { 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 } ); Cookie.write( 'zmMontageScale', '', { duration: 10*365 } );
$('scale').set('value', '' ); $('scale').set('value', '' );
$('width').set('value', ''); $('width').set('value', '');
@ -152,6 +210,17 @@ function changeSize() {
for ( var x = 0; x < monitors.length; x++ ) { for ( var x = 0; x < monitors.length; x++ ) {
var monitor = monitors[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*/ /*Stream could be an applet so can't use moo tools*/
var streamImg = $( 'liveStream'+monitor.id ); var streamImg = $( 'liveStream'+monitor.id );
if ( streamImg ) { if ( streamImg ) {
@ -181,13 +250,32 @@ function changeSize() {
function changeScale() { function changeScale() {
var scale = $('scale').get('value'); 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++ ) { for ( var x = 0; x < monitors.length; x++ ) {
var monitor = monitors[x]; var monitor = monitors[x];
var newWidth = ( monitorData[x].width * scale ) / SCALE_BASE; var newWidth = ( monitorData[x].width * scale ) / SCALE_BASE;
var newHeight = ( monitorData[x].height * 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*/ /*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 ) {
if ( streamImg.nodeName == 'IMG' ) { if ( streamImg.nodeName == 'IMG' ) {
var src = streamImg.src; var src = streamImg.src;
@ -208,22 +296,72 @@ function changeScale() {
zonesSVG.style.height = newHeight + "px"; zonesSVG.style.height = newHeight + "px";
} }
} }
$('width').set('value', ''); }
$('height').set('value', '');
Cookie.write( 'zmMontageScale', scale, { duration: 10*365 } ); function toGrid(value) {
Cookie.write( 'zmMontageWidth', '', { duration: 10*365 } ); return Math.round(value / 80) * 80;
Cookie.write( 'zmMontageHeight', '', { duration: 10*365 } ); }
// 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(); var monitors = new Array();
function initPage() { function initPage() {
for ( var i = 0; i < monitorData.length; i++ ) { for ( var i = 0; i < monitorData.length; i++ ) {
monitors[i] = new Monitor(monitorData[i]); monitors[i] = new Monitor(monitorData[i]);
var delay = Math.round( (Math.random()+0.5)*statusRefreshTimeout ); var delay = Math.round( (Math.random()+0.75)*statusRefreshTimeout );
monitors[i].start(delay); monitors[i].start(delay);
} }
selectLayout($('layout')); selectLayout('#zmMontageLayout');
} }
// Kick everything off // Kick everything off
window.addEvent( 'domready', initPage ); window.addEvent( 'domready', initPage );

View File

@ -35,8 +35,18 @@ monitorData[monitorData.length] = {
'connKey': <?php echo $monitor->connKey() ?>, 'connKey': <?php echo $monitor->connKey() ?>,
'width': <?php echo $monitor->Width() ?>, 'width': <?php echo $monitor->Width() ?>,
'height':<?php echo $monitor->Height() ?>, '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 <?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
?> ?>

View File

@ -665,7 +665,7 @@ if ( ZM_HAS_V4L && ($tab != 'misc' || $monitor->Type()!= 'Local') ) {
<?php <?php
} }
?> ?>
<table id="contentTable" class="major" cellspacing="0"> <table id="contentTable" class="major">
<tbody> <tbody>
<?php <?php
switch ( $tab ) { switch ( $tab ) {

View File

@ -23,6 +23,8 @@ if ( !canView('Stream') ) {
return; return;
} }
require_once('includes/MontageLayout.php');
$showControl = false; $showControl = false;
$showZones = false; $showZones = false;
if ( isset( $_REQUEST['showZones'] ) ) { if ( isset( $_REQUEST['showZones'] ) ) {
@ -57,58 +59,52 @@ if ( isset( $_REQUEST['scale'] ) ) {
if ( ! $scale ) if ( ! $scale )
$scale = 100; $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'), session_start();
'montage_2wide.css' => translate('Mtg2widgrd'),
'montage_3wide.css' => translate('Mtg3widgrd'),
'montage_4wide.css' => translate('Mtg4widgrd'),
'montage_3wide50enlarge.css' => translate('Mtg3widgrx'),
);
$layout = ''; $layout = '';
if ( isset($_COOKIE['zmMontageLayout']) ) if ( isset($_COOKIE['zmMontageLayout']) ) {
$layout = $_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(); $options = array();
if ( isset($_COOKIE['zmMontageWidth']) and $_COOKIE['zmMontageWidth'] ) if ( isset($_COOKIE['zmMontageWidth']) and $_COOKIE['zmMontageWidth'] ) {
$options['width'] = $_COOKIE['zmMontageWidth']; $_SESSION['zmMontageWidth'] = $options['width'] = $_COOKIE['zmMontageWidth'];
else } elseif ( isset($_SESSION['zmMontageWidth']) and $_SESSION['zmMontageWidth'] ) {
$options['width'] = $_SESSION['zmMontageWidth'];
} else
$options['width'] = ''; $options['width'] = '';
if ( isset($_COOKIE['zmMontageHeight']) and $_COOKIE['zmMontageHeight'] ) 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 else
$options['height'] = ''; $options['height'] = '';
session_write_close();
if ( $scale ) if ( $scale )
$options['scale'] = $scale; $options['scale'] = $scale;
ob_start(); ob_start();
# This will end up with the group_id of the deepest selection include('_monitor_filters.php');
$group_id = Group::get_group_dropdowns(); $filterbar = ob_get_contents();
$group_dropdowns = ob_get_contents();
ob_end_clean(); 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 = array();
$monitors_dropdown = array( '' => 'All' ); foreach( $displayMonitors as &$row ) {
$sql = "SELECT * FROM Monitors WHERE Function != 'None'"; if ( $row['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'] ) ) {
continue; continue;
}
$row['Scale'] = $scale; $row['Scale'] = $scale;
$row['PopupScale'] = reScale( SCALE_BASE, $row['DefaultScale'], ZM_WEB_DEFAULT_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'] ) if ( ZM_OPT_CONTROL && $row['ControlId'] && $row['Controllable'] )
$showControl = true; $showControl = true;
$row['connKey'] = generateConnKey(); $row['connKey'] = generateConnKey();
$Monitor = $monitors[] = new Monitor( $row );
$monitors_dropdown[$Monitor->Id()] = $Monitor->Name();
if ( ! isset( $widths[$row['Width']] ) ) { if ( ! isset( $widths[$row['Width']] ) ) {
$widths[$row['Width']] = $row['Width']; $widths[$row['Width']] = $row['Width'];
} }
if ( ! isset( $heights[$row['Height']] ) ) { if ( ! isset( $heights[$row['Height']] ) ) {
$heights[$row['Height']] = $row['Height']; $heights[$row['Height']] = $row['Height'];
} }
$monitors[] = new Monitor( $row );
} # end foreach Monitor } # end foreach Monitor
xhtmlHeaders(__FILE__, translate('Montage') ); xhtmlHeaders(__FILE__, translate('Montage') );
@ -141,26 +136,36 @@ if ( $showControl ) {
} }
if ( $showZones ) { 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 <?php
} else { } 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 <?php
} }
?> ?>
</div> </div>
<div id="headerControl"> <?php echo $filterbar ?>
<span id="groupControl"><label><?php echo translate('Group') ?>:</label> <div id="sizeControl">
<?php echo $group_dropdowns; ?> <form action="index.php?view=montage" method="post">
</span> <input type="hidden" name="object" value="MontageLayout"/>
<span id="monitorControl"><label><?php echo translate('Monitor') ?>:</label> <input type="hidden" name="action" value="Save"/>
<?php echo htmlSelect( 'monitor_id', $monitors_dropdown, $monitor_id, array('onchange'=>'changeMonitor(this);') ); ?>
</span>
<span id="widthControl"><label><?php echo translate('Width') ?>:</label><?php echo htmlSelect( 'width', $widths, $options['width'], 'changeSize(this);' ); ?></span> <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="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="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> </div>
<div id="content"> <div id="content">
@ -169,7 +174,7 @@ if ( $showZones ) {
foreach ( $monitors as $monitor ) { foreach ( $monitors as $monitor ) {
$connkey = $monitor->connKey(); // Minor hack $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="monitor<?php echo $monitor->Id() ?>" class="monitor idle">
<div id="imageFeed<?php echo $monitor->Id() ?>" class="imageFeed" onclick="createPopup( '?view=watch&amp;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() ); ?> );"> <div id="imageFeed<?php echo $monitor->Id() ?>" class="imageFeed" onclick="createPopup( '?view=watch&amp;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 <?php
@ -210,16 +215,13 @@ foreach ( $monitors as $monitor ) {
$row['Coords'] = pointsToCoords( $row['Points'] ); $row['Coords'] = pointsToCoords( $row['Points'] );
$row['AreaCoords'] = preg_replace( '/\s+/', ',', $row['Coords'] ); $row['AreaCoords'] = preg_replace( '/\s+/', ',', $row['Coords'] );
$zones[] = $row; $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;"> <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 <?php
foreach( array_reverse($zones) as $zone ) { foreach( array_reverse($zones) as $zone ) {
?> echo '<polygon points="'. $zone['AreaCoords'] .'" class="'. $zone['Type'].'" />';
<polygon points="<?php echo $zone['AreaCoords'] ?>" class="<?php echo $zone['Type']?>" />
<?php
} // end foreach zone } // end foreach zone
?> ?>
Sorry, your browser does not support inline SVG Sorry, your browser does not support inline SVG

View File

@ -55,62 +55,10 @@ if ( !canView( 'Events' ) ) {
} }
ob_start(); ob_start();
# This will end up with the group_id of the deepest selection include('_monitor_filters.php');
$group_id = Group::get_group_dropdowns(); $filter_bar = ob_get_contents();
$group_dropdowns = ob_get_contents();
ob_end_clean(); 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 // 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) // 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. // 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'] ) ) { if ( ! empty( $user['MonitorIds'] ) ) {
$eventsSql .= ' AND M.Id IN ('.$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'].')'; $frameSql .= ' AND E.MonitorId IN ('.$user['MonitorIds'].')';
} }
if ( $monitor_id ) { if ( $monitor_id ) {
$conditions[] = 'Id=?';
$values[] = $monitor_id;
$eventsSql .= ' AND M.Id='.$monitor_id; $eventsSql .= ' AND M.Id='.$monitor_id;
$frameSql .= ' AND E.MonitorId='.$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 // 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']) ) { if ( !isset($_REQUEST['minTime']) && !isset($_REQUEST['maxTime']) ) {
$time = time(); $time = time();
$maxTime = strftime("%FT%T",$time); $maxTime = strftime("%FT%T",$time);
@ -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'; $frameSql .= ' GROUP BY E.Id, E.MonitorId, F.TimeStamp, F.Delta ORDER BY E.MonitorId, F.TimeStamp ASC';
$monitors = array(); $monitors = array();
$monitorsSql = 'SELECT * FROM Monitors' . ( count($conditions) ? ' WHERE ' . implode(' AND ', $conditions ) : '' ).' ORDER BY Sequence ASC'; foreach( $displayMonitors as &$row ) {
foreach( dbFetchAll( $monitorsSql, null, $values ) as $row ) { if ( $row['Function'] == 'None' )
continue;
$Monitor = new Monitor( $row ); $Monitor = new Monitor( $row );
$monitors[] = $Monitor; $monitors[] = $Monitor;
} }
@ -243,32 +184,7 @@ xhtmlHeaders(__FILE__, translate('MontageReview') );
<form action="<?php echo $_SERVER['PHP_SELF'] ?>" method="get"> <form action="<?php echo $_SERVER['PHP_SELF'] ?>" method="get">
<input type="hidden" name="view" value="montagereview"/> <input type="hidden" name="view" value="montagereview"/>
<div id="header"> <div id="header">
<div id="headerControl"> <?php echo $filter_bar ?>
<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
}
?>
<div id="DateTimeDiv"> <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="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);"> <input type="datetime-local" name="maxTime" id="maxTime" value="<?php echo preg_replace('/ /', 'T', $maxTime ) ?>" onchange="changeDateTime(this);">

View File

@ -25,6 +25,11 @@ if ( !canView( 'Stream' ) ) {
return; return;
} }
if ( ! isset($_REQUEST['mid']) ) {
$view = 'error';
return;
}
// This is for input sanitation // This is for input sanitation
$mid = intval( $_REQUEST['mid'] ); $mid = intval( $_REQUEST['mid'] );
if ( ! visibleMonitor( $mid ) ) { if ( ! visibleMonitor( $mid ) ) {