Search code examples
objective-cxcode4itunesscripting-bridge

Play specific title in iTunes via ScriptingBridge


I'm trying to write an application that interacts with iTunes via ScriptingBridge. I works well so far, but the options of this method seem to be very limited.

I want to play song with a given name, but it looks like there's no way to do this. I haven't found anything similar in iTunes.h…

In AppleScript it's just three lines of code:

tell application "iTunes"
    play (some file track whose name is "Yesterday")
end tell

And then iTunes starts to play a classic Beatles song. Is there any was I can do this with ScriptingBridge or do I have to run this AppleScript from my app?


Solution

  • It's not as simple as the AppleScript version, but it's certainly possible.

    Method one

    Get a pointer to the iTunes library:

    iTunesApplication *iTunesApp = [SBApplication applicationWithBundleIdentifier:@"com.apple.iTunes"];
    SBElementArray *iTunesSources = [iTunesApp sources];
    iTunesSource *library;
    for (iTunesSource *thisSource in iTunesSources) {
        if ([thisSource kind] == iTunesESrcLibrary) {
            library = thisSource;
            break;
        }
    }
    

    Get an array containing all the audio file tracks in the library:

    SBElementArray *libraryPlaylists = [library libraryPlaylists];
    iTunesLibraryPlaylist *libraryPlaylist = [libraryPlaylists objectAtIndex:0];
    SBElementArray *musicTracks = [self.libraryPlaylist fileTracks];    
    

    Then filter the array to find tracks with the title you're looking for.

    NSArray *tracksWithOurTitle = [musicTracks filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"%K == %@", @"name", @"Yesterday"]];   
    // Remember, there might be several tracks with that title; you need to figure out how to find the one you want. 
    iTunesTrack *rightTrack = [tracksWithOurTitle objectAtIndex:0];
    [rightTrack playOnce:YES];
    

    Method two

    Get a pointer to the iTunes library as above. Then use the Scripting Bridge searchFor: only: method:

    SBElementArray *tracksWithOurTitle = [library searchFor:@"Yesterday" only:kSrS];
    // This returns every song whose title *contains* "Yesterday" ...
    // You'll need a better way to than this to pick the one you want.
    iTunesTrack *rightTrack = [tracksWithOurTitle objectAtIndex:0];
    [rightTrack playOnce:YES];
    

    Caveat to method two: The iTunes.h file incorrectly claims that the searchFor: only: method returns an iTunesTrack*, when in fact (for obvious reasons) it returns an SBElementArray*. You can edit the header file to get rid of the resulting compiler warning.