0

I'm having a problem with the Scripting Bridge framework in 10.5. Specifically, I use this code to create a new user playlist in iTunes:

NSDictionary *propertiesDict = [NSDictionary dictionaryWithObject:@"playlistName" forKey:@"name"];
playlistToReturn = (iTunesUserPlaylist*)[[[iTunesApp classForScriptingClass:@"user playlist"] alloc] initWithProperties:propertiesDict];
SBElementArray *sourcesArray = [iTunesApp sources];
iTunesSource *librarySource = [sourcesArray objectAtIndex:0];
SBElementArray *userPlaylistsArray = [librarySource userPlaylists];
[userPlaylistsArray addObject:playlistToReturn];

This code works fine in 10.6. The playlist is created correctly, and I can add songs to it later.

However, on 10.5, an error is generated:

Apple event:'core'\'crel'{
'kocl':'cUsP',
'insh':'insl'{
              'kobj':'obj '{
                            'want':'cUsP',
                            'from':'obj '{
                                          'want':'cSrc',
                                          'from':'null'(),
                                          'form':'ID  ',
                                          'seld':42 },
                            'form':'indx',
                            'seld':'abso'($206C6C61$) },
              'kpos':'end ' },
'prdt':{
              'pnam':'utxt'("playlistName") }
};

Error Domain=SBError Code=-10014 UserInfo=0x152c8cb0 "Operation could not be completed. (SBError error -10014.)"

Why?

  • -10014: errAENotASingleObject. Googling for that turned up this: http://www.cocoabuilder.com/archive/cocoa/275842-sb-won-create-an-element-on-10-5.html – Peter Hosey Apr 13 '10 at 17:17
  • I suppose that "because ScriptingBridge is evil" is not an acceptable answer. – TechZen Apr 13 '10 at 19:25
  • Heh. The problem is that SB doesn't speak Apple events quite the same way that AppleScript and various scriptable apps speak them. See http://stackoverflow.com/questions/1309958/avoiding-applescript-through-ruby-rb-appscript-or-rubyosa/1316563#1316563 for a longer discussion. The kludge-around here is to use -insertObject:atIndex: to insert after an existing playlist element (you'll get away with this as iTunes always has one or more existing playlists). Or use appscript, which mimics AppleScript's approach so is more capable and much less prone to application compatibility problems. – has Apr 14 '10 at 12:14

2 Answers2

0

Peter: Thanks for your link, that was enough to get me to start looking for a different solution.

Since 10.5 apparently can't handle creation of objects very well, I've modified the way I create the empty playlist. Instead what I do is create an XML object for the empty playlist, and then use Scripting Bridge's add:to: command which successfully adds the playlist. Then I use Scripting Bridge to search for the newly created playlist. Here's some relevant code:

    NSDictionary *innerDictionary = [NSDictionary dictionaryWithObject:playlistName forKey:@"Name"];
    NSArray *innerArray = [NSArray arrayWithObject:innerDictionary];
    NSDictionary *outerDictionary = [NSDictionary dictionaryWithObject:innerArray forKey:@"Playlists"];

    [outerDictionary writeToFile:pathToWriteXMLFile atomically:YES];
    [iTunesApp add:[NSArray arrayWithObject:[NSURL fileURLWithPath:pathToWriteXMLFile]] to:nil];

This successfully creates the playlist on 10.5. Then, to actually retrieve the iTunesUserPlaylist* object:

    SBElementArray *playlistArray = [[[iTunesApp sources] objectAtIndex:0] userPlaylists];
    NSPredicate *playlistPredicate = [NSPredicate predicateWithFormat:@"name == %@",playlistName];
    NSArray *playlistSearchArray = [playlistArray filteredArrayUsingPredicate:playlistPredicate];

Note that you can be even more rigorous by looping through the playlistSearchArray and checking whether the playlist is empty -- since it's a newly created playlist, that's the one you want.

0

I have an application that does this and works on 10.5. The only difference I can see between your code and mine is the last line. I use the following...

[userPlaylistsArray insertObject:playlistToReturn atIndex:0];

Give it a try...

regulus6633
  • 18,848
  • 5
  • 41
  • 49
  • This doesn't seem to work for me. I also got an error when I used insertObject:atIndex:, unless I cast userPlaylistsArray as an NSMutableArray. – Simone Manganelli Apr 13 '10 at 19:08