Example #1
0
 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
Example #2
0
	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))
Example #3
0
 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
Example #4
0
	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)
Example #5
0
 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))
Example #6
0
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
Example #7
0
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)
Example #8
0
	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()
Example #9
0
	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
Example #10
0
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()
Example #11
0
 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)
Example #12
0
 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")
Example #13
0
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")
Example #14
0
def lock():
    global locked
    if locked:
        log.warning("kgs driver is locked")
        return False
    locked = True
    return True
Example #15
0
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.")
Example #16
0
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)
Example #17
0
    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))
Example #18
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
Example #19
0
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)
Example #20
0
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)
Example #21
0
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
Example #23
0
	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
Example #24
0
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
Example #26
0
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)
Example #27
0
	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
Example #28
0
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()
Example #29
0
	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)
Example #30
0
	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)
Example #31
0
    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, 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))
Example #35
0
    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)
Example #36
0
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)
Example #38
0
	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
Example #39
0
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
Example #40
0
	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)
Example #41
0
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]
Example #43
0
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
            )
Example #44
0
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
Example #45
0
	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
Example #47
0
	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
Example #48
0
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.")
Example #49
0
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
Example #50
0
	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])
Example #52
0
    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
Example #53
0
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()
Example #55
0
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
Example #57
0
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")