From 5d8db0a320a1cdca40160d1e25218233fd9f1a9c Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 10 Dec 2021 15:34:35 -0500 Subject: [PATCH] Merge cycle functionality into watch view. Add period dropdown, countdown timer, toggle the sidebar. Fix auth on statusAjax, and don't use status ajax unless we are in still mode. Apply some min-width to fps so they don't jump around. Only update their content if it has changed (fewer browser renders). --- web/skins/classic/css/base/views/watch.css | 53 ++-- web/skins/classic/views/js/watch.js | 242 +++++++++++----- web/skins/classic/views/js/watch.js.php | 74 +++-- web/skins/classic/views/watch.php | 308 +++++++++++++++------ 4 files changed, 482 insertions(+), 195 deletions(-) diff --git a/web/skins/classic/css/base/views/watch.css b/web/skins/classic/css/base/views/watch.css index 17bf1593d..64fb81b16 100644 --- a/web/skins/classic/css/base/views/watch.css +++ b/web/skins/classic/css/base/views/watch.css @@ -1,6 +1,8 @@ #header { - display: flex; - justify-content: space-between; +} + +#sidebar { + min-width: 140px; } #menuControls { @@ -19,19 +21,22 @@ #monitorStatus { margin: 4px auto; text-align: center; -} - -#monitorStatus #enableDisableAlarms { - float: left; -} - -#monitorStatus #forceCancelAlarm { - float: right; + display: inline-block; } #monitorStatus #monitorState { } +#replayStatus { + margin: 3px 0 2px; + text-align: center; + display: inline-block; +} + +#replayStatus > span { + padding: 0 4px; +} + #dvrControls { margin-top: 3px; margin-bottom: 2px; @@ -67,15 +72,6 @@ cursor: default; } -#replayStatus { - margin: 3px 0 2px; - text-align: center; - clear: both; -} - -#replayStatus > span { - padding: 0 4px; -} #events { margin: 0 auto; @@ -116,3 +112,22 @@ span.alert { background-color: #DCDCDC; } +.controlHeader { + width: 100%; +} + +#viewingFPS, +#captureFPS, +#analysisFPS +{ + display: inline-block; +} +#stateValue, +#viewingFPSValue, +#captureFPSValue, +#analysisFPSValue +{ + display: inline-block; + min-width: 40px; + text-align: right; +} diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js index 324e7f7e0..8a0f527c9 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -44,7 +44,7 @@ function ajaxRequest(params) { data.view = 'request'; data.request = 'watch'; data.mid = monitorId; - if ( auth_hash ) data.auth = auth_hash; + if (auth_hash) data.auth = auth_hash; $j.getJSON(thisUrl, data) .done(function(data) { @@ -94,8 +94,48 @@ function showPtzControls() { showMode = 'control'; } +function changeSize() { + var width = $j('#width').val(); + var height = $j('#height').val(); + + // Scale the frame + monitor_frame = $j('#imageFeed'); + if (!monitor_frame) { + console.log('Error finding frame'); + return; + } + if (width) monitor_frame.css('width', width); + if (height) monitor_frame.css('height', height); + + var streamImg = document.getElementById('liveStream'+monitorData[monIdx].id); + if (streamImg) { + if (streamImg.nodeName == 'IMG') { + let src = streamImg.src; + streamImg.src = ''; + src = src.replace(/width=[\.\d]+/i, 'width='+parseInt(width)); + src = src.replace(/height=[\.\d]+/i, 'height='+parseInt(height)); + src = src.replace(/rand=\d+/i, 'rand='+Math.floor((Math.random() * 1000000) )); + streamImg.src = src; + } + streamImg.style.width = width ? width : null; + streamImg.style.height = height ? height : null; + } else { + console.log('Did not find liveStream'+monitorData[monIdx].id); + } + $j('#scale').val(''); + setCookie('zmCycleScale', '', 3600); + setCookie('zmCycleWidth', width, 3600); + setCookie('zmCycleHeight', height, 3600); +} // end function changeSize() + function changeScale() { var scale = $j('#scale').val(); + $j('#width').val('auto'); + $j('#height').val('auto'); + setCookie('zmCycleScale', scale, 3600); + setCookie('zmCycleWidth', 'auto', 3600); + setCookie('zmCycleHeight', 'auto', 3600); + var newWidth; var newHeight; var autoScale; @@ -104,7 +144,7 @@ function changeScale() { // 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' || scale == 'auto') { - var newSize = scaleToFit(monitorWidth, monitorHeight, $j('#liveStream'+monitorId), $j('#replayStatus')); + const newSize = scaleToFit(monitorWidth, monitorHeight, $j('#liveStream'+monitorId), $j('#replayStatus')); newWidth = newSize.width; newHeight = newSize.height; autoScale = newSize.autoScale; @@ -118,16 +158,18 @@ function changeScale() { var streamImg = $j('#liveStream'+monitorId); if (streamImg) { - var oldSrc = streamImg.attr('src'); - streamImg.attr('src', ''); - // This is so that we don't waste bandwidth and let the browser do all the scaling. - if (autoScale > 100) autoScale = 100; - if (scale > 100) scale = 100; - var newSrc = oldSrc.replace(/scale=\d+/i, 'scale='+((scale == 'auto' || scale == '0') ? autoScale : scale)); + if (streamImg.nodeName == 'IMG') { + const oldSrc = streamImg.attr('src'); + streamImg.attr('src', ''); + // This is so that we don't waste bandwidth and let the browser do all the scaling. + if (autoScale > 100) autoScale = 100; + if (scale > 100) scale = 100; + const newSrc = oldSrc.replace(/scale=\d+/i, 'scale='+((scale == 'auto' || scale == '0') ? autoScale : scale)); - streamImg.width(newWidth); - streamImg.height(newHeight); - streamImg.attr('src', newSrc); + streamImg.width(newWidth); + streamImg.height(newHeight); + streamImg.attr('src', newSrc); + } } else { console.error('No element found for liveStream'+monitorId); } @@ -200,9 +242,15 @@ function getStreamCmdResponse(respObj, respText) { // 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) { streamStatus = respObj.status; - $j('#fpsValue').text(streamStatus.fps); - $j('#capturefpsValue').text(streamStatus.capturefps); - $j('#analysisfpsValue').text(streamStatus.analysisfps); + 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); @@ -287,31 +335,19 @@ function getStreamCmdResponse(respObj, respText) { // Try to reload the image stream. var streamImg = $j('#liveStream'+monitorId); if (streamImg) { - var oldSrc = streamImg.attr('src'); - var newSrc = oldSrc.replace(/auth=\w+/i, 'auth='+streamStatus.auth); - if (oldSrc != newSrc) { - streamImg.attr('src', newSrc); - table.bootstrapTable('refresh'); + const oldSrc = streamImg.attr('src'); + if (oldSrc) { + const newSrc = oldSrc.replace(/auth=\w+/i, 'auth='+streamStatus.auth); + if (oldSrc != newSrc) { + streamImg.attr('src', newSrc); + table.bootstrapTable('refresh'); + } } } } // end if have a new auth hash } // end if respObj.status } else { checkStreamForErrors('getStreamCmdResponse', respObj);//log them - // Try to reload the image stream. - // If it's an auth error, we should reload the whole page. - console.log("have error"); - //window.location.reload(); - var streamImg = $j('#liveStream'+monitorId); - if (streamImg) { - var oldSrc = streamImg.attr('src'); - var newSrc = oldSrc.replace(/rand=\d+/i, 'rand='+Math.floor((Math.random() * 1000000) )); - - streamImg.attr('src', newSrc); - console.log('Changing livestream src to ' + newSrc); - } else { - console.log('Unable to find streamImg liveStream'); - } } var streamCmdTimeout = statusRefreshTimeout; @@ -368,6 +404,7 @@ function streamCmdPlay(action) { } function streamCmdReq(data) { + if (auth_hash) data.auth = auth_hash; $j.getJSON(monitorUrl + '?view=request&request=stream&connkey='+connKey, data) .done(getStreamCmdResponse) .fail(getStreamCmdError); @@ -386,10 +423,7 @@ function streamCmdStop(action) { setButtonState('fastRevBtn', 'unavail'); } if (action) { - var data = {}; - if (auth_hash) data.auth = auth_hash; - data.command = CMD_STOP; - streamCmdReq(data); + streamCmdReq({command: CMD_STOP}); } setButtonState('stopBtn', 'unavail'); setButtonState('playBtn', 'active'); @@ -407,7 +441,6 @@ function streamCmdFastFwd(action) { } if (action) { var data = {}; - if (auth_hash) data.auth = auth_hash; data.command = CMD_FASTFWD; streamCmdReq(data); } @@ -425,7 +458,6 @@ function streamCmdSlowFwd(action) { } if (action) { var data = {}; - if (auth_hash) data.auth = auth_hash; data.command = CMD_SLOWFWD; streamCmdReq(data); } @@ -447,7 +479,6 @@ function streamCmdSlowRev(action) { } if (action) { var data = {}; - if (auth_hash) data.auth = auth_hash; data.command = CMD_SLOWREV; streamCmdReq(data); } @@ -469,7 +500,6 @@ function streamCmdFastRev(action) { } if (action) { var data = {}; - if (auth_hash) data.auth = auth_hash; data.command = CMD_FASTREV; streamCmdReq(data); } @@ -477,7 +507,6 @@ function streamCmdFastRev(action) { function streamCmdZoomIn(x, y) { var data = {}; - if (auth_hash) data.auth = auth_hash; data.x = x; data.y = y; data.command = CMD_ZOOMIN; @@ -486,14 +515,12 @@ function streamCmdZoomIn(x, y) { function streamCmdZoomOut() { var data = {}; - if (auth_hash) data.auth = auth_hash; data.command = CMD_ZOOMOUT; streamCmdReq(data); } function streamCmdScale(scale) { var data = {}; - if (auth_hash) data.auth = auth_hash; data.command = CMD_SCALE; data.scale = scale; streamCmdReq(data); @@ -501,7 +528,6 @@ function streamCmdScale(scale) { function streamCmdPan(x, y) { var data = {}; - if (auth_hash) data.auth = auth_hash; data.x = x; data.y = y; data.command = CMD_PAN; @@ -510,11 +536,11 @@ function streamCmdPan(x, y) { function streamCmdQuery() { var data = {}; - if (auth_hash) data.auth = auth_hash; data.command = CMD_QUERY; streamCmdReq(data); } +/* getStatusCmd is used when not streaming, since there is no persistent zms */ function getStatusCmdResponse(respObj, respText) { watchdogOk('status'); if (statusCmdTimer) { @@ -522,32 +548,33 @@ function getStatusCmdResponse(respObj, respText) { } if (respObj.result == 'Ok') { - $j('#fpsValue').text(respObj.monitor.FrameRate); + $j('#captureFPSValue').text(respObj.monitor.FrameRate); setAlarmState(respObj.monitor.Status); } else { checkStreamForErrors('getStatusCmdResponse', respObj); } var statusCmdTimeout = statusRefreshTimeout; - if ( alarmState == STATE_ALARM || alarmState == STATE_ALERT ) { + if (alarmState == STATE_ALARM || alarmState == STATE_ALERT) { statusCmdTimeout = statusCmdTimeout/5; } statusCmdTimer = setTimeout(statusCmdQuery, statusCmdTimeout); } function statusCmdQuery() { - $j.getJSON(monitorUrl + '?view=request&request=status&entity=monitor&element[]=Status&element[]=FrameRate&id='+monitorId) + $j.getJSON(monitorUrl + '?view=request&request=status&entity=monitor&element[]=Status&element[]=FrameRate&id='+monitorId+'&'+auth_relay) .done(getStatusCmdResponse) .fail(logAjaxFail); - streamCmdTimer = null; + statusCmdTimer = null; } function alarmCmdReq(data) { + if (auth_hash) data.auth = auth_hash; $j.getJSON(monitorUrl + '?view=request&request=alarm&id='+monitorId, data) .done(getAlarmCmdResponse) .fail(function(jqxhr, textStatus, error) { - if ( textStatus === "timeout" ) { + if (textStatus === 'timeout') { streamCmdQuery(); } else { logAjaxFail(jqxhr, textStatus, error); @@ -561,14 +588,12 @@ function getAlarmCmdResponse(respObj, respText) { function cmdDisableAlarms() { var data = {}; - if (auth_hash) data.auth = auth_hash; data.command = 'disableAlarms'; alarmCmdReq(data); } function cmdEnableAlarms() { var data = {}; - if (auth_hash) data.auth = auth_hash; data.command = 'enableAlarms'; alarmCmdReq(data); } @@ -583,7 +608,6 @@ function cmdAlarm() { function cmdForceAlarm() { var data = {}; - if (auth_hash) data.auth = auth_hash; data.command = 'forceAlarm'; alarmCmdReq(data); if (window.event) window.event.preventDefault(); @@ -591,7 +615,6 @@ function cmdForceAlarm() { function cmdCancelForcedAlarm() { var data = {}; - if (auth_hash) data.auth = auth_hash; data.command = 'cancelForcedAlarm'; alarmCmdReq(data); if (window.event) window.event.preventDefault(); @@ -607,6 +630,7 @@ function cmdForce() { } function controlReq(data) { + if (auth_hash) data.auth = auth_hash; $j.getJSON(monitorUrl + '?view=request&request=control&id='+monitorId, data) .done(getControlResponse) .fail(logAjaxFail); @@ -639,16 +663,16 @@ function controlCmd(event) { var data = {}; if (event && (xtell || ytell)) { - var target = event.target; - var offset = $j(target).offset(); - var width = $j(target).width(); - var height = $j(target).height(); + const target = event.target; + const offset = $j(target).offset(); + const width = $j(target).width(); + const height = $j(target).height(); - var x = event.pageX - offset.left; - var y = event.pageY - offset.top; + const x = event.pageX - offset.left; + const y = event.pageY - offset.top; if (xtell) { - var xge = parseInt((x*100)/width); + let xge = parseInt((x*100)/width); if (xtell == -1) { xge = 100 - xge; } else if (xtell == 2) { @@ -657,7 +681,7 @@ function controlCmd(event) { data.xge = xge; } if (ytell) { - var yge = parseInt((y*100)/height); + let yge = parseInt((y*100)/height); if (ytell == -1) { yge = 100 - yge; } else if (ytell == 2) { @@ -667,7 +691,6 @@ function controlCmd(event) { } } - if (auth_hash) data.auth = auth_hash; data.control = control; controlReq(data); @@ -678,7 +701,6 @@ function controlCmd(event) { function controlCmdImage(x, y) { var data = {}; - if (auth_hash) data.auth = auth_hash; data.scale = scale; data.control = imageControlMode; data.x = x; @@ -768,7 +790,6 @@ function reloadWebSite() { function updatePresetLabels() { var lblNdx = $j('#ctrlPresetForm option:selected').val(); - $j('#newLabel').val(labels[lblNdx]); } @@ -878,7 +899,7 @@ function initPage() { // Load the PTZ Preset modal into the DOM if (monitorControllable) getCtrlPresetModal(); // Load the settings modal into the DOM - if (monitorType == "Local") getSettingsModal(); + if (monitorType == 'Local') getSettingsModal(); } if (monitorType != 'WebSite') { @@ -886,15 +907,12 @@ function initPage() { statusCmdTimer = setTimeout(statusCmdQuery, (Math.random()+0.1)*statusRefreshTimeout); setInterval(watchdogCheck, statusRefreshTimeout*2, 'status'); } else { - streamCmdTimer = setTimeout(streamCmdQuery, (Math.random()+0.1)*statusRefreshTimeout); setInterval(watchdogCheck, statusRefreshTimeout*2, 'stream'); } if (canStreamNative || (streamMode == 'single')) { var streamImg = $j('#imageFeed img'); - if (!streamImg) { - streamImg = $j('#imageFeed object'); - } + if (!streamImg) streamImg = $j('#imageFeed object'); if (!streamImg) { console.error('No streamImg found for imageFeed'); } else { @@ -905,6 +923,10 @@ function initPage() { streamImg.click(function(event) { handleClick(event); }); + streamImg.on("error", function(thing) { + console.log("Error loading image"); + console.log(thing); + }); } } // end if have streamImg } // streamMode native or single @@ -944,6 +966,18 @@ function initPage() { $j('#settingsModal').modal('show'); }); + bindButton('#cyclePlayBtn', 'click', null, cycleStart); + bindButton('#cyclePauseBtn', 'click', null, cyclePause); + bindButton('#cycleNextBtn', 'click', null, cycleNext); + bindButton('#cyclePrevBtn', 'click', null, cyclePrev); + bindButton('#cycleToggle', 'click', null, cycleToggle); + bindButton('#cyclePeriod', 'change', null, cyclePeriodChange); + if (cycle) { + cycleStart(); + } else { + cyclePause(); + } + // Only enable the settings button for local cameras settingsBtn.prop('disabled', !(canView.Control && (monitorType == 'Local'))); @@ -972,7 +1006,6 @@ function initPage() { function watchFullscreen() { const btn = document.getElementById('fullscreenBtn'); - console.log(btn); if (btn.firstElementChild.innerHTML=='fullscreen') { const content = document.getElementById('content'); openFullscreen(content); @@ -985,5 +1018,70 @@ function watchFullscreen() { } } +var intervalId; +var secondsToCycle = 0; + +function nextCycleView() { + secondsToCycle --; + if (secondsToCycle<=0) { + window.location.replace('?view=watch&mid='+nextMid+'&mode='+mode+'&cycle=true'); + } + $j('#secondsToCycle').text(secondsToCycle); +} + +function cyclePause() { + clearInterval(intervalId); + $j('#cyclePauseBtn').hide(); + $j('#cyclePlayBtn').show(); +} + +function cycleStart() { + secondsToCycle = $j('#cyclePeriod').val(); + intervalId = setInterval(nextCycleView, 1000); + $j('#cyclePauseBtn').show(); + $j('#cyclePlayBtn').hide(); +} + +function cycleNext() { + monIdx ++; + if (monIdx >= monitorData.length) { + monIdx = 0; + } + if (!monitorData[monIdx]) { + console.log('No monitorData for ' + monIdx); + } + window.location.replace('?view=watch&cycle=true&mid='+monitorData[monIdx].id+'&mode='+mode); +} + +function cyclePrev() { + monIdx --; + if (monIdx < 0) { + monIdx = monitorData.length - 1; + } + if (!monitorData[monIdx]) { + console.log('No monitorData for ' + monIdx); + } + window.location.replace('?view=watch&cycle=true&mid='+monitorData[monIdx].id+'&mode='+mode); +} + +function cyclePeriodChange() { + const cyclePeriodSelect = $j('#cyclePeriod'); + secondsToCycle = cyclePeriodSelect.val(); + setCookie('zmCyclePeriod', secondsToCycle, 3600); +} +function cycleToggle(e) { + sidebar = $j('#sidebar'); + button = $j('#cycleToggle'); + if (sidebar.is(":visible")) { + sidebar.hide(); + setCookie('zmCycleShow', false, 3600); + } else { + sidebar.show(); + setCookie('zmCycleShow', true, 3600); + } + button.toggleClass('btn-secondary'); + button.toggleClass('btn-primary'); +} + // Kick everything off $j(document).ready(initPage); diff --git a/web/skins/classic/views/js/watch.js.php b/web/skins/classic/views/js/watch.js.php index 74a86100c..ab09d6ca5 100644 --- a/web/skins/classic/views/js/watch.js.php +++ b/web/skins/classic/views/js/watch.js.php @@ -1,21 +1,20 @@ // // Import constants // -var deleteString = ""; - -var enableAlarmsStr = ""; -var disableAlarmsStr = ""; -var forceAlarmStr = ""; -var cancelForcedAlarmStr = ""; var CMD_NONE = ; var CMD_PAUSE = ; @@ -34,14 +33,13 @@ var CMD_NEXT = ; var CMD_SEEK = ; var CMD_QUERY = ; -var SCALE_BASE = ; - var SOUND_ON_ALARM = ; var POPUP_ON_ALARM = ; var LIST_THUMBS = ; var streamMode = ""; var showMode = ""; +var cycle = ; var connKey = ''; var maxDisplayEvents = ; @@ -55,6 +53,28 @@ var monitorRefresh = 'Refresh() ?>'; var monitorStreamReplayBuffer = StreamReplayBuffer() ?>; var monitorControllable = Controllable()?'true':'false' ?>; +var monIdx = ''; +var nextMid = ""; +var mode = ""; + +var monitorData = new Array(); + +monitorData[monitorData.length] = { + 'id': Id() ?>, + 'width': ViewWidth() ?>, + 'height':ViewHeight() ?>, + 'url': 'UrlToIndex() ?>', + 'onclick': function(){window.location.assign( '?view=watch&mid=Id() ?>' );}, + 'type': 'Type() ?>', + 'refresh': 'Refresh() ?>' +}; + + +var SCALE_BASE = ; var scale = ''; var statusRefreshTimeout = ; @@ -63,17 +83,16 @@ var imageRefreshTimeout = ; var canStreamNative = ; -Control(); - if ( $control->CanMoveMap() ) { ?> -var imageControlMode = "moveMap"; -CanMoveRel() ) { ?> -var imageControlMode = "movePseudoMap"; -CanMoveCon() ) { ?> -var imageControlMode = "moveConMap"; - -var imageControlMode = null; - +var imageControlMode = 'Control(); +if ($control->CanMoveMap()) { + echo 'moveMap'; +} else if ($control->CanMoveRel()) { + echo 'movePseudoMap'; +} else if ($control->CanMoveCon()) { + echo 'moveConMap'; +} +?>'; var refreshApplet = ; var appletRefreshTime = ; @@ -81,17 +100,18 @@ var appletRefreshTime = ; var labels = new Array(); Id() ) ) as $row ) { - $labels[$row['Preset']] = $row['Label']; -} - -foreach ($labels as $index=>$label) { -?> -labels[] = ''; -Id())) as $row) { + $label = $labels[$row['Preset']] = $row['Label']; + echo 'labels['. validInt($index) .'] = '.validJsStr($label).'\''; } ?> +var deleteString = ""; +var enableAlarmsStr = ""; +var disableAlarmsStr = ""; +var forceAlarmStr = ""; +var cancelForcedAlarmStr = ""; var translate = { + "seconds": "", "Fullscreen": "", "Exit Fullscreen": "", }; diff --git a/web/skins/classic/views/watch.php b/web/skins/classic/views/watch.php index beab28ac1..58d24ac85 100644 --- a/web/skins/classic/views/watch.php +++ b/web/skins/classic/views/watch.php @@ -18,143 +18,296 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // -if ( !canView('Stream') ) { +if (!canView('Stream')) { $view = 'error'; return; } +require_once('includes/Monitor.php'); + +ob_start(); +include('_monitor_filters.php'); +$filterbar = ob_get_contents(); +ob_end_clean(); -if ( !isset($_REQUEST['mid']) ) { - $view = 'error'; - return; -} // This is for input sanitation -$mid = intval($_REQUEST['mid']); -if ( !visibleMonitor($mid) ) { +$mid = isset($_REQUEST['mid']) ? intval($_REQUEST['mid']) : 0; + +$widths = array( + 'auto' => translate('auto'), + '100%' => '100%', + '160px' => '160px', + '320px' => '320px', + '352px' => '352px', + '640px' => '640px', + '1280px' => '1280px', + '1920px' => '1920px' +); + +$heights = array( + 'auto' => translate('auto'), + '240px' => '240px', + '480px' => '480px', + '720px' => '720px', + '1080px' => '1080px', +); + +$monitors = array(); +$monitor_index = 0; +foreach ($displayMonitors as &$row) { + if ($row['Function'] == 'None') continue; + if ($mid and ($row['Id'] == $mid)) $monitor_index = count($monitors); + $monitors[] = new ZM\Monitor($row); + if (!isset($widths[$row['Width'].'px'])) { + $widths[$row['Width'].'px'] = $row['Width'].'px'; + } + if (!isset($heights[$row['Height'].'px'])) { + $heights[$row['Height'].'px'] = $row['Height'].'px'; + } + unset($row); +} # end foreach Monitor + +if (!$mid) { + $mid = $monitors[0]->Id(); + $monitor_index = 0; +} + +if (!visibleMonitor($mid)) { $view = 'error'; return; } -require_once('includes/Monitor.php'); $monitor = new ZM\Monitor($mid); - +$nextMid = ($monitor_index == count($monitors)-1) ? $monitors[0]->Id() : $monitors[$monitor_index+1]->Id(); +$cycle = isset($_REQUEST['cycle']) and ($_REQUEST['cycle'] == 'true'); +$showCycle = $cycle; +ZM\Error("Show cycle: $showCycle"); +if (isset($_COOKIE['zmCycleShow'])) { + $showCycle = $_COOKIE['zmCycleShow'] == 'true'; + ZM\Error("Show cycle: $showCycle"); +} else { + ZM\Error("Show cycle: not set"); +} #Whether to show the controls button $showPtzControls = ( ZM_OPT_CONTROL && $monitor->Controllable() && canView('Control') && $monitor->Type() != 'WebSite' ); -if ( isset($_REQUEST['scale']) ) { +$options = array(); +if (empty($_REQUEST['mode'])) { + $options['mode'] = canStream() ? 'stream' : 'still'; +} else { + $options['mode'] = validHtmlStr($_REQUEST['mode']); +} +zm_session_start(); + +$period = ZM_WEB_REFRESH_CYCLE; +if (isset($_REQUEST['period'])) { + $period = validInt($_REQUEST['period']); +} else if (isset($_COOKIE['zmCyclePeriod'])) { + $period = validInt($_COOKIE['zmCyclePeriod']); +} + +if (isset($_REQUEST['scale'])) { $scale = validInt($_REQUEST['scale']); } else if ( isset($_COOKIE['zmWatchScale'.$mid]) ) { $scale = $_COOKIE['zmWatchScale'.$mid]; } else { $scale = $monitor->DefaultScale(); } +$options['scale'] = $scale; + +if (isset($_REQUEST['width'])) { + $options['width'] = validInt($_REQUEST['width']); +} else if ( isset($_COOKIE['zmCycleWidth']) and $_COOKIE['zmCycleWidth'] ) { + $_SESSION['zmCycleWidth'] = $options['width'] = $_COOKIE['zmCycleWidth']; +#} elseif ( isset($_SESSION['zmCycleWidth']) and $_SESSION['zmCycleWidth'] ) { + #$options['width'] = $_SESSION['zmCycleWidth']; +} else { + $options['width'] = ''; +} +if (isset($_REQUEST['height'])) { + $options['height'] =validInt($_REQUEST['height']); +} else if (isset($_COOKIE['zmCycleHeight']) and $_COOKIE['zmCycleHeight']) { + $_SESSION['zmCycleHeight'] = $options['height'] = $_COOKIE['zmCycleHeight']; +#else if ( isset($_SESSION['zmCycleHeight']) and $_SESSION['zmCycleHeight'] ) + #$options['height'] = $_SESSION['zmCycleHeight']; +} else { + $options['height'] = ''; +} +session_write_close(); $connkey = generateConnKey(); - $streamMode = getStreamMode(); -$popup = ((isset($_REQUEST['popup'])) && ($_REQUEST['popup'] == 1)); - noCacheHeaders(); xhtmlHeaders(__FILE__, $monitor->Name().' - '.translate('Feed')); ?> +