def drop_keep_clipboard(nnavi500, capitalization, spacing): # Maintain standard spark functionality for non-strings if capitalization == 0 and spacing == 0 and nnavi500 == 1: Key("c-v").execute() return # Get clipboard text if nnavi500 > 1: key = str(nnavi500) if key in _CLIP: text = _CLIP[key] else: get_current_engine().speak("slot empty") text = None else: text = Clipboard.get_system_text() # Format if necessary, and paste if text is not None: cb = Clipboard(from_system=True) if capitalization != 0 or spacing != 0: text = textformat.TextFormat.formatted_text( capitalization, spacing, text) Clipboard.set_system_text(text) time.sleep(settings.settings([u'miscellaneous', u'keypress_wait'])/1000.) Key("c-v").execute() time.sleep(settings.settings([u'miscellaneous', u'keypress_wait'])/1000.) # Restore the clipboard contents. cb.copy_to_system()
def _bring_add(self, launch_type, key): # Add current program or highlighted text to bring me if launch_type == "program": path = utilities.get_active_window_path() if not path: # dragonfly.get_current_engine().speak("program not detected") printer.out("Program path for bring me not found ") elif launch_type == 'file': files = utilities.get_selected_files(folders=False) path = files[0] if files else None # or allow adding multiple files elif launch_type == 'folder': files = utilities.get_selected_files(folders=True) path = files[ 0] if files else None # or allow adding multiple folders else: Key("a-d/5").execute() fail, path = context.read_selected_without_altering_clipboard() if fail == 2: # FIXME: A better solution would be to specify a number of retries and the time interval. time.sleep(0.1) _, path = context.read_selected_without_altering_clipboard() if not path: printer.out("Selection for bring me not found ") Key("escape").execute() if not path: import dragonfly message = 'Cannot add %s as %s to bring me: cannot get path' % ( launch_type, key) printer.out(message) dragonfly.get_current_engine().speak(message) return config_copy = self._config.get_copy() config_copy[launch_type][str(key)] = path self._refresh(config_copy)
def text_punc_dict(): # Insurers comma is recognized consistently with DNS/Natlink and # if/else statement workaround engines that do not expect punctuation symbol as a command if hasattr(dragonfly.get_current_engine(), "name"): if (dragonfly.get_current_engine().name == 'natlink'): comma = "(comma | ,)" else: comma = "comma" else: comma = "comma" _id = _inv_dtpb() return { "ace": " ", "clamor": "!", "chocky": "\"", "hash tag": "#", "Dolly": "$", "modulo": "%", "ampersand": "&", "apostrophe | single quote | chicky": "'", "left " + _id["()"]: "(", "right " + _id["()"]: ")", "starling": "*", "plus": "+", comma: ",", "minus": "-", "period | dot": ".", "slash": "/", "deckle": ":", "semper": ";", "[is] less than | left " + _id["<>"]: "<", "[is] less [than] [or] equal [to]": "<=", "equals": "=", "[is] equal to": "==", "[is] greater than | right " + _id["<>"]: ">", "[is] greater [than] [or] equal [to]": ">=", "questo": "?", "(atty | at symbol)": "@", "left " + _id["[]"]: "[", "backslash": "\\", "right " + _id["[]"]: "]", "carrot": "^", "underscore": "_", "ticky | ((left | right) " + _id["``"] + " )": "`", "left " + _id["{}"]: "{", "pipe (sim | symbol)": "|", "right " + _id["{}"]: "}", "tilde": "~", }
def _engine_timers(self): # Timer to synchronize natlink.getMicState/SetRecognitionMode with mode_state in case of changed by end-user via DNS GUI. if self.engine == 'natlink' and self.sync_timer is None: sync_timer = get_current_engine().create_timer( callback=self._engine_modes_manager._sync_mode, interval=1) sync_timer.start() # A timer to change microphone state to "sleep" after X amount of seconds after last successful recognition if self.sleep_timer is None and settings.SETTINGS["engine"][ "mic_sleep_timer_on"] == True: self.sleep_timer = get_current_engine().create_timer( callback=self._sleep_timer, interval=int(settings.SETTINGS["engine"]["mic_sleep_timer"])) self.sleep_timer.start() register_recognition_callback(function=self._reset_sleep_timer)
def __init__(self): self._baseimport = builtins.__import__ builtins.__import__ = self._import self._parent = None # Dictionary where key is the module name (e.g. # 'casterplugin.dictation') and value contains the entries # `module` (module object) and `dependencies` # (list of modules which the module depends on) self._modules = {} self.watched_plugin_modules = {} get_current_engine().create_timer(self.reload, 10)
def reboot(): # TODO: Save engine arguments elsewhere and retrieves for reboot. Allows for user-defined arguments. popen_parameters = [] engine = get_current_engine() if engine.name == 'kaldi': engine.disconnect() subprocess.Popen([sys.executable, '-m', 'dragonfly', 'load', '_*.py', '--engine', 'kaldi', '--no-recobs-messages']) if engine.name == 'sapi5inproc': engine.disconnect() subprocess.Popen([sys.executable, '-m', 'dragonfly', 'load', '--engine', 'sapi5inproc', '_*.py', '--no-recobs-messages']) if engine.name in ["sapi5shared", "sapi5"]: popen_parameters.append(settings.SETTINGS["paths"]["REBOOT_PATH_WSR"]) popen_parameters.append(settings.SETTINGS["paths"]["WSR_PATH"]) printer.out(popen_parameters) subprocess.Popen(popen_parameters) if engine.name == 'natlink': import natlinkstatus # pylint: disable=import-error status = natlinkstatus.NatlinkStatus() if status.NatlinkIsEnabled() == 1: # Natlink in-process popen_parameters.append(settings.SETTINGS["paths"]["REBOOT_PATH"]) popen_parameters.append(settings.SETTINGS["paths"]["ENGINE_PATH"]) username = status.getUserName() popen_parameters.append(username) printer.out(popen_parameters) subprocess.Popen(popen_parameters) else: # Natlink out-of-process engine.disconnect() subprocess.Popen([sys.executable, '-m', 'dragonfly', 'load', '--engine', 'natlink', '_*.py', '--no-recobs-messages'])
def clear_log(): # Function to clear status window. # Natlink status window not used an out-of-process mode. # TODO: window_exists utilized when engine launched through Dragonfly CLI via bat in future try: if WIN32: clearcmd = "cls" # Windows OS else: clearcmd = "clear" # Linux if get_current_engine().name == 'natlink': import natlinkstatus # pylint: disable=import-error status = natlinkstatus.NatlinkStatus() if status.NatlinkIsEnabled() == 1: import win32gui # pylint: disable=import-error handle = get_window_by_title( "Messages from Python Macros") or get_window_by_title( "Messages from Natlink") rt_handle = win32gui.FindWindowEx(handle, None, "RICHEDIT", None) win32gui.SetWindowText(rt_handle, "") else: if window_exists(windowname="Caster: Status Window"): os.system(clearcmd) else: if window_exists(windowname="Caster: Status Window"): os.system(clearcmd) else: printer.out("clear_log: Not implemented with GUI") except Exception as e: printer.out(e)
def __init__(self): from castervoice.lib import control self._engine_modes_manager = control.nexus().engine_modes_manager self.engine = get_current_engine().name self.sync_timer = None self.sleep_timer = None if self.engine != 'natlink': # Other engines besides natlink needs a default mic state for sleep_timer self._engine_modes_manager.mic_state = "on" if self.engine != "text": self._engine_timers() self._set_default_mic_mode() self._set_engine_default_mode()
def initialize(cls): # Remove "normal" and "off" from 'states' for non-DNS based engines. if engine != 'natlink': cls.engine_modes.pop("normal", 0) cls.mic_modes.pop("off", 7) #if self.engine == 'natlink': # Sets 1st index key ("normal" or "command") depending on engine type as default mode cls.engine_state = cls.previous_engine_state = next( iter(cls.engine_modes.keys())) # Timer to synchronize natlink.getMicState/SetRecognitionMode with mode_state in case of changed by end-user via DNS GUI. if engine == 'natlink' and cls.timer_callback is None: cls.timer_callback = get_current_engine().create_timer( callback=cls._sync_mode, interval=1) cls.timer_callback.start()
def bootstrap_start_server_proxy(self): """ There are two parts to getting Sikuli running: the server and the server proxy. The server is an independent process, which needs to already be running before the server proxy is started. This method attempts to start the server proxy and then if that fails, it starts the server and sets a timer to retry the server proxy. """ try: # if the server is already running, this should go off without a hitch self._start_server_proxy() except Exception: self._start_server() five_seconds = 5 self._timer = get_current_engine().create_timer( self._retry_server_proxy, five_seconds)
def show_window(): title = None engine = get_current_engine().name if engine == 'natlink': import natlinkstatus # pylint: disable=import-error status = natlinkstatus.NatlinkStatus() if status.NatlinkIsEnabled() == 1: if six.PY2: title = "Messages from Python Macros" else: title = "Messages from Natlink" else: title = "Caster: Status Window" if engine != 'natlink': title = "Caster: Status Window" windows = Window.get_matching_windows(title=title) if windows: windows[0].set_foreground()
class EngineConfigLate: """ Initializes engine specific customizations after Nexus has initialized. Grammars are loaded into engine. """ from castervoice.lib import settings from dragonfly import get_current_engine engine = get_current_engine().name def __init__(self): from castervoice.lib.ctrl.mgr.engine_manager import EngineModesManager self.EngineModesManager = EngineModesManager.initialize() if self.engine != "text": self.set_default_mic_mode() self.set_engine_default_mode() def set_default_mic_mode(self): """ Sets the microphone state on Caster startup. """ # Only DNS supports mic_state 'off'. Substituts `sleep` mode on other engines" if self.settings.SETTINGS["engine"][ "default_mic"]: # Default is `False` default_mic_state = self.settings.SETTINGS["engine"][ "mic_mode"] # Default is `on` if self.engine != "natlink" and default_mic_state == "off": default_mic_state = "sleep" self.EngineModesManager.set_mic_mode(default_mic_state) def set_engine_default_mode(self): """ Sets the engine mode on Caster startup. """ # Only DNS supports 'normal'. Substituts `command` mode on other engines" if self.settings.SETTINGS["engine"][ "default_engine_mode"]: # Default is `False` default_mode = self.settings.SETTINGS["engine"][ "engine_mode"] # Default is `normal` if self.engine != "natlink" and default_mode == "normal": default_mode = "command" self.EngineModesManager.set_engine_mode(mode=default_mode, state=True)
def __init__(self, ExclusiveManager): self.engine_modes = { "normal": 0, "command": 2, "dictation": 1, "numbers": 3, "spell": 4 } self.mic_modes = {"on": 5, "sleeping": 6, "off": 7} self.engine_state = None self.previous_engine_state = None self.mic_state = None self.engine = get_current_engine().name self._exclusive_manager = ExclusiveManager # Remove "normal" and "off" from 'states' for non-DNS based engines. if self.engine != 'natlink': self.engine_modes.pop("normal", 0) self.mic_modes.pop("off", 7) # Sets 1st index key ("normal" or "command") depending on engine type as default mode self.engine_state = self.previous_engine_state = next( iter(self.engine_modes.keys()))
def begin(self): '''here pass along a closure to the timer multiplexer''' execute_context_levels = self.executeCL context_level = self.forward[0] repetitions = self.repetitions count = {"value": 0} execute = self.execute def closure(): do_terminate = execute_context_levels(context_level) if do_terminate: execute(do_terminate) elif repetitions != 0: # if not run forever count["value"] += 1 if count["value"] == repetitions: execute(False) self.closure = closure self.timer = get_current_engine().create_timer(self.closure, self.time_in_seconds) self.closure()
def _create_asynchronous(n): last_utterance_index = 2 if len(_history) == 0: return # ContextStack adds the word to history before executing it for WSR if get_current_engine().name in [ "sapi5shared", "sapi5", "sapi5inproc" ]: if len(_history) == 1: return # Calculatees last utterance from recognition history and creates list of str for Dragonfly Playback utterance = list( map(str, _history[len(_history) - last_utterance_index])) if utterance[0] == "again": return forward = [L(S(["cancel"], lambda: Again._repeat(utterance)))] AsynchronousAction(forward, rdescript="Repeat Last Action", time_in_seconds=0.2, repetitions=int(n), blocking=False).execute()
def _create_asynchronous(n): if len(_history) == 0: return last_utterance_index = 2 if get_current_engine().name in [ "sapi5shared", "sapi5", "sapi5inproc" ]: # ContextStack adds the word to history before executing it if len(_history) == 1: return last_utterance_index = 2 utterance = [ str(x) for x in " ".join(_history[len(_history) - last_utterance_index]).split() ] if utterance[0] == "again": return forward = [L(S(["cancel"], lambda: Again._repeat(utterance)))] AsynchronousAction(forward, rdescript="Repeat Last Action", time_in_seconds=0.2, repetitions=int(n), blocking=False).execute()
def text_punc_dict(): # Insurers comma is recognized consistently with DNS/Natlink and # if/else statement workaround engines that do not expect punctuation symbol as a command if (dragonfly.get_current_engine().name == 'natlink'): comma = "(comma | ,)" else: comma = "comma" _id = _inv_dtpb() return { "ace": " ", "clamor": "!", "chocky": "\"", "hash tag": "#", "Dolly": "$", "modulo": "%", "ampersand": "&", "apostrophe | single quote | chicky": "'", "left " + _id["()"]: "(", "right " + _id["()"]: ")", # Additional Parens keywords "lefty": "(", "righty": ")", "starling": "*", "plus": "+", comma: ",", "minus": "-", # Adding another hyphen word. Need to check for some reason dash is # already responding is a '-'. Not sure if that's a built-in # Dragon feature. "dash": "-", "period | dot": ".", "slash": "/", "deckle": ":", "semper": ";", # Less than / greater than "less": "<", "great": ">", # "[is] less than | left " + _id["<>"]: "<", "left " + _id["<>"]: "<", "[is] less [than] [or] equal [to]": "<=", "equals sign": "=", "[is] equal to": "==", # "[is] greater than | right " + _id["<>"]: ">", "right " + _id["<>"]: ">", "[is] greater [than] [or] equal [to]": ">=", "questo": "?", "(atty | at symbol)": "@", "left " + _id["[]"]: "[", "backslash": "\\", "right " + _id["[]"]: "]", "carrot": "^", # Easier underscrore" "under": "_", "underscore": "_", "ticky | ((left | right) " + _id["``"] + " )": "`", "left " + _id["{}"]: "{", "pipe (sim | symbol)": "|", "right " + _id["{}"]: "}", # Individual curls "right curl": "{", "left curl": "}", "tilde": "~", # Multi-symbol "dunder | dunderscore": "__", "equals": " = ", "less than": " < ", "greater than": " > ", "equality": " == ", "hash": "# " }
from dragonfly import get_current_engine from castervoice.lib import printer if get_current_engine().name == 'natlink': import natlink class EngineModesManager(object): """ Manages engine modes and microphone states using backend engine API and through dragonfly grammar exclusivity. """ def __init__(self, ExclusiveManager): self.engine_modes = { "normal": 0, "command": 2, "dictation": 1, "numbers": 3, "spell": 4 } self.mic_modes = {"on": 5, "sleeping": 6, "off": 7} self.engine_state = None self.previous_engine_state = None self.mic_state = None self.engine = get_current_engine().name self._exclusive_manager = ExclusiveManager # Remove "normal" and "off" from 'states' for non-DNS based engines. if self.engine != 'natlink': self.engine_modes.pop("normal", 0) self.mic_modes.pop("off", 7) # Sets 1st index key ("normal" or "command") depending on engine type as default mode
def start(self): from dragonfly import get_current_engine get_current_engine().create_timer(lambda: self._update(), self._time_in_seconds)
def start(self): get_current_engine().create_timer(lambda: self._update(), self._time_in_seconds)
def say_number(n): text = "I said number " + str(n) engine = get_current_engine() if engine: engine.speak(text) print(text)
class EngineModesManager(object): """ Manages engine modes and microphone states using backend engine API and through dragonfly grammar exclusivity. """ engine = get_current_engine().name if engine == 'natlink': import natlink engine_modes = {"normal":0, "command":2, "dictation":1,"numbers":3, "spell":4} mic_modes = ["on", "sleeping", "off"] engine_state = None previous_engine_state = None mic_state = None def initialize(self): # Remove "normal" and "off" from 'states' for non-DNS based engines. if self.engine != 'natlink': self.engine_modes.pop("normal", 0) self.mic_modes.remove("off") # Sets 1st index key ("normal" or "command") depending on engine type as default mode self.engine_state = self.previous_engine_state = next(iter(self.engine_modes.keys())) def set_mic_mode(self, mode): """ Changes the engine microphone mode 'on': mic is on 'sleeping': mic from the sleeping and can be woken up by command 'off': mic off and cannot be turned back on by voice. (DNS Only) """ if mode in self.mic_modes: self.mic_state = mode if self.engine == 'natlink': self.natlink.setMicState(mode) # From here other engines use grammar exclusivity to re-create the sleep mode #if mode != "off": # off does not need grammar exclusivity #pass # TODO: Implement mic mode sleep mode using grammar exclusivity. This should override DNS is built in sleep grammar but kept in sync automatically with natlink.setmic_state else: printer.out("Caster: 'set_mic_mode' is not implemented for '{}'".format(self.engine)) else: printer.out("Caster: '{}' is not a valid. set_mic_state modes are: 'off' - DNS Only, 'on', 'sleeping'".format(mode)) def get_mic_mode(self): """ Returns mic state. mode: string """ return self.mic_state def set_engine_mode(self, mode=None, state=True): """ Sets the engine mode so that only certain types of commands/dictation are recognized. 'state': Bool - enable/disable mode. 'True': replaces current mode (Default) 'False': restores previous mode 'normal': dictation and command (Default: DNS only) 'dictation': Dictation only 'command': Commands only (Default: Other engines) 'numbers': Numbers only 'spell': Spelling only """ if state and mode is not None: # Track previous engine state # TODO: Timer to synchronize natlink.getMicState() with mengine_state in case of changed by end-user via DNS GUI. self.previous_engine_state = self.engine_state else: if not state: # Restore previous mode mode = self.previous_engine_state else: printer.out("Caster: set_engine_mode: 'State' cannot be 'True' with a undefined a 'mode'") if mode in self.engine_modes: if self.engine == 'natlink': try: self.natlink.execScript("SetRecognitionMode {}".format(self.engine_modes[mode])) # engine_modes[mode] is an integer self.engine_state = mode except Exception as e: printer.out("natlink.execScript failed \n {}".format(e)) else: # TODO: Implement mode exclusivity. This should override DNS is built in sleep grammar but kept in sync automatically with natlinks SetRecognitionMode # Once DNS enters its native mode exclusivity will override the any native DNS mode except for normal/command mode. if self.engine == 'text': self.engine_state = mode else: printer.out("Caster: 'set_engine_mode' is not implemented for '{}'".format(self.engine)) else: printer.out("Caster: '{}' mode is not a valid. set_engine_mode: Modes: 'normal'- DNS Only, 'dictation', 'command', 'numbers', 'spell'".format(mode)) def get_engine_mode(self): """ Returns engine mode. mode: str """ return self.engine_state
"DouglasGridRule", "RainbowGridRule", "SudokuGridRule", # HMC GUI control rules: "HMCRule", "HMCConfirmRule", "HMCDirectoryRule", "HMCHistoryRule", "HMCLaunchRule", "HMCSettingsRule", # GUI Rules "HistoryRule", "ChainAlias", "Alias", # other common rules "BringRule", "Again" ] # default-on modules that are platform or engine specific if sys.platform == "win32": CORE.extend([ "LegionGridRule" ]) if dragonfly.get_current_engine().name == 'natlink': CORE.append("DragonRule") # internal rules INTERNAL = [ "GrammarActivatorRule", "HooksActivationRule", "TransformersActivationRule", "ManualGrammarReloadRule" ] # default companion rules COMPANION_STARTER = { "Navigation": ["NavigationNon"], "Java": ["JavaNon"], "Matlab": ["MatlabNon"], "Prolog": ["PrologNon"], "Python": ["PythonNon"],
class EngineConfigLate: """ Initializes engine specific customizations after Nexus has initialized. Grammars are loaded into engine. """ from castervoice.lib.ctrl.mgr.engine_manager import EngineModesManager engine = get_current_engine().name sync_timer = None sleep_timer = None def __init__(self): self.EngineModesManager.initialize() if self.engine != 'natlink': # Other engines besides natlink needs a default mic state for sleep_timer self.EngineModesManager.mic_state = "on" if self.engine != "text": self._engine_timers() self._set_default_mic_mode() self._set_engine_default_mode() def _engine_timers(self): # Timer to synchronize natlink.getMicState/SetRecognitionMode with mode_state in case of changed by end-user via DNS GUI. if self.engine == 'natlink' and self.sync_timer is None: sync_timer = get_current_engine().create_timer( callback=self.EngineModesManager._sync_mode, interval=1) sync_timer.start() # A timer to change microphone state to "sleep" after X amount of seconds after last successful recognition if self.sleep_timer is None and settings.SETTINGS["engine"][ "mic_sleep_timer_on"] == True: self.sleep_timer = get_current_engine().create_timer( callback=self._sleep_timer, interval=int(settings.SETTINGS["engine"]["mic_sleep_timer"])) self.sleep_timer.start() register_recognition_callback(function=self._reset_sleep_timer) def _sleep_timer(self): """ Puts microphone to sleep if "on" via sleep_timer callback every x seconds """ if self.EngineModesManager.get_mic_mode() == "on": self.EngineModesManager.set_mic_mode("sleeping") def _reset_sleep_timer(self, words=None): """ A register_recognition_callback to reset the timer for sleep_timer based on last successful recognition """ self.sleep_timer.stop() time.sleep(0.15) self.sleep_timer.start() def _set_default_mic_mode(self): """ Sets the microphone state on Caster startup. """ # Only DNS supports mic_state 'off'. Substituts `sleep` mode on other engines" if settings.SETTINGS["engine"]["default_mic"]: # Default is `False` # Default is `on` default_mic_state = settings.SETTINGS["engine"]["mic_mode"] if self.engine != "natlink" and default_mic_state == "off": default_mic_state = "sleep" self.EngineModesManager.set_mic_mode(default_mic_state) def _set_engine_default_mode(self): """ Sets the engine mode on Caster startup. """ # Only DNS supports 'normal'. Substituts `command` mode on other engines" # Default is `False` if settings.SETTINGS["engine"]["default_engine_mode"]: # Default is `normal` default_mode = settings.SETTINGS["engine"]["engine_mode"] if self.engine != "natlink" and default_mode == "normal": default_mode = "command" self.EngineModesManager.set_engine_mode(mode=default_mode, state=True)
from dragonfly import get_engine, get_current_engine, FuncContext, Function, MappingRule, Grammar, Choice, Dictation from castervoice.lib import printer engine = get_current_engine().name if engine == 'natlink': import natlink class EngineModesManager(object): """ Manages engine modes and microphone states using backend engine API and through dragonfly grammar exclusivity. """ engine_modes = { "normal": 0, "command": 2, "dictation": 1, "numbers": 3, "spell": 4 } mic_modes = {"on": 5, "sleeping": 6, "off": 7} engine_state = None previous_engine_state = None mic_state = None timer_callback = None @classmethod def initialize(cls): # Remove "normal" and "off" from 'states' for non-DNS based engines. if engine != 'natlink': cls.engine_modes.pop("normal", 0) cls.mic_modes.pop("off", 7)
DIRECTION_STANDARD = { "sauce [E]": "up", "dunce [E]": "down", "lease [E]": "left", "ross [E]": "right", "back": "left" } def get_direction_choice(name): global DIRECTION_STANDARD return Choice(name, DIRECTION_STANDARD) # Insurers comma is recognized consistently with DNS/Natlink # if/else statement workaround engines that do not expect punctuation symbol as a command if hasattr(dragonfly.get_current_engine(), "name"): if (dragonfly.get_current_engine().name == 'natlink'): comma = "(comma | ,)" else: comma = "comma" else: comma = "comma" ''' Target Choice Note: distinct token types were removed because A) a general purpose fill token is easier to remember than 10 of them, and B) the user of a programming language will know what they're supposed to get filled with ''' TARGET_CHOICE = Choice( "target", { comma: ",",