diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index bf598b646..fbc7cad3c 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -283,6 +283,7 @@ CREATE TABLE `Filters` ( `Id` int(10) unsigned NOT NULL auto_increment, `Name` varchar(64) NOT NULL default '', `UserId` int(10) unsigned, + `ExecuteInterval` int(10) unsigned NOT NULL default '60', `Query_json` text NOT NULL, `AutoArchive` tinyint(3) unsigned NOT NULL default '0', `AutoUnarchive` tinyint(3) unsigned NOT NULL default '0', diff --git a/db/zm_update-1.35.25.sql b/db/zm_update-1.35.25.sql index 387ef09b0..16df91d74 100644 --- a/db/zm_update-1.35.25.sql +++ b/db/zm_update-1.35.25.sql @@ -56,7 +56,7 @@ EXECUTE stmt; SET @s = (SELECT IF( (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() AND table_name = 'Monitor_Status' - AND column_name = 'DayEvents' + AND column_name = 'DayEventDiskSpace' ) > 0, "ALTER TABLE `Monitor_Status` DROP `DayEventDiskSpace`", "SELECT 'Column DayEventDiskSpace already removed from Monitor_Status'" diff --git a/db/zm_update-1.37.6.sql b/db/zm_update-1.37.6.sql new file mode 100644 index 000000000..7c79886ad --- /dev/null +++ b/db/zm_update-1.37.6.sql @@ -0,0 +1,18 @@ +-- +-- Update Filters table to have a ExecuteInterval Column +-- + +SELECT 'Checking for ExecuteInterval in Filters'; +SET @s = (SELECT IF( + (SELECT COUNT(*) + FROM INFORMATION_SCHEMA.COLUMNS + WHERE table_name = 'Filters' + AND table_schema = DATABASE() + AND column_name = 'ExecuteInterval' + ) > 0, +"SELECT 'Column ExecuteInterval already exists in Filters'", +"ALTER TABLE Filters ADD COLUMN `ExecuteInterval` int(10) unsigned NOT NULL default '60' AFTER `UserId`" +)); + +PREPARE stmt FROM @s; +EXECUTE stmt; diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index 8d49c0d7f..f5aeebf2d 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -36,7 +36,7 @@ %global _hardened_build 1 Name: zoneminder -Version: 1.37.5 +Version: 1.37.6 Release: 1%{?dist} Summary: A camera monitoring and analysis tool Group: System Environment/Daemons diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm b/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm index 0db46ff0d..7b3efad46 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm @@ -56,6 +56,7 @@ $primary_key = 'Id'; %fields = map { $_ => $_ } qw( Id Name +ExecuteInterval Query_json AutoArchive AutoUnarchive @@ -106,7 +107,6 @@ sub Execute { $sql =~ s/zmSystemLoad/$load/g; } - $sql .= ' FOR UPDATE' if $$self{LockRows}; Debug("Filter::Execute SQL ($sql)"); my $sth = $ZoneMinder::Database::dbh->prepare_cached($sql) @@ -371,10 +371,7 @@ sub Sql { if ( @auto_terms ) { $sql .= ' AND ( '.join(' or ', @auto_terms).' )'; } - if ( !$filter_expr->{sort_field} ) { - $filter_expr->{sort_field} = 'StartDateTime'; - $filter_expr->{sort_asc} = 0; - } + my $sort_column = ''; if ( $filter_expr->{sort_field} eq 'Id' ) { $sort_column = 'E.Id'; @@ -406,14 +403,23 @@ sub Sql { $sort_column = 'E.MaxScore'; } elsif ( $filter_expr->{sort_field} eq 'DiskSpace' ) { $sort_column = 'E.DiskSpace'; - } else { - $sort_column = 'E.StartDateTime'; + } elsif ( $filter_expr->{sort_field} ne '' ) { + $sort_column = 'E.'.$filter_expr->{sort_field}; } - my $sort_order = $filter_expr->{sort_asc} ? 'ASC' : 'DESC'; - $sql .= ' ORDER BY '.$sort_column.' '.$sort_order; - if ( $filter_expr->{limit} ) { + if ( $sort_column ne '' ) { + $sql .= ' ORDER BY '.$sort_column.' '.($filter_expr->{sort_asc} ? 'ASC' : 'DESC'); + } + if ($filter_expr->{limit}) { $sql .= ' LIMIT 0,'.$filter_expr->{limit}; } + if ($$self{LockRows}) { + $sql .= ' FOR UPDATE OF E' + } else { + $sql .= ' FOR SHARE OF E' + } + if ($filter_expr->{skip_locked}) { + $sql .= ' SKIP LOCKED'; + } $self->{Sql} = $sql; } # end if has Sql return $self->{Sql}; diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in index e7fdcd35f..e0c9bf971 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in @@ -42,6 +42,7 @@ our @ISA = qw(Exporter ZoneMinder::Base); # will save memory. our %EXPORT_TAGS = ( constants => [ qw( + STATE_UNKNOWN STATE_IDLE STATE_PREALARM STATE_ALARM @@ -98,11 +99,12 @@ our $VERSION = $ZoneMinder::Base::VERSION; use ZoneMinder::Config qw(:all); use ZoneMinder::Logger qw(:all); -use constant STATE_IDLE => 0; -use constant STATE_PREALARM => 1; -use constant STATE_ALARM => 2; -use constant STATE_ALERT => 3; -use constant STATE_TAPE => 4; +use constant STATE_UNKNOWN => 0; +use constant STATE_IDLE => 1; +use constant STATE_PREALARM => 2; +use constant STATE_ALARM => 3; +use constant STATE_ALERT => 4; +use constant STATE_TAPE => 5; use constant ACTION_GET => 1; use constant ACTION_SET => 2; diff --git a/scripts/zmfilter.pl.in b/scripts/zmfilter.pl.in index 08ae4abf2..fd927020f 100644 --- a/scripts/zmfilter.pl.in +++ b/scripts/zmfilter.pl.in @@ -138,7 +138,6 @@ $ENV{PATH} = '/bin:/usr/bin:/usr/local/bin'; $ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; -my $delay = $Config{ZM_FILTER_EXECUTE_INTERVAL}; my $event_id = 0; if (!EVENT_PATH) { @@ -174,6 +173,7 @@ my @filters; my $last_action = 0; while (!$zm_terminate) { + my $delay = $Config{ZM_FILTER_EXECUTE_INTERVAL}; my $now = time; if (($now - $last_action) > $Config{ZM_FILTER_RELOAD_DELAY}) { Debug('Reloading filters'); @@ -183,6 +183,15 @@ while (!$zm_terminate) { foreach my $filter (@filters) { last if $zm_terminate; + + my $elapsed = ($now - $$filter{last_ran}); + if ($$filter{last_ran} and ($elapsed < $$filter{ExecuteInterval})) { + my $filter_delay = $$filter{ExecuteInterval} - ($now - $$filter{last_ran}); + $delay = $filter_delay if $filter_delay < $delay; + Debug("Setting delay to $delay because ExecuteInterval=$$filter{ExecuteInterval} and $elapsed have elapsed"); + next; + } + if ($$filter{Concurrent} and !($filter_id or $filter_name)) { my ( $proc ) = $0 =~ /(\S+)/; my ( $id ) = $$filter{Id} =~ /(\d+)/; @@ -191,8 +200,9 @@ while (!$zm_terminate) { system(qq`$proc --filter_id $id &`); } else { checkFilter($filter); + $$filter{last_ran} = $now; } - } + } # end foreach filter last if (!$daemon and ($filter_name or $filter_id)) or $zm_terminate; @@ -362,11 +372,6 @@ sub checkFilter { } # end if AutoCopy if ( $filter->{UpdateDiskSpace} ) { - if ( $$filter{LockRows} ) { - $ZoneMinder::Database::dbh->begin_work(); - $Event->lock_and_load(); - } - my $old_diskspace = $$Event{DiskSpace}; my $new_diskspace = $Event->DiskSpace(undef); diff --git a/scripts/zmtrigger.pl.in b/scripts/zmtrigger.pl.in index 041d1c449..83fcf29f5 100644 --- a/scripts/zmtrigger.pl.in +++ b/scripts/zmtrigger.pl.in @@ -166,13 +166,9 @@ while (!$zm_terminate) { foreach my $connection ( values(%spawned_connections) ) { if ( vec($rout, $connection->fileno(), 1) ) { Debug('Got input from spawned connection ' - .$connection->name() - .' (' - .$connection->fileno() - .')' - ); + .$connection->name().' ('.$connection->fileno().')'); my $messages = $connection->getMessages(); - if ( defined($messages) ) { + if (defined($messages)) { foreach my $message ( @$messages ) { handleMessage($connection, $message); } @@ -199,34 +195,32 @@ while (!$zm_terminate) { # Check polled connections foreach my $connection ( @in_poll_connections ) { my $messages = $connection->getMessages(); - if ( defined($messages) ) { - foreach my $message ( @$messages ) { - handleMessage($connection, $message); - } + if (defined($messages)) { + foreach my $message (@$messages) { handleMessage($connection, $message) }; } } # Check for alarms that might have happened my @out_messages; foreach my $monitor ( values %monitors ) { + if ($$monitor{Function} eq 'None') { + $monitor_reload_time = 0; + next; + } - if ( ! zmMemVerify($monitor) ) { + if (!zmMemVerify($monitor)) { # Our attempt to verify the memory handle failed. We should reload the monitors. # Don't need to zmMemInvalidate because the monitor reload will do it. push @needsReload, $monitor; next; } - my ( $state, $last_event ) = zmMemRead( $monitor, - [ + my ($state, $last_event) = zmMemRead($monitor, [ 'shared_data:state', 'shared_data:last_event' - ] - ); + ]); -#print( "$monitor->{Id}: S:$state, LE:$last_event" ); -#print( "$monitor->{Id}: mS:$monitor->{LastState}, mLE:$monitor->{LastEvent}" ); - if ( $state == STATE_ALARM or $state == STATE_ALERT ) { + if ($state == STATE_ALARM or $state == STATE_ALERT) { # In alarm state if ( !defined($monitor->{LastEvent}) or ($last_event != $monitor->{LastEvent}) diff --git a/src/zm_buffer.cpp b/src/zm_buffer.cpp index 4cb580aa4..c65d8b24a 100644 --- a/src/zm_buffer.cpp +++ b/src/zm_buffer.cpp @@ -65,7 +65,7 @@ unsigned int Buffer::expand(unsigned int count) { int Buffer::read_into(int sd, unsigned int bytes) { // Make sure there is enough space this->expand(bytes); - Debug(3, "Reading %u btes", bytes); + Debug(3, "Reading %u bytes", bytes); int bytes_read = ::read(sd, mTail, bytes); if (bytes_read > 0) { mTail += bytes_read; diff --git a/src/zm_rgb.h b/src/zm_rgb.h index 58ad9bfae..ef1d46ce3 100644 --- a/src/zm_rgb.h +++ b/src/zm_rgb.h @@ -118,41 +118,34 @@ constexpr Rgb kRGBTransparent = 0x01000000; /* Convert RGB colour value into BGR\ARGB\ABGR */ inline Rgb rgb_convert(Rgb p_col, int p_subpixorder) { - Rgb result; + Rgb result = 0; - switch(p_subpixorder) { - + switch (p_subpixorder) { case ZM_SUBPIX_ORDER_BGR: case ZM_SUBPIX_ORDER_BGRA: - { - BLUE_PTR_BGRA(&result) = BLUE_VAL_RGBA(p_col); - GREEN_PTR_BGRA(&result) = GREEN_VAL_RGBA(p_col); - RED_PTR_BGRA(&result) = RED_VAL_RGBA(p_col); - } - break; + BLUE_PTR_BGRA(&result) = BLUE_VAL_RGBA(p_col); + GREEN_PTR_BGRA(&result) = GREEN_VAL_RGBA(p_col); + RED_PTR_BGRA(&result) = RED_VAL_RGBA(p_col); + break; case ZM_SUBPIX_ORDER_ARGB: - { - BLUE_PTR_ARGB(&result) = BLUE_VAL_RGBA(p_col); - GREEN_PTR_ARGB(&result) = GREEN_VAL_RGBA(p_col); - RED_PTR_ARGB(&result) = RED_VAL_RGBA(p_col); - } - break; + BLUE_PTR_ARGB(&result) = BLUE_VAL_RGBA(p_col); + GREEN_PTR_ARGB(&result) = GREEN_VAL_RGBA(p_col); + RED_PTR_ARGB(&result) = RED_VAL_RGBA(p_col); + break; case ZM_SUBPIX_ORDER_ABGR: - { - BLUE_PTR_ABGR(&result) = BLUE_VAL_RGBA(p_col); - GREEN_PTR_ABGR(&result) = GREEN_VAL_RGBA(p_col); - RED_PTR_ABGR(&result) = RED_VAL_RGBA(p_col); - } - break; - /* Grayscale */ + BLUE_PTR_ABGR(&result) = BLUE_VAL_RGBA(p_col); + GREEN_PTR_ABGR(&result) = GREEN_VAL_RGBA(p_col); + RED_PTR_ABGR(&result) = RED_VAL_RGBA(p_col); + break; + /* Grayscale */ case ZM_SUBPIX_ORDER_NONE: - result = p_col & 0xff; - break; + result = p_col & 0xff; + break; default: - return p_col; - break; + result = p_col; + break; } - + return result; } diff --git a/src/zmc.cpp b/src/zmc.cpp index c2f14e254..29e9886fd 100644 --- a/src/zmc.cpp +++ b/src/zmc.cpp @@ -365,6 +365,7 @@ int main(int argc, char *argv[]) { monitor->Id()); zmDbDo(sql); } + monitors.clear(); Image::Deinitialise(); Debug(1, "terminating"); diff --git a/utils/do_debian_package.sh b/utils/do_debian_package.sh index 29ebdc0ef..00dcd44e9 100755 --- a/utils/do_debian_package.sh +++ b/utils/do_debian_package.sh @@ -218,8 +218,8 @@ rm .gitignore cd ../ -if [ ! -e "$DIRECTORY.orig.tar.gz" ]; then - read -p "$DIRECTORY.orig.tar.gz does not exist, create it? [Y/n]" +if [ -e "$DIRECTORY.orig.tar.gz" ]; then + read -p "$DIRECTORY.orig.tar.gz exists, overwrite it? [Y/n]" if [[ "$REPLY" == "" || "$REPLY" == [yY] ]]; then tar zcf $DIRECTORY.orig.tar.gz $DIRECTORY.orig fi; diff --git a/version b/version index e2ba07049..e22b12fd6 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.37.5 +1.37.6 diff --git a/web/ajax/events.php b/web/ajax/events.php index 090fe476e..4db6b99cc 100644 --- a/web/ajax/events.php +++ b/web/ajax/events.php @@ -48,7 +48,7 @@ if (isset($_REQUEST['order'])) { } else if (strtolower($_REQUEST['order']) == 'desc') { $order = 'DESC'; } else { - Warning("Invalid value for order " . $_REQUEST['order']); + Warning('Invalid value for order ' . $_REQUEST['order']); } } @@ -170,18 +170,23 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim // The names of columns shown in the event view that are NOT dB columns in the database $col_alt = array('Monitor', 'Storage'); - if (!in_array($sort, array_merge($columns, $col_alt))) { - ZM\Error('Invalid sort field: ' . $sort); - $sort = 'Id'; + if ( $sort != '' ) { + if (!in_array($sort, array_merge($columns, $col_alt))) { + ZM\Error('Invalid sort field: ' . $sort); + $sort = ''; + } else if ( $sort == 'Monitor' ) { + $sort = 'M.Name'; + } else { + $sort = 'E.'.$sort; + } } $values = array(); $likes = array(); $where = $filter->sql()?' WHERE ('.$filter->sql().')' : ''; - $sort = $sort == 'Monitor' ? 'M.Name' : 'E.'.$sort; $col_str = 'E.*, M.Name AS Monitor'; - $sql = 'SELECT ' .$col_str. ' FROM `Events` AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id'.$where.' ORDER BY '.$sort.' '.$order; + $sql = 'SELECT ' .$col_str. ' FROM `Events` AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id'.$where.($sort?' ORDER BY '.$sort.' '.$order:''); $storage_areas = ZM\Storage::find(); $StorageById = array(); diff --git a/web/ajax/modals/filterdebug.php b/web/ajax/modals/filterdebug.php index 725539a99..f3a961874 100644 --- a/web/ajax/modals/filterdebug.php +++ b/web/ajax/modals/filterdebug.php @@ -9,13 +9,13 @@ '; } else { $filter = new ZM\Filter($_REQUEST['fid']); - if ( ! $filter->Id() ) { + if (!$filter->Id()) { echo '
Filter not found for id '.$_REQUEST['fid'].'
'; } } @@ -25,7 +25,16 @@ // We have to manually insert the csrf key into the form when using a modal generated via ajax call echo getCSRFinputHTML(); ?> -

sql() ?>

+

+FROM Monitors AS M INNER JOIN Events AS E ON (M.Id = E.MonitorId)
WHERE
'; + $sql .= $filter->sql(); + $sql .= $filter->sort_field() ? ' ORDER BY '.$filter->sort_field(). ' ' .($filter->sort_asc() ? 'ASC' : 'DESC') : ''; + $sql .= $filter->limit() ? ' LIMIT '.$filter->limit() : ''; + $sql .= $filter->skip_locked() ? ' SKIP LOCKED' : ''; + + echo $sql; +?>

diff --git a/web/api/app/Controller/MonitorsController.php b/web/api/app/Controller/MonitorsController.php index 07098623e..193e8a61a 100644 --- a/web/api/app/Controller/MonitorsController.php +++ b/web/api/app/Controller/MonitorsController.php @@ -321,12 +321,20 @@ class MonitorsController extends AppController { } $monitor = $this->Monitor->find('first', array( - 'fields' => array('Id', 'Type', 'Device'), + 'fields' => array('Id', 'Type', 'Device', 'Function'), 'conditions' => array('Id' => $id) )); // Clean up the returned array $monitor = Set::extract('/Monitor/.', $monitor); + if ($monitor[0]['Function'] == 'None') { + $this->set(array( + 'status' => false, + 'statustext' => 'Monitor function is set to None', + '_serialize' => array('status','statustext'), + )); + return; + } // Pass -d for local, otherwise -m if ( $monitor[0]['Type'] == 'Local' ) { diff --git a/web/includes/Filter.php b/web/includes/Filter.php index a155d97a8..4fdd8e43f 100644 --- a/web/includes/Filter.php +++ b/web/includes/Filter.php @@ -9,6 +9,8 @@ class Filter extends ZM_Object { protected $defaults = array( 'Id' => null, 'Name' => '', + 'UserId' => 0, + 'ExecuteInterval' => 60, 'AutoExecute' => 0, 'AutoExecuteCmd' => '', 'AutoEmail' => 0, @@ -26,7 +28,6 @@ class Filter extends ZM_Object { 'AutoCopy' => 0, 'AutoCopyTo' => 0, 'UpdateDiskSpace' => 0, - 'UserId' => 0, 'Background' => 0, 'Concurrent' => 0, 'Query_json' => '', @@ -62,6 +63,7 @@ class Filter extends ZM_Object { } # end foreach term $this->_querystring .= $separator.urlencode($objectname.'[Query][sort_asc]').'='.$this->sort_asc(); $this->_querystring .= $separator.urlencode($objectname.'[Query][sort_field]').'='.$this->sort_field(); + $this->_querystring .= $separator.urlencode($objectname.'[Query][skip_locked]').'='.$this->skip_locked(); $this->_querystring .= $separator.urlencode($objectname.'[Query][limit]').'='.$this->limit(); if ( $this->Id() ) { $this->_querystring .= $separator.$objectname.urlencode('[Id]').'='.$this->Id(); @@ -207,18 +209,29 @@ class Filter extends ZM_Object { } public function sort_asc( ) { - if ( func_num_args( ) ) { + if (func_num_args()) { $Query = $this->Query(); $Query['sort_asc'] = func_get_arg(0); $this->Query($Query); } - if ( isset( $this->Query()['sort_asc'] ) ) { + if (isset($this->Query()['sort_asc'])) { return $this->{'Query'}['sort_asc']; } return ZM_WEB_EVENT_SORT_ORDER == 'asc' ? 1 : 0; #return $this->defaults{'sort_asc'}; } + public function skip_locked() { + if (func_num_args()) { + $Query = $this->Query(); + $Query['skip_locked'] = func_get_arg(0); + $this->Query($Query); + } + if (isset($this->Query()['skip_locked'])) + return $this->{'Query'}['skip_locked']; + return false; + } + public function limit( ) { if ( func_num_args( ) ) { $Query = $this->Query(); diff --git a/web/skins/classic/css/base/views/watch.css b/web/skins/classic/css/base/views/watch.css index 17bf1593d..64fb81b16 100644 --- a/web/skins/classic/css/base/views/watch.css +++ b/web/skins/classic/css/base/views/watch.css @@ -1,6 +1,8 @@ #header { - display: flex; - justify-content: space-between; +} + +#sidebar { + min-width: 140px; } #menuControls { @@ -19,19 +21,22 @@ #monitorStatus { margin: 4px auto; text-align: center; -} - -#monitorStatus #enableDisableAlarms { - float: left; -} - -#monitorStatus #forceCancelAlarm { - float: right; + display: inline-block; } #monitorStatus #monitorState { } +#replayStatus { + margin: 3px 0 2px; + text-align: center; + display: inline-block; +} + +#replayStatus > span { + padding: 0 4px; +} + #dvrControls { margin-top: 3px; margin-bottom: 2px; @@ -67,15 +72,6 @@ cursor: default; } -#replayStatus { - margin: 3px 0 2px; - text-align: center; - clear: both; -} - -#replayStatus > span { - padding: 0 4px; -} #events { margin: 0 auto; @@ -116,3 +112,22 @@ span.alert { background-color: #DCDCDC; } +.controlHeader { + width: 100%; +} + +#viewingFPS, +#captureFPS, +#analysisFPS +{ + display: inline-block; +} +#stateValue, +#viewingFPSValue, +#captureFPSValue, +#analysisFPSValue +{ + display: inline-block; + min-width: 40px; + text-align: right; +} diff --git a/web/skins/classic/views/filter.php b/web/skins/classic/views/filter.php index b441db349..8445d2c12 100644 --- a/web/skins/classic/views/filter.php +++ b/web/skins/classic/views/filter.php @@ -367,6 +367,7 @@ for ( $i=0; $i < count($terms); $i++ ) { translate('None'), 'Id' => translate('AttrId'), 'Name' => translate('AttrName'), 'Cause' => translate('AttrCause'), @@ -383,10 +384,18 @@ $sort_fields = array( ); echo htmlSelect('filter[Query][sort_field]', $sort_fields, $filter->sort_field()); $sort_dirns = array( - '1' => translate('SortAsc'), - '0' => translate('SortDesc') - ); -echo htmlSelect( 'filter[Query][sort_asc]', $sort_dirns, $filter->sort_asc() ); + '1' => translate('SortAsc'), + '0' => translate('SortDesc') +); +echo htmlSelect('filter[Query][sort_asc]', $sort_dirns, $filter->sort_asc()); +?> + + + +translate('No'), '1'=>translate('Yes')), + $filter->skip_locked()); ?> @@ -468,9 +477,13 @@ if ( ZM_OPT_MESSAGE ) {

- + Background() ) { ?> checked="checked" data-on-click-this="updateButtons"/>

+

+ + +

Concurrent() ) { ?> checked="checked" data-on-click-this="updateButtons"/> diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js index 324e7f7e0..8a0f527c9 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -44,7 +44,7 @@ function ajaxRequest(params) { data.view = 'request'; data.request = 'watch'; data.mid = monitorId; - if ( auth_hash ) data.auth = auth_hash; + if (auth_hash) data.auth = auth_hash; $j.getJSON(thisUrl, data) .done(function(data) { @@ -94,8 +94,48 @@ function showPtzControls() { showMode = 'control'; } +function changeSize() { + var width = $j('#width').val(); + var height = $j('#height').val(); + + // Scale the frame + monitor_frame = $j('#imageFeed'); + if (!monitor_frame) { + console.log('Error finding frame'); + return; + } + if (width) monitor_frame.css('width', width); + if (height) monitor_frame.css('height', height); + + var streamImg = document.getElementById('liveStream'+monitorData[monIdx].id); + if (streamImg) { + if (streamImg.nodeName == 'IMG') { + let src = streamImg.src; + streamImg.src = ''; + src = src.replace(/width=[\.\d]+/i, 'width='+parseInt(width)); + src = src.replace(/height=[\.\d]+/i, 'height='+parseInt(height)); + src = src.replace(/rand=\d+/i, 'rand='+Math.floor((Math.random() * 1000000) )); + streamImg.src = src; + } + streamImg.style.width = width ? width : null; + streamImg.style.height = height ? height : null; + } else { + console.log('Did not find liveStream'+monitorData[monIdx].id); + } + $j('#scale').val(''); + setCookie('zmCycleScale', '', 3600); + setCookie('zmCycleWidth', width, 3600); + setCookie('zmCycleHeight', height, 3600); +} // end function changeSize() + function changeScale() { var scale = $j('#scale').val(); + $j('#width').val('auto'); + $j('#height').val('auto'); + setCookie('zmCycleScale', scale, 3600); + setCookie('zmCycleWidth', 'auto', 3600); + setCookie('zmCycleHeight', 'auto', 3600); + var newWidth; var newHeight; var autoScale; @@ -104,7 +144,7 @@ function changeScale() { // times and what the consequences would be $j(window).off('resize', endOfResize); //remove resize handler when Scale to Fit is not active if (scale == '0' || scale == 'auto') { - var newSize = scaleToFit(monitorWidth, monitorHeight, $j('#liveStream'+monitorId), $j('#replayStatus')); + const newSize = scaleToFit(monitorWidth, monitorHeight, $j('#liveStream'+monitorId), $j('#replayStatus')); newWidth = newSize.width; newHeight = newSize.height; autoScale = newSize.autoScale; @@ -118,16 +158,18 @@ function changeScale() { var streamImg = $j('#liveStream'+monitorId); if (streamImg) { - var oldSrc = streamImg.attr('src'); - streamImg.attr('src', ''); - // This is so that we don't waste bandwidth and let the browser do all the scaling. - if (autoScale > 100) autoScale = 100; - if (scale > 100) scale = 100; - var newSrc = oldSrc.replace(/scale=\d+/i, 'scale='+((scale == 'auto' || scale == '0') ? autoScale : scale)); + if (streamImg.nodeName == 'IMG') { + const oldSrc = streamImg.attr('src'); + streamImg.attr('src', ''); + // This is so that we don't waste bandwidth and let the browser do all the scaling. + if (autoScale > 100) autoScale = 100; + if (scale > 100) scale = 100; + const newSrc = oldSrc.replace(/scale=\d+/i, 'scale='+((scale == 'auto' || scale == '0') ? autoScale : scale)); - streamImg.width(newWidth); - streamImg.height(newHeight); - streamImg.attr('src', newSrc); + streamImg.width(newWidth); + streamImg.height(newHeight); + streamImg.attr('src', newSrc); + } } else { console.error('No element found for liveStream'+monitorId); } @@ -200,9 +242,15 @@ function getStreamCmdResponse(respObj, respText) { // The get status command can get backed up, in which case we won't be able to get the semaphore and will exit. if (respObj.status) { streamStatus = respObj.status; - $j('#fpsValue').text(streamStatus.fps); - $j('#capturefpsValue').text(streamStatus.capturefps); - $j('#analysisfpsValue').text(streamStatus.analysisfps); + if ($j('#viewingFPSValue').text() != streamStatus.fps) { + $j('#viewingFPSValue').text(streamStatus.fps); + } + if ($j('#captureFPSValue').text() != streamStatus.capturefps) { + $j('#captureFPSValue').text(streamStatus.capturefps); + } + if ($j('#analysisFPSValue').text() != streamStatus.analysisfps) { + $j('#analysisFPSValue').text(streamStatus.analysisfps); + } setAlarmState(streamStatus.state); @@ -287,31 +335,19 @@ function getStreamCmdResponse(respObj, respText) { // Try to reload the image stream. var streamImg = $j('#liveStream'+monitorId); if (streamImg) { - var oldSrc = streamImg.attr('src'); - var newSrc = oldSrc.replace(/auth=\w+/i, 'auth='+streamStatus.auth); - if (oldSrc != newSrc) { - streamImg.attr('src', newSrc); - table.bootstrapTable('refresh'); + const oldSrc = streamImg.attr('src'); + if (oldSrc) { + const newSrc = oldSrc.replace(/auth=\w+/i, 'auth='+streamStatus.auth); + if (oldSrc != newSrc) { + streamImg.attr('src', newSrc); + table.bootstrapTable('refresh'); + } } } } // end if have a new auth hash } // end if respObj.status } else { checkStreamForErrors('getStreamCmdResponse', respObj);//log them - // Try to reload the image stream. - // If it's an auth error, we should reload the whole page. - console.log("have error"); - //window.location.reload(); - var streamImg = $j('#liveStream'+monitorId); - if (streamImg) { - var oldSrc = streamImg.attr('src'); - var newSrc = oldSrc.replace(/rand=\d+/i, 'rand='+Math.floor((Math.random() * 1000000) )); - - streamImg.attr('src', newSrc); - console.log('Changing livestream src to ' + newSrc); - } else { - console.log('Unable to find streamImg liveStream'); - } } var streamCmdTimeout = statusRefreshTimeout; @@ -368,6 +404,7 @@ function streamCmdPlay(action) { } function streamCmdReq(data) { + if (auth_hash) data.auth = auth_hash; $j.getJSON(monitorUrl + '?view=request&request=stream&connkey='+connKey, data) .done(getStreamCmdResponse) .fail(getStreamCmdError); @@ -386,10 +423,7 @@ function streamCmdStop(action) { setButtonState('fastRevBtn', 'unavail'); } if (action) { - var data = {}; - if (auth_hash) data.auth = auth_hash; - data.command = CMD_STOP; - streamCmdReq(data); + streamCmdReq({command: CMD_STOP}); } setButtonState('stopBtn', 'unavail'); setButtonState('playBtn', 'active'); @@ -407,7 +441,6 @@ function streamCmdFastFwd(action) { } if (action) { var data = {}; - if (auth_hash) data.auth = auth_hash; data.command = CMD_FASTFWD; streamCmdReq(data); } @@ -425,7 +458,6 @@ function streamCmdSlowFwd(action) { } if (action) { var data = {}; - if (auth_hash) data.auth = auth_hash; data.command = CMD_SLOWFWD; streamCmdReq(data); } @@ -447,7 +479,6 @@ function streamCmdSlowRev(action) { } if (action) { var data = {}; - if (auth_hash) data.auth = auth_hash; data.command = CMD_SLOWREV; streamCmdReq(data); } @@ -469,7 +500,6 @@ function streamCmdFastRev(action) { } if (action) { var data = {}; - if (auth_hash) data.auth = auth_hash; data.command = CMD_FASTREV; streamCmdReq(data); } @@ -477,7 +507,6 @@ function streamCmdFastRev(action) { function streamCmdZoomIn(x, y) { var data = {}; - if (auth_hash) data.auth = auth_hash; data.x = x; data.y = y; data.command = CMD_ZOOMIN; @@ -486,14 +515,12 @@ function streamCmdZoomIn(x, y) { function streamCmdZoomOut() { var data = {}; - if (auth_hash) data.auth = auth_hash; data.command = CMD_ZOOMOUT; streamCmdReq(data); } function streamCmdScale(scale) { var data = {}; - if (auth_hash) data.auth = auth_hash; data.command = CMD_SCALE; data.scale = scale; streamCmdReq(data); @@ -501,7 +528,6 @@ function streamCmdScale(scale) { function streamCmdPan(x, y) { var data = {}; - if (auth_hash) data.auth = auth_hash; data.x = x; data.y = y; data.command = CMD_PAN; @@ -510,11 +536,11 @@ function streamCmdPan(x, y) { function streamCmdQuery() { var data = {}; - if (auth_hash) data.auth = auth_hash; data.command = CMD_QUERY; streamCmdReq(data); } +/* getStatusCmd is used when not streaming, since there is no persistent zms */ function getStatusCmdResponse(respObj, respText) { watchdogOk('status'); if (statusCmdTimer) { @@ -522,32 +548,33 @@ function getStatusCmdResponse(respObj, respText) { } if (respObj.result == 'Ok') { - $j('#fpsValue').text(respObj.monitor.FrameRate); + $j('#captureFPSValue').text(respObj.monitor.FrameRate); setAlarmState(respObj.monitor.Status); } else { checkStreamForErrors('getStatusCmdResponse', respObj); } var statusCmdTimeout = statusRefreshTimeout; - if ( alarmState == STATE_ALARM || alarmState == STATE_ALERT ) { + if (alarmState == STATE_ALARM || alarmState == STATE_ALERT) { statusCmdTimeout = statusCmdTimeout/5; } statusCmdTimer = setTimeout(statusCmdQuery, statusCmdTimeout); } function statusCmdQuery() { - $j.getJSON(monitorUrl + '?view=request&request=status&entity=monitor&element[]=Status&element[]=FrameRate&id='+monitorId) + $j.getJSON(monitorUrl + '?view=request&request=status&entity=monitor&element[]=Status&element[]=FrameRate&id='+monitorId+'&'+auth_relay) .done(getStatusCmdResponse) .fail(logAjaxFail); - streamCmdTimer = null; + statusCmdTimer = null; } function alarmCmdReq(data) { + if (auth_hash) data.auth = auth_hash; $j.getJSON(monitorUrl + '?view=request&request=alarm&id='+monitorId, data) .done(getAlarmCmdResponse) .fail(function(jqxhr, textStatus, error) { - if ( textStatus === "timeout" ) { + if (textStatus === 'timeout') { streamCmdQuery(); } else { logAjaxFail(jqxhr, textStatus, error); @@ -561,14 +588,12 @@ function getAlarmCmdResponse(respObj, respText) { function cmdDisableAlarms() { var data = {}; - if (auth_hash) data.auth = auth_hash; data.command = 'disableAlarms'; alarmCmdReq(data); } function cmdEnableAlarms() { var data = {}; - if (auth_hash) data.auth = auth_hash; data.command = 'enableAlarms'; alarmCmdReq(data); } @@ -583,7 +608,6 @@ function cmdAlarm() { function cmdForceAlarm() { var data = {}; - if (auth_hash) data.auth = auth_hash; data.command = 'forceAlarm'; alarmCmdReq(data); if (window.event) window.event.preventDefault(); @@ -591,7 +615,6 @@ function cmdForceAlarm() { function cmdCancelForcedAlarm() { var data = {}; - if (auth_hash) data.auth = auth_hash; data.command = 'cancelForcedAlarm'; alarmCmdReq(data); if (window.event) window.event.preventDefault(); @@ -607,6 +630,7 @@ function cmdForce() { } function controlReq(data) { + if (auth_hash) data.auth = auth_hash; $j.getJSON(monitorUrl + '?view=request&request=control&id='+monitorId, data) .done(getControlResponse) .fail(logAjaxFail); @@ -639,16 +663,16 @@ function controlCmd(event) { var data = {}; if (event && (xtell || ytell)) { - var target = event.target; - var offset = $j(target).offset(); - var width = $j(target).width(); - var height = $j(target).height(); + const target = event.target; + const offset = $j(target).offset(); + const width = $j(target).width(); + const height = $j(target).height(); - var x = event.pageX - offset.left; - var y = event.pageY - offset.top; + const x = event.pageX - offset.left; + const y = event.pageY - offset.top; if (xtell) { - var xge = parseInt((x*100)/width); + let xge = parseInt((x*100)/width); if (xtell == -1) { xge = 100 - xge; } else if (xtell == 2) { @@ -657,7 +681,7 @@ function controlCmd(event) { data.xge = xge; } if (ytell) { - var yge = parseInt((y*100)/height); + let yge = parseInt((y*100)/height); if (ytell == -1) { yge = 100 - yge; } else if (ytell == 2) { @@ -667,7 +691,6 @@ function controlCmd(event) { } } - if (auth_hash) data.auth = auth_hash; data.control = control; controlReq(data); @@ -678,7 +701,6 @@ function controlCmd(event) { function controlCmdImage(x, y) { var data = {}; - if (auth_hash) data.auth = auth_hash; data.scale = scale; data.control = imageControlMode; data.x = x; @@ -768,7 +790,6 @@ function reloadWebSite() { function updatePresetLabels() { var lblNdx = $j('#ctrlPresetForm option:selected').val(); - $j('#newLabel').val(labels[lblNdx]); } @@ -878,7 +899,7 @@ function initPage() { // Load the PTZ Preset modal into the DOM if (monitorControllable) getCtrlPresetModal(); // Load the settings modal into the DOM - if (monitorType == "Local") getSettingsModal(); + if (monitorType == 'Local') getSettingsModal(); } if (monitorType != 'WebSite') { @@ -886,15 +907,12 @@ function initPage() { statusCmdTimer = setTimeout(statusCmdQuery, (Math.random()+0.1)*statusRefreshTimeout); setInterval(watchdogCheck, statusRefreshTimeout*2, 'status'); } else { - streamCmdTimer = setTimeout(streamCmdQuery, (Math.random()+0.1)*statusRefreshTimeout); setInterval(watchdogCheck, statusRefreshTimeout*2, 'stream'); } if (canStreamNative || (streamMode == 'single')) { var streamImg = $j('#imageFeed img'); - if (!streamImg) { - streamImg = $j('#imageFeed object'); - } + if (!streamImg) streamImg = $j('#imageFeed object'); if (!streamImg) { console.error('No streamImg found for imageFeed'); } else { @@ -905,6 +923,10 @@ function initPage() { streamImg.click(function(event) { handleClick(event); }); + streamImg.on("error", function(thing) { + console.log("Error loading image"); + console.log(thing); + }); } } // end if have streamImg } // streamMode native or single @@ -944,6 +966,18 @@ function initPage() { $j('#settingsModal').modal('show'); }); + bindButton('#cyclePlayBtn', 'click', null, cycleStart); + bindButton('#cyclePauseBtn', 'click', null, cyclePause); + bindButton('#cycleNextBtn', 'click', null, cycleNext); + bindButton('#cyclePrevBtn', 'click', null, cyclePrev); + bindButton('#cycleToggle', 'click', null, cycleToggle); + bindButton('#cyclePeriod', 'change', null, cyclePeriodChange); + if (cycle) { + cycleStart(); + } else { + cyclePause(); + } + // Only enable the settings button for local cameras settingsBtn.prop('disabled', !(canView.Control && (monitorType == 'Local'))); @@ -972,7 +1006,6 @@ function initPage() { function watchFullscreen() { const btn = document.getElementById('fullscreenBtn'); - console.log(btn); if (btn.firstElementChild.innerHTML=='fullscreen') { const content = document.getElementById('content'); openFullscreen(content); @@ -985,5 +1018,70 @@ function watchFullscreen() { } } +var intervalId; +var secondsToCycle = 0; + +function nextCycleView() { + secondsToCycle --; + if (secondsToCycle<=0) { + window.location.replace('?view=watch&mid='+nextMid+'&mode='+mode+'&cycle=true'); + } + $j('#secondsToCycle').text(secondsToCycle); +} + +function cyclePause() { + clearInterval(intervalId); + $j('#cyclePauseBtn').hide(); + $j('#cyclePlayBtn').show(); +} + +function cycleStart() { + secondsToCycle = $j('#cyclePeriod').val(); + intervalId = setInterval(nextCycleView, 1000); + $j('#cyclePauseBtn').show(); + $j('#cyclePlayBtn').hide(); +} + +function cycleNext() { + monIdx ++; + if (monIdx >= monitorData.length) { + monIdx = 0; + } + if (!monitorData[monIdx]) { + console.log('No monitorData for ' + monIdx); + } + window.location.replace('?view=watch&cycle=true&mid='+monitorData[monIdx].id+'&mode='+mode); +} + +function cyclePrev() { + monIdx --; + if (monIdx < 0) { + monIdx = monitorData.length - 1; + } + if (!monitorData[monIdx]) { + console.log('No monitorData for ' + monIdx); + } + window.location.replace('?view=watch&cycle=true&mid='+monitorData[monIdx].id+'&mode='+mode); +} + +function cyclePeriodChange() { + const cyclePeriodSelect = $j('#cyclePeriod'); + secondsToCycle = cyclePeriodSelect.val(); + setCookie('zmCyclePeriod', secondsToCycle, 3600); +} +function cycleToggle(e) { + sidebar = $j('#sidebar'); + button = $j('#cycleToggle'); + if (sidebar.is(":visible")) { + sidebar.hide(); + setCookie('zmCycleShow', false, 3600); + } else { + sidebar.show(); + setCookie('zmCycleShow', true, 3600); + } + button.toggleClass('btn-secondary'); + button.toggleClass('btn-primary'); +} + // Kick everything off $j(document).ready(initPage); diff --git a/web/skins/classic/views/js/watch.js.php b/web/skins/classic/views/js/watch.js.php index 74a86100c..ab09d6ca5 100644 --- a/web/skins/classic/views/js/watch.js.php +++ b/web/skins/classic/views/js/watch.js.php @@ -1,21 +1,20 @@ // // Import constants // -var deleteString = ""; - -var enableAlarmsStr = ""; -var disableAlarmsStr = ""; -var forceAlarmStr = ""; -var cancelForcedAlarmStr = ""; var CMD_NONE = ; var CMD_PAUSE = ; @@ -34,14 +33,13 @@ var CMD_NEXT = ; var CMD_SEEK = ; var CMD_QUERY = ; -var SCALE_BASE = ; - var SOUND_ON_ALARM = ; var POPUP_ON_ALARM = ; var LIST_THUMBS = ; var streamMode = ""; var showMode = ""; +var cycle = ; var connKey = ''; var maxDisplayEvents = ; @@ -55,6 +53,28 @@ var monitorRefresh = 'Refresh() ?>'; var monitorStreamReplayBuffer = StreamReplayBuffer() ?>; var monitorControllable = Controllable()?'true':'false' ?>; +var monIdx = ''; +var nextMid = ""; +var mode = ""; + +var monitorData = new Array(); + +monitorData[monitorData.length] = { + 'id': Id() ?>, + 'width': ViewWidth() ?>, + 'height':ViewHeight() ?>, + 'url': 'UrlToIndex() ?>', + 'onclick': function(){window.location.assign( '?view=watch&mid=Id() ?>' );}, + 'type': 'Type() ?>', + 'refresh': 'Refresh() ?>' +}; + + +var SCALE_BASE = ; var scale = ''; var statusRefreshTimeout = ; @@ -63,17 +83,16 @@ var imageRefreshTimeout = ; var canStreamNative = ; -Control(); - if ( $control->CanMoveMap() ) { ?> -var imageControlMode = "moveMap"; -CanMoveRel() ) { ?> -var imageControlMode = "movePseudoMap"; -CanMoveCon() ) { ?> -var imageControlMode = "moveConMap"; - -var imageControlMode = null; - +var imageControlMode = 'Control(); +if ($control->CanMoveMap()) { + echo 'moveMap'; +} else if ($control->CanMoveRel()) { + echo 'movePseudoMap'; +} else if ($control->CanMoveCon()) { + echo 'moveConMap'; +} +?>'; var refreshApplet = ; var appletRefreshTime = ; @@ -81,17 +100,18 @@ var appletRefreshTime = ; var labels = new Array(); Id() ) ) as $row ) { - $labels[$row['Preset']] = $row['Label']; -} - -foreach ($labels as $index=>$label) { -?> -labels[] = ''; -Id())) as $row) { + $label = $labels[$row['Preset']] = $row['Label']; + echo 'labels['. validInt($index) .'] = '.validJsStr($label).'\''; } ?> +var deleteString = ""; +var enableAlarmsStr = ""; +var disableAlarmsStr = ""; +var forceAlarmStr = ""; +var cancelForcedAlarmStr = ""; var translate = { + "seconds": "", "Fullscreen": "", "Exit Fullscreen": "", }; diff --git a/web/skins/classic/views/watch.php b/web/skins/classic/views/watch.php index beab28ac1..58d24ac85 100644 --- a/web/skins/classic/views/watch.php +++ b/web/skins/classic/views/watch.php @@ -18,143 +18,296 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // -if ( !canView('Stream') ) { +if (!canView('Stream')) { $view = 'error'; return; } +require_once('includes/Monitor.php'); + +ob_start(); +include('_monitor_filters.php'); +$filterbar = ob_get_contents(); +ob_end_clean(); -if ( !isset($_REQUEST['mid']) ) { - $view = 'error'; - return; -} // This is for input sanitation -$mid = intval($_REQUEST['mid']); -if ( !visibleMonitor($mid) ) { +$mid = isset($_REQUEST['mid']) ? intval($_REQUEST['mid']) : 0; + +$widths = array( + 'auto' => translate('auto'), + '100%' => '100%', + '160px' => '160px', + '320px' => '320px', + '352px' => '352px', + '640px' => '640px', + '1280px' => '1280px', + '1920px' => '1920px' +); + +$heights = array( + 'auto' => translate('auto'), + '240px' => '240px', + '480px' => '480px', + '720px' => '720px', + '1080px' => '1080px', +); + +$monitors = array(); +$monitor_index = 0; +foreach ($displayMonitors as &$row) { + if ($row['Function'] == 'None') continue; + if ($mid and ($row['Id'] == $mid)) $monitor_index = count($monitors); + $monitors[] = new ZM\Monitor($row); + if (!isset($widths[$row['Width'].'px'])) { + $widths[$row['Width'].'px'] = $row['Width'].'px'; + } + if (!isset($heights[$row['Height'].'px'])) { + $heights[$row['Height'].'px'] = $row['Height'].'px'; + } + unset($row); +} # end foreach Monitor + +if (!$mid) { + $mid = $monitors[0]->Id(); + $monitor_index = 0; +} + +if (!visibleMonitor($mid)) { $view = 'error'; return; } -require_once('includes/Monitor.php'); $monitor = new ZM\Monitor($mid); - +$nextMid = ($monitor_index == count($monitors)-1) ? $monitors[0]->Id() : $monitors[$monitor_index+1]->Id(); +$cycle = isset($_REQUEST['cycle']) and ($_REQUEST['cycle'] == 'true'); +$showCycle = $cycle; +ZM\Error("Show cycle: $showCycle"); +if (isset($_COOKIE['zmCycleShow'])) { + $showCycle = $_COOKIE['zmCycleShow'] == 'true'; + ZM\Error("Show cycle: $showCycle"); +} else { + ZM\Error("Show cycle: not set"); +} #Whether to show the controls button $showPtzControls = ( ZM_OPT_CONTROL && $monitor->Controllable() && canView('Control') && $monitor->Type() != 'WebSite' ); -if ( isset($_REQUEST['scale']) ) { +$options = array(); +if (empty($_REQUEST['mode'])) { + $options['mode'] = canStream() ? 'stream' : 'still'; +} else { + $options['mode'] = validHtmlStr($_REQUEST['mode']); +} +zm_session_start(); + +$period = ZM_WEB_REFRESH_CYCLE; +if (isset($_REQUEST['period'])) { + $period = validInt($_REQUEST['period']); +} else if (isset($_COOKIE['zmCyclePeriod'])) { + $period = validInt($_COOKIE['zmCyclePeriod']); +} + +if (isset($_REQUEST['scale'])) { $scale = validInt($_REQUEST['scale']); } else if ( isset($_COOKIE['zmWatchScale'.$mid]) ) { $scale = $_COOKIE['zmWatchScale'.$mid]; } else { $scale = $monitor->DefaultScale(); } +$options['scale'] = $scale; + +if (isset($_REQUEST['width'])) { + $options['width'] = validInt($_REQUEST['width']); +} else if ( isset($_COOKIE['zmCycleWidth']) and $_COOKIE['zmCycleWidth'] ) { + $_SESSION['zmCycleWidth'] = $options['width'] = $_COOKIE['zmCycleWidth']; +#} elseif ( isset($_SESSION['zmCycleWidth']) and $_SESSION['zmCycleWidth'] ) { + #$options['width'] = $_SESSION['zmCycleWidth']; +} else { + $options['width'] = ''; +} +if (isset($_REQUEST['height'])) { + $options['height'] =validInt($_REQUEST['height']); +} else if (isset($_COOKIE['zmCycleHeight']) and $_COOKIE['zmCycleHeight']) { + $_SESSION['zmCycleHeight'] = $options['height'] = $_COOKIE['zmCycleHeight']; +#else if ( isset($_SESSION['zmCycleHeight']) and $_SESSION['zmCycleHeight'] ) + #$options['height'] = $_SESSION['zmCycleHeight']; +} else { + $options['height'] = ''; +} +session_write_close(); $connkey = generateConnKey(); - $streamMode = getStreamMode(); -$popup = ((isset($_REQUEST['popup'])) && ($_REQUEST['popup'] == 1)); - noCacheHeaders(); xhtmlHeaders(__FILE__, $monitor->Name().' - '.translate('Feed')); ?> +