Merge branch 'master' into storageareas

This commit is contained in:
Isaac Connor 2017-06-04 21:42:56 -04:00
commit 451714a403
28 changed files with 1464 additions and 1425 deletions

View File

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

View File

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

View File

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

View File

@ -1 +1 @@
3.0 (native)
3.0 (quilt)

View File

@ -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',
},
{

View File

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

View File

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

View File

@ -40,15 +40,15 @@ 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(
zmMemKey
zmMemAttach
zmMemDetach
zmMemGet
zmMemPut
zmMemClean
) ],
);
functions => [ qw(
zmMemKey
zmMemAttach
zmMemDetach
zmMemGet
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" );

View File

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

View File

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

View File

@ -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 );
}
}
@ -363,52 +384,53 @@ sub generateVideo {
# If neither capture nor analyse image exists it will try to extract a frame from .mp4 file if exists
# An empty string is returned if no one from methods above works
sub generateImage {
my $event = shift;
my $frame = shift;
my $analyse = do { @_ ? shift : 0 }; # don't return analyse image by default
my $event = shift;
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
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) ) {
$image_path = $capture_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
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) ) {
$image_path = $capture_image_path;
}
return $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,73 +474,72 @@ 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" );
my $ftp = Net::FTP->new(
$Config{ZM_UPLOAD_HOST},
Timeout=>$Config{ZM_UPLOAD_TIMEOUT},
Passive=>$Config{ZM_UPLOAD_FTP_PASSIVE},
Debug=>$Config{ZM_UPLOAD_DEBUG}
);
if ( !$ftp ) {
Error( "Can't create FTP connection: $@" );
return( 0 );
}
$ftp->login( $Config{ZM_UPLOAD_USER}, $Config{ZM_UPLOAD_PASS} )
or Error( "FTP - Can't login" );
$ftp->binary()
or Error( "FTP - Can't go binary" );
$ftp->cwd( $Config{ZM_UPLOAD_REM_DIR} )
or Error( "FTP - Can't cwd" )
if ( $Config{ZM_UPLOAD_REM_DIR} );
$ftp->put( $archLocPath )
or Error( "FTP - Can't upload '$archLocPath'" );
$ftp->quit()
or Error( "FTP - Can't quit" );
} else {
my $host = $Config{ZM_UPLOAD_HOST};
$host .= ":".$Config{ZM_UPLOAD_PORT}
if $Config{ZM_UPLOAD_PORT};
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};
$sftpOptions{port} = $Config{ZM_UPLOAD_PORT}
if $Config{ZM_UPLOAD_PORT};
$sftpOptions{timeout} = $Config{ZM_UPLOAD_TIMEOUT}
if $Config{ZM_UPLOAD_TIMEOUT};
my @more_ssh_args;
push @more_ssh_args, '-o'=>'StrictHostKeyChecking=no'
if ! $Config{ZM_UPLOAD_STRICT};
push @more_ssh_args, '-v'
if $Config{ZM_UPLOAD_DEBUG};
$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 );
return( 0 );
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},
Passive=>$Config{ZM_UPLOAD_FTP_PASSIVE},
Debug=>$Config{ZM_UPLOAD_DEBUG}
);
if ( !$ftp ) {
Error( "Unable tocreate FTP connection: $@" );
return( 0 );
}
$ftp->login( $Config{ZM_UPLOAD_USER}, $Config{ZM_UPLOAD_PASS} )
or Error( "FTP - Unable tologin" );
$ftp->binary()
or Error( "FTP - Unable togo binary" );
$ftp->cwd( $Config{ZM_UPLOAD_REM_DIR} )
or Error( "FTP - Unable tocwd" )
if ( $Config{ZM_UPLOAD_REM_DIR} );
$ftp->put( $archLocPath )
or Error( "FTP - Unable toupload '$archLocPath'" );
$ftp->quit()
or Error( "FTP - Unable toquit" );
} else {
my $host = $Config{ZM_UPLOAD_HOST};
$host .= ':'.$Config{ZM_UPLOAD_PORT}
if $Config{ZM_UPLOAD_PORT};
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};
$sftpOptions{port} = $Config{ZM_UPLOAD_PORT}
if $Config{ZM_UPLOAD_PORT};
$sftpOptions{timeout} = $Config{ZM_UPLOAD_TIMEOUT}
if $Config{ZM_UPLOAD_TIMEOUT};
my @more_ssh_args;
push @more_ssh_args, '-o'=>'StrictHostKeyChecking=no'
if ! $Config{ZM_UPLOAD_STRICT};
push @more_ssh_args, '-v'
if $Config{ZM_UPLOAD_DEBUG};
$sftpOptions{more} = [@more_ssh_args];
my $sftp = Net::SFTP::Foreign->new( $Config{ZM_UPLOAD_HOST}, %sftpOptions );
if ( $sftp->error ) {
Error( "Unable tocreate SFTP connection: ".$sftp->error );
return( 0 );
}
$sftp->setcwd( $Config{ZM_UPLOAD_REM_DIR} )
or Error( "SFTP - Unable tosetcwd: ".$sftp->error )
if $Config{ZM_UPLOAD_REM_DIR};
$sftp->put( $archLocPath, $archFile )
or Error( "SFTP - Unable toupload '$archLocPath': ".$sftp->error );
}
$sftp->setcwd( $Config{ZM_UPLOAD_REM_DIR} )
or Error( "SFTP - Can't setcwd: ".$sftp->error )
if $Config{ZM_UPLOAD_REM_DIR};
$sftp->put( $archLocPath, $archFile )
or Error( "SFTP - Can't upload '$archLocPath': ".$sftp->error );
unlink( $archLocPath );
my $sql = 'UPDATE Events SET Uploaded = 1 WHERE Id = ?';
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Unable toprepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $event->{Id} )
or Fatal( "Unable toexecute '$sql': ".$sth->errstr() );
}
unlink( $archLocPath );
my $sql = "update Events set Uploaded = 1 where Id = ?";
my $sth = $dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $event->{Id} )
or Fatal( "Can't execute '$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);
if ( -e $path ) {
push( @$attachments_ref,
{
type=>"image/jpeg",
path=>$path
}
);
}
}
if ( $attachments_ref && $text =~ s/%EIM%//g ) {
# 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, $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/%EI1A%//g ) {
my $path = generateImage( $event, $first_alarm_frame, "analyse" );
if ( -e $path ) {
push( @$attachments_ref,
{
type=>"image/jpeg",
path=>$path
if ( $attachments_ref && $text =~ s/%EIM%//g ) {
# 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 );
if ( -e $path ) {
push( @$attachments_ref, { type=>'image/jpeg', path=>$path } );
}
);
}
}
if ( $attachments_ref && $text =~ s/%EIMA%//g ) {
# 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");
if ( -e $path ) {
push( @$attachments_ref,
{
type=>"image/jpeg",
path=>$path
}
);
}
}
}
}
if ( $attachments_ref && $text =~ s/%EI1A%//g ) {
my $path = generateImage( $event, $first_alarm_frame, 'analyse' );
if ( -e $path ) {
push( @$attachments_ref, { type=>'image/jpeg', path=>$path } );
}
}
if ( $attachments_ref && $text =~ s/%EIMA%//g ) {
# 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');
if ( -e $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 );
}

View File

@ -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 );
@ -688,18 +683,22 @@ else if ( packet.pts && video_last_pts > packet.pts ) {
}
#endif
}
if (
( packet.stream_index != mAudioStreamId || record_audio )
&&
( key_frame || packetqueue.size() )
) {
packetqueue.queuePacket( &packet );
// 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
if ( packet.stream_index == mVideoStreamId ) {
if ( videoStore ) {
if ( videoStore ) {
//Write the packet to our video store
int ret = videoStore->writeVideoFramePacket( &packet );
if ( ret < 0 ) { //Less than zero and we skipped a frame
@ -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)

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -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
@ -116,7 +133,7 @@ installtrusty () {
# This sets the naming convention for the deb packages
setdebpkgver () {
# Set VERSION to x.xx.x+x e.g. 1.30.2+15
# the last x is number of commits since release
# Creates zoneminder packages in the format: zoneminder-{version}-{release}
@ -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}"
@ -199,7 +230,9 @@ if [ "${TRAVIS_EVENT_TYPE}" == "cron" ] || [ "${TRAVIS}" != "true" ]; then
else
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

View File

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

View 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,20 +201,26 @@ 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 ) ) {
# Generate the frame JPG
# Generate the frame JPG
if ( $Event->DefaultVideo() ) {
$videoPath = $eventPath.'/'.$Event->DefaultVideo();
@ -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,
);

View File

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

View File

@ -1149,17 +1149,17 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&amp;' ) {
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='&amp;' ) {
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='&amp;' ) {
$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";
}

View File

@ -23,29 +23,28 @@
$bad_views = array('monitor', 'log');
function xhtmlHeaders( $file, $title ) {
global $css;
global $skin;
$skinCssFile = getSkinFile( 'css/'.$css.'/skin.css' );
$skinCssPhpFile = getSkinFile( 'css/'.$css.'/skin.css.php' );
global $css;
global $skin;
$skinCssFile = getSkinFile( 'css/'.$css.'/skin.css' );
$skinCssPhpFile = getSkinFile( 'css/'.$css.'/skin.css.php' );
$skinJsFile = getSkinFile( 'js/skin.js' );
$skinJsPhpFile = getSkinFile( 'js/skin.js.php' );
$cssJsFile = getSkinFile( 'js/'.$css.'.js' );
$skinJsFile = getSkinFile( 'js/skin.js' );
$skinJsPhpFile = getSkinFile( 'js/skin.js.php' );
$cssJsFile = getSkinFile( 'js/'.$css.'.js' );
$basename = basename( $file, '.php' );
$viewCssFile = getSkinFile( '/css/'.$css.'/views/'.$basename.'.css' );
$viewCssPhpFile = getSkinFile( '/css/'.$css.'/views/'.$basename.'.css.php' );
$viewJsFile = getSkinFile( 'views/js/'.$basename.'.js' );
$viewJsPhpFile = getSkinFile( 'views/js/'.$basename.'.js.php' );
$basename = basename( $file, '.php' );
$viewCssFile = getSkinFile( '/css/'.$css.'/views/'.$basename.'.css' );
$viewCssPhpFile = getSkinFile( '/css/'.$css.'/views/'.$basename.'.css.php' );
$viewJsFile = getSkinFile( 'views/js/'.$basename.'.js' );
$viewJsPhpFile = getSkinFile( 'views/js/'.$basename.'.js.php' );
extract( $GLOBALS, EXTR_OVERWRITE );
extract( $GLOBALS, EXTR_OVERWRITE );
?>
<!DOCTYPE html>
<html lang="en">
<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"/>
@ -54,17 +53,17 @@ function xhtmlHeaders( $file, $title ) {
<link rel="stylesheet" href="css/bootstrap.min.css" type="text/css"/>
<link rel="stylesheet" href="<?php echo $skinCssFile ?>" type="text/css" media="screen"/>
<?php
if ( $viewCssFile ) {
if ( $viewCssFile ) {
?>
<link rel="stylesheet" href="<?php echo $viewCssFile ?>" type="text/css" media="screen"/>
<?php
}
if ( $viewCssPhpFile ) {
}
if ( $viewCssPhpFile ) {
?>
<style type="text/css">
/*<![CDATA[*/
<?php
require_once( $viewCssPhpFile );
require_once( $viewCssPhpFile );
?>
/*]]>*/
</style>
@ -96,8 +95,9 @@ 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 }
if ( $skinJsPhpFile ) {
<?php
}
if ( $skinJsPhpFile ) {
?>
<script type="text/javascript">
//<![CDATA[
@ -109,20 +109,20 @@ var $j = jQuery.noConflict();
//]]>
</script>
<?php
}
if ( $viewJsPhpFile ) {
}
if ( $viewJsPhpFile ) {
?>
<script type="text/javascript">
//<![CDATA[
<!--
<?php
require_once( $viewJsPhpFile );
require_once( $viewJsPhpFile );
?>
//-->
//]]>
</script>
<?php
}
}
if ( $cssJsFile ) {
?>
<script type="text/javascript" src="<?php echo $cssJsFile ?>"></script>
@ -130,11 +130,11 @@ var $j = jQuery.noConflict();
<script type="text/javascript" src="<?php echo $skinJsFile ?>"></script>
<script type="text/javascript" src="js/logger.js"></script>
<?php
if ( $viewJsFile ) {
if ( $viewJsFile ) {
?>
<script type="text/javascript" src="<?php echo $viewJsFile ?>"></script>
<?php
}
}
?>
</head>
<?php

View File

@ -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&amp;filter[terms][0][attr]=DateTime&amp;filter[terms][0][op]=%3c&amp;filter[terms][0][val]=now', 'zmFilter', 'filter', translate('Filters'), canView( 'Events' ) ) ?>
<input 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.'&amp;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&amp;filter[terms][0][attr]=DateTime&amp;filter[terms][0][op]=%3c&amp;filter[terms][0][val]=now', 'zmFilter', 'filter', translate('Filters'), canView( 'Events' ) ) ?>
<input 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.'&amp;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>

View File

@ -81,7 +81,7 @@ if ( !empty($page) ) {
}
$eventsSql .= " limit $limitStart, $limitAmount";
} elseif ( !empty( $limit ) ) {
$eventsSql .= " limit 0, ".$limit;
$eventsSql .= ' limit 0, '.$limit;
}
$maxWidth = 0;
@ -118,15 +118,15 @@ xhtmlHeaders(__FILE__, translate('Events') );
<div id="headerButtons">
<?php
if ( $pages > 1 ) {
if ( !empty($page) ) {
if ( !empty($page) ) {
?>
<a href="?view=<?php echo $view ?>&amp;page=0<?php echo $filterQuery ?><?php echo $sortQuery ?>&amp;limit=<?php echo $limit ?>"><?php echo translate('ViewAll') ?></a>
<?php
} else {
} else {
?>
<a href="?view=<?php echo $view ?>&amp;page=1<?php echo $filterQuery ?><?php echo $sortQuery ?>&amp;limit=<?php echo $limit ?>"><?php echo translate('ViewPaged') ?></a>
<?php
}
}
}
?>
<a href="#" onclick="closeWindows();"><?php echo translate('Close') ?></a>
@ -173,21 +173,22 @@ 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
}
if ( ZM_WEB_LIST_THUMBS ) {
}
if ( ZM_WEB_LIST_THUMBS ) {
?>
<th class="colThumbnail"><?php echo translate('Thumbnail') ?></th>
<?php
}
}
?>
<th class="colMark"><input type="checkbox" name="toggleCheck" value="1" onclick="toggleCheckbox( this, 'markEids' );"<?php if ( !canEdit( 'Events' ) ) { ?> disabled="disabled"<?php } ?>/></th>
</tr>
<?php
}
$scale = max( reScale( SCALE_BASE, $event->DefaultScale(), ZM_WEB_DEFAULT_SCALE ), SCALE_BASE );
}
$scale = max( reScale( SCALE_BASE, $event->DefaultScale(), ZM_WEB_DEFAULT_SCALE ), SCALE_BASE );
?>
<tr>
<td class="colId"><?php echo makePopupLink( '?view=event&amp;eid='.$event->Id().$filterQuery.$sortQuery.'&amp;page=1', 'zmEvent', array( 'event', reScale( $event->Width(), $scale ), reScale( $event->Height(), $scale ) ), $event->Id().($event->Archived()?'*':'') ) ?></td>
@ -201,35 +202,37 @@ 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&amp;eid='.$event->Id().'&amp;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
}
if ( ZM_WEB_LIST_THUMBS ) {
if ( $thumbData = $event->createListThumbnail() ) {
}
if ( ZM_WEB_LIST_THUMBS ) {
if ( $thumbData = $event->createListThumbnail() ) {
?>
<td class="colThumbnail">
<?php
$imgSrc = '?view=image&amp;eid='.$event->Id().'&amp;fid='.$thumbData['FrameId'].'&amp;width='.$thumbData['Width'].'&amp;height='.$thumbData['Height'];
$streamSrc = getStreamSrc( array( "source=event", "mode=jpeg", "event=".$event->Id(), "scale=".$scale, "maxfps=".ZM_WEB_VIDEO_MAXFPS, "replay=single") );
<?php
$imgSrc = '?view=image&amp;eid='.$event->Id().'&amp;fid='.$thumbData['FrameId'].'&amp;width='.$thumbData['Width'].'&amp;height='.$thumbData['Height'];
$streamSrc = getStreamSrc( array( "source=event", "mode=jpeg", "event=".$event->Id(), "scale=".$scale, "maxfps=".ZM_WEB_VIDEO_MAXFPS, "replay=single") );
$imgHtml = '<img id="thumbnail'.$event->id().'" src="'.$imgSrc.'" alt="'. validHtmlStr('Event '.$event->Id()) .'" style="width:'. validInt($thumbData['Width']) .'px;height:'. validInt( $thumbData['Height'] ).'px;" onmouseover="this.src=\''.$streamSrc.'\';" onmouseout="this.src=\''.$imgSrc.'\';"/>';
$imgHtml = '<img id="thumbnail'.$event->id().'" src="'.$imgSrc.'" alt="'. validHtmlStr('Event '.$event->Id()) .'" style="width:'. validInt($thumbData['Width']) .'px;height:'. validInt( $thumbData['Height'] ).'px;" onmouseover="this.src=\''.$streamSrc.'\';" onmouseout="this.src=\''.$imgSrc.'\';"/>';
echo makePopupLink(
'?view=frame&amp;eid='.$event->Id().'&amp;fid='.$thumbData['FrameId'],
'zmImage',
array( 'image', reScale( $event->Width(), $scale ), reScale( $event->Height(), $scale ) ),
$imgHtml
);
?></td>
echo makePopupLink(
'?view=frame&amp;eid='.$event->Id().'&amp;fid='.$thumbData['FrameId'],
'zmImage',
array( 'image', reScale( $event->Width(), $scale ), reScale( $event->Height(), $scale ) ),
$imgHtml
);
?>
</td>
<?php
} else {
} else {
?>
<td class="colThumbnail">&nbsp;</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"/>

View File

@ -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' );
@ -180,98 +186,108 @@ for ( $i = 0; isset($_REQUEST['filter']) && $i < count($_REQUEST['filter']['term
?>
<tr>
<?php
if ( $i == 0 ) {
if ( $i == 0 ) {
?>
<td>&nbsp;</td>
<?php
} else {
} else {
?>
<td><?php echo buildSelect( "filter[terms][$i][cnj]", $conjunctionTypes ); ?></td>
<?php
}
}
?>
<td><?php if ( count($_REQUEST['filter']['terms']) > 2 ) { echo buildSelect( "filter[terms][$i][obr]", $obracketTypes ); } else { ?>&nbsp;<?php } ?></td>
<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 ( isset($_REQUEST['filter']['terms'][$i]['attr']) ) {
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();
foreach ( dbFetchAll( 'SELECT Id,Name FROM States ORDER BY lower(Name) ASC' ) as $state_row ) {
$states[$state_row['Id']] = $state_row['Name'];
}
} elseif ( $_REQUEST['filter']['terms'][$i]['attr'] == "StateId" ) {
$states = array();
foreach ( dbFetchAll( 'SELECT Id,Name FROM States ORDER BY lower(Name) ASC' ) as $state_row ) {
$states[$state_row['Id']] = $state_row['Name'];
}
?>
<td><?php echo buildSelect( "filter[terms][$i][op]", $opTypes ); ?></td>
<td><?php echo buildSelect( "filter[terms][$i][val]", $states ); ?></td>
<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" ) {
$monitors = array();
foreach ( dbFetchAll( "select Id,Name from Monitors order by Sequence asc" ) as $monitor ) {
if ( visibleMonitor( $monitor['Id'] ) ) {
$monitors[$monitor['Name']] = $monitor['Name'];
}
}
} 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'] ) ) {
$monitors[$monitor['Name']] = $monitor['Name'];
}
}
?>
<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" ) {
$servers = array();
$servers['ZM_SERVER_ID'] = 'Current Server';
foreach ( dbFetchAll( "SELECT Id,Name FROM Servers ORDER BY lower(Name) ASC" ) as $server ) {
$servers[$server['Id']] = $server['Name'];
}
} 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 ) {
$servers[$server['Id']] = $server['Name'];
}
?>
<td><?php echo buildSelect( "filter[terms][$i][op]", $opTypes ); ?></td>
<td><?php echo buildSelect( "filter[terms][$i][val]", $servers ); ?></td>
<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" ) {
$storageareas = array();
$storageareas[0] = 'Default ' . ZM_DIR_EVENTS;
foreach ( dbFetchAll( "SELECT Id,Name FROM Storage ORDER BY lower(Name) ASC" ) as $storage ) {
$storageareas[$storage['Id']] = $storage['Name'];
}
} 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 ) {
$storageareas[$storage['Id']] = $storage['Name'];
}
?>
<td><?php echo buildSelect( "filter[terms][$i][op]", $opTypes ); ?></td>
<td><?php echo buildSelect( "filter[terms][$i][val]", $storageareas ); ?></td>
<?php
} else {
} else {
?>
<td><?php echo buildSelect( "filter[terms][$i][op]", $opTypes ); ?></td>
<td><input name="filter[terms][<?php echo $i ?>][val]" value="<?php echo $_REQUEST['filter']['terms'][$i]['val'] ?>"/></td>
<?php
}
} else {
}
} else {
?>
<td><?php echo buildSelect( "filter[terms][$i][op]", $opTypes ); ?></td>
<td><input name="filter[terms][<?php echo $i ?>][val]" value="<?php echo isset($_REQUEST['filter']['terms'][$i]['val'])?$_REQUEST['filter']['terms'][$i]['val']:'' ?>"/></td>
<?php
}
}
?>
<td><?php if ( count($_REQUEST['filter']['terms']) > 2 ) { echo buildSelect( "filter[terms][$i][cbr]", $cbracketTypes ); } else { ?>&nbsp;<?php } ?></td>
<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>

View File

@ -37,7 +37,7 @@ if ( !empty($fid) ) {
if ( !($frame = dbFetchOne( $sql, NULL, array($eid, $fid) )) )
$frame = array( 'FrameId'=>$fid, 'Type'=>'Normal', 'Score'=>0 );
} else {
$frame = dbFetchOne( 'SELECT * FROM Frames WHERE EventId = ? AND Score = ?', NULL, array( $eid, $Event->MaxScore() ) );
$frame = dbFetchOne( 'SELECT * FROM Frames WHERE EventId = ? AND Score = ?', NULL, array( $eid, $Event->MaxScore() ) );
}
$Frame = new Frame( $frame );
@ -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&amp;eid=<?php echo $Event->Id() ?>&amp;fid=<?php echo $Frame->FrameId() ?>&amp;scale=<?php echo $scale ?>&amp;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&amp;eid=%d&amp;fid=%d&scale=%d&amp;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 ) { ?>

View File

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

View File

@ -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&amp;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
$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' ) )
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 '/>&nbsp;'. $optTrigger ;
?>
<tr><td><?php echo translate('Triggers') ?></td><td>
<?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' )
continue;
if ( $optCount && ($optCount%$breakCount == 0) )
echo '</br>';
?>
<input type="checkbox" name="newMonitor[Triggers][]" value="<?php echo $optTrigger ?>"<?php if ( isset($newMonitor['Triggers']) && in_array( $optTrigger, $newMonitor['Triggers'] ) ) { ?> checked="checked"<?php } ?>/>&nbsp;<?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,70 +856,111 @@ switch ( $tab ) {
<tr id="RTSPDescribe"<?php if ( $monitor->Protocol != 'rtsp' ) { echo ' style="display:none;"'; } ?>><td><?php echo translate('RTSPDescribe') ?>&nbsp;(<?php echo makePopupLink( '?view=optionhelp&amp;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
break;
?>
<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') ?>&nbsp;(<?php echo makePopupLink('?view=optionhelp&amp;option=OPTIONS_RTSPTrans', 'zmOptionHelp', 'optionhelp', '?' ) ?>)</td><td><?php echo buildSelect( "newMonitor[Method]", $rtspFFMpegMethods ); ?></td></tr>
<tr><td><?php echo translate('Options') ?>&nbsp;(<?php echo makePopupLink( '?view=optionhelp&amp;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') ?>&nbsp;(<?php echo makePopupLink( '?view=optionhelp&amp;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
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 == $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
break;
?>
<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
break;
?>
<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' ) ) { ?>&nbsp;<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
$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
break;
?>
<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' ) ) { ?>&nbsp;<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($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
break;
?>
<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
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>