问题
The following code should show a certain track in iTunes:
NSString* iTunesPath = [[NSWorkspace sharedWorkspace] absolutePathForAppBundleWithIdentifier:@"com.apple.iTunes"];
iTunesApplication *iTunes = nil;
if ( iTunesPath ) {
iTunes = [[SBApplication alloc] initWithURL:[NSURL fileURLWithPath:iTunesPath]];
[iTunes setDelegate:self];
}
iTunesSource *librarySource = nil;
NSArray *sources = [iTunes sources];
for (iTunesSource *source in sources) {
if ([source kind] == iTunesESrcLibrary) {
librarySource = source;
break;
}
}
SBElementArray *libraryPlaylist = [librarySource libraryPlaylists];
iTunesLibraryPlaylist *iTLibPlaylist = nil;
if ([libraryPlaylist count] > 0) {
iTLibPlaylist = [libraryPlaylist objectAtIndex:0];
}
SBElementArray *fileTracks = [iTLibPlaylist fileTracks];
iTunesFileTrack *track = [fileTracks objectAtIndex:4];
NSLog(@"Try to reveal track: %@ at path :%@",[track description],[[track location] path]);
[track reveal];
Output:
Try to reveal track: <ITunesFileTrack @0x1364ed20: ITunesFileTrack 4 of ITunesLibraryPlaylist 0 of ITunesSource 0 of application "iTunes" (2474)> at path :/Users/...
But absolutely noting happens. What am I doing wrong? (iTunes Version: 9.0.3)
回答1:
The Library playlist doesn't exist anymore in the UI; it's there in the model, so it shows up in AppleScript, but trying to reveal it or anything in it won't do anything in the UI, as you saw. You can reproduce this in AppleScript as well (reveal track 5 of library playlist 1 of source 1
).
The solution is to talk to the Music playlist, not the Library playlist. “Music” is the second playlist—playlist 2
in AppleScript, [[librarySource playlists] objectAtIndex:1]
in Cocoa.
If you want to reveal a playing item in whatever playlist it's playing in, use reveal current track
(which should be [[iTunes currentTrack] reveal]
, although I haven't tested that).
回答2:
This helped me solve a related issue. Thanks.
I would recommend against using [[librarySource playlists] objectAtIndex:1]
to get the playlist. It feels too much like guessing. You should also avoid iterating through the arrays from Scripting Bridge with a for
loop.
This example solves both problems:
iTunesApplication *iTunes = [SBApplication applicationWithBundleIdentifier:@"com.apple.iTunes"];
iTunesSource *library = [[[[iTunes sources] get] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"kind == %i", iTunesESrcLibrary]] objectAtIndex:0];
iTunesLibraryPlaylist *lp = [[[[library playlists] get] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"specialKind == %i", iTunesESpKMusic]] objectAtIndex:0];
[[library playlists] objectWithName:@"Music"]
also works, but I’m not sure if that’s locale dependent (and the name could change in a future update).
回答3:
Just to add to the answer of Rob McBroom, it would be even better to use firstObject instead of objectAtIndex:0. It will prevent an exception in case your query fails and returns an empty array. This will happen when you search for the Internet radio source (kind == iTunesESrcRadioTuner) and the Internet Radio library is disabled in the preferences.
iTunesApplication* iTunesApp = [SBApplication applicationWithBundleIdentifier:@"com.apple.iTunes"];
iTunesSource* radioTunerSource = [[[[iTunesApp sources] get] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"kind == %i", iTunesESrcRadioTuner]] firstObject];
来源:https://stackoverflow.com/questions/2416285/itunes-scripting-bridge-reveal-does-not-work