def script_decorator(decoratedScript): # Decoratable scripts are functions, not bound instance methods. if not isinstance(decoratedScript, types.FunctionType): log.warning("Using the script decorator is unsupported for %r" % decoratedScript, stack_info=True) return decoratedScript if not decoratedScript.__name__.startswith("script_"): log.warning( "Can't apply script decorator to %r which name does not start with 'script_'" % decoratedScript.__name__, stack_info=True) return decoratedScript decoratedScript.__doc__ = description if category is not None: decoratedScript.category = category if gesture is not None: gestures.append(gesture) if gestures: decoratedScript.gestures = gestures decoratedScript.canPropagate = canPropagate decoratedScript.bypassInputHelp = bypassInputHelp if resumeSayAllMode is not None: decoratedScript.resumeSayAllMode = resumeSayAllMode return decoratedScript
def loadSettings(self, onlyChanged=False): # Method override due to specific logic needed when changing a voice. c=config.conf[self._configSection][self.name] if self.isSupported("voice"): voice=c.get("voice",None) if not onlyChanged or self.voice!=voice: try: changeVoice(self,voice) except: log.warning("Invalid voice: %s" % voice) # Update the configuration with the correct voice. c["voice"]=self.voice # We need to call changeVoice here so that required initialisation can be performed. changeVoice(self,self.voice) elif not onlyChanged: changeVoice(self,None) for s in self.supportedSettings: if s.id == "voice" or c[s.id] is None: continue val=c[s.id] if onlyChanged and getattr(self,s.id)==val: continue setattr(self,s.id, val) log.debug( ( "Loaded changed settings for SynthDriver {}" if onlyChanged else "Loaded settings for SynthDriver {}" ).format(self.name))
def script_decorator(decoratedScript): # Scripts are unbound instance methods in python 2 and functions in python 3. # Therefore, we use inspect.isroutine to check whether a script is either a function or instance method. if not inspect.isroutine(decoratedScript): log.warning("Using the script decorator is unsupported for %r" % decoratedScript, stack_info=True) return decoratedScript if not decoratedScript.__name__.startswith("script_"): log.warning( "Can't apply script decorator to %r which name does not start with 'script_'" % decoratedScript.__name__, stack_info=True) return decoratedScript decoratedScript.__doc__ = description if category is not None: decoratedScript.category = category if gesture is not None: gestures.append(gesture) if gestures: decoratedScript.gestures = gestures decoratedScript.canPropagate = canPropagate decoratedScript.bypassInputHelp = bypassInputHelp if resumeSayAllMode is not None: decoratedScript.resumeSayAllMode = resumeSayAllMode return decoratedScript
def __get__(self, instance, owner): if isinstance(self.fget, classmethod): log.warning("Class properties do not support caching") return self.fget.__get__(instance, owner)() elif not instance: return self return instance._getPropertyViaCache(self.fget)
def loadSettings(self, onlyChanged=False): # Method override due to specific logic needed when changing a voice. c = config.conf[self._configSection][self.name] if self.isSupported("voice"): voice = c.get("voice", None) if not onlyChanged or self.voice != voice: try: changeVoice(self, voice) except: log.warning("Invalid voice: %s" % voice) # Update the configuration with the correct voice. c["voice"] = self.voice # We need to call changeVoice here so that required initialisation can be performed. changeVoice(self, self.voice) elif not onlyChanged: changeVoice(self, None) for s in self.supportedSettings: if s.id == "voice" or c[s.id] is None: continue val = c[s.id] if onlyChanged and getattr(self, s.id) == val: continue setattr(self, s.id, val) log.debug( ("Loaded changed settings for SynthDriver {}" if onlyChanged else "Loaded settings for SynthDriver {}").format(self.name))
def getFileVersionInfo(name, *attributes): """Gets the specified file version info attributes from the provided file.""" if not isinstance(name, text_type): raise TypeError("name must be an unicode string") if not os.path.exists(name): raise RuntimeError("The file %s does not exist" % name) fileVersionInfo = {} # Get size needed for buffer (0 if no info) size = ctypes.windll.version.GetFileVersionInfoSizeW(name, None) if not size: raise RuntimeError("No version information") # Create buffer res = ctypes.create_string_buffer(size) # Load file informations into buffer res ctypes.windll.version.GetFileVersionInfoW(name, None, size, res) r = ctypes.c_uint() l = ctypes.c_uint() # Look for codepages ctypes.windll.version.VerQueryValueW(res, u'\\VarFileInfo\\Translation', ctypes.byref(r), ctypes.byref(l)) if not l.value: raise RuntimeError("No codepage") # Take the first codepage (what else ?) codepage = array.array('H', ctypes.string_at(r.value, 4)) codepage = "%04x%04x" % tuple(codepage) for attr in attributes: if not ctypes.windll.version.VerQueryValueW(res, u'\\StringFileInfo\\%s\\%s' % (codepage, attr), ctypes.byref(r), ctypes.byref(l) ): log.warning("Invalid or unavailable version info attribute for %r: %s" % (name, attr)) fileVersionInfo[attr] = None else: fileVersionInfo[attr] = ctypes.wstring_at(r.value, l.value-1) return fileVersionInfo
def _getFocusLossCancellableSpeechCommand( obj, reason: controlTypes.OutputReason ) -> Optional[_CancellableSpeechCommand]: if reason != controlTypes.REASON_FOCUS or not speech.manager._shouldCancelExpiredFocusEvents(): return None from NVDAObjects import NVDAObject if not isinstance(obj, NVDAObject): log.warning("Unhandled object type. Expected all objects to be descendant from NVDAObject") return None previouslyHadFocus: bool = getattr( obj, WAS_GAIN_FOCUS_OBJ_ATTR_NAME, False ) def isSpeechStillValid(): from eventHandler import lastQueuedFocusObject isLastFocusObj: bool = obj is lastQueuedFocusObject stillValid = isLastFocusObj or not previouslyHadFocus log._speechManagerDebug( "checked if valid (isLast: %s, previouslyHad: %s): %s", isLastFocusObj, previouslyHadFocus, obj.name ) return stillValid return _CancellableSpeechCommand(isSpeechStillValid)
def loadSettings(self, onlyChanged=False): c=config.conf["speech"][self.name] if self.isSupported("voice"): voice=c.get("voice",None) if not onlyChanged or self.voice!=voice: try: changeVoice(self,voice) except: log.warning("Invalid voice: %s" % voice) # Update the configuration with the correct voice. c["voice"]=self.voice # We need to call changeVoice here so that required initialisation can be performed. changeVoice(self,self.voice) elif not onlyChanged: changeVoice(self,None) for s in self.supportedSettings: if s.name=="voice" or c[s.name] is None: continue val=c[s.name] if onlyChanged and getattr(self,s.name)==val: continue setattr(self,s.name,val) if self.name == "sapi4" and ("rate" in c) and c["rate"] == 101: c["rate"] = 100 config.conf.save()
def script_decorator(decoratedScript): # Scripts are unbound instance methods in python 2 and functions in python 3. # Therefore, we use inspect.isroutine to check whether a script is either a function or instance method. if not inspect.isroutine(decoratedScript): log.warning( "Using the script decorator is unsupported for %r" % decoratedScript, stack_info=True ) return decoratedScript if not decoratedScript.__name__.startswith("script_"): log.warning( "Can't apply script decorator to %r which name does not start with 'script_'" % decoratedScript.__name__, stack_info=True ) return decoratedScript decoratedScript.__doc__ = description if category is not None: decoratedScript.category = category if gesture is not None: gestures.append(gesture) if gestures: decoratedScript.gestures = gestures decoratedScript.canPropagate = canPropagate decoratedScript.bypassInputHelp = bypassInputHelp if resumeSayAllMode is not None: decoratedScript.resumeSayAllMode = resumeSayAllMode return decoratedScript
def initialize(): global state, _stateFilename, autoChecker _stateFilename = os.path.join(globalVars.appArgs.configPath, "updateCheckState.pickle") try: state = cPickle.load(file(_stateFilename, "r")) except: log.debugWarning("Couldn't retrieve update state", exc_info=True) # Defaults. state = { "lastCheck": 0, "dontRemindVersion": None, } _setStateToNone(state) # check the pending version against the current version # and make sure that pendingUpdateFile and pendingUpdateVersion are part of the state dictionary. if "pendingUpdateVersion" not in state or state["pendingUpdateVersion"] == versionInfo.version: _setStateToNone(state) # remove all update files except the one that is currently pending (if any) try: for fileName in os.listdir(storeUpdatesDir): f=os.path.join(storeUpdatesDir, fileName) if f != state["pendingUpdateFile"]: os.remove(f) log.debug("Update file %s removed"%f) except OSError: log.warning("Unable to remove old update file %s"%f, exc_info=True) if not globalVars.appArgs.launcher and (config.conf["update"]["autoCheck"] or (config.conf["update"]["startupNotification"] and isPendingUpdate())): autoChecker = AutoUpdateChecker()
def __init__(self, addonName=None, updateInfosFile=None, auto=True, releaseToDev=False): self.addon = None if addonName is None: # get current add-on self.addon = addonHandler.getCodeAddon() else: # find add-on in available add-ons for addon in addonHandler.getAvailableAddons(): if addon.manifest["name"] == addonName: self.addon = addon break if self.addon is None: log.warning("CheckForAddonUpdate: no add-on") return log.warning("Check for %s add-on update" % self.addon.manifest["name"]) self.addonSummary = self.addon.manifest["summary"] self.auto = auto self.releaseToDev = releaseToDev self.destPath = tempfile.mktemp(prefix="myAddons-", suffix=".latest") self.updateInfosFile = updateInfosFile self.title = _("{summary} - update").format(summary=self.addonSummary) # get latest addon update infos latestUpdateInfos = self.getLatestUpdateInfos(self.updateInfosFile) if latestUpdateInfos is None: return # check if service is in maintenance if latestUpdateInfos.get("inMaintenance") and latestUpdateInfos[ "inMaintenance"]: # noqa:E501 if auto: return gui.messageBox( _("The service is temporarily under maintenance. Please, try again later." ), # noqa:E501 self.title, wx.OK | wx.ICON_INFORMATION) return addonUpdateInfos = latestUpdateInfos.get(self.addon.manifest["name"]) if addonUpdateInfos is None: # no update for this add-on wx.CallAfter(self.upToDateDialog, self.auto) return newUpdate = self.checkForNewUpdate(addonUpdateInfos) if newUpdate is None: self.upToDateDialog(self.auto) return (version, url, minimumNVDAVersion, lastTestedNVDAVersion) = newUpdate if not checkCompatibility(self.addon.manifest["summary"], minimumNVDAVersion, lastTestedNVDAVersion, auto): return url = "{baseURL}/{url}/{addonName}-{version}.nvda-addon".format( baseURL=latestUpdateInfos["baseURL"], addonName=self.addon.manifest["name"], url=url, version=version) self.availableUpdateDialog(version, url)
def process_packet(self, pkt): # NOTE: pkt is ESC dedoubled if pkt[0] == BAUM_VP_DEVICE_DETECTION: if len(pkt) == 11: if pkt[10] == 0x01: try: id = tuple(pkt[2:6]) type = tuple(pkt[2:4]) # instantiate the module from the appropriate class based on the module id module = VP_MODULE_CLASSES_MAP[type](self, id) self.connected_modules[module.module_id] = module self.acknowledge_device_arrival(id) except Exception as e: log.error(e) elif pkt[10] == 0x02: # device removal try: del self.connected_modules[tuple(pkt[2:6])] except Exception as e: log.error(e) elif pkt[10] == 0x03: # device rejected # TODO: Inform the user that another module with the same I2C address was connected, # and this causes a communication conflict pass elif pkt[0] == BAUM_VP_DYNAMIC_DATA_BLOCK: m = self.connected_modules[tuple(pkt[2:6])] try: m.input_handler( pkt[6:]) # call the appropriate packet handler for module except Exception: log.error("module not connected or not supported") else: log.warning("invalid VP pkt")
def _loadStringsDic(): global _stringsDics printDebug("vlc_strings: _loadStringsDic") if _stringsDics is not None: printDebug("_loadStringsDic: allready loaded") return # get label to identify vlc language label = _getRandomCheckButtonLabel() if label is None: printDebug("Random Check button is not found") return printDebug("_loadStringsDic: randomCheckButton description= %s" % label) printDebug("_loadStringsDic: search vlc language") # set path of strings ini files directory currAddon = addonHandler.getCodeAddon() stringsIniFilesDir = os.path.join(currAddon.path, _stringsIniFilesDirName) # get list of all strings ini files stringsIniFilesList = _getStringsIniFilesList(stringsIniFilesDir) # search for vlc language languageFound = False for file in stringsIniFilesList: stringsIniFile = os.path.join(stringsIniFilesDir, file) conf = loadFileConfig(stringsIniFile) if conf is None: continue if conf[SCTN_VLC][ID_RandomCheckButtonDescription] == label: # language found log.warning("VLCAccessEnhancement: VLC language found= %s" % conf[SCTN_Main][ID_LanguageName]) # noqa:E501 languageFound = True break if not languageFound: log.warning("_loadStringsDic: no language found") return _stringsDics = conf.copy() printDebug("_loadStringsDic: loaded")
def lock(): global locked if locked: log.warning("kgs driver is locked") return False locked = True return True
def bgPlay(stri): global player if not player or len(stri) == 0: return # Sometimes player.feed() tries to open the device when it's already open, # causing a WindowsError. This code catches and works around this. # [DGL, 2012-12-18 with help from Tyler] tries = 0 while tries < 10: try: player.feed(stri) if tries > 0: log.warning("Eloq speech retries: %d" % (tries)) return except FileNotFoundError: # reset the player if the used soundcard is not present. E.G. the total number of sound devices has changed. player.close() player = nvwave.WavePlayer( 1, 11025, 16, outputDevice=config.conf["speech"]["outputDevice"]) except: player.idle() time.sleep(0.02) tries += 1 log.error("Eloq speech failed to feed one buffer.")
def removeOldLibFiles(destPath,rebootOK=False): """ Removes library files from previous versions of NVDA. @param destPath: The path where NVDA is installed. @ type destPath: string @param rebootOK: If true then files can be removed on next reboot if trying to do so now fails. @type rebootOK: boolean """ for topDir in ('lib','lib64'): currentLibPath=os.path.join(destPath,topDir,versionInfo.version) for parent,subdirs,files in os.walk(os.path.join(destPath,topDir),topdown=False): if parent==currentLibPath: # Lib dir for current installation. Don't touch this! log.debug("Skipping current install lib path: %r"%parent) continue for d in subdirs: path=os.path.join(parent,d) log.debug("Removing old lib directory: %r"%path) try: os.rmdir(path) except OSError: log.warning("Failed to remove a directory no longer needed. This can be manually removed after a reboot or the installer will try removing it again next time. Directory: %r"%path) for f in files: path=os.path.join(parent,f) log.debug("Removing old lib file: %r"%path) try: tryRemoveFile(path,numRetries=2,rebootOK=rebootOK) except RetriableFailure: log.warning("A file no longer needed could not be removed. This can be manually removed after a reboot, or the installer will try again next time. File: %r"%path)
def load(self, fileName, allowComplexSymbols=True): """Load symbol information from a file. @param fileName: The name of the file from which to load symbol information. @type fileName: str @param allowComplexSymbols: Whether to allow complex symbols. @type allowComplexSymbols: bool @raise IOError: If the file cannot be read. """ self.fileName = fileName with codecs.open(fileName, "r", "utf_8_sig", errors="replace") as f: handler = None for line in f: if line.isspace() or line.startswith("#"): # Whitespace or comment. continue line = line.rstrip("\r\n") try: if line == "complexSymbols:" and allowComplexSymbols: handler = self._loadComplexSymbol elif line == "symbols:": handler = self._loadSymbol elif handler: # This is a line within a section, so handle it according to which section we're in. handler(line) else: raise ValueError except ValueError: log.warning(u"Invalid line in file {file}: {line}".format( file=fileName, line=line))
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 enableBridge(): try: props = open(A11Y_PROPS_PATH, "wt") props.write(A11Y_PROPS_CONTENT) log.info("Enabled Java Access Bridge for user") except OSError: log.warning("Couldn't enable Java Access Bridge for user", exc_info=True)
def _warnDeprecatedAliasAppModule() -> None: """This function should be executed at the top level of an alias App Module, to log a deprecation warning when the module is imported. """ import inspect # Determine the name of the module inside which this function is executed by using introspection. # Since the current frame belongs to the calling function inside `appModuleHandler` # we need to retrieve the file name from the preceding frame which belongs to the module in which this # function is executed. currModName = os.path.splitext( os.path.basename(inspect.stack()[1].filename))[0] try: replacementModName = appModules.EXECUTABLE_NAMES_TO_APP_MODS[ currModName] except KeyError: raise RuntimeError( "This function can be executed only inside an alias App Module." ) from None else: deprecatedImportWarning = ( f"Importing appModules.{currModName} is deprecated," f" instead import appModules.{replacementModName}.") log.warning(deprecatedImportWarning) if not globalVars._allowDeprecatedAPI: raise ModuleNotFoundError(deprecatedImportWarning)
def get(key): global runtime_conf try: return runtime_conf[key] except: log.warning("Option {0} has not been set. The default value will be returned.".format(key)) return profile[key].default_value
def getSelectionCountByIA(self, obj): count = 0 try: o = obj.IAccessibleObject id = obj.IAccessibleChildID except Exception: log.warning("getSelectionCountByIA: error") return -1 while o: if o.accState(id) & STATE_SYSTEM_SELECTED: count += 1 try: (o, id) = accNavigate(o, id, NAVDIR_NEXT) except Exception: o = None o = obj.IAccessibleObject id = obj.IAccessibleChildID while o: try: (o, id) = accNavigate(o, id, NAVDIR_PREVIOUS) except Exception: o = None if o and o.accState(id) & STATE_SYSTEM_SELECTED: count += 1 return count
def load(self, fileName): self.fileName=fileName comment="" del self[:] log.debug("Loading speech dictionary '%s'..." % fileName) if not os.path.isfile(fileName): log.debug("file '%s' not found." % fileName) return file = codecs.open(fileName,"r","utf_8_sig",errors="replace") for line in file: if line.isspace(): comment="" continue line=line.rstrip('\r\n') if line.startswith('#'): if comment: comment+=" " comment+=line[1:] else: temp=line.split("\t") if len(temp) ==4: self.append(SpeechDictEntry(temp[0].replace(r'\#','#'),temp[1].replace(r'\#','#'),comment,bool(int(temp[2])),int(temp[3]))) comment="" else: log.warning("can't parse line '%s'" % line) log.debug("%d loaded records." % len(self)) file.close() return
def setDefaultVolumeControl(addonConfigManager): curSpeakersVolume = getSpeakerVolume() if curSpeakersVolume is None: log.warning( "Cannot establish default recovery settings: speakers volume is not available" ) return volume = int(curSpeakersVolume * 100) if volume > 50: volume = 50 volume = 10 * int(volume / 10) if volume == 0: volume = 10 addonConfigManager.setMasterVolumeLevel(volume) log.warning("The recovery speakers volume is set to %s" % volume) minThreshold = 0 if volume == 10 else 10 addonConfigManager.setMinMasterVolumeLevel(minThreshold) log.warning( "For speakers, the min Threshold is set to %s and recovery volume is set to %s" % (minThreshold, volume)) curNVDAVolume = getNVDAVolume() if curNVDAVolume is None: log.warning( "Cannot establish default NVDA recovery settings: NVDAa volume is not available" ) return volume = int(curNVDAVolume * 100) volume = 10 * int(volume / 10) addonConfigManager.setNVDAVolumeLevel(volume) minThreshold = 0 if volume == 10 else 10 addonConfigManager.setMinNVDAVolumeLevel(minThreshold) log.warning( "For NVDA, the min Threshold is set to %s and recovery volume is set to %s" % (minThreshold, volume))
def load(self, fileName): self.fileName=fileName comment="" del self[:] log.debug("Loading speech dictionary '%s'..." % fileName) if not os.path.isfile(fileName): log.debug("file '%s' not found." % fileName) return file = codecs.open(fileName,"r","utf_8_sig",errors="replace") for line in file: if line.isspace(): comment="" continue line=line.rstrip('\r\n') if line.startswith('#'): if comment: comment+=" " comment+=line[1:] else: temp=line.split("\t") if len(temp) ==4: self.append(SpeechDictEntry(temp[0].replace(r'\#','#'),temp[1].replace(r'\#','#'),comment,bool(int(temp[2])),bool(int(temp[3])))) comment="" else: log.warning("can't parse line '%s'" % line) log.debug("%d loaded records." % len(self)) file.close() return
def toggleChannels(balance="center", application=None): log.debug("toggleChannels: %s, %s" % (balance, application)) if not _initialized and isNVDA(application): # cannot toggle sound wx.CallLater( 40, ui.message, _("Not available cause of conflict with another add-on. See NVDA log" )) return applicationsVolumes = getChannels() appMsg = ".".join(application.split(".")[:-1]) applicationsVolumes[nvdaAppName] = _NVDAChannelsVolume if balance == "left": levels = (1.0, 0.0) toMsg = toLeftMsg elif balance == "right": levels = (0.0, 1.0) toMsg = toRightMsg else: levels = (1.0, 1.0) toMsg = inCenterMsg applicationsVolumes[application] = levels updateNVDAAndApplicationsChannelsLevels(applicationsVolumes) msg = "{app} {to}".format(app=appMsg, to=toMsg) from speech import cancelSpeech wx.CallLater(40, cancelSpeech) wx.CallLater(80, ui.message, msg) log.warning(msg)
def load(self, fileName): self.fileName=fileName comment="" del self[:] log.debug("Loading speech dictionary '%s'..." % fileName) if not os.path.isfile(fileName): log.debug("file '%s' not found." % fileName) return file = codecs.open(fileName,"r","utf_8_sig",errors="replace") for line in file: if line.isspace(): comment="" continue line=line.rstrip('\r\n') if line.startswith('#'): if comment: comment+=" " comment+=line[1:] else: temp=line.split("\t") if len(temp) ==4: pattern = temp[0].replace(r'\#','#') replace = temp[1].replace(r'\#','#') try: dictionaryEntry=SpeechDictEntry(pattern, replace, comment, caseSensitive=bool(int(temp[2])), type=int(temp[3])) self.append(dictionaryEntry) except Exception as e: log.exception("Dictionary (\"%s\") entry invalid for \"%s\" error raised: \"%s\"" % (fileName, line, e)) comment="" else: log.warning("can't parse line '%s'" % line) log.debug("%d loaded records." % len(self)) file.close() return
def initialize(): global state, _stateFilename, autoChecker _stateFilename = os.path.join(globalVars.appArgs.configPath, "updateCheckState.pickle") try: # #9038: Python 3 requires binary format when working with pickles. with open(_stateFilename, "rb") as f: state = pickle.load(f) except: log.debugWarning("Couldn't retrieve update state", exc_info=True) # Defaults. state = { "lastCheck": 0, "dontRemindVersion": None, } _setStateToNone(state) # check the pending version against the current version # and make sure that pendingUpdateFile and pendingUpdateVersion are part of the state dictionary. if "pendingUpdateVersion" not in state or state["pendingUpdateVersion"] == versionInfo.version: _setStateToNone(state) # remove all update files except the one that is currently pending (if any) try: for fileName in os.listdir(storeUpdatesDir): f=os.path.join(storeUpdatesDir, fileName) if f != state["pendingUpdateFile"]: os.remove(f) log.debug("Update file %s removed"%f) except OSError: log.warning("Unable to remove old update file %s"%f, exc_info=True) if not globalVars.appArgs.launcher and (config.conf["update"]["autoCheck"] or (config.conf["update"]["startupNotification"] and isPendingUpdate())): autoChecker = AutoUpdateChecker()
def _setCurrentDevice(self, preferredDevice: typing.Union[str, int]) -> None: """ Sets the _outputDeviceID and _outputDeviceName to the preferredDevice if it is available, otherwise falls back to WAVE_MAPPER. @param preferredDevice: The preferred device to use. """ if preferredDevice == WAVE_MAPPER or preferredDevice == self.DEFAULT_DEVICE_KEY: self._outputDeviceID = WAVE_MAPPER self._outputDeviceName = "WAVE_MAPPER" return try: if isinstance(preferredDevice, str): self._outputDeviceID = outputDeviceNameToID( preferredDevice, useDefaultIfInvalid=True # fallback to WAVE_MAPPER ) # If default is used, get the appropriate name. self._outputDeviceName = outputDeviceIDToName(self._outputDeviceID) elif isinstance(preferredDevice, int): self._outputDeviceID = preferredDevice self._outputDeviceName = outputDeviceIDToName(preferredDevice) else: raise TypeError("outputDevice") except (LookupError, TypeError): log.warning( f"Unsupported WavePlayer device argument: {preferredDevice}" f" Falling back to WAVE_MAPPER" ) self._setCurrentDevice(WAVE_MAPPER)
def terminate(self, *args, **kwargs) -> None: """This will be called when NVDA is finished with this global plugin""" super().terminate(*args, **kwargs) try: gui.settingsDialogs.NVDASettingsDialog.categoryClasses.remove(UnmuteSettingsPanel) except IndexError: log.warning("Can't remove %s Settings panel from NVDA settings dialogs", ADDON_SUMMARY)
def save(self): """Save all modified profiles and the base configuration to disk. """ # #7598: give others a chance to either save settings early or terminate tasks. pre_configSave.notify() if not self._shouldWriteProfile: log.info( "Not writing profile, either --secure or --launcher args present" ) return try: self._writeProfileToFile(self.profiles[0].filename, self.profiles[0]) log.info("Base configuration saved") for name in self._dirtyProfiles: self._writeProfileToFile(self._profileCache[name].filename, self._profileCache[name]) log.info("Saved configuration profile %s" % name) self._dirtyProfiles.clear() except Exception as e: log.warning( "Error saving configuration; probably read only file system") log.debugWarning("", exc_info=True) raise e post_configSave.notify()
def removeOldLibFiles(destPath, rebootOK=False): """ Removes library files from previous versions of NVDA. @param destPath: The path where NVDA is installed. @type destPath: string @param rebootOK: If true then files can be removed on next reboot if trying to do so now fails. @type rebootOK: boolean """ for topDir in ('lib', 'lib64', 'libArm64'): currentLibPath = os.path.join(destPath, topDir, versionInfo.version) for parent, subdirs, files in os.walk(os.path.join(destPath, topDir), topdown=False): if parent==currentLibPath: # Lib dir for current installation. Don't touch this! log.debug("Skipping current install lib path: %r"%parent) continue for d in subdirs: path = os.path.join(parent, d) log.debug("Removing old lib directory: %r"%path) try: os.rmdir(path) except OSError: log.warning("Failed to remove a directory no longer needed. This can be manually removed after a reboot or the installer will try removing it again next time. Directory: %r"%path) for f in files: path = os.path.join(parent, f) log.debug("Removing old lib file: %r"%path) try: tryRemoveFile(path, numRetries=2, rebootOK=rebootOK) except RetriableFailure: log.warning("A file no longer needed could not be removed. This can be manually removed after a reboot, or the installer will try again next time. File: %r"%path)
def loadSettings(self): addonConfigFile = os.path.join(globalVars.appArgs.configPath, self._configFileName) configFileExists = False if os.path.exists(addonConfigFile): baseConfig = BaseAddonConfiguration(addonConfigFile) if baseConfig[SCT_General][ ID_ConfigVersion] != self._currentConfigVersion: # old config file must not exist here. Must be deleted os.remove(addonConfigFile) log.warning(" Old config file removed") else: configFileExists = True self.addonConfig = self._versionToConfiguration[ self._currentConfigVersion](addonConfigFile) if self.addonConfig.errors != []: log.warning("Addon configuration file error") self.addonConfig = None return addonDir = os.path.join(os.path.dirname(__file__), "..\\..").decode( "mbcs") # The root of an addon folder oldConfigFile = os.path.join(addonDir, self._configFileName) if os.path.exists(oldConfigFile): if not configFileExists: self.mergeSettings(oldConfigFile) self.saveSettings() os.remove(oldConfigFile) if not configFileExists: self.saveSettings()
def load(self, filename): """Load map entries from a file. The file is an ini file. Each section contains entries for a particular scriptable object class. The section name must be the full Python module and class name. The key of each entry is the script name and the value is a comma separated list of one or more gestures. If the script name is "None", the gesture will be unbound for this class. For example, the following binds the "a" key to move to the next heading in virtual buffers and removes the default "h" binding:: [virtualBuffers.VirtualBuffer] nextHeading = kb:a None = kb:h @param filename: The name of the file to load. @type: str """ self.fileName = filename try: conf = configobj.ConfigObj(filename, file_error=True, encoding="UTF-8") except (configobj.ConfigObjError, UnicodeDecodeError) as e: log.warning("Error in gesture map '%s': %s" % (filename, e)) self.lastUpdateContainedError = True return self.update(conf)
def getFileVersionInfo(name, *attributes): """Gets the specified file version info attributes from the provided file.""" if not isinstance(name, text_type): raise TypeError("name must be an unicode string") fileVersionInfo = {} # Get size needed for buffer (0 if no info) size = ctypes.windll.version.GetFileVersionInfoSizeW(name, None) if not size: raise RuntimeError("No version information") # Create buffer res = ctypes.create_string_buffer(size) # Load file informations into buffer res ctypes.windll.version.GetFileVersionInfoW(name, None, size, res) r = ctypes.c_uint() l = ctypes.c_uint() # Look for codepages ctypes.windll.version.VerQueryValueW(res, u'\\VarFileInfo\\Translation', ctypes.byref(r), ctypes.byref(l)) if not l.value: raise RuntimeError("No codepage") # Take the first codepage (what else ?) codepage = array.array('H', ctypes.string_at(r.value, 4)) codepage = "%04x%04x" % tuple(codepage) for attr in attributes: if not ctypes.windll.version.VerQueryValueW(res, u'\\StringFileInfo\\%s\\%s' % (codepage, attr), ctypes.byref(r), ctypes.byref(l) ): log.warning("Invalid or unavailable version info attribute for %r: %s" % (name, attr)) fileVersionInfo[attr] = None else: fileVersionInfo[attr] = ctypes.wstring_at(r.value, l.value-1) return fileVersionInfo
def loadSettings(self): addonConfigFile = os.path.join(globalVars.appArgs.configPath, self.configFileName) doMerge = True if os.path.exists(addonConfigFile): # there is allready a config file try: baseConfig = BaseAddonConfiguration(addonConfigFile) if baseConfig.errors: e = Exception("Error parsing configuration file:\n%s" % baseConfig.errors) raise e if baseConfig[SCT_General][ ID_ConfigVersion] != self._currentConfigVersion: # it's an old config, but old config file must not exist here. # Must be deleted os.remove(addonConfigFile) log.warning( "%s: Old configuration version found. Config file is removed: %s" % (_addonName, addonConfigFile)) else: # it's the same version of config, so no merge doMerge = False except Exception as e: log.warning(e) # error on reading config file, so delete it os.remove(addonConfigFile) self.warnConfigurationReset() log.warning( "%s Addon configuration file error: configuration reset to factory defaults" % _addonName) if os.path.exists(addonConfigFile): self.addonConfig =\ self._versionToConfiguration[self._currentConfigVersion](addonConfigFile) if self.addonConfig.errors: log.warning(self.addonConfig.errors) log.warning( "%s Addon configuration file error: configuration reset to factory defaults" % _addonName) os.remove(addonConfigFile) self.warnConfigurationReset() # reset configuration to factory defaults self.addonConfig =\ self._versionToConfiguration[self._currentConfigVersion](None) self.addonConfig.filename = addonConfigFile doMerge = False else: # no add-on configuration file found self.addonConfig =\ self._versionToConfiguration[self._currentConfigVersion](None) self.addonConfig.filename = addonConfigFile # merge step oldConfigFile = os.path.join(_curAddon.path, self.configFileName) if os.path.exists(oldConfigFile): if doMerge: self.mergeSettings(oldConfigFile) os.remove(oldConfigFile) if not os.path.exists(addonConfigFile): self.saveSettings(True)
def __init__(self,fget, abstract=False): self.fget=fget if abstract: if isinstance(fget, classmethod): log.warning("Abstract class properties are not supported.") self._abstract = False else: self._abstract = self.__isabstractmethod__=abstract
def _fixBridgeFunc(restype,name,*argtypes,**kwargs): try: func=getattr(bridgeDll,name) except AttributeError: log.warning("%s not found in Java Access Bridge dll"%name) return func.restype=restype func.argtypes=argtypes if kwargs.get('errcheck'): func.errcheck=_errcheck
def next(self): func, args = next(self._gen) try: return func(*args, **self.kwargs) except TypeError: log.warning("Could not execute function {func} defined in {module} module due to unsupported kwargs: {kwargs}".format( func=func.__name__, module=func.__module__ or "unknown", kwargs=self.kwargs ), exc_info=True) return extensionPoints.callWithSupportedKwargs(func, *args, **self.kwargs)
def getConfigDirs(subpath=None): """Retrieve all directories that should be used when searching for configuration. IF C{subpath} is provided, it will be added to each directory returned. @param subpath: The path to be added to each directory, C{None} for none. @type subpath: str @return: The configuration directories in the order in which they should be searched. @rtype: list of str """ log.warning("getConfigDirs is deprecated. Use globalVars.appArgs.configPath instead") return [os.path.join(dir, subpath) if subpath else dir for dir in (globalVars.appArgs.configPath,) ]
def loadSettings(self): c=config.conf["speech"][self.name] if self.isSupported("voice"): voice=c["voice"] try: changeVoice(self,voice) except LookupError: log.warning("No such voice: %s" % voice) # Update the configuration with the correct voice. c["voice"]=self.voice # We need to call changeVoice here so voice dictionaries can be managed changeVoice(self,self.voice) [setattr(self,s.name,c[s.name]) for s in self.supportedSettings if not s.name=="voice" and c[s.name] is not None]
def ensureInit(): # Register builtin providers if a plugin hasn't registered others. if not speechProvider or not brailleProvider or not interactionProvider: from . import mathPlayer try: provider = mathPlayer.MathPlayer() except: log.warning("MathPlayer 4 not available") else: registerProvider( provider, speech=not speechProvider, braille=not brailleProvider, interaction=not interactionProvider )
def save(): """Saves the configuration to the config file. """ #We never want to save config if runing securely if globalVars.appArgs.secure: return global conf if globalVars.configFileError: raise RuntimeError("config file errors still exist") if not os.path.isdir(globalVars.appArgs.configPath): try: os.makedirs(globalVars.appArgs.configPath) except OSError, e: log.warning("Could not create configuration directory") log.debugWarning("", exc_info=True) raise e
def _getAvailableVoices(self): voices=OrderedDict() v=self.tts.GetVoices() for i in range(len(v)): try: ID=v[i].Id name=v[i].GetDescription() try: language=locale.windows_locale[int(v[i].getattribute('language').split(';')[0],16)] except KeyError: language=None except COMError: log.warning("Could not get the voice info. Skipping...") voices[ID]=VoiceInfo(ID,name,language) return voices
def save(self): """Save all modified profiles and the base configuration to disk. """ if globalVars.appArgs.secure: # Never save the config if running securely. return try: self.profiles[0].write() log.info("Base configuration saved") for name in self._dirtyProfiles: self._profileCache[name].write() log.info("Saved configuration profile %s" % name) self._dirtyProfiles.clear() except Exception as e: log.warning("Error saving configuration; probably read only file system") log.debugWarning("", exc_info=True) raise e
def save(self): """Save all modified profiles and the base configuration to disk. """ if not self._shouldWriteProfile: log.info("Not writing profile, either --secure or --launcher args present") return try: self._writeProfileToFile(self.profiles[0].filename, self.profiles[0]) log.info("Base configuration saved") for name in self._dirtyProfiles: self._writeProfileToFile(self._profileCache[name].filename, self._profileCache[name]) log.info("Saved configuration profile %s" % name) self._dirtyProfiles.clear() except Exception as e: log.warning("Error saving configuration; probably read only file system") log.debugWarning("", exc_info=True) raise e
def bgPlay(stri): if len(stri) == 0: return # Sometimes player.feed() tries to open the device when it's already open, # causing a WindowsError. This code catches and works around this. # [DGL, 2012-12-18 with help from Tyler] tries = 0 while tries < 10: try: player.feed(stri) if tries > 0: log.warning("Eloq speech retries: %d" % (tries)) return except: player.idle() time.sleep(0.02) tries += 1 log.error("Eloq speech failed to feed one buffer.")
def upgrade(profile, validator): # when profile is none or empty we can still validate. It should at least have a version set. _ensureVersionProperty(profile) startSchemaVersion = int(profile[SCHEMA_VERSION_KEY]) log.debug("Current config schema version: {0}, latest: {1}".format(startSchemaVersion, latestSchemaVersion)) for fromVersion in xrange(startSchemaVersion, latestSchemaVersion): _doConfigUpgrade(profile, fromVersion) _doValidation(deepcopy(profile), validator) # copy the profile, since validating mutates the object try: # write out the configuration once the upgrade has been validated. This means that if NVDA crashes for some # other reason the file does not need to be upgraded again. profile.write() except Exception as e: log.warning("Error saving configuration; probably read only file system") log.debugWarning("", exc_info=True) pass
def _getAvailableVoices(self): voices=OrderedDict() v=self._getVoiceTokens() # #2629: Iterating uses IEnumVARIANT and GetBestInterface doesn't work on tokens returned by some token enumerators. # Therefore, fetch the items by index, as that method explicitly returns the correct interface. for i in xrange(len(v)): try: ID=v[i].Id name=v[i].GetDescription() try: language=locale.windows_locale[int(v[i].getattribute('language').split(';')[0],16)] except KeyError: language=None except COMError: log.warning("Could not get the voice info. Skipping...") voices[ID]=VoiceInfo(ID,name,language) return voices
def loadSettings(self): c=config.conf["speech"][self.name] if self.isSupported("voice"): voice=c.get("voice",None) try: changeVoice(self,voice) except: log.warning("Invalid voice: %s" % voice) # Update the configuration with the correct voice. c["voice"]=self.voice # We need to call changeVoice here so that required initialisation can be performed. changeVoice(self,self.voice) else: changeVoice(self,None) for s in self.supportedSettings: if s.name=="voice" or c[s.name] is None: continue setattr(self,s.name,c[s.name])
def load(self, filename): """Load map entries from a file. The file is an ini file. Each section contains entries for a particular scriptable object class. The section name must be the full Python module and class name. The key of each entry is the script name and the value is a comma separated list of one or more gestures. If the script name is "None", the gesture will be unbound for this class. For example, the following binds the "a" key to move to the next heading in virtual buffers and removes the default "h" binding:: [virtualBuffers.VirtualBuffer] nextHeading = kb:a None = kb:h @param filename: The name of the file to load. @type: str """ try: conf = configobj.ConfigObj(filename, file_error=True, encoding="UTF-8") except (configobj.ConfigObjError, UnicodeDecodeError), e: log.warning("Error in gesture map '%s': %s" % (filename, e)) self.lastUpdateContainedError = True return
def _watcher(): global isAttemptingRecovery while isRunning: # If the watchdog is suspended, wait until it is resumed. _resumeEvent.wait() # Wait for the core to be alive. # Wait a maximum of NORMAL_CORE_ALIVE_TIMEOUT, but shorten this to a minimum of MIN_CORE_ALIVE_TIMEOUT under special circumstances. waited = 0 while True: # Wait MIN_CORE_ALIVE_TIMEOUT, unless there is less than that time remaining for NORMAL_CORE_ALIVE_TIMEOUT. timeout = min(MIN_CORE_ALIVE_TIMEOUT, NORMAL_CORE_ALIVE_TIMEOUT - waited) if timeout <= 0: # Timeout elapsed. break _coreAliveEvent.wait(timeout) waited += timeout if _coreAliveEvent.isSet() or _shouldRecoverAfterMinTimeout(): break if log.isEnabledFor(log.DEBUGWARNING) and not _coreAliveEvent.isSet(): log.debugWarning("Trying to recover from freeze, core stack:\n%s"% "".join(traceback.format_stack(sys._current_frames()[_coreThreadID]))) lastTime=time.time() while not _coreAliveEvent.isSet(): curTime=time.time() if curTime-lastTime>FROZEN_WARNING_TIMEOUT: lastTime=curTime log.warning("Core frozen in stack:\n%s"% "".join(traceback.format_stack(sys._current_frames()[_coreThreadID]))) # The core is dead, so attempt recovery. isAttemptingRecovery = True _recoverAttempt() _coreAliveEvent.wait(RECOVER_ATTEMPT_INTERVAL) isAttemptingRecovery = False # At this point, the core is alive. _coreAliveEvent.clear() # Wait a bit to avoid excessive resource consumption. time.sleep(CHECK_INTERVAL)
def __init__(self,locale): """ @param locale: The characterDescriptions.dic file will be found by using this locale. @type locale: string """ self._entries = {} fileName=os.path.join('locale',locale,'characterDescriptions.dic') if not os.path.isfile(fileName): raise LookupError(fileName) f = codecs.open(fileName,"r","utf_8_sig",errors="replace") for line in f: if line.isspace() or line.startswith('#'): continue line=line.rstrip('\r\n') temp=line.split("\t") if len(temp) > 1: key=temp.pop(0) self._entries[key] = temp else: log.warning("can't parse line '%s'" % line) log.debug("Loaded %d entries." % len(self._entries)) f.close()
def _watcher(): global isAttemptingRecovery while True: # Wait for the core to die. winKernel.waitForSingleObject(_coreDeadTimer, winKernel.INFINITE) if not isRunning: return # The core hasn't reported alive for MIN_CORE_ALIVE_TIMEOUT. waited = MIN_CORE_ALIVE_TIMEOUT while not _isAlive() and not _shouldRecoverAfterMinTimeout(): # The core is still dead and fast recovery doesn't apply. # Wait up to NORMAL_ALIVE_TIMEOUT. time.sleep(MIN_CORE_ALIVE_TIMEOUT) waited += MIN_CORE_ALIVE_TIMEOUT if waited >= NORMAL_CORE_ALIVE_TIMEOUT: break if _isAlive(): continue if log.isEnabledFor(log.DEBUGWARNING): log.debugWarning("Trying to recover from freeze, core stack:\n%s"% "".join(traceback.format_stack(sys._current_frames()[core.mainThreadId]))) lastTime=time.time() isAttemptingRecovery = True # Cancel calls until the core is alive. # This event will be reset by alive(). windll.kernel32.SetEvent(_cancelCallEvent) # Some calls have to be killed individually. while True: curTime=time.time() if curTime-lastTime>FROZEN_WARNING_TIMEOUT: lastTime=curTime log.warning("Core frozen in stack:\n%s"% "".join(traceback.format_stack(sys._current_frames()[core.mainThreadId]))) _recoverAttempt() time.sleep(RECOVER_ATTEMPT_INTERVAL) if _isAlive(): break isAttemptingRecovery = False
def __init__(self, locale): """Constructor. @param locale: The locale for which symbol pronunciation should be processed. @type locale: str """ self.locale = locale # We need to merge symbol data from several sources. sources = self.sources = [] builtin, user = self.localeSymbols.fetchLocaleData(locale,fallback=False) self.builtinSources = [builtin] self.userSymbols = user sources.append(user) sources.append(builtin) # Always use English as a base. if locale != "en": # Only the builtin data. enBaseSymbols = self.localeSymbols.fetchLocaleData("en")[0] sources.append(enBaseSymbols) self.builtinSources.append(enBaseSymbols) # The computed symbol information from all sources. symbols = self.computedSymbols = collections.OrderedDict() # An indexable list of complex symbols for use in building/executing the regexp. complexSymbolsList = self._computedComplexSymbolsList = [] # A list of multi-character simple symbols for use in building the regexp. multiChars = [] # A list of single character symbols for use in building the regexp. characters = [] # Add all complex symbols first, as they take priority. for source in sources: for identifier, pattern in source.complexSymbols.iteritems(): if identifier in symbols: # Already defined. continue symbol = SpeechSymbol(identifier, pattern) symbols[identifier] = symbol complexSymbolsList.append(symbol) # Supplement the data for complex symbols and add all simple symbols. for source in sources: for identifier, sourceSymbol in source.symbols.iteritems(): try: symbol = symbols[identifier] # We're updating an already existing symbol. except KeyError: # This is a new simple symbol. # (All complex symbols have already been added.) symbol = symbols[identifier] = SpeechSymbol(identifier) if len(identifier) == 1: characters.append(identifier) else: multiChars.append(identifier) # If fields weren't explicitly specified, inherit the value from later sources. if symbol.replacement is None: symbol.replacement = sourceSymbol.replacement if symbol.level is None: symbol.level = sourceSymbol.level if symbol.preserve is None: symbol.preserve = sourceSymbol.preserve if symbol.displayName is None: symbol.displayName = sourceSymbol.displayName # Set defaults for any fields not explicitly set. for symbol in symbols.values(): if symbol.replacement is None: # Symbols without a replacement specified are useless. log.warning(u"Replacement not defined in locale {locale} for symbol: {symbol}".format( symbol=symbol.identifier, locale=self.locale)) del symbols[symbol.identifier] try: complexSymbolsList.remove(symbol) except ValueError: pass continue if symbol.level is None: symbol.level = SYMLVL_ALL if symbol.preserve is None: symbol.preserve = SYMPRES_NEVER if symbol.displayName is None: symbol.displayName = symbol.identifier # Make characters into a regexp character set. characters = "[%s]" % re.escape("".join(characters)) # The simple symbols must be ordered longest first so that the longer symbols will match. multiChars.sort(key=lambda identifier: len(identifier), reverse=True) # Build the regexp. patterns = [ # Strip repeated spaces from the end of the line to stop them from being picked up by repeated. r"(?P<rstripSpace> +$)", # Repeated characters: more than 3 repeats. r"(?P<repeated>(?P<repTmp>%s)(?P=repTmp){3,})" % characters ] # Complex symbols. # Each complex symbol has its own named group so we know which symbol matched. patterns.extend( u"(?P<c{index}>{pattern})".format(index=index, pattern=symbol.pattern) for index, symbol in enumerate(complexSymbolsList)) # Simple symbols. # These are all handled in one named group. # Because the symbols are just text, we know which symbol matched just by looking at the matched text. patterns.append(ur"(?P<simple>{multiChars}|{singleChars})".format( multiChars="|".join(re.escape(identifier) for identifier in multiChars), singleChars=characters )) pattern = "|".join(patterns) try: self._regexp = re.compile(pattern, re.UNICODE) except re.error as e: log.error("Invalid complex symbol regular expression in locale %s: %s" % (locale, e)) raise LookupError
def main(): """NVDA's core main loop. This initializes all modules such as audio, IAccessible, keyboard, mouse, and GUI. Then it initialises the wx application object and sets up the core pump, which checks the queues and executes functions when requested. Finally, it starts the wx main loop. """ log.debug("Core starting") ctypes.windll.user32.SetProcessDPIAware() import config if not globalVars.appArgs.configPath: globalVars.appArgs.configPath=config.getUserDefaultConfigPath(useInstalledPathIfExists=globalVars.appArgs.launcher) #Initialize the config path (make sure it exists) config.initConfigPath() log.info("Config dir: %s"%os.path.abspath(globalVars.appArgs.configPath)) log.debug("loading config") import config config.initialize() if not globalVars.appArgs.minimal and config.conf["general"]["playStartAndExitSounds"]: try: nvwave.playWaveFile("waves\\start.wav") except: pass logHandler.setLogLevelFromConfig() try: lang = config.conf["general"]["language"] import languageHandler log.debug("setting language to %s"%lang) languageHandler.setLanguage(lang) except: log.warning("Could not set language to %s"%lang) import versionInfo log.info("NVDA version %s" % versionInfo.version) log.info("Using Windows version %s" % winVersion.winVersionText) log.info("Using Python version %s"%sys.version) log.info("Using comtypes version %s"%comtypes.__version__) import configobj log.info("Using configobj version %s with validate version %s"%(configobj.__version__,configobj.validate.__version__)) # Set a reasonable timeout for any socket connections NVDA makes. import socket socket.setdefaulttimeout(10) log.debug("Initializing add-ons system") addonHandler.initialize() if globalVars.appArgs.disableAddons: log.info("Add-ons are disabled. Restart NVDA to enable them.") import appModuleHandler log.debug("Initializing appModule Handler") appModuleHandler.initialize() import NVDAHelper log.debug("Initializing NVDAHelper") NVDAHelper.initialize() import speechDictHandler log.debug("Speech Dictionary processing") speechDictHandler.initialize() import speech log.debug("Initializing speech") speech.initialize() if not globalVars.appArgs.minimal and (time.time()-globalVars.startTime)>5: log.debugWarning("Slow starting core (%.2f sec)" % (time.time()-globalVars.startTime)) # Translators: This is spoken when NVDA is starting. speech.speakMessage(_("Loading NVDA. Please wait...")) import wx # wxPython 4 no longer has either of these constants (despite the documentation saying so), some add-ons may rely on # them so we add it back into wx. https://wxpython.org/Phoenix/docs/html/wx.Window.html#wx.Window.Centre wx.CENTER_ON_SCREEN = wx.CENTRE_ON_SCREEN = 0x2 log.info("Using wx version %s"%wx.version()) class App(wx.App): def OnAssert(self,file,line,cond,msg): message="{file}, line {line}:\nassert {cond}: {msg}".format(file=file,line=line,cond=cond,msg=msg) log.debugWarning(message,codepath="WX Widgets",stack_info=True) app = App(redirect=False) # We support queryEndSession events, but in general don't do anything for them. # However, when running as a Windows Store application, we do want to request to be restarted for updates def onQueryEndSession(evt): if config.isAppX: # Automatically restart NVDA on Windows Store update ctypes.windll.kernel32.RegisterApplicationRestart(None,0) app.Bind(wx.EVT_QUERY_END_SESSION, onQueryEndSession) def onEndSession(evt): # NVDA will be terminated as soon as this function returns, so save configuration if appropriate. config.saveOnExit() speech.cancelSpeech() if not globalVars.appArgs.minimal and config.conf["general"]["playStartAndExitSounds"]: try: nvwave.playWaveFile("waves\\exit.wav",async=False) except: pass log.info("Windows session ending") app.Bind(wx.EVT_END_SESSION, onEndSession) log.debug("Initializing braille input") import brailleInput brailleInput.initialize() import braille log.debug("Initializing braille") braille.initialize() import displayModel log.debug("Initializing displayModel") displayModel.initialize() log.debug("Initializing GUI") import gui gui.initialize() import audioDucking if audioDucking.isAudioDuckingSupported(): # the GUI mainloop must be running for this to work so delay it wx.CallAfter(audioDucking.initialize) # #3763: In wxPython 3, the class name of frame windows changed from wxWindowClassNR to wxWindowNR. # NVDA uses the main frame to check for and quit another instance of NVDA. # To remain compatible with older versions of NVDA, create our own wxWindowClassNR. # We don't need to do anything else because wx handles WM_QUIT for all windows. import windowUtils class MessageWindow(windowUtils.CustomWindow): className = u"wxWindowClassNR" #Just define these constants here, so we don't have to import win32con WM_POWERBROADCAST = 0x218 WM_DISPLAYCHANGE = 0x7e PBT_APMPOWERSTATUSCHANGE = 0xA UNKNOWN_BATTERY_STATUS = 0xFF AC_ONLINE = 0X1 NO_SYSTEM_BATTERY = 0X80 #States for screen orientation ORIENTATION_NOT_INITIALIZED = 0 ORIENTATION_PORTRAIT = 1 ORIENTATION_LANDSCAPE = 2 def __init__(self, windowName=None): super(MessageWindow, self).__init__(windowName) self.oldBatteryStatus = None self.orientationStateCache = self.ORIENTATION_NOT_INITIALIZED self.orientationCoordsCache = (0,0) self.handlePowerStatusChange() def windowProc(self, hwnd, msg, wParam, lParam): post_windowMessageReceipt.notify(msg=msg, wParam=wParam, lParam=lParam) if msg == self.WM_POWERBROADCAST and wParam == self.PBT_APMPOWERSTATUSCHANGE: self.handlePowerStatusChange() elif msg == self.WM_DISPLAYCHANGE: self.handleScreenOrientationChange(lParam) def handleScreenOrientationChange(self, lParam): import ui import winUser # Resolution detection comes from an article found at https://msdn.microsoft.com/en-us/library/ms812142.aspx. #The low word is the width and hiword is height. width = winUser.LOWORD(lParam) height = winUser.HIWORD(lParam) self.orientationCoordsCache = (width,height) if width > height: # If the height and width are the same, it's actually a screen flip, and we do want to alert of those! if self.orientationStateCache == self.ORIENTATION_LANDSCAPE and self.orientationCoordsCache != (width,height): return #Translators: The screen is oriented so that it is wider than it is tall. ui.message(_("Landscape" )) self.orientationStateCache = self.ORIENTATION_LANDSCAPE else: if self.orientationStateCache == self.ORIENTATION_PORTRAIT and self.orientationCoordsCache != (width,height): return #Translators: The screen is oriented in such a way that the height is taller than it is wide. ui.message(_("Portrait")) self.orientationStateCache = self.ORIENTATION_PORTRAIT def handlePowerStatusChange(self): #Mostly taken from script_say_battery_status, but modified. import ui import winKernel sps = winKernel.SYSTEM_POWER_STATUS() if not winKernel.GetSystemPowerStatus(sps) or sps.BatteryFlag is self.UNKNOWN_BATTERY_STATUS: return if sps.BatteryFlag & self.NO_SYSTEM_BATTERY: return if self.oldBatteryStatus is None: #Just initializing the cache, do not report anything. self.oldBatteryStatus = sps.ACLineStatus return if sps.ACLineStatus == self.oldBatteryStatus: #Sometimes, this double fires. This also fires when the battery level decreases by 3%. return self.oldBatteryStatus = sps.ACLineStatus if sps.ACLineStatus & self.AC_ONLINE: #Translators: Reported when the battery is plugged in, and now is charging. ui.message(_("Charging battery. %d percent") % sps.BatteryLifePercent) else: #Translators: Reported when the battery is no longer plugged in, and now is not charging. ui.message(_("Not charging battery. %d percent") %sps.BatteryLifePercent) messageWindow = MessageWindow(unicode(versionInfo.name)) # initialize wxpython localization support locale = wx.Locale() lang=languageHandler.getLanguage() wxLang=locale.FindLanguageInfo(lang) if not wxLang and '_' in lang: wxLang=locale.FindLanguageInfo(lang.split('_')[0]) if hasattr(sys,'frozen'): locale.AddCatalogLookupPathPrefix(os.path.join(os.getcwdu(),"locale")) # #8064: Wx might know the language, but may not actually contain a translation database for that language. # If we try to initialize this language, wx will show a warning dialog. # Therefore treat this situation like wx not knowing the language at all. if not locale.IsAvailable(wxLang.Language): wxLang=None if wxLang: try: locale.Init(wxLang.Language) except: log.error("Failed to initialize wx locale",exc_info=True) else: log.debugWarning("wx does not support language %s" % lang) import api import winUser import NVDAObjects.window desktopObject=NVDAObjects.window.Window(windowHandle=winUser.getDesktopWindow()) api.setDesktopObject(desktopObject) api.setFocusObject(desktopObject) api.setNavigatorObject(desktopObject) api.setMouseObject(desktopObject) import JABHandler log.debug("initializing Java Access Bridge support") try: JABHandler.initialize() except NotImplementedError: log.warning("Java Access Bridge not available") except: log.error("Error initializing Java Access Bridge support", exc_info=True) import winConsoleHandler log.debug("Initializing winConsole support") winConsoleHandler.initialize() import UIAHandler log.debug("Initializing UIA support") try: UIAHandler.initialize() except NotImplementedError: log.warning("UIA not available") except: log.error("Error initializing UIA support", exc_info=True) import IAccessibleHandler log.debug("Initializing IAccessible support") IAccessibleHandler.initialize() log.debug("Initializing input core") import inputCore inputCore.initialize() import keyboardHandler log.debug("Initializing keyboard handler") keyboardHandler.initialize() import mouseHandler log.debug("initializing mouse handler") mouseHandler.initialize() import touchHandler log.debug("Initializing touchHandler") try: touchHandler.initialize() except NotImplementedError: pass import globalPluginHandler log.debug("Initializing global plugin handler") globalPluginHandler.initialize() if globalVars.appArgs.install or globalVars.appArgs.installSilent: import gui.installerGui wx.CallAfter(gui.installerGui.doSilentInstall,startAfterInstall=not globalVars.appArgs.installSilent) elif globalVars.appArgs.portablePath and (globalVars.appArgs.createPortable or globalVars.appArgs.createPortableSilent): import gui.installerGui wx.CallAfter(gui.installerGui.doCreatePortable,portableDirectory=globalVars.appArgs.portablePath, silent=globalVars.appArgs.createPortableSilent,startAfterCreate=not globalVars.appArgs.createPortableSilent) elif not globalVars.appArgs.minimal: try: # Translators: This is shown on a braille display (if one is connected) when NVDA starts. braille.handler.message(_("NVDA started")) except: log.error("", exc_info=True) if globalVars.appArgs.launcher: gui.LauncherDialog.run() # LauncherDialog will call doStartupDialogs() afterwards if required. else: wx.CallAfter(doStartupDialogs) import queueHandler # Queue the handling of initial focus, # as API handlers might need to be pumped to get the first focus event. queueHandler.queueFunction(queueHandler.eventQueue, _setInitialFocus) import watchdog import baseObject # Doing this here is a bit ugly, but we don't want these modules imported # at module level, including wx. log.debug("Initializing core pump") class CorePump(gui.NonReEntrantTimer): "Checks the queues and executes functions." def run(self): global _isPumpPending _isPumpPending = False watchdog.alive() try: if touchHandler.handler: touchHandler.handler.pump() JABHandler.pumpAll() IAccessibleHandler.pumpAll() queueHandler.pumpAll() mouseHandler.pumpAll() braille.pumpAll() except: log.exception("errors in this core pump cycle") baseObject.AutoPropertyObject.invalidateCaches() watchdog.asleep() if _isPumpPending and not _pump.IsRunning(): # #3803: Another pump was requested during this pump execution. # As our pump is not re-entrant, schedule another pump. _pump.Start(PUMP_MAX_DELAY, True) global _pump _pump = CorePump() requestPump() log.debug("Initializing watchdog") watchdog.initialize() try: import updateCheck except RuntimeError: updateCheck=None log.debug("Update checking not supported") else: log.debug("initializing updateCheck") updateCheck.initialize() log.info("NVDA initialized") postNvdaStartup.notify() log.debug("entering wx application main loop") app.MainLoop() log.info("Exiting") if updateCheck: _terminate(updateCheck) _terminate(watchdog) _terminate(globalPluginHandler, name="global plugin handler") _terminate(gui) config.saveOnExit() try: if globalVars.focusObject and hasattr(globalVars.focusObject,"event_loseFocus"): log.debug("calling lose focus on object with focus") globalVars.focusObject.event_loseFocus() except: log.exception("Lose focus error") try: speech.cancelSpeech() except: pass import treeInterceptorHandler _terminate(treeInterceptorHandler) _terminate(IAccessibleHandler, name="IAccessible support") _terminate(UIAHandler, name="UIA support") _terminate(winConsoleHandler, name="winConsole support") _terminate(JABHandler, name="Java Access Bridge support") _terminate(appModuleHandler, name="app module handler") _terminate(NVDAHelper) _terminate(touchHandler) _terminate(keyboardHandler, name="keyboard handler") _terminate(mouseHandler) _terminate(inputCore) _terminate(brailleInput) _terminate(braille) _terminate(speech) _terminate(addonHandler) if not globalVars.appArgs.minimal and config.conf["general"]["playStartAndExitSounds"]: try: nvwave.playWaveFile("waves\\exit.wav",async=False) except: pass # #5189: Destroy the message window as late as possible # so new instances of NVDA can find this one even if it freezes during exit. messageWindow.destroy() log.debug("core done")