- | - | - | s | -">/ | -">// | +Id() ?> | +Cause()) ?> | +StartTime() ) ) ?> | +Length() ?>s | +">Frames() ?>/AlarmFrames() ?> | +">TotScore() ?>/AvgScore() ?>/MaxScore() ?> |
- - - - - - - - - + + + + + + + + +
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') );- | - | - | s | -">/ | -">// | +Id() ?> | +Cause()) ?> | +StartTime() ) ) ?> | +Length() ?>s | +">Frames() ?>/AlarmFrames() ?> | +">TotScore() ?>/AvgScore() ?>/MaxScore() ?> |
- - - - - - - - - + + + + + + + + +