Radio 2 recording scripts updated

The most recent update to iTunes broke some of my BBC Radio 2 scripts, the AppleScript and Python scripts I use with AudioHijack Pro to automate the recording and iTunesifying of shows I like. The failures occurred in the parts of the scripts that add artwork to the saved shows. I could have just deleted those parts—the artwork certainly isn’t a critical feature of the shows—but I like seeing Brian Matthew’s crinkly face smiling out at me from my iPod, so I decided to fix things.

Sounds of the 60s artwork

The problem was that I was using PICT files, saved in my ~/Pictures/bbc/ folder, as the album artwork. When I first wrote these scripts, I wanted to use PNG files as the artwork, but I couldn’t get them to work, so I was forced into using PICTs. Now that PICTs don’t work anymore, guess what does? This is why my molars are ground down to little stubs.

So, back to PNGs. And while I was at it, I decided to clean up the bit of code that sets the path to the artwork file. It used to be a nasty kluge of do shell script and POSIX file; now it’s much cleaner. These lines,

set artPath to ((path to pictures folder) as string) & "bbc:60s.png"
set theArt to read (file artPath) as picture

get the image from the PNG file, and this one

set data of artwork 1 of theTrack to theArt

saves it as the artwork for the track in iTunes.

And since I was updating the AppleScripts, I figured it was worthwhile to update my Radio 2 Python library, too. The library was written to grab the stream URLs and the show tracklists from the Radio 2 website, and was specialized to the shows I was listening to back when I wrote it. Since then, I’ve stopped listening to Trevor Nelson, and Mark Lamarr pulled the plug on his great God’s Jukebox show. I’ve decided to give Bob Harris’s Saturday and Sunday shows a try, so the library has been expanded. Here’s the current version:

 1:  import datetime
 2:  import urllib
 3:  import BeautifulSoup
 4:  import re
 6:  # The particulars for the shows we're interested in.
 7:  showinfo = {'jukebox': (5, 'Mark Lamarr'),
 8:              '70s': (6, re.compile(r'Sounds of the 70s')),
 9:              '60s': (5, re.compile(r'Sounds of the 60s')),
10:              'soul': (2, 'Trevor Nelson'),
11:              'saturday': (5, re.compile(r'Bob Harris Saturday')),
12:              'sunday': (6, re.compile(r'Bob Harris Sunday'))}
15:  def recentScheduleURL(showday,
16:    'Return the schedule URL for the most recent showday (0=Mon, 6=Sun) on or before day.'
18:    if isinstance(showday, tuple):
19:      backups = [ (day.weekday() - d) % 7 for d in showday ]
20:      backup = datetime.timedelta(min(backups))
21:    else:
22:      backup = datetime.timedelta((day.weekday() - showday) % 7)
23:    programDay = day - backup
24:    return '' % (programDay.year, programDay.month,
27:  def programCode(show):
28:    'Return the code of the program page for showname on the most recent showday.'
29:    try:
30:      schedHTML = urllib.urlopen(recentScheduleURL(showinfo[show][0])).read()
31:      schedSoup = BeautifulSoup.BeautifulSoup(schedHTML)
32:      return schedSoup.find(name='span', text=showinfo[show][1]).parent.parent['href'].split('/')[-1]
33:    except KeyError:
34:      return None
36:  def trackList(code):
37:    'Return text with the track and artist names for each song played.'
39:    # Get all the track info
40:    progURL = '' + code
41:    progHTML = urllib.urlopen(progURL).read()
42:    progSoup = BeautifulSoup.BeautifulSoup(progHTML)
43:    tracklist = progSoup.findAll('div', 'segment music-segment')
45:    # Create a list of songs with title and artist.
46:    songinfo = []
47:    for t in tracklist:
48:        try:
49:          track  = t.find('span', 'track').string
50:          artist = t.find('span', 'artist').string
51:          songinfo.append('%s\nby %s' % (track, artist))
52:        except AttributeError:
53:          continue
55:    # Generate a plain text list of the song information.
56:    songs = '\n\n'.join(songinfo)
57:    songs = BeautifulSoup.BeautifulStoneSoup(songs, convertEntities=BeautifulSoup.BeautifulStoneSoup.HTML_ENTITIES)
59:    # Get the date of the show.
60:    bdate = progSoup.find('div', 'date').span.string
62:    return '%s\n\n%s' % (bdate, songs)

You’ll note I haven’t deleted the Lamarr or Nelson entries. It costs nothing to keep them in, and the entries may come in handy someday.

The showinfo dictionary is the means by which the Radio 2 schedule is searched for show codes. For example, Sounds of the 60s appears on the Saturday (weekday number 5) schedule.

The recentScheduleURL function returns the URL of the Radio 2 schedule page of the most recent day with a weekday number of the argument showday. The weekday numbers run from 0 for Monday to 6 for Sunday.

The programCode function returns the eight-character string that uniquely identifies the show given as the argument. For example, calling


today will return b00zh2mq, which is the code for last Saturday’s episode of Sounds of the 60s. This code is the key to getting all the information about the episode. The episode page, which includes all the songs played on the show is at  

and the show is streamed at

Finally, the trackList function takes the program code and returns a nice plain text version of the track listing for the episode. This is what I save as the “lyrics” of the show in iTunes so I can easily get the name and artist of tracks I find interesting.

The radio2-stream and radio2-tracklist scripts, which are also in the GitHub repository use the library in what I think are obvious ways to return exactly what you’d expect. Running radio2-stream 60s in Terminal today yields

and running radio2-tracklist 60s yields something thats too long to bother posting here, but it starts with

Sat 19 Mar 2011

Shakin All Over
by Johnny Kidd & The Pirates

Midnight Confessions
by The Grass Roots

and ends, as all the Sounds of the 60s shows do, with

Foot Tapper
by The Shadows

A couple of notes:

First, I know there are ways to download BBC shows directly, rather than recording them from streams, but I’ve never gotten them to work reliably. This may be due to limitations the BBC puts on downloads from outside the UK, or it may be due to my own mistakes. Either way, I’ve stuck with AudioHijack Pro because it works for me.

Second, it’s very easy to adapt these scripts to other shows on Radio 2 and almost as easy to adapt them to shows on other stations. I talked about that in this post from a couple of years ago.