Archive for November 2005


Indrio Development: Fun with DOM

DOM is a swell gal, she treats me all right, just so long as I take her out to her favourite restaurant; Firefox. When I get cheap and go for fast food at Internet Explorer, she’s not happy.

innerHTML is a read only property in IE for the table and tbody elements. Trying to set it causes a very nondescript error with a code of 0. Firefox isn’t totally off the hook either. With large sets of rows there are rendering errors at the bottom of the table if you don’t define a background color. I’m using prototype.js to insert the rows returned from an AJAX call. I kluged a fix for IE by inserting the entire table every time.

Performance building that table was very bad for large result sets (1k+ rows). Python had a built in profiler & CherryPy has profiler support. I totally love this, this rocks 1000% more than Java. Reading and building the data set from iTunes was about 1/10th the total execution time so something else was not very fast. Turns out it was a module for the template engine that only worked with 2.4. I upgraded everything to 2.4 and performance got drastically better.

Now the major bottleneck is with fetching values from iTunes via COM. Thats about 80% of the time is spent in __getattr__ and _ApplyTypes_. Thats the COM stuff translating returned values into Python types and the majority of that time is probably spent in iTunes. The stop gap to give reasonable performance is to limit the number of rendered results.  I picked a ‘magic’ number, 300, which renders in under 2 seconds on my system. This will suck if your trying to search for music by genre and there are 1K+ results for ‘Trance’ in your library. Some sort of paging solution may have to be used to get through a result set like that. I don’t really see that as a major usage pattern in my experience. People generally ask for music by title or artist and this turns out to be very specific and returns a limited number of results.

Cooky TV Output Stuff

I use my TV as a second monitor, its connected via component cable to my GeForce 6600GT. It’s been doing some weird stuff when full screen apps take over the TV display. When one of these apps exists the TV display looks torn at the top, like the resolution or refresh rate isn’t quite right. Nothing I have done seems to fix the problem.

Full screen video always works fine and always fills the televisions entire screen, these apps don’t seam to be the problem. Quitting from Media Center will cause the tearing as will any full screen game. To restore the screen the simplest thing to do is run the ‘TV Wizard’.

I can’t seem to phrase a search for this issue in less than 6 words. If you know where I should post a bug or can get help post a comment.

Indrio Development Continues Apace: HTTP Server

For this particular application I don’t care where the user interface is displayed. In fact it would be cooler if the UI could go somewhere other than where iTunes is. In fact it would also be cool if a couple of people on different computers could access the thing at the same time, bonus. So I decided to send the UI out over an HTTP server to a browser and use a bit of AJAX to make this snappy. This brought development to an impasse, where do you get an HTTP server for python. Apache was out of the question, I’m not having users install that thing just to run this little app, way overkill. In fact what I wanted was fairly specific:

  • Small; as in not large, as in less than 1 MB compiled
  • Embedded; must run from inside the app, no external servers please
  • Must not stop me from talking to COM
  • Must be nice to Unicode strings
  • Must be nice to AJAX
  • Must serve some static files
  • Must server some dynamic content probably composed with a template system

Turns out there was only one system that I could locate that fit the bill, CherryPy. Getting the demo up and running was easy. Getting it to talk to COM was trickier. Its got something to do with threads and CoInitialize-ing them. The docs there almost have the magic formula, you have to hook on to whatever COM object you are calling after you call CoInitialize(). This means you can’t start up COM in the built in __init__ function of your root class in CherryPy, you have to call it from in the InitializeCOM()function, after the call to CoInitialize(). With that sorted I got the HTTP server to stop giving 501 errors and spit out the version of iTunes; “ “. So far so good.

Now I am a big believer in the MVC pattern, code should stay in the code, and the view should be just the view. So next I wanted a template language to put together with CherryPy to complete my tool set. There seem to be a lot of these out there, mainly that want to mess with the HTML your writing to make sure your doing it right. Now, writing XHTML strict isn’t a problem and there is the posibility that I might generate some JavaScript code. The template engine has to be general, small size is a plus, easy to learn is a plus. Cheetah looks almost exactly like Velocity to me, and I’ve worked with Velocity before so its a good fit for a rapid prototype.

Indrio Development Begins: iTunes, COM & Python

Indrio is the name or a road not too far form here. Indrio is also the code name for a little project I’m working on to help me learn Python. It involves talking to iTunes, over COM. This is easier than it sounds. The iTunes SDK documentation is well written, well organized and easy to understand. It’s an easy API to work with, thats the good news.

The bad news is that some of the cool stuff that iTunes is doing in the UI is not available through the COM interface. Of particular interest to me was the Party Shuffle playlist. You can add tracks to it but only at the end i.e. No “Play Next in Party Shuffle” via COM. You can’t determine how many previously played tracks are showing (unless your actually playing that playlist and work it out from the currently playing track). You can’t set the playlist that feeds into the party shuffle or any of the other parameters. These things are not blockers for what I wanted to do but they would have made things much nicer for users.

Then there is fun with ID’s. The docs say that all objects in iTunes support four script friendly functions to return the Source, Playlist, Track & Database ID’s respectively. If you have a problem accessing these functions its because the Source, Playlist and Track functions are declared to start with common letters; sourceID(), playlistID(), trackID(). The database ID function is capitalized as per the docs: TrackDatabaseID(). Also of interest, Python can handle the multiple return values of GetITObjectIDs() by turning them into an array. Score one for Python! Score another one for the Python COM browser which helped me track down the capitalization bug.

iTunes.GetITObjectByID() doesn’t work if all you have is the Database ID, which makes knowing that basically useless. To make GetITObjectID() work you need to know all 4 parameters. That isn’t exactly congruent with the docs. Supplying 0 to any of the parameters throws some sort of error.

The final twist is with Python. It supplies base types when a function returns a derived type over COM. So you have to cast the return type to the type you expected. This had me stumped for a while until I saw this Simon Brunning’s code. win32com.client.CastTo() is the magic bullet that fixes this. I wish there was some good docs for the Python COM interface.

Stay tunes for the next installment where I reveal even less about what Indrio might be or do or why you should care…