Merge branch 'ZoneMinder:master' into patch-141
commit
576dc6a652
|
@ -1384,14 +1384,24 @@ int VideoStore::write_packet(AVPacket *pkt, AVStream *stream) {
|
|||
}
|
||||
pkt->dts = last_dts[stream->index];
|
||||
} else {
|
||||
if ((last_dts[stream->index] != AV_NOPTS_VALUE) and (pkt->dts <= last_dts[stream->index])) {
|
||||
if (last_dts[stream->index] != AV_NOPTS_VALUE) {
|
||||
if (pkt->dts < last_dts[stream->index]) {
|
||||
Warning("non increasing dts, fixing. our dts %" PRId64 " stream %d last_dts %" PRId64 ". reorder_queue_size=%zu",
|
||||
pkt->dts, stream->index, last_dts[stream->index], reorder_queue_size);
|
||||
pkt->dts = last_dts[stream->index]+last_duration[stream->index];
|
||||
if (pkt->dts > pkt->pts) pkt->pts = pkt->dts; // Do it here to avoid warning below
|
||||
} else if (pkt->dts == last_dts[stream->index]) {
|
||||
// Commonly seen
|
||||
Debug(1, "non increasing dts, fixing. our dts %" PRId64 " stream %d last_dts %" PRId64 ". reorder_queue_size=%zu",
|
||||
pkt->dts, stream->index, last_dts[stream->index], reorder_queue_size);
|
||||
// dts MUST monotonically increase, so add 1 which should be a small enough time difference to not matter.
|
||||
pkt->dts = last_dts[stream->index]+1;
|
||||
pkt->dts = last_dts[stream->index]+last_duration[stream->index];
|
||||
if (pkt->dts > pkt->pts) pkt->pts = pkt->dts; // Do it here to avoid warning below
|
||||
}
|
||||
}
|
||||
next_dts[stream->index] = pkt->dts + pkt->duration;
|
||||
last_dts[stream->index] = pkt->dts;
|
||||
last_duration[stream->index] = pkt->duration;
|
||||
}
|
||||
|
||||
if (pkt->pts == AV_NOPTS_VALUE) {
|
||||
|
|
|
@ -86,6 +86,7 @@ class VideoStore {
|
|||
// These are for out, should start at zero. We assume they do not wrap because we just aren't going to save files that big.
|
||||
int64_t *next_dts;
|
||||
std::map<int, int64_t> last_dts;
|
||||
std::map<int, int64_t> last_duration;
|
||||
int64_t audio_next_pts;
|
||||
|
||||
int max_stream_index;
|
||||
|
|
|
@ -440,6 +440,11 @@ switch ( $_REQUEST['layout'] ) {
|
|||
case 'json' :
|
||||
{
|
||||
$response = array( strtolower(validJsStr($_REQUEST['entity'])) => $data );
|
||||
if ( ZM_OPT_USE_AUTH && (ZM_AUTH_RELAY == 'hashed') ) {
|
||||
$auth_hash = generateAuthHash(ZM_AUTH_HASH_IPS);
|
||||
$response['auth'] = $auth_hash;
|
||||
$response['auth_relay'] = get_auth_relay();
|
||||
}
|
||||
if ( isset($_REQUEST['loopback']) )
|
||||
$response['loopback'] = validJsStr($_REQUEST['loopback']);
|
||||
#ZM\Warning(print_r($response, true));
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -243,7 +243,7 @@ function MonitorStream(monitorData) {
|
|||
}});
|
||||
}
|
||||
attachVideo(parseInt(this.id), this.janusPin);
|
||||
this.statusCmdTimer = setInterval(this.statusCmdQuery.bind(this), delay);
|
||||
this.statusCmdTimer = setInterval(this.statusCmdQuery.bind(this), statusRefreshTimeout);
|
||||
return;
|
||||
}
|
||||
if (this.RTSP2WebEnabled) {
|
||||
|
@ -289,7 +289,7 @@ function MonitorStream(monitorData) {
|
|||
webrtcUrl.pathname = "/stream/" + this.id + "/channel/0/webrtc";
|
||||
startRTSP2WebPlay(videoEl, webrtcUrl.href);
|
||||
}
|
||||
this.statusCmdTimer = setInterval(this.statusCmdQuery.bind(this), delay);
|
||||
this.statusCmdTimer = setInterval(this.statusCmdQuery.bind(this), statusRefreshTimeout);
|
||||
return;
|
||||
} else {
|
||||
console.log("ZM_RTSP2WEB_PATH is empty. Go to Options->System and set ZM_RTSP2WEB_PATH accordingly.");
|
||||
|
@ -753,6 +753,15 @@ function MonitorStream(monitorData) {
|
|||
} // end if canEdit.Monitors
|
||||
|
||||
this.setAlarmState(monitorStatus);
|
||||
|
||||
if (respObj.auth_hash) {
|
||||
if (this.auth_hash != respObj.auth_hash) {
|
||||
// Don't reload the stream because it causes annoying flickering. Wait until the stream breaks.
|
||||
console.log("Changed auth from " + this.auth_hash + " to " + respObj.auth_hash);
|
||||
this.streamCmdParms.auth = this.auth_hash = respObj.auth_hash;
|
||||
this.auth_relay = respObj.auth_relay;
|
||||
}
|
||||
} // end if have a new auth hash
|
||||
} else {
|
||||
checkStreamForErrors('getStatusCmdResponse', respObj);
|
||||
}
|
||||
|
|
|
@ -63,6 +63,10 @@ var zmPanZoom = {
|
|||
_this.setTriggerChangedMonitors(id);
|
||||
});
|
||||
} else if (action == "disable") { //Disable a specific object
|
||||
if (!this.panZoom[param['id']]) {
|
||||
console.log(`PanZoom for monitor "${param['id']}" was not initialized.`);
|
||||
return;
|
||||
}
|
||||
$j(document).off('keyup.panzoom keydown.panzoom');
|
||||
$j('.btn-zoom-in').addClass('hidden');
|
||||
$j('.btn-zoom-out').addClass('hidden');
|
||||
|
@ -162,7 +166,9 @@ var zmPanZoom = {
|
|||
const point = {clientX: event.clientX, clientY: event.clientY};
|
||||
this.panZoom[id].zoomToPoint(scale, point, {focal: {x: event.clientX, y: event.clientY}});
|
||||
}
|
||||
if (this.ctrled || this.shifted) {
|
||||
this.setTriggerChangedMonitors(id);
|
||||
}
|
||||
},
|
||||
|
||||
setTriggerChangedMonitors: function(id) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
@ -680,7 +668,7 @@ input[type=button]:disabled,
|
|||
input[type=submit]:disabled,
|
||||
a.disabled,
|
||||
a.btn-primary.disabled,
|
||||
.btn-primary:disabled {
|
||||
.btn-primary.disabled, .btn-primary:disabled, .btn-secondary.disabled, .btn-secondary:disabled {
|
||||
background-color: #aaaaaa;
|
||||
border-color: #bbbbbb;
|
||||
}
|
||||
|
@ -938,6 +926,11 @@ a.flip {
|
|||
clear: both;
|
||||
}
|
||||
|
||||
.monitor .monitorStatus {
|
||||
position: relative;
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
.monitor .monitorStatus.bottom {
|
||||
color: #dddddd;
|
||||
}
|
||||
|
@ -1124,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! */
|
||||
|
||||
|
|
|
@ -167,7 +167,7 @@ button:disabled,
|
|||
input[disabled],
|
||||
input[type=button]:disabled,
|
||||
input[type=submit]:disabled,
|
||||
.btn-primary:disabled {
|
||||
.btn-primary.disabled, .btn-primary:disabled, .btn-secondary.disabled, .btn-secondary:disabled {
|
||||
color: #888888;
|
||||
background-color: #666666;
|
||||
border-color: #666666;
|
||||
|
@ -290,6 +290,10 @@ ul.nav.nav-pills.flex-column {
|
|||
background:#444444;
|
||||
}
|
||||
|
||||
.monitor .monitorStatus {
|
||||
background-color: #222222;
|
||||
}
|
||||
|
||||
/* Change scrollbar style */
|
||||
::-webkit-scrollbar, div::-webkit-scrollbar, nav::-webkit-scrollbar, .chosen-results::-webkit-scrollbar {
|
||||
width: 11px;
|
||||
|
|
|
@ -683,13 +683,13 @@ function endOfResize(e) {
|
|||
* */
|
||||
function scaleToFit(baseWidth, baseHeight, scaleEl, bottomEl, container, panZoomScale = 1) {
|
||||
$j(window).on('resize', endOfResize); //set delayed scaling when Scale to Fit is selected
|
||||
const ratio = baseWidth / baseHeight;
|
||||
if (!container) container = $j('#content');
|
||||
if (!container) {
|
||||
console.error("No container found");
|
||||
return;
|
||||
}
|
||||
|
||||
const ratio = baseWidth / baseHeight;
|
||||
const viewPort = $j(window);
|
||||
// jquery does not provide a bottom offset, and offset does not include margins. outerHeight true minus false gives total vertical margins.
|
||||
var bottomLoc = 0;
|
||||
|
@ -701,22 +701,13 @@ function scaleToFit(baseWidth, baseHeight, scaleEl, bottomEl, container, panZoom
|
|||
console.log("bottomLoc: " + bottomEl.offset().top + " + (" + bottomEl.outerHeight(true) + ' - ' + bottomEl.outerHeight() +') + '+bottomEl.outerHeight(true) + '='+bottomLoc);
|
||||
}
|
||||
let newHeight = viewPort.height() - (bottomLoc - scaleEl.outerHeight(true));
|
||||
console.log("newHeight = " + viewPort.height() +" - " + bottomLoc + ' - ' + scaleEl.outerHeight(true)+'='+newHeight);
|
||||
let newWidth = ratio * newHeight;
|
||||
|
||||
// Let's recalculate everything and reduce the height a little. Necessary if "padding" is specified for "wrapperEventVideo"
|
||||
padding = parseInt(container.css("padding-left")) + parseInt(container.css("padding-right"));
|
||||
newWidth -= padding;
|
||||
newHeight = newWidth / ratio;
|
||||
|
||||
console.log("newWidth = ", newWidth, "container width:", container.innerWidth()-padding);
|
||||
|
||||
if (newHeight < 0 || newWidth > container.innerWidth()-padding) {
|
||||
if (newHeight < 0 || newWidth > container.width()) {
|
||||
// Doesn't fit on screen anyways?
|
||||
newWidth = container.innerWidth()-padding;
|
||||
newWidth = container.width();
|
||||
newHeight = newWidth / ratio;
|
||||
}
|
||||
console.log("newWidth = " + newWidth);
|
||||
let autoScale = Math.round(newWidth / baseWidth * SCALE_BASE * panZoomScale);
|
||||
/* IgorA100 not required due to new "Scale" algorithm & new PanZoom (may 2024)
|
||||
const scales = $j('#scale option').map(function() {
|
||||
|
@ -735,6 +726,7 @@ function scaleToFit(baseWidth, baseHeight, scaleEl, bottomEl, container, panZoom
|
|||
}
|
||||
*/
|
||||
if (autoScale < 10) autoScale = 10;
|
||||
console.log(`container.height=${container.height()}, newWidth=${newWidth}, newHeight=${newHeight}, container width=${container.width()}, autoScale=${autoScale}`);
|
||||
return {width: Math.floor(newWidth), height: Math.floor(newHeight), autoScale: autoScale};
|
||||
}
|
||||
|
||||
|
@ -1162,9 +1154,13 @@ function stringToNumber(str) {
|
|||
return parseInt(str.replace(/\D/g, ''));
|
||||
}
|
||||
|
||||
const font = new FontFaceObserver('Material Icons', {weight: 400});
|
||||
font.load().then(function() {
|
||||
function loadFontFaceObserver() {
|
||||
const font = new FontFaceObserver('Material Icons', {weight: 400});
|
||||
font.load().then(function() {
|
||||
$j('.material-icons').css('display', 'inline-block');
|
||||
}, function() {
|
||||
}, function() {
|
||||
$j('.material-icons').css('display', 'inline-block');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
loadFontFaceObserver();
|
||||
|
|
|
@ -192,7 +192,7 @@ echo 'var rangeTimeSecs='.($maxTimeSecs - $minTimeSecs + 1).";\n";
|
|||
if ( isset($defaultCurrentTimeSecs) )
|
||||
echo 'var currentTimeSecs=parseInt('.$defaultCurrentTimeSecs.");\n";
|
||||
else
|
||||
echo 'var currentTimeSecs=parseInt('.(($minTimeSecs + $maxTimeSecs)/2).");\n";
|
||||
echo 'var currentTimeSecs=parseInt('.$minTimeSecs.");\n";
|
||||
|
||||
echo 'var speeds=[';
|
||||
for ( $i=0; $i < count($speeds); $i++ )
|
||||
|
|
|
@ -8,6 +8,8 @@ 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 currentMonitor;
|
||||
|
||||
var classSidebarL = 'col-sm-3'; /* id="sidebar" */
|
||||
var classSidebarR = 'col-sm-2'; /* id="ptzControls" */
|
||||
|
@ -132,36 +134,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 +147,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 +296,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 +311,7 @@ function onPlay() {
|
|||
setButtonState('fastRevBtn', 'inactive');
|
||||
}
|
||||
} else {
|
||||
setButtonState('stopBtn', 'unavail');
|
||||
//setButtonState('stopBtn', 'unavail');
|
||||
if (monitorStreamReplayBuffer) {
|
||||
setButtonState('fastFwdBtn', 'unavail');
|
||||
setButtonState('slowFwdBtn', 'unavail');
|
||||
|
@ -359,14 +324,21 @@ function onPlay() {
|
|||
function streamCmdPlay(action) {
|
||||
onPlay();
|
||||
if (action) {
|
||||
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 +346,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,13 +596,25 @@ 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();
|
||||
} else if (!event.target.closest('#wrapperMonitor')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (panZoomEnabled) {
|
||||
//event.preventDefault();
|
||||
if (event.target.id) {
|
||||
//We are looking for an object with an ID, because there may be another element in the button.
|
||||
var obj = event.target;
|
||||
} else {
|
||||
var obj = event.target.parentElement;
|
||||
const obj = targetId ? event.target : event.target.parentElement;
|
||||
if (!obj) {
|
||||
console.log("No obj found", targetId, event.target, event.target.parentElement);
|
||||
return;
|
||||
}
|
||||
if (obj.className.includes('btn-zoom-out') || obj.className.includes('btn-zoom-in')) return;
|
||||
|
||||
|
@ -639,8 +627,12 @@ function handleClick(event) {
|
|||
}
|
||||
}
|
||||
|
||||
if (obj.getAttribute('id').indexOf("liveStream") >= 0) {
|
||||
const obj_id = obj.getAttribute('id');
|
||||
if (obj_id) {
|
||||
if (obj_id.indexOf("liveStream") >= 0)
|
||||
zmPanZoom.click(monitorId);
|
||||
} else {
|
||||
console.log("obj does not have an id", obj);
|
||||
}
|
||||
} else {
|
||||
// +++ Old ZoomPan algorithm.
|
||||
|
@ -909,92 +901,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 +918,7 @@ function initPage() {
|
|||
}
|
||||
|
||||
if ((monitorType != 'WebSite') && monitorData.length) {
|
||||
streamStart();
|
||||
streamStart(monitor);
|
||||
if (window.history.length == 1) {
|
||||
$j('#closeControl').html('');
|
||||
}
|
||||
|
@ -1052,6 +959,172 @@ 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');
|
||||
setTimeout(dataOnClick, 100);
|
||||
}
|
||||
|
||||
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;
|
||||
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');
|
||||
applyMonitorControllable();
|
||||
streamPrepareStart(currentMonitor);
|
||||
zmPanZoom.init();
|
||||
loadFontFaceObserver();
|
||||
//document.getElementById('monitor').classList.remove('hidden-shift');
|
||||
}
|
||||
|
||||
function applyMonitorControllable() {
|
||||
const ptzToggle = document.getElementById('ptzToggle');
|
||||
if (!ptzToggle) {
|
||||
console.log('ptz toggle is not present. Likely OPT_CONTROL is off');
|
||||
return;
|
||||
}
|
||||
if (currentMonitor.monitorControllable) {
|
||||
const ptzShow = getCookie('ptzShow');
|
||||
|
||||
ptzToggle.classList.remove("disabled");
|
||||
ptzToggle.disabled=false;
|
||||
sidebarControls.html(currentMonitor.ptzControls);
|
||||
if (ptzShow) {
|
||||
sidebarControls.show();
|
||||
ptzToggle.classList.remove("btn-secondary");
|
||||
ptzToggle.classList.add("btn-primary");
|
||||
} else {
|
||||
sidebarControls.hide();
|
||||
ptzToggle.classList.remove("btn-primary");
|
||||
ptzToggle.classList.add("btn-secondary");
|
||||
}
|
||||
} else {
|
||||
ptzToggle.classList.add("disabled");
|
||||
ptzToggle.disabled=true;
|
||||
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 +1146,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 +1186,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 +1193,22 @@ 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();
|
||||
|
||||
currentMonitor = monitorData.find((o) => {
|
||||
return parseInt(o["id"]) === monitorId;
|
||||
});
|
||||
if (currentMonitor) {
|
||||
applyMonitorControllable();
|
||||
}
|
||||
streamPrepareStart();
|
||||
} // initPage
|
||||
|
||||
function watchFullscreen() {
|
||||
|
@ -1159,7 +1226,7 @@ function watchFullscreen() {
|
|||
}
|
||||
|
||||
function watchAllEvents() {
|
||||
window.location.replace(document.getElementById('allEventsBtn').getAttribute('data-url'));
|
||||
window.location.replace(currentMonitor.urlForAllEvents);
|
||||
}
|
||||
|
||||
var intervalId;
|
||||
|
@ -1181,13 +1248,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 +1272,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 +1296,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 +1329,7 @@ function cycleToggle(e) {
|
|||
button.toggleClass('btn-secondary');
|
||||
button.toggleClass('btn-primary');
|
||||
changeObjectClass();
|
||||
changeSize();
|
||||
monitorsSetScale(monitorId);
|
||||
}
|
||||
|
||||
function ptzToggle(e) {
|
||||
|
@ -1245,7 +1344,7 @@ function ptzToggle(e) {
|
|||
button.toggleClass('btn-secondary');
|
||||
button.toggleClass('btn-primary');
|
||||
changeObjectClass();
|
||||
changeSize();
|
||||
monitorsSetScale(monitorId);
|
||||
}
|
||||
|
||||
function changeRate(e) {
|
||||
|
@ -1310,16 +1409,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') {
|
||||
if (monitorStream !== false) {
|
||||
//monitorStream used on Watch page.
|
||||
if (monitorStream) {
|
||||
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 +1553,30 @@ document.onvisibilitychange = () => {
|
|||
TimerHideShow = clearTimeout(TimerHideShow);
|
||||
TimerHideShow = setTimeout(function() {
|
||||
//Stop monitor when closing or hiding page
|
||||
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
|
||||
|
@ -61,11 +72,11 @@ monitorData[monitorData.length] = {
|
|||
|
||||
var scale = '<?php echo $scale ?>';
|
||||
|
||||
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 ?>;
|
||||
const statusRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_STATUS ?>;
|
||||
const eventsRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_EVENTS ?>;
|
||||
const imageRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_IMAGE ?>;
|
||||
|
||||
var canStream = <?php echo canStream()?'true':'false' ?>;
|
||||
const canStream = <?php echo canStream()?'true':'false' ?>;
|
||||
|
||||
var imageControlMode = '<?php
|
||||
$control = $monitor->Control();
|
||||
|
|
|
@ -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;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$showPtzControls = false;
|
||||
if ($hasPtzControls) {
|
||||
$showPtzControls = true;
|
||||
|
@ -126,10 +134,10 @@ if (!empty($_REQUEST['mode']) and ($_REQUEST['mode']=='still' or $_REQUEST['mode
|
|||
}
|
||||
$options['mode'] = 'single';
|
||||
|
||||
if (!empty($_REQUEST['maxfps']) and validFloat($_REQUEST['maxfps']) and ($_REQUEST['maxfps']>0)) {
|
||||
$options['maxfps'] = validHtmlStr($_REQUEST['maxfps']);
|
||||
if (!empty($_REQUEST['maxfps']) and validNum($_REQUEST['maxfps']) and ($_REQUEST['maxfps']>0)) {
|
||||
$options['maxfps'] = validNum($_REQUEST['maxfps']);
|
||||
} else if (isset($_COOKIE['zmWatchRate'])) {
|
||||
$options['maxfps'] = validHtmlStr($_COOKIE['zmWatchRate']);
|
||||
$options['maxfps'] = validNum($_COOKIE['zmWatchRate']);
|
||||
} else {
|
||||
$options['maxfps'] = ''; // unlimited
|
||||
}
|
||||
|
@ -166,6 +174,7 @@ if ( !isset($scales[$scale])) {
|
|||
$options['scale'] = 0; //Somewhere something is spoiled because of this...
|
||||
|
||||
$streamQualitySelected = '0';
|
||||
# TODO input validation on streamquality
|
||||
if (isset($_REQUEST['streamQuality'])) {
|
||||
$streamQualitySelected = $_REQUEST['streamQuality'];
|
||||
} else if (isset($_COOKIE['zmStreamQuality'])) {
|
||||
|
@ -198,14 +207,19 @@ if (
|
|||
) {
|
||||
$options['scale'] = 0;
|
||||
}
|
||||
if ($monitor->JanusEnabled()) {
|
||||
|
||||
function getStreamModeMonitor($monitor) {
|
||||
if ($monitor->JanusEnabled()) {
|
||||
$streamMode = 'janus';
|
||||
} else if ($monitor->RTSP2WebEnabled()) {
|
||||
} else if ($monitor->RTSP2WebEnabled()) {
|
||||
$streamMode = $monitor->RTSP2WebType();
|
||||
} else {
|
||||
} else {
|
||||
$streamMode = getStreamMode();
|
||||
}
|
||||
return $streamMode;
|
||||
}
|
||||
|
||||
$streamMode = getStreamModeMonitor($monitor);
|
||||
noCacheHeaders();
|
||||
xhtmlHeaders(__FILE__, $monitor->Name().' - '.translate('Feed'));
|
||||
getBodyTopHTML();
|
||||
|
@ -254,6 +268,8 @@ echo getNavBarHTML() ?>
|
|||
<span class="material-icons md-18">open_with</span>
|
||||
</button>
|
||||
<?php
|
||||
} else {
|
||||
echo 'No ptz';
|
||||
}
|
||||
?>
|
||||
<span id="rateControl">
|
||||
|
@ -332,8 +348,34 @@ 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;
|
||||
if ($hasPtzControls) {
|
||||
foreach ( getSkinIncludes('includes/control_functions.php') as $includeFile )
|
||||
require_once $includeFile;
|
||||
}
|
||||
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) {
|
||||
$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 +384,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,11 +428,8 @@ 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>
|
||||
<?php
|
||||
}
|
||||
|
@ -479,14 +495,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>
|
||||
|
|
Loading…
Reference in New Issue