#!/bin/python # -*- coding: utf-8 -*- # Fenrir TTY screen reader # By Chrys, Storm Dragon, and contributors. from fenrirscreenreader.core import debug from fenrirscreenreader.utils import line_utils import string, time, re class outputManager(): def __init__(self): self.lastEcho = '' def initialize(self, environment): self.env = environment self.env['runtime']['settingsManager'].loadDriver( self.env['runtime']['settingsManager'].getSetting('speech', 'driver'), 'speechDriver') self.env['runtime']['settingsManager'].loadDriver( self.env['runtime']['settingsManager'].getSetting('sound', 'driver'), 'soundDriver') def shutdown(self): self.env['runtime']['settingsManager'].shutdownDriver('soundDriver') self.env['runtime']['settingsManager'].shutdownDriver('speechDriver') def presentText(self, text, interrupt=True, soundIcon='', ignorePunctuation=False, announceCapital=False, flush=True): if text == '': return if self.env['runtime']['settingsManager'].getSettingAsBool('speech', 'readNumbersAsDigits') and len(text.strip()) > 1: text = re.sub(r"(\d)", r"\1 ", text).rstrip() self.env['runtime']['debug'].writeDebugOut("presentText:\nsoundIcon:'"+soundIcon+"'\nText:\n" + text, debug.debugLevel.INFO) if self.playSoundIcon(soundIcon, interrupt): self.env['runtime']['debug'].writeDebugOut("soundIcon found", debug.debugLevel.INFO) return if (len(text) > 1) and (text.strip(string.whitespace) == ''): return toAnnounceCapital = announceCapital and text[0].isupper() if toAnnounceCapital: if self.playSoundIcon('capital', False): toAnnounceCapital = False self.lastEcho = text self.speakText(text, interrupt, ignorePunctuation, toAnnounceCapital) def getLastEcho(self): return self.lastEcho def speakText(self, text, interrupt=True, ignorePunctuation=False, announceCapital=False): if not self.env['runtime']['settingsManager'].getSettingAsBool('speech', 'enabled'): self.env['runtime']['debug'].writeDebugOut("Speech disabled in outputManager.speakText", debug.debugLevel.INFO) return if self.env['runtime']['speechDriver'] == None: self.env['runtime']['debug'].writeDebugOut("No speechDriver in outputManager.speakText", debug.debugLevel.ERROR) return if interrupt: self.interruptOutput() try: self.env['runtime']['speechDriver'].setLanguage(self.env['runtime']['settingsManager'].getSetting('speech', 'language')) except Exception as e: self.env['runtime']['debug'].writeDebugOut("setting speech language in outputManager.speakText", debug.debugLevel.ERROR) self.env['runtime']['debug'].writeDebugOut(str(e), debug.debugLevel.ERROR) try: self.env['runtime']['speechDriver'].setVoice(self.env['runtime']['settingsManager'].getSetting('speech', 'voice')) except Exception as e: self.env['runtime']['debug'].writeDebugOut("Error while setting speech voice in outputManager.speakText", debug.debugLevel.ERROR) self.env['runtime']['debug'].writeDebugOut(str(e), debug.debugLevel.ERROR) try: if announceCapital: self.env['runtime']['speechDriver'].setPitch(self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'capitalPitch')) else: self.env['runtime']['speechDriver'].setPitch(self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'pitch')) except Exception as e: self.env['runtime']['debug'].writeDebugOut("setting speech pitch in outputManager.speakText", debug.debugLevel.ERROR) self.env['runtime']['debug'].writeDebugOut(str(e), debug.debugLevel.ERROR) try: self.env['runtime']['speechDriver'].setRate(self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'rate')) except Exception as e: self.env['runtime']['debug'].writeDebugOut("setting speech rate in outputManager.speakText", debug.debugLevel.ERROR) self.env['runtime']['debug'].writeDebugOut(str(e), debug.debugLevel.ERROR) try: self.env['runtime']['speechDriver'].setModule(self.env['runtime']['settingsManager'].getSetting('speech', 'module')) except Exception as e: self.env['runtime']['debug'].writeDebugOut("setting speech module in outputManager.speakText", debug.debugLevel.ERROR) self.env['runtime']['debug'].writeDebugOut(str(e), debug.debugLevel.ERROR) try: self.env['runtime']['speechDriver'].setVolume(self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'volume')) except Exception as e: self.env['runtime']['debug'].writeDebugOut("setting speech volume in outputManager.speakText ", debug.debugLevel.ERROR) self.env['runtime']['debug'].writeDebugOut(str(e), debug.debugLevel.ERROR) try: if self.env['runtime']['settingsManager'].getSettingAsBool('general', 'newLinePause'): cleanText = text.replace('\n', ' , ') else: cleanText = text.replace('\n', ' ') cleanText = self.env['runtime']['textManager'].replaceHeadLines(cleanText) cleanText = self.env['runtime']['punctuationManager'].proceedPunctuation(cleanText, ignorePunctuation) cleanText = re.sub(' +$', ' ', cleanText) self.env['runtime']['speechDriver'].speak(cleanText) self.env['runtime']['debug'].writeDebugOut("Speak: "+ cleanText, debug.debugLevel.INFO) except Exception as e: self.env['runtime']['debug'].writeDebugOut("\"speak\" in outputManager.speakText ", debug.debugLevel.ERROR) self.env['runtime']['debug'].writeDebugOut(str(e), debug.debugLevel.ERROR) def interruptOutput(self): try: self.env['runtime']['speechDriver'].cancel() self.env['runtime']['debug'].writeDebugOut("Interrupt speech", debug.debugLevel.INFO) except: pass def playSoundIcon(self, soundIcon='', interrupt=True): if soundIcon == '': return False soundIcon = soundIcon.upper() if not self.env['runtime']['settingsManager'].getSettingAsBool('sound', 'enabled'): self.env['runtime']['debug'].writeDebugOut("Sound disabled in outputManager.playSoundIcon", debug.debugLevel.INFO) return False try: e = self.env['soundIcons'][soundIcon] except: self.env['runtime']['debug'].writeDebugOut("SoundIcon doesnt exist: " + soundIcon, debug.debugLevel.WARNING) return False if self.env['runtime']['soundDriver'] == None: self.env['runtime']['debug'].writeDebugOut("No soundDriver in outputManager.playSoundIcon: soundDriver not loaded", debug.debugLevel.ERROR) return False try: self.env['runtime']['soundDriver'].setVolume(self.env['runtime']['settingsManager'].getSettingAsFloat('sound', 'volume')) except Exception as e: self.env['runtime']['debug'].writeDebugOut("outputManager.playSoundIcon::setVolume: " + str(e), debug.debugLevel.ERROR) try: self.env['runtime']['soundDriver'].playSoundFile(self.env['soundIcons'][soundIcon], interrupt) return True except Exception as e: self.env['runtime']['debug'].writeDebugOut("outputManager.playSoundIcon::playSoundFile: " + str(e), debug.debugLevel.ERROR) return False return False def playFrequence(self, frequence, duration, interrupt=True): if not self.env['runtime']['settingsManager'].getSettingAsBool('sound', 'enabled'): self.env['runtime']['debug'].writeDebugOut("Sound disabled in outputManager.playFrequence", debug.debugLevel.INFO) return False if frequence < 1 or frequence > 20000: self.env['runtime']['debug'].writeDebugOut("outputManager.playFrequence::Filefrequence is out of range:" + str(frequence), debug.debugLevel.INFO) return False if self.env['runtime']['soundDriver'] == None: self.env['runtime']['debug'].writeDebugOut("No soundDriver in outputManager.playFrequence: soundDriver not loaded", debug.debugLevel.ERROR) return False try: self.env['runtime']['soundDriver'].setVolume(self.env['runtime']['settingsManager'].getSettingAsFloat('sound', 'volume')) except Exception as e: self.env['runtime']['debug'].writeDebugOut("outputManager.playSoundIcon::setVolume: " + str(e), debug.debugLevel.ERROR) adjustVolume = 0.0 try: adjustVolume = 1.0 - (frequence / 20000) except: pass if adjustVolume > 9.0: adjustVolume = 9.0 try: self.env['runtime']['soundDriver'].playFrequence(frequence, duration, adjustVolume, interrupt) return True except Exception as e: self.env['runtime']['debug'].writeDebugOut("outputManager.playSoundIcon::playSoundFile: " + str(e), debug.debugLevel.ERROR) return False return False def tempDisableSpeech(self): if self.env['runtime']['settingsManager'].getSettingAsBool('speech', 'enabled'): self.presentText(_("speech temporary disabled"), soundIcon='SpeechOff', interrupt=True) self.env['commandBuffer']['enableSpeechOnKeypress'] = True self.env['runtime']['settingsManager'].setSetting('speech', 'enabled', str(not self.env['runtime']['settingsManager'].getSettingAsBool('speech', 'enabled'))) self.interruptOutput() def announceActiveCursor(self, interrupt_p=False): if self.env['runtime']['cursorManager'].isReviewMode(): self.presentText(' review cursor ', interrupt=interrupt_p) else: self.presentText(' text cursor ', interrupt=interrupt_p)