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.

Sudoku Solver source code

I've made available the Delphi/Kylix source code, for the server part of my online Sudoku Solver.

The program can find solutions by brute force, and in many cases using logical deduction alone. The logical solver is considered adequate for its purpose, which is to give hints and validate against mistakes.

sodit.dpr
Main project file
SudokuSets.pas
Optimised library for set based operations, such as iterating permutations.
SudokuDeclarations.pas
Constants and type declarations.

The source code for "Sudoku Solver" is provided without warranty, and for non-commercial purposes only. "Sudoku solver" is copyright © 2007 - 2008 Geoffrey Swift. All rights are reserved.

Download: http://www.trollied.org/~blimey/sodit.zip (8 KB)
My name is URL

I've got through several email addresses, with all manner of quirky names, due to various reasons beyond my control. So I have finally gone ahead and acquired the geoffswift.com domain.

There's a new website on http://www.geoffswift.com/ with just a simple contact page for now. Some further content may be transferred from trollied.org in due course.

Atom to RSS 2.0 feed conversion

I am pleased to say that there is now a valid RSS 2.0 feed available for my blog. Previously there was just the Atom 1.0 feed, since this is format I am using for storage.

I couldn't find any available Atom to RSS conversion utilities, except for atom2rss.xsl from http://atom.geekhood.net/. I had tried using this a while ago, but found it would not produce valid RSS and even corrupted parts of my text through inappropriate handling of escape sequences.

Feeling a bit more confident in my XSLT, I set about addressing these issues. The feed validation service from w3.org now tells me that "this is a valid RSS feed", and so consider this to be good enough for my purposes.

It is slightly disappointing that RSS limits you to a single enclosure (podcast) for each item in a channel, whereas Atom allows for multiple enclosures. Because of this it is not recommended to use the RSS feed since you will actually lose out on some of the mp3 content.

My Atom feed has brought to light some cases that cause a problem with the XSLT code, and there are probably other valid Atom feeds that would not be translated to a valid RSS feed. Nonetheless I feel this is an improvement and am releasing this updated version into the public domain.

I've emailed my fixes over to porneL who originally wrote atom2rss.xsl, and he's kindly updated his site to include my changes.

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!

Sudoku enhancements

The Sudoku page has been improved today. When entering a number, some simple checks are made for an error. If the number entered is OK, it automatically moves to the next cell ready for another number to be typed. I updated the server application also, and the solution can be interactively solved. The server now solves easy parts of the puzzle as you key it in. This is implemented using AJAX programming techniques.

I would also like to set up a daily puzzle. The Pascal source code for the server side solution engine might get posted, if I find time to tidy it up. Please leave comments if you have any ideas!

CRUD features of blog

So far the Atom 1.0 XML feed for my blog has been written by hand using the Vim editor. Recent development on the website for the blog means that I may create, read, update and delete blog entries using a web browser. Browsing the blog through the web already possible, but this is now more or less complete CRUD.

Blog is open for comments

The latest feature of my site is one that allows anyone to post a comment against items in my blog. Just like the blog itself, the storage mechanism is an Atom xml file, so there's even a feed.

While writing a template for the comment form in XSL, I found an interesting problem with whitespace normalisation. The XHTML produced originally included a tag like this <textarea/>, rather than <textarea></textarea>. Internet Explorer doesn't recognise XHTML, and so ignores the fact the tag has been closed as per XML rules. The result is that any subsequent HTML is assumed to be the contents of the textarea, and could be clearly seen as such on screen!

I solved a similar problem with script tags, by putting the opening and closing tags on separate lines. But this technique means the form does not initially appear blank, rather the blank line appears in the textarea instead. The solution I adopted was to use the "zero width no-break space" Unicode character, resulting in an apparently blank form:

<textarea> <xsl:text>&#65279;</xsl:text> </textarea>

This all looked fine, until I tried validating the form in DHTML. Although the form appears blank to the user, and does even in "view source", it is not blank! To check for the comment being blank, I stripped out the \uFEFF character in JavaScript first. Internet Explorer's JavaScript implementation at least understands Unicode regular expressions!

The form validation is written generically also, a new script looks for any forms and adds in a new onsubmit event handler. This event handler processes any elements with the attribute class="mandatory", and notifies the user they are blank. The message displayed on screen even makes use of the text in the <label> associated with the form element.

Attempt at hAtom microformat

I have managed to incorporate the hAtom microformat into the XHTML rendering of my atom feed on my webpage, albeit with limited success. Adding the extra class attributes to the XHTML elements in the XSL template seemed simple enough, but the microformat stipulates marking up the HTML element that corresponds to an atom:entry with class="hentry". Unfortunately I'm using a <dl> tag in place of an atom:feed, and using <dt> and <dd> tags for the atom:title and atom:summary respectively. Owing to the fact that these are the only valid child entities for a <dl> tag, I have to lose half the data per post! I can't for example just put in a <div class="hentry"> around each post, as that would not be valid XHTML. The existing DHTML code is geared up to use this hierarchical structure, so fully supporting hAtom might have to go on the back burner. A permalink for individual posts works OK in htatom2atom, but that's because the post title is taken from the <head> of the XHTML document.

Internet Explorer Kludges

In a previous post, I had complained about Internet Explorer being broken. It turns out that it actually is possible to set and check the class of a DOM element, but Internet Explorer erroneously uses the moniker className rather than class. So for example, the following works fine in all modern browsers, but has no effect in Internet Explorer:

node.setAttribute('class', 'example');

The following example solves the problem for Internet Explorer:

node.setAttribute('className', 'example');
node.setAttribute('class', 'example');

I have also found that Internet Explorer evaluates String.split() differently, when given a regular expression as a parameter. Notably the array of values returned does not include any empty string values. For example "a,,c".split(/,/) will confusingly be evaluated as ["a", "c"] rather than ["a", "", "c"].

This caused a problem with highlighting search terms, when the search term was at the beginning of a string, and the unhighlighted prefix would be the empty string. I was able to work around this by using a sentinel value, to prefix the text.

Submenu items for blog categories

The existing menu had a flat structure, but now can accept hidden submenus. If present, a submenu will appear when moving the mouse over the appropriate top-level menu item.

I've populated the menu structure using AJAX techniques on my Atom feed. Menu items containing links to blog posts can now be found underneath the "blog", "updates" and "podcasts" menu items in the main menu. The posts are listed according to the category.

Highlighting of search terms from referer

Having had a look through my referer logs, it was clear people were obviously using Google to find the site. To make things easier to find, search terms used on Google are now highlighted in the page when a user finds their way here.

The work happens in the browser, rather than the web server producing a modified version specially for the user. This way caching all works as normal.

The first step is to parse the search query, into individual terms. Then my code recursively searches through the DOM and finds any text nodes which match the current search term. Any such text node is then replaced by a sequence of nodes containing either highlighted and unhighlited text.

The hard work in this is all done through regular expressions and the DOM/CSS. Try it out for yourself and use view source if you're really interested!

Yahoo! search engine integrated (and not Google)

I've used the Yahoo! search API within my personal site, and now have my own personal search engine. Having registered my "application", it was relatively straightforward to invoke the search engine using REST. The results come back in various formats including Serialized PHP and JSON - for me it made the most sense to use the default XML format. Having written a suitable template in XSL, it was a breeze to incorporate the search results into the site. There is some fiddly DHTML to put a search box in the top right corner of each page. I am pleased with the results, for my effort anyway.

Yahoo trumped Google on this occasion, as they aren't letting anyone sign up for their SOAP based search service. Both are taking data from my sitemap.xml file, but Yahoo allows you to submit an Atom feed as well. I noticed that Google Webmaster Tools reported a page not found in the "Web crawl errors" section. The URI was /~blimey/{sitemap:loc} - which GoogleBot attempted to spider, since my sitemap.xsl file contains the code <a href="{sitemap:loc}"> - d'oh! Google has mistaken my expression in XSL as a literal URL. I added noindex to the meta tag for robots in my sitemap.xsl, maybe in an equally daft way that'll help!

Code matures and delivers gzipped CSS

I've removed the big clunky "valid XHTML" and "valid CSS" icons, since the code is fairly mature and I'm confident it produces valid output. Besides which, I'm using a browser plugin to invoke the W3 validator now anyway.

I also ensured the CSS is sent gzipped where possible, with appropriate headers to allow them to be cached by browsers/proxies. The XHTML, JavaScript and RSS were already delivered in this fashion.

I made some of the code more generic, with a config file as well. This is because I'm using much of the code on another website now. As it is a commercial site, it's a good thing it seems to works OK!

Next job is probably allowing comments on blog posts, or some kind of archive / search facility for the blog.

HTTP Redirect for blog category tweak

I made the site a bit cleaner and removed some repetition in the content. The "updates" and "podcasts" categories each already had their own dedicated php page, to be directly accessed from the main menu. When the XPath query passed to the generic blog page would result in either of these categories, an HTTP redirect automagically sends you there instead. This then ties the blog filtering/navigation into the overall site navigation. Currently this is hardcoded, so I may look into a more generic mechanism to facilitate the addition of further categories into the main menu. Either way the XPath in the query string for blog.php generated by the XSL will work, as it did before.

delicious fixes / permalink titles

After an extensive break from working on the code for my website, I had a session involving PHP, XSL and C.

The egosurfing page didn't display all links, since del.icio.us limits the number of items returned in an RSS feed. It was trivial to adapt the XSL to use the XML produced by the del.icio.us API, although the HTTP-Authentication aspect was a bit trickier. Since it was necessary to hardcode my password somewhere, I wrote a setgid binary (chmod 2711) in C which is a wrapper for wget. Only my user can read the file which contains the password, but it can still be executed by the Apache process.

Individual blog posts now have a more appropriate <title>, when the permalink is used. The motivation being better exposure in the blogosphere, since the <title> tag being of importance for SEO. This wasn't so much trouble to implement, as I already had the Atom post and web page XHTML in DOM documents.

Blog attempt

Have refactored the XSL code for the podcasts/site updates pages, so that an XPath query can be passed into a generic implementation. This means I can have the blog.php page filter out individual posts for permalinks and by category currently. I'm doing this by manipulating DOM nodes in the XSL before applying it, seems to work alright anyway. This essentially paves the way for making a more fully featured search engine and navigation system. Maybe once it's working and I've run out of things to implement I might have more to say to justify its existence!

Radio Play list

While listening to internet radio stations, I found it a bit tedious to have to visit the radio station's site and find the link to tune in. This would then clear out the play list in media player.

My solution is a php page, which aggregates the play lists from various sites: http://www.trollied.org/~blimey/radio.m3u. Now I can channel-hop, just as I would when watching TV!

This wasn't so difficult to implement, the radio stations use either file format of m3u, pls or asx. The asx file format was tackled with some xsl, pls files are parsed with php's parse_ini() and m3u was absolutely effortless. I used the curl library in php to make a HTTP HEAD requests, to check each of the streams are up.

This is something I wrote for my own use, but I realised others might find it useful. I started a thread advertising this on the dogsonacid forum, so it will be interesting to see if there's any feedback.

Sanity checks for legacy browsers

I've been using a few sites which take screenshots of a website in different browsers for you. This sites are: http://browsershots.org , http://www.browsercam.com and http://www.browsrcamp.com/

This is a very useful service. It has enabled me to find and fix problems in legacy browsers. In many cases there is just a sanity check to detect whether the browser is capable of performing a required feature. Some problems I haven't yet solved because the browser simply crashed without giving me any kind of error message to go on.

XHTML document.writeln() imposter functions.

I thought it'd be a nice idea to include my del.icio.us tagrolls on my homepage. This is made possible by some JavaScript served up by their website. Unfortunately their implementation relies on document.writeln() which is not compatible with XHTML.

Undeterred, I created imposter versions of document.write and document.writeln. My implementations progressively concatenate the parameters into a buffer. When the web page loads, the buffered XHTML is positioned appropriately by using an empty placeholder tag.

I originally tried parsing the buffer as an XML document, with the intention of merging the XML nodes into the XHTML document. I tried using xmlDoc.documentElement.cloneNode(true) as a parameter for appendChild() on an XHTML node.

While this worked like a charm in both Firefox and Opera, Internet Explorer complains of "Interface not supported" and Safari has a fatal error! The failing browsers have an incompatibility of XML and XHTML DOM nodes, even though they both support a common DOM interface.

In the end I had to write my own version of cloneNode() to copy elements between the incompatible schemas and ensure valid nesting of elements. There's an exception handler that fails over to using innerHTML complete with IE kludges just in case.

If you're interested to see how this was achieved, please feel free to view the JavaScript source code.

Sudoku Solver page added

I dug out some Delphi code I wrote to solve Sudoku puzzles, and it compiled unmodified in Kylix. This and a bit of XMLHttpRequest are now the basis for the backend of the Sudoku solver. If time permits, I'll make it solve the puzzle as you key it in, something like Google suggest.

Flash MP3 player for podcast enclosures

Having seen thefixup.net, I felt the need for a flash MP3 player for my podcasts too. I'm using the same one, which is the Audio Player Wordpress plugin from 1 Pixel Out. While it's nicely packaged up, it seems the authors have perhaps missed a trick that perhaps playing MP3s might be useful for non Wordpress sites! It was fun reverse engineering it into my XSL anyway, although I wish I knew how to write Flash myself.

Updates page created

Having made my PHP and XSL more generic, there's an updates page. Much like the podcasts page, it's syndicated from the Atom XML. More blog categories may follow, as needed. Must get around to a page for displaying individual posts, for permalinks etc.

Much needed remixing and MP3 tagging
I've remixed a couple of tracks here, tweaked the graphical equalizer and added some reverb etc. I even managed to persuade XMPlay to repeat properly with a fade out too. This sounds so much better than the defaults, so I'll be sure to give similar treatment to the other XM files. I even put on ID3 tags too, but had trouble picking a genre; so Christian Gangster Rap it is!
Download: http://www.trollied.org/~blimey/amusic.mp3 (782 KB)
Download: http://www.trollied.org/~blimey/phoique2.mp3 (903 KB)
Parse Atom with XSL not PHP

I've written some XSL to process the RSS from del.icio.us, and my own Atom feed. See the results on these pages: http://www.trollied.org/~blimey/egosurfing.php and http://www.trollied.org/~blimey/podcasts.php.

Prior to using XSL, I was using the Simplepie PHP library. Google webmaster tools reported that this produced an error when the site was crawled, although it looks alright in a web browser. Also Simplepie had poor support for Atom, and as a workaround I was making use the RSS conversion of the Atom feed. The RSS conversion works using XSL anyway.

I had originally looked into using Magpie RSS, which had no support for Atom. Conclusion is both PHP libraries are redundant, in favour of XSL which obviously supports anything XML; RSS, Atom or otherwise.

Menu created, conditional HTTP GET etc

I found the time to write a DHTML menu for this site. The page gets restructured onload to put it in there.

I also ensured that the Last-Modified and ETag headers are set so pages can be cached appropriately, seems Apache2Handler takes care of the rest.

I also did a style sheet for the Atom feed, in case anyone is still using older browsers.

All the pages are now sent back compressed, for compatible clients.

The individual JavaScript files are rolled up into one big file to minimise on browser requests / round trips, and like the other pages it's all zipped and with suitable Last-Modified header based on the newest script's time stamp.

Font Resizing
I've added functionality which lets you choose the font size used for my site now. Click on the letter 'A' of the appropriate size at the bottom of the page. There's a "span" element which is a place holder, and the letters are added in using DOM.
All the code is in an external script. The intention is to ultimately add a navigation/menu part to the site using similar techniques.
Google Ranking
After a long wait the site now appears in Google search results. For the first time, I've attained the #1 spot for Geoffrey Swift. Seems a bit of extra SEO is required to achieve the same for "Geoffrey Swift", Geoff Swift and "Geoff Swift" though!
Egosurfing

I've added a page with links to external sites which pertain to me, more syndication of RSS this time powered by del.icio.us.

Podcast page
I've syndicated the atom feed back into the website itself, to provide download URLs for the DJ mix MP3z.
Website Created with feeds
My website is up and running, but could definitely use some more work! Today I've got around to adding Atom and RSS feeds. The RSS feed is generated from the Atom XML using PHP and XSLT.