diff options
| author | Pliable Pixels <pliablepixels@gmail.com> | 2017-09-21 12:49:18 -0400 |
|---|---|---|
| committer | Pliable Pixels <pliablepixels@gmail.com> | 2017-09-21 12:49:18 -0400 |
| commit | b28028ac4082842143b0f528d6bc539da6ccb419 (patch) | |
| tree | 1e26ea969a781ed8e323fca4e3c76345113fc694 /www/js/EventModalCtrl.js | |
| parent | 676270d21beed31d767a06c89522198c77d5d865 (diff) | |
mega changes, including updates and X
Diffstat (limited to 'www/js/EventModalCtrl.js')
| -rw-r--r-- | www/js/EventModalCtrl.js | 1873 |
1 files changed, 1873 insertions, 0 deletions
diff --git a/www/js/EventModalCtrl.js b/www/js/EventModalCtrl.js new file mode 100644 index 00000000..b8a7acbc --- /dev/null +++ b/www/js/EventModalCtrl.js @@ -0,0 +1,1873 @@ +// Common Controller for the montage view +/* jshint -W041 */ +/* jslint browser: true*/ +/* global saveAs, cordova,StatusBar,angular,console,ionic, moment, Chart */ + +angular.module('zmApp.controllers').controller('EventModalCtrl', ['$scope', '$rootScope', 'zm', 'NVRDataModel', '$ionicSideMenuDelegate', '$timeout', '$interval', '$ionicModal', '$ionicLoading', '$http', '$state', '$stateParams', '$ionicHistory', '$ionicScrollDelegate', '$q', '$sce', 'carouselUtils', '$ionicPopup', '$translate', '$filter', 'SecuredPopups', function($scope, $rootScope, zm, NVRDataModel, $ionicSideMenuDelegate, $timeout, $interval, $ionicModal, $ionicLoading, $http, $state, $stateParams, $ionicHistory, $ionicScrollDelegate, $q, $sce, carouselUtils, $ionicPopup, $translate, $filter, SecuredPopups) +{ + + // from parent scope + var currentEvent = $scope.currentEvent; + var nphTimer; + var eventQueryHandle; + $scope.loginData = NVRDataModel.getLogin(); + $scope.currentRate = '-'; + var timeFormat = 'MM/DD/YYYY HH:mm:ss'; + var event; + var gEvent; + var handle; + + var framearray = { + + labels: [], + datasets: [ + { + //label: '# of Votes', + backgroundColor: 'rgba(242, 12, 12, 0.5)', + borderColor: 'rgba(242, 12, 12, 0.5)', + data: [], + }] + }; + + var frameoptions = []; + + var eventImageDigits = 5; // failsafe + $scope.currentProgress = { + progress: 0 + }; + $scope.sliderProgress = { + progress: 0 + }; + NVRDataModel.getKeyConfigParams(0) + .then(function(data) + { + //console.log ("***GETKEY: " + JSON.stringify(data)); + eventImageDigits = parseInt(data); + NVRDataModel.log("Image padding digits reported as " + eventImageDigits); + }); + + $scope.animationInProgress = false; + $scope.imageFit = true; + // FIXME: This is a hack - for some reason + // the custom slider view is messed up till the image loads + // in modal view + $scope.showModalRangeSider = false; + $scope.isModalActive = true; + + $timeout(function() + { + $scope.showModalRangeSider = true; + + }, 2000); + + document.addEventListener("pause", onPause, false); + document.addEventListener("resume", onResume, false); + + $rootScope.authSession = "undefined"; + $ionicLoading.show( + { + template: $translate.instant('kNegotiatingStreamAuth'), + animation: 'fade-in', + showBackdrop: true, + duration: zm.loadingTimeout, + maxWidth: 300, + showDelay: 0 + }); + var ld = NVRDataModel.getLogin(); + + $scope.currentStreamMode = ld.gapless ? 'gapless' : 'single'; + NVRDataModel.log("Using stream mode " + $scope.currentStreamMode); + + NVRDataModel.debug("EventModalCtrl called from " + $ionicHistory.currentStateName()); + // This is not needed for event mode + + NVRDataModel.debug("Setting playback to " + $scope.streamMode); + + $rootScope.validMonitorId = $scope.monitors[0].Monitor.Id; + NVRDataModel.getAuthKey($rootScope.validMonitorId, (Math.floor((Math.random() * 999999) + 1)).toString()) + .then(function(success) + { + $ionicLoading.hide(); + $rootScope.authSession = success; + NVRDataModel.log("Modal: Stream authentication construction: " + $rootScope.authSession); + + }, + function(error) + { + + $ionicLoading.hide(); + NVRDataModel.debug("ModalCtrl: Error details of stream auth:" + error); + //$rootScope.authSession=""; + NVRDataModel.log("Modal: Error returned Stream authentication construction. Retaining old value of: " + $rootScope.authSession); + }); + + //-------------------------------------------------------------------------------------- + // Handles bandwidth change, if required + // + //-------------------------------------------------------------------------------------- + + $rootScope.$on("bandwidth-change", function(e, data) + { + // not called for offline, I'm only interested in BW switches + NVRDataModel.debug("Got network change:" + data); + var ds; + if (data == 'lowbw') + { + ds = $translate.instant('kLowBWDisplay'); + } + else + { + ds = $translate.instant('kHighBWDisplay'); + } + NVRDataModel.displayBanner('net', [ds]); + + var ld = NVRDataModel.getLogin(); + + $scope.singleImageQuality = (NVRDataModel.getBandwidth() == "lowbw") ? zm.eventSingleImageQualityLowBW : ld.singleImageQuality; + }); + + //------------------------------------------------------- + // we use this to reload the connkey if authkey changed + //------------------------------------------------------ + + $rootScope.$on("auth-success", function() + { + + NVRDataModel.debug("EventModalCtrl: Re-login detected, resetting everything & re-generating connkey"); + NVRDataModel.stopNetwork("Auth-Success inside EventModalCtrl"); + $scope.connKey = (Math.floor((Math.random() * 999999) + 1)).toString(); + //console.log ("********* OFFSET FROM AUTH SUCC"); + $timeout(function() + { + sendCommand('14', $scope.connKey, '&offset=' + $scope.currentProgress.progress); + }, 500); + //$timeout.cancel(eventQueryHandle); + //eventQueryHandle = $timeout (function(){checkEvent();}, zm.eventPlaybackQuery); + + }); + + //------------------------------------------------------- + // tap to pause + //------------------------------------------------------ + + $scope.togglePause = function() + { + $scope.isPaused = !$scope.isPaused; + NVRDataModel.debug("Paused is " + $scope.isPaused); + sendCommand($scope.isPaused ? '1' : '2', $scope.connKey); + + }; + + $scope.onPlayerReady = function(api) + { + + // we need this timeout to avoid load interrupting + // play -- I suppose its an angular digest foo thing + console.log ("*********** ON PLAY READY"); + handle = api; + + $ionicLoading.show( + { + template: "<ion-spinner icon='ripple' class='spinner-energized'></ion-spinner><br/>" + $translate.instant('kVideoLoading')+"...", + + }); + NVRDataModel.debug("Player is ready"); + $timeout(function() + { + handle.pause(); + handle.setPlayback(NVRDataModel.getLogin().videoPlaybackSpeed); + handle.play(); + NVRDataModel.debug ("*** Invoking play"); + + }, 300); + + // window.stop(); + }; + + $scope.onPlaybackUpdate = function(rate) + { + console.log ("UPDATED RATE TO "+rate); + var ld = NVRDataModel.getLogin(); + ld.videoPlaybackSpeed = rate; + NVRDataModel.setLogin(ld); + }; + + $scope.onCanPlay = function() + { + + console.log ("*********** CAN PLAY"); + $ionicLoading.hide(); + NVRDataModel.debug("This video can be played"); + $scope.videoObject.config.cuepoints.points = []; + // now set up cue points + NVRDataModel.debug("Setting cue points.."); + NVRDataModel.debug ("API-Total length:"+currentEvent.Event.Length); + NVRDataModel.debug ("Player-Total length:"+handle.totalTime/1000); + + for (var l=0; l<currentEvent.Frame.length; l++ ) + { + if (currentEvent.Frame[l].Type=='Alarm') + { + // var ft = moment(currentEvent.Frame[l].TimeStamp); + //var s = factor*Math.abs(st.diff(ft,'seconds')); + + var s = currentEvent.Frame[l].Delta; + + //console.log("START="+currentEvent.Event.StartTime); + //console.log("END="+currentEvent.Frame[l].TimeStamp); + NVRDataModel.debug ("alarm cue at:"+s+"s"); + $scope.videoObject.config.cuepoints.points.push({time:s}); + } + } + }; + + $scope.onVideoError = function(event) + { + $ionicLoading.hide(); + if (!$scope.isModalActive) return; + NVRDataModel.debug("player reported a video error:" + JSON.stringify(event)); + $rootScope.zmPopup = SecuredPopups.show('alert', + { + title: $translate.instant('kError'), + template: $rootScope.platformOS == 'desktop' ? $translate.instant('kVideoError') : $translate.instant('kVideoErrorMobile'), + okText: $translate.instant('kButtonOk'), + cancelText: $translate.instant('kButtonCancel'), + }); + + }; + + //------------------------------------------------------- + // This is what we call every zm.EventQueryInterval + // it really only queries to get status to it can display + // zms takes care of the display + //------------------------------------------------------ + + function checkEvent() + { + + if ($scope.modalFromTimelineIsOpen == false) + { + NVRDataModel.log("Modal was closed in timeline, cancelling timer"); + $interval.cancel(eventQueryHandle); + return; + } + + //console.log ("Event timer"); + //console.log ("Event timer"); + $scope.checkEventOn = true; + if ($scope.defaultVideo !== undefined && $scope.defaultVideo != '') + { + //console.log("playing video, not using zms, skipping event commands"); + } + else + { + processEvent('99', $scope.connKey); + } + } + + function sendCommand(cmd, connkey, extras, rq) + { + var d = $q.defer(); + + if ($scope.defaultVideo !== undefined && $scope.defaultVideo != '') + { + // console.log("playing video, not using zms, skipping event commands"); + d.resolve(true); + return (d.promise); + } + + var loginData = NVRDataModel.getLogin(); + //console.log("Sending CGI command to " + loginData.url); + var rqtoken = rq ? rq : "stream"; + var myauthtoken = $rootScope.authSession.replace("&auth=", ""); + //&auth= + $http( + { + method: 'POST', + /*timeout: 15000,*/ + url: loginData.url + '/index.php', + headers: + { + 'Content-Type': 'application/x-www-form-urlencoded', + //'Accept': '*/*', + }, + transformRequest: function(obj) + { + var str = []; + for (var p in obj) + str.push(encodeURIComponent(p) + "=" + + encodeURIComponent(obj[p])); + var foo = str.join("&"); + if (extras) + { + foo = foo + extras; + //console.log("EXTRAS****SUB RETURNING " + foo); + } + //console.log("CGI subcommand=" + foo); + return foo; + + }, + + data: + { + view: "request", + request: rqtoken, + connkey: connkey, + command: cmd, + auth: myauthtoken, + // user: loginData.username, + // pass: loginData.password + } + }) + .then(function(resp) + { + NVRDataModel.debug("sendCmd response:" + JSON.stringify(resp)); + d.resolve(resp); + return (d.promise); + + }, + function(resp) + { + NVRDataModel.debug("sendCmd error:" + JSON.stringify(resp)); + d.reject(resp); + return (d.promise); + }); + + return (d.promise); + } + + function processEvent(cmd, connkey) + { + + if ($scope.blockSlider) + { + //console.log("Not doing ZMS Command as slider is depressed..."); + return; + } + + var loginData = NVRDataModel.getLogin(); + //console.log("sending process Event command to " + loginData.url); + var myauthtoken = $rootScope.authSession.replace("&auth=", ""); + //&auth= + var req = $http( + { + method: 'POST', + /*timeout: 15000,*/ + url: loginData.url + '/index.php', + headers: + { + 'Content-Type': 'application/x-www-form-urlencoded', + //'Accept': '*/*', + }, + transformRequest: function(obj) + { + var str = []; + for (var p in obj) + str.push(encodeURIComponent(p) + "=" + + encodeURIComponent(obj[p])); + var foo = str.join("&"); + //console.log("****processEvent subcommands RETURNING " + foo); + return foo; + }, + + data: + { + view: "request", + request: "stream", + connkey: connkey, + command: cmd, + auth: myauthtoken, + // user: loginData.username, + // pass: loginData.password + } + }); + + req.success(function(resp) + { + // NVRDataModel.debug ("processEvent success:"+JSON.stringify(resp)); + + if (resp.result == "Ok") + { + + $scope.currentProgress.progress = resp.status.progress; + $scope.eventId = resp.status.event; + $scope.d_eventId = $scope.eventId; + $scope.currentRate = resp.status.rate; + + if ($scope.currentProgress.progress > $scope.currentEventDuration) $scope.currentProgress.progress = $scope.currentEventDuration; + $scope.progressText = "At " + $scope.currentProgress.progress + "s of " + $scope.currentEventDuration + "s"; + + $scope.sliderProgress.progress = $scope.currentProgress.progress; + + // lets not do this and use zms to move forward or back + // as this code conflicts with fast rev etc + //if (Math.floor(resp.status.progress) >=$scope.currentEventDuration) + + //$timeout (checkEvent(), zm.eventPlaybackQuery); + //eventQueryHandle = $timeout (function(){checkEvent();}, zm.eventPlaybackQuery); + + } + else // resp.result was messed up + + { + NVRDataModel.debug("Hmm I found an error " + JSON.stringify(resp)); + //window.stop(); + $scope.connKey = (Math.floor((Math.random() * 999999) + 1)).toString(); + + // console.log (JSON.stringify(resp)); + $timeout(function() + { + sendCommand('14', $scope.connKey, '&offset=' + $scope.currentProgress.progress); + }, 500); + NVRDataModel.debug("so I'm regenerating Connkey to " + $scope.connKey); + //eventQueryHandle = $timeout (function(){checkEvent();}, zm.eventPlaybackQuery); + } + }); + + req.error(function(resp) + { + NVRDataModel.debug("processEvent error:" + JSON.stringify(resp)); + //eventQueryHandle = $timeout (function(){checkEvent();}, zm.eventPlaybackQuery); + + }); + + } + + function onPause() + { + + // $interval.cancel(modalIntervalHandle); + + // FIXME: Do I need to setAwake(false) here? + $interval.cancel(eventQueryHandle); + NVRDataModel.log("EventModalCtrl: paused, killing timer"); + + } + + function onResume() + { + NVRDataModel.debug("EventModalCtrl: Modal resume called"); + $rootScope.modalRand = Math.floor((Math.random() * 100000) + 1); + + } + + $scope.finishedLoadingImage = function() + { + // console.log("***Monitor image FINISHED Loading***"); + $ionicLoading.hide(); + + }; + + $scope.enableSliderBlock = function() + { + $scope.blockSlider = true; + }; + + $scope.youChangedSlider = function() + { + + //console.log("YOU changed " + $scope.sliderProgress.progress); + $scope.currentProgress.progress = $scope.sliderProgress.progress; + sendCommand('14', $scope.connKey, '&offset=' + $scope.currentProgress.progress) + .then(function(s) + { + $scope.blockSlider = false; + }, function(e) + { + $scope.blockSlider = false; + }); + + }; + + //----------------------------------------------------------------------- + // Sucess/Error handlers for saving a snapshot of the + // monitor image to phone storage + //----------------------------------------------------------------------- + + function SaveSuccess() + { + $ionicLoading.show( + { + template: $translate.instant('kDone'), + noBackdrop: true, + duration: 1000 + }); + NVRDataModel.debug("ModalCtrl:Photo saved successfuly"); + } + + function SaveError(e) + { + $ionicLoading.show( + { + template: $translate.instant('kErrorSave'), + noBackdrop: true, + duration: 2000 + }); + NVRDataModel.log("Error saving image: " + e.message); + //console.log("***ERROR"); + } + + $scope.jumpToOffsetInEvent = function() + { + // streamReq.send( streamParms+"&command="+CMD_SEEK+"&offset="+offset ); + }; + + //----------------------------------------------------------------------- + // Saves a snapshot of the monitor image to phone storage + //----------------------------------------------------------------------- + + $scope.saveEventImageToPhoneWithPerms = function(onlyAlarms) + { + + if ($rootScope.platformOS != 'android') + { + processSaveEventImageToPhone(onlyAlarms); + return; + } + + // if we are on android do the 6.x+ hasPermissions flow + NVRDataModel.debug("EventModalCtrl: Permission checking for write"); + var permissions = cordova.plugins.permissions; + permissions.hasPermission(permissions.WRITE_EXTERNAL_STORAGE, checkPermissionCallback, null); + + function checkPermissionCallback(status) + { + if (!status.hasPermission) + { + SaveError("No permission to write to external storage"); + } + permissions.requestPermission(permissions.WRITE_EXTERNAL_STORAGE, succ, err); + } + + function succ(s) + { + processSaveEventImageToPhone(onlyAlarms); + } + + function err(e) + { + SaveError("Error in requestPermission"); + } + }; + + function processSaveEventImageToPhone(onlyAlarms) + { + + if ($scope.loginData.useNphZmsForEvents) + { + NVRDataModel.log("Use ZMS stream to save to phone"); + saveEventImageToPhoneZms(onlyAlarms); + + } + else + { + saveEventImageToPhone(onlyAlarms); + } + + } + + function saveEventImageToPhoneZms(onlyAlarms) + { + // The strategy here is to build the array now so we can grab frames + // $scope.currentProgress.progress is the seconds where we are + // $scope.eventId is the event Id + + $scope.isPaused = true; + + $ionicLoading.show( + { + template: $translate.instant('kPleaseWait'), + noBackdrop: true, + duration: zm.httpTimeout + }); + sendCommand('1', $scope.connKey). + then(function(resp) + { + + // console.log ("PAUSE ANSWER IS " + JSON.stringify(resp)); + $scope.currentProgress.progress = resp.data.status.progress; + // console.log ("STEP 0 progress is " + $scope.currentProgress.progress); + $scope.slides = []; + + var apiurl = $scope.loginData.apiurl + "/events/" + $scope.eventId + ".json"; + NVRDataModel.debug("prepared to get frame details using " + apiurl); + $http.get(apiurl) + .then(function(success) + { + + event = success.data.event; + + event.Event.BasePath = computeBasePath(event); + event.Event.relativePath = computeRelativePath(event); + $scope.playbackURL = $scope.loginData.url; + $scope.eventBasePath = event.Event.BasePath; + $scope.relativePath = event.Event.relativePath; + + // now lets get approx frame # + + var totalTime = event.Event.Length; + var totalFrames = event.Event.Frames; + + var myFrame = Math.round(totalFrames / totalTime * $scope.currentProgress.progress); + + // console.log ("STEP 0: playback " + $scope.playbackURL + " total time " + totalTime + " frames " + totalFrames); + + if (myFrame > totalFrames) myFrame = totalFrames; + + // console.log ("STEP 0 myFrame is " + myFrame); + // console.log ("DUMPING " + JSON.stringify(event)); + $scope.mycarousel.index = myFrame; + // console.log ("STEP 1 : Computed index as "+ $scope.mycarousel.index); + var i, p = 0; + for (i = 1; i <= event.Frame.length; i++) + { + var fname = padToN(event.Frame[i - 1].FrameId, eventImageDigits) + "-capture.jpg"; + // console.log ("Building " + fname); + + // console.log ("DUMPING ONE " + JSON.stringify(event.Frame[i-1])); + // onlyAlarms means only copy alarmed frames + if (onlyAlarms) + { + if (event.Frame[i - 1] && event.Frame[i - 1].Type == 'Alarm') + { + p++; + $scope.slides.push( + { + id: event.Frame[i - 1].FrameId, + img: fname, + }); + //console.log ("ALARM PUSHED " + fname); + } + } + else // push all frames + { + //now handle bulk frames pushing before pushing this one + if (event.Frame[i-1].Type == 'Bulk') + { + var f1 = parseInt(event.Frame[i-2].FrameId); + var f2 = parseInt(event.Frame[i-1].FrameId); + + //console.log ("Filling in bulk from:"+f1+" to "+(f2-1)); + for (var bulk=f1+1; bulk < f2; bulk++) + { + //console.log ("Storing bulk:"+bulk); + var bfname = padToN(bulk, eventImageDigits) + "-capture.jpg"; + p++; + $scope.slides.push({ + id: bulk, + img: bfname + + }); + + + } + } + //console.log ("storing: "+event.Frame[i - 1].FrameId); + p++; + $scope.slides.push( + { + id: event.Frame[i - 1].FrameId, + img: fname, + }); + + + + } + + } + //console.log ("I PUSHED:" + p+" BUT SLIDE LENGHT BEFORE DISPLAY:"+$scope.slides.length); + // console.log ("STEP 2 : calling Save Event To Phone"); + $ionicLoading.hide(); + saveEventImageToPhone(onlyAlarms); + + }, + function(err) + { + $ionicLoading.hide(); + NVRDataModel.log("snapshot API Error: Could not get frames " + JSON.stringify(err)); + + $ionicLoading.show( + { + template: $translate.instant('kErrorRetrievingFrames'), + noBackdrop: true, + duration: 4000 + }); + }); + }, + + function(err) + { + NVRDataModel.debug("Error pausing stream before snapshot " + JSON.stringify(err)); + $ionicLoading.hide(); + } + + ); // then + + } + + // don't think this is used anymore + function saveEventImageToPhone(onlyAlarms) + { + // console.log ("________________UNUSED?_______________________"); + var curState = carouselUtils.getStop(); + carouselUtils.setStop(true); + + //console.log("Your index is " + $scope.mycarousel.index); + //console.log("Associated image is " + $scope.slides[$scope.mycarousel.index].img); + + NVRDataModel.debug("ModalCtrl: SaveEventImageToPhone called"); + var canvas, context, imageDataUrl, imageData; + var loginData = NVRDataModel.getLogin(); + + // for alarms only + if (onlyAlarms) $scope.mycarousel.index = 0; + var url = $scope.playbackURL + '/index.php?view=image&rand=' + $rootScope.rand + "&path=" + $scope.relativePath + $scope.slides[$scope.mycarousel.index].img; + + $scope.selectEventUrl = url; + $scope.slideIndex = $scope.mycarousel.index; + $scope.slideLastIndex = $scope.slides.length - 1; + console.log ("FRAMES LENGTH IS " +$scope.slideLastIndex ); + + // console.log ("URL TO DISPLAY " + url); + + $rootScope.zmPopup = $ionicPopup.show( + { + template: '<center>Frame: {{slideIndex+1}} / {{slideLastIndex+1}}</center><br/><img src="{{selectEventUrl}}" width="100%" />', + title: 'Select ' + (onlyAlarms ? 'Alarmed ' : '') + 'frame to save', + subTitle: 'use left and right arrows to change', + scope: $scope, + cssClass: 'popup95', + buttons: [ + { + // left 1 + text: '', + type: 'button-small button-energized ion-chevron-left', + onTap: function(e) + { + if ($scope.slideIndex > 0) $scope.slideIndex--; + $scope.selectEventUrl = $scope.playbackURL + '/index.php?view=image&rand=' + $rootScope.rand + "&path=" + $scope.relativePath + $scope.slides[$scope.slideIndex].img; + //NVRDataModel.log("selected frame is " + $scope.slideIndex); + + console.log("URL TO DISPLAY " + $scope.slides[$scope.slideIndex].img); + + e.preventDefault(); + } + }, + { + // right 1 + text: '', + type: 'button-small button-energized ion-chevron-right', + onTap: function(e) + { + if ($scope.slideIndex < $scope.slideLastIndex) $scope.slideIndex++; + $scope.selectEventUrl = $scope.playbackURL + '/index.php?view=image&rand=' + $rootScope.rand + "&path=" + $scope.relativePath + $scope.slides[$scope.slideIndex].img; + //NVRDataModel.log("selected frame is " + $scope.slideIndex); + console.log("URL TO DISPLAY " + $scope.slides[$scope.slideIndex].img); + e.preventDefault(); + } + }, + { + // left 10 + text: '', + type: 'button-small button-energized ion-skip-backward', + onTap: function(e) + { + var tempVar = $scope.slideIndex; + tempVar -= 10; + if (tempVar < 0) tempVar = 0; + $scope.slideIndex = tempVar; + + $scope.selectEventUrl = $scope.playbackURL + '/index.php?view=image&rand=' + $rootScope.rand + "&path=" + $scope.relativePath + $scope.slides[$scope.slideIndex].img; + //NVRDataModel.log("selected frame is " + $scope.slideIndex); + + e.preventDefault(); + } + }, + { + // right 10 + text: '', + type: 'button-small button-energized ion-skip-forward', + onTap: function(e) + { + var tempVar = $scope.slideIndex; + tempVar += 10; + if (tempVar > $scope.slideLastIndex) tempVar = $scope.slideLastIndex; + $scope.slideIndex = tempVar; + if ($scope.slideIndex < $scope.slideLastIndex) $scope.slideIndex++; + $scope.selectEventUrl = $scope.playbackURL + '/index.php?view=image&rand=' + $rootScope.rand + "&path=" + $scope.relativePath + $scope.slides[$scope.slideIndex].img; + //NVRDataModel.log("selected frame is " + $scope.slideIndex); + e.preventDefault(); + } + }, + + { + text: '', + type: 'button-assertive button-small ion-close-round' + }, + { + text: '', + type: 'button-positive button-small ion-checkmark-round', + onTap: function(e) + { + saveNow(); + + } + } + ] + }); + + function saveNow() + { + $ionicLoading.show( + { + template: $translate.instant('kSavingSnapshot') + "...", + noBackdrop: true, + duration: zm.httpTimeout + }); + var url = $scope.selectEventUrl; + NVRDataModel.log("saveNow: File path to grab is " + url); + + var img = new Image(); + img.onload = function() + { + // console.log("********* ONLOAD"); + canvas = document.createElement('canvas'); + canvas.width = img.width; + canvas.height = img.height; + context = canvas.getContext('2d'); + context.drawImage(img, 0, 0); + + imageDataUrl = canvas.toDataURL('image/jpeg', 1.0); + imageData = imageDataUrl.replace(/data:image\/jpeg;base64,/, ''); + + if ($rootScope.platformOS != "desktop") + { + try + { + + cordova.exec( + SaveSuccess, + SaveError, + 'Canvas2ImagePlugin', + 'saveImageDataToLibrary', [imageData] + ); + // carouselUtils.setStop(curState); + } + catch (e) + { + + SaveError(e.message); + // carouselUtils.setStop(curState); + } + } + else + { + + var fname = $scope.relativePath + $scope.slides[$scope.slideIndex].img + ".png"; + fname = fname.replace(/\//, "-"); + fname = fname.replace(/\.jpg/, ''); + + canvas.toBlob(function(blob) + { + saveAs(blob, fname); + SaveSuccess(); + }); + } + }; + try + { + img.src = url; + // console.log ("SAVING IMAGE SOURCE"); + } + catch (e) + { + SaveError(e.message); + } + } + } + + $scope.reloadView = function() + { + NVRDataModel.log("Reloading view for modal view, recomputing rand"); + $rootScope.modalRand = Math.floor((Math.random() * 100000) + 1); + $scope.isModalActive = true; + }; + + $scope.scaleImage = function() + { + + $scope.imageFit = !$scope.imageFit; + console.log("Switching image style to " + $scope.imageFit); + }; + + $scope.$on('$ionicView.enter', function() + { + //console.log (">>>>>>>>>>>>>>>>>>>> MODAL VIEW ENTER"); + + }); + + $scope.$on('modal.shown', function(e, m) + { + + if (m.id != 'footage') + + return; + + $scope.isToggleListMenu = true; + $scope.videoDynamicTime = ""; + $scope.videoIsReady = false; + var ld = NVRDataModel.getLogin(); + $scope.loginData = NVRDataModel.getLogin(); + + $scope.singleImageQuality = (NVRDataModel.getBandwidth() == "lowbw") ? zm.eventSingleImageQualityLowBW : ld.singleImageQuality; + $scope.blockSlider = false; + $scope.checkEventOn = false; + //$scope.singleImageQuality = 100; + + //$scope.commandURL = $scope.currentEvent.Event.baseURL+"/index.php"; + // NVRDataModel.log (">>>>>>>>>>>>>>>>>>ZMS url command is " + $scope.commandURL); + + currentEvent = $scope.currentEvent; + + //console.log("Current Event " + JSON.stringify(currentEvent)); + $scope.connKey = (Math.floor((Math.random() * 999999) + 1)).toString(); + NVRDataModel.debug("Generated Connkey:" + $scope.connKey); + + $scope.currentFrame = 1; + $scope.isPaused = false; + + gEvent = $scope.currentEvent; + //console.log ("CURRENT EVENT " + JSON.stringify($scope.currentEvent)); + // + $scope.currentEventDuration = Math.floor($scope.currentEvent.Event.Length); + //console.log ($scope.event.Event.Frames); + if (currentEvent && currentEvent.Event) + { + //console.log ("************ CALLING PREPARE MODAL ***********"); + prepareModalEvent(currentEvent.Event.Id); + if (ld.useNphZmsForEvents) + { + $timeout(function() + { + + if ($scope.modal != undefined && $scope.modal.isShown()) + { + NVRDataModel.log(">>>Starting checkAllEvents interval..."); + + //eventQueryHandle = $timeout (checkEvent(), zm.eventPlaybackQuery); + + $interval.cancel(eventQueryHandle); + eventQueryHandle = $interval(function() + { + checkEvent(); + // console.log ("Refreshing Image..."); + }.bind(this), (NVRDataModel.getBandwidth() == "lowbw") ? zm.eventPlaybackQueryLowBW : zm.eventPlaybackQuery); + } + else + { + NVRDataModel.log(">>>Modal was exited, not starting checkAllEvents"); + } + + }, 5000); + } + + } + + }); + + //var current_data; + function drawGraph() + { + + var cv = document.getElementById("eventchart"); + var ctx = cv.getContext("2d"); + + frameoptions = { + responsive: true, + legend: false, + title: + { + display: false, + text: "" + }, + scales: + { + yAxes: [ + { + display: false, + scaleLabel: + { + display: false, + labelString: 'value', + } + + }], + xAxes: [ + { + type: 'time', + display: false, + time: + { + + format: timeFormat, + tooltipFormat: 'll HH:mm', + min: framearray.datasets[0].data[0].x, + max: framearray.datasets[0].data[framearray.datasets[0].data.length - 1].x, + displayFormats: + { + + } + }, + scaleLabel: + { + display: false, + labelString: '' + } + + }] + } + }; + + $timeout(function() + { + + var myChart = new Chart(ctx, + { + type: 'line', + data: framearray, + options: frameoptions, + }); + + }); + } + + $scope.videoTime = function(s, c) + { + var a, o; + if (NVRDataModel.getLogin().useLocalTimeZone) + { + a = moment.tz(s, NVRDataModel.getTimeZoneNow()).tz(moment.tz.guess()); + + } + else + { + a = moment(s); + } + a.add(c); + + o = a.format("MMM Do " + NVRDataModel.getTimeFormatSec()); + $scope.videoDynamicTime = o; + //return a.format("MMM Do "+o); + + }; + + $scope.$on('modal.removed', function(e, m) + { + console.log("************* REMOVE CALLED"); + $interval.cancel(eventQueryHandle); + if (m.id != 'footage') + return; + + $scope.isModalActive = false; + + NVRDataModel.debug("Modal removed - killing connkey"); + sendCommand(17, $scope.connKey); + //$timeout (function(){NVRDataModel.stopNetwork("Modal removed inside EventModalCtrl");},400); + + // Execute action + }); + + // Playback speed adjuster + $scope.adjustSpeed = function(val) + { + + if ($scope.defaultVideo !== undefined && $scope.defaultVideo != '') + { + + $ionicLoading.show( + { + template: $translate.instant('kUseVideoControls'), + noBackdrop: true, + duration: 3000 + }); + return; + } + + var ld = NVRDataModel.getLogin(); + + if (ld.useNphZmsForEvents) + { + + var cmd; + $scope.isPaused = false; + switch (val) + { + case 'ff': + cmd = 4; + break; + case 'fr': + cmd = 7; + break; + case 'np': + cmd = 2; + break; + case 'p': + cmd = 1; + $scope.isPaused = true; + break; + default: + cmd = 0; + } + + $ionicLoading.show( + { + template: $translate.instant('kPleaseWait') + "...", + noBackdrop: true, + duration: zm.httpTimeout + }); + + sendCommand(cmd, $scope.connKey) + .then(function(success) + { + $ionicLoading.hide(); + + }, + function(err) + { + $ionicLoading.hide(); + NVRDataModel.debug("Error in adjust speed: " + JSON.stringify(err)); + } + ); + + } + else // not using nph + { + + switch (val) + { + + case "super": + $scope.eventSpeed = 20 / $scope.event.Event.Frames; + carouselUtils.setDuration($scope.eventSpeed); + break; + case "normal": + $scope.eventSpeed = $scope.event.Event.Length / $scope.event.Event.Frames; + //$scope.eventSpeed = 5; + carouselUtils.setDuration($scope.eventSpeed); + + break; + case "faster": + $scope.eventSpeed = $scope.eventSpeed / 2; + if ($scope.eventSpeed < 20 / $scope.event.Event.Frames) + $scope.eventSpeed = 10 / $scope.event.Event.Frames; + carouselUtils.setDuration($scope.eventSpeed); + break; + case "slower": + $scope.eventSpeed = $scope.eventSpeed * 2; + carouselUtils.setDuration($scope.eventSpeed); + + break; + default: + + } + NVRDataModel.debug("Set playback speed to " + $scope.eventSpeed); + + $ionicLoading.show( + { + template: $translate.instant('kPlaybackInterval') + ': ' + $scope.eventSpeed.toFixed(3) + "ms", + animation: 'fade-in', + showBackdrop: false, + duration: 1500, + maxWidth: 300, + showDelay: 0 + }); + } + + }; + + $scope.toggleListMenu = function() + { + + $scope.isToggleListMenu = !$scope.isToggleListMenu; + }; + + $scope.toggleGapless = function() + { + // console.log(">>>>>>>>>>>>>>GAPLESS TOGGLE INSIDE MODAL"); + $scope.loginData.gapless = !$scope.loginData.gapless; + NVRDataModel.setLogin($scope.loginData); + + NVRDataModel.debug("EventModalCtrl: gapless has changed resetting everything & re-generating connkey"); + NVRDataModel.stopNetwork("EventModalCtrl-toggle gapless"); + NVRDataModel.debug("Regenerating connkey as gapless has changed"); + // console.log ("********* OFFSET FROM TOGGLE GAPLESS"); + $scope.connKey = (Math.floor((Math.random() * 999999) + 1)).toString(); + $timeout(function() + { + sendCommand('14', $scope.connKey, '&offset=' + $scope.currentProgress.progress); + }, 500); + //$timeout.cancel(eventQueryHandle); + //eventQueryHandle = $timeout (function(){checkEvent();}, zm.eventPlaybackQuery); + + }; + + // This function returns neighbor events if applicable + function neighborEvents(eid) + { + var d = $q.defer(); + // now get event details to show alarm frames + var loginData = NVRDataModel.getLogin(); + var myurl = loginData.apiurl + '/events/' + eid + ".json"; + var neighbors = { + prev: "", + next: "" + }; + $http.get(myurl) + .success(function(data) + { + + // In Timeline view, gapless should stick to the same monitor + if ($scope.followSameMonitor == "1") // we are viewing only one monitor + { + NVRDataModel.debug("Getting next event for same monitor Id "); + neighbors.prev = data.event.Event.PrevOfMonitor ? data.event.Event.PrevOfMonitor : ""; + neighbors.next = data.event.Event.NextOfMonitor ? data.event.Event.NextOfMonitor : ""; + } + else + { + neighbors.prev = data.event.Event.Prev ? data.event.Event.Prev : ""; + neighbors.next = data.event.Event.Next ? data.event.Event.Next : ""; + } + NVRDataModel.debug("Neighbor events of " + eid + "are Prev:" + + neighbors.prev + " and Next:" + neighbors.next); + + d.resolve(neighbors); + return (d.promise); + }) + .error(function(err) + { + NVRDataModel.log("Error retrieving neighbors" + JSON.stringify(err)); + d.reject(neighbors); + return (d.promise); + + }); + return (d.promise); + + } + + $scope.zoomImage = function(val) + { + var zl = parseInt($ionicScrollDelegate.$getByHandle("imgscroll").getScrollPosition().zoom); + if (zl == 1 && val == -1) + { + NVRDataModel.debug("Already zoomed out max"); + return; + } + + zl += val; + NVRDataModel.debug("Zoom level is " + zl); + $ionicScrollDelegate.$getByHandle("imgscroll").zoomTo(zl, true); + + }; + + //-------------------------------------------------------- + //Navigate to next/prev event in full screen mode + //-------------------------------------------------------- + + $scope.onSwipeEvent = function(eid, dirn) + { + //console.log("HERE"); + var ld = NVRDataModel.getLogin(); + if (!ld.canSwipeMonitors) return; + + if ($ionicScrollDelegate.$getByHandle("imgscroll").getScrollPosition().zoom != 1) + { + //console.log("Image is zoomed in - not honoring swipe"); + return; + } + + if (ld.useNphZmsForEvents) + { + NVRDataModel.log("using zms to move "); + jumpToEventZms($scope.connKey, dirn); + // sendCommand ( dirn==1?'13':'12',$scope.connKey); + + } + else + { + jumpToEvent(eid, dirn); + } + + //console.log("JUMPING"); + + }; + + $scope.jumpToEvent = function(eid, dirn) + { + // console.log("jumptoevent"); + var ld = NVRDataModel.getLogin(); + if (ld.useNphZmsForEvents) + { + NVRDataModel.log("using zms to move "); + jumpToEventZms($scope.connKey, dirn); + // sendCommand ( dirn==1?'13':'12',$scope.connKey); + + } + else + { + jumpToEvent(eid, dirn); + } + + }; + + function jumpToEvent(eid, dirn) + { + NVRDataModel.log("Event jump called with:" + eid); + if (eid == "") + { + $ionicLoading.show( + { + template: $translate.instant('kNoMoreEvents'), + noBackdrop: true, + duration: 2000 + }); + + return; + } + + var slidein; + var slideout; + if (dirn == 1) + { + slideout = "animated slideOutLeft"; + slidein = "animated slideInRight"; + } + else + { + slideout = "animated slideOutRight"; + slidein = "animated slideInLeft"; + } + var element = angular.element(document.getElementById("full-screen-event")); + element.addClass(slideout).one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', outWithOld); + + function outWithOld() + { + + NVRDataModel.log("ModalCtrl:Stopping network pull..."); + NVRDataModel.stopNetwork("EventModalCtrl-out with old"); + $scope.animationInProgress = true; + // give digest time for image to swap + // 100 should be enough + $timeout(function() + { + element.removeClass(slideout); + element.addClass(slidein) + .one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', inWithNew); + prepareModalEvent(eid); + }, 200); + } + + function inWithNew() + { + element.removeClass(slidein); + $scope.animationInProgress = false; + carouselUtils.setStop(false); + } + + } + + function humanizeTime(str) + { + // if (NVRDataModel.getLogin().useLocalTimeZone) + return moment.tz(str, NVRDataModel.getTimeZoneNow()).fromNow(); + // else + // return moment(str).fromNow(); + + } + + function jumpToEventZms(connkey, dirn) + { + + if ($scope.defaultVideo !== undefined && $scope.defaultVideo != '') + { + + $ionicLoading.show( + { + template: $translate.instant('kEventNavVidFeeds'), + noBackdrop: true, + duration: 3000 + }); + return; + + } + var cmd = dirn == 1 ? '13' : '12'; + $scope.d_eventId = "..."; + NVRDataModel.debug("Sending " + cmd + " to " + connkey); + + $ionicLoading.show( + { + template: $translate.instant('kSwitchingEvents') + "...", + noBackdrop: true, + duration: zm.httpTimeout + }); + + //console.log("Send command connkey: " + connkey); + sendCommand(cmd, connkey) + .then( + function(success) + { + //console.log ("jump success " + JSON.stringify(success)); + $ionicLoading.hide(); + }, + function(error) + { + + NVRDataModel.debug("Hmm jump error " + JSON.stringify(error)); + NVRDataModel.stopNetwork("EventModalCtrl-jumptoEventZms error"); + $scope.connKey = (Math.floor((Math.random() * 999999) + 1)).toString(); + // console.log ("********* OFFSET FROM JUMPTOEVENTZMS ERROR"); + $timeout(function() + { + sendCommand('14', $scope.connKey, '&offset=' + $scope.currentProgress.progress); + }, 500); + NVRDataModel.debug("so I'm regenerating Connkey to " + $scope.connKey); + //$timeout.cancel(eventQueryHandle); + // eventQueryHandle = $timeout (function(){checkEvent();}, zm.eventPlaybackQuery); + $ionicLoading.hide(); + }); + var slidein; + var slideout; + if (dirn == 1) + { + slideout = "animated slideOutLeft"; + slidein = "animated slideInRight"; + } + else + { + slideout = "animated slideOutRight"; + slidein = "animated slideInLeft"; + } + var element = angular.element(document.getElementById("full-screen-event")); + element.addClass(slideout).one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', outWithOld); + + function outWithOld() + { + + $timeout(function() + { + element.removeClass(slideout); + element.addClass(slidein) + .one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', inWithNew); + + }, 200); + } + + function inWithNew() + { + element.removeClass(slidein); + + } + + } + + //-------------------------------------------------------- + // utility function + //-------------------------------------------------------- + + function computeRelativePath(event) + { + var relativePath = ""; + var loginData = NVRDataModel.getLogin(); + var str = event.Event.StartTime; + var yy = moment(str).locale('en').format('YY'); + var mm = moment(str).locale('en').format('MM'); + var dd = moment(str).locale('en').format('DD'); + var hh = moment(str).locale('en').format('HH'); + var min = moment(str).locale('en').format('mm'); + var sec = moment(str).locale('en').format('ss'); + relativePath = event.Event.MonitorId + "/" + + yy + "/" + + mm + "/" + + dd + "/" + + hh + "/" + + min + "/" + + sec + "/"; + return relativePath; + + } + + //-------------------------------------------------------- + // utility function + //-------------------------------------------------------- + + function computeBasePath(event) + { + var basePath = ""; + var loginData = NVRDataModel.getLogin(); + var str = event.Event.StartTime; + var yy = moment(str).locale('en').format('YY'); + var mm = moment(str).locale('en').format('MM'); + var dd = moment(str).locale('en').format('DD'); + var hh = moment(str).locale('en').format('HH'); + var min = moment(str).locale('en').format('mm'); + var sec = moment(str).locale('en').format('ss'); + + basePath = loginData.url + "/events/" + + event.Event.MonitorId + "/" + + yy + "/" + + mm + "/" + + dd + "/" + + hh + "/" + + min + "/" + + sec + "/"; + return basePath; + } + + //------------------------------------------------------------------------- + // Called when rncarousel or video player finished playing event + //------------------------------------------------------------------------- + + $scope.playbackFinished = function() + { + playbackFinished(); + }; + + function playbackFinished() + { + // currentEvent is updated with the currently playing event in prepareModalEvent() + NVRDataModel.log("Playback of event " + currentEvent.Event.Id + " is finished"); + + if ($scope.loginData.gapless) + { + + neighborEvents(currentEvent.Event.Id) + .then(function(success) + { + + // lets give a second before gapless transition to the next event + $timeout(function() + { + $scope.nextId = success.next; + $scope.prevId = success.prev; + NVRDataModel.debug("Gapless move to event " + $scope.nextId); + jumpToEvent($scope.nextId, 1); + }, 1000); + }, + function(error) + { + NVRDataModel.debug("Error in neighbor call " + + JSON.stringify(error)); + }); + } + else + { + NVRDataModel.debug("not going to next event, gapless is off"); + } + } + + //-------------------------------------------------------- + // Called by openModal as well as jump to event + // what it basically does is get a detailed event API + // for an event ID and constructs required playback + // parameters + // Note that openModal is called with the top level event + // API. Some parameters are repeated across both + //-------------------------------------------------------- + + function prepareModalEvent(eid) + { + + // Lets get the detailed event API + var loginData = NVRDataModel.getLogin(); + var myurl = loginData.apiurl + '/events/' + eid + ".json"; + NVRDataModel.log("*** Constructed API for detailed events: " + myurl); + $scope.humanizeTime = "..."; + $scope.mName = "..."; + $http.get(myurl) + .then(function(success) + { + + // console.log ("DUCCESS::"+JSON.stringify(success)); + var event = success.data.event; + currentEvent = event; + + event.Event.BasePath = computeBasePath(event); + event.Event.relativePath = computeRelativePath(event); + + event.Event.streamingURL = NVRDataModel.getStreamingURL(event.Event.MonitorId); + // event.Event.baseURL = NVRDataModel.getBaseURL (event.Event.MonitorId); + event.Event.baseURL = loginData.url; + event.Event.imageMode = NVRDataModel.getImageMode(event.Event.MonitorId); + + //console.log (JSON.stringify( success)); + $scope.eventName = event.Event.Name; + $scope.eventId = event.Event.Id; + $scope.d_eventId = $scope.eventId; + $scope.eFramesNum = event.Event.Frames; + $scope.eventDur = Math.round(event.Event.Length); + $scope.loginData = NVRDataModel.getLogin(); + $scope.humanizeTime = humanizeTime(event.Event.StartTime); + $scope.mName = NVRDataModel.getMonitorName(event.Event.MonitorId); + //console.log (">>>>>>>>HUMANIZE " + $scope.humanizeTime); + + //console.log("**** VIDEO STATE IS " + event.Event.DefaultVideo); + if (typeof event.Event.DefaultVideo === 'undefined') + event.Event.DefaultVideo = ""; + + $scope.defaultVideo = event.Event.DefaultVideo; + + //console.log("loginData is " + JSON.stringify($scope.loginData)); + //console.log("Event ID is " + $scope.eventId); + //console.log("video is " + $scope.defaultVideo); + + neighborEvents(event.Event.Id) + .then(function(success) + { + $scope.nextId = success.next; + $scope.prevId = success.prev; + }, + function(error) + { + //console.log(JSON.stringify(error)); + }); + + $scope.nextId = "..."; + $scope.prevId = "..."; + + event.Event.video = {}; + var videoURL; + + if ((event.Event.imageMode == 'path') || NVRDataModel.getLogin().forceImageModePath) + videoURL = event.Event.baseURL + "/events/" + event.Event.relativePath + event.Event.DefaultVideo; + else + videoURL = event.Event.baseURL + "/index.php?view=view_video&eid=" + event.Event.Id; + + // hack + //videoURL = "http://static.videogular.com/assets/videos/videogular.mp4"; + //videoURL = "http://arjunrc.ddns.net:8888/foo2.mp4"; + $scope.video_url = videoURL; + + console.log("************** VIDEO IS " + videoURL); + + NVRDataModel.debug("Video url passed to player is: " + videoURL); + + // console.log (">>>>>>>>>>>>>"+loginData.url+"-VS-"+event.Event.baseURL); + + //console.log("************** VIDEO IS " + videoURL); + + $scope.videoObject = { + config: + { + autoPlay: true, + responsive: false, + nativeControls: false, + nativeFullScreen:false, + + playsInline: true, + sources: [ + { + src: $sce.trustAsResourceUrl(videoURL), + type: "video/mp4" + } + + ], + + theme: "lib/videogular-themes-default/videogular.css", + cuepoints: { + theme: { + url:"lib/videogular-cuepoints/cuepoints.css" + }, + points: [], + } + } + }; + + // $scope.videoObject = angular.copy(event.Event.video); + + $scope.playbackURL = $scope.loginData.url; + + $scope.videoIsReady = true; + + /* we don't need this for electron + if ($rootScope.platformOS == "desktop") { + $scope.playbackURL = zm.desktopUrl; + } */ + + $scope.eventBasePath = event.Event.BasePath; + $scope.relativePath = event.Event.relativePath; + $rootScope.rand = Math.floor(Math.random() * (999999 - 111111 + 1)) + 111111; + + $scope.slider_modal_options = { + from: 1, + to: event.Event.Frames, + realtime: true, + step: 1, + className: "mySliderClass", + callback: function(value, released) + { + //console.log("CALLBACK"+value+released); + $ionicScrollDelegate.freezeScroll(!released); + + }, + //modelLabels:function(val) {return "";}, + smooth: false, + css: + { + background: + { + "background-color": "silver" + }, + before: + { + "background-color": "purple" + }, + default: + { + "background-color": "white" + }, // default value: 1px + after: + { + "background-color": "green" + }, // zone after default value + pointer: + { + "background-color": "red" + }, // circle pointer + range: + { + "background-color": "red" + } // use it if double value + }, + scale: [] + + }; + + $scope.mycarousel.index = 0; + $scope.ionRange.index = 1; + $scope.eventSpeed = $scope.event.Event.Length / $scope.event.Event.Frames; + + //console.log("**Resetting range"); + $scope.slides = []; + var i; + for (i = 1; i <= event.Event.Frames; i++) + { + var fname = padToN(i, eventImageDigits) + "-capture.jpg"; + // console.log ("Building " + fname); + $scope.slides.push( + { + id: i, + img: fname + }); + } + + // now get event details to show alarm frames + + //$scope.FrameArray = event.Frame; + // $scope.slider_options.scale=[]; + // $scope.slider_modal_options.scale = []; + + // lets + framearray.datasets[0].data = []; + for (i = 0; i < event.Frame.length; i++) + { + + var ts = moment(event.Frame[i].TimeStamp).format(timeFormat); + + //console.log ("pushing s:" + event.Frame[i].Score+" t:"+ts); + + framearray.datasets[0].data.push( + { + x: ts, + y: event.Frame[i].Score + }); + framearray.labels.push(""); + + } + $scope.totalEventTime = Math.round(parseFloat(event.Event.Length)) - 1; + $scope.currentEventTime = 0; + + // video mode doesn't need this graph - it won't really work + if ($scope.defaultVideo == undefined || $scope.defaultVideo == '') + { + $timeout(function() + { + drawGraph(); + }, 500); + } + + }, + function(err) + { + NVRDataModel.log("Error retrieving detailed frame API " + JSON.stringify(err)); + NVRDataModel.displayBanner('error', ['could not retrieve frame details', 'please try again']); + }); + + } + + if (typeof $scope.ionRange !== 'undefined') + { + $scope.$watch('ionRange.index', function() + { + // + $scope.mycarousel.index = parseInt($scope.ionRange.index) - 1; + + if (carouselUtils.getStop() == true) + return; + + //console.log ("***ION RANGE CHANGED TO " + $scope.mycarousel.index); + }); + } + + if (typeof $scope.mycarousel !== 'undefined') + { + $scope.$watch('mycarousel.index', function() + { + + if (currentEvent && $scope.ionRange.index == parseInt(currentEvent.Event.Frames - 1)) + { + playbackFinished(); + } + // end of playback from quick scrub + // so ignore gapless + + if ($scope.event && $scope.ionRange.index == parseInt($scope.event.Event.Frames) - 1) + { + if (!$scope.modal || $scope.modal.isShown() == false) + { + // console.log("quick scrub playback over"); + carouselUtils.setStop(true); + $scope.ionRange.index = 0; + $scope.mycarousel.index = 1; + } + + } + if (carouselUtils.getStop() == true) + return; + $scope.ionRange.index = ($scope.mycarousel.index + 1).toString(); + // console.log ("***IONRANGE RANGE CHANGED TO " + $scope.ionRange.index); + + }); + } + + function padToN(number, digits) + { + + var i; + var stringMax = ""; + var stringLeading = ""; + for (i = 1; i <= digits; i++) + { + stringMax = stringMax + "9"; + if (i != digits) stringLeading = stringLeading + "0"; + } + var numMax = parseInt(stringMax); + + if (number <= numMax) + { + number = (stringLeading + number).slice(-digits); + } + //console.log ("PADTON: returning " + number); + return number; + } + +}]); |
