Friday, 18 January 2013

Raspberry Pi A2DP Bluetooth Audio Receiver

I wanted to use a Raspberry Pi to act as a Bluetooth audio receiver or my Hi-Fi so that I could connect a phone/tablet easily to some proper speakers wirelessly. Rather than reinventing the wheel 'kmonkey' has already achieved most of what I set out to do over here; check this out first.

The only issue now is the manual intervention needed to connect up a new Bluetooth source to the output sink. I initially created a simple bash script to poll pulseaudio (every 5 seconds) and run the necessary commands as and when a new device is connected. You can see the script here and all the pertinent commands are explained over in kmonkey's blog. This is all good, but will need to be run manually using something like,

# nohup ./bt_audio_attach &

This is a bit rubbish and you'll be pleased to know there is a better way to get this done, UDEV!

Over at the Raspbery Pi forums  there's some discussion on using UDEV scripts to automate this process entirely. Initially I had had some issues with their scripts and was experiencing source disconnects after ~20 seconds of playback. Another problem was that a new incoming Bluetooth connection would scupper the currently connected device which may be quite undesirable (e.g. if anyone else in the house uses another device with your setup as my wife does).

I've re-factored my original methodology into the following UDEV script at the bottom of this post. The major improvement here is that we no longer interfere with any currently running Bluetooth playback and we also add the ability to easily specify a user to run our commands as. You could always use the 'Pi' user (or your own user account), but I don't like giving random background processes my full privileges. You can create such an unprivileged user like so,

# useradd -rMN -g nogroup -G lp,audio btaudio

To trigger the udev script when a new device connects create (or modify) an even handler in /etc/udev/rules.d/99-input.rules adding the following content rules,

We're now almost running a fully headless A2DP receiver, except one problem, the 20 second cut outs. It turns out this happens because pulseaudio times out playback for users if they are not active, like our 'btaudio' user. Back at the forums some suggest running pulse as a system process, but before heading down that route you really should read this information. Instead we just need to disable timeouts by adding a line in '/etc/pulse/client.conf' to read,

extra-arguments = --exit-idle-time=-1 --log-target=syslog

Enjoy!

OK, not quite. For reasons not yet understood this is still not working from a cold start as I would like it to. Instead it begins working only after a user has logged in, even if that user immediately logs out again. I run my setup headless and have to login once via SSH to kick things off. Once I've done that it runs seamlessly for weeks at a time. Suggestions welcome.

Tuesday, 1 January 2013

Blocking Adverts from the Roku Menu

UPDATE: 18 May 2013 - A new firmware (v5) has changed the way ads are handled on the Roku so that this guide is no longer relevant. Rest assured I am looking into this. 

Roku are are a pretty neat little media streaming box but one thing that I think lets them down are the trashy and mostly irrelevant adverts on the home page. Wouldn't it be great if you could get rid of these?

The ads are served by the third party ad platform, ZEDO. You can block the ads from displaying by simply blocking this domain entirely or by being more targeted and blocking the specific sub-domain serving the Roku ads. A TCPDUMP of my Roku shows that the ad images currently come from 'd7.zedo.com' (although this may change).

I block them by adding a custom DNS record for this sub-domain to my home router pointing to the loopback address (127.0.0.1). There are or course many other ways you could do this, but the best way will largely depend on your own set-up and resources.

Wednesday, 8 December 2010

An Exercise in Form Validation using JavaScript Prototyping

Form validation is an important part of most websites and more specifically client side validation is an important contribution to the the user experience.

In the brave new world of "Web 2.0" we have access to tools like JQuery to help developers to do this sort of jazz with AJAX and the like. This however (regardless of how straight forward it actually is) is still scary and complicated for anyone not already familiar with JavaScript.

The code I want to talk about here is of my own creation. I'll be the first to admit that "I am not a developer", and so the code itself may not be technically perfect, for this I make little apologies.

What I set out to do is create a reusable code class; a class which can be reused to validate any form without modification or an excess of additional javascript. I also took the opportunity to tinker with 'prototyping' to take a true object orientated approach to the code; this makes it fast and hopefully easy to follow.

In reality the minimum code requirements for any page containing a form would look a little bit like this:
<script type="text/javascript">

var myValidator = new ValidatorClass();

function submitForm() {
 myValidator.checkForm();
}
</script>

Take notice of the lack of any reference to HTML object names or ids, the code is entirely generic, all we are doing is instantiating the class.

The types of validation for form elements themselves are set within the form elements tag with the simple addition of some attributes such as
validate, valmand, valmin, valmax etc.

Any number of compatible commands can be used in combination, e.g. a text field which is mandatory and has a minimum and maximum character length could be defined as such:
<input type=text validate valmin=5 valmax=15>

The consequence of this should be obvious but do note the lack of any scripting or complex syntax.

I've prepared a demonstration form displaying some of the key features. The javascript itself is also available for download, and contains more extensive details on the classes use.

Feel free to play.

Tuesday, 20 July 2010

If you were an animal what would you be and why?

Recently I was asked to be involved in the recruitment process at my place of work and had to, with the help of two of my team members, spend half an hour interviewing prospective job candidates. Now I've had a few interviews in my time and seem mostly to do quite well in that kind of situation, but this would be my first experience on the other side of the table.

I remember having read interview guides before now that had warned me to be prepared for silly questions like 'If you were an animal what would you be and why?'. So with the simple intention of using this very question as an icebreaker (and partly becaused I'd enjoy using such a cliché) we decided I could kick off with it.

We weren't hoping to get anything useful out of it at all, but in hindsight the animal question proved way more valuable than I could have ever expected, not because of any in depth analysis into the answers, such as lions as leaders or any crap like that, but purely on how the interviews handled such a ridiculous question (something the candidates would come across regularly in the role)!

Now some gave boring answers like cat or dog for various reasons. Now I wasn't judging them on imagination here so credit to them for playing along. What it did do though was trigger a stock response of 'oh, I'm a [if cat then dog and vice-versa] person', which generally got a chuckle which was kind of the point. Ice broken, lets move on.

In the worst case a candidate snapped back with 'What are asking me that for!'. Instantly showing just how intolerant they were to BS questions and showing a confrontational side which is never a good idea in an interview. Who cares about the animal, we've got a major attitude problem here!

Finally the best responses showed comedy, personality, or at least a little imagination. I didn't care which animal, or indeed why, but was just happy in the knowledge that the interviewee is a relaxed fast thinker with good people skills to boot, especially if they made us laugh.

So in short, don't dismiss silly interview questions, they can be more valuable than you think.

Thursday, 17 June 2010

Spawning many VirtualBox machines from a single VDI

What I'm taking about here is a way to have many VirtualBox machines based upon a single hard drive image. There are many reasons why you might like to do this, but the most compelling is probably saving time by not having to install an OS over and over again, especially useful if you do anything like software testing.

Our goal is a single vdi (virtual disk) file which contains a vanilla installation of our favourite OS which we can then use to conjure up a fresh new machine in a jiffy.

Assuming you already have VirtualBox installed our first step is (maybe for the last time ever!) to install our OS into a new virtual machine. Now I shan't go through this as it's pretty straight forward and if you're reading this it's the sort of thing you have probably done a hundred times before.

One thing of note during the initial setup is the 'Virtual Hard Disk' configuration. Be sure to allocate enough space to allow for all potential applications of the image. It would be wise to select 'Dynamically expanding storage' so that your vdi will only be as big as it needs to be.

Once you have your new machine in a state suitable to spawn other machine from (patched, base software installed etc) shut it down and we can move on.

Now unregister the vdi from the virtual machine used to constuct it, you can do this on the command line using VBoxManage, or a number of ways through the gui. I use the gui 'Virtual Media Manager' (found under the 'file' menu in your VirtualBox interface).

Now this is where we run out of functionality in the VirtualBox gui and we'll have to resort to the command line. We need to change the type of our vdi from 'normal' to 'immutable' by running:
VBoxManage modifyhd /full/path/to/my/vdi --type immutable

Back in the gui interface, in the machine storage configuration, reallocate the now immutable vdi file to the original build machine. You should now be able to boot this again just as before. Excellent!

Now create a new machine, but this time when selecting a hard disk choose to use an existing disk and select our immutable vdi. Awesome it works! (hopefully)

That is almost it! Just one more thing to be very aware of. Going back into the Virtual Media Manager your'll notice you can now expand a list against the immutable vdi. Inspecting these will show you that they are 'differencing' disks, associated to our machines using the immutable vdi above. These differencing disks allow our machine to diverge in state.

HOWEVER the default configuration of these differencing disks is to RESET each time the machine is powered on. This may be just what you want, to be able to boot a clean state each time, perfect for testing software. However if you want your new machines to preserve their states there is one more command to run.

From the media manager note the id of the differencing disk you want to preserve state, it's contained in the Location path at the bottom of the window and is enclosed in {}. It'll look a bit like this,
3f80ade2-0380-4087-88e8-21edc3a8d85

Now run,
VBoxManage modifyhd Your-Disk-Id-In_Here --autoreset off

This will be remember from here on in for this machine and all snapshots taken from it in the future.

Monday, 22 March 2010

Cloning VMs with Multiple Snapshots in VirtualBox

I'll keep this short and sweet. I needed a way to backup a VirtualBox machine with multiple snapshots to a single detached VDI.

'VBoxManage' is the command line tool with all the useful VirtualBox tools, and I had used its 'clonehd' to good effect before now to clone existing VDI files. However as you may already know, when you snapshot a VirtualBox you end up with multiple VDI files; so how can we consolidate these into one VDI without having to mess around merging existing snapshots on a live service?

Quite simply use the UUID of the state you wish to clone, this will create a new VDI of the associated snapshot, merged with ALL previous states... cool huh? You can get this out of the virtual disk management tool in the gui, or from the XML definition file for the machine, it'll look a bit like:
c6804c54-a8ca-4829-9eaf-132f8b1dd38a

So to make a spanking new single VDI for this saved state, run:
$ VBoxManage clonehd c6804c54-a8ca-4829-9eaf-132f8b1dd38a MyNew.vdi

Simples!

Tuesday, 19 January 2010

Banana Bread!

Just for a delicious change from geek speak, here is my recipe for Banana Bread (more of a cake really).

225g self raising flour (I like wholemeal)
½ teaspoon salt
100g butter or margarine (unsalted)
170g soft dark brown sugar
75g raisins (or sultanas)
2 ripe bananas
½ teaspoon vanilla essence
1 egg, beaten
3 tablespoons milk (or dark rum!)

Oven: 160 oC, 325 oF, Gas Mark 3

If you have time, or are prepared far enough in advance, it's extra tasty if you can soak the raisins overnight in dark rum, any rum that doesn't get adsorbed can substitute the milk in the recipe.

1)Line the bottom of a loaf tin with greaseproof paper and grease it up.

2)Put the flour and salt into a bowl, cut the butter up and add. Rub in until it resembles fine bread crumbs.

3) Stir in sugar and raisins. Mash in banana with fork (Well duh) and add to the mixture with the vanilla essence, egg and milk. Beat.

4) Put in tin.

5) Sift or sprinkle some of the dark sugar over the top of the mixture to give it a delicious sweet crispy top.

6) Cook (on a baking sheet in a pre-heated oven) for an hour and a half until… done.

7) Eat!… Or, if you have the patience, leave it to cool in the tin for ten minutes and then on a rack for some more time.