Welcome to Geoffrey Swift's βlog. Please subscribe to the Atom feed.


Radio Tuner update

My Radio Tuner page lets you tune into a large number of internet radio stations, by providing playlists suitable for your favourite media player application. You can even tune in directly from my website using the Flash player.

I have been syndicating the Pirate Radio Toolbar's station list for some time, and am pleased to announce that I have implemented a similar interface for DJ Pete's Internet Radio Tuner. You no longer need to install any software to enjoy the station lists provided to users of these applications.

Unfortunately dnbstations.co.uk appears to be defunct, so I have removed the interface to it. I have however added several new stations to my own station list, diversifying the genres to include Techno and Goa Trance.

Converting XSPF to M3U and PLS with XSLT

I'm now syndicating another internet radio station playlist, the new one is from http://www.dnbstations.co.uk/. This didn't take long to implement, as I was able to reuse existing code which converts from XSPF to both M3U and PLS. I did write some new code to convert a Wimpy play list to XSPF, this was pretty easy as the formats are very similar.

The XSLT code to convert a Wimpy play list to XSPF, and from XSPF to M3U and XSPF to PLS is hereby released into the public domain.

Not only does www.dnbstations.co.uk provide the Wimpy playlist, they act as a proxy for all the streams. This seems to be wasteful of their bandwidth, when they could easily let listeners access the stream directly. I was quite surprised when I noticed this, thinking that the stream URLs were just using HTTP redirects. Maybe they'll redo this in the future, depending on how successful they are!

Streaming Radio Formats

Implementing my radio player took more experimentation and research than actual coding. As with most software, things turn out more complicated than first anticipated!

To tune in into an Internet radio station, normally you would click on a link on the station's website. From this link your browser will download a play list file, which in turn contains the URL that your favourite media player can use to access the station's live stream. My goal was to make this accessible in a more convenient manner, by allowing access to several radio stations in one place.

So I decided to create my own play list file that contained all the relevant URLs for my favourite stations. I wrote a PHP script that would generate this this play list by downloading each station's play list and extracting the relevant stream URL.

Play list file formats

There are three main formats used for these play list files, which are ASX (Windows Media Player), M3U and PLS (WinAmp).

Easiest to parse was M3U, this is just an ordinary text file that has the URL as a line of text. As PLS is an INI file, this seemed easy using PHP's built in functions to parse INI files. I quickly found that the PHP functions were unreliable so I wrote a kludge to get the URL myself, using a simple regular expression.

In a previous article I discussed problems with ASX files not being XML, so I avoided using this format unless the station did not also offer M3U or PLS. By sheer luck the few stations I am accessing via ASX are well formed XML. Unfortunately the structure of these ASX files vary, so it took a few iterations of the XSLT code to extract the stream URL realiably.

The file format I ultimately create my play list is is XSPF, as this is a well defined format based upon XML. From the master XSPF play list, I can readily generate ASX, M3U and PLS by using XSLT. Having the playlists available for means good support for tuning in with various different media players. I would personally recommend using the XSPF play list in VLC Media Player.

Streaming from a web page

I felt the stations should ideally be available directly a browser, without requiring an external application to be installed. After trying a few different options I opted to use the "XSPF Web Music Player" written in Flash. Getting Flash working is an exercise in itself made easy using the UFO JavaScript library. This setup offers good compatibility with typical browser setups.

Fixing the stream URL

The biggest problem with this was presented by a strange behaviour of Shoutcast servers. When you access the stream URL for a Shoutcast server using a web browser, you are served up a web page about the stream. This HTML content is provided instead of the MP3 stream, on the basis of the User-Agent header of the HTTP request.

Generally browser plugins have their HTTP requests made for them by the browser, so HTML content is delivered to a Flash movie or a Quicktime regardless. The exception to this is the Windows Media Player plugin, which bypasses the browser completely; disregarding proxy settings etc.

Shoutcast servers do provide a special URL that allows you to ensure the MP3 stream is returned regardless of the User-Agent. You just append ;stream.nsv for example http://example.com:1234/ becomes http://example.com:1234/;stream.nsv.

Appending this string confuses any servers that aren't using Shoutcast though. So it became necessary to probe each server, to adjust the URL where required. This works by impersonating Firefox and when HTML comes back, that's Shoutcast.

Memory usage

One significant problem appears to be that of memory consumption while listening to a stream. If you're listening for a few hours or so, expect your memory usage to be in the 100s of megabytes. This is enough to cause problems in a typical PC setup. A workaround for this is to stop and restart the stream occasionally.

The reason behind this is that the MP3 stream is treated as if a very long MP3 file is being downloaded. What you've heard so far remains in memory even though, with the exception of Real Player, you can't seek backwards. This is a well known problem that affects nearly all media players and browser/plugin combinations except VLC Media Player.

Recommended use

If you use the M3U or PLS play lists, you may well just see IP addresses and port numbers rather than meaningful station names. This is a limitation of the file formats used, and isn't fixable. Using the XSPF play list is recommended as it has the station name and website link. Also you can use the XSPF play list in VLC Media Player, without having to worry about your memory usage.

ASX and XML are incompatible

I have been working with various playlist file formats as part of my internet radio project. This has involved creating XSPF playlists from XML sources and using XSLT to convert from XSPF to the alternative PLS and M3U formats.

According to the Simple ASX article on MSDN: an ASX file is an eXtensible Markup Language (XML)-based text file which references a Uniform Resource Locator (URL) for a piece of media content. Having read this I felt that ASX files ought fit neatly into my XML and XSLT based architecture. Only when implementing this, did I discover that ASX actually has quite limited compatibility with XML.

The XML validation tool xmllint rejected a couple of ASX files, since they included the copyright symbol © encoded using ISO-8859-1. It seemed easy to solved this problem, by explicitly specifying the encoding in the XML declaration e.g. <?xml version="1.0" encoding="iso-8859-1"?>. Although the file could then be validated as XML using xmllint, Windows Media Player would simply not load this modified ASX file. It was then apparent that ASX is not compatible with XML.

Some URLs referenced in ASX files may well have query strings, which are of course delimited with ampersands. After seeing a few of these I noticed that none of the ampersand characters were escaped as they should be in XML. For a well formed XML document, a literal ampersand charater should be represented using an escape sequence, e.g. &amp;.

I edit an ASX file to make it valid XML, by ensuring the appropriate escape sequences were used. The play list came up in Windows Media Player, but it did not play as expected. When looking at the properties of the relevant track in Windows Media Player, the text &amp; could be clearly seen as part of the URL. Although I had made an ASX file into a valid XML document, once again this was futile since the ASX file was not interpreted as intended.

To summarise here are some quirks of ASX files that make it incompatible with XML:

  • The default encoding for ASX appears to be ISO-8859-1.
  • An XML declaration cannot be included in an ASX file.
  • Ampersand characters in ASX files are parsed as literal text and should not be escaped as &amp;.

To work around these problems, I wrote a PHP script that downloads an ASX file and converts it in an XML format. To achieve this it simply escapes all the ampersands, and serves this modified content with an appropriate HTTP header for ISO-8859-1 encoding: Content-Type: text/xml; charset=iso-8859-1. Aside from XML incompatibilities many ASX files are tag soup. My PHP script therefore includes kludges to address problems specific to the ASX files I'm working with.

This wasn't quite the clean solution I originally had in mind, but I am now able to import from multiple ASX files across the web. It was less trouble working around PHP's woeful ini file parsing routines to get the PLS file format supported, but that's another story!

Pirate Radio Toolbar "pirated"

Having made my own list of favourite internet radio stations available online, I was quite interested to hear about the "Pirate Radio Toolbar." I downloaded and installed the toolbar, and found it offered an impressive list of pirate radio stations. Most are pirate radio stations that also stream over the internet, a lot of the others were internet based stations that also play underground music.

The toolbar software itself is created (or rather configured) using the Conduit website. Conduit allows anyone to sign up to create similar toolbars for commercial use. These toolbars can be configured to have many different features, one of which is a radio playlist.

My sole interest was the list of stations, since I regularly enjoy listening to internet radio. The rest of the tool bar offered nothing I wanted; it merely obscured the top of my web browser. It seemed much more appropriate to listen using a more fully featured purpose built program like VLC Media Player to tune in. With music playing in another program you can obviously hide the player behind your browser!

So I mused with the idea of extracting the relevant data into an appropriate format. Using the Fiddler HTTP debugger, the URL for their play list data became apparent quite quickly.

The play list for the Pirate Radio Toolbar (and other Conduit toolbars) arrives over the web in an XML format, which is ideal for manipulation with the XSLT (the programming language used for my website). So I wrote some XSLT code to convert the playlist into an XSPF format, ideal for use in VLC Media Player.

I wrote a shell script to download the Pirate Radio Toolbar station list using wget, and convert it using xsltproc and my XSLT stylesheet code. This script runs nightly using cron, so my copy of the station list should keep up to date with any new stations they add.

I even wrote a couple of extra XSLT stylesheets to convert XSPF to the PLS and extended M3u file formats. I make use of these stylesheets to generate my own dynamic radio playlist now. I might post this XSLT code up for download in case anyone else wants to do similar conversions.

Please visit my radio page for more details. I host my own radio station play list, which exclusively comprises high bitrate drum and bass, jungle and dubstep.

Download: http://www.trollied.org/~blimey/pirateradio.xspf
Web based Radio Tuner

I'm pleased to announce a brand new version of my radio tuner. This is now embedded into my website using a the XSPF Web Music Player, which is written in Flash. I hope other people will enjoy using it as much as I am, any feedback is welcome.

Radio Tuner in IE7 - XSLT meets conditional comments

Getting Internet Explorer 7 to work with the HTML version of my internet radio tuner was no walk in the park. Read further to learn how to avoid the same pitfalls.

The first problem was that using <object type="application/x-mplayer2" data= … > yields the error "Internet Explorer has blocked this site from using an ActiveX control in an unsafe manner. As a result, this page may not display correctly." Puzzlingly I found that there is no such warning when using <embed type="application/x-mplayer2" src= … > instead.

Using <embed> rather than <object> just for the sake of Internet Explorer didn't make me feel entirely happy, as this proprietary tag is not valid HTML. To solve this problem and retain the validity of my HTML, I chose to use the even more proprietary trick specific to Internet Explorer - conditional comments. This means that the IE specific <embed> is effectively commented out, and the <object> tag is ignored by IE. See some example HTML below:

<!--[if IE]> <embed type="application/x-mplayer2" src="" width="290" height="64"></embed> <![endif]--> <!--[if !IE]><!--> <object type="application/x-mplayer2" data="" width="290" height="64"></object> <!--<![endif]-->

This was slightly tricky to get right in the XSLT. I could have tried using xsl:comment and CDATA sections, but xsl:text and disable-output-escaping seemed like less trouble:

<xsl:text disable-output-escaping="yes">&lt;!--[if IE]&gt;</xsl:text> <embed type="application/x-mplayer2" src="{@href}" width="290" height="64"/> <xsl:text disable-output-escaping="yes">&lt;![endif]--&gt;</xsl:text> <xsl:text disable-output-escaping="yes">&lt;!--[if !IE]&gt;&lt;!--&gt;</xsl:text> <object type="application/x-mplayer2" data="{@href}" width="290" height="64"/> <xsl:text disable-output-escaping="yes">&lt;!--&lt;![endif]--&gt;</xsl:text>

Problem number two relates to the "fix" Microsoft have made to avoid infringement of Eolas Technologies' patent "distributed hypermedia method for automatically invoking external application providing interaction and display of embedded objects within a hypermedia document." This means that Internet Explorer displays a message saying "Click to activate and use the control". Surprisingly the music starts playing automatically anyway, but this is still a minor annoyance. The problem was solved by calling this JavaScript function via document.onload():

function eolasWorkaround() { var i; if ('Microsoft Internet Explorer' != navigator.appName) { return; } if (typeof document.getElementsByTagName == 'undefined') { return; } var embeds = document.getElementsByTagName("embed"); for (i = 0; i < embeds.length; i++) { embeds[i].outerHTML = embeds[i].outerHTML; } }

This complete solution seems to work quite well on all the Windows based browsers I have available now, even Internet Explorer! I have no facility to develop and test this on other platforms, which may not know which plugin to use for the MIME type "application/x-mplayer2". I intend to address this in due course.

In any case the MIME type should strictly speaking be "audio/mpegurl", but this is not supported by Windows. But in case of any difficulty, you can always just click the hypertext link to download the radio.m3u playlist and play it in an external application.

Eolas is a registered trademark of Eolas Technologies Inc. Microsoft, Windows, ActiveX and Internet Explorer are registered trademarks of Microsoft Corporation in the United States and other countries.

Radio tuner revamp

My homepage has a link to tune into my internet radio presets. This play list file is generated automatically by the web server, which checks whether each of my favourite stations is currently available.

I've updated some of the dead links for some Drum & Bass stations that have moved, and included some new Dubstep stations also. There's now also only one entry in the play list per station, to make channel hopping easier. This also makes the list load up quicker as it does fewer checks.

Give it a try, just click on the link to the file radio.m3u, it should open up in Media Player or iTunes etc. let me know what you think!