mirror of
https://github.com/ZoneMinder/zoneminder.git
synced 2026-04-04 14:04:17 -04:00
Merge pull request #4062 from IgorA100/patch-135
When viewing in a cycle, move to the next stream without reloading Watch page
This commit is contained in:
@@ -495,7 +495,7 @@ public static function getStatuses() {
|
||||
unset($args['zones']);
|
||||
|
||||
$streamSrc .= '?'.http_build_query($args, '', $querySep);
|
||||
|
||||
$this->streamSrc = $streamSrc;
|
||||
return $streamSrc;
|
||||
} // end function getStreamSrc
|
||||
|
||||
|
||||
@@ -469,18 +469,6 @@ body.sticky #content {
|
||||
* Generic useful classes, especially with mootools
|
||||
*/
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.hidden-shift {
|
||||
position: absolute !important; left: -999em !important;
|
||||
}
|
||||
|
||||
.invisible {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
@@ -1129,3 +1117,18 @@ html::-webkit-scrollbar-thumb, div::-webkit-scrollbar-thumb, nav::-webkit-scroll
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
/* +++ This block should always be located at the end! */
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.hidden-shift {
|
||||
position: absolute !important; left: -999em !important;
|
||||
}
|
||||
|
||||
.invisible {
|
||||
visibility: hidden;
|
||||
}
|
||||
/* --- This block should always be located at the end! */
|
||||
|
||||
|
||||
@@ -1152,9 +1152,13 @@ function stringToNumber(str) {
|
||||
return parseInt(str.replace(/\D/g, ''));
|
||||
}
|
||||
|
||||
const font = new FontFaceObserver('Material Icons', {weight: 400});
|
||||
font.load().then(function() {
|
||||
$j('.material-icons').css('display', 'inline-block');
|
||||
}, function() {
|
||||
$j('.material-icons').css('display', 'inline-block');
|
||||
});
|
||||
function loadFontFaceObserver() {
|
||||
const font = new FontFaceObserver('Material Icons', {weight: 400});
|
||||
font.load().then(function() {
|
||||
$j('.material-icons').css('display', 'inline-block');
|
||||
}, function() {
|
||||
$j('.material-icons').css('display', 'inline-block');
|
||||
});
|
||||
}
|
||||
|
||||
loadFontFaceObserver();
|
||||
|
||||
@@ -8,6 +8,7 @@ var sidebarControls = $j('#ptzControls');
|
||||
var wrapperMonitor = $j('#wrapperMonitor');
|
||||
var filterQuery = '&filter[Query][terms][0][attr]=MonitorId&filter[Query][terms][0][op]=%3d&filter[Query][terms][0][val]='+monitorId;
|
||||
var idle = 0;
|
||||
var monitorStream = false; /* Stream is not started */
|
||||
|
||||
var classSidebarL = 'col-sm-3'; /* id="sidebar" */
|
||||
var classSidebarR = 'col-sm-2'; /* id="ptzControls" */
|
||||
@@ -132,36 +133,11 @@ function showPtzControls() {
|
||||
showMode = 'control';
|
||||
}
|
||||
|
||||
function changeSize() {
|
||||
var width = $j('#width').val();
|
||||
var height = $j('#height').val();
|
||||
|
||||
//monitorStream.setScale('0', width, height);
|
||||
monitorsSetScale(monitorId);
|
||||
//$j('#scale').val('0');
|
||||
$j('#sidebar ul').height($j('#wrapperMonitor').height()-$j('#cycleButtons').height());
|
||||
|
||||
//setCookie('zmWatchScale', '0');
|
||||
setCookie('zmWatchWidth', width);
|
||||
setCookie('zmWatchHeight', height);
|
||||
} // end function changeSize()
|
||||
|
||||
function changeScale() {
|
||||
const scale = $j('#scale').val();
|
||||
setCookie('zmWatchScaleNew'+monitorId, scale);
|
||||
setCookie('zmCycleScale', scale);
|
||||
monitorsSetScale(monitorId);
|
||||
/*
|
||||
const scale = $j('#scale').val();
|
||||
setCookie('zmWatchScale'+monitorId, scale);
|
||||
$j('#width').val('auto');
|
||||
$j('#height').val('auto');
|
||||
setCookie('zmCycleScale', scale);
|
||||
setCookie('zmWatchWidth', 'auto');
|
||||
setCookie('zmWatchHeight', 'auto');
|
||||
|
||||
setScale();
|
||||
*/
|
||||
}
|
||||
|
||||
function changeStreamQuality() {
|
||||
@@ -170,22 +146,6 @@ function changeStreamQuality() {
|
||||
monitorsSetScale(monitorId);
|
||||
}
|
||||
|
||||
// Implement current scale, as opposed to changing it
|
||||
function setScale() {
|
||||
/*
|
||||
const scale = $j('#scale').val();
|
||||
//monitorStream.setScale(scale, $j('#width').val(), $j('#height').val());
|
||||
monitorsSetScale(monitorId);
|
||||
// Always turn it off, we will re-add it below. I don't know if you can add a callback multiple
|
||||
// times and what the consequences would be
|
||||
$j(window).off('resize', endOfResize); //remove resize handler when Scale to Fit is not active
|
||||
if (scale == '0') {
|
||||
$j(window).on('resize', endOfResize); //remove resize handler when Scale to Fit is not active
|
||||
changeSize();
|
||||
}
|
||||
*/
|
||||
} // end function changeScale
|
||||
|
||||
function getStreamCmdResponse(respObj, respText) {
|
||||
watchdogOk('stream');
|
||||
streamCmdTimer = clearTimeout(streamCmdTimer);
|
||||
@@ -335,10 +295,14 @@ function streamCmdPause(action) {
|
||||
}
|
||||
|
||||
function onPlay() {
|
||||
setButtonState('pauseBtn', 'inactive');
|
||||
setButtonState('playBtn', 'active');
|
||||
//monitorStream.setup_onplay(onPlay); //IgorA100 Added for testing, but probably not required
|
||||
//setButtonState('pauseBtn', 'inactive');
|
||||
//setButtonState('playBtn', 'active');
|
||||
setButtonStateWatch('pauseBtn', 'inactive');
|
||||
setButtonStateWatch('stopBtn', 'inactive');
|
||||
setButtonStateWatch('playBtn', 'unavail');
|
||||
if (monitorStream.status.delayed == true) {
|
||||
setButtonState('stopBtn', 'inactive');
|
||||
//setButtonState('stopBtn', 'inactive');
|
||||
if (monitorStreamReplayBuffer) {
|
||||
setButtonState('fastFwdBtn', 'inactive');
|
||||
setButtonState('slowFwdBtn', 'inactive');
|
||||
@@ -346,7 +310,7 @@ function onPlay() {
|
||||
setButtonState('fastRevBtn', 'inactive');
|
||||
}
|
||||
} else {
|
||||
setButtonState('stopBtn', 'unavail');
|
||||
//setButtonState('stopBtn', 'unavail');
|
||||
if (monitorStreamReplayBuffer) {
|
||||
setButtonState('fastFwdBtn', 'unavail');
|
||||
setButtonState('slowFwdBtn', 'unavail');
|
||||
@@ -359,14 +323,21 @@ function onPlay() {
|
||||
function streamCmdPlay(action) {
|
||||
onPlay();
|
||||
if (action) {
|
||||
monitorStream.streamCommand(CMD_PLAY);
|
||||
if (monitorStream.started) {
|
||||
//Stream was on pause
|
||||
monitorStream.streamCommand(CMD_PLAY);
|
||||
} else {
|
||||
//Stream has been stopped
|
||||
monitorStream.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function streamCmdStop(action) {
|
||||
setButtonState('pauseBtn', 'inactive');
|
||||
setButtonState('playBtn', 'unavail');
|
||||
setButtonState('stopBtn', 'active');
|
||||
monitorStream.onplay = false; //Without this line, "onPlay" is triggered immediately due to "if (this.onplay) this.onplay();" in MonitorStream.js
|
||||
//setButtonState('pauseBtn', 'inactive');
|
||||
//setButtonState('playBtn', 'unavail');
|
||||
//setButtonState('stopBtn', 'active');
|
||||
if (monitorStreamReplayBuffer) {
|
||||
setButtonState('fastFwdBtn', 'unavail');
|
||||
setButtonState('slowFwdBtn', 'unavail');
|
||||
@@ -374,10 +345,14 @@ function streamCmdStop(action) {
|
||||
setButtonState('fastRevBtn', 'unavail');
|
||||
}
|
||||
if (action) {
|
||||
monitorStream.streamCommand(CMD_STOP);
|
||||
//monitorStream.streamCommand(CMD_STOP);
|
||||
monitorStream.kill();
|
||||
}
|
||||
setButtonState('stopBtn', 'unavail');
|
||||
setButtonState('playBtn', 'active');
|
||||
//setButtonState('stopBtn', 'unavail');
|
||||
//setButtonState('playBtn', 'active');
|
||||
setButtonStateWatch('playBtn', 'inactive');
|
||||
setButtonStateWatch('stopBtn', 'unavail');
|
||||
setButtonStateWatch('pauseBtn', 'unavail');
|
||||
}
|
||||
|
||||
function streamCmdFastFwd(action) {
|
||||
@@ -620,9 +595,18 @@ function fetchImage(streamImage) {
|
||||
}
|
||||
|
||||
function handleClick(event) {
|
||||
const targetId = event.target.id;
|
||||
if (targetId.indexOf("nav-link") >= 0) { //Navigation through monitors
|
||||
cycleStop(event.target);
|
||||
const oldId = stringToNumber(document.querySelector('[id ^= "liveStream"]').id);
|
||||
const newId = stringToNumber(targetId);
|
||||
streamReStart(oldId, newId);
|
||||
} else if (event.target.closest('#dvrControls')) { //Controls DVR
|
||||
cyclePause();
|
||||
}
|
||||
if (panZoomEnabled) {
|
||||
//event.preventDefault();
|
||||
if (event.target.id) {
|
||||
if (targetId) {
|
||||
//We are looking for an object with an ID, because there may be another element in the button.
|
||||
var obj = event.target;
|
||||
} else {
|
||||
@@ -909,92 +893,7 @@ function controlSetClicked() {
|
||||
}
|
||||
}
|
||||
|
||||
function streamStart() {
|
||||
monitorStream = new MonitorStream(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());
|
||||
monitorsSetScale(monitorId);
|
||||
monitorStream.start();
|
||||
if (streamMode == 'single') {
|
||||
monitorStream.setup_onclick(fetchImage);
|
||||
} else {
|
||||
monitorStream.setup_onclick(handleClick);
|
||||
monitorStream.setup_onmove(handleMove);
|
||||
}
|
||||
monitorStream.setup_onpause(onPause);
|
||||
monitorStream.setup_onplay(onPlay);
|
||||
monitorStream.setup_onalarm(refresh_events_table);
|
||||
|
||||
monitorStream.setButton('enableAlarmButton', enableAlmBtn);
|
||||
monitorStream.setButton('forceAlarmButton', forceAlmBtn);
|
||||
monitorStream.setButton('zoomOutButton', $j('zoomOutBtn'));
|
||||
if (canEdit.Monitors) {
|
||||
// Will be enabled by streamStatus ajax
|
||||
enableAlmBtn.on('click', cmdAlarm);
|
||||
forceAlmBtn.on('click', cmdForce);
|
||||
} else {
|
||||
forceAlmBtn.prop('title', forceAlmBtn.prop('title') + ': disabled because cannot edit Monitors');
|
||||
enableAlmBtn.prop('title', enableAlmBtn.prop('title') + ': disabled because cannot edit Monitors');
|
||||
}
|
||||
|
||||
/*
|
||||
if (streamMode == 'single') {
|
||||
statusCmdTimer = setTimeout(statusCmdQuery, 200);
|
||||
setInterval(watchdogCheck, statusRefreshTimeout*2, 'status');
|
||||
} else {
|
||||
streamCmdTimer = setTimeout(streamCmdQuery, 200);
|
||||
setInterval(watchdogCheck, statusRefreshTimeout*2, 'stream');
|
||||
}
|
||||
if (canStream || (streamMode == 'single')) {
|
||||
var streamImg = $j('#imageFeed img');
|
||||
if (!streamImg) streamImg = $j('#imageFeed object');
|
||||
if (!streamImg) {
|
||||
console.error('No streamImg found for imageFeed');
|
||||
} else {
|
||||
if (streamMode == 'single') {
|
||||
streamImg.click(streamImg, fetchImage);
|
||||
setInterval(fetchImage, imageRefreshTimeout, $j('#imageFeed img'));
|
||||
} else {
|
||||
streamImg.click(function(event) {
|
||||
handleClick(event);
|
||||
});
|
||||
streamImg.on("error", function(thing) {
|
||||
console.log("Error loading image");
|
||||
console.log(thing);
|
||||
setInterval(fetchImage, 100, $j('#imageFeed img'));
|
||||
});
|
||||
}
|
||||
} // end if have streamImg
|
||||
} // streamMode native or single
|
||||
*/
|
||||
}
|
||||
|
||||
function initPage() {
|
||||
// +++ Support of old ZoomPan algorithm
|
||||
var useOldZoomPan = getCookie('zmUseOldZoomPan');
|
||||
const btnZoomOutBtn = document.getElementById('zoomOutBtn'); //Zoom out button below Frame. She may not
|
||||
if (useOldZoomPan) {
|
||||
panZoomEnabled = false;
|
||||
if (btnZoomOutBtn) {
|
||||
btnZoomOutBtn.classList.remove("hidden");
|
||||
}
|
||||
} else {
|
||||
if (btnZoomOutBtn) {
|
||||
btnZoomOutBtn.classList.add("hidden");
|
||||
}
|
||||
}
|
||||
$j("#use-old-zoom-pan").click(function() {
|
||||
useOldZoomPan = this.checked;
|
||||
setCookie('zmUseOldZoomPan', this.checked);
|
||||
location.reload();
|
||||
});
|
||||
document.getElementById('use-old-zoom-pan').checked = useOldZoomPan;
|
||||
// --- Support of old ZoomPan algorithm
|
||||
|
||||
zmPanZoom.init();
|
||||
|
||||
function streamPrepareStart(monitor=null) {
|
||||
if (canView.Control) {
|
||||
// Load the settings modal into the DOM
|
||||
if (monitorType == 'Local') getSettingsModal();
|
||||
@@ -1011,7 +910,7 @@ function initPage() {
|
||||
}
|
||||
|
||||
if ((monitorType != 'WebSite') && monitorData.length) {
|
||||
streamStart();
|
||||
streamStart(monitor);
|
||||
if (window.history.length == 1) {
|
||||
$j('#closeControl').html('');
|
||||
}
|
||||
@@ -1052,6 +951,163 @@ function initPage() {
|
||||
setInterval(reloadWebSite, monitorRefresh*1000);
|
||||
}
|
||||
|
||||
// Manage the generate Edit button
|
||||
bindButton('#editBtn', 'click', null, function onEditClick(evt) {
|
||||
evt.preventDefault();
|
||||
window.location.assign("?view=monitor&mid="+monitorId);
|
||||
});
|
||||
|
||||
const el = document.querySelector('.imageFeed');
|
||||
el.addEventListener('mouseenter', handleMouseEnter);
|
||||
el.addEventListener('mouseleave', handleMouseLeave);
|
||||
|
||||
const i = setInterval(function() {
|
||||
if (document.querySelector('[id ^= "liveStream"]').offsetHeight > 20) {
|
||||
//You need to wait until the image appears.
|
||||
clearInterval(i);
|
||||
document.getElementById('monitor').classList.remove('hidden-shift');
|
||||
monitorsSetScale(monitorId);
|
||||
}
|
||||
}, 100);
|
||||
setButtonStateWatch('stopBtn', 'active');
|
||||
}
|
||||
|
||||
function handleMouseEnter(event) {
|
||||
//Displaying "Scale" and other buttons at the top of the monitor image
|
||||
const id = stringToNumber(this.id);
|
||||
$j('#button_zoom' + id).stop(true, true).slideDown('fast');
|
||||
}
|
||||
|
||||
function handleMouseLeave(event) {
|
||||
const id = stringToNumber(this.id);
|
||||
$j('#button_zoom' + id).stop(true, true).slideUp('fast');
|
||||
}
|
||||
|
||||
function streamStart(monitor = null) {
|
||||
if (monitor) {
|
||||
monitorStream = new MonitorStream(monitor);
|
||||
} else {
|
||||
monitorStream = new MonitorStream(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());
|
||||
//monitorsSetScale(monitorId);
|
||||
monitorStream.start();
|
||||
if (streamMode == 'single') {
|
||||
monitorStream.setup_onclick(fetchImage);
|
||||
} else {
|
||||
monitorStream.setup_onclick(handleClick);
|
||||
monitorStream.setup_onmove(handleMove);
|
||||
}
|
||||
monitorStream.setup_onpause(onPause);
|
||||
monitorStream.setup_onplay(onPlay);
|
||||
monitorStream.setup_onalarm(refresh_events_table);
|
||||
|
||||
monitorStream.setButton('enableAlarmButton', enableAlmBtn);
|
||||
monitorStream.setButton('forceAlarmButton', forceAlmBtn);
|
||||
monitorStream.setButton('zoomOutButton', $j('zoomOutBtn'));
|
||||
if (canEdit.Monitors) {
|
||||
// Will be enabled by streamStatus ajax
|
||||
enableAlmBtn.on('click', cmdAlarm);
|
||||
forceAlmBtn.on('click', cmdForce);
|
||||
} else {
|
||||
forceAlmBtn.prop('title', forceAlmBtn.prop('title') + ': disabled because cannot edit Monitors');
|
||||
enableAlmBtn.prop('title', enableAlmBtn.prop('title') + ': disabled because cannot edit Monitors');
|
||||
}
|
||||
}
|
||||
|
||||
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 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;
|
||||
document.querySelector('title').textContent = newMonitorName;
|
||||
url.searchParams.set('mid', monitorId);
|
||||
history.pushState(null, "", url);
|
||||
|
||||
zmPanZoom.action('disable', {id: oldId});
|
||||
if (monitorStream) {
|
||||
monitorStream.kill();
|
||||
}
|
||||
el.removeEventListener('mouseenter', handleMouseEnter);
|
||||
el.removeEventListener('mouseleave', handleMouseLeave);
|
||||
|
||||
//Change main monitor block
|
||||
document.getElementById('monitor').innerHTML = currentMonitor.streamHTML;
|
||||
|
||||
//Change active element of the navigation menu
|
||||
document.getElementById('nav-item-cycle'+oldId).querySelector('a').classList.remove("active");
|
||||
document.getElementById('nav-item-cycle'+newId).querySelector('a').classList.add("active");
|
||||
|
||||
//Set global variables from the current monitor
|
||||
monitorWidth = currentMonitor.monitorWidth;
|
||||
monitorHeight = currentMonitor.monitorHeight;
|
||||
monitorType = currentMonitor.monitorType;
|
||||
monitorRefresh = currentMonitor.monitorRefresh;
|
||||
monitorStreamReplayBuffer = currentMonitor.monitorStreamReplayBuffer;
|
||||
monitorControllable = currentMonitor.monitorControllable;
|
||||
streamMode = currentMonitor.streamMode;
|
||||
|
||||
table.bootstrapTable('destroy');
|
||||
streamPrepareStart(currentMonitor);
|
||||
applyMonitorControllable(currentMonitor);
|
||||
zmPanZoom.init();
|
||||
loadFontFaceObserver();
|
||||
//document.getElementById('monitor').classList.remove('hidden-shift');
|
||||
}
|
||||
|
||||
function applyMonitorControllable(currentMonitor) {
|
||||
if (currentMonitor.monitorControllable) {
|
||||
const ptzShow = getCookie('ptzShow');
|
||||
document.getElementById('ptzToggle').classList.remove("hidden");
|
||||
sidebarControls.html(currentMonitor.ptzControls);
|
||||
if (ptzShow) {
|
||||
sidebarControls.show();
|
||||
document.getElementById('ptzToggle').classList.remove("btn-secondary");
|
||||
document.getElementById('ptzToggle').classList.add("btn-primary");
|
||||
} else {
|
||||
sidebarControls.hide();
|
||||
document.getElementById('ptzToggle').classList.remove("btn-primary");
|
||||
document.getElementById('ptzToggle').classList.add("btn-secondary");
|
||||
}
|
||||
} else {
|
||||
document.getElementById('ptzToggle').classList.add("hidden");
|
||||
sidebarControls.html('');
|
||||
sidebarControls.hide();
|
||||
}
|
||||
changeObjectClass();
|
||||
}
|
||||
|
||||
function initPage() {
|
||||
// +++ Support of old ZoomPan algorithm
|
||||
var useOldZoomPan = getCookie('zmUseOldZoomPan');
|
||||
const btnZoomOutBtn = document.getElementById('zoomOutBtn'); //Zoom out button below Frame. She may not
|
||||
if (useOldZoomPan) {
|
||||
panZoomEnabled = false;
|
||||
if (btnZoomOutBtn) {
|
||||
btnZoomOutBtn.classList.remove("hidden");
|
||||
}
|
||||
} else {
|
||||
if (btnZoomOutBtn) {
|
||||
btnZoomOutBtn.classList.add("hidden");
|
||||
}
|
||||
}
|
||||
$j("#use-old-zoom-pan").click(function() {
|
||||
useOldZoomPan = this.checked;
|
||||
setCookie('zmUseOldZoomPan', this.checked);
|
||||
location.reload();
|
||||
});
|
||||
document.getElementById('use-old-zoom-pan').checked = useOldZoomPan;
|
||||
// --- Support of old ZoomPan algorithm
|
||||
|
||||
zmPanZoom.init();
|
||||
|
||||
// Manage the BACK button
|
||||
bindButton('#backBtn', 'click', null, function onBackClick(evt) {
|
||||
evt.preventDefault();
|
||||
@@ -1073,12 +1129,6 @@ function initPage() {
|
||||
$j('#settingsModal').modal('show');
|
||||
});
|
||||
|
||||
// Manage the generate Edit button
|
||||
bindButton('#editBtn', 'click', null, function onEditClick(evt) {
|
||||
evt.preventDefault();
|
||||
window.location.assign("?view=monitor&mid="+monitorId);
|
||||
});
|
||||
|
||||
bindButton('#cyclePlayBtn', 'click', null, cycleStart);
|
||||
bindButton('#cyclePauseBtn', 'click', null, cyclePause);
|
||||
bindButton('#cycleNextBtn', 'click', null, cycleNext);
|
||||
@@ -1119,17 +1169,6 @@ function initPage() {
|
||||
}
|
||||
}, 10*1000);
|
||||
}
|
||||
$j(".imageFeed").hover(
|
||||
//Displaying "Scale" and other buttons at the top of the monitor image
|
||||
function() {
|
||||
const id = stringToNumber(this.id);
|
||||
$j('#button_zoom' + id).stop(true, true).slideDown('fast');
|
||||
},
|
||||
function() {
|
||||
const id = stringToNumber(this.id);
|
||||
$j('#button_zoom' + id).stop(true, true).slideUp('fast');
|
||||
}
|
||||
);
|
||||
|
||||
setInterval(() => {
|
||||
//Updating Scale. When quickly scrolling the mouse wheel or quickly pressing Zoom In/Out, you should not set Scale very often.
|
||||
@@ -1137,11 +1176,18 @@ function initPage() {
|
||||
monitorsSetScale(monitorId);
|
||||
updateScale = false;
|
||||
}
|
||||
}, 500);
|
||||
}, 300);
|
||||
|
||||
document.getElementById('monitor').classList.remove('hidden-shift');
|
||||
document.addEventListener('click', function(event) {
|
||||
handleClick(event);
|
||||
});
|
||||
|
||||
//document.getElementById('monitor').classList.remove('hidden-shift');
|
||||
changeObjectClass();
|
||||
changeSize();
|
||||
streamPrepareStart();
|
||||
if (monitorStream) {
|
||||
applyMonitorControllable(monitorStream);
|
||||
}
|
||||
} // initPage
|
||||
|
||||
function watchFullscreen() {
|
||||
@@ -1159,7 +1205,10 @@ function watchFullscreen() {
|
||||
}
|
||||
|
||||
function watchAllEvents() {
|
||||
window.location.replace(document.getElementById('allEventsBtn').getAttribute('data-url'));
|
||||
const currentMonitor = monitorData.find((o) => {
|
||||
return parseInt(o["id"]) === monitorId;
|
||||
});
|
||||
window.location.replace(currentMonitor.urlForAllEvents);
|
||||
}
|
||||
|
||||
var intervalId;
|
||||
@@ -1181,13 +1230,20 @@ function cyclePause() {
|
||||
}
|
||||
|
||||
function cycleStart() {
|
||||
secondsToCycle = $j('#cyclePeriod').val();
|
||||
if (secondsToCycle == 0) secondsToCycle = $j('#cyclePeriod').val();
|
||||
intervalId = setInterval(nextCycleView, 1000);
|
||||
cycle = true;
|
||||
$j('#cyclePauseBtn').show();
|
||||
$j('#cyclePlayBtn').hide();
|
||||
}
|
||||
|
||||
function cycleStop(target) {
|
||||
secondsToCycle = 0;
|
||||
monIdx = target.getAttribute('data-monIdx');
|
||||
$j('#secondsToCycle').text('');
|
||||
cyclePause();
|
||||
}
|
||||
|
||||
function cycleNext() {
|
||||
monIdx ++;
|
||||
if (monIdx >= monitorData.length) {
|
||||
@@ -1198,7 +1254,19 @@ function cycleNext() {
|
||||
}
|
||||
clearInterval(intervalId);
|
||||
monitorStream.kill();
|
||||
window.location.replace('?view=watch&cycle='+cycle+'&mid='+monitorData[monIdx].id+'&mode='+mode);
|
||||
|
||||
// +++ Start next monitor
|
||||
let oldId;
|
||||
if (monIdx == 0) {
|
||||
oldId = monitorData[monitorData.length-1].id;
|
||||
} else {
|
||||
oldId = monitorData[monIdx-1].id;
|
||||
}
|
||||
const newId = monitorData[monIdx].id;
|
||||
streamReStart(oldId, newId);
|
||||
cycleStart();
|
||||
// --- Start next monitor
|
||||
//window.location.replace('?view=watch&cycle='+cycle+'&mid='+monitorData[monIdx].id+'&mode='+mode);
|
||||
}
|
||||
|
||||
function cyclePrev() {
|
||||
@@ -1210,8 +1278,21 @@ function cyclePrev() {
|
||||
console.log('No monitorData for ' + monIdx);
|
||||
}
|
||||
clearInterval(intervalId);
|
||||
monitorStream.stop();
|
||||
window.location.replace('?view=watch&cycle='+cycle+'&mid='+monitorData[monIdx].id+'&mode='+mode);
|
||||
//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 newId = monitorData[monIdx].id;
|
||||
streamReStart(oldId, newId);
|
||||
cycleStart();
|
||||
// --- Start previous monitors
|
||||
//window.location.replace('?view=watch&cycle='+cycle+'&mid='+monitorData[monIdx].id+'&mode='+mode);
|
||||
}
|
||||
|
||||
function cyclePeriodChange() {
|
||||
@@ -1230,7 +1311,7 @@ function cycleToggle(e) {
|
||||
button.toggleClass('btn-secondary');
|
||||
button.toggleClass('btn-primary');
|
||||
changeObjectClass();
|
||||
changeSize();
|
||||
monitorsSetScale(monitorId);
|
||||
}
|
||||
|
||||
function ptzToggle(e) {
|
||||
@@ -1245,7 +1326,7 @@ function ptzToggle(e) {
|
||||
button.toggleClass('btn-secondary');
|
||||
button.toggleClass('btn-primary');
|
||||
changeObjectClass();
|
||||
changeSize();
|
||||
monitorsSetScale(monitorId);
|
||||
}
|
||||
|
||||
function changeRate(e) {
|
||||
@@ -1310,16 +1391,20 @@ function panZoomOut(el) {
|
||||
function monitorsSetScale(id=null) {
|
||||
//This function will probably need to be moved to the main JS file, because now used on Watch & Montage pages
|
||||
if (id || typeof monitorStream !== 'undefined') {
|
||||
//monitorStream used on Watch page.
|
||||
if (monitorStream) {
|
||||
if (monitorStream !== false) {
|
||||
//monitorStream used on Watch page.
|
||||
var curentMonitor = monitorStream;
|
||||
} else {
|
||||
} else if (typeof monitors !== 'undefined') {
|
||||
//used on Montage, Watch & Event page.
|
||||
var curentMonitor = monitors.find((o) => {
|
||||
return parseInt(o["id"]) === id;
|
||||
});
|
||||
} else {
|
||||
//Stream is missing
|
||||
return;
|
||||
}
|
||||
//const el = document.getElementById('liveStream'+id);
|
||||
if (panZoomEnabled) {
|
||||
if (panZoomEnabled && zmPanZoom.panZoom[id]) {
|
||||
var panZoomScale = zmPanZoom.panZoom[id].getScale();
|
||||
} else {
|
||||
var panZoomScale = 1;
|
||||
@@ -1450,12 +1535,30 @@ document.onvisibilitychange = () => {
|
||||
TimerHideShow = clearTimeout(TimerHideShow);
|
||||
TimerHideShow = setTimeout(function() {
|
||||
//Stop monitor when closing or hiding page
|
||||
monitorStream.kill();
|
||||
if (monitorStream) {
|
||||
monitorStream.kill();
|
||||
}
|
||||
}, 15*1000);
|
||||
} else {
|
||||
//Start monitor when show page
|
||||
if (!monitorStream.started) {
|
||||
if (monitorStream && !monitorStream.started) {
|
||||
monitorStream.start();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function setButtonStateWatch(element_id, btnClass) {
|
||||
//Temporary function so as not to break anything else, because analysis of the setButtonState function in skin.js is required,
|
||||
//and also review the logic of the buttons and more (if (this.onplay) this.onplay() in MonitorStream.js) var element = document.getElementById(element_id);
|
||||
var element = document.getElementById(element_id);
|
||||
if ( element ) {
|
||||
element.className = btnClass;
|
||||
if (btnClass == 'unavail') {
|
||||
element.disabled = true;
|
||||
} else {
|
||||
element.disabled = false;
|
||||
}
|
||||
} else {
|
||||
console.log('Element was null or not found in setButtonState. id:'+element_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
global $nextMid;
|
||||
global $options;
|
||||
global $monitors;
|
||||
global $monitorsExtraData;
|
||||
global $streamMode;
|
||||
global $showPtzControls;
|
||||
global $monitor;
|
||||
@@ -53,7 +54,17 @@ monitorData[monitorData.length] = {
|
||||
'onclick': function(){window.location.assign( '?view=watch&mid=<?php echo $m->Id() ?>' );},
|
||||
'type': '<?php echo $m->Type() ?>',
|
||||
'refresh': '<?php echo $m->Refresh() ?>',
|
||||
'janus_pin': '<?php echo $m->Janus_Pin() ?>'
|
||||
'janus_pin': '<?php echo $m->Janus_Pin() ?>',
|
||||
'streamHTML': '<?php echo str_replace(array("\r\n", "\r", "\n"), '', $monitorsExtraData[$m->Id()]['StreamHTML']) ?>',
|
||||
'urlForAllEvents': '<?php echo $monitorsExtraData[$m->Id()]['urlForAllEvents'] ?>',
|
||||
'ptzControls': '<?php echo str_replace(array("\r\n", "\r", "\n"), '', $monitorsExtraData[$m->Id()]['ptzControls']) ?>',
|
||||
'monitorWidth': parseInt('<?php echo $m->ViewWidth() ?>'),
|
||||
'monitorHeight': parseInt('<?php echo $m->ViewHeight() ?>'),
|
||||
'monitorType': '<?php echo $m->Type() ?>',
|
||||
'monitorRefresh': '<?php echo $m->Refresh() ?>',
|
||||
'monitorStreamReplayBuffer': parseInt('<?php echo $m->StreamReplayBuffer() ?>'),
|
||||
'monitorControllable': <?php echo $m->Controllable()?'true':'false' ?>,
|
||||
'streamMode': '<?php echo getStreamModeMonitor($m) ?>'
|
||||
};
|
||||
<?php
|
||||
} // end foreach monitor
|
||||
|
||||
@@ -103,7 +103,15 @@ if (!$cycle and isset($_COOKIE['zmCycleShow'])) {
|
||||
$showCycle = $_COOKIE['zmCycleShow'] == 'true';
|
||||
}
|
||||
#Whether to show the controls button
|
||||
$hasPtzControls = ( ZM_OPT_CONTROL && $monitor->Controllable() && canView('Control') && $monitor->Type() != 'WebSite' );
|
||||
$hasPtzControls = false;
|
||||
foreach ($monitors as $m) {
|
||||
if (( ZM_OPT_CONTROL && $m->Controllable() && canView('Control') && $m->Type() != 'WebSite' )) {
|
||||
//If there is control for at least one camera, then we display the block.
|
||||
$hasPtzControls = true;
|
||||
}
|
||||
}
|
||||
//$hasPtzControls = ( ZM_OPT_CONTROL && $monitor->Controllable() && canView('Control') && $monitor->Type() != 'WebSite' );
|
||||
|
||||
$showPtzControls = false;
|
||||
if ($hasPtzControls) {
|
||||
$showPtzControls = true;
|
||||
@@ -198,14 +206,19 @@ if (
|
||||
) {
|
||||
$options['scale'] = 0;
|
||||
}
|
||||
if ($monitor->JanusEnabled()) {
|
||||
$streamMode = 'janus';
|
||||
} else if ($monitor->RTSP2WebEnabled()) {
|
||||
$streamMode = $monitor->RTSP2WebType();
|
||||
} else {
|
||||
$streamMode = getStreamMode();
|
||||
|
||||
function getStreamModeMonitor($monitor) {
|
||||
if ($monitor->JanusEnabled()) {
|
||||
$streamMode = 'janus';
|
||||
} else if ($monitor->RTSP2WebEnabled()) {
|
||||
$streamMode = $monitor->RTSP2WebType();
|
||||
} else {
|
||||
$streamMode = getStreamMode();
|
||||
}
|
||||
return $streamMode;
|
||||
}
|
||||
|
||||
$streamMode = getStreamModeMonitor($monitor);
|
||||
noCacheHeaders();
|
||||
xhtmlHeaders(__FILE__, $monitor->Name().' - '.translate('Feed'));
|
||||
getBodyTopHTML();
|
||||
@@ -332,8 +345,32 @@ echo htmlSelect('cyclePeriod', $cyclePeriodOptions, $period, array('id'=>'cycleP
|
||||
</div>
|
||||
<ul class="nav nav-pills flex-column">
|
||||
<?php
|
||||
if ($monitor->Type() != 'WebSite') {
|
||||
$options['state'] = true;
|
||||
}
|
||||
$monitorsExtraData = [];
|
||||
$monitorJanusUsed = false;
|
||||
$dataMonIdx=0;
|
||||
foreach ($monitors as $m) {
|
||||
echo '<li class="nav-item"><a class="nav-link'.( $m->Id() == $monitor->Id() ? ' active' : '' ).'" href="?view=watch&mid='.$m->Id().'">'.$m->Name().'</a></li>';
|
||||
$monitorsExtraData[$m->Id()]['StreamHTML'] = $m->getStreamHTML($options);
|
||||
$monitorsExtraData[$m->Id()]['urlForAllEvents'] = "?view=events&page=1&filter%5BQuery%5D%5Bterms%5D%5B0%5D%5Battr%5D=Monitor&filter%5BQuery%5D%5Bterms%5D%5B0%5D%5Bop%5D=%3D&filter%5BQuery%5D%5Bterms%5D%5B0%5D%5Bval%5D=".$m->Id()."&filter%5BQuery%5D%5Bsort_asc%5D=1&filter%5BQuery%5D%5Bsort_field%5D=StartDateTime&filter%5BQuery%5D%5Bskip_locked%5D=&filter%5BQuery%5D%5Blimit%5D=0";
|
||||
if ($m->JanusEnabled()) {
|
||||
$monitorJanusUsed = true;
|
||||
}
|
||||
$monitorsExtraData[$m->Id()]['ptzControls'] = '';
|
||||
if ($hasPtzControls) {
|
||||
foreach ( getSkinIncludes('includes/control_functions.php') as $includeFile )
|
||||
require_once $includeFile;
|
||||
$ptzControls = ptzControls($m);
|
||||
$monitorsExtraData[$m->Id()]['ptzControls'] = $ptzControls;
|
||||
}
|
||||
echo '<li id="nav-item-cycle'.$m->Id().'" class="nav-item"><a id="nav-link'.$m->Id().'" class="nav-link'.( $m->Id() == $monitor->Id() ? ' active' : '' ).'" data-monIdx='.$dataMonIdx++.' href="#">'.$m->Name().'</a></li>';
|
||||
}
|
||||
if ($monitorJanusUsed) {
|
||||
?>
|
||||
<script src="<?php echo cache_bust('js/adapter.min.js') ?>"></script>
|
||||
<script src="/javascript/janus/janus.js"></script>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</ul>
|
||||
@@ -342,66 +379,43 @@ echo htmlSelect('cyclePeriod', $cyclePeriodOptions, $period, array('id'=>'cycleP
|
||||
<div id="monitor" class="monitor hidden-shift"
|
||||
>
|
||||
<?php
|
||||
if ($monitor->Type() != 'WebSite') {
|
||||
$options['state'] = true;
|
||||
}
|
||||
echo $monitor->getStreamHTML($options);
|
||||
?>
|
||||
</div><!-- id="Monitor" -->
|
||||
<?php
|
||||
if ($monitor->Type() != 'WebSite') {
|
||||
?>
|
||||
<div class="buttons" id="dvrControls">
|
||||
<!--
|
||||
<button type="button" id="getImageBtn" title="<?php echo translate('Download Image') ?>"/>
|
||||
-->
|
||||
<?php
|
||||
if ($streamMode == 'jpeg') {
|
||||
if ($monitor->StreamReplayBuffer() != 0) {
|
||||
?>
|
||||
<button type="button" id="fastRevBtn" title="<?php echo translate('Rewind') ?>" class="unavail" disabled="disabled" data-on-click-true="streamCmdFastRev">
|
||||
<i class="material-icons md-18">fast_rewind</i>
|
||||
</button>
|
||||
<button type="button" id="slowRevBtn" title="<?php echo translate('StepBack') ?>" class="unavail" disabled="disabled" data-on-click-true="streamCmdSlowRev">
|
||||
<i class="material-icons md-18">chevron_right</i>
|
||||
<i class="material-icons md-18">chevron_left</i>
|
||||
</button>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<button type="button" id="pauseBtn" title="<?php echo translate('Pause') ?>" class="inactive" data-on-click-true="streamCmdPause">
|
||||
<i class="material-icons md-18">pause</i>
|
||||
</button>
|
||||
<button type="button" id="stopBtn" title="<?php echo translate('Stop') ?>" class="unavail" disabled="disabled" data-on-click-true="streamCmdStop" style="display:none;">
|
||||
<button type="button" id="stopBtn" title="<?php echo translate('Stop') ?>" class="unavail" disabled="disabled" data-on-click-true="streamCmdStop">
|
||||
<i class="material-icons md-18">stop</i>
|
||||
</button>
|
||||
<button type="button" id="playBtn" title="<?php echo translate('Play') ?>" class="active" disabled="disabled" data-on-click-true="streamCmdPlay">
|
||||
<i class="material-icons md-18">play_arrow</i>
|
||||
</button>
|
||||
<?php
|
||||
if ($monitor->StreamReplayBuffer() != 0) {
|
||||
?>
|
||||
<button type="button" id="slowFwdBtn" title="<?php echo translate('StepForward') ?>" class="unavail" disabled="disabled" data-on-click-true="streamCmdSlowFwd">
|
||||
<i class="material-icons md-18">chevron_right</i>
|
||||
</button>
|
||||
<button type="button" id="fastFwdBtn" title="<?php echo translate('FastForward') ?>" class="unavail" disabled="disabled" data-on-click-true="streamCmdFastFwd">
|
||||
<i class="material-icons md-18">fast_forward</i>
|
||||
</button>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<button type="button" id="zoomOutBtn" title="<?php echo translate('ZoomOut') ?>" class="avail" data-on-click="zoomOutClick">
|
||||
<i class="material-icons md-18">zoom_out</i>
|
||||
</button>
|
||||
<?php
|
||||
} // end if streamMode==jpeg
|
||||
?>
|
||||
</div><!--dvrControls-->
|
||||
<?php } // end if $monitor->Type() != 'WebSite' ?>
|
||||
<div class="buttons" id="extButton">
|
||||
<button type="button" id="fullscreenBtn" title="<?php echo translate('Fullscreen') ?>" class="avail" data-on-click="watchFullscreen">
|
||||
<i class="material-icons md-18">fullscreen</i>
|
||||
</button>
|
||||
<button type="button" id="allEventsBtn" title="<?php echo translate('All Events') ?>" class="avail" data-on-click="watchAllEvents" data-url="?view=events&page=1&filter%5BQuery%5D%5Bterms%5D%5B0%5D%5Battr%5D=Monitor&filter%5BQuery%5D%5Bterms%5D%5B0%5D%5Bop%5D=%3D&filter%5BQuery%5D%5Bterms%5D%5B0%5D%5Bval%5D=<?php echo $monitor->Id()?>&filter%5BQuery%5D%5Bsort_asc%5D=1&filter%5BQuery%5D%5Bsort_field%5D=StartDateTime&filter%5BQuery%5D%5Bskip_locked%5D=&filter%5BQuery%5D%5Blimit%5D=0"><?php echo translate('All Events') ?>
|
||||
<button type="button" id="allEventsBtn" title="<?php echo translate('All Events') ?>" class="avail" data-on-click="watchAllEvents"><?php echo translate('All Events') ?>
|
||||
</button>
|
||||
</div>
|
||||
</div><!-- id="wrapperMonitor" -->
|
||||
@@ -409,12 +423,9 @@ if ($streamMode == 'jpeg') {
|
||||
<!-- START Control -->
|
||||
<?php
|
||||
if ( $hasPtzControls ) {
|
||||
foreach ( getSkinIncludes('includes/control_functions.php') as $includeFile )
|
||||
require_once $includeFile;
|
||||
?>
|
||||
<div id="ptzControls" class="col-sm-2 ptzControls"<?php echo $showPtzControls ? '' : ' style="display:none;"'?>>
|
||||
<?php echo ptzControls($monitor) ?>
|
||||
</div>
|
||||
<div id="ptzControls" class="col-sm-2 ptzControls"<?php echo $showPtzControls ? '' : ' style="display:none;"'?>>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
@@ -479,14 +490,6 @@ if ( canView('Events') && ($monitor->Type() != 'WebSite') ) {
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
if ( $monitor->JanusEnabled() ) {
|
||||
?>
|
||||
<script src="<?php echo cache_bust('js/adapter.min.js') ?>"></script>
|
||||
<script src="/javascript/janus/janus.js"></script>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<?php
|
||||
if ( $monitor->RTSP2WebEnabled() and $monitor->RTSP2WebType == "HLS") {
|
||||
?>
|
||||
<script src="<?php echo cache_bust('js/hls.js') ?>"></script>
|
||||
|
||||
Reference in New Issue
Block a user