def initialize(): global _remoteLib, _remoteLoader64, localLib, winEventHookID,generateBeep,VBuf_getTextInRange localLib=cdll.LoadLibrary('lib/nvdaHelperLocal.dll') for name,func in [ ("nvdaController_speakText",nvdaController_speakText), ("nvdaController_cancelSpeech",nvdaController_cancelSpeech), ("nvdaController_brailleMessage",nvdaController_brailleMessage), ("nvdaControllerInternal_inputLangChangeNotify",nvdaControllerInternal_inputLangChangeNotify), ("nvdaControllerInternal_displayModelTextChangeNotify",nvdaControllerInternal_displayModelTextChangeNotify), ("nvdaControllerInternal_logMessage",nvdaControllerInternal_logMessage), ]: try: _setDllFuncPointer(localLib,"_%s"%name,func) except AttributeError: log.error("nvdaHelperLocal function pointer for %s could not be found, possibly old nvdaHelperLocal dll"%name) localLib.startServer() generateBeep=localLib.generateBeep generateBeep.argtypes=[c_char_p,c_float,c_uint,c_ubyte,c_ubyte] generateBeep.restype=c_uint # Handle VBuf_getTextInRange's BSTR out parameter so that the BSTR will be freed automatically. VBuf_getTextInRange = CFUNCTYPE(c_int, c_int, c_int, c_int, POINTER(BSTR), c_int)( ("VBuf_getTextInRange", localLib), ((1,), (1,), (1,), (2,), (1,))) #Load nvdaHelperRemote.dll but with an altered search path so it can pick up other dlls in lib h=windll.kernel32.LoadLibraryExW(os.path.abspath(ur"lib\nvdaHelperRemote.dll"),0,0x8) if not h: log.critical("Error loading nvdaHelperRemote.dll: %s" % WinError()) return _remoteLib=CDLL("nvdaHelperRemote",handle=h) if _remoteLib.injection_initialize(globalVars.appArgs.secure) == 0: raise RuntimeError("Error initializing NVDAHelperRemote") if os.environ.get('PROCESSOR_ARCHITEW6432')=='AMD64': _remoteLoader64=RemoteLoader64() winEventHookID=winUser.setWinEventHook(EVENT_TYPEDCHARACTER,EVENT_TYPEDCHARACTER,0,winEventCallback,0,0,0)
def onRunCOMRegistrationFixesCommand(self, evt): if isInMessageBox: return if gui.messageBox( # Translators: A message to warn the user when starting the COM Registration Fixing tool _("You are about to run the COM Registration Fixing tool. This tool will try to fix common system problems that stop NVDA from being able to access content in many programs including Firefox and Internet Explorer. This tool must make changes to the System registry and therefore requires administrative access. Are you sure you wish to proceed?"), # Translators: The title of the warning dialog displayed when launching the COM Registration Fixing tool _("Warning"),wx.YES|wx.NO|wx.ICON_WARNING,self )==wx.NO: return progressDialog = IndeterminateProgressDialog(mainFrame, # Translators: The title of the dialog presented while NVDA is running the COM Registration fixing tool _("COM Registration Fixing Tool"), # Translators: The message displayed while NVDA is running the COM Registration fixing tool _("Please wait while NVDA tries to fix your system's COM registrations.") ) try: config.execElevated(config.SLAVE_FILENAME,["fixCOMRegistrations"]) except: log.error("Could not execute fixCOMRegistrations command",exc_info=True) progressDialog.done() del progressDialog # Translators: The message displayed when the COM Registration Fixing tool completes. gui.messageBox(_("COM Registration Fixing tool complete"), # Translators: The title of a dialog presented when the COM Registration Fixing tool is complete. _("COM Registration Fixing Tool"), wx.OK)
def internal_keyUpEvent(vkCode,scanCode,extended,injected): """Event called by winInputHook when it receives a keyUp. """ try: global lastNVDAModifier, lastNVDAModifierReleaseTime, bypassNVDAModifier, passKeyThroughCount, lastPassThroughKeyDown, currentModifiers if injected: return True keyCode = (vkCode, extended) if passKeyThroughCount >= 1: if lastPassThroughKeyDown == keyCode: # This key has been released. lastPassThroughKeyDown = None passKeyThroughCount -= 1 if passKeyThroughCount == 0: passKeyThroughCount = -1 return True if lastNVDAModifier and keyCode == lastNVDAModifier: # The last pressed NVDA modifier key is being released and there were no key presses in between. # The user may want to press it again quickly to pass it through. lastNVDAModifierReleaseTime = time.time() # If we were bypassing the NVDA modifier, stop doing so now, as there will be no more repeats. bypassNVDAModifier = False currentModifiers.discard(keyCode) if keyCode in trappedKeys: trappedKeys.remove(keyCode) return False except: log.error("", exc_info=True) return True
def winEventCallback(handle,eventID,window,objectID,childID,threadID,timestamp): global lastKeyboardLayoutChangeEventTime try: if eventID==EVENT_TYPEDCHARACTER: handleTypedCharacter(window,objectID,childID) except: log.error("helper.winEventCallback", exc_info=True)
def completeRemove(self,runUninstallTask=True): if runUninstallTask: try: # #2715: The add-on must be added to _availableAddons here so that # translations can be used in installTasks module. _availableAddons[self.path] = self self.runInstallTask("onUninstall") except: log.error("task 'onUninstall' on addon '%s' failed"%self.name,exc_info=True) finally: del _availableAddons[self.path] tempPath=tempfile.mktemp(suffix=DELETEDIR_SUFFIX,dir=os.path.dirname(self.path)) try: os.rename(self.path,tempPath) except (WindowsError,IOError): raise RuntimeError("Cannot rename add-on path for deletion") shutil.rmtree(tempPath,ignore_errors=True) if os.path.exists(tempPath): log.error("Error removing addon directory %s, deferring until next NVDA restart"%self.path) # clean up the addons state. If an addon with the same name is installed, it should not be automatically # disabled / blocked. log.debug("removing addon {} from _disabledAddons/_blockedAddons".format(self.name)) _disabledAddons.discard(self.name) _blockedAddons.discard(self.name) saveState()
def _getAvailableAddonsFromPath(path): """ Gets available add-ons from path. An addon is only considered available if the manifest file is loaded with no errors. @param path: path from where to find addon directories. @type path: string @rtype generator of Addon instances """ log.debug("Listing add-ons from %s", path) for p in os.listdir(path): if p.endswith(DELETEDIR_SUFFIX): continue addon_path = os.path.join(path, p) if os.path.isdir(addon_path) and addon_path not in ('.', '..'): log.debug("Loading add-on from %s", addon_path) try: a = Addon(addon_path) name = a.manifest['name'] log.debug( "Found add-on {name} - {a.version}." " Requires API: {a.minimumNVDAVersion}." " Last-tested API: {a.lastTestedNVDAVersion}".format( name=name, a=a )) if a.isDisabled: log.debug("Disabling add-on %s", name) if not isAddonCompatible(a): log.debugWarning("Add-on %s is considered incompatible", name) _blockedAddons.add(a.name) yield a except: log.error("Error loading Addon from path: %s", addon_path, exc_info=True)
def fetchAppModule(processID,appName): """Returns an appModule found in the appModules directory, for the given application name. @param processID: process ID for it to be associated with @type processID: integer @param appName: the application name for which an appModule should be found. @type appName: unicode or str @returns: the appModule, or None if not found @rtype: AppModule """ # First, check whether the module exists. # We need to do this separately because even though an ImportError is raised when a module can't be found, it might also be raised for other reasons. # Python 2.x can't properly handle unicode module names, so convert them. modName = appName.encode("mbcs") if doesAppModuleExist(modName): try: return __import__("appModules.%s" % modName, globals(), locals(), ("appModules",)).AppModule(processID, appName) except: log.error("error in appModule %r"%modName, exc_info=True) # We can't present a message which isn't unicode, so use appName, not modName. # Translators: This is presented when errors are found in an appModule (example output: error in appModule explorer). ui.message(_("Error in appModule %s")%appName) # Use the base AppModule. return AppModule(processID, appName)
def __call__(self,sample_rate,user_data): try: self.__player.set_sample_rate(sample_rate) return 1 except: log.error("RHVoice sample rate callback",exc_info=True) return 0
def getSynthList(): synthList=[] # The synth that should be placed at the end of the list. lastSynth = None for loader, name, isPkg in pkgutil.iter_modules(synthDrivers.__path__): if name.startswith('_'): continue try: synth=_getSynthDriver(name) except: log.error("Error while importing SynthDriver %s"%name,exc_info=True) continue try: if synth.check(): if synth.name == "silence": lastSynth = (synth.name,synth.description) else: synthList.append((synth.name,synth.description)) else: log.debugWarning("Synthesizer '%s' doesn't pass the check, excluding from list"%name) except: log.error("",exc_info=True) synthList.sort(key=lambda s : s[1].lower()) if lastSynth: synthList.append(lastSynth) return synthList
def _initBaseConf(self, factoryDefaults=False): fn = os.path.join(globalVars.appArgs.configPath, "nvda.ini") if factoryDefaults: profile = ConfigObj(None, indent_type="\t", encoding="UTF-8") profile.filename = fn else: try: profile = ConfigObj(fn, indent_type="\t", encoding="UTF-8") self.baseConfigError = False except: log.error("Error loading base configuration", exc_info=True) self.baseConfigError = True return self._initBaseConf(factoryDefaults=True) # Python converts \r\n to \n when reading files in Windows, so ConfigObj can't determine the true line ending. profile.newlines = "\r\n" for key in self.BASE_ONLY_SECTIONS: # These sections are returned directly from the base config, so validate them here. try: sect = profile[key] except KeyError: profile[key] = {} # ConfigObj mutates this into a configobj.Section. sect = profile[key] sect.configspec = self.spec[key] profile.validate(self.validator, section=sect) self._profileCache[None] = profile self.profiles.append(profile) self._handleProfileSwitch()
def __init__(self): # #6140: Migrate to new table names as smoothly as possible. tableName = config.conf["braille"]["inputTable"] newTableName = brailleTables.RENAMED_TABLES.get(tableName) if newTableName: tableName = config.conf["braille"]["inputTable"] = newTableName try: self._table = brailleTables.getTable(tableName) except LookupError: log.error("Invalid table: %s" % tableName) self._table = brailleTables.getTable(FALLBACK_TABLE) #: A buffer of entered braille cells so that state set by previous cells can be maintained; #: e.g. capital and number signs. self.bufferBraille = [] #: The text translated so far from the cells in L{bufferBraille}. self.bufferText = u"" #: Indexes of cells which produced text. #: For example, this includes letters and numbers, but not number signs, #: since a number sign by itself doesn't produce text. #: This is used when erasing cells to determine when to backspace an actual character. self.cellsWithText = set() #: The cells in L{bufferBraille} that have not yet been translated #: or were translated but did not produce any text. #: This is used to show these cells to the user while they're entering braille. #: This is a string of Unicode braille. #: @type: unicode self.untranslatedBraille = "" #: The position in L{brailleBuffer} where untranslated braille begins. self.untranslatedStart = 0 #: The user's cursor position within the untranslated braille. #: This enables the user to move within the untranslated braille. self.untranslatedCursorPos = 0 #: The time at which uncontracted characters were sent to the system. self._uncontSentTime = None config.configProfileSwitched.register(self.handleConfigProfileSwitch)
def tryRemoveFile(path,numRetries=6,retryInterval=0.5,rebootOK=False): dirPath=os.path.dirname(path) tempPath=tempfile.mktemp(dir=dirPath) try: os.rename(path,tempPath) except (WindowsError,IOError): raise RetriableFailure("Failed to rename file %s before remove"%path) for count in xrange(numRetries): try: if os.path.isdir(tempPath): shutil.rmtree(tempPath) else: os.remove(tempPath) return except OSError: pass time.sleep(retryInterval) if rebootOK: log.debugWarning("Failed to delete file %s, marking for delete on reboot"%tempPath) MoveFileEx=windll.kernel32.MoveFileExW if isinstance(tempPath,unicode) else windll.kernel32.MoveFileExA MoveFileEx("\\\\?\\"+tempPath,None,4) return try: os.rename(tempPath,path) except: log.error("Unable to rename back to %s before retriable failier"%path) raise RetriableFailure("File %s could not be removed"%path)
def installAddon(self, addonPath, closeAfter=False): try: try: bundle=addonHandler.AddonBundle(addonPath) except: log.error("Error opening addon bundle from %s"%addonPath,exc_info=True) # Translators: The message displayed when an error occurs when opening an add-on package for adding. gui.messageBox(_("Failed to open add-on package file at %s - missing file or invalid file format")%addonPath, # Translators: The title of a dialog presented when an error occurs. _("Error"), wx.OK | wx.ICON_ERROR) return # Translators: A message asking the user if they really wish to install an addon. if gui.messageBox(_("Are you sure you want to install this add-on? Only install add-ons from trusted sources.\nAddon: {summary} {version}\nAuthor: {author}").format(**bundle.manifest), # Translators: Title for message asking if the user really wishes to install an Addon. _("Add-on Installation"), wx.YES|wx.NO|wx.ICON_WARNING)!=wx.YES: return bundleName=bundle.manifest['name'] prevAddon=None for addon in self.curAddons: if not addon.isPendingRemove and bundleName==addon.manifest['name']: prevAddon=addon break if prevAddon: # Translators: A message asking if the user wishes to update a previously installed add-on with this one. if gui.messageBox(_("A version of this add-on is already installed. Would you like to update it?"), # Translators: A title for the dialog asking if the user wishes to update a previously installed add-on with this one. _("Add-on Installation"), wx.YES|wx.NO|wx.ICON_WARNING)!=wx.YES: return prevAddon.requestRemove() progressDialog = gui.IndeterminateProgressDialog(gui.mainFrame, # Translators: The title of the dialog presented while an Addon is being installed. _("Installing Add-on"), # Translators: The message displayed while an addon is being installed. _("Please wait while the add-on is being installed.")) try: gui.ExecAndPump(addonHandler.installAddonBundle,bundle) except: log.error("Error installing addon bundle from %s"%addonPath,exc_info=True) self.refreshAddonsList() progressDialog.done() del progressDialog # Translators: The message displayed when an error occurs when installing an add-on package. gui.messageBox(_("Failed to install add-on from %s")%addonPath, # Translators: The title of a dialog presented when an error occurs. _("Error"), wx.OK | wx.ICON_ERROR) return else: self.refreshAddonsList(activeIndex=-1) progressDialog.done() del progressDialog finally: if closeAfter: # #4460: If we do this immediately, wx seems to drop the WM_QUIT sent if the user chooses to restart. # This seems to have something to do with the wx.ProgressDialog. # The CallLater seems to work around this. wx.CallLater(1, self.Close)
def _handlePacket(self, packet): mode=packet[1] if mode=="\x00": # Cursor routing routingIndex = ord(packet[3]) try: inputCore.manager.executeGesture(RoutingInputGesture(routingIndex)) except inputCore.NoInputGestureAction: pass elif mode=="\x01": # Braille input or function key if not self._model: return _keys = sum(ord(packet[4+i])<<(i*8) for i in xrange(4)) keys = set() for keyHex in self._model.keys: if _keys & keyHex: # This key is pressed _keys -= keyHex keys.add(keyHex) if _keys == 0: break if _keys: log.error("Unknown key(s) 0x%x received from Hims display"%_keys) return try: inputCore.manager.executeGesture(KeyInputGesture(self._model, keys)) except inputCore.NoInputGestureAction: pass elif mode=="\x02": # Cell count self.numCells=ord(packet[3])
def initialize(): for eventType in winEventIDsToNVDAEventNames.keys(): hookID=winUser.setWinEventHook(eventType,eventType,0,cWinEventCallback,0,0,0) if hookID: winEventHookIDs.append(hookID) else: log.error("initialize: could not register callback for event %s (%s)"%(eventType,winEventIDsToNVDAEventNames[eventType]))
def __call__(self,name,user_data): try: self.index=int(name) return 1 except: log.error("RHVoice mark callback",exc_info=True) return 0
def _setDuckingState(switch): global _lastDuckedTime with _duckingRefCountLock: try: import gui ATWindow=gui.mainFrame.GetHandle() if switch: oledll.oleacc.AccSetRunningUtilityState(ATWindow,ANRUS_ducking_AUDIO_ACTIVE|ANRUS_ducking_AUDIO_ACTIVE_NODUCK,ANRUS_ducking_AUDIO_ACTIVE|ANRUS_ducking_AUDIO_ACTIVE_NODUCK) _lastDuckedTime=time.time() else: oledll.oleacc.AccSetRunningUtilityState(ATWindow,ANRUS_ducking_AUDIO_ACTIVE|ANRUS_ducking_AUDIO_ACTIVE_NODUCK,ANRUS_ducking_AUDIO_ACTIVE_NODUCK) except WindowsError as e: # When the NVDA build is not signed, audio ducking fails with access denied. # A developer built launcher is unlikely to be signed. Catching this error stops developers from looking into # "expected" errors. # ERROR_ACCESS_DENIED is 0x5 # https://docs.microsoft.com/en-us/windows/desktop/debug/system-error-codes--0-499- ERROR_ACCESS_DENIED = 0x80070005 errorCode = e.winerror & 0xFFFFFFFF # we only care about the first 8 hex values. if errorCode == ERROR_ACCESS_DENIED: log.warning("Unable to set ducking state: ERROR_ACCESS_DENIED.") else: # we want developers to hear the "error sound", and to halt, so still raise the exception. log.error( "Unknown error when setting ducking state: Error number: {:#010X}".format(errorCode), exc_info=True ) raise e
def executeMouseMoveEvent(x,y): global currentMouseWindow desktopObject=api.getDesktopObject() displays = [ wx.Display(i).GetGeometry() for i in xrange(wx.Display.GetCount()) ] x, y = getMouseRestrictedToScreens(x, y, displays) screenWidth, screenHeight, minPos = getTotalWidthAndHeightAndMinimumPosition(displays) if config.conf["mouse"]["audioCoordinatesOnMouseMove"]: playAudioCoordinates(x, y, screenWidth, screenHeight, minPos, config.conf['mouse']['audioCoordinates_detectBrightness'], config.conf['mouse']['audioCoordinates_blurFactor']) oldMouseObject=api.getMouseObject() mouseObject=desktopObject.objectFromPoint(x, y) while mouseObject and mouseObject.beTransparentToMouse: mouseObject=mouseObject.parent if not mouseObject: return if oldMouseObject==mouseObject: mouseObject=oldMouseObject else: api.setMouseObject(mouseObject) try: eventHandler.executeEvent("mouseMove",mouseObject,x=x,y=y) oldMouseObject=mouseObject except: log.error("api.notifyMouseMoved", exc_info=True)
def initialize(voice = default_jtalk_voice): global player, voice_args global speaker_attenuation voice_args = voice speaker_attenuation = voice_args['speaker_attenuation'] if not _espeak.espeakDLL: _espeak.initialize() log.debug("jtalk using eSpeak version %s" % _espeak.info()) _espeak.setVoiceByLanguage("en") _espeak.setVoiceAndVariant(variant=voice["espeak_variant"]) if not player: player = nvwave.WavePlayer(channels=1, samplesPerSec=voice_args['samp_rate'], bitsPerSample=16, outputDevice=config.conf["speech"]["outputDevice"]) if not _bgthread.bgThread: _bgthread.initialize() if not mecab: Mecab_initialize(log.info, jtalk_dir, dic_dir, user_dics) jtalkPrepare.setup() jt_dll = os.path.join(jtalk_dir, 'libopenjtalk.dll') log.debug('jt_dll %s' % jt_dll) libjt_initialize(jt_dll) log.debug(libjt_version()) if os.path.isfile(voice_args['htsvoice']): libjt_load(voice_args['htsvoice']) log.info("loaded " + voice_args['htsvoice']) else: log.error("load error " + voice_args['htsvoice']) libjt_set_alpha(voice_args['alpha']) libjt_set_beta(voice_args['beta'])
def setDisplayByName(self, name): if not name: self.display = None self.displaySize = 0 return try: newDisplay = _getDisplayDriver(name) if newDisplay == self.display.__class__: # This is the same driver as was already set, so just re-initialise it. self.display.terminate() newDisplay = self.display newDisplay.__init__() else: newDisplay = newDisplay() if self.display: try: self.display.terminate() except: log.error("Error terminating previous display driver", exc_info=True) self.display = newDisplay self.displaySize = newDisplay.numCells self.enabled = bool(self.displaySize) config.conf["braille"]["display"] = name log.info("Loaded braille display driver %s" % name) return True except: log.error("Error initializing display driver", exc_info=True) self.setDisplayByName("noBraille") return False
def getWindowScalingFactor(window): """Gets the logical scaling factor used for the given window handle. This is based off the Dpi reported by windows for the given window handle / divided by the "base" DPI level of 96. Typically this is a result of using the scaling percentage in the windows display settings. 100% is typically 96 DPI, 150% is typically 144 DPI. @param window: a native Windows window handle (hWnd) @returns the logical scaling factor. EG. 1.0 if the window DPI level is 96, 1.5 if the window DPI level is 144""" user32 = ctypes.windll.user32 try: winDpi = user32.GetDpiForWindow(window) except: log.debug("GetDpiForWindow failed, using GetDeviceCaps instead") dc = user32.GetDC(window) winDpi = ctypes.windll.gdi32.GetDeviceCaps(dc, LOGPIXELSX) ret = user32.ReleaseDC(window, dc) if ret != 1: log.error("Unable to release the device context.") # For GetDpiForWindow: an invalid hwnd value will result in a return value of 0. # There is little information about what GetDeviceCaps does in the case of a failure for LOGPIXELSX, however, # a value of zero is certainly an error. if winDpi <= 0: log.debugWarning("Failed to get the DPI for the window, assuming a " "DPI of {} and using a scaling of 1.0. The hWnd value " "used was: {}".format(DEFAULT_DPI_LEVEL, window)) return 1.0 return winDpi / DEFAULT_DPI_LEVEL
def speak(self,speech_sequence): spell_mode=False text_list=[] for item in speech_sequence: if isinstance(item,basestring): s=unicode(item).translate(self.__char_mapping) text_list.append((u'<say-as interpret-as="characters">%s</say-as>' % s) if spell_mode else s) elif isinstance(item,speech.IndexCommand): text_list.append('<mark name="%d"/>' % item.index) elif isinstance(item,speech.CharacterModeCommand): if item.state: spell_mode=True else: spell_mode=False elif isinstance(item,speech.SpeechCommand): log.debugWarning("Unsupported speech command: %s"%item) else: log.error("Unknown speech: %s"%item) text=u"".join(text_list) fmt_str=u'<speak><voice name="%s" variant="%d"><prosody rate="%f%%" pitch="%f%%" volume="%f%%">%s</prosody></voice></speak>' variant=self.__lib.RHVoice_find_variant(self.__variant) if variant==0: variant=1 rate=convert_to_native_percent(self.__rate,*self.__native_rate_range) pitch=convert_to_native_percent(self.__pitch,*self.__native_pitch_range) volume=convert_to_native_percent(self.__volume,*self.__native_volume_range) ssml=fmt_str % (self.__voice,variant,rate,pitch,volume,text) self.__tts_queue.put(ssml)
def speak(self,speechSequence): defaultLanguage=self._language textList=[] langChanged=False for item in speechSequence: if isinstance(item,basestring): s=unicode(item) # Replace \01, as this is used for embedded commands. #Also replace < and > as espeak handles xml s=s.translate({ord(u'\01'):None,ord(u'<'):u'<',ord(u'>'):u'>'}) textList.append(s) elif isinstance(item,speech.IndexCommand): textList.append("<mark name=\"%d\" />"%item.index) elif isinstance(item,speech.CharacterModeCommand): textList.append("<say-as interpret-as=\"characters\">" if item.state else "</say-as>") elif isinstance(item,speech.LangChangeCommand): if langChanged: textList.append("</voice>") textList.append("<voice xml:lang=\"%s\">"%(item.lang if item.lang else defaultLanguage).replace('_','-')) langChanged=True elif isinstance(item,speech.SpeechCommand): log.debugWarning("Unsupported speech command: %s"%item) else: log.error("Unknown speech: %s"%item) if langChanged: textList.append("</voice>") text=u"".join(textList) _espeak.speak(text)
def initialize(): config.addConfigDirsToPythonPackagePath(globalPlugins) for plugin in listPlugins(): try: runningPlugins.add(plugin()) except: log.error("Error initializing global plugin %r" % plugin, exc_info=True)
def _initBaseConf(self, factoryDefaults=False): fn = os.path.join(globalVars.appArgs.configPath, "nvda.ini") if factoryDefaults: profile = self._loadConfig(None) profile.filename = fn else: try: profile = self._loadConfig(fn) # a blank config returned if fn does not exist self.baseConfigError = False except: log.error("Error loading base configuration", exc_info=True) self.baseConfigError = True return self._initBaseConf(factoryDefaults=True) for key in self.BASE_ONLY_SECTIONS: # These sections are returned directly from the base config, so validate them here. try: sect = profile[key] except KeyError: profile[key] = {} # ConfigObj mutates this into a configobj.Section. sect = profile[key] sect.configspec = self.spec[key] profile.validate(self.validator, section=sect) self._profileCache[None] = profile self.profiles.append(profile) self._handleProfileSwitch()
def onEnableDisable(self, evt): index=self.addonsList.GetFirstSelected() if index<0: return addon=self.curAddons[index] shouldDisable = self._shouldDisable(addon) try: # Counterintuitive, but makes sense when context is taken into account. addon.enable(not shouldDisable) except addonHandler.AddonError: log.error("Couldn't change state for %s add-on"%addon.name, exc_info=True) if shouldDisable: # Translators: The message displayed when the add-on cannot be disabled. message = _("Could not disable the {description} add-on.").format( description=addon.manifest['summary']) else: # Translators: The message displayed when the add-on cannot be enabled. message = _("Could not enable the {description} add-on.").format( description=addon.manifest['summary']) gui.messageBox( message, # Translators: The title of a dialog presented when an error occurs. _("Error"), wx.OK | wx.ICON_ERROR ) return self.enableDisableButton.SetLabel(_("&Enable add-on") if shouldDisable else _("&Disable add-on")) self.refreshAddonsList(activeIndex=index)
def setSynth(name,isFallback=False): global _curSynth,_audioOutputDevice if name is None: _curSynth.terminate() _curSynth=None return True if name=='auto': # Default to OneCore on Windows 10 and above, and eSpeak on previous Operating Systems name='oneCore' if winVersion.winVersion.major>=10 else 'espeak' if _curSynth: _curSynth.cancel() _curSynth.terminate() prevSynthName = _curSynth.name _curSynth = None else: prevSynthName = None try: _curSynth=getSynthInstance(name) _audioOutputDevice=config.conf["speech"]["outputDevice"] if not isFallback: config.conf["speech"]["synth"]=name log.info("Loaded synthDriver %s"%name) return True except: log.error("setSynth", exc_info=True) if prevSynthName: setSynth(prevSynthName,isFallback=True) elif name not in ('espeak','silence'): setSynth('espeak',isFallback=True) elif name=='espeak': setSynth('silence',isFallback=True) return False
def speak(self,speechSequence): """ Speaks the given sequence of text and speech commands. This base implementation will fallback to making use of the old speakText and speakCharacter methods. But new synths should override this method to support its full functionality. @param speechSequence: a list of text strings and SpeechCommand objects (such as index and parameter changes). @type speechSequence: list of string and L{speechCommand} """ import speech lastIndex=None text="" origSpeakFunc=self.speakText speechSequence=iter(speechSequence) while True: item = next(speechSequence,None) if text and (item is None or isinstance(item,(speech.IndexCommand,speech.CharacterModeCommand))): # Either we're about to handle a command or this is the end of the sequence. # Speak the text since the last command we handled. origSpeakFunc(text,index=lastIndex) text="" lastIndex=None if item is None: # No more items. break if isinstance(item,basestring): # Merge the text between commands into a single chunk. text+=item elif isinstance(item,speech.IndexCommand): lastIndex=item.index elif isinstance(item,speech.CharacterModeCommand): origSpeakFunc=self.speakCharacter if item.state else self.speakText elif isinstance(item,speech.SpeechCommand): log.debugWarning("Unknown speech command: %s"%item) else: log.error("Unknown item in speech sequence: %s"%item)
def doCreatePortable(portableDirectory,copyUserConfig=False): d = gui.IndeterminateProgressDialog(gui.mainFrame, # Translators: The title of the dialog presented while a portable copy of NVDA is bieng created. _("Creating Portable Copy"), # Translators: The message displayed while a portable copy of NVDA is bieng created. _("Please wait while a portable copy of NVDA is created.")) try: gui.ExecAndPump(installer.createPortableCopy,portableDirectory,copyUserConfig) except Exception as e: log.error("Failed to create portable copy",exc_info=True) d.done() if isinstance(e,installer.RetriableFailure): # Translators: a message dialog asking to retry or cancel when NVDA portable copy creation fails message=_("NVDA is unable to remove or overwrite a file.") # Translators: the title of a retry cancel dialog when NVDA portable copy creation fails title=_("File in Use") if winUser.MessageBox(None,message,title,winUser.MB_RETRYCANCEL)==winUser.IDRETRY: return doCreatePortable(portableDirectory,copyUserConfig) # Translators: The message displayed when an error occurs while creating a portable copy of NVDA. # %s will be replaced with the specific error message. gui.messageBox(_("Failed to create portable copy: %s")%e, _("Error"), wx.OK | wx.ICON_ERROR) return d.done() # Translators: The message displayed when a portable copy of NVDA has been successfully created. # %s will be replaced with the destination directory. gui.messageBox(_("Successfully created a portable copy of NVDA at %s")%portableDirectory, _("Success"))
def executeGesture(self, gesture): """Perform the action associated with a gesture. @param gesture: The gesture to execute. @type gesture: L{InputGesture} @raise NoInputGestureAction: If there is no action to perform. """ if watchdog.isAttemptingRecovery: # The core is dead, so don't try to perform an action. # This lets gestures pass through unhindered where possible, # as well as stopping a flood of actions when the core revives. raise NoInputGestureAction script = gesture.script focus = api.getFocusObject() if focus.sleepMode is focus.SLEEP_FULL or (focus.sleepMode and not getattr(script, 'allowInSleepMode', False)): raise NoInputGestureAction wasInSayAll=False if gesture.isModifier: if not self.lastModifierWasInSayAll: wasInSayAll=self.lastModifierWasInSayAll=sayAllHandler.isRunning() elif self.lastModifierWasInSayAll: wasInSayAll=True self.lastModifierWasInSayAll=False else: wasInSayAll=sayAllHandler.isRunning() if wasInSayAll: gesture.wasInSayAll=True speechEffect = gesture.speechEffectWhenExecuted if speechEffect == gesture.SPEECHEFFECT_CANCEL: queueHandler.queueFunction(queueHandler.eventQueue, speech.cancelSpeech) elif speechEffect in (gesture.SPEECHEFFECT_PAUSE, gesture.SPEECHEFFECT_RESUME): queueHandler.queueFunction(queueHandler.eventQueue, speech.pauseSpeech, speechEffect == gesture.SPEECHEFFECT_PAUSE) if log.isEnabledFor(log.IO) and not gesture.isModifier: log.io("Input: %s" % gesture.logIdentifier) if self._captureFunc: try: if self._captureFunc(gesture) is False: return except: log.error("Error in capture function, disabling", exc_info=True) self._captureFunc = None if gesture.isModifier: raise NoInputGestureAction if config.conf["keyboard"]["speakCommandKeys"] and gesture.shouldReportAsCommand: queueHandler.queueFunction(queueHandler.eventQueue, speech.speakMessage, gesture.displayName) gesture.reportExtra() if script: scriptHandler.queueScript(script, gesture) return raise NoInputGestureAction
def formatForGUI(versionTuple): """Converts a version tuple to a string for displaying in the GUI Examples: - (2018, 1, 1) becomes "2018.1.1" - (2018, 1, 0) becomes "2018.1" - (0, 0, 0) becomes "0.0" """ try: year, major, minor = versionTuple return buildVersion.formatVersionForGUI(year, major, minor) except ( ValueError, # Too few/many values to unpack TypeError # versionTuple is None or some other incorrect type ): # This path should never be hit. But the appearance of "unknown" in the GUI is a better outcome # than an exception and unusable dialog. # Translators: shown when an addon API version string is unknown default = _("unknown") log.error("Unable to format versionTuple: {}".format( repr(versionTuple)), exc_info=True) return default
def setSynth(name, isFallback=False): global _curSynth, _audioOutputDevice if name is None: _curSynth.terminate() _curSynth = None return True if name == 'auto': name = defaultSynthPriorityList[0] if _curSynth: _curSynth.cancel() _curSynth.terminate() prevSynthName = _curSynth.name _curSynth = None else: prevSynthName = None try: _curSynth = getSynthInstance(name) _audioOutputDevice = config.conf["speech"]["outputDevice"] if not isFallback: config.conf["speech"]["synth"] = name log.info("Loaded synthDriver %s" % name) return True except: # noqa: E722 # Legacy bare except log.error("setSynth", exc_info=True) # As there was an error loading this synth: if prevSynthName: # There was a previous synthesizer, so switch back to that one. setSynth(prevSynthName, isFallback=True) else: # There was no previous synth, so fallback to the next available default synthesizer # that has not been tried yet. try: nextIndex = defaultSynthPriorityList.index(name) + 1 except ValueError: nextIndex = 0 if nextIndex < len(defaultSynthPriorityList): newName = defaultSynthPriorityList[nextIndex] setSynth(newName, isFallback=True) return False
def onPasteButton(self, event): index = self.symbolsListBox.GetSelection() if index == -1: # Translators: This is a message announced in complex symbols dialog. speakLater(300, _("No symbol selected")) return symbol = self.complexSymbolsList[index] symbolDescription = self.symbolsListBox.GetString(index) result = copyToClip(symbol) if not result: c = ord(symbol) log.error("error copyToClip symbol:%s (%s) code = %d" % ( self.symbolDescriptionList[index], symbol, c)) else: # Translators: This is a message announced in complex symbols dialog. msg = _("{0} pasted").format(self.symbolDescriptionList[index]) ui.message(msg) time.sleep(2.0) core.callLater(200, SendKey, "Control+v") from ..settings import _addonConfigManager _addonConfigManager.updateLastSymbolsList(symbolDescription, symbol) self.Close()
def registerAddonFileAssociation(slaveExe): try: # Create progID for NVDA ad-ons with winreg.CreateKeyEx(winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\Classes\\%s" % addonHandler.NVDA_ADDON_PROG_ID, 0, winreg.KEY_WRITE) as k: # Translators: A file extension label for NVDA add-on package. winreg.SetValueEx(k, None, 0, winreg.REG_SZ, _("NVDA add-on package")) with winreg.CreateKeyEx(k, "DefaultIcon", 0, winreg.KEY_WRITE) as k2: winreg.SetValueEx(k2, None, 0, winreg.REG_SZ, "@{slaveExe},1".format(slaveExe=slaveExe)) # Point the open verb to nvda_slave addons_installAddonPackage action with winreg.CreateKeyEx(k, "shell\\open\\command", 0, winreg.KEY_WRITE) as k2: winreg.SetValueEx(k2, None, 0, winreg.REG_SZ, u"\"{slaveExe}\" addons_installAddonPackage \"%1\"".format(slaveExe=slaveExe)) # Now associate addon extension to the created prog id. with winreg.CreateKeyEx(winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\Classes\\.%s" % addonHandler.BUNDLE_EXTENSION, 0, winreg.KEY_WRITE) as k: winreg.SetValueEx(k, None, 0, winreg.REG_SZ, addonHandler.NVDA_ADDON_PROG_ID) winreg.SetValueEx(k, "Content Type", 0, winreg.REG_SZ, addonHandler.BUNDLE_MIMETYPE) # Add NVDA to the "open With" list k2 = winreg.CreateKeyEx(k, "OpenWithProgids\\%s" % addonHandler.NVDA_ADDON_PROG_ID, 0, winreg.KEY_WRITE) winreg.CloseKey(k2) # Notify the shell that a file association has changed: shellapi.SHChangeNotify(shellapi.SHCNE_ASSOCCHANGED, shellapi.SHCNF_IDLIST, None, None) except WindowsError: log.error("Can not create addon file association.", exc_info=True)
def onExecuteScriptButton(self, evt): def callback(script, gestureOrgestureCls): self._executeScriptWaitingTimer = None wx.CallLater(200, speech.cancelSpeech) wx.CallLater(500, self._executeScript, script, gestureOrgestureCls, self.repeatCount) self.Destroy() self.repeatCount = self.repeatCount + 1 if self._executeScriptWaitingTimer is not None else 0 if self._executeScriptWaitingTimer is not None: self._executeScriptWaitingTimer.Stop() self._executeScriptWaitingTimer = None selectedItems = self.tree.getSelectedItemData() if selectedItems is None: item = None else: # get the leaf of the selection item = next((item for item in reversed(selectedItems) if item is not None), None) if not item: return scriptInfo = item.scriptInfo script = self.getScript(item) if not script: log.error("no script to run: %s, %s, %s" % ( scriptInfo.scriptName, scriptInfo.className, scriptInfo.moduleName)) return try: gestureCls = inputCore._getGestureClsForIdentifier(scriptInfo.gestures[0]) except Exception: gestureCls = KeyboardInputGesture gesture = None if gestureCls == KeyboardInputGesture and len(scriptInfo.gestures): identifier = scriptInfo.gestures[0] key = identifier.split(":", 1)[1] gesture = KeyboardInputGesture.fromName(key) gestureOrGestureCls = gesture if gesture else gestureCls from ..settings import _addonConfigManager delay = _addonConfigManager.getMaximumDelayBetweenSameScript() self._executeScriptWaitingTimer = wx.CallLater(delay, callback, script, gestureOrGestureCls)
def OnExportClick(self, evt): with wx.FileDialog(self, message=_("Export file..."), defaultDir=base_path, defaultFile="export.rule", wildcard="rule files (*.rule)|*.rule", style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) as entryDialog: if entryDialog.ShowModal() != wx.ID_OK: return pathname = entryDialog.GetPath() temp = {} for key, mathrule in self.mathrules: temp[key] = mathrule temp['node'] = self.A8M_mathrule['node'] temp['none'] = self.A8M_mathrule['none'] try: A8M_PM.save_math_rule(temp, path=pathname) except IOError as e: log.error("Error saving user unicode dictionary: %s" % e)
def _bg(self): success = False for url in self.urls: try: self._download(url) except: log.error("Error downloading %s" % url, exc_info=True) else: #Successfully downloaded or canceled if not self._shouldCancel: success = True break else: # None of the URLs succeeded. self._guiExec(self._error) return if not success: try: os.remove(self.destPath) except OSError: pass return self._guiExec(self._downloadSuccess)
def _getProvidersFromFileSystem(): for loader, moduleName, isPkg in pkgutil.iter_modules(visionEnhancementProviders.__path__): if moduleName.startswith('_'): continue try: # Get each piece of info in a new statement so any exceptions raised identifies the line correctly. provider = _getProviderClass(moduleName) providerSettings = provider.getSettings() providerId = providerSettings.getId() displayName = providerSettings.getDisplayName() yield providerInfo.ProviderInfo( providerId=providerId, moduleName=moduleName, displayName=displayName, providerClass=provider ) except Exception: # Purposely catch everything as we don't know what a provider might raise. log.error( f"Error while importing vision enhancement provider module {moduleName}", exc_info=True ) continue
def callback(wav,numsamples,event): try: global player, isSpeaking, _numBytesPushed if not isSpeaking: return CALLBACK_ABORT_SYNTHESIS indexes = [] for e in event: if e.type==espeakEVENT_MARK: indexNum = int(decodeEspeakString(e.id.name)) # e.audio_position is ms since the start of this utterance. # Convert to bytes since the start of the utterance. BYTES_PER_SAMPLE = 2 MS_PER_SEC = 1000 bytesPerMS = player.samplesPerSec * BYTES_PER_SAMPLE // MS_PER_SEC indexByte = e.audio_position * bytesPerMS # Subtract bytes in the utterance that have already been handled # to give us the byte offset into the samples for this callback. indexByte -= _numBytesPushed indexes.append((indexNum, indexByte)) elif e.type==espeakEVENT_LIST_TERMINATED: break if not wav: player.idle() onIndexReached(None) isSpeaking = False return CALLBACK_CONTINUE_SYNTHESIS wav = string_at(wav, numsamples * sizeof(c_short)) if numsamples>0 else b"" prevByte = 0 for indexNum, indexByte in indexes: player.feed(wav[prevByte:indexByte], onDone=lambda indexNum=indexNum: onIndexReached(indexNum)) prevByte = indexByte if not isSpeaking: return CALLBACK_ABORT_SYNTHESIS player.feed(wav[prevByte:]) _numBytesPushed += len(wav) return CALLBACK_CONTINUE_SYNTHESIS except: log.error("callback", exc_info=True)
def callback(wav,numsamples,event): try: global player, isSpeaking, lastIndex if not isSpeaking: return 1 for e in event: if e.type==espeakEVENT_MARK: lastIndex=int(e.id.name) elif e.type==espeakEVENT_LIST_TERMINATED: break if not wav: player.idle() isSpeaking = False return 0 if numsamples > 0: try: player.feed(string_at(wav, numsamples * sizeof(c_short))) except: log.debugWarning("Error feeding audio to nvWave",exc_info=True) return 0 except: log.error("callback", exc_info=True)
def showUnknownCompatDialog(): from gui import addonGui, mainFrame, runScriptModalDialog if any(getAddonsWithUnknownCompatibility()): try: incompatibleAddonsDlg = addonGui.IncompatibleAddonsDialog(parent=mainFrame) except RuntimeError: log.error("Unable to open IncompatibleAddonsDialog", exc_info=True) return else: return unknownCompatAddons = incompatibleAddonsDlg.unknownCompatibilityAddonsList def afterDialog(res): # we may need to change the enabled addons / restart nvda here shouldPromptRestart = False for addon in unknownCompatAddons: if isAddonConsideredCompatible(addon): addon.enable(True) shouldPromptRestart = True saveState() if shouldPromptRestart: addonGui.promptUserForRestart() runScriptModalDialog(incompatibleAddonsDlg, afterDialog)
def onInstallDragonCommands(evt): #Translators: Warning about having custom commands already. goAhead = gui.messageBox( _("If you are on a computer with shared commands, and you have multiple users using these commands, this will override them. Please do not proceed unless you are sure you aren't sharing commands over a network. if you are, please read \"Importing Commands Into a Shared System\" in the Dictation Bridge documentation for manual steps.\nDo you want to proceed?" ), #Translators: Warning dialog title. _("Warning: Potentially Dangerous Opperation Will be Performed"), wx.YES | wx.NO) if goAhead == wx.NO: return dialog = gui.IndeterminateProgressDialog( gui.mainFrame, #Translators: Title for a dialog shown when Dragon Commands are being installed! _("Dragon Command Installation"), #Translators: Message shown in the progress dialog for dragon command installation. _("Please wait while Dragon commands are installed.")) try: gui.ExecAndPump(_onInstallDragonCommands) except: #Catch all, because if this fails, bad bad bad. log.error("DictationBridge commands failed to install!", exc_info=True) finally: dialog.done()
def _loadBuffer(self): try: if log.isEnabledFor(log.DEBUG): startTime = time.time() self.VBufHandle = NVDAHelper.localLib.VBuf_createBuffer( self.rootNVDAObject.appModule.helperLocalBindingHandle, self.rootDocHandle, self.rootID, self.backendName) if not self.VBufHandle: raise RuntimeError("Could not remotely create virtualBuffer") except: log.error("", exc_info=True) queueHandler.queueFunction(queueHandler.eventQueue, self._loadBufferDone, success=False) return if log.isEnabledFor(log.DEBUG): log.debug( "Buffer load took %.3f sec, %d chars" % (time.time() - startTime, NVDAHelper.localLib.VBuf_getTextLength(self.VBufHandle))) queueHandler.queueFunction(queueHandler.eventQueue, self._loadBufferDone)
def showHelp(helpId: str): """Display the corresponding section of the user guide when either the Help button in an NVDA dialog is pressed or the F1 key is pressed on a recognized control. """ import ui import queueHandler if not helpId: # Translators: Message indicating no context sensitive help is available for the control or dialog. noHelpMessage = _("No help available here.") queueHandler.queueFunction(queueHandler.eventQueue, ui.message, noHelpMessage) return helpFile = documentationUtils.getDocFilePath("userGuide.html") if helpFile is None: # Translators: Message shown when trying to display context sensitive help, # indicating that the user guide could not be found. noHelpMessage = _("No user guide found.") log.debugWarning("No user guide found: possible cause - running from source without building user docs") queueHandler.queueFunction(queueHandler.eventQueue, ui.message, noHelpMessage) return log.debug(f"Opening help: helpId = {helpId}, userGuidePath: {helpFile}") nvdaTempDir = os.path.join(tempfile.gettempdir(), "nvda") if not os.path.exists(nvdaTempDir): os.mkdir(nvdaTempDir) contextHelpRedirect = os.path.join(nvdaTempDir, "contextHelp.html") try: # a redirect is necessary because not all browsers support opening a fragment URL from the command line. writeRedirect(helpId, helpFile, contextHelpRedirect) except Exception: log.error("Unable to write context help redirect file.", exc_info=True) return try: os.startfile(f"file://{contextHelpRedirect}") except Exception: log.error("Unable to launch context help.", exc_info=True)
def startRecognition(self, current_source, current_engine_type): try: engine = self.getCurrentEngine(current_engine_type) repeatCount = scriptHandler.getLastScriptRepeatCount() textResultWhenRepeatGesture = not config.conf["onlineOCRGeneral"][ "swapRepeatedCountEffect"] if not current_source == "clipboardImage" and self.isScreenCurtainRunning( ): ui.message( _("Please disable screen curtain before recognition.")) return if repeatCount == 0: if not engine: ui.message(_("Cannot get recognition engine")) return engine.text_result = textResultWhenRepeatGesture if current_source == "navigatorObject": recogUi.recognizeNavigatorObject(engine) return else: imageInfo, recognizeImage = self.getImageFromSource( current_source) if not recognizeImage: ui.message( _("Clipboard URL source is not implemented.")) return pixels = recognizeImage.tobytes("raw", "BGRX") # Translators: Reported when content recognition begins. ui.message(_("Recognizing")) engine.recognize(pixels, imageInfo, recogUi._recogOnResult) elif repeatCount == 1: engine.text_result = not textResultWhenRepeatGesture except Exception as e: from logHandler import log log.error(getattr(e, 'message', repr(e))) ui.message( _("Error occurred, when trying to start recognition, Please change source or engine and try again." ))
def doCreatePortable(portableDirectory,copyUserConfig=False,silent=False,startAfterCreate=False): d = gui.IndeterminateProgressDialog(gui.mainFrame, # Translators: The title of the dialog presented while a portable copy of NVDA is bieng created. _("Creating Portable Copy"), # Translators: The message displayed while a portable copy of NVDA is bieng created. _("Please wait while a portable copy of NVDA is created.")) try: gui.ExecAndPump(installer.createPortableCopy,portableDirectory,copyUserConfig) except Exception as e: log.error("Failed to create portable copy",exc_info=True) d.done() if isinstance(e,installer.RetriableFailure): # Translators: a message dialog asking to retry or cancel when NVDA portable copy creation fails message=_("NVDA is unable to remove or overwrite a file.") # Translators: the title of a retry cancel dialog when NVDA portable copy creation fails title=_("File in Use") if winUser.MessageBox(None,message,title,winUser.MB_RETRYCANCEL)==winUser.IDRETRY: return doCreatePortable(portableDirectory,copyUserConfig,silent,startAfterCreate) # Translators: The message displayed when an error occurs while creating a portable copy of NVDA. # %s will be replaced with the specific error message. gui.messageBox(_("Failed to create portable copy: %s")%e, _("Error"), wx.OK | wx.ICON_ERROR) return d.done() if not silent: # Translators: The message displayed when a portable copy of NVDA has been successfully created. # %s will be replaced with the destination directory. gui.messageBox(_("Successfully created a portable copy of NVDA at %s")%portableDirectory, _("Success")) if silent or startAfterCreate: newNVDA = None if startAfterCreate: newNVDA = core.NewNVDAInstance( filePath=os.path.join(portableDirectory, 'nvda.exe'), ) if not core.triggerNVDAExit(newNVDA): log.error("NVDA already in process of exiting, this indicates a logic error.")
def __init__(self): super(BrailleInputHandler, self).__init__() # #6140: Migrate to new table names as smoothly as possible. tableName = config.conf["braille"]["inputTable"] newTableName = brailleTables.RENAMED_TABLES.get(tableName) if newTableName: tableName = config.conf["braille"]["inputTable"] = newTableName try: self._table = brailleTables.getTable(tableName) except LookupError: log.error("Invalid table: %s" % tableName) self._table = brailleTables.getTable(FALLBACK_TABLE) #: A buffer of entered braille cells so that state set by previous cells can be maintained; #: e.g. capital and number signs. self.bufferBraille = [] #: The text translated so far from the cells in L{bufferBraille}. self.bufferText = u"" #: Indexes of cells which produced text. #: For example, this includes letters and numbers, but not number signs, #: since a number sign by itself doesn't produce text. #: This is used when erasing cells to determine when to backspace an actual character. self.cellsWithText = set() #: The cells in L{bufferBraille} that have not yet been translated #: or were translated but did not produce any text. #: This is used to show these cells to the user while they're entering braille. #: This is a string of Unicode braille. self.untranslatedBraille = "" #: The position in L{brailleBuffer} where untranslated braille begins. self.untranslatedStart = 0 #: The user's cursor position within the untranslated braille. #: This enables the user to move within the untranslated braille. self.untranslatedCursorPos = 0 #: The time at which uncontracted characters were sent to the system. self._uncontSentTime = None #: The modifiers currently being held virtually to be part of the next braille input gesture. self.currentModifiers = set() config.post_configProfileSwitch.register( self.handlePostConfigProfileSwitch)
def __init__(self, port="Auto"): log.info("BAUM VarioPro Init") super().__init__() self.numCells = 0 self._dev = None self.bp_trans_prev_byte = 0 # BAUM protocol transport layer (ESC dedoubling) self.mainModule = None self.statusModule = None self.telephoneModule = None self.connected_modules = {} try: if port == "auto": tryPorts = self._getAutoPorts( hwPortUtils.listComPorts(onlyAvailable=True)) else: tryPorts = ((port, "serial"), ) for port, portType in tryPorts: if self._dev: if self._dev.is_open(): self._dev.close() self._dev = hwIo.Serial(port, baudrate=BAUD_RATE, timeout=self.timeout, writeTimeout=self.timeout, onReceive=self._onReceive) self.vp_query_modules() for i in range(10): # wait for dev arrival self._dev.waitForRead(self.timeout) if self.numCells: break else: log.error("Device arrival timeout") except Exception as e: log.error(e) raise RuntimeError("No BAUM VarioPro display found")
def terminate(): import brailleViewer brailleViewer.destroyBrailleViewer() for instance, state in gui.SettingsDialog._instances.items(): if state is gui.SettingsDialog._DIALOG_DESTROYED_STATE: log.error( "Destroyed but not deleted instance of settings dialog exists: {!r}".format(instance) ) else: log.debug("Exiting NVDA with an open settings dialog: {!r}".format(instance)) global mainFrame # This is called after the main loop exits because WM_QUIT exits the main loop # without destroying all objects correctly and we need to support WM_QUIT. # Therefore, any request to exit should exit the main loop. safeAppExit() # #4460: We need another iteration of the main loop # so that everything (especially the TaskBarIcon) is cleaned up properly. # ProcessPendingEvents doesn't seem to work, but MainLoop does. # Because the top window gets destroyed, # MainLoop thankfully returns pretty quickly. wx.GetApp().MainLoop() mainFrame = None
def moveToCell(self, type, whichOne ): row = Row(self, self.row) column = Column(self, self.column) if type == "row": if (whichOne in ["first", "previous"] and column.isFirst) or (whichOne in ["last", "next"] and column.isLast): #table's limit ui.message(_("table's limit")) return False newCell = row.getCell(whichOne, self.columnIndex) elif type == "column": if (whichOne in ["first", "previous"] and row.isFirst) or (whichOne in ["last", "next"] and row.isLast): #table's limit ui.message(_("table's limit")) return False # move cell in column newCell = column.getCell(whichOne, self.rowIndex) else: # error log.error("moveToCell: invalid parameter %s" %type) if newCell: newCell.goTo() return newCell return False
def getObjectByHierarchy(oParent, iHierarchy): try: sHierarchy = _audacityHierarchyID[iHierarchy] except: return None try: o = oParent if len(sHierarchy): Hierarchy = sHierarchy.split("|") for i in Hierarchy: iChild = int(i) if o and iChild <= o.childCount: o = o.getChild(iChild) else: # error, no child return None return o except: log.error("error getObjectByHierarchy: %s, parent: %s" % (sHierarchy, oParent.name)) return None
def triggerNVDAExit(newNVDA: Optional[NewNVDAInstance] = None) -> bool: """ Used to safely exit NVDA. If a new instance is required to start after exit, queue one by specifying instance information with `newNVDA`. @return: True if this is the first call to trigger the exit, and the shutdown event was queued. """ from gui.message import isInMessageBox import queueHandler global _hasShutdownBeenTriggered with _shuttingDownFlagLock: safeToExit = not isInMessageBox() if not safeToExit: log.error("NVDA cannot exit safely, ensure open dialogs are closed") return False elif _hasShutdownBeenTriggered: log.debug("NVDA has already been triggered to exit safely.") return False else: # queue this so that the calling process can exit safely (eg a Popup menu) queueHandler.queueFunction(queueHandler.eventQueue, _doShutdown, newNVDA) _hasShutdownBeenTriggered = True log.debug("_doShutdown has been queued") return True
def nextLine(self): try: dest = self._readingInfo.copy() moved = dest.move(self._getReadingUnit(), 1) if not moved: if self.allowPageTurns and isinstance( dest.obj, textInfos.DocumentWithPageTurns): try: dest.obj.turnPage() except RuntimeError: pass else: dest = dest.obj.makeTextInfo(textInfos.POSITION_FIRST) else: # no page turn support return dest.collapse() self._setCursor(dest) sayCurrentLine() except BaseException as e: log.error("Error with scroll function patch, disabling: %s" % e) configBE.conf["patch"]["scrollBraille"] = False configBE.conf["general"]["speakScroll"] = False core.restart()
def findBestAPIClass(cls, kwargs, relation=None): """ Finds out the highest-level APIClass this object can get to given these kwargs, and updates the kwargs and returns the APIClass. @param relation: the relationship of a possible new object of this type to another object creating it (e.g. parent). @param type: string @param kwargs: the arguments necessary to construct an object of the class this method was called on. @type kwargs: dictionary @returns: the new APIClass @rtype: DynamicNVDAObjectType """ newAPIClass = cls if 'getPossibleAPIClasses' in newAPIClass.__dict__: for possibleAPIClass in newAPIClass.getPossibleAPIClasses( kwargs, relation=relation): if 'kwargsFromSuper' not in possibleAPIClass.__dict__: log.error( "possible API class %s does not implement kwargsFromSuper" % possibleAPIClass) continue if possibleAPIClass.kwargsFromSuper(kwargs, relation=relation): return possibleAPIClass.findBestAPIClass(kwargs, relation=relation) return newAPIClass if newAPIClass is not NVDAObject else None
def completeRemove(self,runUninstallTask=True): if runUninstallTask: try: # #2715: The add-on must be added to _availableAddons here so that # translations can be used in installTasks module. _availableAddons[self.path] = self self.runInstallTask("onUninstall") except: log.error("task 'onUninstall' on addon '%s' failed"%self.name,exc_info=True) finally: del _availableAddons[self.path] tempPath=tempfile.mktemp(suffix=DELETEDIR_SUFFIX,dir=os.path.dirname(self.path)) try: os.rename(self.path,tempPath) except (WindowsError,IOError): raise RuntimeError("Cannot rename add-on path for deletion") shutil.rmtree(tempPath,ignore_errors=True) if os.path.exists(tempPath): log.error("Error removing addon directory %s, deferring until next NVDA restart"%self.path) # clean up the addons state log.debug("removing addon {} from _disabledAddons".format(self.name)) _disabledAddons.discard(self.name) saveState()
def executeMouseMoveEvent(x,y): global currentMouseWindow desktopObject=api.getDesktopObject() screenLeft,screenTop,screenWidth,screenHeight=desktopObject.location x=min(max(screenLeft,x),(screenLeft+screenWidth)-1) y=min(max(screenTop,y),(screenTop+screenHeight)-1) if config.conf["mouse"]["audioCoordinatesOnMouseMove"]: playAudioCoordinates(x,y,screenWidth,screenHeight,config.conf['mouse']['audioCoordinates_detectBrightness'],config.conf['mouse']['audioCoordinates_blurFactor']) oldMouseObject=api.getMouseObject() mouseObject=desktopObject.objectFromPoint(x,y) while mouseObject and mouseObject.beTransparentToMouse: mouseObject=mouseObject.parent if not mouseObject: return if oldMouseObject==mouseObject: mouseObject=oldMouseObject else: api.setMouseObject(mouseObject) try: eventHandler.executeEvent("mouseMove",mouseObject,x=x,y=y) oldMouseObject=mouseObject except: log.error("api.notifyMouseMoved", exc_info=True)
def __init__( self, targetDll: str, importDll: str, funcName: str, newFunction # result of ctypes.WINFUNCTYPE ): # dllImportTableHooks_hookSingle expects byte strings. try: self._hook=NVDAHelper.localLib.dllImportTableHooks_hookSingle( targetDll.encode("mbcs"), importDll.encode("mbcs"), funcName.encode("mbcs"), newFunction ) except UnicodeEncodeError: log.error("Error encoding FunctionHooker input parameters", exc_info=True) self._hook = None if self._hook: log.debug(f"Hooked {funcName}") else: log.error(f"Could not hook {funcName}") raise RuntimeError(f"Could not hook {funcName}")
def speak(self, speechSequence): textList = [] charMode = False for item in speechSequence: if isinstance(item, basestring): textList.append(item.replace('\\', '\\\\')) elif isinstance(item, speech.IndexCommand): textList.append("\\mrk=%d\\" % item.index) elif isinstance(item, speech.CharacterModeCommand): textList.append("\\RmS=1\\" if item.state else "\\RmS=0\\") charMode = item.state elif isinstance(item, speech.SpeechCommand): log.debugWarning("Unsupported speech command: %s" % item) else: log.error("Unknown speech: %s" % item) if charMode: # Some synths stay in character mode if we don't explicitly disable it. textList.append("\\RmS=0\\") text = "".join(textList) flags = TTSDATAFLAG_TAGGED self._ttsCentral.TextData(VOICECHARSET.CHARSET_TEXT, flags, TextSDATA(text), self._bufSinkPtr, ITTSBufNotifySink._iid_)
def loadBasicSymbolCategories(self): symbol_description_separator = "\t" curCategory = None fileName = self.getSymbolCategoriesDicPath() if fileName is None: return False symbolCategories = {} orderedSymbols = {} with codecs.open(fileName, "r", "utf_8_sig", errors="replace") as f: for line in f: if line.isspace() or line.startswith("#"): # Whitespace or comment. continue line = line.rstrip("\r\n") if self.isCategorieName(line): curCategory = line[1:-1] self.basicOrderedSymbolCategoryNames.append(curCategory) symbolCategories[curCategory] = {} orderedSymbols[curCategory] = [] continue tempLine = line.split(symbol_description_separator) if (len(tempLine) == 2) and tempLine[0] and tempLine[1]: symbol = tempLine[0] description = tempLine[1] if curCategory is None: log.error("Symbol without category: %s" % line) continue symbolCategories[curCategory][symbol] = description orderedSymbols[curCategory].append(symbol) else: log.error("Symbol and description incorrect: %s" % line) if len(symbolCategories) == 0: return False self.basicSymbolCategoriesDic = symbolCategories.copy() self.orderedSymbols = orderedSymbols.copy() return True
def onRunCOMRegistrationFixesCommand(self, evt): if isModalMessageBoxActive(): return if messageBox( # Translators: A message to warn the user when starting the COM Registration Fixing tool _("You are about to run the COM Registration Fixing tool. This tool will try to fix common system problems that stop NVDA from being able to access content in many programs including Firefox and Internet Explorer. This tool must make changes to the System registry and therefore requires administrative access. Are you sure you wish to proceed?" ), # Translators: The title of the warning dialog displayed when launching the COM Registration Fixing tool _("Warning"), wx.YES | wx.NO | wx.ICON_WARNING, self) == wx.NO: return progressDialog = IndeterminateProgressDialog( mainFrame, # Translators: The title of the dialog presented while NVDA is running the COM Registration fixing tool _("COM Registration Fixing Tool"), # Translators: The message displayed while NVDA is running the COM Registration fixing tool _("Please wait while NVDA tries to fix your system's COM registrations." )) try: import systemUtils systemUtils.execElevated(config.SLAVE_FILENAME, ["fixCOMRegistrations"]) except: log.error("Could not execute fixCOMRegistrations command", exc_info=True) progressDialog.done() del progressDialog messageBox( _( # Translators: The message displayed when the COM Registration Fixing tool completes. "The COM Registration Fixing tool has finished. " "It is highly recommended that you restart your computer now, to make sure the changes take full effect." ), # Translators: The title of a dialog presented when the COM Registration Fixing tool is complete. _("COM Registration Fixing Tool"), wx.OK)