diff --git a/web/js/MonitorStream.js b/web/js/MonitorStream.js index 54669a964..17f43c4b9 100644 --- a/web/js/MonitorStream.js +++ b/web/js/MonitorStream.js @@ -13,15 +13,22 @@ function MonitorStream(monitorData) { this.janusEnabled = monitorData.janusEnabled; this.scale = 100; this.status = null; - this.alarmState = STATE_IDLE; this.lastAlarmState = STATE_IDLE; + this.streamCmdTimer = null; this.streamCmdParms = { view: 'request', request: 'stream', connkey: this.connKey }; + this.ajaxQueue = null; this.type = monitorData.type; this.refresh = monitorData.refresh; + + this.buttons = {}; // index by name + this.setButton = function(name, element) { + this.buttons.name = element; + }; + this.element = null; this.getElement = function() { if (this.element) return this.element; @@ -36,7 +43,7 @@ function MonitorStream(monitorData) { this.show = function() { const stream = this.getElement(); if (!stream.src) { - stream.src = this.url_to_zms+"&mode=single&scale=100&connkey="+this.connKey; + stream.src = this.url_to_zms+"&mode=single&scale=100&connkey="+this.connKey+this.auth_relay; } }; @@ -48,7 +55,7 @@ function MonitorStream(monitorData) { const oldSrc = img.getAttribute('src'); if (!oldSrc) { - console.log("No src on img?!"); + console.log('No src on img?!'); console.log(img); return; } @@ -58,13 +65,10 @@ function MonitorStream(monitorData) { console.log("Scaling to: " + newscale); if (newscale == '0' || newscale == 'auto') { - let bottomElement = document.getElementById('replayStatus'); - if (!bottomElement) { - bottomElement = document.getElementById('monitorState'); - } + const bottomElement = document.getElementById('monitorState'+this.id); var newSize = scaleToFit(this.width, this.height, $j(img), $j(bottomElement)); - console.log(newSize); + //console.log(newSize); newWidth = newSize.width; newHeight = newSize.height; autoScale = parseInt(newSize.autoScale); @@ -83,11 +87,8 @@ function MonitorStream(monitorData) { } img.setAttribute('src', newSrc); }; - this.start = function(delay) { - // Step 1 make sure we are streaming instead of a static image - const stream = this.getElement(); - if (!stream) return; + this.start = function(delay) { if (this.janusEnabled) { var id = parseInt(this.id); var server; @@ -106,47 +107,46 @@ function MonitorStream(monitorData) { attachVideo(id); return; } + + const stream = this.getElement(); + if (!stream) return; if (!stream.src) { - // Website Monitors won't have an img tag + // Website Monitors won't have an img tag, neither will video console.log('No src for #liveStream'+this.id); console.log(stream); return; } + // Step 1 make sure we are streaming instead of a static image src = stream.src.replace(/mode=single/i, 'mode=jpeg'); - if ( -1 == src.search('connkey') ) { + if (-1 == src.search('connkey')) { src += '&connkey='+this.connKey; } - if ( stream.src != src ) { + if (stream.src != src) { console.log("Setting to streaming: " + src); stream.src = ''; stream.src = src; } - setTimeout(this.streamCmdQuery.bind(this), delay); + setTimeout(this.statusQuery.bind(this), delay); }; + this.stop = function() { if ( 0 ) { - var stream = $j('#liveStream'+this.id)[0]; - if ( ! stream ) { - console.log('No live stream'); - return; - } + const stream = this.getElement(); + if (!stream) return; src = stream.src.replace(/mode=jpeg/i, 'mode=single'); - if ( stream.src != src ) { + if (stream.src != src) { console.log("Setting to stopped"); stream.src = ''; stream.src = src; } } - this.streamCmdParms.command = CMD_STOP; - this.streamCmdReq(this.streamCmdParms); + this.streamCommand(CMD_STOP); }; this.pause = function() { - this.streamCmdParms.command = CMD_PAUSE; - this.streamCmdReq(this.streamCmdParms); + this.streamCommand(CMD_PAUSE); }; this.play = function() { - this.streamCmdParms.command = CMD_PLAY; - this.streamCmdReq(this.streamCmdParms); + this.streamCommand(CMD_PLAY); }; this.eventHandler = function(event) { @@ -154,77 +154,142 @@ function MonitorStream(monitorData) { }; this.onclick = function(evt) { - var el = evt.currentTarget; - var id = el.getAttribute("data-monitor-id"); - var url = '?view=watch&mid='+id; - evt.preventDefault(); - window.location.assign(url); + console.log('onclick'); }; - this.setup_onclick = function() { - var el = document.getElementById('imageFeed'+this.id); - if ( el ) el.addEventListener('click', this.onclick, false); + this.setup_onclick = function(func) { + this.onclick = func; + const el = this.getElement(); + if (!el) return; + el.addEventListener('click', this.onclick, false); }; + this.disable_onclick = function() { - document.getElementById('imageFeed'+this.id).removeEventListener('click', this.onclick ); + const el = this.getElement(); + if (!el) return; + el.removeEventListener('click', this.onclick); + }; + + this.onpause = function() { + console.log('onpause'); + }; + this.setup_onpause = function(func) { + this.onpause = func; + }; + this.onplay = null; + this.setup_onplay = function(func) { + this.onplay = func; }; this.setStateClass = function(jobj, stateClass) { - if ( !jobj ) { + if (!jobj) { + console.log("No obj in setStateClass"); return; } - if ( !jobj.hasClass( stateClass ) ) { - if ( stateClass != 'alarm' ) jobj.removeClass('alarm'); - if ( stateClass != 'alert' ) jobj.removeClass('alert'); - if ( stateClass != 'idle' ) jobj.removeClass('idle'); + if (!jobj.hasClass(stateClass)) { + if (stateClass != 'alarm') jobj.removeClass('alarm'); + if (stateClass != 'alert') jobj.removeClass('alert'); + if (stateClass != 'idle') jobj.removeClass('idle'); jobj.addClass(stateClass); } }; + this.setAlarmState = function(alarmState) { + var stateClass = ''; + if (alarmState == STATE_ALARM) { + stateClass = 'alarm'; + } else if (alarmState == STATE_ALERT) { + stateClass = 'alert'; + } + + const stateValue = $j('#stateValue'+this.id); + if (stateValue.length) { + stateValue.text(stateStrings[alarmState]); + if (stateClass) { + stateValue.addClass(stateClass); + } else { + stateValue.removeClass(); + } + } else { + console.log("No statevalue"); + } + //const monitorState = $j('#monitorState'+this.id); + //if (monitorState.length) this.setStateClass(monitorState, stateClass); + + const isAlarmed = ( alarmState == STATE_ALARM || alarmState == STATE_ALERT ); + const wasAlarmed = ( this.lastAlarmState == STATE_ALARM || this.lastAlarmState == STATE_ALERT ); + + const newAlarm = ( isAlarmed && !wasAlarmed ); + const oldAlarm = ( !isAlarmed && wasAlarmed ); + + if (newAlarm) { + if (SOUND_ON_ALARM) { + // Enable the alarm sound + if (!msieVer) { + $j('#alarmSound').removeClass('hidden'); + } else { + $j('#MediaPlayer').trigger('play'); + } + } + if (POPUP_ON_ALARM) { + window.focus(); + } + if (this.onalarm) { + this.onalarm(); + } + } + if (oldAlarm) { // done with an event do a refresh + if (SOUND_ON_ALARM) { + // Disable alarm sound + if (!msieVer) { + $j('#alarmSound').addClass('hidden'); + } else { + $j('#MediaPlayer').trigger('pause'); + } + } + if (this.onalarm) { + this.onalarm(); + } + } + this.lastAlarmState = alarmState; + }; // end function setAlarmState( currentAlarmState ) + + this.onalarm = null; + this.setup_onalarm = function(func) { + this.onalarm = func; + }; + this.onFailure = function(jqxhr, textStatus, error) { + // Assuming temporary problem, retry in a bit. setTimeout(this.streamCmdQuery.bind(this), 1000*statusRefreshTimeout); logAjaxFail(jqxhr, textStatus, error); }; this.getStreamCmdResponse = function(respObj, respText) { - var stream = $j('#liveStream'+this.id)[0]; - + var stream = this.getElement(); if (!stream) { - console.log('No live stream'); return; } //watchdogOk('stream'); - if (streamCmdTimer) { - streamCmdTimer = clearTimeout(streamCmdTimer); + if (this.streamCmdTimer) { + this.streamCmdTimer = clearTimeout(this.streamCmdTimer); } - if ( respObj.result == 'Ok' ) { - if ( respObj.status ) { - this.status = respObj.status; - this.alarmState = this.status.state; - - var stateClass = ''; - if ( this.alarmState == STATE_ALARM ) { - stateClass = 'alarm'; - } else if ( this.alarmState == STATE_ALERT ) { - stateClass = 'alert'; - } else { - stateClass = 'idle'; - } + if (respObj.result == 'Ok') { + if (respObj.status) { + const streamStatus = this.status = respObj.status; if ( ( (typeof COMPACT_MONTAGE === 'undefined') || !COMPACT_MONTAGE) && (this.type != 'WebSite') ) { - const viewingFPSValue = $j('#vewingFPSValue'+this.id); + const viewingFPSValue = $j('#viewingFPSValue'+this.id); const captureFPSValue = $j('#captureFPSValue'+this.id); const analysisFPSValue = $j('#analysisFPSValue'+this.id); - const stateValue = $j('#stateValue'+this.id); - const monitorState = $j('#monitorState'+this.id); if (viewingFPSValue.length && (viewingFPSValue.text != this.status.fps)) { viewingFPSValue.text(this.status.fps); @@ -236,40 +301,104 @@ function MonitorStream(monitorData) { captureFPSValue.text(this.status.capturefps); } - if (stateValue.length) stateValue.text(stateStrings[this.alarmState]); - if (monitorState.length) this.setStateClass(monitorState, stateClass); - } - - this.setStateClass($j('#monitor'+this.id), stateClass); - - /*Stream could be an applet so can't use moo tools*/ - //stream.parentNode().className = stateClass; - - var isAlarmed = ( this.alarmState == STATE_ALARM || this.alarmState == STATE_ALERT ); - var wasAlarmed = ( this.lastAlarmState == STATE_ALARM || this.lastAlarmState == STATE_ALERT ); - - var newAlarm = ( isAlarmed && !wasAlarmed ); - var oldAlarm = ( !isAlarmed && wasAlarmed ); - - if (newAlarm) { - if (false && SOUND_ON_ALARM) { - // Enable the alarm sound - $j('#alarmSound').removeClass('hidden'); + const levelValue = $j('#levelValue'); + if (levelValue.length) { + levelValue.text(this.status.level); + var newClass = 'ok'; + if (this.status.level > 95) { + newClass = 'alarm'; + } else if (this.status.level > 80) { + newClass = 'alert'; + } + levelValue.removeClass(); + levelValue.addClass(newClass); } - if ((typeof POPUP_ON_ALARM !== 'undefined') && POPUP_ON_ALARM) { - windowToFront(); + + const delayString = secsToTime(this.status.delay); + + if (this.status.paused == true) { + $j('#modeValue'+this.id).text('Paused'); + $j('#rate'+this.id).addClass('hidden'); + $j('#delayValue'+this.id).text(delayString); + $j('#delay'+this.id).removeClass('hidden'); + $j('#level'+this.id).removeClass('hidden'); + this.onpause(); + } else if (this.status.delayed == true) { + $j('#modeValue'+this.id).text('Replay'); + $j('#rateValue'+this.id).text(this.status.rate); + $j('#rate'+this.id).removeClass('hidden'); + $j('#delayValue'+this.id).text(delayString); + $j('#delay'+this.id).removeClass('hidden'); + $j('#level'+this.id).removeClass('hidden'); + if (this.status.rate == 1) { + if (this.onplay) this.onplay(); + } else if (this.status.rate > 0) { + if (this.status.rate < 1) { + streamCmdSlowFwd(false); + } else { + streamCmdFastFwd(false); + } + } else { + if (this.status.rate > -1) { + streamCmdSlowRev(false); + } else { + streamCmdFastRev(false); + } + } // rate + } else { + $j('#modeValue'+this.id).text('Live'); + $j('#rate'+this.id).addClass('hidden'); + $j('#delay'+this.id).addClass('hidden'); + $j('#level'+this.id).addClass('hidden'); + if (this.onplay) this.onplay(); + } // end if paused or delayed + + $j('#zoomValue'+this.id).text(this.status.zoom); + if ('zoomOutBtn' in this.buttons) { + if (this.status.zoom == '1.0') { + setButtonState('zoomOutBtn', 'unavail'); + } else { + setButtonState('zoomOutBtn', 'inactive'); + } } - } - if (false && SOUND_ON_ALARM) { - if ( oldAlarm ) { - // Disable alarm sound - $j('#alarmSound').addClass('hidden'); + } // end if compact montage + + this.setAlarmState(this.status.state); + + if (canEdit.Monitors) { + if (streamStatus.enabled) { + if ('enableAlarmButton' in this.buttons) { + this.buttons.enableAlarmButton.addClass('disabled'); + this.buttons.enableAlarmButton.prop('title', disableAlarmsStr); + } + if ('forceAlarmButton' in this.buttons) { + if (streamStatus.forced) { + this.buttons.forceAlarmButton.addClass('disabled'); + this.buttons.forceAlarmButton.prop('title', cancelForcedAlarmStr); + } else { + this.buttons.forceAlarmButton.removeClass('disabled'); + this.buttons.forceAlarmButton.prop('title', forceAlarmStr); + } + this.buttons.forceAlarmButton.prop('disabled', false); + } + } else { + if ('enableAlarmButton' in this.buttons) { + this.buttons.enableAlarmButton.removeClass('disabled'); + this.buttons.enableAlarmButton.prop('title', enableAlarmsStr); + } + if ('forceAlarmButton' in this.buttons) { + this.buttons.forceAlarmButton.prop('disabled', true); + } } - } + if ('enableAlarmButton' in this.buttons) { + this.buttons.enableAlarmButton.prop('disabled', false); + } + } // end if canEdit.Monitors + if (this.status.auth) { if (this.status.auth != this.auth_hash) { // Try to reload the image stream. - if (stream) { + if (stream && stream.src) { const oldsrc = stream.src; stream.src = ''; stream.src = oldsrc.replace(/auth=\w+/i, 'auth='+this.status.auth); @@ -283,23 +412,25 @@ function MonitorStream(monitorData) { console.error(respObj.message); // Try to reload the image stream. if (stream) { - if ( stream.src ) { + if (stream.src) { console.log('Reloading stream: ' + stream.src); src = stream.src.replace(/rand=\d+/i, 'rand='+Math.floor((Math.random() * 1000000) )); - if ( src != stream.src ) { + // Maybe navbar updated auth FIXME + if (src != stream.src) { stream.src = src; } else { console.log("Failed to update rand on stream src"); } - } else { } } else { console.log('No stream to reload?'); } } // end if Ok or not + }; - this.lastAlarmState = this.alarmState; - setTimeout(this.streamCmdQuery.bind(this), statusRefreshTimeout); + this.statusQuery = function() { + this.streamCmdQuery(CMD_QUERY); + setTimeout(this.statusQuery.bind(this), statusRefreshTimeout); }; this.streamCmdQuery = function(resent) { @@ -310,15 +441,44 @@ function MonitorStream(monitorData) { } }; - if ( this.type != 'WebSite' ) { + this.streamCommand = function(command) { + if (typeof(command) == 'object') { + for (const key in command) this.streamCmdParms[key] = command[key]; + } else { + this.streamCmdParms.command = command; + } + this.streamCmdReq(this.streamCmdParms); + }; + + this.alarmCommand = function(command) { + if (this.ajaxQueue) { + this.ajaxQueue.abort(); + } + const alarmCmdParms = Object.assign({}, this.streamCmdParms); + alarmCmdParms.request = 'alarm'; + alarmCmdParms.command = command; + alarmCmdParms.id = this.id; + + this.ajaxQueue = jQuery.ajaxQueue({ + url: this.url, + data: alarmCmdParms, dataType: "json"}) + .done(this.getStreamCmdResponse.bind(this)) + .fail(this.onFailure.bind(this)); + }; + + if (this.type != 'WebSite') { + $j.ajaxSetup({timeout: AJAX_TIMEOUT}); + if (auth_hash) { + this.streamCmdParms.auth = auth_hash; + } else if ( auth_relay ) { + this.streamCmdParms.auth_relay = ''; + } + this.streamCmdReq = function(streamCmdParms) { - if ( auth_hash ) { - this.streamCmdParms.auth = auth_hash; - } else if ( auth_relay ) { - this.streamCmdParms.auth_relay = ''; + if (this.ajaxQueue) { + this.ajaxQueue.abort(); } - $j.ajaxSetup({timeout: AJAX_TIMEOUT}); - $j.getJSON(this.url, streamCmdParms) + this.ajaxQueue = jQuery.ajaxQueue({url: this.url, data: streamCmdParms, dataType: "json"}) .done(this.getStreamCmdResponse.bind(this)) .fail(this.onFailure.bind(this)); }; @@ -326,7 +486,7 @@ function MonitorStream(monitorData) { this.analyse_frames = true; this.show_analyse_frames = function(toggle) { this.analyse_frames = toggle; - this.streamCmdParms.command = this.analyse_frames?CMD_ANALYZE_ON:CMD_ANALYZE_OFF; + this.streamCmdParms.command = this.analyse_frames ? CMD_ANALYZE_ON : CMD_ANALYZE_OFF; this.streamCmdReq(this.streamCmdParms); }; } // end function MonitorStream