Jeb Wilkins

Coding and climbing in Cumbria.

FTP Bundle for Textmate

I’ve just added a very simplistic Bundle for Textmate which will upload files when you save them. Its got two commands, one to set the FTP settings, which are just held in a YAML file in the TM Project root (Bundles -> FTP -> Edit FTP Settings). The second command is bound to Command-S so will upload the files when they are saved, if an ftp settings file is present. For those of you used to Dreamweaver and its ilk then the behavior is pretty similar to that.

It doesn’t handle the initial pulling down of the folders of files, there are plenty of good FTP clients out there that will do that for you.

To get the bundle go to

From there you can either download a zip/tarball (click the Download source button) or just do a git clone into your ~/Library/Application Support/TextMate/Bundles folder.

A2DP on the Cheap

Wow, its been a while since I last blogged - oh well first new years resolution, start blogging again.

I’ve been wanting a way to broadcast music/film audio from my laptop to my stereo in the living room. I could’ve got an iTrip or similar but having a dongle out the side of the laptop seems kinda clunky, besides the laptop has bluetooth built in. A quick hunt found that most A2DP receivers are pretty expensive, but I could get Belkins first generation TuneStage for IPod pretty cheap (ie 15 - 20 quid) off eBay. A bit more hunting shows why - the transmitter only works with old 3g and 4g ipods, but the receiver part is standard A2DP so works just fine with a computer (and presumably iPhones, Android phones, etc).

To get it going with my Macbook, I needed to pair with the TuneStage RX device (its in discovery mode when the blue light flashes), this failed at first but theres an options button on the failure screen, the magic option was setting it to pair without a passcode. I could then choose the TuneStage from the Bluetooth icon in the menu bar, and use that for audio - at this point the device wanted a second pairing step - requesting a passcode from the laptop, enter 1111 and suddenly the sound is coming out the TuneStage.

So far its working well, sound quality seems fine but its only hooked up to a pair of computer speakers at the moment.


I’m busy writing a Rails plugin, following good Test Driven Development practices, ie Writing tests, checking they fail, then writing code to make them pass. This time though the tests passed straight off, without me writing the functionality - hmm, v. weird!

Hacking in Lua

I use an alternative window manager called Awesome - it works a bit differently to a normal Gnome desktop. One feature I miss is the run command in Gnome which takes whatever you throw at it and tries to act accordingly - give it a url and it opens a web browser, give it a path and it opens the file manager, give it a program and in runs the program.

Awesome has a simple run command but it only launches programs. It turns out Awesome is really really configurable with all behavior coded in Lua. A quick hunt through the config file (which is just lua code) revealed

key({ modkey }, "F1",
        function ()
  { prompt = "Run: " },
            awful.util.spawn, awful.completion.bash,
            awful.util.getdir("cache") .. "/history")

awful.util.spawn is the importent part, its used to spawn the chosen program, so I just needed to supply my own spawning program. A half hour of learning at Lua later and I’d got the following function, which i now use instead of awful.util.spawn

function gnomeopen(cmd, sn, screen)
  if os.execute("which " .. cmd) == 0 then
    return awful.util.spawn(cmd, sn, screen)
    return awful.util.spawn("gnome-open " .. cmd, sn, screen)

This uses unixes which to check for whether theres a matching program, then either runs it as before, or passes it through the gnome-open program.

I’m Back

Well, I’m finally back in Kendal enjoying the rain :)

The winter went well, though not quite as planned. I got lots of climbing done and seemed to improve whilst out in spain. Since getting back I’ve been bouncing around between my parents and various friends whilst waiting for some freelance work to get going.

Now I’m more settled in Kendal I need to start looking to the future and find some additional work!

Offline Web Browser

Whilst on my travels I’ve moved from using to liferea, and to using evolution, acccessing my gmail account via imap. This works great until I click on a webpage link - if I’m still in the internet cafe, no problem, otherwise I end up cutting and pasting the links into a text file to be read later.

This seemed something well suited to automation, in the end this turned out to be surprisingly easy - the dbus part took all of 5 minutes following the excellent tutorial at

The first script is set as my default browser in gnome. It queries NetworkManager over dbus to check whether I’m online and either opens the link to cats it onto a text file, and sends a desktop notification to say its saved the link.


!/usr/bin/env ruby

require ‘dbus’

def online? bus = DBus::SystemBus.instance nm_service = bus.service(“org.freedesktop.NetworkManager”) nm = nm_service.object(‘/org/freedesktop/NetworkManager’) nm.introspect nm.default_iface = “org.freedesktop.NetworkManager” nm.state.first == 3 end

if /https?:\/\/localhost/ =~ ARGV[0] or online? system “/usr/bin/firefox ‘#{ARGV[0]}’ &” else“#{ENV[‘HOME’]}/.offline_links”, “a”) do |f| f.write “#{ARGV[0]}\n” end notify-send -t 3000 -i info 'Added Offline Link' '#{ARGV[0]}' end


The second script is hooked up to a button in my gnome-panel - this opens all the links in their own tabs in firefox, then removes the file of links.


!/usr/bin/env ruby

require ‘fileutils’

f = “#{ENV[‘HOME’]}/.offline_links” links = { |link| link.strip } system “/usr/bin/firefox #{links.join(‘ ’)} &” FileUtils.rm “#{ENV[‘HOME’]}/.offline_links” `

Lost in Spain

Well the Ski season didn’t last quite as long as planned, the credit crunch hit and the job vanished after the new year rush. Initially I was pretty gutted but as with anything, change brings opportunity.

Rather than race back to England, me and Ellie decided to take an extended climbing trip instead. We’d moved out of our house, quit our jobs and had no fixed costs in England - a rare luxury. So I’m now in Southern Spain, in the Costa Blanca going sport climbing every day. We drove down through France, spending a couple of weeks relaxing near Carcassone before going to Costa Daurada. Unfortunately whilst it was very sunny it was also very windy and bitterly cold so we moved onto to here. Next on the list is El Chorro, beyond that some more travelling I guess.

I’ve rather lucked out and have some freelance work arranged for when I return to England at the end of March but would be keen to hear of any other freelance Rails, PHP or Python work going in northern England.

Sony Walkman and Libmtp

A bit more research and the current solution seems to be to talk to the Walkman (NWZ-S638F) via MTP rather than USB Mass Storage. To make this happen you need an updated libmtp for it to recognise the Walkman. Since Jaunty is still at 0.30 version of libmtp I’ve backported the debian experimental version which is the latest v0.34.

This means the Walkman now is recognised and works fine in Rhythmbox - Banshee seems to crash a lot but I’m not sure if this is because of my backported libmtp or because of other mtp bugs in Banshee.

So if you want to use a recent Walkman with Interpid Ibex install the libmtp files linked below.

libmtp8_0.3.4-1_i386.deb libmtp-doc_0.3.4-1_all.deb mtp-tools_0.3.4-1_i386.deb and optionally libmtp-dev_0.3.4-1_i386.deb

Sony Walkman and Id3 Madness

My girlfriend wanted an MP3 player for her birthday - this seemed simple enough, figured I’d just get her an iPod. A bit of research later and it seems like Ubuntu doesn’t support current Nano’s. A trip to a local electronics store and I find theres now some nice looking Sony Walkmans, similar size, capacity, etc with good battery life so I get one of those. And so the journey begins.

Initially I assumes it would be an MTP device - Walkmans certainly used to be. Turns out its actually a USB Mass Storage device instead, which should be even simpler - just copy the files onto the drive, hell I can even use Rsync for syncing, thats cool.

Now I enter the world of id3 stupidity - id3v1 doesn’t handle wierd characters in song names very well, and id3v2 has a couple of common varients v2.3 which most media players seem to support, and v2.4 which all the gstreamer software supports - and the two aren’t compatible so sound-juicer/rhythmbox/banshee all generate mp3’s with tags that don’t show up on the Walkman (or many other dap’s by the sound of it) - not much use.

The second problem is that the Walkman relies on the album art being included in the id3 tag - which neither banshee or rhythmbox put there (or sound juicer for that matter). The current solution seems to be to force the Walkman back to MTP mode, where banshee can hand the player the mp3 file and metadata separately and the device will maintain is database without reading from the id3 data. This which means an updated libmtp and hal-info file so next on the list is to rebuild the latest copies of these from debian experimental and see if that solves any of my problems.

Failing that I think the new version of banshee that came out last week may support the Nanos - so I may be back to using an iPod - the best supported media player on linux is the most proprietary, how ridiculous.

As an aside there is and id3 muxer in development for gstreamer which will generate the v2.3 tags most DAPs seem to need - unfortunately there seems to be no momentum from the gstreamer boys to get this included in the distribution, the patches have sat dormant in gnomes bugzilla for a year. Next obvious item on the list would be to add album art support to sound-juicer, would be an interesting GSoC project.

Time for a Change

Since last summer I’ve been working on a fairly major Ruby on Rails application for a client of ours, and with that finally having gone live and been running well for a few months it seemed a good time to follow an ambition I’ve had since my days at uni - to do a Ski Season.

So after 3 good years I’ve left Ibex Internet, my former employer and I’m off to work in Courchevel in France with Ellie, my girlfriend, where we’ll be running a Ski Chalet together, following a rather stereotypical pattern of me taking our clients out Skiing during the day and her providing the culinary delights during the evening.

I’m now starting to look to the future and beyond the ski season I’ve got no formal plans, though I’m currently thinking of ‘going solo’ and starting my own business providing programming skills to the various Web Design agencies in the area, and providing RubyOnRails skills to companies from further a field who need them. So if anyone needs a good Rails or PHP programmer next summer I may be your man.