Skip to main content

Controlling iTunes from Java: a better Java/COM integration with Tiger

Posted by kohsuke on January 28, 2005 at 6:27 AM PST

iTunes for Windows comes with a COM API that lets you access its playlists, track information, artworks, and everything. You can even control the iTunes window size.

For those who don't know COM, it stands for Component Object Model, a standard programming infrastructure used in Microsoft Windows to expose APIs. In Windows, a lot of very interesting APIs are available through COM, and ever since J2SE 5.0 was released, I've been interested in using annotations to make it easy to call these APIs.

So here I am. Using com4j, you can access arbitrary API designed by using COM, including this iTunes API, from Java.

Here is how it works. An API designed by using COM usually comes with a "type library", which is metadata that describes the exposed API. Using the tlbimp tool from com4j, you can generate a set of Java interface definitions from a type library. A typical generated interface definition looks like this:

public interface IiTunes extends Com4jObject {
     * Reposition to the beginning of the current track or
     * go to the previous track if already at start of current track.
    void backTrack();
     * Play the specified file path, adding it to the library
     * if not already present.
    void playFile(String filePath);


Unlike other similar Java/COM bridge libraries, com4j only generates interfaces, not classes. The runtime system of com4j uses annotations to figure out how to bridge a method call to COM.

This approach has a number of key advantages over classic Java/COM bridge libraries. Firstly, all the methods are strongly typed, making it obvious to how to invoke them, where some existing libraries forces you to work more like Java reflection, where nothing is strongly typed. Some other libraries statically generate a lot of code to bridge method calls correctly, which bloats your application. Compared to that, use of annotations in com4j reduces the code size significantly.

Secondly, oftentimes, because neither the type library nor tlbimp is perfect, it generates a signature that isn't quite right. For example, if one of the method has the following signature:

HRESULT setTitle( [in] wchar* text );
tlbimp has no way of knowing whether it's passing a string or an array of char. So it might just give you the following:

void updatePolygon(char[] text);

I had a painful experience like this when I used C#/COM bridge to invoke DirectShow. Because com4j only generates interfaces, you can change this very easily to "void updatePolygon(String text)". This ability of tweaking the generated definitions is very useful when dealing with a real APIs.

I hope you find com4j interesting!

Related Topics >>