#!/usr/bin/perl =pod =head1 NAME $RCSfile: setbg,v $ Set background =head1 VERSION =over =item Author Andrew DeFaria =item Revision: $Revision: 1.10 $ =item Created: Fri Mar 18 01:14:38 PST 2005 =item Modified: $Date: 2012/11/09 15:31:30 $ =back =head1 SYNOPSIS Usage: setbg [-u|sage] [-h|elp] [-ve|rbose] [-d|ebug] [-s|leep ] [-bgdirs -bgdirs ...] Where: -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|gdirs: Directories to scan for images =head1 DESCRIPTION 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 strict; use warnings; use FindBin; use Getopt::Long; use Proc::ProcessTable; use File::Spec; use CGI qw/:standard/; use lib "$FindBin::Bin/../lib"; use Pod::Usage; use DateUtils; use Display; use Logger; use Utils; my $VERSION = '$Revision: 1.11 $'; ($VERSION) = ($VERSION =~ /\$Revision: (.*) /); my $processes = Proc::ProcessTable->new; my %opts = ( sleep => 60, usage => sub { pod2usage }, help => sub { pod2usage (-verbose => 2)}, verbose => sub { set_verbose }, debug => sub { set_debug }, ); my %totals; sub displayStats () { my $statsFile = Logger->new( name => ".$FindBin::Script.stats", path => $ENV{HOME}, extension => '', ); $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; return; } # displayStats sub fillPictures () { my @images; $totals{bgdirs} = 0; for (@{$opts{bgdirs}}) { my @pics = `find "$_" -type f -name "*.jpg"`; chomp @pics; push @images, @pics; push @{$opts{bgdircnt}}, scalar @pics; $totals{bgdirs}++; } # for $totals{images} = scalar @images; return @images; } # fillPictures sub updateSetBG ($) { my ($image) = @_; open my $setbg, '>', "$ENV{HOME}/.$FindBin::Script" or error "Unable to open $ENV{HOME}/.$FindBin::Script for writing - $!", 1; display $image, $setbg; close $setbg; my $msg = localtime() . ":$image"; open my $hist, '>>', "$ENV{HOME}/.$FindBin::Script.hist" or error "Unable to open $ENV{HOME}/.$FindBin::Script.hist for append - $!", 1; display $msg, $hist; close $hist; return; } # updateSetBG 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 @argvCopy = @ARGV; GetOptions ( \%opts, 'usage', 'help', 'verbose', 'debug', 'sleep=i', 'bgdirs=s@', ) || Usage; 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]; $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 @images = fillPictures; Usage "No images to display. Must specify -bgdirs" unless @images; $SIG{USR2} = \&SwitchWallPaper; $SIG{USR1} = \&fillPictures; my $debugger = $DB::OUT; my $today; truncate "$ENV{HOME}/.$FindBin::Script.hist", 0; EnterDaemonMode unless defined $DB::OUT; while () { my $image = escapeHTML ($images[int (rand $#images)]); my $cmd = "$setbg $setbgOpts$image\" 2> /dev/null"; my @output = `$cmd`; if ($? != 0) { error "Trying to set background - command used \"$cmd\"\n\nOutput\n\n" . join "\n", @output; $totals{errors}++; } else { $totals{'Images displayed'}++; updateSetBG $image; } # if displayStats; $today = YMD; sleep $opts{sleep} * 60; if ($today ne YMD){ @images = fillPictures; displayStats; } # if } # while