Fixed typo in pod
[clearscm.git] / bin / setbg
1 #!/usr/bin/perl
2
3 =pod
4
5 =head1 NAME $RCSfile: setbg,v $
6
7 Set background
8
9 =head1 VERSION
10
11 =over
12
13 =item Author
14
15 Andrew DeFaria <Andrew@ClearSCM.com>
16
17 =item Revision:
18
19 $Revision: 1.10 $
20
21 =item Created:
22
23 Fri Mar 18 01:14:38 PST 2005
24
25 =item Modified:
26
27 $Date: 2012/11/09 15:31:30 $
28
29 =back
30
31 =head1 SYNOPSIS
32
33  Usage: setbg [-u|sage] [-h|elp] [-ve|rbose] [-d|ebug] [-s|leep <n>]
34               [-bgdirs <bgdir> -bgdirs ...]
35  
36  Where:
37
38  -u|sage:     Displays this usage
39  -h|elp:      Display full help
40  -ve|rbose:   Be verbose
41  -d|ebug:     Output debug messages
42
43  -s|leep:     Number of minutes to sleep between setting the background
44              (Default: 1 hour)
45  -b|gdirs:    Directories to scan for images
46
47 =head1 DESCRIPTION
48
49 This script sets the background image randomly based on images found in bgdirs.
50 Note if this script is run again it senses that it was previously run and sends
51 the previous script a SIGUSR2 which the script intrprets as "Change the
52 background now", then exits.
53
54 Data is written to the following files:
55
56  ~/.setbg:      Contains the filename of the current background image
57  ~/.setbg.hist  Contains a history of all images displayed for this run
58  ~/.setbg.stats Contains statistical information for the current run
59
60 Also note that this script will process a SIGUSR1 to mean "re-evaluate the
61 contents of the bgdirs incase it has changed and display a new image". This is
62 useful for script to be able to alert setbg that something has changed. For
63 example, a script named rmbg might look at ~/.setbg to get the name of the
64 current background image file and remove it then signal setbg with SIGUSR1 to
65 have it re-evaluate the state of bgdirs. 
66
67 Finally setbg will perform the this re-evaluation at midnight everyday. This is
68 useful because we point setbg to look at -bgdirs from Dropbox where Camera 
69 Uploads is included and new pictures can arrive everyday.
70
71 =cut
72
73 use strict;
74 use warnings;
75
76 use FindBin;
77 use Getopt::Long;
78 use Proc::ProcessTable;
79 use File::Spec;
80 use CGI qw/:standard/;
81
82 use lib "$FindBin::Bin/../lib";
83
84 use Pod::Usage;
85
86 use DateUtils;
87 use Display;
88 use Logger;
89 use Utils;
90
91 my $VERSION  = '$Revision: 1.11 $';
92   ($VERSION) = ($VERSION =~ /\$Revision: (.*) /);
93
94 my $processes = Proc::ProcessTable->new;
95 my %opts = (
96   sleep   => 60,
97   usage   => sub { pod2usage },
98   help    => sub { pod2usage (-verbose => 2)},
99   verbose => sub { set_verbose },
100   debug   => sub { set_debug },
101 );
102
103 my %totals;
104
105 sub displayStats () {
106   my $statsFile = Logger->new(
107     name      => ".$FindBin::Script.stats",
108     path      => $ENV{HOME},
109     extension => '',
110   );
111
112   $statsFile->log('At ' . localtime());
113   $statsFile->log('Sleep: ' . $opts{sleep});
114   $statsFile->log('Image directories:');
115
116   for (my $i = 0; $i < scalar @{$opts{bgdirs}}; $i++) {
117     $statsFile->log("\t$opts{bgdirs}[$i]: $opts{bgdircnt}[$i]")
118   } # for
119
120   Stats \%totals, $statsFile;
121
122   return;
123 } # displayStats
124
125 sub fillPictures () {
126   my @images;
127
128   $totals{bgdirs} = 0;
129
130   for (@{$opts{bgdirs}}) {
131     my @pics = `find "$_" -type f -name "*.jpg"`;
132
133     chomp @pics;
134
135     push @images, @pics;
136     push @{$opts{bgdircnt}}, scalar @pics;
137
138     $totals{bgdirs}++;
139   } # for
140
141   $totals{images} = scalar @images;
142
143   return @images;
144 } # fillPictures
145
146 sub updateSetBG ($) {
147   my ($image) = @_;
148
149   open my $setbg, '>', "$ENV{HOME}/.$FindBin::Script"
150     or error "Unable to open $ENV{HOME}/.$FindBin::Script for writing - $!", 1;
151
152   display $image, $setbg;
153
154   close $setbg;
155
156   my $msg = localtime() . ":$image";
157
158   open my $hist, '>>', "$ENV{HOME}/.$FindBin::Script.hist"
159     or error "Unable to open $ENV{HOME}/.$FindBin::Script.hist for append - $!", 1;
160
161   display $msg, $hist;
162
163   close $hist;
164
165   return;
166 } # updateSetBG
167
168 sub SwitchWallPaper {
169   # We don't need to do anything here, just handle the interrupt and
170   # let the while loop continue.
171   debug 'SwitchWallPaper: Interrupt received';
172   displayStats;
173
174   return;
175 } # SwitchWallPaper
176
177 ## Main
178 verbose "$FindBin::Script v$VERSION";
179
180 my @argvCopy = @ARGV;
181
182 GetOptions (
183   \%opts,
184   'usage',
185   'help',
186   'verbose',
187   'debug',
188   'sleep=i',
189   'bgdirs=s@',
190 ) || Usage;
191
192 local $0 = "$FindBin::Script " . join ' ', @argvCopy;
193
194 for my $process (@{$processes->table}) {
195   if ($process->cmndline =~ /setbg/ and
196       $process->pid != $$) { 
197     kill 12, $process->pid;
198
199     exit 0;
200   } # if
201 } # for
202
203 for (my $i = 0; $i < scalar @{$opts{bgdirs}}; $i++) {
204   error "$opts{bgdirs}[$i] is not a directory", 1 unless -d $opts{bgdirs}[$i];
205
206   $opts{bgdirs}[$i] = File::Spec->rel2abs ($opts{bgdirs}[$i]);
207 } # for
208
209 # Using gsettings
210 my $setbg     = "gsettings";
211 my $setbgOpts= "set org.gnome.desktop.background picture-uri \"file://";
212
213 my @images = fillPictures;
214
215 Usage "No images to display. Must specify -bgdirs" unless @images;
216
217 $SIG{USR2} = \&SwitchWallPaper;
218 $SIG{USR1} = \&fillPictures;
219
220 my $debugger = $DB::OUT;
221 my $today;
222
223 truncate "$ENV{HOME}/.$FindBin::Script.hist", 0;
224
225 EnterDaemonMode unless defined $DB::OUT;
226
227 while () {
228   my $image = escapeHTML ($images[int (rand $#images)]);
229
230   my $cmd = "$setbg $setbgOpts$image\" 2> /dev/null";
231
232   my @output = `$cmd`;
233
234   if ($? != 0) {
235     error "Trying to set background - command used \"$cmd\"\n\nOutput\n\n" . 
236       join "\n", @output;
237     $totals{errors}++;
238   } else {
239     $totals{'Images displayed'}++;
240
241     updateSetBG $image;
242   } # if
243
244   displayStats;
245
246   $today = YMD;
247
248   sleep $opts{sleep} * 60;
249
250   if ($today ne YMD){
251     @images = fillPictures;
252
253     displayStats;
254   } # if
255 } # while