Merge branch 'master' of github.com:/ZoneMinder/zoneminder
This commit is contained in:
commit
b060e0835c
|
@ -282,6 +282,7 @@ DROP TABLE IF EXISTS `Filters`;
|
|||
CREATE TABLE `Filters` (
|
||||
`Id` int(10) unsigned NOT NULL auto_increment,
|
||||
`Name` varchar(64) NOT NULL default '',
|
||||
`UserId` int(10) unsigned,
|
||||
`Query_json` text NOT NULL,
|
||||
`AutoArchive` tinyint(3) unsigned NOT NULL default '0',
|
||||
`AutoVideo` tinyint(3) unsigned NOT NULL default '0',
|
||||
|
@ -787,6 +788,7 @@ INSERT INTO `Filters`
|
|||
`AutoCopy`,
|
||||
`AutoCopyTo`,
|
||||
`UpdateDiskSpace`,
|
||||
`UserId`,
|
||||
`Background`,
|
||||
`Concurrent`
|
||||
)
|
||||
|
@ -807,6 +809,7 @@ INSERT INTO `Filters`
|
|||
0/*AutoMove*/,0/*MoveTo*/,
|
||||
0/*AutoCopy*/,0/*CopyTo*/,
|
||||
0/*UpdateDiskSpace*/,
|
||||
1/*UserId = admin*/,
|
||||
1/*Background*/,
|
||||
0/*Concurrent*/
|
||||
);
|
||||
|
@ -830,6 +833,7 @@ INSERT INTO `Filters`
|
|||
`AutoCopy`,
|
||||
`AutoCopyTo`,
|
||||
`UpdateDiskSpace`,
|
||||
`UserId`,
|
||||
`Background`,
|
||||
`Concurrent`
|
||||
)
|
||||
|
@ -849,6 +853,7 @@ VALUES (
|
|||
0/*AutoMove*/,0/*MoveTo*/,
|
||||
0/*AutoCopy*/,0/*CopyTo*/,
|
||||
1/*UpdateDiskSpace*/,
|
||||
1/*UserId=admin*/,
|
||||
1/*Background*/,
|
||||
0/*Concurrent*/
|
||||
);
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
|
||||
AND table_name = 'Filters'
|
||||
AND column_name = 'UserId'
|
||||
) > 0,
|
||||
"SELECT 'Column UserId already exists in Filters'",
|
||||
"ALTER TABLE `Filters` ADD `UserId` int(10) unsigned AFTER `Name`"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
|
@ -28,7 +28,7 @@
|
|||
%global _hardened_build 1
|
||||
|
||||
Name: zoneminder
|
||||
Version: 1.35.4
|
||||
Version: 1.35.5
|
||||
Release: 1%{?dist}
|
||||
Summary: A camera monitoring and analysis tool
|
||||
Group: System Environment/Daemons
|
||||
|
|
|
@ -83,7 +83,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
|
|||
,libssl | libssl1.0.0 | libssl1.1
|
||||
,libcrypt-eksblowfish-perl
|
||||
,libdata-entropy-perl
|
||||
,libvncclient1
|
||||
,libvncclient1|libvncclient0
|
||||
Recommends: ${misc:Recommends}
|
||||
,libapache2-mod-php5 | libapache2-mod-php | php5-fpm | php-fpm
|
||||
,mysql-server | mariadb-server | virtual-mysql-server
|
||||
|
|
|
@ -352,6 +352,11 @@ sub GenerateVideo {
|
|||
sub delete {
|
||||
my $event = $_[0];
|
||||
|
||||
if ( !$event->canEdit() ) {
|
||||
Warning('No permission to delete event.');
|
||||
return 'No permission to delete event.';
|
||||
}
|
||||
|
||||
my $in_zmaudit = ( $0 =~ 'zmaudit.pl$');
|
||||
|
||||
if ( ! $in_zmaudit ) {
|
||||
|
@ -402,6 +407,11 @@ sub delete {
|
|||
sub delete_files {
|
||||
my $event = shift;
|
||||
|
||||
if ( !$event->canEdit() ) {
|
||||
Warning('No permission to delete event.');
|
||||
return 'No permission to delete event.';
|
||||
}
|
||||
|
||||
foreach my $Storage (
|
||||
@_ ? ($_[0]) : (
|
||||
new ZoneMinder::Storage($$event{StorageId}),
|
||||
|
@ -570,6 +580,11 @@ sub DiskSpace {
|
|||
sub CopyTo {
|
||||
my ( $self, $NewStorage ) = @_;
|
||||
|
||||
if ( !$self->canEdit() ) {
|
||||
Warning('No permission to copy event.');
|
||||
return 'No permission to copy event.';
|
||||
}
|
||||
|
||||
my $OldStorage = $self->Storage(undef);
|
||||
my ( $OldPath ) = ( $self->Path() =~ /^(.*)$/ ); # De-taint
|
||||
if ( ! -e $OldPath ) {
|
||||
|
@ -734,8 +749,13 @@ sub CopyTo {
|
|||
} # end sub CopyTo
|
||||
|
||||
sub MoveTo {
|
||||
|
||||
my ( $self, $NewStorage ) = @_;
|
||||
|
||||
if ( !$self->canEdit() ) {
|
||||
Warning('No permission to move event.');
|
||||
return 'No permission to move event.';
|
||||
}
|
||||
|
||||
my $OldStorage = $self->Storage(undef);
|
||||
|
||||
my $error = $self->CopyTo($NewStorage);
|
||||
|
@ -857,16 +877,32 @@ sub files {
|
|||
|
||||
sub has_capture_jpegs {
|
||||
@{$_[0]{capture_jpegs}} = grep(/^\d+\-capture\.jpg$/, $_[0]->files());
|
||||
Debug("have " . @{$_[0]{capture_jpegs}} . " capture jpegs");
|
||||
Debug('have ' . @{$_[0]{capture_jpegs}} . ' capture jpegs');
|
||||
return @{$_[0]{capture_jpegs}} ? 1 : 0;
|
||||
}
|
||||
|
||||
sub has_analyse_jpegs {
|
||||
@{$_[0]{analyse_jpegs}} = grep(/^\d+\-analyse\.jpg$/, $_[0]->files());
|
||||
Debug("have " . @{$_[0]{analyse_jpegs}} . " analyse jpegs");
|
||||
Debug('have ' . @{$_[0]{analyse_jpegs}} . ' analyse jpegs');
|
||||
return @{$_[0]{analyse_jpegs}} ? 1 : 0;
|
||||
}
|
||||
|
||||
sub canEdit {
|
||||
my $self = shift;
|
||||
if ( !$ZoneMinder::user ) {
|
||||
# No user loaded... assume running as system
|
||||
return 1;
|
||||
}
|
||||
if ( !$$ZoneMinder::user{MonitorIds} ) {
|
||||
# User has no monitor limitations
|
||||
return 1;
|
||||
}
|
||||
if ( $$ZoneMinder::user{Events} eq 'Edit' ) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
} # end sub canEdit
|
||||
|
||||
1;
|
||||
__END__
|
||||
|
||||
|
|
|
@ -49,49 +49,34 @@ use ZoneMinder::Database qw(:all);
|
|||
require ZoneMinder::Storage;
|
||||
require ZoneMinder::Server;
|
||||
|
||||
sub Name {
|
||||
if ( @_ > 1 ) {
|
||||
$_[0]{Name} = $_[1];
|
||||
}
|
||||
return $_[0]{Name};
|
||||
} # end sub Path
|
||||
use vars qw/ $table $primary_key %fields /;
|
||||
$table = 'Users';
|
||||
$primary_key = 'Id';
|
||||
|
||||
sub find {
|
||||
shift if $_[0] eq 'ZoneMinder::Filter';
|
||||
my %sql_filters = @_;
|
||||
|
||||
my $sql = 'SELECT * FROM Filters';
|
||||
my @sql_filters;
|
||||
my @sql_values;
|
||||
|
||||
if ( exists $sql_filters{Name} ) {
|
||||
push @sql_filters , ' Name = ? ';
|
||||
push @sql_values, $sql_filters{Name};
|
||||
}
|
||||
|
||||
$sql .= ' WHERE ' . join(' AND ', @sql_filters ) if @sql_filters;
|
||||
$sql .= ' LIMIT ' . $sql_filters{limit} if $sql_filters{limit};
|
||||
|
||||
my $sth = $ZoneMinder::Database::dbh->prepare_cached($sql)
|
||||
or Fatal("Can't prepare '$sql': ".$ZoneMinder::Database::dbh->errstr());
|
||||
my $res = $sth->execute(@sql_values)
|
||||
or Fatal("Can't execute '$sql': ".$sth->errstr());
|
||||
|
||||
my @results;
|
||||
|
||||
while( my $db_filter = $sth->fetchrow_hashref() ) {
|
||||
my $filter = new ZoneMinder::Filter($$db_filter{Id}, $db_filter);
|
||||
push @results, $filter;
|
||||
} # end while
|
||||
$sth->finish();
|
||||
|
||||
return @results;
|
||||
}
|
||||
|
||||
sub find_one {
|
||||
my @results = find(@_);
|
||||
return $results[0] if @results;
|
||||
}
|
||||
%fields = map { $_ => $_ } qw(
|
||||
Id
|
||||
Name
|
||||
Query_json
|
||||
AutoArchive
|
||||
AutoVideo
|
||||
AutoUpload
|
||||
AutoEmail
|
||||
EmailTo
|
||||
EmailSubject
|
||||
EmailBody
|
||||
AutoMessage
|
||||
AutoExecute
|
||||
AutoExecuteCmd
|
||||
AutoDelete
|
||||
AutoMove
|
||||
AutoMoveTo
|
||||
AutoCopy
|
||||
AutoCopyTo
|
||||
UpdateDiskSpace
|
||||
UserId
|
||||
Background
|
||||
Concurrent
|
||||
);
|
||||
|
||||
sub Execute {
|
||||
my $self = $_[0];
|
||||
|
@ -324,14 +309,9 @@ sub Sql {
|
|||
} # end if terms
|
||||
|
||||
if ( $self->{Sql} ) {
|
||||
if ( $self->{AutoMessage} ) {
|
||||
# Include all events, including events that are still ongoing
|
||||
# and have no EndTime yet
|
||||
$sql .= ' WHERE ( '.$self->{Sql}.' )';
|
||||
} else {
|
||||
# Only include closed events (events with valid EndTime)
|
||||
$sql .= ' WHERE (E.EndTime IS NOT NULL) AND ( '.$self->{Sql}.' )';
|
||||
}
|
||||
$sql .= ' WHERE ( '.$self->{Sql}.' )';
|
||||
}
|
||||
my @auto_terms;
|
||||
if ( $self->{AutoArchive} ) {
|
||||
|
@ -458,6 +438,15 @@ sub DateTimeToSQL {
|
|||
return POSIX::strftime('%Y-%m-%d %H:%M:%S', localtime($dt_val));
|
||||
}
|
||||
|
||||
sub User {
|
||||
my $self = shift;
|
||||
$$self{User} = shift if @_;
|
||||
if ( ! $$self{User} and $$self{UserId} ) {
|
||||
$$self{User} = ZoneMinder::User->find_one(Id=>$$self{UserId});
|
||||
}
|
||||
return $$self{User};
|
||||
}
|
||||
|
||||
1;
|
||||
__END__
|
||||
# Below is stub documentation for your module. You'd better edit it!
|
||||
|
|
|
@ -28,6 +28,9 @@ our %EXPORT_TAGS = (
|
|||
makePath
|
||||
jsonEncode
|
||||
jsonDecode
|
||||
systemStatus
|
||||
packageControl
|
||||
daemonControl
|
||||
) ]
|
||||
);
|
||||
push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS;
|
||||
|
@ -531,6 +534,38 @@ sub jsonDecode {
|
|||
return $result;
|
||||
}
|
||||
|
||||
sub packageControl {
|
||||
my $command = shift;
|
||||
my $string = $Config{ZM_PATH_BIN}.'/zmpkg.pl '.$command;
|
||||
$string .= ' 2>/dev/null >&- <&- >/dev/null';
|
||||
executeShellCommand($string);
|
||||
}
|
||||
|
||||
sub daemonControl {
|
||||
my ($command, $daemon, $args) = @_;
|
||||
my $string = $Config{ZM_PATH_BIN}.'/zmdc.pl '.$command;
|
||||
if ( $daemon ) {
|
||||
$string .= ' ' . $daemon;
|
||||
if ( $args ) {
|
||||
$string .= ' ' . $args;
|
||||
}
|
||||
}
|
||||
#$string .= ' 2>/dev/null >&- <&- >/dev/null';
|
||||
executeShellCommand($string);
|
||||
}
|
||||
|
||||
sub systemStatus {
|
||||
my $command = $Config{ZM_PATH_BIN}.'/zmdc.pl check';
|
||||
my $output = qx($command);
|
||||
my $status = $? >> 8;
|
||||
if ( $status || logDebugging() ) {
|
||||
$output = '' if !defined($output);
|
||||
chomp($output);
|
||||
Debug("Command: $command Output: $output");
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
1;
|
||||
__END__
|
||||
# Below is stub documentation for your module. You'd better edit it!
|
||||
|
@ -542,7 +577,6 @@ ZoneMinder::General - Utility Functions for ZoneMinder
|
|||
=head1 SYNOPSIS
|
||||
|
||||
use ZoneMinder::General;
|
||||
blah blah blah
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
|
@ -561,6 +595,9 @@ of the ZoneMinder scripts
|
|||
makePath
|
||||
jsonEncode
|
||||
jsonDecode
|
||||
packageControl
|
||||
daemonControl
|
||||
systemStatus
|
||||
) ]
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
# ==========================================================================
|
||||
#
|
||||
# ZoneMinder User Module
|
||||
# Copyright (C) 2020 ZoneMinder LLC
|
||||
#
|
||||
# This program 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 program 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.
|
||||
#
|
||||
# ==========================================================================
|
||||
|
||||
package ZoneMinder::Frame;
|
||||
|
||||
use 5.006;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
require ZoneMinder::Base;
|
||||
require ZoneMinder::Object;
|
||||
|
||||
use parent qw(ZoneMinder::Object);
|
||||
|
||||
use vars qw/ $table $primary_key %fields /;
|
||||
$table = 'Users';
|
||||
$primary_key = 'Id';
|
||||
|
||||
%fields = map { $_ => $_ } qw(
|
||||
Id
|
||||
Username
|
||||
Password
|
||||
Language
|
||||
Enabled
|
||||
Stream
|
||||
Events
|
||||
Control
|
||||
Monitors
|
||||
Groups
|
||||
Devices
|
||||
System
|
||||
MaxBandwidth
|
||||
MonitorIds
|
||||
TokenMinExpiry
|
||||
APIEnabled
|
||||
);
|
||||
|
||||
1;
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
ZoneMinder::User - Perl Class for Users
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use ZoneMinder::User;
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Isaac Connor, E<lt>isaac@zoneminder.comE<gt>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
Copyright (C) 2001-2017 ZoneMinder LLC
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the same terms as Perl itself, either Perl version 5.8.3 or,
|
||||
at your option, any later version of Perl 5 you may have available.
|
||||
|
||||
|
||||
=cut
|
|
@ -119,25 +119,30 @@ GetOptions(
|
|||
) or pod2usage(-exitstatus => -1);
|
||||
|
||||
my $dbh = zmDbConnect(undef, { mysql_multi_statements=>1 } );
|
||||
if ( !$dbh ) {
|
||||
die "Unable to connect to db\n";
|
||||
}
|
||||
$Config{ZM_DB_USER} = $dbUser;
|
||||
$Config{ZM_DB_PASS} = $dbPass;
|
||||
# we escape dbpass with single quotes so that $ in the password has no effect, but dbpass could have a ' in it.
|
||||
$dbPass =~ s/'/\\'/g;
|
||||
|
||||
if ( ! ($check || $freshen || $rename || $zoneFix || $migrateEvents || $version) ) {
|
||||
if ( $Config{ZM_DYN_DB_VERSION} ) {
|
||||
$version = $Config{ZM_DYN_DB_VERSION};
|
||||
} else {
|
||||
print( STDERR "Please give a valid option\n" );
|
||||
print(STDERR "Please give a valid option\n");
|
||||
pod2usage(-exitstatus => -1);
|
||||
}
|
||||
}
|
||||
|
||||
if ( ($check + $freshen + $rename + $zoneFix + $migrateEvents + ($version?1:0)) > 1 ) {
|
||||
print( STDERR "Please give only one option\n" );
|
||||
print(STDERR "Please give only one option\n");
|
||||
pod2usage(-exitstatus => -1);
|
||||
}
|
||||
|
||||
if ( $check && $Config{ZM_CHECK_FOR_UPDATES} ) {
|
||||
print( "Update agent starting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" );
|
||||
print('Update agent starting at '.strftime('%y/%m/%d %H:%M:%S', localtime() )."\n");
|
||||
|
||||
my $currVersion = $Config{ZM_DYN_CURR_VERSION};
|
||||
my $lastVersion = $Config{ZM_DYN_LAST_VERSION};
|
||||
|
@ -147,23 +152,23 @@ if ( $check && $Config{ZM_CHECK_FOR_UPDATES} ) {
|
|||
$currVersion = $Config{ZM_VERSION};
|
||||
|
||||
my $sql = "update Config set Value = ? where Name = 'ZM_DYN_CURR_VERSION'";
|
||||
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute( "$currVersion" ) or die( "Can't execute: ".$sth->errstr() );
|
||||
my $sth = $dbh->prepare_cached($sql) or die("Can't prepare '$sql': ".$dbh->errstr());
|
||||
my $res = $sth->execute($currVersion) or die("Can't execute: ".$sth->errstr());
|
||||
$sth->finish();
|
||||
}
|
||||
|
||||
while( 1 ) {
|
||||
while ( 1 ) {
|
||||
my $now = time();
|
||||
if ( !$lastVersion || !$lastCheck || (($now-$lastCheck) > CHECK_INTERVAL) ) {
|
||||
Info( "Checking for updates\n" );
|
||||
Info('Checking for updates');
|
||||
|
||||
use LWP::UserAgent;
|
||||
my $ua = LWP::UserAgent->new;
|
||||
$ua->agent( "ZoneMinder Update Agent/".ZM_VERSION );
|
||||
$ua->agent('ZoneMinder Update Agent/'.ZM_VERSION);
|
||||
if ( $Config{ZM_UPDATE_CHECK_PROXY} ) {
|
||||
$ua->proxy( 'http', $Config{ZM_UPDATE_CHECK_PROXY} );
|
||||
$ua->proxy('http', $Config{ZM_UPDATE_CHECK_PROXY});
|
||||
}
|
||||
my $req = HTTP::Request->new( GET=>'https://update.zoneminder.com/version.txt' );
|
||||
my $req = HTTP::Request->new(GET=>'https://update.zoneminder.com/version.txt');
|
||||
my $res = $ua->request($req);
|
||||
|
||||
if ( $res->is_success ) {
|
||||
|
@ -171,63 +176,63 @@ if ( $check && $Config{ZM_CHECK_FOR_UPDATES} ) {
|
|||
chomp($lastVersion);
|
||||
$lastCheck = $now;
|
||||
|
||||
Info( "Got version: '".$lastVersion."'\n" );
|
||||
Info('Got version: '.$lastVersion);
|
||||
|
||||
my $lv_sql = "update Config set Value = ? where Name = 'ZM_DYN_LAST_VERSION'";
|
||||
my $lv_sth = $dbh->prepare_cached( $lv_sql ) or die( "Can't prepare '$lv_sql': ".$dbh->errstr() );
|
||||
my $lv_res = $lv_sth->execute( $lastVersion ) or die( "Can't execute: ".$lv_sth->errstr() );
|
||||
my $lv_sql = 'UPDATE Config SET Value = ? WHERE Name = \'ZM_DYN_LAST_VERSION\'';
|
||||
my $lv_sth = $dbh->prepare_cached($lv_sql) or die("Can't prepare '$lv_sql': ".$dbh->errstr());
|
||||
my $lv_res = $lv_sth->execute($lastVersion) or die("Can't execute: ".$lv_sth->errstr());
|
||||
$lv_sth->finish();
|
||||
|
||||
my $lc_sql = "update Config set Value = ? where Name = 'ZM_DYN_LAST_CHECK'";
|
||||
my $lc_sth = $dbh->prepare_cached( $lc_sql ) or die( "Can't prepare '$lc_sql': ".$dbh->errstr() );
|
||||
my $lc_res = $lc_sth->execute( $lastCheck ) or die( "Can't execute: ".$lc_sth->errstr() );
|
||||
my $lc_sql = 'UPDATE Config SET Value = ? WHERE Name = \'ZM_DYN_LAST_CHECK\'';
|
||||
my $lc_sth = $dbh->prepare_cached($lc_sql) or die("Can't prepare '$lc_sql': ".$dbh->errstr());
|
||||
my $lc_res = $lc_sth->execute($lastCheck) or die("Can't execute: ".$lc_sth->errstr());
|
||||
$lc_sth->finish();
|
||||
} else {
|
||||
Error( "Error check failed: '".$res->status_line()."'\n" );
|
||||
Error('Error check failed: \''.$res->status_line().'\'');
|
||||
}
|
||||
}
|
||||
sleep( 3600 );
|
||||
sleep(3600);
|
||||
}
|
||||
print( "Update agent exiting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" );
|
||||
print('Update agent exiting at '.strftime('%y/%m/%d %H:%M:%S', localtime())."\n");
|
||||
}
|
||||
|
||||
if ( $rename ) {
|
||||
require File::Find;
|
||||
|
||||
chdir( EVENT_PATH );
|
||||
chdir(EVENT_PATH);
|
||||
|
||||
sub renameImage {
|
||||
my $file = $_;
|
||||
|
||||
# Ignore directories
|
||||
if ( -d $file ) {
|
||||
print( "Checking directory '$file'\n" );
|
||||
print("Checking directory '$file'\n");
|
||||
return;
|
||||
}
|
||||
if ( $file !~ /(capture|analyse)-(\d+)(\.jpg)/ ) {
|
||||
return;
|
||||
}
|
||||
my $newFile = "$2-$1$3";
|
||||
my $newFile = $2.'-'.$1.$3;
|
||||
|
||||
print( "Renaming '$file' to '$newFile'\n" );
|
||||
rename( $file, $newFile ) or warn( "Can't rename '$file' to '$newFile'" );
|
||||
print("Renaming '$file' to '$newFile'\n");
|
||||
rename($file, $newFile) or warn("Can't rename '$file' to '$newFile'");
|
||||
}
|
||||
|
||||
File::Find::find( \&renameImage, '.' );
|
||||
}
|
||||
if ( $zoneFix ) {
|
||||
File::Find::find(\&renameImage, '.');
|
||||
} # end if rename
|
||||
|
||||
my $sql = "select Z.*, M.Width as MonitorWidth, M.Height as MonitorHeight from Zones as Z inner join Monitors as M on Z.MonitorId = M.Id where Z.Units = 'Percent'";
|
||||
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() );
|
||||
if ( $zoneFix ) {
|
||||
my $sql = "SELECT Z.*, M.Width AS MonitorWidth, M.Height AS MonitorHeight FROM Zones AS Z INNER JOIN Monitors AS M ON Z.MonitorId = M.Id WHERE Z.Units = 'Percent'";
|
||||
my $sth = $dbh->prepare_cached($sql) or die("Can't prepare '$sql': ".$dbh->errstr());
|
||||
my $res = $sth->execute() or die("Can't execute: ".$sth->errstr());
|
||||
my @zones;
|
||||
while( my $zone = $sth->fetchrow_hashref() ) {
|
||||
push( @zones, $zone );
|
||||
while ( my $zone = $sth->fetchrow_hashref() ) {
|
||||
push(@zones, $zone);
|
||||
}
|
||||
$sth->finish();
|
||||
|
||||
$sql = 'update Zones set MinAlarmPixels = ?, MaxAlarmPixels = ?, MinFilterPixels = ?, MaxFilterPixels = ?, MinBlobPixels = ?, MaxBlobPixels = ? where Id = ?';
|
||||
$sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
$sql = 'UPDATE Zones SET MinAlarmPixels = ?, MaxAlarmPixels = ?, MinFilterPixels = ?, MaxFilterPixels = ?, MinBlobPixels = ?, MaxBlobPixels = ? WHERE Id = ?';
|
||||
$sth = $dbh->prepare_cached($sql) or die("Can't prepare '$sql': ".$dbh->errstr());
|
||||
foreach my $zone ( @zones ) {
|
||||
my $zone_width = (($zone->{HiX}*$zone->{MonitorWidth})-($zone->{LoX}*$zone->{MonitorWidth}))/100;
|
||||
my $zone_height = (($zone->{HiY}*$zone->{MonitorHeight})-($zone->{LoY}*$zone->{MonitorHeight}))/100;
|
||||
|
@ -241,78 +246,84 @@ if ( $zoneFix ) {
|
|||
($zone->{MinBlobPixels}*$monitor_area)/$zone_area,
|
||||
($zone->{MaxBlobPixels}*$monitor_area)/$zone_area,
|
||||
$zone->{Id}
|
||||
) or die( "Can't execute: ".$sth->errstr() );
|
||||
) or die("Can't execute: ".$sth->errstr());
|
||||
}
|
||||
$sth->finish();
|
||||
}
|
||||
} # end if zoneFix
|
||||
|
||||
if ( $migrateEvents ) {
|
||||
my $webUid = (getpwnam( $Config{ZM_WEB_USER} ))[2];
|
||||
my $webGid = (getgrnam( $Config{ZM_WEB_USER} ))[2];
|
||||
my $webUid = (getpwnam($Config{ZM_WEB_USER}))[2];
|
||||
my $webGid = (getgrnam($Config{ZM_WEB_USER}))[2];
|
||||
|
||||
if ( !(($> == 0) || ($> == $webUid)) ) {
|
||||
print( "Error, migrating events can only be done as user root or ".$Config{ZM_WEB_USER}.".\n" );
|
||||
exit( -1 );
|
||||
print("Error, migrating events can only be done as user root or ".$Config{ZM_WEB_USER}.".\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
# Run as web user/group
|
||||
$( = $webGid;
|
||||
$) = $webGid;
|
||||
$) = $webGid;
|
||||
$< = $webUid;
|
||||
$> = $webUid;
|
||||
|
||||
print( "\nAbout to convert saved events to deep storage, please ensure that ZoneMinder is fully stopped before proceeding.\nThis process is not easily reversible. Are you sure you wish to proceed?\n\nPress 'y' to continue or 'n' to abort : " );
|
||||
print('
|
||||
About to convert saved events to deep storage, please ensure that ZoneMinder is fully stopped before proceeding.
|
||||
This process is not easily reversible. Are you sure you wish to proceed?
|
||||
|
||||
Press \'y\' to continue or \'n\' to abort : ');
|
||||
my $response = <STDIN>;
|
||||
chomp( $response );
|
||||
chomp($response);
|
||||
while ( $response !~ /^[yYnN]$/ ) {
|
||||
print( "Please press 'y' to continue or 'n' to abort only : " );
|
||||
print("Please press 'y' to continue or 'n' to abort only : ");
|
||||
$response = <STDIN>;
|
||||
chomp( $response );
|
||||
chomp($response);
|
||||
}
|
||||
|
||||
if ( $response =~ /^[yY]$/ ) {
|
||||
print( "Converting all events to deep storage.\n" );
|
||||
print("Converting all events to deep storage.\n");
|
||||
|
||||
chdir( $Config{ZM_PATH_WEB} );
|
||||
my $sql = "select *, unix_timestamp(StartTime) as UnixStartTime from Events";
|
||||
my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
chdir($Config{ZM_PATH_WEB});
|
||||
my $sql = 'SELECT *, unix_timestamp(StartTime) AS UnixStartTime FROM Events';
|
||||
my $sth = $dbh->prepare_cached($sql) or Fatal("Can't prepare '$sql': ".$dbh->errstr());
|
||||
my $res = $sth->execute();
|
||||
if ( !$res ) {
|
||||
Fatal( "Can't fetch Events: ".$sth->errstr() );
|
||||
Fatal("Can't fetch Events: ".$sth->errstr());
|
||||
}
|
||||
|
||||
while( my $event = $sth->fetchrow_hashref() ) {
|
||||
my $oldEventPath = $Config{ZM_DIR_EVENTS}.'/'.$event->{MonitorId}.'/'.$event->{Id};
|
||||
|
||||
if ( !-d $oldEventPath ) {
|
||||
print( "Warning, can't find old event path '$oldEventPath', already converted?\n" );
|
||||
print("Warning, can't find old event path '$oldEventPath', already converted?\n");
|
||||
next;
|
||||
}
|
||||
|
||||
print( "Converting event ".$event->{Id}."\n" );
|
||||
my $newDatePath = $Config{ZM_DIR_EVENTS}.'/'.$event->{MonitorId}.'/'.strftime( "%y/%m/%d", localtime($event->{UnixStartTime}) );
|
||||
my $newTimePath = strftime( "%H/%M/%S", localtime($event->{UnixStartTime}) );
|
||||
print('Converting event '.$event->{Id}."\n");
|
||||
my $newDatePath = $Config{ZM_DIR_EVENTS}.'/'.$event->{MonitorId}.'/'.strftime('%y/%m/%d', localtime($event->{UnixStartTime}));
|
||||
my $newTimePath = strftime('%H/%M/%S', localtime($event->{UnixStartTime}));
|
||||
my $newEventPath = $newDatePath.'/'.$newTimePath;
|
||||
( my $truncEventPath = $newEventPath ) =~ s|/\d+$||;
|
||||
makePath( $truncEventPath, $Config{ZM_PATH_WEB} );
|
||||
makePath($truncEventPath, $Config{ZM_PATH_WEB});
|
||||
my $idLink = $newDatePath.'/.'.$event->{Id};
|
||||
symlink( $newTimePath, $idLink ) or die( "Can't symlink $newTimePath -> $idLink: $!" );
|
||||
rename( $oldEventPath, $newEventPath ) or die( "Can't move $oldEventPath -> $newEventPath: $!" );
|
||||
symlink($newTimePath, $idLink) or die("Can't symlink $newTimePath -> $idLink: $!");
|
||||
rename($oldEventPath, $newEventPath) or die("Can't move $oldEventPath -> $newEventPath: $!");
|
||||
}
|
||||
$sth->finish();
|
||||
|
||||
print( "Updating configuration.\n" );
|
||||
print("Updating configuration.\n");
|
||||
$sql = "UPDATE `Config` SET `Value` = ? WHERE `Name` = 'ZM_USE_DEEP_STORAGE'";
|
||||
$sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
$res = $sth->execute( 1 ) or die( "Can't execute: ".$sth->errstr() );
|
||||
$sth = $dbh->prepare_cached($sql) or die( "Can't prepare '$sql': ".$dbh->errstr());
|
||||
$res = $sth->execute(1) or die("Can't execute: ".$sth->errstr());
|
||||
$sth->finish();
|
||||
|
||||
print( "All events converted.\n\n" );
|
||||
print("All events converted.\n\n");
|
||||
} else {
|
||||
print( "Aborting event conversion.\n\n" );
|
||||
print("Aborting event conversion.\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
if ( $freshen ) {
|
||||
print( "\nFreshening configuration in database\n" );
|
||||
print("\nFreshening configuration in database\n");
|
||||
migratePaths();
|
||||
migratePasswords();
|
||||
ZoneMinder::Config::loadConfigFromDB();
|
||||
|
@ -324,8 +335,8 @@ if ( $interactive ) {
|
|||
# Now check for MyISAM Tables
|
||||
my @MyISAM_Tables;
|
||||
my $sql = "SELECT `table_name` FROM INFORMATION_SCHEMA.TABLES WHERE `table_schema`='zm' AND `engine` = 'MyISAM'";
|
||||
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() );
|
||||
my $sth = $dbh->prepare_cached($sql) or die("Can't prepare '$sql': ".$dbh->errstr());
|
||||
my $res = $sth->execute() or die("Can't execute: ".$sth->errstr());
|
||||
|
||||
while( my $dbTable = $sth->fetchrow() ) {
|
||||
push @MyISAM_Tables, $dbTable;
|
||||
|
@ -333,17 +344,22 @@ if ( $interactive ) {
|
|||
$sth->finish();
|
||||
|
||||
if ( @MyISAM_Tables ) {
|
||||
print( "\nPrevious versions of ZoneMinder used the MyISAM database engine.\nHowever, the recommended database engine is InnoDB.\n");
|
||||
print( "\nHint: InnoDB tables are much less likely to be corrupted during an unclean shutdown.\n\nPress 'y' to convert your tables to InnoDB or 'n' to skip : ");
|
||||
print('
|
||||
Previous versions of ZoneMinder used the MyISAM database engine.
|
||||
However, the recommended database engine is InnoDB.
|
||||
|
||||
Hint: InnoDB tables are much less likely to be corrupted during an unclean shutdown.
|
||||
|
||||
Press \'y\' to convert your tables to InnoDB or \'n\' to skip : ');
|
||||
my $response = <STDIN>;
|
||||
chomp( $response );
|
||||
if ( $response =~ /^[yY]$/ ) {
|
||||
$dbh->do(q|SET sql_mode='traditional'|); # Elevate warnings to errors
|
||||
print "\nConverting MyISAM tables to InnoDB. Please wait.\n";
|
||||
foreach (@MyISAM_Tables) {
|
||||
print "\nConverting MyISAM tables to InnoDB. Please wait.\n";
|
||||
foreach ( @MyISAM_Tables ) {
|
||||
my $sql = "ALTER TABLE `$_` ENGINE = InnoDB";
|
||||
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() );
|
||||
my $sth = $dbh->prepare_cached($sql) or die("Can't prepare '$sql': ".$dbh->errstr());
|
||||
my $res = $sth->execute() or die("Can't execute: ".$sth->errstr());
|
||||
$sth->finish();
|
||||
}
|
||||
$dbh->do(q|SET sql_mode=''|); # Set mode back to default
|
||||
|
@ -360,23 +376,31 @@ if ( $version ) {
|
|||
exit(0);
|
||||
}
|
||||
|
||||
print( "\nInitiating database upgrade to version ".ZM_VERSION." from version $version\n" );
|
||||
my $start_zm = 0;
|
||||
print("\nInitiating database upgrade to version ".ZM_VERSION." from version $version\n");
|
||||
if ( $interactive ) {
|
||||
if ( $Config{ZM_DYN_DB_VERSION} && $Config{ZM_DYN_DB_VERSION} ne $version ) {
|
||||
print( "\nWARNING - You have specified an upgrade from version $version but the database version found is ".$Config{ZM_DYN_DB_VERSION}.". Is this correct?\nPress enter to continue or ctrl-C to abort : " );
|
||||
if ( $Config{ZM_DYN_DB_VERSION} && ($Config{ZM_DYN_DB_VERSION} ne $version) ) {
|
||||
print("\nWARNING - You have specified an upgrade from version $version but the database version found is $Config{ZM_DYN_DB_VERSION}. Is this correct?\nPress enter to continue or ctrl-C to abort : ");
|
||||
my $response = <STDIN>;
|
||||
}
|
||||
|
||||
print( "\nPlease ensure that ZoneMinder is stopped on your system prior to upgrading the database.\nPress enter to continue or ctrl-C to stop : " );
|
||||
my $response = <STDIN>;
|
||||
if ( systemStatus() eq 'running' ) {
|
||||
print"\nZoneMinder system appears to be running. While not strictly required, it is advised to stop ZM during the update process. Would you like to stop ZM now? [Yn]:";
|
||||
my $response = <STDIN>;
|
||||
chomp($response);
|
||||
if ( $response !~ /Yy/ ) {
|
||||
packageControl('stop');
|
||||
$start_zm = 1;
|
||||
}
|
||||
}
|
||||
|
||||
print( "\nDo you wish to take a backup of your database prior to upgrading?\nThis may result in a large file in @ZM_TMPDIR@ if you have a lot of events.\nPress 'y' for a backup or 'n' to continue : " );
|
||||
$response = <STDIN>;
|
||||
chomp( $response );
|
||||
print("\nDo you wish to take a backup of your database prior to upgrading?\nThis may result in a large file in @ZM_TMPDIR@ if you have a lot of events.\nPress 'y' for a backup or 'n' to continue : ");
|
||||
my $response = <STDIN>;
|
||||
chomp($response);
|
||||
while ( $response !~ /^[yYnN]$/ ) {
|
||||
print( "Please press 'y' for a backup or 'n' to continue only : " );
|
||||
print("Please press 'y' for a backup or 'n' to continue only : ");
|
||||
$response = <STDIN>;
|
||||
chomp( $response );
|
||||
chomp($response);
|
||||
}
|
||||
|
||||
if ( $response =~ /^[yY]$/ ) {
|
||||
|
@ -384,21 +408,22 @@ if ( $version ) {
|
|||
my $command = 'mysqldump';
|
||||
if ( defined($portOrSocket) ) {
|
||||
if ( $portOrSocket =~ /^\// ) {
|
||||
$command .= " -S".$portOrSocket;
|
||||
$command .= ' -S'.$portOrSocket;
|
||||
} else {
|
||||
$command .= " -h".$host." -P".$portOrSocket;
|
||||
$command .= ' -h'.$host.' -P'.$portOrSocket;
|
||||
}
|
||||
} else {
|
||||
$command .= " -h".$host;
|
||||
$command .= ' -h'.$host;
|
||||
}
|
||||
if ( $dbUser ) {
|
||||
$command .= ' -u'.$dbUser;
|
||||
$command .= ' -p"'.$dbPass.'"' if $dbPass;
|
||||
$command .= ' -p\''.$dbPass.'\'' if $dbPass;
|
||||
}
|
||||
my $backup = "@ZM_TMPDIR@/".$Config{ZM_DB_NAME}."-".$version.".dump";
|
||||
$command .= " --add-drop-table --databases ".$Config{ZM_DB_NAME}." > ".$backup;
|
||||
print( "Creating backup to $backup. This may take several minutes.\n" );
|
||||
print( "Executing '$command'\n" ) if ( logDebugging() );
|
||||
my $backup = '@ZM_TMPDIR@/'.$Config{ZM_DB_NAME}.'-'.$version.'.dump';
|
||||
$command .= ' --add-drop-table --databases '.$Config{ZM_DB_NAME}.' > '.$backup;
|
||||
print("Creating backup to $backup. This may take several minutes.\n");
|
||||
($command) = $command =~ /(.*)/; # detaint
|
||||
print("Executing '$command'\n") if logDebugging();
|
||||
my $output = qx($command);
|
||||
my $status = $? >> 8;
|
||||
if ( $status || logDebugging() ) {
|
||||
|
@ -933,7 +958,12 @@ if ( $version ) {
|
|||
#my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
#my $res = $sth->execute( ) or die( "Can't execute: ".$sth->errstr() );
|
||||
#$sth->finish();
|
||||
|
||||
print("\nDatabase upgrade to version ".ZM_VERSION." successful.\n\n");
|
||||
if ( $start_zm ) {
|
||||
print("Starting ZM since we stopped it for the update\n");
|
||||
packageControl('start');
|
||||
}
|
||||
} # end if version
|
||||
|
||||
zmDbDisconnect();
|
||||
|
@ -969,7 +999,7 @@ sub patchDB {
|
|||
my $dbh = shift;
|
||||
my $version = shift;
|
||||
|
||||
my ( $host, $portOrSocket ) = ( $Config{ZM_DB_HOST} =~ /^([^:]+)(?::(.+))?$/ );
|
||||
my ( $host, $portOrSocket ) = ( $Config{ZM_DB_HOST} =~ /^([^:]+)(?::(.+))?$/ ) if $Config{ZM_DB_HOST};
|
||||
my $command = 'mysql';
|
||||
if ( defined($portOrSocket) ) {
|
||||
if ( $portOrSocket =~ /^\// ) {
|
||||
|
@ -977,12 +1007,12 @@ sub patchDB {
|
|||
} else {
|
||||
$command .= ' -h'.$host.' -P'.$portOrSocket;
|
||||
}
|
||||
} else {
|
||||
} elsif ( $host ) {
|
||||
$command .= ' -h'.$host;
|
||||
}
|
||||
if ( $dbUser ) {
|
||||
$command .= ' -u'.$dbUser;
|
||||
$command .= ' -p"'.$dbPass.'"' if $dbPass;
|
||||
$command .= ' -p\''.$dbPass.'\'' if $dbPass;
|
||||
}
|
||||
$command .= ' '.$Config{ZM_DB_NAME}.' < ';
|
||||
if ( $updateDir ) {
|
||||
|
@ -993,6 +1023,7 @@ sub patchDB {
|
|||
$command .= '/zm_update-'.$version.'.sql';
|
||||
|
||||
print("Executing '$command'\n") if logDebugging();
|
||||
($command) = $command =~ /(.*)/; # detaint
|
||||
my $output = qx($command);
|
||||
my $status = $? >> 8;
|
||||
if ( $status || logDebugging() ) {
|
||||
|
|
|
@ -976,10 +976,12 @@ int FfmpegCamera::CaptureAndRecord(
|
|||
return -1;
|
||||
}
|
||||
#if HAVE_LIBAVUTIL_HWCONTEXT_H
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 89, 0, 89, 0)
|
||||
if ( (ret == AVERROR_INVALIDDATA ) && (hw_pix_fmt != AV_PIX_FMT_NONE) ) {
|
||||
use_hwaccel = false;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
zm_av_packet_unref(&packet);
|
||||
|
|
|
@ -1905,11 +1905,11 @@ void Image::MaskPrivacy( const unsigned char *p_bitmask, const Rgb pixel_colour
|
|||
/* RGB32 compatible: complete */
|
||||
void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int size, const Rgb fg_colour, const Rgb bg_colour )
|
||||
{
|
||||
strncpy( text, p_text, sizeof(text)-1 );
|
||||
strncpy(text, p_text, sizeof(text)-1);
|
||||
|
||||
unsigned int index = 0;
|
||||
unsigned int line_no = 0;
|
||||
unsigned int text_len = strlen( text );
|
||||
unsigned int text_len = strlen(text);
|
||||
unsigned int line_len = 0;
|
||||
const char *line = text;
|
||||
|
||||
|
@ -1928,10 +1928,10 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int
|
|||
const bool bg_trans = (bg_colour == RGB_TRANSPARENT);
|
||||
|
||||
int zm_text_bitmask = 0x80;
|
||||
if (size == 2)
|
||||
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;
|
||||
|
||||
|
@ -1967,10 +1967,19 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int
|
|||
unsigned char *temp_ptr = ptr;
|
||||
for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) {
|
||||
int f;
|
||||
if (size == 2)
|
||||
if ( size == 2 ) {
|
||||
if ( (line[c] * ZM_CHAR_HEIGHT * size) + r > sizeof(bigfontdata) ) {
|
||||
Warning("Unsupported character %c in %s", line[c], line);
|
||||
continue;
|
||||
}
|
||||
f = bigfontdata[(line[c] * ZM_CHAR_HEIGHT * size) + r];
|
||||
else
|
||||
} else {
|
||||
if ( (line[c] * ZM_CHAR_HEIGHT) + r > sizeof(fontdata) ) {
|
||||
Warning("Unsupported character %c in %s", line[c], line);
|
||||
continue;
|
||||
}
|
||||
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 )
|
||||
|
@ -1989,10 +1998,19 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int
|
|||
unsigned char *temp_ptr = ptr;
|
||||
for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) {
|
||||
int f;
|
||||
if (size == 2)
|
||||
if ( size == 2 ) {
|
||||
if ( (line[c] * ZM_CHAR_HEIGHT * size) + r > sizeof(bigfontdata) ) {
|
||||
Warning("Unsupported character %c in %s", line[c], line);
|
||||
continue;
|
||||
}
|
||||
f = bigfontdata[(line[c] * ZM_CHAR_HEIGHT * size) + r];
|
||||
else
|
||||
} else {
|
||||
if ( (line[c] * ZM_CHAR_HEIGHT) + r > sizeof(fontdata) ) {
|
||||
Warning("Unsupported character %c in %s", line[c], line);
|
||||
continue;
|
||||
}
|
||||
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 ) {
|
||||
|
@ -2016,10 +2034,19 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int
|
|||
Rgb* temp_ptr = (Rgb*)ptr;
|
||||
for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) {
|
||||
int f;
|
||||
if (size == 2)
|
||||
if ( size == 2 ) {
|
||||
if ( (line[c] * ZM_CHAR_HEIGHT * size) + r > sizeof(bigfontdata) ) {
|
||||
Warning("Unsupported character %c in %s", line[c], line);
|
||||
continue;
|
||||
}
|
||||
f = bigfontdata[(line[c] * ZM_CHAR_HEIGHT * size) + r];
|
||||
else
|
||||
} else {
|
||||
if ( (line[c] * ZM_CHAR_HEIGHT) + r > sizeof(fontdata) ) {
|
||||
Warning("Unsupported character %c in %s", line[c], line);
|
||||
continue;
|
||||
}
|
||||
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 ) {
|
||||
|
|
|
@ -1274,56 +1274,62 @@ uint32_t LocalCamera::AutoSelectFormat(int p_colours) {
|
|||
#define capString(test,prefix,yesString,noString,capability) \
|
||||
(test) ? (prefix yesString " " capability "\n") : (prefix noString " " capability "\n")
|
||||
|
||||
bool LocalCamera::GetCurrentSettings( const char *device, char *output, int version, bool verbose ) {
|
||||
bool LocalCamera::GetCurrentSettings(const char *device, char *output, int version, bool verbose) {
|
||||
output[0] = 0;
|
||||
char *output_ptr = output;
|
||||
|
||||
char queryDevice[PATH_MAX] = "";
|
||||
int devIndex = 0;
|
||||
do {
|
||||
if ( device )
|
||||
if ( device ) {
|
||||
strncpy(queryDevice, device, sizeof(queryDevice)-1);
|
||||
else
|
||||
} else {
|
||||
sprintf(queryDevice, "/dev/video%d", devIndex);
|
||||
}
|
||||
|
||||
if ( (vid_fd = open(queryDevice, O_RDWR)) <= 0 ) {
|
||||
if ( device ) {
|
||||
Error("Failed to open video device %s: %s", queryDevice, strerror(errno));
|
||||
if ( verbose )
|
||||
sprintf(output+strlen(output), "Error, failed to open video device %s: %s\n",
|
||||
output_ptr += sprintf(output_ptr, "Error, failed to open video device %s: %s\n",
|
||||
queryDevice, strerror(errno));
|
||||
else
|
||||
sprintf(output+strlen(output), "error%d\n", errno);
|
||||
output_ptr += sprintf(output_ptr, "error%d\n", errno);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if ( verbose )
|
||||
sprintf(output+strlen(output), "Video Device: %s\n", queryDevice);
|
||||
else
|
||||
sprintf(output+strlen(output), "d:%s|", queryDevice);
|
||||
if ( verbose ) {
|
||||
output_ptr += sprintf(output_ptr, "Video Device: %s\n", queryDevice);
|
||||
} else {
|
||||
output_ptr += sprintf(output_ptr, "d:%s|", queryDevice);
|
||||
}
|
||||
|
||||
#if ZM_HAS_V4L2
|
||||
if ( version == 2 ) {
|
||||
struct v4l2_capability vid_cap;
|
||||
if ( vidioctl(vid_fd, VIDIOC_QUERYCAP, &vid_cap) < 0 ) {
|
||||
Error("Failed to query video device: %s", strerror(errno));
|
||||
if ( verbose )
|
||||
sprintf(output, "Error, failed to query video capabilities %s: %s\n",
|
||||
if ( verbose ) {
|
||||
output_ptr += sprintf(output_ptr, "Error, failed to query video capabilities %s: %s\n",
|
||||
queryDevice, strerror(errno));
|
||||
else
|
||||
sprintf(output, "error%d\n", errno);
|
||||
return false;
|
||||
} else {
|
||||
output_ptr += sprintf(output_ptr, "error%d\n", errno);
|
||||
}
|
||||
if ( device )
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( verbose ) {
|
||||
sprintf(output+strlen(output), "General Capabilities\n");
|
||||
sprintf(output+strlen(output), " Driver: %s\n", vid_cap.driver);
|
||||
sprintf(output+strlen(output), " Card: %s\n", vid_cap.card);
|
||||
sprintf(output+strlen(output), " Bus: %s\n", vid_cap.bus_info);
|
||||
sprintf(output+strlen(output), " Version: %u.%u.%u\n",
|
||||
(vid_cap.version>>16)&0xff, (vid_cap.version>>8)&0xff, vid_cap.version&0xff);
|
||||
sprintf(output+strlen(output), " Type: 0x%x\n%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
|
||||
output_ptr += sprintf(output_ptr, "General Capabilities\n"
|
||||
" Driver: %s\n"
|
||||
" Card: %s\n"
|
||||
" Bus: %s\n"
|
||||
" Version: %u.%u.%u\n"
|
||||
" Type: 0x%x\n%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
|
||||
vid_cap.driver, vid_cap.card, vid_cap.bus_info,
|
||||
(vid_cap.version>>16)&0xff, (vid_cap.version>>8)&0xff, vid_cap.version&0xff,
|
||||
vid_cap.capabilities,
|
||||
capString(vid_cap.capabilities&V4L2_CAP_VIDEO_CAPTURE, " ", "Supports", "Does not support", "video capture (X)"),
|
||||
capString(vid_cap.capabilities&V4L2_CAP_VIDEO_OUTPUT, " ", "Supports", "Does not support", "video output"),
|
||||
|
@ -1345,17 +1351,16 @@ bool LocalCamera::GetCurrentSettings( const char *device, char *output, int vers
|
|||
capString(vid_cap.capabilities&V4L2_CAP_STREAMING, " ", "Supports", "Does not support", "streaming i/o (X)")
|
||||
);
|
||||
} else {
|
||||
sprintf(output+strlen(output), "D:%s|", vid_cap.driver);
|
||||
sprintf(output+strlen(output), "C:%s|", vid_cap.card);
|
||||
sprintf(output+strlen(output), "B:%s|", vid_cap.bus_info);
|
||||
sprintf(output+strlen(output), "V:%u.%u.%u|", (vid_cap.version>>16)&0xff, (vid_cap.version>>8)&0xff, vid_cap.version&0xff);
|
||||
sprintf(output+strlen(output), "T:0x%x|", vid_cap.capabilities);
|
||||
output_ptr += sprintf(output_ptr, "D:%s|C:%s|B:%s|V:%u.%u.%u|T:0x%x|"
|
||||
, vid_cap.driver
|
||||
, vid_cap.card
|
||||
, vid_cap.bus_info
|
||||
, (vid_cap.version>>16)&0xff, (vid_cap.version>>8)&0xff, vid_cap.version&0xff
|
||||
, vid_cap.capabilities);
|
||||
}
|
||||
|
||||
if ( verbose )
|
||||
sprintf(output+strlen(output), " Standards:\n");
|
||||
else
|
||||
sprintf(output+strlen(output), "S:");
|
||||
output_ptr += sprintf(output_ptr, verbose ? " Standards:\n" : "S:");
|
||||
|
||||
struct v4l2_standard standard;
|
||||
int standardIndex = 0;
|
||||
do {
|
||||
|
@ -1370,25 +1375,20 @@ bool LocalCamera::GetCurrentSettings( const char *device, char *output, int vers
|
|||
} else {
|
||||
Error("Failed to enumerate standard %d: %d %s", standard.index, errno, strerror(errno));
|
||||
if ( verbose )
|
||||
sprintf(output, "Error, failed to enumerate standard %d: %d %s\n", standard.index, errno, strerror(errno));
|
||||
output_ptr += sprintf(output_ptr, "Error, failed to enumerate standard %d: %d %s\n", standard.index, errno, strerror(errno));
|
||||
else
|
||||
sprintf(output, "error%d\n", errno);
|
||||
output_ptr += sprintf(output_ptr, "error%d\n", errno);
|
||||
// Why return? Why not continue trying other things?
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ( verbose )
|
||||
sprintf(output+strlen(output), " %s\n", standard.name);
|
||||
else
|
||||
sprintf(output+strlen(output), "%s/", standard.name);
|
||||
}
|
||||
while ( standardIndex++ >= 0 );
|
||||
if ( !verbose && output[strlen(output)-1] == '/')
|
||||
output[strlen(output)-1] = '|';
|
||||
output_ptr += sprintf(output_ptr, (verbose ? " %s\n" : "%s/"), standard.name);
|
||||
} while ( standardIndex++ >= 0 );
|
||||
|
||||
if ( verbose )
|
||||
sprintf(output+strlen(output), " Formats:\n");
|
||||
else
|
||||
sprintf(output+strlen(output), "F:");
|
||||
if ( !verbose && (*(output_ptr-1) == '/') )
|
||||
*(output_ptr-1) = '|';
|
||||
|
||||
output_ptr += sprintf(output_ptr, verbose ? " Formats:\n" : "F:");
|
||||
struct v4l2_fmtdesc format;
|
||||
int formatIndex = 0;
|
||||
do {
|
||||
|
@ -1403,15 +1403,15 @@ bool LocalCamera::GetCurrentSettings( const char *device, char *output, int vers
|
|||
} else {
|
||||
Error("Failed to enumerate format %d: %s", format.index, strerror(errno));
|
||||
if ( verbose )
|
||||
sprintf(output, "Error, failed to enumerate format %d: %s\n", format.index, strerror(errno));
|
||||
output_ptr += sprintf(output_ptr, "Error, failed to enumerate format %d: %s\n", format.index, strerror(errno));
|
||||
else
|
||||
sprintf(output, "error%d\n", errno);
|
||||
output_ptr += sprintf(output_ptr, "error%d\n", errno);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ( verbose )
|
||||
sprintf(
|
||||
output+strlen(output),
|
||||
output_ptr += sprintf(
|
||||
output_ptr,
|
||||
" %s (0x%02hhx%02hhx%02hhx%02hhx)\n",
|
||||
format.description,
|
||||
(format.pixelformat>>24)&0xff,
|
||||
|
@ -1419,33 +1419,34 @@ bool LocalCamera::GetCurrentSettings( const char *device, char *output, int vers
|
|||
(format.pixelformat>>8)&0xff,
|
||||
format.pixelformat&0xff);
|
||||
else
|
||||
sprintf(
|
||||
output+strlen(output),
|
||||
output_ptr += sprintf(
|
||||
output_ptr,
|
||||
"0x%02hhx%02hhx%02hhx%02hhx/",
|
||||
(format.pixelformat>>24)&0xff,
|
||||
(format.pixelformat>>16)&0xff,
|
||||
(format.pixelformat>>8)&0xff,
|
||||
(format.pixelformat)&0xff);
|
||||
} while ( formatIndex++ >= 0 );
|
||||
|
||||
if ( !verbose )
|
||||
output[strlen(output)-1] = '|';
|
||||
*(output_ptr-1) = '|';
|
||||
else
|
||||
sprintf(output+strlen(output), "Crop Capabilities\n");
|
||||
output_ptr += sprintf(output_ptr, "Crop Capabilities\n");
|
||||
|
||||
struct v4l2_cropcap cropcap;
|
||||
memset(&cropcap, 0, sizeof(cropcap));
|
||||
cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
if ( vidioctl( vid_fd, VIDIOC_CROPCAP, &cropcap ) < 0 ) {
|
||||
if ( vidioctl(vid_fd, VIDIOC_CROPCAP, &cropcap) < 0 ) {
|
||||
if ( errno != EINVAL ) {
|
||||
/* Failed querying crop capability, write error to the log and continue as if crop is not supported */
|
||||
Error("Failed to query crop capabilities: %s", strerror(errno));
|
||||
}
|
||||
|
||||
if ( verbose ) {
|
||||
sprintf(output+strlen(output), " Cropping is not supported\n");
|
||||
output_ptr += sprintf(output_ptr, " Cropping is not supported\n");
|
||||
} else {
|
||||
/* Send fake crop bounds to not confuse things parsing this, such as monitor probe */
|
||||
sprintf(output+strlen(output), "B:%dx%d|",0,0);
|
||||
output_ptr += sprintf(output_ptr, "B:%dx%d|", 0, 0);
|
||||
}
|
||||
} else {
|
||||
struct v4l2_crop crop;
|
||||
|
@ -1459,19 +1460,23 @@ bool LocalCamera::GetCurrentSettings( const char *device, char *output, int vers
|
|||
}
|
||||
|
||||
if ( verbose ) {
|
||||
sprintf(output+strlen(output), " Cropping is not supported\n");
|
||||
output_ptr += sprintf(output_ptr, " Cropping is not supported\n");
|
||||
} else {
|
||||
/* Send fake crop bounds to not confuse things parsing this, such as monitor probe */
|
||||
sprintf(output+strlen(output), "B:%dx%d|",0,0);
|
||||
output_ptr += sprintf(output_ptr, "B:%dx%d|",0,0);
|
||||
}
|
||||
} else {
|
||||
/* Cropping supported */
|
||||
if ( verbose ) {
|
||||
sprintf(output+strlen(output), " Bounds: %d x %d\n", cropcap.bounds.width, cropcap.bounds.height);
|
||||
sprintf(output+strlen(output), " Default: %d x %d\n", cropcap.defrect.width, cropcap.defrect.height);
|
||||
sprintf(output+strlen(output), " Current: %d x %d\n", crop.c.width, crop.c.height);
|
||||
output_ptr += sprintf(output_ptr,
|
||||
" Bounds: %d x %d\n"
|
||||
" Default: %d x %d\n"
|
||||
" Current: %d x %d\n"
|
||||
, cropcap.bounds.width, cropcap.bounds.height
|
||||
, cropcap.defrect.width, cropcap.defrect.height
|
||||
, crop.c.width, crop.c.height);
|
||||
} else {
|
||||
sprintf(output+strlen(output), "B:%dx%d|", cropcap.bounds.width, cropcap.bounds.height);
|
||||
output_ptr += sprintf(output_ptr, "B:%dx%d|", cropcap.bounds.width, cropcap.bounds.height);
|
||||
}
|
||||
}
|
||||
} /* Crop code */
|
||||
|
@ -1488,17 +1493,14 @@ bool LocalCamera::GetCurrentSettings( const char *device, char *output, int vers
|
|||
}
|
||||
Error("Failed to enumerate input %d: %s", input.index, strerror(errno));
|
||||
if ( verbose )
|
||||
sprintf(output, "Error, failed to enumerate input %d: %s\n", input.index, strerror(errno));
|
||||
output_ptr += sprintf(output_ptr, "Error, failed to enumerate input %d: %s\n", input.index, strerror(errno));
|
||||
else
|
||||
sprintf(output, "error%d\n", errno);
|
||||
output_ptr += sprintf(output_ptr, "error%d\n", errno);
|
||||
return false;
|
||||
}
|
||||
} while ( inputIndex++ >= 0 );
|
||||
|
||||
if ( verbose )
|
||||
sprintf(output+strlen(output), "Inputs: %d\n", inputIndex);
|
||||
else
|
||||
sprintf(output+strlen(output), "I:%d|", inputIndex);
|
||||
output_ptr += sprintf(output_ptr, verbose?"Inputs: %d\n":"I:%d|", inputIndex);
|
||||
|
||||
inputIndex = 0;
|
||||
do {
|
||||
|
@ -1512,65 +1514,84 @@ bool LocalCamera::GetCurrentSettings( const char *device, char *output, int vers
|
|||
}
|
||||
Error("Failed to enumerate input %d: %s", input.index, strerror(errno));
|
||||
if ( verbose )
|
||||
sprintf(output, "Error, failed to enumerate input %d: %s\n", input.index, strerror(errno));
|
||||
output_ptr += sprintf(output_ptr, "Error, failed to enumerate input %d: %s\n", input.index, strerror(errno));
|
||||
else
|
||||
sprintf(output, "error%d\n", errno);
|
||||
output_ptr += sprintf(output_ptr, "error%d\n", errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( vidioctl(vid_fd, VIDIOC_S_INPUT, &input.index) < 0 ) {
|
||||
Error("Failed to set video input %d: %s", input.index, strerror(errno));
|
||||
if ( verbose )
|
||||
sprintf(output, "Error, failed to switch to input %d: %s\n", input.index, strerror(errno));
|
||||
output_ptr += sprintf(output_ptr, "Error, failed to switch to input %d: %s\n", input.index, strerror(errno));
|
||||
else
|
||||
sprintf(output, "error%d\n", errno);
|
||||
output_ptr += sprintf(output_ptr, "error%d\n", errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( verbose ) {
|
||||
sprintf( output+strlen(output), " Input %d\n", input.index );
|
||||
sprintf( output+strlen(output), " Name: %s\n", input.name );
|
||||
sprintf( output+strlen(output), " Type: %s\n", input.type==V4L2_INPUT_TYPE_TUNER?"Tuner":(input.type==V4L2_INPUT_TYPE_CAMERA?"Camera":"Unknown") );
|
||||
sprintf( output+strlen(output), " Audioset: %08x\n", input.audioset );
|
||||
sprintf( output+strlen(output), " Standards: 0x%llx\n", input.std );
|
||||
output_ptr += sprintf( output,
|
||||
" Input %d\n"
|
||||
" Name: %s\n"
|
||||
" Type: %s\n"
|
||||
" Audioset: %08x\n"
|
||||
" Standards: 0x%llx\n"
|
||||
, input.index
|
||||
, input.name
|
||||
, input.type==V4L2_INPUT_TYPE_TUNER?"Tuner":(input.type==V4L2_INPUT_TYPE_CAMERA?"Camera":"Unknown")
|
||||
, input.audioset
|
||||
, input.std );
|
||||
} else {
|
||||
sprintf( output+strlen(output), "i%d:%s|", input.index, input.name );
|
||||
sprintf( output+strlen(output), "i%dT:%s|", input.index, input.type==V4L2_INPUT_TYPE_TUNER?"Tuner":(input.type==V4L2_INPUT_TYPE_CAMERA?"Camera":"Unknown") );
|
||||
sprintf( output+strlen(output), "i%dS:%llx|", input.index, input.std );
|
||||
output_ptr += sprintf( output_ptr, "i%d:%s|i%dT:%s|i%dS:%llx|"
|
||||
, input.index, input.name
|
||||
, input.index, input.type==V4L2_INPUT_TYPE_TUNER?"Tuner":(input.type==V4L2_INPUT_TYPE_CAMERA?"Camera":"Unknown")
|
||||
, input.index, input.std);
|
||||
}
|
||||
|
||||
if ( verbose ) {
|
||||
sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_POWER, "Power ", "off", "on", " (X)" ) );
|
||||
sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_SIGNAL, "Signal ", "not detected", "detected", " (X)" ) );
|
||||
sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_COLOR, "Colour Signal ", "not detected", "detected", "" ) );
|
||||
sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_H_LOCK, "Horizontal Lock ", "not detected", "detected", "" ) );
|
||||
output_ptr += sprintf( output_ptr, " %s %s %s %s"
|
||||
, capString(input.status&V4L2_IN_ST_NO_POWER, "Power ", "off", "on", " (X)")
|
||||
, capString(input.status&V4L2_IN_ST_NO_SIGNAL, "Signal ", "not detected", "detected", " (X)")
|
||||
, capString(input.status&V4L2_IN_ST_NO_COLOR, "Colour Signal ", "not detected", "detected", "")
|
||||
, capString(input.status&V4L2_IN_ST_NO_H_LOCK, "Horizontal Lock ", "not detected", "detected", ""));
|
||||
} else {
|
||||
sprintf( output+strlen(output), "i%dSP:%d|", input.index, (input.status&V4L2_IN_ST_NO_POWER)?0:1 );
|
||||
sprintf( output+strlen(output), "i%dSS:%d|", input.index, (input.status&V4L2_IN_ST_NO_SIGNAL)?0:1 );
|
||||
sprintf( output+strlen(output), "i%dSC:%d|", input.index, (input.status&V4L2_IN_ST_NO_COLOR)?0:1 );
|
||||
sprintf( output+strlen(output), "i%dHP:%d|", input.index, (input.status&V4L2_IN_ST_NO_H_LOCK)?0:1 );
|
||||
output_ptr += sprintf( output_ptr, "i%dSP:%d|i%dSS:%d|i%dSC:%d|i%dHP:%d|"
|
||||
, input.index, (input.status&V4L2_IN_ST_NO_POWER)?0:1
|
||||
, input.index, (input.status&V4L2_IN_ST_NO_SIGNAL)?0:1
|
||||
, input.index, (input.status&V4L2_IN_ST_NO_COLOR)?0:1
|
||||
, input.index, (input.status&V4L2_IN_ST_NO_H_LOCK)?0:1 );
|
||||
}
|
||||
} while ( inputIndex++ >= 0 );
|
||||
if ( !verbose )
|
||||
output[strlen(output)-1] = '\n';
|
||||
*(output_ptr-1) = '\n';
|
||||
}
|
||||
#endif // ZM_HAS_V4L2
|
||||
#if ZM_HAS_V4L1
|
||||
if ( version == 1 ) {
|
||||
struct video_capability vid_cap;
|
||||
memset( &vid_cap, 0, sizeof(video_capability) );
|
||||
if ( ioctl( vid_fd, VIDIOCGCAP, &vid_cap ) < 0 ) {
|
||||
Error( "Failed to get video capabilities: %s", strerror(errno) );
|
||||
memset(&vid_cap, 0, sizeof(video_capability));
|
||||
if ( ioctl(vid_fd, VIDIOCGCAP, &vid_cap) < 0 ) {
|
||||
Error("Failed to get video capabilities: %s", strerror(errno));
|
||||
if ( verbose )
|
||||
sprintf( output, "Error, failed to get video capabilities %s: %s\n", queryDevice, strerror(errno) );
|
||||
output_ptr += sprintf(output_ptr,
|
||||
"Error, failed to get video capabilities %s: %s\n",
|
||||
queryDevice, strerror(errno));
|
||||
else
|
||||
sprintf( output, "error%d\n", errno );
|
||||
return( false );
|
||||
output_ptr += sprintf(output_ptr, "error%d\n", errno);
|
||||
return false;
|
||||
}
|
||||
if ( verbose ) {
|
||||
sprintf( output+strlen(output), "Video Capabilities\n" );
|
||||
sprintf( output+strlen(output), " Name: %s\n", vid_cap.name );
|
||||
sprintf( output+strlen(output), " Type: %d\n%s%s%s%s%s%s%s%s%s%s%s%s%s%s", vid_cap.type,
|
||||
output_ptr += sprintf( output_ptr, "Video Capabilities\n"
|
||||
" Name: %s\n"
|
||||
" Type: %d\n%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
|
||||
" Video Channels: %d\n"
|
||||
" Audio Channels: %d\n"
|
||||
" Maximum Width: %d\n"
|
||||
" Maximum Height: %d\n"
|
||||
" Minimum Width: %d\n"
|
||||
" Minimum Height: %d\n",
|
||||
vid_cap.name,
|
||||
vid_cap.type,
|
||||
(vid_cap.type&VID_TYPE_CAPTURE)?" Can capture\n":"",
|
||||
(vid_cap.type&VID_TYPE_TUNER)?" Can tune\n":"",
|
||||
(vid_cap.type&VID_TYPE_TELETEXT)?" Does teletext\n":"",
|
||||
|
@ -1584,63 +1605,72 @@ bool LocalCamera::GetCurrentSettings( const char *device, char *output, int vers
|
|||
(vid_cap.type&VID_TYPE_MPEG_DECODER)?" Can decode MPEG streams\n":"",
|
||||
(vid_cap.type&VID_TYPE_MPEG_ENCODER)?" Can encode MPEG streams\n":"",
|
||||
(vid_cap.type&VID_TYPE_MJPEG_DECODER)?" Can decode MJPEG streams\n":"",
|
||||
(vid_cap.type&VID_TYPE_MJPEG_ENCODER)?" Can encode MJPEG streams\n":""
|
||||
);
|
||||
sprintf( output+strlen(output), " Video Channels: %d\n", vid_cap.channels );
|
||||
sprintf( output+strlen(output), " Audio Channels: %d\n", vid_cap.audios );
|
||||
sprintf( output+strlen(output), " Maximum Width: %d\n", vid_cap.maxwidth );
|
||||
sprintf( output+strlen(output), " Maximum Height: %d\n", vid_cap.maxheight );
|
||||
sprintf( output+strlen(output), " Minimum Width: %d\n", vid_cap.minwidth );
|
||||
sprintf( output+strlen(output), " Minimum Height: %d\n", vid_cap.minheight );
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf( output+strlen(output), "N:%s|", vid_cap.name );
|
||||
sprintf( output+strlen(output), "T:%d|", vid_cap.type );
|
||||
sprintf( output+strlen(output), "nC:%d|", vid_cap.channels );
|
||||
sprintf( output+strlen(output), "nA:%d|", vid_cap.audios );
|
||||
sprintf( output+strlen(output), "mxW:%d|", vid_cap.maxwidth );
|
||||
sprintf( output+strlen(output), "mxH:%d|", vid_cap.maxheight );
|
||||
sprintf( output+strlen(output), "mnW:%d|", vid_cap.minwidth );
|
||||
sprintf( output+strlen(output), "mnH:%d|", vid_cap.minheight );
|
||||
(vid_cap.type&VID_TYPE_MJPEG_ENCODER)?" Can encode MJPEG streams\n":"",
|
||||
vid_cap.channels,
|
||||
vid_cap.audios,
|
||||
vid_cap.maxwidth,
|
||||
vid_cap.maxheight,
|
||||
vid_cap.minwidth,
|
||||
vid_cap.minheight );
|
||||
} else {
|
||||
output_ptr += sprintf(output_ptr, "N:%s|T:%d|nC:%d|nA:%d|mxW:%d|mxH:%d|mnW:%d|mnH:%d|"
|
||||
, vid_cap.name
|
||||
, vid_cap.type
|
||||
, vid_cap.channels
|
||||
, vid_cap.audios
|
||||
, vid_cap.maxwidth
|
||||
, vid_cap.maxheight
|
||||
, vid_cap.minwidth
|
||||
, vid_cap.minheight);
|
||||
}
|
||||
|
||||
struct video_window vid_win;
|
||||
memset( &vid_win, 0, sizeof(video_window) );
|
||||
if ( ioctl( vid_fd, VIDIOCGWIN, &vid_win ) < 0 ) {
|
||||
Error( "Failed to get window attributes: %s", strerror(errno) );
|
||||
memset(&vid_win, 0, sizeof(video_window));
|
||||
if ( ioctl(vid_fd, VIDIOCGWIN, &vid_win) < 0 ) {
|
||||
Error("Failed to get window attributes: %s", strerror(errno));
|
||||
if ( verbose )
|
||||
sprintf( output, "Error, failed to get window attributes: %s\n", strerror(errno) );
|
||||
output_ptr += sprintf(output_ptr, "Error, failed to get window attributes: %s\n", strerror(errno));
|
||||
else
|
||||
sprintf( output, "error%d\n", errno );
|
||||
output_ptr += sprintf(output_ptr, "error%d\n", errno);
|
||||
return false;
|
||||
}
|
||||
if ( verbose ) {
|
||||
sprintf( output+strlen(output), "Window Attributes\n" );
|
||||
sprintf( output+strlen(output), " X Offset: %d\n", vid_win.x );
|
||||
sprintf( output+strlen(output), " Y Offset: %d\n", vid_win.y );
|
||||
sprintf( output+strlen(output), " Width: %d\n", vid_win.width );
|
||||
sprintf( output+strlen(output), " Height: %d\n", vid_win.height );
|
||||
output_ptr += sprintf(output_ptr,
|
||||
"Window Attributes\n"
|
||||
" X Offset: %d\n"
|
||||
" Y Offset: %d\n"
|
||||
" Width: %d\n"
|
||||
" Height: %d\n"
|
||||
, vid_win.x
|
||||
, vid_win.y
|
||||
, vid_win.width
|
||||
, vid_win.height );
|
||||
} else {
|
||||
sprintf( output+strlen(output), "X:%d|", vid_win.x );
|
||||
sprintf( output+strlen(output), "Y:%d|", vid_win.y );
|
||||
sprintf( output+strlen(output), "W:%d|", vid_win.width );
|
||||
sprintf( output+strlen(output), "H:%d|", vid_win.height );
|
||||
output_ptr += sprintf(output_ptr, "X:%d|Y:%d|W:%d|H:%d|",
|
||||
vid_win.height, vid_win.x, vid_win.y, vid_win.width);
|
||||
}
|
||||
|
||||
struct video_picture vid_pic;
|
||||
memset( &vid_pic, 0, sizeof(video_picture) );
|
||||
if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic ) < 0 ) {
|
||||
Error( "Failed to get picture attributes: %s", strerror(errno) );
|
||||
memset(&vid_pic, 0, sizeof(video_picture));
|
||||
if ( ioctl(vid_fd, VIDIOCGPICT, &vid_pic) < 0 ) {
|
||||
Error("Failed to get picture attributes: %s", strerror(errno));
|
||||
if ( verbose )
|
||||
sprintf( output, "Error, failed to get picture attributes: %s\n", strerror(errno) );
|
||||
output_ptr += sprintf(output_ptr, "Error, failed to get picture attributes: %s\n", strerror(errno));
|
||||
else
|
||||
sprintf( output, "error%d\n", errno );
|
||||
output_ptr += sprintf(output_ptr, "error%d\n", errno);
|
||||
return false;
|
||||
}
|
||||
if ( verbose ) {
|
||||
sprintf( output+strlen(output), "Picture Attributes\n" );
|
||||
sprintf( output+strlen(output), " Palette: %d - %s\n", vid_pic.palette,
|
||||
output_ptr += sprintf(output_ptr,
|
||||
"Picture Attributes\n"
|
||||
" Palette: %d - %s\n"
|
||||
" Colour Depth: %d\n"
|
||||
" Brightness: %d\n"
|
||||
" Hue: %d\n"
|
||||
" Colour :%d\n"
|
||||
" Contrast: %d\n"
|
||||
" Whiteness: %d\n"
|
||||
, vid_pic.palette,
|
||||
vid_pic.palette==VIDEO_PALETTE_GREY?"Linear greyscale":(
|
||||
vid_pic.palette==VIDEO_PALETTE_HI240?"High 240 cube (BT848)":(
|
||||
vid_pic.palette==VIDEO_PALETTE_RGB565?"565 16 bit RGB":(
|
||||
|
@ -1659,66 +1689,77 @@ bool LocalCamera::GetCurrentSettings( const char *device, char *output, int vers
|
|||
vid_pic.palette==VIDEO_PALETTE_YUV411P?"YUV 4:1:1 Planar":(
|
||||
vid_pic.palette==VIDEO_PALETTE_YUV420P?"YUV 4:2:0 Planar":(
|
||||
vid_pic.palette==VIDEO_PALETTE_YUV410P?"YUV 4:1:0 Planar":"Unknown"
|
||||
))))))))))))))))));
|
||||
sprintf( output+strlen(output), " Colour Depth: %d\n", vid_pic.depth );
|
||||
sprintf( output+strlen(output), " Brightness: %d\n", vid_pic.brightness );
|
||||
sprintf( output+strlen(output), " Hue: %d\n", vid_pic.hue );
|
||||
sprintf( output+strlen(output), " Colour :%d\n", vid_pic.colour );
|
||||
sprintf( output+strlen(output), " Contrast: %d\n", vid_pic.contrast );
|
||||
sprintf( output+strlen(output), " Whiteness: %d\n", vid_pic.whiteness );
|
||||
))))))))))))))))),
|
||||
vid_pic.depth,
|
||||
vid_pic.brightness,
|
||||
vid_pic.hue,
|
||||
vid_pic.colour,
|
||||
vid_pic.contrast,
|
||||
vid_pic.whiteness
|
||||
);
|
||||
} else {
|
||||
sprintf( output+strlen(output), "P:%d|", vid_pic.palette );
|
||||
sprintf( output+strlen(output), "D:%d|", vid_pic.depth );
|
||||
sprintf( output+strlen(output), "B:%d|", vid_pic.brightness );
|
||||
sprintf( output+strlen(output), "h:%d|", vid_pic.hue );
|
||||
sprintf( output+strlen(output), "Cl:%d|", vid_pic.colour );
|
||||
sprintf( output+strlen(output), "Cn:%d|", vid_pic.contrast );
|
||||
sprintf( output+strlen(output), "w:%d|", vid_pic.whiteness );
|
||||
output_ptr += sprintf(output_ptr, "P:%d|D:%d|B:%d|h:%d|Cl:%d|Cn:%d|w:%d|",
|
||||
vid_pic.palette,
|
||||
vid_pic.depth,
|
||||
vid_pic.brightness,
|
||||
vid_pic.hue,
|
||||
vid_pic.colour,
|
||||
vid_pic.contrast,
|
||||
vid_pic.whiteness
|
||||
);
|
||||
}
|
||||
|
||||
for ( int chan = 0; chan < vid_cap.channels; chan++ ) {
|
||||
struct video_channel vid_src;
|
||||
memset( &vid_src, 0, sizeof(video_channel) );
|
||||
memset(&vid_src, 0, sizeof(video_channel));
|
||||
vid_src.channel = chan;
|
||||
if ( ioctl( vid_fd, VIDIOCGCHAN, &vid_src ) < 0 ) {
|
||||
Error( "Failed to get channel %d attributes: %s", chan, strerror(errno) );
|
||||
if ( ioctl(vid_fd, VIDIOCGCHAN, &vid_src) < 0 ) {
|
||||
Error("Failed to get channel %d attributes: %s", chan, strerror(errno));
|
||||
if ( verbose )
|
||||
sprintf( output, "Error, failed to get channel %d attributes: %s\n", chan, strerror(errno) );
|
||||
output_ptr += sprintf(output_ptr, "Error, failed to get channel %d attributes: %s\n", chan, strerror(errno));
|
||||
else
|
||||
sprintf( output, "error%d\n", errno );
|
||||
output_ptr += sprintf(output_ptr, "error%d\n", errno);
|
||||
return false;
|
||||
}
|
||||
if ( verbose ) {
|
||||
sprintf( output+strlen(output), "Channel %d Attributes\n", chan );
|
||||
sprintf( output+strlen(output), " Name: %s\n", vid_src.name );
|
||||
sprintf( output+strlen(output), " Channel: %d\n", vid_src.channel );
|
||||
sprintf( output+strlen(output), " Flags: %d\n%s%s", vid_src.flags,
|
||||
(vid_src.flags&VIDEO_VC_TUNER)?" Channel has a tuner\n":"",
|
||||
(vid_src.flags&VIDEO_VC_AUDIO)?" Channel has audio\n":""
|
||||
);
|
||||
sprintf( output+strlen(output), " Type: %d - %s\n", vid_src.type,
|
||||
output_ptr += sprintf(output_ptr,
|
||||
"Channel %d Attributes\n"
|
||||
" Name: %s\n"
|
||||
" Channel: %d\n"
|
||||
" Flags: %d\n%s%s"
|
||||
" Type: %d - %s\n"
|
||||
" Format: %d - %s\n"
|
||||
, chan
|
||||
, vid_src.name
|
||||
, vid_src.channel
|
||||
, vid_src.flags
|
||||
, (vid_src.flags&VIDEO_VC_TUNER)?" Channel has a tuner\n":""
|
||||
, (vid_src.flags&VIDEO_VC_AUDIO)?" Channel has audio\n":""
|
||||
, vid_src.type,
|
||||
vid_src.type==VIDEO_TYPE_TV?"TV":(
|
||||
vid_src.type==VIDEO_TYPE_CAMERA?"Camera":"Unknown"
|
||||
));
|
||||
sprintf( output+strlen(output), " Format: %d - %s\n", vid_src.norm,
|
||||
)
|
||||
, vid_src.norm,
|
||||
vid_src.norm==VIDEO_MODE_PAL?"PAL":(
|
||||
vid_src.norm==VIDEO_MODE_NTSC?"NTSC":(
|
||||
vid_src.norm==VIDEO_MODE_SECAM?"SECAM":(
|
||||
vid_src.norm==VIDEO_MODE_AUTO?"AUTO":"Unknown"
|
||||
))));
|
||||
} else {
|
||||
sprintf( output+strlen(output), "n%d:%s|", chan, vid_src.name );
|
||||
sprintf( output+strlen(output), "C%d:%d|", chan, vid_src.channel );
|
||||
sprintf( output+strlen(output), "Fl%d:%x|", chan, vid_src.flags );
|
||||
sprintf( output+strlen(output), "T%d:%d|", chan, vid_src.type );
|
||||
sprintf( output+strlen(output), "F%d:%d%s|", chan, vid_src.norm, chan==(vid_cap.channels-1)?"":"," );
|
||||
output_ptr += sprintf(output_ptr, "n%d:%s|C%d:%d|Fl%d:%x|T%d:%d|F%d:%d%s|"
|
||||
, chan, vid_src.name
|
||||
, chan, vid_src.channel
|
||||
, chan, vid_src.flags
|
||||
, chan, vid_src.type
|
||||
, chan, vid_src.norm, chan==(vid_cap.channels-1)?"":","
|
||||
);
|
||||
}
|
||||
}
|
||||
if ( !verbose )
|
||||
output[strlen(output)-1] = '\n';
|
||||
*output_ptr = '\n';
|
||||
}
|
||||
#endif // ZM_HAS_V4L1
|
||||
close( vid_fd );
|
||||
close(vid_fd);
|
||||
if ( device )
|
||||
break;
|
||||
} while ( ++devIndex < 32 );
|
||||
|
|
|
@ -24,6 +24,7 @@ class Filter extends ZM_Object {
|
|||
'AutoCopy' => 0,
|
||||
'AutoCopyTo' => 0,
|
||||
'UpdateDiskSpace' => 0,
|
||||
'UserId' => 0,
|
||||
'Background' => 0,
|
||||
'Concurrent' => 0,
|
||||
'Query_json' => '',
|
||||
|
|
|
@ -19,9 +19,9 @@ class Group extends ZM_Object {
|
|||
|
||||
public function delete() {
|
||||
if ( property_exists($this, 'Id') ) {
|
||||
dbQuery('DELETE FROM Groups_Monitors WHERE GroupId=?', array($this->{'Id'}));
|
||||
dbQuery('UPDATE Groups SET ParentId=NULL WHERE ParentId=?', array($this->{'Id'}));
|
||||
dbQuery('DELETE FROM Groups WHERE Id=?', array($this->{'Id'}));
|
||||
dbQuery('DELETE FROM `Groups_Monitors` WHERE `GroupId`=?', array($this->{'Id'}));
|
||||
dbQuery('UPDATE `Groups` SET `ParentId`=NULL WHERE `ParentId`=?', array($this->{'Id'}));
|
||||
dbQuery('DELETE FROM `Groups` WHERE Id=?', array($this->{'Id'}));
|
||||
if ( isset($_COOKIE['zmGroup']) ) {
|
||||
if ( $this->{'Id'} == $_COOKIE['zmGroup'] ) {
|
||||
unset($_COOKIE['zmGroup']);
|
||||
|
@ -47,7 +47,7 @@ class Group extends ZM_Object {
|
|||
|
||||
public function MonitorIds( ) {
|
||||
if ( ! property_exists($this, 'MonitorIds') ) {
|
||||
$this->{'MonitorIds'} = dbFetchAll('SELECT MonitorId FROM Groups_Monitors WHERE GroupId=?', 'MonitorId', array($this->{'Id'}));
|
||||
$this->{'MonitorIds'} = dbFetchAll('SELECT `MonitorId` FROM `Groups_Monitors` WHERE `GroupId`=?', 'MonitorId', array($this->{'Id'}));
|
||||
}
|
||||
return $this->{'MonitorIds'};
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ class Group extends ZM_Object {
|
|||
session_write_close();
|
||||
}
|
||||
|
||||
return htmlSelect( 'GroupId[]', Group::get_dropdown_options(), isset($_SESSION['GroupId'])?$_SESSION['GroupId']:null, array(
|
||||
return htmlSelect('GroupId[]', Group::get_dropdown_options(), isset($_SESSION['GroupId'])?$_SESSION['GroupId']:null, array(
|
||||
'data-on-change' => 'submitThisForm',
|
||||
'class'=>'chosen',
|
||||
'multiple'=>'multiple',
|
||||
|
|
|
@ -306,7 +306,7 @@ class ZM_Object {
|
|||
$fields = array_keys($fields);
|
||||
|
||||
if ( $this->Id() ) {
|
||||
$sql = 'UPDATE '.$table.' SET '.implode(', ', array_map(function($field) {return '`'.$field.'`=?';}, $fields)).' WHERE Id=?';
|
||||
$sql = 'UPDATE `'.$table.'` SET '.implode(', ', array_map(function($field) {return '`'.$field.'`=?';}, $fields)).' WHERE Id=?';
|
||||
$values = array_map(function($field){ return $this->{$field};}, $fields);
|
||||
$values[] = $this->{'Id'};
|
||||
if ( dbQuery($sql, $values) )
|
||||
|
@ -314,8 +314,8 @@ class ZM_Object {
|
|||
} else {
|
||||
unset($fields['Id']);
|
||||
|
||||
$sql = 'INSERT INTO '.$table.
|
||||
' ('.implode(', ', array_map(function($field) {return '`'.$field.'`';}, $fields)).
|
||||
$sql = 'INSERT INTO `'.$table.
|
||||
'` ('.implode(', ', array_map(function($field) {return '`'.$field.'`';}, $fields)).
|
||||
') VALUES ('.
|
||||
implode(', ', array_map(function($field){return '?';}, $fields)).')';
|
||||
|
||||
|
@ -331,7 +331,7 @@ class ZM_Object {
|
|||
public function delete() {
|
||||
$class = get_class($this);
|
||||
$table = $class::$table;
|
||||
dbQuery("DELETE FROM $table WHERE Id=?", array($this->{'Id'}));
|
||||
dbQuery("DELETE FROM `$table` WHERE Id=?", array($this->{'Id'}));
|
||||
if ( isset($object_cache[$class]) and isset($object_cache[$class][$this->{'Id'}]) )
|
||||
unset($object_cache[$class][$this->{'Id'}]);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
namespace ZM;
|
||||
require_once('database.php');
|
||||
require_once('Object.php');
|
||||
|
||||
|
||||
class User extends ZM_Object {
|
||||
protected static $table = 'Users';
|
||||
|
||||
protected $defaults = array(
|
||||
'Id' => null,
|
||||
'Username' => '',
|
||||
'Password' => '',
|
||||
'Language' => '',
|
||||
'Enabled' => 1,
|
||||
'Stream' => 'None',
|
||||
'Events' => 'None',
|
||||
'Control' => 'None',
|
||||
'Monitors' => 'None',
|
||||
'Groups' => 'None',
|
||||
'Devices' => 'None',
|
||||
'System'=> 'None',
|
||||
'MaxBandwidth' =>'',
|
||||
'MonitorIds' =>'',
|
||||
'TokenMinExpiry' => 0,
|
||||
'APIEnabled'=> 1,
|
||||
);
|
||||
|
||||
public static function find( $parameters = array(), $options = array() ) {
|
||||
return ZM_Object::_find(get_class(), $parameters, $options);
|
||||
}
|
||||
|
||||
public static function find_one( $parameters = array(), $options = array() ) {
|
||||
return ZM_Object::_find_one(get_class(), $parameters, $options);
|
||||
}
|
||||
|
||||
public function Name( ) {
|
||||
return $this->{'Username'};
|
||||
}
|
||||
|
||||
public static function Indexed_By_Id() {
|
||||
$results = array();
|
||||
foreach ( ZM_Object::_find('ZM\User', null, array('order'=>'lower(Username)')) as $Object ) {
|
||||
$results[$Object->Id()] = $Object;
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
|
||||
} # end class User
|
||||
?>
|
|
@ -25,21 +25,28 @@ define('DB_LOG_DEBUG', 2);
|
|||
$GLOBALS['dbLogLevel'] = DB_LOG_OFF;
|
||||
|
||||
$GLOBALS['dbConn'] = false;
|
||||
require_once('logger.php');
|
||||
|
||||
function dbConnect() {
|
||||
global $dbConn;
|
||||
|
||||
if ( strpos(ZM_DB_HOST, ':') ) {
|
||||
// Host variable may carry a port or socket.
|
||||
list($host, $portOrSocket) = explode(':', ZM_DB_HOST, 2);
|
||||
if ( ctype_digit($portOrSocket) ) {
|
||||
$socket = ':host='.$host . ';port='.$portOrSocket;
|
||||
$dsn = ZM_DB_TYPE;
|
||||
if ( ZM_DB_HOST ) {
|
||||
if ( strpos(ZM_DB_HOST, ':') ) {
|
||||
// Host variable may carry a port or socket.
|
||||
list($host, $portOrSocket) = explode(':', ZM_DB_HOST, 2);
|
||||
if ( ctype_digit($portOrSocket) ) {
|
||||
$dsn .= ':host='.$host.';port='.$portOrSocket.';';
|
||||
} else {
|
||||
$dsn .= ':unix_socket='.$portOrSocket.';';
|
||||
}
|
||||
} else {
|
||||
$socket = ':unix_socket='.$portOrSocket;
|
||||
$dsn .= ':host='.ZM_DB_HOST.';';
|
||||
}
|
||||
} else {
|
||||
$socket = ':host='.ZM_DB_HOST;
|
||||
$dsn .= ':host=localhost;';
|
||||
}
|
||||
$dsn .= 'dbname='.ZM_DB_NAME;
|
||||
|
||||
try {
|
||||
$dbOptions = null;
|
||||
|
@ -49,21 +56,24 @@ function dbConnect() {
|
|||
PDO::MYSQL_ATTR_SSL_KEY => ZM_DB_SSL_CLIENT_KEY,
|
||||
PDO::MYSQL_ATTR_SSL_CERT => ZM_DB_SSL_CLIENT_CERT,
|
||||
);
|
||||
$dbConn = new PDO(ZM_DB_TYPE . $socket . ';dbname='.ZM_DB_NAME, ZM_DB_USER, ZM_DB_PASS, $dbOptions);
|
||||
$dbConn = new PDO($dsn, ZM_DB_USER, ZM_DB_PASS, $dbOptions);
|
||||
} else {
|
||||
$dbConn = new PDO(ZM_DB_TYPE . $socket . ';dbname='.ZM_DB_NAME, ZM_DB_USER, ZM_DB_PASS);
|
||||
$dbConn = new PDO($dsn, ZM_DB_USER, ZM_DB_PASS);
|
||||
}
|
||||
|
||||
$dbConn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
|
||||
$dbConn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
} catch(PDOException $ex) {
|
||||
echo 'Unable to connect to ZM db.' . $ex->getMessage();
|
||||
echo "Unable to connect to ZM db using dsn $dsn host".ZM_DB_HOST.' user: ('.ZM_DB_USER.') password ('.ZM_DB_PASS.': '.$ex->getMessage();
|
||||
error_log('Unable to connect to ZM DB ' . $ex->getMessage());
|
||||
$dbConn = null;
|
||||
}
|
||||
}
|
||||
return $dbConn;
|
||||
} // end function dbConnect
|
||||
|
||||
dbConnect();
|
||||
if ( !dbConnect() ) {
|
||||
ZM\Fatal('Failed db connection');
|
||||
}
|
||||
|
||||
function dbDisconnect() {
|
||||
global $dbConn;
|
||||
|
|
|
@ -1505,15 +1505,15 @@ function getLoad() {
|
|||
function getDiskPercent($path = ZM_DIR_EVENTS) {
|
||||
$total = disk_total_space($path);
|
||||
if ( $total === false ) {
|
||||
Error('disk_total_space returned false. Verify the web account user has access to ' . $path);
|
||||
ZM\Error('disk_total_space returned false. Verify the web account user has access to ' . $path);
|
||||
return 0;
|
||||
} elseif ( $total == 0 ) {
|
||||
Error('disk_total_space indicates the following path has a filesystem size of zero bytes ' . $path);
|
||||
ZM\Error('disk_total_space indicates the following path has a filesystem size of zero bytes ' . $path);
|
||||
return 100;
|
||||
}
|
||||
$free = disk_free_space($path);
|
||||
if ( $free === false ) {
|
||||
Error('disk_free_space returned false. Verify the web account user has access to ' . $path);
|
||||
ZM\Error('disk_free_space returned false. Verify the web account user has access to ' . $path);
|
||||
}
|
||||
$space = round((($total - $free) / $total) * 100);
|
||||
return $space;
|
||||
|
@ -2069,7 +2069,7 @@ function logState() {
|
|||
if ( $count['Level'] <= ZM\Logger::PANIC )
|
||||
$count['Level'] = ZM\Logger::FATAL;
|
||||
if ( !($levelCount = $levelCounts[$count['Level']]) ) {
|
||||
Error('Unexpected Log level '.$count['Level']);
|
||||
ZM\Error('Unexpected Log level '.$count['Level']);
|
||||
next;
|
||||
}
|
||||
if ( $levelCount[1] && $count['LevelCount'] >= $levelCount[1] ) {
|
||||
|
|
|
@ -100,14 +100,17 @@ class Logger {
|
|||
$tempDatabaseLevel = $options['databaseLevel'];
|
||||
else
|
||||
$tempDatabaseLevel = ZM_LOG_LEVEL_DATABASE;
|
||||
|
||||
if ( isset($options['fileLevel']) )
|
||||
$tempFileLevel = $options['fileLevel'];
|
||||
else
|
||||
$tempFileLevel = ZM_LOG_LEVEL_FILE;
|
||||
|
||||
if ( isset($options['weblogLevel']) )
|
||||
$tempWeblogLevel = $options['weblogLevel'];
|
||||
else
|
||||
$tempWeblogLevel = ZM_LOG_LEVEL_WEBLOG;
|
||||
|
||||
if ( isset($options['syslogLevel']) )
|
||||
$tempSyslogLevel = $options['syslogLevel'];
|
||||
else
|
||||
|
|
|
@ -376,6 +376,7 @@ $SLANG = array(
|
|||
'Filters' => 'Filters',
|
||||
'FilterUnset' => 'You must specify a filter width and height',
|
||||
'FilterUploadEvents' => 'Upload all matches',
|
||||
'FilterUser' => 'User to run filter as',
|
||||
'FilterVideoEvents' => 'Create video for all matches',
|
||||
'First' => 'First',
|
||||
'FlippedHori' => 'Flipped Horizontally',
|
||||
|
|
|
@ -205,6 +205,7 @@ getBodyTopHTML();
|
|||
<?php
|
||||
ob_start();
|
||||
?>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover table-condensed consoleTable">
|
||||
<thead class="thead-highlight">
|
||||
<tr>
|
||||
|
@ -390,9 +391,10 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
|
|||
<?php if ( canEdit('Monitors') ) { ?>
|
||||
<td class="colMark"></td>
|
||||
<?php } ?>
|
||||
</tr>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<?php xhtmlFooter() ?>
|
||||
|
|
|
@ -27,6 +27,7 @@ require_once('includes/Storage.php');
|
|||
require_once('includes/Filter.php');
|
||||
require_once('includes/Monitor.php');
|
||||
require_once('includes/Zone.php');
|
||||
require_once('includes/User.php');
|
||||
parseSort();
|
||||
|
||||
$filterNames = array(''=>translate('ChooseFilter'));
|
||||
|
@ -200,6 +201,18 @@ if ( (null !== $filter->Concurrent()) and $filter->Concurrent() )
|
|||
<label for="filter[Name]"><?php echo translate('Name') ?></label>
|
||||
<input type="text" id="filter[Name]" name="filter[Name]" value="<?php echo validHtmlStr($filter->Name()) ?>" data-on-input-this="updateButtons"/>
|
||||
</p>
|
||||
<?php if ( ZM_OPT_USE_AUTH ) { ?>
|
||||
<p><label><?php echo translate('FilterUser') ?></label>
|
||||
<?php
|
||||
global $user;
|
||||
echo htmlSelect('filter[UserId]',
|
||||
ZM\User::Indexed_By_Id(),
|
||||
//ZM\User::find(),
|
||||
$filter->UserId() ? $filter->UserId() : $user['Id']
|
||||
); ?>
|
||||
</p>
|
||||
<?php } ?>
|
||||
<p>
|
||||
<table id="fieldsTable" class="filterTable">
|
||||
<tbody>
|
||||
<?php
|
||||
|
|
|
@ -308,7 +308,7 @@ function pauseClicked() {
|
|||
streamPause();
|
||||
}
|
||||
|
||||
function streamPause( ) {
|
||||
function streamPause() {
|
||||
$j('#modeValue').html('Paused');
|
||||
setButtonState( $('pauseBtn'), 'active' );
|
||||
setButtonState( $('playBtn'), 'inactive' );
|
||||
|
|
|
@ -747,9 +747,11 @@ function fetchImage( streamImage ) {
|
|||
}
|
||||
|
||||
function handleClick( event ) {
|
||||
var target = event.target;
|
||||
var x = event.page.x - $(target).getLeft();
|
||||
var y = event.page.y - $(target).getTop();
|
||||
var $target = $(event.target);
|
||||
var scaleX = parseInt(monitorWidth / $target.getWidth());
|
||||
var scaleY = parseInt(monitorHeight / $target.getHeight());
|
||||
var x = (event.page.x - $target.getLeft()) * scaleX;
|
||||
var y = (event.page.y - $target.getTop()) * scaleY;
|
||||
|
||||
if ( showMode == 'events' || !imageControlMode ) {
|
||||
if ( event.shift ) {
|
||||
|
@ -848,7 +850,7 @@ function initPage() {
|
|||
if ( refreshApplet && appletRefreshTime ) {
|
||||
appletRefresh.delay(appletRefreshTime*1000);
|
||||
}
|
||||
if ( scale == 'auto' ) changeScale();
|
||||
if ( scale == '0' || scale == 'auto' ) changeScale();
|
||||
if ( window.history.length == 1 ) {
|
||||
$j('#closeControl').html('');
|
||||
}
|
||||
|
|
|
@ -179,12 +179,16 @@ function toPixels(field, maxValue) {
|
|||
if ( field.value != '' ) {
|
||||
field.value = Math.round((field.value*maxValue)/100);
|
||||
}
|
||||
field.setAttribute('step', 1);
|
||||
field.setAttribute('max', monitorArea);
|
||||
}
|
||||
|
||||
function toPercent(field, maxValue) {
|
||||
if ( field.value != '' ) {
|
||||
field.value = Math.round((100*100*field.value)/maxValue)/100;
|
||||
}
|
||||
field.setAttribute('step', 0.01);
|
||||
field.setAttribute('max', 100);
|
||||
}
|
||||
|
||||
function applyZoneUnits() {
|
||||
|
@ -384,7 +388,7 @@ function saveChanges(element) {
|
|||
if ( validateForm(form) ) {
|
||||
submitForm(form);
|
||||
if ( form.elements['newZone[Type]'].value == 'Privacy' ) {
|
||||
alert( 'Capture process for this monitor will be restarted for the Privacy zone changes to take effect.' );
|
||||
alert('Capture process for this monitor will be restarted for the Privacy zone changes to take effect.');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -151,11 +151,11 @@ if ( $showControl ) {
|
|||
}
|
||||
if ( $showZones ) {
|
||||
?>
|
||||
<a id="ShowZones" href="?view=montage&showZones=0">Hide Zones</a>
|
||||
<a id="HideZones" href="?view=montage&showZones=0"><?php echo translate('Hide Zones')?></a>
|
||||
<?php
|
||||
} else {
|
||||
?>
|
||||
<a id="ShowZones" href="?view=montage&showZones=1">Show Zones</a>
|
||||
<a id="ShowZones" href="?view=montage&showZones=1"><?php echo translate('Show Zones')?></a>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -96,12 +96,14 @@ function probeProfiles($device_ep, $soapversion, $username, $password) {
|
|||
if ( $lines = @execONVIF("profiles $device_ep $soapversion $username $password") ) {
|
||||
foreach ( $lines as $line ) {
|
||||
$line = rtrim( $line );
|
||||
if ( preg_match('|^(.+),\s*(.+),\s*(.+),\s*(.+),\s*(.+),\s*(.+),\s*(.+)\s*$|', $line, $matches) ) {
|
||||
$stream_uri = $matches[7];
|
||||
|
||||
if ( preg_match('|^([^,]+),\s*([^,]+),\s*([^,]+),\s*(\d+),\s*(\d+),\s*(\d+),\s*([^,]+),\s*(.+)\s*$|', $line, $matches) ) {
|
||||
$stream_uri = $matches[8];
|
||||
// add user@pass to URI
|
||||
if ( preg_match('|^(\S+://)(.+)$|', $stream_uri, $tokens) ) {
|
||||
$stream_uri = $tokens[1].$username.':'.$password.'@'.$tokens[2];
|
||||
}
|
||||
ZM\Warning(print_r($matches,1));
|
||||
|
||||
$profile = array( # 'monitor' part of camera
|
||||
'Type' => 'Ffmpeg',
|
||||
|
@ -113,6 +115,7 @@ function probeProfiles($device_ep, $soapversion, $username, $password) {
|
|||
'Profile' => $matches[1],
|
||||
'Name' => $matches[2],
|
||||
'Encoding' => $matches[3],
|
||||
'Transport' => $matches[7],
|
||||
);
|
||||
$profiles[] = $profile;
|
||||
} else {
|
||||
|
@ -261,10 +264,17 @@ if ( !isset($_REQUEST['step']) || ($_REQUEST['step'] == '1') ) {
|
|||
$monitor = $camera['monitor'];
|
||||
|
||||
$sourceString = "${profile['Name']} : ${profile['Encoding']}" .
|
||||
" (${profile['Width']}x${profile['Height']} @ ${profile['MaxFPS']}fps)";
|
||||
" (${profile['Width']}x${profile['Height']} @ ${profile['MaxFPS']}fps ${profile['Transport']})";
|
||||
// copy technical details
|
||||
$monitor['Width'] = $profile['Width'];
|
||||
$monitor['Height'] = $profile['Height'];
|
||||
if ( $profile['Transport'] == 'RTP-Multicast' ) {
|
||||
$monitor['Method'] = 'rtpMulti';
|
||||
} else if ( $profile['Transport'] == 'RTP-Unicast' ) {
|
||||
$monitor['Method'] = 'rtpUni';
|
||||
} else {
|
||||
$monitor['Method'] = 'rtpRtsp';
|
||||
}
|
||||
// The maxfps fields do not work for ip streams. Can re-enable if that is fixed.
|
||||
// $monitor['MaxFPS'] = $profile['MaxFPS'];
|
||||
// $monitor['AlarmMaxFPS'] = $profile['AlarmMaxFPS'];
|
||||
|
|
|
@ -174,29 +174,36 @@ xhtmlHeaders(__FILE__, translate('Zone'));
|
|||
<tr>
|
||||
<th scope="row"><?php echo translate('Type') ?></th>
|
||||
<td colspan="2"><?php echo htmlSelect('newZone[Type]', $optTypes, $newZone['Type'],
|
||||
array('onchange'=>'applyZoneType()')); ?></td>
|
||||
array('data-on-change'=>'applyZoneType')); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><?php echo translate('Preset') ?></th>
|
||||
<td colspan="2">
|
||||
<?php echo htmlSelect('presetSelector', $presetNames,
|
||||
( isset($_REQUEST['presetSelector']) ? $_REQUEST['presetSelector'] : null),
|
||||
array('onchange'=>'applyPreset()', 'onblur'=>'this.selectedIndex=0') )
|
||||
array('data-on-change'=>'applyPreset', 'onblur'=>'this.selectedIndex=0') )
|
||||
?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><?php echo translate('Units') ?></th>
|
||||
<td colspan="2"><?php echo htmlSelect('newZone[Units]', $optUnits, $newZone['Units'],
|
||||
array('onchange'=>'applyZoneUnits()') ) ?></td>
|
||||
<td colspan="2">
|
||||
<?php
|
||||
echo htmlSelect('newZone[Units]', $optUnits, $newZone['Units'],
|
||||
array('data-on-change'=>'applyZoneUnits')
|
||||
);
|
||||
# Used later for number inputs
|
||||
$step = $newZone['Units'] == 'Percent' ? ' step="0.01" max="100"' : '';
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><?php echo translate('ZoneAlarmColour') ?></th>
|
||||
<td colspan="2">
|
||||
<input type="number" name="newAlarmRgbR" value="<?php echo ($newZone['AlarmRGB']>>16)&0xff ?>" size="3"/>
|
||||
<input type="number" name="newAlarmRgbR" value="<?php echo ($newZone['AlarmRGB']>>16)&0xff ?>" min="0" max="255"/>
|
||||
/
|
||||
<input type="number" name="newAlarmRgbG" value="<?php echo ($newZone['AlarmRGB']>>8)&0xff ?>" size="3"/>
|
||||
<input type="number" name="newAlarmRgbG" value="<?php echo ($newZone['AlarmRGB']>>8)&0xff ?>" min="0" max="255"/>
|
||||
/
|
||||
<input type="number" name="newAlarmRgbB" value="<?php echo $newZone['AlarmRGB']&0xff ?>" size="3"/>
|
||||
<input type="number" name="newAlarmRgbB" value="<?php echo $newZone['AlarmRGB']&0xff ?>" min="0" max="255"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -205,45 +212,45 @@ xhtmlHeaders(__FILE__, translate('Zone'));
|
|||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><?php echo translate('ZoneMinMaxPixelThres') ?></th>
|
||||
<td><input type="number" name="newZone[MinPixelThreshold]" value="<?php echo $newZone['MinPixelThreshold'] ?>" size="4"/></td>
|
||||
<td><input type="number" name="newZone[MaxPixelThreshold]" value="<?php echo $newZone['MaxPixelThreshold'] ?>" size="4"/></td>
|
||||
<td><input type="number" name="newZone[MinPixelThreshold]" value="<?php echo $newZone['MinPixelThreshold'] ?>"/></td>
|
||||
<td><input type="number" name="newZone[MaxPixelThreshold]" value="<?php echo $newZone['MaxPixelThreshold'] ?>"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><?php echo translate('ZoneFilterSize') ?></th>
|
||||
<td><input type="number" name="newZone[FilterX]" value="<?php echo $newZone['FilterX'] ?>" size="4"/></td>
|
||||
<td><input type="number" name="newZone[FilterY]" value="<?php echo $newZone['FilterY'] ?>" size="4"/></td>
|
||||
<td><input type="number" name="newZone[FilterX]" value="<?php echo $newZone['FilterX'] ?>"/></td>
|
||||
<td><input type="number" name="newZone[FilterY]" value="<?php echo $newZone['FilterY'] ?>"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><?php echo translate('ZoneArea') ?></th>
|
||||
<td colspan="2"><input type="number" name="newZone[TempArea]" value="<?php echo $newZone['Area'] ?>" size="7" disabled="disabled"/></td>
|
||||
<td colspan="2"><input type="number" name="newZone[TempArea]" value="<?php echo $newZone['Area'] ?>" disabled="disabled"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><?php echo translate('ZoneMinMaxAlarmArea') ?></th>
|
||||
<td><input type="number" name="newZone[MinAlarmPixels]" value="<?php echo $newZone['MinAlarmPixels'] ?>" size="6"/></td>
|
||||
<td><input type="number" name="newZone[MaxAlarmPixels]" value="<?php echo $newZone['MaxAlarmPixels'] ?>" size="6"/></td>
|
||||
<td><input type="number" name="newZone[MinAlarmPixels]" value="<?php echo $newZone['MinAlarmPixels'] ?>"<?php echo $step ?> min="0"/></td>
|
||||
<td><input type="number" name="newZone[MaxAlarmPixels]" value="<?php echo $newZone['MaxAlarmPixels'] ?>"<?php echo $step ?> min="0"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><?php echo translate('ZoneMinMaxFiltArea') ?></th>
|
||||
<td><input type="number" name="newZone[MinFilterPixels]" value="<?php echo $newZone['MinFilterPixels'] ?>" size="6"/></td>
|
||||
<td><input type="number" name="newZone[MaxFilterPixels]" value="<?php echo $newZone['MaxFilterPixels'] ?>" size="6"/></td>
|
||||
<td><input type="number" name="newZone[MinFilterPixels]" value="<?php echo $newZone['MinFilterPixels'] ?>"<?php echo $step ?> min="0"/></td>
|
||||
<td><input type="number" name="newZone[MaxFilterPixels]" value="<?php echo $newZone['MaxFilterPixels'] ?>"<?php echo $step ?> min="0"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><?php echo translate('ZoneMinMaxBlobArea') ?></th>
|
||||
<td><input type="number" name="newZone[MinBlobPixels]" value="<?php echo $newZone['MinBlobPixels'] ?>" size="6"/></td>
|
||||
<td><input type="number" name="newZone[MaxBlobPixels]" value="<?php echo $newZone['MaxBlobPixels'] ?>" size="6"/></td>
|
||||
<td><input type="number" name="newZone[MinBlobPixels]" value="<?php echo $newZone['MinBlobPixels'] ?>"<?php echo $step ?> min="0"/></td>
|
||||
<td><input type="number" name="newZone[MaxBlobPixels]" value="<?php echo $newZone['MaxBlobPixels'] ?>"<?php echo $step ?> min="0"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><?php echo translate('ZoneMinMaxBlobs') ?></th>
|
||||
<td><input type="number" name="newZone[MinBlobs]" value="<?php echo $newZone['MinBlobs'] ?>" size="4"/></td>
|
||||
<td><input type="number" name="newZone[MaxBlobs]" value="<?php echo $newZone['MaxBlobs'] ?>" size="4"/></td>
|
||||
<td><input type="number" name="newZone[MinBlobs]" value="<?php echo $newZone['MinBlobs'] ?>" min="0"/></td>
|
||||
<td><input type="number" name="newZone[MaxBlobs]" value="<?php echo $newZone['MaxBlobs'] ?>" min="0"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><?php echo translate('ZoneOverloadFrames') ?></th>
|
||||
<td colspan="2"><input type="number" name="newZone[OverloadFrames]" value="<?php echo $newZone['OverloadFrames'] ?>" size="4"/></td>
|
||||
<td colspan="2"><input type="number" name="newZone[OverloadFrames]" value="<?php echo $newZone['OverloadFrames'] ?>" min="0"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><?php echo translate('ZoneExtendAlarmFrames') ?></th>
|
||||
<td colspan="2"><input type="number" name="newZone[ExtendAlarmFrames]" value="<?php echo $newZone['ExtendAlarmFrames'] ?>" size="4"/></td>
|
||||
<td colspan="2"><input type="number" name="newZone[ExtendAlarmFrames]" value="<?php echo $newZone['ExtendAlarmFrames'] ?>" min="0"/></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
Loading…
Reference in New Issue