Merge branch 'storageareas' of github.com:ConnorTechnology/ZoneMinder into storageareas

This commit is contained in:
Isaac Connor 2017-10-18 13:27:13 -04:00
commit b11a514823
15 changed files with 158 additions and 116 deletions

View File

@ -69,7 +69,7 @@ void zmLoadConfig() {
Debug( 1, "Fetching ZM_SERVER_ID For Name = %s", staticConfig.SERVER_NAME.c_str() );
std::string sql = stringtf("SELECT Id FROM Servers WHERE Name='%s'", staticConfig.SERVER_NAME.c_str() );
zmDbRow dbrow;
zmDbRow dbrow;
if ( dbrow.fetch( sql.c_str() ) ) {
staticConfig.SERVER_ID = atoi(dbrow[0]);
} else {
@ -81,12 +81,12 @@ void zmLoadConfig() {
Debug( 1, "Fetching ZM_SERVER_NAME For Id = %d", staticConfig.SERVER_ID );
std::string sql = stringtf("SELECT Name FROM Servers WHERE Id='%d'", staticConfig.SERVER_ID );
zmDbRow dbrow;
if ( dbrow.fetch( sql.c_str() ) ) {
staticConfig.SERVER_NAME = std::string(dbrow[0]);
} else {
Fatal("Can't get ServerName for Server ID %d", staticConfig.SERVER_ID );
}
zmDbRow dbrow;
if ( dbrow.fetch( sql.c_str() ) ) {
staticConfig.SERVER_NAME = std::string(dbrow[0]);
} else {
Fatal("Can't get ServerName for Server ID %d", staticConfig.SERVER_ID );
}
if ( staticConfig.SERVER_ID ) {
Debug( 3, "Multi-server configuration detected. Server is %d.", staticConfig.SERVER_ID );

View File

@ -131,16 +131,17 @@ void Logger::initialise( const std::string &id, const Options &options ) {
this->id( id );
std::string tempLogFile;
if ( options.mLogPath.size() ) {
mLogPath = options.mLogPath;
tempLogFile = mLogPath+"/"+mId+".log";
}
if ( options.mLogFile.size() )
tempLogFile = options.mLogFile;
else
tempLogFile = mLogPath+"/"+mId+".log";
if ( (envPtr = getTargettedEnv( "LOG_FILE" )) )
tempLogFile = envPtr;
else if ( options.mLogFile.size() )
tempLogFile = options.mLogFile;
else {
if ( options.mLogPath.size() ) {
mLogPath = options.mLogPath;
}
tempLogFile = mLogPath+"/"+mId+".log";
}
Level tempLevel = INFO;
Level tempTermLevel = mTermLevel;
@ -560,7 +561,7 @@ void logInit( const char *name, const Logger::Options &options ) {
if ( !Logger::smInstance )
Logger::smInstance = new Logger();
Logger::Options tempOptions = options;
tempOptions.mLogPath = staticConfig.PATH_LOGS.c_str();
tempOptions.mLogPath = staticConfig.PATH_LOGS;
Logger::smInstance->initialise( name, tempOptions );
}

View File

@ -56,8 +56,7 @@ public:
typedef std::map<Level,std::string> StringMap;
typedef std::map<Level,int> IntMap;
class Options
{
class Options {
public:
int mTermLevel;
int mDatabaseLevel;
@ -166,8 +165,7 @@ public:
}
Level level( Level=NOOPT );
bool debugOn()
{
bool debugOn() {
return( mEffectiveLevel >= DEBUG1 );
}
@ -190,20 +188,16 @@ public:
void logInit( const char *name, const Logger::Options &options=Logger::Options() );
void logTerm();
inline const std::string &logId()
{
inline const std::string &logId() {
return( Logger::fetch()->id() );
}
inline Logger::Level logLevel()
{
inline Logger::Level logLevel() {
return( Logger::fetch()->level() );
}
inline void logCapLevel( Logger::Level level )
{
inline void logCapLevel( Logger::Level level ) {
Logger::fetch()->level( level );
}
inline Logger::Level logDebugging()
{
inline Logger::Level logDebugging() {
return( Logger::fetch()->debugOn() );
}

View File

@ -1198,7 +1198,7 @@ bool Monitor::Analyse() {
int pending_frames = shared_data->last_write_index - shared_data->last_read_index;
if ( pending_frames < 0 ) pending_frames += image_buffer_count;
Debug( 4, "RI:%d, WI: %d, PF = %d, RM = %d, Step = %d", shared_data->last_read_index, shared_data->last_write_index, pending_frames, read_margin, step );
Debug( 4, "ReadIndex:%d, WriteIndex: %d, PendingFrames = %d, ReadMargin = %d, Step = %d", shared_data->last_read_index, shared_data->last_write_index, pending_frames, read_margin, step );
if ( step <= pending_frames ) {
index = (shared_data->last_read_index+step)%image_buffer_count;
} else {

View File

@ -57,8 +57,7 @@ behind.
#include "zm_signal.h"
#include "zm_monitor.h"
void Usage()
{
void Usage() {
fprintf( stderr, "zma -m <monitor_id>\n" );
fprintf( stderr, "Options:\n" );
fprintf( stderr, " -m, --monitor <monitor_id> : Specify which monitor to use\n" );
@ -67,8 +66,7 @@ void Usage()
exit( 0 );
}
int main( int argc, char *argv[] )
{
int main( int argc, char *argv[] ) {
self = argv[0];
srand( getpid() * time( 0 ) );
@ -82,18 +80,15 @@ int main( int argc, char *argv[] )
{0, 0, 0, 0}
};
while (1)
{
while (1) {
int option_index = 0;
int c = getopt_long (argc, argv, "m:h:v", long_options, &option_index);
if (c == -1)
{
if ( c == -1 ) {
break;
}
switch (c)
{
switch (c) {
case 'm':
id = atoi(optarg);
break;
@ -110,8 +105,7 @@ int main( int argc, char *argv[] )
}
}
if (optind < argc)
{
if (optind < argc) {
fprintf( stderr, "Extraneous options, " );
while (optind < argc)
printf ("%s ", argv[optind++]);
@ -119,8 +113,7 @@ int main( int argc, char *argv[] )
Usage();
}
if ( id < 0 )
{
if ( id < 0 ) {
fprintf( stderr, "Bogus monitor %d\n", id );
Usage();
exit( 0 );
@ -137,8 +130,7 @@ int main( int argc, char *argv[] )
Monitor *monitor = Monitor::Load( id, true, Monitor::ANALYSIS );
if ( monitor )
{
if ( monitor ) {
Info( "In mode %d/%d, warming up", monitor->GetFunction(), monitor->Enabled() );
zmSetDefaultHupHandler();
@ -154,43 +146,34 @@ int main( int argc, char *argv[] )
monitor->UpdateAdaptiveSkip();
last_analysis_update_time = time( 0 );
while( !zm_terminate )
{
while( !zm_terminate ) {
// Process the next image
sigprocmask( SIG_BLOCK, &block_set, 0 );
// Some periodic updates are required for variable capturing framerate
if ( analysis_update_delay )
{
if ( analysis_update_delay ) {
cur_time = time( 0 );
if ( (unsigned int)( cur_time - last_analysis_update_time ) > analysis_update_delay )
{
if ( (unsigned int)( cur_time - last_analysis_update_time ) > analysis_update_delay ) {
analysis_rate = monitor->GetAnalysisRate();
monitor->UpdateAdaptiveSkip();
last_analysis_update_time = cur_time;
}
}
if ( !monitor->Analyse() )
{
if ( !monitor->Analyse() ) {
usleep( monitor->Active()?ZM_SAMPLE_RATE:ZM_SUSPENDED_RATE );
}
else if ( analysis_rate )
{
} else if ( analysis_rate ) {
usleep( analysis_rate );
}
if ( zm_reload )
{
if ( zm_reload ) {
monitor->Reload();
zm_reload = false;
}
sigprocmask( SIG_UNBLOCK, &block_set, 0 );
}
delete monitor;
}
else
{
} else {
fprintf( stderr, "Can't find monitor with id of %d\n", id );
}
Image::Deinitialise();

View File

@ -48,10 +48,16 @@ class Event {
}
public function __call( $fn, array $args){
if ( count( $args ) ) {
$this->{$fn} = $args[0];
}
if ( array_key_exists( $fn, $this ) ) {
return $this->{$fn};
#array_unshift($args, $this);
#call_user_func_array( $this->{$fn}, $args);
$backTrace = debug_backtrace();
$file = $backTrace[1]['file'];
$line = $backTrace[1]['line'];
Warning( "Unknown function call Event->$fn from $file:$line" );
}
}

View File

@ -36,10 +36,16 @@ class Frame {
return new Event( $this->{'EventId'} );
}
public function __call( $fn, array $args){
if( array_key_exists( $fn, $this ) ) {
if ( count( $args ) ) {
$this->{$fn} = $args[0];
}
if ( array_key_exists( $fn, $this ) ) {
return $this->{$fn};
#array_unshift($args, $this);
#call_user_func_array( $this->{$fn}, $args);
$backTrace = debug_backtrace();
$file = $backTrace[1]['file'];
$line = $backTrace[1]['line'];
Warning( "Unknown function call Frame->$fn from $file:$line" );
}
}

View File

@ -58,10 +58,16 @@ class Storage {
}
public function __call( $fn, array $args= NULL){
if(isset($this->{$fn})){
if ( count( $args ) ) {
$this->{$fn} = $args[0];
}
if ( array_key_exists( $fn, $this ) ) {
return $this->{$fn};
#array_unshift($args, $this);
#call_user_func_array( $this->{$fn}, $args);
$backTrace = debug_backtrace();
$file = $backTrace[1]['file'];
$line = $backTrace[1]['line'];
Warning( "Unknown function call Storage->$fn from $file:$line" );
}
}
public static function find_all() {

View File

@ -127,10 +127,10 @@ function dbQuery( $sql, $params=NULL ) {
} else {
$result = $dbConn->query( $sql );
}
//if ( $params )
//Warning("SQL: $sql" . implode(',',$params));
//else
//Warning("SQL: $sql" );
if ( $params )
Warning("SQL: $sql" . implode(',',$params));
else
Warning("SQL: $sql" );
} catch(PDOException $e) {
Error( "SQL-ERR '".$e->getMessage()."', statement was '".$sql."' params:" . implode(',',$params) );
}

View File

@ -48,11 +48,13 @@ function xhtmlHeaders( $file, $title ) {
<title><?php echo ZM_WEB_TITLE_PREFIX ?> - <?php echo validHtmlStr($title) ?></title>
<?php
if ( file_exists( "skins/$skin/css/$css/graphics/favicon.ico" ) ) {
echo "<link rel=\"icon\" type=\"image/ico\" href=\"skins/$skin/css/$css/graphics/favicon.ico\"/>";
echo "<link rel=\"shortcut icon\" href=\"skins/$skin/css/$css/graphics/favicon.ico\"/>";
echo "<link rel=\"icon\" type=\"image/ico\" href=\"skins/$skin/css/$css/graphics/favicon.ico\"/>\n";
echo "<link rel=\"shortcut icon\" href=\"skins/$skin/css/$css/graphics/favicon.ico\"/>\n";
} else {
echo '<link rel="icon" type="image/ico" href="graphics/favicon.ico"/>';
echo '<link rel="shortcut icon" href="graphics/favicon.ico"/>';
echo '
<link rel="icon" type="image/ico" href="graphics/favicon.ico"/>
<link rel="shortcut icon" href="graphics/favicon.ico"/>
';
}
?>
<link rel="stylesheet" href="css/reset.css" type="text/css"/>
@ -107,6 +109,7 @@ if ( file_exists( "skins/$skin/css/$css/graphics/favicon.ico" ) ) {
<script src="skins/<?php echo $skin ?>/js/moment.min.js"></script>
<?php
}
if ( $skinJsPhpFile ) {
?>
<script type="text/javascript">

View File

@ -158,6 +158,8 @@ if ( $pagination ) {
<tbody>
<?php
$count = 0;
$disk_space_total = 0;
foreach ( $events as $event ) {
if ( ($count++%ZM_WEB_EVENTS_PER_PAGE) == 0 ) {
?>
@ -174,7 +176,8 @@ foreach ( $events as $event ) {
<th class="colAvgScore"><a href="<?php echo sortHeader( 'AvgScore' ) ?>"><?php echo translate('AvgBrScore') ?><?php echo sortTag( 'AvgScore' ) ?></a></th>
<th class="colMaxScore"><a href="<?php echo sortHeader( 'MaxScore' ) ?>"><?php echo translate('MaxBrScore') ?><?php echo sortTag( 'MaxScore' ) ?></a></th>
<?php
if ( ZM_WEB_EVENT_DISK_SPACE ) { ?>
if ( ZM_WEB_EVENT_DISK_SPACE ) {
?>
<th class="colDiskSpace"><a href="<?php echo sortHeader( 'DiskSpace' ) ?>"><?php echo translate('DiskSpace') ?><?php echo sortTag( 'DiskSpace' ) ?></a></th>
<?php
}
@ -206,6 +209,7 @@ makePopupLink( '?view=monitor&amp;mid='.$event->MonitorId(), 'zmMonitor'.$event-
<td class="colMaxScore"><?php echo makePopupLink( '?view=frame&amp;eid='.$event->Id().'&amp;fid=0', 'zmImage', array( 'image', reScale( $event->Width(), $scale ), reScale( $event->Height(), $scale ) ), $event->MaxScore() ) ?></td>
<?php
if ( ZM_WEB_EVENT_DISK_SPACE ) {
$disk_space_total += $event->DiskSpace();
?>
<td class="colDiskSpace"><?php echo human_filesize( $event->DiskSpace() ) ?></td>
<?php
@ -248,6 +252,24 @@ Warning("Not Using snapshot" . $event->Path().'/snapshot.jpg' );
}
?>
</tbody>
<?php
if ( ZM_WEB_EVENT_DISK_SPACE ) {
?>
<tfoot>
<tr>
<td colspan="11">Totals:</td>
<td class="colDiskSpace"><?php echo human_filesize( $disk_space_total ) ?></td>
<?php
if ( ZM_WEB_LIST_THUMBS ) {
?><td></td>
<?php
}
?>
</tr>
</tfoot>
<?php
}
?>
</table>
<?php
if ( $pagination ) {

View File

@ -1,3 +1,5 @@
var date = new Date();
function evaluateLoadTimes() {
// Only consider it a completed event if we load ALL monitors, then zero all and start again
var start=0;
@ -16,6 +18,7 @@ function evaluateLoadTimes() {
monitorLoadStartTimems[monId] = 0;
monitorLoadEndTimems[monId] = 0;
}
freeTimeLastIntervals[imageLoadTimesEvaluated++] = 1 - ((end - start)/currentDisplayInterval);
if ( imageLoadTimesEvaluated < imageLoadTimesNeeded ) return;
var avgFrac=0;
@ -35,7 +38,7 @@ function evaluateLoadTimes() {
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
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) + ".";
@ -52,6 +55,7 @@ function SetImageSource( monId, time ) {
if ( eMonId[i] == monId && time >= eStartSecs[i] && time <= eEndSecs[i] ) {
var duration = eEndSecs[i]-eStartSecs[i];
var frame = parseInt((time - eStartSecs[i])/(duration)*eventFrames[i])+1;
console.log("SetImageSource: " + time + " duration: " + duration + " frame: " + frame );
return "index.php?view=image&eid=" + eId[i] + '&fid='+frame + "&width=" + monitorCanvasObj[monId].width + "&height=" + monitorCanvasObj[monId].height;
}
} // end for
@ -133,17 +137,18 @@ function timerFire() {
// 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 ( 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
console.log("Current time " + currentTimeSecs + " + " + playSecsperInterval + " >= " + maxTimeSecs + " so stopping");
setSpeed(0);
outputUpdate(currentTimeSecs);
} else {
outputUpdate(currentTimeSecs + playSecsperInterval);
outputUpdate(playSecsperInterval + currentTimeSecs);
}
return;
}
@ -353,15 +358,14 @@ function redrawScreen() {
timerFire(); // force a fire in case it's not timing
}
function outputUpdate(val) {
drawSliderOnGraph(val);
function outputUpdate(time) {
drawSliderOnGraph(time);
for ( var i=0; i < numMonitors; i++ ) {
loadImage2Monitor(monitorPtr[i],SetImageSource(monitorPtr[i],val));
loadImage2Monitor(monitorPtr[i],SetImageSource(monitorPtr[i],time));
}
currentTimeSecs = parseInt(val);
currentTimeSecs = time;
}
/// Found this here: http://stackoverflow.com/questions/55677/how-do-i-get-the-coordinates-of-a-mouse-click-on-a-canvas-element
function relMouseCoords(event){
var totalOffsetX = 0;
@ -370,11 +374,10 @@ function relMouseCoords(event){
var canvasY = 0;
var currentElement = this;
do{
do {
totalOffsetX += currentElement.offsetLeft - currentElement.scrollLeft;
totalOffsetY += currentElement.offsetTop - currentElement.scrollTop;
}
while(currentElement = currentElement.offsetParent)
} while(currentElement = currentElement.offsetParent);
canvasX = event.pageX - totalOffsetX;
canvasY = event.pageY - totalOffsetY;
@ -413,8 +416,8 @@ function setFit(value) {
redrawScreen();
}
function showScale(newscale) // updates slider only
{
function showScale(newscale) {
// updates slider only
$('scaleslideroutput').innerHTML = parseFloat(newscale).toFixed(2).toString() + " x";
return;
}
@ -434,17 +437,18 @@ function showSpeed(val) {
$('speedslideroutput').innerHTML = parseFloat(speeds[val]).toFixed(2).toString() + " x";
}
function setSpeed(val) { // Note parameter is the index not the speed
function setSpeed( speed_index ) {
if ( liveMode == 1 ) return; // we shouldn't actually get here but just in case
currentSpeed=parseFloat(speeds[val]);
speedIndex = val;
playSecsperInterval = currentSpeed * currentDisplayInterval / 1000;
showSpeed(val);
currentSpeed = parseFloat(speeds[speed_index]);
speedIndex = speed_index;
playSecsperInterval = Math.floor( 1000 * currentSpeed * currentDisplayInterval ) / 1000000;
console.log("playSecsPerInterval: " + playSecsperInterval + " = currentspeed:" + currentSpeed + " * " + currentDisplayInterval + " /1000");
showSpeed(speed_index);
if ( timerInterval != currentDisplayInterval || currentSpeed == 0 ) timerFire(); // if the timer isn't firing we need to trigger it to update
}
function setLive(value) {
liveMode=value;
liveMode = value;
redrawScreen();
}
@ -452,13 +456,17 @@ function setLive(value) {
//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
// The section below are to reload this program with new parameters
function clicknav(minSecs,maxSecs,arch,live) {// we use the current time if we can
var now = new Date() / 1000;
function clicknav(minSecs,maxSecs,live) {// we use the current time if we can
var now = Math.floor( date.getTime() / 1000 );
var tz_difference = ( -1 * date.getTimezoneOffset() * 60 ) - server_utc_offset;
now -= tz_difference;
var minStr = "";
var maxStr = "";
var currentStr = "";
if ( minSecs > 0 ) {
if(maxSecs > now)
if ( maxSecs > now )
maxSecs = parseInt(now);
maxStr="&maxTime=" + secs2inputstr(maxSecs);
$('maxTime').value = secs2inputstr(maxSecs);
@ -492,44 +500,47 @@ function clicknav(minSecs,maxSecs,arch,live) {// we use the current time if we c
var uri = "?view=" + currentView + fitStr + groupStr + minStr + maxStr + currentStr + intervalStr + liveStr + zoomStr + "&scale=" + $j("#scaleslider")[0].value + "&speed=" + speeds[$j("#speedslider")[0].value];
window.location = uri;
} // end function clickNav
} // end function clicknav
function click_lastHour() {
var now = new Date() / 1000;
clicknav(now - 3600 + 1, now,1,0);
var now = Math.floor( date.getTime() / 1000 );
now -= -1 * date.getTimezoneOffset() * 60;
now += server_utc_offset;
clicknav(now - 3599, now, 0);
}
function click_lastEight() {
var now = new Date() / 1000;
clicknav(now - 3600*8 + 1, now,1,0);
var now = Math.floor( date.getTime() / 1000 );
now -= -1 * date.getTimezoneOffset() * 60 - server_utc_offset;
clicknav(now - 3600*8 + 1, now, 0);
}
function click_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);
clicknav(minTimeSecs,maxTimeSecs,0);
}
function click_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);
clicknav(minTimeSecs,maxTimeSecs,0);
}
function click_panleft() {
minTimeSecs = parseInt(minTimeSecs - rangeTimeSecs/2);
maxTimeSecs = minTimeSecs + rangeTimeSecs - 1;
clicknav(minTimeSecs,maxTimeSecs,1,0);
clicknav(minTimeSecs,maxTimeSecs,0);
}
function click_panright() {
minTimeSecs = parseInt(minTimeSecs + rangeTimeSecs/2);
maxTimeSecs = minTimeSecs + rangeTimeSecs - 1;
clicknav(minTimeSecs,maxTimeSecs,1,0);
clicknav(minTimeSecs,maxTimeSecs,0);
}
function click_all_events() {
clicknav(0,0,1,0);
clicknav(0,0,0);
}
function allnon() {
clicknav(0,0,0,0);
clicknav(0,0,0);
}
/// >>>>>>>>>>>>>>>>> handles packing different size/aspect monitors on screen <<<<<<<<<<<<<<<<<<<<<<<<
@ -701,7 +712,6 @@ function changeDateTime(e) {
zoomStr += "&z" + monitorPtr[i].toString() + "=" + monitorZoomScale[monitorPtr[i]].toFixed(2);
var uri = "?view=" + currentView + fitStr + groupStr + minStr + maxStr + liveStr + zoomStr + "&scale=" + $j("#scaleslider")[0].value + "&speed=" + speeds[$j("#speedslider")[0].value];
alert(uri);
window.location = uri;
}

View File

@ -1,4 +1,10 @@
var server_utc_offset = <?php
$TimeZone = new DateTimeZone( ini_get('date.timezone') );
$now = new DateTime('now', $TimeZone);
$offset = $TimeZone->getOffset($now);
echo $offset . '; // ' . floor($offset / 3600) . ' hours ';
?>
var currentScale=<?php echo $defaultScale?>;
var liveMode=<?php echo $initialModeIsLive?>;
var fitMode=<?php echo $fitMode?>;

View File

@ -2,6 +2,7 @@ var filterQuery = '<?php echo validJsStr($filterQuery) ?>';
<?php
$jsMonitors = array();
$fields = array('Name', 'LabelFormat', 'SaveJPEGs', 'VideoWriter');
foreach ( $monitors as $monitor ) {
if ( !empty($monitorIds[$monitor['Id']]) ) {

View File

@ -75,12 +75,16 @@ Warning("Path to snapshot: $path");
$Event = new Event( $_REQUEST['eid'] );
$Frame = Frame::find_one( array( 'EventId' => $_REQUEST['eid'], 'FrameId' => $_REQUEST['fid'] ) );
if ( ! $Frame ) {
$previousBulkFrame = dbFetchOne( "SELECT * FROM Frames WHERE EventId=? AND FrameId < ? AND Type='BULK'", NULL, array($_REQUEST['eid'], $_REQUEST['fid'] ) );
$nextBulkFrame = dbFetchOne( "SELECT * FROM Frames WHERE EventId=? AND FrameId > ? AND Type='BULK'", NULL, array($_REQUEST['eid'], $_REQUEST['fid'] ) );
$previousBulkFrame = dbFetchOne( "SELECT * FROM Frames WHERE EventId=? AND FrameId < ? AND Type='BULK' ORDER BY FrameID DESC LIMIT 1", NULL, array($_REQUEST['eid'], $_REQUEST['fid'] ) );
$nextBulkFrame = dbFetchOne( "SELECT * FROM Frames WHERE EventId=? AND FrameId > ? AND Type='BULK' ORDER BY FrameID ASC LIMIT 1", NULL, array($_REQUEST['eid'], $_REQUEST['fid'] ) );
if ( $previousBulkFrame and $nextBulkFrame ) {
$Frame = new Frame( $previousBulkFrame );
$Frame->Id( $_REQUEST['fid'] );
$Frame->Delta( $previousBulkFrame['Delta'] + ( ( $nextBulkFrame['Delta'] - $previousBulkFrame['Delta'] ) * ( $previousBulkFrame['Id']/$nextBulkFrame['Id'] ) ) );
$Frame->FrameId( $_REQUEST['fid'] );
$percentage = floor( ( $Frame->FrameId() - $previousBulkFrame['FrameId'] ) / ( $nextBulkFrame['FrameId'] / $previousBulkFrame['FrameId'] ) )/100;
$Frame->Delta( $previousBulkFrame['Delta'] + floor( 100* ( $nextBulkFrame['Delta'] - $previousBulkFrame['Delta'] ) * $percentage )/100 );
Logger::Debug("Got virtual frame from Bulk Frames previous delta: " . $previousBulkFrame['Delta'] . " + nextdelta:" . $nextBulkFrame['Delta'] . ' - ' . $previousBulkFrame['Delta'] . ' * ' . $percentage );
} else {
Fatal("No Frame found for event(".$_REQUEST['eid'].") and frame id(".$_REQUEST['fid'].")");
}