With this simple piece of applescript I can list the names of all songs within iTunes
tell application "iTunes"
set mainLibrary to library playlist 1
repeat with nexttrack in (get every track of mainLibrary)
try
name of nexttrack
end try
end repeat
end tell
I then run it as Java 7 code using ScriptEngine, however it is only obvious how to get the result of the script which in this case is the name of the last track only.
StringBuilder script =new StringBuilder();
script.append("tell application \"iTunes\"\n");
script.append("set mainLibrary to library playlist 1\n");
script.append("repeat with nexttrack in (get every track of mainLibrary)\n");
script.append("try\n");
script.append("name of nexttrack\n");
script.append("end try\n");
script.append("end repeat\n");
script.append("end tell\n");
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("AppleScript");
System.out.println(engine.eval(script.toString()));
How do can I capture the name of all tracks , i.e all output from the script. I assume I have to redirect standard out to a Reader, but cannot see how to do it.
Update:
I found this article
http://www.informit.com/articles/article.aspx?p=696621&seqNum=6
But updating by code to
StringBuilder script =new StringBuilder();
script.append("tell application \"iTunes\"\n");
script.append("set mainLibrary to library playlist 1\n");
script.append("repeat with nexttrack in (get every track of mainLibrary)\n");
script.append("try\n");
script.append("name of nexttrack\n");
script.append("end try\n");
script.append("end repeat\n");
script.append("end tell\n");
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("AppleScript");
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
StringWriter swError = new StringWriter();
PrintWriter pwError = new PrintWriter(swError);
engine.getContext().setWriter(pw);
engine.getContext().setErrorWriter(pwError);
System.out.println(engine.eval(script.toString()));
System.out.println("************* engine:"+sw.getBuffer());
System.out.println("************* engine error:"+swError.getBuffer());
Just outputs
See You on the Other Side (short)
************* engine:
************* engine error:
So you can clearly see the script works as the eval shows the name of the last track , but I'm getting nothing back from the redirected writers. Wondering does this actually work for applescript ?
Update 2 I wrote a test in Javascript and found setting the writers DID WORK for that so Im thinking that either
I'd like to think (2) was the problem, but I canot find any reference to outputting text in Applescript, echo is not a valid command and the print command does actually try to print to a printer rather than print to stdout as it would in Java or C.
Update 3 So I couldn't get this working, and now wondering if Applescript only ever writes the return value. I found an example of using stdout ( or so i thought) but I think that was just a naming convention, and in fact all it does is continually append data to a variable, and eventually return that.
So I did it get something working by using the following script stored in a file, and then used in Java with engine.eval(new java.io.FileReader("filename")
tell application "iTunes"
set output to ""
set mainLibrary to library playlist 1
repeat with nexttrack in (get every track of mainLibrary)
if (class of nexttrack is file track) then
try
set trackname to name of nexttrack
set loc to location of nexttrack
set locpath to POSIX path of loc
set persistid to persistent ID of nexttrack
set nextline to trackname & "::" & locpath & "::" & persistid
set output to output & "\n" & nextline
end try
end if
end repeat
copy output to stdout
end tell
but this doesnt actually resolve the original question, and the one problem with it is that if there is any error then I wont get anything back, whereas if it failed halfway through reading my iTuneslibrary and I was using stdout I would at least get half the data back.
To answer you original question, you get back whatever you "return" at the end of the script. If you do not have a specific "return" statement then by default you get back the result from the last action (which in your case is the last iteration of the repeat loop). Therefore if you need more than the last action returned you must create the return value in your script and then return it at the end.
but this doesnt actually resolve the original question, and the one problem with it is that if there is any error then I wont get anything back, whereas if it failed halfway through reading my iTuneslibrary and I was using stdout I would at least get half the data back. This is incorrect. The try block around your code will make applescript ignore the errors and continue, so anything you collect that doesn't error will still get returned.
Note that you have some errors in your latest applescript code. Especially this line makes no sense as applescript doesn't know what stdout is. So your comment is incorrect.
copy output to stdout
Here's what you need to do. As mentioned, you use "return" to return something. So I cleaned up your code. This will put each line of the repeat loop on a separate line of the output variable, which you return at the end of your code, which you can then parse once you bring it into your javascript code. Try this...
tell application "iTunes"
set output to ""
set mainLibrary to library playlist 1
repeat with nexttrack in (get every track of mainLibrary)
if (class of nexttrack is file track) then
try
set trackname to name of nexttrack
set loc to location of nexttrack
set locpath to POSIX path of loc
set persistid to (persistent ID of nexttrack) as text
set nextline to trackname & "::" & locpath & "::" & persistid & return
set output to output & nextline
end try
end if
end repeat
end tell
return output
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With