Merge branch 'master' into zma_to_thread
This commit is contained in:
commit
0702b64cc4
|
@ -450,6 +450,7 @@ CREATE TABLE `Monitors` (
|
|||
`Type` enum('Local','Remote','File','Ffmpeg','Libvlc','cURL','WebSite','NVSocket','VNC') NOT NULL default 'Local',
|
||||
`Function` enum('None','Monitor','Modect','Record','Mocord','Nodect') NOT NULL default 'Monitor',
|
||||
`Enabled` tinyint(3) unsigned NOT NULL default '1',
|
||||
`DecodingEnabled` tinyint(3) unsigned NOT NULL default '1',
|
||||
`LinkedMonitors` varchar(255),
|
||||
`Triggers` set('X10') NOT NULL default '',
|
||||
`ONVIF_URL` VARCHAR(255) NOT NULL DEFAULT '',
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
|
||||
AND table_name = 'Monitors'
|
||||
AND column_name = 'DecodingEnabled'
|
||||
) > 0,
|
||||
"SELECT 'Column DecodingEnabled already exists in Monitors'",
|
||||
"ALTER TABLE Monitors ADD `DecodingEnabled` tinyint(3) unsigned NOT NULL default '1' AFTER `Enabled`"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
|
@ -28,7 +28,7 @@
|
|||
%global _hardened_build 1
|
||||
|
||||
Name: zoneminder
|
||||
Version: 1.35.15
|
||||
Version: 1.35.16
|
||||
Release: 1%{?dist}
|
||||
Summary: A camera monitoring and analysis tool
|
||||
Group: System Environment/Daemons
|
||||
|
|
|
@ -32,6 +32,7 @@ require ZoneMinder::Base;
|
|||
require ZoneMinder::Object;
|
||||
require ZoneMinder::Storage;
|
||||
require ZoneMinder::Frame;
|
||||
require ZoneMinder::Monitor;
|
||||
require Date::Manip;
|
||||
require File::Find;
|
||||
require File::Path;
|
||||
|
@ -915,6 +916,15 @@ sub canEdit {
|
|||
return 0;
|
||||
} # end sub canEdit
|
||||
|
||||
sub Monitor {
|
||||
my $self = shift;
|
||||
$$self{Monitor} = shift if @_;
|
||||
if ( !$$self{Monitor} ) {
|
||||
$$self{Monitor} = new ZoneMinder::Monitor($$self{MonitorId});
|
||||
}
|
||||
return $$self{Monitor};
|
||||
}
|
||||
|
||||
1;
|
||||
__END__
|
||||
|
||||
|
|
|
@ -91,6 +91,9 @@ while( 1 ) {
|
|||
}
|
||||
} # end if ZM_LOG_DATABASE_LIMIT
|
||||
|
||||
# Delete any sessions that are more ethan a week old. Limiting to 100 because mysql sucks
|
||||
zmDbDo('DELETE FROM Sessions WHERE access < ? LIMIT 100', time - (60*60*24*7));
|
||||
|
||||
sleep($Config{ZM_STATS_UPDATE_INTERVAL});
|
||||
} # end while (1)
|
||||
|
||||
|
|
|
@ -71,8 +71,8 @@
|
|||
// This is the official SQL (and ordering of the fields) to load a Monitor.
|
||||
// It will be used whereever a Monitor dbrow is needed. WHERE conditions can be appended
|
||||
std::string load_monitor_sql =
|
||||
"SELECT `Id`, `Name`, `ServerId`, `StorageId`, `Type`, `Function`+0, `Enabled`, `LinkedMonitors`, "
|
||||
"`AnalysisFPSLimit`, `AnalysisUpdateDelay`, `MaxFPS`, `AlarmMaxFPS`,"
|
||||
"SELECT `Id`, `Name`, `ServerId`, `StorageId`, `Type`, `Function`+0, `Enabled`, `DecodingEnabled`, "
|
||||
"`LinkedMonitors`, `AnalysisFPSLimit`, `AnalysisUpdateDelay`, `MaxFPS`, `AlarmMaxFPS`,"
|
||||
"`Device`, `Channel`, `Format`, `V4LMultiBuffer`, `V4LCapturesPerFrame`, " // V4L Settings
|
||||
"`Protocol`, `Method`, `Options`, `User`, `Pass`, `Host`, `Port`, `Path`, `Width`, `Height`, `Colours`, `Palette`, `Orientation`+0, `Deinterlacing`, "
|
||||
"`DecoderHWAccelName`, `DecoderHWAccelDevice`, `RTSPDescribe`, "
|
||||
|
@ -596,6 +596,18 @@ void Monitor::Load(MYSQL_ROW dbrow, bool load_zones=true, Purpose p = QUERY) {
|
|||
if ( mkdir(monitor_dir.c_str(), 0755) && ( errno != EEXIST ) ) {
|
||||
Error("Can't mkdir %s: %s", monitor_dir.c_str(), strerror(errno));
|
||||
}
|
||||
|
||||
decoding_enabled = !(
|
||||
( function == RECORD or function == NODECT )
|
||||
and
|
||||
( savejpegs == 0 )
|
||||
and
|
||||
( videowriter == H264PASSTHROUGH )
|
||||
and
|
||||
!decoding_enabled
|
||||
);
|
||||
Debug(1, "Decoding enabled: %d", decoding_enabled);
|
||||
|
||||
} else if ( purpose == ANALYSIS ) {
|
||||
while (
|
||||
( !(this->connect() and shared_data->valid) )
|
||||
|
|
|
@ -243,6 +243,7 @@ protected:
|
|||
CameraType type;
|
||||
Function function; // What the monitor is doing
|
||||
bool enabled; // Whether the monitor is enabled or asleep
|
||||
bool decoding_enabled; // Whether the monitor will decode h264/h265 packets
|
||||
|
||||
std::string protocol;
|
||||
std::string method;
|
||||
|
@ -424,6 +425,9 @@ public:
|
|||
return false;
|
||||
return enabled;
|
||||
}
|
||||
inline bool DecodingEnabled() const {
|
||||
return decoding_enabled;
|
||||
}
|
||||
inline const char *EventPrefix() const { return event_prefix; }
|
||||
inline bool Ready() const {
|
||||
if ( function <= MONITOR ) {
|
||||
|
|
|
@ -6,7 +6,7 @@ $data = array();
|
|||
// INITIALIZE AND CHECK SANITY
|
||||
//
|
||||
|
||||
if ( !canEdit('Events') ) $message = 'Insufficient permissions for user '.$user['Username'];
|
||||
if ( !canView('Events') ) $message = 'Insufficient permissions for user '.$user['Username'];
|
||||
|
||||
if ( empty($_REQUEST['task']) ) {
|
||||
$message = 'Must specify a task';
|
||||
|
@ -74,10 +74,22 @@ if ( isset($_REQUEST['limit']) ) {
|
|||
|
||||
switch ( $task ) {
|
||||
case 'archive' :
|
||||
foreach ( $eids as $eid ) archiveRequest($task, $eid);
|
||||
break;
|
||||
case 'unarchive' :
|
||||
# The idea is that anyone can archive, but only people with Event Edit permission can unarchive..
|
||||
if ( !canEdit('Events') ) {
|
||||
ajaxError('Insufficient permissions for user '.$user['Username']);
|
||||
return;
|
||||
}
|
||||
foreach ( $eids as $eid ) archiveRequest($task, $eid);
|
||||
break;
|
||||
case 'delete' :
|
||||
if ( !canEdit('Events') ) {
|
||||
ajaxError('Insufficient permissions for user '.$user['Username']);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( $eids as $eid ) $data[] = deleteRequest($eid);
|
||||
break;
|
||||
case 'query' :
|
||||
|
@ -217,12 +229,12 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim
|
|||
$event = new ZM\Event($row);
|
||||
|
||||
$scale = intval(5*100*ZM_WEB_LIST_THUMB_WIDTH / $event->Width());
|
||||
$imgSrc = $event->getThumbnailSrc(array(),'&');
|
||||
$imgSrc = $event->getThumbnailSrc(array(), '&');
|
||||
$streamSrc = $event->getStreamSrc(array(
|
||||
'mode'=>'jpeg', 'scale'=>$scale, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'replay'=>'single', 'rate'=>'400'), '&');
|
||||
|
||||
// Modify the row data as needed
|
||||
$row['imgHtml'] = '<img id="thumbnail' .$event->Id(). '" src="' .$imgSrc. '" alt="' .validHtmlStr('Event ' .$event->Id()). '" style="width:' .validInt($event->ThumbnailWidth()). 'px;height:' .validInt($event->ThumbnailHeight()).'px;" stream_src="' .$streamSrc. '" still_src="' .$imgSrc. '"/>';
|
||||
$row['imgHtml'] = '<img id="thumbnail' .$event->Id(). '" src="' .$imgSrc. '" alt="Event '.$event->Id().'" width="' .validInt($event->ThumbnailWidth()). '" height="' .validInt($event->ThumbnailHeight()).'" stream_src="' .$streamSrc. '" still_src="' .$imgSrc. '"/>';
|
||||
$row['Name'] = validHtmlStr($row['Name']);
|
||||
$row['Archived'] = $row['Archived'] ? translate('Yes') : translate('No');
|
||||
$row['Emailed'] = $row['Emailed'] ? translate('Yes') : translate('No');
|
||||
|
|
|
@ -161,15 +161,30 @@ function queryRequest($eid, $search, $advsearch, $sort, $offset, $order, $limit)
|
|||
$returned_rows = array();
|
||||
foreach ( array_slice($filtered_rows, $offset, $limit) as $row ) {
|
||||
if ( ZM_WEB_LIST_THUMBS ) {
|
||||
|
||||
# Build the path to the potential analysis image
|
||||
$analImage = sprintf('%0'.ZM_EVENT_IMAGE_DIGITS.'d-analyse.jpg', $row['FrameId']);
|
||||
$analPath = $Event->Path().'/'.$analImage;
|
||||
$alarmFrame = $row['Type'] == 'Alarm';
|
||||
$hasAnalImage = $alarmFrame && file_exists($analPath) && filesize($analPath);
|
||||
|
||||
# Our base img source component, which we will add on to
|
||||
$base_img_src = '?view=image&fid=' .$row['Id'];
|
||||
|
||||
# if an analysis images exists, use it as the thumbnail
|
||||
if ( $hasAnalImage ) $base_img_src .= '&show=analyse';
|
||||
|
||||
# Build the subcomponents needed for the image source
|
||||
$ratio_factor = $Monitor->ViewHeight() / $Monitor->ViewWidth();
|
||||
$thmb_width = ZM_WEB_LIST_THUMB_WIDTH ? 'width='.ZM_WEB_LIST_THUMB_WIDTH : '';
|
||||
$thmb_height = 'height="'.( ZM_WEB_LIST_THUMB_HEIGHT ? ZM_WEB_LIST_THUMB_HEIGHT : ZM_WEB_LIST_THUMB_WIDTH*$ratio_factor ) .'"';
|
||||
$thmb_fn = 'filename=' .$Event->MonitorId(). '_' .$row['EventId']. '_' .$row['FrameId']. '.jpg';
|
||||
|
||||
# Assemble the scaled and unscaled image source image source components
|
||||
$img_src = join('&', array_filter(array($base_img_src, $thmb_width, $thmb_height, $thmb_fn)));
|
||||
$full_img_src = join('&', array_filter(array($base_img_src, $thmb_fn)));
|
||||
$frame_src = '?view=frame&eid=' .$row['EventId']. '&fid=' .$row['FrameId'];
|
||||
|
||||
# finally, we assemble the the entire thumbnail img src structure, whew
|
||||
$row['Thumbnail'] = '<img src="' .$img_src. '" '.$thmb_width. ' ' .$thmb_height. 'img_src="' .$img_src. '" full_img_src="' .$full_img_src. '">';
|
||||
}
|
||||
$returned_rows[] = $row;
|
||||
|
|
|
@ -37,11 +37,39 @@ if ( !canEdit('Monitors') ) return;
|
|||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>
|
||||
<div class="form-group" id="FunctionFunction">
|
||||
<label for="newFunction"><?php echo translate('Function') ?></label>
|
||||
<?php echo htmlSelect('newFunction', ZM\getMonitorFunctionTypes(), null, array('id'=>'newFunction')); ?>
|
||||
<label for="newEnabled"><?php echo translate('Enabled') ?></label>
|
||||
<div id="function_help">
|
||||
<?php
|
||||
foreach ( ZM\getMonitorFunctionTypes() as $fn => $translated ) {
|
||||
if ( isset($OLANG['FUNCTION_'.strtoupper($fn)]) ) {
|
||||
echo '<div class="form-text" id="'.$fn.'Help">'.$OLANG['FUNCTION_'.strtoupper($fn)]['Help'].'</div>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="FunctionAnalysisEnabled">
|
||||
<label for="newEnabled"><?php echo translate('Analysis Enabled') ?></label>
|
||||
<input type="checkbox" name="newEnabled" id="newEnabled" value="1"/>
|
||||
</p>
|
||||
<?php
|
||||
if ( isset($OLANG['FUNCTION_ANALYSIS_ENABLED']) ) {
|
||||
echo '<div class="form-text">'.$OLANG['FUNCTION_ANALYSIS_ENABLED']['Help'].'</div>';
|
||||
}
|
||||
?>
|
||||
|
||||
</div>
|
||||
<div class="form-group" id="FunctionDecodingEnabled">
|
||||
<label for="newDecodingEnabled"><?php echo translate('Decoding Enabled') ?></label>
|
||||
<input type="checkbox" name="newDecodingEnabled" id="newDecodingEnabled" value="1"/>
|
||||
<?php
|
||||
if ( isset($OLANG['FUNCTION_DECODING_ENABLED']) ) {
|
||||
echo '<div class="form-text">'.$OLANG['FUNCTION_DECODING_ENABLED']['Help'].'</div>';
|
||||
}
|
||||
?>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="funcSaveBtn btn btn-primary"><?php echo translate('Save') ?></button>
|
||||
|
|
|
@ -6,6 +6,7 @@ if ( empty($_REQUEST['fid']) ) ajaxError('Frame Id Not Provided');
|
|||
$eid = $_REQUEST['eid'];
|
||||
$fid = $_REQUEST['fid'];
|
||||
$row = ( isset($_REQUEST['row']) ) ? $_REQUEST['row'] : '';
|
||||
$raw = isset($_REQUEST['raw']);
|
||||
$data = array();
|
||||
|
||||
// Not sure if this is required
|
||||
|
@ -16,8 +17,28 @@ if ( ZM_OPT_USE_AUTH && (ZM_AUTH_RELAY == 'hashed') ) {
|
|||
}
|
||||
}
|
||||
|
||||
$data['html'] = getStatsTableHTML($eid, $fid, $row);
|
||||
$data['id'] = '#contentStatsTable' .$row;
|
||||
if ( $raw ) {
|
||||
$sql = 'SELECT S.*,E.*,Z.Name AS ZoneName,Z.Units,Z.Area,M.Name AS MonitorName FROM Stats AS S LEFT JOIN Events AS E ON S.EventId = E.Id LEFT JOIN Zones AS Z ON S.ZoneId = Z.Id LEFT JOIN Monitors AS M ON E.MonitorId = M.Id WHERE S.EventId = ? AND S.FrameId = ? ORDER BY S.ZoneId';
|
||||
$stat = dbFetchOne( $sql, NULL, array( $eid, $fid ) );
|
||||
if ( $stat ) {
|
||||
$stat['ZoneName'] = validHtmlStr($stat['ZoneName']);
|
||||
$stat['PixelDiff'] = validHtmlStr($stat['PixelDiff']);
|
||||
$stat['AlarmPixels'] = sprintf( "%d (%d%%)", $stat['AlarmPixels'], (100*$stat['AlarmPixels']/$stat['Area']) );
|
||||
$stat['FilterPixels'] = sprintf( "%d (%d%%)", $stat['FilterPixels'], (100*$stat['FilterPixels']/$stat['Area']) );
|
||||
$stat['BlobPixels'] = sprintf( "%d (%d%%)", $stat['BlobPixels'], (100*$stat['BlobPixels']/$stat['Area']) );
|
||||
$stat['Blobs'] = validHtmlStr($stat['Blobs']);
|
||||
if ( $stat['Blobs'] > 1 ) {
|
||||
$stat['BlobSizes'] = sprintf( "%d-%d (%d%%-%d%%)", $stat['MinBlobSize'], $stat['MaxBlobSize'], (100*$stat['MinBlobSize']/$stat['Area']), (100*$stat['MaxBlobSize']/$stat['Area']) );
|
||||
} else {
|
||||
$stat['BlobSizes'] = sprintf( "%d (%d%%)", $stat['MinBlobSize'], 100*$stat['MinBlobSize']/$stat['Area'] );
|
||||
}
|
||||
$stat['AlarmLimits'] = validHtmlStr($stat['MinX'].",".$stat['MinY']."-".$stat['MaxX'].",".$stat['MaxY']);
|
||||
}
|
||||
$data['raw'] = $stat;
|
||||
} else {
|
||||
$data['html'] = getStatsTableHTML($eid, $fid, $row);
|
||||
$data['id'] = '#contentStatsTable' .$row;
|
||||
}
|
||||
|
||||
ajaxResponse($data);
|
||||
return;
|
||||
|
|
|
@ -35,6 +35,7 @@ class Monitor extends ZM_Object {
|
|||
'Type' => 'Ffmpeg',
|
||||
'Function' => 'Mocord',
|
||||
'Enabled' => array('type'=>'boolean','default'=>1),
|
||||
'DecodingEnabled' => array('type'=>'boolean','default'=>1),
|
||||
'LinkedMonitors' => array('type'=>'set', 'default'=>null),
|
||||
'Triggers' => array('type'=>'set','default'=>''),
|
||||
'ONVIF_URL' => '',
|
||||
|
|
|
@ -250,8 +250,8 @@ class ZM_Object {
|
|||
} else if ( property_exists($this, $field) ) {
|
||||
$type = (array_key_exists($field, $this->defaults) && is_array($this->defaults[$field])) ? $this->defaults[$field]['type'] : 'scalar';
|
||||
if ( $type == 'set' ) {
|
||||
$old_value = is_array($this->$field) ? $this->$field : explode(',', $this->$field);
|
||||
$new_value = is_array($value) ? $value : explode(',', $value);
|
||||
$old_value = is_array($this->$field) ? $this->$field : ($this->$field ? explode(',', $this->$field) : array());
|
||||
$new_value = is_array($value) ? $value : ($value ? explode(',', $value) : array());
|
||||
|
||||
$diff = array_recursive_diff($old_value, $new_value);
|
||||
if ( count($diff) ) {
|
||||
|
|
|
@ -55,6 +55,7 @@ if ( $action == 'save' ) {
|
|||
'Controllable' => 0,
|
||||
'TrackMotion' => 0,
|
||||
'Enabled' => 0,
|
||||
'DecodingEnabled' => 0,
|
||||
'Exif' => 0,
|
||||
'RTSPDescribe' => 0,
|
||||
'V4LMultiBuffer' => '',
|
||||
|
@ -82,7 +83,7 @@ if ( $action == 'save' ) {
|
|||
}
|
||||
}
|
||||
|
||||
$changes = $monitor->changes($_REQUEST['newMonitor'], $types);
|
||||
$changes = $monitor->changes($_REQUEST['newMonitor']);
|
||||
$restart = false;
|
||||
|
||||
if ( count($changes) ) {
|
||||
|
|
|
@ -105,7 +105,7 @@ function validateUser($username='', $password='') {
|
|||
|
||||
function userLogout() {
|
||||
global $user;
|
||||
ZM\Info('User "'.$user['Username'].'" logged out');
|
||||
ZM\Info('User "'.($user?$user['Username']:'no one').'" logged out');
|
||||
$user = null;// unset only clears the local variable
|
||||
zm_session_clear();
|
||||
}
|
||||
|
@ -187,7 +187,26 @@ function getAuthUser($auth) {
|
|||
} // end if $auth == $authHash
|
||||
} // end foreach hour
|
||||
} // end foreach user
|
||||
|
||||
if ( isset($_SESSION['username']) ) {
|
||||
# In a multi-server case, we might be logged in as another user and so the auth hash didn't work
|
||||
$sql = 'SELECT * FROM Users WHERE Enabled = 1 AND Username != ?';
|
||||
|
||||
foreach ( dbFetchAll($sql, NULL, $values) as $user ) {
|
||||
$now = time();
|
||||
for ( $i = 0; $i < ZM_AUTH_HASH_TTL; $i++, $now -= 3600 ) { // Try for last TTL hours
|
||||
$time = localtime($now);
|
||||
$authKey = ZM_AUTH_HASH_SECRET.$user['Username'].$user['Password'].$remoteAddr.$time[2].$time[3].$time[4].$time[5];
|
||||
$authHash = md5($authKey);
|
||||
|
||||
if ( $auth == $authHash ) {
|
||||
return $user;
|
||||
} // end if $auth == $authHash
|
||||
} // end foreach hour
|
||||
} // end foreach user
|
||||
} // end if
|
||||
} // end if using auth hash
|
||||
|
||||
ZM\Error("Unable to authenticate user from auth hash '$auth'");
|
||||
return null;
|
||||
} // end getAuthUser($auth)
|
||||
|
|
|
@ -1200,8 +1200,8 @@ function sortHeader($field, $querySep='&') {
|
|||
'?view='.$view,
|
||||
'page=1'.(isset($_REQUEST['filter'])?$_REQUEST['filter']['query']:''),
|
||||
'sort_field='.$field,
|
||||
'sort_asc='.($_REQUEST['sort_field'] == $field ? !$_REQUEST['sort_asc'] : 0),
|
||||
'limit='.validInt($_REQUEST['limit']),
|
||||
'sort_asc='.( ( isset($_REQUEST['sort_field']) and ( $_REQUEST['sort_field'] == $field ) ) ? !$_REQUEST['sort_asc'] : 0),
|
||||
'limit='.(isset($_REQUEST['limit']) ? validInt($_REQUEST['limit']) : ''),
|
||||
(isset($_REQUEST['eid']) ? 'eid='.$_REQUEST['eid'] : '' ),
|
||||
));
|
||||
}
|
||||
|
@ -2149,14 +2149,15 @@ function folder_size($dir) {
|
|||
} // end function folder_size
|
||||
|
||||
function human_filesize($size, $precision = 2) {
|
||||
$units = array('B','kB','MB','GB','TB','PB','EB','ZB','YB');
|
||||
$units = array('B ','kB','MB','GB','TB','PB','EB','ZB','YB');
|
||||
$step = 1024;
|
||||
$i = 0;
|
||||
while (($size / $step) > 0.9) {
|
||||
$size = $size / $step;
|
||||
$i++;
|
||||
}
|
||||
return round($size, $precision).$units[$i];
|
||||
# The idea is that we can right align this and have the digits columns line up nicely.
|
||||
return sprintf('%.'.$precision.'f', round($size, $precision)).$units[$i];
|
||||
}
|
||||
|
||||
function csrf_startup() {
|
||||
|
|
|
@ -1073,6 +1073,70 @@ $OLANG = array(
|
|||
certainly not what you want! To unlink monitors you can ctrl-click.
|
||||
'
|
||||
),
|
||||
'FUNCTION_NONE' => array(
|
||||
'Help' => '
|
||||
In None mode no processes are started. No capturing will occur.
|
||||
'
|
||||
),
|
||||
'FUNCTION_MONITOR' => array(
|
||||
'Help' => '
|
||||
In Monitor mode the capture process (zmc) will connect to the camera and stream data.
|
||||
It will be decoded if necessary and live viewing will be possible.
|
||||
No motion detection will be performed. This monitor type cannot save video.
|
||||
'
|
||||
),
|
||||
'FUNCTION_MODECT' => array(
|
||||
'Help' => '
|
||||
In Modect mode the capture process (zmc) will connect to the camera and stream data.
|
||||
It will be decoded if necessary and live viewing will be possible.
|
||||
In addition a process (zma) will analyse the video for motion.
|
||||
When motion is detected, events will be created and video will be stored.
|
||||
Motion data will be stored in the database for each event.
|
||||
Events may also be triggered externally (zmtrigger) or by linked monitors.
|
||||
'
|
||||
),
|
||||
'FUNCTION_RECORD' => array(
|
||||
'Help' => '
|
||||
In Record mode the capture process (zmc) will connect to the camera and stream data.
|
||||
It will be decoded if necessary and live viewing will be possible.
|
||||
In addition a process (zma) will run but will not perform motion detection.
|
||||
Events will be created at fixed intervals and video will be stored.
|
||||
'
|
||||
),
|
||||
'FUNCTION_MOCORD' => array(
|
||||
'Help' => '
|
||||
In Mocord mode the capture process (zmc) will connect to the camera and stream data.
|
||||
It will be decoded if necessary and live viewing will be possible.
|
||||
In addition a process (zma) will analyse the video for motion.
|
||||
Events will be created at fixed intervals or at start and stop of motion.
|
||||
Video will always be stored to disk and events will have the motion data stored in the database.
|
||||
Events may also be triggered externally (zmtrigger) or by linked monitors.
|
||||
'
|
||||
),
|
||||
'FUNCTION_NODECT' => array(
|
||||
'Help' => '
|
||||
In Nodect mode the capture process (zmc) will connect to the camera and stream data.
|
||||
It will be decoded if necessary and live viewing will be possible.
|
||||
In addition a process (zma) will run and will check any linked cameras for their alarm status.
|
||||
When linked cameras or an external trigger (zmtrigger) are alarmed, events will be created
|
||||
and video will be stored. No other motion detection will occur.
|
||||
'
|
||||
),
|
||||
'FUNCTION_ANALYSIS_ENABLED' => array(
|
||||
'Help' => '
|
||||
When in Modect, Mocord, Nodect or RECORD mode the analysis process can be turned on/off.
|
||||
This setting sets the default state when the process starts up.
|
||||
It can then be turned on/off through external triggers zmtrigger zmu or the web ui.
|
||||
When not enabled no motion detection or linked monitor checking will be performed and
|
||||
no events will be created. The zma process will still be running waiting to be enabled.
|
||||
'
|
||||
),
|
||||
'FUNCTION_DECODING_ENABLED' => array(
|
||||
'Help' => '
|
||||
When in Record or Nodect mode and using H264Passthrough with no jpegs being saved, we can
|
||||
optionally choose to not decode the H264/H265 packets. This will drastically reduce cpu use
|
||||
but will make live view unavailable for this monitor.'
|
||||
),
|
||||
|
||||
// 'LANG_DEFAULT' => array(
|
||||
// 'Prompt' => "This is a new prompt for this option",
|
||||
|
|
|
@ -741,3 +741,6 @@ a.flip {
|
|||
float: right;
|
||||
margin-right: -20px;
|
||||
}
|
||||
#content table.major .colDiskSpace {
|
||||
text-align: right;
|
||||
}
|
||||
|
|
|
@ -99,3 +99,6 @@
|
|||
.StatusFilter select {
|
||||
min-width: 130px;
|
||||
}
|
||||
#FunctionFunction {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
|
|
@ -42,3 +42,6 @@ input[name="newMonitor[Height]"] {
|
|||
select.chosen {
|
||||
width: 100%;
|
||||
}
|
||||
tr td:first-child {
|
||||
min-width: 300px;
|
||||
}
|
||||
|
|
|
@ -871,8 +871,8 @@ function xhtmlFooter() {
|
|||
<script src="tools/mootools/mootools-more.js"></script>
|
||||
<script src="js/mootools.ext.js"></script>
|
||||
<?php } ?>
|
||||
<script src="skins/<?php echo $skin; ?>/js/jquery.js"></script>
|
||||
<script src="skins/<?php echo $skin; ?>/js/jquery-ui-1.12.1/jquery-ui.js"></script>
|
||||
<script src="skins/<?php echo $skin; ?>/js/jquery.min.js"></script>
|
||||
<script src="skins/<?php echo $skin; ?>/js/jquery-ui-1.12.1/jquery-ui.min.js"></script>
|
||||
<script src="skins/<?php echo $skin; ?>/js/bootstrap.min.js"></script>
|
||||
<?php echo output_script_if_exists(array(
|
||||
'js/bootstrap-table.min.js',
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1 +0,0 @@
|
|||
jquery-2.2.4.js
|
|
@ -1 +0,0 @@
|
|||
https://code.jquery.com/jquery-2.2.4.js
|
|
@ -0,0 +1 @@
|
|||
jquery-3.5.1.min.js
|
|
@ -0,0 +1 @@
|
|||
https://code.jquery.com/jquery-3.5.1.min.js
|
|
@ -241,7 +241,7 @@ if ( currentView != 'none' && currentView != 'login' ) {
|
|||
$j(document).ready(function() {
|
||||
// Load the Logout and State modals into the dom
|
||||
$j('#logoutButton').click(clickLogout);
|
||||
if ( canEditSystem ) $j('#stateModalBtn').click(getStateModal);
|
||||
if ( canEdit.System ) $j('#stateModalBtn').click(getStateModal);
|
||||
|
||||
// Trigger autorefresh of the widget bar stats on the navbar
|
||||
if ( $j('.navbar').length ) {
|
||||
|
@ -894,8 +894,9 @@ function thumbnail_onmouseover(event) {
|
|||
timeout = setTimeout(function() {
|
||||
var img = event.target;
|
||||
var imgClass = ( currentView == 'console' ) ? 'zoom-console' : 'zoom';
|
||||
var imgAttr = ( currentView == 'frames' ) ? 'full_img_src' : 'stream_src';
|
||||
img.src = '';
|
||||
img.src = img.getAttribute('stream_src');
|
||||
img.src = img.getAttribute(imgAttr);
|
||||
img.addClass(imgClass);
|
||||
}, 350);
|
||||
}
|
||||
|
@ -904,8 +905,9 @@ function thumbnail_onmouseout(event) {
|
|||
clearTimeout(timeout);
|
||||
var img = event.target;
|
||||
var imgClass = ( currentView == 'console' ) ? 'zoom-console' : 'zoom';
|
||||
var imgAttr = ( currentView == 'frames' ) ? 'img_src' : 'still_src';
|
||||
img.src = '';
|
||||
img.src = img.getAttribute('still_src');
|
||||
img.src = img.getAttribute(imgAttr);
|
||||
img.removeClass(imgClass);
|
||||
}
|
||||
|
||||
|
|
|
@ -40,14 +40,17 @@ var thisUrl = '<?php echo ZM_BASE_URL.preg_replace('/\.php.*$/i', '.php', $_SERV
|
|||
var skinPath = '<?php echo ZM_SKIN_PATH ?>';
|
||||
var serverId = '<?php echo defined('ZM_SERVER_ID') ? ZM_SERVER_ID : '' ?>';
|
||||
|
||||
var canEditSystem = <?php echo canEdit('System')?'true':'false' ?>;
|
||||
var canViewSystem = <?php echo canView('System')?'true':'false' ?>;
|
||||
var canEditEvents = <?php echo canEdit('Events')?'true':'false' ?>;
|
||||
var canViewEvents = <?php echo canView('Events')?'true':'false' ?>;
|
||||
var canEditMonitors = <?php echo canEdit('Monitors')?'true':'false' ?>;
|
||||
var canViewMonitors = <?php echo canView('Monitors')?'true':'false' ?>;
|
||||
|
||||
var canEditGroups = <?php echo canEdit('Groups')?'true':'false' ?>;
|
||||
var canView = {};
|
||||
var canEdit = {};
|
||||
<?php
|
||||
$perms = array("Stream", "Events", "Control", "Monitors", "Groups", "System", "Devices");
|
||||
foreach ( $perms as $perm ) {
|
||||
?>
|
||||
canView["<?php echo $perm ?>"] = <?php echo canView($perm)?'true':'false' ?>;
|
||||
canEdit["<?php echo $perm ?>"] = <?php echo canEdit($perm)?'true':'false' ?>;
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
var ANIMATE_THUMBS = <?php echo ZM_WEB_ANIMATE_THUMBS?'true':'false' ?>;
|
||||
|
||||
|
|
|
@ -135,8 +135,6 @@ if ( !$Event->Id() ) {
|
|||
} else {
|
||||
if ( !file_exists($Event->Path()) )
|
||||
echo '<div class="error">Event was not found at '.$Event->Path().'. It is unlikely that playback will be possible.</div>';
|
||||
|
||||
$storage = validHtmlStr($Event->Storage()->Name()).( $Event->SecondaryStorageId() ? ', '.validHtmlStr($Event->SecondaryStorage()->Name()) : '' );
|
||||
?>
|
||||
|
||||
<!-- BEGIN HEADER -->
|
||||
|
@ -214,64 +212,7 @@ if ( canEdit('Events') ) {
|
|||
<div class="">
|
||||
<!-- VIDEO STATISTICS TABLE -->
|
||||
<table id="eventStatsTable" class="table-sm table-borderless">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th class="text-right"><?php echo translate('EventId') ?></th>
|
||||
<td id="dataEventId"><?php echo $Event->Id() ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="text-right"><?php echo translate('EventName') ?></th>
|
||||
<td id="dataEventName"><?php echo $Event->Name() ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="text-right"><?php echo translate('AttrMonitorId') ?></th>
|
||||
<td id="dataMonitorId"><?php echo $Monitor->Id() ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="text-right"><?php echo translate('AttrMonitorName') ?></th>
|
||||
<td id="dataMonitorName"><?php echo validHtmlStr($Monitor->Name()) ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="text-right"><?php echo translate('Cause') ?></th>
|
||||
<td id="dataCause"><?php echo validHtmlStr($Event->Cause()) ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="text-right"><?php echo translate('AttrStartTime') ?></th>
|
||||
<td id="dataStartTime"><?php echo strftime(STRF_FMT_DATETIME_SHORT, strtotime($Event->StartDateTime())) ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="text-right"><?php echo translate('Duration') ?></th>
|
||||
<td id="dataDuration"><?php echo $Event->Length().'s' ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="text-right"><?php echo translate('AttrFrames') ?></th>
|
||||
<td id="dataFrames"><?php echo $Event->Frames() ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="text-right"><?php echo translate('AttrAlarmFrames') ?></th>
|
||||
<td id="dataAlarmFrames"><?php echo $Event->AlarmFrames() ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="text-right"><?php echo translate('AttrTotalScore') ?></th>
|
||||
<td id="dataTotalScore"><?php echo $Event->TotScore() ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="text-right"><?php echo translate('AttrAvgScore') ?></th>
|
||||
<td id="dataAvgScore"><?php echo $Event->AvgScore() ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="text-right"><?php echo translate('AttrMaxScore') ?></th>
|
||||
<td id="dataMaxScore"><?php echo $Event->MaxScore() ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="text-right"><?php echo translate('DiskSpace') ?></th>
|
||||
<td id="dataDiskSpace"><?php echo human_filesize($Event->DiskSpace(null)) ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="text-right"><?php echo translate('Storage') ?></th>
|
||||
<td id="dataStorage"><?php echo $storage?></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<!-- EVENT STATISTICS POPULATED BY JAVASCRIPT -->
|
||||
</table>
|
||||
</div>
|
||||
<div class="">
|
||||
|
|
|
@ -143,21 +143,21 @@ $event_count = 0;
|
|||
while ( $event_row = dbFetchNext($results) ) {
|
||||
$event = new ZM\Event($event_row);
|
||||
$scale = max(reScale(SCALE_BASE, $event->Monitor()->DefaultScale(), ZM_WEB_DEFAULT_SCALE), SCALE_BASE);
|
||||
$event_link = '?view=event&eid='.$event->Id().$filterQuery.$sortQuery.'&page=1';
|
||||
?>
|
||||
<tr<?php echo $event->Archived() ? ' class="archived"' : '' ?>>
|
||||
<td class="colId">
|
||||
<input type="hidden" name="eids[]" value="<?php echo $event->Id()?>"/>
|
||||
<a href="?view=event&eid=<?php echo $event->Id().$filterQuery.$sortQuery ?>&page=1"><?php echo $event->Id().($event->Archived()?'*':'') ?></a>
|
||||
<a href="<?php echo $event_link ?>"><?php echo $event->Id().($event->Archived()?'*':'') ?></a>
|
||||
</td>
|
||||
<td class="colName"><a href="?view=event&eid=<?php echo $event->Id().$filterQuery.$sortQuery ?>&page=1"><?php echo validHtmlStr($event->Name()).($event->Archived()?'*':'') ?></a></td>
|
||||
<td class="colMonitorName"><?php echo makeLink( '?view=monitor&mid='.$event->MonitorId(), $event->MonitorName(), canEdit( 'Monitors' ) ) ?></td>
|
||||
<td class="colCause"><?php echo makeLink( '#', validHtmlStr($event->Cause()), canEdit( 'Events' ), 'title="' .htmlspecialchars($event->Notes()). '" class="eDetailLink" data-eid=' .$event->Id(). '"') ?></td>
|
||||
<td class="colName"><a href="<?php echo $event_link ?>"><?php echo validHtmlStr($event->Name()).($event->Archived()?'*':'') ?></a></td>
|
||||
<td class="colMonitorName"><?php echo makeLink('?view=monitor&mid='.$event->MonitorId(), $event->MonitorName(), canEdit('Monitors')) ?></td>
|
||||
<td class="colCause"><?php echo makeLink($event_link, validHtmlStr($event->Cause()), canView('Events'), 'title="' .htmlspecialchars($event->Notes()). '" class="eDetailLink" data-eid="'.$event->Id().'"') ?></td>
|
||||
<td class="colTime"><?php echo strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->StartDateTime())) .
|
||||
( $event->EndDateTime() ? ' until ' . strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->EndDateTime()) ) : '' ) ?>
|
||||
</td>
|
||||
<td class="colDuration"><?php echo gmdate("H:i:s", $event->Length() ) ?></td>
|
||||
<td class="colFrames"><?php echo makeLink( '?view=frames&eid='.$event->Id(), $event->Frames() ) ?></td>
|
||||
<td class="colAlarmFrames"><?php echo makeLink( '?view=frames&eid='.$event->Id(), $event->AlarmFrames() ) ?></td>
|
||||
( $event->EndDateTime() ? ' until ' . strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->EndDateTime())) : '' ) ?></td>
|
||||
<td class="colDuration"><?php echo gmdate('H:i:s', $event->Length()) ?></td>
|
||||
<td class="colFrames"><?php echo makeLink('?view=frames&eid='.$event->Id(), $event->Frames()) ?></td>
|
||||
<td class="colAlarmFrames"><?php echo makeLink('?view=frames&eid='.$event->Id(), $event->AlarmFrames()) ?></td>
|
||||
<td class="colTotScore"><?php echo $event->TotScore() ?></td>
|
||||
<td class="colAvgScore"><?php echo $event->AvgScore() ?></td>
|
||||
<td class="colMaxScore"><?php echo $event->MaxScore() ?></td>
|
||||
|
@ -168,9 +168,7 @@ while ( $event_row = dbFetchNext($results) ) {
|
|||
echo '<td class="colDiskSpace">'.human_filesize($event->DiskSpace()).'</td>';
|
||||
}
|
||||
unset($event);
|
||||
echo '
|
||||
</tr>
|
||||
';
|
||||
echo PHP_EOL.'</tr>'.PHP_EOL;
|
||||
} # end foreach event
|
||||
?>
|
||||
</tbody>
|
||||
|
@ -179,9 +177,7 @@ while ( $event_row = dbFetchNext($results) ) {
|
|||
<td colspan="11"><?php echo $event_count ?> events</td>
|
||||
<?php
|
||||
if ( ZM_WEB_EVENT_DISK_SPACE ) {
|
||||
?>
|
||||
<td class="colDiskSpace"><?php echo human_filesize($disk_space_total);?></td>
|
||||
<?php
|
||||
echo '<td class="colDiskSpace">'.human_filesize($disk_space_total).'</td>'.PHP_EOL;
|
||||
}
|
||||
?>
|
||||
</tr>
|
||||
|
|
|
@ -49,7 +49,7 @@ $prevFid = $fid-1;
|
|||
$nextFid = $fid+1;
|
||||
$lastFid = $maxFid;
|
||||
|
||||
$alarmFrame = $Frame->Type() == 'Alarm';
|
||||
$alarmFrame = ( $Frame->Type() == 'Alarm' ) ? 1 : 0;
|
||||
|
||||
if ( isset($_REQUEST['scale']) ) {
|
||||
$scale = validNum($_REQUEST['scale']);
|
||||
|
@ -103,7 +103,14 @@ xhtmlHeaders(__FILE__, translate('Frame').' - '.$Event->Id().' - '.$Frame->Frame
|
|||
</form>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<div id="content" class="d-flex flex-row justify-content-center">
|
||||
|
||||
|
||||
<table id="frameStatsTable" class="table-sm table-borderless pr-3">
|
||||
<!-- FRAME STATISTICS POPULATED BY AJAX -->
|
||||
</table>
|
||||
|
||||
<div>
|
||||
<p id="image">
|
||||
<?php if ( $imageData['hasAnalImage'] ) {
|
||||
echo sprintf('<a href="?view=frame&eid=%d&fid=%d&scale=%d&show=%s">', $Event->Id(), $Frame->FrameId(), $scale, ( $show=='anal'?'capt':'anal' ) );
|
||||
|
@ -152,6 +159,7 @@ if ( file_exists($rImagePath) ) {
|
|||
class="<?php echo $imageData['imageClass'] ?>"
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -112,7 +112,7 @@ function reloadWindow() {
|
|||
function manageFunctionModal(evt) {
|
||||
evt.preventDefault();
|
||||
|
||||
if ( !canEditEvents ) {
|
||||
if ( !canEdit.Events ) {
|
||||
enoperm();
|
||||
return;
|
||||
}
|
||||
|
@ -151,8 +151,25 @@ function manageFunctionModal(evt) {
|
|||
console.error("Unable to find form with id function_form");
|
||||
return;
|
||||
}
|
||||
function_form.elements['newFunction'].onchange=function() {
|
||||
$j('#function_help div').hide();
|
||||
$j('#'+this.value+'Help').show();
|
||||
if ( this.value == 'Monitor' || this.value == 'None' ) {
|
||||
$j('#FunctionAnalysisEnabled').hide();
|
||||
} else {
|
||||
$j('#FunctionAnalysisEnabled').show();
|
||||
}
|
||||
if ( this.value == 'Record' || this.value == 'Nodect' ) {
|
||||
$j('#FunctionDecodingEnabled').show();
|
||||
} else {
|
||||
$j('#FunctionDecodingEnabled').hide();
|
||||
}
|
||||
};
|
||||
function_form.elements['newFunction'].value = monitor.Function;
|
||||
function_form.elements['newFunction'].onchange();
|
||||
|
||||
function_form.elements['newEnabled'].checked = monitor.Enabled == '1';
|
||||
function_form.elements['newDecodingEnabled'].checked = monitor.DecodingEnabled == '1';
|
||||
function_form.elements['mid'].value = mid;
|
||||
document.getElementById('function_monitor_name').innerHTML = monitor.Name;
|
||||
|
||||
|
|
|
@ -24,7 +24,8 @@ var monitors = new Array();
|
|||
'Url': '<?php echo $monitor->UrlToIndex( ZM_MIN_STREAMING_PORT ? ($monitor->Id() + ZM_MIN_STREAMING_PORT) : '') ?>',
|
||||
'Type': '<?php echo $monitor->Type() ?>',
|
||||
'Function': '<?php echo $monitor->Function() ?>',
|
||||
'Enabled': '<?php echo $monitor->Enabled() ?>'
|
||||
'Enabled': '<?php echo $monitor->Enabled() ?>',
|
||||
'DecodingEnabled': '<?php echo $monitor->DecodingEnabled() ?>'
|
||||
};
|
||||
<?php
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ function getDelConfirmModal(key) {
|
|||
// Manage the DELETE CONFIRMATION modal button
|
||||
function manageDelConfirmModalBtns() {
|
||||
document.getElementById("delConfirmBtn").addEventListener("click", function onDelConfirmClick(evt) {
|
||||
if ( ! canEditControl ) {
|
||||
if ( ! canEdit.Control ) {
|
||||
enoperm();
|
||||
return;
|
||||
}
|
||||
|
@ -67,9 +67,9 @@ function initPage() {
|
|||
function() {
|
||||
selections = table.bootstrapTable('getSelections');
|
||||
|
||||
addNewBtn.prop('disabled', (selections.length || !canEditControl));
|
||||
editBtn.prop('disabled', !((selections.length == 1) && canEditControl));
|
||||
deleteBtn.prop('disabled', !(selections.length && canEditControl));
|
||||
addNewBtn.prop('disabled', (selections.length || !canEdit.Control));
|
||||
editBtn.prop('disabled', !((selections.length == 1) && canEdit.Control));
|
||||
deleteBtn.prop('disabled', !(selections.length && canEdit.Control));
|
||||
});
|
||||
|
||||
// Init the bootstrap-table
|
||||
|
@ -92,7 +92,7 @@ function initPage() {
|
|||
|
||||
// Manage the DELETE button
|
||||
document.getElementById("deleteBtn").addEventListener("click", function onDeleteClick(evt) {
|
||||
if ( ! canEditControl ) {
|
||||
if ( ! canEdit.Control ) {
|
||||
enoperm();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
var canEditControl = <?php echo canEdit('Control')?'true':'false' ?>;
|
|
@ -42,7 +42,7 @@ function getDelConfirmModal(key) {
|
|||
// Manage the DELETE CONFIRMATION modal button
|
||||
function manageDelConfirmModalBtns() {
|
||||
document.getElementById("delConfirmBtn").addEventListener("click", function onDelConfirmClick(evt) {
|
||||
if ( ! canEditDevice ) {
|
||||
if ( ! canEdit.Device ) {
|
||||
enoperm();
|
||||
return;
|
||||
}
|
||||
|
@ -91,9 +91,9 @@ function initPage() {
|
|||
// Init the bootstrap-table
|
||||
table.bootstrapTable({icons: icons});
|
||||
|
||||
if ( canEditDevice ) enableDeviceModal();
|
||||
if ( canEdit.Device ) enableDeviceModal();
|
||||
|
||||
newDeviceBtn.prop('disabled', !canEditDevice);
|
||||
newDeviceBtn.prop('disabled', !canEdit.Device);
|
||||
|
||||
// Manage the BACK button
|
||||
document.getElementById("backBtn").addEventListener("click", function onBackClick(evt) {
|
||||
|
@ -112,7 +112,7 @@ function initPage() {
|
|||
|
||||
// Manage the DELETE button
|
||||
document.getElementById("deleteBtn").addEventListener("click", function onDeleteClick(evt) {
|
||||
if ( ! canEditDevice ) {
|
||||
if ( ! canEdit.Device ) {
|
||||
enoperm();
|
||||
return;
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ function initPage() {
|
|||
function() {
|
||||
selections = table.bootstrapTable('getSelections');
|
||||
|
||||
deleteBtn.prop('disabled', !(selections.length && canEditDevice));
|
||||
deleteBtn.prop('disabled', !(selections.length && canEdit.Device));
|
||||
});
|
||||
|
||||
// Process mouse clicks on the table cells
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
var canEditDevice = <?php echo canEdit('Devices') ? 'true' : 'false' ?>;
|
|
@ -598,8 +598,8 @@ function getEventResponse(respObj, respText) {
|
|||
$j('dataStorage').text( eventData.Storage );
|
||||
|
||||
// Refresh the status of the archive buttons
|
||||
archiveBtn.prop('disabled', !(!eventData.Archived && canEditEvents));
|
||||
unarchiveBtn.prop('disabled', !(eventData.Archived && canEditEvents));
|
||||
archiveBtn.prop('disabled', !(!eventData.Archived && canEdit.Events));
|
||||
unarchiveBtn.prop('disabled', !(eventData.Archived && canEdit.Events));
|
||||
|
||||
history.replaceState(null, null, '?view=event&eid=' + eventData.Id + filterQuery + sortQuery); //if popup removed, check if this allows forward
|
||||
// Technically, events can be different sizes, so may need to update the size of the image, but it might be better to have it stay scaled...
|
||||
|
@ -1032,20 +1032,10 @@ function handleClick( event ) {
|
|||
}
|
||||
}
|
||||
|
||||
// Load the Delete Confirmation Modal HTML via Ajax call
|
||||
function getDelConfirmModal() {
|
||||
$j.getJSON(thisUrl + '?request=modal&modal=delconfirm')
|
||||
.done(function(data) {
|
||||
insertModalHtml('deleteConfirm', data.html);
|
||||
manageDelConfirmModalBtns();
|
||||
})
|
||||
.fail(logAjaxFail);
|
||||
}
|
||||
|
||||
// Manage the DELETE CONFIRMATION modal button
|
||||
function manageDelConfirmModalBtns() {
|
||||
document.getElementById("delConfirmBtn").addEventListener("click", function onDelConfirmClick(evt) {
|
||||
if ( ! canEditEvents ) {
|
||||
if ( ! canEdit.Events ) {
|
||||
enoperm();
|
||||
return;
|
||||
}
|
||||
|
@ -1075,9 +1065,21 @@ function getEvtStatsCookie() {
|
|||
return stats;
|
||||
}
|
||||
|
||||
function getStat() {
|
||||
table.empty().append('<tbody>');
|
||||
$j.each( eventDataStrings, function( key ) {
|
||||
var th = $j('<th>').addClass('text-right').text(eventDataStrings[key]);
|
||||
var tdString = ( eventData[key].length ) ? eventData[key] : 'n/a';
|
||||
var td = $j('<td>').text(tdString);
|
||||
var row = $j('<tr>').append(th, td);
|
||||
|
||||
$j('#eventStatsTable tbody').append(row);
|
||||
});
|
||||
}
|
||||
|
||||
function initPage() {
|
||||
// Load the delete confirmation modal into the DOM
|
||||
getDelConfirmModal();
|
||||
// Load the event stats
|
||||
getStat();
|
||||
|
||||
var stats = getEvtStatsCookie();
|
||||
if ( stats != 'on' ) table.toggle(false);
|
||||
|
@ -1134,13 +1136,13 @@ function initPage() {
|
|||
});
|
||||
|
||||
// enable or disable buttons based on current selection and user rights
|
||||
renameBtn.prop('disabled', !canEditEvents);
|
||||
archiveBtn.prop('disabled', !(!eventData.Archived && canEditEvents));
|
||||
unarchiveBtn.prop('disabled', !(eventData.Archived && canEditEvents));
|
||||
editBtn.prop('disabled', !canEditEvents);
|
||||
exportBtn.prop('disabled', !canViewEvents);
|
||||
downloadBtn.prop('disabled', !canViewEvents);
|
||||
deleteBtn.prop('disabled', !canEditEvents);
|
||||
renameBtn.prop('disabled', !canEdit.Events);
|
||||
archiveBtn.prop('disabled', !(!eventData.Archived && canEdit.Events));
|
||||
unarchiveBtn.prop('disabled', !(eventData.Archived && canEdit.Events));
|
||||
editBtn.prop('disabled', !canEdit.Events);
|
||||
exportBtn.prop('disabled', !canView.Events);
|
||||
downloadBtn.prop('disabled', !canView.Events);
|
||||
deleteBtn.prop('disabled', !canEdit.Events);
|
||||
|
||||
// Don't enable the back button if there is no previous zm page to go back to
|
||||
backBtn.prop('disabled', !document.referrer.length);
|
||||
|
@ -1183,7 +1185,7 @@ function initPage() {
|
|||
|
||||
// Manage the UNARCHIVE button
|
||||
document.getElementById("unarchiveBtn").addEventListener("click", function onUnarchiveClick(evt) {
|
||||
if ( ! canEditEvents ) {
|
||||
if ( ! canEdit.Events ) {
|
||||
enoperm();
|
||||
return;
|
||||
}
|
||||
|
@ -1198,7 +1200,7 @@ function initPage() {
|
|||
|
||||
// Manage the EDIT button
|
||||
document.getElementById("editBtn").addEventListener("click", function onEditClick(evt) {
|
||||
if ( ! canEditEvents ) {
|
||||
if ( ! canEdit.Events ) {
|
||||
enoperm();
|
||||
return;
|
||||
}
|
||||
|
@ -1253,12 +1255,23 @@ function initPage() {
|
|||
|
||||
// Manage the DELETE button
|
||||
document.getElementById("deleteBtn").addEventListener("click", function onDeleteClick(evt) {
|
||||
if ( ! canEditEvents ) {
|
||||
if ( ! canEdit.Events ) {
|
||||
enoperm();
|
||||
return;
|
||||
}
|
||||
|
||||
evt.preventDefault();
|
||||
if ( ! $j('#deleteConfirm').length ) {
|
||||
// Load the delete confirmation modal into the DOM
|
||||
$j.getJSON(thisUrl + '?request=modal&modal=delconfirm')
|
||||
.done(function(data) {
|
||||
insertModalHtml('deleteConfirm', data.html);
|
||||
manageDelConfirmModalBtns();
|
||||
$j('#deleteConfirm').modal('show');
|
||||
})
|
||||
.fail(logAjaxFail);
|
||||
return;
|
||||
}
|
||||
$j('#deleteConfirm').modal('show');
|
||||
});
|
||||
}
|
||||
|
|
|
@ -42,17 +42,46 @@ var eventData = {
|
|||
Id: '<?php echo $Event->Id() ?>',
|
||||
Name: '<?php echo $Event->Name() ?>',
|
||||
MonitorId: '<?php echo $Event->MonitorId() ?>',
|
||||
MonitorName: '<?php echo validJsStr($Monitor->Name()) ?>',
|
||||
Cause: '<?php echo validHtmlStr($Event->Cause()) ?>',
|
||||
Width: '<?php echo $Event->Width() ?>',
|
||||
Height: '<?php echo $Event->Height() ?>',
|
||||
Length: '<?php echo $Event->Length() ?>',
|
||||
StartDateTime: '<?php echo $Event->StartDateTime() ?>',
|
||||
StartDateTimeFmt: '<?php echo strftime(STRF_FMT_DATETIME_SHORT, strtotime($Event->StartDateTime())) ?>',
|
||||
EndDateTime: '<?php echo $Event->EndDateTime() ?>',
|
||||
Frames: '<?php echo $Event->Frames() ?>',
|
||||
MonitorName: '<?php echo validJsStr($Monitor->Name()) ?>',
|
||||
AlarmFrames: '<?php echo $Event->AlarmFrames() ?>',
|
||||
TotScore: '<?php echo $Event->TotScore() ?>',
|
||||
AvgScore: '<?php echo $Event->AvgScore() ?>',
|
||||
MaxScore: '<?php echo $Event->MaxScore() ?>',
|
||||
DiskSpace: '<?php echo human_filesize($Event->DiskSpace(null)) ?>',
|
||||
Storage: '<?php validHtmlStr($Event->Storage()->Name()).( $Event->SecondaryStorageId() ? ', '.validHtmlStr($Event->SecondaryStorage()->Name()) : '' ) ?>',
|
||||
Archived: <?php echo $Event->Archived?'true':'false' ?>
|
||||
Storage: '<?php echo validHtmlStr($Event->Storage()->Name()).( $Event->SecondaryStorageId() ? ', '.validHtmlStr($Event->SecondaryStorage()->Name()) : '' ) ?>',
|
||||
ArchivedStr: '<?php echo $Event->Archived ? translate('Yes') : translate('No') ?>',
|
||||
EmailedStr: '<?php echo $Event->Emailed ? translate('Yes') : translate('No') ?>',
|
||||
Archived: <?php echo $Event->Archived?'true':'false' ?>,
|
||||
Emailed: <?php echo $Event->Emailed?'true':'false' ?>
|
||||
};
|
||||
|
||||
var eventDataStrings = {
|
||||
Id: '<?php echo translate('EventId') ?>',
|
||||
Name: '<?php echo translate('EventName') ?>',
|
||||
MonitorId: '<?php echo translate('AttrMonitorId') ?>',
|
||||
MonitorName: '<?php echo translate('AttrMonitorName') ?>',
|
||||
Cause: '<?php echo translate('Cause') ?>',
|
||||
StartDateTimeFmt: '<?php echo translate('AttrStartTime') ?>',
|
||||
Length: '<?php echo translate('Duration') ?>',
|
||||
Frames: '<?php echo translate('AttrFrames') ?>',
|
||||
AlarmFrames: '<?php echo translate('AttrAlarmFrames') ?>',
|
||||
TotScore: '<?php echo translate('AttrTotalScore') ?>',
|
||||
AvgScore: '<?php echo translate('AttrAvgScore') ?>',
|
||||
MaxScore: '<?php echo translate('AttrMaxScore') ?>',
|
||||
DiskSpace: '<?php echo translate('DiskSpace') ?>',
|
||||
Storage: '<?php echo translate('Storage') ?>',
|
||||
ArchivedStr: '<?php echo translate('Archived') ?>',
|
||||
EmailedStr: '<?php echo translate('Emailed') ?>'
|
||||
};
|
||||
|
||||
var monitorUrl = '<?php echo $Event->Storage()->Server()->UrlToIndex(); ?>';
|
||||
|
||||
var filterQuery = '<?php echo isset($filterQuery)?validJsStr(htmlspecialchars_decode($filterQuery)):'' ?>';
|
||||
|
@ -63,7 +92,6 @@ var rate = '<?php echo $rate ?>'; // really only used when setting up initial pl
|
|||
var scale = "<?php echo $scale ?>";
|
||||
var LabelFormat = "<?php echo validJsStr($Monitor->LabelFormat())?>";
|
||||
|
||||
var canEditEvents = <?php echo canEdit('Events')?'true':'false' ?>;
|
||||
var streamTimeout = <?php echo 1000*ZM_WEB_REFRESH_STATUS ?>;
|
||||
|
||||
var canStreamNative = <?php echo canStreamNative()?'true':'false' ?>;
|
||||
|
|
|
@ -58,8 +58,8 @@ function processRows(rows) {
|
|||
row.Id = '<a href="?view=event&eid=' + eid + filterQuery + sortQuery + '&page=1">' + eid + '</a>';
|
||||
row.Name = '<a href="?view=event&eid=' + eid + filterQuery + sortQuery + '&page=1">' + row.Name + '</a>'
|
||||
+ '<br/><div class="small text-nowrap text-muted">' + archived + emailed + '</div>';
|
||||
if ( canEditMonitors ) row.Monitor = '<a href="?view=monitor&mid=' + mid + '">' + row.Monitor + '</a>';
|
||||
if ( canEditEvents ) row.Cause = '<a href="#" title="' + row.Notes + '" class="eDetailLink" data-eid="' + eid + '">' + row.Cause + '</a>';
|
||||
if ( canEdit.Monitors ) row.Monitor = '<a href="?view=monitor&mid=' + mid + '">' + row.Monitor + '</a>';
|
||||
if ( canEdit.Events ) row.Cause = '<a href="#" title="' + row.Notes + '" class="eDetailLink" data-eid="' + eid + '">' + row.Cause + '</a>';
|
||||
if ( row.Notes.indexOf('detected:') >= 0 ) {
|
||||
row.Cause = row.Cause + '<a href="?view=image&eid=' + eid + '&fid=objdetect"><div class="small text-nowrap text-muted"><u>' + row.Notes + '</u></div></a>';
|
||||
} else if ( row.Notes != 'Forced Web: ' ) {
|
||||
|
@ -105,7 +105,7 @@ function getDelConfirmModal() {
|
|||
// Manage the DELETE CONFIRMATION modal button
|
||||
function manageDelConfirmModalBtns() {
|
||||
document.getElementById("delConfirmBtn").addEventListener("click", function onDelConfirmClick(evt) {
|
||||
if ( ! canEditEvents ) {
|
||||
if ( ! canEdit.Events ) {
|
||||
enoperm();
|
||||
return;
|
||||
}
|
||||
|
@ -163,13 +163,13 @@ function initPage() {
|
|||
function() {
|
||||
selections = table.bootstrapTable('getSelections');
|
||||
|
||||
viewBtn.prop('disabled', !(selections.length && canViewEvents));
|
||||
archiveBtn.prop('disabled', !(selections.length && canEditEvents));
|
||||
unarchiveBtn.prop('disabled', !(getArchivedSelections()) && canEditEvents);
|
||||
editBtn.prop('disabled', !(selections.length && canEditEvents));
|
||||
exportBtn.prop('disabled', !(selections.length && canViewEvents));
|
||||
downloadBtn.prop('disabled', !(selections.length && canViewEvents));
|
||||
deleteBtn.prop('disabled', !(selections.length && canEditEvents));
|
||||
viewBtn.prop('disabled', !(selections.length && canView.Events));
|
||||
archiveBtn.prop('disabled', !(selections.length && canEdit.Events));
|
||||
unarchiveBtn.prop('disabled', !(getArchivedSelections()) && canEdit.Events);
|
||||
editBtn.prop('disabled', !(selections.length && canEdit.Events));
|
||||
exportBtn.prop('disabled', !(selections.length && canView.Events));
|
||||
downloadBtn.prop('disabled', !(selections.length && canView.Events));
|
||||
deleteBtn.prop('disabled', !(selections.length && canEdit.Events));
|
||||
});
|
||||
|
||||
// Don't enable the back button if there is no previous zm page to go back to
|
||||
|
@ -228,7 +228,7 @@ function initPage() {
|
|||
|
||||
// Manage the UNARCHIVE button
|
||||
document.getElementById("unarchiveBtn").addEventListener("click", function onUnarchiveClick(evt) {
|
||||
if ( ! canEditEvents ) {
|
||||
if ( ! canEdit.Events ) {
|
||||
enoperm();
|
||||
return;
|
||||
}
|
||||
|
@ -246,7 +246,7 @@ function initPage() {
|
|||
|
||||
// Manage the EDIT button
|
||||
document.getElementById("editBtn").addEventListener("click", function onEditClick(evt) {
|
||||
if ( ! canEditEvents ) {
|
||||
if ( ! canEdit.Events ) {
|
||||
enoperm();
|
||||
return;
|
||||
}
|
||||
|
@ -292,7 +292,7 @@ function initPage() {
|
|||
|
||||
// Manage the DELETE button
|
||||
document.getElementById("deleteBtn").addEventListener("click", function onDeleteClick(evt) {
|
||||
if ( ! canEditEvents ) {
|
||||
if ( ! canEdit.Events ) {
|
||||
enoperm();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -64,12 +64,10 @@ function exportResponse(respObj, respText) {
|
|||
}
|
||||
|
||||
function exportEvents( ) {
|
||||
var parms = 'view=event&request=event&action=export';
|
||||
parms += '&'+$('contentForm').toQueryString();
|
||||
var query = new Request.JSON( {
|
||||
url: thisUrl,
|
||||
url: '?view=event&request=event&action=export',
|
||||
method: 'post',
|
||||
data: parms,
|
||||
data: $('contentForm').toQueryString(),
|
||||
onSuccess: exportResponse
|
||||
} );
|
||||
query.send();
|
||||
|
|
|
@ -40,6 +40,24 @@ document.addEventListener('DOMContentLoaded', function onDCL() {
|
|||
document.getElementById('scaleControl').addEventListener('change', changeScale);
|
||||
});
|
||||
|
||||
function getStat(params) {
|
||||
$j.getJSON(thisUrl + '?view=request&request=stats&raw=true', params)
|
||||
.done(function(data) {
|
||||
var stat = data.raw;
|
||||
|
||||
$j('#frameStatsTable').empty().append('<tbody>');
|
||||
$j.each( statHeaderStrings, function( key ) {
|
||||
var th = $j('<th>').addClass('text-right').text(statHeaderStrings[key]);
|
||||
var tdString = ( stat ) ? stat[key] : 'n/a';
|
||||
var td = $j('<td>').text(tdString);
|
||||
var row = $j('<tr>').append(th, td);
|
||||
|
||||
$j('#frameStatsTable tbody').append(row);
|
||||
});
|
||||
})
|
||||
.fail(logAjaxFail);
|
||||
}
|
||||
|
||||
function initPage() {
|
||||
var backBtn = $j('#backBtn');
|
||||
|
||||
|
@ -65,6 +83,9 @@ function initPage() {
|
|||
evt.preventDefault();
|
||||
window.location.href = thisUrl+'?view=stats&eid='+eid+'&fid='+fid;
|
||||
});
|
||||
|
||||
// Load the frame stats
|
||||
getStat({eid: eid, fid: fid});
|
||||
}
|
||||
|
||||
$j(document).ready(function() {
|
||||
|
|
|
@ -13,3 +13,15 @@ var eid = <?php echo $eid ?>;
|
|||
var fid = <?php echo $fid ?>;
|
||||
var record_event_stats = <?php echo ZM_RECORD_EVENT_STATS ?>;
|
||||
var alarmFrame = <?php echo $alarmFrame ?>;
|
||||
|
||||
var statHeaderStrings = {};
|
||||
statHeaderStrings.ZoneName = "<?php echo translate('Zone') ?>";
|
||||
statHeaderStrings.PixelDiff = "<?php echo translate('PixelDiff') ?>";
|
||||
statHeaderStrings.AlarmPixels = "<?php echo translate('AlarmPx') ?>";
|
||||
statHeaderStrings.FilterPixels = "<?php echo translate('FilterPx') ?>";
|
||||
statHeaderStrings.BlobPixels = "<?php echo translate('BlobPx') ?>";
|
||||
statHeaderStrings.Blobs = "<?php echo translate('Blobs') ?>";
|
||||
statHeaderStrings.BlobSizes = "<?php echo translate('BlobSizes') ?>";
|
||||
statHeaderStrings.AlarmLimits = "<?php echo translate('AlarmLimits') ?>";
|
||||
statHeaderStrings.Score = "<?php echo translate('Score') ?>";
|
||||
|
||||
|
|
|
@ -26,27 +26,6 @@ function processRows(rows) {
|
|||
return rows;
|
||||
}
|
||||
|
||||
function thumbnail_onmouseover(event) {
|
||||
var img = event.target;
|
||||
img.src = '';
|
||||
img.src = img.getAttribute('full_img_src');
|
||||
}
|
||||
|
||||
function thumbnail_onmouseout(event) {
|
||||
var img = event.target;
|
||||
img.src = '';
|
||||
img.src = img.getAttribute('img_src');
|
||||
}
|
||||
|
||||
function initThumbAnimation() {
|
||||
if ( WEB_ANIMATE_THUMBS ) {
|
||||
$j('.colThumbnail img').each(function() {
|
||||
this.addEventListener('mouseover', thumbnail_onmouseover, false);
|
||||
this.addEventListener('mouseout', thumbnail_onmouseout, false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function processClicks(event, field, value, row, $element) {
|
||||
if ( field == 'Score' ) {
|
||||
window.location.assign('?view=stats&eid='+row.EventId+'&fid='+row.FrameId);
|
||||
|
@ -118,8 +97,7 @@ function initPage() {
|
|||
var thumb_ndx = $j('#framesTable tr th').filter(function() {
|
||||
return $j(this).text().trim() == 'Thumbnail';
|
||||
}).index();
|
||||
var thmbClass = WEB_ANIMATE_THUMBS ? 'colThumbnail zoom' : 'colThumbnail';
|
||||
table.find("tr td:nth-child(" + (thumb_ndx+1) + ")").addClass(thmbClass);
|
||||
table.find("tr td:nth-child(" + (thumb_ndx+1) + ")").addClass('colThumbnail');
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ function deleteGroup( element ) {
|
|||
}
|
||||
|
||||
function configureButtons( element ) {
|
||||
if ( canEditGroups ) {
|
||||
if ( canEdit.Groups ) {
|
||||
var form = element.form;
|
||||
if ( element.checked ) {
|
||||
form.deleteBtn.disabled = (element.value == 0);
|
||||
|
@ -64,7 +64,7 @@ function configModalBtns() {
|
|||
console.log("No groupForm found");
|
||||
return;
|
||||
}
|
||||
if ( !canEditGroups ) {
|
||||
if ( !canEdit.Groups ) {
|
||||
console.log("Cannot edit groups");
|
||||
form.elements['action'].disabled = disabled;
|
||||
return;
|
||||
|
|
|
@ -146,6 +146,24 @@ function initPage() {
|
|||
el.oninput = window['update_estimated_ram_use'].bind(el);
|
||||
});
|
||||
|
||||
document.querySelectorAll('select[name="newMonitor[Function]"]').forEach(function(el) {
|
||||
el.onchange = function() {
|
||||
$j('#function_help div').hide();
|
||||
$j('#'+this.value+'Help').show();
|
||||
if ( this.value == 'Monitor' || this.value == 'None' ) {
|
||||
$j('#FunctionEnabled').hide();
|
||||
} else {
|
||||
$j('#FunctionEnabled').show();
|
||||
}
|
||||
if ( this.value == 'Record' || this.value == 'Nodect' ) {
|
||||
$j('#FunctionDecodingEnabled').show();
|
||||
} else {
|
||||
$j('#FunctionDecodingEnabled').hide();
|
||||
}
|
||||
};
|
||||
el.onchange();
|
||||
});
|
||||
|
||||
$j('.chosen').chosen();
|
||||
|
||||
// Don't enable the back button if there is no previous zm page to go back to
|
||||
|
|
|
@ -62,11 +62,11 @@ function initPage() {
|
|||
var NewStorageBtn = $j('#NewStorageBtn');
|
||||
var NewServerBtn = $j('#NewServerBtn');
|
||||
|
||||
if ( canEditSystem ) enableStorageModal();
|
||||
if ( canEditSystem ) enableServerModal();
|
||||
if ( canEdit.System ) enableStorageModal();
|
||||
if ( canEdit.System ) enableServerModal();
|
||||
|
||||
NewStorageBtn.prop('disabled', !canEditSystem);
|
||||
NewServerBtn.prop('disabled', !canEditSystem);
|
||||
NewStorageBtn.prop('disabled', !canEdit.System);
|
||||
NewServerBtn.prop('disabled', !canEdit.System);
|
||||
}
|
||||
|
||||
$j(document).ready(function() {
|
||||
|
|
|
@ -4,4 +4,3 @@ if ( restartWarning ) {
|
|||
alert( "<?php echo translate('OptionRestartWarning') ?>" );
|
||||
}
|
||||
|
||||
var canEditSystem = <?php echo canEdit('System') ? 'true' : 'false' ?>;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
var streamCmdTimer = null;
|
||||
var streamStatus;
|
||||
var auth_hash;
|
||||
var alarmState = STATE_IDLE;
|
||||
|
@ -9,23 +10,6 @@ var forceAlmBtn = $j('#forceAlmBtn');
|
|||
var table = $j('#eventList');
|
||||
var filterQuery = '&filter[Query][terms][0][attr]=MonitorId&filter[Query][terms][0][op]=%3d&filter[Query][terms][0][val]='+monitorId;
|
||||
|
||||
if ( monitorType != 'WebSite' ) {
|
||||
var streamCmdParms = 'view=request&request=stream&connkey='+connKey;
|
||||
if ( auth_hash ) {
|
||||
streamCmdParms += '&auth='+auth_hash;
|
||||
}
|
||||
var streamCmdReq = new Request.JSON( {
|
||||
url: monitorUrl,
|
||||
method: 'get',
|
||||
timeout: AJAX_TIMEOUT,
|
||||
link: 'chain',
|
||||
onError: getStreamCmdError,
|
||||
onSuccess: getStreamCmdResponse,
|
||||
onFailure: getStreamCmdFailure
|
||||
} );
|
||||
var streamCmdTimer = null;
|
||||
}
|
||||
|
||||
/*
|
||||
This is the format of the json object sent by bootstrap-table
|
||||
|
||||
|
@ -194,10 +178,6 @@ function getStreamCmdError(text, error) {
|
|||
window.location.reload();
|
||||
}
|
||||
|
||||
function getStreamCmdFailure(xhr) {
|
||||
console.log(xhr);
|
||||
}
|
||||
|
||||
function getStreamCmdResponse(respObj, respText) {
|
||||
watchdogOk('stream');
|
||||
if ( streamCmdTimer ) {
|
||||
|
@ -267,7 +247,7 @@ function getStreamCmdResponse(respObj, respText) {
|
|||
setButtonState('zoomOutBtn', 'inactive');
|
||||
}
|
||||
|
||||
if ( canEditMonitors ) {
|
||||
if ( canEdit.Monitors ) {
|
||||
if ( streamStatus.enabled ) {
|
||||
enableAlmBtn.addClass('disabled');
|
||||
enableAlmBtn.prop('title', disableAlarmsStr);
|
||||
|
@ -285,7 +265,7 @@ function getStreamCmdResponse(respObj, respText) {
|
|||
forceAlmBtn.prop('disabled', true);
|
||||
}
|
||||
enableAlmBtn.prop('disabled', false);
|
||||
} // end if canEditMonitors
|
||||
} // end if canEdit.Monitors
|
||||
|
||||
if ( streamStatus.auth ) {
|
||||
auth_hash = streamStatus.auth;
|
||||
|
@ -296,10 +276,7 @@ function getStreamCmdResponse(respObj, respText) {
|
|||
var newSrc = oldSrc.replace(/auth=\w+/i, 'auth='+streamStatus.auth);
|
||||
streamImg.src = newSrc;
|
||||
}
|
||||
streamCmdParms = streamCmdParms.replace(/auth=\w+/i, 'auth='+streamStatus.auth);
|
||||
statusCmdParms = statusCmdParms.replace(/auth=\w+/i, 'auth='+streamStatus.auth);
|
||||
table.bootstrapTable('refresh');
|
||||
controlParms = controlParms.replace(/auth=\w+/i, 'auth='+streamStatus.auth);
|
||||
} // end if have a new auth hash
|
||||
} // end if respObj.status
|
||||
} else {
|
||||
|
@ -339,7 +316,10 @@ function streamCmdPause( action ) {
|
|||
setButtonState('fastRevBtn', 'inactive');
|
||||
}
|
||||
if ( action ) {
|
||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_PAUSE);
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
data.command = CMD_PAUSE;
|
||||
streamCmdReq(data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -364,10 +344,21 @@ function streamCmdPlay( action ) {
|
|||
}
|
||||
}
|
||||
if ( action ) {
|
||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_PLAY);
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
data.command = CMD_PLAY;
|
||||
streamCmdReq(data);
|
||||
}
|
||||
}
|
||||
|
||||
function streamCmdReq(data) {
|
||||
$j.getJSON(thisUrl + '?view=request&request=stream&connkey='+connKey, data)
|
||||
.done(getStreamCmdResponse)
|
||||
.fail(getStreamCmdError);
|
||||
|
||||
streamCmdTimer = null;
|
||||
}
|
||||
|
||||
function streamCmdStop( action ) {
|
||||
setButtonState('pauseBtn', 'inactive');
|
||||
setButtonState('playBtn', 'unavail');
|
||||
|
@ -379,7 +370,10 @@ function streamCmdStop( action ) {
|
|||
setButtonState('fastRevBtn', 'unavail');
|
||||
}
|
||||
if ( action ) {
|
||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_STOP);
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
data.command = CMD_STOP;
|
||||
streamCmdReq(data);
|
||||
}
|
||||
setButtonState('stopBtn', 'unavail');
|
||||
setButtonState('playBtn', 'active');
|
||||
|
@ -396,7 +390,10 @@ function streamCmdFastFwd( action ) {
|
|||
setButtonState('fastRevBtn', 'inactive');
|
||||
}
|
||||
if ( action ) {
|
||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_FASTFWD);
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
data.command = CMD_FASTFWD;
|
||||
streamCmdReq(data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -411,7 +408,10 @@ function streamCmdSlowFwd( action ) {
|
|||
setButtonState('fastRevBtn', 'inactive');
|
||||
}
|
||||
if ( action ) {
|
||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_SLOWFWD);
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
data.command = CMD_SLOWFWD;
|
||||
streamCmdReq(data);
|
||||
}
|
||||
setButtonState('pauseBtn', 'active');
|
||||
if ( monitorStreamReplayBuffer ) {
|
||||
|
@ -430,7 +430,10 @@ function streamCmdSlowRev( action ) {
|
|||
setButtonState('fastRevBtn', 'inactive');
|
||||
}
|
||||
if ( action ) {
|
||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_SLOWREV);
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
data.command = CMD_SLOWREV;
|
||||
streamCmdReq(data);
|
||||
}
|
||||
setButtonState('pauseBtn', 'active');
|
||||
if ( monitorStreamReplayBuffer ) {
|
||||
|
@ -449,43 +452,51 @@ function streamCmdFastRev( action ) {
|
|||
setButtonState('fastRevBtn', 'inactive');
|
||||
}
|
||||
if ( action ) {
|
||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_FASTREV);
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
data.command = CMD_FASTREV;
|
||||
streamCmdReq(data);
|
||||
}
|
||||
}
|
||||
|
||||
function streamCmdZoomIn( x, y ) {
|
||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_ZOOMIN+"&x="+x+"&y="+y);
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
data.x = x;
|
||||
data.y = y;
|
||||
data.command = CMD_ZOOMIN;
|
||||
streamCmdReq(data);
|
||||
}
|
||||
|
||||
function streamCmdZoomOut() {
|
||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_ZOOMOUT);
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
data.command = CMD_ZOOMOUT;
|
||||
streamCmdReq(data);
|
||||
}
|
||||
|
||||
function streamCmdScale( scale ) {
|
||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_SCALE+"&scale="+scale);
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
data.command = CMD_SCALE;
|
||||
data.scale = scale;
|
||||
streamCmdReq(data);
|
||||
}
|
||||
|
||||
function streamCmdPan( x, y ) {
|
||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_PAN+"&x="+x+"&y="+y);
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
data.x = x;
|
||||
data.y = y;
|
||||
data.command = CMD_PAN;
|
||||
streamCmdReq(data);
|
||||
}
|
||||
|
||||
function streamCmdQuery() {
|
||||
streamCmdReq.send(streamCmdParms+"&command="+CMD_QUERY);
|
||||
}
|
||||
|
||||
if ( monitorType != 'WebSite' ) {
|
||||
var statusCmdParms = "view=request&request=status&entity=monitor&id="+monitorId+"&element[]=Status&element[]=FrameRate";
|
||||
if ( auth_hash ) {
|
||||
statusCmdParms += '&auth='+auth_hash;
|
||||
}
|
||||
var statusCmdReq = new Request.JSON( {
|
||||
url: monitorUrl,
|
||||
method: 'get',
|
||||
timeout: AJAX_TIMEOUT,
|
||||
link: 'cancel',
|
||||
onSuccess: getStatusCmdResponse
|
||||
} );
|
||||
var statusCmdTimer = null;
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
data.command = CMD_QUERY;
|
||||
streamCmdReq(data);
|
||||
}
|
||||
|
||||
function getStatusCmdResponse(respObj, respText) {
|
||||
|
@ -509,23 +520,23 @@ function getStatusCmdResponse(respObj, respText) {
|
|||
}
|
||||
|
||||
function statusCmdQuery() {
|
||||
statusCmdReq.send(statusCmdParms);
|
||||
$j.getJSON(thisUrl + '?view=request&request=status&entity=monitor&element[]=Status&element[]=FrameRate&id='+monitorId)
|
||||
.done(getStatusCmdResponse)
|
||||
.fail(logAjaxFail);
|
||||
|
||||
streamCmdTimer = null;
|
||||
}
|
||||
|
||||
if ( monitorType != 'WebSite' ) {
|
||||
var alarmCmdParms = 'view=request&request=alarm&id='+monitorId;
|
||||
if ( auth_hash ) {
|
||||
alarmCmdParms += '&auth='+auth_hash;
|
||||
}
|
||||
var alarmCmdReq = new Request.JSON( {
|
||||
url: monitorUrl,
|
||||
method: 'get',
|
||||
timeout: AJAX_TIMEOUT,
|
||||
link: 'cancel',
|
||||
onSuccess: getAlarmCmdResponse,
|
||||
onTimeout: streamCmdQuery
|
||||
} );
|
||||
var alarmCmdFirst = true;
|
||||
function alarmCmdReq(data) {
|
||||
$j.getJSON(thisUrl + '?view=request&request=alarm&id='+monitorId, data)
|
||||
.done(getAlarmCmdResponse)
|
||||
.fail(function(jqxhr, textStatus, error) {
|
||||
if (textstatus === "timeout") {
|
||||
streamCmdQuery();
|
||||
} else {
|
||||
logAjaxFail(jqxhr, textStatus, error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getAlarmCmdResponse(respObj, respText) {
|
||||
|
@ -533,11 +544,17 @@ function getAlarmCmdResponse(respObj, respText) {
|
|||
}
|
||||
|
||||
function cmdDisableAlarms() {
|
||||
alarmCmdReq.send(alarmCmdParms+"&command=disableAlarms");
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
data.command = 'disableAlarms';
|
||||
alarmCmdReq(data);
|
||||
}
|
||||
|
||||
function cmdEnableAlarms() {
|
||||
alarmCmdReq.send(alarmCmdParms+"&command=enableAlarms");
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
data.command = 'enableAlarms';
|
||||
alarmCmdReq(data);
|
||||
}
|
||||
|
||||
function cmdAlarm() {
|
||||
|
@ -549,17 +566,19 @@ function cmdAlarm() {
|
|||
}
|
||||
|
||||
function cmdForceAlarm() {
|
||||
alarmCmdReq.send(alarmCmdParms+"&command=forceAlarm");
|
||||
if ( window.event ) {
|
||||
window.event.preventDefault();
|
||||
}
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
data.command = 'forceAlarm';
|
||||
alarmCmdReq(data);
|
||||
if ( window.event ) window.event.preventDefault();
|
||||
}
|
||||
|
||||
function cmdCancelForcedAlarm() {
|
||||
alarmCmdReq.send(alarmCmdParms+"&command=cancelForcedAlarm");
|
||||
if ( window.event ) {
|
||||
window.event.preventDefault();
|
||||
}
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
data.command = 'cancelForcedAlarm';
|
||||
alarmCmdReq(data);
|
||||
if ( window.event ) window.event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -571,18 +590,10 @@ function cmdForce() {
|
|||
}
|
||||
}
|
||||
|
||||
if ( monitorType != 'WebSite' ) {
|
||||
var controlParms = 'view=request&request=control&id='+monitorId;
|
||||
if ( auth_hash ) {
|
||||
controlParms += '&auth='+auth_hash;
|
||||
}
|
||||
var controlReq = new Request.JSON( {
|
||||
url: monitorUrl,
|
||||
method: 'post',
|
||||
timeout: AJAX_TIMEOUT,
|
||||
link: 'cancel',
|
||||
onSuccess: getControlResponse
|
||||
} );
|
||||
function controlReq(data) {
|
||||
$j.getJSON(thisUrl + '?view=request&request=control&id='+monitorId, data)
|
||||
.done(getControlResponse)
|
||||
.fail(logAjaxFail);
|
||||
}
|
||||
|
||||
function getControlResponse(respObj, respText) {
|
||||
|
@ -601,7 +612,8 @@ function controlCmd(event) {
|
|||
xtell = button.getAttribute('data-xtell');
|
||||
ytell = button.getAttribute('data-ytell');
|
||||
|
||||
var locParms = '';
|
||||
var data = {};
|
||||
|
||||
if ( event && (xtell || ytell) ) {
|
||||
var target = event.target;
|
||||
var offset = $j(target).offset();
|
||||
|
@ -618,7 +630,7 @@ function controlCmd(event) {
|
|||
} else if ( xtell == 2 ) {
|
||||
xge = 2*(50 - xge);
|
||||
}
|
||||
locParms += '&xge='+xge;
|
||||
data.xge = xge;
|
||||
}
|
||||
if ( ytell ) {
|
||||
var yge = parseInt((y*100)/height);
|
||||
|
@ -627,28 +639,35 @@ function controlCmd(event) {
|
|||
} else if ( ytell == 2 ) {
|
||||
yge = 2*(50 - yge);
|
||||
}
|
||||
locParms += '&yge='+yge;
|
||||
data.yge = yge;
|
||||
}
|
||||
}
|
||||
controlReq.send(controlParms+"&control="+control+locParms);
|
||||
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
data.control = control;
|
||||
controlReq(data);
|
||||
|
||||
if ( streamMode == 'single' ) {
|
||||
fetchImage.pass($('imageFeed').getElement('img')).delay(1000);
|
||||
setTimeout(fetchImage, 1000, $j('#imageFeed img'));
|
||||
}
|
||||
}
|
||||
|
||||
function controlCmdImage( x, y ) {
|
||||
var imageControlParms = controlParms;
|
||||
imageControlParms += '&scale='+scale;
|
||||
imageControlParms += '&control='+imageControlMode;
|
||||
var data = {};
|
||||
if ( auth_hash ) data.auth = auth_hash;
|
||||
data.scale = scale;
|
||||
data.control = imageControlMode;
|
||||
data.x = x;
|
||||
data.y = y;
|
||||
controlReq(data);
|
||||
|
||||
controlReq.send( imageControlParms+"&x="+x+"&y="+y );
|
||||
if ( streamMode == 'single' ) {
|
||||
fetchImage.pass( $('imageFeed').getElement('img') ).delay( 1000 );
|
||||
setTimeout(fetchImage, 1000, $j('#imageFeed img'));
|
||||
}
|
||||
}
|
||||
|
||||
function fetchImage( streamImage ) {
|
||||
streamImage.src = streamImage.src.replace(/rand=\d+/i, 'rand='+Math.floor((Math.random() * 1000000) ));
|
||||
streamImage.attr('src', streamImage.attr('src').replace(/rand=\d+/i, 'rand='+Math.floor((Math.random() * 1000000) )));
|
||||
}
|
||||
|
||||
function handleClick( event ) {
|
||||
|
@ -772,7 +791,7 @@ function processClicks(event, field, value, row, $element) {
|
|||
// Manage the DELETE CONFIRMATION modal button
|
||||
function manageDelConfirmModalBtns() {
|
||||
document.getElementById("delConfirmBtn").addEventListener("click", function onDelConfirmClick(evt) {
|
||||
if ( ! canEditEvents ) {
|
||||
if ( ! canEdit.Events ) {
|
||||
enoperm();
|
||||
return;
|
||||
}
|
||||
|
@ -795,7 +814,7 @@ function manageDelConfirmModalBtns() {
|
|||
}
|
||||
|
||||
function initPage() {
|
||||
if ( canViewControl ) {
|
||||
if ( canView.Control ) {
|
||||
// Load the PTZ Preset modal into the DOM
|
||||
if ( monitorControllable ) getCtrlPresetModal();
|
||||
// Load the settings modal into the DOM
|
||||
|
@ -805,25 +824,25 @@ function initPage() {
|
|||
if ( monitorType != 'WebSite' ) {
|
||||
if ( streamMode == 'single' ) {
|
||||
statusCmdTimer = statusCmdQuery.delay( (Math.random()+0.1)*statusRefreshTimeout );
|
||||
watchdogCheck.pass('status').periodical(statusRefreshTimeout*2);
|
||||
setInterval(watchdogCheck, statusRefreshTimeout*2, 'status');
|
||||
} else {
|
||||
streamCmdTimer = streamCmdQuery.delay( (Math.random()+0.1)*statusRefreshTimeout );
|
||||
watchdogCheck.pass('stream').periodical(statusRefreshTimeout*2);
|
||||
setInterval(watchdogCheck, statusRefreshTimeout*2, 'stream');
|
||||
}
|
||||
|
||||
if ( canStreamNative || (streamMode == 'single') ) {
|
||||
var streamImg = $('imageFeed').getElement('img');
|
||||
var streamImg = $j('#imageFeed img');
|
||||
if ( !streamImg ) {
|
||||
streamImg = $('imageFeed').getElement('object');
|
||||
streamImg = $j('#imageFeed object');
|
||||
}
|
||||
if ( !streamImg ) {
|
||||
console.error('No streamImg found for imageFeed');
|
||||
} else {
|
||||
if ( streamMode == 'single' ) {
|
||||
streamImg.addEvent('click', fetchImage.pass(streamImg));
|
||||
fetchImage.pass(streamImg).periodical(imageRefreshTimeout);
|
||||
streamImg.click(streamImg, fetchImage);
|
||||
setInterval(fetchImage, imageRefreshTimeout, $j('#imageFeed img'));
|
||||
} else {
|
||||
streamImg.addEvent('click', function(event) {
|
||||
streamImg.click(function(event) {
|
||||
handleClick(event);
|
||||
});
|
||||
}
|
||||
|
@ -866,7 +885,7 @@ function initPage() {
|
|||
});
|
||||
|
||||
// Only enable the settings button for local cameras
|
||||
settingsBtn.prop('disabled', !canViewControl);
|
||||
settingsBtn.prop('disabled', !canView.Control);
|
||||
if ( monitorType != 'Local' ) settingsBtn.hide();
|
||||
|
||||
// Init the bootstrap-table
|
||||
|
|
|
@ -73,9 +73,7 @@ var statusRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_STATUS ?>;
|
|||
var eventsRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_EVENTS ?>;
|
||||
var imageRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_IMAGE ?>;
|
||||
|
||||
var canEditMonitors = <?php echo canEdit( 'Monitors' )?'true':'false' ?>;
|
||||
var canStreamNative = <?php echo canStreamNative()?'true':'false' ?>;
|
||||
var canViewControl = <?php echo canView( 'Control' )?'true':'false' ?>;
|
||||
|
||||
var canPlayPauseAudio = Browser.ie;
|
||||
|
||||
|
|
|
@ -128,7 +128,6 @@ var streamSrc = "<?php echo preg_replace( '/&/', '&', $streamSrc ) ?>";
|
|||
var statusRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_STATUS ?>;
|
||||
var imageRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_IMAGE ?>;
|
||||
|
||||
var canEditMonitors = <?php echo canEdit( 'Monitors' )?'true':'false' ?>;
|
||||
var canStreamNative = <?php echo canStreamNative()?'true':'false' ?>;
|
||||
|
||||
var canPlayPauseAudio = Browser.ie;
|
||||
|
|
|
@ -470,7 +470,7 @@ if ( canEdit('Monitors') ) {
|
|||
<div class="tab-content" id="pills-tabContent">
|
||||
<?php
|
||||
foreach ( $tabs as $name=>$value ) {
|
||||
echo '<div id="pills-'.$name.'" class="tab-pane fade'.($name==$tab ? ' show active' : '').'" role="tabpanel" area-labelledby="'.$name.'-tab">';
|
||||
echo '<div id="pills-'.$name.'" class="tab-pane fade'.($name==$tab ? ' show active' : '').'" role="tabpanel" aria-labelledby="'.$name.'-tab">';
|
||||
?>
|
||||
<table class="major">
|
||||
<tbody>
|
||||
|
@ -502,6 +502,9 @@ switch ( $name ) {
|
|||
<td class="text-right pr-3"><?php echo translate('SourceType') ?></td>
|
||||
<td><?php echo htmlSelect('newMonitor[Type]', $sourceTypes, $monitor->Type()); ?></td>
|
||||
</tr>
|
||||
<?php
|
||||
if ( $monitor->Type() != 'WebSite' ) {
|
||||
?>
|
||||
<tr>
|
||||
<td class="text-right pr-3"><?php echo translate('Function') ?></td>
|
||||
<td>
|
||||
|
@ -512,15 +515,37 @@ switch ( $name ) {
|
|||
}
|
||||
echo htmlSelect('newMonitor[Function]', $function_options, $monitor->Function());
|
||||
?>
|
||||
<div id="function_help">
|
||||
<?php
|
||||
foreach ( ZM\getMonitorFunctionTypes() as $fn => $translated ) {
|
||||
if ( isset($OLANG['FUNCTION_'.strtoupper($fn)]) ) {
|
||||
echo '<div class="form-text" id="'.$fn.'Help">'.$OLANG['FUNCTION_'.strtoupper($fn)]['Help'].'</div>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-right pr-3"><?php echo translate('Enabled') ?></td>
|
||||
<td><input type="checkbox" name="newMonitor[Enabled]" value="1"<?php echo $monitor->Enabled() ? ' checked="checked"' : '' ?>/></td>
|
||||
</tr>
|
||||
<tr id="FunctionEnabled">
|
||||
<td class="text-right pr-3"><?php echo translate('Analysis Enabled') ?></td>
|
||||
<td><input type="checkbox" name="newMonitor[Enabled]" value="1"<?php echo $monitor->Enabled() ? ' checked="checked"' : '' ?>/>
|
||||
<?php
|
||||
if ( $monitor->Type() != 'WebSite' ) {
|
||||
if ( isset($OLANG['FUNCTION_ANALYSIS_ENABLED']) ) {
|
||||
echo '<div class="form-text">'.$OLANG['FUNCTION_ANALYSIS_ENABLED']['Help'].'</div>';
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="FunctionDecodingEnabled">
|
||||
<td class="text-right pr-3"><?php echo translate('Decoding Enabled') ?></td>
|
||||
<td><input type="checkbox" name="newMonitor[DecodingEnabled]" value="1"<?php echo $monitor->DecodingEnabled() ? ' checked="checked"' : '' ?>/>
|
||||
<?php
|
||||
if ( isset($OLANG['FUNCTION_DECODING_ENABLED']) ) {
|
||||
echo '<div class="form-text">'.$OLANG['FUNCTION_DECODING_ENABLED']['Help'].'</div>';
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-right pr-3"><?php echo translate('LinkedMonitors'); echo makeHelpLink('OPTIONS_LINKED_MONITORS') ?></td>
|
||||
<td>
|
||||
|
@ -825,11 +850,14 @@ include('_monitor_source_nvsocket.php');
|
|||
'320x240'=>'320x240',
|
||||
'320x200'=>'320x200',
|
||||
'352x240'=>'352x240 CIF',
|
||||
'352x480'=>'352x480',
|
||||
'640x480'=>'640x480',
|
||||
'640x400'=>'640x400',
|
||||
'704x240'=>'704x240 2CIF',
|
||||
'704x480'=>'704x480 4CIF',
|
||||
'720x480'=>'720x480 D1',
|
||||
'704x576'=>'704x576 D1 PAL',
|
||||
'720x480'=>'720x480 Full D1 NTSC',
|
||||
'720x576'=>'720x576 Full D1 PAL',
|
||||
'1280x720'=>'1280x720 720p',
|
||||
'1280x800'=>'1280x800',
|
||||
'1280x960'=>'1280x960 960p',
|
||||
|
|
Loading…
Reference in New Issue