Merge branch 'master' into storageareas

This commit is contained in:
Isaac Connor 2019-02-13 09:42:03 -05:00
commit d1b3b23c09
6 changed files with 306 additions and 85 deletions

View File

@ -3,6 +3,205 @@ Ubuntu
.. contents::
Easy Way: Ubuntu 18.04
----------------------
These instructions are for a brand new ubuntu 18.04 system which does not have ZM
installed.
It is recommended that you use an Ubuntu Server install and select the LAMP option
during install to install Apache, MySQL and PHP. If you failed to do this you can
achieve the same result by running:
::
sudo tasksel install lamp-server
During installation it will ask you to set up a master/root password for the MySQL.
Installing LAMP is not ZoneMinder specific so you will find plenty of resources to
guide you with a quick search.
**Step 1:** Either run commands in this install using sudo or use the below to become root
::
sudo -i
**Step 2:** Update Repos
.. topic :: Latest Release
ZoneMinder is now part of the current standard Ubuntu repository, but
sometimes the official repository can lag behind. To find out check our
`releases page <https://github.com/ZoneMinder/zoneminder/releases>`_ for
the latest release.
Alternatively, the ZoneMinder project team maintains a `PPA <https://askubuntu.com/questions/4983/what-are-ppas-and-how-do-i-use-them>`_, which is updated immediately
following a new release of ZoneMinder. To use this repository instead of the
official Ubuntu repository, enter the following from the command line:
::
add-apt-repository ppa:iconnor/zoneminder
Please note that as of 1.32.0 We are creating a new PPA for each major version, as a means to prevent automatic upgrades from one major version to another. So instead of the above ppa line use the following:
::
add-apt-repository ppa:iconnor/zoneminder-1.32
If you are on Trusty or Xenial, you may want to add both, as there are some packages for dependencies included in the old ppa.
Update repo and upgrade.
::
apt-get update
apt-get upgrade
apt-get dist-upgrade
**Step 3:** Configure MySQL
.. sidebar :: Note
The MySQL default configuration file (/etc/mysql/mysql.cnf)is read through
several symbolic links beginning with /etc/mysql/my.cnf as follows:
| /etc/mysql/my.cnf -> /etc/alternatives/my.cnf
| /etc/alternatives/my.cnf -> /etc/mysql/mysql.cnf
| /etc/mysql/mysql.cnf is a basic file
Certain new defaults in MySQL 5.7 cause some issues with ZoneMinder < 1.32.0,
the workaround is to modify the sql_mode setting of MySQL. Please note that these
changes are NOT required for ZoneMinder 1.32.0 and some people have reported them
causing problems in 1.32.0.
To better manage the MySQL server it is recommended to copy the sample config file and
replace the default my.cnf symbolic link.
::
rm /etc/mysql/my.cnf (this removes the current symbolic link)
cp /etc/mysql/mysql.conf.d/mysqld.cnf /etc/mysql/my.cnf
To change MySQL settings:
::
nano /etc/mysql/my.cnf
In the [mysqld] section add the following
::
sql_mode = NO_ENGINE_SUBSTITUTION
CTRL+o then [Enter] to save
CTRL+x to exit
Restart MySQL
::
systemctl restart mysql
**Step 4:** Install ZoneMinder
::
apt-get install zoneminder
**Step 5:** Configure the ZoneMinder Database
This step should not be required on ZoneMinder 1.32.0.
::
mysql -uroot -p < /usr/share/zoneminder/db/zm_create.sql
mysql -uroot -p -e "grant lock tables,alter,drop,select,insert,update,delete,create,index,alter routine,create routine, trigger,execute on zm.* to 'zmuser'@localhost identified by 'zmpass';"
**Step 6:** Set permissions
Set /etc/zm/zm.conf to root:www-data 740 and www-data access to content
::
chmod 740 /etc/zm/zm.conf
chown root:www-data /etc/zm/zm.conf
chown -R www-data:www-data /usr/share/zoneminder/
**Step 7:** Configure Apache correctly:
::
a2enmod cgi
a2enmod rewrite
a2enconf zoneminder
You may also want to enable to following modules to improve caching performance
::
a2enmod expires
a2enmod headers
**Step 8:** Enable and start Zoneminder
::
systemctl enable zoneminder
systemctl start zoneminder
**Step 9:** Edit Timezone in PHP
::
nano /etc/php/7.2/apache2/php.ini
Search for [Date] (Ctrl + w then type Date and press Enter) and change
date.timezone for your time zone, see [this](http://php.net/manual/en/timezones.php).
**Don't forget to remove the ; from in front of date.timezone**
::
[Date]
; Defines the default timezone used by the date functions
; http://php.net/date.timezone
date.timezone = America/New_York
CTRL+o then [Enter] to save
CTRL+x to exit
**Step 10:** Reload Apache service
::
systemctl reload apache2
**Step 11:** Making sure ZoneMinder works
1. Open up a browser and go to ``http://hostname_or_ip/zm`` - should bring up ZoneMinder Console
2. (Optional API Check)Open up a tab in the same browser and go to ``http://hostname_or_ip/zm/api/host/getVersion.json``
If it is working correctly you should get version information similar to the example below:
::
{
"version": "1.29.0",
"apiversion": "1.29.0.1"
}
**Congratulations** Your installation is complete
PPA install may need some tweaking of ZMS_PATH in ZoneMinder options. `Socket_sendto or no live streaming`_
Easy Way: Ubuntu 16.04
----------------------
These instructions are for a brand new ubuntu 16.04 system which does not have ZM

View File

@ -31,17 +31,21 @@ extern "C" {
#include "libavutil/time.h"
}
VideoStore::VideoStore(const char *filename_in, const char *format_in,
AVStream *p_video_in_stream,
AVStream *p_audio_in_stream, int64_t nStartTime,
Monitor *monitor) {
VideoStore::VideoStore(
const char *filename_in,
const char *format_in,
AVStream *p_video_in_stream,
AVStream *p_audio_in_stream,
int64_t nStartTime,
Monitor *monitor
) {
video_in_stream = p_video_in_stream;
audio_in_stream = p_audio_in_stream;
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
video_in_ctx = avcodec_alloc_context3(NULL);
avcodec_parameters_to_context(video_in_ctx,
video_in_stream->codecpar);
avcodec_parameters_to_context(video_in_ctx, video_in_stream->codecpar);
video_in_ctx->time_base = video_in_stream->time_base;
// zm_dump_codecpar( video_in_stream->codecpar );
#else
video_in_ctx = video_in_stream->codec;
@ -91,18 +95,17 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
video_out_ctx = avcodec_alloc_context3(NULL);
// Copy params from instream to ctx
ret = avcodec_parameters_to_context(video_out_ctx,
video_in_stream->codecpar);
if (ret < 0) {
Error("Could not initialize ctx parameteres");
ret = avcodec_parameters_to_context(video_out_ctx, video_in_stream->codecpar);
if ( ret < 0 ) {
Error("Could not initialize video_out_ctx parameters");
return;
} else {
zm_dump_codec(video_out_ctx);
}
video_out_stream = avformat_new_stream(oc, NULL);
if (!video_out_stream) {
Error("Unable to create video out stream\n");
if ( !video_out_stream ) {
Error("Unable to create video out stream");
return;
} else {
Debug(2, "Success creating video out stream");
@ -117,7 +120,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
// Now copy them to the out stream
ret = avcodec_parameters_from_context(video_out_stream->codecpar,
video_out_ctx);
if (ret < 0) {
if ( ret < 0 ) {
Error("Could not initialize stream parameteres");
return;
} else {
@ -143,7 +146,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
} else {
Debug(3, "Success copying ctx");
}
if (!video_out_ctx->codec_tag) {
if ( !video_out_ctx->codec_tag ) {
Debug(2, "No codec_tag");
if (!oc->oformat->codec_tag ||
av_codec_get_id(oc->oformat->codec_tag,
@ -182,17 +185,17 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
}
Monitor::Orientation orientation = monitor->getOrientation();
if (orientation) {
if (orientation == Monitor::ROTATE_0) {
if ( orientation ) {
if ( orientation == Monitor::ROTATE_0 ) {
} else if (orientation == Monitor::ROTATE_90) {
dsr = av_dict_set(&video_out_stream->metadata, "rotate", "90", 0);
if (dsr < 0) Warning("%s:%d: title set failed", __FILE__, __LINE__);
} else if (orientation == Monitor::ROTATE_180) {
if ( dsr < 0 ) Warning("%s:%d: title set failed", __FILE__, __LINE__);
} else if ( orientation == Monitor::ROTATE_180 ) {
dsr = av_dict_set(&video_out_stream->metadata, "rotate", "180", 0);
if (dsr < 0) Warning("%s:%d: title set failed", __FILE__, __LINE__);
} else if (orientation == Monitor::ROTATE_270) {
if ( dsr < 0 ) Warning("%s:%d: title set failed", __FILE__, __LINE__);
} else if ( orientation == Monitor::ROTATE_270 ) {
dsr = av_dict_set(&video_out_stream->metadata, "rotate", "270", 0);
if (dsr < 0) Warning("%s:%d: title set failed", __FILE__, __LINE__);
if ( dsr < 0 ) Warning("%s:%d: title set failed", __FILE__, __LINE__);
} else {
Warning("Unsupported Orientation(%d)", orientation);
}
@ -209,13 +212,14 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
resample_ctx = NULL;
#endif
if (audio_in_stream) {
if ( audio_in_stream ) {
Debug(3, "Have audio stream");
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
audio_in_ctx = avcodec_alloc_context3(NULL);
ret = avcodec_parameters_to_context(audio_in_ctx,
audio_in_stream->codecpar);
audio_in_ctx->time_base = audio_in_stream->time_base;
#else
audio_in_ctx = audio_in_stream->codec;
#endif
@ -225,7 +229,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
avcodec_string(error_buffer, sizeof(error_buffer), audio_in_ctx, 0);
Debug(2, "Got something other than AAC (%s)", error_buffer);
if (!setup_resampler()) {
if ( !setup_resampler() ) {
return;
}
} else {
@ -541,6 +545,7 @@ bool VideoStore::setup_resampler() {
// Some formats (i.e. WAV) do not produce the proper channel layout
if ( audio_in_ctx->channel_layout == 0 ) {
Debug(2, "Setting input channel layout to mono");
// Perhaps we should not be modifying the audio_in_ctx....
audio_in_ctx->channel_layout = av_get_channel_layout("mono");
}
@ -635,10 +640,10 @@ bool VideoStore::setup_resampler() {
#if defined(HAVE_LIBSWRESAMPLE)
resample_ctx = swr_alloc_set_opts(NULL,
av_get_default_channel_layout(audio_out_ctx->channels),
audio_out_ctx->channel_layout,
audio_out_ctx->sample_fmt,
audio_out_ctx->sample_rate,
av_get_default_channel_layout(audio_in_ctx->channels),
audio_in_ctx->channel_layout,
audio_in_ctx->sample_fmt,
audio_in_ctx->sample_rate,
0, NULL);
@ -716,10 +721,11 @@ bool VideoStore::setup_resampler() {
}
// Setup the data pointers in the AVFrame
if ( avcodec_fill_audio_frame(out_frame, audio_out_ctx->channels,
audio_out_ctx->sample_fmt,
(const uint8_t *)converted_in_samples,
audioSampleBuffer_size, 0) < 0 ) {
if ( avcodec_fill_audio_frame(
out_frame, audio_out_ctx->channels,
audio_out_ctx->sample_fmt,
(const uint8_t *)converted_in_samples,
audioSampleBuffer_size, 0) < 0) {
Error("Could not allocate converted in sample pointers");
return false;
}
@ -897,10 +903,14 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
return 0;
}
Debug(2,
"Input Frame: samples(%d), format(%d), sample_rate(%d), channel "
"layout(%d)",
in_frame->nb_samples, in_frame->format,
in_frame->sample_rate, in_frame->channel_layout);
"In Frame: samples(%d), format(%d), sample_rate(%d), "
"channels(%d) channel layout(%d) pts(%" PRId64 ")",
in_frame->nb_samples,
in_frame->format,
in_frame->sample_rate,
in_frame->channels,
in_frame->channel_layout,
in_frame->pts);
#else
/**
* Decode the audio frame stored in the packet.
@ -926,12 +936,12 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
// decoded data
zm_dump_frame(in_frame, "In frame");
zm_dump_frame(out_frame, "Out frame before resample");
if (
#if defined(HAVE_LIBSWRESAMPLE)
#if 0
(ret = swr_convert(resample_ctx,
out_frame->data, frame_size,
(const uint8_t**)in_frame->data, in_frame->nb_samples
(const uint8_t**)in_frame->data,
in_frame->nb_samples
))
#else
(ret = swr_convert_frame(resample_ctx, out_frame, in_frame))
@ -940,16 +950,15 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
#else
#if defined(HAVE_LIBAVRESAMPLE)
(ret = avresample_convert(resample_ctx, NULL, 0, 0, in_frame->data,
0, in_frame->nb_samples))
0, in_frame->nb_samples))
#endif
#endif
#endif
< 0 ) {
av_frame_unref(in_frame);
if ( ret < 0 ) {
Error("Could not resample frame (error '%s')",
av_make_error_string(ret).c_str());
av_frame_unref(in_frame);
return 0;
}
av_frame_unref(in_frame);
#if defined(HAVE_LIBAVRESAMPLE)
int samples_available = avresample_available(resample_ctx);
@ -981,8 +990,8 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
// av_frame_unref( out_frame );
if ((ret = avcodec_receive_packet(audio_out_ctx, &opkt)) < 0) {
if (AVERROR(EAGAIN) == ret) {
if ( (ret = avcodec_receive_packet(audio_out_ctx, &opkt)) < 0 ) {
if ( AVERROR(EAGAIN) == ret ) {
// THe codec may need more samples than it has, perfectly valid
Debug(3, "Could not recieve packet (error '%s')",
av_make_error_string(ret).c_str());

View File

@ -91,7 +91,7 @@ echo output_link_if_exists( array(
<!--Chosen can't be cache-busted because it loads sprites by relative path-->
<link rel="stylesheet" href="skins/classic/js/chosen/chosen.min.css" type="text/css"/>
<?php
if ($basename == 'watch') {
if ( $basename == 'watch' ) {
echo output_link_if_exists( array(
'/css/base/views/control.css',
'/css/'.$css.'/views/control.css'
@ -100,11 +100,9 @@ echo output_link_if_exists( array(
if ( $viewCssPhpFile ) {
?>
<style type="text/css">
/*<![CDATA[*/
<?php
require_once( $viewCssPhpFile );
require_once($viewCssPhpFile);
?>
/*]]>*/
</style>
<?php
}
@ -219,7 +217,7 @@ function getBodyTopHTML() {
} // end function getBodyTopHTML
function getNavBarHTML($reload = null) {
# Provide a facility to turn off the headers if you put headers=0 into the url
# Provide a facility to turn off the headers if you put navbar=0 into the url
if ( isset($_REQUEST['navbar']) and $_REQUEST['navbar']=='0' )
return '';
@ -258,10 +256,12 @@ function getNavBarHTML($reload = null) {
</div>
<div class="collapse navbar-collapse" id="main-header-nav">
<?php if ( canView('Monitors') ) { ?>
<ul class="nav navbar-nav">
<?php if ( $user and $user['Username'] ) { ?>
<?php if ( canView('Monitors') ) { ?>
<li><a href="?view=console"><?php echo translate('Console') ?></a></li>
<?php if ( canView( 'System' ) ) { ?>
<?php } // end if canView('Monitors') ?>
<?php if ( canView('System') ) { ?>
<li><a href="?view=options"><?php echo translate('Options') ?></a></li>
<li>
<?php
@ -272,17 +272,17 @@ function getNavBarHTML($reload = null) {
}
echo makePopupLink( '?view=log', 'zmLog', 'log', '<span class="'.logState().'">'.translate('Log').'</span>' );
}
} // end if canview(System)
?></li>
<?php
if ( ZM_OPT_X10 && canView( 'Devices' ) ) { ?>
} // end if canview(System)
if ( ZM_OPT_X10 && canView('Devices') ) { ?>
<li><a href="?view=devices">Devices</a></li>
<?php } ?>
<li><a href="?view=groups"<?php echo $view=='groups'?' class="selected"':''?>><?php echo translate('Groups') ?></a></li>
<li><a href="?view=filter<?php echo $filterQuery.$sortQuery.$limitQuery ?>"<?php echo $view=='filter'?' class="selected"':''?>><?php echo translate('Filters') ?></a></li>
<?php
if ( canView( 'Stream' ) ) {
if ( canView('Stream') ) {
?>
<li><a href="?view=cycle"<?php echo $view=='cycle'?' class="selected"':''?>><?php echo translate('Cycle') ?></a></li>
<li><a href="?view=montage"<?php echo $view=='montage'?' class="selected"':''?>><?php echo translate('Montage') ?></a></li>
@ -295,44 +295,44 @@ if (isset($_REQUEST['filter']['Query']['terms']['attr'])) {
$terms = $_REQUEST['filter']['Query']['terms'];
$count = 0;
foreach ($terms as $term) {
if ($term['attr'] == "StartDateTime") {
if ( $term['attr'] == 'StartDateTime' ) {
$count += 1;
if ($term['op'] == '>=') $minTime = $term['val'];
if ($term['op'] == '<=') $maxTime = $term['val'];
}
}
if ($count == 2) {
if ( $count == 2 ) {
$montageReviewQuery = '&minTime='.$minTime.'&maxTime='.$maxTime;
}
}
if ( canView('Events') ) {
?>
<li><a href="?view=montagereview<?php echo isset($montageReviewQuery)?'&fit=1'.$montageReviewQuery.'&live=0':'' ?>"<?php echo $view=='montagereview'?' class="selected"':''?>><?php echo translate('MontageReview')?></a></li>
<li><a href="?view=montagereview<?php echo isset($montageReviewQuery)?'&fit=1'.$montageReviewQuery.'&live=0':'' ?>"<?php echo $view=='montagereview'?' class="selected"':''?>><?php echo translate('MontageReview')?></a></li>
<?php
}
?>
<li><a href="?view=report_event_audit"<?php echo $view=='report_event_audit'?' class="selected"':''?>><?php echo translate('ReportEventAudit') ?></a></li>
<li><a href="#"><span id="flip" class="glyphicon glyphicon-menu-<?php echo ( isset($_COOKIE['zmHeaderFlip']) and $_COOKIE['zmHeaderFlip'] == 'down') ? 'down' : 'up' ?> pull-right"></span></a></li>
</ul>
<?php } // end if canView('Monitors') ?>
<div class="navbar-right">
<?php if ( ZM_OPT_USE_AUTH and $user ) { ?>
<p class="navbar-text"><i class="material-icons">account_circle</i> <?php echo makePopupLink( '?view=logout', 'zmLogout', 'logout', $user['Username'], (ZM_AUTH_TYPE == "builtin") ) ?> </p>
<?php } ?>
<?php if ( canEdit( 'System' ) ) { ?>
<?php if ( canEdit('System') ) { ?>
<button type="button" class="btn btn-default navbar-btn" data-toggle="modal" data-target="#modalState"><?php echo $status ?></button>
<?php } else if ( canView( 'System' ) ) { ?>
<p class="navbar-text"> <?php echo $status ?> </p>
<?php } else if ( canView('System') ) { ?>
<p class="navbar-text"> <?php echo $status ?></p>
<?php } ?>
</div>
<?php } # end if !$user or $user['Id'] meaning logged in ?>
</div><!-- End .navbar-collapse -->
</div> <!-- End .container-fluid -->
<div id="panel"<?php echo ( isset($_COOKIE['zmHeaderFlip']) and $_COOKIE['zmHeaderFlip'] == 'down' ) ? 'style="display:none;"' : '' ?>>
<?php
}//end reload null. Runs on full page load
} //end reload null. Runs on full page load
if ( (!ZM_OPT_USE_AUTH) or $user ) {
if ($reload == 'reload') ob_start();
@ -342,7 +342,7 @@ if ($reload == 'reload') ob_start();
<?php echo makePopupLink( '?view=bandwidth', 'zmBandwidth', 'bandwidth', "<i class='material-icons md-18'>network_check</i>&nbsp;".$bandwidth_options[$_COOKIE['zmBandwidth']] . ' ', ($user && $user['MaxBandwidth'] != 'low' ) ) ?>
</div>
<div id="Version" class="pull-right">
<?php echo makePopupLink( '?view=version', 'zmVersion', 'version', '<span class="version '.$versionClass.'">v'.ZM_VERSION.'</span>', canEdit( 'System' ) ) ?>
<?php echo makePopupLink( '?view=version', 'zmVersion', 'version', '<span class="version '.$versionClass.'">v'.ZM_VERSION.'</span>', canEdit('System') ) ?>
</div>
<ul class="list-inline">
<li class="Load"><i class="material-icons md-18">trending_up</i>&nbsp;<?php echo translate('Load') ?>: <?php echo getLoad() ?></li>
@ -366,9 +366,9 @@ if ($reload == 'reload') ob_start();
$func = function($S){
$class = '';
if ( $S->disk_usage_percent() > 98 ) {
$class = "error";
$class = 'error';
} else if ( $S->disk_usage_percent() > 90 ) {
$class = "warning";
$class = 'warning';
}
$title = human_filesize($S->disk_used_space()) . ' of ' . human_filesize($S->disk_total_space()).
( ( $S->disk_used_space() != $S->event_disk_space() ) ? ' ' .human_filesize($S->event_disk_space()) . ' used by events' : '' );

View File

@ -18,7 +18,7 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
if ( !canView( 'Control' ) ) {
if ( !canView('Control') ) {
$view = 'error';
return;
}
@ -26,16 +26,16 @@ if ( !canView( 'Control' ) ) {
$params = array();
$groupSql = '';
if ( !empty($_REQUEST['group']) ) {
$groupSql = " AND gm.GroupId = :groupid";
$params[":groupid"] = $_REQUEST['group'];
$groupSql = ' AND gm.GroupId = :groupid';
$params[':groupid'] = $_REQUEST['group'];
}
$mid = !empty($_REQUEST['mid']) ? validInt($_REQUEST['mid']) : 0;
$sql = "SELECT m.* FROM Monitors m INNER JOIN Groups_Monitors AS gm ON m.Id = gm.MonitorId WHERE m.Function != 'None' AND m.Controllable = 1$groupSql ORDER BY Sequence";
$mids = array();
foreach( dbFetchAll( $sql, false, $params ) as $row ) {
if ( !visibleMonitor( $row['Id'] ) ) {
foreach ( dbFetchAll($sql, false, $params) as $row ) {
if ( !visibleMonitor($row['Id']) ) {
continue;
}
if ( empty($mid) )
@ -43,14 +43,14 @@ foreach( dbFetchAll( $sql, false, $params ) as $row ) {
$mids[$row['Id']] = $row['Name'];
}
foreach ( getSkinIncludes( 'includes/control_functions.php' ) as $includeFile )
foreach ( getSkinIncludes('includes/control_functions.php') as $includeFile )
require_once $includeFile;
$monitor = new Monitor( $mid );
$monitor = new Monitor($mid);
$focusWindow = true;
xhtmlHeaders(__FILE__, translate('Control') );
xhtmlHeaders(__FILE__, translate('Control'));
?>
<body>
<div id="page">
@ -62,13 +62,13 @@ xhtmlHeaders(__FILE__, translate('Control') );
<div id="headerControl">
<form name="contentForm" id="contentForm" method="get" action="?">
<input type="hidden" name="view" value="<?php echo $view ?>"/>
<?php echo buildSelect( "mid", $mids, "this.form.submit();" ); ?>
<?php echo buildSelect('mid', $mids, 'this.form.submit();'); ?>
</form>
</div>
</div>
<div id="content">
<div id="ptzControls" class="ptzControls">
<?php echo ptzControls( $monitor ) ?>
<?php echo ptzControls($monitor) ?>
</div>
</div>
</div>

View File

@ -194,7 +194,23 @@ while ( $event_row = dbFetchNext($results) ) {
<td class="colName"><a href="?view=event&amp;eid=<?php echo $event->Id().$filterQuery.$sortQuery.'&amp;page=1">'.validHtmlStr($event->Name()).($event->Archived()?'*':'') ?></a></td>
<td class="colMonitorName"><?php echo makePopupLink( '?view=monitor&amp;mid='.$event->MonitorId(), 'zmMonitor'.$event->Monitorid(), 'monitor', $event->MonitorName(), canEdit( 'Monitors' ) ) ?></td>
<td class="colCause"><?php echo makePopupLink( '?view=eventdetail&amp;eid='.$event->Id(), 'zmEventDetail', 'eventdetail', validHtmlStr($event->Cause()), canEdit( 'Events' ), 'title="'.htmlspecialchars($event->Notes()).'"' ) ?>
<?php if ($event->Notes() && ($event->Notes() != 'Forced Web: ')) echo "<br/><div class=\"small text-nowrap text-muted\">".$event->Notes()."</div>" ?></td>
<?php
# display notes as small text
if ($event->Notes()) {
# if notes include detection objects, then link it to objdetect.jpg
if (strpos($event->Notes(),"detected:")!== false){
# make a link
echo makePopupLink( '?view=image&amp;eid='.$event->Id().'&amp;fid=objdetect', 'zmImage',
array('image', reScale($event->Width(), $scale), reScale($event->Height(), $scale)),
"<div class=\"small text-nowrap text-muted\"><u>".$event->Notes()."</u></div>");
}
elseif ($event->Notes() != 'Forced Web: ') {
echo "<br/><div class=\"small text-nowrap text-muted\">".$event->Notes()."</div>";
}
}
?>
</td>
<td class="colTime"><?php echo strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->StartTime())) .
( $event->EndTime() ? ' until ' . strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->EndTime()) ) : '' ) ?>
</td>

View File

@ -78,23 +78,21 @@ if ( empty($_REQUEST['path']) ) {
}
if ( $_REQUEST['fid'] == 'objdetect' ) {
$Event = new Event($_REQUEST['eid']);
$path = $Event->Path().'/objdetect.jpg';
unset($Event); # we don't want event object related processing later for this case
if ( !file_exists($path)) {
$path = $Event->Path().'/objdetect.jpg';
if ( !file_exists($path) ) {
header('HTTP/1.0 404 Not Found');
Fatal("File ".$path." does not exist. Please make sure store_frame_in_zm is enabled in the object detection config");
Fatal("File $path does not exist. Please make sure store_frame_in_zm is enabled in the object detection config");
}
}
else if ( $_REQUEST['fid'] == 'alarm' ) {
$Frame = new Frame();
$Frame->Id('objdetect');
} else if ( $_REQUEST['fid'] == 'alarm' ) {
# look for first alarmed frame
$Frame = Frame::find_one(array('EventId'=>$_REQUEST['eid'], 'Type'=>'Alarm'),
array('order'=>'FrameId ASC'));
if ( !$Frame ) { # no alarms, get first one I find
$Frame = Frame::find_one(array('EventId'=>$_REQUEST['eid']));
if ( !$Frame ) {
Warning("No frame found for event " + $_REQUEST['eid']);
Warning('No frame found for event '.$_REQUEST['eid']);
$Frame = new Frame();
$Frame->Delta(1);
$Frame->FrameId(1);
@ -107,8 +105,7 @@ if ( empty($_REQUEST['path']) ) {
} else {
$path = $Event->Path().'/alarm.jpg';
}
}
else if ( $_REQUEST['fid'] == 'snapshot' ) {
} else if ( $_REQUEST['fid'] == 'snapshot' ) {
$Frame = Frame::find_one(array('EventId'=>$_REQUEST['eid'], 'Score'=>$Event->MaxScore()));
if ( !$Frame )
$Frame = Frame::find_one(array('EventId'=>$_REQUEST['eid']));