2013-08-12 25 views
5

Con questo semplice pezzo di AppleScript posso elencare i nomi di tutti i brani in iTunesCome si fa a ottenere output di JavaScript in Java utilizzando ScriptEngine

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 

ho quindi eseguirlo come codice Java 7 utilizzando ScriptEngine, tuttavia è ovvio come ottenere il risultato della sceneggiatura che in questo caso è solo il nome dell'ultima traccia.

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. 

Aggiornamento:

I found this article 

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

Ma l'aggiornamento per codice a

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

uscite Proprio

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

Quindi è possibile vedere chiaramente che la sceneggiatura funziona mentre la valutazione mostra il nome dell'ultima traccia, ma non ricevo nulla dagli scrittori reindirizzati. Ti chiedi cosa funzioni effettivamente per il applescript?

Update 2 ho scritto un test in Javascript e trovato l'impostazione degli scrittori ha funzionato per che così Im pensando che sia

  1. C'è qualcosa di rotto nel motore di script per Applescript (Im usando una recente costruzione 1.7.0_40-ea-B29) della versione di accesso iniziale di Java 7 su OSX)
  2. mio Applescript è sbagliato, vale a dire non solo nome NextTrack dovrei fare qualcosa di simile eco nome NextTrack alla realtà fare i andare allo stdout.

Mi piacerebbe pensare (2) era il problema, ma io canot trovare alcun riferimento al testo di output in Applescript, echo non è un comando valido e il comando distampa realtà non provare a stampare a una stampante invece di stampare su stdout come si farebbe in Java o C.

Update 3 Quindi non ho potuto ottenere questo lavoro, e ora si domandano se Applescript scrive sempre e solo il valore di ritorno. Ho trovato un esempio di utilizzo di stdout (o almeno così pensavo), ma penso che fosse solo una convenzione di denominazione, e infatti tutto ciò che fa è continuamente aggiungere dati a una variabile e alla fine restituirlo.

Così ho fatto ottenere qualcosa di lavoro utilizzando il seguente script memorizzato in un file, e quindi utilizzato in Java con engine.eval (nuova 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 

ma questo in realtà non risolve la domanda originale, e l'unico problema è che se c'è qualche errore allora non otterrò nulla indietro, mentre se fallisse a metà lettura del mio iTuneslibrary e stavo usando lo stdout, almeno me ne andrei i dati tornano.

risposta

2

Per rispondere alla domanda originale, si ottiene tutto ciò che si "torna" alla fine della sceneggiatura. Se non si dispone di una specifica istruzione "return", per impostazione predefinita si ottiene il risultato dell'ultima azione (che nel tuo caso è l'ultima iterazione del ciclo di ripetizione). Pertanto, se è necessario più dell'ultima azione restituita, è necessario creare il valore restituito nello script e quindi restituirlo alla fine.

ma questo doesnt realmente risolvere la domanda originale, e quello problema con esso è che se c'è qualche errore di allora io non otterrete nulla indietro, mentre se non è riuscito a metà strada attraverso la lettura del mio iTuneslibrary ed ero usando stdout vorrei almeno recuperare metà dei dati. Questo non è corretto. Il blocco try attorno al tuo codice farà sì che applescript ignori gli errori e continui, quindi tutto ciò che raccogli che non ha errori verrà comunque restituito.

Si noti che si hanno alcuni errori nell'ultimo codice di codice AppleScript. Soprattutto questa linea non ha senso in quanto il applescript non sa cosa sia lo stdout. Quindi il tuo commento non è corretto.

copy output to stdout 

Ecco cosa è necessario fare. Come accennato, si usa "return" per restituire qualcosa. Quindi ho ripulito il tuo codice. In questo modo ogni riga del ciclo di ripetizione viene posizionata su una riga separata della variabile di uscita, che viene restituita alla fine del codice, che è possibile analizzare dopo averlo inserito nel codice javascript. Prova questo ...

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 
+0

Grazie capisco la tua risposta. Ma quello che non capisco è se il applescript può essere usato per scrivere l'output su stdout mentre viene eseguito, o se non può mai scrivere su stdout se non scrivendo l'ultima istruzione value/return al termine dello script. Questo è importnat nel mio caso come una lib di iTunes può contenere 50.000 canzoni e quindi l'output dovrebbe contenere 50.000 posizioni e nomi di brani. –

+0

No, non è possibile scrivere su stdout mentre lo script sta procedendo. Puoi scrivere una sola volta alla fine dello script come spiegato. Tuttavia, è possibile scrivere un file riga per riga nel ciclo di ripetizione e quindi leggere il file dal codice javascript dopo che il applescript è stato completato ... se necessario. – regulus6633

+0

In realtà è da codice java, è un peccato speravo di poter evitare la creazione di file temporanei, sembra davvero strano il manuale per OSX sembra implicare che l'output viene scritto quando si discute -e l'opzione –