=head1 SYNOPSIS
- Usage: setbg [-u|sage] [-ve|rbose] [-d|ebug] [-s|leep <n>] [-bgdir <bgdir>]
-
+ Usage: setbg [-u|sage] [-h|elp] [-ve|rbose] [-d|ebug] [-s|leep <n>]
+ [-bgdirs <bgdir> -bgdirs ...]
+
Where:
- -u|sage: Displays this usage
- -ve|rbose: Be verbose
- -d|ebug: Output debug messages
+ -u|sage: Displays this usage
+ -h|elp: Display full help
+ -ve|rbose: Be verbose
+ -d|ebug: Output debug messages
- -s|leep: Number of minutes to sleep between setting the background
- (Default: 1 hour)
- -b|gdir: Directory to scan for images (Default: /web/Pictures)
+ -s|leep: Number of minutes to sleep between setting the background
+ (Default: 1 hour)
+ -l|ockscreen: Change lockscreen backround (Default: False)
+ -b|gdirs: Directories to scan for images
=head1 DESCRIPTION
-This script sets the background image randomly based on images $imgDir. Note
-if this script is run again it senses that it was previously run and sends the
-previous script a SIGUSR2 which the script intrprets as "Change the background
-now", then exits.
+This script sets the background image randomly based on images found in bgdirs.
+Note if this script is run again it senses that it was previously run and sends
+the previous script a SIGUSR2 which the script intrprets as "Change the
+background now", then exits.
+
+Data is written to the following files:
+
+ ~/.setbg: Contains the filename of the current background image
+ ~/.setbg.hist Contains a history of all images displayed for this run
+ ~/.setbg.stats Contains statistical information for the current run
+
+Also note that this script will process a SIGUSR1 to mean "re-evaluate the
+contents of the bgdirs incase it has changed and display a new image". This is
+useful for script to be able to alert setbg that something has changed. For
+example, a script named rmbg might look at ~/.setbg to get the name of the
+current background image file and remove it then signal setbg with SIGUSR1 to
+have it re-evaluate the state of bgdirs.
+
+Finally setbg will perform the this re-evaluation at midnight everyday. This is
+useful because we point setbg to look at -bgdirs from Dropbox where Camera
+Uploads is included and new pictures can arrive everyday.
=cut
use lib "$FindBin::Bin/../lib";
+use Pod::Usage;
+
use DateUtils;
use Display;
use Logger;
use Utils;
-my $VERSION = '$Revision: 1.10 $';
+my $VERSION = '$Revision: 1.12 $';
($VERSION) = ($VERSION =~ /\$Revision: (.*) /);
-my $processes = new Proc::ProcessTable;
-my @imgDirs;
-my %totals;
-
-foreach my $process (@{$processes->table}) {
- if ($process->cmndline =~ /setbg/ and
- $process->pid != $$) {
- kill 12, $process->pid;
+my $processes = Proc::ProcessTable->new;
+my %opts = (
+ sleep => 60,
+ lockscreen => 0,
+ usage => sub { pod2usage },
+ help => sub { pod2usage (-verbose => 2)},
+ verbose => sub { set_verbose },
+ debug => sub { set_debug },
+);
- exit 0;
- } # if
-} # foreach
+my %totals;
sub displayStats () {
my $statsFile = Logger->new(
);
$statsFile->log('At ' . localtime());
+ $statsFile->log('Sleep: ' . $opts{sleep});
+ $statsFile->log('Image directories:');
+
+ for (my $i = 0; $i < scalar @{$opts{bgdirs}}; $i++) {
+ $statsFile->log("\t$opts{bgdirs}[$i]: $opts{bgdircnt}[$i]")
+ } # for
Stats \%totals, $statsFile;
sub fillPictures () {
my @images;
- foreach (@imgDirs) {
- my @pics = `find "$_" -type f -name "*.jpg"`;
+ $totals{bgdirs} = 0;
+
+ for (@{$opts{bgdirs}}) {
+ my ($status, @pics) = Execute "find \"$_/\" -type f";
chomp @pics;
- push @images, @pics;
- } # foreach
+
+ push @images, grep(/jpg$|png$|gif$/i, @pics);
+
+ @pics = grep(/jpg$|png$|gif$/i, @pics);
+
+ push @{$opts{bgdircnt}}, scalar @pics;
+
+ $totals{bgdirs}++;
+ } # for
$totals{images} = scalar @images;
return @images;
} # fillPictures
-sub updateSetBG ($) {
- my ($image) = @_;
+sub writeHistory($) {
+ my ($msg) = @_;
- open my $log, '>', "$ENV{HOME}/.$FindBin::Script"
- or error "Unable to open $ENV{HOME}/.$FindBin::Script for writing - $!", 1;
+ open my $hist, '>>', "$ENV{HOME}/.$FindBin::Script.hist"
+ or error "Unable to open $ENV{HOME}/.$FindBin::Script.hist for append - $!", 1;
- display $image, $log;
+ $msg = localtime() . $msg;
- close $log;
+ display $msg, $hist;
- open $log, '>>', "$ENV{HOME}/.$FindBin::Script.hist"
- or error "Unable to open $ENV{HOME}/.$FindBin::Script.hist for append - $!", 1;
+ close $hist;
+} # writeHistory
- my $msg = localtime() . ":$image";
+sub updateSetBG($$) {
+ my ($bgimage, $lockimage) = @_;
- display $msg, $log;
+ open my $setbg, '>', "$ENV{HOME}/.$FindBin::Script"
+ or error "Unable to open $ENV{HOME}/.$FindBin::Script for writing - $!", 1;
- close $log;
+ display $bgimage, $setbg;
+
+ close $setbg;
+
+ my $msg = ":$bgimage";
+ $msg .= " lock:$lockimage" if $opts{lockscreen};
+
+ writeHistory $msg;
return;
} # updateSetBG
-$0 = "$FindBin::Script " . join ' ', @ARGV;
+sub SwitchWallPaper {
+ # We don't need to do anything here, just handle the interrupt and
+ # let the while loop continue.
+ debug 'SwitchWallPaper: Interrupt received';
+ displayStats;
+
+ return;
+} # SwitchWallPaper
+## Main
verbose "$FindBin::Script v$VERSION";
-my $sleep = 60 * 60;
+my @argvCopy = @ARGV;
GetOptions (
- 'usage' => sub { Usage },
- 'verbose' => sub { set_verbose },
- 'debug' => sub { set_debug },
- 'sleep=i' => \$sleep,
- 'bgdir=s' => \@imgDirs,
+ \%opts,
+ 'usage',
+ 'help',
+ 'verbose',
+ 'debug',
+ 'sleep=i',
+ 'lockscreen',
+ 'bgdirs=s@',
) || Usage;
-for (my $i = 0; $i < scalar @imgDirs; $i++) {
- error "$imgDirs[$i] is not a directory", 1 unless -d $imgDirs[$i];
+local $0 = "$FindBin::Script " . join ' ', @argvCopy;
+
+for my $process (@{$processes->table}) {
+ if ($process->cmndline =~ /setbg/ and
+ $process->pid != $$) {
+ kill 12, $process->pid;
+
+ exit 0;
+ } # if
+} # for
+
+for (my $i = 0; $i < scalar @{$opts{bgdirs}}; $i++) {
+ error "$opts{bgdirs}[$i] is not a directory", 1 unless -d $opts{bgdirs}[$i];
- $imgDirs[$i] = File::Spec->rel2abs ($imgDirs[$i]);
-} # foreach
+ $opts{bgdirs}[$i] = File::Spec->rel2abs ($opts{bgdirs}[$i]);
+} # for
# Using gsettings
-my $setbg = "gsettings";
-my $setbgOpts= "set org.gnome.desktop.background picture-uri \"file://";
+my $setbg = "gsettings";
+my $setbgOpts = "set org.gnome.desktop.background picture-uri \"file://";
+my $setLockOpts = "set org.gnome.desktop.screensaver picture-uri \"file://";
my @images = fillPictures;
-Usage "No images to display. Must specify -bgdir" unless @images;
-
-sub SwitchWallPaper {
- # We don't need to do anything here, just handle the interrupt and
- # let the while loop continue.
- debug 'SwitchWallPaper: Interrupt received';
- displayStats;
-} # SwitchWallPaper
+Usage "No images to display. Must specify -bgdirs" unless @images;
$SIG{USR2} = \&SwitchWallPaper;
$SIG{USR1} = \&fillPictures;
EnterDaemonMode unless defined $DB::OUT;
+my $pickNewImages = 1;
+my ($bgimage, $lockimage);
+
while () {
- my $image = escapeHTML ($images[int (rand $#images)]);
+ if ($pickNewImages) {
+ $bgimage = escapeHTML ($images[int (rand $#images)]);
+ $lockimage = escapeHTML ($images[int (rand $#images)]);
+ } # if
+
+ my $monitorIsOn;
- my $cmd = "$setbg $setbgOpts$image\" 2> /dev/null";
+ my ($status, @output) = Execute("xset q | grep Monitor | awk '{print \$3}'");
- my @output = `$cmd`;
+ if ($status or $output[0] eq 'Off') {
+ writeHistory ":Monitor off, not setting background to $bgimage - will keep trying";
- if ($? != 0) {
- error "Trying to set background - command used \"$cmd\"\n\nOutput\n\n" .
- join "\n", @output;
- $totals{errors}++;
+ $pickNewImages = 0;
} else {
- $totals{'Images displayed'}++;
+ $pickNewImages = 1;
+
+ my $cmd = "$setbg $setbgOpts$bgimage\" 2> /dev/null";
+
+ ($status, @output) = Execute $cmd;
- updateSetBG $image;
+ if ($status) {
+ error "Trying to set background - command used \"$cmd\"\n\nOutput\n\n" .
+ join "\n", @output;
+ $totals{errors}++;
+ } else {
+ $totals{'Images displayed'}++;
+ } # if
+
+ if ($opts{lockscreen}) {
+ $cmd = "$setbg $setLockOpts$lockimage\" 2> /dev/null";
+
+ ($status, @output) = Execute $cmd;
+
+ if ($status != 0) {
+ error "Trying to set lock screen - command used \"$cmd\"\n\nOutput\n\n" .
+ join "\n", @output;
+ $totals{errors}++;
+ } else {
+ $totals{'Lock screens displayed'}++;
+ } # if
+ } # if
+
+ updateSetBG $bgimage, $lockimage;
} # if
+ displayStats;
+
$today = YMD;
- sleep $sleep;
+ sleep $opts{sleep} * 60;
if ($today ne YMD){
@images = fillPictures;
+
+ displayStats;
} # if
} # while