Re: How to access iTunes using cocoa
Re: How to access iTunes using cocoa
- Subject: Re: How to access iTunes using cocoa
- From: has <email@hidden>
- Date: Tue, 26 Jan 2010 19:13:28 +0000
Jens Alfke wrote:
> On Jan 26, 2010, at 9:41 AM, Paul Sanders wrote:
>
>> I use Cocoa's NSAppleScript class. This seems to work fine on Tiger, Leopard and Snow Leopard.
>
> Yup, it just has the limitation that you have to run the script synchronously, which sucks since many iTunes commands can take a long time. There's no workaround to this that I've been able to find, since NSAppleScript is not thread-safe.
AppleScript and NSAppleScript are thread-safe in 10.6.
As for slowness, iTunes may not be a speed demon when it has many tens of thousands of tracks to wade through, but in a lot of cases the performance problems are primarily due to inefficient design in your own code. The Apple Event Object Model was optimized for System 7, where IPC was extremely expensive, so generally works best if you can use a few complex commands rather than lots of simple commands.
e.g. This is dog slow because it sends 3*N+1 Apple events (where N is the number of tracks), each of which takes time for iTunes to process:
set the_result to {}
tell application "iTunes"
repeat with track_ref in every track of library playlist 1
set end of the_result to {name, album, artist} of track_ref
end repeat
end tell
the_result
whereas this returns the same data (albeit in a different arrangement) using just 3 Apple events, so is blazing fast by comparison:
tell application "iTunes"
set the_result to {name, album, artist} of every track of playlist 1
end tell
Apple event IPC is based on RPC + first-class queries, not OOP as most folks assume (a rough analogy would be XPath queries over XML-RPC). If you try to apply OO idioms to it when moving large numbers of values between processes, performance will suck even by IPC standards.
Similarly, if you want to filter for specific tracks, you'll get much better performance if you can formulate a more complex query for iTunes to resolve rather than pull out all of the data and search it yourself:
tell application "iTunes"
make new user playlist with properties {name:"Post"}
duplicate (every track of library playlist 1 whose album = "Post" and artist = "Björk") to playlist "Post"
end tell
If you're curious, running that through ASTranslate formats each Apple event in objc-appscript syntax (which is handy as a starting point for developing your own ObjC code, and avoiding off-topic moderation:):
#import "ITGlue/ITGlue.h"
ITApplication *itunes = [ITApplication applicationWithName: @"iTunes"];
ITMakeCommand *cmd = [[[itunes make] new_: [ITConstant userPlaylist]]
withProperties: [NSDictionary dictionaryWithObject:
@"Post" forKey: [ITConstant name]]];
id result = [cmd send];
#import "ITGlue/ITGlue.h"
ITApplication *itunes = [ITApplication applicationWithName: @"iTunes"];
ITReference *ref = [[[[itunes libraryPlaylists] at: 1] tracks] byTest:
[[[ITIts album] equals: @"Post"] AND:
[[ITIts artist] equals: @"Björk"]]];
ITDuplicateCommand *cmd = [[ref duplicate] to:
[[itunes playlists] byName: @"Post"]];
id result = [cmd send];
HTH
has
--
Control AppleScriptable applications from Python, Ruby and ObjC:
http://appscript.sourceforge.net
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden