Indrio development took a back seat to some other more important real world stuff for a while. I’ll get into that at a later time but right now I’m gonna focus on Indrio.
Some parts of the iTunes API are shamefully slow. The Enumerator for ITrackCollection operates in n ² time. So the time it takes to walk the list grows quadratically with the length of the list. Iterating over the list with python and calling Item is actually faster that the enumerator. That was a bit of a shock. Item() is definitely n ², access at the end of the list is much slower than at the start of the list.
Even if Apple were to fix this we are talking about 5 seconds here which would give a max speedup of 2.2 seconds. Thats still too slow for search as you type. Besides, have you ever seen what happens when you drop a 5k rows worth of table into a web page? It won’t render correctly on anything.
The real solution is to page the results. This way access to the results is fast even in the worst case scenario at the end of a large list. This is what you would do in a real GUI application anyway. Never show the user more information that then can digest and Never do processing for anything you didn’t show the user.
The search for answers to Inrdio’s speed problems lead me down a path of optimizations that tightly coupled the iTunes stuff to the web server. Some of the optimizations were good but I’m not going to pay for them with bad architecture. So I took a step back and completely abstracted everything behind three classes: AudioPlayerInterface, TrackList, & Track.
The AudioPlayerInterface supports searching, queuing, and provides information about what songs will play/are playing. The TrackList supports the paged access to tracks, either from search results or from the playlist. Tracks are, of course, tracks with information like Artist, Title and so on.
In the iTunes implementation of TrackList is extremely fast. You construct a TrackList without having to iterate through the tracks. Then the web application module can get a page of tracks and compose them with the templating engine.
Access to Track data is done as its requested. The absolute minimum number of COM calls are made to render each template. The Track interface uses the wrapper pattern so its thin and fast. This way the tracks can support a large set of properties without having to copy each one into a temporary variable. The extra fields can be used by other templates, like the one that will render what playing now.
Expect a release (with code) as soon as I get the obvious bugs out.