Keeping it Small and Simple

2008.01.25

Simple wallpaper tool in Ruby

Filed under: Ruby Programming — Tags: , , , , — Lorenzo E. Danielsson @ 15:39

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.

Advertisements

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: