AppleScript: è possibile controllare se Speech è attualmente in esecuzione?

1

Voglio ricreare esattamente la funzione di scorciatoia da tastiera di sintesi vocale di MacOS con AppleScript. Quando dico "esattamente", intendo "esattamente".

L'opzione built-in può essere trovata in Preferenze di Sistema → Dettatura e amp; Voce → Sintesi vocale:

Eccoladescrizionediquestafunzione:

Setakeycombinationtospeakselectedtext.

Usethiskeycombinationtohearyourcomputerspeakselectedtext.Ifthecomputerisspeaking,pressthekeystostop.

Laragionepercuivoglioricrearequestafunzione(invecediusarlasemplicemente)èperchéèbacata;avoltefunziona,ma,altrevolte,premolascorciatoiadatastieraenonsuccedenulla.SelocodificomanualmenteinAppleScript,sperocheilprocessosiapiùaffidabile.

CapiscocomeavviareeinterrompereSpeechinAppleScript, come spiegato qui .

Ma mi piacerebbe usare la stessa scorciatoia da tastiera, e quindi lo stesso file .scpt, per avviare e fermare il parlato, rispecchiando la funzionalità della scorciatoia da tastiera vocale incorporata.

Sto usando FastScripts per eseguire il file .scpt con una scorciatoia da tastiera.

Se lo stesso file .scpt è responsabile sia dell'avvio che dell'arresto del parlato, lo script richiede un'istruzione if nella parte superiore di AppleScript, o qualcosa di simile, per controllare immediatamente se il parlato è attualmente in corso o meno, prima lo script può procedere. Non so come implementare questo controllo, o se è addirittura possibile.

Ma ecco cosa ho:

if <This is where I need your help, Ask Different> then
    say "" with stopping current speech
    error number -128 -- quits the AppleScript
end if



-- Back up original clipboard contents:
set savedClipboard to my fetchStorableClipboard()

-- Copy selected text to clipboard:
tell application "System Events" to keystroke "c" using {command down}
delay 1 -- Without this, the clipboard may have stale data.

set theSelectedText to the clipboard

-- Restore original clipboard:
my putOnClipboard:savedClipboard

-- Speak the selected text:
say theSelectedText waiting until completion no





use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"


on fetchStorableClipboard()
    set aMutableArray to current application's NSMutableArray's array() -- used to store contents
    -- get the pasteboard and then its pasteboard items
    set thePasteboard to current application's NSPasteboard's generalPasteboard()
    -- loop through pasteboard items
    repeat with anItem in thePasteboard's pasteboardItems()
        -- make a new pasteboard item to store existing item's stuff
        set newPBItem to current application's NSPasteboardItem's alloc()'s init()
        -- get the types of data stored on the pasteboard item
        set theTypes to anItem's types()
        -- for each type, get the corresponding data and store it all in the new pasteboard item
        repeat with aType in theTypes
            set theData to (anItem's dataForType:aType)'s mutableCopy()
            if theData is not missing value then
                (newPBItem's setData:theData forType:aType)
            end if
        end repeat
        -- add new pasteboard item to array
        (aMutableArray's addObject:newPBItem)
    end repeat
    return aMutableArray
end fetchStorableClipboard


on putOnClipboard:theArray
    -- get pasteboard
    set thePasteboard to current application's NSPasteboard's generalPasteboard()
    -- clear it, then write new contents
    thePasteboard's clearContents()
    thePasteboard's writeObjects:theArray
end putOnClipboard:

(Originariamente, volevo che l'AppleScript parlasse the clipboard , ma poi mi sono reso conto che questo stava sovrascrivendo il contenuto degli appunti originali. Quindi, in realtà, voglio che l'AppleScript parli il contenuto della variabile theSelectedText , come dimostrato nel codice precedente.)

    
posta rubik's sphere 10.02.2017 - 22:43
fonte

1 risposta

3

È possibile con il comando say in una shell, non con il comando say di AppleScript.

Informazioni per il comando AppleScript:

  • puoi interrompere il discorso di dire comando dallo stesso script fino al lo script esegue, non dopo l'uscita dallo script.
  • Esempio:
say "I want to recreate macOS's built-in Text To Speech" waiting until completion no
delay 0.5
say "" with stopping current speech -- this stop the first say command of this script
delay 1
say "Hello"

Questo script usa il comando say in una shell per pronunciare il contenuto del comando pbpaste (gli appunti) e mette il PID del comando say su una proprietà persistente:

use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"
property this_say_Pid : missing value -- the persistent property

if this_say_Pid is not missing value then -- check the pid of all 'say' commands, if exists then quit the unix process
    set allSayPid to {}
    try
        set allSayPid to words of (do shell script "pgrep -x 'say'")
    end try
    if this_say_Pid is in allSayPid then -- the PID = an item in the list
        do shell script "/bin/kill " & this_say_Pid -- quit this process to stop the speech
        error number -128 -- quits the AppleScript
    end if
end if

-- Back up original clipboard contents:
set savedClipboard to my fetchStorableClipboard()

-- Copy selected text to clipboard:
tell application "System Events" to keystroke "c" using {command down}
delay 1 -- Without this, the clipboard may have stale data.

-- Speak the clipboard:
--  pbpaste = the contents of the clipboard , this run the commands without waiting, and get the PID of the 'say' command 
set this_say_Pid to do shell script "LANG=en_US.UTF-8 pbpaste -Prefer txt | say > /dev/null 2>&1 & echo $!"

-- Restore original clipboard:
my putOnClipboard:savedClipboard

on fetchStorableClipboard()
    set aMutableArray to current application's NSMutableArray's array() -- used to store contents
    -- get the pasteboard and then its pasteboard items
    set thePasteboard to current application's NSPasteboard's generalPasteboard()
    -- loop through pasteboard items
    repeat with anItem in thePasteboard's pasteboardItems()
        -- make a new pasteboard item to store existing item's stuff
        set newPBItem to current application's NSPasteboardItem's alloc()'s init()
        -- get the types of data stored on the pasteboard item
        set theTypes to anItem's types()
        -- for each type, get the corresponding data and store it all in the new pasteboard item
        repeat with aType in theTypes
            set theData to (anItem's dataForType:aType)'s mutableCopy()
            if theData is not missing value then
                (newPBItem's setData:theData forType:aType)
            end if
        end repeat
        -- add new pasteboard item to array
        (aMutableArray's addObject:newPBItem)
    end repeat
    return aMutableArray
end fetchStorableClipboard


on putOnClipboard:theArray
    -- get pasteboard
    set thePasteboard to current application's NSPasteboard's generalPasteboard()
    -- clear it, then write new contents
    thePasteboard's clearContents()
    thePasteboard's writeObjects:theArray
end putOnClipboard:

È possibile che il primo script non funzioni, se il valore della variabile this_say_Pid non persiste tra le esecuzioni, dipende da come verrà avviato lo script. In tal caso, è necessario scrivere il PID in un file, quindi utilizzare questo script:

use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"

set tFile to POSIX path of (path to temporary items as text) & "_the_Pid_of_say_command_of_this_script.txt" -- the temp file
set this_say_Pid to missing value
try
    set this_say_Pid to paragraph 1 of (read tFile) -- get the pid of the last speech
end try

if this_say_Pid is not in {"", missing value} then -- check the pid of all 'say' commands, if exists then quit the unix process
    set allSayPid to {}
    try
        set allSayPid to words of (do shell script "pgrep -x 'say'")
    end try
    if this_say_Pid is in allSayPid then -- the PID = an item in the list
        do shell script "/bin/kill " & this_say_Pid -- quit this process to stop the speech
        error number -128 -- quits the AppleScript
    end if
end if

-- Back up original clipboard contents:
set savedClipboard to my fetchStorableClipboard()

-- Copy selected text to clipboard:
tell application "System Events" to keystroke "c" using {command down}
delay 1 -- Without this, the clipboard may have stale data.

-- Speak the clipboard:

--  pbpaste = the contents of the clipboard , this run the commands without waiting, and it write the PID of the 'say' command to the temp file
do shell script "LANG=en_US.UTF-8 pbpaste -Prefer txt | say > /dev/null 2>&1 & echo $! > " & quoted form of tFile

-- Restore original clipboard:
my putOnClipboard:savedClipboard

-- *** Important *** : This script is not complete,  you must add the 'putOnClipboard:' handler and the 'fetchStorableClipboard()' handler to this script.
    
risposta data 11.02.2017 - 22:12
fonte

Leggi altre domande sui tag