mirror of
https://github.com/ZoneMinder/zoneminder.git
synced 2026-03-30 03:32:14 -04:00
Merge branch 'master' of github.com:ZoneMinder/zoneminder
This commit is contained in:
@@ -7,7 +7,7 @@ web/js/videojs.zoomrotate.js
|
||||
web/js/fontfaceobserver.standalone.js
|
||||
web/skins/classic/js/bootstrap-4.5.0.js
|
||||
web/skins/classic/js/bootstrap.bundle.min.js
|
||||
web/skins/classic/js/bootstrap-table-1.22.3
|
||||
web/skins/classic/js/bootstrap-table-1.23.3
|
||||
web/skins/classic/js/chosen
|
||||
web/skins/classic/js/dateTimePicker
|
||||
web/skins/classic/js/jquery-*.js
|
||||
@@ -16,7 +16,6 @@ web/skins/classic/js/jquery.js
|
||||
web/skins/classic/js/moment.js
|
||||
web/skins/classic/js/video.js
|
||||
web/skins/classic/assets
|
||||
web/tools/mootools
|
||||
web/js/janus.js
|
||||
web/js/ajaxQueue.js
|
||||
web/js/hls.js
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -199,10 +199,6 @@ web/cmake_install.cmake
|
||||
web/events/
|
||||
web/images/
|
||||
web/includes/config.php
|
||||
web/tools/mootools/CMakeFiles/
|
||||
web/tools/mootools/cmake_install.cmake
|
||||
web/tools/mootools/mootools-core.js
|
||||
web/tools/mootools/mootools-more.js
|
||||
web/undef.log
|
||||
zm.conf
|
||||
zmconfgen.pl
|
||||
|
||||
@@ -289,7 +289,7 @@ bool EventStream::loadEventData(uint64_t event_id) {
|
||||
frame.in_db);
|
||||
} // end foreach db row
|
||||
|
||||
if (event_data->end_time.time_since_epoch() != Seconds(0)) {
|
||||
if (event_data->end_time.time_since_epoch() != Seconds(0) and event_data->duration != Seconds(0)) {
|
||||
Microseconds delta;
|
||||
if (!last_frame) {
|
||||
// There were no frames in db
|
||||
|
||||
@@ -188,7 +188,7 @@ int FfmpegCamera::Capture(std::shared_ptr<ZMPacket> &zm_packet) {
|
||||
start_read_time = std::chrono::steady_clock::now();
|
||||
int ret;
|
||||
AVFormatContext *formatContextPtr;
|
||||
int64_t lastPTS;
|
||||
int64_t lastPTS = -1;
|
||||
|
||||
if ( mSecondFormatContext and
|
||||
(
|
||||
@@ -242,7 +242,7 @@ int FfmpegCamera::Capture(std::shared_ptr<ZMPacket> &zm_packet) {
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if ( packet->stream_index == mAudioStreamId) {
|
||||
if (packet->stream_index == mAudioStreamId) {
|
||||
lastPTS = mLastAudioPTS;
|
||||
} else if ( packet->stream_index == mVideoStreamId) {
|
||||
lastPTS = mLastVideoPTS;
|
||||
@@ -287,7 +287,7 @@ int FfmpegCamera::Capture(std::shared_ptr<ZMPacket> &zm_packet) {
|
||||
mFirstVideoPTS = packet->pts;
|
||||
|
||||
mLastVideoPTS = packet->pts - mFirstVideoPTS;
|
||||
} else {
|
||||
} else if (stream == mAudioStream) {
|
||||
if (mFirstAudioPTS == AV_NOPTS_VALUE)
|
||||
mFirstAudioPTS = packet->pts;
|
||||
|
||||
|
||||
@@ -94,7 +94,6 @@ define('STATE_IDLE', 1);
|
||||
define('STATE_PREALARM', 2);
|
||||
define('STATE_ALARM', 3);
|
||||
define('STATE_ALERT', 4);
|
||||
define('STATE_TAPE', 5);
|
||||
|
||||
//
|
||||
// DVR Control Commands
|
||||
|
||||
@@ -50,7 +50,7 @@ function MonitorStream(monitorData) {
|
||||
};
|
||||
|
||||
this.img_onerror = function() {
|
||||
console.log('Image stream has been stoppd! stopping streamCmd');
|
||||
console.log('Image stream has been stopped! stopping streamCmd');
|
||||
this.streamCmdTimer = clearInterval(this.streamCmdTimer);
|
||||
};
|
||||
this.img_onload = function() {
|
||||
@@ -375,10 +375,21 @@ function MonitorStream(monitorData) {
|
||||
};
|
||||
|
||||
this.pause = function() {
|
||||
this.streamCommand(CMD_PAUSE);
|
||||
if (this.element.src) {
|
||||
this.streamCommand(CMD_PAUSE);
|
||||
} else {
|
||||
this.element.pause();
|
||||
this.statusCmdTimer = clearInterval(this.statusCmdTimer);
|
||||
}
|
||||
};
|
||||
|
||||
this.play = function() {
|
||||
this.streamCommand(CMD_PLAY);
|
||||
if (this.element.src) {
|
||||
this.streamCommand(CMD_PLAY);
|
||||
} else {
|
||||
this.element.play();
|
||||
this.statusCmdTimer = setInterval(this.statusCmdQuery.bind(this), statusRefreshTimeout);
|
||||
}
|
||||
};
|
||||
|
||||
this.eventHandler = function(event) {
|
||||
@@ -681,7 +692,6 @@ function MonitorStream(monitorData) {
|
||||
this.getStatusCmdResponse=function(respObj, respText) {
|
||||
//watchdogOk('status');
|
||||
if (respObj.result == 'Ok') {
|
||||
const monitorStatus = respObj.monitor.Status;
|
||||
const captureFPSValue = $j('#captureFPSValue'+this.id);
|
||||
const analysisFPSValue = $j('#analysisFPSValue'+this.id);
|
||||
const viewingFPSValue = $j('#viewingFPSValue'+this.id);
|
||||
@@ -720,42 +730,45 @@ function MonitorStream(monitorData) {
|
||||
}
|
||||
|
||||
if (canEdit.Monitors) {
|
||||
if (monitorStatus.enabled) {
|
||||
if ('enableAlarmButton' in this.buttons) {
|
||||
if ('enableAlarmButton' in this.buttons) {
|
||||
if (monitor.Analysing == 'None') {
|
||||
// Not doing analysis, so enable/disable button should be grey
|
||||
|
||||
if (!this.buttons.enableAlarmButton.hasClass('disabled')) {
|
||||
this.buttons.enableAlarmButton.addClass('disabled');
|
||||
this.buttons.enableAlarmButton.prop('title', disableAlarmsStr);
|
||||
}
|
||||
}
|
||||
if ('forceAlarmButton' in this.buttons) {
|
||||
if (monitorStatus.forced) {
|
||||
if (!this.buttons.forceAlarmButton.hasClass('disabled')) {
|
||||
this.buttons.forceAlarmButton.addClass('disabled');
|
||||
this.buttons.forceAlarmButton.prop('title', cancelForcedAlarmStr);
|
||||
}
|
||||
} else {
|
||||
if (this.buttons.forceAlarmButton.hasClass('disabled')) {
|
||||
this.buttons.forceAlarmButton.removeClass('disabled');
|
||||
this.buttons.forceAlarmButton.prop('title', forceAlarmStr);
|
||||
}
|
||||
}
|
||||
this.buttons.forceAlarmButton.prop('disabled', false);
|
||||
}
|
||||
} else {
|
||||
if ('enableAlarmButton' in this.buttons) {
|
||||
} else {
|
||||
this.buttons.enableAlarmButton.removeClass('disabled');
|
||||
this.buttons.enableAlarmButton.prop('title', enableAlarmsStr);
|
||||
}
|
||||
if ('forceAlarmButton' in this.buttons) {
|
||||
this.buttons.forceAlarmButton.prop('disabled', true);
|
||||
}
|
||||
}
|
||||
if ('enableAlarmButton' in this.buttons) {
|
||||
} // end if doing analysis
|
||||
this.buttons.enableAlarmButton.prop('disabled', false);
|
||||
} // end if have enableAlarmButton
|
||||
|
||||
if ('forceAlarmButton' in this.buttons) {
|
||||
if (monitor.Status == STATE_ALARM || monitor.Status == STATE_ALERT) {
|
||||
// Ic0n: My thought here is that the non-disabled state should be for killing an alarm
|
||||
// and the disabled state should be to force an alarm
|
||||
if (this.buttons.forceAlarmButton.hasClass('disabled')) {
|
||||
this.buttons.forceAlarmButton.removeClass('disabled');
|
||||
this.buttons.forceAlarmButton.prop('title', cancelForcedAlarmStr);
|
||||
}
|
||||
} else {
|
||||
if (!this.buttons.forceAlarmButton.hasClass('disabled')) {
|
||||
// Looks disabled
|
||||
this.buttons.forceAlarmButton.addClass('disabled');
|
||||
this.buttons.forceAlarmButton.prop('title', forceAlarmStr);
|
||||
}
|
||||
}
|
||||
this.buttons.forceAlarmButton.prop('disabled', false);
|
||||
} else {
|
||||
console.log("No forceAlarmButton");
|
||||
}
|
||||
} else {
|
||||
console.log("Can't edit");
|
||||
} // end if canEdit.Monitors
|
||||
|
||||
this.setAlarmState(monitorStatus);
|
||||
this.setAlarmState(monitor.Status);
|
||||
|
||||
if (respObj.auth_hash) {
|
||||
if (auth_hash != respObj.auth_hash) {
|
||||
@@ -807,7 +820,7 @@ function MonitorStream(monitorData) {
|
||||
|
||||
this.alarmCommand = function(command) {
|
||||
if (this.ajaxQueue) {
|
||||
console.log('Aborting in progress ajax for alarm');
|
||||
console.log('Aborting in progress ajax for alarm', this.ajaxQueue);
|
||||
// Doing this for responsiveness, but we could be aborting something important. Need smarter logic
|
||||
this.ajaxQueue.abort();
|
||||
}
|
||||
|
||||
@@ -1123,6 +1123,20 @@ html::-webkit-scrollbar-thumb, div::-webkit-scrollbar-thumb, nav::-webkit-scroll
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-height:600px) {
|
||||
.sticky #mfbpanel {
|
||||
max-height: 40vh;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.sticky #toolbar {
|
||||
max-height: 20vh;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
/* +++ Control button block in the Stream image*/
|
||||
.block-button-center {
|
||||
position: absolute;
|
||||
|
||||
@@ -107,7 +107,6 @@ const STATE_IDLE = <?php echo STATE_IDLE ?>;
|
||||
const STATE_PREALARM = <?php echo STATE_PREALARM ?>;
|
||||
const STATE_ALARM = <?php echo STATE_ALARM ?>;
|
||||
const STATE_ALERT = <?php echo STATE_ALERT ?>;
|
||||
const STATE_TAPE = <?php echo STATE_TAPE ?>;
|
||||
|
||||
const CMD_ANALYZE_ON = <?php echo CMD_ANALYZE_ON ?>;
|
||||
const CMD_ANALYZE_OFF = <?php echo CMD_ANALYZE_OFF ?>;
|
||||
|
||||
@@ -199,6 +199,7 @@ function renderAlarmCues(containerEl) {
|
||||
// if we shouldn't just use the event length endtime-starttime
|
||||
var cueRatio = containerEl.width() / (event_length * 100);
|
||||
var minAlarm = Math.ceil(1/cueRatio);
|
||||
var spanTime = 0;
|
||||
var spanTimeStart = 0;
|
||||
var spanTimeEnd = 0;
|
||||
var alarmed = 0;
|
||||
@@ -230,8 +231,8 @@ function renderAlarmCues(containerEl) {
|
||||
//console.log(left, frame.Delta, event_length, containerEl.width());
|
||||
spanTimeStart = spanTimeEnd;
|
||||
} else if ( (frame.Type !== 'Alarm') && (alarmed == 1) ) { //from alarm to nothing. End alarm and start nothing.
|
||||
futNone = 0;
|
||||
indexPlus = i+1;
|
||||
let futNone = 0;
|
||||
let indexPlus = i+1;
|
||||
if (((frame.Delta * 100) - spanTimeStart) < minAlarm && indexPlus < num_cueFrames) {
|
||||
//alarm is too short and there is more event
|
||||
continue;
|
||||
@@ -1667,7 +1668,7 @@ function initPage() {
|
||||
mapDiv.style.height='450px';
|
||||
}
|
||||
if ( window.L ) {
|
||||
map = L.map('LocationMap', {
|
||||
const map = L.map('LocationMap', {
|
||||
center: L.latLng(eventData.Latitude, eventData.Longitude),
|
||||
zoom: 8,
|
||||
onclick: function() {
|
||||
|
||||
@@ -148,135 +148,6 @@ function changeStreamQuality() {
|
||||
monitorsSetScale(monitorId);
|
||||
}
|
||||
|
||||
function getStreamCmdResponse(respObj, respText) {
|
||||
watchdogOk('stream');
|
||||
streamCmdTimer = clearTimeout(streamCmdTimer);
|
||||
if (respObj.result == 'Ok') {
|
||||
// The get status command can get backed up, in which case we won't be able to get the semaphore and will exit.
|
||||
if (respObj.status) {
|
||||
const streamStatus = respObj.status;
|
||||
if ($j('#viewingFPSValue').text() != streamStatus.fps) {
|
||||
$j('#viewingFPSValue').text(streamStatus.fps);
|
||||
}
|
||||
if ($j('#captureFPSValue').text() != streamStatus.capturefps) {
|
||||
$j('#captureFPSValue').text(streamStatus.capturefps);
|
||||
}
|
||||
if ($j('#analysisFPSValue').text() != streamStatus.analysisfps) {
|
||||
$j('#analysisFPSValue').text(streamStatus.analysisfps);
|
||||
}
|
||||
|
||||
setAlarmState(streamStatus.state);
|
||||
|
||||
$j('#levelValue').text(streamStatus.level);
|
||||
var newClass = 'ok';
|
||||
if (streamStatus.level > 95) {
|
||||
newClass = 'alarm';
|
||||
} else if (streamStatus.level > 80) {
|
||||
newClass = 'alert';
|
||||
}
|
||||
$j('#levelValue').removeClass();
|
||||
$j('#levelValue').addClass(newClass);
|
||||
|
||||
var delayString = secsToTime(streamStatus.delay);
|
||||
|
||||
if (streamStatus.paused == true) {
|
||||
$j('#modeValue').text('Paused');
|
||||
$j('#rate').addClass('hidden');
|
||||
$j('#delayValue').text(delayString);
|
||||
$j('#delay').removeClass('hidden');
|
||||
$j('#level').removeClass('hidden');
|
||||
streamCmdPause(false);
|
||||
} else if (streamStatus.delayed == true) {
|
||||
$j('#modeValue').text('Replay');
|
||||
$j('#rateValue').text(streamStatus.rate);
|
||||
$j('#rate').removeClass('hidden');
|
||||
$j('#delayValue').text(delayString);
|
||||
$j('#delay').removeClass('hidden');
|
||||
$j('#level').removeClass('hidden');
|
||||
if (streamStatus.rate == 1) {
|
||||
streamCmdPlay(false);
|
||||
} else if (streamStatus.rate > 0) {
|
||||
if (streamStatus.rate < 1) {
|
||||
streamCmdSlowFwd(false);
|
||||
} else {
|
||||
streamCmdFastFwd(false);
|
||||
}
|
||||
} else {
|
||||
if (streamStatus.rate > -1) {
|
||||
streamCmdSlowRev(false);
|
||||
} else {
|
||||
streamCmdFastRev(false);
|
||||
}
|
||||
} // rate
|
||||
} else {
|
||||
$j('#modeValue').text('Live');
|
||||
$j('#rate').addClass('hidden');
|
||||
$j('#delay').addClass('hidden');
|
||||
$j('#level').addClass('hidden');
|
||||
streamCmdPlay(false);
|
||||
} // end if paused or delayed
|
||||
|
||||
$j('#zoomValue').text(streamStatus.zoom);
|
||||
if (streamStatus.zoom == '1.0') {
|
||||
setButtonState('zoomOutBtn', 'unavail');
|
||||
} else {
|
||||
setButtonState('zoomOutBtn', 'inactive');
|
||||
}
|
||||
|
||||
if (canEdit.Monitors) {
|
||||
if (streamStatus.enabled) {
|
||||
enableAlmBtn.addClass('disabled');
|
||||
enableAlmBtn.prop('title', disableAlarmsStr);
|
||||
if (streamStatus.forced) {
|
||||
forceAlmBtn.addClass('disabled');
|
||||
forceAlmBtn.prop('title', cancelForcedAlarmStr);
|
||||
} else {
|
||||
forceAlmBtn.removeClass('disabled');
|
||||
forceAlmBtn.prop('title', forceAlarmStr);
|
||||
}
|
||||
forceAlmBtn.prop('disabled', false);
|
||||
} else {
|
||||
enableAlmBtn.removeClass('disabled');
|
||||
enableAlmBtn.prop('title', enableAlarmsStr);
|
||||
forceAlmBtn.prop('disabled', true);
|
||||
}
|
||||
enableAlmBtn.prop('disabled', false);
|
||||
} // end if canEdit.Monitors
|
||||
|
||||
if (streamStatus.auth) {
|
||||
auth_hash = streamStatus.auth;
|
||||
// Try to reload the image stream.
|
||||
var streamImg = $j('#liveStream'+monitorId);
|
||||
if (streamImg) {
|
||||
const oldSrc = streamImg.attr('src');
|
||||
if (oldSrc) {
|
||||
const newSrc = oldSrc.replace(/auth=\w+/i, 'auth='+streamStatus.auth);
|
||||
if (oldSrc != newSrc) {
|
||||
streamImg.attr('src', ''); // Required or chrome doesn't stop the stream
|
||||
streamImg.attr('src', newSrc);
|
||||
table.bootstrapTable('refresh');
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end if have a new auth hash
|
||||
} // end if respObj.status
|
||||
} else {
|
||||
console.log("Not ok");
|
||||
checkStreamForErrors('getStreamCmdResponse', respObj);//log them
|
||||
setTimeout(fetchImage, 1000, $j('#imageFeed img')[0]);
|
||||
}
|
||||
|
||||
var streamCmdTimeout = statusRefreshTimeout;
|
||||
if (alarmState == STATE_ALARM || alarmState == STATE_ALERT) {
|
||||
streamCmdTimeout = streamCmdTimeout/5;
|
||||
}
|
||||
streamCmdTimer = setTimeout(streamCmdQuery, streamCmdTimeout);
|
||||
}
|
||||
|
||||
function streamCmdQuery() {
|
||||
streamCmdReq({command: CMD_QUERY});
|
||||
}
|
||||
|
||||
function onPause() {
|
||||
setButtonState('pauseBtn', 'active');
|
||||
setButtonState('playBtn', 'inactive');
|
||||
@@ -292,7 +163,7 @@ function onPause() {
|
||||
function streamCmdPause(action) {
|
||||
onPause();
|
||||
if (action) {
|
||||
monitorStream.streamCommand(CMD_PAUSE);
|
||||
monitorStream.pause();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,7 +198,7 @@ function streamCmdPlay(action) {
|
||||
if (action) {
|
||||
if (monitorStream.started) {
|
||||
//Stream was on pause
|
||||
monitorStream.streamCommand(CMD_PLAY);
|
||||
monitorStream.play();
|
||||
} else {
|
||||
//Stream has been stopped
|
||||
monitorStream.start();
|
||||
@@ -383,7 +254,7 @@ function streamCmdSlowFwd(action) {
|
||||
setButtonState('fastRevBtn', 'inactive');
|
||||
}
|
||||
if (action) {
|
||||
monitorStream.command(CMD_SLOWFWD);
|
||||
monitorStream.streamCommand(CMD_SLOWFWD);
|
||||
}
|
||||
setButtonState('pauseBtn', 'active');
|
||||
if (monitorStreamReplayBuffer) {
|
||||
@@ -402,7 +273,7 @@ function streamCmdSlowRev(action) {
|
||||
setButtonState('fastRevBtn', 'inactive');
|
||||
}
|
||||
if (action) {
|
||||
monitorStream.command(CMD_SLOWREV);
|
||||
monitorStream.streamCommand(CMD_SLOWREV);
|
||||
}
|
||||
setButtonState('pauseBtn', 'active');
|
||||
if (monitorStreamReplayBuffer) {
|
||||
@@ -421,7 +292,7 @@ function streamCmdFastRev(action) {
|
||||
setButtonState('fastRevBtn', 'inactive');
|
||||
}
|
||||
if (action) {
|
||||
monitorStream.command(CMD_FASTREV);
|
||||
monitorStream.streamCommand(CMD_FASTREV);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -502,9 +373,9 @@ function cmdCancelForcedAlarm() {
|
||||
|
||||
function cmdForce() {
|
||||
if (forceAlmBtn.hasClass('disabled')) {
|
||||
cmdCancelForcedAlarm();
|
||||
} else {
|
||||
cmdForceAlarm();
|
||||
} else {
|
||||
cmdCancelForcedAlarm();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -753,31 +624,6 @@ function zoomOutClick(event) {
|
||||
}
|
||||
}
|
||||
|
||||
var watchdogInactive = {
|
||||
'stream': false,
|
||||
'status': false
|
||||
};
|
||||
|
||||
var watchdogFunctions = {
|
||||
'stream': streamCmdQuery,
|
||||
'status': statusCmdQuery,
|
||||
};
|
||||
|
||||
//Make sure the various refreshes are still taking effect
|
||||
function watchdogCheck(type) {
|
||||
if (watchdogInactive[type]) {
|
||||
console.log("Detected streamWatch of type: " + type + " stopped, restarting");
|
||||
watchdogFunctions[type]();
|
||||
watchdogInactive[type] = false;
|
||||
} else {
|
||||
watchdogInactive[type] = true;
|
||||
}
|
||||
}
|
||||
|
||||
function watchdogOk(type) {
|
||||
watchdogInactive[type] = false;
|
||||
}
|
||||
|
||||
function reloadWebSite() {
|
||||
document.getElementById('imageFeed').innerHTML = document.getElementById('imageFeed').innerHTML;
|
||||
}
|
||||
@@ -949,7 +795,7 @@ function streamPrepareStart(monitor=null) {
|
||||
|
||||
// Update table links each time after new data is loaded
|
||||
table.on('post-body.bs.table', function(data) {
|
||||
var thumb_ndx = $j('#eventList tr th').filter(function() {
|
||||
const thumb_ndx = $j('#eventList tr th').filter(function() {
|
||||
return $j(this).text().trim() == 'Thumbnail';
|
||||
}).index();
|
||||
table.find("tr td:nth-child(" + (thumb_ndx+1) + ")").addClass('colThumbnail');
|
||||
@@ -993,11 +839,7 @@ function handleMouseLeave(event) {
|
||||
}
|
||||
|
||||
function streamStart(monitor = null) {
|
||||
if (monitor) {
|
||||
monitorStream = new MonitorStream(monitor);
|
||||
} else {
|
||||
monitorStream = new MonitorStream(monitorData[monIdx]);
|
||||
}
|
||||
monitorStream = new MonitorStream(monitor ? monitor : monitorData[monIdx]);
|
||||
monitorStream.setBottomElement(document.getElementById('dvrControls'));
|
||||
// Start the fps and status updates. give a random delay so that we don't assault the server
|
||||
//monitorStream.setScale($j('#scale').val(), $j('#width').val(), $j('#height').val());
|
||||
@@ -1027,15 +869,17 @@ function streamStart(monitor = null) {
|
||||
}
|
||||
|
||||
function streamReStart(oldId, newId) {
|
||||
document.getElementById('monitor').classList.add('hidden-shift');
|
||||
const el = document.querySelector('.imageFeed');
|
||||
const newMonitorName = document.getElementById('nav-item-cycle'+newId).querySelector('a').textContent;
|
||||
const monitor_div = document.getElementById('monitor');
|
||||
monitor_div.classList.add('hidden-shift');
|
||||
|
||||
currentMonitor = monitorData.find((o) => {
|
||||
return parseInt(o["id"]) === newId;
|
||||
});
|
||||
const url = new URL(document.location.href);
|
||||
monitorId = newId;
|
||||
filterQuery = '&filter[Query][terms][0][attr]=MonitorId&filter[Query][terms][0][op]=%3d&filter[Query][terms][0][val]='+monitorId;
|
||||
|
||||
const newMonitorName = document.getElementById('nav-item-cycle'+newId).querySelector('a').textContent;
|
||||
document.querySelector('title').textContent = newMonitorName;
|
||||
url.searchParams.set('mid', monitorId);
|
||||
history.pushState(null, "", url);
|
||||
@@ -1044,11 +888,13 @@ function streamReStart(oldId, newId) {
|
||||
if (monitorStream) {
|
||||
monitorStream.kill();
|
||||
}
|
||||
|
||||
const el = document.querySelector('.imageFeed');
|
||||
el.removeEventListener('mouseenter', handleMouseEnter);
|
||||
el.removeEventListener('mouseleave', handleMouseLeave);
|
||||
|
||||
//Change main monitor block
|
||||
document.getElementById('monitor').innerHTML = currentMonitor.streamHTML;
|
||||
monitor_div.innerHTML = currentMonitor.streamHTML;
|
||||
|
||||
//Change active element of the navigation menu
|
||||
document.getElementById('nav-item-cycle'+oldId).querySelector('a').classList.remove("active");
|
||||
@@ -1154,7 +1000,7 @@ function initPage() {
|
||||
bindButton('#cyclePrevBtn', 'click', null, cyclePrev);
|
||||
bindButton('#cycleToggle', 'click', null, cycleToggle);
|
||||
bindButton('#cyclePeriod', 'change', null, cyclePeriodChange);
|
||||
if (monitorData.length && cycle) {
|
||||
if (monitorData.length > 1 && cycle) {
|
||||
cycleStart();
|
||||
} else {
|
||||
cyclePause();
|
||||
@@ -1170,6 +1016,8 @@ function initPage() {
|
||||
setInterval(function() {
|
||||
if (idle >= ZM_WEB_VIEWING_TIMEOUT) {
|
||||
streamCmdPause(true);
|
||||
const cycle_was = cycle;
|
||||
cyclePause();
|
||||
let ayswModal = $j('#AYSWModal');
|
||||
if (!ayswModal.length) {
|
||||
$j.getJSON('?request=modal&modal=areyoustillwatching')
|
||||
@@ -1177,6 +1025,7 @@ function initPage() {
|
||||
ayswModal = insertModalHtml('AYSWModal', data.html);
|
||||
$j('#AYSWYesBtn').on('click', function() {
|
||||
streamCmdPlay(true);
|
||||
if (cycle_was) cycleStart();
|
||||
idle = 0;
|
||||
});
|
||||
ayswModal.modal('show');
|
||||
@@ -1192,6 +1041,7 @@ function initPage() {
|
||||
setInterval(() => {
|
||||
//Updating Scale. When quickly scrolling the mouse wheel or quickly pressing Zoom In/Out, you should not set Scale very often.
|
||||
if (updateScale) {
|
||||
console.log('set scale for ', monitorId);
|
||||
monitorsSetScale(monitorId);
|
||||
updateScale = false;
|
||||
}
|
||||
@@ -1210,13 +1060,11 @@ function initPage() {
|
||||
if (currentMonitor) {
|
||||
applyMonitorControllable();
|
||||
}
|
||||
streamPrepareStart();
|
||||
streamPrepareStart(currentMonitor);
|
||||
|
||||
// Creating a ResizeObserver Instance
|
||||
observer = new ResizeObserver((objResizes) => {
|
||||
objResizes.forEach((obj) => {
|
||||
monitorsSetScale(monitorId);
|
||||
});
|
||||
updateScale = true;
|
||||
});
|
||||
|
||||
// Registering an observer on an element
|
||||
@@ -1284,6 +1132,7 @@ function cycleStop(target) {
|
||||
cyclePause();
|
||||
}
|
||||
|
||||
// FIXME this runs within the interval handler and can take >50ms which will cause chrome to complain.
|
||||
function cycleNext() {
|
||||
monIdx ++;
|
||||
if (monIdx >= monitorData.length) {
|
||||
@@ -1293,18 +1142,12 @@ function cycleNext() {
|
||||
console.log('No monitorData for ' + monIdx);
|
||||
}
|
||||
clearInterval(intervalId);
|
||||
monitorStream.kill();
|
||||
|
||||
// +++ Start next monitor
|
||||
let oldId;
|
||||
if (monIdx == 0) {
|
||||
oldId = monitorData[monitorData.length-1].id;
|
||||
} else {
|
||||
oldId = monitorData[monIdx-1].id;
|
||||
}
|
||||
const oldId = monitorData[(monIdx == 0) ? monitorData.length-1 : monIdx-1].id;
|
||||
const newId = monitorData[monIdx].id;
|
||||
streamReStart(oldId, newId);
|
||||
cycleStart();
|
||||
if (cycle) cycleStart();
|
||||
// --- Start next monitor
|
||||
//window.location.replace('?view=watch&cycle='+cycle+'&mid='+monitorData[monIdx].id+'&mode='+mode);
|
||||
}
|
||||
@@ -1318,19 +1161,12 @@ function cyclePrev() {
|
||||
console.log('No monitorData for ' + monIdx);
|
||||
}
|
||||
clearInterval(intervalId);
|
||||
//monitorStream.stop();
|
||||
monitorStream.kill();
|
||||
|
||||
// +++ Start previous monitor
|
||||
let oldId;
|
||||
if (monIdx == monitorData.length - 1) {
|
||||
oldId = monitorData[0].id;
|
||||
} else {
|
||||
oldId = monitorData[monIdx+1].id;
|
||||
}
|
||||
const oldId = monitorData[(monIdx == monitorData.length - 1)? 0 : monIdx+1].id;
|
||||
const newId = monitorData[monIdx].id;
|
||||
streamReStart(oldId, newId);
|
||||
cycleStart();
|
||||
if (cycle) cycleStart();
|
||||
// --- Start previous monitors
|
||||
//window.location.replace('?view=watch&cycle='+cycle+'&mid='+monitorData[monIdx].id+'&mode='+mode);
|
||||
}
|
||||
@@ -1512,21 +1348,23 @@ function monitorsSetScale(id=null) {
|
||||
overrideHW = true;
|
||||
}
|
||||
|
||||
const monitor_div = document.getElementById('monitor'+id);
|
||||
if (!monitor_div) console.log("No monitor div for ", id);
|
||||
if (resize) {
|
||||
if (scale == '0') {
|
||||
document.getElementById('monitor'+id).style.width = 'max-content'; //Required when switching from resize=false to resize=true
|
||||
monitor_div.style.width = 'max-content'; //Required when switching from resize=false to resize=true
|
||||
}
|
||||
document.getElementById('monitor'+id).style.maxWidth = maxWidth;
|
||||
monitor_div.style.maxWidth = maxWidth;
|
||||
if (!landscape) { //PORTRAIT
|
||||
document.getElementById('monitor'+id).style.width = 'max-content';
|
||||
monitor_div.style.width = 'max-content';
|
||||
document.getElementById('liveStream'+id).style.height = height;
|
||||
}
|
||||
} else {
|
||||
document.getElementById('liveStream'+id).style.height = '';
|
||||
document.getElementById('monitor'+id).style.width = width;
|
||||
document.getElementById('monitor'+id).style.maxWidth = '';
|
||||
monitor_div.style.width = width;
|
||||
monitor_div.style.maxWidth = '';
|
||||
if (scale == 'fit_to_width') {
|
||||
document.getElementById('monitor'+id).style.width = '';
|
||||
monitor_div.style.width = '';
|
||||
} else if (scale == '100') {
|
||||
document.getElementById('liveStream'+id).style.width = width;
|
||||
}
|
||||
@@ -1535,10 +1373,10 @@ function monitorsSetScale(id=null) {
|
||||
curentMonitor.setScale(defScale, width, height, {resizeImg: resize, scaleImg: panZoomScale, streamQuality: $j('#streamQuality').val()});
|
||||
if (overrideHW) {
|
||||
if (!landscape) { //PORTRAIT
|
||||
document.getElementById('monitor'+id).style.width = 'max-content';
|
||||
monitor_div.style.width = 'max-content';
|
||||
} else {
|
||||
document.getElementById('liveStream'+id).style.height = 'auto';
|
||||
document.getElementById('monitor'+id).style.width = 'auto';
|
||||
monitor_div.style.width = 'auto';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -1574,20 +1412,20 @@ function monitorsSetScale(id=null) {
|
||||
}
|
||||
|
||||
if (resize) {
|
||||
document.getElementById('monitor'+id).style.width = 'max-content'; //Required when switching from resize=false to resize=true
|
||||
monitor_div.style.width = 'max-content'; //Required when switching from resize=false to resize=true
|
||||
}
|
||||
//monitors[i].setScale(0, parseInt(el.clientWidth * panZoomScale) + 'px', parseInt(el.clientHeight * panZoomScale) + 'px', {resizeImg:true, scaleImg:panZoomScale});
|
||||
monitors[i].setScale(0, width, height, {resizeImg: resize, scaleImg: panZoomScale});
|
||||
if (!resize) {
|
||||
document.getElementById('liveStream'+id).style.height = '';
|
||||
if (scale == 'fit_to_width') {
|
||||
document.getElementById('monitor'+id).style.width = '';
|
||||
monitor_div.style.width = '';
|
||||
} else if (scale == '100') {
|
||||
document.getElementById('monitor'+id).style.width = 'max-content';
|
||||
monitor_div.style.width = 'max-content';
|
||||
document.getElementById('liveStream'+id).style.width = width;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end foreach monitor
|
||||
}
|
||||
setButtonSizeOnStream();
|
||||
}
|
||||
@@ -1606,7 +1444,7 @@ document.onvisibilitychange = () => {
|
||||
}, 15*1000);
|
||||
} else {
|
||||
//Start monitor when show page
|
||||
if (monitorStream && !monitorStream.started) {
|
||||
if (monitorStream && !monitorStream.started && (idle<ZM_WEB_VIEWING_TIMEOUT)) {
|
||||
monitorStream.start();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user