AppleScript: ¿Es posible verificar si Speech se está ejecutando actualmente?

1

Quiero recrear exactamente la función de método abreviado de teclado Texto a voz incorporado de macOS con AppleScript. Cuando digo "exactamente", quiero decir "exactamente".

La opción incorporada se puede encontrar en Preferencias del sistema → Dictado & Speech → Text to Speech:

Aquíestáladescripcióndeestafunción:

  

Establezcaunacombinacióndeteclasparahablareltextoseleccionado.

    

Useestacombinacióndeteclasparaescucharasucomputadorahablareltextoseleccionado.Silacomputadoraestáhablando,presionelasteclasparaparar.

Larazónporlaquequierovolveracrearestacaracterística(enlugardesimplementeusarla)esporquetieneerrores;Avecesfunciona,perootrasvecespresionoelatajodetecladoynopasanada.SilocodificomanualmenteenAppleScript,esperoqueelprocesoseamásconfiable.

ComprendocómoiniciarydetenerSpeechenAppleScript, como se explica aquí .

Pero me gustaría usar el mismo método abreviado de teclado y, por lo tanto, el mismo archivo .scpt, tanto para iniciar como para detener el habla, lo que refleja la funcionalidad del método abreviado de teclado de voz integrado.

Estoy utilizando FastScripts para ejecutar el archivo .scpt con un método abreviado de teclado.

Si el mismo archivo .scpt se encarga de iniciar y detener el habla, la secuencia de comandos requiere una instrucción if en la parte superior del AppleScript, o algo similar, para verificar de inmediato si se está hablando o no la voz, antes el guión puede proceder. No sé cómo implementar esta comprobación, o si es posible.

Pero, esto es lo que tengo:

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:

(Originalmente, quería que AppleScript hablara the clipboard , pero luego me di cuenta de que esto estaba sobrescribiendo el contenido original del portapapeles. Entonces, en realidad quiero que AppleScript exprese el contenido de la variable theSelectedText , como se demuestra en el código anterior.)

    
pregunta rubik's sphere 10.02.2017 - 22:43

1 respuesta

3

Es posible con el comando say en un shell, no con el comando AppleScript say .

Información para el comando say de AppleScript:

  • puede detener el discurso de decir comando desde el mismo script hasta que secuencia de comandos ejecutada, no después de que la secuencia de comandos salga.
  • Ejemplo:
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"

Este script usa el comando say en un shell para hablar el contenido del comando pbpaste (el portapapeles), y coloca el PID del comando say en una propiedad 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:

Es posible que el primer script no funcione, si el valor de la variable this_say_Pid no persiste en las ejecuciones, depende de cómo se ejecutará el script. En ese caso, debe escribir el PID en un archivo, así que use este 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.
    
respondido por el jackjr300 11.02.2017 - 22:12

Lea otras preguntas en las etiquetas