Simple wallpaper tool in Ruby
Ben is constantly on the look-out for small applications that he can write in order to practice his Ruby skills. This morning he told me he wants to write a “wallpaper switcher” (or whatever you call those things). It seemed like an interesting little program, so I hastily put this together.
1 #! /usr/bin/ruby
2
3 # A wallpaper tool.
4
5 require ‘optparse‘
6
7 def parsedir(path)
8 a = []
9
10 Dir.new(path).each do |file|
11 next if file =~ /^\./
12
13 fp = "#{path}/#{file}"
14 File.directory?(fp) ? a.concat(parsedir(fp)) : a << fp
15 end
16 a
17 end
18
19 options = {
20 :dir => nil,
21 :file => nil,
22 :interval => 60,
23 :random => false,
24 :use => ‘wmsetbg‘
25 }
26
27 begin
28 OptionParser.new do |opts|
29 opts.banner = "usage: #{$0} [options]"
30
31 opts.on("-d", "–directory=DIR", String, "scan directory") do |dir|
32 options[:dir] = dir
33 end
34
35 opts.on("-f", "–file=FILE", String, "read wallpapers from file") do |file|
36 options[:file] = file
37 end
38
39 opts.on("-i", "–interval=I", Integer, "set the interval") do |interval|
40 options[:interval] = interval
41 end
42
43 opts.on("-r", "–[no-]random", "randomize the order") do |r|
44 options[:random] = r
45 end
46
47 opts.on("-u", "–use=APP", String, "set the utility to use") do |use|
48 options[:use] = use
49 end
50 end.parse!
51 rescue OptionParser::InvalidOption => err
52 $stderr.print err.to_s + "\n"
53 exit
54 rescue OptionParser::MissingArgument => err
55 $stderr.print err.to_s + "\n"
56 exit
57 end
58
59 wp = []
60 wp.concat(IO.readlines(options[:file])) unless options[:file].nil?
61 wp.concat(parsedir(options[:dir])) unless options[:dir].nil?
62 wp.collect! { |image| image.chomp }.delete_if { |image| !File.exists? image }
63 abort "No wallpapers in list." if wp.empty?
64
65 %w[TERM INT].each do |sig|
66 trap(sig) {
67 puts "Are you crazy?? What are you doing to me?"
68 exit
69 }
70 end
71
72 loop do
73 (options[:random] ? wp.sort_by { rand } : wp).each { |image|
74 `#{options[:use]} #{image} > /dev/null 2>&1`
75 sleep options[:interval]
76 }
77 end
Improving it
Several ideas come to mind:
- Add standard options like –help
- Handle errors.
- Make sure all the files added to the wp array actually are images.
- Add an option to make the program run through the wallpapers once only (or a certain number of times.
- Currently all the images get scaled by default (using wmsetbg). Add options for centering, tiling etc. images.
- I’m calling a utility called wmsetbg, which comes with Window Maker. Instead of doing this, you could set the “paint” an image on the root window yourself. Look into Ruby/Xlib, Imlib2-ruby or any other library that you know of that will allow you access to the root window.
- I’m sure you can think of lots more.
If you really wanted to take this little exercise a bit further you could create a custom format for the wallpapers file. For example, it could look like this
path/to/wallpaper:options
Where options would be something like scale, center, tile, etc. You could take it way too far and create an XML file with all kinds of options, such as display such-and-such image only during a specific time of the day, or on a specific day or interval of days. This way you could have special images for special occasions, such as Yule, Easter and so on. If you do decide to implement this, you may also want to consider a visit to your shrink. You are going waaay overboard and need help. Urgently.
Does it work with JRuby?
I’m glad you asked. Short answer: yes. Long answer: Hell, yeah!
Does it work with Ruby 1.9?
Yes it does. Notice that there are some things you could do to ruby1.9-ify it. For instance, you could initialize the options array as follows:
options = {
dir: nil,
file: nil,
interval: 60,
random: false,
use: ‘wmsetbg‘
}
Does it work with Rubinius?
Yes, of course it does!
I did discover one small annoyance. Hitting CTRL+C will display the “Are you..” message alright, but the program will keep running. Not sure why, but I’ll look into that.


