Go Back   MacRumors Forums > Apple Systems and Services > Programming > Mac Programming

Reply
 
Thread Tools Search this Thread Display Modes
Old Nov 3, 2008, 02:14 PM   #1
mlikesit
macrumors newbie
 
Join Date: Nov 2008
How do I use objc-appscript to create a new playlist in iTunes?

I am writing an app in Xcode and need to create a new playlist in iTUnes, and add specific tracks to it.

Here is the code I have so far:

Code:
-(ITunesError *) savePlaylist:(Playlist *) playlist {
	ITunesError * rv = [[ITunesError new]retain];

        //Get name of playlist we want to create
	NSString * name = [playlist name];
	ITReference *playlistRef = [[itunes playlists] byName:name];
	
        /* Find a unique name for playlist we are creating */
	if([[[playlistRef exists]send] boolValue]){
		int i = 1;
		NSString * n = @"";
		do{
			n = [NSString stringWithFormat:@"%@_%d", name, i];
			playlistRef = 	[[itunes playlists] byName:n];
			i++;
		}while([[[playlistRef exists]send] boolValue]);
		name = n;
	}
	
        //Create new playlist in itunes
	[[[[itunes make] new_: [ITConstant playlist]] withProperties: [NSDictionary dictionaryWithObject: name forKey: [ITConstant name]]] send];
	
	
        //Returns the main music library for iTunes
	ITReference *main = [self getRefToMainPlaylist];
	ITReference * tracks = [main tracks];
	
	//NSArray * trackNames = [[tracks name] getItem];
	//NSArray * artistNames = [[tracks artist] getItem];
	NSArray * locations = [[tracks location ] getItem];
	
	NSMutableArray *files = [NSMutableArray array];
	for(int j = 0; j < 10; j++){
		ASAlias * alias = (ASAlias *) [locations objectAtIndex:j];
		NSLog([alias path]);
		NSURL *file = [NSURL fileURLWithPath: [alias path]];
		[files addObject: file];
	}

        /* At this point here is what we have:
           playlistRef - Reference to playlist we just created in itunes
           files - Array of NSURL objects pointing to files on disk.
        */
	NSError * error = 0;
	[[[itunes add: files] to: playlistRef] sendWithError:&error];	
	if(error){
		[rv setErrorObject:error];
		NSLog([rv getErrorMessage]);	
	}
        return nil;
}
In the code above, i'm not too picky about what tracks I add (I'll worry about that after I can add a track to the playlist) so for now it is just adding the first N tracks from the iTUnes main track library.

When I run the code above the error message contained in NSError is:
Quote:
Application error: the AppleEvent was not handled by any handler
which comes from when I try to add the files to the playlist.

Any help here would be greatly appreciated.
mlikesit is offline   0 Reply With Quote
Old Nov 4, 2008, 06:37 AM   #2
hhas
macrumors regular
 
Join Date: Oct 2007
Quote:
Originally Posted by mlikesit View Post
I am writing an app in Xcode and need to create a new playlist in iTUnes, and add specific tracks to it.

Here is the code I have so far:

Code:
[...]
	NSMutableArray *files = [NSMutableArray array];
	for(int j = 0; j < 10; j++){
		ASAlias * alias = (ASAlias *) [locations objectAtIndex:j];
		NSLog([alias path]);
		NSURL *file = [NSURL fileURLWithPath: [alias path]];
		[files addObject: file];
	}

        /* At this point here is what we have:
           playlistRef - Reference to playlist we just created in itunes
           files - Array of NSURL objects pointing to files on disk.
        */
	NSError * error = 0;
	[[[itunes add: files] to: playlistRef] sendWithError:&error];
Couple of things:

1. Take care when casting values returned by application commands, in this case, the (ASAlias*) cast. Some application commands may return different types at different times, e.g. getting a track's location property will return an alias if the file exists, or a 'missing value' constant if it doesn't. If you want to specify the return type, do it when you're constructing the application command, e.g. in this case use [[tracks location] getListOfType: typeAlias error:&error], which will return a coercion error if it encounters a missing track. Alternatively, use -[NSObject isKindOfClass:] to check the returned value's class before using it.

2. You shouldn't need to re-pack ASAliases as NSURLs if you're only passing them back to iTunes; iTunes should accept either. OTOH, using ASAliases in other Cocoa APIs is a pain as they're not API-compatible with NSURLs (I need to work on this), but you can at least get an NSURL directly via -[ASAlias url], or else you can tell appscript to coerce the values returned by the application command to the desired type for you (in this case typeFileURL).

3. If you're importing files that aren't already in iTunes, use its 'add' command. In this case though you're wanting to add tracks that already exist in your library playlist to a user playlist, and for that you should use iTunes' 'duplicate' command. Don't have sample code to hand (ask if you need some), but it should be pretty straightforward. iTunes' 'duplicate' command appears to accept either a single-track reference or a multi-track reference (most apps do), though not a list of references (most apps don't), e.g. these work:

Code:
tell application "iTunes"
	duplicate (track 1 of library playlist 1) to playlist "test"
end tell

tell application "iTunes"
	duplicate (tracks 1 thru 5 of library playlist 1) to playlist "test"
end tell
but this doesn't:

Code:
tell application "iTunes"
	set tracksList to (get tracks 1 thru 5 of library playlist 1)
	duplicate tracksList to playlist "test"
end tell
So if you need to add multiple tracks, either create a single reference that identifies all the tracks you want (e.g. by using a by-test specifier) and use that in the 'duplicate' command, or iterate over a list of references and duplicate them one at a time.

Tips:

- You can use ASTranslate (available from the appscript website) to convert the above iTunes commands from AppleScript to ObjC syntax, which is handy if you've got an AppleScript-based example and need some help with translating it into ObjC.

- Doug's iTunes (http://dougscripts.com/) has tons of iTunes-related AppleScripts, many of which can be viewed in Script Editor; also very handy when you're trying to work out how to perform a particular task. As you've probably noticed, iTunes' own scripting documentation (like that of most apps) is very thin and doesn't tell you half the stuff you actually need to know in order to script it effectively - so other folks' scripts can be a valuable source of hints and solutions.
__________________
Learn AppleScript, 3rd edition, Sanderson & Rosenthal:
http://www.apress.com/9781430223610
hhas is offline   0 Reply With Quote
Old Nov 4, 2008, 08:54 AM   #3
mlikesit
Thread Starter
macrumors newbie
 
Join Date: Nov 2008
Can't create new Playlist

Thank you for mentioning ASTranslate, wish I would have found out about it when I started this app instead of when I was almost done.

Using it, I have figured out how to add existing tracks to an existing playlist, but I am still having problems creating a new playlist.

So i've created this method to simply create a playlist. I got the code from ASTranslate and the only modification I made was to sendWithError.

Applescript Code
Code:
tell application "iTunes"
	make new user playlist with properties {name:"DUH"}
end tell
Translates to the following Appscript code:
Code:
-(NSError *) createPlaylist:(NSString *) playlist{
	ITMakeCommand *cmd = [[[itunes make] new_: [ITConstant userPlaylist]] withProperties: [NSDictionary dictionaryWithObject: @"Playlist" forKey: [ITConstant name]]];
	NSError * rv = 0;
	[cmd sendWithError:&rv];
	return rv;
}
When I run the Applescript code, it creates a new playlist in iTunes. When I run the objective-c appscript code, I get the following error:

Quote:
Error Domain=net.sourceforge.appscript.objc-appscript.ErrorDomain Code=-10001 UserInfo=0x1af030 "Application error: / invalid TELHandle or handle not found (-10001)"
I have now idea why that happens or what it means and I don't understand why it works when I run the Applescript but not when I run the Appscript.
mlikesit is offline   0 Reply With Quote
Old Nov 4, 2008, 01:00 PM   #4
hhas
macrumors regular
 
Join Date: Oct 2007
Quote:
Originally Posted by mlikesit View Post
So i've created this method to simply create a playlist. I got the code from ASTranslate and the only modification I made was to sendWithError. [...] When I run the Applescript code, it creates a new playlist in iTunes. When I run the objective-c appscript code, I get the following error:
Hmm. Wonderfully helpful error message. That you get different behaviour with appscript to AppleScript is a concern, but so far I'm unable to reproduce the problem here (iTunes 8.0.1 on 10.5.5/i386), e.g.:

Code:
#import "ITGlue/ITGlue.h"

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

ITApplication *itunes = [ITApplication applicationWithName: @"iTunes"];

ITMakeCommand *cmd = [[[itunes make] new_: [ITConstant userPlaylist]] 
						   withProperties: [NSDictionary dictionaryWithObject: @"DUH"
																	   forKey: [ITConstant name]]];

NSError *error;
id result = [cmd sendWithError:&error];
NSLog(@"Result = %@", result);
NSLog(@"Error = %@", error);

    [pool drain];
    return 0;
}
produces:

Code:
2008-11-04 18:23:29.561 itunes-newplaylist[23202:10b] Result = [[[[[ITApplication applicationWithName: @"/Applications/iTunes.app"] sources] byID: [NSNumber numberWithInt: 41]] userPlaylists] byID: [NSNumber numberWithInt: 56496]]
2008-11-04 18:23:29.563 itunes-newplaylist[23202:10b] Error = (null)
which makes it hard to troubleshoot the problem at this end without more info.

A couple things to try:

- Build the Appscript framework using the latest objc-appscript trunk, regenerate your glue using ASDictionary 0.11.0 and do a clean build of your project to check there isn't a version mismatch between them.

- Run iTunes with AEDebug enabled and email me the trace for 'make' event sent by AppleScript and the trace for the 'make' event sent by appscript. Also include your OS version, iTunes version and hardware type.
__________________
Learn AppleScript, 3rd edition, Sanderson & Rosenthal:
http://www.apress.com/9781430223610
hhas is offline   0 Reply With Quote

Reply
MacRumors Forums > Apple Systems and Services > Programming > Mac Programming

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Similar Threads
thread Thread Starter Forum Replies Last Post
iTunes - how to delete playlist from iPhone without deleting from iTunes RandomHavoc Mac Applications and Mac App Store 0 Dec 27, 2013 11:05 PM
iTunes 11 - can't create playlist/manage music manually on iPod???? sunrisemusic iPod touch 5 Oct 28, 2013 02:01 PM
Create a recently added music to iphone playlist? kristoffer4 iPhone 1 Sep 22, 2013 02:47 AM
iTunes syncing issues and iTunes Match playlist problems mully1121 Mac Applications and Mac App Store 3 Feb 7, 2013 05:54 PM

Forum Jump

All times are GMT -5. The time now is 06:02 PM.

Mac Rumors | Mac | iPhone | iPhone Game Reviews | iPhone Apps

Mobile Version | Fixed | Fluid | Fluid HD
Copyright 2002-2013, MacRumors.com, LLC