View Full Version : Adding files
mj_1903
08-05-2003, 05:47 AM
Recently at MacHack I was told about a new method in iTunes 4 of adding songs to iTunes on the fly. At this time I add songs using a Cocoa method which is highly ineffective.
Could someone please point me in the direction of adding files to iTunes, creating playlists and adding files to these playlists? (Of course when I talk about files I am indicating anything that iTunes can play).
Thanks in advance.
Doug Adams
08-05-2003, 07:46 AM
I don't understand -- What sort of "new method"? What is the "Cocoa" method?
eustacescrubb
08-05-2003, 11:01 AM
I guess the Cocoa method is like other methods, only more chocolaty-o-lishous? :D
Doug Adams
08-05-2003, 02:17 PM
only more chocolaty-o-lishous
Well it sounds super monster-killin' awesome and I believe I'd like to try that method.
mj_1903
08-05-2003, 03:53 PM
I am not actually sure it was a new method (it was a new method for me as Applescript is not my forte).
The Cocoa method is simply [[NSWorkspace sharedWorkspace] openFile:@"" withApplication:@""];
Of course that has the highly undesirable affect of the song starting to play...I just want to place all the songs one at a time in iTunes and if need be in playlists (lets just say that my iTunes database was corrupted by my experimentation and I want to use the iTunes xml library to programmatically reinsert all the songs. I simply would like to know how to do that.)
Thanks.
Doug Adams
08-05-2003, 04:18 PM
The Cocoa method is simply [[NSWorkspace sharedWorkspace] openFile:@"" withApplication:@""];
:eek: This is an area with which I am not personally acquainted.
However, if you mean you want to know how to add tracks to playlists and otherwise manage them with AppleScript, have a look at the info posted here (http://www.malcolmadams.com/itunes/itinfo/info02.shtml). Sorry to be -- what may turn out to be -- less than helpful.
mj_1903
08-05-2003, 06:30 PM
Ok, the make new playlist function is a good start.
There is the open command which will load a file into iTunes and then force it to play.
What I think I want is what acquisition does, that being creates a playlist and places songs in it without playing them (these are new songs that need to be added to the iTunes library.)
Do you know how to achieve this?
Mat
hi mat,
the link doug posted cover this with applescript if thats what you are interested in using..
have a look at specifically the "add" command which allows you the add a new track to a playlist without actually playing it, if the track is already known to itunes then the "duplicate" command is what you would use or else you will end up with duplicate library entries for the song..
the creation of the playlist is also covered by dougs' post...
Deeg
mj_1903
08-05-2003, 11:49 PM
Ah thanks for that...misinterpreted the script as being another method for making the application play songs (the same as my workspace method in cocoa above).
Well that basically covers everything. If I want to simply add to the main Library, do I just import to Library (obviously you can see my applescript is lacking...but I am always interested in learning).
Cheers.
if you use the add command for new tracks and add it to "library playlist 1" specifically it gets added to the main library playlist rather than a user created one.. its important to use the numerical reference rather than the name of the playlist because its possible for an enduser to rename their main library list but regardless of what they name it to, its always playlist number 1
mj_1903
08-06-2003, 12:06 AM
Ok, thanks very much for that, you have been a great help.
Mat
you're welcome.. post back if you have any new issues
mj_1903
08-06-2003, 01:38 AM
Well, seems I have not gotten it correct yet.
@"tell application \"iTunes\" to add {\"%@\"} to playlist \"library playlist 1\""
Where %@ is the path that I will use does not function. From my experience earlier I did not need an end tell statement to get it to work.
tell application "iTunes" add {"%@"} to playlist "library playlist 1"
Is the exact script...which I cannot get to function.
Mat
mj_1903
08-06-2003, 01:42 AM
Btw, this is the path I am using:
Volumes:Mathew Peterson's iPod:iPod_Control:Music:F11:Sweet Emotion.mp3
Which I know is correct.
Mat
Doug Adams
08-06-2003, 06:58 AM
Try this:
set myFile to "Volumes:Mathew Peterson's iPod:iPod_Control:Music:F11:Sweet Emotion.mp3" as alias
Also, regarding the "end tell" observation, you don't need an "end tell" if you are writing a single line statement, like:
tell application "iTunes" to add myFile to library playlist 1
A compound block would require the "end":
tell application "iTunes"
add myFile to library playlist 1
play library playlist 1
end tell
mj_1903
08-08-2003, 12:22 AM
Well, continuing this sad saga of not being able to get the applescript to run inside cocoa (even though I know I can run them and have done so before).
Right now the applescript looks basically like this:
set myFile to "PathName" as alias
tell application "iTunes" to add myFile to playlist "library playlist 1"
As far as I know this is correct and should run happily. Sadly...it doesn't. Have I made any mistakes which might be making it compile and run incorrectly? Unfortunately the Cocoa debugger for applescript doesn't give very good run time error descriptions basically just saying whether it executed or didn't.
Thanks again,
Mat
Doug Adams
08-08-2003, 08:14 AM
Try:
set myFile to "PathName" as alias
tell application "iTunes" to add myFile to library playlist 1
library playlist 1 is the main library. Since it's an object, it doesn't require quotes, like a string value would.
I thought you originally wanted to move it to a particular playlist. In that case:
set myFile to "some:PathName.mp3" as alias
tell application "iTunes"
set newFile to (add myFile)
if not (exists playlist named "My Playlist") then
set myP to (make new playlist with properties {name:"My Playlist"})
end if
duplicate newFile to myP
end tell
The add command always adds a track to the "main" library, library playlist 1, so you don't need to specify it.
mj_1903
08-08-2003, 09:53 AM
Ok, I can get my scripts to work as applescripts, just not inside Cocoa, so partly for my own reason and partly so we can all think about it I am documenting this process I am going through.
Just a quick explanation, before placing script text in the method that executes it we have to create a string.
NSString *scriptText = [NSString stringWithFormat:@"tell application \"iTunes\" \n\
playpause \n\
end tell"];
That script happily works and it pauses iTunes as expected.
NSString *scriptText = @"set myFile to \"la.m4a\" as alias \n\
return (myFile as string)";
This script refuses to return a string value associated with that file that works. It returns (null).
Just to check whether I am returning correctly.
NSString *scriptText = @"return \"stopped\"";
Returns stopped as expected.
NSString *scriptText = [NSString stringWithFormat:@"tell application \"iTunes\" \n\
set myP to (make new playlist with properties {name:\"My Playlist\"}) \n\
end tell"];
This works perfectly. A name playlist was created with that name in iTunes.
NSString *scriptText = @"set myFile to \"la.m4a\" as alias \n\
tell application \"iTunes\" to add myFile to library playlist 1";
Fails. Obviously doesn't help us at all in moving forward.
Also:
tell application \"iTunes\" to add {\"myFile\"} to library playlist 1
Does not help either.
tell application \"iTunes\" to add myFile
Neither does that.
NSString *scriptText = @"tell application \"iTunes\" \n\
add {\"la.m4a\"} \n\
end tell";
Nor does that.
Well as you can see, slightly frustrating....I am beginning to think its impossible to add a simple song to itunes.
Mat
mj_1903
08-08-2003, 12:05 PM
So I continue along trying and simply move to script editor to test my scripts.
Your script Doug obviously works.
set myFile to ":la.m4a" as alias
tell application "iTunes" to add myFile to library playlist 1
When I turn this into a string in Cocoa, it doesn't work.
NSString *scriptText = @"set myFile to \":la.m4a\" as alias \n\
tell application \"iTunes\" to add myFile to library playlist 1";
So I think it will not work.
Doug Adams
08-08-2003, 12:14 PM
Can't you use an AppleScript as a included file in your Cocoa project?
http://www.macdevcenter.com/pub/a/mac/2002/04/12/applescript.html
mj_1903
08-08-2003, 12:16 PM
Yup I can, but that means I can't change the paths dynamically, unless there is some way for Applescript to get info from the app.
ok... looking at your code and which bits work and which bits dont.. i think the issue is with the setting of the alias rather than the tell's to itunes.. and i dont know cocoa at all but the example of the code you have posted is missing the
[NSString stringWithFormat:@
code after the equals sign compared to those bits that do work..
what does that bit of code do ?
mj_1903
08-14-2003, 03:48 PM
Well, a few days ago I worked it out. It seems applescript in Cocoa handles paths differently than normal applescript, so paths that work fine in a script throw up real nice errors in Cocoa. It was quite annoying to track down.
For future reference, should I post the code that does work?
Also, in terms of your question deeg, if you are interested, stringWithFormat allows you to create a string with sections that are created dynamically whereas the other method I was doing, which was just creating a set string, allows none of those features.
Mat
Mat,
thanks for the info... i for one would be interested in seeing the code, although its not strictly applescript but its interesting none the less... you never know we might end up writing cocoa app's :cool:
mj_1903
08-14-2003, 07:22 PM
Ok, here is the code:
NSString *scriptText = [NSString stringWithFormat:@"set myFile to \"%@\" as alias \n\
tell application \"iTunes\" to add myFile to library playlist 1", [NSString stringWithFormat:@"%@%@", [main getName], [main oldPathWithIdentifier:[[addObjects objectAtIndex:i] longValue]]]];
NSAppleScript *play= [[NSAppleScript alloc] initWithSource:scriptText];
[play executeAndReturnError:nil];
[play release];
Basically to make it easier to understand...I am creating a string on the fly which will be turned into our applescript. I then instantiate an applescript class with that string, execute it and then release the memory.
As to creating the string, I am calling the iPodName, the path of the file on the iPod from another function from a unique identifier located in an array.
Its complicated...but makes sense when running. If you have questions, fire away.
Mat
whats
[NSString stringWithFormat:@"%@%@", [main getName], [main oldPathWithIdentifier:[[addObjects objectAtIndex:i] longValue]]]];
doing ?
mj_1903
08-14-2003, 07:41 PM
Originally posted by deeg
[NSString stringWithFormat:@"%@%@", [main getName], [main oldPathWithIdentifier:[[addObjects objectAtIndex:i] longValue]]]];
Ok, here's a quick explanation.
@"here is something" is a standard string.
[NSString stringWithFormat:@""] will return a string with whatever is better the quotes. It also has a nice method whereby it will replace %@ in a string with whatever data is listed afterwards. For instance:
[NSString stringWithFormat:@"The date is", [someMethod toGetDate]];
Will return a string @"The date is 11th June 1999"
So, with that method above in the main code, we have a string being created with the name of the iPod first and then a call to my method oldPathWithIdentifier: which will return a path in iPod style (iPodName:TheRest:OfThe:Path) for the identifier which is stored in an array. The identifier is the standard identifier that iTunes uses (8 characters from memory).
I hope that explains everything for you.
Mat
so i take it that getname and oldpathwithidentifier are "subroutines" you have in the code ? does the "main" indicate the location of the those subroutines and the
:[[addObjects objectAtIndex:i] are variables which are used by the oldpathwithidentifier routine ? how is the "i" in the objactatindex parameter iterated or does it happen automatically ?
also how is the built path associated with the variable "%@" in the applescript ..is this specified by "%@%@" in the stringwithformat parameter
mj_1903
08-15-2003, 05:18 PM
getName and oldPathWithIdentifier are methods in another class which is specified by main. addObjects is an array of identifiers while objectAtIndex:i is a call to the array to get the identifier for that loop. i is being implemented elsewhere...this routine is called the number of times corresponding to the number of songs on the iPod.
stringWithFormat will place any data into a %@ statement in the corresponding string. So for instance, in the scripttext, the %@ is the location of the file created by the stringWithFormat method on the inside....so we create the location using two %@%@ and we then add the location to the string we will compile again with the %@ method.
well it looks more interesting than applescript and easier than perl :).. care to recommend any books ?
mj_1903
08-15-2003, 07:02 PM
Yeah, I programmed Perl 4.0 back in the days, was a good language, but Cocoa truly is more powerful.
So as for books...I highly recommend to start Aaron Hillegass's book, Cocoa Programming for Mac OS X (http://www.amazon.com/exec/obidos/tg/detail/-/0201726831/qid=1060985094/sr=8-1/ref=sr_8_1/104-4519486-0654328?v=glance&s=books&n=507846) for starters. Just a quick bit of advice...if you are struggling, keep going. The initial leraning curve is quite painful but once you are over it, there is no application you cannot write.
It took me about 9 months to learn it to a level that anything I could think I could produce and now I happily write shareware Cocoa full time.
As for good sites, check out cocoadevcentral.com and cocoadev.com for more advice and assistance (I frequent the latter quite regularly).
Hope this helps,
Mat
mj_1903
08-28-2003, 07:40 PM
Well I'm back again. I have been noticing with Applescript that I can create an object in an app...for instance:
In mail I can create a new message as an object and do things to it.
I can create a playlist in iTunes and do thing with it.
Can I create a tune as we have been doing and do things to it? I know how to access the playling tune as an object and do whatever, but if I have just added an item, or am adding an item, can I have it as an object?
Thanks,
Mat
it depends on what you want to do... you can change somethings but not others... if you have a look at a tracks properties in the itunes applescript dictionary (in the editor, file>open dictionary) you can see things you can access, those properties marked as "ro" can be read but not changed..e.g the played count...
You also would need to take into account some of the preferences the user has set.. for example if they have enabled the option for itunes to organise the music folder and you change the artist info then the path to the track is going to change also...
mj_1903
08-29-2003, 04:08 AM
Yup, I know that much. I know that ratings can be changed on the fly (I have an app already doing that) but its only affecting the currently playing song. What I want to do is change the rating as soon as I add the song to the playlist (using the methods before or using new methods.
Thanks.
Mat
ok... do you get any info back from your add request.. such as the track database id .. had a chance to play at work... this is ok for
applescript... if you select the music file in the finder and then...
tell app "finder"
set theselectedtrack to selection as alias
end tell
tell app "iTunes"
set x to (add theselectedtrack)
set rating of x to "65"
end tell
the add line returns the the track id as its result, you can then use the result to identify the track when changing its rating...you dont need the finder tell block since you are setting the alias by another method, its just included to demo the principle
mj_1903
09-09-2003, 06:42 PM
Thanks mate, the code works fantastically as usual.
Have a good one,
Mat