Merge branch 'master' into rtsp_server
This commit is contained in:
commit
99e7ae3505
|
@ -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
|
||||
|
|
|
@ -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`, "
|
||||
|
@ -272,6 +272,7 @@ Monitor::Monitor()
|
|||
type(LOCAL),
|
||||
function(NONE),
|
||||
enabled(0),
|
||||
decoding_enabled(0),
|
||||
//protocol
|
||||
//method
|
||||
//options
|
||||
|
@ -362,7 +363,7 @@ Monitor::Monitor()
|
|||
|
||||
/*
|
||||
std::string load_monitor_sql =
|
||||
"SELECT Id, Name, ServerId, StorageId, Type, Function+0, Enabled, LinkedMonitors, "
|
||||
"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, RTSPDescribe, "
|
||||
|
@ -409,6 +410,7 @@ void Monitor::Load(MYSQL_ROW dbrow, bool load_zones=true, Purpose p = QUERY) {
|
|||
col++;
|
||||
function = (Function)atoi(dbrow[col]); col++;
|
||||
enabled = dbrow[col] ? atoi(dbrow[col]) : 0; col++;
|
||||
decoding_enabled = dbrow[col] ? atoi(dbrow[col]) : 0; col++;
|
||||
|
||||
ReloadLinkedMonitors(dbrow[col]); col++;
|
||||
|
||||
|
@ -596,6 +598,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));
|
||||
}
|
||||
|
||||
// Do this here to save a few cycles with all the comparisons
|
||||
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 ) {
|
||||
// FIXME Now that zma is a thread, this might not get called. Unless maybe we are redoing motion detection in a separate program.
|
||||
while (
|
||||
|
@ -2160,7 +2174,7 @@ void Monitor::ReloadZones() {
|
|||
void Monitor::ReloadLinkedMonitors(const char *p_linked_monitors) {
|
||||
Debug(1, "Reloading linked monitors for monitor %s, '%s'", name, p_linked_monitors);
|
||||
if ( n_linked_monitors ) {
|
||||
for( int i=0; i < n_linked_monitors; i++ ) {
|
||||
for ( int i=0; i < n_linked_monitors; i++ ) {
|
||||
delete linked_monitors[i];
|
||||
}
|
||||
delete[] linked_monitors;
|
||||
|
@ -2489,7 +2503,6 @@ int Monitor::Capture() {
|
|||
}
|
||||
|
||||
shared_data->signal = signal_check_points ? CheckSignal(capture_image) : true;
|
||||
Debug(1, "signal check points? %d", signal_check_points);
|
||||
shared_data->last_write_index = index;
|
||||
shared_data->last_write_time = image_buffer[index].timestamp->tv_sec;
|
||||
image_count++;
|
||||
|
@ -2826,9 +2839,12 @@ int Monitor::PrimeCapture() {
|
|||
video_stream_id = camera->get_VideoStreamId();
|
||||
audio_stream_id = camera->get_AudioStreamId();
|
||||
packetqueue = new zm_packetqueue(image_buffer_count, video_stream_id, audio_stream_id);
|
||||
}
|
||||
Debug(2, "Video stream id is %d, audio is %d, minimum_packets to keep in buffer %d",
|
||||
video_stream_id, audio_stream_id, pre_event_buffer_count);
|
||||
} else {
|
||||
Debug(2, "Not Video stream id is %d, audio is %d, minimum_packets to keep in buffer %d",
|
||||
video_stream_id, audio_stream_id, pre_event_buffer_count);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2839,6 +2855,7 @@ int Monitor::Close() {
|
|||
delete packetqueue;
|
||||
packetqueue = nullptr;
|
||||
}
|
||||
Debug(1, "Closing camera");
|
||||
return camera->Close();
|
||||
};
|
||||
Monitor::Orientation Monitor::getOrientation() const { return orientation; }
|
||||
|
|
|
@ -245,6 +245,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 ) {
|
||||
|
|
|
@ -48,14 +48,21 @@ zm_packetqueue::~zm_packetqueue() {
|
|||
}
|
||||
|
||||
while ( !pktQueue.empty() ) {
|
||||
Debug(1, "Fronting packet %d", pktQueue.empty());
|
||||
ZMPacket * packet = pktQueue.front();
|
||||
Debug(1, "poppng packet %d", packet->image_index);
|
||||
pktQueue.pop_front();
|
||||
if ( packet->image_index == -1 ) {
|
||||
Debug(1, "Deletng packet");
|
||||
delete packet;
|
||||
}
|
||||
}
|
||||
|
||||
delete[] packet_counts;
|
||||
Debug(1, "Done in destrcutor");
|
||||
packet_counts = nullptr;
|
||||
mutex.unlock();
|
||||
condition.notify_all();
|
||||
}
|
||||
|
||||
/* Enqueues the given packet. Will maintain the analysis_it pointer and image packet counts.
|
||||
|
@ -351,10 +358,13 @@ ZMPacket *zm_packetqueue::get_analysis_packet() {
|
|||
Debug(1, "Locking in get_analysis_packet");
|
||||
std::unique_lock<std::mutex> lck(mutex);
|
||||
|
||||
while ( ((! pktQueue.size()) || ( analysis_it == pktQueue.end() )) && !zm_terminate ) {
|
||||
while ( ((! pktQueue.size()) or ( analysis_it == pktQueue.end() )) and !zm_terminate and !deleting ) {
|
||||
Debug(2, "waiting. Queue size %d analysis_it == end? %d", pktQueue.size(), ( analysis_it == pktQueue.end() ) );
|
||||
condition.wait(lck);
|
||||
}
|
||||
if ( deleting ) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//Debug(2, "Distance from head: (%d)", std::distance( pktQueue.begin(), analysis_it ) );
|
||||
//Debug(2, "Distance from end: (%d)", std::distance( analysis_it, pktQueue.end() ) );
|
||||
|
@ -364,6 +374,7 @@ ZMPacket *zm_packetqueue::get_analysis_packet() {
|
|||
Debug(2,"waiting. Queue size %d analysis_it == end? %d", pktQueue.size(), ( analysis_it == pktQueue.end() ) );
|
||||
condition.wait(lck);
|
||||
if ( deleting ) {
|
||||
Debug(1, "deleting");
|
||||
// packetqueue is being deleted, do not assume we have a lock on the packet
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -553,8 +553,8 @@ int ParseEncoderParameters(
|
|||
}
|
||||
|
||||
valueoffset = line.find('=');
|
||||
if ( valueoffset == std::string::npos || valueoffset+1 >= line.length() || valueoffset == 0 ) {
|
||||
Warning("Failed parsing encoder parameters line %d: Invalid pair", lineno);
|
||||
if ( valueoffset == std::string::npos || (valueoffset+1 >= line.length()) || (valueoffset == 0) ) {
|
||||
Warning("Failed parsing encoder parameters line %d %s: Invalid pair", lineno, line.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -319,14 +319,10 @@ int main(int argc, char *argv[]) {
|
|||
if ( monitors[i]->PreCapture() < 0 ) {
|
||||
Error("Failed to pre-capture monitor %d %d (%d/%d)",
|
||||
monitors[i]->Id(), monitors[i]->Name(), i+1, n_monitors);
|
||||
monitors[i]->Close();
|
||||
result = -1;
|
||||
break;
|
||||
}
|
||||
if ( monitors[i]->Capture() < 0 ) {
|
||||
Error("Failed to capture image from monitor %d %s (%d/%d)",
|
||||
monitors[i]->Id(), monitors[i]->Name(), i+1, n_monitors);
|
||||
monitors[i]->Close();
|
||||
Error("Failed to capture image from monitor %d %s (%d/%d)",
|
||||
monitors[i]->Id(), monitors[i]->Name(), i+1, n_monitors);
|
||||
result = -1;
|
||||
|
@ -335,7 +331,6 @@ int main(int argc, char *argv[]) {
|
|||
if ( monitors[i]->PostCapture() < 0 ) {
|
||||
Error("Failed to post-capture monitor %d %s (%d/%d)",
|
||||
monitors[i]->Id(), monitors[i]->Name(), i+1, n_monitors);
|
||||
monitors[i]->Close();
|
||||
result = -1;
|
||||
break;
|
||||
}
|
||||
|
@ -383,6 +378,9 @@ int main(int argc, char *argv[]) {
|
|||
zm_reload = false;
|
||||
} // end if zm_reload
|
||||
} // end while ! zm_terminate and connected
|
||||
for ( int i = 0; i < n_monitors; i++ ) {
|
||||
monitors[i]->Close();
|
||||
}
|
||||
|
||||
delete [] alarm_capture_delays;
|
||||
delete [] capture_delays;
|
||||
|
@ -398,6 +396,7 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
} // end foreach monitor
|
||||
delete [] analysis_threads;
|
||||
|
||||
} // end while ! zm_terminate outer connection loop
|
||||
Debug(1,"Updating Monitor status");
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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' ?>;
|
||||
|
||||
|
|
|
@ -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']);
|
||||
|
|
|
@ -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...
|
||||
|
@ -1045,7 +1045,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;
|
||||
}
|
||||
|
@ -1134,13 +1134,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 +1183,7 @@ function initPage() {
|
|||
|
||||
// Manage the UNARCHIVE button
|
||||
document.getElementById("unarchiveBtn").addEventListener("click", function onUnarchiveClick(evt) {
|
||||
if ( ! canEditEvents ) {
|
||||
if ( ! canEdit.Events ) {
|
||||
enoperm();
|
||||
return;
|
||||
}
|
||||
|
@ -1198,7 +1198,7 @@ function initPage() {
|
|||
|
||||
// Manage the EDIT button
|
||||
document.getElementById("editBtn").addEventListener("click", function onEditClick(evt) {
|
||||
if ( ! canEditEvents ) {
|
||||
if ( ! canEdit.Events ) {
|
||||
enoperm();
|
||||
return;
|
||||
}
|
||||
|
@ -1253,7 +1253,7 @@ function initPage() {
|
|||
|
||||
// Manage the DELETE button
|
||||
document.getElementById("deleteBtn").addEventListener("click", function onDeleteClick(evt) {
|
||||
if ( ! canEditEvents ) {
|
||||
if ( ! canEdit.Events ) {
|
||||
enoperm();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -63,7 +63,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();
|
||||
|
|
|
@ -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 ) {
|
||||
|
@ -269,7 +249,7 @@ function getStreamCmdResponse(respObj, respText) {
|
|||
setButtonState('zoomOutBtn', 'inactive');
|
||||
}
|
||||
|
||||
if ( canEditMonitors ) {
|
||||
if ( canEdit.Monitors ) {
|
||||
if ( streamStatus.enabled ) {
|
||||
enableAlmBtn.addClass('disabled');
|
||||
enableAlmBtn.prop('title', disableAlarmsStr);
|
||||
|
@ -287,7 +267,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;
|
||||
|
@ -298,10 +278,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 {
|
||||
|
@ -341,7 +318,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -366,10 +346,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');
|
||||
|
@ -381,7 +372,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');
|
||||
|
@ -398,7 +392,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -413,7 +410,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 ) {
|
||||
|
@ -432,7 +432,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 ) {
|
||||
|
@ -451,43 +454,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) {
|
||||
|
@ -511,23 +522,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;
|
||||
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);
|
||||
}
|
||||
var alarmCmdReq = new Request.JSON( {
|
||||
url: monitorUrl,
|
||||
method: 'get',
|
||||
timeout: AJAX_TIMEOUT,
|
||||
link: 'cancel',
|
||||
onSuccess: getAlarmCmdResponse,
|
||||
onTimeout: streamCmdQuery
|
||||
} );
|
||||
var alarmCmdFirst = true;
|
||||
});
|
||||
}
|
||||
|
||||
function getAlarmCmdResponse(respObj, respText) {
|
||||
|
@ -535,11 +546,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() {
|
||||
|
@ -551,17 +568,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;
|
||||
}
|
||||
|
||||
|
@ -573,18 +592,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) {
|
||||
|
@ -603,7 +614,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();
|
||||
|
@ -620,7 +632,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);
|
||||
|
@ -629,28 +641,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 ) {
|
||||
|
@ -774,7 +793,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;
|
||||
}
|
||||
|
@ -797,7 +816,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
|
||||
|
@ -807,25 +826,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);
|
||||
});
|
||||
}
|
||||
|
@ -868,7 +887,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>
|
||||
|
|
Loading…
Reference in New Issue