Hacking on Tilt

Tilt, or 3D view as it is known in Firefox, is an awesome visual tool that really lets you see the structure of a webpage. It shows you just how deep your tag hierarchy goes which might give signs of your page being too complex or even help you spot errors in your markup that you wouldn’t otherwise notice. But what if it could do more? What if there were different ways to visualise the same page? What if even web developers could create their own visualisations?

I’ve had this idea knocking around in my head for a while now and the devtools work week was the perfect time to hack on it. Here are some results, click through for larger images:

Normal 3D view
Normal 3D view
Only give depth to links
Only give depth to links
Only give depth to links going off-site
Only give depth to links going off-site
Only give depth to elements that have a different style on hover
Only give depth to elements that have a different style on hover

This is all achieved with some changes to Firefox itself to make Tilt handle more generic visualisations along with an extension that then overrides Tilt’s default visualisation. Because the extension has access to everything Firefox knows about the webpage it can use some interested sources of data about the page, including those not found in the DOM. This one I particularly like, it makes the element’s depth proportional to the number of attached DOM event listeners:

Give depth to elements based on the number of attached event listeners
Give depth to elements based on the number of attached event listeners

Just look at that search box, and what’s up with the two buttons having different height?

The code just calls a JS function to get the height for each element displayed in 3D view. It’s really easy to use DOM functions to highlight different things about the elements and while I think some of the examples I made are interesting I think it will be more interesting to just let web-devs come up with and share their own visualisations. To that end I also demoed using scratchpad to write whatever function you like to control the visualisation. You can see a screencast of it in action.

Something that struck me towards the end of the week is that it could be awesome to pair this up with external sources of data like analytics. What about being able to view your page with links given depth proportional to how often users click them? Seems like an awesome way to really understand where your users are going and maybe why.

I’m hoping to get the changes to Firefox landed soon maybe with an additional patch to properly support extensibility of Tilt, right now the extension works by replacing a function in a JSM which is pretty hacky, but it wouldn’t be difficult to make it nicer than that. After that I’ll be interested to see what visualisation ideas others come up with.

Pop-free sound from a Raspberry Pi running XBMC

UPDATE: I’ll leave this around for posterity but a large part of this problem has now been fixed in the latest Raspberry Pi firmware. See here for instructions for raspbmc until that gets updated.

I’ve been in the process of setting up a Raspberry Pi in my office so I can play my mp3 collection through my old stereo. It’s generally gone well and I have to take my hat off to the developers of Raspbmc which makes setting up XBMC on the Pi ridiculously easy and fast. It didn’t take me long to have Airplay set up and running as well as being able to use my phone to remote control XBMC to play things direct from my music library sitting on my Synology NAS. Quite a nice setup really.

Just one problem. I play the music out through the Pi’s audio jack which doesn’t have a fantastic DAC. The big noticeable issue is audible pops every-time XBMC starts and stops playing. For Airplay this isn’t too bad, you get a pop when it first starts but only another after you stop playing. Playing direct on XBMC though you get two pops between each track as it stops playing one and starts the next. Very annoying. It’s a pretty well known problem and the best solution so far is to simply never stop playing. If you have a player that uses pulseaudio then you can configure it to keep the audio stream going even when idle. Of course it isn’t that easy, XBMC doesn’t use pulseaudio on the Pi. There is some work going on that might change that but for now it is very buggy to the point of being unusable. It seemed I was stuck … or was I?

It took some experimentation but I finally came across something of a hack that solves the problem for me. It probably works on other distributions but I did all this using Raspbmc.

First as root you want to do this:

echo "snd-bcm2835" >>/etc/modules

This makes the kernel module for the sound devices load on startup. It allows alsa and by proxy pulseaudio to talk to the audio hardware. Next edit /etc/pulse/system.pa and comment out this line:

load-module module-suspend-on-idle

This tells pulseaudio to keep the audio stream alive even when not playing anything. Now reboot your Pi. Once it is started up copy a plain wav file (nothing mp3 encoded or anything) to the Pi, log in and play it through pulseaudio:

paplay test.wav

If it doesn’t come out of the speakers then alsa might be trying to play to the HDMI port. Try running this then running the above command again:

sudo amixer cset numid=3 1

What just happened is pulseaudio played the sound file, but now should have kept the audio hardware active and will continue to do so until the Pi is next turned off. You might think that that might mean that XBMC can’t play anything now. You’d be wrong, it plays just fine and no longer suffers from the popping between tracks. Occasionally I hear a pop when I first start playing after startup, but after that I’ve not heard any issues.

There are probably easier ways to initialise pulseaudio but I don’t mind playing some sound on every startup to let me know my Pi is ready. I made it automatic by sticking this at the top of .bashrc for the pi user (which is used to run xbmc):

/usr/bin/paplay $HOME/test.wav

It means it also plays every-time I log in with ssh but I’m not expecting to do that much now it’s all working. I’m sure someone will point out the better way to do this that I’m too lazy to look for now everything is working for me.