Compare commits
2 Commits
4716ce55bc
...
3f54f5f4bc
Author | SHA1 | Date |
---|---|---|
John Mertz | 3f54f5f4bc | |
John Mertz | 3f07586ae9 |
|
@ -2,16 +2,20 @@
|
||||||
|
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
|
use POSIX;
|
||||||
|
|
||||||
use lib "$ENV{HOME}/perl5/lib/perl5";
|
use lib "$ENV{HOME}/perl5/lib/perl5";
|
||||||
|
|
||||||
our $debug = 1; # For testing, will output configuration and errors if true
|
our $debug = 1; # For testing, will output configuration and errors if true
|
||||||
|
our %settings;
|
||||||
|
our @e;
|
||||||
|
our $pidfile = "/tmp/$ENV{USER}-wallpaper.pid";
|
||||||
|
|
||||||
use AnyEvent::Sway;
|
use AnyEvent::Sway;
|
||||||
our $s = AnyEvent::Sway->new();
|
our $s = AnyEvent::Sway->new();
|
||||||
|
|
||||||
our $o = $s->get_outputs->recv();
|
our $o = $s->get_outputs->recv();
|
||||||
die "No outputs detected.\n" unless (scalar(@$o) > 1);
|
die "No outputs detected.\n" unless (scalar(@$o));
|
||||||
|
|
||||||
sub usage()
|
sub usage()
|
||||||
{
|
{
|
||||||
|
@ -30,28 +34,31 @@ are currently enabled will be set.\n
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# SIGUSR reset the timer, force immediate reload, continue looping
|
||||||
$SIG{USR1} = sub {
|
$SIG{USR1} = sub {
|
||||||
# TODO: Update the timeout method so that the daemon will simply run the job as a function.
|
alarm 0;
|
||||||
# when SIGUSR1 is received, force the alarm to expire immediately in order to rotate the image without delay.
|
run(%settings);
|
||||||
print "This should rotate the image, but it doesn't yet";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# SIGTERM reset the timer, clean pid, and allow for the main loop to finish run
|
||||||
$SIG{TERM} = sub {
|
$SIG{TERM} = sub {
|
||||||
|
alarm 0;
|
||||||
clean();
|
clean();
|
||||||
exit(0);
|
$settings{daemon} = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
$SIG{INT} = sub {
|
# SIGKILL clean pid then exit immediately
|
||||||
|
$SIG{KILL} = sub {
|
||||||
clean();
|
clean();
|
||||||
exit(0);
|
exit(0);
|
||||||
};
|
};
|
||||||
|
|
||||||
sub clean
|
sub clean
|
||||||
{
|
{
|
||||||
my $pidfile = "/var/run/$ENV{HOME}-wallpaper.pid";
|
|
||||||
if (-e $pidfile) {
|
if (-e $pidfile) {
|
||||||
open (my $fh, '<', $pidfile);
|
open (my $fh, '<', $pidfile);
|
||||||
my $p = <$fh>;
|
my $p = <$fh>;
|
||||||
|
close($fh);
|
||||||
chomp $p;
|
chomp $p;
|
||||||
kill($p);
|
kill($p);
|
||||||
unlink($pidfile);
|
unlink($pidfile);
|
||||||
|
@ -60,14 +67,12 @@ sub clean
|
||||||
|
|
||||||
sub choose_image
|
sub choose_image
|
||||||
{
|
{
|
||||||
my $path = shift;
|
my @w = glob("$settings{path}/*");
|
||||||
|
|
||||||
my @w = glob("$path/*");
|
|
||||||
return undef unless (scalar(@w));
|
return undef unless (scalar(@w));
|
||||||
|
|
||||||
my @i;
|
my @i;
|
||||||
foreach (@w) {
|
foreach (@w) {
|
||||||
if (-d "$path/$_") {
|
if (-d "$settings{path}/$_") {
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
if ($_ =~ m/\.(png|jpg)$/) {
|
if ($_ =~ m/\.(png|jpg)$/) {
|
||||||
|
@ -110,7 +115,7 @@ sub crop
|
||||||
my ($iw, $ih) = $im->Get("columns", "rows");
|
my ($iw, $ih) = $im->Get("columns", "rows");
|
||||||
|
|
||||||
# Return full size if it is smaller in either dimension then the output
|
# Return full size if it is smaller in either dimension then the output
|
||||||
if ($iw < $ow || $ih < $oh) {
|
if ($iw <= $ow || $ih <= $oh) {
|
||||||
print "Not cropping $image because it is too small\n";
|
print "Not cropping $image because it is too small\n";
|
||||||
$cropped =~ s#-cropped\.([^\.]+)$#\.$1#;
|
$cropped =~ s#-cropped\.([^\.]+)$#\.$1#;
|
||||||
use File::Copy;
|
use File::Copy;
|
||||||
|
@ -159,12 +164,62 @@ sub set_background
|
||||||
return "Failed to run Sway IPC command '$cmd'";
|
return "Failed to run Sway IPC command '$cmd'";
|
||||||
}
|
}
|
||||||
|
|
||||||
my @targets;
|
sub run
|
||||||
my $daemon = 0;
|
{
|
||||||
my $delay = 300;
|
my @err;
|
||||||
my $crop = 1;
|
# Local copy of targets so that it will re-check active every time
|
||||||
my $path;
|
my @t = $settings{targets} if (defined($settings{targets}));
|
||||||
|
unless (scalar(@t)) {
|
||||||
|
@t = get_active();
|
||||||
|
push(@err, "No target outputs") unless (scalar(@t));
|
||||||
|
}
|
||||||
|
foreach my $a (@t) {
|
||||||
|
my $image = choose_image($settings{path});
|
||||||
|
if (defined($image)) {
|
||||||
|
if ( -r "$image" ) {
|
||||||
|
print "selected $image\n";
|
||||||
|
my $cropped;
|
||||||
|
if ($settings{crop}) {
|
||||||
|
if ($settings{debug}) {
|
||||||
|
print "Cropping image for '$a' using '$image'\n";
|
||||||
|
}
|
||||||
|
my ($ow, $oh) = get_size($a);
|
||||||
|
$cropped = crop($image, $ow, $oh);
|
||||||
|
unless ($cropped) {
|
||||||
|
push(@err, "Failed to generate cropped image") unless ($cropped);
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$cropped = $image;
|
||||||
|
}
|
||||||
|
my $e = set_background($a,$cropped);
|
||||||
|
push(@err, $e) if (defined($e));
|
||||||
|
if ($settings{crop}) {
|
||||||
|
print "Deleting $cropped\n";
|
||||||
|
#unlink($cropped) || push(@err, "Failed to delete $cropped after setting: $!");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
push(@err, "$a: Unable to read image $image");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
push(@err, "$a: Unable to select image from $settings{path}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($settings{debug} && $settings{daemon}) {
|
||||||
|
print STDERR join("\n",@err);
|
||||||
|
} else {
|
||||||
|
@e = @err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# Collect arguments
|
||||||
|
################################################################################
|
||||||
|
my @targets;
|
||||||
|
my $daemon;
|
||||||
|
my $delay;
|
||||||
|
my $crop;
|
||||||
|
my $path;
|
||||||
while (my $arg = shift(@ARGV)) {
|
while (my $arg = shift(@ARGV)) {
|
||||||
if ($arg eq '-h' || $arg eq '--help') {
|
if ($arg eq '-h' || $arg eq '--help') {
|
||||||
usage();
|
usage();
|
||||||
|
@ -191,13 +246,13 @@ while (my $arg = shift(@ARGV)) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
die "Invalid rotation delay: $delay" unless ($delay =~ m/^\d+$/);
|
################################################################################
|
||||||
|
# Validate arguments
|
||||||
|
################################################################################
|
||||||
|
|
||||||
if ($path) {
|
die "Invalid rotation delay: $delay" if (defined($delay) && $delay !~ m/^\d+$/);
|
||||||
die "Invalid wallpaper path '$path'. Not a directory." unless (-d $path);
|
|
||||||
} else {
|
die "Invalid wallpaper path '$path'. Not a directory." if (defined($path) && !-d $path);
|
||||||
$path = "$ENV{HOME}/wallpapers";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scalar(@targets)) {
|
if (scalar(@targets)) {
|
||||||
my @kept;
|
my @kept;
|
||||||
|
@ -216,72 +271,59 @@ if (scalar(@targets)) {
|
||||||
@targets = @kept;
|
@targets = @kept;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($daemon) {
|
$settings{targets} = @targets || undef;
|
||||||
|
$settings{daemon} = $daemon || 0;
|
||||||
|
$settings{path} = $path || "$ENV{HOME}/wallpapers";
|
||||||
|
$settings{crop} = $crop || 1;
|
||||||
|
$settings{delay} = $delay || 300;
|
||||||
|
$settings{debug} = $debug || 0;
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# For if daemonized
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
if ($settings{daemon}) {
|
||||||
my $p = fork();
|
my $p = fork();
|
||||||
if ($p) {
|
if ($p) {
|
||||||
my $pidfile = "/var/run/$ENV{HOME}-wallpaper.pid";
|
if (open(my $fh, ">", $pidfile)) {
|
||||||
open(my $fh, ">", $pidfile) || die "Failed to open pidfile: $pidfile";
|
print $fh "$p" || die "Failed to write pid ($p) to pidfile $pidfile";
|
||||||
print $fh "Daemonized as PID: $p\n" || die "Failed to write pid ($p) to pidfile $pidfile";
|
|
||||||
close($fh);
|
close($fh);
|
||||||
|
} else {
|
||||||
|
print "Failed to open pidfile: $pidfile: $!\n";
|
||||||
|
}
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
#setpgrp;
|
||||||
|
#setsid;
|
||||||
|
umask 0;
|
||||||
|
# TODO: configure systemD logging
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($debug) {
|
################################################################################
|
||||||
print "Initial configuration:\n";
|
# Main
|
||||||
print " Targets: ( " . ( join(" ",@targets) || "All active" ) . " )\n";
|
################################################################################
|
||||||
print " Daemon: $daemon\n";
|
|
||||||
print " Path: $path\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
my @e;
|
|
||||||
do {
|
do {
|
||||||
my @err;
|
run(%settings);
|
||||||
# Local copy of targets so that it will re-check active every time
|
if ($settings{daemon}) {
|
||||||
my @t = @targets;
|
my $normal = "reload wallpaper";
|
||||||
unless (scalar(@t)) {
|
eval {
|
||||||
@t = get_active();
|
$SIG{ALRM} = sub { print "$normal\n" };
|
||||||
push(@err, "No target outputs") unless (scalar(@t));
|
alarm $settings{delay};
|
||||||
}
|
POSIX::pause();
|
||||||
foreach my $a (@t) {
|
alarm 0;
|
||||||
my $image = choose_image($path);
|
};
|
||||||
if (defined($image)) {
|
if ($@ && $@ !~ quotemeta($normal)) {
|
||||||
if ( -r "$image" ) {
|
if ($settings{debug}) {
|
||||||
print "selected $image\n";
|
print $normal;
|
||||||
my $cropped;
|
|
||||||
if ($crop) {
|
|
||||||
if ($debug) {
|
|
||||||
print "Cropping image for '$a' using '$image'\n";
|
|
||||||
}
|
|
||||||
my ($ow, $oh) = get_size($a);
|
|
||||||
$cropped = crop($image, $ow, $oh);
|
|
||||||
unless ($cropped) {
|
|
||||||
push(@err, "Failed to generate cropped image") unless ($cropped);
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$cropped = $image;
|
|
||||||
}
|
|
||||||
my $e = set_background($a,$cropped);
|
|
||||||
push(@err, $e) if (defined($e));
|
|
||||||
if ($crop) {
|
|
||||||
print "Deleting $cropped\n";
|
|
||||||
#unlink($cropped) || push(@err, "Failed to delete $cropped after setting: $!");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
push(@err, "$a: Unable to read image $image");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
push(@err, "$a: Unable to select image from $path");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($debug && $daemon) {
|
|
||||||
print STDERR join("\n",@err);
|
|
||||||
sleep($delay);
|
|
||||||
} else {
|
|
||||||
@e = @err;
|
|
||||||
}
|
}
|
||||||
} while ($daemon);
|
} while ($settings{daemon});
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# If we made it to here, it was not daemonized. Output errors and exit
|
||||||
|
################################################################################
|
||||||
|
|
||||||
if (scalar(@e)) {
|
if (scalar(@e)) {
|
||||||
die "Failure while not running as daemon:\n" .
|
die "Failure while not running as daemon:\n" .
|
||||||
|
|
Loading…
Reference in New Issue