Monday, 24 October 2011

XAML Magic: Turning an Ugly Silverlight Duckling into a Beautiful Photoshopped Swan

Over the last few weeks I’ve had the privilege of working with Ayende and the Hibernating Rhinos team on the new management UI for RavenDB. Never one to follow the herd (unless perhaps it consisted of Rhinos), Ayende’s bucking the trend and building it in Silverlight.

My part was to beautify the application by mimicking Photoshop designs that a designer had created for a new version of the RavenDB website. I was quite pleased with the way it turned out, and the screenshots Ayende posted on his blog got some favourable feedback.

Ayende asked me to write a blog post on the transmogrification process, and he has just published it on the company blog. Go read it, to find out how I turned this


into this


Monday, 3 October 2011

Announcing the launch of Mixed In Key 5

I’m very pleased to announce that Mixed In Key LLC, one of my clients, have just launched the product I’ve been working on for the last eight months. Mixed In Key 5.0 is for DJs who put together their DJ sets using harmonic mixing, a technique for ensuring a musically pleasing transition from one track to the next by eliminating key clashes. Mixed In Key 5.0

How it works

The Camelot WheelMixed In Key supplies the key ingredient to successful harmonic mixing. It analyses every song in a DJ’s collection and determines which key it is written in (by key, I mean musical key, like C#, F#, A Minor, etc.). Every song is then added to a searchable database.

The other ingredient comes from music theory, and has been cleverly codified by Mark Davis into the Camelot Wheel. This shows the relationship between each key in a diagram arranged like a clock. To build a harmonic mix, a DJ finds the key of his first song on the wheel (so E Major is at the twelve o’clock position). For his next song he should pick one in a key which is an “hour” to the left or right, or stay at the same hour but switch between major or minor keys. Mixed In Key 5.0 includes a clickable Camelot Wheel to instantly search the database for songs in a particular key.

Under the bonnet

The User Interface is all built in WPF. As I hinted in an earlier blog post, I had a great time taking the designs beautifully drawn up for us in Photoshop by our designers and mapping them into XAML. Though I have to say, it is a painstaking process, poking all those pixels into precisely the prescribed positions – I guess it took something like 5 or 6 days to polish the 4 screens in the applications.

But more important than looking gorgeous, Mixed In Key 5.0 had to be fast and responsive (we started the project many months before Windows 8 was announced, otherwise that would have been “fast and fluid”). I have to thank the Task Parallel Library in .Net 4.0 for making this really easy to achieve (though not as easy as it will be in C# 5.0, when we get our hands on the await keyword).

At the heart of the application is song analysis, which is a process with several steps. First, we read the song data using some custom DirectShow filters (DirectShow is actually rather fun to use once you’ve got the hang of it). Then we send extracts of the data off to our analysis server in the cloud for processing. Finally we have to add it to the database. Each of the steps takes a while to complete, so are ideal candidates for Tasks.

.Net 4.5 has a rather nice Dataflow library that is ideal for setting up a pipeline of tasks that need to be processed asynchronously. But that’s not out yet, so I used some extensions that Stephen Toub wrote to the current TPL library for chaining Tasks together. Here’s what our analysis pipeline looks like:

AnalyzeSongAudio(progressReporter, file)
   .Then(audioAnalysis => file.AudioAnalysis = audioAnalysis)
   .Then(_ => ReadFileTags(file))
   .Then(tags => file.Tags = tags)
   .Then(() => SetItemStatus(file, QueuedFileStatus.DetectingKey))
   .Then(_ => DetectKey(file))
   .Then(result => file.SongAnalysisResult = result)
   .Then(_ => RewriteTags(file))
   .Then(result => AddSongToCollection(file))
   .Then(song => UpdateQueuedFileWithSong(file, song))
   .Then(() => SetItemStatus(file, QueuedFileStatus.UpdatingFile))
   .Then(() => UpdateFile(file))
   .Then(() => SetItemStatus(file, QueuedFileStatus.Completed))
.OnError(task => UpdateItemWithError(file, task.Exception.InnerException), Schedulers.UIThread)
.ContinueWith(t => DecrementQueuedFileCount(), TaskContinuationOptions.ExecuteSynchronously);

As an aside, do you know the best thing about using Tasks in your application? You get your free lunches back again! As PCs get more and more cores, your application will automatically scale to take advantage of them.

What a launch!

Yakov, the founder of Mixed In Key LLC, tells me that the launch has been very successful already.The Mixed In Key Twitter stream has been flooded with happy comments. Here are a few of my favourites:

Woke up without a hangover, got called off jury duty & @MixedInKeyjust came out with version 5.0 that analyzes video!!! Start of a good day

@MixedInKey You guys did it! #MIK5 is working like a charm. Gorgeous interface, unrivaled speed, heaps new features and still easy to use!!

My new @MixedInKey purchase rocks! Firing on all 4 cores at the moment at 100% CPU, this thing is #fast! Currently scanning 3000 songs :)

@MixedInKey is very very fast! Like a thunder! The multicore processing is the best feature

So Congratulations to Yakov and the rest of the Mixed In Key team, and thanks for letting me help out on such an exciting project.