diff --git a/README.md b/README.md index 8f607c0c0..94774364c 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ This is the recommended method to install ZoneMinder onto your system. ZoneMinde If a repository that hosts ZoneMinder packages is not available for your distro, then you are encouraged to build your own package, rather than build from source. While each distro is different in ways that set it apart from all the others, they are often similar enough to allow you to adapt another distro's package building instructions to your own. -### Building a ZoneMinder Package +### Building a ZoneMinder Package ### Building ZoneMinder into a package is not any harder than building from source. As a matter of fact, if you have successfully built ZoneMinder from source in the past, then you may find these steps to be easier. @@ -55,7 +55,7 @@ Please visit our [ReadtheDocs site](https://zoneminder.readthedocs.org/en/stable ### Package Maintainers Many of the ZoneMinder configration variable default values are not configurable at build time through autotools or cmake. A new tool called *zmeditconfigdata.sh* has been added to allow package maintainers to manipulate any variable stored in ConfigData.pm without patching the source. -For example, let's say I have created a new ZoneMinder package that contains the cambolzola javascript file. However, by default cambozola support is turned off. To fix that, add this to the pacakging script: +For example, let's say I have created a new ZoneMinder package that contains the cambozola javascript file. However, by default cambozola support is turned off. To fix that, add this to the pacakging script: ```bash ./utils/zmeditconfigdata.sh ZM_OPT_CAMBOZOLA yes ``` diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index e5910bddb..91c34163d 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -781,6 +781,7 @@ INSERT INTO `Controls` VALUES (NULL,'D-LINK DCS-3415','Remote','DCS3415',0,0,0,1 INSERT INTO `Controls` VALUES (NULL,'IOS Camera','Ffmpeg','IPCAMIOS',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,1,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0); INSERT INTO `Controls` VALUES (NULL,'Dericam P2','Ffmpeg','DericamP2',0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,10,0,1,1,1,0,0,0,1,1,0,0,0,0,1,1,45,0,0,1,0,0,0,0,1,1,45,0,0,0,0); INSERT INTO `Controls` VALUES (NULL,'Trendnet','Remote','Trendnet',1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0); +INSERT INTO `Controls` VALUES (NULL,'PSIA','Remote','PSIA',0,0,0,1,0,0,1,0,0,0,0,0,0,0,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,20,0,1,1,1,0,0,1,0,1,0,0,0,0,1,-100,100,0,0,1,0,0,0,0,1,-100,100,0,0,0,0); INSERT INTO `Controls` VALUES (NULL,'Dahua','Remote','Dahua',0,0,0,1,0,0,1,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,20,0,1,1,1,0,0,1,0,1,0,0,0,0,1,1,8,0,0,1,0,0,0,0,1,1,8,0,0,0,0); -- @@ -808,6 +809,7 @@ INSERT into MonitorPresets VALUES (NULL,'Axis IP, mpeg4, unicast','Remote','rtsp INSERT into MonitorPresets VALUES (NULL,'Axis IP, mpeg4, multicast','Remote','rtsp',0,255,'rtsp','rtpMulti','',554,'/mpeg4/media.amp','/trackID=',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); INSERT into MonitorPresets VALUES (NULL,'Axis IP, mpeg4, RTP/RTSP','Remote','rtsp',0,255,'rtsp','rtpRtsp','',554,'/mpeg4/media.amp','/trackID=',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); INSERT into MonitorPresets VALUES (NULL,'Axis IP, mpeg4, RTP/RTSP/HTTP','Remote',NULL,NULL,NULL,'rtsp','rtpRtspHttp','',554,'/mpeg4/media.amp','/trackID=',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES (NULL,'D-link DCS-930L, 640x480, mjpeg','Remote','http',0,0,'http','simple','',80,'/mjpeg.cgi',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100); INSERT INTO MonitorPresets VALUES (NULL,'Panasonic IP, 320x240, mpjpeg','Remote','http',0,0,'http','simple','',80,'/nphMotionJpeg?Resolution=320x240&Quality=Standard',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100); INSERT INTO MonitorPresets VALUES (NULL,'Panasonic IP, 320x240, jpeg','Remote','http',0,0,'http','simple','',80,'/SnapshotJPEG?Resolution=320x240&Quality=Standard',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100); INSERT INTO MonitorPresets VALUES (NULL,'Panasonic IP, 320x240, jpeg, max 5 FPS','Remote','http',0,0,'http','simple','',80,'/SnapshotJPEG?Resolution=320x240&Quality=Standard',NULL,320,240,3,5.0,0,NULL,NULL,NULL,100,100); diff --git a/db/zm_update-1.32.2.sql b/db/zm_update-1.32.2.sql new file mode 100644 index 000000000..0bb156dad --- /dev/null +++ b/db/zm_update-1.32.2.sql @@ -0,0 +1,5 @@ +-- +-- This updates a 1.32.1 database to 1.32.2 +-- +-- No changes required +-- diff --git a/db/zm_update-1.32.3.sql b/db/zm_update-1.32.3.sql new file mode 100644 index 000000000..fe38baede --- /dev/null +++ b/db/zm_update-1.32.3.sql @@ -0,0 +1,9 @@ +-- +-- This updates a 1.32.2 database to 1.32.3 +-- + +-- +-- Add some additional monitor preset values +-- + +INSERT INTO MonitorPresets VALUES (NULL,'D-link DCS-930L, 640x480, mjpeg','Remote','http',0,0,'http','simple','',80,'/mjpeg.cgi',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100); diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index 32f052ecd..de1d408ea 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -25,7 +25,7 @@ %global _hardened_build 1 Name: zoneminder -Version: 1.32.1 +Version: 1.32.2 Release: 1%{?dist} Summary: A camera monitoring and analysis tool Group: System Environment/Daemons @@ -320,6 +320,13 @@ EOF %dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_localstatedir}/run/zoneminder %changelog +* Sat Oct 13 2018 Andrew Bauer - 1.32.2-1 +- 1.32.2 release +- Bug fix release + +* Thu Oct 04 2018 Sérgio Basto - 1.32.1-2 +- Mass rebuild for x264 and/or x265 + * Tue Oct 2 2018 Andrew Bauer - 1.32.1-1 - 1.32.1 release - Bug fix release diff --git a/docs/api.rst b/docs/api.rst index 942d701e2..a6d0cc9aa 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -13,6 +13,13 @@ The API is built in CakePHP and lives under the ``/api`` directory. It provides a RESTful service and supports CRUD (create, retrieve, update, delete) functions for Monitors, Events, Frames, Zones and Config. +Enabling API +^^^^^^^^^^^^ +A default ZoneMinder installs with APIs enabled. You can explictly enable/disable the APIs +via the Options->System menu by enabling/disabling ``OPT_USE_API``. Note that if you intend +to use APIs with 3rd party apps, such as zmNinja or others that use APIs, you should also +enable ``AUTH_HASH_LOGINS``. + Login, Logout & API Security ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The APIs tie into ZoneMinder's existing security model. This means if you have diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/PSIA.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/PSIA.pm new file mode 100644 index 000000000..fe067fe1f --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/PSIA.pm @@ -0,0 +1,365 @@ +package ZoneMinder::Control::PSIA; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Control; + +our @ISA = qw(ZoneMinder::Control); + +our $REALM = 'TV-IP450PI'; +our $USERNAME = 'admin'; +our $PASSWORD = ''; +our $ADDRESS = ''; +our $PROTOCOL = 'http://'; + +use ZoneMinder::Logger qw(:all); +use ZoneMinder::Config qw(:all); +use ZoneMinder::Database qw(zmDbConnect); + +sub open +{ + my $self = shift; + $self->loadMonitor(); + + if ( ( $self->{Monitor}->{ControlAddress} =~ /^(?https?:\/\/)?(?[^:@]+)?:?(?[^\/@]+)?@?(?
.*)$/ ) ) { + $PROTOCOL = $+{PROTOCOL} if $+{PROTOCOL}; + $USERNAME = $+{USERNAME} if $+{USERNAME}; + $PASSWORD = $+{PASSWORD} if $+{PASSWORD}; + $ADDRESS = $+{ADDRESS} if $+{ADDRESS}; + } else { + Error('Failed to parse auth from address ' . $self->{Monitor}->{ControlAddress}); + $ADDRESS = $self->{Monitor}->{ControlAddress}; + } + if ( !($ADDRESS =~ /:/) ) { + Error('You generally need to also specify the port. I will append :80'); + $ADDRESS .= ':80'; + } + + use LWP::UserAgent; + $self->{ua} = LWP::UserAgent->new; + $self->{ua}->agent( "ZoneMinder Control Agent/".$ZoneMinder::Base::ZM_VERSION ); + $self->{state} = 'closed'; + Debug( "sendCmd credentials control address:'".$ADDRESS + ."' realm:'" . $REALM + . "' username:'" . $USERNAME + . "' password:'".$PASSWORD + ."'" + ); + $self->{ua}->credentials($ADDRESS, $REALM, $USERNAME, $PASSWORD); + + # Detect REALM + my $req = HTTP::Request->new(GET=>$PROTOCOL . $ADDRESS . "/PSIA/PTZ/channels"); + my $res = $self->{ua}->request($req); + + if ($res->is_success) { + $self->{state} = 'open'; + return; + } elsif (! $res->is_success) { + Debug("Need newer REALM"); + if ( $res->status_line() eq '401 Unauthorized' ) { + my $headers = $res->headers(); + foreach my $k ( keys %$headers ) { + Debug("Initial Header $k => $$headers{$k}"); + } # end foreach + if ( $$headers{'www-authenticate'} ) { + my ($auth, $tokens) = $$headers{'www-authenticate'} =~ /^(\w+)\s+(.*)$/; + if ($tokens =~ /\w+="([^"]+)"/i) { + $REALM = $1; + Debug("Changing REALM to $REALM"); + $self->{ua}->credentials($ADDRESS, $REALM, $USERNAME, $PASSWORD); + } # end if + } else { + Debug("No WWW-Authenticate header"); + } # end if www-authenticate header + } # end if $res->status_line() eq '401 Unauthorized' + } # end elsif ! $res->is_success +} + +sub close +{ + my $self = shift; + $self->{state} = 'closed'; +} + +sub printMsg +{ + my $self = shift; + my $msg = shift; + my $msg_len = length($msg); + + Debug( $msg."[".$msg_len."]" ); +} + +sub sendGetRequest { + my $self = shift; + my $url_path = shift; + + my $result = undef; + + my $url = $PROTOCOL . $ADDRESS . $url_path; + my $req = HTTP::Request->new(GET=>$url); + + my $res = $self->{ua}->request($req); + + if ($res->is_success) { + $result = !undef; + } else { + if ( $res->status_line() eq '401 Unauthorized' ) { + Error( "Error check failed, trying again: USERNAME: $USERNAME realm: $REALM password: " . $PASSWORD ); + Error("Content was " . $res->content() ); + my $res = $self->{ua}->request($req); + if ( $res->is_success ) { + $result = !undef; + } else { + Error("Content was " . $res->content() ); + } + } + if ( ! $result ) { + Error("Error check failed: '".$res->status_line()); + } + } + return($result); +} +sub sendPutRequest { + my $self = shift; + my $url_path = shift; + my $content = shift; + + my $result = undef; + + my $url = $PROTOCOL . $ADDRESS . $url_path; + my $req = HTTP::Request->new(PUT=>$url); + if(defined($content)) { + $req->content_type("application/x-www-form-urlencoded; charset=UTF-8"); + $req->content('' . "\n" . $content); + } + + my $res = $self->{ua}->request($req); + + if ($res->is_success) { + $result = !undef; + } else { + if ( $res->status_line() eq '401 Unauthorized' ) { + Error( "Error check failed, trying again: USERNAME: $USERNAME realm: $REALM password: " . $PASSWORD ); + Error("Content was " . $res->content() ); + my $res = $self->{ua}->request($req); + if ( $res->is_success ) { + $result = !undef; + } else { + Error("Content was " . $res->content() ); + } + } + if ( ! $result ) { + Error( "Error check failed: '".$res->status_line()."' cmd:'".$cmd."'" ); + } + } + return($result); +} +sub sendDeleteRequest { + my $self = shift; + my $url_path = shift; + + my $result = undef; + + my $url = $PROTOCOL . $ADDRESS . $url_path; + my $req = HTTP::Request->new(DELETE=>$url); + my $res = $self->{ua}->request($req); + if ($res->is_success) { + $result = !undef; + } else { + if ( $res->status_line() eq '401 Unauthorized' ) { + Error( "Error check failed, trying again: USERNAME: $USERNAME realm: $REALM password: " . $PASSWORD ); + Error("Content was " . $res->content() ); + my $res = $self->{ua}->request($req); + if ( $res->is_success ) { + $result = !undef; + } else { + Error("Content was " . $res->content() ); + } + } + if ( ! $result ) { + Error( "Error check failed: '".$res->status_line()."' cmd:'".$cmd."'" ); + } + } + return($result); +} + +sub move +{ + my $self = shift; + my $panPercentage = shift; + my $tiltPercentage = shift; + my $zoomPercentage = shift; + + my $cmd = "set_relative_pos&posX=$panSteps&posY=$tiltSteps"; + my $ptzdata = ''; + $ptzdata .= '' . $panPercentage . ''; + $ptzdata .= '' . $tiltPercentage . ''; + $ptzdata .= '' . $zoomPercentage . ''; + $ptzdata .= '500'; + $ptzdata .= ''; + $self->sendPutRequest("/PSIA/PTZ/channels/1/momentary", $ptzdata); +} + +sub moveRelUpLeft +{ + my $self = shift; + Debug( "Move Up Left" ); + $self->move(-50, 50, 0); +} + +sub moveRelUp +{ + my $self = shift; + Debug( "Move Up" ); + $self->move(0, 50, 0); +} + +sub moveRelUpRight +{ + my $self = shift; + Debug( "Move Up Right" ); + $self->move(50, 50, 0); +} + +sub moveRelLeft +{ + my $self = shift; + Debug( "Move Left" ); + $self->move(-50, 0, 0); +} + +sub moveRelRight +{ + my $self = shift; + Debug( "Move Right" ); + $self->move(50, 0, 0); +} + +sub moveRelDownLeft +{ + my $self = shift; + Debug( "Move Down Left" ); + $self->move(-50, -50, 0); +} + +sub moveRelDown +{ + my $self = shift; + Debug( "Move Down" ); + $self->move(0, -50, 0); +} + +sub moveRelDownRight +{ + my $self = shift; + Debug( "Move Down Right" ); + $self->move(50, -50, 0); +} + +sub zoomRelTele +{ + my $self = shift; + Debug("Zoom Relative Tele"); + $self->move(0, 0, 50); +} + +sub zoomRelWide +{ + my $self = shift; + Debug("Zoom Relative Wide"); + $self->move(0, 0, -50); +} + + +sub presetClear +{ + my $self = shift; + my $params = shift; + my $preset_id = $self->getParam($params, 'preset'); + my $url_path = "/PSIA/PTZ/channels/1/presets/" . $preset_id; + $self->sendDeleteRequest($url_path); +} + + +sub presetSet +{ + my $self = shift; + my $params = shift; + + my $preset_id = $self->getParam($params, 'preset'); + + my $dbh = zmDbConnect(1); + my $sql = 'SELECT * FROM ControlPresets WHERE MonitorId = ? AND Preset = ?'; + my $sth = $dbh->prepare($sql) + or Fatal("Can't prepare sql '$sql': " . $dbh->errstr()); + my $res = $sth->execute($self->{Monitor}->{Id}, $preset_id) + or Fatal("Can't execute sql '$sql': " . $sth->errstr()); + my $control_preset_row = $sth->fetchrow_hashref(); + my $new_label_name = $control_preset_row->{'Label'}; + + my $url_path = "/PSIA/PTZ/channels/1/presets/" . $preset_id; + my $ptz_preset_data = ''; + $ptz_preset_data .= '' . $preset_id . ''; + $ptz_preset_data .= '' . $new_label_name . ''; + $ptz_preset_data .= ''; + $self->sendPutRequest($url_path, $ptz_preset_data); +} + +sub presetGoto +{ + my $self = shift; + my $params = shift; + my $preset_id = $self->getParam($params, 'preset'); + + my $url_path = '/PSIA/PTZ/channels/1/presets/' . $preset_id . '/goto'; + + $self->sendPutRequest($url_path); +} + + +1; +__END__ + +=head1 NAME + +ZoneMinder::Control::PSIA - Perl module for cameras implementing the PSIA +(Physical Security Interoperability Alliance), IP Media Devices API +specification + +=head1 SYNOPSIS + +use ZoneMinder::Control::PSIA; +place this in /usr/share/perl5/ZoneMinder/Control + +=head1 DESCRIPTION + +This has so far been tested with: +- Trendnet TV-IP450PI + +=head2 EXPORT + +None by default. + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2018 ZoneMinder LLC + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +=cut diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm index 16535d9e3..3caa6af4a 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm @@ -704,6 +704,8 @@ sub Fatal( @ ) { if ( $SIG{TERM} and ( $SIG{TERM} ne 'DEFAULT' ) ) { $SIG{TERM}(); } + # I think if we don't disconnect we will leave sockets around in TIME_WAIT + zmDbDisconnect(); exit(-1); } diff --git a/scripts/zmfilter.pl.in b/scripts/zmfilter.pl.in index f87393266..f9029016a 100644 --- a/scripts/zmfilter.pl.in +++ b/scripts/zmfilter.pl.in @@ -69,6 +69,7 @@ use Time::HiRes qw/gettimeofday/; use Getopt::Long; use autouse 'Pod::Usage'=>qw(pod2usage); use autouse 'Data::Dumper'=>qw(Dumper); +use File::Path qw(make_path); my $daemon = 0; my $filter_name = ''; @@ -162,7 +163,7 @@ my $delay = $Config{ZM_FILTER_EXECUTE_INTERVAL}; my $event_id = 0; if ( ! EVENT_PATH ) { - Error("No event path defined. Config was $Config{ZM_DIR_EVENTS}\n"); + Error("No event path defined. Config was $Config{ZM_DIR_EVENTS}"); die; } @@ -173,11 +174,11 @@ chdir( EVENT_PATH ); my $dbh = zmDbConnect(); if ( $filter_name ) { - Info("Scanning for events using filter '$filter_name'\n"); + Info("Scanning for events using filter '$filter_name'"); } elsif ( $filter_id ) { - Info("Scanning for events using filter id '$filter_id'\n"); + Info("Scanning for events using filter id '$filter_id'"); } else { - Info("Scanning for events using all filters\n"); + Info("Scanning for events using all filters"); } if ( ! ( $filter_name or $filter_id ) ) { @@ -191,7 +192,7 @@ my $last_action = 0; while( !$zm_terminate ) { my $now = time; if ( ($now - $last_action) > $Config{ZM_FILTER_RELOAD_DELAY} ) { - Debug("Reloading filters\n"); + Debug("Reloading filters"); $last_action = $now; @filters = getFilters({ Name=>$filter_name, Id=>$filter_id }); } @@ -211,7 +212,7 @@ while( !$zm_terminate ) { last if (!$daemon and ($filter_name or $filter_id)) or $zm_terminate; - Debug("Sleeping for $delay seconds\n"); + Debug("Sleeping for $delay seconds"); sleep($delay); } @@ -292,48 +293,48 @@ sub checkFilter { last if $zm_terminate; my $Event = new ZoneMinder::Event($$event{Id}, $event); - Debug("Checking event $event->{Id}"); + Debug("Checking event $Event->{Id}"); my $delete_ok = !undef; $dbh->ping(); if ( $filter->{AutoArchive} ) { - Info("Archiving event $event->{Id}"); + Info("Archiving event $Event->{Id}"); # Do it individually to avoid locking up the table for new events my $sql = 'UPDATE Events SET Archived = 1 WHERE Id = ?'; my $sth = $dbh->prepare_cached( $sql ) or Fatal("Unable to prepare '$sql': ".$dbh->errstr()); - my $res = $sth->execute( $event->{Id} ) + my $res = $sth->execute( $Event->{Id} ) or Error("Unable to execute '$sql': ".$dbh->errstr()); } if ( $Config{ZM_OPT_FFMPEG} && $filter->{AutoVideo} ) { - if ( !$event->{Videoed} ) { - $delete_ok = undef if !generateVideo($filter, $event); + if ( !$Event->{Videoed} ) { + $delete_ok = undef if !generateVideo($filter, $Event); } } if ( $Config{ZM_OPT_EMAIL} && $filter->{AutoEmail} ) { - if ( !$event->{Emailed} ) { + if ( !$Event->{Emailed} ) { $delete_ok = undef if !sendEmail($filter, $Event); } } if ( $Config{ZM_OPT_MESSAGE} && $filter->{AutoMessage} ) { - if ( !$event->{Messaged} ) { + if ( !$Event->{Messaged} ) { $delete_ok = undef if !sendMessage($filter, $Event); } } if ( $Config{ZM_OPT_UPLOAD} && $filter->{AutoUpload} ) { - if ( !$event->{Uploaded} ) { + if ( !$Event->{Uploaded} ) { $delete_ok = undef if !uploadArchFile($filter, $Event); } } if ( $filter->{AutoExecute} ) { - if ( !$event->{Executed} ) { - $delete_ok = undef if !executeCommand($filter, $event); + if ( !$Event->{Executed} ) { + $delete_ok = undef if !executeCommand($filter, $Event); } } if ( $filter->{AutoDelete} ) { if ( $delete_ok ) { $Event->delete(); } else { - Error("Unable toto delete event $event->{Id} as previous operations failed"); + Error("Unable to delete event $Event->{Id} as previous operations failed"); } } # end if AutoDelete @@ -364,11 +365,11 @@ sub checkFilter { sub generateVideo { my $filter = shift; - my $event = shift; + my $Event = shift; my $phone = shift; - my $rate = $event->{DefaultRate}/100; - my $scale = $event->{DefaultScale}/100; + my $rate = $Event->{DefaultRate}/100; + my $scale = $Event->{DefaultScale}/100; my $format; my @ffmpeg_formats = split(/\s+/, $Config{ZM_FFMPEG_FORMATS}); @@ -393,7 +394,7 @@ sub generateVideo { my $command = join('', $Config{ZM_PATH_BIN}, '/zmvideo.pl -e ', - $event->{Id}, + $Event->{Id}, ' -r ', $rate, ' -s ', @@ -405,10 +406,10 @@ sub generateVideo { chomp($output); my $status = $? >> 8; if ( $status || logDebugging() ) { - Debug("Output: $output\n"); + Debug("Output: $output"); } if ( $status ) { - Error("Video generation '$command' failed with status: $status\n"); + Error("Video generation '$command' failed with status: $status"); if ( wantarray() ) { return( undef, undef ); } @@ -417,8 +418,8 @@ sub generateVideo { my $sql = 'UPDATE Events SET Videoed = 1 WHERE Id = ?'; my $sth = $dbh->prepare_cached($sql) or Fatal("Unable to prepare '$sql': ".$dbh->errstr()); - my $res = $sth->execute($event->{Id}) - or Fatal("Unable toexecute '$sql': ".$dbh->errstr()); + my $res = $sth->execute($Event->{Id}) + or Fatal("Unable to execute '$sql': ".$dbh->errstr()); if ( wantarray() ) { return( $format, $output ); } @@ -453,7 +454,7 @@ sub generateImage { chomp( $output ); my $status = $? >> 8; if ( $status || logDebugging() ) { - Debug("Output: $output\n"); + Debug("Output: $output"); } if ( $status ) { Error("Failed $command status $status"); @@ -467,22 +468,30 @@ sub generateImage { sub uploadArchFile { my $filter = shift; - my $event = shift; + my $Event = shift; if ( ! $Config{ZM_UPLOAD_HOST} ) { Error('Cannot upload archive as no upload host defined'); return( 0 ); } - my $archFile = $event->{MonitorName}.'-'.$event->{Id}; - my $archImagePath = $event->Path() + # Try to make the path to the upload folder if it doesn't already exist + make_path( $Config{ZM_UPLOAD_LOC_DIR} ); + + # Complain if the upload folder is still not writable + if ( ! -w $Config{ZM_UPLOAD_LOC_DIR} ) { + Error("Upload folder either does not exist or is not writable: $Config{ZM_UPLOAD_LOC_DIR}"); + return(0); + } + + my $archFile = $Event->{MonitorName}.'-'.$Event->{Id}; + my $archImagePath = $Event->Path() .'/' .( ( $Config{ZM_UPLOAD_ARCH_ANALYSE} ) - ? '{*analyse,*capture}' - : '*capture' + ? '{*analyse.jpg,*capture.jpg,snapshot.jpg,*.mp4}' + : '{*capture.jpg,snapshot.jpg,*.mp4}' ) - .'.jpg' ; my @archImageFiles = glob($archImagePath); my $archLocPath; @@ -492,11 +501,11 @@ sub uploadArchFile { $archFile .= '.zip'; $archLocPath = $Config{ZM_UPLOAD_LOC_DIR}.'/'.$archFile; my $zip = Archive::Zip->new(); - Info("Creating upload file '$archLocPath', ".int(@archImageFiles)." files\n"); + Info("Creating upload file '$archLocPath', ".int(@archImageFiles).' files'); my $status = &AZ_OK; foreach my $imageFile ( @archImageFiles ) { - Debug("Adding $imageFile\n"); + Debug("Adding $imageFile"); my $member = $zip->addFile($imageFile); if ( !$member ) { Error("Unable toto add image file $imageFile to zip archive $archLocPath"); @@ -524,7 +533,7 @@ sub uploadArchFile { $archFile .= '.tar'; } $archLocPath = $Config{ZM_UPLOAD_LOC_DIR}.'/'.$archFile; - Info("Creating upload file '$archLocPath', ".int(@archImageFiles)." files\n"); + Info("Creating upload file '$archLocPath', ".int(@archImageFiles).' files'); if ( $archError = !Archive::Tar->create_archive( $archLocPath, @@ -540,7 +549,7 @@ sub uploadArchFile { return( 0 ); } else { if ( $Config{ZM_UPLOAD_PROTOCOL} eq 'ftp' ) { - Info('Uploading to '.$Config{ZM_UPLOAD_HOST}." using FTP"); + Info('Uploading to '.$Config{ZM_UPLOAD_HOST}.' using FTP'); my $ftp = Net::FTP->new( $Config{ZM_UPLOAD_HOST}, Timeout=>$Config{ZM_UPLOAD_TIMEOUT}, @@ -548,24 +557,24 @@ sub uploadArchFile { Debug=>$Config{ZM_UPLOAD_DEBUG} ); if ( !$ftp ) { - Error("Unable tocreate FTP connection: $@"); + Error("Unable to create FTP connection: $@"); return 0; } $ftp->login($Config{ZM_UPLOAD_USER}, $Config{ZM_UPLOAD_PASS}) - or Error("FTP - Unable tologin"); + or Error("FTP - Unable to login"); $ftp->binary() - or Error("FTP - Unable togo binary"); + or Error("FTP - Unable to go binary"); $ftp->cwd($Config{ZM_UPLOAD_REM_DIR}) - or Error("FTP - Unable tocwd") + or Error("FTP - Unable to cwd") if ( $Config{ZM_UPLOAD_REM_DIR} ); $ftp->put( $archLocPath ) - or Error("FTP - Unable toupload '$archLocPath'"); + or Error("FTP - Unable to upload '$archLocPath'"); $ftp->quit() - or Error("FTP - Unable toquit"); + or Error("FTP - Unable to quit"); } else { my $host = $Config{ZM_UPLOAD_HOST}; $host .= ':'.$Config{ZM_UPLOAD_PORT} if $Config{ZM_UPLOAD_PORT}; - Info('Uploading to '.$host." using SFTP\n"); + Info('Uploading to '.$host.' using SFTP'); my %sftpOptions = ( host=>$Config{ZM_UPLOAD_HOST}, user=>$Config{ZM_UPLOAD_USER} ($Config{ZM_UPLOAD_PASS} ? (password=>$Config{ZM_UPLOAD_PASS}) : ()), @@ -580,7 +589,7 @@ sub uploadArchFile { $sftpOptions{more} = [@more_ssh_args]; my $sftp = Net::SFTP::Foreign->new($Config{ZM_UPLOAD_HOST}, %sftpOptions); if ( $sftp->error ) { - Error("Unable tocreate SFTP connection: ".$sftp->error); + Error("Unable to create SFTP connection: ".$sftp->error); return 0; } $sftp->setcwd($Config{ZM_UPLOAD_REM_DIR}) @@ -592,9 +601,9 @@ sub uploadArchFile { unlink($archLocPath); my $sql = 'UPDATE Events SET Uploaded = 1 WHERE Id = ?'; my $sth = $dbh->prepare_cached($sql) - or Fatal("Unable toprepare '$sql': ".$dbh->errstr()); - my $res = $sth->execute($event->{Id}) - or Fatal("Unable toexecute '$sql': ".$dbh->errstr()); + or Fatal("Unable to prepare '$sql': ".$dbh->errstr()); + my $res = $sth->execute($Event->{Id}) + or Fatal("Unable to execute '$sql': ".$dbh->errstr()); } return 1; } # end sub uploadArchFile @@ -622,9 +631,9 @@ sub substituteTags { WHERE EventId = ? AND Type = 'Alarm' ORDER BY FrameId`; my $sth = $dbh->prepare_cached($sql) - or Fatal("Unable toprepare '$sql': ".$dbh->errstr()); + or Fatal("Unable to prepare '$sql': ".$dbh->errstr()); my $res = $sth->execute($Event->{Id}) - or Fatal( "Unable toexecute '$sql': ".$dbh->errstr()); + or Fatal("Unable to execute '$sql': ".$dbh->errstr()); my $rows = 0; while( my $frame = $sth->fetchrow_hashref() ) { if ( !$first_alarm_frame ) { @@ -796,7 +805,7 @@ sub sendEmail { $ssmtp_location = qx('which ssmtp'); } if ( !$ssmtp_location ) { - Debug('Unable tofind ssmtp, trying MIME::Lite->send'); + Debug('Unable to find ssmtp, trying MIME::Lite->send'); MIME::Lite->send('smtp', $Config{ZM_EMAIL_HOST}, Timeout=>60); $mail->send(); } else { @@ -828,16 +837,16 @@ sub sendEmail { } }; if ( $@ ) { - Error("Unable tosend email: $@"); + Error("Unable to send email: $@"); return 0; } else { Info('Notification email sent'); } my $sql = 'UPDATE Events SET Emailed = 1 WHERE Id = ?'; my $sth = $dbh->prepare_cached($sql) - or Fatal("Unable toprepare '$sql': ".$dbh->errstr()); + or Fatal("Unable to prepare '$sql': ".$dbh->errstr()); my $res = $sth->execute($Event->{Id}) - or Fatal("Unable toexecute '$sql': ".$dbh->errstr()); + or Fatal("Unable to execute '$sql': ".$dbh->errstr()); return 1; } @@ -898,7 +907,7 @@ sub sendMessage { $ssmtp_location = qx('which ssmtp'); } if ( !$ssmtp_location ) { - Debug('Unable tofind ssmtp, trying MIME::Lite->send'); + Debug('Unable to find ssmtp, trying MIME::Lite->send'); MIME::Lite->send(smtp=>$Config{ZM_EMAIL_HOST}, Timeout=>60); $mail->send(); } else { @@ -933,29 +942,29 @@ sub sendMessage { } }; if ( $@ ) { - Error("Unable tosend email: $@"); + Error("Unable to send email: $@"); return 0; } else { Info('Notification message sent'); } my $sql = 'UPDATE Events SET Messaged = 1 WHERE Id = ?'; my $sth = $dbh->prepare_cached($sql) - or Fatal("Unable toprepare '$sql': ".$dbh->errstr()); + or Fatal("Unable to prepare '$sql': ".$dbh->errstr()); my $res = $sth->execute($Event->{Id}) - or Fatal("Unable toexecute '$sql': ".$dbh->errstr()); + or Fatal("Unable to execute '$sql': ".$dbh->errstr()); return 1; } # end sub sendMessage sub executeCommand { my $filter = shift; - my $event = shift; + my $Event = shift; - my $event_path = $event->Path(); + my $event_path = $Event->Path(); my $command = $filter->{AutoExecuteCmd}; $command .= " $event_path"; - $command = substituteTags($command, $filter, $event); + $command = substituteTags($command, $filter, $Event); Info("Executing '$command'"); my $output = qx($command); @@ -971,7 +980,7 @@ sub executeCommand { my $sql = 'UPDATE Events SET Executed = 1 WHERE Id = ?'; my $sth = $dbh->prepare_cached($sql) or Fatal("Unable to prepare '$sql': ".$dbh->errstr()); - my $res = $sth->execute( $event->{Id} ) + my $res = $sth->execute( $Event->{Id} ) or Fatal("Unable to execute '$sql': ".$dbh->errstr()); } return( 1 ); diff --git a/scripts/zmpkg.pl.in b/scripts/zmpkg.pl.in index d11e04d5a..b29235f65 100644 --- a/scripts/zmpkg.pl.in +++ b/scripts/zmpkg.pl.in @@ -44,7 +44,6 @@ delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; my $store_state=''; # PP - will remember state name passed logInit(); -Info("Aftere LogInit"); my $command = $ARGV[0]||''; if ( $command eq 'version' ) { diff --git a/scripts/zmtrigger.pl.in b/scripts/zmtrigger.pl.in index 1e849f3cd..b16e1cdd4 100644 --- a/scripts/zmtrigger.pl.in +++ b/scripts/zmtrigger.pl.in @@ -88,13 +88,13 @@ delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; logInit(); logSetSignal(); -Info( "Trigger daemon starting\n" ); +Info( "Trigger daemon starting" ); my $dbh = zmDbConnect(); my $base_rin = ''; foreach my $connection ( @connections ) { - Info( "Opening connection '$connection->{name}'\n" ); + Info( "Opening connection '$connection->{name}'" ); $connection->open(); } @@ -109,7 +109,7 @@ foreach my $connection ( @in_select_connections ) { my %spawned_connections; my %monitors; my $monitor_reload_time = 0; -my $needsReload = 0; +my @needsReload; loadMonitors(); $! = undef; @@ -127,14 +127,14 @@ while( 1 ) { my $nfound = select( my $rout = $rin, undef, my $eout = $ein, $timeout ); if ( $nfound > 0 ) { - Debug( "Got input from $nfound connections\n" ); + Debug( "Got input from $nfound connections" ); foreach my $connection ( @in_select_connections ) { if ( vec( $rout, $connection->fileno(), 1 ) ) { Debug( 'Got input from connection ' .$connection->name() .' (' .$connection->fileno() - .")\n" + .")" ); if ( $connection->spawns() ) { my $new_connection = $connection->accept(); @@ -143,7 +143,7 @@ while( 1 ) { .$new_connection->fileno() .'), ' .int(keys(%spawned_connections)) - ." spawned connections\n" + ." spawned connections" ); } else { my $messages = $connection->getMessages(); @@ -162,7 +162,7 @@ while( 1 ) { .$connection->name() .' (' .$connection->fileno() - .")\n" + .")" ); my $messages = $connection->getMessages(); if ( defined($messages) ) { @@ -175,7 +175,7 @@ while( 1 ) { .$connection->fileno() .'), ' .int(keys(%spawned_connections)) - ." spawned connections\n" + ." spawned connections" ); $connection->close(); } @@ -206,7 +206,7 @@ while( 1 ) { 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. - $needsReload = 1; + push @needsReload, $monitor; next; } @@ -217,8 +217,8 @@ while( 1 ) { ] ); -#print( "$monitor->{Id}: S:$state, LE:$last_event\n" ); -#print( "$monitor->{Id}: mS:$monitor->{LastState}, mLE:$monitor->{LastEvent}\n" ); +#print( "$monitor->{Id}: S:$state, LE:$last_event" ); +#print( "$monitor->{Id}: mS:$monitor->{LastState}, mLE:$monitor->{LastEvent}" ); if ( $state == STATE_ALARM || $state == STATE_ALERT ) { # In alarm state if ( !defined($monitor->{LastEvent}) @@ -261,14 +261,14 @@ while( 1 ) { } if ( my @action_times = keys(%actions) ) { - Debug( "Checking for timed actions\n" ); + Debug( "Checking for timed actions" ); my $now = time(); foreach my $action_time ( sort( grep { $_ < $now } @action_times ) ) { - Info( "Found actions expiring at $action_time\n" ); + Info( "Found actions expiring at $action_time" ); foreach my $action ( @{$actions{$action_time}} ) { my $connection = $action->{connection}; my $message = $action->{message}; - Info( "Found action '$message'\n" ); + Info( "Found action '$message'" ); handleMessage( $connection, $message ); } delete( $actions{$action_time} ); @@ -293,23 +293,41 @@ while( 1 ) { } } -# If necessary reload monitors - if ( $needsReload || ((time() - $monitor_reload_time) > MONITOR_RELOAD_INTERVAL )) { + # Reload all monitors from the dB every MONITOR_RELOAD_INTERVAL + if ( (time() - $monitor_reload_time) > MONITOR_RELOAD_INTERVAL ) { foreach my $monitor ( values(%monitors) ) { -# Free up any used memory handle - zmMemInvalidate( $monitor ); + zmMemInvalidate( $monitor ); # Free up any used memory handle } loadMonitors(); - $needsReload = 0; + @needsReload = (); # We just reloaded all monitors so no need reload a specific monitor + # If we have NOT just reloaded all monitors, reload a specific monitor if its shared mem changed + } elsif ( @needsReload ) { + foreach my $monitor ( @needsReload ) { + loadMonitor($monitor); + } + @needsReload = (); } + # zmDbConnect will ping and reconnect if neccessary $dbh = zmDbConnect(); } # end while ( 1 ) -Info( "Trigger daemon exiting\n" ); +Info( "Trigger daemon exiting" ); exit; +sub loadMonitor { + my $monitor = shift; + + Debug( "Loading monitor $monitor" ); + zmMemInvalidate( $monitor ); + + if ( zmMemVerify( $monitor ) ) { # This will re-init shared memory + $monitor->{LastState} = zmGetMonitorState( $monitor ); + $monitor->{LastEvent} = zmGetLastEvent( $monitor ); + } +} + sub loadMonitors { - Debug( "Loading monitors\n" ); + Debug( "Loading monitors" ); $monitor_reload_time = time(); my %new_monitors = (); @@ -323,7 +341,7 @@ sub loadMonitors { my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID} : () ) or Fatal( "Can't execute: ".$sth->errstr() ); while( my $monitor = $sth->fetchrow_hashref() ) { - if ( zmMemVerify( $monitor ) ) { + if ( zmMemVerify( $monitor ) ) { # This will re-init shared memory $monitor->{LastState} = zmGetMonitorState( $monitor ); $monitor->{LastEvent} = zmGetLastEvent( $monitor ); } @@ -344,14 +362,14 @@ sub handleMessage { my $monitor = $monitors{$id}; if ( !$monitor ) { - Warning( "Can't find monitor '$id' for message '$message'\n" ); + Warning( "Can't find monitor '$id' for message '$message'" ); return; } - Debug( "Found monitor for id '$id'\n" ); + Debug( "Found monitor for id '$id'" ); next if ( !zmMemVerify( $monitor ) ); - Debug( "Handling action '$action'\n" ); + Debug( "Handling action '$action'" ); if ( $action =~ /^(enable|disable)(?:\+(\d+))?$/ ) { my $state = $1; my $delay = $2; @@ -362,7 +380,7 @@ sub handleMessage { } # Force a reload $monitor_reload_time = 0; - Info( "Set monitor to $state\n" ); + Info( "Set monitor to $state" ); if ( $delay ) { my $action_text = $id.'|'.( ($state eq 'enable') ? 'disable' @@ -379,7 +397,7 @@ sub handleMessage { if ( $trigger eq 'on' ) { zmTriggerEventOn( $monitor, $score, $cause, $text ); zmTriggerShowtext( $monitor, $showtext ) if defined($showtext); - Info( "Trigger '$trigger' '$cause'\n" ); + Info( "Trigger '$trigger' '$cause'" ); if ( $delay ) { my $action_text = $id.'|cancel'; handleDelay($delay, $connection, $action_text); @@ -392,7 +410,7 @@ sub handleMessage { my $last_event = zmGetLastEvent( $monitor ); zmTriggerEventOff( $monitor ); zmTriggerShowtext( $monitor, $showtext ) if defined($showtext); - Info( "Trigger '$trigger'\n" ); + Info( "Trigger '$trigger'" ); # Wait til it's finished while( zmInAlarm( $monitor ) && ($last_event == zmGetLastEvent( $monitor )) @@ -406,12 +424,12 @@ sub handleMessage { } elsif( $action eq 'cancel' ) { zmTriggerEventCancel( $monitor ); zmTriggerShowtext( $monitor, $showtext ) if defined($showtext); - Info( "Cancelled event\n" ); + Info( "Cancelled event" ); } elsif( $action eq 'show' ) { zmTriggerShowtext( $monitor, $showtext ); - Info( "Updated show text to '$showtext'\n" ); + Info( "Updated show text to '$showtext'" ); } else { - Error( "Unrecognised action '$action' in message '$message'\n" ); + Error( "Unrecognised action '$action' in message '$message'" ); } } # end sub handleMessage @@ -426,7 +444,7 @@ sub handleDelay { $action_array = $actions{$action_time} = []; } push( @$action_array, { connection=>$connection, message=>$action_text } ); - Debug( "Added timed event '$action_text', expires at $action_time (+$delay secs)\n" ); + Debug( "Added timed event '$action_text', expires at $action_time (+$delay secs)" ); } 1; __END__ diff --git a/src/zm_eventstream.cpp b/src/zm_eventstream.cpp index 416251089..9f7eae4ec 100644 --- a/src/zm_eventstream.cpp +++ b/src/zm_eventstream.cpp @@ -755,6 +755,12 @@ void EventStream::runStream() { // commands may set send_frame to true while(checkCommandQueue()); + // Update modified time of the socket .lock file so that we can tell which ones are stale. + if ( now.tv_sec - last_comm_update.tv_sec > 3600 ) { + touch(sock_path_lock); + last_comm_update = now; + } + if ( step != 0 ) curr_frame_id += step; diff --git a/src/zm_image.cpp b/src/zm_image.cpp index c4b76028e..491ae8470 100644 --- a/src/zm_image.cpp +++ b/src/zm_image.cpp @@ -1094,8 +1094,7 @@ bool Image::DecodeJpeg( const JOCTET *inbuffer, int inbuffer_size, unsigned int jpeg_read_header( cinfo, TRUE ); - if ( cinfo->num_components != 1 && cinfo->num_components != 3 ) - { + if ( cinfo->num_components != 1 && cinfo->num_components != 3 ) { Error( "Unexpected colours when reading jpeg image: %d", colours ); jpeg_abort_decompress( cinfo ); return( false ); @@ -1110,8 +1109,7 @@ bool Image::DecodeJpeg( const JOCTET *inbuffer, int inbuffer_size, unsigned int new_width = cinfo->image_width; new_height = cinfo->image_height; - if ( width != new_width || height != new_height ) - { + if ( width != new_width || height != new_height ) { Debug(9,"Image dimensions differ. Old: %ux%u New: %ux%u",width,height,new_width,new_height); } @@ -1173,7 +1171,7 @@ cinfo->out_color_space = JCS_RGB; } break; } - } + } // end switch if(WriteBuffer(new_width, new_height, new_colours, new_subpixelorder) == NULL) { Error("Failed requesting writeable buffer for reading JPEG image."); @@ -1185,21 +1183,18 @@ cinfo->out_color_space = JCS_RGB; JSAMPROW row_pointer; /* pointer to a single row */ int row_stride = width * colours; /* physical row width in buffer */ - while ( cinfo->output_scanline < cinfo->output_height ) - { + while ( cinfo->output_scanline < cinfo->output_height ) { row_pointer = &buffer[cinfo->output_scanline * row_stride]; jpeg_read_scanlines( cinfo, &row_pointer, 1 ); } jpeg_finish_decompress( cinfo ); - return( true ); + return true; } -bool Image::EncodeJpeg( JOCTET *outbuffer, int *outbuffer_size, int quality_override ) const -{ - if ( config.colour_jpeg_files && colours == ZM_COLOUR_GRAY8 ) - { +bool Image::EncodeJpeg( JOCTET *outbuffer, int *outbuffer_size, int quality_override ) const { + if ( config.colour_jpeg_files && colours == ZM_COLOUR_GRAY8 ) { Image temp_image( *this ); temp_image.Colourise(ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB ); return( temp_image.EncodeJpeg( outbuffer, outbuffer_size, quality_override ) ); @@ -1209,8 +1204,7 @@ bool Image::EncodeJpeg( JOCTET *outbuffer, int *outbuffer_size, int quality_over struct jpeg_compress_struct *cinfo = encodejpg_ccinfo[quality]; - if ( !cinfo ) - { + if ( !cinfo ) { cinfo = encodejpg_ccinfo[quality] = new jpeg_compress_struct; cinfo->err = jpeg_std_error( &jpg_err.pub ); jpg_err.pub.error_exit = zm_jpeg_error_exit; @@ -1276,7 +1270,7 @@ cinfo->out_color_space = JCS_RGB; } break; } - } + } // end switch jpeg_set_defaults( cinfo ); jpeg_set_quality( cinfo, quality, FALSE ); @@ -1286,44 +1280,38 @@ cinfo->out_color_space = JCS_RGB; JSAMPROW row_pointer; /* pointer to a single row */ int row_stride = cinfo->image_width * colours; /* physical row width in buffer */ - while ( cinfo->next_scanline < cinfo->image_height ) - { + while ( cinfo->next_scanline < cinfo->image_height ) { row_pointer = &buffer[cinfo->next_scanline * row_stride]; jpeg_write_scanlines( cinfo, &row_pointer, 1 ); } jpeg_finish_compress( cinfo ); - return( true ); + return true; } #if HAVE_ZLIB_H -bool Image::Unzip( const Bytef *inbuffer, unsigned long inbuffer_size ) -{ +bool Image::Unzip( const Bytef *inbuffer, unsigned long inbuffer_size ) { unsigned long zip_size = size; int result = uncompress( buffer, &zip_size, inbuffer, inbuffer_size ); - if ( result != Z_OK ) - { - Error( "Unzip failed, result = %d", result ); - return( false ); + if ( result != Z_OK ) { + Error("Unzip failed, result = %d", result); + return false; } - if ( zip_size != (unsigned int)size ) - { - Error( "Unzip failed, size mismatch, expected %d bytes, got %ld", size, zip_size ); - return( false ); + if ( zip_size != (unsigned int)size ) { + Error("Unzip failed, size mismatch, expected %d bytes, got %ld", size, zip_size); + return false; } - return( true ); + return true; } -bool Image::Zip( Bytef *outbuffer, unsigned long *outbuffer_size, int compression_level ) const -{ +bool Image::Zip( Bytef *outbuffer, unsigned long *outbuffer_size, int compression_level ) const { int result = compress2( outbuffer, outbuffer_size, buffer, size, compression_level ); - if ( result != Z_OK ) - { - Error( "Zip failed, result = %d", result ); - return( false ); + if ( result != Z_OK ) { + Error("Zip failed, result = %d", result); + return false; } - return( true ); + return true; } #endif // HAVE_ZLIB_H @@ -1337,11 +1325,11 @@ bool Image::Crop( unsigned int lo_x, unsigned int lo_y, unsigned int hi_x, unsig } if ( hi_x > (width-1) || ( hi_y > (height-1) ) ) { Error( "Attempting to crop outside image, %d,%d -> %d,%d not in %d,%d", lo_x, lo_y, hi_x, hi_y, width-1, height-1 ); - return( false ); + return false; } if ( new_width == width && new_height == height ) { - return( true ); + return true; } unsigned int new_size = new_width*new_height*colours; @@ -1356,24 +1344,22 @@ bool Image::Crop( unsigned int lo_x, unsigned int lo_y, unsigned int hi_x, unsig AssignDirect(new_width, new_height, colours, subpixelorder, new_buffer, new_size, ZM_BUFTYPE_ZM); - return( true ); + return true; } -bool Image::Crop( const Box &limits ) -{ - return( Crop( limits.LoX(), limits.LoY(), limits.HiX(), limits.HiY() ) ); +bool Image::Crop( const Box &limits ) { + return Crop( limits.LoX(), limits.LoY(), limits.HiX(), limits.HiY() ); } /* Far from complete */ /* Need to implement all possible of overlays possible */ -void Image::Overlay( const Image &image ) -{ - if ( !(width == image.width && height == image.height) ) - { - Panic( "Attempt to overlay different sized images, expected %dx%d, got %dx%d", width, height, image.width, image.height ); +void Image::Overlay( const Image &image ) { + if ( !(width == image.width && height == image.height) ) { + Panic("Attempt to overlay different sized images, expected %dx%d, got %dx%d", + width, height, image.width, image.height); } - if( colours == image.colours && subpixelorder != image.subpixelorder ) { + if ( colours == image.colours && subpixelorder != image.subpixelorder ) { Warning("Attempt to overlay images of same format but with different subpixel order."); } @@ -1383,10 +1369,8 @@ void Image::Overlay( const Image &image ) const uint8_t* psrc = image.buffer; uint8_t* pdest = buffer; - while( pdest < max_ptr ) - { - if ( *psrc ) - { + while( pdest < max_ptr ) { + if ( *psrc ) { *pdest = *psrc; } pdest++; @@ -1401,10 +1385,8 @@ void Image::Overlay( const Image &image ) const uint8_t* psrc = image.buffer; uint8_t* pdest = buffer; - while( pdest < max_ptr ) - { - if ( RED_PTR_RGBA(psrc) || GREEN_PTR_RGBA(psrc) || BLUE_PTR_RGBA(psrc) ) - { + while( pdest < max_ptr ) { + if ( RED_PTR_RGBA(psrc) || GREEN_PTR_RGBA(psrc) || BLUE_PTR_RGBA(psrc) ) { RED_PTR_RGBA(pdest) = RED_PTR_RGBA(psrc); GREEN_PTR_RGBA(pdest) = GREEN_PTR_RGBA(psrc); BLUE_PTR_RGBA(pdest) = BLUE_PTR_RGBA(psrc); @@ -1421,11 +1403,10 @@ void Image::Overlay( const Image &image ) const Rgb* prsrc = (Rgb*)image.buffer; Rgb* prdest = (Rgb*)buffer; - if(subpixelorder == ZM_SUBPIX_ORDER_RGBA || subpixelorder == ZM_SUBPIX_ORDER_BGRA) { + if ( subpixelorder == ZM_SUBPIX_ORDER_RGBA || subpixelorder == ZM_SUBPIX_ORDER_BGRA ) { /* RGB\BGR\RGBA\BGRA subpixel order - Alpha byte is last */ while (prdest < max_ptr) { - if ( RED_PTR_RGBA(prsrc) || GREEN_PTR_RGBA(prsrc) || BLUE_PTR_RGBA(prsrc) ) - { + if ( RED_PTR_RGBA(prsrc) || GREEN_PTR_RGBA(prsrc) || BLUE_PTR_RGBA(prsrc) ) { *prdest = *prsrc; } prdest++; @@ -1434,8 +1415,7 @@ void Image::Overlay( const Image &image ) } else { /* ABGR\ARGB subpixel order - Alpha byte is first */ while (prdest < max_ptr) { - if ( RED_PTR_ABGR(prsrc) || GREEN_PTR_ABGR(prsrc) || BLUE_PTR_ABGR(prsrc) ) - { + if ( RED_PTR_ABGR(prsrc) || GREEN_PTR_ABGR(prsrc) || BLUE_PTR_ABGR(prsrc) ) { *prdest = *prsrc; } prdest++; @@ -1449,10 +1429,8 @@ void Image::Overlay( const Image &image ) const uint8_t* psrc = image.buffer; uint8_t* pdest = buffer; - while( pdest < max_ptr ) - { - if ( *psrc ) - { + while( pdest < max_ptr ) { + if ( *psrc ) { RED_PTR_RGBA(pdest) = GREEN_PTR_RGBA(pdest) = BLUE_PTR_RGBA(pdest) = *psrc; } pdest += 3; @@ -1465,10 +1443,8 @@ void Image::Overlay( const Image &image ) const uint8_t* psrc = image.buffer; uint8_t* pdest = buffer; - while( pdest < max_ptr ) - { - if ( RED_PTR_RGBA(psrc) || GREEN_PTR_RGBA(psrc) || BLUE_PTR_RGBA(psrc) ) - { + while( pdest < max_ptr ) { + if ( RED_PTR_RGBA(psrc) || GREEN_PTR_RGBA(psrc) || BLUE_PTR_RGBA(psrc) ) { RED_PTR_RGBA(pdest) = RED_PTR_RGBA(psrc); GREEN_PTR_RGBA(pdest) = GREEN_PTR_RGBA(psrc); BLUE_PTR_RGBA(pdest) = BLUE_PTR_RGBA(psrc); @@ -1487,11 +1463,10 @@ void Image::Overlay( const Image &image ) Rgb* prdest = (Rgb*)buffer; const uint8_t* psrc = image.buffer; - if(subpixelorder == ZM_SUBPIX_ORDER_RGBA || subpixelorder == ZM_SUBPIX_ORDER_BGRA) { + if ( subpixelorder == ZM_SUBPIX_ORDER_RGBA || subpixelorder == ZM_SUBPIX_ORDER_BGRA ) { /* RGBA\BGRA subpixel order - Alpha byte is last */ - while (prdest < max_ptr) { - if ( *psrc ) - { + while ( prdest < max_ptr ) { + if ( *psrc ) { RED_PTR_RGBA(prdest) = GREEN_PTR_RGBA(prdest) = BLUE_PTR_RGBA(prdest) = *psrc; } prdest++; @@ -1499,9 +1474,8 @@ void Image::Overlay( const Image &image ) } } else { /* ABGR\ARGB subpixel order - Alpha byte is first */ - while (prdest < max_ptr) { - if ( *psrc ) - { + while ( prdest < max_ptr ) { + if ( *psrc ) { RED_PTR_ABGR(prdest) = GREEN_PTR_ABGR(prdest) = BLUE_PTR_ABGR(prdest) = *psrc; } prdest++; @@ -1519,11 +1493,10 @@ void Image::Overlay( const Image &image ) Rgb* prdest = (Rgb*)buffer; const Rgb* prsrc = (Rgb*)image.buffer; - if(image.subpixelorder == ZM_SUBPIX_ORDER_RGBA || image.subpixelorder == ZM_SUBPIX_ORDER_BGRA) { + if ( image.subpixelorder == ZM_SUBPIX_ORDER_RGBA || image.subpixelorder == ZM_SUBPIX_ORDER_BGRA ) { /* RGB\BGR\RGBA\BGRA subpixel order - Alpha byte is last */ - while (prdest < max_ptr) { - if ( RED_PTR_RGBA(prsrc) || GREEN_PTR_RGBA(prsrc) || BLUE_PTR_RGBA(prsrc) ) - { + while ( prdest < max_ptr ) { + if ( RED_PTR_RGBA(prsrc) || GREEN_PTR_RGBA(prsrc) || BLUE_PTR_RGBA(prsrc) ) { *prdest = *prsrc; } prdest++; @@ -1531,9 +1504,8 @@ void Image::Overlay( const Image &image ) } } else { /* ABGR\ARGB subpixel order - Alpha byte is first */ - while (prdest < max_ptr) { - if ( RED_PTR_ABGR(prsrc) || GREEN_PTR_ABGR(prsrc) || BLUE_PTR_ABGR(prsrc) ) - { + while ( prdest < max_ptr ) { + if ( RED_PTR_ABGR(prsrc) || GREEN_PTR_ABGR(prsrc) || BLUE_PTR_ABGR(prsrc) ) { *prdest = *prsrc; } prdest++; @@ -1545,61 +1517,49 @@ void Image::Overlay( const Image &image ) } /* RGB32 compatible: complete */ -void Image::Overlay( const Image &image, unsigned int x, unsigned int y ) -{ - if ( !(width < image.width || height < image.height) ) - { - Panic( "Attempt to overlay image too big for destination, %dx%d > %dx%d", image.width, image.height, width, height ); +void Image::Overlay( const Image &image, unsigned int x, unsigned int y ) { + if ( !(width < image.width || height < image.height) ) { + Panic("Attempt to overlay image too big for destination, %dx%d > %dx%d", + image.width, image.height, width, height ); } - if ( !(width < (x+image.width) || height < (y+image.height)) ) - { - Panic( "Attempt to overlay image outside of destination bounds, %dx%d @ %dx%d > %dx%d", image.width, image.height, x, y, width, height ); + if ( !(width < (x+image.width) || height < (y+image.height)) ) { + Panic("Attempt to overlay image outside of destination bounds, %dx%d @ %dx%d > %dx%d", + image.width, image.height, x, y, width, height ); } - if ( !(colours == image.colours) ) - { - Panic( "Attempt to partial overlay differently coloured images, expected %d, got %d", colours, image.colours ); + if ( !(colours == image.colours) ) { + Panic("Attempt to partial overlay differently coloured images, expected %d, got %d", + colours, image.colours); } unsigned int lo_x = x; unsigned int lo_y = y; unsigned int hi_x = (x+image.width)-1; unsigned int hi_y = (y+image.height-1); - if ( colours == ZM_COLOUR_GRAY8 ) - { + if ( colours == ZM_COLOUR_GRAY8 ) { const uint8_t *psrc = image.buffer; - for ( unsigned int y = lo_y; y <= hi_y; y++ ) - { + for ( unsigned int y = lo_y; y <= hi_y; y++ ) { uint8_t *pdest = &buffer[(y*width)+lo_x]; - for ( unsigned int x = lo_x; x <= hi_x; x++ ) - { + for ( unsigned int x = lo_x; x <= hi_x; x++ ) { *pdest++ = *psrc++; } } - } - else if ( colours == ZM_COLOUR_RGB24 ) - { + } else if ( colours == ZM_COLOUR_RGB24 ) { const uint8_t *psrc = image.buffer; - for ( unsigned int y = lo_y; y <= hi_y; y++ ) - { + for ( unsigned int y = lo_y; y <= hi_y; y++ ) { uint8_t *pdest = &buffer[colours*((y*width)+lo_x)]; - for ( unsigned int x = lo_x; x <= hi_x; x++ ) - { + for ( unsigned int x = lo_x; x <= hi_x; x++ ) { *pdest++ = *psrc++; *pdest++ = *psrc++; *pdest++ = *psrc++; } } - } - else if ( colours == ZM_COLOUR_RGB32 ) - { + } else if ( colours == ZM_COLOUR_RGB32 ) { const Rgb *psrc = (Rgb*)(image.buffer); - for ( unsigned int y = lo_y; y <= hi_y; y++ ) - { + for ( unsigned int y = lo_y; y <= hi_y; y++ ) { Rgb *pdest = (Rgb*)&buffer[((y*width)+lo_x)<<2]; - for ( unsigned int x = lo_x; x <= hi_x; x++ ) - { + for ( unsigned int x = lo_x; x <= hi_x; x++ ) { *pdest++ = *psrc++; } } @@ -1609,8 +1569,7 @@ void Image::Overlay( const Image &image, unsigned int x, unsigned int y ) } -void Image::Blend( const Image &image, int transparency ) -{ +void Image::Blend( const Image &image, int transparency ) { #ifdef ZM_IMAGE_PROFILING struct timespec start,end,diff; unsigned long long executetime; @@ -1618,12 +1577,16 @@ void Image::Blend( const Image &image, int transparency ) #endif uint8_t* new_buffer; - if ( !(width == image.width && height == image.height && colours == image.colours && subpixelorder == image.subpixelorder) ) - { - Panic( "Attempt to blend different sized images, expected %dx%dx%d %d, got %dx%dx%d %d", width, height, colours, subpixelorder, image.width, image.height, image.colours, image.subpixelorder ); + if ( !( + width == image.width && height == image.height + && colours == image.colours + && subpixelorder == image.subpixelorder + ) ) { + Panic("Attempt to blend different sized images, expected %dx%dx%d %d, got %dx%dx%d %d", + width, height, colours, subpixelorder, image.width, image.height, image.colours, image.subpixelorder ); } - if(transparency <= 0) + if ( transparency <= 0 ) return; new_buffer = AllocBuffer(size); @@ -1644,7 +1607,7 @@ void Image::Blend( const Image &image, int transparency ) Debug(5, "Blend: %u colours blended in %llu nanoseconds, %lu million colours/s\n",size,executetime,milpixels); #endif - AssignDirect( width, height, colours, subpixelorder, new_buffer, size, ZM_BUFTYPE_ZM); + AssignDirect(width, height, colours, subpixelorder, new_buffer, size, ZM_BUFTYPE_ZM); } Image *Image::Merge( unsigned int n_images, Image *images[] ) { @@ -1655,7 +1618,8 @@ Image *Image::Merge( unsigned int n_images, Image *images[] ) { unsigned int colours = images[0]->colours; for ( unsigned int i = 1; i < n_images; i++ ) { if ( !(width == images[i]->width && height == images[i]->height && colours == images[i]->colours) ) { - Panic( "Attempt to merge different sized images, expected %dx%dx%d, got %dx%dx%d, for image %d", width, height, colours, images[i]->width, images[i]->height, images[i]->colours, i ); + Panic("Attempt to merge different sized images, expected %dx%dx%d, got %dx%dx%d, for image %d", + width, height, colours, images[i]->width, images[i]->height, images[i]->colours, i ); } } @@ -1683,7 +1647,8 @@ Image *Image::Merge( unsigned int n_images, Image *images[], double weight ) { unsigned int colours = images[0]->colours; for ( unsigned int i = 1; i < n_images; i++ ) { if ( !(width == images[i]->width && height == images[i]->height && colours == images[i]->colours) ) { - Panic( "Attempt to merge different sized images, expected %dx%dx%d, got %dx%dx%d, for image %d", width, height, colours, images[i]->width, images[i]->height, images[i]->colours, i ); + Panic("Attempt to merge different sized images, expected %dx%dx%d, got %dx%dx%d, for image %d", + width, height, colours, images[i]->width, images[i]->height, images[i]->colours, i ); } } @@ -1703,8 +1668,7 @@ Image *Image::Merge( unsigned int n_images, Image *images[], double weight ) { return result; } -Image *Image::Highlight( unsigned int n_images, Image *images[], const Rgb threshold, const Rgb ref_colour ) -{ +Image *Image::Highlight( unsigned int n_images, Image *images[], const Rgb threshold, const Rgb ref_colour ) { if ( n_images == 1 ) return new Image(*images[0]); unsigned int width = images[0]->width; @@ -1712,7 +1676,8 @@ Image *Image::Highlight( unsigned int n_images, Image *images[], const Rgb thres unsigned int colours = images[0]->colours; for ( unsigned int i = 1; i < n_images; i++ ) { if ( !(width == images[i]->width && height == images[i]->height && colours == images[i]->colours) ) { - Panic( "Attempt to highlight different sized images, expected %dx%dx%d, got %dx%dx%d, for image %d", width, height, colours, images[i]->width, images[i]->height, images[i]->colours, i ); + Panic( "Attempt to highlight different sized images, expected %dx%dx%d, got %dx%dx%d, for image %d", + width, height, colours, images[i]->width, images[i]->height, images[i]->colours, i ); } } @@ -1738,26 +1703,25 @@ Image *Image::Highlight( unsigned int n_images, Image *images[], const Rgb thres pdest += 3; } } - return( result ); + return result; } /* New function to allow buffer re-using instead of allocationg memory for the delta image every time */ -void Image::Delta( const Image &image, Image* targetimage) const -{ +void Image::Delta( const Image &image, Image* targetimage) const { #ifdef ZM_IMAGE_PROFILING struct timespec start,end,diff; unsigned long long executetime; unsigned long milpixels; #endif - if ( !(width == image.width && height == image.height && colours == image.colours && subpixelorder == image.subpixelorder) ) - { - Panic( "Attempt to get delta of different sized images, expected %dx%dx%d %d, got %dx%dx%d %d", width, height, colours, subpixelorder, image.width, image.height, image.colours, image.subpixelorder); + if ( !(width == image.width && height == image.height && colours == image.colours && subpixelorder == image.subpixelorder) ) { + Panic( "Attempt to get delta of different sized images, expected %dx%dx%d %d, got %dx%dx%d %d", + width, height, colours, subpixelorder, image.width, image.height, image.colours, image.subpixelorder); } uint8_t *pdiff = targetimage->WriteBuffer(width, height, ZM_COLOUR_GRAY8, ZM_SUBPIX_ORDER_NONE); - if(pdiff == NULL) { + if ( pdiff == NULL ) { Panic("Failed requesting writeable buffer for storing the delta image"); } @@ -1847,34 +1811,24 @@ void Image::MaskPrivacy( const unsigned char *p_bitmask, const Rgb pixel_colour unsigned char *ptr = &buffer[0]; unsigned int i = 0; - for ( unsigned int y = 0; y < height; y++ ) - { - if ( colours == ZM_COLOUR_GRAY8 ) - { - for ( unsigned int x = 0; x < width; x++, ptr++ ) - { + for ( unsigned int y = 0; y < height; y++ ) { + if ( colours == ZM_COLOUR_GRAY8 ) { + for ( unsigned int x = 0; x < width; x++, ptr++ ) { if ( p_bitmask[i] ) *ptr = pixel_bw_col; i++; } - } - else if ( colours == ZM_COLOUR_RGB24 ) - { - for ( unsigned int x = 0; x < width; x++, ptr += colours ) - { - if ( p_bitmask[i] ) - { + } else if ( colours == ZM_COLOUR_RGB24 ) { + for ( unsigned int x = 0; x < width; x++, ptr += colours ) { + if ( p_bitmask[i] ) { RED_PTR_RGBA(ptr) = pixel_r_col; GREEN_PTR_RGBA(ptr) = pixel_g_col; BLUE_PTR_RGBA(ptr) = pixel_b_col; } i++; } - } - else if ( colours == ZM_COLOUR_RGB32 ) - { - for ( unsigned int x = 0; x < width; x++, ptr += colours ) - { + } else if ( colours == ZM_COLOUR_RGB32 ) { + for ( unsigned int x = 0; x < width; x++, ptr += colours ) { Rgb *temp_ptr = (Rgb*)ptr; if ( p_bitmask[i] ) *temp_ptr = pixel_rgb_col; @@ -1884,8 +1838,7 @@ void Image::MaskPrivacy( const unsigned char *p_bitmask, const Rgb pixel_colour Panic("MaskPrivacy called with unexpected colours: %d", colours); return; } - - } + } // end foreach y } /* RGB32 compatible: complete */ @@ -1917,8 +1870,7 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int if (size == 2) zm_text_bitmask = 0x8000; - while ( (index < text_len) && (line_len = strcspn( line, "\n" )) ) - { + while ( (index < text_len) && (line_len = strcspn( line, "\n" )) ) { unsigned int line_width = line_len * ZM_CHAR_WIDTH * size; @@ -1948,62 +1900,46 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int if ( hi_line_y > height ) hi_line_y = height; - if ( colours == ZM_COLOUR_GRAY8 ) - { + if ( colours == ZM_COLOUR_GRAY8 ) { unsigned char *ptr = &buffer[(lo_line_y*width)+lo_line_x]; - for ( unsigned int y = lo_line_y, r = 0; y < hi_line_y && r < (ZM_CHAR_HEIGHT * size); y++, r++, ptr += width ) - { + for ( unsigned int y = lo_line_y, r = 0; y < hi_line_y && r < (ZM_CHAR_HEIGHT * size); y++, r++, ptr += width ) { unsigned char *temp_ptr = ptr; - for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) - { + for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) { int f; if (size == 2) f = bigfontdata[(line[c] * ZM_CHAR_HEIGHT * size) + r]; else f = fontdata[(line[c] * ZM_CHAR_HEIGHT) + r]; - for ( unsigned int i = 0; i < (ZM_CHAR_WIDTH * size) && x < hi_line_x; i++, x++, temp_ptr++ ) - { - if ( f & (zm_text_bitmask >> i) ) - { + for ( unsigned int i = 0; i < (ZM_CHAR_WIDTH * size) && x < hi_line_x; i++, x++, temp_ptr++ ) { + if ( f & (zm_text_bitmask >> i) ) { if ( !fg_trans ) *temp_ptr = fg_bw_col; - } - else if ( !bg_trans ) - { + } else if ( !bg_trans ) { *temp_ptr = bg_bw_col; } } } } - } - else if ( colours == ZM_COLOUR_RGB24 ) - { + } else if ( colours == ZM_COLOUR_RGB24 ) { unsigned int wc = width * colours; unsigned char *ptr = &buffer[((lo_line_y*width)+lo_line_x)*colours]; - for ( unsigned int y = lo_line_y, r = 0; y < hi_line_y && r < (ZM_CHAR_HEIGHT * size); y++, r++, ptr += wc ) - { + for ( unsigned int y = lo_line_y, r = 0; y < hi_line_y && r < (ZM_CHAR_HEIGHT * size); y++, r++, ptr += wc ) { unsigned char *temp_ptr = ptr; - for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) - { + for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) { int f; if (size == 2) f = bigfontdata[(line[c] * ZM_CHAR_HEIGHT * size) + r]; else f = fontdata[(line[c] * ZM_CHAR_HEIGHT) + r]; - for ( unsigned int i = 0; i < (ZM_CHAR_WIDTH * size) && x < hi_line_x; i++, x++, temp_ptr += colours ) - { - if ( f & (zm_text_bitmask >> i) ) - { - if ( !fg_trans ) - { + for ( unsigned int i = 0; i < (ZM_CHAR_WIDTH * size) && x < hi_line_x; i++, x++, temp_ptr += colours ) { + if ( f & (zm_text_bitmask >> i) ) { + if ( !fg_trans ) { RED_PTR_RGBA(temp_ptr) = fg_r_col; GREEN_PTR_RGBA(temp_ptr) = fg_g_col; BLUE_PTR_RGBA(temp_ptr) = fg_b_col; } - } - else if ( !bg_trans ) - { + } else if ( !bg_trans ) { RED_PTR_RGBA(temp_ptr) = bg_r_col; GREEN_PTR_RGBA(temp_ptr) = bg_g_col; BLUE_PTR_RGBA(temp_ptr) = bg_b_col; @@ -2011,33 +1947,24 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int } } } - } - else if ( colours == ZM_COLOUR_RGB32 ) - { + } else if ( colours == ZM_COLOUR_RGB32 ) { unsigned int wc = width * colours; uint8_t *ptr = &buffer[((lo_line_y*width)+lo_line_x)<<2]; - for ( unsigned int y = lo_line_y, r = 0; y < hi_line_y && r < (ZM_CHAR_HEIGHT * size); y++, r++, ptr += wc ) - { + for ( unsigned int y = lo_line_y, r = 0; y < hi_line_y && r < (ZM_CHAR_HEIGHT * size); y++, r++, ptr += wc ) { Rgb* temp_ptr = (Rgb*)ptr; - for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) - { + for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) { int f; if (size == 2) f = bigfontdata[(line[c] * ZM_CHAR_HEIGHT * size) + r]; else f = fontdata[(line[c] * ZM_CHAR_HEIGHT) + r]; - for ( unsigned int i = 0; i < (ZM_CHAR_WIDTH * size) && x < hi_line_x; i++, x++, temp_ptr++ ) - { - if ( f & (zm_text_bitmask >> i) ) - { - if ( !fg_trans ) - { + for ( unsigned int i = 0; i < (ZM_CHAR_WIDTH * size) && x < hi_line_x; i++, x++, temp_ptr++ ) { + if ( f & (zm_text_bitmask >> i) ) { + if ( !fg_trans ) { *temp_ptr = fg_rgb_col; } - } - else if ( !bg_trans ) - { + } else if ( !bg_trans ) { *temp_ptr = bg_rgb_col; } } @@ -2050,8 +1977,7 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int } index += line_len; - while ( text[index] == '\n' ) - { + while ( text[index] == '\n' ) { index++; } line = text+index; @@ -2072,8 +1998,7 @@ void Image::Timestamp( const char *label, const time_t when, const Coord &coord, } /* RGB32 compatible: complete */ -void Image::Colourise(const unsigned int p_reqcolours, const unsigned int p_reqsubpixelorder) -{ +void Image::Colourise(const unsigned int p_reqcolours, const unsigned int p_reqsubpixelorder) { Debug(9, "Colourise: Req colours: %u Req subpixel order: %u Current colours: %u Current subpixel order: %u",p_reqcolours,p_reqsubpixelorder,colours,subpixelorder); if ( colours != ZM_COLOUR_GRAY8) { @@ -2090,9 +2015,9 @@ void Image::Colourise(const unsigned int p_reqcolours, const unsigned int p_reqs Rgb subpixel; Rgb newpixel; - if ( p_reqsubpixelorder == ZM_SUBPIX_ORDER_ABGR || p_reqsubpixelorder == ZM_SUBPIX_ORDER_ARGB) { + if ( p_reqsubpixelorder == ZM_SUBPIX_ORDER_ABGR || p_reqsubpixelorder == ZM_SUBPIX_ORDER_ARGB ) { /* ARGB\ABGR subpixel order. alpha byte is first (mem+0), so we need to shift the pixel left in the end */ - for(unsigned int i=0;iLo().Y():0; unsigned int hi_x = limits?limits->Hi().X():width-1; unsigned int hi_y = limits?limits->Hi().Y():height-1; - if ( colours == ZM_COLOUR_GRAY8 ) - { - for ( unsigned int y = lo_y; y <= hi_y; y++ ) - { + if ( colours == ZM_COLOUR_GRAY8 ) { + for ( unsigned int y = lo_y; y <= hi_y; y++ ) { unsigned char *p = &buffer[(y*width)+lo_x]; - for ( unsigned int x = lo_x; x <= hi_x; x++, p++) - { + for ( unsigned int x = lo_x; x <= hi_x; x++, p++) { *p = colour; } } - } - else if ( colours == ZM_COLOUR_RGB24 ) - { - for ( unsigned int y = lo_y; y <= hi_y; y++ ) - { + } else if ( colours == ZM_COLOUR_RGB24 ) { + for ( unsigned int y = lo_y; y <= hi_y; y++ ) { unsigned char *p = &buffer[colours*((y*width)+lo_x)]; - for ( unsigned int x = lo_x; x <= hi_x; x++, p += 3) - { + for ( unsigned int x = lo_x; x <= hi_x; x++, p += 3) { RED_PTR_RGBA(p) = RED_VAL_RGBA(colour); GREEN_PTR_RGBA(p) = GREEN_VAL_RGBA(colour); BLUE_PTR_RGBA(p) = BLUE_VAL_RGBA(colour); } } - } - else if ( colours == ZM_COLOUR_RGB32 ) /* RGB32 */ - { - for ( unsigned int y = lo_y; y <= (unsigned int)hi_y; y++ ) - { + } else if ( colours == ZM_COLOUR_RGB32 ) /* RGB32 */ { + for ( unsigned int y = lo_y; y <= (unsigned int)hi_y; y++ ) { Rgb *p = (Rgb*)&buffer[((y*width)+lo_x)<<2]; - for ( unsigned int x = lo_x; x <= (unsigned int)hi_x; x++, p++) - { + for ( unsigned int x = lo_x; x <= (unsigned int)hi_x; x++, p++) { /* Fast, copies the entire pixel in a single pass */ *p = colour; } @@ -2245,15 +2153,13 @@ void Image::Fill( Rgb colour, const Box *limits ) } /* RGB32 compatible: complete */ -void Image::Fill( Rgb colour, int density, const Box *limits ) -{ +void Image::Fill( Rgb colour, int density, const Box *limits ) { /* Allow the faster version to be used if density is not used (density=1) */ - if(density <= 1) + if ( density <= 1 ) return Fill(colour,limits); - if ( !(colours == ZM_COLOUR_GRAY8 || colours == ZM_COLOUR_RGB24 || colours == ZM_COLOUR_RGB32 ) ) - { - Panic( "Attempt to fill image with unexpected colours %d", colours ); + if ( !(colours == ZM_COLOUR_GRAY8 || colours == ZM_COLOUR_RGB24 || colours == ZM_COLOUR_RGB32 ) ) { + Panic("Attempt to fill image with unexpected colours %d", colours); } /* Convert the colour's RGBA subpixel order into the image's subpixel order */ @@ -2263,25 +2169,18 @@ void Image::Fill( Rgb colour, int density, const Box *limits ) unsigned int lo_y = limits?limits->Lo().Y():0; unsigned int hi_x = limits?limits->Hi().X():width-1; unsigned int hi_y = limits?limits->Hi().Y():height-1; - if ( colours == ZM_COLOUR_GRAY8 ) - { - for ( unsigned int y = lo_y; y <= hi_y; y++ ) - { + if ( colours == ZM_COLOUR_GRAY8 ) { + for ( unsigned int y = lo_y; y <= hi_y; y++ ) { unsigned char *p = &buffer[(y*width)+lo_x]; - for ( unsigned int x = lo_x; x <= hi_x; x++, p++) - { + for ( unsigned int x = lo_x; x <= hi_x; x++, p++) { if ( ( x == lo_x || x == hi_x || y == lo_y || y == hi_y ) || (!(x%density) && !(y%density) ) ) *p = colour; } } - } - else if ( colours == ZM_COLOUR_RGB24 ) - { - for ( unsigned int y = lo_y; y <= hi_y; y++ ) - { + } else if ( colours == ZM_COLOUR_RGB24 ) { + for ( unsigned int y = lo_y; y <= hi_y; y++ ) { unsigned char *p = &buffer[colours*((y*width)+lo_x)]; - for ( unsigned int x = lo_x; x <= hi_x; x++, p += 3) - { + for ( unsigned int x = lo_x; x <= hi_x; x++, p += 3) { if ( ( x == lo_x || x == hi_x || y == lo_y || y == hi_y ) || (!(x%density) && !(y%density) ) ) { RED_PTR_RGBA(p) = RED_VAL_RGBA(colour); GREEN_PTR_RGBA(p) = GREEN_VAL_RGBA(colour); @@ -2289,38 +2188,30 @@ void Image::Fill( Rgb colour, int density, const Box *limits ) } } } - } - else if ( colours == ZM_COLOUR_RGB32 ) /* RGB32 */ - { - for ( unsigned int y = lo_y; y <= hi_y; y++ ) - { + } else if ( colours == ZM_COLOUR_RGB32 ) /* RGB32 */ { + for ( unsigned int y = lo_y; y <= hi_y; y++ ) { Rgb* p = (Rgb*)&buffer[((y*width)+lo_x)<<2]; - for ( unsigned int x = lo_x; x <= hi_x; x++, p++) - { + for ( unsigned int x = lo_x; x <= hi_x; x++, p++) { if ( ( x == lo_x || x == hi_x || y == lo_y || y == hi_y ) || (!(x%density) && !(y%density) ) ) /* Fast, copies the entire pixel in a single pass */ *p = colour; } } } - } /* RGB32 compatible: complete */ -void Image::Outline( Rgb colour, const Polygon &polygon ) -{ - if ( !(colours == ZM_COLOUR_GRAY8 || colours == ZM_COLOUR_RGB24 || colours == ZM_COLOUR_RGB32 ) ) - { - Panic( "Attempt to outline image with unexpected colours %d", colours ); +void Image::Outline( Rgb colour, const Polygon &polygon ) { + if ( !(colours == ZM_COLOUR_GRAY8 || colours == ZM_COLOUR_RGB24 || colours == ZM_COLOUR_RGB32 ) ) { + Panic("Attempt to outline image with unexpected colours %d", colours); } /* Convert the colour's RGBA subpixel order into the image's subpixel order */ colour = rgb_convert(colour,subpixelorder); int n_coords = polygon.getNumCoords(); - for ( int j = 0, i = n_coords-1; j < n_coords; i = j++ ) - { + for ( int j = 0, i = n_coords-1; j < n_coords; i = j++ ) { const Coord &p1 = polygon.getCoord( i ); const Coord &p2 = polygon.getCoord( j ); @@ -2335,8 +2226,7 @@ void Image::Outline( Rgb colour, const Polygon &polygon ) double grad; //Debug( 9, "dx: %.2lf, dy: %.2lf", dx, dy ); - if ( fabs(dx) <= fabs(dy) ) - { + if ( fabs(dx) <= fabs(dy) ) { //Debug( 9, "dx <= dy" ); if ( y1 != y2 ) grad = dx/dy; @@ -2346,35 +2236,25 @@ void Image::Outline( Rgb colour, const Polygon &polygon ) double x; int y, yinc = (y1 dy" ); if ( x1 != x2 ) grad = dy/dx; @@ -2385,42 +2265,31 @@ void Image::Outline( Rgb colour, const Polygon &polygon ) double y; int x, xinc = (x1= Logger::DEBUG9 ) - { - for ( int i = 0; i < n_global_edges; i++ ) - { + if ( logLevel() >= Logger::DEBUG9 ) { + for ( int i = 0; i < n_global_edges; i++ ) { Debug( 9, "%d: min_y: %d, max_y:%d, min_x:%.2f, 1/m:%.2f", i, global_edges[i].min_y, global_edges[i].max_y, global_edges[i].min_x, global_edges[i]._1_m ); } } @@ -2468,60 +2334,46 @@ void Image::Fill( Rgb colour, int density, const Polygon &polygon ) int n_active_edges = 0; Edge active_edges[n_global_edges]; int y = global_edges[0].min_y; - do - { - for ( int i = 0; i < n_global_edges; i++ ) - { - if ( global_edges[i].min_y == y ) - { - Debug( 9, "Moving global edge" ); + do { + for ( int i = 0; i < n_global_edges; i++ ) { + if ( global_edges[i].min_y == y ) { + Debug(9, "Moving global edge"); active_edges[n_active_edges++] = global_edges[i]; - if ( i < (n_global_edges-1) ) - { + if ( i < (n_global_edges-1) ) { //memcpy( &global_edges[i], &global_edges[i+1], sizeof(*global_edges)*(n_global_edges-i) ); memmove( &global_edges[i], &global_edges[i+1], sizeof(*global_edges)*(n_global_edges-i) ); i--; } n_global_edges--; - } - else - { + } else { break; } } qsort( active_edges, n_active_edges, sizeof(*active_edges), Edge::CompareX ); #ifndef ZM_DBG_OFF - if ( logLevel() >= Logger::DEBUG9 ) - { - for ( int i = 0; i < n_active_edges; i++ ) - { + if ( logLevel() >= Logger::DEBUG9 ) { + for ( int i = 0; i < n_active_edges; i++ ) { Debug( 9, "%d - %d: min_y: %d, max_y:%d, min_x:%.2f, 1/m:%.2f", y, i, active_edges[i].min_y, active_edges[i].max_y, active_edges[i].min_x, active_edges[i]._1_m ); } } #endif - if ( !(y%density) ) - { + if ( !(y%density) ) { //Debug( 9, "%d", y ); - for ( int i = 0; i < n_active_edges; ) - { + for ( int i = 0; i < n_active_edges; ) { int lo_x = int(round(active_edges[i++].min_x)); int hi_x = int(round(active_edges[i++].min_x)); - if( colours == ZM_COLOUR_GRAY8 ) { + if ( colours == ZM_COLOUR_GRAY8 ) { unsigned char *p = &buffer[(y*width)+lo_x]; - for ( int x = lo_x; x <= hi_x; x++, p++) - { - if ( !(x%density) ) - { + for ( int x = lo_x; x <= hi_x; x++, p++) { + if ( !(x%density) ) { //Debug( 9, " %d", x ); *p = colour; } } - } else if( colours == ZM_COLOUR_RGB24 ) { + } else if ( colours == ZM_COLOUR_RGB24 ) { unsigned char *p = &buffer[colours*((y*width)+lo_x)]; - for ( int x = lo_x; x <= hi_x; x++, p += 3) - { - if ( !(x%density) ) - { + for ( int x = lo_x; x <= hi_x; x++, p += 3) { + if ( !(x%density) ) { RED_PTR_RGBA(p) = RED_VAL_RGBA(colour); GREEN_PTR_RGBA(p) = GREEN_VAL_RGBA(colour); BLUE_PTR_RGBA(p) = BLUE_VAL_RGBA(colour); @@ -2529,10 +2381,8 @@ void Image::Fill( Rgb colour, int density, const Polygon &polygon ) } } else if( colours == ZM_COLOUR_RGB32 ) { Rgb *p = (Rgb*)&buffer[((y*width)+lo_x)<<2]; - for ( int x = lo_x; x <= hi_x; x++, p++) - { - if ( !(x%density) ) - { + for ( int x = lo_x; x <= hi_x; x++, p++) { + if ( !(x%density) ) { /* Fast, copies the entire pixel in a single pass */ *p = colour; } @@ -2541,43 +2391,35 @@ void Image::Fill( Rgb colour, int density, const Polygon &polygon ) } } y++; - for ( int i = n_active_edges-1; i >= 0; i-- ) - { - if ( y >= active_edges[i].max_y ) // Or >= as per sheets - { + for ( int i = n_active_edges-1; i >= 0; i-- ) { + if ( y >= active_edges[i].max_y ) { + // Or >= as per sheets Debug( 9, "Deleting active_edge" ); - if ( i < (n_active_edges-1) ) - { + if ( i < (n_active_edges-1) ) { //memcpy( &active_edges[i], &active_edges[i+1], sizeof(*active_edges)*(n_active_edges-i) ); memmove( &active_edges[i], &active_edges[i+1], sizeof(*active_edges)*(n_active_edges-i) ); } n_active_edges--; - } - else - { + } else { active_edges[i].min_x += active_edges[i]._1_m; } } } while ( n_global_edges || n_active_edges ); } -void Image::Fill( Rgb colour, const Polygon &polygon ) -{ +void Image::Fill( Rgb colour, const Polygon &polygon ) { Fill( colour, 1, polygon ); } /* RGB32 compatible: complete */ -void Image::Rotate( int angle ) -{ +void Image::Rotate( int angle ) { angle %= 360; - if ( !angle ) - { + if ( !angle ) { return; } - if ( angle%90 ) - { + if ( angle%90 ) { return; } @@ -2708,39 +2550,28 @@ void Image::Flip( bool leftright ) { unsigned char *d_ptr = flip_buffer; unsigned char *max_d_ptr = flip_buffer + size; - if ( colours == ZM_COLOUR_GRAY8 ) - { - while( d_ptr < max_d_ptr ) - { - for ( unsigned int j = 0; j < width; j++ ) - { + if ( colours == ZM_COLOUR_GRAY8 ) { + while( d_ptr < max_d_ptr ) { + for ( unsigned int j = 0; j < width; j++ ) { s_ptr--; *d_ptr++ = *s_ptr; } s_ptr += line_bytes2; } - } - else if ( colours == ZM_COLOUR_RGB32 ) - { + } else if ( colours == ZM_COLOUR_RGB32 ) { Rgb* s_rptr = (Rgb*)s_ptr; Rgb* d_rptr = (Rgb*)flip_buffer; Rgb* max_d_rptr = (Rgb*)max_d_ptr; - while( d_rptr < max_d_rptr ) - { - for ( unsigned int j = 0; j < width; j++ ) - { + while( d_rptr < max_d_rptr ) { + for ( unsigned int j = 0; j < width; j++ ) { s_rptr--; *d_rptr++ = *s_rptr; } s_rptr += width * 2; } - } - else /* Assume RGB24 */ - { - while( d_ptr < max_d_ptr ) - { - for ( unsigned int j = 0; j < width; j++ ) - { + } else /* Assume RGB24 */ { + while( d_ptr < max_d_ptr ) { + for ( unsigned int j = 0; j < width; j++ ) { s_ptr -= 3; *d_ptr++ = *s_ptr; *d_ptr++ = *(s_ptr+1); @@ -2749,15 +2580,12 @@ void Image::Flip( bool leftright ) { s_ptr += line_bytes2; } } - } - else - { + } else { // Vertical flip, top to bottom unsigned char *s_ptr = buffer+(height*line_bytes); unsigned char *d_ptr = flip_buffer; - while( s_ptr > buffer ) - { + while( s_ptr > buffer ) { s_ptr -= line_bytes; memcpy( d_ptr, s_ptr, line_bytes ); d_ptr += line_bytes; @@ -2768,15 +2596,12 @@ void Image::Flip( bool leftright ) { } -void Image::Scale( unsigned int factor ) -{ - if ( !factor ) - { +void Image::Scale( unsigned int factor ) { + if ( !factor ) { Error( "Bogus scale factor %d found", factor ); return; } - if ( factor == ZM_SCALE_BASE ) - { + if ( factor == ZM_SCALE_BASE ) { return; } @@ -2787,8 +2612,7 @@ void Image::Scale( unsigned int factor ) uint8_t* scale_buffer = AllocBuffer(scale_buffer_size); - if ( factor > ZM_SCALE_BASE ) - { + if ( factor > ZM_SCALE_BASE ) { unsigned char *pd = scale_buffer; unsigned int wc = width*colours; unsigned int nwc = new_width*colours; @@ -2796,20 +2620,16 @@ void Image::Scale( unsigned int factor ) unsigned int last_h_index = 0; unsigned int last_w_index = 0; unsigned int h_index; - for ( unsigned int y = 0; y < height; y++ ) - { + for ( unsigned int y = 0; y < height; y++ ) { unsigned char *ps = &buffer[y*wc]; unsigned int w_count = ZM_SCALE_BASE/2; unsigned int w_index; last_w_index = 0; - for ( unsigned int x = 0; x < width; x++ ) - { + for ( unsigned int x = 0; x < width; x++ ) { w_count += factor; w_index = w_count/ZM_SCALE_BASE; - for (unsigned int f = last_w_index; f < w_index; f++ ) - { - for ( unsigned int c = 0; c < colours; c++ ) - { + for (unsigned int f = last_w_index; f < w_index; f++ ) { + for ( unsigned int c = 0; c < colours; c++ ) { *pd++ = *(ps+c); } } @@ -2818,8 +2638,7 @@ void Image::Scale( unsigned int factor ) } h_count += factor; h_index = h_count/ZM_SCALE_BASE; - for ( unsigned int f = last_h_index+1; f < h_index; f++ ) - { + for ( unsigned int f = last_h_index+1; f < h_index; f++ ) { memcpy( pd, pd-nwc, nwc ); pd += nwc; } @@ -2827,9 +2646,7 @@ void Image::Scale( unsigned int factor ) } new_width = last_w_index; new_height = last_h_index; - } - else - { + } else { unsigned char *pd = scale_buffer; unsigned int wc = width*colours; unsigned int xstart = factor/2; @@ -2838,31 +2655,24 @@ void Image::Scale( unsigned int factor ) unsigned int last_h_index = 0; unsigned int last_w_index = 0; unsigned int h_index; - for ( unsigned int y = 0; y < (unsigned int)height; y++ ) - { + for ( unsigned int y = 0; y < (unsigned int)height; y++ ) { h_count += factor; h_index = h_count/ZM_SCALE_BASE; - if ( h_index > last_h_index ) - { + if ( h_index > last_h_index ) { unsigned int w_count = xstart; unsigned int w_index; last_w_index = 0; unsigned char *ps = &buffer[y*wc]; - for ( unsigned int x = 0; x < (unsigned int)width; x++ ) - { + for ( unsigned int x = 0; x < (unsigned int)width; x++ ) { w_count += factor; w_index = w_count/ZM_SCALE_BASE; - if ( w_index > last_w_index ) - { - for ( unsigned int c = 0; c < colours; c++ ) - { + if ( w_index > last_w_index ) { + for ( unsigned int c = 0; c < colours; c++ ) { *pd++ = *ps++; } - } - else - { + } else { ps += colours; } last_w_index = w_index; @@ -2878,29 +2688,23 @@ void Image::Scale( unsigned int factor ) } -void Image::Deinterlace_Discard() -{ +void Image::Deinterlace_Discard() { /* Simple deinterlacing. Copy the even lines into the odd lines */ - if ( colours == ZM_COLOUR_GRAY8 ) - { + if ( colours == ZM_COLOUR_GRAY8 ) { const uint8_t *psrc; uint8_t *pdest; - for (unsigned int y = 0; y < (unsigned int)height; y += 2) - { + for (unsigned int y = 0; y < (unsigned int)height; y += 2) { psrc = buffer + (y * width); pdest = buffer + ((y+1) * width); for (unsigned int x = 0; x < (unsigned int)width; x++) { *pdest++ = *psrc++; } } - } - else if ( colours == ZM_COLOUR_RGB24 ) - { + } else if ( colours == ZM_COLOUR_RGB24 ) { const uint8_t *psrc; uint8_t *pdest; - for (unsigned int y = 0; y < (unsigned int)height; y += 2) - { + for (unsigned int y = 0; y < (unsigned int)height; y += 2) { psrc = buffer + ((y * width) * 3); pdest = buffer + (((y+1) * width) * 3); for (unsigned int x = 0; x < (unsigned int)width; x++) { @@ -2909,13 +2713,10 @@ void Image::Deinterlace_Discard() *pdest++ = *psrc++; } } - } - else if ( colours == ZM_COLOUR_RGB32 ) - { + } else if ( colours == ZM_COLOUR_RGB32 ) { const Rgb *psrc; Rgb *pdest; - for (unsigned int y = 0; y < (unsigned int)height; y += 2) - { + for (unsigned int y = 0; y < (unsigned int)height; y += 2) { psrc = (Rgb*)(buffer + ((y * width) << 2)); pdest = (Rgb*)(buffer + (((y+1) * width) << 2)); for (unsigned int x = 0; x < (unsigned int)width; x++) { @@ -2928,17 +2729,14 @@ void Image::Deinterlace_Discard() } -void Image::Deinterlace_Linear() -{ +void Image::Deinterlace_Linear() { /* Simple deinterlacing. The odd lines are average of the line above and line below */ const uint8_t *pbelow, *pabove; uint8_t *pcurrent; - if ( colours == ZM_COLOUR_GRAY8 ) - { - for (unsigned int y = 1; y < (unsigned int)(height-1); y += 2) - { + if ( colours == ZM_COLOUR_GRAY8 ) { + for (unsigned int y = 1; y < (unsigned int)(height-1); y += 2) { pabove = buffer + ((y-1) * width); pbelow = buffer + ((y+1) * width); pcurrent = buffer + (y * width); @@ -2952,11 +2750,8 @@ void Image::Deinterlace_Linear() for (unsigned int x = 0; x < (unsigned int)width; x++) { *pcurrent++ = *pabove++; } - } - else if ( colours == ZM_COLOUR_RGB24 ) - { - for (unsigned int y = 1; y < (unsigned int)(height-1); y += 2) - { + } else if ( colours == ZM_COLOUR_RGB24 ) { + for (unsigned int y = 1; y < (unsigned int)(height-1); y += 2) { pabove = buffer + (((y-1) * width) * 3); pbelow = buffer + (((y+1) * width) * 3); pcurrent = buffer + ((y * width) * 3); @@ -2974,11 +2769,8 @@ void Image::Deinterlace_Linear() *pcurrent++ = *pabove++; *pcurrent++ = *pabove++; } - } - else if ( colours == ZM_COLOUR_RGB32 ) - { - for (unsigned int y = 1; y < (unsigned int)(height-1); y += 2) - { + } else if ( colours == ZM_COLOUR_RGB32 ) { + for (unsigned int y = 1; y < (unsigned int)(height-1); y += 2) { pabove = buffer + (((y-1) * width) << 2); pbelow = buffer + (((y+1) * width) << 2); pcurrent = buffer + ((y * width) << 2); @@ -3004,16 +2796,13 @@ void Image::Deinterlace_Linear() } -void Image::Deinterlace_Blend() -{ +void Image::Deinterlace_Blend() { /* Simple deinterlacing. Blend the fields together. 50% blend */ uint8_t *pabove, *pcurrent; - if ( colours == ZM_COLOUR_GRAY8 ) - { - for (unsigned int y = 1; y < (unsigned int)height; y += 2) - { + if ( colours == ZM_COLOUR_GRAY8 ) { + for (unsigned int y = 1; y < (unsigned int)height; y += 2) { pabove = buffer + ((y-1) * width); pcurrent = buffer + (y * width); for (unsigned int x = 0; x < (unsigned int)width; x++) { @@ -3021,11 +2810,8 @@ void Image::Deinterlace_Blend() *pcurrent++ = *pabove++; } } - } - else if ( colours == ZM_COLOUR_RGB24 ) - { - for (unsigned int y = 1; y < (unsigned int)height; y += 2) - { + } else if ( colours == ZM_COLOUR_RGB24 ) { + for (unsigned int y = 1; y < (unsigned int)height; y += 2) { pabove = buffer + (((y-1) * width) * 3); pcurrent = buffer + ((y * width) * 3); for (unsigned int x = 0; x < (unsigned int)width; x++) { @@ -3037,11 +2823,8 @@ void Image::Deinterlace_Blend() *pcurrent++ = *pabove++; } } - } - else if ( colours == ZM_COLOUR_RGB32 ) - { - for (unsigned int y = 1; y < (unsigned int)height; y += 2) - { + } else if ( colours == ZM_COLOUR_RGB32 ) { + for (unsigned int y = 1; y < (unsigned int)height; y += 2) { pabove = buffer + (((y-1) * width) << 2); pcurrent = buffer + ((y * width) << 2); for (unsigned int x = 0; x < (unsigned int)width; x++) { @@ -3061,8 +2844,7 @@ void Image::Deinterlace_Blend() } -void Image::Deinterlace_Blend_CustomRatio(int divider) -{ +void Image::Deinterlace_Blend_CustomRatio(int divider) { /* Simple deinterlacing. Blend the fields together at a custom ratio. */ /* 1 = 50% blending */ /* 2 = 25% blending */ @@ -3076,10 +2858,8 @@ void Image::Deinterlace_Blend_CustomRatio(int divider) Error("Deinterlace called with invalid blend ratio"); } - if ( colours == ZM_COLOUR_GRAY8 ) - { - for (unsigned int y = 1; y < (unsigned int)height; y += 2) - { + if ( colours == ZM_COLOUR_GRAY8 ) { + for (unsigned int y = 1; y < (unsigned int)height; y += 2) { pabove = buffer + ((y-1) * width); pcurrent = buffer + (y * width); for (unsigned int x = 0; x < (unsigned int)width; x++) { @@ -3089,11 +2869,8 @@ void Image::Deinterlace_Blend_CustomRatio(int divider) *pabove++ = subpix2; } } - } - else if ( colours == ZM_COLOUR_RGB24 ) - { - for (unsigned int y = 1; y < (unsigned int)height; y += 2) - { + } else if ( colours == ZM_COLOUR_RGB24 ) { + for (unsigned int y = 1; y < (unsigned int)height; y += 2) { pabove = buffer + (((y-1) * width) * 3); pcurrent = buffer + ((y * width) * 3); for (unsigned int x = 0; x < (unsigned int)width; x++) { @@ -3111,11 +2888,8 @@ void Image::Deinterlace_Blend_CustomRatio(int divider) *pabove++ = subpix2; } } - } - else if ( colours == ZM_COLOUR_RGB32 ) - { - for (unsigned int y = 1; y < (unsigned int)height; y += 2) - { + } else if ( colours == ZM_COLOUR_RGB32 ) { + for (unsigned int y = 1; y < (unsigned int)height; y += 2) { pabove = buffer + (((y-1) * width) << 2); pcurrent = buffer + ((y * width) << 2); for (unsigned int x = 0; x < (unsigned int)width; x++) { @@ -3203,25 +2977,25 @@ void sse2_fastblend(const uint8_t* col1, const uint8_t* col2, uint8_t* result, u static uint32_t clearmask = 0; static double current_blendpercent = 0.0; - if(current_blendpercent != blendpercent) { + if ( current_blendpercent != blendpercent ) { /* Attempt to match the blending percent to one of the possible values */ - if(blendpercent < 2.34375) { + if ( blendpercent < 2.34375 ) { // 1.5625% blending divider = 6; clearmask = 0x03030303; - } else if(blendpercent < 4.6875) { + } else if ( blendpercent < 4.6875 ) { // 3.125% blending divider = 5; clearmask = 0x07070707; - } else if(blendpercent < 9.375) { + } else if ( blendpercent < 9.375 ) { // 6.25% blending divider = 4; clearmask = 0x0F0F0F0F; - } else if(blendpercent < 18.75) { + } else if ( blendpercent < 18.75 ) { // 12.5% blending divider = 3; clearmask = 0x1F1F1F1F; - } else if(blendpercent < 37.5) { + } else if ( blendpercent < 37.5 ) { // 25% blending divider = 2; clearmask = 0x3F3F3F3F; @@ -3267,21 +3041,21 @@ __attribute__((noinline)) void std_fastblend(const uint8_t* col1, const uint8_t* static double current_blendpercent = 0.0; const uint8_t* const max_ptr = result + count; - if(current_blendpercent != blendpercent) { + if ( current_blendpercent != blendpercent ) { /* Attempt to match the blending percent to one of the possible values */ - if(blendpercent < 2.34375) { + if ( blendpercent < 2.34375 ) { // 1.5625% blending divider = 6; - } else if(blendpercent < 4.6875) { + } else if ( blendpercent < 4.6875 ) { // 3.125% blending divider = 5; - } else if(blendpercent < 9.375) { + } else if ( blendpercent < 9.375 ) { // 6.25% blending divider = 4; - } else if(blendpercent < 18.75) { + } else if ( blendpercent < 18.75 ) { // 12.5% blending divider = 3; - } else if(blendpercent < 37.5) { + } else if ( blendpercent < 37.5 ) { // 25% blending divider = 2; } else { @@ -3291,8 +3065,7 @@ __attribute__((noinline)) void std_fastblend(const uint8_t* col1, const uint8_t* current_blendpercent = blendpercent; } - - while(result < max_ptr) { + while ( result < max_ptr ) { result[0] = ((col2[0] - col1[0])>>divider) + col1[0]; result[1] = ((col2[1] - col1[1])>>divider) + col1[1]; result[2] = ((col2[2] - col1[2])>>divider) + col1[2]; @@ -3317,11 +3090,11 @@ __attribute__((noinline)) void std_fastblend(const uint8_t* col1, const uint8_t* } /* FastBlend Neon for AArch32 */ -#if (defined(__arm__) && !defined(ZM_STRIP_NEON)) +#if (defined(__arm__) && defined(__ARM_PCS_VFP) && !defined(ZM_STRIP_NEON)) __attribute__((noinline,__target__("fpu=neon"))) #endif void neon32_armv7_fastblend(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count, double blendpercent) { -#if (defined(__arm__) && !defined(ZM_STRIP_NEON)) +#if (defined(__arm__) && defined(__ARM_PCS_VFP) && !defined(ZM_STRIP_NEON)) static int8_t divider = 0; static double current_blendpercent = 0.0; @@ -3490,9 +3263,8 @@ __attribute__((noinline)) void std_blend(const uint8_t* col1, const uint8_t* col double opacity = 1.0 - divide; const uint8_t* const max_ptr = result + count; - while(result < max_ptr) { + while ( result < max_ptr ) { *result++ = (*col1++ * opacity) + (*col2++ * divide); - } } @@ -3708,11 +3480,11 @@ __attribute__((noinline)) void std_delta8_abgr(const uint8_t* col1, const uint8_ } /* Grayscale Neon for AArch32 */ -#if (defined(__arm__) && !defined(ZM_STRIP_NEON)) +#if (defined(__arm__) && defined(__ARM_PCS_VFP) && !defined(ZM_STRIP_NEON)) __attribute__((noinline,__target__("fpu=neon"))) #endif void neon32_armv7_delta8_gray8(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { -#if (defined(__arm__) && !defined(ZM_STRIP_NEON)) +#if (defined(__arm__) && defined(__ARM_PCS_VFP) && !defined(ZM_STRIP_NEON)) /* Q0(D0,D1) = col1+0 */ /* Q1(D2,D3) = col1+16 */ @@ -3784,11 +3556,11 @@ __attribute__((noinline)) void neon64_armv8_delta8_gray8(const uint8_t* col1, co } /* RGB32 Neon for AArch32 */ -#if (defined(__arm__) && !defined(ZM_STRIP_NEON)) +#if (defined(__arm__) && defined(__ARM_PCS_VFP) && !defined(ZM_STRIP_NEON)) __attribute__((noinline,__target__("fpu=neon"))) #endif void neon32_armv7_delta8_rgb32(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count, uint32_t multiplier) { -#if (defined(__arm__) && !defined(ZM_STRIP_NEON)) +#if (defined(__arm__) && defined(__ARM_PCS_VFP) && !defined(ZM_STRIP_NEON)) /* Q0(D0,D1) = col1+0 */ /* Q1(D2,D3) = col1+16 */ @@ -4692,8 +4464,7 @@ __attribute__((noinline)) void zm_convert_rgb565_rgba(const uint8_t* col1, uint8 /************************************************* DEINTERLACE FUNCTIONS *************************************************/ /* Grayscale */ -__attribute__((noinline)) void std_deinterlace_4field_gray8(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) -{ +__attribute__((noinline)) void std_deinterlace_4field_gray8(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) { uint8_t *pcurrent, *pabove, *pncurrent, *pnabove, *pbelow; const uint8_t* const max_ptr = col1 + (width*(height-1)); const uint8_t *max_ptr2; @@ -4703,8 +4474,7 @@ __attribute__((noinline)) void std_deinterlace_4field_gray8(uint8_t* col1, uint8 pabove = col1; pnabove = col2; pbelow = col1 + (width*2); - while(pcurrent < max_ptr) - { + while(pcurrent < max_ptr) { max_ptr2 = pcurrent + width; while(pcurrent < max_ptr2) { if((unsigned int)((abs(*pnabove - *pabove) + abs(*pncurrent - *pcurrent)) >> 1) >= threshold) { @@ -4721,7 +4491,6 @@ __attribute__((noinline)) void std_deinterlace_4field_gray8(uint8_t* col1, uint8 pabove += width; pnabove += width; pbelow += width; - } /* Special case for the last line */ @@ -4738,8 +4507,7 @@ __attribute__((noinline)) void std_deinterlace_4field_gray8(uint8_t* col1, uint8 } /* RGB */ -__attribute__((noinline)) void std_deinterlace_4field_rgb(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) -{ +__attribute__((noinline)) void std_deinterlace_4field_rgb(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) { uint8_t *pcurrent, *pabove, *pncurrent, *pnabove, *pbelow; const unsigned int row_width = width*3; const uint8_t* const max_ptr = col1 + (row_width * (height-1)); @@ -4752,8 +4520,7 @@ __attribute__((noinline)) void std_deinterlace_4field_rgb(uint8_t* col1, uint8_t pabove = col1; pnabove = col2; pbelow = col1 + ((width*2)*3); - while(pcurrent < max_ptr) - { + while(pcurrent < max_ptr) { max_ptr2 = pcurrent + row_width; while(pcurrent < max_ptr2) { r = abs(pnabove[0] - pabove[0]); @@ -4780,7 +4547,6 @@ __attribute__((noinline)) void std_deinterlace_4field_rgb(uint8_t* col1, uint8_t pabove += row_width; pnabove += row_width; pbelow += row_width; - } /* Special case for the last line */ @@ -4807,8 +4573,7 @@ __attribute__((noinline)) void std_deinterlace_4field_rgb(uint8_t* col1, uint8_t } /* BGR */ -__attribute__((noinline)) void std_deinterlace_4field_bgr(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) -{ +__attribute__((noinline)) void std_deinterlace_4field_bgr(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) { uint8_t *pcurrent, *pabove, *pncurrent, *pnabove, *pbelow; const unsigned int row_width = width*3; const uint8_t* const max_ptr = col1 + (row_width * (height-1)); @@ -4821,8 +4586,7 @@ __attribute__((noinline)) void std_deinterlace_4field_bgr(uint8_t* col1, uint8_t pabove = col1; pnabove = col2; pbelow = col1 + ((width*2)*3); - while(pcurrent < max_ptr) - { + while(pcurrent < max_ptr) { max_ptr2 = pcurrent + row_width; while(pcurrent < max_ptr2) { b = abs(pnabove[0] - pabove[0]); @@ -4876,8 +4640,7 @@ __attribute__((noinline)) void std_deinterlace_4field_bgr(uint8_t* col1, uint8_t } /* RGBA */ -__attribute__((noinline)) void std_deinterlace_4field_rgba(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) -{ +__attribute__((noinline)) void std_deinterlace_4field_rgba(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) { uint8_t *pcurrent, *pabove, *pncurrent, *pnabove, *pbelow; const unsigned int row_width = width*4; const uint8_t* const max_ptr = col1 + (row_width * (height-1)); @@ -4890,8 +4653,7 @@ __attribute__((noinline)) void std_deinterlace_4field_rgba(uint8_t* col1, uint8_ pabove = col1; pnabove = col2; pbelow = col1 + (row_width*2); - while(pcurrent < max_ptr) - { + while(pcurrent < max_ptr) { max_ptr2 = pcurrent + row_width; while(pcurrent < max_ptr2) { r = abs(pnabove[0] - pabove[0]); @@ -4918,7 +4680,6 @@ __attribute__((noinline)) void std_deinterlace_4field_rgba(uint8_t* col1, uint8_ pabove += row_width; pnabove += row_width; pbelow += row_width; - } /* Special case for the last line */ @@ -4945,8 +4706,7 @@ __attribute__((noinline)) void std_deinterlace_4field_rgba(uint8_t* col1, uint8_ } /* BGRA */ -__attribute__((noinline)) void std_deinterlace_4field_bgra(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) -{ +__attribute__((noinline)) void std_deinterlace_4field_bgra(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) { uint8_t *pcurrent, *pabove, *pncurrent, *pnabove, *pbelow; const unsigned int row_width = width*4; const uint8_t* const max_ptr = col1 + (row_width * (height-1)); @@ -4959,8 +4719,7 @@ __attribute__((noinline)) void std_deinterlace_4field_bgra(uint8_t* col1, uint8_ pabove = col1; pnabove = col2; pbelow = col1 + (row_width*2); - while(pcurrent < max_ptr) - { + while(pcurrent < max_ptr) { max_ptr2 = pcurrent + row_width; while(pcurrent < max_ptr2) { b = abs(pnabove[0] - pabove[0]); @@ -4987,7 +4746,6 @@ __attribute__((noinline)) void std_deinterlace_4field_bgra(uint8_t* col1, uint8_ pabove += row_width; pnabove += row_width; pbelow += row_width; - } /* Special case for the last line */ @@ -5014,8 +4772,7 @@ __attribute__((noinline)) void std_deinterlace_4field_bgra(uint8_t* col1, uint8_ } /* ARGB */ -__attribute__((noinline)) void std_deinterlace_4field_argb(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) -{ +__attribute__((noinline)) void std_deinterlace_4field_argb(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) { uint8_t *pcurrent, *pabove, *pncurrent, *pnabove, *pbelow; const unsigned int row_width = width*4; const uint8_t* const max_ptr = col1 + (row_width * (height-1)); @@ -5028,8 +4785,7 @@ __attribute__((noinline)) void std_deinterlace_4field_argb(uint8_t* col1, uint8_ pabove = col1; pnabove = col2; pbelow = col1 + (row_width*2); - while(pcurrent < max_ptr) - { + while(pcurrent < max_ptr) { max_ptr2 = pcurrent + row_width; while(pcurrent < max_ptr2) { r = abs(pnabove[1] - pabove[1]); @@ -5056,7 +4812,6 @@ __attribute__((noinline)) void std_deinterlace_4field_argb(uint8_t* col1, uint8_ pabove += row_width; pnabove += row_width; pbelow += row_width; - } /* Special case for the last line */ @@ -5083,8 +4838,7 @@ __attribute__((noinline)) void std_deinterlace_4field_argb(uint8_t* col1, uint8_ } /* ABGR */ -__attribute__((noinline)) void std_deinterlace_4field_abgr(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) -{ +__attribute__((noinline)) void std_deinterlace_4field_abgr(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) { uint8_t *pcurrent, *pabove, *pncurrent, *pnabove, *pbelow; const unsigned int row_width = width*4; const uint8_t* const max_ptr = col1 + (row_width * (height-1)); @@ -5097,8 +4851,7 @@ __attribute__((noinline)) void std_deinterlace_4field_abgr(uint8_t* col1, uint8_ pabove = col1; pnabove = col2; pbelow = col1 + (row_width*2); - while(pcurrent < max_ptr) - { + while(pcurrent < max_ptr) { max_ptr2 = pcurrent + row_width; while(pcurrent < max_ptr2) { b = abs(pnabove[1] - pabove[1]); diff --git a/src/zm_image.h b/src/zm_image.h index dafd067f1..66e7ef32e 100644 --- a/src/zm_image.h +++ b/src/zm_image.h @@ -274,6 +274,7 @@ void std_delta8_rgba(const uint8_t* col1, const uint8_t* col2, uint8_t* result, void std_delta8_bgra(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count); void std_delta8_argb(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count); void std_delta8_abgr(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count); + void neon32_armv7_delta8_gray8(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count); void neon32_armv7_delta8_rgba(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count); void neon32_armv7_delta8_bgra(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count); diff --git a/src/zm_monitorstream.cpp b/src/zm_monitorstream.cpp index 56396e256..65e9af579 100644 --- a/src/zm_monitorstream.cpp +++ b/src/zm_monitorstream.cpp @@ -531,6 +531,12 @@ void MonitorStream::runStream() { Debug(2, "Have checking command Queue for connkey: %d", connkey ); got_command = true; } + // Update modified time of the socket .lock file so that we can tell which ones are stale. + if ( now.tv_sec - last_comm_update.tv_sec > 3600 ) { + touch(sock_path_lock); + last_comm_update = now; + } + } if ( paused ) { diff --git a/src/zm_stream.cpp b/src/zm_stream.cpp index c9f74622a..7ab844d78 100644 --- a/src/zm_stream.cpp +++ b/src/zm_stream.cpp @@ -332,6 +332,8 @@ void StreamBase::openComms() { snprintf(rem_sock_path, sizeof(rem_sock_path), "%s/zms-%06dw.sock", staticConfig.PATH_SOCKS.c_str(), connkey); strncpy(rem_addr.sun_path, rem_sock_path, sizeof(rem_addr.sun_path)-1); rem_addr.sun_family = AF_UNIX; + + gettimeofday(&last_comm_update, NULL); } // end if connKey > 0 Debug(2, "comms open"); } // end void StreamBase::openComms() diff --git a/src/zm_stream.h b/src/zm_stream.h index 4e8343b8c..f9364bbef 100644 --- a/src/zm_stream.h +++ b/src/zm_stream.h @@ -85,6 +85,7 @@ protected: int step; struct timeval now; + struct timeval last_comm_update; double base_fps; double effective_fps; diff --git a/src/zm_utils.cpp b/src/zm_utils.cpp index 94c681dd5..adc10cf8e 100644 --- a/src/zm_utils.cpp +++ b/src/zm_utils.cpp @@ -24,6 +24,8 @@ #include #include #include +#include /* Definition of AT_* constants */ +#include #if defined(__arm__) #include #endif @@ -414,3 +416,22 @@ Warning("ZM Compiled without LIBCURL. UriDecoding not implemented."); #endif } +void touch(const char *pathname) { + int fd = open(pathname, + O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK, + 0666); + if ( fd < 0 ) { + // Couldn't open that path. + Error("Couldn't open() path \"%s in touch", pathname); + return; + } + int rc = utimensat(AT_FDCWD, + pathname, + nullptr, + 0); + if ( rc ) { + Error("Couldn't utimensat() path %s in touch", pathname); + return; + } +} + diff --git a/src/zm_utils.h b/src/zm_utils.h index 8352edecb..d1340cf4b 100644 --- a/src/zm_utils.h +++ b/src/zm_utils.h @@ -63,5 +63,5 @@ extern unsigned int neonversion; char *timeval_to_string( struct timeval tv ); std::string UriDecode( const std::string &encoded ); - +void touch( const char *pathname ); #endif // ZM_UTILS_H diff --git a/utils/do_debian_package.sh b/utils/do_debian_package.sh index 82ded025a..71f1ec460 100755 --- a/utils/do_debian_package.sh +++ b/utils/do_debian_package.sh @@ -23,7 +23,7 @@ case $i in shift # past argument=value ;; -d=*|--distro=*) - DISTRO="${i#*=}" + DISTROS="${i#*=}" shift # past argument=value ;; -i=*|--interactive=*) @@ -74,11 +74,15 @@ else echo "Doing $TYPE build" fi; -if [ "$DISTRO" == "" ]; then - DISTRO=`lsb_release -a 2>/dev/null | grep Codename | awk '{print $2}'`; - echo "Defaulting to $DISTRO for distribution"; +if [ "$DISTROS" == "" ]; then + if [ "$RELEASE" != "" ]; then + DISTROS="xenial,bionic,trusty" + else + DISTROS=`lsb_release -a 2>/dev/null | grep Codename | awk '{print $2}'`; + fi; + echo "Defaulting to $DISTROS for distribution"; else - echo "Building for $DISTRO"; + echo "Building for $DISTROS"; fi; # Release is a special mode... it uploads to the release ppa and cannot have a snapshot @@ -116,6 +120,18 @@ else fi; fi +PPA=""; +if [ "$RELEASE" != "" ]; then + # We need to use our official tarball for the original source, so grab it and overwrite our generated one. + IFS='.' read -r -a VERSION <<< "$RELEASE" + PPA="ppa:iconnor/zoneminder-${VERSION[0]}.${VERSION[1]}" +else + if [ "$BRANCH" == "" ]; then + PPA="ppa:iconnor/zoneminder-master"; + else + PPA="ppa:iconnor/zoneminder-$BRANCH"; + fi; +fi; # Instead of cloning from github each time, if we have a fork lying around, update it and pull from there instead. if [ ! -d "${GITHUB_FORK}_zoneminder_release" ]; then @@ -154,6 +170,11 @@ if [ "$SNAPSHOT" != "stable" ] && [ "$SNAPSHOT" != "" ]; then fi; DIRECTORY="zoneminder_$VERSION"; +if [ -d "$DIRECTORY.orig" ]; then + echo "$DIRECTORY.orig already exists. Please delete it." + exit 0; +fi; + echo "Doing $TYPE release $DIRECTORY"; mv "${GITHUB_FORK}_zoneminder_release" "$DIRECTORY.orig"; if [ $? -ne 0 ]; then @@ -161,6 +182,7 @@ if [ $? -ne 0 ]; then echo "Setting up build dir failed."; exit $?; fi; + cd "$DIRECTORY.orig"; # Init submodules @@ -172,36 +194,45 @@ rm -rf .git rm .gitignore cd ../ -tar zcf $DIRECTORY.orig.tar.gz $DIRECTORY.orig -cd $DIRECTORY.orig +if [ ! -e "$DIRECTORY.orig.tar.gz" ]; then + tar zcf $DIRECTORY.orig.tar.gz $DIRECTORY.orig +fi; -# Generate Changlog -if [ "$DISTRO" == "trusty" ] || [ "$DISTRO" == "precise" ]; then - mv distros/ubuntu1204 debian -else - if [ "$DISTRO" == "wheezy" ]; then - mv distros/debian debian - else - mv distros/ubuntu1604 debian +IFS=',' ;for DISTRO in `echo "$DISTROS"`; do + echo "Generating package for $DISTRO"; + cd $DIRECTORY.orig + + if [ -e "debian" ]; then + rm -rf debian fi; -fi; -if [ "$DEBEMAIL" != "" ] && [ "$DEBFULLNAME" != "" ]; then - AUTHOR="$DEBFULLNAME <$DEBEMAIL>" -else - if [ -z `hostname -d` ] ; then - AUTHOR="`getent passwd $USER | cut -d ':' -f 5 | cut -d ',' -f 1` <`whoami`@`hostname`.local>" + # Generate Changlog + if [ "$DISTRO" == "trusty" ] || [ "$DISTRO" == "precise" ]; then + cp -Rpd distros/ubuntu1204 debian + else + if [ "$DISTRO" == "wheezy" ]; then + cp -Rpd distros/debian debian + else + cp -Rpd distros/ubuntu1604 debian + fi; + fi; + + if [ "$DEBEMAIL" != "" ] && [ "$DEBFULLNAME" != "" ]; then + AUTHOR="$DEBFULLNAME <$DEBEMAIL>" else - AUTHOR="`getent passwd $USER | cut -d ':' -f 5 | cut -d ',' -f 1` <`whoami`@`hostname`>" + if [ -z `hostname -d` ] ; then + AUTHOR="`getent passwd $USER | cut -d ':' -f 5 | cut -d ',' -f 1` <`whoami`@`hostname`.local>" + else + AUTHOR="`getent passwd $USER | cut -d ':' -f 5 | cut -d ',' -f 1` <`whoami`@`hostname`>" + fi fi -fi -if [ "$URGENCY" = "" ]; then - URGENCY="medium" -fi; + if [ "$URGENCY" = "" ]; then + URGENCY="medium" + fi; -if [ "$SNAPSHOT" == "stable" ]; then -cat < debian/changelog + if [ "$SNAPSHOT" == "stable" ]; then + cat < debian/changelog zoneminder ($VERSION-$DISTRO${PACKAGE_VERSION}) $DISTRO; urgency=$URGENCY * Release $VERSION @@ -209,59 +240,92 @@ zoneminder ($VERSION-$DISTRO${PACKAGE_VERSION}) $DISTRO; urgency=$URGENCY -- $AUTHOR $DATE EOF -cat < debian/NEWS + cat < debian/NEWS zoneminder ($VERSION-$DISTRO${PACKAGE_VERSION}) $DISTRO; urgency=$URGENCY * Release $VERSION -- $AUTHOR $DATE EOF -else -cat < debian/changelog + else + cat < debian/changelog zoneminder ($VERSION-$DISTRO${PACKAGE_VERSION}) $DISTRO; urgency=$URGENCY * -- $AUTHOR $DATE EOF -cat < debian/changelog + cat < debian/changelog zoneminder ($VERSION-$DISTRO${PACKAGE_VERSION}) $DISTRO; urgency=$URGENCY * -- $AUTHOR $DATE EOF -fi; + fi; -if [ $TYPE == "binary" ]; then - # Auto-install all ZoneMinder's depedencies using the Debian control file - sudo apt-get install devscripts equivs - sudo mk-build-deps -ir ./debian/control - echo "Status: $?" - DEBUILD=debuild -else - if [ $TYPE == "local" ]; then + if [ $TYPE == "binary" ]; then # Auto-install all ZoneMinder's depedencies using the Debian control file sudo apt-get install devscripts equivs sudo mk-build-deps -ir ./debian/control echo "Status: $?" - DEBUILD="debuild -i -us -uc -b" - else - # Source build, don't need build depends. - DEBUILD="debuild -S -sa" + DEBUILD=debuild + else + if [ $TYPE == "local" ]; then + # Auto-install all ZoneMinder's depedencies using the Debian control file + sudo apt-get install devscripts equivs + sudo mk-build-deps -ir ./debian/control + echo "Status: $?" + DEBUILD="debuild -i -us -uc -b" + else + # Source build, don't need build depends. + DEBUILD="debuild -S -sa" + fi; + fi; + if [ "$DEBSIGN_KEYID" != "" ]; then + DEBUILD="$DEBUILD -k$DEBSIGN_KEYID" + fi + eval $DEBUILD + if [ $? -ne 0 ]; then + echo "Error status code is: $?" + echo "Build failed."; + exit $?; fi; -fi; -if [ "$DEBSIGN_KEYID" != "" ]; then - DEBUILD="$DEBUILD -k$DEBSIGN_KEYID" -fi -$DEBUILD -if [ $? -ne 0 ]; then -echo "Error status code is: $?" - echo "Build failed."; - exit $?; -fi; -cd ../ + cd ../ + + if [ $TYPE == "binary" ]; then + if [ "$INTERACTIVE" != "no" ]; then + read -p "Not doing dput since it's a binary release. Do you want to install it? (y/N)" + if [[ $REPLY == [yY] ]]; then + sudo dpkg -i $DIRECTORY*.deb + fi; + read -p "Do you want to upload this binary to zmrepo? (y/N)" + if [[ $REPLY == [yY] ]]; then + if [ "$RELEASE" != "" ]; then + scp "zoneminder_${VERSION}-${DISTRO}"* "zoneminder-doc_${VERSION}-${DISTRO}"* "zoneminder-dbg_${VERSION}-${DISTRO}"* "zoneminder_${VERSION}.orig.tar.gz" "zmrepo@zmrepo.connortechnology.com:debian/stable/mini-dinstall/incoming/" + else + if [ "$BRANCH" == "" ]; then + scp "zoneminder_${VERSION}-${DISTRO}"* "zoneminder-doc_${VERSION}-${DISTRO}"* "zoneminder-dbg_${VERSION}-${DISTRO}"* "zoneminder_${VERSION}.orig.tar.gz" "zmrepo@zmrepo.connortechnology.com:debian/master/mini-dinstall/incoming/" + else + scp "$DIRECTORY-${DISTRO}"* "zoneminder-doc_${VERSION}-${DISTRO}"* "zoneminder-dbg_${VERSION}-${DISTRO}"* "zoneminder_${VERSION}.orig.tar.gz" "zmrepo@zmrepo.connortechnology.com:debian/${BRANCH}/mini-dinstall/incoming/" + fi; + fi; + fi; + fi; + else + SC="zoneminder_${VERSION}-${DISTRO}${PACKAGE_VERSION}_source.changes"; + + dput="Y"; + if [ "$INTERACTIVE" != "no" ]; then + read -p "Ready to dput $SC to $PPA ? Y/N..."; + if [[ "$REPLY" == [yY] ]]; then + dput $PPA $SC + fi; + fi; + fi; +done; # foreach distro + if [ "$INTERACTIVE" != "no" ]; then read -p "Do you want to keep the checked out version of Zoneminder (incase you want to modify it later) [y/N]" [[ $REPLY == [yY] ]] && { mv "$DIRECTORY.orig" zoneminder_release; echo "The checked out copy is preserved in zoneminder_release"; } || { rm -fr "$DIRECTORY.orig"; echo "The checked out copy has been deleted"; } @@ -270,53 +334,4 @@ else rm -fr "$DIRECTORY.orig"; echo "The checked out copy has been deleted"; fi -if [ $TYPE == "binary" ]; then - if [ "$INTERACTIVE" != "no" ]; then - read -p "Not doing dput since it's a binary release. Do you want to install it? (y/N)" - if [[ $REPLY == [yY] ]]; then - sudo dpkg -i $DIRECTORY*.deb - fi; - read -p "Do you want to upload this binary to zmrepo? (y/N)" - if [[ $REPLY == [yY] ]]; then - if [ "$RELEASE" != "" ]; then - scp "zoneminder_${VERSION}-${DISTRO}"* "zoneminder-doc_${VERSION}-${DISTRO}"* "zoneminder-dbg_${VERSION}-${DISTRO}"* "zoneminder_${VERSION}.orig.tar.gz" "zmrepo@zmrepo.connortechnology.com:debian/stable/mini-dinstall/incoming/" - else - if [ "$BRANCH" == "" ]; then - scp "zoneminder_${VERSION}-${DISTRO}"* "zoneminder-doc_${VERSION}-${DISTRO}"* "zoneminder-dbg_${VERSION}-${DISTRO}"* "zoneminder_${VERSION}.orig.tar.gz" "zmrepo@zmrepo.connortechnology.com:debian/master/mini-dinstall/incoming/" - else - scp "$DIRECTORY-${DISTRO}"* "zoneminder-doc_${VERSION}-${DISTRO}"* "zoneminder-dbg_${VERSION}-${DISTRO}"* "zoneminder_${VERSION}.orig.tar.gz" "zmrepo@zmrepo.connortechnology.com:debian/${BRANCH}/mini-dinstall/incoming/" - fi; - fi; - fi; - fi; -else - SC="zoneminder_${VERSION}-${DISTRO}${PACKAGE_VERSION}_source.changes"; - PPA=""; - if [ "$RELEASE" != "" ]; then - # We need to use our official tarball for the original source, so grab it and overwrite our generated one. - if [ ! -e "$RELEASE.tar.gz" ]; then - echo "Grabbing official source tarball from github." - wget "https://github.com/ZoneMinder/zoneminder/archive/$RELEASE.tar.gz" - fi; - echo "Overwriting generated zoneminder_${VERSION}.orig.tar.gz with source tarball from github"; - cp "$RELEASE.tar.gz" "zoneminder_${VERSION}.orig.tar.gz" - IFS='.' read -r -a VERSION <<< "$RELEASE" - PPA="ppa:iconnor/zoneminder-${VERSION[0]}.${VERSION[1]}" - else - if [ "$BRANCH" == "" ]; then - PPA="ppa:iconnor/zoneminder-master"; - else - PPA="ppa:iconnor/zoneminder-$BRANCH"; - fi; - fi; - - dput="Y"; - if [ "$INTERACTIVE" != "no" ]; then - read -p "Ready to dput $SC to $PPA ? Y/N..."; - if [[ "$REPLY" == [yY] ]]; then - dput $PPA $SC - fi; - fi; -fi; - diff --git a/version b/version index 96cd6ee1e..c78d39b8e 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.32.1 +1.32.2 diff --git a/web/api/app/Controller/HostController.php b/web/api/app/Controller/HostController.php index 6dd9e5211..017bce798 100644 --- a/web/api/app/Controller/HostController.php +++ b/web/api/app/Controller/HostController.php @@ -69,7 +69,7 @@ class HostController extends AppController { $this->Session->read('user'); # this is needed for command line/curl to recognize a session $zmAuthRelay = $this->Config->find('first',array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_AUTH_RELAY')))['Config']['Value']; if ( $zmAuthRelay == 'hashed' ) { - $zmAuthHashIps= $this->Config->find('first',array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_AUTH_HASH_IPS')))['Config']['Value']; + $zmAuthHashIps = $this->Config->find('first',array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_AUTH_HASH_IPS')))['Config']['Value']; $credentials = 'auth='.generateAuthHash($zmAuthHashIps); } else if ( $zmAuthRelay == 'plain' ) { // user will need to append the store password here @@ -101,27 +101,25 @@ class HostController extends AppController { $this->loadModel('Monitor'); // If $mid is passed, see if it is valid - if ($mid) { - if (!$this->Monitor->exists($mid)) { + if ( $mid ) { + if ( !$this->Monitor->exists($mid) ) { throw new NotFoundException(__('Invalid monitor')); } } - $zm_dir_events = $this->Config->find('list', array( - 'conditions' => array('Name' => 'ZM_DIR_EVENTS'), - 'fields' => array('Name', 'Value') - )); - $zm_dir_events = $zm_dir_events['ZM_DIR_EVENTS' ]; + $zm_dir_events = ZM_DIR_EVENTS; // Test to see if $zm_dir_events is relative or absolute - if ('/' === "" || strrpos($zm_dir_events, '/', -strlen($zm_dir_events)) !== TRUE) { + #if ('/' === "" || strrpos($zm_dir_events, '/', -strlen($zm_dir_events)) !== TRUE) { + if ( substr($zm_dir_events, 0, 1) != '/' ) { // relative - so add the full path - $zm_dir_events = Configure::read('ZM_PATH_WEB') . '/' . $zm_dir_events; + $zm_dir_events = ZM_PATH_WEB . '/' . $zm_dir_events; } - if ($mid) { + if ( $mid ) { // Get disk usage for $mid - $usage = shell_exec ("du -sh0 $zm_dir_events/$mid | awk '{print $1}'"); + Logger::Debug("Executing du -s0 $zm_dir_events/$mid | awk '{print $1}'"); + $usage = shell_exec("du -s0 $zm_dir_events/$mid | awk '{print $1}'"); } else { $monitors = $this->Monitor->find('all', array( 'fields' => array('Id', 'Name', 'WebColour') diff --git a/web/api/app/Controller/StorageController.php b/web/api/app/Controller/StorageController.php new file mode 100644 index 000000000..325dea4dd --- /dev/null +++ b/web/api/app/Controller/StorageController.php @@ -0,0 +1,157 @@ +Storage->recursive = 0; + + $options = ''; + $storage_areas = $this->Storage->find('all',$options); + $this->set(array( + 'storage' => $storage_areas, + '_serialize' => array('storage') + )); + } + +/** + * view method + * + * @throws NotFoundException + * @param string $id + * @return void + */ + public function view($id = null) { + $this->Storage->recursive = 0; + if (!$this->Storage->exists($id)) { + throw new NotFoundException(__('Invalid storage area')); + } + $restricted = ''; + + $options = array('conditions' => array( + array('Storage.' . $this->Storage->primaryKey => $id), + $restricted + ) + ); + $storage = $this->Storage->find('first', $options); + $this->set(array( + 'storage' => $storage, + '_serialize' => array('storage') + )); + } + +/** + * add method + * + * @return void + */ + public function add() { + if ( $this->request->is('post') ) { + + global $user; + $canEdit = (!$user) || ($user['System'] == 'Edit'); + if ( !$canEdit ) { + throw new UnauthorizedException(__('Insufficient privileges')); + return; + } + + $this->Storage->create(); + if ( $this->Storage->save($this->request->data) ) { + # Might be nice to send it a start request + #$this->daemonControl($this->Storage->id, 'start', $this->request->data); + return $this->flash(__('The storage area has been saved.'), array('action' => 'index')); + } + } + } + +/** + * edit method + * + * @throws NotFoundException + * @param string $id + * @return void + */ + public function edit($id = null) { + $this->Storage->id = $id; + + global $user; + $canEdit = (!$user) || ($user['System'] == 'Edit'); + if ( !$canEdit ) { + throw new UnauthorizedException(__('Insufficient privileges')); + return; + } + + if ( !$this->Storage->exists($id) ) { + throw new NotFoundException(__('Invalid storage area')); + } + if ( $this->Storage->save($this->request->data) ) { + $message = 'Saved'; + } else { + $message = 'Error'; + } + + $this->set(array( + 'message' => $message, + '_serialize' => array('message') + )); + // - restart this storage area after change + #$this->daemonControl($this->Storage->id, 'restart', $this->request->data); + } + +/** + * delete method + * + * @throws NotFoundException + * @param string $id + * @return void + */ + public function delete($id = null) { + global $user; + $canEdit = (!$user) || ($user['System'] == 'Edit'); + if ( !$canEdit ) { + throw new UnauthorizedException(__('Insufficient privileges')); + return; + } + + $this->Storage->id = $id; + if ( !$this->Storage->exists() ) { + throw new NotFoundException(__('Invalid storage area')); + } + $this->request->allowMethod('post', 'delete'); + + #$this->daemonControl($this->Storage->id, 'stop'); + + if ( $this->Storage->delete() ) { + return $this->flash(__('The storage area has been deleted.'), array('action' => 'index')); + } else { + return $this->flash(__('The storage area could not be deleted. Please, try again.'), array('action' => 'index')); + } + } +} diff --git a/web/css/overlay.css b/web/css/overlay.css index de7ed5ecb..28714ebf5 100644 --- a/web/css/overlay.css +++ b/web/css/overlay.css @@ -19,7 +19,7 @@ .overlayHeader { float: left; - background-color: #dddddd; + background-color: #853131; width: 100%; border-bottom: 1px solid #666666; color: black; diff --git a/web/includes/Frame.php b/web/includes/Frame.php index 82c9d2daf..74a18ef59 100644 --- a/web/includes/Frame.php +++ b/web/includes/Frame.php @@ -55,7 +55,7 @@ class Frame { #return $_SERVER['PHP_SELF'].'?view=image&fid='.$this->{'Id'}.'&show='.$show.'&filename='.$this->Event()->MonitorId().'_'.$this->{'EventId'}.'_'.$this->{'FrameId'}.'.jpg'; } // end function getImageSrc - public static function find( $parameters = array(), $limit = NULL ) { + public static function find( $parameters = array(), $options = NULL ) { $sql = 'SELECT * FROM Frames'; $values = array(); if ( sizeof($parameters) ) { @@ -65,17 +65,23 @@ class Frame { ) ); $values = array_values( $parameters ); } - if ( $limit ) { - if ( is_integer( $limit ) or ctype_digit( $limit ) ) { - $sql .= ' LIMIT ' . $limit; - } else { - $backTrace = debug_backtrace(); - $file = $backTrace[1]['file']; - $line = $backTrace[1]['line']; - Error("Invalid value for limit($limit) passed to Frame::find from $file:$line"); - return array(); - } - } + if ( $options ) { + if ( isset($options['order']) ) { + $sql .= ' ORDER BY ' . $options['order']; + } + if ( isset($options['limit']) ) { + if ( is_integer($options['limit']) or ctype_digit($options['limit']) ) { + $sql .= ' LIMIT ' . $options['limit']; + } else { + $backTrace = debug_backtrace(); + $file = $backTrace[1]['file']; + $line = $backTrace[1]['line']; + Error("Invalid value for limit(".$options['limit'].") passed to Frame::find from $file:$line"); + return array(); + } + } + } + $results = dbFetchAll($sql, NULL, $values); if ( $results ) { return array_map( function($id){ return new Frame($id); }, $results ); @@ -83,8 +89,9 @@ class Frame { return array(); } - public static function find_one( $parameters = array() ) { - $results = Frame::find( $parameters, 1 ); + public static function find_one( $parameters = array(), $options = null ) { + $options['limit'] = 1; + $results = Frame::find($parameters, $options); if ( ! sizeof($results) ) { return; } diff --git a/web/includes/Monitor.php b/web/includes/Monitor.php index a3bd1b738..2d84f5dae 100644 --- a/web/includes/Monitor.php +++ b/web/includes/Monitor.php @@ -152,19 +152,23 @@ private $control_fields = array( } if ( $this->{'Controllable'} ) { $s = dbFetchOne('SELECT * FROM Controls WHERE Id=?', NULL, array($this->{'ControlId'}) ); - foreach ($s as $k => $v) { - if ( $k == 'Id' ) { - continue; -# The reason for these is that the name overlaps Monitor fields. - } else if ( $k == 'Protocol' ) { - $this->{'ControlProtocol'} = $v; - } else if ( $k == 'Name' ) { - $this->{'ControlName'} = $v; - } else if ( $k == 'Type' ) { - $this->{'ControlType'} = $v; - } else { - $this->{$k} = $v; + if ( $s ) { + foreach ($s as $k => $v) { + if ( $k == 'Id' ) { + continue; + # The reason for these is that the name overlaps Monitor fields. + } else if ( $k == 'Protocol' ) { + $this->{'ControlProtocol'} = $v; + } else if ( $k == 'Name' ) { + $this->{'ControlName'} = $v; + } else if ( $k == 'Type' ) { + $this->{'ControlType'} = $v; + } else { + $this->{$k} = $v; + } } + } else { + Warning('No Controls found for monitor '.$this->{'Id'} . ' ' . $this->{'Name'}.' althrough it is marked as controllable'); } } global $monitor_cache; @@ -381,7 +385,7 @@ private $control_fields = array( } else if ( $this->ServerId() ) { $Server = $this->Server(); - $url = $Server->Url() . '/zm/api/monitors/'.$this->{'Id'}.'.json'; + $url = ZM_BASE_PROTOCOL . '://'.$Server->Hostname().'/zm/api/monitors/'.$this->{'Id'}.'.json'; if ( ZM_OPT_USE_AUTH ) { if ( ZM_AUTH_RELAY == 'hashed' ) { $url .= '?auth='.generateAuthHash( ZM_AUTH_HASH_IPS ); @@ -547,7 +551,7 @@ private $control_fields = array( } // end function Source public function Url() { - return $this->Server()->Url() .':'. ( ZM_MIN_STREAMING_PORT ? (ZM_MIN_STREAMING_PORT+$this->Id()) : $_SERVER['SERVER_PORT'] ); + return $this->Server()->Url( ZM_MIN_STREAMING_PORT ? (ZM_MIN_STREAMING_PORT+$this->Id()) : null ); } } // end class Monitor diff --git a/web/includes/Server.php b/web/includes/Server.php index 0b7d72a20..09d415e63 100644 --- a/web/includes/Server.php +++ b/web/includes/Server.php @@ -38,13 +38,20 @@ class Server { } } - public function Url() { + public function Url( $port = null ) { + $url = ZM_BASE_PROTOCOL . '://'; if ( $this->Id() ) { - return ZM_BASE_PROTOCOL . '://'. $this->Hostname(); + $url .= $this->Hostname(); } else { - return ZM_BASE_PROTOCOL . '://'. $_SERVER['SERVER_NAME']; - return ''; + $url .= $_SERVER['SERVER_NAME']; } + if ( $port ) { + $url .= ':'.$port; + } else { + $url .= ':'.$_SERVER['SERVER_PORT']; + } + $url .= $_SERVER['PHP_SELF']; + return $url; } public function Hostname() { if ( isset( $this->{'Hostname'} ) and ( $this->{'Hostname'} != '' ) ) { diff --git a/web/includes/auth.php b/web/includes/auth.php index 9cf8d37c1..c7df780ba 100644 --- a/web/includes/auth.php +++ b/web/includes/auth.php @@ -116,7 +116,7 @@ function generateAuthHash($useRemoteAddr, $force=false) { $time = time(); $mintime = $time - ( ZM_AUTH_HASH_TTL * 1800 ); - if ( $force or ( !isset($_SESSION['AuthHash']) ) or ( $_SESSION['AuthHashGeneratedAt'] < $mintime ) ) { + if ( $force or ( !isset($_SESSION['AuthHash'.$_SESSION['remoteAddr']]) ) or ( $_SESSION['AuthHashGeneratedAt'] < $mintime ) ) { # Don't both regenerating Auth Hash if an hour hasn't gone by yet $local_time = localtime(); $authKey = ''; @@ -133,7 +133,7 @@ function generateAuthHash($useRemoteAddr, $force=false) { session_start(); $close_session = 1; } - $_SESSION['AuthHash'] = $auth; + $_SESSION['AuthHash'.$_SESSION['remoteAddr']] = $auth; $_SESSION['AuthHashGeneratedAt'] = $time; session_write_close(); } else { @@ -143,7 +143,7 @@ function generateAuthHash($useRemoteAddr, $force=false) { #} else { #Logger::Debug("Using cached auth " . $_SESSION['AuthHash'] ." beacuse generatedat:" . $_SESSION['AuthHashGeneratedAt'] . ' < now:'. $time . ' - ' . ZM_AUTH_HASH_TTL . ' * 1800 = '. $mintime); } # end if AuthHash is not cached - return $_SESSION['AuthHash']; + return $_SESSION['AuthHash'.$_SESSION['remoteAddr']]; } # end if using AUTH and AUTH_RELAY return ''; } diff --git a/web/includes/functions.php b/web/includes/functions.php index e610ad8dd..0f49f611c 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -40,15 +40,16 @@ function CORSHeaders() { # The following is left for future reference/use. $valid = false; - $servers = dbFetchAll('SELECT * FROM Servers'); - if ( sizeof($servers) <= 1 ) { + $Servers = Server::find(); + if ( sizeof($Servers) <= 1 ) { # Only need CORSHeaders in the event that there are multiple servers in use. + # ICON: Might not be true. multi-port? return; } - foreach( $servers as $row ) { - $Server = new Server($row); - if ( preg_match('/^'.preg_quote($Server->Url(),'/').'/', $_SERVER['HTTP_ORIGIN']) ) { + foreach( $Servers as $Server ) { + if ( preg_match('/^(https?:\/\/)?'.preg_quote($Server->Hostname(),'/').'/', $_SERVER['HTTP_ORIGIN']) ) { $valid = true; + Logger::Debug("Setting Access-Controll-Allow-Origin from " . $_SERVER['HTTP_ORIGIN']); header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']); header('Access-Control-Allow-Headers: x-requested-with,x-request'); break; diff --git a/web/index.php b/web/index.php index 2569f2bb7..addddce06 100644 --- a/web/index.php +++ b/web/index.php @@ -183,14 +183,13 @@ foreach ( getSkinIncludes('skin.php') as $includeFile ) require_once $includeFile; if ( ZM_OPT_USE_AUTH ) { - if ( ZM_AUTH_HASH_LOGINS ) { - if ( empty($user) && ! empty($_REQUEST['auth']) ) { + if ( ZM_AUTH_HASH_LOGINS && empty($user) && ! empty($_REQUEST['auth']) ) { if ( $authUser = getAuthUser($_REQUEST['auth']) ) { userLogin($authUser['Username'], $authUser['Password'], true); } } - } else if ( isset($_REQUEST['username']) and isset($_REQUEST['password']) ) { - userLogin($_REQUEST['username'], $_REQUEST['password'], false); + else if ( isset($_REQUEST['username']) and isset($_REQUEST['password']) ) { + userLogin($_REQUEST['username'], $_REQUEST['password'], false); } if ( !empty($user) ) { // generate it once here, while session is open. Value will be cached in session and return when called later on diff --git a/web/lang/default.php b/web/lang/default.php index 85f27cfe1..3f29757d7 100644 --- a/web/lang/default.php +++ b/web/lang/default.php @@ -41,4 +41,3 @@ $DLANG = array( ); ?> - diff --git a/web/robots.txt b/web/robots.txt index 1f53798bb..9bef8dea6 100644 --- a/web/robots.txt +++ b/web/robots.txt @@ -1,2 +1,3 @@ User-agent: * Disallow: / +### \ No newline at end of file diff --git a/web/skins/classic/css/dark/views/control.css b/web/skins/classic/css/dark/views/control.css index af0eeccf2..31a937323 100644 --- a/web/skins/classic/css/dark/views/control.css +++ b/web/skins/classic/css/dark/views/control.css @@ -21,7 +21,7 @@ } .ptzControls input[type=image] { - border: 0px; + border: 0; } .ptzControls .controlsPanel .arrowControl { @@ -115,7 +115,7 @@ } .ptzControls .controlsPanel .pantiltPanel .pantiltControls .centerBtn { - background: url("../skins/classic/graphics/graphics/center.png") no-repeat 0 0; + background: url("../skins/classic/graphics/center.png") no-repeat 0 0; } .ptzControls .controlsPanel .pantiltPanel .pantiltControls .rightBtn { diff --git a/web/skins/classic/includes/functions.php b/web/skins/classic/includes/functions.php index 84862d9d4..ceb12d621 100644 --- a/web/skins/classic/includes/functions.php +++ b/web/skins/classic/includes/functions.php @@ -124,6 +124,7 @@ echo output_link_if_exists( array( jQuery("#flip").click(function(){ jQuery("#panel").slideToggle("slow"); jQuery("#flip").toggleClass('glyphicon-menu-down').toggleClass('glyphicon-menu-up'); + Cookie.write( 'zmHeaderFlip', jQuery('#flip').hasClass('glyphicon-menu-up') ? 'up' : 'down', { duration: 10*365 } ); }); }); @@ -208,6 +209,9 @@ echo output_link_if_exists( array( } // end function xhtmlHeaders( $file, $title ) function getNavBarHTML($reload = null) { + # Provide a facility to turn off the headers if you put headers=0 into the url + if ( isset($_REQUEST['navbar']) and $_REQUEST['navbar']=='0' ) + return ''; $versionClass = (ZM_DYN_DB_VERSION&&(ZM_DYN_DB_VERSION!=ZM_VERSION))?'errorText':''; global $running; @@ -303,7 +307,7 @@ if (isset($_REQUEST['filter']['Query']['terms']['attr'])) { } ?>
  • >
  • -
  • +
  • @@ -321,7 +325,7 @@ if (isset($_REQUEST['filter']['Query']['terms']['attr'])) { -
    +
    >
    '; + $html .= ''; # This will end up with the group_id of the deepest selection $group_id = isset($_SESSION['Group']) ? $_SESSION['Group'] : null; $html .= Group::get_group_dropdown(); @@ -114,7 +114,7 @@ $html .= htmlSelect('Function[]', $Functions, $html .= ''; if ( count($ServersById) > 1 ) { - $html .= ''; + $html .= ''; $html .= htmlSelect('ServerId[]', $ServersById, (isset($_SESSION['ServerId'])?$_SESSION['ServerId']:''), array( @@ -128,7 +128,7 @@ if ( count($ServersById) > 1 ) { } # end if have Servers if ( count($StorageById) > 1 ) { - $html .= ''; + $html .= ''; $html .= htmlSelect('StorageId[]', $StorageById, (isset($_SESSION['StorageId'])?$_SESSION['StorageId']:''), array( @@ -140,7 +140,7 @@ if ( count($StorageById) > 1 ) { $html .= ''; } # end if have Storage Areas -$html .= ''; +$html .= ''; $status_options = array( 'Unknown' => translate('StatusUnknown'), 'NotRunning' => translate('StatusNotRunning'), @@ -157,7 +157,7 @@ $html .= htmlSelect( 'Status[]', $status_options, ) ); $html .= ''; - $html .= ''; + $html .= ''; $html .= ''; $html .= ''; @@ -232,7 +232,7 @@ $html .= htmlSelect( 'Status[]', $status_options, $displayMonitors[] = $monitors[$i]; } # end foreach monitor - $html .= ''; + $html .= ''; $html .= htmlSelect('MonitorId[]', $monitors_dropdown, $selected_monitor_ids, array( 'onchange'=>'this.form.submit();', diff --git a/web/skins/classic/views/console.php b/web/skins/classic/views/console.php index 864bb956f..46575ffa0 100644 --- a/web/skins/classic/views/console.php +++ b/web/skins/classic/views/console.php @@ -217,7 +217,7 @@ ob_start(); echo ''. $j .''; } ?> - + diff --git a/web/skins/classic/views/events.php b/web/skins/classic/views/events.php index b1c58205e..6d2505f61 100644 --- a/web/skins/classic/views/events.php +++ b/web/skins/classic/views/events.php @@ -191,7 +191,8 @@ while ( $event_row = dbFetchNext($results) ) { '.$event->Id().($event->Archived()?'*':'') ?> '.validHtmlStr($event->Name()).($event->Archived()?'*':'') ?> MonitorId(), 'zmMonitor'.$event->Monitorid(), 'monitor', $event->MonitorName(), canEdit( 'Monitors' ) ) ?> - Id(), 'zmEventDetail', 'eventdetail', validHtmlStr($event->Cause()), canEdit( 'Events' ), 'title="'.htmlspecialchars($event->Notes()).'"' ) ?> + Id(), 'zmEventDetail', 'eventdetail', validHtmlStr($event->Cause()), canEdit( 'Events' ), 'title="'.htmlspecialchars($event->Notes()).'"' ) ?> + Notes() && ($event->Notes() != 'Forced Web: ')) echo "
    ".$event->Notes()."
    " ?> StartTime())) . ( $event->EndTime() ? ' until ' . strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->EndTime()) ) : '' ) ?> diff --git a/web/skins/classic/views/filter.php b/web/skins/classic/views/filter.php index d573c9d56..2be6c264c 100644 --- a/web/skins/classic/views/filter.php +++ b/web/skins/classic/views/filter.php @@ -253,7 +253,7 @@ for ( $i=0; $i < count($terms); $i++ ) { - + connKey() ?>, 'width': Width() ?>, 'height':Height() ?>, - 'server_url': 'Url() ?>', + 'url': 'Url() ?>', 'onclick': function(){createPopup( '?view=watch&mid=Id() ?>', 'zmWatchId() ?>', 'watch', Width(), $monitor->PopupScale() ); ?>, Height(), $monitor->PopupScale() ); ?> );}, 'type': 'Type() ?>', 'refresh': 'Refresh() ?>' diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js index a1d5b5f29..bab0888c7 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -110,7 +110,7 @@ if ( monitorType != 'WebSite' ) { if ( auth_hash ) streamCmdParms += '&auth='+auth_hash; var streamCmdReq = new Request.JSON( { - url: monitorUrl+thisUrl, + url: monitorUrl, method: 'get', timeout: AJAX_TIMEOUT, link: 'chain', @@ -367,7 +367,7 @@ if ( monitorType != 'WebSite' ) { var statusCmdParms = "view=request&request=status&entity=monitor&id="+monitorId+"&element[]=Status&element[]=FrameRate"; if ( auth_hash ) statusCmdParms += '&auth='+auth_hash; - var statusCmdReq = new Request.JSON( { url: monitorUrl+thisUrl, method: 'get', data: statusCmdParms, timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getStatusCmdResponse } ); + var statusCmdReq = new Request.JSON( { url: monitorUrl, method: 'get', data: statusCmdParms, timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getStatusCmdResponse } ); var statusCmdTimer = null; } @@ -397,8 +397,8 @@ if ( monitorType != 'WebSite' ) { if ( auth_hash ) alarmCmdParms += '&auth='+auth_hash; var alarmCmdReq = new Request.JSON( { - url: monitorUrl+thisUrl, - method: 'post', + url: monitorUrl, + method: 'get', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getAlarmCmdResponse, @@ -455,7 +455,15 @@ if ( monitorType != 'WebSite' ) { var eventCmdParms = "view=request&request=status&entity=events&id="+monitorId+"&count="+maxDisplayEvents+"&sort=Id%20desc"; if ( auth_hash ) eventCmdParms += '&auth='+auth_hash; - var eventCmdReq = new Request.JSON( { url: thisUrl, method: 'post', timeout: AJAX_TIMEOUT, data: eventCmdParms, link: 'cancel', onSuccess: getEventCmdResponse, onTimeout: eventCmdQuery } ); + var eventCmdReq = new Request.JSON( { + url: monitorUrl, + method: 'get', + timeout: AJAX_TIMEOUT, + data: eventCmdParms, + link: 'cancel', + onSuccess: getEventCmdResponse, + onTimeout: eventCmdQuery + } ); var eventCmdTimer = null; var eventCmdFirst = true; } @@ -565,7 +573,7 @@ if ( monitorType != 'WebSite' ) { var controlParms = "view=request&request=control&id="+monitorId; if ( auth_hash ) controlParms += '&auth='+auth_hash; - var controlReq = new Request.JSON( { url: thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getControlResponse } ); + var controlReq = new Request.JSON( { url: monitorUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getControlResponse } ); } function getControlResponse( respObj, respText ) { @@ -617,7 +625,7 @@ function controlCmdImage( x, y ) { controlReq.send( imageControlParms+"&x="+x+"&y="+y ); if ( streamMode == "single" ) fetchImage.pass( $('imageFeed').getElement('img') ).delay( 1000 ); -} +} function fetchImage( streamImage ) { streamImage.src = streamImage.src.replace(/rand=\d+/i,'rand='+Math.floor((Math.random() * 1000000) )); diff --git a/web/skins/classic/views/js/zone.js b/web/skins/classic/views/js/zone.js index 023671588..6389e3ce9 100644 --- a/web/skins/classic/views/js/zone.js +++ b/web/skins/classic/views/js/zone.js @@ -471,7 +471,13 @@ function setAlarmState( currentAlarmState ) { } var streamCmdParms = "view=request&request=stream&connkey="+connKey; -var streamCmdReq = new Request.JSON( { url: monitorUrl+thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getStreamCmdResponse } ); +var streamCmdReq = new Request.JSON( { + url: monitorUrl, + method: 'get', + timeout: AJAX_TIMEOUT, + link: 'cancel', + onSuccess: getStreamCmdResponse +} ); var streamCmdTimer = null; var streamStatus; @@ -546,7 +552,14 @@ function streamCmdQuery() { } var statusCmdParms = "view=request&request=status&entity=monitor&id="+monitorId+"&element[]=Status&element[]=FrameRate"; -var statusCmdReq = new Request.JSON( { url: monitorUrl+thisUrl, method: 'post', data: statusCmdParms, timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getStatusCmdResponse } ); +var statusCmdReq = new Request.JSON( { + url: monitorUrl, + method: 'get', + data: statusCmdParms, + timeout: AJAX_TIMEOUT, + link: 'cancel', + onSuccess: getStatusCmdResponse +} ); var statusCmdTimer = null; function getStatusCmdResponse( respObj, respText ) { @@ -652,11 +665,13 @@ function initPage() { // Imported from watch.js and modified for new zone edit view // + var delay = (Math.random()+0.1)*statusRefreshTimeout; + //console.log("Delay for status updates is: " + delay ); if ( streamMode == "single" ) { - statusCmdTimer = statusCmdQuery.delay( (Math.random()+0.1)*statusRefreshTimeout ); + statusCmdTimer = statusCmdQuery.delay( delay ); watchdogCheck.pass('status').periodical(statusRefreshTimeout*2); } else { - streamCmdTimer = streamCmdQuery.delay( (Math.random()+0.1)*statusRefreshTimeout ); + streamCmdTimer = streamCmdQuery.delay( delay ); watchdogCheck.pass('stream').periodical(statusRefreshTimeout*2); } diff --git a/web/skins/classic/views/js/zone.js.php b/web/skins/classic/views/js/zone.js.php index 49946f767..434fec679 100644 --- a/web/skins/classic/views/js/zone.js.php +++ b/web/skins/classic/views/js/zone.js.php @@ -101,7 +101,7 @@ var streamMode = ""; var connKey = ''; var monitorId = Id() ?>; -var monitorUrl = 'Server()->Url() ) ?>'; +var monitorUrl = 'Url() ) ?>'; var streamSrc = ""; diff --git a/web/skins/classic/views/js/zones.js b/web/skins/classic/views/js/zones.js index a01f8b56f..9ada175bc 100644 --- a/web/skins/classic/views/js/zones.js +++ b/web/skins/classic/views/js/zones.js @@ -1,5 +1,5 @@ var streamCmdParms = "view=request&request=stream&connkey="+connKey; -var streamCmdReq = new Request.JSON( { url: monitorUrl+thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'cancel' } ); +var streamCmdReq = new Request.JSON( { url: monitorUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'cancel' } ); function streamCmdQuit( action ) { if ( action ) diff --git a/web/skins/classic/views/js/zones.js.php b/web/skins/classic/views/js/zones.js.php index ca234085e..d7144d18a 100644 --- a/web/skins/classic/views/js/zones.js.php +++ b/web/skins/classic/views/js/zones.js.php @@ -1,4 +1,4 @@ var connKey = ''; -var monitorUrl = 'Server()->Url() ) ?>'; +var monitorUrl = 'Url() ) ?>'; var CMD_QUIT = ; diff --git a/web/skins/classic/views/log.php b/web/skins/classic/views/log.php index 4f2650865..d13381e2f 100644 --- a/web/skins/classic/views/log.php +++ b/web/skins/classic/views/log.php @@ -45,17 +45,16 @@ xhtmlHeaders(__FILE__, translate('SystemLog') );
    - - - - - + + + + +
    - - - - + + +
    @@ -89,7 +88,7 @@ xhtmlHeaders(__FILE__, translate('SystemLog') ); - +
    @@ -137,8 +136,8 @@ xhtmlHeaders(__FILE__, translate('SystemLog') );
    :
    - - + +
    diff --git a/web/skins/classic/views/montage.php b/web/skins/classic/views/montage.php index 9f0cf8998..a0ebdce0a 100644 --- a/web/skins/classic/views/montage.php +++ b/web/skins/classic/views/montage.php @@ -135,7 +135,7 @@ xhtmlHeaders(__FILE__, translate('Montage'));