Merge branch 'storageareas' of github.com:ConnorTechnology/ZoneMinder into storageareas
This commit is contained in:
commit
b166579f4b
|
@ -27,7 +27,7 @@ zmdc.pl - ZoneMinder Daemon Control script
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
zmdc.pl {command} [daemon [options]]
|
zmdc.pl {command} [daemon [options]]
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
@ -39,12 +39,13 @@ connect to the server and pass instructions to it.
|
||||||
|
|
||||||
=head1 OPTIONS
|
=head1 OPTIONS
|
||||||
|
|
||||||
{command} - One of 'startup|shutdown|status|check|logrot' or
|
{command} - One of 'startup|shutdown|status|check|logrot' or
|
||||||
'start|stop|restart|reload|version'.
|
'start|stop|restart|reload|version'.
|
||||||
[daemon [options]] - Daemon name and options, required for second group of commands
|
[daemon [options]] - Daemon name and options, required for second group of commands
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
use strict;
|
use strict;
|
||||||
|
use warnings;
|
||||||
use bytes;
|
use bytes;
|
||||||
|
|
||||||
# ==========================================================================
|
# ==========================================================================
|
||||||
|
@ -53,7 +54,9 @@ use bytes;
|
||||||
#
|
#
|
||||||
# ==========================================================================
|
# ==========================================================================
|
||||||
|
|
||||||
use constant MAX_CONNECT_DELAY => 10;
|
# in useconds, not seconds.
|
||||||
|
use constant MAX_CONNECT_DELAY => 10*1000*1000;
|
||||||
|
use constant KILL_DELAY => 10*1000; # 1/10th of a second
|
||||||
|
|
||||||
# ==========================================================================
|
# ==========================================================================
|
||||||
#
|
#
|
||||||
|
@ -66,6 +69,7 @@ use ZoneMinder;
|
||||||
use POSIX;
|
use POSIX;
|
||||||
use Socket;
|
use Socket;
|
||||||
use IO::Handle;
|
use IO::Handle;
|
||||||
|
use Time::HiRes qw(usleep);
|
||||||
use autouse 'Pod::Usage'=>qw(pod2usage);
|
use autouse 'Pod::Usage'=>qw(pod2usage);
|
||||||
#use Data::Dumper;
|
#use Data::Dumper;
|
||||||
|
|
||||||
|
@ -98,10 +102,10 @@ my @daemons = (
|
||||||
'zmupdate.pl',
|
'zmupdate.pl',
|
||||||
'zmtrack.pl',
|
'zmtrack.pl',
|
||||||
'zmtelemetry.pl'
|
'zmtelemetry.pl'
|
||||||
);
|
);
|
||||||
|
|
||||||
my $command = shift @ARGV;
|
my $command = shift @ARGV;
|
||||||
if( !$command ) {
|
if( ! $command ) {
|
||||||
print( STDERR "No command given\n" );
|
print( STDERR "No command given\n" );
|
||||||
pod2usage(-exitstatus => -1);
|
pod2usage(-exitstatus => -1);
|
||||||
}
|
}
|
||||||
|
@ -111,7 +115,7 @@ if ( $command eq 'version' ) {
|
||||||
}
|
}
|
||||||
my $needs_daemon = $command !~ /(?:startup|shutdown|status|check|logrot|version)/;
|
my $needs_daemon = $command !~ /(?:startup|shutdown|status|check|logrot|version)/;
|
||||||
my $daemon = shift( @ARGV );
|
my $daemon = shift( @ARGV );
|
||||||
if( $needs_daemon && !$daemon ) {
|
if ( $needs_daemon && ! $daemon ) {
|
||||||
print( STDERR "No daemon given\n" );
|
print( STDERR "No daemon given\n" );
|
||||||
pod2usage(-exitstatus => -1);
|
pod2usage(-exitstatus => -1);
|
||||||
}
|
}
|
||||||
|
@ -128,8 +132,8 @@ if ( $needs_daemon ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach my $arg ( @ARGV ) {
|
foreach my $arg ( @ARGV ) {
|
||||||
# Detaint arguments, if they look ok
|
# Detaint arguments, if they look ok
|
||||||
#if ( $arg =~ /^(-{0,2}[\w]+)/ )
|
#if ( $arg =~ /^(-{0,2}[\w]+)/ )
|
||||||
if ( $arg =~ /^(-{0,2}[\w\/?&=.-]+)$/ ) {
|
if ( $arg =~ /^(-{0,2}[\w\/?&=.-]+)$/ ) {
|
||||||
push( @args, $1 );
|
push( @args, $1 );
|
||||||
} else {
|
} else {
|
||||||
|
@ -142,8 +146,10 @@ socket( CLIENT, PF_UNIX, SOCK_STREAM, 0 ) or Fatal( "Can't open socket: $!" );
|
||||||
|
|
||||||
my $saddr = sockaddr_un( SOCK_FILE );
|
my $saddr = sockaddr_un( SOCK_FILE );
|
||||||
my $server_up = connect( CLIENT, $saddr );
|
my $server_up = connect( CLIENT, $saddr );
|
||||||
if ( !$server_up ) {
|
if ( ! $server_up ) {
|
||||||
|
# Server is not up. Some commands can still be handled
|
||||||
if ( $command eq 'logrot' ) {
|
if ( $command eq 'logrot' ) {
|
||||||
|
# If server is not running, then logrotate doesn't need to do anything.
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
if ( $command eq 'check' ) {
|
if ( $command eq 'check' ) {
|
||||||
|
@ -153,43 +159,47 @@ if ( !$server_up ) {
|
||||||
print( "Unable to connect to server using socket at " . SOCK_FILE . "\n" );
|
print( "Unable to connect to server using socket at " . SOCK_FILE . "\n" );
|
||||||
exit( -1 );
|
exit( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
# The server isn't there
|
# The server isn't there
|
||||||
print( "Starting server\n" );
|
print( "Starting server\n" );
|
||||||
close( CLIENT );
|
close( CLIENT );
|
||||||
|
|
||||||
if ( my $cpid = fork() ) {
|
if ( my $cpid = fork() ) {
|
||||||
|
# Parent process just sleep and fall through
|
||||||
|
|
||||||
|
# I'm still not sure why we need to re-init the logs
|
||||||
logInit();
|
logInit();
|
||||||
|
|
||||||
# Parent process just sleep and fall through
|
|
||||||
socket( CLIENT, PF_UNIX, SOCK_STREAM, 0 ) or Fatal( "Can't open socket: $!" );
|
socket( CLIENT, PF_UNIX, SOCK_STREAM, 0 ) or Fatal( "Can't open socket: $!" );
|
||||||
my $attempts = 0;
|
my $attempts = 0;
|
||||||
while (!connect( CLIENT, $saddr )) {
|
while( !connect( CLIENT, $saddr ) ) {
|
||||||
$attempts++;
|
$attempts++;
|
||||||
|
Error("Waiting for zmdc.pl server process, attempt $attempts" );
|
||||||
Fatal( "Can't connect: $!" ) if ($attempts > MAX_CONNECT_DELAY);
|
Fatal( "Can't connect: $!" ) if ($attempts > MAX_CONNECT_DELAY);
|
||||||
sleep(1);
|
usleep(100);
|
||||||
}
|
} # end while
|
||||||
} elsif ( defined($cpid) ) {
|
} elsif ( defined($cpid) ) {
|
||||||
ZMServer::run();
|
ZMServer::run();
|
||||||
} else {
|
} else {
|
||||||
Fatal( "Can't fork: $!" );
|
Fatal( "Can't fork: $!" );
|
||||||
}
|
}
|
||||||
}
|
} # end if ! server is up
|
||||||
if ( $command eq 'check' && !$daemon ) {
|
|
||||||
|
if ( $command eq 'check' && ! $daemon ) {
|
||||||
print( "running\n" );
|
print( "running\n" );
|
||||||
exit();
|
exit();
|
||||||
} elsif ( $command eq 'startup' ) {
|
} elsif ( $command eq 'startup' ) {
|
||||||
# Our work here is done
|
# Our work here is done
|
||||||
exit() if ( !$server_up );
|
exit() if ( !$server_up );
|
||||||
}
|
}
|
||||||
|
|
||||||
# The server is there, connect to it
|
# The server is there, connect to it
|
||||||
#print( "Writing commands\n" );
|
#print( "Writing commands\n" );
|
||||||
CLIENT->autoflush();
|
CLIENT->autoflush();
|
||||||
my $message = "$command";
|
my $message = join(';', $command, ( $daemon ? $daemon : () ), @args );
|
||||||
$message .= ";$daemon" if ( $daemon );
|
|
||||||
$message .= ";".join( ';', @args ) if ( @args );
|
|
||||||
print( CLIENT $message );
|
print( CLIENT $message );
|
||||||
shutdown( CLIENT, 1 );
|
shutdown( CLIENT, 1 );
|
||||||
while ( my $line = <CLIENT> ) {
|
while( my $line = <CLIENT> ) {
|
||||||
chomp( $line );
|
chomp( $line );
|
||||||
print( "$line\n" );
|
print( "$line\n" );
|
||||||
}
|
}
|
||||||
|
@ -202,6 +212,7 @@ exit;
|
||||||
package ZMServer;
|
package ZMServer;
|
||||||
|
|
||||||
use strict;
|
use strict;
|
||||||
|
use warnings;
|
||||||
use bytes;
|
use bytes;
|
||||||
|
|
||||||
@EXTRA_PERL_LIB@
|
@EXTRA_PERL_LIB@
|
||||||
|
@ -275,7 +286,7 @@ sub run {
|
||||||
} elsif ( $command eq 'reload' ) {
|
} elsif ( $command eq 'reload' ) {
|
||||||
reload( $daemon, @args );
|
reload( $daemon, @args );
|
||||||
} elsif ( $command eq 'startup' ) {
|
} elsif ( $command eq 'startup' ) {
|
||||||
# Do nothing, this is all we're here for
|
# Do nothing, this is all we're here for
|
||||||
dPrint( ZoneMinder::Logger::WARNING, "Already running, ignoring command '$command'\n" );
|
dPrint( ZoneMinder::Logger::WARNING, "Already running, ignoring command '$command'\n" );
|
||||||
} elsif ( $command eq 'shutdown' ) {
|
} elsif ( $command eq 'shutdown' ) {
|
||||||
shutdownAll();
|
shutdownAll();
|
||||||
|
@ -298,9 +309,9 @@ sub run {
|
||||||
}
|
}
|
||||||
} elsif ( $nfound < 0 ) {
|
} elsif ( $nfound < 0 ) {
|
||||||
if ( $! == EINTR ) {
|
if ( $! == EINTR ) {
|
||||||
# Dead child, will be reaped
|
# Dead child, will be reaped
|
||||||
#print( "Probable dead child\n" );
|
#print( "Probable dead child\n" );
|
||||||
# See if it needs to start up again
|
# See if it needs to start up again
|
||||||
restartPending();
|
restartPending();
|
||||||
} elsif ( $! == EPIPE ) {
|
} elsif ( $! == EPIPE ) {
|
||||||
Error( "Can't select: $!" );
|
Error( "Can't select: $!" );
|
||||||
|
@ -308,7 +319,7 @@ sub run {
|
||||||
Fatal( "Can't select: $!" );
|
Fatal( "Can't select: $!" );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
#print( "Select timed out\n" );
|
#print( "Select timed out\n" );
|
||||||
restartPending();
|
restartPending();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -353,7 +364,7 @@ sub start {
|
||||||
my $process = $cmd_hash{$command};
|
my $process = $cmd_hash{$command};
|
||||||
|
|
||||||
if ( !$process ) {
|
if ( !$process ) {
|
||||||
# It's not running, or at least it's not been started by us
|
# It's not running, or at least it's not been started by us
|
||||||
$process = { daemon=>$daemon, args=>\@args, command=>$command, keepalive=>!undef };
|
$process = { daemon=>$daemon, args=>\@args, command=>$command, keepalive=>!undef };
|
||||||
} elsif ( $process->{pid} && $pid_hash{$process->{pid}} ) {
|
} elsif ( $process->{pid} && $pid_hash{$process->{pid}} ) {
|
||||||
dPrint( ZoneMinder::Logger::INFO, "'$process->{command}' already running at "
|
dPrint( ZoneMinder::Logger::INFO, "'$process->{command}' already running at "
|
||||||
|
@ -381,7 +392,7 @@ sub start {
|
||||||
$cmd_hash{$process->{command}} = $pid_hash{$cpid} = $process;
|
$cmd_hash{$process->{command}} = $pid_hash{$cpid} = $process;
|
||||||
sigprocmask( SIG_SETMASK, $sigset ) or Fatal( "Can't restore SIGCHLD: $!" );
|
sigprocmask( SIG_SETMASK, $sigset ) or Fatal( "Can't restore SIGCHLD: $!" );
|
||||||
} elsif ( defined($cpid ) ) {
|
} elsif ( defined($cpid ) ) {
|
||||||
# Force reconnection to the db.
|
# Force reconnection to the db.
|
||||||
zmDbConnect(1);
|
zmDbConnect(1);
|
||||||
logReinit();
|
logReinit();
|
||||||
|
|
||||||
|
@ -399,7 +410,7 @@ sub start {
|
||||||
|
|
||||||
my @good_args;
|
my @good_args;
|
||||||
foreach my $arg ( @args ) {
|
foreach my $arg ( @args ) {
|
||||||
# Detaint arguments, if they look ok
|
# Detaint arguments, if they look ok
|
||||||
if ( $arg =~ /^(-{0,2}[\w\/?&=.-]+)$/ ) {
|
if ( $arg =~ /^(-{0,2}[\w\/?&=.-]+)$/ ) {
|
||||||
push( @good_args, $1 );
|
push( @good_args, $1 );
|
||||||
} else {
|
} else {
|
||||||
|
@ -415,7 +426,7 @@ sub start {
|
||||||
POSIX::close( $fd++ );
|
POSIX::close( $fd++ );
|
||||||
}
|
}
|
||||||
|
|
||||||
# Child process
|
# Child process
|
||||||
$SIG{CHLD} = 'DEFAULT';
|
$SIG{CHLD} = 'DEFAULT';
|
||||||
$SIG{INT} = 'DEFAULT';
|
$SIG{INT} = 'DEFAULT';
|
||||||
$SIG{TERM} = 'DEFAULT';
|
$SIG{TERM} = 'DEFAULT';
|
||||||
|
@ -474,7 +485,7 @@ sub kill_until_dead {
|
||||||
}
|
}
|
||||||
|
|
||||||
sigprocmask(SIG_UNBLOCK, $blockset) or die "dying at unblock...\n";
|
sigprocmask(SIG_UNBLOCK, $blockset) or die "dying at unblock...\n";
|
||||||
usleep( 100 );
|
usleep( KILL_DELAY );
|
||||||
sigprocmask(SIG_BLOCK, $blockset, $sigset ) or die "dying at block...\n";
|
sigprocmask(SIG_BLOCK, $blockset, $sigset ) or die "dying at block...\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -581,7 +592,7 @@ sub reaper {
|
||||||
$out_str .= 'normally';
|
$out_str .= 'normally';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#print( ", core dumped" ) if ( $core_dumped );
|
#print( ", core dumped" ) if ( $core_dumped );
|
||||||
$out_str .= "\n";
|
$out_str .= "\n";
|
||||||
|
|
||||||
if ( $exit_status == 0 ) {
|
if ( $exit_status == 0 ) {
|
||||||
|
@ -591,16 +602,16 @@ sub reaper {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $process->{keepalive} ) {
|
if ( $process->{keepalive} ) {
|
||||||
# Schedule for immediate restart
|
# Schedule for immediate restart
|
||||||
$cmd_hash{$process->{command}} = $process;
|
$cmd_hash{$process->{command}} = $process;
|
||||||
if ( !$process->{delay} || ($process->{runtime} > $Config{ZM_MAX_RESTART_DELAY} ) ) {
|
if ( !$process->{delay} || ($process->{runtime} > $Config{ZM_MAX_RESTART_DELAY} ) ) {
|
||||||
#start( $process->{daemon}, @{$process->{args}} );
|
#start( $process->{daemon}, @{$process->{args}} );
|
||||||
$process->{pending} = $process->{stopped};
|
$process->{pending} = $process->{stopped};
|
||||||
$process->{delay} = 5;
|
$process->{delay} = 5;
|
||||||
} else {
|
} else {
|
||||||
$process->{pending} = $process->{stopped}+$process->{delay};
|
$process->{pending} = $process->{stopped}+$process->{delay};
|
||||||
$process->{delay} *= 2;
|
$process->{delay} *= 2;
|
||||||
# Limit the start delay to 15 minutes max
|
# Limit the start delay to 15 minutes max
|
||||||
if ( $process->{delay} > $Config{ZM_MAX_RESTART_DELAY} ) {
|
if ( $process->{delay} > $Config{ZM_MAX_RESTART_DELAY} ) {
|
||||||
$process->{delay} = $Config{ZM_MAX_RESTART_DELAY};
|
$process->{delay} = $Config{ZM_MAX_RESTART_DELAY};
|
||||||
}
|
}
|
||||||
|
@ -612,7 +623,7 @@ sub reaper {
|
||||||
}
|
}
|
||||||
|
|
||||||
sub restartPending {
|
sub restartPending {
|
||||||
# Restart any pending processes
|
# Restart any pending processes
|
||||||
foreach my $process ( values( %cmd_hash ) ) {
|
foreach my $process ( values( %cmd_hash ) ) {
|
||||||
if ( $process->{pending} && $process->{pending} <= time() ) {
|
if ( $process->{pending} && $process->{pending} <= time() ) {
|
||||||
dPrint( ZoneMinder::Logger::INFO, "Starting pending process, $process->{command}\n" );
|
dPrint( ZoneMinder::Logger::INFO, "Starting pending process, $process->{command}\n" );
|
||||||
|
@ -623,12 +634,12 @@ sub restartPending {
|
||||||
|
|
||||||
sub shutdownAll {
|
sub shutdownAll {
|
||||||
foreach my $pid ( keys %pid_hash ) {
|
foreach my $pid ( keys %pid_hash ) {
|
||||||
# This is a quick fix because a SIGCHLD can happen and alter pid_hash while we are in here.
|
# This is a quick fix because a SIGCHLD can happen and alter pid_hash while we are in here.
|
||||||
next if ! $pid_hash{$pid};
|
next if ! $pid_hash{$pid};
|
||||||
send_stop( 1, $pid_hash{$pid} );
|
send_stop( 1, $pid_hash{$pid} );
|
||||||
}
|
}
|
||||||
foreach my $pid ( keys %pid_hash ) {
|
foreach my $pid ( keys %pid_hash ) {
|
||||||
# This is a quick fix because a SIGCHLD can happen and alter pid_hash while we are in here.
|
# This is a quick fix because a SIGCHLD can happen and alter pid_hash while we are in here.
|
||||||
next if ! $pid_hash{$pid};
|
next if ! $pid_hash{$pid};
|
||||||
|
|
||||||
my $process = $pid_hash{$pid};
|
my $process = $pid_hash{$pid};
|
||||||
|
@ -637,7 +648,9 @@ sub shutdownAll {
|
||||||
delete( $cmd_hash{$$process{command}} );
|
delete( $cmd_hash{$$process{command}} );
|
||||||
delete( $pid_hash{$pid} );
|
delete( $pid_hash{$pid} );
|
||||||
}
|
}
|
||||||
|
if ( 0 ) {
|
||||||
killAll( 5 );
|
killAll( 5 );
|
||||||
|
}
|
||||||
dPrint( ZoneMinder::Logger::INFO, "Server shutdown at "
|
dPrint( ZoneMinder::Logger::INFO, "Server shutdown at "
|
||||||
.strftime( '%y/%m/%d %H:%M:%S', localtime() )
|
.strftime( '%y/%m/%d %H:%M:%S', localtime() )
|
||||||
."\n"
|
."\n"
|
||||||
|
@ -653,8 +666,7 @@ sub check {
|
||||||
my $daemon = shift;
|
my $daemon = shift;
|
||||||
my @args = @_;
|
my @args = @_;
|
||||||
|
|
||||||
my $command = $daemon;
|
my $command = join( ' ', $daemon, @args );
|
||||||
$command .= ' '.join( ' ', ( @args ) ) if ( @args );
|
|
||||||
my $process = $cmd_hash{$command};
|
my $process = $cmd_hash{$command};
|
||||||
if ( !$process ) {
|
if ( !$process ) {
|
||||||
cPrint( "unknown\n" );
|
cPrint( "unknown\n" );
|
||||||
|
@ -662,7 +674,7 @@ sub check {
|
||||||
cPrint( "pending\n" );
|
cPrint( "pending\n" );
|
||||||
} else {
|
} else {
|
||||||
my $cpid = $process->{pid};
|
my $cpid = $process->{pid};
|
||||||
if ( !$pid_hash{$cpid} ) {
|
if ( ! $pid_hash{$cpid} ) {
|
||||||
cPrint( "stopped\n" );
|
cPrint( "stopped\n" );
|
||||||
} else {
|
} else {
|
||||||
cPrint( "running\n" );
|
cPrint( "running\n" );
|
||||||
|
@ -675,28 +687,27 @@ sub status {
|
||||||
my @args = @_;
|
my @args = @_;
|
||||||
|
|
||||||
if ( defined($daemon) ) {
|
if ( defined($daemon) ) {
|
||||||
my $command = $daemon;
|
my $command = join( ' ', $daemon, @args );
|
||||||
$command .= ' '.join( ' ', ( @args ) ) if ( @args );
|
|
||||||
my $process = $cmd_hash{$command};
|
my $process = $cmd_hash{$command};
|
||||||
if ( !$process ) {
|
if ( ! $process ) {
|
||||||
dPrint( ZoneMinder::Logger::DEBUG, "'$command' not running\n" );
|
dPrint( ZoneMinder::Logger::DEBUG, "'$command' not running\n" );
|
||||||
return();
|
return();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $process->{pending} ) {
|
if ( $process->{pending} ) {
|
||||||
dPrint( ZoneMinder::Logger::DEBUG, "'$process->{command}' pending at "
|
dPrint( ZoneMinder::Logger::DEBUG, "'$process->{command}' pending at "
|
||||||
.strftime( '%y/%m/%d %H:%M:%S', localtime( $process->{pending}) )
|
.strftime( '%y/%m/%d %H:%M:%S', localtime( $process->{pending} ) )
|
||||||
."\n"
|
."\n"
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
my $cpid = $process->{pid};
|
my $cpid = $process->{pid};
|
||||||
if ( !$pid_hash{$cpid} ) {
|
if ( ! $pid_hash{$cpid} ) {
|
||||||
dPrint( ZoneMinder::Logger::DEBUG, "'$command' not running\n" );
|
dPrint( ZoneMinder::Logger::DEBUG, "'$command' not running\n" );
|
||||||
return();
|
return();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dPrint( ZoneMinder::Logger::DEBUG, "'$process->{command}' running since "
|
dPrint( ZoneMinder::Logger::DEBUG, "'$process->{command}' running since "
|
||||||
.strftime( '%y/%m/%d %H:%M:%S', localtime( $process->{started}) )
|
.strftime( '%y/%m/%d %H:%M:%S', localtime( $process->{started} ) )
|
||||||
.", pid = $process->{pid}"
|
.", pid = $process->{pid}"
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -712,11 +723,11 @@ sub status {
|
||||||
foreach my $process ( values( %cmd_hash ) ) {
|
foreach my $process ( values( %cmd_hash ) ) {
|
||||||
if ( $process->{pending} ) {
|
if ( $process->{pending} ) {
|
||||||
dPrint( ZoneMinder::Logger::DEBUG, "'$process->{command}' pending at "
|
dPrint( ZoneMinder::Logger::DEBUG, "'$process->{command}' pending at "
|
||||||
.strftime( '%y/%m/%d %H:%M:%S', localtime( $process->{pending}) )
|
.strftime( '%y/%m/%d %H:%M:%S', localtime( $process->{pending} ) )
|
||||||
."\n"
|
."\n"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
} # end foreach process
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,8 +74,7 @@ static deinterlace_4field_fptr_t fptr_deinterlace_4field_gray8;
|
||||||
/* Pointer to image buffer memory copy function */
|
/* Pointer to image buffer memory copy function */
|
||||||
imgbufcpy_fptr_t fptr_imgbufcpy;
|
imgbufcpy_fptr_t fptr_imgbufcpy;
|
||||||
|
|
||||||
Image::Image()
|
Image::Image() {
|
||||||
{
|
|
||||||
if ( !initialised )
|
if ( !initialised )
|
||||||
Initialise();
|
Initialise();
|
||||||
width = 0;
|
width = 0;
|
||||||
|
@ -91,8 +90,7 @@ Image::Image()
|
||||||
text[0] = '\0';
|
text[0] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
Image::Image( const char *filename )
|
Image::Image( const char *filename ) {
|
||||||
{
|
|
||||||
if ( !initialised )
|
if ( !initialised )
|
||||||
Initialise();
|
Initialise();
|
||||||
width = 0;
|
width = 0;
|
||||||
|
@ -798,13 +796,13 @@ bool Image::ReadJpeg( const char *filename, unsigned int p_colours, unsigned int
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
/* Assume RGB */
|
/* Assume RGB */
|
||||||
/*
|
/*
|
||||||
#ifdef JCS_EXTENSIONS
|
#ifdef JCS_EXTENSIONS
|
||||||
cinfo->out_color_space = JCS_EXT_RGB;
|
cinfo->out_color_space = JCS_EXT_RGB;
|
||||||
#else
|
#else
|
||||||
cinfo->out_color_space = JCS_RGB;
|
cinfo->out_color_space = JCS_RGB;
|
||||||
#endif
|
#endif
|
||||||
*/
|
*/
|
||||||
cinfo->out_color_space = JCS_RGB;
|
cinfo->out_color_space = JCS_RGB;
|
||||||
new_subpixelorder = ZM_SUBPIX_ORDER_RGB;
|
new_subpixelorder = ZM_SUBPIX_ORDER_RGB;
|
||||||
}
|
}
|
||||||
|
@ -928,13 +926,13 @@ bool Image::WriteJpeg( const char *filename, int quality_override, struct timeva
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
/* Assume RGB */
|
/* Assume RGB */
|
||||||
/*
|
/*
|
||||||
#ifdef JCS_EXTENSIONS
|
#ifdef JCS_EXTENSIONS
|
||||||
cinfo->out_color_space = JCS_EXT_RGB;
|
cinfo->out_color_space = JCS_EXT_RGB;
|
||||||
#else
|
#else
|
||||||
cinfo->out_color_space = JCS_RGB;
|
cinfo->out_color_space = JCS_RGB;
|
||||||
#endif
|
#endif
|
||||||
*/
|
*/
|
||||||
cinfo->in_color_space = JCS_RGB;
|
cinfo->in_color_space = JCS_RGB;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -946,20 +944,20 @@ bool Image::WriteJpeg( const char *filename, int quality_override, struct timeva
|
||||||
cinfo->dct_method = JDCT_FASTEST;
|
cinfo->dct_method = JDCT_FASTEST;
|
||||||
|
|
||||||
jpeg_start_compress( cinfo, TRUE );
|
jpeg_start_compress( cinfo, TRUE );
|
||||||
if ( config.add_jpeg_comments && text[0] )
|
if ( config.add_jpeg_comments && text[0] ) {
|
||||||
{
|
|
||||||
jpeg_write_marker( cinfo, JPEG_COM, (const JOCTET *)text, strlen(text) );
|
jpeg_write_marker( cinfo, JPEG_COM, (const JOCTET *)text, strlen(text) );
|
||||||
}
|
}
|
||||||
// If we have a non-zero time (meaning a parameter was passed in), then form a simple exif segment with that time as DateTimeOriginal and SubsecTimeOriginal
|
// If we have a non-zero time (meaning a parameter was passed in), then form a simple exif segment with that time as DateTimeOriginal and SubsecTimeOriginal
|
||||||
// No timestamp just leave off the exif section.
|
// No timestamp just leave off the exif section.
|
||||||
if(timestamp.tv_sec)
|
if(timestamp.tv_sec)
|
||||||
{
|
{
|
||||||
#define EXIFTIMES_MS_OFFSET 0x36 // three decimal digits for milliseconds
|
#define EXIFTIMES_MS_OFFSET 0x36 // three decimal digits for milliseconds
|
||||||
#define EXIFTIMES_MS_LEN 0x03
|
#define EXIFTIMES_MS_LEN 0x03
|
||||||
#define EXIFTIMES_OFFSET 0x3E // 19 characters format '2015:07:21 13:14:45' not including quotes
|
#define EXIFTIMES_OFFSET 0x3E // 19 characters format '2015:07:21 13:14:45' not including quotes
|
||||||
#define EXIFTIMES_LEN 0x13 // = 19
|
#define EXIFTIMES_LEN 0x13 // = 19
|
||||||
#define EXIF_CODE 0xE1
|
#define EXIF_CODE 0xE1
|
||||||
|
|
||||||
|
// This is a lot of stuff to allocate on the stack. Recommend char *timebuf[64];
|
||||||
char timebuf[64], msbuf[64];
|
char timebuf[64], msbuf[64];
|
||||||
strftime(timebuf, sizeof timebuf, "%Y:%m:%d %H:%M:%S", localtime(&(timestamp.tv_sec)));
|
strftime(timebuf, sizeof timebuf, "%Y:%m:%d %H:%M:%S", localtime(&(timestamp.tv_sec)));
|
||||||
snprintf(msbuf, sizeof msbuf, "%06d",(int)(timestamp.tv_usec)); // we only use milliseconds because that's all defined in exif, but this is the whole microseconds because we have it
|
snprintf(msbuf, sizeof msbuf, "%06d",(int)(timestamp.tv_usec)); // we only use milliseconds because that's all defined in exif, but this is the whole microseconds because we have it
|
||||||
|
@ -971,8 +969,8 @@ bool Image::WriteJpeg( const char *filename, int quality_override, struct timeva
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
0xff, 0x00 };
|
0xff, 0x00 };
|
||||||
memcpy(&exiftimes[EXIFTIMES_OFFSET], timebuf,EXIFTIMES_LEN);
|
memcpy(&exiftimes[EXIFTIMES_OFFSET], timebuf,EXIFTIMES_LEN);
|
||||||
memcpy(&exiftimes[EXIFTIMES_MS_OFFSET], msbuf ,EXIFTIMES_MS_LEN);
|
memcpy(&exiftimes[EXIFTIMES_MS_OFFSET], msbuf, EXIFTIMES_MS_LEN);
|
||||||
jpeg_write_marker (cinfo, EXIF_CODE, (const JOCTET *)exiftimes, sizeof(exiftimes) );
|
jpeg_write_marker( cinfo, EXIF_CODE, (const JOCTET *)exiftimes, sizeof(exiftimes) );
|
||||||
}
|
}
|
||||||
|
|
||||||
JSAMPROW row_pointer; /* pointer to a single row */
|
JSAMPROW row_pointer; /* pointer to a single row */
|
||||||
|
@ -1081,13 +1079,13 @@ bool Image::DecodeJpeg( const JOCTET *inbuffer, int inbuffer_size, unsigned int
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
/* Assume RGB */
|
/* Assume RGB */
|
||||||
/*
|
/*
|
||||||
#ifdef JCS_EXTENSIONS
|
#ifdef JCS_EXTENSIONS
|
||||||
cinfo->out_color_space = JCS_EXT_RGB;
|
cinfo->out_color_space = JCS_EXT_RGB;
|
||||||
#else
|
#else
|
||||||
cinfo->out_color_space = JCS_RGB;
|
cinfo->out_color_space = JCS_RGB;
|
||||||
#endif
|
#endif
|
||||||
*/
|
*/
|
||||||
cinfo->out_color_space = JCS_RGB;
|
cinfo->out_color_space = JCS_RGB;
|
||||||
new_subpixelorder = ZM_SUBPIX_ORDER_RGB;
|
new_subpixelorder = ZM_SUBPIX_ORDER_RGB;
|
||||||
}
|
}
|
||||||
|
@ -1185,13 +1183,13 @@ bool Image::EncodeJpeg( JOCTET *outbuffer, int *outbuffer_size, int quality_over
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
/* Assume RGB */
|
/* Assume RGB */
|
||||||
/*
|
/*
|
||||||
#ifdef JCS_EXTENSIONS
|
#ifdef JCS_EXTENSIONS
|
||||||
cinfo->out_color_space = JCS_EXT_RGB;
|
cinfo->out_color_space = JCS_EXT_RGB;
|
||||||
#else
|
#else
|
||||||
cinfo->out_color_space = JCS_RGB;
|
cinfo->out_color_space = JCS_RGB;
|
||||||
#endif
|
#endif
|
||||||
*/
|
*/
|
||||||
cinfo->in_color_space = JCS_RGB;
|
cinfo->in_color_space = JCS_RGB;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2007,18 +2005,14 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image::Timestamp( const char *label, const time_t when, const Coord &coord, const int size )
|
void Image::Timestamp( const char *label, const time_t when, const Coord &coord, const int size ) {
|
||||||
{
|
|
||||||
char time_text[64];
|
char time_text[64];
|
||||||
strftime( time_text, sizeof(time_text), "%y/%m/%d %H:%M:%S", localtime( &when ) );
|
strftime( time_text, sizeof(time_text), "%y/%m/%d %H:%M:%S", localtime( &when ) );
|
||||||
char text[64];
|
char text[64];
|
||||||
if ( label )
|
if ( label ) {
|
||||||
{
|
|
||||||
snprintf( text, sizeof(text), "%s - %s", label, time_text );
|
snprintf( text, sizeof(text), "%s - %s", label, time_text );
|
||||||
Annotate( text, coord, size );
|
Annotate( text, coord, size );
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
Annotate( time_text, coord, size );
|
Annotate( time_text, coord, size );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue