diff --git a/web/skins/classic/views/js/montagereview.js b/web/skins/classic/views/js/montagereview.js new file mode 100644 index 000000000..58067e123 --- /dev/null +++ b/web/skins/classic/views/js/montagereview.js @@ -0,0 +1,709 @@ +function evaluateLoadTimes() { + // Only consider it a completed event if we load ALL monitors, then zero all and start again + var start=0; + var end=0; + if(liveMode!=1 && currentSpeed==0) return; // don't evaluate when we are not moving as we can do nothing really fast. + for(var i=0; i"") { + if( monitorLoadEndTimems[i]==0) return; // if we have a monitor with no time yet just wait + if( start == 0 || start > monitorLoadStartTimems[i] ) start = monitorLoadStartTimems[i]; + if( end == 0 || end < monitorLoadEndTimems[i] ) end = monitorLoadEndTimems[i]; + } + } + if(start==0 || end==0) return; // we really should not get here + for(var i=0; i= 0.9) currentDisplayInterval = (currentDisplayInterval * 0.50).toFixed(1); // we can go much faster + else if (avgFrac >= 0.8) currentDisplayInterval = (currentDisplayInterval * 0.55).toFixed(1); + else if (avgFrac >= 0.7) currentDisplayInterval = (currentDisplayInterval * 0.60).toFixed(1); + else if (avgFrac >= 0.6) currentDisplayInterval = (currentDisplayInterval * 0.65).toFixed(1); + else if (avgFrac >= 0.5) currentDisplayInterval = (currentDisplayInterval * 0.70).toFixed(1); + else if (avgFrac >= 0.4) currentDisplayInterval = (currentDisplayInterval * 0.80).toFixed(1); + else if (avgFrac >= 0.35) currentDisplayInterval = (currentDisplayInterval * 0.90).toFixed(1); + else if (avgFrac >= 0.3) currentDisplayInterval = (currentDisplayInterval * 1.00).toFixed(1); + else if (avgFrac >= 0.25) currentDisplayInterval = (currentDisplayInterval * 1.20).toFixed(1); + else if (avgFrac >= 0.2) currentDisplayInterval = (currentDisplayInterval * 1.50).toFixed(1); + else if (avgFrac >= 0.1) currentDisplayInterval = (currentDisplayInterval * 2.00).toFixed(1); + else currentDisplayInterval = (currentDisplayInterval * 2.50).toFixed(1); + currentDisplayInterval=Math.min(Math.max(currentDisplayInterval, 30),10000); // limit this from about 30fps to .1 fps + imageLoadTimesEvaluated=0; + setSpeed(speedIndex); + $('fps').innerHTML="Display refresh rate is " + (1000 / currentDisplayInterval).toFixed(1) + " per second, avgFrac=" + avgFrac.toFixed(3) + "."; +} + +function SetImageSource(monId,val) { + if ( liveMode == 1 ) { + return monitorImageObject[monId].src.replace(/rand=\d+/i, 'rand='+Math.floor((Math.random() * 1000000) )); + + } else { + for(var i=0, eIdlength = eId.length; i= eStartSecs[i] && val <= eEndSecs[i]) { + var frame=parseInt((val - eStartSecs[i])/(eEndSecs[i]-eStartSecs[i])*eventFrames[i])+1; + return "index.php?view=image&eid=" + eId[i] + '&fid='+frame + "&width=" + monitorCanvasObj[monId].width + "&height=" + monitorCanvasObj[monId].height; + } + } // end for + return "no data"; + } +} + +function imagedone(obj, monId, success) { + if(success) { + monitorCanvasCtx[monId].drawImage( monitorImageObject[monId], 0, 0, monitorCanvasObj[monId].width, monitorCanvasObj[monId].height ); + var iconSize=(Math.max(monitorCanvasObj[monId].width, monitorCanvasObj[monId].height) * 0.10); + monitorCanvasCtx[monId].font = "600 " + iconSize.toString() + "px Arial"; + monitorCanvasCtx[monId].fillStyle="white"; + monitorCanvasCtx[monId].globalCompositeOperation="difference"; + monitorCanvasCtx[monId].fillText("+",iconSize*0.2, iconSize*1.2); + monitorCanvasCtx[monId].fillText("-",monitorCanvasObj[monId].width - iconSize*1.2, iconSize*1.2); + monitorCanvasCtx[monId].globalCompositeOperation="source-over"; + monitorLoadEndTimems[monId] = new Date().getTime(); // elapsed time to load + evaluateLoadTimes(); + } + monitorLoading[monId]=false; + if(!success) { + // if we had a failrue queue up the no-data image + loadImage2Monitor(monId,"no data"); // leave the staged URL if there is one, just ignore it here. + } else { + if(monitorLoadingStageURL[monId]=="") return; + loadImage2Monitor(monId,monitorLoadingStageURL[monId]); + monitorLoadingStageURL[monId]=""; + } + return; +} + +function loadImage2Monitor(monId,url) { + if ( monitorLoading[monId] && monitorImageObject[monId].src != url ) { + // never queue the same image twice (if it's loading it has to be defined, right? + monitorLoadingStageURL[monId] = url; // we don't care if we are overriting, it means it didn't change fast enough + } else { + if ( monitorImageObject[monId].src == url ) return; // do nothing if it's the same + if ( url == 'no data' ) { + monitorCanvasCtx[monId].fillStyle="white"; + monitorCanvasCtx[monId].fillRect(0,0,monitorCanvasObj[monId].width,monitorCanvasObj[monId].height); + var textSize=monitorCanvasObj[monId].width * 0.15; + var text="No Data"; + monitorCanvasCtx[monId].font = "600 " + textSize.toString() + "px Arial"; + monitorCanvasCtx[monId].fillStyle="black"; + var textWidth = monitorCanvasCtx[monId].measureText(text).width; + monitorCanvasCtx[monId].fillText(text,monitorCanvasObj[monId].width/2 - textWidth/2,monitorCanvasObj[monId].height/2); + } else { + monitorLoading[monId]=true; + monitorLoadStartTimems[monId]=new Date().getTime(); + monitorImageObject[monId].src=url; // starts a load but doesn't refresh yet, wait until ready + } + } +} +function timerFire() { + // See if we need to reschedule + if(currentDisplayInterval != timerInterval || currentSpeed == 0) { + // zero just turn off interrupts + clearInterval(timerObj); + timerInterval=currentDisplayInterval; + if(currentSpeed>0 || liveMode!=0) timerObj=setInterval(timerFire,timerInterval); // don't fire out of live mode if speed is zero + } + + if (liveMode) outputUpdate(currentTimeSecs); // In live mode we basically do nothing but redisplay + else if (currentTimeSecs + playSecsperInterval >= maxTimeSecs) // beyond the end just stop + { + setSpeed(0); + outputUpdate(currentTimeSecs); + } + else outputUpdate(currentTimeSecs + playSecsperInterval); + return; +} + +function drawSliderOnGraph(val) { + var sliderWidth=10; + var sliderLineWidth=1; + var sliderHeight=cHeight; + + if(liveMode==1) { + val=Math.floor( Date.now() / 1000); + } + // Set some sizes + + var labelpx = Math.max( 6, Math.min( 20, parseInt(cHeight * timeLabelsFractOfRow / (numMonitors+1)) ) ); + var labbottom=parseInt(cHeight * 0.2 / (numMonitors+1)).toString() + "px"; // This is positioning same as row labels below, but from bottom so 1-position + var labfont=labelpx + "px Georgia"; // set this like below row labels + + if(numMonitors>0) { + // if we have no data to display don't do the slider itself + var sliderX=parseInt( (val - minTimeSecs) / rangeTimeSecs * cWidth - sliderWidth/2); // position left side of slider + if(sliderX < 0) sliderX=0; + if(sliderX+sliderWidth > cWidth) sliderX=cWidth-sliderWidth-1; + + // If we have data already saved first restore it from LAST time + + if(typeof underSlider !== 'undefined') + { + ctx.putImageData(underSlider,underSliderX, 0, 0, 0, sliderWidth, sliderHeight); + underSlider=undefined; + } + if(liveMode==0) // we get rid of the slider if we switch to live (since it may not be in the "right" place) + { + // Now save where we are putting it THIS time + underSlider=ctx.getImageData(sliderX, 0, sliderWidth, sliderHeight); + // And add in the slider' + ctx.lineWidth=sliderLineWidth; + ctx.strokeStyle='black'; + // looks like strokes are on the outside (or could be) so shrink it by the line width so we replace all the pixels + ctx.strokeRect(sliderX+sliderLineWidth,sliderLineWidth,sliderWidth - 2*sliderLineWidth, sliderHeight - 2*sliderLineWidth); + underSliderX=sliderX; + } + var o = $('scruboutput'); + if(liveMode==1) + { + o.innerHTML="Live Feed @ " + (1000 / currentDisplayInterval).toFixed(1) + " fps"; + o.style.color="red"; + } + else + { + o.innerHTML=secs2dbstr(val); + o.style.color="blue"; + } + o.style.position="absolute"; + o.style.bottom=labbottom; + o.style.font=labfont; + // try to get length and then when we get too close to the right switch to the left + var len = o.offsetWidth; + var x; + if(sliderX > cWidth/2) + x=sliderX - len - 10; + else + x=sliderX + 10; + o.style.left=x.toString() + "px"; + } + + // This displays (or not) the left/right limits depending on how close the slider is. + // Because these change widths if the slider is too close, use the slider width as an estimate for the left/right label length (i.e. don't recalculate len from above) + // If this starts to collide increase some of the extra space + + var o = $('scrubleft'); + o.innerHTML=secs2dbstr(minTimeSecs); + o.style.position="absolute"; + o.style.bottom=labbottom; + o.style.font=labfont; + o.style.left="5px"; + if(numMonitors==0) // we need a len calculation if we skipped the slider + len = o.offsetWidth; + // If the slider will overlay part of this suppress (this is the left side) + if(len + 10 > sliderX || cWidth < len * 4 ) // that last check is for very narrow browsers + o.style.display="none"; + else + { + o.style.display="inline"; + o.style.display="inline-flex"; // safari won't take this but will just ignore + } + + var o = $('scrubright'); + o.innerHTML=secs2dbstr(maxTimeSecs); + o.style.position="absolute"; + o.style.bottom=labbottom; + o.style.font=labfont; + // If the slider will overlay part of this suppress (this is the right side) + o.style.left=(cWidth - len - 15).toString() + "px"; + if(sliderX > cWidth - len - 20 || cWidth < len * 4 ) + o.style.display="none"; + else + { + o.style.display="inline"; + o.style.display="inline-flex"; + } +} + +function drawGraph() +{ + var divWidth=$('timelinediv').clientWidth + canvas.width = cWidth = divWidth; // Let it float and determine width (it should be sized a bit smaller percentage of window) + canvas.height=cHeight = parseInt(window.innerHeight * 0.10); + if(eId.length==0) + { + ctx.font="40px Georgia"; + ctx.fillStyle="Black"; + ctx.globalAlpha=1; + var t="No data found in range - choose differently"; + var l=ctx.measureText(t).width; + ctx.fillText(t,(cWidth - l)/2, cHeight-10); + underSlider=undefined; + return; + } + var rowHeight=parseInt(cHeight / (numMonitors + 1) ); // Leave room for a scale of some sort + + // first fill in the bars for the events (not alarms) + + for(var i=0; i0); i++) // Now put in scored frames (if any) + { + var x1=parseInt( (fTimeFromSecs[i] - minTimeSecs) / rangeTimeSecs * cWidth) ; // round low end down + var x2=parseInt( (fTimeToSecs[i] - minTimeSecs) / rangeTimeSecs * cWidth + 0.5 ) ; // round up + if(x2-x1 < 2) x2=x1+2; // So it is visible make them all at least this number of seconds wide + ctx.fillStyle=monitorColour[fMonId[i]]; + ctx.globalAlpha = 0.4 + 0.6 * (1 - fScore[i]/maxScore); // Background is scaled but even lowest is twice as dark as the background + ctx.fillRect(x1,monitorIndex[fMonId[i]]*rowHeight,x2-x1,rowHeight); + } + for(var i=0; i0) + { + if(maxSecs > now) + maxSecs = parseInt(now); + maxStr="&maxTime=" + secs2dbstr(maxSecs); + } + if(maxSecs>0) + minStr="&minTime=" + secs2dbstr(minSecs); + if(maxSecs==0 && minSecs==0) + { + minStr="&minTime=01/01/1950 12:00:00"; + maxStr="&maxTime=12/31/2035 12:00:00"; + } + var intervalStr="&displayinterval=" + currentDisplayInterval.toString(); + if(minSecs && maxSecs) + { + if(currentTimeSecs > minSecs && currentTimeSecs < maxSecs) // make sure time is in the new range + currentStr="¤t=" + secs2dbstr(currentTimeSecs); + } + + var liveStr="&live=0"; + if(live==1) + liveStr="&live=1"; + + var fitStr="&fit=0"; + if(fitMode==1) + fitStr="&fit=1"; + + var zoomStr=""; + for(var i=0; i 1.01) // allow for some up/down changes and just treat as 1 of almost 1 + zoomStr += "&z" + monitorPtr[i].toString() + "=" + monitorZoomScale[monitorPtr[i]].toFixed(2); + + var uri = "?view=" + currentView + fitStr + groupStr + minStr + maxStr + currentStr + intervalStr + liveStr + zoomStr + "&scale=" + document.getElementById("scaleslider").value + "&speed=" + speeds[document.getElementById("speedslider").value]; + window.location=uri; +} + +function lastHour() +{ + var now = new Date() / 1000; + clicknav(now - 3600 + 1, now,1,0); +} +function lastEight() +{ + var now = new Date() / 1000; + clicknav(now - 3600*8 + 1, now,1,0); +} +function zoomin() +{ + rangeTimeSecs = parseInt(rangeTimeSecs / 2); + minTimeSecs = parseInt(currentTimeSecs - rangeTimeSecs/2); // this is the slider current time, we center on that + maxTimeSecs = parseInt(currentTimeSecs + rangeTimeSecs/2); + clicknav(minTimeSecs,maxTimeSecs,1,0); +} + +function zoomout() +{ + rangeTimeSecs = parseInt(rangeTimeSecs * 2); + minTimeSecs = parseInt(currentTimeSecs - rangeTimeSecs/2); // this is the slider current time, we center on that + maxTimeSecs = parseInt(currentTimeSecs + rangeTimeSecs/2); + clicknav(minTimeSecs,maxTimeSecs,1,0); +} +function panleft() +{ + minTimeSecs = parseInt(minTimeSecs - rangeTimeSecs/2); + maxTimeSecs = minTimeSecs + rangeTimeSecs - 1; + clicknav(minTimeSecs,maxTimeSecs,1,0); +} +function panright() +{ + minTimeSecs = parseInt(minTimeSecs + rangeTimeSecs/2); + maxTimeSecs = minTimeSecs + rangeTimeSecs - 1; + clicknav(minTimeSecs,maxTimeSecs,1,0); +} +function allof() +{ + clicknav(0,0,1,0); +} +function allnon() +{ + clicknav(0,0,0,0); +} +/// >>>>>>>>>>>>>>>>> handles packing different size/aspect monitors on screen <<<<<<<<<<<<<<<<<<<<<<<< + +function compSize(a, b) // sort array by some size parameter - height seems to work best. A semi-greedy algorithm +{ + if ( monitorHeight[a] * monitorWidth[a] * monitorNormalizeScale[a] * monitorZoomScale[a] * monitorNormalizeScale[a] * monitorZoomScale[a] > monitorHeight[b] * monitorWidth[b] * monitorNormalizeScale[b] * monitorZoomScale[b] * monitorNormalizeScale[b] * monitorZoomScale[b]) return -1; + else if ( monitorHeight[a] * monitorWidth[a] * monitorNormalizeScale[a] * monitorZoomScale[a] * monitorNormalizeScale[a] * monitorZoomScale[a] == monitorHeight[b] * monitorWidth[b] * monitorNormalizeScale[b] * monitorZoomScale[b] * monitorNormalizeScale[b] * monitorZoomScale[b]) return 0; + else return 1; +} + + +function maxfit2(divW, divH) +{ + var bestFitX=[]; // how we arranged the so-far best match + var bestFitX2=[]; + var bestFitY=[]; + var bestFitY2=[]; + var bestFitScale; + + var minScale=0.05; + var maxScale=5.00; + var bestFitArea=0; + + var borders=-1; + + monitorPtr.sort(compSize); + + while(1) + { + if( maxScale - minScale < 0.01 ) break; + var thisScale = (maxScale + minScale) / 2; + var allFit=1; + var thisArea=0; + var thisX=[]; // top left + var thisY=[]; + var thisX2=[]; // bottom right + var thisY2=[]; + + for(var m=0; m=divW) return 0; + if(y+h>=divH) return 0; + for(var i=0; i<=d; i++) + if( !( thisX[i]>x+w-1 || thisX2[i] < x || thisY[i] > y+h-1 || thisY2[i] < y ) ) return 0; + return 1; // it's OK + } + + if(borders<=0) borders=$("Monitor"+monitorPtr[m]).getStyle("border").toInt() * 2; // assume fixed size border, and added to both sides and top/bottom + // try fitting over first, then down. Each new one must land at either upper right or lower left corner of last (try in that order) + // Pick the one with the smallest Y, then smallest X if Y equal + var fitX = 999999999; + var fitY = 999999999; + for( adjacent=0; adjacent0) // only rearrange if we could fit -- otherwise just do nothing, let them start coming out, whatever + { + for(m=0; m>>>>>>>>>>>>>>> Handles individual monitor clicks and navigation to the standard event/watch display + +function showOneMonitor(monId) // link out to the normal view of one event's data +{ + // We know the monitor, need to determine the event based on current time + var url; + if(liveMode!=0) url="?view=watch&mid=" + monId.toString(); + else + for(var i=0; i= eStartSecs[i] && currentTimeSecs <= eEndSecs[i]) + url="?view=event&eid=" + eId[i] + '&fid=' + parseInt(Math.max(1, Math.min(eventFrames[i], eventFrames[i] * (currentTimeSecs - eStartSecs[i]) / (eEndSecs[i] - eStartSecs[i] + 1) ) )); + createPopup(url, 'zmEvent', 'event', monitorWidth[eMonId[i]], monitorHeight[eMonId[i]]); +} + +function zoom(monId,scale) +{ + var lastZoomMonPriorScale=monitorZoomScale[monId]; + monitorZoomScale[monId] *= scale; + if(redrawScreen()==0) // failure here is probably because we zoomed too far + { + monitorZoomScale[monId]=lastZoomMonPriorScale; + alert("You can't zoom that far -- rolling back"); + redrawScreen(); // put things back and hope it works + } +} + +function clickMonitor(event,monId) +{ + var pos_x = event.offsetX ? (event.offsetX) : event.pageX - $("Monitor"+monId.toString()).offsetLeft; + var pos_y = event.offsetY ? (event.offsetY) : event.pageY - $("Monitor"+monId.toString()).offsetTop; + if(pos_x < $("Monitor"+monId.toString()).width/4 && pos_y < $("Monitor"+monId.toString()).height/4) zoom(monId,1.15); + else if(pos_x > $("Monitor"+monId.toString()).width * 3/4 && pos_y < $("Monitor"+monId.toString()).height/4) zoom(monId,1/1.15); + else showOneMonitor(monId); + return; +} + +// >>>>>>>>> Initialization that runs on window load by being at the bottom + +function initPage() { + canvas=$("timeline"); + ctx=canvas.getContext('2d'); + for ( var i = 0; i < monitorPtr.length; i += 1 ) { + var monId = monitorPtr[i]; + monitorCanvasObj[monId] = $('Monitor'+monId ); + monitorCanvasCtx[monId]=monitorCanvasObj[monId].getContext('2d'); + } + drawGraph(); + setSpeed(speedIndex); + setFit(fitMode); // will redraw + setLive(liveMode); // will redraw +} +window.addEventListener("resize",redrawScreen); +// Kick everything off +window.addEvent( 'domready', initPage ); diff --git a/web/skins/classic/views/js/montagereview.js.php b/web/skins/classic/views/js/montagereview.js.php new file mode 100644 index 000000000..8248a2c67 --- /dev/null +++ b/web/skins/classic/views/js/montagereview.js.php @@ -0,0 +1,190 @@ + +var currentScale=; +var liveMode=; +var fitMode=; +var currentSpeed=; // slider scale, which is only for replay and relative to real time +var speedIndex=; +var currentDisplayInterval=; // will be set based on performance, this is the display interval in milliseconds for history, and fps for live, and dynamically determined (in ms) +var playSecsperInterval=1; // How many seconds of recorded image we play per refresh determined by speed (replay rate) and display interval; (default=1 if coming from live) +var timerInterval; // milliseconds between interrupts +var timerObj; // object to hold timer interval; +var freeTimeLastIntervals=[]; // Percentage of current interval used in loading most recent image +var imageLoadTimesEvaluated=0; // running count +var imageLoadTimesNeeded=15; // and how many we need +var timeLabelsFractOfRow = 0.9; +var eMonId = []; +var eId = []; +var eStartSecs = []; +var eEndSecs = []; +var eventFrames = []; // this is going to presume all frames equal durationlength +var zeropad = ; +var groupStr=; + + $event['StartTimeSecs']) $minTimeSecs = $event['StartTimeSecs']; + if( $maxTimeSecs < $event['CalcEndTimeSecs']) $maxTimeSecs = $event['CalcEndTimeSecs']; + echo "eMonId[$index]=" . $event['MonitorId'] . "; + eId[$index]=" . $event['Id'] . "; + eStartSecs[$index]=" . $event['StartTimeSecs'] . "; + eEndSecs[$index]=" . $event['CalcEndTimeSecs'] . "; + eventFrames[$index]=" . $event['Frames'] . ";\n"; + + $index = $index + 1; + if($event['MaxScore']>0) + $anyAlarms = true; + echo "\n"; +} + +// if there is no data set the min/max to the passed in values +if($index == 0) { + if(isset($minTime) && isset($maxTime)) { + $minTimeSecs = strtotime($minTime); + $maxTimeSecs = strtotime($maxTime); + } else { + // this is the case of no passed in times AND no data -- just set something arbitrary + $minTimeSecs=strtotime('1950-06-01 01:01:01'); // random time so there's something to display + $maxTimeSecs=time() + 86400; + } +} + +// We only reset the calling time if there was no calling time +if(!isset($minTime) || !isset($maxTime)) { + $maxTime = strftime($maxTimeSecs); + $minTime = strftime($minTimeSecs); +} else { + $minTimeSecs = strtotime($minTime); + $maxTimeSecs = strtotime($maxTime); +} + +// If we had any alarms in those events, this builds the list of all alarm frames, but consolidated down to (nearly) contiguous segments +// comparison in else governs how aggressively it consolidates + +echo "var fMonId = [];\n"; +echo "var fTimeFromSecs = [];\n"; +echo "var fTimeToSecs = [];\n"; +echo "var fScore = [];\n"; +$maxScore=0; +$index=0; +$mId=-1; +$fromSecs=-1; +$toSecs=-1; +$maxScore=-1; + +if($anyAlarms) { + foreach( dbFetchAll ($frameSql) as $frame ) { + if($mId<0) { + $mId=$frame['MonitorId']; + $fromSecs=$frame['TimeStampSecs']; + $toSecs=$frame['TimeStampSecs']; + $maxScore=$frame['Score']; + } else if ($mId != $frame['MonitorId'] || $frame['TimeStampSecs'] - $toSecs > 10) { + // dump this one start a new + $index++; + echo " fMonId[$index]=" . $mId . ";"; + echo " fTimeFromSecs[$index]=" . $fromSecs . ";"; + echo " fTimeToSecs[$index]=" . $toSecs . ";"; + echo " fScore[$index]=" . $maxScore . ";\n"; + $mId=$frame['MonitorId']; + $fromSecs=$frame['TimeStampSecs']; + $toSecs=$frame['TimeStampSecs']; + $maxScore=$frame['Score']; + } else { + // just add this one on + $toSecs=$frame['TimeStampSecs']; + if($maxScore < $frame['Score']) $maxScore=$frame['Score']; + } + } +} +if($mId>0) { + echo " fMonId[$index]=" . $mId . ";"; + echo " fTimeFromSecs[$index]=" . $fromSecs . ";"; + echo " fTimeToSecs[$index]=" . $toSecs . ";"; + echo " fScore[$index]=" . $maxScore . ";\n"; +} + +echo "var maxScore=$maxScore;\n"; // used to skip frame load if we find no alarms. +echo "var monitorName = [];\n"; +echo "var monitorLoading = [];\n"; +echo "var monitorImageObject = [];\n"; +echo "var monitorLoadingStageURL = [];\n"; +echo "var monitorLoadStartTimems = [];\n"; +echo "var monitorLoadEndTimems = [];\n"; +echo "var monitorColour = [];\n"; +echo "var monitorWidth = [];\n"; +echo "var monitorHeight = [];\n"; +echo "var monitorIndex = [];\n"; +echo "var monitorNormalizeScale = [];\n"; +echo "var monitorZoomScale = [];\n"; +echo "var monitorCanvasObj = [];\n"; // stash location of these here so we don't have to search +echo "var monitorCanvasCtx = [];\n"; +echo "var monitorPtr = []; // monitorName[monitorPtr[0]] is first monitor\n"; + + +$numMonitors=0; // this array is indexed by the monitor ID for faster access later, so it may be sparse +$avgArea=floatval(0); // Calculations the normalizing scale + +foreach ($monitors as $m) { + $avgArea = $avgArea + floatval($m->Width() * $m->Height()); + $numMonitors++; +} + +if($numMonitors>0) $avgArea= $avgArea / $numMonitors; + +$numMonitors=0; +foreach ($monitors as $m) { + echo " monitorLoading[" . $m->Id() . "]=false;\n"; + echo " monitorImageObject[" . $m->Id() . "]=new Image();\n"; + echo " monitorImageObject[" . $m->Id() . "].src='".$m->getStreamSrc( array('mode'=>'single','scale'=>$defaultScale) )."';\n"; + echo " monitorImageObject[" . $m->Id() . "].onload = function() {imagedone(this, ".$m->Id().",true )};\n"; + echo " monitorImageObject[" . $m->Id() . "].onerror = function() {imagedone(this, ".$m->Id().",false )};\n"; + echo " monitorLoadingStageURL[" . $m->Id() . "] = '';\n"; + echo " monitorColour[" . $m->Id() . "]=\"" . $m->WebColour() . "\";\n"; + echo " monitorWidth[" . $m->Id() . "]=" . $m->Width() . ";\n"; + echo " monitorHeight[" . $m->Id() . "]=" . $m->Height() . ";\n"; + echo " monitorIndex[" . $m->Id() . "]=" . $numMonitors . ";\n"; + echo " monitorName[" . $m->Id() . "]=\"" . $m->Name() . "\";\n"; + echo " monitorLoadStartTimems[" . $m->Id() . "]=0;\n"; + echo " monitorLoadEndTimems[" . $m->Id() . "]=0;\n"; + echo " monitorNormalizeScale[" . $m->Id() . "]=" . sqrt($avgArea / ($m->Width() * $m->Height() )) . ";\n"; + $zoomScale=1.0; + if(isset($_REQUEST[ 'z' . $m->Id() ]) ) + $zoomScale = floatval( validHtmlStr($_REQUEST[ 'z' . $m->Id() ]) ); + echo " monitorZoomScale[" . $m->Id() . "]=" . $zoomScale . ";\n"; + echo " monitorPtr[" . $numMonitors . "]=" . $m->Id() . ";\n"; + $numMonitors += 1; +} +echo "var numMonitors = $numMonitors;\n"; +echo "var minTimeSecs=" . $minTimeSecs . ";\n"; +echo "var maxTimeSecs=" . $maxTimeSecs . ";\n"; +echo "var rangeTimeSecs=" . ( $maxTimeSecs - $minTimeSecs + 1) . ";\n"; +if(isset($defaultCurrentTime)) + echo "var currentTimeSecs=" . strtotime($defaultCurrentTime) . ";\n"; +else + echo "var currentTimeSecs=" . ($minTimeSecs + $maxTimeSecs)/2 . ";\n"; + +echo "var speeds=["; +for ($i=0; $i0)?", ":"") . $speeds[$i]; +echo "];\n"; +?> + +var scrubAsObject=document.getElementById('scrub'); +var cWidth; // save canvas width +var cHeight; // save canvas height +var canvas; // global canvas definition so we don't have to keep looking it up +var ctx; +var underSlider; // use this to hold what is hidden by the slider +var underSliderX; // Where the above was taken from (left side, Y is zero) + diff --git a/web/skins/classic/views/montagereview.php b/web/skins/classic/views/montagereview.php index 5a153dd9e..0c4342e8e 100644 --- a/web/skins/classic/views/montagereview.php +++ b/web/skins/classic/views/montagereview.php @@ -95,20 +95,20 @@ // if ( !canView( 'Events' ) ) { - $view = 'error'; - return; + $view = 'error'; + return; } require_once( 'includes/Monitor.php' ); # FIXME THere is no way to select group at this time. if ( !empty($_REQUEST['group']) ) { - $group = $_REQUEST['group']; - $row = dbFetchOne( 'SELECT * FROM Groups WHERE Id = ?', NULL, array($_REQUEST['group']) ); - $monitorsSql = "SELECT * FROM Monitors WHERE Function != 'None' AND find_in_set( Id, '".$row['MonitorIds']."' ) "; + $group = $_REQUEST['group']; + $row = dbFetchOne( 'SELECT * FROM Groups WHERE Id = ?', NULL, array($_REQUEST['group']) ); + $monitorsSql = "SELECT * FROM Monitors WHERE Function != 'None' AND find_in_set( Id, '".$row['MonitorIds']."' ) "; } else { - $monitorsSql = "SELECT * FROM Monitors WHERE Function != 'None'"; - $group = ''; + $monitorsSql = "SELECT * FROM Monitors WHERE Function != 'None'"; + $group = ''; } // Note that this finds incomplete events as well, and any frame records written, but still cannot "see" to the end frame @@ -222,7 +222,7 @@ $monitors = array(); $monitorsSql .= ' ORDER BY Sequence ASC'; $index=0; foreach( dbFetchAll( $monitorsSql ) as $row ) { - $monitors[$index] = $row; + $monitors[$index] = new Monitor( $row ); $index = $index + 1; } @@ -270,921 +270,15 @@ input[type=range]::-ms-tooltip { +
'; foreach ($monitors as $m) { - echo 'No Canvas Support!!'; + echo 'No Canvas Support!!'; } -echo "
\n"; -echo "

evaluating fps

\n"; -echo " + +

evaluating fps