%PDF- %PDF-
Direktori : /usr/lib/python3/dist-packages/orca/ |
Current File : //usr/lib/python3/dist-packages/orca/speech.py |
# Orca # # Copyright 2004-2009 Sun Microsystems Inc. # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the # Free Software Foundation, Inc., Franklin Street, Fifth Floor, # Boston MA 02110-1301 USA. """Manages the default speech server for orca. A script can use this as its speech server, or it can feel free to create one of its own.""" __id__ = "$Id$" __version__ = "$Revision$" __date__ = "$Date$" __copyright__ = "Copyright (c) 2005-2009 Sun Microsystems Inc." __license__ = "LGPL" import importlib import time from . import debug from . import logger from . import settings from . import speech_generator from .speechserver import VoiceFamily from .acss import ACSS _logger = logger.getLogger() log = _logger.newLog("speech") # The speech server to use for all speech operations. # _speechserver = None # The last time something was spoken. _timestamp = 0 def _initSpeechServer(moduleName, speechServerInfo): global _speechserver if not moduleName: return factory = None try: factory = importlib.import_module(f'orca.{moduleName}') except Exception: try: factory = importlib.import_module(moduleName) except Exception: debug.printException(debug.LEVEL_SEVERE) # Now, get the speech server we care about. # speechServerInfo = settings.speechServerInfo if speechServerInfo: _speechserver = factory.SpeechServer.getSpeechServer(speechServerInfo) if not _speechserver: _speechserver = factory.SpeechServer.getSpeechServer() if speechServerInfo: tokens = ["SPEECH: Invalid speechServerInfo:", speechServerInfo] debug.printTokens(debug.LEVEL_INFO, tokens, True) if not _speechserver: raise Exception(f"ERROR: No speech server for factory: {moduleName}") def init(): debug.printMessage(debug.LEVEL_INFO, 'SPEECH: Initializing', True) if _speechserver: debug.printMessage(debug.LEVEL_INFO, 'SPEECH: Already initialized', True) return # HACK: Orca goes to incredible lengths to avoid a broken configuration, so this # last-chance override exists to get the speech system loaded, without risking # it being written to disk unintentionally. if settings.speechSystemOverride: setattr(settings, 'speechServerFactory', settings.speechSystemOverride) setattr(settings, 'speechServerInfo', ['Default Synthesizer', 'default']) try: moduleName = settings.speechServerFactory _initSpeechServer(moduleName, settings.speechServerInfo) except Exception: moduleNames = settings.speechFactoryModules for moduleName in moduleNames: if moduleName != settings.speechServerFactory: try: _initSpeechServer(moduleName, None) if _speechserver: break except Exception: debug.printException(debug.LEVEL_SEVERE) if _speechserver: tokens = ["SPEECH: Using speech server factory:", moduleName] debug.printTokens(debug.LEVEL_INFO, tokens, True) else: msg = 'SPEECH: Not available' debug.printMessage(debug.LEVEL_INFO, msg, True) debug.printMessage(debug.LEVEL_INFO, 'SPEECH: Initialized', True) def checkSpeechSetting(): msg = "SPEECH: Checking speech setting." debug.printMessage(debug.LEVEL_INFO, msg, True) if not settings.enableSpeech: shutdown() else: init() def __resolveACSS(acss=None): if isinstance(acss, ACSS): family = acss.get(acss.FAMILY) try: family = VoiceFamily(family) except Exception: family = VoiceFamily({}) acss[acss.FAMILY] = family return acss elif isinstance(acss, list) and len(acss) == 1: return ACSS(acss[0]) elif isinstance(acss, dict): return ACSS(acss) else: voices = settings.voices return ACSS(voices[settings.DEFAULT_VOICE]) def sayAll(utteranceIterator, progressCallback): if settings.silenceSpeech: return if _speechserver: _speechserver.sayAll(utteranceIterator, progressCallback) else: for [context, acss] in utteranceIterator: logLine = f"SPEECH OUTPUT: '{context.utterance}'" debug.printMessage(debug.LEVEL_INFO, logLine, True) log.info(logLine) def _speak(text, acss, interrupt): """Speaks the individual string using the given ACSS.""" if not _speechserver: logLine = f"SPEECH OUTPUT: '{text}' {acss}" debug.printMessage(debug.LEVEL_INFO, logLine, True) log.info(logLine) return voice = ACSS(settings.voices.get(settings.DEFAULT_VOICE)) try: voice.update(__resolveACSS(acss)) except Exception as error: msg = f"SPEECH: Exception updated voice with {acss}: {error}" debug.printMessage(debug.LEVEL_INFO, msg, True) resolvedVoice = __resolveACSS(voice) msg = f"SPEECH OUTPUT: '{text}' {resolvedVoice}" debug.printMessage(debug.LEVEL_INFO, msg, True) _speechserver.speak(text, resolvedVoice, interrupt) def speak(content, acss=None, interrupt=True): """Speaks the given content. The content can be either a simple string or an array of arrays of objects returned by a speech generator.""" if settings.silenceSpeech: return validTypes = (str, list, speech_generator.Pause, speech_generator.LineBreak, ACSS) error = "SPEECH: Bad content sent to speak():" if not isinstance(content, validTypes): debug.printMessage(debug.LEVEL_INFO, error + str(content), True, True) return global _timestamp if _timestamp: msg = f"SPEECH: Last spoke {time.time() - _timestamp:.4f} seconds ago" debug.printMessage(debug.LEVEL_INFO, msg, True) _timestamp = time.time() if isinstance(content, str): msg = f"SPEECH: Speak '{content}' acss: {acss}" debug.printMessage(debug.LEVEL_INFO, msg, True) else: tokens = ["SPEECH: Speak", content, ", acss:", acss] debug.printTokens(debug.LEVEL_INFO, tokens, True) if isinstance(content, str): _speak(content, acss, interrupt) if not isinstance(content, list): return toSpeak = [] activeVoice = acss if acss is not None: activeVoice = ACSS(acss) for element in content: if not isinstance(element, validTypes): debug.printMessage(debug.LEVEL_INFO, error + str(element), True, True) elif isinstance(element, list): speak(element, acss, interrupt) elif isinstance(element, str): if len(element): toSpeak.append(element) elif toSpeak: newVoice = ACSS(acss) newItemsToSpeak = [] if isinstance(element, speech_generator.Pause): if toSpeak[-1] and toSpeak[-1][-1].isalnum(): toSpeak[-1] += '.' elif isinstance(element, ACSS): newVoice.update(element) if activeVoice is None: activeVoice = newVoice if newVoice == activeVoice: continue tokens = ["SPEECH: New voice", newVoice, " != active voice", activeVoice] debug.printTokens(debug.LEVEL_INFO, tokens, True) newItemsToSpeak.append(toSpeak.pop()) if toSpeak: string = " ".join(toSpeak) _speak(string, activeVoice, interrupt) activeVoice = newVoice toSpeak = newItemsToSpeak if toSpeak: string = " ".join(toSpeak) _speak(string, activeVoice, interrupt) def speakKeyEvent(event, acss=None): """Speaks a key event immediately. Arguments: - event: input_event.KeyboardEvent to speak. """ if settings.silenceSpeech: return global _timestamp if _timestamp: msg = f"SPEECH: Last spoke {time.time() - _timestamp:.4f} seconds ago" debug.printMessage(debug.LEVEL_INFO, msg, True) _timestamp = time.time() keyname = event.getKeyName() lockingStateString = event.getLockingStateString() acss = __resolveACSS(acss) msg = f"{keyname} {lockingStateString}" logLine = f"SPEECH OUTPUT: '{msg.strip()}' {acss}" debug.printMessage(debug.LEVEL_INFO, logLine, True) log.info(logLine) if _speechserver: _speechserver.speakKeyEvent(event, acss) def speakCharacter(character, acss=None): """Speaks a single character immediately. Arguments: - character: text to be spoken - acss: acss.ACSS instance; if None, the default voice settings will be used. Otherwise, the acss settings will be used to augment/override the default voice settings. """ if settings.silenceSpeech: return global _timestamp if _timestamp: msg = f"SPEECH: Last spoke {time.time() - _timestamp:.4f} seconds ago" debug.printMessage(debug.LEVEL_INFO, msg, True) _timestamp = time.time() acss = __resolveACSS(acss) tokens = [f"SPEECH OUTPUT: '{character}'", acss] debug.printTokens(debug.LEVEL_INFO, tokens, True) log.info(f"SPEECH OUTPUT: '{character}'") if _speechserver: _speechserver.speakCharacter(character, acss=acss) def getInfo(): info = None if _speechserver: info = _speechserver.getInfo() return info def stop(): if _speechserver: _speechserver.stop() def shutdown(): debug.printMessage(debug.LEVEL_INFO, 'SPEECH: Shutting down', True) global _speechserver if _speechserver: _speechserver.shutdownActiveServers() _speechserver = None def reset(text=None, acss=None): if _speechserver: _speechserver.reset(text, acss) def getSpeechServer(): return _speechserver