Latest Idiotic Hack

I run MPD to play music at home.

In a burst of inspiration, today I hacked a new feature into my twitter client. If it sees a hashtag of #MPD in a tweet (or direct message), it takes the rest of the message, tries to find a song with a matching title (in my collection), and adds it to my play queue.

There’s no guarantee I’ll actually listen to them, but they’ll show up in my last.fm stream if I do…

Peppa Popper

I was inspired by a children’s TV show Peppa Pig visits Daddy Pig’s Office and the fact that my daughter (aged 16 months) has been taking marginally more interest in the computer.

So I did a quick hack to write a program like Mrs Cat uses in the show. It shows a white screen, and when you press keys, it displays coloured shapes. In my version, the colour and shape displayed is consistent for each key, so the user can learn which key to press for a given shape.

If you have Java Web Start installed, you can run it from here – press ‘Q’ to quit.

Otherwise, source code is here (SVN).

Slightly to my surprise, my daughter actually seems to enjoy playing with the end result. She’s been ‘asking’ to play it again (by miming pressing the keyboard), and when she plays it, she will press keys and point at the screen and say ‘ooh’.

testing vs. documentation

I have made some progress on my automatic ipod transfer script

The first step is to set Nautilus (that’s the file browser in the Gnome desktop) preferences, since it is the program which deals with automatically mounting media. So in Nautilus->Edit->Preferences->Media I set the ‘Media Handling’ for ‘Music Player’ to run a script of my choice when the ipod is connected.

The next step was finding a Python script in the python-gpod examples directory which just copies over some files to an ipod – so I copied and tweaked that. (I don’t write Python very much, but I can just about understand a short existing script).

Because I’m not comfortable with Python, I wrote a Bash script to be the real driver. So it is called by Nautilus when the ipod is connected, and it finds the podcasts I want to copy over, and calls the Python script just to add them.

Originally, I hardcoded the ipod mount point into the Bash script. This will be fine on my systems, but it seemed a little silly – I was convinced that Nautilus must pass the mount point somehow to the programs it starts, otherwise in general they would have trouble deciding what to do. Unfortunately I couldn’t find any documentation on how the script would be started.

The alternative to reading documentation is testing and seeing what happens. So I wrote a script which just appends it’s arguments and environment variables into a file. I set this up as the program for Nautilus to run, and connected the ipod, then looked in my log file. Sure enough, the first (and only) argument to the test program was the path of the mount point. So now I can use that in my real script, and it will be a bit more flexible.

Just a little reminder of a point I’ve mentioned before – writing a small test script and seeing what happens is often easier and quicker than reading documentation to find out what should happen.

what’s in a name

In some conversations recently, I found that some other people were interested in a little tool I have written. I started wondering about setting up a Google Code project for it, since that makes it easier to ‘expose’ in some ways.

The first hurdle is that it would need to have a unique name. I don’t think ‘My Mail Tool’ is going to cut it. Any suggestions?

The benefits of Google Code are that it gives me a standardised wiki, issue tracking and subversion without much work on my part. The trade-off is that I give up control to some extent. I could set up similar things on my own web space, but I’d have to do a bit more work.

the step beyond ‘it works for me’

I wrote a new version of my command line twitter client1. It now has coloured output, which helps me read more easily. Also it grabs direct messages and tweets referring to me, as well as the regular friends updates.

As with most of the personal software I write, it is some files with links into the right place to make it work on my system, and dependencies taken care of by virtue of my having installed them already. If someone else wanted to use it, they’d have to know what they were doing, or I’d have to provide a lot of instructions2.

So I started thinking about packaging – making the application simple for someone else to install. I think it’s pretty cool: so wouldn’t someone else?

But packaging is tricky. At a minimum I’d have to rearrange the code I have, add some supporting files and package specification. Figuring out what all the dependencies really are might take a while. Is it worth the effort?

I’d also have to decide which kind of package to use. The application is written in Ruby, so I could make it a Ruby gem. But then it would only really be installable by Ruby developers, and it’s meant to be an end-user program, not a library. Or I could package it as a DEB for my Linux distributions of choice, but it might be tricky taking into account the other rubygems it depends on – as explained here, rubygems do not sit well alongside Deb packages

In the end, I suspect I will use the program myself, and move on to the many other projects on my to-do list – I don’t get much value out of spending my time making packages.

1 It’s a complete rewrite, so I’m not sure if ‘version’ is the right word.

2 In fact, when I copied it to another of my computers, I had an unanticipated issue which I had to investigate to make it work just for myself.

how to loop by line in bash

ORIGIFS=$IFS; IFS=`echo -en "\n\b"`; for line in $(cat my_list_file); do echo $line; done; IFS=$ORIGIFS

automatic podcast transfer to ipod?

I have an iPod and a PC. When I connect the former to the latter, I would like it to automatically copy over the most recent podcast(s) from a certain directory on the PC, onto the iPod. This should not require any user interaction after plugging in the iPod.

The PC is running Ubuntu 9.10, and gtkpod works with the iPod – but I’m tired of opening a file browser and dragging files over every time.

Any suggestions?

web testing with curl

It happened again. You have an annoying bug with your Java web application, and you’re stepping through with your debugger, and… whoops! looks like you just missed an important line. You fire off the same request again, so you go back to your browser and go through the steps to that point – did I mention it was an Ajax request?

This is where I start using curl. I know that all the data my request depends on is in the combination of the URL, the POST body (maybe) and the cookies. So I can set up a single line curl command that includes all of those, and use my command line history (up arrow) to run it repeatedly, as many times as I need to fix the bug. No mousing required.

video is best enjoyed on the TV

We recently acquired an Asus O!Play HDP-R1. This is a small box which connects to the TV and the home network so it can play video shared over the network. Since our main source of entertainment is downloaded video, we’d been looking out for something like this for a while, and this one had the right combination of features and price. It’s nice to be able to watch things while slouched in a comfy chair instead of sitting at the PC.

Like quite a few small devices these days, the box runs a version of Linux, and a site has sprung up for people looking into how to modify the firm/software running on it. I haven’t done that myself (except for a firmware update), but I have been trying out ways to feed more content to the box.

First I got it playing DVDs. It doesn’t have a DVD drive, but I can put a DVD in my PC and share it. I basically followed the instructions from this other forum but shared the disk over Samba instead of NFS. It uses ‘dvdreadfs’ so that it effectively decrypts the DVD and then shares the decrypted version. On the video box we just have to navigate into the right Samba share and play the first file listed in video_ts, and it seems to deal with the DVD menu etc. properly.

Next we have it playing YouTube video. This is possible because the recent firmware updates added support for browsing UPnP media shares. The MediaTomb media server software has the capability to share YouTube videos – but you have to build from the latest svn version for it to work. It also requires transcoding software to convert the video from flv into mpeg, which means that it probably won’t work on our file server which is a low power machine. So I built and ran MediaTomb, and changed the config to enable YouTube and point it at my YouTube user account. On the video box we browse into UPnP and YouTube appears under ‘Online Services’. There is quite a delay when opening YouTube videos though.

random compiz wallpaper

Since I have a growing number of pictures of my baby daughter, I wanted to randomly select some to use as desktop wallpaper. I put a bunch of pictures in my ‘wallpaper’ directory and wrote this script to deal with them.

#!/usr/bin/env ruby
 
require 'pathname'
require 'dbus'
 
$wallpaper_dir = Pathname '/home/edward/wallpapers'
$screensize = `xrandr | grep '*' | tr -s ' ' | cut -f 2 -d' '`.chomp!
$sized_wallpaper = $wallpaper_dir.join ".resized#{$screensize}"
$sized_wallpaper.mkpath unless $sized_wallpaper.exist?
 
$wallpaper_dir.entries.select do |f|
    p = f.expand_path($wallpaper_dir)
    p.file? && !$sized_wallpaper.join(p.basename).exist?
end.each do |f|
    p = f.expand_path($wallpaper_dir)
    `convert -geometry #{$screensize} #{p} #{$sized_wallpaper.join(p.basename)}`
end
 
session_bus = DBus::SessionBus.instance
 
compiz = session_bus.service("org.freedesktop.compiz")
hsize = compiz.object('/org/freedesktop/compiz/core/screen0/hsize')
hsize.introspect
ihsize = hsize["org.freedesktop.compiz"]
 
desktops = ihsize.get.first
puts desktops
pictures = $sized_wallpaper.entries.map{|f| f.expand_path($sized_wallpaper)}.select{|p| p.file? }.shuffle.map{|p| p.to_s}
puts pictures
if pictures.size > desktops
    pictures = pictures[0, desktops]
end
 
bgimg = compiz.object('/org/freedesktop/compiz/wallpaper/screen0/bg_image')
bgimg.introspect
ibgimg = bgimg["org.freedesktop.compiz"]
ibgimg.set(pictures)

Some notes:

  • the combination of how the ruby-dbus library and the compiz dbus interfaces work is a little clunky. I’ve started making a library to help cover up some of the weirdness here.
  • I couldn’t find a good way to test the screen size from code, so ended up with the line which calls =xrandr= and parses its output. Not very maintainable.
  • I was going to set up the script to run from cron every hour or so but it causes a noticeable pause on the desktop when Compiz actually swaps the pictures so I just run it occasionally.