diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index 21a4d4cc1..e9fcfe85e 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -205,6 +205,7 @@ CREATE TABLE `Events` ( `Messaged` tinyint(3) unsigned NOT NULL default '0', `Executed` tinyint(3) unsigned NOT NULL default '0', `Notes` text, + `Orientation` enum('0','90','180','270','hori','vert') NOT NULL default '0', PRIMARY KEY (`Id`,`MonitorId`), KEY `MonitorId` (`MonitorId`), KEY `StartTime` (`StartTime`), @@ -396,6 +397,7 @@ CREATE TABLE `Monitors` ( `WebColour` varchar(32) NOT NULL default 'red', `Exif` tinyint(1) unsigned NOT NULL default '0', `Sequence` smallint(5) unsigned default NULL, + `Orientation` enum('0','90','180','270','hori','vert') NOT NULL default '0', PRIMARY KEY (`Id`) ) ENGINE=@ZM_MYSQL_ENGINE@; diff --git a/db/zm_update-1.30.8.sql b/db/zm_update-1.30.8.sql new file mode 100644 index 000000000..5e5dd4ccd --- /dev/null +++ b/db/zm_update-1.30.8.sql @@ -0,0 +1,17 @@ +-- +-- This updates a 1.30.7 database to 1.30.8 +-- + +SET @s = (SELECT IF( + (SELECT COUNT(*) + FROM INFORMATION_SCHEMA.COLUMNS + WHERE table_name = 'Events' + AND table_schema = DATABASE() + AND column_name = 'Orientation' + ) > 0, +"SELECT 'Column Orientation exists in Events'", +"ALTER TABLE `Events` ADD `Orientation` enum('0','90','180','270','hori','vert') NOT NULL default '0' AFTER Notes", +)); + +PREPARE stmt FROM @s; +EXECUTE stmt; diff --git a/src/zm_event.cpp b/src/zm_event.cpp index 7d47d18c7..b6cfc88a5 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -84,7 +84,7 @@ Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string static char sql[ZM_SQL_MED_BUFSIZ]; struct tm *stime = localtime( &start_time.tv_sec ); - snprintf( sql, sizeof(sql), "insert into Events ( MonitorId, StorageId, Name, StartTime, Width, Height, Cause, Notes, Videoed ) values ( %d, %d, 'New Event', from_unixtime( %ld ), %d, %d, '%s', '%s', %d )", monitor->Id(), storage->Id(), start_time.tv_sec, monitor->Width(), monitor->Height(), cause.c_str(), notes.c_str(), videoEvent ); + snprintf( sql, sizeof(sql), "insert into Events ( MonitorId, StorageId, Name, StartTime, Width, Height, Cause, Notes, Orientation, Videoed ) values ( %d, %d, 'New Event', from_unixtime( %ld ), %d, %d, '%s', '%s', %d, %d )", monitor->Id(), storage->Id(), start_time.tv_sec, monitor->Width(), monitor->Height(), cause.c_str(), notes.c_str(), monitor->getOrientation(), videoEvent ); if ( mysql_query( &dbconn, sql ) ) { Error( "Can't insert event: %s. sql was (%s)", mysql_error( &dbconn ), sql ); exit( mysql_errno( &dbconn ) ); @@ -1243,7 +1243,14 @@ bool EventStream::sendFrame( int delta_us ) { static struct stat filestat; FILE *fdj = NULL; + if ( monitor->GetOptSaveJPEGs() & 1) { snprintf( filepath, sizeof(filepath), Event::capture_file_format, event_data->path, curr_frame_id ); + } else if ( monitor->GetOptSaveJPEGs() & 2 ) { + snprintf( filepath, sizeof(filepath), Event::analyse_file_format, event_data->path, curr_frame_id ); + } else { + Fatal("JPEGS not saved.zms is not capable of streaming jpegs from mp4 yet"); + return false; + } #if HAVE_LIBAVCODEC if ( type == STREAM_MPEG ) { diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 742dcf1cd..a13b96a68 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -4178,4 +4178,4 @@ int Monitor::PreCapture() { int Monitor::PostCapture() { return( camera->PostCapture() ); } -Monitor::Orientation Monitor::getOrientation()const { return orientation; } +Monitor::Orientation Monitor::getOrientation() const { return orientation; } diff --git a/src/zm_storage.cpp b/src/zm_storage.cpp index 3fca93479..8856208e3 100644 --- a/src/zm_storage.cpp +++ b/src/zm_storage.cpp @@ -76,7 +76,6 @@ Storage::Storage( unsigned int p_id ) { Debug(1,"No id passed to Storage constructor. Using default path %s instead", path ); strcpy(name, "Default"); } - } Storage::~Storage() { diff --git a/version b/version index 13bc3394f..1377f8848 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.30.7 +1.30.8 diff --git a/web/ajax/event.php b/web/ajax/event.php index a78ccd1a9..5291f0f7a 100644 --- a/web/ajax/event.php +++ b/web/ajax/event.php @@ -6,7 +6,7 @@ if ( empty($_REQUEST['id']) && empty($_REQUEST['eids']) ) { if ( canView( 'Events' ) ) { switch ( $_REQUEST['action'] ) { - case "video" : { + case 'video' : { if ( empty($_REQUEST['videoFormat']) ) { ajaxError( "Video Generation Failure, no format given" ); } elseif ( empty($_REQUEST['rate']) ) { @@ -77,11 +77,9 @@ if ( canView( 'Events' ) ) { } } -if ( canEdit( 'Events' ) ) -{ - switch ( $_REQUEST['action'] ) - { - case "rename" : +if ( canEdit( 'Events' ) ) { + switch ( $_REQUEST['action'] ) { + case 'rename' : { if ( !empty($_REQUEST['eventName']) ) dbQuery( 'UPDATE Events SET Name = ? WHERE Id = ?', array( $_REQUEST['eventName'], $_REQUEST['id'] ) ); @@ -90,24 +88,29 @@ if ( canEdit( 'Events' ) ) ajaxResponse( array( 'refreshEvent'=>true, 'refreshParent'=>true ) ); break; } - case "eventdetail" : + case 'eventdetail' : { dbQuery( 'UPDATE Events SET Cause = ?, Notes = ? WHERE Id = ?', array( $_REQUEST['newEvent']['Cause'], $_REQUEST['newEvent']['Notes'], $_REQUEST['id'] ) ); ajaxResponse( array( 'refreshEvent'=>true, 'refreshParent'=>true ) ); break; } - case "archive" : - case "unarchive" : + case 'archive' : + case 'unarchive' : { $archiveVal = ($_REQUEST['action'] == "archive")?1:0; dbQuery( 'UPDATE Events SET Archived = ? WHERE Id = ?', array( $archiveVal, $_REQUEST['id']) ); ajaxResponse( array( 'refreshEvent'=>true, 'refreshParent'=>false ) ); break; } - case "delete" : + case 'delete' : { - deleteEvent( $_REQUEST['id'] ); - ajaxResponse( array( 'refreshEvent'=>false, 'refreshParent'=>true ) ); + $Event = new Event( $_REQUEST['id'] ); + if ( ! $Event->Id() ) { + ajaxResponse( array( 'refreshEvent'=>false, 'refreshParent'=>true, 'message'=> 'Event not found.' ) ); + } else { + $Event->delete(); + ajaxResponse( array( 'refreshEvent'=>false, 'refreshParent'=>true ) ); + } break; } } diff --git a/web/includes/Event.php b/web/includes/Event.php index 430c64202..5199338df 100644 --- a/web/includes/Event.php +++ b/web/includes/Event.php @@ -14,6 +14,10 @@ class Event { } elseif ( is_array( $IdOrRow ) ) { $row = $IdOrRow; } else { + $backTrace = debug_backtrace(); + $file = $backTrace[1]['file']; + $line = $backTrace[1]['line']; + Error("Unknown argument passed to Event Constructor from $file:$line)"); Error("Unknown argument passed to Event Constructor ($IdOrRow)"); return; } @@ -30,6 +34,9 @@ class Event { public function Storage() { return new Storage( isset($this->{'StorageId'}) ? $this->{'StorageId'} : NULL ); } + public function Monitor() { + return new Monitor( isset($this->{'MonitorId'}) ? $this->{'MonitorId'} : NULL ); + } public function __call( $fn, array $args){ if ( array_key_exists( $fn, $this ) ) { return $this->{$fn}; diff --git a/web/includes/actions.php b/web/includes/actions.php index 8cf17ff6e..18c4fe128 100644 --- a/web/includes/actions.php +++ b/web/includes/actions.php @@ -289,14 +289,15 @@ if ( !empty($action) ) { if ( !empty($_REQUEST['mid']) && canEdit( 'Monitors', $_REQUEST['mid'] ) ) { $mid = validInt($_REQUEST['mid']); if ( $action == 'function' ) { - $monitor = dbFetchOne( "SELECT * FROM Monitors WHERE Id=?", NULL, array($mid) ); + $monitor = dbFetchOne( 'SELECT * FROM Monitors WHERE Id=?', NULL, array($mid) ); $newFunction = validStr($_REQUEST['newFunction']); - $newEnabled = isset( $_REQUEST['newEnabled'] ) and $_REQUEST['newEnabled'] != '1' ? '0' : '1'; + # Because we use a checkbox, it won't get passed in the request. So not being in _REQUEST means 0 + $newEnabled = ( !isset( $_REQUEST['newEnabled'] ) or $_REQUEST['newEnabled'] != '1' ) ? '0' : '1'; $oldFunction = $monitor['Function']; $oldEnabled = $monitor['Enabled']; if ( $newFunction != $oldFunction || $newEnabled != $oldEnabled ) { - dbQuery( "update Monitors set Function=?, Enabled=? where Id=?", array( $newFunction, $newEnabled, $mid ) ); + dbQuery( 'UPDATE Monitors SET Function=?, Enabled=? WHERE Id=?', array( $newFunction, $newEnabled, $mid ) ); $monitor['Function'] = $newFunction; $monitor['Enabled'] = $newEnabled; diff --git a/web/includes/functions.php b/web/includes/functions.php index f912e6eec..3b6f2b542 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -468,10 +468,11 @@ function getEventDefaultVideoPath( $event ) { } function deletePath( $path ) { -Error("deletePath $path"); if ( is_dir( $path ) ) { +Debug("deletePath rm -rf $path"); system( escapeshellcmd( "rm -rf ".$path ) ); } else { +Debug("deletePath unlink $path"); unlink( $path ); } } @@ -486,6 +487,8 @@ function deleteEvent( $event ) { if ( gettype($event) != 'array' ) { # $event could be an eid, so turn it into an event hash $event = new Event( $event ); + } else { +Debug("Event type: " . gettype($event)); } global $user; diff --git a/web/skins/classic/css/classic/views/montage.css b/web/skins/classic/css/classic/views/montage.css index f37156633..e923b3d69 100644 --- a/web/skins/classic/css/classic/views/montage.css +++ b/web/skins/classic/css/classic/views/montage.css @@ -42,4 +42,8 @@ #monitors .monitorState { margin: 2px auto; text-align: center; + border: 0; +} +#monitors .alert .monitorState { + border: 0; } diff --git a/web/skins/classic/css/dark/views/montage.css b/web/skins/classic/css/dark/views/montage.css index 9eba3c569..b8ed08697 100644 --- a/web/skins/classic/css/dark/views/montage.css +++ b/web/skins/classic/css/dark/views/montage.css @@ -42,4 +42,9 @@ #monitors .monitorState { margin: 2px auto; text-align: center; + border: 0; } +#monitors .alert .monitorState { + border: 0; +} + diff --git a/web/skins/classic/css/flat/views/montage.css b/web/skins/classic/css/flat/views/montage.css index e198e5a0b..c1b8b86f0 100644 --- a/web/skins/classic/css/flat/views/montage.css +++ b/web/skins/classic/css/flat/views/montage.css @@ -48,4 +48,8 @@ #monitors .monitorState { margin: 2px auto; text-align: center; + border: 0; +} +#monitors .alert .monitorState { + border: 0; } diff --git a/web/skins/classic/includes/functions.php b/web/skins/classic/includes/functions.php index 42ee5ec52..849d35db8 100644 --- a/web/skins/classic/includes/functions.php +++ b/web/skins/classic/includes/functions.php @@ -220,6 +220,7 @@ function getNavBarHTML() { ?>
  • +
  • diff --git a/web/skins/classic/js/skin.js b/web/skins/classic/js/skin.js index a4776471b..38c05e1e9 100644 --- a/web/skins/classic/js/skin.js +++ b/web/skins/classic/js/skin.js @@ -102,7 +102,12 @@ function getPopupSize( tag, width, height ) function zmWindow() { var zmWin = window.open( 'http://www.zoneminder.com', 'ZoneMinder' ); - zmWin.focus(); + if ( ! zmWin ) { + // if popup blocking is enabled, the popup won't be defined. + console.log("Please disable popup blocking."); + } else { + zmWin.focus(); + } } function createPopup( url, name, tag, width, height ) @@ -114,7 +119,12 @@ function createPopup( url, name, tag, width, height ) if ( popupSize.height > 0 ) popupDimensions += ",height="+popupSize.height; var popup = window.open( url, name, popupOptions+popupDimensions ); - popup.focus(); + if ( ! popup ) { + // if popup blocking is enabled, the popup won't be defined. + console.log("Please disable popup blocking."); + } else { + popup.focus(); + } } function createEventPopup( eventId, eventFilter, width, height ) @@ -125,7 +135,12 @@ function createEventPopup( eventId, eventFilter, width, height ) var name = 'zmEvent'; var popupSize = getPopupSize( 'event', width, height ); var popup = window.open( url, name, popupOptions+",width="+popupSize.width+",height="+popupSize.height ); - popup.focus(); + if ( ! popup ) { + // if popup blocking is enabled, the popup won't be defined. + console.log("Please disable popup blocking."); + } else { + popup.focus(); + } } function createFramesPopup( eventId, width, height ) @@ -134,7 +149,12 @@ function createFramesPopup( eventId, width, height ) var name = 'zmFrames'; var popupSize = getPopupSize( 'frames', width, height ); var popup = window.open( url, name, popupOptions+",width="+popupSize.width+",height="+popupSize.height ); - popup.focus(); + if ( ! popup ) { + // if popup blocking is enabled, the popup won't be defined. + console.log("Please disable popup blocking."); + } else { + popup.focus(); + } } function createFramePopup( eventId, frameId, width, height ) @@ -143,7 +163,12 @@ function createFramePopup( eventId, frameId, width, height ) var name = 'zmFrame'; var popupSize = getPopupSize( 'frame', width, height ); var popup = window.open( url, name, popupOptions+",width="+popupSize.width+",height="+popupSize.height ); - popup.focus(); + if ( ! popup ) { + // if popup blocking is enabled, the popup won't be defined. + console.log("Please disable popup blocking."); + } else { + popup.focus(); + } } function windowToFront() diff --git a/web/skins/classic/views/event.php b/web/skins/classic/views/event.php index 125127127..8e247af4e 100644 --- a/web/skins/classic/views/event.php +++ b/web/skins/classic/views/event.php @@ -18,36 +18,35 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // -if ( !canView( 'Events' ) ) -{ - $view = "error"; +if ( !canView( 'Events' ) ) { + $view = 'error'; return; } $eid = validInt( $_REQUEST['eid'] ); $fid = !empty($_REQUEST['fid'])?validInt($_REQUEST['fid']):1; -$sql = 'SELECT E.*,M.Name AS MonitorName,E.Width,E.Height,M.DefaultRate,M.DefaultScale,M.VideoWriter,M.SaveJPEGs,M.Orientation,M.LabelFormat FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE E.Id = ?'; -$sql_values = array( $eid ); - +$Event = new Event( $eid ); +$Monitor = $Event->Monitor(); if ( $user['MonitorIds'] ) { - $monitor_ids = explode( ',', $user['MonitorIds'] ); - $sql .= ' AND MonitorId IN (' .implode( ',', array_fill(0,count($monitor_ids),'?') ) . ')'; - $sql_values = array_merge( $sql_values, $monitor_ids ); + $monitor_ids = explode( ',', $user['MonitorIds'] ); + if ( count($monitor_ids) and ! in_array( $Event->MonitorId(), $monitors_ids ) ) { + $view = 'error'; + return; + } } -$event = dbFetchOne( $sql, NULL, $sql_values ); if ( isset( $_REQUEST['rate'] ) ) $rate = validInt($_REQUEST['rate']); else - $rate = reScale( RATE_BASE, $event['DefaultRate'], ZM_WEB_DEFAULT_RATE ); + $rate = reScale( RATE_BASE, $Monitor->DefaultRate(), ZM_WEB_DEFAULT_RATE ); if ( isset( $_REQUEST['scale'] ) ) { $scale = validInt($_REQUEST['scale']); -} else if ( isset( $_COOKIE['zmWatchScale'.$event['MonitorId']] ) ) { - $scale = $_COOKIE['zmEventScale'.$event['MonitorId']]; +} else if ( isset( $_COOKIE['zmWatchScale'.$Event->MonitorId()] ) ) { + $scale = $_COOKIE['zmEventScale'.$Event->MonitorId()]; } else { - $scale = reScale( SCALE_BASE, $event['DefaultScale'], ZM_WEB_DEFAULT_SCALE ); + $scale = reScale( SCALE_BASE, $Monitor->DefaultScale(), ZM_WEB_DEFAULT_SCALE ); } $replayModes = array( @@ -73,11 +72,11 @@ else { // videojs zoomrotate only when direct recording $Zoom = 1; $Rotation = 0; -if ( $event['VideoWriter'] == "2" ) { +if ( $Monitor->VideoWriter() == '2' ) { # Passthrough - $Rotation = $event['Orientation']; - if ( in_array($event['Orientation'],array('90','270')) ) - $Zoom = $event['Height']/$event['Width']; + $Rotation = $Event->Orientation(); + if ( in_array($Event->Orientation(),array('90','270')) ) + $Zoom = $Event->Height()/$Event->Width(); } parseSort(); @@ -85,7 +84,7 @@ parseFilter( $_REQUEST['filter'] ); $filterQuery = $_REQUEST['filter']['query']; $panelSections = 40; -$panelSectionWidth = (int)ceil(reScale($event['Width'],$scale)/$panelSections); +$panelSectionWidth = (int)ceil(reScale($Event->Width(),$scale)/$panelSections); $panelWidth = ($panelSections*$panelSectionWidth-1); $connkey = generateConnKey(); @@ -97,110 +96,102 @@ xhtmlHeaders(__FILE__, translate('Event') );
    +Id() ) { + echo 'Event was not found.'; +} else { +?>
    - - - - - - + + + + + +
    s">/">//Id() ?>Cause()) ?>StartTime() ) ) ?>Length() ?>s">Frames() ?>/AlarmFrames() ?>">TotScore() ?>/AvgScore() ?>/MaxScore() ?>
    DefaultVideo() ) { ?>
    -
    - - - - - - + + + + + + -
    +
    DefaultVideo() ) { ?>class="hidden" > Width(), $scale ), reScale( $Event->Height(), $scale ), ZM_MPEG_LIVE_FORMAT ); +} else { $streamSrc = getStreamSrc( array( "source=event", "mode=jpeg", "event=".$eid, "frame=".$fid, "scale=".$scale, "rate=".$rate, "maxfps=".ZM_WEB_VIDEO_MAXFPS, "replay=".$replayMode) ); - if ( canStreamNative() ) - { - outputImageStream( "evtStream", $streamSrc, reScale( $event['Width'], $scale ), reScale( $event['Height'], $scale ), validHtmlStr($event['Name']) ); + if ( canStreamNative() ) { + outputImageStream( "evtStream", $streamSrc, reScale( $Event->Width(), $scale ), reScale( $Event->Height(), $scale ), validHtmlStr($Event->Name()) ); + } else { + outputHelperStream( "evtStream", $streamSrc, reScale( $Event->Width(), $scale ), reScale( $Event->Height(), $scale ) ); } - else - { - outputHelperStream( "evtStream", $streamSrc, reScale( $event['Width'], $scale ), reScale( $event['Height'], $scale ) ); - } -} +} // end if stream method ?>

    - - - - - - - - - + + + + + + + + +

    :   @@ -209,23 +200,14 @@ else : x
    -
    -SaveJPEGs() & 3) { // frames or analysis ?> -
    +
    diff --git a/web/skins/classic/views/frame.php b/web/skins/classic/views/frame.php index 1c5cce354..d4a8dc38d 100644 --- a/web/skins/classic/views/frame.php +++ b/web/skins/classic/views/frame.php @@ -18,9 +18,8 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // -if ( !canView( 'Events' ) ) -{ - $view = "error"; +if ( !canView( 'Events' ) ) { + $view = 'error'; return; } @@ -56,7 +55,13 @@ if ( isset( $_REQUEST['scale'] ) ) else $scale = max( reScale( SCALE_BASE, $event['DefaultScale'], ZM_WEB_DEFAULT_SCALE ), SCALE_BASE ); -$imageData = getImageSrc( $event, $frame, $scale, (isset($_REQUEST['show']) && $_REQUEST['show']=="capt") ); +$show = 'capt'; +if ( isset($_REQUEST['show']) ) { + $show = $_REQUEST['show']; +#} else if ( $imageData['hasAnalImage'] ) { + #$show = 'anal'; +} +$imageData = getImageSrc( $event, $frame, $scale, ($show=="capt") ); $imagePath = $imageData['thumbPath']; $eventPath = $imageData['eventPath']; @@ -79,23 +84,16 @@ xhtmlHeaders(__FILE__, translate('Frame')." - ".$event['Id']." - ".$Frame->Frame

    - -" class="" width="" height="" alt="EventId()."-".$Frame->FrameId() ?>"> - - - -<?php echo $Frame->EventId().FrameId() ?>" class=""/> - - -

    + + <?php echo $Frame->EventId().FrameId() ?>" class=""/> +

    FrameId() > 1 ) { ?> - - + + FrameId() < $maxFid ) { ?> - - + +

    diff --git a/web/skins/classic/views/function.php b/web/skins/classic/views/function.php index a52020185..3cc00b3fc 100644 --- a/web/skins/classic/views/function.php +++ b/web/skins/classic/views/function.php @@ -18,9 +18,8 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // -if ( !canEdit( 'Monitors' ) ) -{ - $view = "error"; +if ( !canEdit( 'Monitors' ) ) { + $view = 'error'; return; } @@ -43,8 +42,7 @@ xhtmlHeaders(__FILE__, translate('Function')." - ".validHtmlStr($monitor['Name']

    step=0.10 width=20% onchange='setScale(this.value)' oninput='showScale(this.value)'/> x

    -
    +
    value= step=1 wdth=20% onchange='setSpeed(this.value)' oninput='showSpeed(this.value)'/> fps
    - - - - - - - - - + + + + + + + + +
    -
    - - - - +
    + + + +
    \n"; -foreach ($monitors as $m) -{ - { - echo "No Canvas Support!!\n"; - } +foreach ($monitors as $m) { + echo "No Canvas Support!!\n"; } echo "
    \n"; echo "

    evaluating fps

    \n"; @@ -331,8 +328,7 @@ $maxTimeSecs = strtotime("1950-01-01 01:01:01"); $index=0; $anyAlarms=false; -foreach( dbFetchAll( $eventsSql ) as $event ) -{ +foreach( dbFetchAll( $eventsSql ) as $event ) { if( $minTimeSecs > $event['StartTimeSecs']) $minTimeSecs=$event['StartTimeSecs']; if( $maxTimeSecs < $event['CalcEndTimeSecs']) $maxTimeSecs=$event['CalcEndTimeSecs']; echo "eMonId[$index]=" . $event['MonitorId'] . "; eId[$index]=" . $event['Id'] . "; "; @@ -349,30 +345,25 @@ foreach( dbFetchAll( $eventsSql ) as $event ) echo "\n"; } -if($index == 0) // if there is no data set the min/max to the passed in values -{ - 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=strtotime('2020-06-02 02:02:02'); - } +// 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=strtotime('2020-06-02 02:02:02'); + } } // 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(!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 @@ -389,41 +380,37 @@ $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"; +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"; @@ -446,17 +433,15 @@ 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++; +foreach ($monitors as $m) { + $avgArea = $avgArea + floatval($m['Width'] * $m['Height']); + $numMonitors++; } if($numMonitors>0) $avgArea= $avgArea / $numMonitors; $numMonitors=0; -foreach ($monitors as $m) -{ +foreach ($monitors as $m) { echo " monitorLoading[" . $m['Id'] . "]=false; "; echo " monitorImageObject[" . $m['Id'] . "]=null; "; echo " monitorLoadingStageURL[" . $m['Id'] . "] = ''; "; @@ -543,34 +528,28 @@ function evaluateLoadTimes() $('fps').innerHTML="Display refresh rate is " + (1000 / currentDisplayInterval).toFixed(1) + " per second, avgFrac=" + avgFrac.toFixed(3) + "."; } -function SetImageSource(monId,val) -{ - if(liveMode==1) - { // This uses the standard php routine to set up the url and authentication, but because it is called repeatedly the built in random number is not usable, so one is appended below for two total (yuck) - var effectiveScale = (100.0 * monitorCanvasObj[monId].width) / monitorWidth[monId]; - var $x = "" + "&monitor=" + monId.toString() + "&scale=" + effectiveScale + Math.random().toString() ; - return $x; - } - else - { - var zeropad = ; - for(var i=0, var eIdlength = eId.length; i= eStartSecs[i] && val <= eEndSecs[i]) - { - var frame=parseInt((val - eStartSecs[i])/(eEndSecs[i]-eStartSecs[i])*eventFrames[i])+1; - img = "index.php?view=image&eid=" + eId[i] + '&fid='+frame + "&width=" + monitorCanvasObj[monId].width + "&height=" + monitorCanvasObj[monId].height; - return img; - } - } - return "no data"; - } +function SetImageSource(monId,val) { + if(liveMode==1) { + // This uses the standard php routine to set up the url and authentication, but because it is called repeatedly the built in random number is not usable, so one is appended below for two total (yuck) + var effectiveScale = (100.0 * monitorCanvasObj[monId].width) / monitorWidth[monId]; + var $x = "" + "&monitor=" + monId.toString() + "&scale=" + effectiveScale + Math.random().toString() ; + return $x; + } else { + var zeropad = ; + 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; + img = "index.php?view=image&eid=" + eId[i] + '&fid='+frame + "&width=" + monitorCanvasObj[monId].width + "&height=" + monitorCanvasObj[monId].height; + return img; + } + } // end for + return "no data"; + } } -function imagedone(obj, monId, success) -{ - if(success) - { +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"; @@ -583,10 +562,10 @@ function imagedone(obj, monId, success) evaluateLoadTimes(); } monitorLoading[monId]=false; - if(!success) // if we had a failrue queue up the no-data image + 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 - { + } else { if(monitorLoadingStageURL[monId]=="") return; loadImage2Monitor(monId,monitorLoadingStageURL[monId]); monitorLoadingStageURL[monId]=""; @@ -594,24 +573,19 @@ function imagedone(obj, monId, success) 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 - { +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 { var skipthis=0; if( typeof monitorImageObject[monId] !== "undefined" && monitorImageObject[monId] != null && monitorImageObject[monId].src == url ) return; // do nothing if it's the same - if( monitorImageObject[monId] == null ) - { + if( monitorImageObject[monId] == null ) { monitorImageObject[monId]=new Image(); monitorImageObject[monId].onload = function() {imagedone(this, monId,true )}; monitorImageObject[monId].onerror = function() {imagedone(this, monId,false)}; } - if(url=='no data') - { + 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; @@ -620,43 +594,38 @@ function loadImage2Monitor(monId,url) 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 - { + } 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 - } +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; + 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) -{ +function drawSliderOnGraph(val) { var sliderWidth=10; var sliderLineWidth=1; var sliderHeight=cHeight; - if(liveMode==1) - { + if(liveMode==1) { val=Math.floor( Date.now() / 1000); } // Set some sizes @@ -665,8 +634,8 @@ function drawSliderOnGraph(val) 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 - { + 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; @@ -896,18 +865,17 @@ HTMLCanvasElement.prototype.relMouseCoords = relMouseCoords; // These are the functions for mouse movement in the timeline. Note that touch is treated as a mouse move with mouse down var mouseisdown=false; -function mdown(event) {mouseisdown=true; mmove(event)} +function mdown(event) {mouseisdown=true; mmove(event);} function mup(event) {mouseisdown=false;} function mout(event) {mouseisdown=false;} // if we go outside treat it as release function tmove(event) {mouseisdown=true; mmove(event);} -function mmove(event) -{ - if(mouseisdown) // only do anything if the mouse is depressed while on the sheet - { - var sec = minTimeSecs + rangeTimeSecs / event.target.width * event.target.relMouseCoords(event).x; - outputUpdate(sec); - } +function mmove(event) { + if(mouseisdown) { + // only do anything if the mouse is depressed while on the sheet + var sec = minTimeSecs + rangeTimeSecs / event.target.width * event.target.relMouseCoords(event).x; + outputUpdate(sec); + } } function secs2dbstr (s) diff --git a/web/views/image.php b/web/views/image.php index 5278c44a5..8d2a68f14 100644 --- a/web/views/image.php +++ b/web/views/image.php @@ -74,8 +74,9 @@ if ( empty($_REQUEST['path']) ) { } if ( ! file_exists( $path ) ) { +Debug( "$path does not exist"); # Generate the frame JPG - if ( $Event->DefaultVideo() ) { + if ( $show == 'capt' and $Event->DefaultVideo() ) { $command ='ffmpeg -i '.$Event->Path().'/'.$Event->DefaultVideo().' -vf "select=gte(n\\,'.$Frame->FrameId().'),setpts=PTS-STARTPTS" '.$path; #$command ='ffmpeg -v 0 -i '.$Storage->Path().'/'.$Event->Path().'/'.$Event->DefaultVideo().' -vf "select=gte(n\\,'.$Frame->FrameId().'),setpts=PTS-STARTPTS" '.$path; Debug( "Running $command" );