5

有了这个简单的applescript,我可以列出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

然后我使用 ScriptEngine 将它作为 Java 7 代码运行,但是如何获得脚本的结果很明显,在这种情况下,它只是最后一首曲目的名称。

    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.

更新:

I found this article 

http://www.informit.com/articles/article.aspx?p=696621&seqNum=6

但是通过代码更新为

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());

只是输出

See You on the Other Side (short)
************* engine:
************* engine error:

因此,您可以清楚地看到脚本的工作原理,因为 eval 显示了最后一首曲目的名称,但我没有从重定向的作者那里得到任何回报。想知道这真的适用于 applescript 吗?

更新 2 我用 Javascript 编写了一个测试,发现设置作者确实有效,所以我认为要么

  1. 在 OSX 上 Java 7 的早期访问版本的 Applescript 脚本引擎(我使用最近的版本 1.7.0_40-ea-b29)有一些问题)
  2. 我的 Applescript 是错误的,即,而不仅仅是nexttrack 的名称,我应该做一些类似nexttrack 的 echo name 的事情,以使其真正进入标准输出。

我想(2)是问题所在,但我找不到任何关于在 Applescript 中输出文本的引用,echo不是有效命令,并且print命令实际上确实尝试打印到打印机而不是打印到 stdout,因为它会在Java或C中。

更新 3 所以我无法让它工作,现在想知道 Applescript 是否只写返回值。我找到了一个使用 stdout 的示例(或者我认为),但我认为这只是一个命名约定,实际上它所做的只是不断地将数据附加到一个变量,并最终返回它。

所以我通过使用存储在文件中的以下脚本,然后在 Java 中使用 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

但这实际上并没有解决最初的问题,它的一个问题是,如果有任何错误,那么我不会得到任何回报,而如果它在读取我的 iTuneslibrary 的过程中失败并且我正在使用 stdout,我至少会得到一半数据回来。

4

1 回答 1

2

为了回答您最初的问题,您可以在脚本结尾处“返回”任何内容。如果您没有特定的“return”语句,则默认情况下您会从最后一个操作(在您的情况下是重复循环的最后一次迭代)中返回结果。因此,如果您需要的不仅仅是返回的最后一个操作,您必须在脚本中创建返回值,然后在最后返回它。

但这实际上并没有解决最初的问题,它的一个问题是,如果有任何错误,那么我不会得到任何回报,而如果它在读取我的 iTunes 库的过程中失败并且我正在使用 stdout,我至少会得到一半数据回来。这是不正确的。代码周围的 try 块将使 applescript 忽略错误并继续,因此您收集的任何没有错误的内容仍将返回。

请注意,您最新的 applescript 代码中有一些错误。尤其是这一行毫无意义,因为 applescript 不知道 stdout 是什么。所以你的评论是不正确的。

copy output to stdout

这是你需要做的。如前所述,您使用“return”返回某些内容。所以我清理了你的代码。这会将重复循环的每一行放在输出变量的单独行上,您在代码末尾返回,然后您可以在将其带入您的 JavaScript 代码后对其进行解析。尝试这个...

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
于 2013-08-12T14:40:01.277 回答