Merge branch 'master' of github.com:ZoneMinder/zoneminder

This commit is contained in:
Isaac Connor 2021-12-09 15:09:50 -05:00
commit 6e01bca187
16 changed files with 251 additions and 184 deletions

View File

@ -21,28 +21,6 @@
# #
# ========================================================================== # ==========================================================================
=head1 NAME
zmfilter.pl - ZoneMinder tool to filter events
=head1 SYNOPSIS
zmfilter.pl [-f <filter name>,--filter=<filter name>] [--filter_id=<filter id>] | -v, --version
=head1 DESCRIPTION
This script continuously monitors the recorded events for the given
monitor and applies any filters which would delete and/or upload
matching events.
=head1 OPTIONS
-f{filter name}, --filter={filter name} - The name of a specific filter to run
--filter_id={filter id} - The id of a specific filter to run
-v, --version - Print ZoneMinder version
=cut
use strict; use strict;
use bytes; use bytes;
@ -163,7 +141,7 @@ delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
my $delay = $Config{ZM_FILTER_EXECUTE_INTERVAL}; my $delay = $Config{ZM_FILTER_EXECUTE_INTERVAL};
my $event_id = 0; my $event_id = 0;
if ( !EVENT_PATH ) { if (!EVENT_PATH) {
Error('No event path defined. Config was '.$Config{ZM_DIR_EVENTS}); Error('No event path defined. Config was '.$Config{ZM_DIR_EVENTS});
die; die;
} }
@ -195,22 +173,22 @@ if ( ! ( $filter_name or $filter_id ) ) {
my @filters; my @filters;
my $last_action = 0; my $last_action = 0;
while( !$zm_terminate ) { while (!$zm_terminate) {
my $now = time; my $now = time;
if ( ($now - $last_action) > $Config{ZM_FILTER_RELOAD_DELAY} ) { if (($now - $last_action) > $Config{ZM_FILTER_RELOAD_DELAY}) {
Debug('Reloading filters'); Debug('Reloading filters');
$last_action = $now; $last_action = $now;
@filters = getFilters({ Name=>$filter_name, Id=>$filter_id }); @filters = getFilters({ Name=>$filter_name, Id=>$filter_id });
} }
foreach my $filter ( @filters ) { foreach my $filter (@filters) {
last if $zm_terminate; last if $zm_terminate;
if ( $$filter{Concurrent} and ! ( $filter_id or $filter_name ) ) { if ($$filter{Concurrent} and !($filter_id or $filter_name)) {
my ( $proc ) = $0 =~ /(\S+)/; my ( $proc ) = $0 =~ /(\S+)/;
my ( $id ) = $$filter{Id} =~ /(\d+)/; my ( $id ) = $$filter{Id} =~ /(\d+)/;
Debug("Running concurrent filter process $proc --filter_id $$filter{Id} => $id for $$filter{Name}"); Debug("Running concurrent filter process $proc --filter_id $$filter{Id} => $id for $$filter{Name}");
system(qq`$proc --filter "$$filter{Name}" &`); system(qq`$proc --filter_id $id &`);
} else { } else {
checkFilter($filter); checkFilter($filter);
} }
@ -1051,9 +1029,7 @@ sub executeCommand {
my $filter = shift; my $filter = shift;
my $Event = shift; my $Event = shift;
my $event_path = $Event->Path(); my $command = $filter->{AutoExecuteCmd}.' '.$Event->Path();
my $command = $filter->{AutoExecuteCmd}.' '.$event_path;
$command = substituteTags($command, $filter, $Event); $command = substituteTags($command, $filter, $Event);
Info("Executing '$command'"); Info("Executing '$command'");
@ -1063,15 +1039,37 @@ sub executeCommand {
chomp($output); chomp($output);
Debug("Output: $output"); Debug("Output: $output");
} }
if ( $status ) { if ($status) {
Error("Command '$command' exited with status: $status"); Error("Command '$command' exited with status: $status");
return 0; return 0;
} else { } else {
my $sql = 'UPDATE `Events` SET `Executed` = 1 WHERE `Id` = ?'; zmSQLExecute('UPDATE `Events` SET `Executed` = 1 WHERE `Id` = ?', $Event->{Id});
my $sth = $dbh->prepare_cached($sql)
or Fatal("Unable to prepare '$sql': ".$dbh->errstr());
my $res = $sth->execute( $Event->{Id} )
or Fatal("Unable to execute '$sql': ".$dbh->errstr());
} }
return( 1 ); return 1;
} }
1;
__END__
=head1 NAME
zmfilter.pl - ZoneMinder tool to select events and perform actions on them
=head1 SYNOPSIS
zmfilter.pl [-f <filter name>,--filter=<filter name>] [--filter_id=<filter id>] [--daemon] | -v, --version
=head1 DESCRIPTION
This script performs a specified database query to select recorded events and performs specified actions on them
such as email reporting, deleting, moving, etc. If the --daemon option is given it will remain resident, repeating
the query and applying actions. This is normally managed by zmdc.pl however it can be used manually as well.
=head1 OPTIONS
-f{filter name}, --filter={filter name} - The name of a specific filter to run
--filter_id={filter id} - The id of a specific filter to run
--daemon - Causes zmfilter.pl to stay running endlessly repeating the filter(s).
-v, --version - Print ZoneMinder version
=cut

View File

@ -3047,9 +3047,6 @@ int Monitor::PrimeCapture() {
int Monitor::PreCapture() const { return camera->PreCapture(); } int Monitor::PreCapture() const { return camera->PreCapture(); }
int Monitor::PostCapture() const { return camera->PostCapture(); } int Monitor::PostCapture() const { return camera->PostCapture(); }
int Monitor::Close() { int Monitor::Close() {
if (close_event_thread.joinable()) {
close_event_thread.join();
}
// Because the stream indexes may change we have to clear out the packetqueue // Because the stream indexes may change we have to clear out the packetqueue
if (decoder) { if (decoder) {
decoder->Stop(); decoder->Stop();
@ -3067,10 +3064,14 @@ int Monitor::Close() {
video_fifo = nullptr; video_fifo = nullptr;
} }
if (close_event_thread.joinable()) {
close_event_thread.join();
}
std::lock_guard<std::mutex> lck(event_mutex); std::lock_guard<std::mutex> lck(event_mutex);
if (event) { if (event) {
Info("%s: image_count:%d - Closing event %" PRIu64 ", shutting down", name.c_str(), image_count, event->Id()); Info("%s: image_count:%d - Closing event %" PRIu64 ", shutting down", name.c_str(), image_count, event->Id());
closeEvent(); closeEvent();
close_event_thread.join();
} }
if (camera) camera->Close(); if (camera) camera->Close();
return 1; return 1;

View File

@ -13,6 +13,10 @@ class Zone extends ZM_Object {
'Name' => '', 'Name' => '',
'Type' => 'Active', 'Type' => 'Active',
'Units' => 'Pixels', 'Units' => 'Pixels',
'NumCoords' => '0',
'Coords' => 0,
'Area' => '0',
'AlarmRGB' => '0',
'CheckMethod' => 'Blobs', 'CheckMethod' => 'Blobs',
'MinPixelThreshold' => null, 'MinPixelThreshold' => null,
'MaxPixelThreshold' => null, 'MaxPixelThreshold' => null,
@ -46,5 +50,17 @@ class Zone extends ZM_Object {
return new Monitor(); return new Monitor();
} }
public function Points() {
return coordsToPoints($this->Coords());
}
public function AreaCoords() {
return preg_replace('/\s+/', ',', $this->Coords());
}
public function svg_polygon() {
return '<polygon points="'.$this->AreaCoords().'" class="'.$this->Type().'" />';
}
} # end class Zone } # end class Zone
?> ?>

View File

@ -87,11 +87,12 @@ define('ZM_PCRE', '@ZM_PCRE@'); // PCRE support enabled
// //
// Alarm states // Alarm states
// //
define('STATE_IDLE', 0); define('STATE_UNKNOWN', 0);
define('STATE_PREALARM', 1); define('STATE_IDLE', 1);
define('STATE_ALARM', 2); define('STATE_PREALARM', 2);
define('STATE_ALERT', 3); define('STATE_ALARM', 3);
define('STATE_TAPE', 4); define('STATE_ALERT', 4);
define('STATE_TAPE', 5);
// //
// DVR Control Commands // DVR Control Commands

View File

@ -77,7 +77,7 @@ height: 100%;
position: relative; position: relative;
} }
#imageFeed { #videoFeed {
display: inline-block; display: inline-block;
position: relative; position: relative;
text-align: center; text-align: center;
@ -263,3 +263,17 @@ height: 100%;
height: 100%; height: 100%;
background-color: #999999; background-color: #999999;
} }
svg.zones {
position:absolute;
top: 0;
left: 0;
background: none;
width: 100%;
/*
height: 100%;
*/
}
#videoobj {
width: 100%;
height: 100%;
}

View File

@ -0,0 +1,19 @@
.zones polygon {
fill-opacity: 0.25;
}
.Active {
stroke: #ff0000;
fill: #ff0000;
}
.Inclusive {
stroke: #FFA500;
fill: #FFA500;
}
.Exclusive {
stroke: #800080;
fill: #800080;
}
.Preclusive {
stroke: #0000FF;
fill: #0000FF;
}

View File

@ -90,3 +90,18 @@ unset($user_without_password['Password']);
echo json_encode($user_without_password); echo json_encode($user_without_password);
?>; ?>;
var running = <?php echo daemonCheck()?'true':'false' ?>; var running = <?php echo daemonCheck()?'true':'false' ?>;
var STATE_UNKNOWN = <?php echo STATE_UNKNOWN ?>;
var STATE_IDLE = <?php echo STATE_IDLE ?>;
var STATE_PREALARM = <?php echo STATE_PREALARM ?>;
var STATE_ALARM = <?php echo STATE_ALARM ?>;
var STATE_ALERT = <?php echo STATE_ALERT ?>;
var STATE_TAPE = <?php echo STATE_TAPE ?>;
var stateStrings = new Array();
stateStrings[STATE_UNKNOWN] = "<?php echo translate('Unknown') ?>";
stateStrings[STATE_IDLE] = "<?php echo translate('Idle') ?>";
stateStrings[STATE_PREALARM] = "<?php echo translate('Prealarm') ?>";
stateStrings[STATE_ALARM] = "<?php echo translate('Alarm') ?>";
stateStrings[STATE_ALERT] = "<?php echo translate('Alert') ?>";
stateStrings[STATE_TAPE] = "<?php echo translate('Record') ?>";

View File

@ -260,31 +260,37 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
?> ?>
<tr id="<?php echo 'monitor_id-'.$monitor['Id'] ?>" title="<?php echo $monitor['Id'] ?>"> <tr id="<?php echo 'monitor_id-'.$monitor['Id'] ?>" title="<?php echo $monitor['Id'] ?>">
<?php <?php
$source_class = 'infoText';
$source_class_reason = '';
if ( (!$monitor['Status'] || $monitor['Status'] == 'NotRunning') && $monitor['Type']!='WebSite' ) { if ( (!$monitor['Status'] || $monitor['Status'] == 'NotRunning') && $monitor['Type']!='WebSite' ) {
$source_class = 'errorText'; $source_class = 'errorText';
$source_class_reason = translate('Not Running');
} else { } else {
if ( $monitor['CaptureFPS'] == '0.00' ) { if ( $monitor['CaptureFPS'] == '0.00' ) {
$source_class = 'errorText'; $source_class = 'errorText';
$source_class_reason = translate('No capture FPS');
} else if ( (!$monitor['AnalysisFPS']) && ($monitor['Function']!='Monitor') && ($monitor['Function'] != 'Nodect') ) { } else if ( (!$monitor['AnalysisFPS']) && ($monitor['Function']!='Monitor') && ($monitor['Function'] != 'Nodect') ) {
$source_class = 'warnText'; $source_class = 'warnText';
} else { $source_class_reason = translate('No analysis FPS');
$source_class = 'infoText';
} }
} }
if ( $monitor['Function'] == 'None' )
$function_class = 'errorText';
else
$function_class = 'infoText';
$function_class = 'infoText';
if ($monitor['Function'] == 'None') {
$function_class = 'errorText';
}
$dot_class = $source_class;
$dot_class_reason = $source_class_reason;
if ( $function_class != 'infoText' ) {
$dot_class = $function_class;
} else if (($monitor['Function'] == 'Modect' || $monitor['Function'] == 'Mocord') and !$monitor['Enabled']) {
$dot_class .= ' warnText';
$dot_class_reason .= ' '.translate('Analysis is disabled');
}
$scale = max(reScale(SCALE_BASE, $monitor['DefaultScale'], ZM_WEB_DEFAULT_SCALE), SCALE_BASE); $scale = max(reScale(SCALE_BASE, $monitor['DefaultScale'], ZM_WEB_DEFAULT_SCALE), SCALE_BASE);
$stream_available = canView('Stream') and $monitor['Type']=='WebSite' or ($monitor['CaptureFPS'] && $monitor['Function'] != 'None'); $stream_available = canView('Stream') and $monitor['Type']=='WebSite' or ($monitor['CaptureFPS'] && $monitor['Function'] != 'None');
$dot_class = $source_class;
if ( $function_class != 'infoText' ) {
$dot_class = $function_class;
} else if ( !$monitor['Enabled'] ) {
$dot_class .= ' warnText';
}
if ( ZM_WEB_ID_ON_CONSOLE ) { if ( ZM_WEB_ID_ON_CONSOLE ) {
?> ?>
@ -317,7 +323,7 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
} }
?> ?>
<td class="colName"> <td class="colName">
<i class="material-icons md-18 <?php echo $dot_class ?>">lens</i> <i class="material-icons md-18 <?php echo $dot_class ?>" title="<?php echo $dot_class_reason ?>">lens</i>
<a <?php echo ($stream_available ? 'href="?view=watch&amp;mid='.$monitor['Id'].'">' : '>') . validHtmlStr($monitor['Name']) ?></a><br/> <a <?php echo ($stream_available ? 'href="?view=watch&amp;mid='.$monitor['Id'].'">' : '>') . validHtmlStr($monitor['Name']) ?></a><br/>
<?php echo $imgHTML ?> <?php echo $imgHTML ?>
<div class="small text-nowrap text-muted"> <div class="small text-nowrap text-muted">

View File

@ -25,47 +25,57 @@ if ( !canView('Events') ) {
require_once('includes/Event.php'); require_once('includes/Event.php');
require_once('includes/Filter.php'); require_once('includes/Filter.php');
require_once('includes/Zone.php');
$eid = validInt($_REQUEST['eid']); $eid = validInt($_REQUEST['eid']);
$fid = !empty($_REQUEST['fid']) ? validInt($_REQUEST['fid']) : 1; $fid = !empty($_REQUEST['fid']) ? validInt($_REQUEST['fid']) : 1;
$Event = new ZM\Event($eid); $Event = new ZM\Event($eid);
if ( $user['MonitorIds'] ) { $monitor = $Event->Monitor();
$monitor_ids = explode(',', $user['MonitorIds']);
if ( count($monitor_ids) and ! in_array($Event->MonitorId(), $monitor_ids) ) { if (!$monitor->canView()) {
$view = 'error'; $view = 'error';
return; return;
}
} }
$Monitor = $Event->Monitor();
if ( isset($_REQUEST['rate']) ) { zm_session_start();
if (isset($_REQUEST['rate']) ) {
$rate = validInt($_REQUEST['rate']); $rate = validInt($_REQUEST['rate']);
} else if ( isset($_COOKIE['zmEventRate']) ) { } else if (isset($_COOKIE['zmEventRate'])) {
$rate = $_COOKIE['zmEventRate']; $rate = $_COOKIE['zmEventRate'];
} else { } else {
$rate = reScale(RATE_BASE, $Monitor->DefaultRate(), ZM_WEB_DEFAULT_RATE); $rate = reScale(RATE_BASE, $monitor->DefaultRate(), ZM_WEB_DEFAULT_RATE);
} }
if ( isset($_REQUEST['scale']) ) { if (isset($_REQUEST['scale'])) {
$scale = validInt($_REQUEST['scale']); $scale = validInt($_REQUEST['scale']);
} else if ( isset($_COOKIE['zmEventScale'.$Event->MonitorId()]) ) { } else if (isset($_COOKIE['zmEventScale'.$Event->MonitorId()])) {
$scale = $_COOKIE['zmEventScale'.$Event->MonitorId()]; $scale = $_COOKIE['zmEventScale'.$Event->MonitorId()];
} else { } else {
$scale = $Monitor->DefaultScale(); $scale = $monitor->DefaultScale();
}
$showZones = false;
if (isset($_REQUEST['showZones'])) {
$showZones = $_REQUEST['showZones'] == 1;
$_SESSION['zmEventShowZones'.$monitor->Id()] = $showZones;
} else if (isset($_COOKIE['zmEventShowZones'.$monitor->Id()])) {
$showZones = $_COOKIE['zmEventShowZones'.$monitor->Id()] == 1;
} else if (isset($_SESSION['zmEventShowZones'.$monitor->Id()]) ) {
$showZones = $_SESSION['zmEventShowZones'.$monitor->Id()];
} }
$codec = 'auto'; $codec = 'auto';
if ( isset($_REQUEST['codec']) ) { if (isset($_REQUEST['codec'])) {
$codec = $_REQUEST['codec']; $codec = $_REQUEST['codec'];
zm_session_start();
$_SESSION['zmEventCodec'.$Event->MonitorId()] = $codec; $_SESSION['zmEventCodec'.$Event->MonitorId()] = $codec;
session_write_close();
} else if ( isset($_SESSION['zmEventCodec'.$Event->MonitorId()]) ) { } else if ( isset($_SESSION['zmEventCodec'.$Event->MonitorId()]) ) {
$codec = $_SESSION['zmEventCodec'.$Event->MonitorId()]; $codec = $_SESSION['zmEventCodec'.$Event->MonitorId()];
} else { } else {
$codec = $Monitor->DefaultCodec(); $codec = $monitor->DefaultCodec();
} }
session_write_close();
$codecs = array( $codecs = array(
'auto' => translate('Auto'), 'auto' => translate('Auto'),
'MP4' => translate('MP4'), 'MP4' => translate('MP4'),
@ -79,32 +89,30 @@ $replayModes = array(
'gapless' => translate('ReplayGapless'), 'gapless' => translate('ReplayGapless'),
); );
if ( isset($_REQUEST['streamMode']) ) if (isset($_REQUEST['streamMode']))
$streamMode = validHtmlStr($_REQUEST['streamMode']); $streamMode = validHtmlStr($_REQUEST['streamMode']);
else else
$streamMode = 'video'; $streamMode = 'video';
$replayMode = ''; $replayMode = '';
if ( isset($_REQUEST['replayMode']) ) if (isset($_REQUEST['replayMode']))
$replayMode = validHtmlStr($_REQUEST['replayMode']); $replayMode = validHtmlStr($_REQUEST['replayMode']);
if ( isset($_COOKIE['replayMode']) && preg_match('#^[a-z]+$#', $_COOKIE['replayMode']) ) if (isset($_COOKIE['replayMode']) && preg_match('#^[a-z]+$#', $_COOKIE['replayMode']))
$replayMode = validHtmlStr($_COOKIE['replayMode']); $replayMode = validHtmlStr($_COOKIE['replayMode']);
if ( ( !$replayMode ) or ( !$replayModes[$replayMode] ) ) { if ((!$replayMode) or !$replayModes[$replayMode]) {
$replayMode = 'none'; $replayMode = 'none';
} }
$video_tag = false; $video_tag = ($Event->DefaultVideo() and ($codec == 'MP4' or $codec == 'auto'));
if ( $Event->DefaultVideo() and ( $codec == 'MP4' or $codec == 'auto' ) ) {
$video_tag = true;
}
// videojs zoomrotate only when direct recording // videojs zoomrotate only when direct recording
$Zoom = 1; $Zoom = 1;
$Rotation = 0; $Rotation = 0;
if ( $Monitor->VideoWriter() == '2' ) { if ($monitor->VideoWriter() == '2') {
# Passthrough # Passthrough
$Rotation = $Event->Orientation(); $Rotation = $Event->Orientation();
if ( in_array($Event->Orientation(),array('90','270')) ) if (in_array($Event->Orientation(),array('90','270')))
$Zoom = $Event->Height()/$Event->Width(); $Zoom = $Event->Height()/$Event->Width();
} }
@ -143,7 +151,7 @@ if ( $Event->Id() and !file_exists($Event->Path()) )
<div id="toolbar" > <div id="toolbar" >
<button id="backBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Back') ?>" disabled><i class="fa fa-arrow-left"></i></button> <button id="backBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Back') ?>" disabled><i class="fa fa-arrow-left"></i></button>
<button id="refreshBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Refresh') ?>" ><i class="fa fa-refresh"></i></button> <button id="refreshBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Refresh') ?>" ><i class="fa fa-refresh"></i></button>
<?php if ( $Event->Id() ) { ?> <?php if ($Event->Id()) { ?>
<button id="renameBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Rename') ?>" disabled><i class="fa fa-font"></i></button> <button id="renameBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Rename') ?>" disabled><i class="fa fa-font"></i></button>
<button id="archiveBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Archive') ?>" disabled><i class="fa fa-archive"></i></button> <button id="archiveBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Archive') ?>" disabled><i class="fa fa-archive"></i></button>
<button id="unarchiveBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Unarchive') ?>" disabled><i class="fa fa-file-archive-o"></i></button> <button id="unarchiveBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Unarchive') ?>" disabled><i class="fa fa-file-archive-o"></i></button>
@ -158,7 +166,13 @@ if ( $Event->Id() and !file_exists($Event->Path()) )
<button id="statsBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Stats') ?>" ><i class="fa fa-info"></i></button> <button id="statsBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Stats') ?>" ><i class="fa fa-info"></i></button>
<button id="framesBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Frames') ?>" ><i class="fa fa-picture-o"></i></button> <button id="framesBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Frames') ?>" ><i class="fa fa-picture-o"></i></button>
<button id="deleteBtn" class="btn btn-danger" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Delete') ?>"><i class="fa fa-trash"></i></button> <button id="deleteBtn" class="btn btn-danger" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Delete') ?>"><i class="fa fa-trash"></i></button>
<?php } // end if Event->Id ?> <?php
if (canView('System')) { ?>
<button id="toggleZonesButton" class="btn btn-<?php echo $showZones?'normal':'secondary'?>" title="<?php echo translate(($showZones?'Hide':'Show').' Zones')?>" ><span class="material-icons"><?php echo $showZones?'layers_clear':'layers'?></span</button>
<?php
}
} // end if Event->Id
?>
</div> </div>
<h2><?php echo translate('Event').' '.$Event->Id() ?></h2> <h2><?php echo translate('Event').' '.$Event->Id() ?></h2>
@ -190,10 +204,10 @@ if ( $Event->Id() and !file_exists($Event->Path()) )
<div class=""> <div class="">
<div id="eventVideo"> <div id="eventVideo">
<!-- VIDEO CONTENT --> <!-- VIDEO CONTENT -->
<?php
if ( $video_tag ) {
?>
<div id="videoFeed"> <div id="videoFeed">
<?php
if ($video_tag) {
?>
<video autoplay id="videoobj" class="video-js vjs-default-skin" <video autoplay id="videoobj" class="video-js vjs-default-skin"
style="transform: matrix(1, 0, 0, 1, 0, 0);" style="transform: matrix(1, 0, 0, 1, 0, 0);"
<?php echo $scale ? 'width="'.reScale($Event->Width(), $scale).'"' : '' ?> <?php echo $scale ? 'width="'.reScale($Event->Width(), $scale).'"' : '' ?>
@ -209,21 +223,17 @@ if ( $video_tag ) {
<track id="monitorCaption" kind="captions" label="English" srclang="en" src='data:plain/text;charset=utf-8,"WEBVTT\n\n 00:00:00.000 --> 00:00:01.000 ZoneMinder"' default/> <track id="monitorCaption" kind="captions" label="English" srclang="en" src='data:plain/text;charset=utf-8,"WEBVTT\n\n 00:00:00.000 --> 00:00:01.000 ZoneMinder"' default/>
Your browser does not support the video tag. Your browser does not support the video tag.
</video> </video>
</div><!--videoFeed-->
<?php <?php
} else { } else {
?>
<div id="imageFeed">
<?php
if ( (ZM_WEB_STREAM_METHOD == 'mpeg') && ZM_MPEG_LIVE_FORMAT ) { if ( (ZM_WEB_STREAM_METHOD == 'mpeg') && ZM_MPEG_LIVE_FORMAT ) {
$streamSrc = $Event->getStreamSrc(array('mode'=>'mpeg', 'scale'=>$scale, 'rate'=>$rate, 'bitrate'=>ZM_WEB_VIDEO_BITRATE, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'format'=>ZM_MPEG_REPLAY_FORMAT, 'replay'=>$replayMode),'&amp;'); $streamSrc = $Event->getStreamSrc(array('mode'=>'mpeg', 'scale'=>$scale, 'rate'=>$rate, 'bitrate'=>ZM_WEB_VIDEO_BITRATE, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'format'=>ZM_MPEG_REPLAY_FORMAT, 'replay'=>$replayMode),'&amp;');
outputVideoStream('evtStream', $streamSrc, reScale( $Event->Width(), $scale ).'px', reScale( $Event->Height(), $scale ).'px', ZM_MPEG_LIVE_FORMAT ); outputVideoStream('evtStream', $streamSrc, reScale( $Event->Width(), $scale ).'px', reScale( $Event->Height(), $scale ).'px', ZM_MPEG_LIVE_FORMAT );
} else { } else {
$streamSrc = $Event->getStreamSrc(array('mode'=>'jpeg', 'frame'=>$fid, 'scale'=>$scale, 'rate'=>$rate, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'replay'=>$replayMode),'&amp;'); $streamSrc = $Event->getStreamSrc(array('mode'=>'jpeg', 'frame'=>$fid, 'scale'=>$scale, 'rate'=>$rate, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'replay'=>$replayMode),'&amp;');
if ( canStreamNative() ) { if ( canStreamNative() ) {
outputImageStream('evtStream', $streamSrc, reScale($Event->Width(), $scale).'px', reScale($Event->Height(), $scale).'px', validHtmlStr($Event->Name())); outputImageStream('evtStream', $streamSrc, '100%', '100%', validHtmlStr($Event->Name()));
} else { } else {
outputHelperStream('evtStream', $streamSrc, reScale($Event->Width(), $scale).'px', reScale($Event->Height(), $scale).'px' ); outputHelperStream('evtStream', $streamSrc, '100%', '100%');
} }
} // end if stream method } // end if stream method
?> ?>
@ -231,10 +241,18 @@ if ( (ZM_WEB_STREAM_METHOD == 'mpeg') && ZM_MPEG_LIVE_FORMAT ) {
<div id="progressBar" style="width: <?php echo reScale($Event->Width(), $scale);?>px;"> <div id="progressBar" style="width: <?php echo reScale($Event->Width(), $scale);?>px;">
<div class="progressBox" id="progressBox" title="" style="width: 0%;"></div> <div class="progressBox" id="progressBox" title="" style="width: 0%;"></div>
</div><!--progressBar--> </div><!--progressBar-->
</div><!--imageFeed-->
<?php <?php
} /*end if !DefaultVideo*/ } /*end if !DefaultVideo*/
?> ?>
<svg class="zones" id="zones<?php echo $monitor->Id() ?>" style="display:<?php echo $showZones ? 'block' : 'none'; ?>" viewBox="0 0 <?php echo $monitor->ViewWidth().' '.$monitor->ViewHeight() ?>" preserveAspectRatio="none">
<?php
foreach (ZM\Zone::find(array('MonitorId'=>$monitor->Id()), array('order'=>'Area DESC')) as $zone) {
echo $zone->svg_polygon();
} // end foreach zone
?>
Sorry, your browser does not support inline SVG
</svg>
</div><!--videoFeed-->
<p id="dvrControls"> <p id="dvrControls">
<button type="button" id="prevBtn" title="<?php echo translate('Prev') ?>" class="inactive" data-on-click-true="streamPrev"> <button type="button" id="prevBtn" title="<?php echo translate('Prev') ?>" class="inactive" data-on-click-true="streamPrev">
<i class="material-icons md-18">skip_previous</i> <i class="material-icons md-18">skip_previous</i>
@ -268,8 +286,8 @@ if ( (ZM_WEB_STREAM_METHOD == 'mpeg') && ZM_MPEG_LIVE_FORMAT ) {
<span id="mode"><?php echo translate('Mode') ?>: <span id="modeValue">Replay</span></span> <span id="mode"><?php echo translate('Mode') ?>: <span id="modeValue">Replay</span></span>
<span id="rate"><?php echo translate('Rate') ?>: <span id="rate"><?php echo translate('Rate') ?>:
<?php <?php
#rates are defined in skins/classic/includes/config.php #rates are defined in skins/classic/includes/config.php
echo htmlSelect('rate', $rates, intval($rate), array('id'=>'rateValue')); echo htmlSelect('rate', $rates, intval($rate), array('id'=>'rateValue'));
?> ?>
<!--<span id="rateValue"><?php echo $rate/100 ?></span>x</span>--> <!--<span id="rateValue"><?php echo $rate/100 ?></span>x</span>-->
<span id="progress"><?php echo translate('Progress') ?>: <span id="progressValue">0</span>s</span> <span id="progress"><?php echo translate('Progress') ?>: <span id="progressValue">0</span>s</span>
@ -283,4 +301,7 @@ echo htmlSelect('rate', $rates, intval($rate), array('id'=>'rateValue'));
</div><!--content--> </div><!--content-->
</div><!--page--> </div><!--page-->
<?php xhtmlFooter() ?> <?php
echo output_link_if_exists(array('css/base/zones.css'));
xhtmlFooter();
?>

View File

@ -177,7 +177,7 @@ function changeScale() {
var newWidth; var newWidth;
var newHeight; var newHeight;
var autoScale; var autoScale;
var eventViewer= $j(vid ? '#videoobj' : '#evtStream'); var eventViewer= $j(vid ? '#videoobj' : '#videoFeed');
var alarmCue = $j('div.alarmCue'); var alarmCue = $j('div.alarmCue');
var bottomEl = $j('#replayStatus'); var bottomEl = $j('#replayStatus');
@ -910,12 +910,12 @@ function initPage() {
progressBarNav(); progressBarNav();
streamCmdTimer = setTimeout(streamQuery, 500); streamCmdTimer = setTimeout(streamQuery, 500);
if (canStreamNative) { if (canStreamNative) {
if (!$j('#imageFeed')) { if (!$j('#videoFeed')) {
console.log('No element with id tag imageFeed found.'); console.log('No element with id tag videoFeed found.');
} else { } else {
var streamImg = $j('#imageFeed img'); var streamImg = $j('#videoFeed img');
if (!streamImg) { if (!streamImg) {
streamImg = $j('#imageFeed object'); streamImg = $j('#videoFeed object');
} }
$j(streamImg).click(function(event) { $j(streamImg).click(function(event) {
handleClick(event); handleClick(event);
@ -1071,5 +1071,27 @@ function initPage() {
}); });
} // end initPage } // end initPage
document.getElementById('toggleZonesButton').addEventListener('click', toggleZones);
function toggleZones(e) {
const zones = $j('#zones'+eventData.MonitorId);
const button = document.getElementById('toggleZonesButton');
if (zones.length) {
if (zones.is(":visible")) {
zones.hide();
button.setAttribute('title', showZonesString);
button.innerHTML = '<span class="material-icons">layers</span>';
setCookie('zmEventShowZones'+eventData.MonitorId, '0', 3600);
} else {
zones.show();
button.setAttribute('title', hideZonesString);
button.innerHTML = '<span class="material-icons">layers_clear</span>';
setCookie('zmEventShowZones'+eventData.MonitorId, '1', 3600);
}
} else {
console.error("Zones svg not found");
}
}
// Kick everything off // Kick everything off
$j(document).ready(initPage); $j(document).ready(initPage);

View File

@ -1,7 +1,7 @@
<?php <?php
global $connkey; global $connkey;
global $Event; global $Event;
global $Monitor; global $monitor;
global $filterQuery; global $filterQuery;
global $sortQuery; global $sortQuery;
global $rates; global $rates;
@ -43,8 +43,9 @@ var eventData = {
Id: '<?php echo $Event->Id() ?>', Id: '<?php echo $Event->Id() ?>',
Name: '<?php echo $Event->Name() ?>', Name: '<?php echo $Event->Name() ?>',
MonitorId: '<?php echo $Event->MonitorId() ?>', MonitorId: '<?php echo $Event->MonitorId() ?>',
MonitorName: '<?php echo validJsStr($Monitor->Name()) ?>', MonitorName: '<?php echo validJsStr($monitor->Name()) ?>',
Cause: '<?php echo validHtmlStr($Event->Cause()) ?>', Cause: '<?php echo validHtmlStr($Event->Cause()) ?>',
Notes: '<?php echo $Event->Notes()?>',
Width: '<?php echo $Event->Width() ?>', Width: '<?php echo $Event->Width() ?>',
Height: '<?php echo $Event->Height() ?>', Height: '<?php echo $Event->Height() ?>',
Length: '<?php echo $Event->Length() ?>', Length: '<?php echo $Event->Length() ?>',
@ -72,6 +73,7 @@ var eventDataStrings = {
MonitorId: '<?php echo translate('AttrMonitorId') ?>', MonitorId: '<?php echo translate('AttrMonitorId') ?>',
MonitorName: '<?php echo translate('AttrMonitorName') ?>', MonitorName: '<?php echo translate('AttrMonitorName') ?>',
Cause: '<?php echo translate('Cause') ?>', Cause: '<?php echo translate('Cause') ?>',
Notes: '<?php echo translate('Notes') ?>',
StartDateTimeShort: '<?php echo translate('AttrStartTime') ?>', StartDateTimeShort: '<?php echo translate('AttrStartTime') ?>',
Length: '<?php echo translate('Duration') ?>', Length: '<?php echo translate('Duration') ?>',
Frames: '<?php echo translate('AttrFrames') ?>', Frames: '<?php echo translate('AttrFrames') ?>',
@ -93,7 +95,7 @@ var sortQuery = '<?php echo isset($sortQuery)?validJsStr(htmlspecialchars_decode
var rates = <?php echo json_encode(array_keys($rates)) ?>; var rates = <?php echo json_encode(array_keys($rates)) ?>;
var rate = '<?php echo $rate ?>'; // really only used when setting up initial playback rate. var rate = '<?php echo $rate ?>'; // really only used when setting up initial playback rate.
var scale = "<?php echo $scale ?>"; var scale = "<?php echo $scale ?>";
var LabelFormat = "<?php echo validJsStr($Monitor->LabelFormat())?>"; var LabelFormat = "<?php echo validJsStr($monitor->LabelFormat())?>";
var streamTimeout = <?php echo 1000*ZM_WEB_REFRESH_STATUS ?>; var streamTimeout = <?php echo 1000*ZM_WEB_REFRESH_STATUS ?>;
@ -105,6 +107,8 @@ var streamMode = '<?php echo $streamMode ?>';
// //
var deleteString = "<?php echo validJsStr(translate('Delete')) ?>"; var deleteString = "<?php echo validJsStr(translate('Delete')) ?>";
var causeString = "<?php echo validJsStr(translate('AttrCause')) ?>"; var causeString = "<?php echo validJsStr(translate('AttrCause')) ?>";
var showZonesString = "<?php echo validJsStr(translate('Show Zones'))?>";
var hideZonesString = "<?php echo validJsStr(translate('Hide Zones'))?>";
var WEB_LIST_THUMB_WIDTH = '<?php echo ZM_WEB_LIST_THUMB_WIDTH ?>'; var WEB_LIST_THUMB_WIDTH = '<?php echo ZM_WEB_LIST_THUMB_WIDTH ?>';
var WEB_LIST_THUMB_HEIGHT = '<?php echo ZM_WEB_LIST_THUMB_HEIGHT ?>'; var WEB_LIST_THUMB_HEIGHT = '<?php echo ZM_WEB_LIST_THUMB_HEIGHT ?>';
var popup = '<?php echo $popup ?>'; var popup = '<?php echo $popup ?>';

View File

@ -1,18 +1,6 @@
// //
// Import constants // Import constants
// //
var STATE_IDLE = <?php echo STATE_IDLE ?>;
var STATE_PREALARM = <?php echo STATE_PREALARM ?>;
var STATE_ALARM = <?php echo STATE_ALARM ?>;
var STATE_ALERT = <?php echo STATE_ALERT ?>;
var STATE_TAPE = <?php echo STATE_TAPE ?>;
var stateStrings = new Array();
stateStrings[STATE_IDLE] = "<?php echo translate('Idle') ?>";
stateStrings[STATE_PREALARM] = "<?php echo translate('Idle') ?>";
stateStrings[STATE_ALARM] = "<?php echo translate('Alarm') ?>";
stateStrings[STATE_ALERT] = "<?php echo translate('Alert') ?>";
stateStrings[STATE_TAPE] = "<?php echo translate('Record') ?>";
var CMD_QUERY = <?php echo CMD_QUERY ?>; var CMD_QUERY = <?php echo CMD_QUERY ?>;

View File

@ -9,18 +9,6 @@
// //
// Import constants // Import constants
// //
var STATE_IDLE = <?php echo STATE_IDLE ?>;
var STATE_PREALARM = <?php echo STATE_PREALARM ?>;
var STATE_ALARM = <?php echo STATE_ALARM ?>;
var STATE_ALERT = <?php echo STATE_ALERT ?>;
var STATE_TAPE = <?php echo STATE_TAPE ?>;
var stateStrings = new Array();
stateStrings[STATE_IDLE] = "<?php echo translate('Idle') ?>";
stateStrings[STATE_PREALARM] = "<?php echo translate('Idle') ?>";
stateStrings[STATE_ALARM] = "<?php echo translate('Alarm') ?>";
stateStrings[STATE_ALERT] = "<?php echo translate('Alert') ?>";
stateStrings[STATE_TAPE] = "<?php echo translate('Record') ?>";
var deleteString = "<?php echo translate('Delete') ?>"; var deleteString = "<?php echo translate('Delete') ?>";

View File

@ -94,20 +94,6 @@ var deleteString = "<?php echo translate('Delete') ?>";
// Imported from watch.js.php and modified for new zone edit view // Imported from watch.js.php and modified for new zone edit view
// //
var STATE_IDLE = <?php echo STATE_IDLE ?>;
var STATE_PREALARM = <?php echo STATE_PREALARM ?>;
var STATE_ALARM = <?php echo STATE_ALARM ?>;
var STATE_ALERT = <?php echo STATE_ALERT ?>;
var STATE_TAPE = <?php echo STATE_TAPE ?>;
var stateStrings = new Array();
stateStrings[STATE_IDLE] = "<?php echo translate('Idle') ?>";
stateStrings[STATE_PREALARM] = "<?php echo translate('Idle') ?>";
stateStrings[STATE_ALARM] = "<?php echo translate('Alarm') ?>";
stateStrings[STATE_ALERT] = "<?php echo translate('Alert') ?>";
stateStrings[STATE_TAPE] = "<?php echo translate('Record') ?>";
var CMD_PAUSE = <?php echo CMD_PAUSE ?>; var CMD_PAUSE = <?php echo CMD_PAUSE ?>;
var CMD_PLAY = <?php echo CMD_PLAY ?>; var CMD_PLAY = <?php echo CMD_PLAY ?>;
var CMD_STOP = <?php echo CMD_STOP ?>; var CMD_STOP = <?php echo CMD_STOP ?>;

View File

@ -17,25 +17,10 @@ monitorData[monitorData.length] = {
} }
?> ?>
var STATE_IDLE = <?php echo STATE_IDLE ?>;
var STATE_PREALARM = <?php echo STATE_PREALARM ?>;
var STATE_ALARM = <?php echo STATE_ALARM ?>;
var STATE_ALERT = <?php echo STATE_ALERT ?>;
var STATE_TAPE = <?php echo STATE_TAPE ?>;
var stateStrings = new Array();
stateStrings[STATE_IDLE] = "<?php echo translate('Idle') ?>";
stateStrings[STATE_PREALARM] = "<?php echo translate('PreAlarm') ?>";
stateStrings[STATE_ALARM] = "<?php echo translate('Alarm') ?>";
stateStrings[STATE_ALERT] = "<?php echo translate('Alert') ?>";
stateStrings[STATE_TAPE] = "<?php echo translate('Record') ?>";
var CMD_PAUSE = <?php echo CMD_PAUSE ?>; var CMD_PAUSE = <?php echo CMD_PAUSE ?>;
var CMD_PLAY = <?php echo CMD_PLAY ?>; var CMD_PLAY = <?php echo CMD_PLAY ?>;
var CMD_STOP = <?php echo CMD_STOP ?>; var CMD_STOP = <?php echo CMD_STOP ?>;
var CMD_QUERY = <?php echo CMD_QUERY ?>; var CMD_QUERY = <?php echo CMD_QUERY ?>;
var CMD_QUIT = <?php echo CMD_QUIT ?>; var CMD_QUIT = <?php echo CMD_QUIT ?>;
var statusRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_STATUS ?>; var statusRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_STATUS ?>;

View File

@ -24,6 +24,7 @@ if ( !canView('Stream') ) {
} }
require_once('includes/MontageLayout.php'); require_once('includes/MontageLayout.php');
require_once('includes/Zone.php');
$showControl = false; $showControl = false;
$showZones = false; $showZones = false;
@ -49,7 +50,6 @@ $heights = array(
'1080' => '1080px', '1080' => '1080px',
); );
$layouts = ZM\MontageLayout::find(NULL, array('order'=>"lower('Name')")); $layouts = ZM\MontageLayout::find(NULL, array('order'=>"lower('Name')"));
$layoutsById = array(); $layoutsById = array();
foreach ( $layouts as $l ) { foreach ( $layouts as $l ) {
@ -278,27 +278,25 @@ foreach ( $monitors as $monitor ) {
} }
$zones = array(); $zones = array();
foreach( dbFetchAll('SELECT * FROM Zones WHERE MonitorId=? ORDER BY Area DESC', NULL, array($monitor->Id()) ) as $row ) { foreach ( ZM\Zone::find(array('MonitorId'=>$monitor->Id()), array('order'=>'Area DESC')) as $row ) {
$row['Points'] = coordsToPoints($row['Coords']); $points = $row->Points();
if ($scale) {
if ( $scale ) { limitPoints($points, 0, 0, $monitor->Width(), $monitor->Height());
limitPoints($row['Points'], 0, 0, $monitor->Width(), $monitor->Height());
} else { } else {
limitPoints($row['Points'], 0, 0, limitPoints($points, 0, 0,
( $width ? $width-1 : $monitor->ViewWidth()-1 ), ( $width ? $width-1 : $monitor->ViewWidth()-1 ),
( $height ? $height-1 : $monitor->ViewHeight()-1 ) ( $height ? $height-1 : $monitor->ViewHeight()-1 )
); );
} }
$row['Coords'] = pointsToCoords($row['Points']); $row->Coords(pointsToCoords($points));
$row['AreaCoords'] = preg_replace('/\s+/', ',', $row['Coords']);
$zones[] = $row; $zones[] = $row;
} // end foreach Zone } // end foreach Zone
?> ?>
<svg class="zones" id="zones<?php echo $monitor->Id() ?>" style="position:absolute; top: 0; left: 0; background: none; width: 100%; height: 100%;" viewBox="0 0 <?php echo $monitor->ViewWidth() ?> <?php echo $monitor->ViewHeight() ?>" preserveAspectRatio="none"> <svg class="zones" id="zones<?php echo $monitor->Id() ?>" style="position:absolute; top: 0; left: 0; background: none; width: 100%; height: 100%;" viewBox="0 0 <?php echo $monitor->ViewWidth().' '.$monitor->ViewHeight() ?>" preserveAspectRatio="none">
<?php <?php
foreach ( array_reverse($zones) as $zone ) { foreach (array_reverse($zones) as $zone) {
echo '<polygon points="'. $zone['AreaCoords'] .'" class="'. $zone['Type'].'" />'; echo $zone->svg_polygon();
} // end foreach zone } // end foreach zone
?> ?>
Sorry, your browser does not support inline SVG Sorry, your browser does not support inline SVG
@ -308,9 +306,14 @@ foreach ( array_reverse($zones) as $zone ) {
?> ?>
</div> </div>
<?php <?php
if ( (!ZM_WEB_COMPACT_MONTAGE) && ($monitor->Type() != 'WebSite') ) { if ((!ZM_WEB_COMPACT_MONTAGE) && ($monitor->Type() != 'WebSite')) {
?> ?>
<div id="monitorState<?php echo $monitor->Id() ?>" class="monitorState idle"><?php echo translate('State') ?>:&nbsp;<span id="stateValue<?php echo $monitor->Id() ?>"></span>&nbsp;-&nbsp;<span id="fpsValue<?php echo $monitor->Id() ?>"></span>&nbsp;fps</div> <div id="monitorState<?php echo $monitor->Id() ?>" class="monitorState idle">
<?php echo translate('State') ?>:
<span id="stateValue<?php echo $monitor->Id() ?>"></span>
&nbsp;-&nbsp;
<span id="fpsValue<?php echo $monitor->Id() ?>"></span>&nbsp;fps
</div>
<?php <?php
} }
?> ?>