Converting iTunes playlists with ruby

Just posting this here in case anyone else has a similar setup.

I've got an xbox running XBMC hooked up to my home stereo system, but all my music is stored and organised in iTunes. The folder containing the music is shared so the xbox can see it, so all my music is available in XBMC with no problems. The one thing I was missing is all my iTunes playlists.

Along with virtually every other music player, XBMC uses a standard .m3u text file format to define playlists. I think the '#EXT...' stuff is specific to XBMC, but I'm not sure.

Needless to say, iTunes is not compatible with this at all. But, it is possible to export a playlist from iTunes, in its own bizarre XML format

One quick ruby script later, and I can convert the iTunes XML to M3U, including a remapping of file locations because iTunes has a different name for the root music folder (in fact, it has 2 different names for it because I moved the folder once, but the older playlists seem to still use the original location, somehow. Hence the alternatives in the ITUNES_ROOT regexp).

Finally, a noddy bash script to convert all the .xml playlist files in a directory to .m3u and transfer them to the xbox using ncftp

I still have to right-click on my playlists in iTunes and choose 'Export Song List' for each one, but that's not too arduous. I could probably write an AppleScript or something to do that for me, but in my case it's not worth the extra effort.

If you find any of this stuff useful, please drop a note in the comments.




Client collaboration via github

UPDATE: The post-receive URL on github has now been moved to a new "Services" tab on the project edit page.

It can be a hassle setting up and maintaining development environments
for clients; particularly if they're not very technical, or if they
use Windows.

I usually set up a separate VPS for each client's project as a
development/staging server, and it would be great if they could
just edit the source files on there. Then they could play around
and see the effect of their changes in realtime. The trouble is
that this requires some kind of remote editing or file-syncing setup
(e.g. SSH+vi), which can be troublesome to set up.

So, I'm trying out a combination of github's in-browser source
editing, plus a post-receive URL pointing to the client's development
VPS. Here's how it should work.

  • I set up the client's project as a github repository, and add the client as a collaborator.

  • The client makes changes to the view/css files using github's in-browser editor.

  • When they commit their changes, github posts to a listener on the client's development VPS (using a post-receive hook)

  • The listener on the VPS pulls the client's changes

  • The client views their development site to see the changes in (nearly) realtime

This is surprisingly easy to set up. I'll walk you through setting this up for a dummy "Hello, world" rails application. The ingredients we'll be using are;

  • github - a free account will do fine, for this demo

  • A development server - github will be posting to a URL on this server, so you need to be able to access it from the internet

  • A listener to pull changes from github, whenever there's a new commit. I'm going to use a very simple sinatra application, running via a command-line mongrel instance.

  • An application to act as our super-important client project

Setup a simple rails project as a github repository. You can just use a
bare "rails foobar" project - no need to set up databases.

Now, ssh to your development server (the one github will be posting to when your client makes changes). Setup a clone of the github repo.

For this demo, use the "public" clone url (the one that starts with "git://github.com").

You can use this technique for a private repo - otherwise it would be a bit pointless - but that takes a bit more SSH setup than I want to get into in this post.

I'm using "screen" so that I can start the demo application running
in a terminal and have it keep running after I log out. If you don't
know about the unix screen command, go learn about it right now.
After SSH it's one of the most useful tools to have in your toolbox.

cd dstest
[Ctrl-A D to detach from screen]

So, now the application is running, and you can open a browser window to;


and see the "Welcome to Ruby on Rails" page.

Now for the listener which will pull our client's changes.

If you haven't already got them, you will need sinatra and mongrel on your development server;

sudo gem install sinatra
sudo gem install mongrel

Now, put the following into a file called "gitmon.rb"

require 'rubygems'
require 'sinatra'
post '/update_site' do
dir = '/home/david/dstest'
system "cd #{dir}; git pull"
"Site updated\n"

You will need to change the "dir" line to
be the full path to your rails project.

Now use screen again to start a listener that will continue to run after you log out;

ruby gitmon.rb
[Ctrl-A D to detach from screen]

The listener will start up on Sinatra's
default port, 4567. You can test it by


You should see "Sinatra doesn't know this diddy."

Now we just need to tell github to post to the listener whenever it gets new commits.

Login to your github account and go to
your repository's edit page.

Setup the "Post-receive URL" as;


That should do it.

Now, edit a file (e.g. public/index.html) using the github in-browser editor (if you're not logged-in, you won't see the edit link). Commit your change.

Refresh the browser window you've got open to;


and you should see your changes (it can take a few seconds before your site updates).

This is just the tip of the iceberg, and there are a lot of ways this technique could be extended (e.g. hooks to run migrations after a "git pull" on the development server, or getting the sinatra listener to post to Campfire whenever a client commits something).

Also, there is a lot of information in the POST from github, which we're just ignoring here.

I hope you find this useful. I'll be setting it up for one of my clients very soon, so I'm keen to see how it works out.


Setting up Ubuntu 8.10 for Ruby on Rails development

Here's how I've set up my laptop, running Ubuntu 8.10 (Intrepid Ibex) for Ruby on Rails development. You'll need to run the following commands from the command-line as root. These commands worked for me, but I take no responsibility if you trash your box by doing this ;)

There is some duplication here, because I sometimes setup servers with different sub-sets of the software I use on my development laptop. Don't worry about this. It does no harm if you tell apt-get or aptitude to install the same package twice - it will just ignore you the second time.

Not all of the gems here are required for RoR development, but I use cucumber for integration testing, and it has some pre-requisites.

# General/Pre-requisite packages
aptitude install \
build-essential \
screen \
subversion \
mysql-client \
telnet \
meld \
vim \
vim-gnome \
exuberant-ctags \
tk8.5 \
apache2-prefork-dev \

# mysql server
# use apt-get to avoid installing exim4
DEBIAN_FRONTEND=noninteractive apt-get install --assume-yes \
mysql-server mysql-client \
libmysqlclient15-dev libmysql-ruby1.8

# git
mkdir gitcore
cd gitcore
wget http://kernel.org/pub/software/scm/git/git-
apt-get build-dep git-core --assume-yes
tar xzvf git-
cd git-
make install

# Ruby
aptitude --assume-yes install ruby1.8-dev ruby1.8 ri1.8 rdoc1.8 \
irb1.8 libreadline-ruby1.8 libruby1.8 libopenssl-ruby
ln -s /usr/bin/ruby1.8 /usr/local/bin/ruby;
ln -s /usr/bin/ri1.8 /usr/local/bin/ri;
ln -s /usr/bin/rdoc1.8 /usr/local/bin/rdoc;
ln -s /usr/bin/irb1.8 /usr/local/bin/irb;
ln -s /usr/local/bin/ruby /usr/bin/ruby

# Rubygems. You REALLY don't want to let aptitude install rubygems.
wget http://rubyforge.org/frs/download.php/45905/rubygems-1.3.1.tgz
tar xzf rubygems-1.3.1.tgz
cd rubygems-1.3.1
ruby setup.rb
ln -s /usr/bin/gem1.8 /usr/bin/gem
for g in rails rake capistrano capistrano-ext hpricot treetop ruby-debug term-ansicolor mongrel cheat passenger annotate-models rak; do gem install $g; done

Have fun.