var loadedLiveGrids = {} var monitorPops = {} var liveGridElements = {} var runningJpegStreams = {} var liveGrid = $('#monitors_live') var liveGridOpenCountElements = $('.liveGridOpenCount') var liveGridOpenCount = 0 // var onLiveStreamInitiateExtensions = [] function onLiveStreamInitiate(callback){ onLiveStreamInitiateExtensions.push(callback) } var onLiveStreamCloseExtensions = [] function onLiveStreamClose(callback){ onLiveStreamCloseExtensions.push(callback) } var onSignalCheckLiveStreamExtensions = [] function onSignalCheckLiveStream(callback){ onSignalCheckLiveStreamExtensions.push(callback) } var onBuildStreamElementExtensions = [] function onBuildStreamElement(callback){ onBuildStreamElementExtensions.push(callback) } // function setLiveGridOpenCount(addOrRemove){ liveGridOpenCount += addOrRemove liveGridOpenCountElements.text(liveGridOpenCount) } function getLiveGridData(){ return liveGrid.data('gridstack') } function getMonitorsPerRow(){ var x switch(dashboardOptions().montage){ case'1': x = '12' break; case'2': x = '6' break; case'3': x = '4' break; case'4': x = '3' break; case'5': x = '5' break; case'6': x = '2' break; default://3 x = '4' break; } return x } function saveLiveGridBlockPositions() { var monitors = {} liveGrid.find(" .monitor_item").each(function(n,v){ var el = $(v) var item = {} item.ke = el.attr('data-ke') item.mid = el.attr('data-mid') item.x = el.attr('data-gs-x') item.y = el.attr('data-gs-y') item.height = el.attr('data-gs-height') item.width = el.attr('data-gs-width') monitors[item.ke+''+item.mid] = item }) $user.details.monitorOrder = monitors; mainSocket.f({f:'monitorOrder',monitorOrder:monitors}) } function buildStreamElementHtml(streamType){ var html = '' if(window.jpegModeOn === true){ html = ''; }else{ switch(streamType){ case'hls':case'flv':case'mp4': html = ``; break; case'mjpeg': html = ''; break; case'jpeg': html = ''; break; default://base64//h265 html = ''; break; } $.each(onBuildStreamElementExtensions,function(n,extender){ var newHtml = extender(streamType) html = newHtml ? newHtml : html }) } return html } function resetMonitorCanvas(monitorId,initiateAfter,subStreamChannel){ var monitor = loadedMonitors[monitorId] var details = monitor.details var streamType = subStreamChannel ? details.substream ? details.substream.output.stream_type : 'hls' : details.stream_type if(!liveGridElements[monitorId])return; var streamBlock = liveGridElements[monitorId].monitorItem.find('.stream-block') closeLiveGridPlayer(monitorId,false) streamBlock.find('.stream-element').remove() streamBlock.append(buildStreamElementHtml(streamType)) if(initiateAfter)initiateLiveGridPlayer(monitor,subStreamChannel) } function replaceMonitorInfoInHtml(htmlString,monitor){ var monitorMutes = dashboardOptions().monitorMutes || {} return htmlString .replaceAll('$GROUP_KEY',monitor.ke) .replaceAll('$MONITOR_ID',monitor.mid) .replaceAll('$MONITOR_MODE',monitor.mode) .replaceAll('$MONITOR_NAME',monitor.name) .replaceAll('$MONITOR_MUTE_ICON',(monitorMutes[monitor.mid] !== 1 ? 'volume-up' : 'volume-off')); } function buildLiveGridBlock(monitor){ if(monitor.mode === 'stop'){ new PNotify({ title: lang.sorryNo, text: lang[`Cannot watch a monitor that isn't running.`], type: 'danger' }) return } var monitorDetails = safeJsonParse(monitor.details) var monitorLiveId = `monitor_live_${monitor.mid}` var subStreamChannel = monitor.subStreamChannel var streamType = subStreamChannel ? monitorDetails.substream ? monitorDetails.substream.output.stream_type : 'hls' : monitorDetails.stream_type var streamElement = buildStreamElementHtml(streamType) var streamBlockInfo = definitions['Monitor Stream Window'] if(!loadedLiveGrids[monitor.mid])loadedLiveGrids[monitor.mid] = {} var baseHtml = `
${streamBlockInfo.streamBlockPreHtml || ''}
${streamBlockInfo.streamBlockHudHtml || ''}
${streamBlockInfo.streamBlockHudControlsHtml || ''}
${streamElement}
${streamBlockInfo.gridBlockAfterContentHtml || ''}
` return replaceMonitorInfoInHtml(baseHtml,monitor) } function drawPtzControlsOnLiveGridBlock(monitorId){ var monitorItem = $('#monitor_live_' + monitorId) var ptzControls = monitorItem.find('.PTZ_controls'); if(ptzControls.length>0){ ptzControls.remove() }else{ var html = `
${safeJsonParse(loadedMonitors[monitorId].details,{}).is_onvif === '1' ? `
${lang['Set Home']}
` : ``}
` monitorItem.append(html) } } function drawVideoCardToMiniList(monitorId,video,skipLimitCheck){ var theVideoList = liveGridElements[monitorId].miniVideoList if(!skipLimitCheck){ var rowsDrawn = theVideoList.find('.video-row') if(rowsDrawn.length > 10)rowsDrawn.last().remove() } theVideoList.prepend(createVideoRow(video,`col-12 mb-2`)) } function loadVideoMiniList(monitorId){ getVideos({ monitorId: monitorId, limit: 10, },function(data){ var videos = data.videos $.each(videos.reverse(),function(n,video){ drawVideoCardToMiniList(monitorId,video,true) }) }) } function drawLiveGridBlock(monitorConfig,subStreamChannel){ var monitorId = monitorConfig.mid if($('#monitor_live_' + monitorId).length === 0){ var x = 0; var y = 0; var monitorsPerRow = getMonitorsPerRow() var width = monitorsPerRow var height = width; var isSmallMobile = isMobile && window.innerWidth <= 812; var html = buildLiveGridBlock(monitorConfig) if($user.details && $user.details.monitorOrder && $user.details.monitorOrder[monitorConfig.ke+''+monitorId]){ var saved = $user.details.monitorOrder[monitorConfig.ke+''+monitorId]; x = saved.x; y = saved.y; width = saved.width; height = saved.height; } var autoPlacement = false if(dashboardOptions().switches.monitorOrder !== 1){ autoPlacement = true } liveGrid.data('gridstack').addWidget($(html), x, y, isSmallMobile ? 4 : height, isSmallMobile ? 4 : height, autoPlacement); var theBlock = $('#monitor_live_' + monitorId); var streamElement = theBlock.find('.stream-element') liveGridElements[monitorId] = { monitorItem: theBlock, streamElement: streamElement, eventObjects: theBlock.find('.stream-objects'), motionMeter: theBlock.find('.indifference .progress-bar'), motionMeterText: theBlock.find('.indifference .progress-bar span'), width: streamElement.width(), height: streamElement.height(), miniVideoList: theBlock.find('.videos-mini'), } try{ if(safeJsonParse(monitorConfig.details).control === "1"){ theBlock.find('[monitor="control_toggle"]').show() }else{ theBlock.find('.pad').remove(); theBlock.find('[monitor="control_toggle"]').hide() } }catch(re){ debugLog(re) } setCosmeticMonitorInfo(loadedMonitors[monitorId],subStreamChannel) setLiveGridOpenCount(1) } initiateLiveGridPlayer(loadedMonitors[monitorId],subStreamChannel) } function initiateLiveGridPlayer(monitor,subStreamChannel){ var livePlayerElement = loadedLiveGrids[monitor.mid] var details = monitor.details var groupKey = monitor.ke var monitorId = monitor.mid var loadedMonitor = loadedMonitors[monitorId] var loadedPlayer = loadedLiveGrids[monitor.mid] var websocketPath = checkCorrectPathEnding(location.pathname) + 'socket.io' var containerElement = $(`#monitor_live_${monitor.mid}`) var streamType = subStreamChannel ? details.substream ? details.substream.output.stream_type : 'hls' : details.stream_type if(location.search === '?p2p=1'){ websocketPath = '/socket.io' // websocketQuery.machineId = machineId } switch(streamType){ case'jpeg': startJpegStream(monitorId) break; case'b64': if(loadedPlayer.Base64 && loadedPlayer.Base64.connected){ loadedPlayer.Base64.disconnect() } loadedPlayer.Base64 = io(location.origin,{ path: websocketPath, query: websocketQuery, transports: ['websocket'], forceNew: false}) var ws = loadedPlayer.Base64 var buffer ws.on('diconnect',function(){ console.log('Base64 Stream Disconnected') }) ws.on('connect',function(){ ws.emit('Base64',{ auth: $user.auth_token, uid: $user.uid, ke: monitor.ke, id: monitor.mid, channel: subStreamChannel }) if(!loadedPlayer.ctx || loadedPlayer.ctx.length === 0){ loadedPlayer.ctx = containerElement.find('canvas'); } var ctx = loadedPlayer.ctx[0] var ctx2d = ctx.getContext("2d") loadedPlayer.image = new Image() var image = loadedPlayer.image image.onload = function() { loadedPlayer.imageLoading = false var x = 0 var y = 0 ctx.getContext("2d").drawImage(image,x,y,ctx.width,ctx.height) URL.revokeObjectURL(loadedPlayer.imageUrl) } ws.on('data',function(imageData){ try{ if(loadedPlayer.imageLoading === true)return console.log('drop'); loadedPlayer.imageLoading = true var arrayBufferView = new Uint8Array(imageData); var blob = new Blob( [ arrayBufferView ], { type: "image/jpeg" } ); loadedPlayer.imageUrl = URL.createObjectURL( blob ); loadedPlayer.image.src = loadedPlayer.imageUrl loadedPlayer.last_frame = 'data:image/jpeg;base64,'+base64ArrayBuffer(imageData) }catch(er){ debugLog('base64 frame') } // $.ccio.init('signal',d); }) }) break; case'mp4': setTimeout(function(){ var stream = containerElement.find('.stream-element'); var onPoseidonError = function(){ // setTimeout(function(){ // mainSocket.f({f:'monitor',ff:'watch_on',id:monitor.mid}) // },5000) } if(!loadedPlayer.PoseidonErrorCount)loadedPlayer.PoseidonErrorCount = 0 if(loadedPlayer.PoseidonErrorCount >= 5)return if(monitor.details.stream_flv_type==='ws'){ if(loadedPlayer.Poseidon){ loadedPlayer.Poseidon.stop() revokeVideoPlayerUrl(monitorId) } try{ loadedPlayer.Poseidon = new Poseidon({ video: stream[0], auth_token: $user.auth_token, ke: monitor.ke, uid: $user.uid, id: monitor.mid, url: location.origin, path: websocketPath, query: websocketQuery, onError : onPoseidonError, channel : subStreamChannel }) loadedPlayer.Poseidon.start(); }catch(err){ // onPoseidonError() console.log('onTryPoseidonError',err) } }else{ stream.attr('src',getApiPrefix(`mp4`)+'/'+monitor.mid + (subStreamChannel ? `/${subStreamChannel}` : '')+'/s.mp4?time=' + (new Date()).getTime()) stream[0].onerror = function(err){ console.error(err) } } },1000) break; case'flv': if (flvjs.isSupported()) { if(loadedPlayer.flv){ loadedPlayer.flv.destroy() revokeVideoPlayerUrl(monitorId) } var options = {}; if(monitor.details.stream_flv_type==='ws'){ if(monitor.details.stream_flv_maxLatency&&monitor.details.stream_flv_maxLatency!==''){ monitor.details.stream_flv_maxLatency = parseInt(monitor.details.stream_flv_maxLatency) }else{ monitor.details.stream_flv_maxLatency = 20000; } options = { type: 'flv', isLive: true, auth_token: $user.auth_token, ke: monitor.ke, uid: $user.uid, id: monitor.mid, maxLatency: monitor.details.stream_flv_maxLatency, hasAudio:false, url: location.origin, path: websocketPath, channel : subStreamChannel, query: websocketQuery } }else{ options = { type: 'flv', isLive: true, url: getApiPrefix(`flv`)+'/'+monitor.mid + (subStreamChannel ? `/${subStreamChannel}` : '')+'/s.flv' } } loadedPlayer.flv = flvjs.createPlayer(options); loadedPlayer.flv.attachMediaElement(containerElement.find('.stream-element')[0]); loadedPlayer.flv.on('error',function(err){ console.log(err) }); loadedPlayer.flv.load(); loadedPlayer.flv.play(); }else{ new PNotify({title:'Stream cannot be started',text:'FLV.js is not supported on this browser. Try another stream type.',type:'error'}); } break; case'hls': function createSteamNow(){ clearTimeout(loadedPlayer.m3uCheck) var url = getApiPrefix(`hls`) + '/' + monitor.mid + (subStreamChannel ? `/${subStreamChannel}` : '') + '/s.m3u8' $.get(url,function(m3u){ if(m3u == 'File Not Found'){ loadedPlayer.m3uCheck = setTimeout(function(){ createSteamNow() },2000) }else{ var video = containerElement.find('.stream-element')[0] if (isAppleDevice) { video.src = url; video.addEventListener('loadedmetadata', function() { setTimeout(function(){ video.play(); },3000) }, false); }else{ var hlsOptions = safeJsonParse(dashboardOptions().hlsOptions) || {} if(hlsOptions instanceof String){ hlsOptions = {} new PNotify({ title: lang['Invalid JSON'], text: lang.hlsOptionsInvalid, type: `warning`, }) } if(loadedPlayer.hls){ loadedPlayer.hls.destroy() revokeVideoPlayerUrl(monitorId) } loadedPlayer.hls = new Hls(hlsOptions) loadedPlayer.hls.loadSource(url) loadedPlayer.hls.attachMedia(video) loadedPlayer.hls.on(Hls.Events.MANIFEST_PARSED,function() { if (video.paused) { video.play(); } }); } } }) } createSteamNow() break; case'mjpeg': var liveStreamElement = containerElement.find('.stream-element') var setSource = function(){ liveStreamElement.attr('src',getApiPrefix(`mjpeg`)+'/'+monitorId + (subStreamChannel ? `/${subStreamChannel}` : '')) liveStreamElement.unbind('ready') liveStreamElement.ready(function(){ setTimeout(function(){ liveStreamElement.contents().find("body").append('') },1000) }) } setSource() liveStreamElement.on('error',function(err){ setTimeout(function(){ setSource() },4000) }) break; } $.each(onLiveStreamInitiateExtensions,function(n,extender){ extender(streamType,monitor,loadedPlayer,subStreamChannel) }) var monitorMutes = dashboardOptions().monitorMutes || {} if(dashboardOptions().switches.monitorMuteAudio === 1){ containerElement.find('video').each(function(n,el){ el.muted = "muted" }) }else{ var hasFocus = windowFocus && window.hadFocus $.each(loadedMonitors,function(frontId,monitor){ setTimeout(() => { var monitorId = monitor.mid var muted = monitorMutes[monitorId] try{ var vidEl = $('.monitor_item[mid="' + monitorId + '"] video')[0] if(vidEl.length === 0)return; if(muted === 1){ vidEl.muted = true }else{ if(hasFocus){ vidEl.muted = false }else{ console.error('User must have window active to unmute.') } } }catch(err){ // console.log(err) } },2000) }) } //initiate signal check if(streamType !== 'useSubstream'){ var signalCheckInterval = (isNaN(loadedMonitor.details.signal_check) ? 10 : parseFloat(loadedMonitor.details.signal_check)) * 1000 * 60 if(signalCheckInterval > 0){ clearInterval(loadedPlayer.signal) loadedPlayer.signal = setInterval(function(){ signalCheckLiveStream({ mid: monitorId, checkSpeed: 1000, }) },signalCheckInterval); } } } function revokeVideoPlayerUrl(monitorId){ try{ URL.revokeObjectURL(liveGridElements[monitorId].streamElement[0].src) }catch(err){ debugLog(err) } } function closeLiveGridPlayer(monitorId,killElement){ try{ var livePlayerElement = loadedLiveGrids[monitorId] if(livePlayerElement){ if(livePlayerElement.hls){livePlayerElement.hls.destroy()} if(livePlayerElement.Poseidon){livePlayerElement.Poseidon.stop()} if(livePlayerElement.Base64){livePlayerElement.Base64.disconnect()} if(livePlayerElement.dash){livePlayerElement.dash.reset()} if(livePlayerElement.jpegInterval){ stopJpegStream(monitorId) } $.each(onLiveStreamCloseExtensions,function(n,extender){ extender(livePlayerElement) }) } if(liveGridElements[monitorId])revokeVideoPlayerUrl(monitorId) clearInterval(livePlayerElement.signal) }catch(err){ console.log(err) } if(killElement){ var theElement = $('#monitor_live_'+monitorId) if(theElement.length > 0){ getLiveGridData().removeWidget(theElement) setLiveGridOpenCount(-1) delete(loadedLiveGrids[monitorId]) delete(liveGridElements[monitorId]) } } } function callMonitorToLiveGrid(v){ var watchedOn = dashboardOptions().watch_on || {} if(watchedOn[v.ke] && watchedOn[v.ke][v.mid] === 1 && loadedMonitors[v.mid] && loadedMonitors[v.mid].mode !== 'stop'){ mainSocket.f({f:'monitor',ff:'watch_on',id:v.mid}) openLiveGrid() } } function loadPreviouslyOpenedLiveGridBlocks(){ $.getJSON(getApiPrefix(`monitor`),function(data){ $.each(data,function(n,v){ callMonitorToLiveGrid(v) }) setTimeout(function(){ sortListMonitors() if(dashboardOptions().switches.jpegMode === 1){ mainSocket.f({ f: 'monitor', ff: 'jpeg_on' }) } },1000) drawMonitorGroupList() }) } function closeAllLiveGridPlayers(rememberClose){ var watchedOn = dashboardOptions().watch_on || {} $.each(watchedOn,function(n,groupOfMons){ $.each(groupOfMons,function(monitorId,monitor){ if(monitor === 1){ mainSocket.f({f:'monitor',ff:'watch_off',id: monitorId}) } }) }) } function saveLiveGridBlockOpenState(monitorId,groupKey,state){ var openBlocks = dashboardOptions().watch_on || {} openBlocks[groupKey] = openBlocks[groupKey] ? openBlocks[groupKey] : {} openBlocks[groupKey][monitorId] = state || 0 dashboardOptions('watch_on',openBlocks) } function openLiveGrid(){ if(tabTree.name !== 'liveGrid'){ openTab('liveGrid',{}) } } function popOutMonitor(monitorId){ var monitorPop = monitorPops[monitorId] function finish(img){ if(monitorPop){ monitorPop.close() } monitorPop = window.open(getApiPrefix() + '/embed/' + $user.ke + '/' + monitorId + '/fullscreen|jquery|relative|gui','pop_' + monitorId + $user.auth_token,'height='+img.height+',width='+img.width); } if(loadedLiveGrids[monitorId]){ getSnapshot(loadedMonitors[monitorId],function(url){ $('#temp').html('') var img=$('#temp img')[0] img.onload = function(){ finish(img) } img.src = url }) }else{ var img = { height: 720, width: 1280 } finish(img) } } function fullScreenLiveGridStream(monitorItem){ var videoElement = monitorItem.find('.stream-element') monitorItem.addClass('fullscreen') if(videoElement.is('canvas')){ var theBody = $('body') videoElement.attr('height',theBody.height()) videoElement.attr('width',theBody.width()) } fullScreenInit(videoElement[0]) } function toggleJpegMode(){ var sendData = { f: 'monitor', ff: 'jpeg_on' } if(window.jpegModeOn === true){ sendData.ff = 'jpeg_off' } mainSocket.f(sendData) } function startJpegStream(monitorId){ if(loadedLiveGrids[monitorId]){ var monitor = loadedMonitors[monitorId] var loadedBlock = loadedLiveGrids[monitorId] var jpegInterval = !isNaN(monitor.details.jpegInterval) ? parseFloat(monitor.details.jpegInterval) : 1 resetMonitorCanvas(monitorId,false) var streamElement = $('#monitor_live_' + monitorId + ' .stream-element'); // stopJpegStream(monitorId) var jpegUrl = getApiPrefix('jpeg') + '/' + monitorId + '/s.jpg?time=' function drawNewFrame(){ streamElement.attr('src',jpegUrl + (new Date()).getTime()) } streamElement.on('load',function(){ loadedBlock.jpegInterval = setTimeout(drawNewFrame,1000/jpegInterval) }).on('error',function(){ loadedBlock.jpegInterval = setTimeout(drawNewFrame,1000/jpegInterval) }) drawNewFrame() } } function stopJpegStream(monitorId){ var livePlayerElement = loadedLiveGrids[monitorId] if(!livePlayerElement)return; try{ liveGridElements[monitorId].streamElement.off('load').off('error') clearTimeout(livePlayerElement.jpegInterval) }catch(err){ console.log(err) console.log(monitorId) } } function startAllJpegStreams(monitorId){ $.each(loadedMonitors,function(n,monitor){ startJpegStream(monitor.mid) }) } function stopAllJpegStreams(monitorId){ $.each(loadedMonitors,function(n,monitor){ stopJpegStream(monitor.mid) }) } function canBackgroundStream(){ return tabTree.name === 'liveGrid' && dashboardOptions().switches.backgroundStream === 1 } function resetLiveGridDimensionsInMemory(monitorId){ var theRef = liveGridElements[monitorId] theRef.width = theRef.streamElement.width() theRef.height = theRef.streamElement.height() } function resetAllLiveGridDimensionsInMemory(monitorId){ $.each(liveGridElements,function(monitorId,data){ resetLiveGridDimensionsInMemory(monitorId) }) } function signalCheckLiveStream(options){ try{ var monitorId = options.mid var monitorConfig = loadedMonitors[monitorId] var liveGridData = liveGridElements[monitorId] var monitorItem = liveGridData.monitorItem var monitorDetails = monitorConfig.details var checkCount = 0 var base64Data = null; var checkSpeed = options.checkSpeed || 1000 var subStreamChannel = monitor.subStreamChannel var streamType = subStreamChannel ? monitorDetails.substream ? monitorDetails.substream.output.stream_type : 'hls' : monitorDetails.stream_type function failedStreamCheck(){ if(monitorConfig.signal_check_log == 1){ logWriterDraw('[mid="'+monitorId+'"]',{ log: { type: 'Stream Check', msg: lang.clientStreamFailedattemptingReconnect } }) } mainSocket.f({f:'monitor',ff:'watch_on',id:monitorId}); } function succeededStreamCheck(){ if(monitorConfig.signal_check_log == 1){ logWriterDraw('[mid="'+monitorId+'"]',{ log: { type: 'Stream Check', msg : lang.Success } }) } } function executeCheck(){ switch(streamType){ case'b64': monitorItem.resize() break; case'hls':case'flv':case'mp4': if(monitorItem.find('video')[0].paused){ failedStreamCheck() }else{ succeededStreamCheck() } break; default: if(dashboardOptions().jpeg_on === true){return} getSnapshot({ monitor: loadedMonitors[monitorId], },function(url){ base64Data = url; setTimeout(function(){ getSnapshot({ monitor: loadedMonitors[monitorId], },function(url){ if(base64Data === url){ if(checkCount < 3){ ++checkCount; setTimeout(function(){ executeCheck(); },checkSpeed) }else{ failedStreamCheck() } }else{ succeededStreamCheck() } }); },checkSpeed) }); break; } $.each(onSignalCheckLiveStreamExtensions,function(n,extender){ extender(streamType,monitorItem) }) } executeCheck(); }catch(err){ var errorStack = err.stack; function phraseFoundInErrorStack(x){return errorStack.indexOf(x) > -1} if(phraseFoundInErrorStack("The HTMLImageElement provided is in the 'broken' state.")){ mainSocket.f({f:'monitor',ff:'watch_on',id:monitorId}); } clearInterval(liveGridData.signal); delete(liveGridData.signal); } } $(document).ready(function(e){ liveGrid .on('dblclick','.stream-hud',function(){ $(this).parents('[data-mid]').find('[monitor="fullscreen"]').click(); }) $('body') .resize(function(){ resetAllLiveGridDimensionsInMemory() }) .on('click','.launch-live-grid-monitor',function(){ var monitorId = $(this).parents('[data-mid]').attr('data-mid') // if(isMobile){ // createLivePlayerTab(loadedMonitors[monitorId]) // }else{ mainSocket.f({ f: 'monitor', ff: 'watch_on', id: monitorId }) openLiveGrid() // } }) .on('click','.reconnect-live-grid-monitor',function(){ var monitorId = $(this).parents('[data-mid]').attr('data-mid') mainSocket.f({ f: 'monitor', ff: 'watch_on', id: monitorId }) }) .on('click','.close-live-grid-monitor',function(){ var monitorId = $(this).parents('[data-mid]').attr('data-mid') mainSocket.f({ f: 'monitor', ff: 'watch_off', id: monitorId }) setTimeout(function(){ saveLiveGridBlockOpenState(monitorId,$user.ke,0) },1000) }) .on('click','.snapshot-live-grid-monitor',function(){ var monitorId = $(this).parents('[data-mid]').attr('data-mid') getSnapshot({ monitor: loadedMonitors[monitorId], },function(url){ $('#temp').html('a').find('a')[0].click(); }) }) .on('click','.toggle-live-grid-monitor-logs',function(){ var monitorItem = $(this).parents('[data-mid]') var monitorId = monitorItem.attr('data-mid') monitorItem.toggleClass('show_data') var dataBlocks = monitorItem.find('.stream-block,.mdl-data_window') if(monitorItem.hasClass('show_data')){ loadVideoMiniList(monitorId) dataBlocks.addClass('col-md-6').removeClass('col-md-12') }else{ dataBlocks.addClass('col-md-12').removeClass('col-md-6') } }) .on('click','.toggle-live-grid-monitor-ptz-controls',function(){ var monitorItem = $(this).parents('[data-mid]').attr('data-mid') drawPtzControlsOnLiveGridBlock(monitorItem) }) .on('click','.toggle-live-grid-monitor-menu,.mdl-overlay-menu-backdrop',function(){ var monitorItem = $(this).parents('[data-mid]') var monitorId = monitorItem.attr('data-mid') monitorItem.find('.mdl-overlay-menu-backdrop').toggleClass('hidden') }) .on('click','.mdl-overlay-menu',function(e){ e.stopPropagation() return false; }) .on('click','.toggle-live-grid-monitor-fullscreen',function(){ var monitorItem = $(this).parents('[data-mid]') fullScreenLiveGridStream(monitorItem) }) .on('click','.run-live-grid-monitor-pop',function(){ var monitorId = $(this).parents('[data-mid]').attr('data-mid') popOutMonitor(monitorId) }) .on('click','.toggle-monitor-substream',function(){ var monitorId = $(this).parents('[data-mid]').attr('data-mid') toggleSubStream(monitorId) }) .on('click','.run-live-grid-monitor-ptz',function(){ var el = $(this) var monitorId = el.parents('[data-mid]').attr('data-mid') var switchChosen = el.attr('data-ptz-control') runPtzCommand(monitorId,switchChosen) }) .on('click','.run-monitor-detection-trigger-test',function(){ var el = $(this) var monitorId = el.parents('[data-mid]').attr('data-mid') runTestDetectionTrigger(monitorId) }) $('.open-all-monitors').click(function(){ $.each(loadedMonitors,function(monitorId,monitor){ mainSocket.f({ f: 'monitor', ff: 'watch_on', id: monitor.mid }) openLiveGrid() }) }) $('.close-all-monitors').click(function(){ $.each(loadedMonitors,function(monitorId,monitor){ mainSocket.f({ f: 'monitor', ff: 'watch_off', id: monitor.mid }) setTimeout(function(){ saveLiveGridBlockOpenState(monitorId,$user.ke,0) },1000) }) }) liveGrid .gridstack({ cellHeight: 80, verticalMargin: 0, }) .on('dragstop', function(event,ui){ setTimeout(function(){ saveLiveGridBlockPositions() },700) }) .on('gsresizestop', function(){ resetAllLiveGridDimensionsInMemory() saveLiveGridBlockPositions() }); addOnTabReopen('liveGrid', function () { loadPreviouslyOpenedLiveGridBlocks() }) addOnTabAway('liveGrid', function () { closeAllLiveGridPlayers() }) onInitWebsocket(function (d){ loadPreviouslyOpenedLiveGridBlocks() }) onWebSocketEvent(function (d){ switch(d.f){ case'init_success': // loadPreviouslyOpenedLiveGridBlocks() break; case'video_build_success': d.status = 1 d.mid = d.id || d.mid if(liveGridElements[d.mid] && liveGridElements[d.mid].streamElement)drawVideoCardToMiniList(d.mid,createVideoLinks(d),false) break; case'monitor_watch_off':case'monitor_stopping': var monitorId = d.mid || d.id closeLiveGridPlayer(monitorId,(d.f === 'monitor_watch_off')) break; case'monitor_status': if( tabTree.name === 'liveGrid' && ( d.code === 2 || d.code === 3 ) ){ var monitorId = d.mid || d.id setTimeout(function(){ callMonitorToLiveGrid(loadedMonitors[monitorId]) },2000) } break; case'substream_start': loadedMonitors[d.mid].subStreamChannel = d.channel setTimeout(() => { resetMonitorCanvas(d.mid,true,d.channel) },3000) break; case'substream_end': loadedMonitors[d.mid].subStreamChannel = null resetMonitorCanvas(d.mid,true,null) break; case'monitor_watch_on': var monitorId = d.mid || d.id var loadedMonitor = loadedMonitors[monitorId] var subStreamChannel = d.subStreamChannel if(!loadedMonitor.subStreamChannel && loadedMonitor.details.stream_type === 'useSubstream'){ toggleSubStream(monitorId,function(){ drawLiveGridBlock(loadedMonitors[monitorId],subStreamChannel) saveLiveGridBlockOpenState(monitorId,$user.ke,1) }) }else{ drawLiveGridBlock(loadedMonitors[monitorId],subStreamChannel) saveLiveGridBlockOpenState(monitorId,$user.ke,1) } break; case'mode_jpeg_off': window.jpegModeOn = false $.each(loadedMonitors,function(n,v){ stopJpegStream(v.mid) resetMonitorCanvas(v.mid) initiateLiveGridPlayer(v) }) $('body').removeClass('jpegMode') break; case'mode_jpeg_on': window.jpegModeOn = true startAllJpegStreams() $('body').addClass('jpegMode') break; case'detector_trigger': var monitorId = d.id var liveGridElement = liveGridElements[monitorId] if(liveGridElement){ var monitorElement = liveGridElement.monitorItem var livePlayerElement = loadedLiveGrids[monitorId] if(d.doObjectDetection === true){ monitorElement.addClass('doObjectDetection') clearTimeout(livePlayerElement.detector_trigger_doObjectDetection_timeout) livePlayerElement.detector_trigger_doObjectDetection_timeout = setTimeout(function(){ monitorElement.removeClass('doObjectDetection') },3000) }else{ monitorElement.removeClass('doObjectDetection') } if(d.details.matrices&&d.details.matrices.length>0){ drawMatrices(d,{ theContainer: liveGridElement.eventObjects, height: liveGridElement.height, width: liveGridElement.width, }) } if(d.details.confidence){ var eventConfidence = d.details.confidence if(eventConfidence > 100)eventConfidence = 100 liveGridElement.motionMeter.css('width',eventConfidence + '%'); liveGridElement.motionMeterText[0].innerHtml = d.details.confidence+'% change in '+d.details.name+'' } monitorElement.addClass('detector_triggered') clearTimeout(livePlayerElement.detector_trigger_timeout); livePlayerElement.detector_trigger_timeout = setTimeout(function(){ monitorElement.removeClass('detector_triggered'); liveGridElement.eventObjects.find('.stream-detected-object,.stream-detected-point').remove() },800); playAudioAlert() var monitorPop = monitorPops[monitorId] if($user.details.event_mon_pop === '1' && (!monitorPop || monitorPop.closed === true)){ popOutMonitor(monitorId) } // console.log({ // ke: d.ke, // mid: monitorId, // log: { // type: lang['Event Occurred'], // msg: d.details, // } // }) } break; } }) $(window).focus(function(){ if(canBackgroundStream()){ loadPreviouslyOpenedLiveGridBlocks() } }).blur(function(){ if(canBackgroundStream()){ closeAllLiveGridPlayers() } }) dashboardSwitchCallbacks.monitorOrder = function(toggleState){ if(toggleState !== 1){ $('.monitor_item').attr('data-gs-auto-position','yes') }else{ $('.monitor_item').attr('data-gs-auto-position','no') } } dashboardSwitchCallbacks.monitorMuteAudio = function(toggleState){ var monitorMutes = dashboardOptions().monitorMutes || {} $('.monitor_item video').each(function(n,vidEl){ var el = $(this) var monitorId = el.parents('[data-mid]').attr('data-mid') if(toggleState === 1){ el.attr('muted','muted') }else{ if(monitorMutes[monitorId] !== 1){ el.removeAttr('muted') } } }) } dashboardSwitchCallbacks.jpegMode = toggleJpegMode })