Code, Compose, Bike, Brew

…though not necessarily in that order

Conditionally Collecting Objects in Groovy

| Comments

Groovy’s Collections collect() method is great for iterating a collection and generating a new collection containing transformed results. For example:

import groovy.transform.Immutable

// Define a 'User' class
class User {
  String firstName
  String lastName
  boolean administrator

// Create a couple of users
def users = [new User("Edd", "Grant", true), new User("Jon", "Doe", false)]

// Use collect() to generate a list of their full names
def fullNames = users.collect() { user ->
  "${user.firstName} ${user.lastName}"

assert ["Edd Grant", "Jon Doe"] == fullNames

Sometimes, however, what we really want is something more akin to ‘collect where some criteria is met’ and collect() doesn’t provide a mechanism for doing this. This is because this functionality is provided by a different method, Groovy implements the findResults method which collects only non-null results. This allows us to filter the source collection really easily. For example:

import groovy.transform.Immutable

// Define a 'User' class
class User {
  String firstName
  String lastName
  boolean administrator

// Create a couple of users
def edd = new User("Edd", "Grant", true)
def users = [edd, new User("Jon", "Doe", false)]

// Use collect() to generate a list of administrators
def administrators = users.findResults() { user ->
  user.administrator ? user : null

assert [edd] == administrators

collect() has been around since v1.8.5 whereas findResults() is a more recent addition, being introduced in v2.2.0.

Running Logitech Media Server in Docker

| Comments

I recently signed up for Spotify’s 30 day free trial, having such convenient access to so much music was great, but when it came to an end and I was faced with the prospect of paying for my first month I was reminded just how little Spotify actually pays musicians per play. Despite being a software engineer in a very digital age I have always preferred to buy music on a physical artefact on Vinyl or CD. I prefer to have the artefact itself as I find it gives me a different listening experience when compared to digital media, I tend to give the music more time and attention if I sit down and listen to the CD or record vs just bunging some ear phones in and playing some tunes on my phone. Where possible I also prefer to buy from the artist or their label direct to make sure that they are adequately compensated for their work so that they can earn a living and can carry on making the music that I love. Finally having the physical CD also gives me the ability to control how I store the music in my digital library e.g. what software and format I use to rip the physical media.

So having said no to Spotify I found myself missing the ability to choose from a wide range of Music when on the go, so I thought I’d set up Logitech Media Server (LMS) (formally known as ‘Squeezeserver’ or ‘Slimserver’) on my Fitlet-h. I’m sharing my notes on how I went about this in case it’s useful to anyone.


I wanted to try running the Squeezeserver in Docker, a quick search on the Docker Hub showed that there is already a Docker image which does just that. So let’s see if we can run it locally first of all:

mkdir -p /tmp/squeezebox # This is just a temporary directory in which the Squeezeserver will store its state
export MY_MUSIC_DIRECTORY=/Data/Music # This is the path to my music directory on my local machine
docker run -d \
           -p 9000:9000 \
           -p 9090:9090 \
           -p 3483:3483 \
           -p 3483:3483/udp \
           -v /tmp/squeesezerver/state:/srv/squeezebox \
           -v ${MY_MUSIC_DIRECTORY}:/srv/music \

Note: the docker image name is specified incorrectly on the Docker Hub page as larsks/logitech/media-server. It is in fact larsks/logitech-media-server

Let’s see if it’s running:

➜  ~ sudo docker ps                   
CONTAINER ID        IMAGE                          COMMAND             CREATED              STATUS              PORTS                                                                                            NAMES
9a8f50ea19c5        larsks/logitech-media-server   "/"    About a minute ago   Up About a minute>3483/tcp,>9000/tcp,>9090/tcp,>3483/udp   amazing_mccarthy

So far so good. Opening a browser at brought up the LMS interface and everything worked perfectly.


So we’ve got a Docker image which we think is good enough to use, the next step is to orchestrate the provisioning of this container on to the host that we want to run LMS from.

The outline of what we want to do is something like:

  • Install Docker
  • Pull the image
  • Start the image, exposing the relevant ports and mounting the appropriate paths etc
  • Do a bit of extra configuration to ensure the container starts on boot etc.

I’m a big fan of Ansible and it seemed like a natural fit here, so that’s what I’ve used.

Installing Docker

A quick check of Ansible Galaxy brought back quite a few Docker roles. I had a quick scan of them and settled on angstwad.docker_ubuntu which seems to be very well written is very comprehensive in that it does all of the required post-installation configuration required in order to get Docker to work.

To pull and install the role locally I did this:

ansible-galaxy install angstwad.docker_ubuntu

Writing the Playbook

Next task was to write a basic playbook to do the necessary bits and pieces, here’s a very basic play which covers all of the steps required.

# Install logitech-media-server
- hosts: fitlet
    logitech_media_server_base_directory: /Data/logitech-media-server

    - file:
      become: true
      tags: logitech

    - { role: angstwad.docker_ubuntu, become: true, tags: logitech}

    - docker_container:
        name: logitech-media-server
        image: larsks/logitech-media-server
        published_ports: ["3483:3483", "9000:9000", "9090:9090"]
              - /Data/Music:/srv/music
              - ":/srv/squeezebox"
        restart_policy: unless-stopped
      become: true
      tags: logitech

Run the Playbook

Now we’ve got our playbook it’s time to run it against the target host, in my case the magic incantation is:

ansible-playbook -i inventories/dev/dev.ini fitlet.yml -vv --tags logitech

Having provisioned the host we should now be able to acess the LMS webapp on port 9000 of the IP address that it has bound to, in my case this was the IP on eth0 which gave me a URL of

Secure it with a username and password

Important note: The security that comes with LMS is terrible, it runs over http only and uses basic auth, which as I’m sure you know is a completely insecure combination. In its defense, I would imagine that exposing one’s music collection over the internet was not a key design consideration. However given that we’re just playing here I’ll continue to detail the steps I followed to make it accessible to me from anywhere, but please, if you set this up yourself remember that the username and password you use here should not be considered secure.

The security menu is buried several levels down in the UI, to access it navigate through the following:

  • Settings button (Bottom right hand corner)
  • Advanced tab
  • Click the twisty on the left hand side (which probably says ‘Formatting’)
  • Select ‘Security’
  • Configure the page appropriately for your needs.

Making it accessible from anywhere

Now that we’ve ‘secured’ the UI we can make it accessible from the outside world, the exact steps required will vary from setup to setup but a simple setup probably won’t be a million miles away from the following:

Export ports

Expose the following ports and protocols on your WAN interface:

  • 3484 tcp (for connections from players) and udp (for SlimProto commands)
  • 9000 tcp (for http access to the webapp)
  • 9090 tcp (for telnet *shudder* access to the CLI)

Configure Dynamic DNS (Optional)

Unless you have a static IP address you’ll probably want to configure Dynamic DNS to point a particular DNS name to your WAN interface e.g. Once you’ve done this you should be able to access the LMS webapp at the DNS name you’ve configured e.g.

Get an App

The final step I took was to configure my Android phone as a LMS ‘player’, this typically requires 2 apps: The first app talks the LMS protocols and registers your device as a ‘player’. The 2nd app provides a UI of your music collection to you and provides the ‘controls’ e.g. play/ pause/ volume/ search etc.

I use Squeezeplayer as the controller app and Squeezer as the player app, I find this combination of apps to work really well. I have also tried the official Logitech Squeezebox Controller app in the past but couldn’t get it working reliably as it seems to require your local LMS server to be on a local network, which of course in this case is not the case. I have also tried Squeeze Commander but recent versions seems to have stopped working for me and I found its UI quite unintuitive.

I don’t use Apple devices so I’ve no idea what apps are available here but if you do then let me know and I’ll happily add some notes here.

Future tweaks:

Functionally speaking the above works really well, I have access to my entire music collection anywhere I have my phone and can stream over $g or Wireless depending on what’s available. However the security issue really irks me, so perhaps a next step would be to see if it’s possible to put LMS behind something which will do TLS termination (perhaps nginx)… I’d be interested to hear from anyone who has done any securing or hardening of LMS so drop me a line in the comments if you have and don’t mind sharing the details of your implementation.

That’s it for this entry, I hope this helps someone achieve portability of their entire music library, please drop me a line in the comments if you spot any inaccuracies or have any questions or comments.



A Song a Day - Day 5 - Elbow - the Stops

| Comments

A couple of friends have nominated me on FaceBook to post a song every day for seven days, and nominate someone each day to do the same. This is Day 4.

This is The Stops by Elbow, definitely one of my favourite Elbow tunes. I love the imagery that Mr Garvey conjures up in this one, not many do folk do words better than he in my opinion.

A Song a Day - Day 4 - Squarepusher - Beep Street

| Comments

A couple of friends have nominated me on FaceBook to post a song every day for seven days, and nominate someone each day to do the same. This is Day 4.

Today I’m giving you ‘Beep Street’ by Squarepusher. Why? Because it’s one of the most amazing tunes I’ve ever heard and because nobody will ever be able to program beats like Mr Tom Jenkinson can!

Get yer lugoles wrapped around this one!

A Song a Day - Day 3 - Lewis Parker - Communications (Feat. Jehst)

| Comments

A couple of friends have nominated me on FaceBook to post a song every day for seven days, and nominate someone each day to do the same. This is Day 3.

Today I’m going with some UK Hip-Hop. This is Lewis Parker - Communications (Feat. Jehst) from the album ‘It’s All Happening Now’ (The Ancients Series Three)

Lewis Parker and Jehst are two of my favourite producers/ MCs and have contributed a lot to the development of Hip Hop in the UK. Jehst’s verse on this track reminds me of my own childhood spending probably hundreds of hours starting at Notator/ Cubase on an old Atari ST and later a PC learning how to make beats and music.

A Song a Day - Day 2 - Cat Stevens - Where Do the Children Play

| Comments

A couple of friends have nominated me on FaceBook to post a song every day for seven days, and nominate someone each day to do the same. This is Day 2.

Today I’m sharing ‘Where do the children play’ by Cat Stevens (now known as Yusuf Islam), it’s from his album ‘Tea for the Tillerman’ which is one of my favourite albums.

The song was written in 1970 but I think the questions he asks are every bit as relevant today. As a dad of 3 it inspires me to think about and try to positively influence the environment that we’re building for our kids’ generation.

This song also makes me think of family, in particular my Mum, as it was through her record collection that I was introduced to Cat Stevens. Thanks Mum!

A Song a Day - Day 1 - Nuyorican Soul - I Am the Black Gold of the Sun (4 Hero Remix)

| Comments


A couple of friends have nominated me on FaceBook to post a piece of music which means something to me each day for 7 days. I haven’t written anything here in an awfully long time so I thought I’d post them here too.

It’s amazing what a simple nomination can do, my mind has immediately gone in to overdrive trying to figure out how to whittle down all the music I love to just 7 songs… I’m going to need to make a list!

This is Day 1. I’m starting with Nuyorican Soul: I am the black gold of the sun (4 Hero Remix). It’s a hugely positive tune and never fails to cheer me up if I’m down. I also love the fact that it puts together computers and real instruments so seamlessly. My favourite thing though is that the drop is four and a half minutes in! That’s four and a half minutes of Nuyourican goodness followed by another four or so of some of Luke Parkhouse’s finest beats all put together with Marc Mac and Dego’s wizardy!

Vagrant-roller Now Updated for Roller 5

| Comments

Last year I put together a little GitHub project called vagrant-roller which provisioned an Apache Roller VM with very little effort. The initial version of the project provisioned a Roller v4 VM but there were a couple of issues getting the latest version of Roller (v5) to work.

I have had a bit of spare time recently and managed to get everything working so you can now provision either v4 or v5 as you prefer. I have also re-written the provisioning mechanism to use Ansible as I find it to be a much more capable and productive tool than Puppet, which I was previously using.

Any questions etc welcome either on the vagrant-roller project itself or as comments here (see below).



Alpine 3552, 3353, 3354 Car Amplifier Manuals

| Comments

Waaaay back in 2005 I posted on a car audio forum asking if anyone had the manual for an Alpine 3553 amplifier. I had the amp but no manual and couldn’t figure out the power ratings and whether it was stable at 2 ohms. Unfortunately Alpine themselves didn’t seem to have it in their manual database.

Some kind soul sent me what they had of the 3553 manual along with the 3552 and 3554 manuals, from this I managed to figure out the information I needed. Every month or so I now get an email or two from people who happen upon my post asking me if I’ve still got the manuals, just goes to show how, after all these years, the 3553 is still alive and kicking!

So, for anyone who’s after these manuals here are the files as I received them:

Alpine 3552 Manual

Alpine 3553 Manual - Single Page only I’m afraid

Alpine 3554 Manual

Note: By posting these here I am not claiming any right of ownership of the files, which of course belong to Alpine.

@Alpine: If there’s a problem with me hosting these files please let me know and I’ll duly remove them (and please add them to your manual Database so people can get to them!).



Crossing the Line in to the Dark Side… Or More Aptly Put “I’ve Only Gone and Bought Myself a Shiny New Cyclo-Cross Bike!”

| Comments

For the last 4-5 years my trusty downhill/freeride/dirt-jump/trail centre/ hard-tail has been ferrying me back and forth from my places of work. Each day I cycle my 2 * 10 mile journey, trying (usually in vain) to keep up with the sensible folk on their fast road bikes. When I first started commuting on the hard-tail I got a bit of a kick out of the fact that it was so much fun riding a bike built for anything other than road-riding on the road. I could hop obstacles, manual over sleeping policemen and do massive stoppies in to the bike boxes at lights. Plus having a whopping 200mm disk on the front gave me bundles of confidence that I could stop in no time when bus or taxi drivers pull their seemingly obligatory crazy daily manoeuvres.

There’s always been one thing which I’ve found difficult though - getting good road speed. At first I didn’t really care as I was having so much fun, but over the years I guess my base level of fitness has improved and I’ve started trying to keep pace with the faster bikes on the road. This is when I realised that riding a heavy mountain bike with 2.4” dirt jump tyres, a chain device and lots of heavy components does not make for an easy time trying to break the london-commute-speed-record! And so over the years I’ve felt the gentle yet persistent tug from the dark side, that all mountain bikers fear… that’s right, I’ve started to want a road bike!

Ok, so I’m being dramatic, there is no “dark side”, I’m sure road bikes are ace, it’s just I’ve never ridden one before. Also given my limited distance of ~100 miles a week I wasn’t sure a full-on road bike was what I wanted (lots of roadies I know regularly do 100 miles in a day!).

So what then?

I’ve been hearing more and more about a discipline called Cyclo-cross recently and after chatting to a few mates who have some experience I decided it definitely sounded like something I should find out about. Cyclo-Cross is a mixture of on and off road riding on what is ostensibly a souped up road-bike (i.e. slightly different geometry, disk brakes (usually) and thin but treaded tyres for off-road). The folks who do it seem to be of fine fettle and essentially like throwing themselves down slippery trails on fairly inappropriate bikes (hang on I’m sensing a theme emriding tree roots on narrow tyres with drop bars seem like a good example here!). After watching a few YouTube entries my decision had been made - I needed a Cyclo-cross bike!

Fast forward through lots of internet research to last weekend when I picked up shiny new bike from BonVelo (who are lovely, friendly and generally awesome by the way), a Kinesis Crosslight Pro6… and it’s beauuuutiful!:

Alt text

Riding the thing

This Monday was my first commute on the Kinesis. I didn’t have much time to fettle over the weekend in preparation so I took a few tools in case I needed to make any adjustments en-route.

Things I thought would be scary:

  • SPDs: I was a bit nervous of riding SPDs as I’ve never used them before but after slightly slackening the cleats off from their default position I found that they were pretty easy to clip in and out of. On Monday I made sure to clip out uber early when approaching lights but on Tuesday I did a bit of trackstand practise and found that I could still trackstand easily enough on the new bike so as not to need to unclip at lights.

Things I didn’t think would be scary that are:

  • General balance: I’m used to riding my Easton MonkeyLites which are nice and wide, in contrast the bars on the Kinesis are so narrow and consequentially the bike feels massively unstable which makes me feel vulnerable to traffic.
  • Brakes don’t work very well (yet): Again being used to Avid Elixirs with a 200m disc my mechanical 160mm bb7’s feel somewhat lacking by comparison. They seem so be getting more grippy as they bed in though so should be easy enough to get used to.
  • Trying to stand up and pedal hard and nearly catapulting myself diagonally over the bars. This is getting easier each day as I get use to the bike but I think I could benefit from improving my core + upper body strength.
  • Cornering on those tiny little tyres: The road/tyre contact patch is literally tiny! Definitely an opportunity to improve my cornering skills!
  • General riding position: It’s mental, I’m hunched over like Quasimodo!
  • How in the name of all things sane am I supposed to ride this thing offroad?! Actually I’m quite looking forward to figuring this out so am going to try out for the London Cyclo-Cross Summer Series which looks like a noob friendly way of getting some off-road practise done just down the road in Herne Hill.

Things that are ace:

  • It is SO fast!
  • It it SO light!
  • Bunny Hops really easily

What next?

I’m enjoying riding the Kinesis more and more every day, so I think next steps are just to continue to get more familiar with the bike and then see if I can get some of that all important road speed I was after. Actually I can see that happening already, in the last few days I have started to consistently take 3 minutes out of my 35 minute to-work journey and 5 minutes off my 38 minute return journey. Something must be going right there!

I’m also really looking forwards to riding the bike offroad at the summer-series, that’s going to be quite a different kettle of fish to riding downhill I bet!