EyeTunes framework
EyeTunes.framework is a Cocoa Framework that abstracts away all the ugly Carbon Apple Events magic and allows you to directly control iTunes from any Cocoa Application.
Features
- Get all references to iTunes playlists, tracks and album art.
- Set any writable fields that iTunes exposes such as Track name, artwork and much more.
- Control iTunes and select playlists and tracks by using either track filenames or database ids.
- Search the iTunes library just like the search box does.
- Extract persistent ID and fetch tracks using such ids.
Example
To grab an NSImage from the current playing track (say you're implementing some new album art viewier), you can use this simple snippet:
#import <EyeTunes/EyeTunes.h>
- (NSImage *) getArtworkOfPlayingSong {
EyeTunes *eyetunes = [EyeTunes sharedInstance];
ETTrack *currentTrack = [eyetunes currentTrack];
if (!currentTrack)
return nil;
return [[currentTrack artwork] objectAtIndex:0];
}
To see more examples of how to use EyeTunes in your projects, look at the EyeTunes main.m debug program or the Album Art Widget Plugin Source Code
Building and Using EyeTunes
You need Mac OS X 10.4 and Xcode 2.x. EyeTunes itself is written for iTunes 6.0, but possibly works with iTunes 4.7 without and problems except access to some fields may return an error.
Obtaining EyeTunes
It is highly recommended you checkout the latest source from SVN rather than the release tarball.
To checkout through SVN, install Subversion if you haven't already (via Webkit) and type this command in the terminal:
svn checkout http://svn.liquidx.net/svn/mac/EyeTunes/trunk EyeTunes
Otherwise, a snapshot of the latest release is here: EyeTunes-1.3.2.zip (76KB) (Released: 03 Jun 2007)
Version Changes: ChangeLog
Building/Including EyeTunes
You will probably want to include it in your project rather than
building it standalone. There are two ways to include the code into
your project. First one is to just copy all the files into your
project and add them to your target. This way you do not have to deal
with copying the framework into your YourApplication.app/Contents/Frameworks.
The second method, is probably the preferred method because it means you can build a version of EyeTunes and never have to worry about it again.
- Build the EyeTunes project as usual using the target Eyetunes.framework and Deployment build type in Xcode.
-
Drag the resulting framework from Finder (located in
./EyeTunes/build/Deployment/) into your Project's framework tree. You will probably be prompted to add to a target. - Now add a new Project Build Phase to your target called Copy Files.
- In the properties of this Build Phase, select "Frameworks" as the type and drag the Eyetunes.framework from your project tree into this build phase. For more information on this, please read the Apple Documentation or CocoaDev on Embedding Frameworks.
NOTE: You cannot include a framework inside a bundle (for example, a widget plugin bundle). You will just have to use the first method.
Known Users
There are a couple of known sightings of the EyeTunes framework in the wild including:
- Album Art Widget. Of course!
- Menuet, Menu Control for iTunes and more.
- FetchYourLyrics, I guess it does what the name suggests.
- Corripio, Fetches album art for your iTunes.
- Tangerine, Make delicious playlists.
- CoverSutra, iTunes Hotkey, Last.fm client, Apple Remote all in one.
- Awaken, iTunes alarm clock.
- BezelTunes, iTunes Controller Widget
If you do use EyeTunes.framework in your code, I would be very happy if you could drop me an email just so I know where the code has ended up. The code is licensed under the BSD license, so it means you can use it in your commercial, freeware or open source product. Of course, if you feel so included to, you can always give me a token of appreciation like a free license to your app or just a couple of bucks :)
Boring Internal Implementation Details
In case people want to know how easy/hard it is to interface with a Carbon application like iTunes through Carbon Apple Events, here is an explaination of all the mechanisms involved.
Note: A lot of this information is gathered from mailing lists, and bits of code and old webpages that are around.
Overview
The basis of EyeTunes is an ETAppleEventObject that acts as a proxy between your application code and the remote object that is accessed through AppleEvents. On top of that, ETTrack and ETPlaylists are subclasses of this object, and use the functions in there to perform the following possible actions:
- Get a property (int, float, string) of a remote object.
- Set a property (int, float, string) of a remote object.
- Get the all the elements of a class that belongs to the remote object.
- Modify the nth element of a class that belongs to the remote object.
As an example of what the above means, imagine the remote object being an iTunes track. An example property that you can set/get would be the trackName. However, the artwork is not a primitive type (int, float string), so that instead is stored as a "class" of the remote object.
So the actual implementation of [ETTrack setArtwork:atIndex:] is actually more complicated as it is dealing with "class" rather than a primitive type.
To that end, modify EyeTunes is quite straightforward. If there is a property that is not exposed, then just find out the DescType (see SDEF) and copy a similar field in ETTrack or ETPlaylist. When working with custom types it is a little more difficult.
Because every property query will result in an AppleEvent being sent, thus if performance is an issue, the programmer should cache these results.
About Apple Events
Here are some notes about Apple Events that I have discovered over the course of writing the EyeTunes framework and may be important to other people who would like to hack on the code or perform similar feats on other Apple Scriptable products.
Rsrc, AETE and SDEF
iTunes is a Carbon application, therefore it stores its AppleScriptability information in a slightly different way. That is is uses a format called AETE. You can find the definition in the iTunes.rsrc file inside /Application/iTunes.app/Contents/Resources.
Copy the iTunes.rsrc file from the iTunes.app bundle to a temporary directory, and use Aete2sdef to generate an sdef file. This is an XML file that defines all the classes, parameters and commands similar to what Apple's Script Editor Dictionary pane uses. Except the difference is that all the "code" elements are named. These are the 4 character codes that are very similar to HFS File Type codes.
Carbon Apple Events
Short explanation of what Carbon Apple Events and how it fits into the grand scheme of things such as Apple Script.
AEDesc and AEGizmo
Where to find information on AEDesc and AEGizmo
Running Script Editor through gdb
Use this to sniff AEGizmo strings and understand how event codes are encoded. Apple explains how to do this very well in this Technical Note TN2045.
Running iTunes through gdb
Kinda useless unless you want to do some mach_inject magic on it, but its complicated enough that it deserves a mention. Not that EyeTunes framework actually does anything as evil as that.
Contact
If you have any bug reports, you can either leave a comment or directly email me at alastair[at]tse.id.au.
Add a comment
Alastair Tse says
- 1 month, 3 weeks ago (22/03/2008)
Mime says
You can delete this comment after having fixed it.
- 1 month, 3 weeks ago (21/03/2008)
Manni says
This framework works really great! Thank you very much for it!
I've already built a small application which can control iTunes.
But it is missing a volime slider.
I haven't found a way to control the volume of iTunes with the eyeTunes framework.
Can anybody help me how to do this?
Thanks
- 8 months, 4 weeks ago (20/08/2007)
David says
I have never been able to get -(ETTrack *)trackWithPersistentId:(long long int)persistentId; or - (ETTrack *)trackWithPersistentIdString:(NSString *)persistentId; to work.
If anyone has any ideas on this, that would be great.
Thanks
- 9 months ago (14/08/2007)
Vincent says
I have a problem with this library. A thread check all the seconds if a track has been changed or if a song has been delete/added. But when I close iTunes when the thread is running and I restart iTunes. The thread is blocked at a line like
ETPlaylist * libraryPlaylist = [eyeTunes libraryPlaylist];
approximately 5 minutes later, the thread can run again.
Someone have a solution?
Thx
- 9 months ago (13/08/2007)
Luke Sheridan says
EyeTunes class
-(int) position;
- (int) position
{
return [self getPropertyAsIntegerForDesc:ET_APP_PLAYER_POSITION];
}
EventCode
#define ET_APP_PLAYER_POSITION 'pPos'
- 1 year, 5 months ago (02/12/2006)

Atom Feed for the Blog Entries