Merge branch 'master' into storageareas
This commit is contained in:
commit
451714a403
|
@ -1,6 +1,8 @@
|
|||
language: cpp
|
||||
sudo: required
|
||||
dist: trusty
|
||||
git:
|
||||
depth: 9999999
|
||||
notifications:
|
||||
irc: chat.freenode.net#zoneminder-dev
|
||||
branches:
|
||||
|
@ -20,6 +22,7 @@ addons:
|
|||
- git
|
||||
- curl
|
||||
- sshfs
|
||||
- sed
|
||||
env:
|
||||
matrix:
|
||||
- OS=el DIST=6
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
zoneminder (1.28.1-1) unstable; urgency=low
|
||||
|
||||
This version is no longer automatically initialize or upgrade database.
|
||||
See README.Debian for details.
|
||||
|
||||
Changed installation paths (please correct your web server configuration):
|
||||
/usr/share/zoneminder --> /usr/share/zoneminder/www
|
||||
/usr/lib/cgi-bin --> /usr/lib/zoneminder/cgi-bin
|
||||
|
||||
-- Dmitry Smirnov <onlyjob@debian.org> Tue, 31 Mar 2015 15:12:17 +1100
|
|
@ -1,5 +1,8 @@
|
|||
<<<<<<< HEAD
|
||||
zoneminder (1.31.0-trusty) trusty; urgency=medium
|
||||
|
||||
* placeholder
|
||||
|
||||
-- Isaac Connor <iconnor@connortechnology.com> Fri, 13 May 2016 09:45:49 -0400
|
||||
=======
|
||||
>>>>>>> master
|
||||
|
|
|
@ -1 +1 @@
|
|||
3.0 (native)
|
||||
3.0 (quilt)
|
||||
|
|
|
@ -1600,7 +1600,7 @@ our @options = (
|
|||
this overhead is fairly small but may be noticeable on IO-constrained
|
||||
systems.
|
||||
`,
|
||||
type => $types{string},
|
||||
type => $types{boolean},
|
||||
category => 'web',
|
||||
},
|
||||
{
|
||||
|
|
|
@ -223,9 +223,7 @@ sub GenerateVideo {
|
|||
|
||||
my $status = $? >> 8;
|
||||
if ( $status ) {
|
||||
Error( "Unable to generate video, check "
|
||||
.$event_path."/ffmpeg.log for details"
|
||||
);
|
||||
Error( "Unable to generate video, check $event_path/ffmpeg.log for details");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -271,7 +269,6 @@ sub delete {
|
|||
}
|
||||
} # end sub delete
|
||||
|
||||
|
||||
sub delete_files {
|
||||
|
||||
my $Storage = new ZoneMinder::Storage( $_[0]{StorageId} );
|
||||
|
@ -353,49 +350,26 @@ sub age {
|
|||
|
||||
1;
|
||||
__END__
|
||||
# Below is stub documentation for your module. You'd better edit it!
|
||||
|
||||
=head1 NAME
|
||||
|
||||
ZoneMinder::Database - Perl extension for blah blah blah
|
||||
ZoneMinder::Event - Perl Class for events
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use ZoneMinder::Event;
|
||||
blah blah blah
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Stub documentation for ZoneMinder, created by h2xs. It looks like the
|
||||
author of the extension was negligent enough to leave the stub
|
||||
unedited.
|
||||
|
||||
Blah blah blah.
|
||||
|
||||
=head2 EXPORT
|
||||
|
||||
None by default.
|
||||
|
||||
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
Mention other useful documentation such as the documentation of
|
||||
related modules or operating system documentation (such as man pages
|
||||
in UNIX), or any relevant external documentation such as RFCs or
|
||||
standards.
|
||||
|
||||
If you have a mailing list set up for your module, mention it here.
|
||||
|
||||
If you have a web site set up for your module, mention it here.
|
||||
The Event class has everything you need to deal with events from Perl.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Philip Coombes, E<lt>philip.coombes@zoneminder.comE<gt>
|
||||
Isaac Connor, E<lt>isaac@zoneminder.comE<gt>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
Copyright (C) 2001-2008 Philip Coombes
|
||||
Copyright (C) 2001-2017 ZoneMinder LLC
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the same terms as Perl itself, either Perl version 5.8.3 or,
|
||||
|
|
|
@ -41,7 +41,7 @@ our @ISA = qw(Exporter ZoneMinder::Base);
|
|||
# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
|
||||
# will save memory.
|
||||
our %EXPORT_TAGS = (
|
||||
'constants' => [ qw(
|
||||
constants => [ qw(
|
||||
STATE_IDLE
|
||||
STATE_PREALARM
|
||||
STATE_ALARM
|
||||
|
@ -56,7 +56,7 @@ our %EXPORT_TAGS = (
|
|||
TRIGGER_ON
|
||||
TRIGGER_OFF
|
||||
) ],
|
||||
'functions' => [ qw(
|
||||
functions => [ qw(
|
||||
zmMemVerify
|
||||
zmMemInvalidate
|
||||
zmMemRead
|
||||
|
@ -83,7 +83,7 @@ our %EXPORT_TAGS = (
|
|||
);
|
||||
push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS;
|
||||
|
||||
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
|
||||
our @EXPORT_OK = ( @{ $EXPORT_TAGS{all} } );
|
||||
|
||||
our @EXPORT = qw();
|
||||
|
||||
|
@ -142,43 +142,43 @@ our $native = $arch/8;
|
|||
our $mem_seq = 0;
|
||||
|
||||
our $mem_data = {
|
||||
'shared_data' => { 'type'=>'SharedData', 'seq'=>$mem_seq++, 'contents'=> {
|
||||
'size' => { 'type'=>'uint32', 'seq'=>$mem_seq++ },
|
||||
'last_write_index' => { 'type'=>'uint32', 'seq'=>$mem_seq++ },
|
||||
'last_read_index' => { 'type'=>'uint32', 'seq'=>$mem_seq++ },
|
||||
'state' => { 'type'=>'uint32', 'seq'=>$mem_seq++ },
|
||||
'last_event' => { 'type'=>'uint32', 'seq'=>$mem_seq++ },
|
||||
'action' => { 'type'=>'uint32', 'seq'=>$mem_seq++ },
|
||||
'brightness' => { 'type'=>'int32', 'seq'=>$mem_seq++ },
|
||||
'hue' => { 'type'=>'int32', 'seq'=>$mem_seq++ },
|
||||
'colour' => { 'type'=>'int32', 'seq'=>$mem_seq++ },
|
||||
'contrast' => { 'type'=>'int32', 'seq'=>$mem_seq++ },
|
||||
'alarm_x' => { 'type'=>'int32', 'seq'=>$mem_seq++ },
|
||||
'alarm_y' => { 'type'=>'int32', 'seq'=>$mem_seq++ },
|
||||
'valid' => { 'type'=>'uint8', 'seq'=>$mem_seq++ },
|
||||
'active' => { 'type'=>'uint8', 'seq'=>$mem_seq++ },
|
||||
'signal' => { 'type'=>'uint8', 'seq'=>$mem_seq++ },
|
||||
'format' => { 'type'=>'uint8', 'seq'=>$mem_seq++ },
|
||||
'imagesize' => { 'type'=>'uint32', 'seq'=>$mem_seq++ },
|
||||
'epadding1' => { 'type'=>'uint32', 'seq'=>$mem_seq++ },
|
||||
'epadding2' => { 'type'=>'uint32', 'seq'=>$mem_seq++ },
|
||||
'startup_time' => { 'type'=>'time_t64', 'seq'=>$mem_seq++ },
|
||||
'last_write_time' => { 'type'=>'time_t64', 'seq'=>$mem_seq++ },
|
||||
'last_read_time' => { 'type'=>'time_t64', 'seq'=>$mem_seq++ },
|
||||
'control_state' => { 'type'=>'uint8[256]', 'seq'=>$mem_seq++ },
|
||||
shared_data => { type=>'SharedData', seq=>$mem_seq++, contents=> {
|
||||
size => { type=>'uint32', seq=>$mem_seq++ },
|
||||
last_write_index => { type=>'uint32', seq=>$mem_seq++ },
|
||||
last_read_index => { type=>'uint32', seq=>$mem_seq++ },
|
||||
state => { type=>'uint32', seq=>$mem_seq++ },
|
||||
last_event => { type=>'uint32', seq=>$mem_seq++ },
|
||||
action => { type=>'uint32', seq=>$mem_seq++ },
|
||||
brightness => { type=>'int32', seq=>$mem_seq++ },
|
||||
hue => { type=>'int32', seq=>$mem_seq++ },
|
||||
colour => { type=>'int32', seq=>$mem_seq++ },
|
||||
contrast => { type=>'int32', seq=>$mem_seq++ },
|
||||
alarm_x => { type=>'int32', seq=>$mem_seq++ },
|
||||
alarm_y => { type=>'int32', seq=>$mem_seq++ },
|
||||
valid => { type=>'uint8', seq=>$mem_seq++ },
|
||||
active => { type=>'uint8', seq=>$mem_seq++ },
|
||||
signal => { type=>'uint8', seq=>$mem_seq++ },
|
||||
format => { type=>'uint8', seq=>$mem_seq++ },
|
||||
imagesize => { type=>'uint32', seq=>$mem_seq++ },
|
||||
epadding1 => { type=>'uint32', seq=>$mem_seq++ },
|
||||
epadding2 => { type=>'uint32', seq=>$mem_seq++ },
|
||||
startup_time => { type=>'time_t64', seq=>$mem_seq++ },
|
||||
last_write_time => { type=>'time_t64', seq=>$mem_seq++ },
|
||||
last_read_time => { type=>'time_t64', seq=>$mem_seq++ },
|
||||
control_state => { type=>'uint8[256]', seq=>$mem_seq++ },
|
||||
}
|
||||
},
|
||||
'trigger_data' => { 'type'=>'TriggerData', 'seq'=>$mem_seq++, 'contents'=> {
|
||||
'size' => { 'type'=>'uint32', 'seq'=>$mem_seq++ },
|
||||
'trigger_state' => { 'type'=>'uint32', 'seq'=>$mem_seq++ },
|
||||
'trigger_score' => { 'type'=>'uint32', 'seq'=>$mem_seq++ },
|
||||
'padding' => { 'type'=>'uint32', 'seq'=>$mem_seq++ },
|
||||
'trigger_cause' => { 'type'=>'int8[32]', 'seq'=>$mem_seq++ },
|
||||
'trigger_text' => { 'type'=>'int8[256]', 'seq'=>$mem_seq++ },
|
||||
'trigger_showtext' => { 'type'=>'int8[256]', 'seq'=>$mem_seq++ },
|
||||
trigger_data => { type=>'TriggerData', seq=>$mem_seq++, 'contents'=> {
|
||||
size => { type=>'uint32', seq=>$mem_seq++ },
|
||||
trigger_state => { type=>'uint32', seq=>$mem_seq++ },
|
||||
trigger_score => { type=>'uint32', seq=>$mem_seq++ },
|
||||
padding => { type=>'uint32', seq=>$mem_seq++ },
|
||||
trigger_cause => { type=>'int8[32]', seq=>$mem_seq++ },
|
||||
trigger_text => { type=>'int8[256]', seq=>$mem_seq++ },
|
||||
trigger_showtext => { type=>'int8[256]', seq=>$mem_seq++ },
|
||||
}
|
||||
},
|
||||
'end' => { 'seq'=>$mem_seq++, 'size'=> 0 }
|
||||
end => { seq=>$mem_seq++, size=>0 }
|
||||
};
|
||||
|
||||
our $mem_size = 0;
|
||||
|
@ -420,7 +420,7 @@ sub zmMemWrite {
|
|||
} elsif ( $type =~ /^uint8\[\d+\]$/ ) {
|
||||
$data = pack( 'C'.$size, $value );
|
||||
} else {
|
||||
Fatal( "Unexpected type '".$type."' found for '".$field."'" );
|
||||
Fatal( "Unexpected type \"$type\" found for \"$field\"" );
|
||||
}
|
||||
|
||||
if ( !zmMemPut( $monitor, $offset, $size, $data ) ) {
|
||||
|
|
|
@ -40,7 +40,7 @@ our @ISA = qw(Exporter ZoneMinder::Base);
|
|||
# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
|
||||
# will save memory.
|
||||
our %EXPORT_TAGS = (
|
||||
'functions' => [ qw(
|
||||
functions => [ qw(
|
||||
zmMemKey
|
||||
zmMemAttach
|
||||
zmMemDetach
|
||||
|
@ -48,7 +48,7 @@ our %EXPORT_TAGS = (
|
|||
zmMemPut
|
||||
zmMemClean
|
||||
) ],
|
||||
);
|
||||
);
|
||||
push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS;
|
||||
|
||||
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
|
||||
|
@ -102,7 +102,7 @@ sub zmMemAttach {
|
|||
return ( undef );
|
||||
}
|
||||
my $MMAP;
|
||||
if ( !open( $MMAP, "+<", $mmap_file ) ) {
|
||||
if ( !open( $MMAP, '+<', $mmap_file ) ) {
|
||||
Error( sprintf( "Can't open memory map file '%s': $!\n", $mmap_file ) );
|
||||
return( undef );
|
||||
}
|
||||
|
@ -122,6 +122,7 @@ sub zmMemAttach {
|
|||
|
||||
sub zmMemDetach {
|
||||
my $monitor = shift;
|
||||
|
||||
if ( $monitor->{MMap} ) {
|
||||
if ( ! munmap( ${$monitor->{MMap}} ) ) {
|
||||
Warn( "Unable to munmap for monitor $$monitor{Id}\n");
|
||||
|
@ -174,7 +175,7 @@ sub zmMemPut {
|
|||
|
||||
sub zmMemClean {
|
||||
Debug( "Removing memory map files\n" );
|
||||
my $mapPath = $Config{ZM_PATH_MAP}."/zm.mmap.*";
|
||||
my $mapPath = $Config{ZM_PATH_MAP}.'/zm.mmap.*';
|
||||
foreach my $mapFile( glob( $mapPath ) ) {
|
||||
( $mapFile ) = $mapFile =~ /^(.+)$/;
|
||||
Debug( "Removing memory map file '$mapFile'\n" );
|
||||
|
|
|
@ -61,49 +61,22 @@ sub Storage {
|
|||
|
||||
1;
|
||||
__END__
|
||||
# Below is stub documentation for your module. You'd better edit it!
|
||||
|
||||
=head1 NAME
|
||||
|
||||
ZoneMinder::Database - Perl extension for blah blah blah
|
||||
ZoneMinder::Monitor - Perl Class for Monitors
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use ZoneMinder::Monitor;
|
||||
blah blah blah
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Stub documentation for ZoneMinder, created by h2xs. It looks like the
|
||||
author of the extension was negligent enough to leave the stub
|
||||
unedited.
|
||||
|
||||
Blah blah blah.
|
||||
|
||||
=head2 EXPORT
|
||||
|
||||
None by default.
|
||||
|
||||
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
Mention other useful documentation such as the documentation of
|
||||
related modules or operating system documentation (such as man pages
|
||||
in UNIX), or any relevant external documentation such as RFCs or
|
||||
standards.
|
||||
|
||||
If you have a mailing list set up for your module, mention it here.
|
||||
|
||||
If you have a web site set up for your module, mention it here.
|
||||
use ZoneMinder::Monitor;
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Philip Coombes, E<lt>philip.coombes@zoneminder.comE<gt>
|
||||
Isaac Connor, E<lt>isaac@zoneminder.comE<gt>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
Copyright (C) 2001-2008 Philip Coombes
|
||||
Copyright (C) 2001-2017 ZoneMinder LLC
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the same terms as Perl itself, either Perl version 5.8.3 or,
|
||||
|
|
|
@ -59,7 +59,7 @@ use bytes;
|
|||
# ==========================================================================
|
||||
|
||||
use constant RECOVER_TAG => '(r)'; # Tag to append to event name when recovered
|
||||
use constant RECOVER_TEXT => "Recovered."; # Text to append to event notes when recovered
|
||||
use constant RECOVER_TEXT => 'Recovered.'; # Text to append to event notes when recovered
|
||||
|
||||
# ==========================================================================
|
||||
#
|
||||
|
@ -98,11 +98,11 @@ logInit();
|
|||
logSetSignal();
|
||||
|
||||
GetOptions(
|
||||
'interactive' =>\$interactive,
|
||||
'continuous' =>\$continuous,
|
||||
'monitor_id=s' =>\$monitor_id,
|
||||
'report' =>\$report,
|
||||
'version' =>\$version
|
||||
continuous =>\$continuous,
|
||||
interactive =>\$interactive,
|
||||
monitor_id =>\$monitor_id,
|
||||
report =>\$report,
|
||||
version =>\$version
|
||||
) or pod2usage(-exitstatus => -1);
|
||||
|
||||
if ( $version ) {
|
||||
|
@ -114,6 +114,10 @@ if ( ($report + $interactive + $continuous) > 1 ) {
|
|||
pod2usage(-exitstatus => -1);
|
||||
}
|
||||
|
||||
if ( ! exists $Config{ZM_AUDIT_MIN_AGE} ) {
|
||||
Fatal('ZM_AUDIT_MIN_AGE is not set in config.');
|
||||
}
|
||||
|
||||
my $dbh = zmDbConnect();
|
||||
|
||||
require ZoneMinder::Monitor;
|
||||
|
@ -128,10 +132,6 @@ my $loop = 1;
|
|||
my $cleaned = 0;
|
||||
MAIN: while( $loop ) {
|
||||
|
||||
if ( ! exists $Config{ZM_AUDIT_MIN_AGE} ) {
|
||||
Fatal("ZM_AUDIT_MIN_AGE is not set in config.");
|
||||
}
|
||||
|
||||
if ( $continuous ) {
|
||||
# if we are running continuously, then just skip to the next
|
||||
# interval, otherwise we are a one off run, so wait a second and
|
||||
|
@ -158,11 +158,11 @@ MAIN: while( $loop ) {
|
|||
|
||||
my %Monitors;
|
||||
my $db_monitors;
|
||||
my $monitorSelectSql = $monitor_id ? 'SELECT * FRO Monitors WHERE Id=?' : 'SELECT * FROM Monitors ORDER BY Id';
|
||||
my $monitorSelectSql = $monitor_id ? 'SELECT * FROM Monitors WHERE Id=?' : 'SELECT * FROM Monitors ORDER BY Id';
|
||||
my $monitorSelectSth = $dbh->prepare_cached( $monitorSelectSql )
|
||||
or Fatal( "Can't prepare '$monitorSelectSql': ".$dbh->errstr() );
|
||||
|
||||
my $eventSelectSql = 'SELECT Id, (unix_timestamp() - unix_timestamp(StartTime)) as Age
|
||||
my $eventSelectSql = 'SELECT Id, (unix_timestamp() - unix_timestamp(StartTime)) AS Age
|
||||
FROM Events WHERE MonitorId = ? ORDER BY Id';
|
||||
my $eventSelectSth = $dbh->prepare_cached( $eventSelectSql )
|
||||
or Fatal( "Can't prepare '$eventSelectSql': ".$dbh->errstr() );
|
||||
|
@ -555,7 +555,7 @@ Debug("Event $db_event is not in fs.");
|
|||
if ( $Config{ZM_LOG_DATABASE_LIMIT} ) {
|
||||
if ( $Config{ZM_LOG_DATABASE_LIMIT} =~ /^\d+$/ ) {
|
||||
# Number of rows
|
||||
my $selectLogRowCountSql = 'SELECT count(*) as Rows from Logs';
|
||||
my $selectLogRowCountSql = 'SELECT count(*) AS Rows FROM Logs';
|
||||
my $selectLogRowCountSth = $dbh->prepare_cached( $selectLogRowCountSql )
|
||||
or Fatal( "Can't prepare '$selectLogRowCountSql': ".$dbh->errstr() );
|
||||
$res = $selectLogRowCountSth->execute()
|
||||
|
@ -569,15 +569,14 @@ Debug("Event $db_event is not in fs.");
|
|||
$res = $deleteLogByRowsSth->execute( $logRows - $Config{ZM_LOG_DATABASE_LIMIT} )
|
||||
or Fatal( "Can't execute: ".$deleteLogByRowsSth->errstr() );
|
||||
if ( $deleteLogByRowsSth->rows() ) {
|
||||
aud_print( 'Deleted '.$deleteLogByRowsSth->rows()
|
||||
." log table entries by count\n" );
|
||||
aud_print( 'Deleted '.$deleteLogByRowsSth->rows() ." log table entries by count\n" );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
# Time of record
|
||||
my $deleteLogByTimeSql =
|
||||
"DELETE low_priority FROM Logs
|
||||
WHERE TimeKey < unix_timestamp(now() - interval ".$Config{ZM_LOG_DATABASE_LIMIT}.')';
|
||||
'DELETE low_priority FROM Logs
|
||||
WHERE TimeKey < unix_timestamp(now() - interval '.$Config{ZM_LOG_DATABASE_LIMIT}.')';
|
||||
my $deleteLogByTimeSth = $dbh->prepare_cached( $deleteLogByTimeSql )
|
||||
or Fatal( "Can't prepare '$deleteLogByTimeSql': ".$dbh->errstr() );
|
||||
$res = $deleteLogByTimeSth->execute()
|
||||
|
|
|
@ -27,7 +27,11 @@ zmfilter.pl - ZoneMinder tool to filter events
|
|||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
<<<<<<< HEAD
|
||||
zmfilter.pl [-f <filter name>,--filter=<filter name>] [--filter_id=<filter id>] | -v, --version
|
||||
=======
|
||||
zmfilter.pl [-f <filter name>,--filter=<filter name>] | -v, --version
|
||||
>>>>>>> master
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
|
@ -70,7 +74,7 @@ use Getopt::Long;
|
|||
use autouse 'Pod::Usage'=>qw(pod2usage);
|
||||
use autouse 'Data::Dumper'=>qw(Dumper);
|
||||
|
||||
my $filter_name = "";
|
||||
my $filter_name = '';
|
||||
my $filter_id;
|
||||
my $version = 0;
|
||||
|
||||
|
@ -93,19 +97,19 @@ use constant EVENT_PATH => ($Config{ZM_DIR_EVENTS}=~m|/|)
|
|||
: ($Config{ZM_PATH_WEB}.'/'.$Config{ZM_DIR_EVENTS})
|
||||
;
|
||||
|
||||
logInit();
|
||||
logSetSignal();
|
||||
logInit();
|
||||
logSetSignal();
|
||||
|
||||
if ( $Config{ZM_OPT_UPLOAD} ) {
|
||||
# Comment these out if you don't have them and don't want to upload
|
||||
# or don't want to use that format
|
||||
if ( $Config{ZM_UPLOAD_ARCH_FORMAT} eq "zip" ) {
|
||||
if ( $Config{ZM_UPLOAD_ARCH_FORMAT} eq 'zip' ) {
|
||||
require Archive::Zip;
|
||||
import Archive::Zip qw( :ERROR_CODES :CONSTANTS );
|
||||
} else {
|
||||
require Archive::Tar;
|
||||
}
|
||||
if ( $Config{ZM_UPLOAD_PROTOCOL} eq "ftp" ) {
|
||||
if ( $Config{ZM_UPLOAD_PROTOCOL} eq 'ftp' ) {
|
||||
require Net::FTP;
|
||||
} else {
|
||||
require Net::SFTP::Foreign;
|
||||
|
@ -144,8 +148,10 @@ if ( ! EVENT_PATH ) {
|
|||
die;
|
||||
}
|
||||
|
||||
# In future, should not be neccessary wrt StorageAreas
|
||||
chdir( EVENT_PATH );
|
||||
|
||||
# SHould not be neccessary... but nice to get a local var. What if it fails?
|
||||
my $dbh = zmDbConnect();
|
||||
|
||||
if ( $filter_name ) {
|
||||
|
@ -157,10 +163,11 @@ if ( $filter_name ) {
|
|||
}
|
||||
|
||||
if ( ! ( $filter_name or $filter_id ) ) {
|
||||
Debug("Sleeping due to start delay: " . START_DELAY . ' seconds...' );
|
||||
sleep( START_DELAY );
|
||||
}
|
||||
|
||||
my $filters;
|
||||
my @filters;
|
||||
my $last_action = 0;
|
||||
|
||||
while( 1 ) {
|
||||
|
@ -194,28 +201,34 @@ sub getFilters {
|
|||
my @sql_values;
|
||||
|
||||
my @filters;
|
||||
my $sql = "SELECT * FROM Filters WHERE";
|
||||
my $sql = 'SELECT * FROM Filters WHERE';
|
||||
if ( $$sql_filters{Name} ) {
|
||||
$sql .= " Name = ? and";
|
||||
$sql .= ' Name = ? AND';
|
||||
push @sql_values, $$sql_filters{Name};
|
||||
} elsif ( $$sql_filters{Id} ) {
|
||||
$sql .= " Id = ? and";
|
||||
$sql .= ' Id = ? AND';
|
||||
push @sql_values, $$sql_filters{Id};
|
||||
} else {
|
||||
$sql .= " Background = 1 and";
|
||||
$sql .= ' Background = 1 AND';
|
||||
}
|
||||
$sql .= "( AutoArchive = 1
|
||||
$sql .= '( AutoArchive = 1
|
||||
or AutoVideo = 1
|
||||
or AutoUpload = 1
|
||||
or AutoEmail = 1
|
||||
or AutoMessage = 1
|
||||
or AutoExecute = 1
|
||||
or AutoDelete = 1
|
||||
) ORDER BY Name";
|
||||
) ORDER BY Name';
|
||||
my $sth = $dbh->prepare_cached( $sql )
|
||||
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute( @sql_values )
|
||||
or Fatal( "Can't execute '$sql': ".$sth->errstr() );
|
||||
or Fatal( "Unable toprepare '$sql': ".$dbh->errstr() );
|
||||
my $res;
|
||||
if ( $filter_name ) {
|
||||
$res = $sth->execute( $filter_name )
|
||||
or Fatal( "Unable toexecute '$sql': ".$sth->errstr() );
|
||||
} else {
|
||||
$res = $sth->execute()
|
||||
or Fatal( "Unable toexecute '$sql': ".$sth->errstr() );
|
||||
}
|
||||
FILTER: while( my $db_filter = $sth->fetchrow_hashref() ) {
|
||||
my $filter = new ZoneMinder::Filter( $$db_filter{Id}, $db_filter );
|
||||
Debug( "Found filter '$db_filter->{Name}'\n" );
|
||||
|
@ -242,14 +255,14 @@ sub checkFilter {
|
|||
|
||||
my @Events = $filter->Execute();
|
||||
Info( join( "Checking filter '$filter->{Name}'",
|
||||
($filter->{AutoDelete}?", delete":""),
|
||||
($filter->{AutoArchive}?", archive":""),
|
||||
($filter->{AutoVideo}?", video":""),
|
||||
($filter->{AutoUpload}?", upload":""),
|
||||
($filter->{AutoEmail}?", email":""),
|
||||
($filter->{AutoMessage}?", message":""),
|
||||
($filter->{AutoExecute}?", execute":""),
|
||||
" returned " , scalar @Events , ' events',
|
||||
($filter->{AutoDelete}?', delete':''),
|
||||
($filter->{AutoArchive}?', archive':''),
|
||||
($filter->{AutoVideo}?', video':''),
|
||||
($filter->{AutoUpload}?', upload':''),
|
||||
($filter->{AutoEmail}?', email':''),
|
||||
($filter->{AutoMessage}?', message':''),
|
||||
($filter->{AutoExecute}?', execute':''),
|
||||
' returned ' , scalar @Events , ' events',
|
||||
"\n",
|
||||
) );
|
||||
|
||||
|
@ -260,11 +273,11 @@ sub checkFilter {
|
|||
if ( $filter->{AutoArchive} ) {
|
||||
Info( "Archiving event $event->{Id}\n" );
|
||||
# Do it individually to avoid locking up the table for new events
|
||||
my $sql = "update Events set Archived = 1 where Id = ?";
|
||||
my $sql = 'UPDATE Events SET Archived = 1 WHERE Id = ?';
|
||||
my $sth = $dbh->prepare_cached( $sql )
|
||||
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
or Fatal( "Unable toprepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute( $event->{Id} )
|
||||
or Error( "Can't execute '$sql': ".$sth->errstr() );
|
||||
or Error( "Unable toexecute '$sql': ".$sth->errstr() );
|
||||
}
|
||||
if ( $Config{ZM_OPT_FFMPEG} && $filter->{AutoVideo} ) {
|
||||
if ( !$event->{Videoed} ) {
|
||||
|
@ -296,7 +309,7 @@ sub checkFilter {
|
|||
my $Event = new ZoneMinder::Event( $$event{Id}, $event );
|
||||
$Event->delete();
|
||||
} else {
|
||||
Error( "Unable to 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 foreach event
|
||||
|
@ -330,8 +343,17 @@ sub generateVideo {
|
|||
$format = $ffmpeg_formats[0];
|
||||
}
|
||||
|
||||
my $command = $Config{ZM_PATH_BIN}."/zmvideo.pl -e "
|
||||
.$event->{Id}." -r ".$rate." -s ".$scale." -f ".$format;
|
||||
my $command = join( '',
|
||||
$Config{ZM_PATH_BIN},
|
||||
'/zmvideo.pl -e ',
|
||||
$event->{Id},
|
||||
' -r ',
|
||||
$rate,
|
||||
' -s ',
|
||||
$scale,
|
||||
' -f ',
|
||||
$format,
|
||||
);
|
||||
my $output = qx($command);
|
||||
chomp( $output );
|
||||
my $status = $? >> 8;
|
||||
|
@ -345,13 +367,12 @@ sub generateVideo {
|
|||
}
|
||||
return( 0 );
|
||||
} else {
|
||||
my $sql = "update Events set Videoed = 1 where Id = ?";
|
||||
my $sql = 'UPDATE Events SET Videoed = 1 WHERE Id = ?';
|
||||
my $sth = $dbh->prepare_cached( $sql )
|
||||
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
or Fatal( "Unable toprepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute( $event->{Id} )
|
||||
or Fatal( "Can't execute '$sql': ".$sth->errstr() );
|
||||
if ( wantarray() )
|
||||
{
|
||||
or Fatal( "Unable toexecute '$sql': ".$sth->errstr() );
|
||||
if ( wantarray() ) {
|
||||
return( $format, $output );
|
||||
}
|
||||
}
|
||||
|
@ -367,48 +388,49 @@ sub generateImage {
|
|||
my $frame = shift;
|
||||
my $analyse = do { @_ ? shift : 0 }; # don't return analyse image by default
|
||||
|
||||
my $capture_image_path = sprintf("%s/%0".$Config{ZM_EVENT_IMAGE_DIGITS}."d-capture.jpg", getEventPath($event), $frame->{FrameId});
|
||||
my $analyse_image_path = sprintf("%s/%0".$Config{ZM_EVENT_IMAGE_DIGITS}."d-analyse.jpg", getEventPath($event), $frame->{FrameId}) if $analyse;
|
||||
my $video_path = sprintf("%s/%d-video.mp4", getEventPath($event), $event->{Id});
|
||||
my $image_path = "";
|
||||
my $capture_image_path = sprintf('%s/%0'.$Config{ZM_EVENT_IMAGE_DIGITS}.'d-capture.jpg', getEventPath($event), $frame->{FrameId});
|
||||
my $analyse_image_path = sprintf('%s/%0'.$Config{ZM_EVENT_IMAGE_DIGITS}.'d-analyse.jpg', getEventPath($event), $frame->{FrameId}) if $analyse;
|
||||
my $video_path = sprintf('%s/%d-video.mp4', getEventPath($event), $event->{Id});
|
||||
my $image_path = '';
|
||||
|
||||
# check if the image file exists. If the file doesn't exist and we use H264 try to extract it from .mp4 video
|
||||
# check if the image file exists. If the file doesn't exist and we use H264 try to extract it from .mp4 video
|
||||
if ( $analyse && -r $analyse_image_path ) {
|
||||
$image_path = $analyse_image_path;
|
||||
} elsif ( -r $capture_image_path ) {
|
||||
$image_path = $capture_image_path;
|
||||
} elsif ( -e $video_path ) {
|
||||
if ( !system("ffmpeg -y -v 0 -i ".$video_path." -vf 'select=gte(n\\,".$frame->{FrameId}."),setpts=PTS-STARTPTS' -vframes 1 -f image2 ".$capture_image_path) ) {
|
||||
if ( !system('ffmpeg -y -v 0 -i '.$video_path." -vf 'select=gte(n\\,".$frame->{FrameId}."),setpts=PTS-STARTPTS' -vframes 1 -f image2 ".$capture_image_path) ) {
|
||||
$image_path = $capture_image_path;
|
||||
}
|
||||
}
|
||||
return $image_path;
|
||||
}
|
||||
|
||||
|
||||
sub uploadArchFile {
|
||||
my $filter = shift;
|
||||
my $event = shift;
|
||||
|
||||
if ( ! $Config{ZM_UPLOAD_HOST} ) {
|
||||
Error( "Cannot upload archive as no upload host defined" );
|
||||
Error( 'Cannot upload archive as no upload host defined' );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
my $archFile = $event->{MonitorName}.'-'.$event->{Id};
|
||||
my $archImagePath = getEventPath( $event )
|
||||
."/"
|
||||
.'/'
|
||||
.(
|
||||
( $Config{ZM_UPLOAD_ARCH_ANALYSE} )
|
||||
? '{*analyse,*capture}'
|
||||
: '*capture'
|
||||
)
|
||||
.".jpg"
|
||||
.'.jpg'
|
||||
;
|
||||
my @archImageFiles = glob($archImagePath);
|
||||
my $archLocPath;
|
||||
|
||||
my $archError = 0;
|
||||
if ( $Config{ZM_UPLOAD_ARCH_FORMAT} eq "zip" ) {
|
||||
if ( $Config{ZM_UPLOAD_ARCH_FORMAT} eq 'zip' ) {
|
||||
$archFile .= '.zip';
|
||||
$archLocPath = $Config{ZM_UPLOAD_LOC_DIR}.'/'.$archFile;
|
||||
my $zip = Archive::Zip->new();
|
||||
|
@ -419,7 +441,7 @@ sub uploadArchFile {
|
|||
Debug( "Adding $imageFile\n" );
|
||||
my $member = $zip->addFile( $imageFile );
|
||||
if ( !$member ) {
|
||||
Error( "Unable to add image file $imageFile to zip archive $archLocPath" );
|
||||
Error( "Unable toto add image file $imageFile to zip archive $archLocPath" );
|
||||
$archError = 1;
|
||||
last;
|
||||
}
|
||||
|
@ -437,7 +459,7 @@ sub uploadArchFile {
|
|||
} else {
|
||||
Error( "Error adding images to zip archive $archLocPath, not writing" );
|
||||
}
|
||||
} elsif ( $Config{ZM_UPLOAD_ARCH_FORMAT} eq "tar" ) {
|
||||
} elsif ( $Config{ZM_UPLOAD_ARCH_FORMAT} eq 'tar' ) {
|
||||
if ( $Config{ZM_UPLOAD_ARCH_COMPRESS} ) {
|
||||
$archFile .= '.tar.gz';
|
||||
} else {
|
||||
|
@ -452,16 +474,15 @@ sub uploadArchFile {
|
|||
@archImageFiles
|
||||
)
|
||||
) {
|
||||
Error( "Tar error: ".Archive::Tar->error()."\n " );
|
||||
Error( 'Tar error: '.Archive::Tar->error()."\n " );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $archError ) {
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
if ( $Config{ZM_UPLOAD_PROTOCOL} eq "ftp" ) {
|
||||
Info( "Uploading to ".$Config{ZM_UPLOAD_HOST}." using FTP\n" );
|
||||
} else {
|
||||
if ( $Config{ZM_UPLOAD_PROTOCOL} eq 'ftp' ) {
|
||||
Info( 'Uploading to '.$Config{ZM_UPLOAD_HOST}." using FTP\n" );
|
||||
my $ftp = Net::FTP->new(
|
||||
$Config{ZM_UPLOAD_HOST},
|
||||
Timeout=>$Config{ZM_UPLOAD_TIMEOUT},
|
||||
|
@ -469,25 +490,25 @@ sub uploadArchFile {
|
|||
Debug=>$Config{ZM_UPLOAD_DEBUG}
|
||||
);
|
||||
if ( !$ftp ) {
|
||||
Error( "Can't create FTP connection: $@" );
|
||||
Error( "Unable tocreate FTP connection: $@" );
|
||||
return( 0 );
|
||||
}
|
||||
$ftp->login( $Config{ZM_UPLOAD_USER}, $Config{ZM_UPLOAD_PASS} )
|
||||
or Error( "FTP - Can't login" );
|
||||
or Error( "FTP - Unable tologin" );
|
||||
$ftp->binary()
|
||||
or Error( "FTP - Can't go binary" );
|
||||
or Error( "FTP - Unable togo binary" );
|
||||
$ftp->cwd( $Config{ZM_UPLOAD_REM_DIR} )
|
||||
or Error( "FTP - Can't cwd" )
|
||||
or Error( "FTP - Unable tocwd" )
|
||||
if ( $Config{ZM_UPLOAD_REM_DIR} );
|
||||
$ftp->put( $archLocPath )
|
||||
or Error( "FTP - Can't upload '$archLocPath'" );
|
||||
or Error( "FTP - Unable toupload '$archLocPath'" );
|
||||
$ftp->quit()
|
||||
or Error( "FTP - Can't quit" );
|
||||
or Error( "FTP - Unable toquit" );
|
||||
} else {
|
||||
my $host = $Config{ZM_UPLOAD_HOST};
|
||||
$host .= ":".$Config{ZM_UPLOAD_PORT}
|
||||
$host .= ':'.$Config{ZM_UPLOAD_PORT}
|
||||
if $Config{ZM_UPLOAD_PORT};
|
||||
Info( "Uploading to ".$host." using SFTP\n" );
|
||||
Info( 'Uploading to '.$host." using SFTP\n" );
|
||||
my %sftpOptions = ( host=>$Config{ZM_UPLOAD_HOST}, user=>$Config{ZM_UPLOAD_USER} );
|
||||
$sftpOptions{password} = $Config{ZM_UPLOAD_PASS}
|
||||
if $Config{ZM_UPLOAD_PASS};
|
||||
|
@ -503,22 +524,22 @@ sub uploadArchFile {
|
|||
$sftpOptions{more} = [@more_ssh_args];
|
||||
my $sftp = Net::SFTP::Foreign->new( $Config{ZM_UPLOAD_HOST}, %sftpOptions );
|
||||
if ( $sftp->error ) {
|
||||
Error( "Can't create SFTP connection: ".$sftp->error );
|
||||
Error( "Unable tocreate SFTP connection: ".$sftp->error );
|
||||
return( 0 );
|
||||
}
|
||||
$sftp->setcwd( $Config{ZM_UPLOAD_REM_DIR} )
|
||||
or Error( "SFTP - Can't setcwd: ".$sftp->error )
|
||||
or Error( "SFTP - Unable tosetcwd: ".$sftp->error )
|
||||
if $Config{ZM_UPLOAD_REM_DIR};
|
||||
$sftp->put( $archLocPath, $archFile )
|
||||
or Error( "SFTP - Can't upload '$archLocPath': ".$sftp->error );
|
||||
or Error( "SFTP - Unable toupload '$archLocPath': ".$sftp->error );
|
||||
}
|
||||
|
||||
unlink( $archLocPath );
|
||||
my $sql = "update Events set Uploaded = 1 where Id = ?";
|
||||
my $sql = 'UPDATE Events SET Uploaded = 1 WHERE Id = ?';
|
||||
my $sth = $dbh->prepare_cached( $sql )
|
||||
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
or Fatal( "Unable toprepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute( $event->{Id} )
|
||||
or Fatal( "Can't execute '$sql': ".$sth->errstr() );
|
||||
or Fatal( "Unable toexecute '$sql': ".$sth->errstr() );
|
||||
}
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
|
@ -535,7 +556,7 @@ sub substituteTags {
|
|||
|
||||
my $monitor = {};
|
||||
if ( $need_monitor ) {
|
||||
my $db_now = strftime( "%Y-%m-%d %H:%M:%S", localtime() );
|
||||
my $db_now = strftime( '%Y-%m-%d %H:%M:%S', localtime() );
|
||||
my $sql = "SELECT
|
||||
M.Id,
|
||||
count(E.Id) as EventCount,
|
||||
|
@ -555,9 +576,9 @@ sub substituteTags {
|
|||
ORDER BY Id"
|
||||
;
|
||||
my $sth = $dbh->prepare_cached( $sql )
|
||||
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
or Fatal( "Unable toprepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute( $event->{MonitorId} )
|
||||
or Fatal( "Can't execute '$sql': ".$sth->errstr() );
|
||||
or Fatal( "Unable toexecute '$sql': ".$sth->errstr() );
|
||||
$monitor = $sth->fetchrow_hashref();
|
||||
$sth->finish();
|
||||
return() if ( !$monitor );
|
||||
|
@ -574,9 +595,9 @@ sub substituteTags {
|
|||
ORDER BY FrameId"
|
||||
;
|
||||
my $sth = $dbh->prepare_cached( $sql )
|
||||
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
or Fatal( "Unable toprepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute( $event->{Id} )
|
||||
or Fatal( "Can't execute '$sql': ".$sth->errstr() );
|
||||
or Fatal( "Unable toexecute '$sql': ".$sth->errstr() );
|
||||
while( my $frame = $sth->fetchrow_hashref() ) {
|
||||
if ( !$first_alarm_frame ) {
|
||||
$first_alarm_frame = $frame;
|
||||
|
@ -615,64 +636,47 @@ sub substituteTags {
|
|||
$text =~ s/%EST%/$event->{TotScore}/g;
|
||||
$text =~ s/%ESA%/$event->{AvgScore}/g;
|
||||
$text =~ s/%ESM%/$event->{MaxScore}/g;
|
||||
|
||||
if ( $first_alarm_frame ) {
|
||||
$text =~ s/%EPI1%/$url?view=frame&mid=$event->{MonitorId}&eid=$event->{Id}&fid=$first_alarm_frame->{FrameId}/g;
|
||||
$text =~ s/%EPIM%/$url?view=frame&mid=$event->{MonitorId}&eid=$event->{Id}&fid=$max_alarm_frame->{FrameId}/g;
|
||||
if ( $attachments_ref && $text =~ s/%EI1%//g ) {
|
||||
my $path = generateImage( $event, $first_alarm_frame);
|
||||
my $path = generateImage( $event, $first_alarm_frame );
|
||||
if ( -e $path ) {
|
||||
push( @$attachments_ref,
|
||||
{
|
||||
type=>"image/jpeg",
|
||||
path=>$path
|
||||
}
|
||||
);
|
||||
push( @$attachments_ref, { type=>'image/jpeg', path=>$path } );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $attachments_ref && $text =~ s/%EIM%//g ) {
|
||||
# Don't attach the same image twice
|
||||
# Don't attach the same image twice
|
||||
if ( !@$attachments_ref
|
||||
|| ($first_alarm_frame->{FrameId} != $max_alarm_frame->{FrameId} )
|
||||
) {
|
||||
my $path = generateImage( $event, $max_alarm_frame);
|
||||
my $path = generateImage( $event, $max_alarm_frame );
|
||||
if ( -e $path ) {
|
||||
push( @$attachments_ref,
|
||||
{
|
||||
type=>"image/jpeg",
|
||||
path=>$path
|
||||
}
|
||||
);
|
||||
push( @$attachments_ref, { type=>'image/jpeg', path=>$path } );
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( $attachments_ref && $text =~ s/%EI1A%//g ) {
|
||||
my $path = generateImage( $event, $first_alarm_frame, "analyse" );
|
||||
my $path = generateImage( $event, $first_alarm_frame, 'analyse' );
|
||||
if ( -e $path ) {
|
||||
push( @$attachments_ref,
|
||||
{
|
||||
type=>"image/jpeg",
|
||||
path=>$path
|
||||
}
|
||||
);
|
||||
push( @$attachments_ref, { type=>'image/jpeg', path=>$path } );
|
||||
}
|
||||
}
|
||||
if ( $attachments_ref && $text =~ s/%EIMA%//g ) {
|
||||
# Don't attach the same image twice
|
||||
# Don't attach the same image twice
|
||||
if ( !@$attachments_ref
|
||||
|| ($first_alarm_frame->{FrameId} != $max_alarm_frame->{FrameId} )
|
||||
) {
|
||||
my $path = generateImage( $event, $max_alarm_frame, "analyse");
|
||||
my $path = generateImage( $event, $max_alarm_frame, 'analyse');
|
||||
if ( -e $path ) {
|
||||
push( @$attachments_ref,
|
||||
{
|
||||
type=>"image/jpeg",
|
||||
path=>$path
|
||||
}
|
||||
);
|
||||
}
|
||||
push( @$attachments_ref, { type=>'image/jpeg', path=>$path } );
|
||||
}
|
||||
}
|
||||
}
|
||||
} # end if $first_alarm_frame
|
||||
|
||||
if ( $attachments_ref && $Config{ZM_OPT_FFMPEG} ) {
|
||||
if ( $text =~ s/%EV%//g ) {
|
||||
my ( $format, $path ) = generateVideo( $filter, $event );
|
||||
|
@ -694,7 +698,7 @@ sub substituteTags {
|
|||
$text =~ s/%FP%/$url?view=filter&mid=$event->{MonitorId}&filter_name=$filter_name/g;
|
||||
|
||||
return( $text );
|
||||
}
|
||||
} # end subsitituteTags
|
||||
|
||||
sub sendEmail {
|
||||
my $filter = shift;
|
||||
|
@ -705,7 +709,7 @@ sub sendEmail {
|
|||
return( 0 );
|
||||
}
|
||||
if ( ! $Config{ZM_EMAIL_ADDRESS} ) {
|
||||
Error( "No email address defined, not sending email" );
|
||||
Error( 'No email address defined, not sending email' );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
@ -726,11 +730,11 @@ sub sendEmail {
|
|||
From => $Config{ZM_FROM_EMAIL},
|
||||
To => $Config{ZM_EMAIL_ADDRESS},
|
||||
Subject => $subject,
|
||||
Type => "multipart/mixed"
|
||||
Type => 'multipart/mixed'
|
||||
);
|
||||
### Add the text message part
|
||||
$mail->attach (
|
||||
Type => "TEXT",
|
||||
Type => 'TEXT',
|
||||
Data => $body
|
||||
);
|
||||
### Add the attachments
|
||||
|
@ -739,7 +743,7 @@ sub sendEmail {
|
|||
$mail->attach(
|
||||
Path => $attachment->{path},
|
||||
Type => $attachment->{type},
|
||||
Disposition => "attachment"
|
||||
Disposition => 'attachment'
|
||||
);
|
||||
}
|
||||
### Send the Message
|
||||
|
@ -752,15 +756,15 @@ sub sendEmail {
|
|||
$ssmtp_location = qx('which ssmtp');
|
||||
}
|
||||
if ( !$ssmtp_location ) {
|
||||
Debug( "Can't find ssmtp, trying MIME::Lite->send" );
|
||||
MIME::Lite->send( "smtp", $Config{ZM_EMAIL_HOST}, Timeout=>60 );
|
||||
Debug( "Unable tofind ssmtp, trying MIME::Lite->send" );
|
||||
MIME::Lite->send( 'smtp', $Config{ZM_EMAIL_HOST}, Timeout=>60 );
|
||||
$mail->send();
|
||||
} else {
|
||||
### Send using SSMTP
|
||||
$mail->send( 'sendmail', $ssmtp_location, $Config{ZM_EMAIL_ADDRESS} );
|
||||
}
|
||||
} else {
|
||||
MIME::Lite->send( "smtp", $Config{ZM_EMAIL_HOST}, Timeout=>60 );
|
||||
MIME::Lite->send( 'smtp', $Config{ZM_EMAIL_HOST}, Timeout=>60 );
|
||||
$mail->send();
|
||||
}
|
||||
} else {
|
||||
|
@ -777,23 +781,23 @@ sub sendEmail {
|
|||
$mail->attach(
|
||||
Path => $attachment->{path},
|
||||
Type => $attachment->{type},
|
||||
Encoding => "base64"
|
||||
Encoding => 'base64'
|
||||
);
|
||||
}
|
||||
$mail->smtpsend( Host => $Config{ZM_EMAIL_HOST}, MailFrom => $Config{ZM_FROM_EMAIL} );
|
||||
}
|
||||
};
|
||||
if ( $@ ) {
|
||||
Error( "Can't send email: $@" );
|
||||
Error( "Unable tosend email: $@" );
|
||||
return( 0 );
|
||||
} else {
|
||||
Info( "Notification email sent\n" );
|
||||
}
|
||||
my $sql = "update Events set Emailed = 1 where Id = ?";
|
||||
my $sql = 'update Events set Emailed = 1 where Id = ?';
|
||||
my $sth = $dbh->prepare_cached( $sql )
|
||||
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
or Fatal( "Unable toprepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute( $event->{Id} )
|
||||
or Fatal( "Can't execute '$sql': ".$sth->errstr() );
|
||||
or Fatal( "Unable toexecute '$sql': ".$sth->errstr() );
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
@ -807,7 +811,7 @@ sub sendMessage {
|
|||
return( 0 );
|
||||
}
|
||||
if ( ! $Config{ZM_MESSAGE_ADDRESS} ) {
|
||||
Error( "No message address defined, not sending message" );
|
||||
Error( 'No message address defined, not sending message' );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
@ -828,11 +832,11 @@ sub sendMessage {
|
|||
From => $Config{ZM_FROM_EMAIL},
|
||||
To => $Config{ZM_MESSAGE_ADDRESS},
|
||||
Subject => $subject,
|
||||
Type => "multipart/mixed"
|
||||
Type => 'multipart/mixed'
|
||||
);
|
||||
### Add the text message part
|
||||
$mail->attach (
|
||||
Type => "TEXT",
|
||||
Type => 'TEXT',
|
||||
Data => $body
|
||||
);
|
||||
### Add the attachments
|
||||
|
@ -841,7 +845,7 @@ sub sendMessage {
|
|||
$mail->attach(
|
||||
Path => $attachment->{path},
|
||||
Type => $attachment->{type},
|
||||
Disposition => "attachment"
|
||||
Disposition => 'attachment'
|
||||
);
|
||||
}
|
||||
### Send the Message
|
||||
|
@ -854,15 +858,15 @@ sub sendMessage {
|
|||
$ssmtp_location = qx('which ssmtp');
|
||||
}
|
||||
if ( !$ssmtp_location ) {
|
||||
Debug( "Can't find ssmtp, trying MIME::Lite->send" );
|
||||
MIME::Lite->send( "smtp", $Config{ZM_EMAIL_HOST}, Timeout=>60 );
|
||||
Debug( 'Unable tofind ssmtp, trying MIME::Lite->send' );
|
||||
MIME::Lite->send( 'smtp', $Config{ZM_EMAIL_HOST}, Timeout=>60 );
|
||||
$mail->send();
|
||||
} else {
|
||||
### Send using SSMTP
|
||||
$mail->send( 'sendmail', $ssmtp_location, $Config{ZM_MESSAGE_ADDRESS} );
|
||||
}
|
||||
} else {
|
||||
MIME::Lite->send( "smtp", $Config{ZM_EMAIL_HOST}, Timeout=>60 );
|
||||
MIME::Lite->send( 'smtp', $Config{ZM_EMAIL_HOST}, Timeout=>60 );
|
||||
$mail->send();
|
||||
}
|
||||
} else {
|
||||
|
@ -879,7 +883,7 @@ sub sendMessage {
|
|||
$mail->attach(
|
||||
Path => $attachment->{path},
|
||||
Type => $attachment->{type},
|
||||
Encoding => "base64"
|
||||
Encoding => 'base64'
|
||||
);
|
||||
}
|
||||
$mail->smtpsend( Host => $Config{ZM_EMAIL_HOST},
|
||||
|
@ -888,16 +892,16 @@ sub sendMessage {
|
|||
}
|
||||
};
|
||||
if ( $@ ) {
|
||||
Error( "Can't send email: $@" );
|
||||
Error( "Unable tosend email: $@" );
|
||||
return( 0 );
|
||||
} else {
|
||||
Info( "Notification message sent\n" );
|
||||
}
|
||||
my $sql = "update Events set Messaged = 1 where Id = ?";
|
||||
my $sql = 'update Events set Messaged = 1 where Id = ?';
|
||||
my $sth = $dbh->prepare_cached( $sql )
|
||||
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
or Fatal( "Unable toprepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute( $event->{Id} )
|
||||
or Fatal( "Can't execute '$sql': ".$sth->errstr() );
|
||||
or Fatal( "Unable toexecute '$sql': ".$sth->errstr() );
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
@ -923,11 +927,11 @@ sub executeCommand {
|
|||
Error( "Command '$command' exited with status: $status\n" );
|
||||
return( 0 );
|
||||
} else {
|
||||
my $sql = "update Events set Executed = 1 where Id = ?";
|
||||
my $sql = 'update Events set Executed = 1 where Id = ?';
|
||||
my $sth = $dbh->prepare_cached( $sql )
|
||||
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
or Fatal( "Unable toprepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute( $event->{Id} )
|
||||
or Fatal( "Can't execute '$sql': ".$sth->errstr() );
|
||||
or Fatal( "Unable toexecute '$sql': ".$sth->errstr() );
|
||||
}
|
||||
return( 1 );
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
#include "zm_ffmpeg_camera.h"
|
||||
|
||||
extern "C"{
|
||||
extern "C" {
|
||||
#include "libavutil/time.h"
|
||||
}
|
||||
#ifndef AV_ERROR_MAX_STRING_SIZE
|
||||
|
@ -125,8 +125,7 @@ int FfmpegCamera::PreCapture()
|
|||
return( 0 );
|
||||
}
|
||||
|
||||
int FfmpegCamera::Capture( Image &image )
|
||||
{
|
||||
int FfmpegCamera::Capture( Image &image ) {
|
||||
if (!mCanCapture){
|
||||
return -1;
|
||||
}
|
||||
|
@ -167,11 +166,8 @@ int FfmpegCamera::Capture( Image &image )
|
|||
Debug( 5, "Got packet from stream %d dts (%d) pts(%d)", packet.stream_index, packet.pts, packet.dts );
|
||||
// What about audio stream? Maybe someday we could do sound detection...
|
||||
if ( packet.stream_index == mVideoStreamId ) {
|
||||
#if LIBAVCODEC_VERSION_CHECK(52, 23, 0, 23, 0)
|
||||
if (avcodec_decode_video2(mVideoCodecContext, mRawFrame, &frameComplete, &packet) < 0)
|
||||
#else
|
||||
if (avcodec_decode_video(mVideoCodecContext, mRawFrame, &frameComplete, packet.data, packet.size) < 0)
|
||||
#endif
|
||||
int ret = zm_avcodec_decode_video( mVideoCodecContext, mRawFrame, &frameComplete, &packet );
|
||||
if ( ret < 0 )
|
||||
Fatal( "Unable to decode frame at frame %d", frameCount );
|
||||
|
||||
Debug( 4, "Decoded video packet at frame %d", frameCount );
|
||||
|
@ -364,7 +360,7 @@ int FfmpegCamera::OpenFfmpeg() {
|
|||
Fatal( "Unable to open codec for video stream from %s", mPath.c_str() );
|
||||
}
|
||||
|
||||
if (mAudioStreamId >= 0) {
|
||||
if ( mAudioStreamId >= 0 ) {
|
||||
mAudioCodecContext = mFormatContext->streams[mAudioStreamId]->codec;
|
||||
if ((mAudioCodec = avcodec_find_decoder(mAudioCodecContext->codec_id)) == NULL) {
|
||||
Debug(1, "Can't find codec for audio stream from %s", mPath.c_str());
|
||||
|
@ -437,7 +433,7 @@ int FfmpegCamera::OpenFfmpeg() {
|
|||
mCanCapture = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
} // int FfmpegCamera::OpenFfmpeg()
|
||||
|
||||
int FfmpegCamera::ReopenFfmpeg() {
|
||||
|
||||
|
@ -462,8 +458,7 @@ int FfmpegCamera::CloseFfmpeg(){
|
|||
av_frame_free( &mRawFrame );
|
||||
|
||||
#if HAVE_LIBSWSCALE
|
||||
if ( mConvertContext )
|
||||
{
|
||||
if ( mConvertContext ) {
|
||||
sws_freeContext( mConvertContext );
|
||||
mConvertContext = NULL;
|
||||
}
|
||||
|
@ -490,8 +485,7 @@ int FfmpegCamera::CloseFfmpeg(){
|
|||
return 0;
|
||||
}
|
||||
|
||||
int FfmpegCamera::FfmpegInterruptCallback(void *ctx)
|
||||
{
|
||||
int FfmpegCamera::FfmpegInterruptCallback(void *ctx) {
|
||||
FfmpegCamera* camera = reinterpret_cast<FfmpegCamera*>(ctx);
|
||||
if (camera->mIsOpening){
|
||||
int now = time(NULL);
|
||||
|
@ -529,14 +523,14 @@ void *FfmpegCamera::ReopenFfmpegThreadCallback(void *ctx){
|
|||
|
||||
//Function to handle capture and store
|
||||
int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event_file ) {
|
||||
if (!mCanCapture){
|
||||
if ( ! mCanCapture ) {
|
||||
return -1;
|
||||
}
|
||||
int ret;
|
||||
static char errbuf[AV_ERROR_MAX_STRING_SIZE];
|
||||
|
||||
// If the reopen thread has a value, but mCanCapture != 0, then we have just reopened the connection to the ffmpeg device, and we can clean up the thread.
|
||||
if (mReopenThread != 0) {
|
||||
if ( mReopenThread != 0 ) {
|
||||
void *retval = 0;
|
||||
|
||||
ret = pthread_join(mReopenThread, &retval);
|
||||
|
@ -548,7 +542,7 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
|
|||
mReopenThread = 0;
|
||||
}
|
||||
|
||||
if (mVideoCodecContext->codec_id != AV_CODEC_ID_H264) {
|
||||
if ( mVideoCodecContext->codec_id != AV_CODEC_ID_H264 ) {
|
||||
Error( "Input stream is not h264. The stored event file may not be viewable in browser." );
|
||||
}
|
||||
|
||||
|
@ -639,6 +633,7 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
|
|||
unsigned int packet_count = 0;
|
||||
ZMPacket *queued_packet;
|
||||
|
||||
// Clear all packets that predate the moment when the recording began
|
||||
packetqueue.clear_unwanted_packets( &recording, mVideoStreamId );
|
||||
|
||||
while ( ( queued_packet = packetqueue.popPacket() ) ) {
|
||||
|
@ -673,7 +668,7 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
|
|||
|
||||
// Buffer video packets, since we are not recording.
|
||||
// All audio packets are keyframes, so only if it's a video keyframe
|
||||
if ( packet.stream_index == mVideoStreamId) {
|
||||
if ( packet.stream_index == mVideoStreamId ) {
|
||||
if ( key_frame ) {
|
||||
Debug(3, "Clearing queue");
|
||||
packetqueue.clearQueue( monitor->GetPreEventCount(), mVideoStreamId );
|
||||
|
@ -689,11 +684,15 @@ else if ( packet.pts && video_last_pts > packet.pts ) {
|
|||
#endif
|
||||
}
|
||||
|
||||
if (
|
||||
( packet.stream_index != mAudioStreamId || record_audio )
|
||||
&&
|
||||
( key_frame || packetqueue.size() )
|
||||
) {
|
||||
// The following lines should ensure that the queue always begins with a video keyframe
|
||||
if ( packet.stream_index == mAudioStreamId ) {
|
||||
//Debug(2, "Have audio packet, reocrd_audio is (%d) and packetqueue.size is (%d)", record_audio, packetqueue.size() );
|
||||
if ( record_audio && packetqueue.size() ) {
|
||||
// if it's audio, and we are doing audio, and there is already something in the queue
|
||||
packetqueue.queuePacket( &packet );
|
||||
}
|
||||
} else if ( packet.stream_index == mVideoStreamId ) {
|
||||
if ( key_frame || packetqueue.size() ) // it's a keyframe or we already have something in the queue
|
||||
packetqueue.queuePacket( &packet );
|
||||
}
|
||||
} // end if recording or not
|
||||
|
@ -779,8 +778,10 @@ else if ( packet.pts && video_last_pts > packet.pts ) {
|
|||
return 0;
|
||||
}
|
||||
} else {
|
||||
Debug(4, "Not recording audio packet" );
|
||||
Debug(4, "Not doing recording of audio packet" );
|
||||
}
|
||||
} else {
|
||||
Debug(4, "Have audio packet, but not recording atm" );
|
||||
}
|
||||
} else {
|
||||
#if LIBAVUTIL_VERSION_CHECK(56, 23, 0, 23, 0)
|
||||
|
|
|
@ -60,14 +60,12 @@ ZMPacket* zm_packetqueue::popPacket( ) {
|
|||
|
||||
unsigned int zm_packetqueue::clearQueue( unsigned int frames_to_keep, int stream_id ) {
|
||||
|
||||
Debug(3, "Clearing all but %d frames", frames_to_keep );
|
||||
Debug(3, "Clearing all but %d frames, queue has %d", frames_to_keep, pktQueue.size() );
|
||||
frames_to_keep += 1;
|
||||
|
||||
if ( pktQueue.empty() ) {
|
||||
Debug(3, "Queue is empty");
|
||||
return 0;
|
||||
} else {
|
||||
Debug(3, "Queue has (%d)", pktQueue.size() );
|
||||
}
|
||||
|
||||
list<ZMPacket *>::reverse_iterator it;
|
||||
|
@ -77,18 +75,19 @@ unsigned int zm_packetqueue::clearQueue( unsigned int frames_to_keep, int stream
|
|||
ZMPacket *zm_packet = *it;
|
||||
AVPacket *av_packet = &(zm_packet->packet);
|
||||
|
||||
Debug(3, "Looking at packet with stream index (%d) with keyframe (%d), frames_to_keep is (%d)", av_packet->stream_index, ( av_packet->flags & AV_PKT_FLAG_KEY ), frames_to_keep );
|
||||
Debug(4, "Looking at packet with stream index (%d) with keyframe (%d), frames_to_keep is (%d)", av_packet->stream_index, ( av_packet->flags & AV_PKT_FLAG_KEY ), frames_to_keep );
|
||||
|
||||
// Want frames_to_keep video keyframes. Otherwise, we may not have enough
|
||||
if ( ( av_packet->stream_index == stream_id) && ( av_packet->flags & AV_PKT_FLAG_KEY ) ) {
|
||||
if (!frames_to_keep)
|
||||
break;
|
||||
frames_to_keep --;
|
||||
}
|
||||
}
|
||||
if ( frames_to_keep ) {
|
||||
Debug(3, "Hit end of queue, still need (%d) video keyframes", frames_to_keep );
|
||||
}
|
||||
unsigned int delete_count = 0;
|
||||
while ( it != pktQueue.rend() ) {
|
||||
Debug(3, "Deleting a packet from the front, count is (%d)", delete_count );
|
||||
Debug(4, "Deleting a packet from the front, count is (%d)", delete_count );
|
||||
|
||||
packet = pktQueue.front();
|
||||
pktQueue.pop_front();
|
||||
|
@ -96,6 +95,7 @@ unsigned int zm_packetqueue::clearQueue( unsigned int frames_to_keep, int stream
|
|||
|
||||
delete_count += 1;
|
||||
}
|
||||
Debug(3, "Deleted (%d) packets", delete_count );
|
||||
return delete_count;
|
||||
} // end unsigned int zm_packetqueue::clearQueue( unsigned int frames_to_keep, int stream_id )
|
||||
|
||||
|
@ -123,10 +123,10 @@ void zm_packetqueue::clear_unwanted_packets( timeval *recording_started, int mVi
|
|||
// Step 2 - pop packets until we get to the packet in step 2
|
||||
list<ZMPacket *>::reverse_iterator it;
|
||||
|
||||
Debug(3, "Looking for keyframe after start recording stream id (%d)", mVideoStreamId );
|
||||
for ( it = pktQueue.rbegin(); it != pktQueue.rend(); ++ it ) {
|
||||
ZMPacket *zm_packet = *it;
|
||||
AVPacket *av_packet = &(zm_packet->packet);
|
||||
Debug(1, "Looking for keyframe after start" );
|
||||
if (
|
||||
( av_packet->flags & AV_PKT_FLAG_KEY )
|
||||
&&
|
||||
|
@ -134,7 +134,7 @@ Debug(1, "Looking for keyframe after start" );
|
|||
&&
|
||||
timercmp( &(zm_packet->timestamp), recording_started, < )
|
||||
) {
|
||||
Debug(1, "Found keyframe before start" );
|
||||
Debug(3, "Found keyframe before start with stream index (%d) with keyframe (%d)", av_packet->stream_index, ( av_packet->flags & AV_PKT_FLAG_KEY ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -143,10 +143,29 @@ Debug(1, "Found keyframe before start" );
|
|||
return;
|
||||
}
|
||||
|
||||
ZMPacket *zm_packet = *it;
|
||||
AVPacket *av_packet = &(zm_packet->packet);
|
||||
Debug(3, "Found packet before start with stream index (%d) with keyframe (%d), distance(%d), size(%d)",
|
||||
av_packet->stream_index,
|
||||
( av_packet->flags & AV_PKT_FLAG_KEY ),
|
||||
distance( it, pktQueue.rend() ),
|
||||
pktQueue.size() );
|
||||
|
||||
unsigned int deleted_frames = 0;
|
||||
ZMPacket *packet = NULL;
|
||||
while ( pktQueue.rend() != it ) {
|
||||
while ( distance( it, pktQueue.rend() ) > 1 ) {
|
||||
//while ( pktQueue.rend() != it ) {
|
||||
packet = pktQueue.front();
|
||||
pktQueue.pop_front();
|
||||
delete packet;
|
||||
deleted_frames += 1;
|
||||
}
|
||||
|
||||
zm_packet = pktQueue.front();
|
||||
av_packet = &(zm_packet->packet);
|
||||
if ( ( ! ( av_packet->flags & AV_PKT_FLAG_KEY ) ) || ( av_packet->stream_index != mVideoStreamId ) ) {
|
||||
Error( "Done looking for keyframe. Deleted %d frames. Remaining frames in queue: %d stream of head packet is (%d), keyframe (%d), distance(%d), packets(%d)", deleted_frames, pktQueue.size(), av_packet->stream_index, ( av_packet->flags & AV_PKT_FLAG_KEY ), distance( it, pktQueue.rend() ), pktQueue.size() );
|
||||
} else {
|
||||
Debug(1, "Done looking for keyframe. Deleted %d frames. Remaining frames in queue: %d stream of head packet is (%d), keyframe (%d), distance(%d), packets(%d)", deleted_frames, pktQueue.size(), av_packet->stream_index, ( av_packet->flags & AV_PKT_FLAG_KEY ), distance( it, pktQueue.rend() ), pktQueue.size() );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include "zm.h"
|
||||
#include "zm_videostore.h"
|
||||
|
||||
extern "C"{
|
||||
extern "C" {
|
||||
#include "libavutil/time.h"
|
||||
}
|
||||
|
||||
|
@ -37,23 +37,23 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
|
|||
int64_t nStartTime,
|
||||
Monitor * monitor
|
||||
) {
|
||||
|
||||
video_input_stream = p_video_input_stream;
|
||||
audio_input_stream = p_audio_input_stream;
|
||||
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
|
||||
video_input_context = avcodec_alloc_context3( NULL );
|
||||
avcodec_parameters_to_context( video_input_context, video_input_stream->codecpar );
|
||||
#else
|
||||
video_input_context = video_input_stream->codec;
|
||||
#endif
|
||||
|
||||
//store inputs in variables local to class
|
||||
filename = filename_in;
|
||||
format = format_in;
|
||||
|
||||
keyframeMessage = false;
|
||||
keyframeSkipNumber = 0;
|
||||
|
||||
Info("Opening video storage stream %s format: %s\n", filename, format);
|
||||
|
||||
//Init everything we need, shouldn't have to do this, ffmpeg_camera or something else will call it.
|
||||
//av_register_all();
|
||||
|
||||
ret = avformat_alloc_output_context2(&oc, NULL, NULL, filename);
|
||||
if ( ret < 0 ) {
|
||||
Warning("Could not create video storage stream %s as no output context"
|
||||
|
@ -62,11 +62,11 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
|
|||
av_make_error_string(ret).c_str()
|
||||
);
|
||||
} else {
|
||||
Debug(2, "Success alocateing output context");
|
||||
Debug(2, "Success allocating output context");
|
||||
}
|
||||
|
||||
//Couldn't deduce format from filename, trying from format name
|
||||
if (!oc) {
|
||||
if ( ! oc ) {
|
||||
avformat_alloc_output_context2(&oc, NULL, format, filename);
|
||||
if (!oc) {
|
||||
Fatal("Could not create video storage stream %s as no output context"
|
||||
|
@ -82,29 +82,47 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
|
|||
if (dsr < 0) Warning("%s:%d: title set failed", __FILE__, __LINE__ );
|
||||
|
||||
oc->metadata = pmetadata;
|
||||
|
||||
output_format = oc->oformat;
|
||||
|
||||
video_output_stream = avformat_new_stream(oc, (AVCodec*)video_input_context->codec);
|
||||
if (!video_output_stream) {
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
|
||||
// Since we are not re-encoding, all we have to do is copy the parameters
|
||||
video_output_context = avcodec_alloc_context3( NULL );
|
||||
|
||||
// Copy params from inputstream to context
|
||||
ret = avcodec_parameters_to_context( video_output_context, video_input_stream->codecpar );
|
||||
if ( ret < 0 ) {
|
||||
Error( "Could not initialize context parameteres");
|
||||
return;
|
||||
} else {
|
||||
Debug( 2, "Success getting parameters");
|
||||
}
|
||||
|
||||
video_output_stream = avformat_new_stream( oc, NULL );
|
||||
if ( ! video_output_stream ) {
|
||||
Fatal("Unable to create video out stream\n");
|
||||
} else {
|
||||
Debug(2, "Success creating video out stream" );
|
||||
}
|
||||
|
||||
video_output_context = video_output_stream->codec;
|
||||
|
||||
#if LIBAVCODEC_VERSION_CHECK(58, 0, 0, 0, 0)
|
||||
Debug(2, "setting parameters");
|
||||
ret = avcodec_parameters_to_context( video_output_context, video_input_stream->codecpar );
|
||||
// Now copy them to the output stream
|
||||
ret = avcodec_parameters_from_context( video_output_stream->codecpar, video_output_context );
|
||||
if ( ret < 0 ) {
|
||||
Error( "Could not initialize stream parameteres");
|
||||
return;
|
||||
} else {
|
||||
Debug(2, "Success getting parameters");
|
||||
Debug(2, "Success setting parameters");
|
||||
}
|
||||
|
||||
zm_dump_stream_format( oc, 0, 0, 1 );
|
||||
#else
|
||||
ret = avcodec_copy_context(video_output_context, video_input_context );
|
||||
video_output_stream = avformat_new_stream(oc, (AVCodec*)video_input_context->codec );
|
||||
if ( ! video_output_stream ) {
|
||||
Fatal("Unable to create video out stream\n");
|
||||
} else {
|
||||
Debug(2, "Success creating video out stream" );
|
||||
}
|
||||
video_output_context = video_output_stream->codec;
|
||||
ret = avcodec_copy_context( video_output_context, video_input_context );
|
||||
if (ret < 0) {
|
||||
Fatal("Unable to copy input video context to output video context %s\n",
|
||||
av_make_error_string(ret).c_str());
|
||||
|
@ -130,7 +148,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
|
|||
|
||||
// WHY?
|
||||
//video_output_context->codec_tag = 0;
|
||||
if (!video_output_context->codec_tag) {
|
||||
if ( ! video_output_context->codec_tag ) {
|
||||
Debug(2, "No codec_tag");
|
||||
if (! oc->oformat->codec_tag
|
||||
|| av_codec_get_id (oc->oformat->codec_tag, video_input_context->codec_tag) == video_output_context->codec_id
|
||||
|
@ -145,6 +163,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
|
|||
}
|
||||
|
||||
Monitor::Orientation orientation = monitor->getOrientation();
|
||||
Debug(3, "Have orientation" );
|
||||
if ( orientation ) {
|
||||
if ( orientation == Monitor::ROTATE_0 ) {
|
||||
|
||||
|
@ -169,13 +188,22 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
|
|||
resample_context = NULL;
|
||||
#endif
|
||||
|
||||
if (audio_input_stream) {
|
||||
if ( audio_input_stream ) {
|
||||
Debug(3, "Have audio stream" );
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
|
||||
|
||||
audio_input_context = avcodec_alloc_context3( NULL );
|
||||
ret = avcodec_parameters_to_context( audio_input_context, audio_input_stream->codecpar );
|
||||
#else
|
||||
audio_input_context = audio_input_stream->codec;
|
||||
#endif
|
||||
|
||||
if ( audio_input_context->codec_id != AV_CODEC_ID_AAC ) {
|
||||
static char error_buffer[256];
|
||||
avcodec_string(error_buffer, sizeof(error_buffer), audio_input_context, 0 );
|
||||
Debug(3, "Got something other than AAC (%s)", error_buffer );
|
||||
Debug(2, "Got something other than AAC (%s)", error_buffer );
|
||||
|
||||
|
||||
if ( ! setup_resampler() ) {
|
||||
return;
|
||||
}
|
||||
|
@ -187,9 +215,16 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
|
|||
Error("Unable to create audio out stream\n");
|
||||
audio_output_stream = NULL;
|
||||
} else {
|
||||
audio_output_context = audio_output_stream->codec;
|
||||
Debug(2, "setting parameters");
|
||||
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
|
||||
audio_output_context = avcodec_alloc_context3( NULL );
|
||||
// Copy params from inputstream to context
|
||||
ret = avcodec_parameters_to_context( audio_output_context, audio_input_stream->codecpar );
|
||||
#else
|
||||
audio_output_context = audio_output_stream->codec;
|
||||
ret = avcodec_copy_context(audio_output_context, audio_input_context);
|
||||
#endif
|
||||
if (ret < 0) {
|
||||
Error("Unable to copy audio context %s\n", av_make_error_string(ret).c_str());
|
||||
audio_output_stream = NULL;
|
||||
|
@ -233,7 +268,8 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
|
|||
//av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0);
|
||||
//av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0);
|
||||
//av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov+default_base_moof", 0);
|
||||
if ((ret = avformat_write_header(oc, &opts)) < 0) {
|
||||
if ((ret = avformat_write_header(oc, NULL)) < 0) {
|
||||
//if ((ret = avformat_write_header(oc, &opts)) < 0) {
|
||||
Warning("Unable to set movflags to frag_custom+dash+delay_moov");
|
||||
/* Write the stream header, if any. */
|
||||
ret = avformat_write_header(oc, NULL);
|
||||
|
@ -252,8 +288,10 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
|
|||
video_last_dts = 0;
|
||||
audio_last_pts = 0;
|
||||
audio_last_dts = 0;
|
||||
previous_pts = 0;
|
||||
previous_dts = 0;
|
||||
video_previous_pts = 0;
|
||||
video_previous_dts = 0;
|
||||
audio_previous_pts = 0;
|
||||
audio_previous_dts = 0;
|
||||
|
||||
} // VideoStore::VideoStore
|
||||
|
||||
|
@ -262,14 +300,14 @@ VideoStore::~VideoStore(){
|
|||
if ( audio_output_codec ) {
|
||||
// Do we need to flush the outputs? I have no idea.
|
||||
AVPacket pkt;
|
||||
int got_packet;
|
||||
int got_packet = 0;
|
||||
av_init_packet(&pkt);
|
||||
pkt.data = NULL;
|
||||
pkt.size = 0;
|
||||
int64_t size;
|
||||
|
||||
while(1) {
|
||||
#if LIBAVCODEC_VERSION_CHECK(58, 0, 0, 0, 0)
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
|
||||
ret = avcodec_receive_packet( audio_output_context, &pkt );
|
||||
#else
|
||||
ret = avcodec_encode_audio2( audio_output_context, &pkt, NULL, &got_packet );
|
||||
|
@ -341,6 +379,18 @@ bool VideoStore::setup_resampler() {
|
|||
#ifdef HAVE_LIBAVRESAMPLE
|
||||
static char error_buffer[256];
|
||||
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
|
||||
// Newer ffmpeg wants to keep everything separate... so have to lookup our own decoder, can't reuse the one from the camera.
|
||||
AVCodec *audio_input_codec = avcodec_find_decoder(audio_input_stream->codecpar->codec_id);
|
||||
#else
|
||||
AVCodec *audio_input_codec = avcodec_find_decoder(audio_input_context->codec_id);
|
||||
#endif
|
||||
ret = avcodec_open2( audio_input_context, audio_input_codec, NULL );
|
||||
if ( ret < 0 ) {
|
||||
Error("Can't open input codec!");
|
||||
return false;
|
||||
}
|
||||
|
||||
audio_output_codec = avcodec_find_encoder(AV_CODEC_ID_AAC);
|
||||
if ( ! audio_output_codec ) {
|
||||
Error("Could not find codec for AAC");
|
||||
|
@ -348,8 +398,8 @@ bool VideoStore::setup_resampler() {
|
|||
}
|
||||
Debug(2, "Have audio output codec");
|
||||
|
||||
audio_output_stream = avformat_new_stream( oc, audio_output_codec );
|
||||
audio_output_context = audio_output_stream->codec;
|
||||
//audio_output_context = audio_output_stream->codec;
|
||||
audio_output_context = avcodec_alloc_context3( audio_output_codec );
|
||||
|
||||
if ( ! audio_output_context ) {
|
||||
Error( "could not allocate codec context for AAC\n");
|
||||
|
@ -359,18 +409,15 @@ bool VideoStore::setup_resampler() {
|
|||
|
||||
Debug(2, "Have audio_output_context");
|
||||
|
||||
AVDictionary *opts = NULL;
|
||||
av_dict_set(&opts, "strict", "experimental", 0);
|
||||
|
||||
/* put sample parameters */
|
||||
audio_output_context->bit_rate = audio_input_context->bit_rate;
|
||||
audio_output_context->sample_rate = audio_input_context->sample_rate;
|
||||
audio_output_context->channels = audio_input_context->channels;
|
||||
audio_output_context->channel_layout = audio_input_context->channel_layout;
|
||||
audio_output_context->sample_fmt = audio_input_context->sample_fmt;
|
||||
//audio_output_context->refcounted_frames = 1;
|
||||
audio_output_context->refcounted_frames = 1;
|
||||
|
||||
if (audio_output_codec->supported_samplerates) {
|
||||
if ( audio_output_codec->supported_samplerates ) {
|
||||
int found = 0;
|
||||
for ( unsigned int i = 0; audio_output_codec->supported_samplerates[i]; i++) {
|
||||
if ( audio_output_context->sample_rate == audio_output_codec->supported_samplerates[i] ) {
|
||||
|
@ -387,36 +434,14 @@ bool VideoStore::setup_resampler() {
|
|||
}
|
||||
|
||||
/* check that the encoder supports s16 pcm input */
|
||||
if (!check_sample_fmt( audio_output_codec, audio_output_context->sample_fmt)) {
|
||||
if ( ! check_sample_fmt( audio_output_codec, audio_output_context->sample_fmt ) ) {
|
||||
Debug( 3, "Encoder does not support sample format %s, setting to FLTP",
|
||||
av_get_sample_fmt_name( audio_output_context->sample_fmt));
|
||||
audio_output_context->sample_fmt = AV_SAMPLE_FMT_FLTP;
|
||||
}
|
||||
|
||||
//audio_output_stream->time_base = audio_input_stream->time_base;
|
||||
audio_output_context->time_base = (AVRational){ 1, audio_output_context->sample_rate };
|
||||
|
||||
Debug(3, "Audio Time bases input stream (%d/%d) input codec: (%d/%d) output_stream (%d/%d) output codec (%d/%d)",
|
||||
audio_input_stream->time_base.num,
|
||||
audio_input_stream->time_base.den,
|
||||
audio_input_context->time_base.num,
|
||||
audio_input_context->time_base.den,
|
||||
audio_output_stream->time_base.num,
|
||||
audio_output_stream->time_base.den,
|
||||
audio_output_context->time_base.num,
|
||||
audio_output_context->time_base.den
|
||||
);
|
||||
|
||||
ret = avcodec_open2(audio_output_context, audio_output_codec, &opts );
|
||||
av_dict_free(&opts);
|
||||
if ( ret < 0 ) {
|
||||
av_strerror(ret, error_buffer, sizeof(error_buffer));
|
||||
Fatal( "could not open codec (%d) (%s)\n", ret, error_buffer );
|
||||
audio_output_codec = NULL;
|
||||
audio_output_context = NULL;
|
||||
audio_output_stream = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
Debug(1, "Audio output bit_rate (%d) sample_rate(%d) channels(%d) fmt(%d) layout(%d) frame_size(%d)",
|
||||
audio_output_context->bit_rate,
|
||||
|
@ -427,7 +452,28 @@ bool VideoStore::setup_resampler() {
|
|||
audio_output_context->frame_size
|
||||
);
|
||||
|
||||
output_frame_size = audio_output_context->frame_size;
|
||||
// Now copy them to the output stream
|
||||
audio_output_stream = avformat_new_stream( oc, audio_output_codec );
|
||||
|
||||
ret = avcodec_parameters_from_context( audio_output_stream->codecpar, audio_output_context );
|
||||
if ( ret < 0 ) {
|
||||
Error( "Could not initialize stream parameteres");
|
||||
return false;
|
||||
}
|
||||
|
||||
AVDictionary *opts = NULL;
|
||||
av_dict_set( &opts, "strict", "experimental", 0);
|
||||
ret = avcodec_open2( audio_output_context, audio_output_codec, &opts );
|
||||
av_dict_free(&opts);
|
||||
if ( ret < 0 ) {
|
||||
av_strerror(ret, error_buffer, sizeof(error_buffer));
|
||||
Fatal( "could not open codec (%d) (%s)\n", ret, error_buffer );
|
||||
audio_output_codec = NULL;
|
||||
audio_output_context = NULL;
|
||||
audio_output_stream = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Create a new frame to store the audio samples. */
|
||||
if (!(input_frame = zm_av_frame_alloc())) {
|
||||
Error("Could not allocate input frame");
|
||||
|
@ -562,9 +608,9 @@ int VideoStore::writeVideoFramePacket( AVPacket *ipkt ) {
|
|||
if ( ipkt->pts < video_last_pts ) {
|
||||
Debug(1, "Resetting video_last_pts from (%d) to (%d)", video_last_pts, ipkt->pts );
|
||||
// wrap around, need to figure out the distance FIXME having this wrong should cause a jump, but then play ok?
|
||||
opkt.pts = previous_pts + av_rescale_q( ipkt->pts, video_input_stream->time_base, video_output_stream->time_base);
|
||||
opkt.pts = video_previous_pts + av_rescale_q( ipkt->pts, video_input_stream->time_base, video_output_stream->time_base);
|
||||
} else {
|
||||
opkt.pts = previous_pts + av_rescale_q( ipkt->pts - video_last_pts, video_input_stream->time_base, video_output_stream->time_base);
|
||||
opkt.pts = video_previous_pts + av_rescale_q( ipkt->pts - video_last_pts, video_input_stream->time_base, video_output_stream->time_base);
|
||||
}
|
||||
}
|
||||
Debug(3, "opkt.pts = %d from ipkt->pts(%d) - last_pts(%d)", opkt.pts, ipkt->pts, video_last_pts );
|
||||
|
@ -588,24 +634,20 @@ int VideoStore::writeVideoFramePacket( AVPacket *ipkt ) {
|
|||
// why are we using cur_dts instead of packet.dts? I think cur_dts is in AV_TIME_BASE_Q, but ipkt.dts is in video_input_stream->time_base
|
||||
if ( video_input_stream->cur_dts < video_last_dts ) {
|
||||
Debug(1, "Resetting video_last_dts from (%d) to (%d) p.dts was (%d)", video_last_dts, video_input_stream->cur_dts, ipkt->dts );
|
||||
opkt.dts = previous_dts + av_rescale_q(video_input_stream->cur_dts, AV_TIME_BASE_Q, video_output_stream->time_base);
|
||||
opkt.dts = video_previous_dts + av_rescale_q(video_input_stream->cur_dts, AV_TIME_BASE_Q, video_output_stream->time_base);
|
||||
} else {
|
||||
opkt.dts = previous_dts + av_rescale_q(video_input_stream->cur_dts - video_last_dts, AV_TIME_BASE_Q, video_output_stream->time_base);
|
||||
opkt.dts = video_previous_dts + av_rescale_q(video_input_stream->cur_dts - video_last_dts, AV_TIME_BASE_Q, video_output_stream->time_base);
|
||||
}
|
||||
Debug(3, "opkt.dts = %d from video_input_stream->cur_dts(%d) - previus_dts(%d)",
|
||||
opkt.dts, video_input_stream->cur_dts, video_last_dts
|
||||
);
|
||||
Debug(3, "opkt.dts = %d from video_input_stream->cur_dts(%d) - previus_dts(%d)", opkt.dts, video_input_stream->cur_dts, video_last_dts );
|
||||
video_last_dts = video_input_stream->cur_dts;
|
||||
} else {
|
||||
if ( ipkt->dts < video_last_dts ) {
|
||||
Debug(1, "Resetting video_last_dts from (%d) to (%d)", video_last_dts, ipkt->dts );
|
||||
opkt.dts = previous_dts + av_rescale_q( ipkt->dts, video_input_stream->time_base, video_output_stream->time_base);
|
||||
opkt.dts = video_previous_dts + av_rescale_q( ipkt->dts, video_input_stream->time_base, video_output_stream->time_base);
|
||||
} else {
|
||||
opkt.dts = previous_dts + av_rescale_q( ipkt->dts - video_last_dts, video_input_stream->time_base, video_output_stream->time_base);
|
||||
opkt.dts = video_previous_dts + av_rescale_q( ipkt->dts - video_last_dts, video_input_stream->time_base, video_output_stream->time_base);
|
||||
}
|
||||
Debug(3, "opkt.dts = %d from ipkt.dts(%d) - previus_dts(%d)",
|
||||
opkt.dts, ipkt->dts, video_last_dts
|
||||
);
|
||||
Debug(3, "opkt.dts = %d from ipkt.dts(%d) - previus_dts(%d)", opkt.dts, ipkt->dts, video_last_dts );
|
||||
video_last_dts = ipkt->dts;
|
||||
}
|
||||
}
|
||||
|
@ -642,15 +684,15 @@ Debug(1, "writing video packet pts(%d) dts(%d) duration(%d)", opkt.pts, opkt.dts
|
|||
dumpPacket( ipkt);
|
||||
dumpPacket(&opkt);
|
||||
|
||||
} else if ((previous_dts > 0) && (previous_dts > opkt.dts)) {
|
||||
Warning("%s:%d: DTS out of order: %lld \u226E %lld; discarding frame", __FILE__, __LINE__, previous_dts, opkt.dts);
|
||||
previous_dts = opkt.dts;
|
||||
} else if ((video_previous_dts > 0) && (video_previous_dts > opkt.dts)) {
|
||||
Warning("%s:%d: DTS out of order: %lld \u226E %lld; discarding frame", __FILE__, __LINE__, video_previous_dts, opkt.dts);
|
||||
video_previous_dts = opkt.dts;
|
||||
dumpPacket(&opkt);
|
||||
|
||||
} else {
|
||||
|
||||
previous_dts = opkt.dts; // Unsure if av_interleaved_write_frame() clobbers opkt.dts when out of order, so storing in advance
|
||||
previous_pts = opkt.pts;
|
||||
video_previous_dts = opkt.dts; // Unsure if av_interleaved_write_frame() clobbers opkt.dts when out of order, so storing in advance
|
||||
video_previous_pts = opkt.pts;
|
||||
ret = av_interleaved_write_frame(oc, &opkt);
|
||||
if(ret<0){
|
||||
// There's nothing we can really do if the frame is rejected, just drop it and get on with the next
|
||||
|
@ -663,21 +705,20 @@ Debug(1, "writing video packet pts(%d) dts(%d) duration(%d)", opkt.pts, opkt.dts
|
|||
|
||||
return 0;
|
||||
|
||||
}
|
||||
} // end int VideoStore::writeVideoFramePacket( AVPacket *ipkt )
|
||||
|
||||
int VideoStore::writeAudioFramePacket( AVPacket *ipkt ) {
|
||||
Debug(4, "writeAudioFrame");
|
||||
|
||||
if(!audio_output_stream) {
|
||||
if ( ! audio_output_stream ) {
|
||||
Debug(1, "Called writeAudioFramePacket when no audio_output_stream");
|
||||
return 0;//FIXME -ve return codes do not free packet in ffmpeg_camera at the moment
|
||||
}
|
||||
|
||||
|
||||
if ( audio_output_codec ) {
|
||||
#ifdef HAVE_LIBAVRESAMPLE
|
||||
|
||||
#if 0
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
|
||||
ret = avcodec_send_packet( audio_input_context, ipkt );
|
||||
if ( ret < 0 ) {
|
||||
Error("avcodec_send_packet fail %s", av_make_error_string(ret).c_str());
|
||||
|
@ -696,26 +737,7 @@ int VideoStore::writeAudioFramePacket( AVPacket *ipkt ) {
|
|||
input_frame->channel_layout,
|
||||
audio_output_context->refcounted_frames
|
||||
);
|
||||
|
||||
ret = avcodec_send_frame( audio_output_context, input_frame );
|
||||
if ( ret < 0 ) {
|
||||
av_frame_unref( input_frame );
|
||||
Error("avcodec_send_frame fail(%d), %s codec is open(%d) is_encoder(%d)", ret, av_make_error_string(ret).c_str(),
|
||||
avcodec_is_open( audio_output_context ),
|
||||
av_codec_is_encoder( audio_output_context->codec)
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
ret = avcodec_receive_packet( audio_output_context, &opkt );
|
||||
if ( ret < 0 ) {
|
||||
av_frame_unref( input_frame );
|
||||
Error("avcodec_receive_packet fail %s", av_make_error_string(ret).c_str());
|
||||
return 0;
|
||||
}
|
||||
av_frame_unref( input_frame );
|
||||
#else
|
||||
|
||||
|
||||
/**
|
||||
* Decode the audio frame stored in the packet.
|
||||
* The input audio stream decoder is used to do this.
|
||||
|
@ -728,15 +750,13 @@ int VideoStore::writeAudioFramePacket( AVPacket *ipkt ) {
|
|||
av_make_error_string(ret).c_str());
|
||||
dumpPacket( ipkt );
|
||||
av_frame_free( &input_frame );
|
||||
zm_av_packet_unref( &opkt );
|
||||
return 0;
|
||||
}
|
||||
if ( ! data_present ) {
|
||||
Debug(2, "Not ready to transcode a frame yet.");
|
||||
zm_av_packet_unref(&opkt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
int frame_size = input_frame->nb_samples;
|
||||
Debug(4, "Frame size: %d", frame_size );
|
||||
|
||||
|
@ -778,11 +798,22 @@ int VideoStore::writeAudioFramePacket( AVPacket *ipkt ) {
|
|||
* Encode the audio frame and store it in the temporary packet.
|
||||
* The output audio stream encoder is used to do this.
|
||||
*/
|
||||
#if LIBAVCODEC_VERSION_CHECK(58, 0, 0, 0, 0)
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 0, 0, 0, 0)
|
||||
if (( ret = avcodec_send_frame( audio_output_context, output_frame ) ) < 0 ) {
|
||||
Error( "Could not send frame (error '%s')",
|
||||
av_make_error_string(ret).c_str());
|
||||
zm_av_packet_unref(&opkt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (( ret = avcodec_receive_packet( audio_output_context, &opkt )) < 0 ) {
|
||||
Error( "Could not recieve packet (error '%s')",
|
||||
av_make_error_string(ret).c_str());
|
||||
zm_av_packet_unref(&opkt);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
if (( ret = avcodec_encode_audio2( audio_output_context, &opkt, output_frame, &data_present )) < 0) {
|
||||
#endif
|
||||
Error( "Could not encode frame (error '%s')",
|
||||
av_make_error_string(ret).c_str());
|
||||
zm_av_packet_unref(&opkt);
|
||||
|
@ -793,8 +824,8 @@ int VideoStore::writeAudioFramePacket( AVPacket *ipkt ) {
|
|||
zm_av_packet_unref(&opkt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
} else {
|
||||
av_init_packet(&opkt);
|
||||
|
@ -807,14 +838,17 @@ int VideoStore::writeAudioFramePacket( AVPacket *ipkt ) {
|
|||
|
||||
//Scale the PTS of the outgoing packet to be the correct time base
|
||||
if ( ipkt->pts != AV_NOPTS_VALUE ) {
|
||||
if ( !audio_last_pts ) {
|
||||
if ( ! audio_last_pts ) {
|
||||
opkt.pts = 0;
|
||||
Debug(1, "No audio_last_pts");
|
||||
} else {
|
||||
if ( audio_last_pts > ipkt->pts ) {
|
||||
Debug(1, "Resetting audeo_start_pts from (%d) to (%d)", audio_last_pts, ipkt->pts );
|
||||
opkt.pts = audio_previous_pts + av_rescale_q(ipkt->pts, audio_input_stream->time_base, audio_output_stream->time_base);
|
||||
} else {
|
||||
opkt.pts = audio_previous_pts + av_rescale_q(ipkt->pts - audio_last_pts, audio_input_stream->time_base, audio_output_stream->time_base);
|
||||
}
|
||||
opkt.pts = previous_pts + av_rescale_q(ipkt->pts - audio_last_pts, audio_input_stream->time_base, audio_output_stream->time_base);
|
||||
Debug(2, "opkt.pts = %d from ipkt->pts(%d) - last_pts(%d)", opkt.pts, ipkt->pts, audio_last_pts );
|
||||
Debug(2, "audio opkt.pts = %d from ipkt->pts(%d) - last_pts(%d)", opkt.pts, ipkt->pts, audio_last_pts );
|
||||
}
|
||||
audio_last_pts = ipkt->pts;
|
||||
} else {
|
||||
|
@ -825,28 +859,30 @@ int VideoStore::writeAudioFramePacket( AVPacket *ipkt ) {
|
|||
//Scale the DTS of the outgoing packet to be the correct time base
|
||||
if ( ! audio_last_dts ) {
|
||||
opkt.dts = 0;
|
||||
|
||||
} else {
|
||||
if( ipkt->dts == AV_NOPTS_VALUE ) {
|
||||
// So if the input has no dts assigned... still need an output dts... so we use cur_dts?
|
||||
|
||||
if ( audio_last_dts > audio_input_stream->cur_dts ) {
|
||||
Debug(1, "Resetting audio_last_pts from (%d) to cur_dts (%d)", audio_last_dts, audio_input_stream->cur_dts );
|
||||
opkt.dts = previous_dts + av_rescale_q( audio_input_stream->cur_dts, AV_TIME_BASE_Q, audio_output_stream->time_base);
|
||||
Debug(1, "Resetting audio_last_dts from (%d) to cur_dts (%d)", audio_last_dts, audio_input_stream->cur_dts );
|
||||
opkt.dts = audio_previous_dts + av_rescale_q( audio_input_stream->cur_dts, AV_TIME_BASE_Q, audio_output_stream->time_base);
|
||||
} else {
|
||||
opkt.dts = previous_dts + av_rescale_q( audio_input_stream->cur_dts - audio_last_dts, AV_TIME_BASE_Q, audio_output_stream->time_base);
|
||||
opkt.dts = audio_previous_dts + av_rescale_q( audio_input_stream->cur_dts - audio_last_dts, AV_TIME_BASE_Q, audio_output_stream->time_base);
|
||||
}
|
||||
audio_last_dts = audio_input_stream->cur_dts;
|
||||
Debug(2, "opkt.dts = %d from video_input_stream->cur_dts(%d) - last_dts(%d)", opkt.dts, audio_input_stream->cur_dts, audio_last_dts );
|
||||
} else {
|
||||
if ( audio_last_dts > ipkt->dts ) {
|
||||
Debug(1, "Resetting audio_last_dts from (%d) to (%d)", audio_last_dts, ipkt->dts );
|
||||
opkt.dts = previous_dts + av_rescale_q(ipkt->dts, audio_input_stream->time_base, audio_output_stream->time_base);
|
||||
opkt.dts = audio_previous_dts + av_rescale_q(ipkt->dts, audio_input_stream->time_base, audio_output_stream->time_base);
|
||||
} else {
|
||||
opkt.dts = previous_dts + av_rescale_q(ipkt->dts - audio_last_dts, audio_input_stream->time_base, audio_output_stream->time_base);
|
||||
opkt.dts = audio_previous_dts + av_rescale_q(ipkt->dts - audio_last_dts, audio_input_stream->time_base, audio_output_stream->time_base);
|
||||
}
|
||||
Debug(2, "opkt.dts = %d from ipkt->dts(%d) - last_dts(%d)", opkt.dts, ipkt->dts, audio_last_dts );
|
||||
}
|
||||
}
|
||||
audio_last_dts = ipkt->dts;
|
||||
if ( opkt.dts > opkt.pts ) {
|
||||
Debug(1,"opkt.dts(%d) must be <= opkt.pts(%d). Decompression must happen before presentation.", opkt.dts, opkt.pts );
|
||||
opkt.dts = opkt.pts;
|
||||
|
@ -854,15 +890,17 @@ int VideoStore::writeAudioFramePacket( AVPacket *ipkt ) {
|
|||
|
||||
// I wonder if we could just use duration instead of all the hoop jumping above?
|
||||
opkt.duration = av_rescale_q(ipkt->duration, audio_input_stream->time_base, audio_output_stream->time_base);
|
||||
Debug( 2, "opkt.pts (%d), opkt.dts(%d) opkt.duration = (%d)", opkt.pts, opkt.dts, opkt.duration );
|
||||
|
||||
// pkt.pos: byte position in stream, -1 if unknown
|
||||
opkt.pos = -1;
|
||||
opkt.flags = ipkt->flags;
|
||||
opkt.stream_index = ipkt->stream_index;
|
||||
Debug(2, "Stream index is %d", opkt.stream_index );
|
||||
|
||||
AVPacket safepkt;
|
||||
memcpy(&safepkt, &opkt, sizeof(AVPacket));
|
||||
audio_previous_dts = opkt.dts; // Unsure if av_interleaved_write_frame() clobbers opkt.dts when out of order, so storing in advance
|
||||
audio_previous_pts = opkt.pts;
|
||||
ret = av_interleaved_write_frame(oc, &opkt);
|
||||
if(ret!=0){
|
||||
Error("Error writing audio frame packet: %s\n", av_make_error_string(ret).c_str());
|
||||
|
|
|
@ -61,8 +61,10 @@ AVAudioResampleContext* resample_context;
|
|||
int64_t audio_last_dts;
|
||||
|
||||
// These are for output, should start at zero. We assume they do not wrap because we just aren't going to save files that big.
|
||||
int64_t previous_pts;
|
||||
int64_t previous_dts;
|
||||
int64_t video_previous_pts;
|
||||
int64_t video_previous_dts;
|
||||
int64_t audio_previous_pts;
|
||||
int64_t audio_previous_dts;
|
||||
|
||||
int64_t filter_in_rescale_delta_last;
|
||||
|
||||
|
|
251
src/zmu.cpp
251
src/zmu.cpp
|
@ -95,8 +95,7 @@ Options for use with monitors:
|
|||
#include "zm_monitor.h"
|
||||
#include "zm_local_camera.h"
|
||||
|
||||
void Usage( int status=-1 )
|
||||
{
|
||||
void Usage( int status=-1 ) {
|
||||
fprintf( stderr, "zmu <-d device_path> [-v] [function] [-U<username> -P<password>]\n" );
|
||||
fprintf( stderr, "zmu <-m monitor_id> [-v] [function] [-U<username> -P<password>]\n" );
|
||||
fprintf( stderr, "General options:\n" );
|
||||
|
@ -167,48 +166,38 @@ typedef enum {
|
|||
ZMU_LIST = 0x10000000,
|
||||
} Function;
|
||||
|
||||
bool ValidateAccess( User *user, int mon_id, int function )
|
||||
{
|
||||
bool ValidateAccess( User *user, int mon_id, int function ) {
|
||||
bool allowed = true;
|
||||
if ( function & (ZMU_STATE|ZMU_IMAGE|ZMU_TIME|ZMU_READ_IDX|ZMU_WRITE_IDX|ZMU_FPS) )
|
||||
{
|
||||
if ( function & (ZMU_STATE|ZMU_IMAGE|ZMU_TIME|ZMU_READ_IDX|ZMU_WRITE_IDX|ZMU_FPS) ) {
|
||||
if ( user->getStream() < User::PERM_VIEW )
|
||||
allowed = false;
|
||||
}
|
||||
if ( function & ZMU_EVENT )
|
||||
{
|
||||
if ( function & ZMU_EVENT ) {
|
||||
if ( user->getEvents() < User::PERM_VIEW )
|
||||
allowed = false;
|
||||
}
|
||||
if ( function & (ZMU_ZONES|ZMU_QUERY|ZMU_LIST) )
|
||||
{
|
||||
if ( function & (ZMU_ZONES|ZMU_QUERY|ZMU_LIST) ) {
|
||||
if ( user->getMonitors() < User::PERM_VIEW )
|
||||
allowed = false;
|
||||
}
|
||||
if ( function & (ZMU_ALARM|ZMU_NOALARM|ZMU_CANCEL|ZMU_RELOAD|ZMU_ENABLE|ZMU_DISABLE|ZMU_SUSPEND|ZMU_RESUME|ZMU_BRIGHTNESS|ZMU_CONTRAST|ZMU_HUE|ZMU_COLOUR) )
|
||||
{
|
||||
if ( function & (ZMU_ALARM|ZMU_NOALARM|ZMU_CANCEL|ZMU_RELOAD|ZMU_ENABLE|ZMU_DISABLE|ZMU_SUSPEND|ZMU_RESUME|ZMU_BRIGHTNESS|ZMU_CONTRAST|ZMU_HUE|ZMU_COLOUR) ) {
|
||||
if ( user->getMonitors() < User::PERM_EDIT )
|
||||
allowed = false;
|
||||
}
|
||||
if ( mon_id > 0 )
|
||||
{
|
||||
if ( !user->canAccess( mon_id ) )
|
||||
{
|
||||
if ( mon_id > 0 ) {
|
||||
if ( !user->canAccess( mon_id ) ) {
|
||||
allowed = false;
|
||||
}
|
||||
}
|
||||
if ( !allowed )
|
||||
{
|
||||
if ( !allowed ) {
|
||||
fprintf( stderr, "Error, insufficient privileges for requested action\n" );
|
||||
exit( -1 );
|
||||
}
|
||||
return( allowed );
|
||||
}
|
||||
|
||||
int main( int argc, char *argv[] )
|
||||
{
|
||||
if ( access(ZM_CONFIG, R_OK) != 0 )
|
||||
{
|
||||
int main( int argc, char *argv[] ) {
|
||||
if ( access(ZM_CONFIG, R_OK) != 0 ) {
|
||||
fprintf( stderr, "Can't open %s: %s\n", ZM_CONFIG, strerror(errno) );
|
||||
exit( -1 );
|
||||
}
|
||||
|
@ -274,18 +263,15 @@ int main( int argc, char *argv[] )
|
|||
int v4lVersion = 1;
|
||||
#endif // ZM_HAS_V4L2/1
|
||||
#endif // ZM_HAS_V4L
|
||||
while (1)
|
||||
{
|
||||
while (1) {
|
||||
int option_index = 0;
|
||||
|
||||
int c = getopt_long (argc, argv, "d:m:vsEDLurwei::S:t::fz::ancqhlB::C::H::O::U:P:A:V:", long_options, &option_index);
|
||||
if (c == -1)
|
||||
{
|
||||
if (c == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
switch (c)
|
||||
{
|
||||
switch (c) {
|
||||
case 'd':
|
||||
if ( optarg )
|
||||
device = optarg;
|
||||
|
@ -385,6 +371,7 @@ int main( int argc, char *argv[] )
|
|||
case 'A':
|
||||
auth = optarg;
|
||||
break;
|
||||
>>>>>>> master
|
||||
#if ZM_HAS_V4L
|
||||
case 'V':
|
||||
v4lVersion = (atoi(optarg)==1)?1:2;
|
||||
|
@ -405,8 +392,7 @@ int main( int argc, char *argv[] )
|
|||
}
|
||||
}
|
||||
|
||||
if (optind < argc)
|
||||
{
|
||||
if (optind < argc) {
|
||||
fprintf( stderr, "Extraneous options, " );
|
||||
while (optind < argc)
|
||||
fprintf( stderr, "%s ", argv[optind++]);
|
||||
|
@ -414,13 +400,11 @@ int main( int argc, char *argv[] )
|
|||
Usage();
|
||||
}
|
||||
|
||||
if ( device && !(function&ZMU_QUERY) )
|
||||
{
|
||||
if ( device && !(function&ZMU_QUERY) ) {
|
||||
fprintf( stderr, "Error, -d option cannot be used with this option\n" );
|
||||
Usage();
|
||||
}
|
||||
if ( scale != -1 && !(function&ZMU_IMAGE) )
|
||||
{
|
||||
if ( scale != -1 && !(function&ZMU_IMAGE) ) {
|
||||
fprintf( stderr, "Error, -S option cannot be used with this option\n" );
|
||||
Usage();
|
||||
}
|
||||
|
@ -435,46 +419,36 @@ int main( int argc, char *argv[] )
|
|||
|
||||
User *user = 0;
|
||||
|
||||
if ( config.opt_use_auth )
|
||||
{
|
||||
if ( strcmp( config.auth_relay, "none" ) == 0 )
|
||||
{
|
||||
if ( !username )
|
||||
{
|
||||
if ( config.opt_use_auth ) {
|
||||
if ( strcmp( config.auth_relay, "none" ) == 0 ) {
|
||||
if ( !username ) {
|
||||
fprintf( stderr, "Error, username must be supplied\n" );
|
||||
exit( -1 );
|
||||
}
|
||||
|
||||
if ( username )
|
||||
{
|
||||
if ( username ) {
|
||||
user = zmLoadUser( username );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !(username && password) && !auth )
|
||||
{
|
||||
} else {
|
||||
if ( !(username && password) && !auth ) {
|
||||
fprintf( stderr, "Error, username and password or auth string must be supplied\n" );
|
||||
exit( -1 );
|
||||
}
|
||||
|
||||
//if ( strcmp( config.auth_relay, "hashed" ) == 0 )
|
||||
{
|
||||
if ( auth )
|
||||
{
|
||||
if ( auth ) {
|
||||
user = zmLoadAuthUser( auth, false );
|
||||
}
|
||||
}
|
||||
//else if ( strcmp( config.auth_relay, "plain" ) == 0 )
|
||||
{
|
||||
if ( username && password )
|
||||
{
|
||||
if ( username && password ) {
|
||||
user = zmLoadUser( username, password );
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( !user )
|
||||
{
|
||||
if ( !user ) {
|
||||
fprintf( stderr, "Error, unable to authenticate user\n" );
|
||||
exit( -1 );
|
||||
}
|
||||
|
@ -482,38 +456,32 @@ int main( int argc, char *argv[] )
|
|||
}
|
||||
|
||||
|
||||
if ( mon_id > 0 )
|
||||
{
|
||||
if ( mon_id > 0 ) {
|
||||
Monitor *monitor = Monitor::Load( mon_id, function&(ZMU_QUERY|ZMU_ZONES), Monitor::QUERY );
|
||||
if ( monitor )
|
||||
{
|
||||
if ( verbose )
|
||||
{
|
||||
if ( monitor ) {
|
||||
if ( verbose ) {
|
||||
printf( "Monitor %d(%s)\n", monitor->Id(), monitor->Name() );
|
||||
}
|
||||
if ( ! monitor->connect() ) {
|
||||
Error( "Can't connect to capture daemon: %d %s", monitor->Id(), monitor->Name() );
|
||||
exit( -1 );
|
||||
}
|
||||
|
||||
char separator = ' ';
|
||||
bool have_output = false;
|
||||
if ( function & ZMU_STATE )
|
||||
{
|
||||
if ( function & ZMU_STATE ) {
|
||||
Monitor::State state = monitor->GetState();
|
||||
if ( verbose )
|
||||
printf( "Current state: %s\n", state==Monitor::ALARM?"Alarm":(state==Monitor::ALERT?"Alert":"Idle") );
|
||||
else
|
||||
{
|
||||
else {
|
||||
if ( have_output ) printf( "%c", separator );
|
||||
printf( "%d", state );
|
||||
have_output = true;
|
||||
}
|
||||
}
|
||||
if ( function & ZMU_TIME )
|
||||
{
|
||||
if ( function & ZMU_TIME ) {
|
||||
struct timeval timestamp = monitor->GetTimestamp( image_idx );
|
||||
if ( verbose )
|
||||
{
|
||||
if ( verbose ) {
|
||||
char timestamp_str[64] = "None";
|
||||
if ( timestamp.tv_sec )
|
||||
strftime( timestamp_str, sizeof(timestamp_str), "%Y-%m-%d %H:%M:%S", localtime( ×tamp.tv_sec ) );
|
||||
|
@ -521,62 +489,50 @@ int main( int argc, char *argv[] )
|
|||
printf( "Time of last image capture: %s.%02ld\n", timestamp_str, timestamp.tv_usec/10000 );
|
||||
else
|
||||
printf( "Time of image %d capture: %s.%02ld\n", image_idx, timestamp_str, timestamp.tv_usec/10000 );
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
if ( have_output ) printf( "%c", separator );
|
||||
printf( "%ld.%02ld", timestamp.tv_sec, timestamp.tv_usec/10000 );
|
||||
have_output = true;
|
||||
}
|
||||
}
|
||||
if ( function & ZMU_READ_IDX )
|
||||
{
|
||||
if ( function & ZMU_READ_IDX ) {
|
||||
if ( verbose )
|
||||
printf( "Last read index: %d\n", monitor->GetLastReadIndex() );
|
||||
else
|
||||
{
|
||||
else {
|
||||
if ( have_output ) printf( "%c", separator );
|
||||
printf( "%d", monitor->GetLastReadIndex() );
|
||||
have_output = true;
|
||||
}
|
||||
}
|
||||
if ( function & ZMU_WRITE_IDX )
|
||||
{
|
||||
if ( function & ZMU_WRITE_IDX ) {
|
||||
if ( verbose )
|
||||
printf( "Last write index: %d\n", monitor->GetLastWriteIndex() );
|
||||
else
|
||||
{
|
||||
else {
|
||||
if ( have_output ) printf( "%c", separator );
|
||||
printf( "%d", monitor->GetLastWriteIndex() );
|
||||
have_output = true;
|
||||
}
|
||||
}
|
||||
if ( function & ZMU_EVENT )
|
||||
{
|
||||
if ( function & ZMU_EVENT ) {
|
||||
if ( verbose )
|
||||
printf( "Last event id: %d\n", monitor->GetLastEvent() );
|
||||
else
|
||||
{
|
||||
else {
|
||||
if ( have_output ) printf( "%c", separator );
|
||||
printf( "%d", monitor->GetLastEvent() );
|
||||
have_output = true;
|
||||
}
|
||||
}
|
||||
if ( function & ZMU_FPS )
|
||||
{
|
||||
if ( function & ZMU_FPS ) {
|
||||
if ( verbose )
|
||||
printf( "Current capture rate: %.2f frames per second\n", monitor->GetFPS() );
|
||||
else
|
||||
{
|
||||
else {
|
||||
if ( have_output ) printf( "%c", separator );
|
||||
printf( "%.2f", monitor->GetFPS() );
|
||||
have_output = true;
|
||||
}
|
||||
}
|
||||
if ( function & ZMU_IMAGE )
|
||||
{
|
||||
if ( verbose )
|
||||
{
|
||||
if ( function & ZMU_IMAGE ) {
|
||||
if ( verbose ) {
|
||||
if ( image_idx == -1 )
|
||||
printf( "Dumping last image captured to Monitor%d.jpg", monitor->Id() );
|
||||
else
|
||||
|
@ -587,77 +543,63 @@ int main( int argc, char *argv[] )
|
|||
}
|
||||
monitor->GetImage( image_idx, scale>0?scale:100 );
|
||||
}
|
||||
if ( function & ZMU_ZONES )
|
||||
{
|
||||
if ( function & ZMU_ZONES ) {
|
||||
if ( verbose )
|
||||
printf( "Dumping zone image to Zones%d.jpg\n", monitor->Id() );
|
||||
monitor->DumpZoneImage( zoneString );
|
||||
}
|
||||
if ( function & ZMU_ALARM )
|
||||
{
|
||||
if ( function & ZMU_ALARM ) {
|
||||
if ( verbose )
|
||||
printf( "Forcing alarm on\n" );
|
||||
monitor->ForceAlarmOn( config.forced_alarm_score, "Forced Web" );
|
||||
}
|
||||
if ( function & ZMU_NOALARM )
|
||||
{
|
||||
if ( function & ZMU_NOALARM ) {
|
||||
if ( verbose )
|
||||
printf( "Forcing alarm off\n" );
|
||||
monitor->ForceAlarmOff();
|
||||
}
|
||||
if ( function & ZMU_CANCEL )
|
||||
{
|
||||
if ( function & ZMU_CANCEL ) {
|
||||
if ( verbose )
|
||||
printf( "Cancelling forced alarm on/off\n" );
|
||||
monitor->CancelForced();
|
||||
}
|
||||
if ( function & ZMU_RELOAD )
|
||||
{
|
||||
if ( function & ZMU_RELOAD ) {
|
||||
if ( verbose )
|
||||
printf( "Reloading monitor settings\n" );
|
||||
monitor->actionReload();
|
||||
}
|
||||
if ( function & ZMU_ENABLE )
|
||||
{
|
||||
if ( function & ZMU_ENABLE ) {
|
||||
if ( verbose )
|
||||
printf( "Enabling event generation\n" );
|
||||
monitor->actionEnable();
|
||||
}
|
||||
if ( function & ZMU_DISABLE )
|
||||
{
|
||||
if ( function & ZMU_DISABLE ) {
|
||||
if ( verbose )
|
||||
printf( "Disabling event generation\n" );
|
||||
monitor->actionDisable();
|
||||
}
|
||||
if ( function & ZMU_SUSPEND )
|
||||
{
|
||||
if ( function & ZMU_SUSPEND ) {
|
||||
if ( verbose )
|
||||
printf( "Suspending event generation\n" );
|
||||
monitor->actionSuspend();
|
||||
}
|
||||
if ( function & ZMU_RESUME )
|
||||
{
|
||||
if ( function & ZMU_RESUME ) {
|
||||
if ( verbose )
|
||||
printf( "Resuming event generation\n" );
|
||||
monitor->actionResume();
|
||||
}
|
||||
if ( function & ZMU_QUERY )
|
||||
{
|
||||
if ( function & ZMU_QUERY ) {
|
||||
char monString[16382] = "";
|
||||
monitor->DumpSettings( monString, verbose );
|
||||
printf( "%s\n", monString );
|
||||
}
|
||||
if ( function & ZMU_BRIGHTNESS )
|
||||
{
|
||||
if ( verbose )
|
||||
{
|
||||
if ( function & ZMU_BRIGHTNESS ) {
|
||||
if ( verbose ) {
|
||||
if ( brightness >= 0 )
|
||||
printf( "New brightness: %d\n", monitor->actionBrightness( brightness ) );
|
||||
else
|
||||
printf( "Current brightness: %d\n", monitor->actionBrightness() );
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
if ( have_output ) printf( "%c", separator );
|
||||
if ( brightness >= 0 )
|
||||
printf( "%d", monitor->actionBrightness( brightness ) );
|
||||
|
@ -666,17 +608,13 @@ int main( int argc, char *argv[] )
|
|||
have_output = true;
|
||||
}
|
||||
}
|
||||
if ( function & ZMU_CONTRAST )
|
||||
{
|
||||
if ( verbose )
|
||||
{
|
||||
if ( function & ZMU_CONTRAST ) {
|
||||
if ( verbose ) {
|
||||
if ( contrast >= 0 )
|
||||
printf( "New brightness: %d\n", monitor->actionContrast( contrast ) );
|
||||
else
|
||||
printf( "Current contrast: %d\n", monitor->actionContrast() );
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
if ( have_output ) printf( "%c", separator );
|
||||
if ( contrast >= 0 )
|
||||
printf( "%d", monitor->actionContrast( contrast ) );
|
||||
|
@ -685,17 +623,13 @@ int main( int argc, char *argv[] )
|
|||
have_output = true;
|
||||
}
|
||||
}
|
||||
if ( function & ZMU_HUE )
|
||||
{
|
||||
if ( verbose )
|
||||
{
|
||||
if ( function & ZMU_HUE ) {
|
||||
if ( verbose ) {
|
||||
if ( hue >= 0 )
|
||||
printf( "New hue: %d\n", monitor->actionHue( hue ) );
|
||||
else
|
||||
printf( "Current hue: %d\n", monitor->actionHue() );
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
if ( have_output ) printf( "%c", separator );
|
||||
if ( hue >= 0 )
|
||||
printf( "%d", monitor->actionHue( hue ) );
|
||||
|
@ -704,17 +638,13 @@ int main( int argc, char *argv[] )
|
|||
have_output = true;
|
||||
}
|
||||
}
|
||||
if ( function & ZMU_COLOUR )
|
||||
{
|
||||
if ( verbose )
|
||||
{
|
||||
if ( function & ZMU_COLOUR ) {
|
||||
if ( verbose ) {
|
||||
if ( colour >= 0 )
|
||||
printf( "New colour: %d\n", monitor->actionColour( colour ) );
|
||||
else
|
||||
printf( "Current colour: %d\n", monitor->actionColour() );
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
if ( have_output ) printf( "%c", separator );
|
||||
if ( colour >= 0 )
|
||||
printf( "%d", monitor->actionColour( colour ) );
|
||||
|
@ -723,26 +653,19 @@ int main( int argc, char *argv[] )
|
|||
have_output = true;
|
||||
}
|
||||
}
|
||||
if ( have_output )
|
||||
{
|
||||
if ( have_output ) {
|
||||
printf( "\n" );
|
||||
}
|
||||
if ( !function )
|
||||
{
|
||||
if ( !function ) {
|
||||
Usage();
|
||||
}
|
||||
delete monitor;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
fprintf( stderr, "Error, invalid monitor id %d\n", mon_id );
|
||||
exit( -1 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( function & ZMU_QUERY )
|
||||
{
|
||||
} else {
|
||||
if ( function & ZMU_QUERY ) {
|
||||
#if ZM_HAS_V4L
|
||||
char vidString[0x10000] = "";
|
||||
bool ok = LocalCamera::GetCurrentSettings( device, vidString, v4lVersion, verbose );
|
||||
|
@ -754,24 +677,20 @@ int main( int argc, char *argv[] )
|
|||
#endif // ZM_HAS_V4L
|
||||
}
|
||||
|
||||
if ( function & ZMU_LIST )
|
||||
{
|
||||
if ( function & ZMU_LIST ) {
|
||||
std::string sql = "select Id, Function+0 from Monitors";
|
||||
if ( !verbose )
|
||||
{
|
||||
if ( !verbose ) {
|
||||
sql += "where Function != 'None'";
|
||||
}
|
||||
sql += " order by Id asc";
|
||||
|
||||
if ( mysql_query( &dbconn, sql.c_str() ) )
|
||||
{
|
||||
if ( mysql_query( &dbconn, sql.c_str() ) ) {
|
||||
Error( "Can't run query: %s", mysql_error( &dbconn ) );
|
||||
exit( mysql_errno( &dbconn ) );
|
||||
}
|
||||
|
||||
MYSQL_RES *result = mysql_store_result( &dbconn );
|
||||
if ( !result )
|
||||
{
|
||||
if ( !result ) {
|
||||
Error( "Can't use query result: %s", mysql_error( &dbconn ) );
|
||||
exit( mysql_errno( &dbconn ) );
|
||||
}
|
||||
|
@ -779,17 +698,13 @@ int main( int argc, char *argv[] )
|
|||
Debug( 1, "Got %d monitors", n_monitors );
|
||||
|
||||
printf( "%4s%5s%6s%9s%14s%6s%6s%8s%8s\n", "Id", "Func", "State", "TrgState", "LastImgTim", "RdIdx", "WrIdx", "LastEvt", "FrmRate" );
|
||||
for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ )
|
||||
{
|
||||
for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) {
|
||||
int mon_id = atoi(dbrow[0]);
|
||||
int function = atoi(dbrow[1]);
|
||||
if ( !user || user->canAccess( mon_id ) )
|
||||
{
|
||||
if ( function > 1 )
|
||||
{
|
||||
if ( !user || user->canAccess( mon_id ) ) {
|
||||
if ( function > 1 ) {
|
||||
Monitor *monitor = Monitor::Load( mon_id, false, Monitor::QUERY );
|
||||
if ( monitor && monitor->connect() )
|
||||
{
|
||||
if ( monitor && monitor->connect() ) {
|
||||
struct timeval tv = monitor->GetTimestamp();
|
||||
printf( "%4d%5d%6d%9d%11ld.%02ld%6d%6d%8d%8.2f\n",
|
||||
monitor->Id(),
|
||||
|
@ -804,9 +719,7 @@ int main( int argc, char *argv[] )
|
|||
);
|
||||
delete monitor;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
struct timeval tv = { 0, 0 };
|
||||
printf( "%4d%5d%6d%9d%11ld.%02ld%6d%6d%8d%8.2f\n",
|
||||
mon_id,
|
||||
|
|
|
@ -39,6 +39,23 @@ checksanity () {
|
|||
|
||||
}
|
||||
|
||||
# Check key variables before calling packpack
|
||||
checkvars () {
|
||||
if [ -z ${VERSION} ]; then
|
||||
echo
|
||||
echo "FATAL: VERSION variable was null. Cannot continue."
|
||||
echo
|
||||
exit 98
|
||||
fi
|
||||
|
||||
if [ -z ${RELEASE} ]; then
|
||||
echo
|
||||
echo "FATAL: RELEASE variable was null. Cannot Continue"
|
||||
echo
|
||||
exit 98
|
||||
fi
|
||||
}
|
||||
|
||||
# Steps common to all builds
|
||||
commonprep () {
|
||||
mkdir -p build
|
||||
|
@ -46,7 +63,7 @@ commonprep () {
|
|||
echo "Checking packpack github repo for changes..."
|
||||
git -C packpack pull origin master
|
||||
else
|
||||
echo "Cloning pakcpack github repo..."
|
||||
echo "Cloning packpack github repo..."
|
||||
git clone https://github.com/packpack/packpack.git packpack
|
||||
fi
|
||||
|
||||
|
@ -125,6 +142,8 @@ setdebpkgver () {
|
|||
export VERSION="$zmver+$commitnum"
|
||||
export RELEASE="${DIST}"
|
||||
|
||||
checkvars
|
||||
|
||||
echo
|
||||
echo "Packpack VERSION has been set to: ${VERSION}"
|
||||
echo "Packpack RELEASE has been set to: ${RELEASE}"
|
||||
|
@ -132,6 +151,16 @@ setdebpkgver () {
|
|||
|
||||
}
|
||||
|
||||
# This adds an entry to the debian changelog
|
||||
setdebchangelog () {
|
||||
DATE=`date -R`
|
||||
cat <<EOF > debian/changelog
|
||||
zoneminder ($VERSION-${DIST}-1) unstable; urgency=low
|
||||
*
|
||||
-- Isaac Connor <iconnor@connortechnology.com> $DATE
|
||||
EOF
|
||||
}
|
||||
|
||||
################
|
||||
# MAIN PROGRAM #
|
||||
################
|
||||
|
@ -154,6 +183,8 @@ if [ "${TRAVIS_EVENT_TYPE}" == "cron" ] || [ "${TRAVIS}" != "true" ]; then
|
|||
export VERSION=$(git describe --long --always | sed -n 's/^\([0-9\.]*\)-\([0-9]*\)-\([a-z0-9]*\)/\1/p')
|
||||
export RELEASE=$(git describe --long --always | sed -n 's/^\([0-9\.]*\)-\([0-9]*\)-\([a-z0-9]*\)/\2/p')
|
||||
|
||||
checkvars
|
||||
|
||||
echo
|
||||
echo "Packpack VERSION has been set to: ${VERSION}"
|
||||
echo "Packpack RELEASE has been set to: ${RELEASE}"
|
||||
|
@ -200,6 +231,8 @@ if [ "${TRAVIS_EVENT_TYPE}" == "cron" ] || [ "${TRAVIS}" != "true" ]; then
|
|||
ln -sfT distros/ubuntu1604 debian
|
||||
fi
|
||||
|
||||
setdebchangelog
|
||||
|
||||
echo "Starting packpack..."
|
||||
packpack/packpack
|
||||
|
||||
|
@ -218,6 +251,8 @@ elif [ "${OS}" == "ubuntu" ] && [ "${DIST}" == "trusty" ] && [ "${ARCH}" == "x86
|
|||
|
||||
ln -sfT distros/ubuntu1204 debian
|
||||
|
||||
setdebchangelog
|
||||
|
||||
echo "Starting packpack..."
|
||||
packpack/packpack
|
||||
|
||||
|
|
|
@ -100,12 +100,12 @@ App::uses('CakeLog', 'Log');
|
|||
CakeLog::config('debug', array(
|
||||
'engine' => 'File',
|
||||
'types' => array('notice', 'info', 'debug'),
|
||||
'file' => 'cake_debug',
|
||||
'file' => '@ZM_LOGDIR@/cake_debug',
|
||||
));
|
||||
CakeLog::config('error', array(
|
||||
'engine' => 'File',
|
||||
'types' => array('warning', 'error', 'critical', 'alert', 'emergency'),
|
||||
'file' => 'cake_error',
|
||||
'file' => '@ZM_LOGDIR@/cake_error',
|
||||
));
|
||||
CakeLog::config('custom_path', array(
|
||||
'engine' => 'File',
|
||||
|
|
|
@ -29,12 +29,15 @@ class Event {
|
|||
Error('No row for Event ' . $IdOrRow );
|
||||
}
|
||||
} // end function __construct
|
||||
|
||||
public function Storage() {
|
||||
return new Storage( isset($this->{'StorageId'}) ? $this->{'StorageId'} : NULL );
|
||||
}
|
||||
|
||||
public function Monitor() {
|
||||
return new Monitor( isset($this->{'MonitorId'}) ? $this->{'MonitorId'} : NULL );
|
||||
}
|
||||
|
||||
public function __call( $fn, array $args){
|
||||
if ( array_key_exists( $fn, $this ) ) {
|
||||
return $this->{$fn};
|
||||
|
@ -54,6 +57,7 @@ class Event {
|
|||
$Storage = $this->Storage();
|
||||
return $Storage->Path().'/'.$this->Relative_Path();
|
||||
}
|
||||
|
||||
public function Relative_Path() {
|
||||
$event_path = '';
|
||||
|
||||
|
@ -197,16 +201,22 @@ class Event {
|
|||
return( $thumbData );
|
||||
} // end function createListThumbnail
|
||||
|
||||
// frame is an array representing the db row for a frame.
|
||||
function getImageSrc( $frame, $scale=SCALE_BASE, $captureOnly=false, $overwrite=false ) {
|
||||
$Storage = new Storage( isset($this->{'StorageId'}) ? $this->{'StorageId'} : NULL );
|
||||
$Event = $this;
|
||||
$eventPath = $Event->Path();
|
||||
|
||||
if ( !is_array($frame) )
|
||||
if ( $frame and ! is_array($frame) ) {
|
||||
# Must be an Id
|
||||
Debug("Assuming that $frame is an Id");
|
||||
$frame = array( 'FrameId'=>$frame, 'Type'=>'' );
|
||||
}
|
||||
|
||||
if ( file_exists( $eventPath.'/snapshot.jpg' ) ) {
|
||||
$captImage = "snapshot.jpg";
|
||||
if ( ( ! $frame ) and file_exists( $eventPath.'/snapshot.jpg' ) ) {
|
||||
# No frame specified, so look for a snapshot to use
|
||||
$captImage = 'snapshot.jpg';
|
||||
Debug("Frame not specified, using snapshot");
|
||||
} else {
|
||||
$captImage = sprintf( '%0'.ZM_EVENT_IMAGE_DIGITS.'d-capture.jpg', $frame['FrameId'] );
|
||||
if ( ! file_exists( $eventPath.'/'.$captImage ) ) {
|
||||
|
@ -275,8 +285,7 @@ class Event {
|
|||
}
|
||||
|
||||
$thumbFile = $thumbPath;
|
||||
if ( $overwrite || !file_exists( $thumbFile ) || !filesize( $thumbFile ) )
|
||||
{
|
||||
if ( $overwrite || ! file_exists( $thumbFile ) || ! filesize( $thumbFile ) ) {
|
||||
// Get new dimensions
|
||||
list( $imageWidth, $imageHeight ) = getimagesize( $imagePath );
|
||||
$thumbWidth = $imageWidth * $fraction;
|
||||
|
@ -290,7 +299,7 @@ class Event {
|
|||
if ( !imagejpeg( $thumbImage, $thumbPath ) )
|
||||
Error( "Can't create thumbnail '$thumbPath'" );
|
||||
}
|
||||
}
|
||||
} # Create thumbnails
|
||||
|
||||
$imageData = array(
|
||||
'eventPath' => $eventPath,
|
||||
|
@ -298,7 +307,7 @@ class Event {
|
|||
'thumbPath' => $thumbPath,
|
||||
'imageFile' => $imagePath,
|
||||
'thumbFile' => $thumbFile,
|
||||
'imageClass' => $alarmFrame?"alarm":"normal",
|
||||
'imageClass' => $alarmFrame?'alarm':'normal',
|
||||
'isAnalImage' => $isAnalImage,
|
||||
'hasAnalImage' => $hasAnalImage,
|
||||
);
|
||||
|
|
|
@ -27,9 +27,11 @@ class Frame {
|
|||
Error("No row for Frame " . $IdOrRow );
|
||||
}
|
||||
} // end function __construct
|
||||
|
||||
public function Storage() {
|
||||
return $this->Event()->Storage();
|
||||
}
|
||||
|
||||
public function Event() {
|
||||
return new Event( $this->{'EventId'} );
|
||||
}
|
||||
|
@ -70,7 +72,9 @@ class Frame {
|
|||
}
|
||||
|
||||
public function getImageSrc( $show='capture' ) {
|
||||
return $_SERVER['PHP_SELF'].'?view=image&fid='.$this->{'Id'}.'&show='.$show.'&filename='.$this->Event()->MonitorId().'_'.$this->{'EventId'}.'_'.$this->{'FrameId'}.'.jpg';
|
||||
|
||||
return $_SERVER['PHP_SELF'].'?view=image&fid='.$this->{'FrameId'}.'&eid='.$this->{'EventId'}.'&show='.$show;
|
||||
#return $_SERVER['PHP_SELF'].'?view=image&fid='.$this->{'Id'}.'&show='.$show.'&filename='.$this->Event()->MonitorId().'_'.$this->{'EventId'}.'_'.$this->{'FrameId'}.'.jpg';
|
||||
} // end function getImageSrc
|
||||
|
||||
public static function find( $parameters = array(), $limit = NULL ) {
|
||||
|
|
|
@ -1149,17 +1149,17 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&' ) {
|
|||
if ( isset($filter['terms']) && count($filter['terms']) ) {
|
||||
for ( $i = 0; $i < count($filter['terms']); $i++ ) {
|
||||
if ( isset($filter['terms'][$i]['cnj']) ) {
|
||||
$filter['query'] .= $querySep."filter[terms][$i][cnj]=".urlencode($filter['terms'][$i]['cnj']);
|
||||
$filter['sql'] .= " ".$filter['terms'][$i]['cnj']." ";
|
||||
$filter['query'] .= $querySep.urlencode("filter[terms][$i][cnj]").'='.urlencode($filter['terms'][$i]['cnj']);
|
||||
$filter['sql'] .= ' '.$filter['terms'][$i]['cnj'].' ';
|
||||
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[terms][$i][cnj]\" value=\"".htmlspecialchars($filter['terms'][$i]['cnj'])."\"/>\n";
|
||||
}
|
||||
if ( isset($filter['terms'][$i]['obr']) ) {
|
||||
$filter['query'] .= $querySep."filter[terms][$i][obr]=".urlencode($filter['terms'][$i]['obr']);
|
||||
$filter['sql'] .= " ".str_repeat( "(", $filter['terms'][$i]['obr'] )." ";
|
||||
$filter['query'] .= $querySep.urlencode("filter[terms][$i][obr]").'='.urlencode($filter['terms'][$i]['obr']);
|
||||
$filter['sql'] .= ' '.str_repeat( '(', $filter['terms'][$i]['obr'] ).' ';
|
||||
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[terms][$i][obr]\" value=\"".htmlspecialchars($filter['terms'][$i]['obr'])."\"/>\n";
|
||||
}
|
||||
if ( isset($filter['terms'][$i]['attr']) ) {
|
||||
$filter['query'] .= $querySep."filter[terms][$i][attr]=".urlencode($filter['terms'][$i]['attr']);
|
||||
$filter['query'] .= $querySep.urlencode("filter[terms][$i][attr]").'='.urlencode($filter['terms'][$i]['attr']);
|
||||
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[terms][$i][attr]\" value=\"".htmlspecialchars($filter['terms'][$i]['attr'])."\"/>\n";
|
||||
switch ( $filter['terms'][$i]['attr'] ) {
|
||||
case 'MonitorName':
|
||||
|
@ -1267,7 +1267,7 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&' ) {
|
|||
case '>' :
|
||||
case '<' :
|
||||
case '<=' :
|
||||
$filter['sql'] .= ' '.$filter['terms'][$i]['op']." $value";
|
||||
$filter['sql'] .= ' '.$filter['terms'][$i]['op'].' '. $value;
|
||||
break;
|
||||
case '=~' :
|
||||
$filter['sql'] .= ' regexp '.$value;
|
||||
|
@ -1276,20 +1276,20 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&' ) {
|
|||
$filter['sql'] .= ' not regexp '.$value;
|
||||
break;
|
||||
case '=[]' :
|
||||
$filter['sql'] .= ' in ('.join( ",", $valueList ).')';
|
||||
$filter['sql'] .= ' in ('.join( ',', $valueList ).')';
|
||||
break;
|
||||
case '![]' :
|
||||
$filter['sql'] .= ' not in ('.join( ',', $valueList ).')';
|
||||
break;
|
||||
}
|
||||
|
||||
$filter['query'] .= $querySep."filter[terms][$i][op]=".urlencode($filter['terms'][$i]['op']);
|
||||
$filter['query'] .= $querySep.urlencode("filter[terms][$i][op]").'='.urlencode($filter['terms'][$i]['op']);
|
||||
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[terms][$i][op]\" value=\"".htmlspecialchars($filter['terms'][$i]['op'])."\"/>\n";
|
||||
$filter['query'] .= $querySep."filter[terms][$i][val]=".urlencode($filter['terms'][$i]['val']);
|
||||
$filter['query'] .= $querySep.urlencode("filter[terms][$i][val]").'='.urlencode($filter['terms'][$i]['val']);
|
||||
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[terms][$i][val]\" value=\"".htmlspecialchars($filter['terms'][$i]['val'])."\"/>\n";
|
||||
}
|
||||
if ( isset($filter['terms'][$i]['cbr']) ) {
|
||||
$filter['query'] .= $querySep."filter[terms][$i][cbr]=".urlencode($filter['terms'][$i]['cbr']);
|
||||
$filter['query'] .= $querySep.urlencode("filter[terms][$i][cbr]").'='.urlencode($filter['terms'][$i]['cbr']);
|
||||
$filter['sql'] .= ' '.str_repeat( ')', $filter['terms'][$i]['cbr'] ).' ';
|
||||
$filter['fields'] .= "<input type=\"hidden\" name=\"filter[terms][$i][cbr]\" value=\"".htmlspecialchars($filter['terms'][$i]['cbr'])."\"/>\n";
|
||||
}
|
||||
|
|
|
@ -45,7 +45,6 @@ function xhtmlHeaders( $file, $title ) {
|
|||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
|
||||
<title><?php echo ZM_WEB_TITLE_PREFIX ?> - <?php echo validHtmlStr($title) ?></title>
|
||||
<link rel="icon" type="image/ico" href="graphics/favicon.ico"/>
|
||||
<link rel="shortcut icon" href="graphics/favicon.ico"/>
|
||||
|
@ -96,7 +95,8 @@ var $j = jQuery.noConflict();
|
|||
<script src="skins/<?php echo $skin ?>/js/video.js"></script>
|
||||
<script src="./js/videojs.zoomrotate.js"></script>
|
||||
<script src="skins/<?php echo $skin ?>/js/moment.min.js"></script>
|
||||
<?php }
|
||||
<?php
|
||||
}
|
||||
if ( $skinJsPhpFile ) {
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
|
|
|
@ -152,30 +152,6 @@ xhtmlHeaders( __FILE__, translate('Console') );
|
|||
<?php } ?>
|
||||
</tr>
|
||||
</thead>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td class="colLeftButtons" colspan="<?php echo $left_columns ?>">
|
||||
<input type="button" class="btn btn-primary" value="<?php echo translate('Refresh') ?>" onclick="location.reload(true);"/>
|
||||
<input type="button" class="btn btn-primary" name="addBtn" value="<?php echo translate('AddNewMonitor') ?>" onclick="addMonitor( this )"/>
|
||||
<!-- <?php echo makePopupButton( '?view=monitor', 'zmMonitor0', 'monitor', translate('AddNewMonitor'), (canEdit( 'Monitors' ) && !$user['MonitorIds']) ) ?> -->
|
||||
<?php echo makePopupButton( '?view=filter&filter[terms][0][attr]=DateTime&filter[terms][0][op]=%3c&filter[terms][0][val]=now', 'zmFilter', 'filter', translate('Filters'), canView( 'Events' ) ) ?>
|
||||
<input class="btn btn-primary" type="button" name="editBtn" value="<?php echo translate('Edit') ?>" onclick="editMonitor( this )" disabled="disabled"/>
|
||||
<input class="btn btn-danger" type="button" name="deleteBtn" value="<?php echo translate('Delete') ?>" onclick="deleteMonitor( this )" disabled="disabled"/>
|
||||
</td>
|
||||
<?php
|
||||
for ( $i = 0; $i < count($eventCounts); $i++ ) {
|
||||
parseFilter( $eventCounts[$i]['filter'] );
|
||||
?>
|
||||
<td class="colEvents"><?php echo makePopupLink( '?view='.$eventsView.'&page=1'.$eventCounts[$i]['filter']['query'], $eventsWindow, $eventsView, $eventCounts[$i]['total'], canView( 'Events' ) ) ?></td>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<td class="colZones"><?php echo $zoneCount ?></td>
|
||||
<?php if ( canEdit('Monitors') ) { ?>
|
||||
<td class="colMark"></td>
|
||||
<?php } ?>
|
||||
</tr>
|
||||
</tfoot>
|
||||
<tbody id="consoleTableBody">
|
||||
<?php
|
||||
for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
|
||||
|
@ -195,7 +171,7 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
|
|||
if ( $monitor['Function'] == 'None' )
|
||||
$fclass = 'errorText';
|
||||
//elseif ( $monitor['Function'] == 'Monitor' )
|
||||
// $fclass = "warnText";
|
||||
// $fclass = 'warnText';
|
||||
else
|
||||
$fclass = 'infoText';
|
||||
if ( !$monitor['Enabled'] )
|
||||
|
@ -251,6 +227,30 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
|
|||
} # end for each monitor
|
||||
?>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td class="colLeftButtons" colspan="<?php echo $left_columns ?>">
|
||||
<input type="button" class="btn btn-primary" value="<?php echo translate('Refresh') ?>" onclick="location.reload(true);"/>
|
||||
<input type="button" class="btn btn-primary" name="addBtn" value="<?php echo translate('AddNewMonitor') ?>" onclick="addMonitor( this )"/>
|
||||
<!-- <?php echo makePopupButton( '?view=monitor', 'zmMonitor0', 'monitor', translate('AddNewMonitor'), (canEdit( 'Monitors' ) && !$user['MonitorIds']) ) ?> -->
|
||||
<?php echo makePopupButton( '?view=filter&filter[terms][0][attr]=DateTime&filter[terms][0][op]=%3c&filter[terms][0][val]=now', 'zmFilter', 'filter', translate('Filters'), canView( 'Events' ) ) ?>
|
||||
<input class="btn btn-primary" type="button" name="editBtn" value="<?php echo translate('Edit') ?>" onclick="editMonitor( this )" disabled="disabled"/>
|
||||
<input class="btn btn-danger" type="button" name="deleteBtn" value="<?php echo translate('Delete') ?>" onclick="deleteMonitor( this )" disabled="disabled"/>
|
||||
</td>
|
||||
<?php
|
||||
for ( $i = 0; $i < count($eventCounts); $i++ ) {
|
||||
parseFilter( $eventCounts[$i]['filter'] );
|
||||
?>
|
||||
<td class="colEvents"><?php echo makePopupLink( '?view='.$eventsView.'&page=1'.$eventCounts[$i]['filter']['query'], $eventsWindow, $eventsView, $eventCounts[$i]['total'], canView( 'Events' ) ) ?></td>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<td class="colZones"><?php echo $zoneCount ?></td>
|
||||
<?php if ( canEdit('Monitors') ) { ?>
|
||||
<td class="colMark"></td>
|
||||
<?php } ?>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -81,7 +81,7 @@ if ( !empty($page) ) {
|
|||
}
|
||||
$eventsSql .= " limit $limitStart, $limitAmount";
|
||||
} elseif ( !empty( $limit ) ) {
|
||||
$eventsSql .= " limit 0, ".$limit;
|
||||
$eventsSql .= ' limit 0, '.$limit;
|
||||
}
|
||||
|
||||
$maxWidth = 0;
|
||||
|
@ -173,7 +173,8 @@ foreach ( $events as $event ) {
|
|||
<th class="colTotScore"><a href="<?php echo sortHeader( 'TotScore' ) ?>"><?php echo translate('TotalBrScore') ?><?php echo sortTag( 'TotScore' ) ?></a></th>
|
||||
<th class="colAvgScore"><a href="<?php echo sortHeader( 'AvgScore' ) ?>"><?php echo translate('AvgBrScore') ?><?php echo sortTag( 'AvgScore' ) ?></a></th>
|
||||
<th class="colMaxScore"><a href="<?php echo sortHeader( 'MaxScore' ) ?>"><?php echo translate('MaxBrScore') ?><?php echo sortTag( 'MaxScore' ) ?></a></th>
|
||||
<?php if ( ZM_WEB_EVENT_DISK_SPACE ) { ?>
|
||||
<?php
|
||||
if ( ZM_WEB_EVENT_DISK_SPACE ) { ?>
|
||||
<th class="colDiskSpace"><a href="<?php echo sortHeader( 'DiskSpace' ) ?>"><?php echo translate('DiskSpace') ?><?php echo sortTag( 'DiskSpace' ) ?></a></th>
|
||||
<?php
|
||||
}
|
||||
|
@ -201,7 +202,9 @@ foreach ( $events as $event ) {
|
|||
<td class="colTotScore"><?php echo $event->TotScore() ?></td>
|
||||
<td class="colAvgScore"><?php echo $event->AvgScore() ?></td>
|
||||
<td class="colMaxScore"><?php echo makePopupLink( '?view=frame&eid='.$event->Id().'&fid=0', 'zmImage', array( 'image', reScale( $event->Width(), $scale ), reScale( $event->Height(), $scale ) ), $event->MaxScore() ) ?></td>
|
||||
<?php if ( ZM_WEB_EVENT_DISK_SPACE ) { ?>
|
||||
<?php
|
||||
if ( ZM_WEB_EVENT_DISK_SPACE ) {
|
||||
?>
|
||||
<td class="colDiskSpace"><?php echo human_filesize( $event->DiskSpace() ) ?></td>
|
||||
<?php
|
||||
}
|
||||
|
@ -209,8 +212,7 @@ foreach ( $events as $event ) {
|
|||
if ( $thumbData = $event->createListThumbnail() ) {
|
||||
?>
|
||||
<td class="colThumbnail">
|
||||
<?php
|
||||
|
||||
<?php
|
||||
$imgSrc = '?view=image&eid='.$event->Id().'&fid='.$thumbData['FrameId'].'&width='.$thumbData['Width'].'&height='.$thumbData['Height'];
|
||||
$streamSrc = getStreamSrc( array( "source=event", "mode=jpeg", "event=".$event->Id(), "scale=".$scale, "maxfps=".ZM_WEB_VIDEO_MAXFPS, "replay=single") );
|
||||
|
||||
|
@ -222,14 +224,15 @@ foreach ( $events as $event ) {
|
|||
array( 'image', reScale( $event->Width(), $scale ), reScale( $event->Height(), $scale ) ),
|
||||
$imgHtml
|
||||
);
|
||||
?></td>
|
||||
?>
|
||||
</td>
|
||||
<?php
|
||||
} else {
|
||||
?>
|
||||
<td class="colThumbnail"> </td>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
} // end if ZM_WEB_LIST_THUMBS
|
||||
?>
|
||||
<td class="colMark"><input type="checkbox" name="markEids[]" value="<?php echo $event->Id() ?>" onclick="configureButton( this, 'markEids' );"<?php if ( !canEdit( 'Events' ) ) { ?> disabled="disabled"<?php } ?>/></td>
|
||||
</tr>
|
||||
|
@ -239,14 +242,12 @@ foreach ( $events as $event ) {
|
|||
</tbody>
|
||||
</table>
|
||||
<?php
|
||||
if ( $pagination )
|
||||
{
|
||||
if ( $pagination ) {
|
||||
?>
|
||||
<h3 class="pagination"><?php echo $pagination ?></h3>
|
||||
<?php
|
||||
}
|
||||
if ( true || canEdit( 'Events' ) )
|
||||
{
|
||||
if ( true || canEdit( 'Events' ) ) {
|
||||
?>
|
||||
<div id="contentButtons">
|
||||
<input type="button" name="viewBtn" value="<?php echo translate('View') ?>" onclick="viewEvents( this, 'markEids' );" disabled="disabled"/>
|
||||
|
|
|
@ -68,7 +68,7 @@ if ( isset( $_REQUEST['reload'] ) and ! $_REQUEST['reload'] ) {
|
|||
$conjunctionTypes = array(
|
||||
'and' => translate('ConjAnd'),
|
||||
'or' => translate('ConjOr')
|
||||
);
|
||||
);
|
||||
$obracketTypes = array();
|
||||
$cbracketTypes = array();
|
||||
if ( isset($_REQUEST['filter']['terms']) ) {
|
||||
|
@ -102,7 +102,8 @@ $attrTypes = array(
|
|||
'StorageId' => translate('AttrStorageArea'),
|
||||
'ServerId' => translate('AttrServer'),
|
||||
'StateId' => translate('AttrStateId'),
|
||||
);
|
||||
);
|
||||
|
||||
$opTypes = array(
|
||||
'=' => translate('OpEq'),
|
||||
'!=' => translate('OpNe'),
|
||||
|
@ -114,15 +115,18 @@ $opTypes = array(
|
|||
'!~' => translate('OpNotMatches'),
|
||||
'=[]' => translate('OpIn'),
|
||||
'![]' => translate('OpNotIn'),
|
||||
);
|
||||
);
|
||||
|
||||
$archiveTypes = array(
|
||||
'0' => translate('ArchUnarchived'),
|
||||
'1' => translate('ArchArchived')
|
||||
);
|
||||
);
|
||||
|
||||
$weekdays = array();
|
||||
for ( $i = 0; $i < 7; $i++ ) {
|
||||
$weekdays[$i] = strftime( "%A", mktime( 12, 0, 0, 1, $i+1, 2001 ) );
|
||||
$weekdays[$i] = strftime( '%A', mktime( 12, 0, 0, 1, $i+1, 2001 ) );
|
||||
}
|
||||
|
||||
$sort_fields = array(
|
||||
'Id' => translate('AttrId'),
|
||||
'Name' => translate('AttrName'),
|
||||
|
@ -136,14 +140,16 @@ $sort_fields = array(
|
|||
'TotScore' => translate('AttrTotalScore'),
|
||||
'AvgScore' => translate('AttrAvgScore'),
|
||||
'MaxScore' => translate('AttrMaxScore'),
|
||||
);
|
||||
);
|
||||
|
||||
$sort_dirns = array(
|
||||
'1' => translate('SortAsc'),
|
||||
'0' => translate('SortDesc')
|
||||
);
|
||||
);
|
||||
|
||||
if ( empty($_REQUEST['sort_field']) ) {
|
||||
$_REQUEST['sort_field'] = ZM_WEB_EVENT_SORT_FIELD;
|
||||
$_REQUEST['sort_asc'] = (ZM_WEB_EVENT_SORT_ORDER == "asc");
|
||||
$_REQUEST['sort_asc'] = (ZM_WEB_EVENT_SORT_ORDER == 'asc');
|
||||
}
|
||||
|
||||
$hasCal = file_exists( 'tools/jscalendar/calendar.js' );
|
||||
|
@ -194,20 +200,30 @@ for ( $i = 0; isset($_REQUEST['filter']) && $i < count($_REQUEST['filter']['term
|
|||
<td><?php echo buildSelect( "filter[terms][$i][attr]", $attrTypes, "clearValue( this, $i ); submitToFilter( this, 0 );" ); ?></td>
|
||||
<?php
|
||||
if ( isset($_REQUEST['filter']['terms'][$i]['attr']) ) {
|
||||
if ( $_REQUEST['filter']['terms'][$i]['attr'] == "Archived" ) {
|
||||
if ( $_REQUEST['filter']['terms'][$i]['attr'] == 'Archived' ) {
|
||||
?>
|
||||
<td><?php echo translate('OpEq') ?><input type="hidden" name="filter[terms][<?php echo $i ?>][op]" value="="/></td>
|
||||
<td><?php echo buildSelect( "filter[terms][$i][val]", $archiveTypes ); ?></td>
|
||||
<?php
|
||||
} elseif ( $_REQUEST['filter']['terms'][$i]['attr'] == "DateTime" ) {
|
||||
} elseif ( $_REQUEST['filter']['terms'][$i]['attr'] == 'DateTime' ) {
|
||||
?>
|
||||
<td><?php echo buildSelect( "filter[terms][$i][op]", $opTypes ); ?></td>
|
||||
<td><input name="filter[terms][<?php echo $i ?>][val]" id="filter[terms][<?php echo $i ?>][val]" value="<?php echo isset($_REQUEST['filter']['terms'][$i]['val'])?validHtmlStr($_REQUEST['filter']['terms'][$i]['val']):'' ?>"/><?php if ( $hasCal ) { ?><script type="text/javascript">Calendar.setup( { inputField: "filter[terms][<?php echo $i ?>][val]", ifFormat: "%Y-%m-%d %H:%M", showsTime: true, timeFormat: "24", showOthers: true, weekNumbers: false });</script><?php } ?></td>
|
||||
<td>
|
||||
<input name="filter[terms][<?php echo $i ?>][val]" id="filter[terms][<?php echo $i ?>][val]" value="<?php echo isset($_REQUEST['filter']['terms'][$i]['val'])?validHtmlStr($_REQUEST['filter']['terms'][$i]['val']):'' ?>"/>
|
||||
<?php if ( $hasCal ) { ?>
|
||||
<script type="text/javascript">Calendar.setup( { inputField: "filter[terms][<?php echo $i ?>][val]", ifFormat: "%Y-%m-%d %H:%M", showsTime: true, timeFormat: "24", showOthers: true, weekNumbers: false });</script>
|
||||
<?php } ?>
|
||||
</td>
|
||||
<?php
|
||||
} elseif ( $_REQUEST['filter']['terms'][$i]['attr'] == "Date" ) {
|
||||
} elseif ( $_REQUEST['filter']['terms'][$i]['attr'] == 'Date' ) {
|
||||
?>
|
||||
<td><?php echo buildSelect( "filter[terms][$i][op]", $opTypes ); ?></td>
|
||||
<td><input name="filter[terms][<?php echo $i ?>][val]" id="filter[terms][<?php echo $i ?>][val]" value="<?php echo isset($_REQUEST['filter']['terms'][$i]['val'])?validHtmlStr($_REQUEST['filter']['terms'][$i]['val']):'' ?>"/><?php if ( $hasCal ) { ?><script type="text/javascript">Calendar.setup( { inputField: "filter[terms][<?php echo $i ?>][val]", ifFormat: "%Y-%m-%d", showOthers: true, weekNumbers: false });</script><?php } ?></td>
|
||||
<td>
|
||||
<input name="filter[terms][<?php echo $i ?>][val]" id="filter[terms][<?php echo $i ?>][val]" value="<?php echo isset($_REQUEST['filter']['terms'][$i]['val'])?validHtmlStr($_REQUEST['filter']['terms'][$i]['val']):'' ?>"/>
|
||||
<?php if ( $hasCal ) { ?>
|
||||
<script type="text/javascript">Calendar.setup( { inputField: "filter[terms][<?php echo $i ?>][val]", ifFormat: "%Y-%m-%d", showOthers: true, weekNumbers: false });</script>
|
||||
<?php } ?>
|
||||
</td>
|
||||
<?php
|
||||
} elseif ( $_REQUEST['filter']['terms'][$i]['attr'] == "StateId" ) {
|
||||
$states = array();
|
||||
|
@ -218,12 +234,12 @@ for ( $i = 0; isset($_REQUEST['filter']) && $i < count($_REQUEST['filter']['term
|
|||
<td><?php echo buildSelect( "filter[terms][$i][op]", $opTypes ); ?></td>
|
||||
<td><?php echo buildSelect( "filter[terms][$i][val]", $states ); ?></td>
|
||||
<?php
|
||||
} elseif ( $_REQUEST['filter']['terms'][$i]['attr'] == "Weekday" ) {
|
||||
} elseif ( $_REQUEST['filter']['terms'][$i]['attr'] == 'Weekday' ) {
|
||||
?>
|
||||
<td><?php echo buildSelect( "filter[terms][$i][op]", $opTypes ); ?></td>
|
||||
<td><?php echo buildSelect( "filter[terms][$i][val]", $weekdays ); ?></td>
|
||||
<?php
|
||||
} elseif ( false && $_REQUEST['filter']['terms'][$i]['attr'] == "MonitorName" ) {
|
||||
} elseif ( false && $_REQUEST['filter']['terms'][$i]['attr'] == 'MonitorName' ) {
|
||||
$monitors = array();
|
||||
foreach ( dbFetchAll( "select Id,Name from Monitors order by Sequence asc" ) as $monitor ) {
|
||||
if ( visibleMonitor( $monitor['Id'] ) ) {
|
||||
|
@ -234,7 +250,7 @@ for ( $i = 0; isset($_REQUEST['filter']) && $i < count($_REQUEST['filter']['term
|
|||
<td><?php echo buildSelect( "filter[terms][$i][op]", $opTypes ); ?></td>
|
||||
<td><?php echo buildSelect( "filter[terms][$i][val]", $monitors ); ?></td>
|
||||
<?php
|
||||
} elseif ( $_REQUEST['filter']['terms'][$i]['attr'] == "ServerId" ) {
|
||||
} elseif ( $_REQUEST['filter']['terms'][$i]['attr'] == 'ServerId' ) {
|
||||
$servers = array();
|
||||
$servers['ZM_SERVER_ID'] = 'Current Server';
|
||||
foreach ( dbFetchAll( "SELECT Id,Name FROM Servers ORDER BY lower(Name) ASC" ) as $server ) {
|
||||
|
@ -244,7 +260,7 @@ for ( $i = 0; isset($_REQUEST['filter']) && $i < count($_REQUEST['filter']['term
|
|||
<td><?php echo buildSelect( "filter[terms][$i][op]", $opTypes ); ?></td>
|
||||
<td><?php echo buildSelect( "filter[terms][$i][val]", $servers ); ?></td>
|
||||
<?php
|
||||
} elseif ( $_REQUEST['filter']['terms'][$i]['attr'] == "StorageId" ) {
|
||||
} elseif ( $_REQUEST['filter']['terms'][$i]['attr'] == 'StorageId' ) {
|
||||
$storageareas = array();
|
||||
$storageareas[0] = 'Default ' . ZM_DIR_EVENTS;
|
||||
foreach ( dbFetchAll( "SELECT Id,Name FROM Storage ORDER BY lower(Name) ASC" ) as $storage ) {
|
||||
|
@ -271,7 +287,7 @@ for ( $i = 0; isset($_REQUEST['filter']) && $i < count($_REQUEST['filter']['term
|
|||
<td><input type="button" onclick="addTerm( this, <?php echo $i+1 ?> )" value="+"/><?php if ( $_REQUEST['filter']['terms'] > 1 ) { ?><input type="button" onclick="delTerm( this, <?php echo $i ?> )" value="-"/><?php } ?></td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
} # end foreach filter
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
@ -279,7 +295,7 @@ for ( $i = 0; isset($_REQUEST['filter']) && $i < count($_REQUEST['filter']['term
|
|||
<table id="sortTable" class="filterTable" cellspacing="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><label for="sort_field"><?php echo translate('SortBy') ?></label><?php echo buildSelect( "sort_field", $sort_fields ); ?><?php echo buildSelect( "sort_asc", $sort_dirns ); ?></td>
|
||||
<td><label for="sort_field"><?php echo translate('SortBy') ?></label><?php echo buildSelect( 'sort_field', $sort_fields ); ?><?php echo buildSelect( 'sort_asc', $sort_dirns ); ?></td>
|
||||
<td><label for="limit"><?php echo translate('LimitResultsPre') ?></label><input type="text" size="6" id="limit" name="limit" value="<?php echo isset($_REQUEST['limit'])?validInt($_REQUEST['limit']):"" ?>"/><?php echo translate('LimitResultsPost') ?></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
@ -339,12 +355,18 @@ if ( ZM_OPT_MESSAGE ) {
|
|||
<div id="contentButtons">
|
||||
<input type="submit" value="<?php echo translate('Submit') ?>" onclick="submitToEvents( this );"/>
|
||||
<input type="button" name="executeButton" id="executeButton" value="<?php echo translate('Execute') ?>" onclick="executeFilter( this );"/>
|
||||
<?php if ( canEdit( 'Events' ) ) { ?>
|
||||
<?php
|
||||
if ( canEdit( 'Events' ) ) {
|
||||
?>
|
||||
<input type="button" value="<?php echo translate('Save') ?>" onclick="saveFilter( this );"/>
|
||||
<?php } ?>
|
||||
<?php if ( canEdit( 'Events' ) && isset($dbFilter) && $dbFilter['Name'] ) { ?>
|
||||
<input type="button" value="<?php echo translate('Delete') ?>" onclick="deleteFilter( this, <?php echo $dbFilter['Id'] ?>, '<?php echo $dbFilter['Name'] ?>' );"/>
|
||||
<?php } ?>
|
||||
<?php
|
||||
if ( isset($dbFilter) && $dbFilter['Name'] ) {
|
||||
?>
|
||||
<input type="button" value="<?php echo translate('Delete') ?>" onclick="deleteFilter( this, '<?php echo $dbFilter['Name'] ?>' );"/>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
?>
|
||||
<input type="button" value="<?php echo translate('Reset') ?>" onclick="submitToFilter( this, 1 );"/>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -60,22 +60,27 @@ if ( isset( $_REQUEST['scale'] ) ) {
|
|||
$scale = max( reScale( SCALE_BASE, $Monitor->DefaultScale(), ZM_WEB_DEFAULT_SCALE ), SCALE_BASE );
|
||||
}
|
||||
|
||||
$imageData = $Event->getImageSrc( $frame, $scale, 0 );
|
||||
if ( ! $imageData ) {
|
||||
Error("No data found for Event $eid frame $fid");
|
||||
$imageData = array();
|
||||
}
|
||||
|
||||
$show = 'capt';
|
||||
if ( isset($_REQUEST['show']) ) {
|
||||
$show = $_REQUEST['show'];
|
||||
#} else if ( $imageData['hasAnalImage'] ) {
|
||||
#$show = 'anal';
|
||||
} else if ( $imageData['hasAnalImage'] ) {
|
||||
$show = 'anal';
|
||||
}
|
||||
$imageData = $Event->getImageSrc( $frame, $scale, ($show=="capt") );
|
||||
|
||||
$imagePath = $imageData['thumbPath'];
|
||||
$eventPath = $imageData['eventPath'];
|
||||
$dImagePath = sprintf( "%s/%0".ZM_EVENT_IMAGE_DIGITS."d-diag-d.jpg", $eventPath, $Frame->FrameId() );
|
||||
$rImagePath = sprintf( "%s/%0".ZM_EVENT_IMAGE_DIGITS."d-diag-r.jpg", $eventPath, $Frame->FrameId() );
|
||||
$dImagePath = sprintf( '%s/%0'.ZM_EVENT_IMAGE_DIGITS.'d-diag-d.jpg', $eventPath, $Frame->FrameId() );
|
||||
$rImagePath = sprintf( '%s/%0'.ZM_EVENT_IMAGE_DIGITS.'d-diag-r.jpg', $eventPath, $Frame->FrameId() );
|
||||
|
||||
$focusWindow = true;
|
||||
|
||||
xhtmlHeaders(__FILE__, translate('Frame')." - ".$Event->Id()." - ".$Frame->FrameId() );
|
||||
xhtmlHeaders(__FILE__, translate('Frame').' - '.$Event->Id()." - ".$Frame->FrameId() );
|
||||
?>
|
||||
<body>
|
||||
<div id="page">
|
||||
|
@ -94,13 +99,13 @@ xhtmlHeaders(__FILE__, translate('Frame')." - ".$Event->Id()." - ".$Frame->Frame
|
|||
</div>
|
||||
<div id="content">
|
||||
<p id="image">
|
||||
<?php if ( $imageData['hasAnalImage'] ) { ?>
|
||||
<a href="?view=frame&eid=<?php echo $Event->Id() ?>&fid=<?php echo $Frame->FrameId() ?>&scale=<?php echo $scale ?>&show=<?php echo $imageData['isAnalImage']?"capt":"anal" ?>">
|
||||
<?php } ?>
|
||||
<img id="frameImg" src="<?php echo $Frame->getImageSrc($imageData['isAnalImage']?'analyse':'capture') ?>" width="<?php echo reScale( $Event->Width(), $Event->DefaultScale(), $scale ) ?>" height="<?php echo reScale( $Event->Height(), $Event->DefaultScale(), $scale ) ?>" alt="<?php echo $Frame->EventId()."-".$Frame->FrameId() ?>" class="<?php echo $imageData['imageClass'] ?>"/>
|
||||
<?php if ( $imageData['hasAnalImage'] ) { ?>
|
||||
</a>
|
||||
<?php } ?>
|
||||
|
||||
<?php if ( $imageData['hasAnalImage'] ) {
|
||||
echo sprintf('<a href="?view=frame&eid=%d&fid=%d&scale=%d&show=%s">', $Event->Id(), $Frame->FrameId(), $scale, ( $show=='anal'?'capt':'anal' ) );
|
||||
} ?>
|
||||
<img id="frameImg" src="<?php echo $Frame->getImageSrc($show=='anal'?'analyse':'capture') ?>" width="<?php echo reScale( $Event->Width(), $Event->DefaultScale(), $scale ) ?>" height="<?php echo reScale( $Event->Height(), $Event->DefaultScale(), $scale ) ?>" alt="<?php echo $Frame->EventId()."-".$Frame->FrameId() ?>" class="<?php echo $imageData['imageClass'] ?>"/>
|
||||
<?php if ( $imageData['hasAnalImage'] ) { ?></a><?php } ?>
|
||||
|
||||
</p>
|
||||
<p id="controls">
|
||||
<?php if ( $Frame->FrameId() > 1 ) { ?>
|
||||
|
|
|
@ -7,13 +7,13 @@ function updateButtons( element ) {
|
|||
var canExecute = false;
|
||||
if ( form.elements['AutoArchive'].checked )
|
||||
canExecute = true;
|
||||
else if ( typeof ZM_OPT_FFMPEG !== "undefined" && form.elements['AutoVideo'].checked )
|
||||
else if ( form.elements['AutoVideo'] && form.elements['AutoVideo'].checked )
|
||||
canExecute = true;
|
||||
else if ( typeof ZM_OPT_UPLOAD !== "undefined" && form.elements['AutoUpload'].checked )
|
||||
else if ( form.elements['AutoUpload'] && form.elements['AutoUpload'].checked )
|
||||
canExecute = true;
|
||||
else if ( typeof ZM_OPT_EMAIL !== "undefined" && form.elements['AutoEmail'].checked )
|
||||
else if ( form.elements['AutoEmail'] && form.elements['AutoEmail'].checked )
|
||||
canExecute = true;
|
||||
else if ( typeof ZM_OPT_MESSAGE !== "undefined" && form.elements['AutoMessage'].checked )
|
||||
else if ( form.elements['AutoMessage'] && form.elements['AutoMessage'].checked )
|
||||
canExecute = true;
|
||||
else if ( form.elements['AutoExecute'].checked && form.elements['AutoExecuteCmd'].value != '' )
|
||||
canExecute = true;
|
||||
|
|
|
@ -52,7 +52,7 @@ if ( ! $Server ) {
|
|||
}
|
||||
|
||||
if ( ! empty($_REQUEST['mid']) ) {
|
||||
$monitor = new Monitor( $_REQUEST['mid'] );
|
||||
$monitor = dbFetchMonitor( $_REQUEST['mid'] );
|
||||
if ( ZM_OPT_X10 )
|
||||
$x10Monitor = dbFetchOne( 'SELECT * FROM TriggersX10 WHERE MonitorId = ?', NULL, array($_REQUEST['mid']) );
|
||||
} else {
|
||||
|
@ -155,13 +155,12 @@ function fourcc( $a, $b, $c, $d ) {
|
|||
}
|
||||
|
||||
if ( isset( $_REQUEST['newMonitor'] ) ) {
|
||||
# Update the monitor object with whatever has been set so far.
|
||||
$monitor->set( $_REQUEST['newMonitor'] );
|
||||
$newMonitor = $_REQUEST['newMonitor'];
|
||||
if ( ZM_OPT_X10 )
|
||||
$newX10Monitor = $_REQUEST['newX10Monitor'];
|
||||
# FIXME: Triggers in the db is a comma separated string. Needs to be an array.
|
||||
#$monitor->Triggers = explode( ',', isset($monitor->Triggers)?$monitor->Triggers:"" );
|
||||
} else {
|
||||
$newMonitor = $monitor;
|
||||
$newMonitor['Triggers'] = explode( ',', isset($monitor['Triggers'])?$monitor['Triggers']:"" );
|
||||
if ( ZM_OPT_X10 )
|
||||
$newX10Monitor = $x10Monitor;
|
||||
}
|
||||
|
@ -176,28 +175,25 @@ if ( $monitor->AlarmMaxFPS == '0.00' )
|
|||
|
||||
if ( !empty($_REQUEST['preset']) ) {
|
||||
$preset = dbFetchOne( 'SELECT Type, Device, Channel, Format, Protocol, Method, Host, Port, Path, Width, Height, Palette, MaxFPS, Controllable, ControlId, ControlDevice, ControlAddress, DefaultRate, DefaultScale FROM MonitorPresets WHERE Id = ?', NULL, array($_REQUEST['preset']) );
|
||||
#$monitor->set( $preset );
|
||||
foreach ( $preset as $name=>$value ) {
|
||||
# Does isset handle NULL's? I don't think this code is correct.
|
||||
if ( isset($value) ) {
|
||||
$monitor->$name = $value;
|
||||
$newMonitor[$name] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( !empty($_REQUEST['probe']) ) {
|
||||
$probe = unserialize(base64_decode($_REQUEST['probe']));
|
||||
foreach ( $probe as $name=>$value ) {
|
||||
# Again I don't think isset is useful here.
|
||||
if ( isset($value) ) {
|
||||
$monitor->$name = $value;
|
||||
$newMonitor[$name] = $value;
|
||||
}
|
||||
}
|
||||
if ( ZM_HAS_V4L && $monitor->Type == 'Local' ) {
|
||||
$monitor->Palette = fourCC( substr($monitor->Palette,0,1), substr($monitor->Palette,1,1), substr($monitor->Palette,2,1), substr($monitor->Palette,3,1) );
|
||||
if ( $monitor->Format == 'PAL' )
|
||||
$monitor->Format = 0x000000ff;
|
||||
elseif ( $monitor->Format == 'NTSC' )
|
||||
$monitor->Format = 0x0000b000;
|
||||
if ( ZM_HAS_V4L && $newMonitor['Type'] == 'Local' ) {
|
||||
$newMonitor['Palette'] = fourCC( substr($newMonitor['Palette'],0,1), substr($newMonitor['Palette'],1,1), substr($newMonitor['Palette'],2,1), substr($newMonitor['Palette'],3,1) );
|
||||
if ( $newMonitor['Format'] == 'PAL' )
|
||||
$newMonitor['Format'] = 0x000000ff;
|
||||
elseif ( $newMonitor['Format'] == 'NTSC' )
|
||||
$newMonitor['Format'] = 0x0000b000;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -469,7 +465,7 @@ $videowriteropts = array(
|
|||
'H264 Camera Passthrough' => 2
|
||||
);
|
||||
|
||||
xhtmlHeaders(__FILE__, translate('Monitor')." - ".validHtmlStr($monitor->Name) );
|
||||
xhtmlHeaders(__FILE__, translate('Monitor')." - ".validHtmlStr($monitor['Name']) );
|
||||
?>
|
||||
<body>
|
||||
<div id="page">
|
||||
|
@ -513,6 +509,10 @@ foreach ( $tabs as $name=>$value ) {
|
|||
<li><a href="#" onclick="submitTab( '<?php echo $name ?>' ); return( false );"><?php echo $value ?></a></li>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<a href="#" onclick="createPopup( '?view=monitorpreset&mid=<?php echo $monitor['Id'] ?>', 'zmMonitorPreset<?php echo $monitor['Id'] ?>', 'monitorpreset' ); return( false );"><?php echo translate('Presets') ?></a>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</ul>
|
||||
|
@ -661,6 +661,7 @@ if ( ZM_HAS_V4L && ($tab != 'misc' || $monitor->Type != 'Local') ) {
|
|||
<input type="hidden" name="newMonitor[SignalCheckColour]" value="<?php echo validHtmlStr($monitor->SignalCheckColour) ?>"/>
|
||||
<?php
|
||||
}
|
||||
if ( ZM_HAS_V4L && ($tab != 'source' || $newMonitor['Type'] != 'Local') ) {
|
||||
?>
|
||||
<table id="contentTable" class="major" cellspacing="0">
|
||||
<tbody>
|
||||
|
@ -754,28 +755,26 @@ switch ( $tab ) {
|
|||
</select></td></tr>
|
||||
<?php
|
||||
} else {
|
||||
?>
|
||||
<tr><td><?php echo translate('RefImageBlendPct') ?></td><td><input type="text" name="newMonitor[RefBlendPerc]" value="<?php echo validHtmlStr($monitor->RefBlendPerc) ?>" size="4"/></td></tr>
|
||||
<tr><td><?php echo translate('AlarmRefImageBlendPct') ?></td><td><input type="text" name="newMonitor[AlarmRefBlendPerc]" value="<?php echo validHtmlStr($monitor->AlarmRefBlendPerc) ?>" size="4"/></td></tr>
|
||||
<?php
|
||||
?>
|
||||
<tr><td><?php echo translate('RefImageBlendPct') ?></td><td><input type="text" name="newMonitor[RefBlendPerc]" value="<?php echo validHtmlStr($newMonitor['RefBlendPerc']) ?>" size="4"/></td></tr>
|
||||
<tr><td><?php echo translate('AlarmRefImageBlendPct') ?></td><td><input type="text" name="newMonitor[AlarmRefBlendPerc]" value="<?php echo validHtmlStr($newMonitor['AlarmRefBlendPerc']) ?>" size="4"/></td></tr>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
?>
|
||||
<tr><td><?php echo translate('Triggers') ?></td><td>
|
||||
<?php
|
||||
<?php
|
||||
$optTriggers = getSetValues( 'Monitors', 'Triggers' );
|
||||
$breakCount = (int)(ceil(count($optTriggers)));
|
||||
$breakCount = min( 3, $breakCount );
|
||||
$optCount = 0;
|
||||
foreach( $optTriggers as $optTrigger ) {
|
||||
if ( ( ! ZM_OPT_X10 ) && ( $optTrigger == 'X10' ) )
|
||||
if ( !ZM_OPT_X10 && $optTrigger == 'X10' )
|
||||
continue;
|
||||
if ( $optCount && ($optCount%$breakCount == 0) )
|
||||
echo '</br>';
|
||||
echo '<input type="checkbox" name="newMonitor[Triggers][]" value="'. $optTrigger .'"';
|
||||
if ( isset($monitor->Triggers) && is_array( $monitor->Triggers ) and in_array( $optTrigger, $monitor->Triggers ) ) {
|
||||
echo ' checked="checked"';
|
||||
}
|
||||
echo '/> '. $optTrigger ;
|
||||
?>
|
||||
<input type="checkbox" name="newMonitor[Triggers][]" value="<?php echo $optTrigger ?>"<?php if ( isset($newMonitor['Triggers']) && in_array( $optTrigger, $newMonitor['Triggers'] ) ) { ?> checked="checked"<?php } ?>/> <?php echo $optTrigger ?>
|
||||
<?php
|
||||
$optCount ++;
|
||||
}
|
||||
if ( !$optCount ) {
|
||||
|
@ -844,9 +843,11 @@ switch ( $tab ) {
|
|||
<tr><td><?php echo translate('Deinterlacing') ?></td><td><select name="newMonitor[Deinterlacing]"><?php foreach ( $deinterlaceopts_v4l2 as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $monitor->Deinterlacing ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
|
||||
<?php
|
||||
} else {
|
||||
?>
|
||||
<tr><td><?php echo translate('Deinterlacing') ?></td><td><select name="newMonitor[Deinterlacing]"><?php foreach ( $deinterlaceopts as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $monitor->Deinterlacing ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
|
||||
<?php
|
||||
?>
|
||||
<tr><td><?php echo translate('DeviceChannel') ?></td><td><select name="newMonitor[Channel]"><?php foreach ( $v4l2DeviceChannels as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $newMonitor['Channel'] ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
|
||||
<tr><td><?php echo translate('DeviceFormat') ?></td><td><select name="newMonitor[Format]"><?php foreach ( $v4l2DeviceFormats as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $newMonitor['Format'] ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
|
||||
<tr><td><?php echo translate('CapturePalette') ?></td><td><select name="newMonitor[Palette]"><?php foreach ( $v4l2LocalPalettes as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $newMonitor['Palette'] ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<?php
|
||||
|
@ -855,69 +856,110 @@ switch ( $tab ) {
|
|||
<tr id="RTSPDescribe"<?php if ( $monitor->Protocol != 'rtsp' ) { echo ' style="display:none;"'; } ?>><td><?php echo translate('RTSPDescribe') ?> (<?php echo makePopupLink( '?view=optionhelp&option=OPTIONS_RTSPDESCRIBE', 'zmOptionHelp', 'optionhelp', '?' ) ?>) </td><td><input type="checkbox" name="newMonitor[RTSPDescribe]" value="1"<?php if ( !empty($monitor->RTSPDescribe) ) { ?> checked="checked"<?php } ?>/></td></tr>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<?php
|
||||
?>
|
||||
<tr><td><?php echo translate('RemoteHostName') ?></td><td><input type="text" name="newMonitor[Host]" value="<?php echo validHtmlStr($newMonitor['Host']) ?>" size="36"/></td></tr>
|
||||
<tr><td><?php echo translate('RemoteHostPort') ?></td><td><input type="text" name="newMonitor[Port]" value="<?php echo validHtmlStr($newMonitor['Port']) ?>" size="6"/></td></tr>
|
||||
<tr><td><?php echo translate('RemoteHostPath') ?></td><td><input type="text" name="newMonitor[Path]" value="<?php echo validHtmlStr($newMonitor['Path']) ?>" size="36"/></td></tr>
|
||||
<?php
|
||||
} elseif ( $newMonitor['Type'] == 'File' ) {
|
||||
?>
|
||||
<tr><td><?php echo translate('SourcePath') ?></td><td><input type="text" name="newMonitor[Path]" value="<?php echo validHtmlStr($newMonitor['Path']) ?>" size="36"/></td></tr>
|
||||
<?php
|
||||
} elseif ( $newMonitor['Type'] == 'cURL' ) {
|
||||
?>
|
||||
<tr><td><?php echo 'URL' ?></td><td><input type="text" name="newMonitor[Path]" value="<?php echo validHtmlStr($newMonitor['Path']) ?>" size="36"/></td></tr>
|
||||
<tr><td><?php echo 'Username' ?></td><td><input type="text" name="newMonitor[User]" value="<?php echo validHtmlStr($newMonitor['User']) ?>" size="12"/></td></tr>
|
||||
<tr><td><?php echo 'Password' ?></td><td><input type="text" name="newMonitor[Pass]" value="<?php echo validHtmlStr($newMonitor['Pass']) ?>" size="12"/></td></tr>
|
||||
<?php
|
||||
} elseif ( $newMonitor['Type'] == 'Ffmpeg' || $newMonitor['Type'] == 'Libvlc' ) {
|
||||
?>
|
||||
<tr><td><?php echo translate('SourcePath') ?></td><td><input type="text" name="newMonitor[Path]" value="<?php echo validHtmlStr($newMonitor['Path']) ?>" size="36"/></td></tr>
|
||||
<tr><td><?php echo translate('RemoteMethod') ?> (<?php echo makePopupLink('?view=optionhelp&option=OPTIONS_RTSPTrans', 'zmOptionHelp', 'optionhelp', '?' ) ?>)</td><td><?php echo buildSelect( "newMonitor[Method]", $rtspFFMpegMethods ); ?></td></tr>
|
||||
<tr><td><?php echo translate('Options') ?> (<?php echo makePopupLink( '?view=optionhelp&option=OPTIONS_'.strtoupper($newMonitor['Type']), 'zmOptionHelp', 'optionhelp', '?' ) ?>)</td><td><input type="text" name="newMonitor[Options]" value="<?php echo validHtmlStr($newMonitor['Options']) ?>" size="36"/></td></tr>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<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 == $newMonitor['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="text" name="newMonitor[Width]" value="<?php echo validHtmlStr($newMonitor['Width']) ?>" size="4" onkeyup="updateMonitorDimensions(this);"/></td></tr>
|
||||
<tr><td><?php echo translate('CaptureHeight') ?> (<?php echo translate('Pixels') ?>)</td><td><input type="text" name="newMonitor[Height]" value="<?php echo validHtmlStr($newMonitor['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><select name="newMonitor[Orientation]"><?php foreach ( $orientations as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $newMonitor['Orientation'] ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
|
||||
<?php
|
||||
if ( $newMonitor['Type'] == 'Local' ) {
|
||||
?>
|
||||
<tr><td><?php echo translate('Deinterlacing') ?></td><td><select name="newMonitor[Deinterlacing]"><?php foreach ( $deinterlaceopts_v4l2 as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $newMonitor['Deinterlacing'] ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
|
||||
<?php
|
||||
} else {
|
||||
?>
|
||||
<tr><td><?php echo translate('Deinterlacing') ?></td><td><select name="newMonitor[Deinterlacing]"><?php foreach ( $deinterlaceopts as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $newMonitor['Deinterlacing'] ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
|
||||
<?php
|
||||
}
|
||||
if ( $newMonitor['Type'] == 'Remote' ) {
|
||||
?>
|
||||
<tr id="RTSPDescribe"<?php if ( $newMonitor['Protocol'] != 'rtsp' ) { echo ' style="display:none;"'; } ?>><td><?php echo translate('RTSPDescribe') ?> (<?php echo makePopupLink( '?view=optionhelp&option=OPTIONS_RTSPDESCRIBE', 'zmOptionHelp', 'optionhelp', '?' ) ?>) </td><td><input type="checkbox" name="newMonitor[RTSPDescribe]" value="1"<?php if ( !empty($newMonitor['RTSPDescribe']) ) { ?> checked="checked"<?php } ?>/></td></tr>
|
||||
<?php
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'storage' :
|
||||
?>
|
||||
<tr><td><?php echo translate('SaveJPEGs') ?></td><td><select name="newMonitor[SaveJPEGs]"><?php foreach ( $savejpegopts as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $monitor->SaveJPEGs ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
|
||||
<tr><td><?php echo translate('VideoWriter') ?></td><td><select name="newMonitor[VideoWriter]"><?php foreach ( $videowriteropts as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $monitor->VideoWriter ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
|
||||
<tr><td><?php echo translate('OptionalEncoderParam') ?></td><td><textarea name="newMonitor[EncoderParameters]" rows="4" cols="36"><?php echo validHtmlStr($monitor->EncoderParameters) ?></textarea></td></tr>
|
||||
<tr><td><?php echo translate('RecordAudio') ?></td><td><input type="checkbox" name="newMonitor[RecordAudio]" value="1"<?php if ($monitor->RecordAudio) { ?> checked="checked"<?php } ?>/></td></tr>
|
||||
<?php
|
||||
?>
|
||||
<tr><td><?php echo translate('SaveJPEGs') ?></td><td><select name="newMonitor[SaveJPEGs]"><?php foreach ( $savejpegopts as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $newMonitor['SaveJPEGs'] ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
|
||||
<tr><td><?php echo translate('VideoWriter') ?></td><td><select name="newMonitor[VideoWriter]"><?php foreach ( $videowriteropts as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $newMonitor['VideoWriter'] ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
|
||||
<tr><td><?php echo translate('OptionalEncoderParam') ?></td><td><textarea name="newMonitor[EncoderParameters]" rows="4" cols="36"><?php echo validHtmlStr($newMonitor['EncoderParameters']) ?></textarea></td></tr>
|
||||
<tr><td><?php echo translate('RecordAudio') ?></td><td><input type="checkbox" name="newMonitor[RecordAudio]" value="1"<?php if ( !empty($newMonitor['RecordAudio']) ) { ?> checked="checked"<?php } ?>/></td></tr>
|
||||
<?php
|
||||
break;
|
||||
case 'timestamp' :
|
||||
{
|
||||
?>
|
||||
<tr><td><?php echo translate('TimestampLabelFormat') ?></td><td><input type="text" name="newMonitor[LabelFormat]" value="<?php echo validHtmlStr($monitor->LabelFormat) ?>" size="32"/></td></tr>
|
||||
<tr><td><?php echo translate('TimestampLabelX') ?></td><td><input type="text" name="newMonitor[LabelX]" value="<?php echo validHtmlStr($monitor->LabelX) ?>" size="4"/></td></tr>
|
||||
<tr><td><?php echo translate('TimestampLabelY') ?></td><td><input type="text" name="newMonitor[LabelY]" value="<?php echo validHtmlStr($monitor->LabelY) ?>" size="4"/></td></tr>
|
||||
<tr><td><?php echo translate('TimestampLabelSize') ?></td><td><select name="newMonitor[LabelSize]"><?php foreach ( $label_size as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $monitor->LabelSize ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
|
||||
<?php
|
||||
?>
|
||||
<tr><td><?php echo translate('TimestampLabelFormat') ?></td><td><input type="text" name="newMonitor[LabelFormat]" value="<?php echo validHtmlStr($newMonitor['LabelFormat']) ?>" size="32"/></td></tr>
|
||||
<tr><td><?php echo translate('TimestampLabelX') ?></td><td><input type="text" name="newMonitor[LabelX]" value="<?php echo validHtmlStr($newMonitor['LabelX']) ?>" size="4"/></td></tr>
|
||||
<tr><td><?php echo translate('TimestampLabelY') ?></td><td><input type="text" name="newMonitor[LabelY]" value="<?php echo validHtmlStr($newMonitor['LabelY']) ?>" size="4"/></td></tr>
|
||||
<tr><td><?php echo translate('TimestampLabelSize') ?></td><td><select name="newMonitor[LabelSize]"><?php foreach ( $label_size as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $newMonitor['LabelSize'] ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
|
||||
<?php
|
||||
break;
|
||||
}
|
||||
case 'buffers' :
|
||||
{
|
||||
?>
|
||||
<tr><td><?php echo translate('ImageBufferSize') ?></td><td><input type="text" name="newMonitor[ImageBufferCount]" value="<?php echo validHtmlStr($monitor->ImageBufferCount) ?>" size="6"/></td></tr>
|
||||
<tr><td><?php echo translate('WarmupFrames') ?></td><td><input type="text" name="newMonitor[WarmupCount]" value="<?php echo validHtmlStr($monitor->WarmupCount) ?>" size="4"/></td></tr>
|
||||
<tr><td><?php echo translate('PreEventImageBuffer') ?></td><td><input type="text" name="newMonitor[PreEventCount]" value="<?php echo validHtmlStr($monitor->PreEventCount) ?>" size="4"/></td></tr>
|
||||
<tr><td><?php echo translate('PostEventImageBuffer') ?></td><td><input type="text" name="newMonitor[PostEventCount]" value="<?php echo validHtmlStr($monitor->PostEventCount) ?>" size="4"/></td></tr>
|
||||
<tr><td><?php echo translate('StreamReplayBuffer') ?></td><td><input type="text" name="newMonitor[StreamReplayBuffer]" value="<?php echo validHtmlStr($monitor->StreamReplayBuffer) ?>" size="6"/></td></tr>
|
||||
<tr><td><?php echo translate('AlarmFrameCount') ?></td><td><input type="text" name="newMonitor[AlarmFrameCount]" value="<?php echo validHtmlStr($monitor->AlarmFrameCount) ?>" size="4"/></td></tr>
|
||||
<?php
|
||||
?>
|
||||
<tr><td><?php echo translate('ImageBufferSize') ?></td><td><input type="text" name="newMonitor[ImageBufferCount]" value="<?php echo validHtmlStr($newMonitor['ImageBufferCount']) ?>" size="6"/></td></tr>
|
||||
<tr><td><?php echo translate('WarmupFrames') ?></td><td><input type="text" name="newMonitor[WarmupCount]" value="<?php echo validHtmlStr($newMonitor['WarmupCount']) ?>" size="4"/></td></tr>
|
||||
<tr><td><?php echo translate('PreEventImageBuffer') ?></td><td><input type="text" name="newMonitor[PreEventCount]" value="<?php echo validHtmlStr($newMonitor['PreEventCount']) ?>" size="4"/></td></tr>
|
||||
<tr><td><?php echo translate('PostEventImageBuffer') ?></td><td><input type="text" name="newMonitor[PostEventCount]" value="<?php echo validHtmlStr($newMonitor['PostEventCount']) ?>" size="4"/></td></tr>
|
||||
<tr><td><?php echo translate('StreamReplayBuffer') ?></td><td><input type="text" name="newMonitor[StreamReplayBuffer]" value="<?php echo validHtmlStr($newMonitor['StreamReplayBuffer']) ?>" size="6"/></td></tr>
|
||||
<tr><td><?php echo translate('AlarmFrameCount') ?></td><td><input type="text" name="newMonitor[AlarmFrameCount]" value="<?php echo validHtmlStr($newMonitor['AlarmFrameCount']) ?>" size="4"/></td></tr>
|
||||
<?php
|
||||
break;
|
||||
}
|
||||
case 'control' :
|
||||
{
|
||||
?>
|
||||
<tr><td><?php echo translate('Controllable') ?></td><td><input type="checkbox" name="newMonitor[Controllable]" value="1"<?php if ( !empty($monitor->Controllable) ) { ?> checked="checked"<?php } ?>/></td></tr>
|
||||
<tr><td><?php echo translate('ControlType') ?></td><td><?php echo htmlSelect( "newMonitor[ControlId]", $controlTypes, $monitor->ControlId(), 'loadLocations( this )' ); ?><?php if ( canEdit( 'Control' ) ) { ?> <a href="#" onclick="createPopup( '?view=controlcaps', 'zmControlCaps', 'controlcaps' );"><?php echo translate('Edit') ?></a><?php } ?></td></tr>
|
||||
<tr><td><?php echo translate('ControlDevice') ?></td><td><input type="text" name="newMonitor[ControlDevice]" value="<?php echo validHtmlStr($monitor->ControlDevice) ?>" size="32"/></td></tr>
|
||||
<tr><td><?php echo translate('ControlAddress') ?></td><td><input type="text" name="newMonitor[ControlAddress]" value="<?php echo validHtmlStr($monitor->ControlAddress) ?>" size="32"/></td></tr>
|
||||
<tr><td><?php echo translate('AutoStopTimeout') ?></td><td><input type="text" name="newMonitor[AutoStopTimeout]" value="<?php echo validHtmlStr($monitor->AutoStopTimeout) ?>" size="4"/></td></tr>
|
||||
<tr><td><?php echo translate('TrackMotion') ?></td><td><input type="checkbox" name="newMonitor[TrackMotion]" value="1"<?php if ( !empty($monitor->TrackMotion) ) { ?> checked="checked"<?php } ?>/></td></tr>
|
||||
<?php
|
||||
?>
|
||||
<tr><td><?php echo translate('Controllable') ?></td><td><input type="checkbox" name="newMonitor[Controllable]" value="1"<?php if ( !empty($newMonitor['Controllable']) ) { ?> checked="checked"<?php } ?>/></td></tr>
|
||||
<tr><td><?php echo translate('ControlType') ?></td><td><?php echo buildSelect( "newMonitor[ControlId]", $controlTypes, 'loadLocations( this )' ); ?><?php if ( canEdit( 'Control' ) ) { ?> <a href="#" onclick="createPopup( '?view=controlcaps', 'zmControlCaps', 'controlcaps' );"><?php echo translate('Edit') ?></a><?php } ?></td></tr>
|
||||
<tr><td><?php echo translate('ControlDevice') ?></td><td><input type="text" name="newMonitor[ControlDevice]" value="<?php echo validHtmlStr($newMonitor['ControlDevice']) ?>" size="32"/></td></tr>
|
||||
<tr><td><?php echo translate('ControlAddress') ?></td><td><input type="text" name="newMonitor[ControlAddress]" value="<?php echo validHtmlStr($newMonitor['ControlAddress']) ?>" size="32"/></td></tr>
|
||||
<tr><td><?php echo translate('AutoStopTimeout') ?></td><td><input type="text" name="newMonitor[AutoStopTimeout]" value="<?php echo validHtmlStr($newMonitor['AutoStopTimeout']) ?>" size="4"/></td></tr>
|
||||
<tr><td><?php echo translate('TrackMotion') ?></td><td><input type="checkbox" name="newMonitor[TrackMotion]" value="1"<?php if ( !empty($newMonitor['TrackMotion']) ) { ?> checked="checked"<?php } ?>/></td></tr>
|
||||
<?php
|
||||
$return_options = array(
|
||||
'-1' => translate('None'),
|
||||
'0' => translate('Home'),
|
||||
'1' => translate('Preset')." 1",
|
||||
);
|
||||
?>
|
||||
<tr><td><?php echo translate('TrackDelay') ?></td><td><input type="text" name="newMonitor[TrackDelay]" value="<?php echo validHtmlStr($monitor->TrackDelay) ?>" size="4"/></td></tr>
|
||||
<tr><td><?php echo translate('ReturnLocation') ?></td><td><?php echo htmlSelect( "newMonitor[ReturnLocation]", $return_options, $monitor->ReturnLocation() ); ?></td></tr>
|
||||
<tr><td><?php echo translate('ReturnDelay') ?></td><td><input type="text" name="newMonitor[ReturnDelay]" value="<?php echo validHtmlStr($monitor->ReturnDelay) ?>" size="4"/></td></tr>
|
||||
<?php
|
||||
?>
|
||||
<tr><td><?php echo translate('TrackDelay') ?></td><td><input type="text" name="newMonitor[TrackDelay]" value="<?php echo validHtmlStr($newMonitor['TrackDelay']) ?>" size="4"/></td></tr>
|
||||
<tr><td><?php echo translate('ReturnLocation') ?></td><td><?php echo buildSelect( "newMonitor[ReturnLocation]", $return_options ); ?></td></tr>
|
||||
<tr><td><?php echo translate('ReturnDelay') ?></td><td><input type="text" name="newMonitor[ReturnDelay]" value="<?php echo validHtmlStr($newMonitor['ReturnDelay']) ?>" size="4"/></td></tr>
|
||||
<?php
|
||||
break;
|
||||
}
|
||||
case 'x10' :
|
||||
{
|
||||
?>
|
||||
?>
|
||||
<tr><td><?php echo translate('X10ActivationString') ?></td><td><input type="text" name="newX10Monitor[Activation]" value="<?php echo validHtmlStr($newX10Monitor['Activation']) ?>" size="20"/></td></tr>
|
||||
<tr><td><?php echo translate('X10InputAlarmString') ?></td><td><input type="text" name="newX10Monitor[AlarmInput]" value="<?php echo validHtmlStr($newX10Monitor['AlarmInput']) ?>" size="20"/></td></tr>
|
||||
<tr><td><?php echo translate('X10OutputAlarmString') ?></td><td><input type="text" name="newX10Monitor[AlarmOutput]" value="<?php echo validHtmlStr($newX10Monitor['AlarmOutput']) ?>" size="20"/></td></tr>
|
||||
<?php
|
||||
<?php
|
||||
break;
|
||||
}
|
||||
case 'misc' :
|
||||
|
@ -954,12 +996,13 @@ switch ( $tab ) {
|
|||
<?php
|
||||
break;
|
||||
}
|
||||
}
|
||||
} // end switch tab
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
<div id="contentButtons">
|
||||
<input type="submit" value="<?php echo translate('Save') ?>"<?php if ( !canEdit( 'Monitors' ) ) { ?> disabled="disabled"<?php } ?>/><input type="button" value="<?php echo translate('Cancel') ?>" onclick="closeWindow()"/>
|
||||
<input type="submit" value="<?php echo translate('Save') ?>"<?php if ( !canEdit( 'Monitors' ) ) { ?> disabled="disabled"<?php } ?>/>
|
||||
<input type="button" value="<?php echo translate('Cancel') ?>" onclick="closeWindow()"/>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
|
Loading…
Reference in New Issue