replaces namespace fenrir with fenrirscreenreader
This commit is contained in:
0
src/fenrirscreenreader/core/__init__.py
Normal file
0
src/fenrirscreenreader/core/__init__.py
Normal file
31
src/fenrirscreenreader/core/applicationManager.py
Normal file
31
src/fenrirscreenreader/core/applicationManager.py
Normal file
@ -0,0 +1,31 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
class applicationManager():
|
||||
def __init__(self):
|
||||
pass
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getCurrentApplication(self):
|
||||
currApp = self.env['screen']['newApplication'].upper()
|
||||
if not currApp:
|
||||
currApp == 'DEFAULT'
|
||||
if currApp == '':
|
||||
currApp == 'DEFAULT'
|
||||
return currApp
|
||||
def getPrevApplication(self):
|
||||
prevApp = self.env['screen']['oldApplication'].upper()
|
||||
if not prevApp:
|
||||
prevApp == 'DEFAULT'
|
||||
if prevApp == '':
|
||||
prevApp == 'DEFAULT'
|
||||
return prevApp
|
||||
def isApplicationChange(self):
|
||||
return self.env['screen']['oldApplication'] != self.env['screen']['newApplication']
|
41
src/fenrirscreenreader/core/brailleDriver.py
Normal file
41
src/fenrirscreenreader/core/brailleDriver.py
Normal file
@ -0,0 +1,41 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
class brailleDriver():
|
||||
def __init__(self):
|
||||
self._isInitialized = False
|
||||
self.deviceSize = None
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
self._isInitialized = True
|
||||
|
||||
def getDeviceSize(self):
|
||||
if not self._isInitialized:
|
||||
return (0,0)
|
||||
return (0,0)
|
||||
|
||||
def writeText(self,text):
|
||||
if not self._isInitialized:
|
||||
return
|
||||
|
||||
def connectDevice(self):
|
||||
pass
|
||||
|
||||
def enterScreen(self, screen):
|
||||
if not self._isInitialized:
|
||||
return
|
||||
|
||||
def leveScreen(self):
|
||||
if not self._isInitialized:
|
||||
return
|
||||
|
||||
def shutdown(self):
|
||||
if not self._isInitialized:
|
||||
return
|
||||
self.leveScreen()
|
||||
self._isInitialized = False
|
24
src/fenrirscreenreader/core/commandData.py
Normal file
24
src/fenrirscreenreader/core/commandData.py
Normal file
@ -0,0 +1,24 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
import time
|
||||
|
||||
# used as shared memory between commands
|
||||
# use this in your own commands
|
||||
commandBuffer = {
|
||||
'enableSpeechOnKeypress': False,
|
||||
'Marks':{'1':None, '2':None},
|
||||
'bookMarks':{},
|
||||
'windowArea':{},
|
||||
}
|
||||
|
||||
# used by the commandManager
|
||||
commandInfo = {
|
||||
#'currCommand': '',
|
||||
'lastCommandExecutionTime': time.time(),
|
||||
'lastCommandRequestTime': time.time(),
|
||||
}
|
223
src/fenrirscreenreader/core/commandManager.py
Normal file
223
src/fenrirscreenreader/core/commandManager.py
Normal file
@ -0,0 +1,223 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
import glob, os, time, inspect
|
||||
currentdir = os.path.dirname(os.path.realpath(os.path.abspath(inspect.getfile(inspect.currentframe()))))
|
||||
fenrirPath = os.path.dirname(currentdir)
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.utils import module_utils
|
||||
|
||||
class commandManager():
|
||||
def __init__(self):
|
||||
pass
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
# commands
|
||||
self.env['commands'] = {}
|
||||
self.env['commandsIgnore'] = {}
|
||||
for commandFolder in self.env['general']['commandFolderList']:
|
||||
self.env['runtime']['commandManager'].loadCommands(commandFolder)
|
||||
if self.env['runtime']['settingsManager'].getSetting('general', 'commandPath') != '':
|
||||
self.env['runtime']['commandManager'].loadCommands(commandFolder,
|
||||
self.env['runtime']['settingsManager'].getSetting('general', 'commandPath'))
|
||||
|
||||
# scripts for scriptKey
|
||||
self.env['runtime']['commandManager'].loadScriptCommands()
|
||||
|
||||
def shutdown(self):
|
||||
for commandFolder in self.env['general']['commandFolderList']:
|
||||
self.env['runtime']['commandManager'].shutdownCommands(commandFolder)
|
||||
|
||||
def loadCommands(self, section='commands',commandPath=''):
|
||||
if commandPath =='':
|
||||
commandPath = fenrirPath+ "/commands/"
|
||||
if not commandPath.endswith('/'):
|
||||
commandPath += '/'
|
||||
commandFolder = commandPath + section +"/"
|
||||
if not os.path.exists(commandFolder):
|
||||
self.env['runtime']['debug'].writeDebugOut("commandFolder not exists:" + commandFolder ,debug.debugLevel.WARNING)
|
||||
return
|
||||
if not os.path.isdir(commandFolder):
|
||||
self.env['runtime']['debug'].writeDebugOut("commandFolder not a directory:" + commandFolder ,debug.debugLevel.ERROR)
|
||||
return
|
||||
if not os.access(commandFolder, os.R_OK):
|
||||
self.env['runtime']['debug'].writeDebugOut("commandFolder not readable:" + commandFolder ,debug.debugLevel.ERROR)
|
||||
return
|
||||
self.env['commands'][section] = {}
|
||||
self.env['commandsIgnore'][section] = {}
|
||||
commandList = glob.glob(commandFolder+'*')
|
||||
for command in commandList:
|
||||
try:
|
||||
fileName, fileExtension = os.path.splitext(command)
|
||||
fileName = fileName.split('/')[-1]
|
||||
if fileName.startswith('__'):
|
||||
continue
|
||||
try:
|
||||
if self.env['commands'][section][fileName.upper()] != None:
|
||||
continue
|
||||
except:
|
||||
pass
|
||||
if fileExtension.lower() == '.py':
|
||||
command_mod = module_utils.importModule(fileName, command)
|
||||
self.env['commands'][section][fileName.upper()] = command_mod.command()
|
||||
self.env['commandsIgnore'][section][fileName.upper()[fileName.upper().find('-')+1:]+'_IGNORE'] = False
|
||||
self.env['commands'][section][fileName.upper()].initialize(self.env)
|
||||
self.env['runtime']['debug'].writeDebugOut("Load command:" + section + "." + fileName.upper() ,debug.debugLevel.INFO, onAnyLevel=True)
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut("Loading command:" + command ,debug.debugLevel.ERROR)
|
||||
self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR)
|
||||
continue
|
||||
|
||||
def loadScriptCommands(self, section='commands', scriptPath=''):
|
||||
if scriptPath =='':
|
||||
scriptPath = self.env['runtime']['settingsManager'].getSetting('general', 'scriptPath')
|
||||
if not scriptPath.endswith('/'):
|
||||
scriptPath += '/'
|
||||
if not os.path.exists(scriptPath):
|
||||
if os.path.exists(fenrirPath +'/../../config/scripts/'):
|
||||
scriptPath = fenrirPath +'/../../config/scripts/'
|
||||
else:
|
||||
self.env['runtime']['debug'].writeDebugOut("scriptpath not exists:" + scriptPath ,debug.debugLevel.WARNING)
|
||||
return
|
||||
if not os.path.isdir(scriptPath):
|
||||
self.env['runtime']['debug'].writeDebugOut("scriptpath not a directory:" + scriptPath ,debug.debugLevel.ERROR)
|
||||
return
|
||||
if not os.access(scriptPath, os.R_OK):
|
||||
self.env['runtime']['debug'].writeDebugOut("scriptpath not readable:" + scriptPath ,debug.debugLevel.ERROR)
|
||||
return
|
||||
commandList = glob.glob(scriptPath+'*')
|
||||
subCommand = fenrirPath + '/commands/commands/subprocess.py'
|
||||
for command in commandList:
|
||||
invalid = False
|
||||
try:
|
||||
fileName, fileExtension = os.path.splitext(command)
|
||||
fileName = fileName.split('/')[-1]
|
||||
if fileName.startswith('__'):
|
||||
continue
|
||||
if fileName.upper() in self.env['commands'][section]:
|
||||
continue
|
||||
command_mod = module_utils.importModule(fileName ,subCommand)
|
||||
self.env['commands'][section][fileName.upper()] = command_mod.command()
|
||||
self.env['commands'][section][fileName.upper()].initialize(self.env,command)
|
||||
self.env['runtime']['debug'].writeDebugOut("Load script:" + section + "." + fileName.upper() ,debug.debugLevel.INFO, onAnyLevel=True)
|
||||
commSettings = fileName.upper().split('__-__')
|
||||
if len(commSettings) == 1:
|
||||
keys = commSettings[0]
|
||||
elif len(commSettings) == 2:
|
||||
keys = commSettings[1]
|
||||
elif len(commSettings) > 2:
|
||||
continue
|
||||
keys = keys.split('__+__')
|
||||
shortcutKeys = []
|
||||
shortcut = []
|
||||
for key in keys:
|
||||
if not self.env['runtime']['settingsManager'].isValidKey(key.upper()):
|
||||
self.env['runtime']['debug'].writeDebugOut("invalid key : "+ key.upper() + ' command:' +commandName ,debug.debugLevel.WARNING)
|
||||
invalid = True
|
||||
break
|
||||
shortcutKeys.append(key.upper())
|
||||
if invalid:
|
||||
continue
|
||||
if not 'KEY_SCRIPT' in shortcutKeys:
|
||||
shortcutKeys.append('KEY_SCRIPT')
|
||||
shortcut.append(1)
|
||||
shortcut.append(sorted(shortcutKeys))
|
||||
self.env['bindings'][str(shortcut)] = fileName.upper()
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut("Loading script:" + command ,debug.debugLevel.ERROR)
|
||||
self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR)
|
||||
continue
|
||||
def shutdownCommands(self, section):
|
||||
for command in sorted(self.env['commands'][section]):
|
||||
try:
|
||||
self.env['commands'][section][command].shutdown()
|
||||
del self.env['commands'][section][command]
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut("Shutdown command:" + section + "." + command ,debug.debugLevel.ERROR)
|
||||
self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR)
|
||||
continue
|
||||
|
||||
def executeSwitchTrigger(self, trigger, unLoadScript, loadScript):
|
||||
if self.env['runtime']['screenManager'].isSuspendingScreen():
|
||||
return
|
||||
#unload
|
||||
oldScript = unLoadScript
|
||||
if self.commandExists(oldScript, trigger):
|
||||
try:
|
||||
self.env['runtime']['debug'].writeDebugOut("Executing switchtrigger.unload:" + trigger + "." + oldScript ,debug.debugLevel.INFO)
|
||||
self.env['commands'][trigger][oldScript].unload()
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut("Executing trigger:" + trigger + "." + oldScript ,debug.debugLevel.ERROR)
|
||||
self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR)
|
||||
#load
|
||||
newScript = loadScript
|
||||
if self.commandExists(newScript, trigger):
|
||||
try:
|
||||
self.env['runtime']['debug'].writeDebugOut("Executing switchtrigger.load:" + trigger + "." + newScript ,debug.debugLevel.INFO)
|
||||
self.env['commands'][trigger][newScript].load()
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut("Executing trigger:" + trigger + "." + newScript ,debug.debugLevel.ERROR)
|
||||
self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR)
|
||||
|
||||
def executeDefaultTrigger(self, trigger, force=False):
|
||||
if not force:
|
||||
if self.env['runtime']['screenManager'].isSuspendingScreen():
|
||||
return
|
||||
for command in sorted(self.env['commands'][trigger]):
|
||||
if self.commandExists(command, trigger):
|
||||
try:
|
||||
if self.env['commandsIgnore'][trigger][command[command.find('-')+1:]+'_IGNORE']:
|
||||
self.env['commandsIgnore'][trigger][command[command.find('-')+1:]+'_IGNORE'] = False
|
||||
self.env['runtime']['debug'].writeDebugOut("Ignore trigger.command:" + trigger + "." + command ,debug.debugLevel.INFO)
|
||||
else:
|
||||
self.env['runtime']['debug'].writeDebugOut("Executing trigger.command:" + trigger + "." + command ,debug.debugLevel.INFO)
|
||||
self.env['commands'][trigger][command].run()
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut("Executing trigger:" + trigger + "." + command + str(e) ,debug.debugLevel.ERROR)
|
||||
|
||||
def executeCommand(self, command, section = 'commands'):
|
||||
if self.env['runtime']['screenManager'].isSuspendingScreen():
|
||||
return
|
||||
if self.commandExists(command, section):
|
||||
try:
|
||||
if self.env['runtime']['helpManager'].isTutorialMode() and section != 'help':
|
||||
self.env['runtime']['debug'].writeDebugOut("Tutorial for command:" + section + "." + command ,debug.debugLevel.INFO)
|
||||
description = self.getCommandDescription(command, section)
|
||||
self.env['runtime']['outputManager'].presentText(description, interrupt=True)
|
||||
else:
|
||||
self.env['runtime']['debug'].writeDebugOut("Executing command:" + section + "." + command ,debug.debugLevel.INFO)
|
||||
self.runCommand(command, section)
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut("Executing command:" + section + "." + command +' ' + str(e),debug.debugLevel.ERROR)
|
||||
|
||||
|
||||
def runCommand(self, command, section = 'commands'):
|
||||
if self.commandExists(command, section):
|
||||
try:
|
||||
self.env['runtime']['debug'].writeDebugOut("runCommand command:" + section + "." + command ,debug.debugLevel.INFO)
|
||||
self.env['commands'][section][command].run()
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut("runCommand command:" + section + "." + command +' ' + str(e),debug.debugLevel.ERROR)
|
||||
self.env['commandInfo']['lastCommandExecutionTime'] = time.time()
|
||||
|
||||
def getCommandDescription(self, command, section = 'commands'):
|
||||
if self.commandExists(command, section):
|
||||
try:
|
||||
return self.env['commands'][section][command].getDescription()
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('commandManager.getCommandDescription:' + str(e),debug.debugLevel.ERROR)
|
||||
self.env['commandInfo']['lastCommandExecutionTime'] = time.time()
|
||||
|
||||
def commandExists(self, command, section = 'commands'):
|
||||
return( command in self.env['commands'][section])
|
||||
def getShortcutForCommand(self, command):
|
||||
shortcut = ''
|
||||
try:
|
||||
shortcut = list(self.env['bindings'].keys())[list(self.env['bindings'].values()).index(command)]
|
||||
except:
|
||||
pass
|
||||
return shortcut
|
109
src/fenrirscreenreader/core/cursorManager.py
Normal file
109
src/fenrirscreenreader/core/cursorManager.py
Normal file
@ -0,0 +1,109 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
class cursorManager():
|
||||
def __init__(self):
|
||||
pass
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def clearMarks(self):
|
||||
self.env['commandBuffer']['Marks']['1'] = None
|
||||
self.env['commandBuffer']['Marks']['2'] = None
|
||||
def isMarkSet(self):
|
||||
return self.env['commandBuffer']['Marks']['1'] != None
|
||||
def isSingleMark(self):
|
||||
return self.env['commandBuffer']['Marks']['1'] != None and \
|
||||
self.env['commandBuffer']['Marks']['2'] == None
|
||||
def isMultibleMark(self):
|
||||
return self.env['commandBuffer']['Marks']['1'] != None and \
|
||||
self.env['commandBuffer']['Marks']['2'] != None
|
||||
def setMark(self):
|
||||
currCursor = None
|
||||
if self.env['screen']['newCursorReview']:
|
||||
currCursor = self.env['screen']['newCursorReview'].copy()
|
||||
else:
|
||||
currCursor = self.env['screen']['newCursor'].copy()
|
||||
if not self.env['commandBuffer']['Marks']['1']:
|
||||
self.env['commandBuffer']['Marks']['1'] = currCursor.copy()
|
||||
return 1
|
||||
else:
|
||||
self.env['commandBuffer']['Marks']['2'] = currCursor.copy()
|
||||
return 2
|
||||
return 0
|
||||
def getReviewOrTextCursor(self):
|
||||
if self.env['screen']['newCursorReview']:
|
||||
return self.env['screen']['newCursorReview'].copy()
|
||||
else:
|
||||
return self.env['screen']['newCursor'].copy()
|
||||
def clearReviewCursor(self):
|
||||
if not self.isReviewMode():
|
||||
return
|
||||
self.env['screen']['oldCursorReview'] = None
|
||||
self.env['screen']['newCursorReview'] = None
|
||||
|
||||
def isCursorHorizontalMove(self):
|
||||
return self.env['screen']['newCursor']['x'] != self.env['screen']['oldCursor']['x']
|
||||
|
||||
def isCursorVerticalMove(self):
|
||||
return self.env['screen']['newCursor']['y'] != self.env['screen']['oldCursor']['y']
|
||||
|
||||
def isReviewMode(self):
|
||||
return self.env['screen']['newCursorReview'] != None
|
||||
|
||||
def enterReviewModeCurrTextCursor(self, overwrite=False):
|
||||
if self.isReviewMode() and not overwrite:
|
||||
return
|
||||
self.env['screen']['oldCursorReview'] = self.env['screen']['newCursorReview']
|
||||
if not self.env['screen']['newCursorReview']:
|
||||
self.env['screen']['newCursorReview'] = self.env['screen']['newCursor'].copy()
|
||||
if self.env['runtime']['settingsManager'].getSettingAsBool('focus', 'highlight') and \
|
||||
self.env['screen']['newCursorAttrib'] != None:
|
||||
if self.env['screen']['newCursorAttrib']['x'] != 0 and \
|
||||
self.env['screen']['newCursorAttrib']['y'] != 0:
|
||||
self.env['screen']['newCursorReview'] = self.env['screen']['newCursorAttrib'].copy()
|
||||
|
||||
def setReviewCursorPosition(self, x, y):
|
||||
if not self.isReviewMode():
|
||||
self.enterReviewModeCurrTextCursor()
|
||||
self.env['screen']['oldCursorReview'] = self.env['screen']['newCursorReview']
|
||||
self.env['screen']['newCursorReview']['x'] = x
|
||||
self.env['screen']['newCursorReview']['y'] = y
|
||||
|
||||
def isApplicationWindowSet(self):
|
||||
try:
|
||||
currApp = self.env['runtime']['applicationManager'].getCurrentApplication()
|
||||
if self.env['commandBuffer']['windowArea'][currApp]['1'] != None:
|
||||
return True
|
||||
except:
|
||||
pass
|
||||
return False
|
||||
def setWindowForApplication(self):
|
||||
if not self.env['commandBuffer']['Marks']['1']:
|
||||
return False
|
||||
if not self.env['commandBuffer']['Marks']['2']:
|
||||
return False
|
||||
currApp = self.env['runtime']['applicationManager'].getCurrentApplication()
|
||||
self.env['commandBuffer']['windowArea'][currApp] = {}
|
||||
|
||||
if self.env['commandBuffer']['Marks']['1']['x'] * self.env['commandBuffer']['Marks']['1']['y'] <= \
|
||||
self.env['commandBuffer']['Marks']['2']['x'] * self.env['commandBuffer']['Marks']['2']['y']:
|
||||
self.env['commandBuffer']['windowArea'][currApp]['1'] = self.env['commandBuffer']['Marks']['1'].copy()
|
||||
self.env['commandBuffer']['windowArea'][currApp]['2'] = self.env['commandBuffer']['Marks']['2'].copy()
|
||||
else:
|
||||
self.env['commandBuffer']['windowArea'][currApp]['1'] = self.env['commandBuffer']['Marks']['2'].copy()
|
||||
self.env['commandBuffer']['windowArea'][currApp]['2'] = self.env['commandBuffer']['Marks']['1'].copy()
|
||||
return True
|
||||
def clearWindowForApplication(self):
|
||||
currApp = self.env['runtime']['applicationManager'].getCurrentApplication()
|
||||
try:
|
||||
del self.env['commandBuffer']['windowArea'][currApp]
|
||||
except:
|
||||
return False
|
||||
return True
|
13
src/fenrirscreenreader/core/debug.py
Normal file
13
src/fenrirscreenreader/core/debug.py
Normal file
@ -0,0 +1,13 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
from enum import Enum
|
||||
|
||||
class debugLevel(Enum):
|
||||
DEACTIVE = 0
|
||||
ERROR = 1
|
||||
WARNING = 2
|
||||
INFO = 3
|
||||
def __int__(self):
|
||||
return self.value
|
||||
def __str__(self):
|
||||
return self.name
|
71
src/fenrirscreenreader/core/debugManager.py
Normal file
71
src/fenrirscreenreader/core/debugManager.py
Normal file
@ -0,0 +1,71 @@
|
||||
#!/usr/bin/python
|
||||
# Debugger module for the Fenrir screen reader.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from datetime import datetime
|
||||
|
||||
class debugManager():
|
||||
def __init__(self, fileName='/var/log/fenrir.log'):
|
||||
self._fileName = fileName
|
||||
self._file = None
|
||||
self._fileOpened = False
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
self.closeDebugFile()
|
||||
def __del__(self):
|
||||
try:
|
||||
self.shutdown()
|
||||
except:
|
||||
pass
|
||||
|
||||
def openDebugFile(self, fileName = ''):
|
||||
self._fileOpened = False
|
||||
if fileName != '':
|
||||
self._fileName = fileName
|
||||
if self._fileName != '':
|
||||
self._file = open(self._fileName,'a')
|
||||
self._fileOpened = True
|
||||
|
||||
def writeDebugOut(self, text, level = debug.debugLevel.DEACTIVE, onAnyLevel=False):
|
||||
|
||||
mode = self.env['runtime']['settingsManager'].getSetting('general','debugMode')
|
||||
if mode == '':
|
||||
mode = 'FILE'
|
||||
mode = mode.upper().split(',')
|
||||
fileMode = 'FILE' in mode
|
||||
printMode = 'PRINT' in mode
|
||||
|
||||
if (self.env['runtime']['settingsManager'].getSettingAsInt('general','debugLevel') < int(level)) and \
|
||||
not (onAnyLevel and self.env['runtime']['settingsManager'].getSettingAsInt('general','debugLevel') > int(debug.debugLevel.DEACTIVE)) :
|
||||
if self._fileOpened:
|
||||
self.closeDebugFile()
|
||||
return
|
||||
else:
|
||||
if not self._fileOpened and fileMode:
|
||||
self.openDebugFile()
|
||||
if onAnyLevel:
|
||||
msg = 'ANY '+ str(level) + ' ' + str(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f'))
|
||||
else:
|
||||
msg = str(level) +' ' + str(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')
|
||||
)
|
||||
msg += ': ' + text
|
||||
if printMode:
|
||||
print(msg)
|
||||
if fileMode:
|
||||
self._file.write(msg + '\n')
|
||||
|
||||
def closeDebugFile(self):
|
||||
if not self._fileOpened:
|
||||
return False
|
||||
if self._file != None:
|
||||
self._file.close()
|
||||
self._fileOpened = False
|
||||
return True
|
||||
|
||||
def getDebugFile(self):
|
||||
return self._fileName
|
||||
|
||||
def setDebugFile(self, fileName):
|
||||
self.closeDebugFile()
|
||||
self._fileName = fileName
|
29
src/fenrirscreenreader/core/environment.py
Normal file
29
src/fenrirscreenreader/core/environment.py
Normal file
@ -0,0 +1,29 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.core.settingsData import settingsData
|
||||
from fenrirscreenreader.core.runtimeData import runtimeData
|
||||
from fenrirscreenreader.core.screenData import screenData
|
||||
from fenrirscreenreader.core.outputData import outputData
|
||||
from fenrirscreenreader.core.generalData import generalData
|
||||
from fenrirscreenreader.core import commandData
|
||||
from fenrirscreenreader.core.inputData import inputData
|
||||
from fenrirscreenreader.core.punctuationData import punctuationData
|
||||
|
||||
environment = {
|
||||
'screen': screenData,
|
||||
'runtime': runtimeData,
|
||||
'general': generalData,
|
||||
'settings': settingsData,
|
||||
'commandInfo': commandData.commandInfo,
|
||||
'commandBuffer': commandData.commandBuffer,
|
||||
'input': inputData,
|
||||
'punctuation': punctuationData,
|
||||
'output': outputData,
|
||||
'soundIcons': {},
|
||||
'bindings': {},
|
||||
}
|
24
src/fenrirscreenreader/core/eventData.py
Normal file
24
src/fenrirscreenreader/core/eventData.py
Normal file
@ -0,0 +1,24 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from enum import Enum
|
||||
|
||||
class fenrirEventType(Enum):
|
||||
Ignore = 0
|
||||
StopMainLoop = 1
|
||||
ScreenUpdate = 2
|
||||
KeyboardInput = 3
|
||||
BrailleInput = 4
|
||||
PlugInputDevice = 5
|
||||
BrailleFlush = 6
|
||||
ScreenChanged = 7
|
||||
HeartBeat = 8 # for time based scheduling
|
||||
ExecuteCommand = 9
|
||||
def __int__(self):
|
||||
return self.value
|
||||
def __str__(self):
|
||||
return self.name
|
85
src/fenrirscreenreader/core/eventManager.py
Normal file
85
src/fenrirscreenreader/core/eventManager.py
Normal file
@ -0,0 +1,85 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.core.eventData import fenrirEventType
|
||||
from queue import Empty
|
||||
import time
|
||||
from multiprocessing import Queue
|
||||
from multiprocessing.sharedctypes import Value
|
||||
from ctypes import c_bool
|
||||
|
||||
class eventManager():
|
||||
def __init__(self):
|
||||
self.running = Value(c_bool, True)
|
||||
self._eventQueue = Queue() # multiprocessing.Queue()
|
||||
self.cleanEventQueue()
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
self.cleanEventQueue()
|
||||
|
||||
def proceedEventLoop(self):
|
||||
event = self._eventQueue.get()
|
||||
st = time.time()
|
||||
self.eventDispatcher(event)
|
||||
#print('NET loop ' + str(time.time() - st))
|
||||
def eventDispatcher(self, event):
|
||||
self.env['runtime']['debug'].writeDebugOut('eventManager:eventDispatcher:start: event:' + str(event['Type']) + ' QueueSize:' + str( self._eventQueue.qsize()),debug.debugLevel.INFO)
|
||||
if not event:
|
||||
return
|
||||
if not event['Type']:
|
||||
return
|
||||
if event['Type'] == fenrirEventType.Ignore:
|
||||
return
|
||||
elif event['Type'] == fenrirEventType.StopMainLoop:
|
||||
self.handleStopMainLoop(event)
|
||||
elif event['Type'] == fenrirEventType.ScreenUpdate:
|
||||
self.env['runtime']['fenrirManager'].handleScreenUpdate(event)
|
||||
elif event['Type'] == fenrirEventType.KeyboardInput:
|
||||
self.env['runtime']['fenrirManager'].handleInput(event)
|
||||
elif event['Type'] == fenrirEventType.BrailleInput:
|
||||
pass
|
||||
elif event['Type'] == fenrirEventType.PlugInputDevice:
|
||||
self.env['runtime']['fenrirManager'].handlePlugInputDevice(event)
|
||||
pass
|
||||
elif event['Type'] == fenrirEventType.BrailleFlush:
|
||||
pass
|
||||
elif event['Type'] == fenrirEventType.ScreenChanged:
|
||||
self.env['runtime']['fenrirManager'].handleScreenChange(event)
|
||||
elif event['Type'] == fenrirEventType.HeartBeat:
|
||||
self.env['runtime']['fenrirManager'].handleHeartBeat(event)
|
||||
elif event['Type'] == fenrirEventType.ExecuteCommand:
|
||||
self.env['runtime']['fenrirManager'].handleExecuteCommand(event)
|
||||
def isMainEventLoopRunning(self):
|
||||
return self.running.value == 1
|
||||
def startMainEventLoop(self):
|
||||
self.running.value = 1
|
||||
while( self.isMainEventLoopRunning()):
|
||||
self.proceedEventLoop()
|
||||
|
||||
def handleStopMainLoop(self, event):
|
||||
self.running.value = 0
|
||||
time.sleep(0.1)
|
||||
def stopMainEventLoop(self):
|
||||
self._eventQueue.put({"Type":fenrirEventType.StopMainLoop,"Data":None})
|
||||
def cleanEventQueue(self):
|
||||
if self._eventQueue.empty():
|
||||
return
|
||||
try:
|
||||
while True:
|
||||
self._eventQueue.get_nowait()
|
||||
except Empty:
|
||||
pass
|
||||
def getEventQueue(self):
|
||||
return self._eventQueue
|
||||
def getRunning(self):
|
||||
return self.running
|
||||
def putToEventQueue(self,event, data):
|
||||
if not isinstance(event, fenrirEventType):
|
||||
return False
|
||||
self._eventQueue.put({"Type":event,"Data":data})
|
||||
return True
|
185
src/fenrirscreenreader/core/fenrirManager.py
Normal file
185
src/fenrirscreenreader/core/fenrirManager.py
Normal file
@ -0,0 +1,185 @@
|
||||
#!/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
import os, sys, signal, time
|
||||
|
||||
from fenrirscreenreader.core import i18n
|
||||
from fenrirscreenreader.core import settingsManager
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.core.eventData import fenrirEventType
|
||||
import argparse
|
||||
|
||||
class fenrirManager():
|
||||
def __init__(self):
|
||||
self.initialized = False
|
||||
cliArgs = self.handleArgs()
|
||||
if not cliArgs:
|
||||
return
|
||||
try:
|
||||
self.environment = settingsManager.settingsManager().initFenrirConfig(cliArgs, self)
|
||||
if not self.environment:
|
||||
raise RuntimeError('Cannot Initialize. Maybe the configfile is not available or not parseable')
|
||||
except RuntimeError:
|
||||
raise
|
||||
self.environment['runtime']['outputManager'].presentText(_("Start Fenrir"), soundIcon='ScreenReaderOn', interrupt=True)
|
||||
signal.signal(signal.SIGINT, self.captureSignal)
|
||||
signal.signal(signal.SIGTERM, self.captureSignal)
|
||||
self.initialized = True
|
||||
self.modifierInput = False
|
||||
self.singleKeyCommand = False
|
||||
self.command = ''
|
||||
def handleArgs(self):
|
||||
args = None
|
||||
parser = argparse.ArgumentParser(description="Fenrir Help")
|
||||
parser.add_argument('-s', '--setting', metavar='SETTING-FILE', default='/etc/fenrir/settings/settings.conf', help='Use a specified settingsfile')
|
||||
parser.add_argument('-o', '--options', metavar='SECTION#SETTING=VALUE,..', default='', help='Overwrite options in given settings file')
|
||||
parser.add_argument('-d', '--debug', action='store_true', help='Turns on Debugmode')
|
||||
parser.add_argument('-p', '--print', action='store_true', help='Print debug messages on screen')
|
||||
try:
|
||||
args = parser.parse_args()
|
||||
except Exception as e:
|
||||
parser.print_help()
|
||||
return args
|
||||
def proceed(self):
|
||||
if not self.initialized:
|
||||
return
|
||||
self.environment['runtime']['eventManager'].startMainEventLoop()
|
||||
self.shutdown()
|
||||
def handleInput(self, event):
|
||||
#startTime = time.time
|
||||
self.environment['runtime']['debug'].writeDebugOut('DEBUG INPUT fenrirMan:' + str(event),debug.debugLevel.INFO)
|
||||
if not event['Data']:
|
||||
event['Data'] = self.environment['runtime']['inputManager'].getInputEvent()
|
||||
if event['Data']:
|
||||
event['Data']['EventName'] = self.environment['runtime']['inputManager'].convertEventName(event['Data']['EventName'])
|
||||
self.environment['runtime']['inputManager'].handleInputEvent(event['Data'])
|
||||
else:
|
||||
return
|
||||
if self.environment['runtime']['inputManager'].noKeyPressed():
|
||||
self.environment['runtime']['inputManager'].clearLastDeepInput()
|
||||
if self.environment['runtime']['screenManager'].isSuspendingScreen():
|
||||
self.environment['runtime']['inputManager'].writeEventBuffer()
|
||||
else:
|
||||
if self.environment['runtime']['helpManager'].isTutorialMode():
|
||||
self.environment['runtime']['inputManager'].clearEventBuffer()
|
||||
|
||||
self.detectCommand()
|
||||
|
||||
if self.modifierInput:
|
||||
self.environment['runtime']['inputManager'].clearEventBuffer()
|
||||
if self.singleKeyCommand:
|
||||
if self.environment['runtime']['inputManager'].noKeyPressed():
|
||||
self.environment['runtime']['inputManager'].clearEventBuffer()
|
||||
else:
|
||||
self.environment['runtime']['inputManager'].writeEventBuffer()
|
||||
if self.environment['runtime']['inputManager'].noKeyPressed():
|
||||
self.modifierInput = False
|
||||
self.singleKeyCommand = False
|
||||
if self.environment['input']['keyForeward'] > 0:
|
||||
self.environment['input']['keyForeward'] -=1
|
||||
self.environment['runtime']['commandManager'].executeDefaultTrigger('onInput')
|
||||
#print('handleInput:',time.time() - startTime)
|
||||
def handleExecuteCommand(self, event):
|
||||
if event['Data'] == '':
|
||||
return
|
||||
command = event['Data']
|
||||
|
||||
if self.environment['runtime']['helpManager'].isTutorialMode():
|
||||
if self.environment['runtime']['commandManager'].commandExists( command, 'help'):
|
||||
self.environment['runtime']['commandManager'].executeCommand( command, 'help')
|
||||
return
|
||||
self.environment['runtime']['commandManager'].executeCommand( command, 'commands')
|
||||
def handleScreenChange(self, event):
|
||||
self.environment['runtime']['screenManager'].hanldeScreenChange(event['Data'])
|
||||
'''
|
||||
if self.environment['runtime']['applicationManager'].isApplicationChange():
|
||||
self.environment['runtime']['commandManager'].executeDefaultTrigger('onApplicationChange')
|
||||
self.environment['runtime']['commandManager'].executeSwitchTrigger('onSwitchApplicationProfile', \
|
||||
self.environment['runtime']['applicationManager'].getPrevApplication(), \
|
||||
self.environment['runtime']['applicationManager'].getCurrentApplication())
|
||||
'''
|
||||
self.environment['runtime']['commandManager'].executeDefaultTrigger('onScreenChanged')
|
||||
self.environment['runtime']['screenDriver'].getCurrScreen()
|
||||
def handleScreenUpdate(self, event):
|
||||
#startTime = time.time()
|
||||
self.environment['runtime']['screenManager'].handleScreenUpdate(event['Data'])
|
||||
'''
|
||||
if self.environment['runtime']['applicationManager'].isApplicationChange():
|
||||
self.environment['runtime']['commandManager'].executeDefaultTrigger('onApplicationChange')
|
||||
self.environment['runtime']['commandManager'].executeSwitchTrigger('onSwitchApplicationProfile', \
|
||||
self.environment['runtime']['applicationManager'].getPrevApplication(), \
|
||||
self.environment['runtime']['applicationManager'].getCurrentApplication())
|
||||
'''
|
||||
# timout for the last keypress
|
||||
if time.time() - self.environment['runtime']['inputManager'].getLastInputTime() >= 0.3:
|
||||
self.environment['runtime']['inputManager'].clearLastDeepInput()
|
||||
# has cursor changed?
|
||||
if self.environment['runtime']['cursorManager'].isCursorVerticalMove() or \
|
||||
self.environment['runtime']['cursorManager'].isCursorHorizontalMove():
|
||||
self.environment['runtime']['commandManager'].executeDefaultTrigger('onCursorChange')
|
||||
self.environment['runtime']['commandManager'].executeDefaultTrigger('onScreenUpdate')
|
||||
self.environment['runtime']['inputManager'].clearLastDeepInput()
|
||||
#print('handleScreenUpdate:',time.time() - startTime)
|
||||
|
||||
def handlePlugInputDevice(self, event):
|
||||
self.environment['runtime']['commandManager'].executeDefaultTrigger('onPlugInputDevice', force=True)
|
||||
|
||||
def handleHeartBeat(self, event):
|
||||
self.environment['runtime']['commandManager'].executeDefaultTrigger('onHeartBeat',force=True)
|
||||
#self.environment['runtime']['outputManager'].brailleText(flush=False)
|
||||
|
||||
def detectCommand(self):
|
||||
if self.environment['input']['keyForeward'] > 0:
|
||||
return
|
||||
if self.environment['runtime']['inputManager'].isKeyPress():
|
||||
self.modifierInput = self.environment['runtime']['inputManager'].currKeyIsModifier()
|
||||
else:
|
||||
if not self.environment['runtime']['inputManager'].noKeyPressed():
|
||||
if self.singleKeyCommand:
|
||||
self.singleKeyCommand = len( self.environment['runtime']['inputManager'].getLastDeepestInput() ) == 1
|
||||
# key is already released. we need the old one
|
||||
if not( self.singleKeyCommand and self.environment['runtime']['inputManager'].noKeyPressed()):
|
||||
shortcut = self.environment['runtime']['inputManager'].getCurrShortcut()
|
||||
self.command = self.environment['runtime']['inputManager'].getCommandForShortcut(shortcut)
|
||||
if not self.modifierInput:
|
||||
if self.environment['runtime']['inputManager'].isKeyPress():
|
||||
if self.command != '':
|
||||
self.singleKeyCommand = True
|
||||
|
||||
if not (self.singleKeyCommand or self.modifierInput):
|
||||
return
|
||||
|
||||
# fire event
|
||||
if self.command != '':
|
||||
if self.modifierInput:
|
||||
self.environment['runtime']['eventManager'].putToEventQueue(fenrirEventType.ExecuteCommand, self.command)
|
||||
self.command = ''
|
||||
else:
|
||||
if self.singleKeyCommand:
|
||||
if self.environment['runtime']['inputManager'].noKeyPressed():
|
||||
self.environment['runtime']['eventManager'].putToEventQueue(fenrirEventType.ExecuteCommand, self.command)
|
||||
self.command = ''
|
||||
|
||||
def shutdownRequest(self):
|
||||
try:
|
||||
self.environment['runtime']['eventManager'].stopMainEventLoop()
|
||||
except:
|
||||
pass
|
||||
def captureSignal(self, siginit, frame):
|
||||
self.shutdownRequest()
|
||||
|
||||
def shutdown(self):
|
||||
self.environment['runtime']['eventManager'].stopMainEventLoop()
|
||||
self.environment['runtime']['outputManager'].presentText(_("Quit Fenrir"), soundIcon='ScreenReaderOff', interrupt=True)
|
||||
self.environment['runtime']['eventManager'].cleanEventQueue()
|
||||
time.sleep(1)
|
||||
for currManager in self.environment['general']['managerList']:
|
||||
if self.environment['runtime'][currManager]:
|
||||
self.environment['runtime'][currManager].shutdown()
|
||||
del self.environment['runtime'][currManager]
|
||||
|
||||
self.environment = None
|
||||
|
18
src/fenrirscreenreader/core/generalData.py
Normal file
18
src/fenrirscreenreader/core/generalData.py
Normal file
@ -0,0 +1,18 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
generalData = {
|
||||
'args': None,
|
||||
'tutorialMode': False,
|
||||
'currUser':'',
|
||||
'prevUser':'',
|
||||
'managerList':['processManager', 'punctuationManager', 'cursorManager', 'applicationManager', 'commandManager'
|
||||
, 'screenManager', 'inputManager','outputManager', 'helpManager', 'memoryManager', 'eventManager', 'debug'],
|
||||
'commandFolderList':['commands','onInput', 'onCursorChange', 'onScreenUpdate','onScreenChanged','onHeartBeat', 'onPlugInputDevice'
|
||||
,'onApplicationChange','onSwitchApplicationProfile','help',],
|
||||
}
|
55
src/fenrirscreenreader/core/headLineManager.py
Normal file
55
src/fenrirscreenreader/core/headLineManager.py
Normal file
@ -0,0 +1,55 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
import re, string
|
||||
|
||||
class headLineManager():
|
||||
def __init__(self):
|
||||
self.regExSingle = re.compile(r'(([^\w\s])\2{5,})')
|
||||
self.regExDouble = re.compile(r'([^\w\s]{2,}){5,}')
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def replaceHeadLines(self, text):
|
||||
# fast len check for bigger typing echo
|
||||
if len(text) < 5:
|
||||
return text
|
||||
# more strong check, to not match if not needed:
|
||||
if len(text.strip(string.ascii_letters+string.digits+string.whitespace)) < 5:
|
||||
return text
|
||||
result = ''
|
||||
newText = ''
|
||||
lastPos = 0
|
||||
for match in self.regExDouble.finditer(text):
|
||||
span = match.span()
|
||||
newText += text[lastPos:span[0]]
|
||||
numberOfChars = len(text[span[0]:span[1]])
|
||||
name = text[span[0]:span[1]][:2]
|
||||
if name[0] == name[1]:
|
||||
newText += ' ' + str(numberOfChars) + ' ' + self.env['runtime']['punctuationManager'].proceedPunctuation(name[0], True) + ' '
|
||||
else:
|
||||
newText += ' ' + str(int(numberOfChars / 2)) + ' ' + self.env['runtime']['punctuationManager'].proceedPunctuation(name, True) + ' '
|
||||
lastPos = span[1]
|
||||
if lastPos != 0:
|
||||
newText += ' '
|
||||
newText += text[lastPos:]
|
||||
lastPos = 0
|
||||
for match in self.regExSingle.finditer(newText):
|
||||
span = match.span()
|
||||
result += text[lastPos:span[0]]
|
||||
numberOfChars = len(newText[span[0]:span[1]])
|
||||
name = newText[span[0]:span[1]][:2]
|
||||
if name[0] == name[1]:
|
||||
result += ' ' + str(numberOfChars) + ' ' + self.env['runtime']['punctuationManager'].proceedPunctuation(name[0], True) + ' '
|
||||
else:
|
||||
result += ' ' + str(int(numberOfChars / 2)) + ' ' + self.env['runtime']['punctuationManager'].proceedPunctuation(name, True) + ' '
|
||||
lastPos = span[1]
|
||||
if lastPos != 0:
|
||||
result += ' '
|
||||
result += newText[lastPos:]
|
||||
return result
|
81
src/fenrirscreenreader/core/helpManager.py
Executable file
81
src/fenrirscreenreader/core/helpManager.py
Executable file
@ -0,0 +1,81 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
|
||||
class helpManager():
|
||||
def __init__(self):
|
||||
self.helpDict = {}
|
||||
self.tutorialListIndex = None
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def toggleTutorialMode(self):
|
||||
self.setTutorialMode(not self.env['general']['tutorialMode'])
|
||||
def setTutorialMode(self, newTutorialMode):
|
||||
self.env['general']['tutorialMode'] = newTutorialMode
|
||||
if newTutorialMode:
|
||||
self.createHelpDict()
|
||||
self.env['bindings'][str([1, ['KEY_ESC']])] = 'TOGGLE_TUTORIAL_MODE'
|
||||
self.env['bindings'][str([1, ['KEY_UP']])] = 'PREV_HELP'
|
||||
self.env['bindings'][str([1, ['KEY_DOWN']])] = 'NEXT_HELP'
|
||||
self.env['bindings'][str([1, ['KEY_SPACE']])] = 'CURR_HELP'
|
||||
else:
|
||||
try:
|
||||
del(self.env['bindings'][str([1, ['KEY_ESC']])])
|
||||
del(self.env['bindings'][str([1, ['KEY_UP']])])
|
||||
del(self.env['bindings'][str([1, ['KEY_DOWN']])])
|
||||
del(self.env['bindings'][str([1, ['KEY_SPACE']])])
|
||||
except:
|
||||
pass
|
||||
def isTutorialMode(self):
|
||||
return self.env['general']['tutorialMode']
|
||||
def getCommandHelpText(self, command, section = 'commands'):
|
||||
commandName = command.lower()
|
||||
commandName = commandName.split('__-__')[0]
|
||||
commandName = commandName.replace('_',' ')
|
||||
commandName = commandName.replace('_',' ')
|
||||
if command == 'TOGGLE_TUTORIAL_MODE':
|
||||
commandDescription = _('toggles the tutorial mode')
|
||||
else:
|
||||
commandDescription = self.env['runtime']['commandManager'].getCommandDescription( command, section = 'commands')
|
||||
if commandDescription == '':
|
||||
commandDescription = 'no Description available'
|
||||
commandShortcut = self.env['runtime']['commandManager'].getShortcutForCommand( command)
|
||||
commandShortcut = commandShortcut.replace('KEY_',' ')
|
||||
commandShortcut = commandShortcut.replace('[','')
|
||||
commandShortcut = commandShortcut.replace(']','')
|
||||
commandShortcut = commandShortcut.replace("'",'')
|
||||
if commandShortcut == '':
|
||||
commandShortcut = 'unbound'
|
||||
helptext = commandName + ', Shortcut ' + commandShortcut + ', Description ' + commandDescription
|
||||
return helptext
|
||||
def createHelpDict(self, section = 'commands'):
|
||||
self.helpDict = {}
|
||||
for command in sorted(self.env['commands'][section].keys()):
|
||||
self.helpDict[len(self.helpDict)] = self.getCommandHelpText(command, section)
|
||||
if len(self.helpDict) > 0:
|
||||
self.tutorialListIndex = 0
|
||||
else:
|
||||
self.tutorialListIndex = None
|
||||
def getHelpForCurrentIndex(self):
|
||||
if self.tutorialListIndex == None:
|
||||
return ''
|
||||
return self.helpDict[self.tutorialListIndex]
|
||||
def nextIndex(self):
|
||||
if self.tutorialListIndex == None:
|
||||
return
|
||||
self.tutorialListIndex += 1
|
||||
if self.tutorialListIndex >= len(self.helpDict):
|
||||
self.tutorialListIndex = 0
|
||||
def prevIndex(self):
|
||||
if self.tutorialListIndex == None:
|
||||
return
|
||||
self.tutorialListIndex -= 1
|
||||
if self.tutorialListIndex < 0:
|
||||
self.tutorialListIndex = len(self.helpDict) - 1
|
11
src/fenrirscreenreader/core/i18n.py
Normal file
11
src/fenrirscreenreader/core/i18n.py
Normal file
@ -0,0 +1,11 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
import gettext
|
||||
import locale
|
||||
|
||||
# the only function we really need to call here is gettext.install. Python3 has simplified this.
|
||||
gettext.install("fenrir")
|
36
src/fenrirscreenreader/core/inputData.py
Normal file
36
src/fenrirscreenreader/core/inputData.py
Normal file
File diff suppressed because one or more lines are too long
52
src/fenrirscreenreader/core/inputDriver.py
Normal file
52
src/fenrirscreenreader/core/inputDriver.py
Normal file
@ -0,0 +1,52 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
class inputDriver():
|
||||
def __init__(self):
|
||||
self._initialized = False
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
self._isInitialized = True
|
||||
def shutdown(self):
|
||||
if self._initialized:
|
||||
self.releaseDevices()
|
||||
self._isInitialized = False
|
||||
def getInputEvent(self):
|
||||
time.sleep(0.05)
|
||||
return None
|
||||
def handleInputEvent(self, event):
|
||||
time.sleep(0.05)
|
||||
if not self._initialized:
|
||||
return
|
||||
def writeEventBuffer(self):
|
||||
if not self._initialized:
|
||||
return
|
||||
def clearEventBuffer(self):
|
||||
if not self._initialized:
|
||||
return
|
||||
del self.env['input']['eventBuffer'][:]
|
||||
def updateInputDevices(self, force = False, init = False):
|
||||
if not self._initialized:
|
||||
return
|
||||
def getLedState(self, led = 0):
|
||||
if not self._initialized:
|
||||
return False
|
||||
return False
|
||||
def toggleLedState(self, led = 0):
|
||||
if not self._initialized:
|
||||
return None
|
||||
def grabDevices(self):
|
||||
if not self._initialized:
|
||||
return None
|
||||
def releaseDevices(self):
|
||||
if not self._initialized:
|
||||
return None
|
||||
def __del__(self):
|
||||
if not self._initialized:
|
||||
return None
|
||||
self.releaseDevices()
|
212
src/fenrirscreenreader/core/inputManager.py
Normal file
212
src/fenrirscreenreader/core/inputManager.py
Normal file
@ -0,0 +1,212 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
import time
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
class inputManager():
|
||||
def __init__(self):
|
||||
self.setLedState = True
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
self.env['runtime']['settingsManager'].loadDriver(\
|
||||
self.env['runtime']['settingsManager'].getSetting('keyboard', 'driver'), 'inputDriver')
|
||||
self.updateInputDevices()
|
||||
# init LEDs with current state
|
||||
self.env['input']['newNumLock'] = self.env['runtime']['inputDriver'].getLedState()
|
||||
self.env['input']['oldNumLock'] = self.env['input']['newNumLock']
|
||||
self.env['input']['newCapsLock'] = self.env['runtime']['inputDriver'].getLedState(1)
|
||||
self.env['input']['oldCapsLock'] = self.env['input']['newCapsLock']
|
||||
self.env['input']['newScrollLock'] = self.env['runtime']['inputDriver'].getLedState(2)
|
||||
self.env['input']['oldScrollLock'] = self.env['input']['newScrollLock']
|
||||
self.lastDeepestInput = []
|
||||
self.lastInputTime = time.time()
|
||||
def shutdown(self):
|
||||
self.removeAllDevices()
|
||||
self.env['runtime']['settingsManager'].shutdownDriver('inputDriver')
|
||||
def getInputEvent(self):
|
||||
return self.env['runtime']['inputDriver'].getInputEvent()
|
||||
def handleInputEvent(self, eventData):
|
||||
self.env['runtime']['debug'].writeDebugOut('DEBUG INPUT inputMan:' + str(eventData),debug.debugLevel.INFO)
|
||||
if not eventData:
|
||||
return
|
||||
self.env['input']['prevInput'] = self.env['input']['currInput'].copy()
|
||||
if eventData['EventState'] == 0:
|
||||
if eventData['EventName'] in self.env['input']['currInput']:
|
||||
self.env['input']['currInput'].remove(eventData['EventName'])
|
||||
if len(self.env['input']['currInput']) > 1:
|
||||
self.env['input']['currInput'] = sorted(self.env['input']['currInput'])
|
||||
elif len(self.env['input']['currInput']) == 0:
|
||||
self.env['input']['shortcutRepeat'] = 1
|
||||
self.setLedState = self.handleLedStates(eventData)
|
||||
self.lastInputTime = time.time()
|
||||
elif eventData['EventState'] == 1:
|
||||
if not eventData['EventName'] in self.env['input']['currInput']:
|
||||
self.env['input']['currInput'].append(eventData['EventName'])
|
||||
if len(self.env['input']['currInput']) > 1:
|
||||
self.env['input']['currInput'] = sorted(self.env['input']['currInput'])
|
||||
if len(self.lastDeepestInput) < len(self.env['input']['currInput']):
|
||||
self.setLastDeepestInput( self.env['input']['currInput'].copy())
|
||||
elif self.lastDeepestInput == self.env['input']['currInput']:
|
||||
if time.time() - self.lastInputTime <= self.env['runtime']['settingsManager'].getSettingAsFloat('keyboard','doubleTapTimeout'):
|
||||
self.env['input']['shortcutRepeat'] += 1
|
||||
else:
|
||||
self.env['input']['shortcutRepeat'] = 1
|
||||
self.setLedState = self.handleLedStates(eventData)
|
||||
self.lastInputTime = time.time()
|
||||
elif eventData['EventState'] == 2:
|
||||
self.lastInputTime = time.time()
|
||||
|
||||
self.env['input']['oldNumLock'] = self.env['input']['newNumLock']
|
||||
self.env['input']['newNumLock'] = self.env['runtime']['inputDriver'].getLedState()
|
||||
self.env['input']['oldCapsLock'] = self.env['input']['newCapsLock']
|
||||
self.env['input']['newCapsLock'] = self.env['runtime']['inputDriver'].getLedState(1)
|
||||
self.env['input']['oldScrollLock'] = self.env['input']['newScrollLock']
|
||||
self.env['input']['newScrollLock'] = self.env['runtime']['inputDriver'].getLedState(2)
|
||||
self.env['runtime']['debug'].writeDebugOut("currInput " + str(self.env['input']['currInput'] ) ,debug.debugLevel.INFO)
|
||||
if self.noKeyPressed():
|
||||
self.env['input']['prevInput'] = []
|
||||
self.setLedState = True
|
||||
|
||||
def handleLedStates(self, mEvent):
|
||||
if not self.setLedState:
|
||||
return self.setLedState
|
||||
if mEvent['EventName'] == 'KEY_NUMLOCK':
|
||||
if mEvent['EventState'] == 1 and not self.env['input']['newNumLock'] == 1:
|
||||
self.env['runtime']['inputDriver'].toggleLedState()
|
||||
return False
|
||||
if mEvent['EventState'] == 0 and not self.env['input']['newNumLock'] == 0:
|
||||
self.env['runtime']['inputDriver'].toggleLedState()
|
||||
return False
|
||||
if mEvent['EventName'] == 'KEY_CAPSLOCK':
|
||||
if mEvent['EventState'] == 1 and not self.env['input']['newCapsLock'] == 1:
|
||||
self.env['runtime']['inputDriver'].toggleLedState(1)
|
||||
return False
|
||||
if mEvent['EventState'] == 0 and not self.env['input']['newCapsLock'] == 0:
|
||||
self.env['runtime']['inputDriver'].toggleLedState(1)
|
||||
return False
|
||||
if mEvent['EventName'] == 'KEY_SCROLLLOCK':
|
||||
if mEvent['EventState'] == 1 and not self.env['input']['newScrollLock'] == 1:
|
||||
self.env['runtime']['inputDriver'].toggleLedState(2)
|
||||
return False
|
||||
if mEvent['EventState'] == 0 and not self.env['input']['newScrollLock'] == 0:
|
||||
self.env['runtime']['inputDriver'].toggleLedState(2)
|
||||
return False
|
||||
return self.setLedState
|
||||
|
||||
def grabAllDevices(self):
|
||||
if self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'grabDevices'):
|
||||
self.env['runtime']['inputDriver'].grabAllDevices()
|
||||
|
||||
def updateInputDevices(self):
|
||||
try:
|
||||
self.env['runtime']['inputDriver'].updateInputDevices()
|
||||
except:
|
||||
pass
|
||||
|
||||
def removeAllDevices(self):
|
||||
try:
|
||||
self.env['runtime']['inputDriver'].removeAllDevices()
|
||||
except:
|
||||
pass
|
||||
|
||||
def convertEventName(self, eventName):
|
||||
if not eventName:
|
||||
return ''
|
||||
if eventName == '':
|
||||
return ''
|
||||
eventName = eventName.upper()
|
||||
if eventName == 'KEY_LEFTCTRL':
|
||||
eventName = 'KEY_CTRL'
|
||||
elif eventName == 'KEY_RIGHTCTRL':
|
||||
eventName = 'KEY_CTRL'
|
||||
elif eventName == 'KEY_LEFTSHIFT':
|
||||
eventName = 'KEY_SHIFT'
|
||||
elif eventName == 'KEY_RIGHTSHIFT':
|
||||
eventName = 'KEY_SHIFT'
|
||||
elif eventName == 'KEY_LEFTALT':
|
||||
eventName = 'KEY_ALT'
|
||||
elif eventName == 'KEY_RIGHTALT':
|
||||
eventName = 'KEY_ALT'
|
||||
elif eventName == 'KEY_LEFTMETA':
|
||||
eventName = 'KEY_META'
|
||||
elif eventName == 'KEY_RIGHTMETA':
|
||||
eventName = 'KEY_META'
|
||||
if self.isFenrirKey(eventName):
|
||||
eventName = 'KEY_FENRIR'
|
||||
if self.isScriptKey(eventName):
|
||||
eventName = 'KEY_SCRIPT'
|
||||
return eventName
|
||||
|
||||
def clearEventBuffer(self):
|
||||
self.env['runtime']['inputDriver'].clearEventBuffer()
|
||||
def setLastDeepestInput(self, currentDeepestInput):
|
||||
self.lastDeepestInput = currentDeepestInput
|
||||
def clearLastDeepInput(self):
|
||||
self.lastDeepestInput = []
|
||||
def getLastInputTime(self):
|
||||
return self.lastInputTime
|
||||
def getLastDeepestInput(self):
|
||||
return self.lastDeepestInput
|
||||
def writeEventBuffer(self):
|
||||
try:
|
||||
if self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'grabDevices'):
|
||||
self.env['runtime']['inputDriver'].writeEventBuffer()
|
||||
self.clearEventBuffer()
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut("Error while writeUInput",debug.debugLevel.ERROR)
|
||||
self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR)
|
||||
|
||||
def noKeyPressed(self):
|
||||
return self.env['input']['currInput'] == []
|
||||
def isKeyPress(self):
|
||||
return (self.env['input']['prevInput'] == []) and (self.env['input']['currInput'] != [])
|
||||
def getPrevDeepestShortcut(self):
|
||||
shortcut = []
|
||||
shortcut.append(self.env['input']['shortcutRepeat'])
|
||||
shortcut.append(self.getLastDeepestInput())
|
||||
return str(shortcut)
|
||||
|
||||
def getPrevShortcut(self):
|
||||
shortcut = []
|
||||
shortcut.append(self.env['input']['shortcutRepeat'])
|
||||
shortcut.append(self.env['input']['prevInput'])
|
||||
return str(shortcut)
|
||||
|
||||
def getCurrShortcut(self, inputSequence = None):
|
||||
shortcut = []
|
||||
shortcut.append(self.env['input']['shortcutRepeat'])
|
||||
if inputSequence:
|
||||
shortcut.append(inputSequence)
|
||||
else:
|
||||
shortcut.append(self.env['input']['currInput'])
|
||||
if len(self.env['input']['prevInput']) < len(self.env['input']['currInput']):
|
||||
if self.env['input']['shortcutRepeat'] > 1 and not self.shortcutExists(str(shortcut)):
|
||||
shortcut = []
|
||||
self.env['input']['shortcutRepeat'] = 1
|
||||
shortcut.append(self.env['input']['shortcutRepeat'])
|
||||
shortcut.append(self.env['input']['currInput'])
|
||||
self.env['runtime']['debug'].writeDebugOut("currShortcut " + str(shortcut) ,debug.debugLevel.INFO)
|
||||
return str(shortcut)
|
||||
|
||||
def currKeyIsModifier(self):
|
||||
if len(self.getLastDeepestInput()) != 1:
|
||||
return False
|
||||
return (self.env['input']['currInput'][0] =='KEY_FENRIR') or (self.env['input']['currInput'][0] == 'KEY_SCRIPT')
|
||||
|
||||
def isFenrirKey(self, eventName):
|
||||
return eventName in self.env['input']['fenrirKey']
|
||||
|
||||
def isScriptKey(self, eventName):
|
||||
return eventName in self.env['input']['scriptKey']
|
||||
|
||||
def getCommandForShortcut(self, shortcut):
|
||||
if not self.shortcutExists(shortcut):
|
||||
return ''
|
||||
return self.env['bindings'][shortcut]
|
||||
|
||||
def shortcutExists(self, shortcut):
|
||||
return(shortcut in self.env['bindings'])
|
123
src/fenrirscreenreader/core/memoryManager.py
Normal file
123
src/fenrirscreenreader/core/memoryManager.py
Normal file
@ -0,0 +1,123 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
import time
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
class memoryManager():
|
||||
def __init__(self):
|
||||
self.listStorage = {}
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def listStorageValid(self,name, checkIndex = False):
|
||||
try:
|
||||
if checkIndex:
|
||||
index = self.listStorage[name]['index']
|
||||
if index == -1:
|
||||
return self.listStorage[name]['list'] == []
|
||||
return self.listStorage[name]['list'][index] != None
|
||||
else:
|
||||
return isinstance(self.listStorage[name]['list'],list)
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut("listStorageValid " + str(e),debug.debugLevel.ERROR)
|
||||
return False
|
||||
def addValueToFirstIndex(self, name, value):
|
||||
if not self.listStorageValid(name):
|
||||
return
|
||||
if self.listStorage[name]['maxLength'] == None:
|
||||
self.listStorage[name]['list'] = [value] + self.listStorage[name]['list']
|
||||
else:
|
||||
self.listStorage[name]['list'] = [value] + self.listStorage[name]['list'][:self.listStorage[name]['maxLength'] -1]
|
||||
self.listStorage[name]['index'] = 0
|
||||
def addIndexList(self, name, maxLength = None, currList = [], currIndex = -1):
|
||||
if len(currList) != 0 and (currIndex == -1):
|
||||
currIndex = 0
|
||||
self.listStorage[name] = {'list': currList, 'index': currIndex, 'maxLength': maxLength}
|
||||
def isLastIndex(self, name):
|
||||
if not self.listStorageValid(name):
|
||||
return False
|
||||
return self.listStorage[name]['index'] == len(self.listStorage[name]['list']) - 1
|
||||
def isFirstIndex(self, name):
|
||||
if not self.listStorageValid(name):
|
||||
return False
|
||||
return self.listStorage[name]['index'] == 0
|
||||
def getNextIndex(self, name):
|
||||
if not self.listStorageValid(name):
|
||||
return False
|
||||
if self.isIndexListEmpty(name):
|
||||
self.listStorage[name]['index'] = -1
|
||||
return False
|
||||
self.listStorage[name]['index'] += 1
|
||||
if self.listStorage[name]['index'] > len(self.listStorage[name]['list']) -1:
|
||||
self.listStorage[name]['index'] = 0
|
||||
return True
|
||||
def setPrefIndex(self, name):
|
||||
if not self.listStorageValid(name):
|
||||
return False
|
||||
if self.isIndexListEmpty(name):
|
||||
self.listStorage[name]['index'] = -1
|
||||
return False
|
||||
self.listStorage[name]['index'] -= 1
|
||||
if self.listStorage[name]['index'] < 0:
|
||||
self.listStorage[name]['index'] = len(self.listStorage[name]['list']) -1
|
||||
return True
|
||||
def setFirstIndex(self, name):
|
||||
if not self.listStorageValid(name):
|
||||
return False
|
||||
if self.isIndexListEmpty(name):
|
||||
self.listStorage[name]['index'] = -1
|
||||
return False
|
||||
self.listStorage[name]['index'] = 0
|
||||
return True
|
||||
def getIndexListLen(self, name):
|
||||
if not self.listStorageValid(name):
|
||||
return 0
|
||||
if self.isIndexListEmpty(name):
|
||||
self.listStorage[name]['index'] = -1
|
||||
return 0
|
||||
return len(self.listStorage[name])
|
||||
def setLastIndex(self, name):
|
||||
if not self.listStorageValid(name):
|
||||
return False
|
||||
if self.isIndexListEmpty(name):
|
||||
self.listStorage[name]['index'] = -1
|
||||
return False
|
||||
self.listStorage[name]['index'] = len(self.listStorage[name]['list']) -1
|
||||
return True
|
||||
def clearCurrentIndexList(self, name):
|
||||
if not self.listStorageValid(name):
|
||||
return False
|
||||
self.listStorage[name]['index'] = []
|
||||
self.listStorage[name]['index'] = -1
|
||||
def getCurrentIndex(self,name):
|
||||
if not self.listStorageValid(name):
|
||||
return False
|
||||
if self.isIndexListEmpty(name):
|
||||
self.listStorage[name]['index'] = -1
|
||||
return False
|
||||
try:
|
||||
return self.listStorage[name]['index']
|
||||
except:
|
||||
retrun -1
|
||||
def isIndexListEmpty(self, name):
|
||||
if not self.listStorageValid(name):
|
||||
return False
|
||||
return len(self.listStorage[name]['list']) == 0
|
||||
def getIndexListElement(self, name):
|
||||
if not self.listStorageValid(name):
|
||||
return None
|
||||
if self.isIndexListEmpty(name):
|
||||
self.listStorage[name]['index'] = -1
|
||||
return None
|
||||
currIndex = self.getCurrentIndex(name)
|
||||
if currIndex == -1:
|
||||
return None
|
||||
try:
|
||||
return self.listStorage[name]['list'][currIndex]
|
||||
except:
|
||||
return None
|
15
src/fenrirscreenreader/core/outputData.py
Normal file
15
src/fenrirscreenreader/core/outputData.py
Normal file
@ -0,0 +1,15 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
import time
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
outputData = {
|
||||
'nextFlush': time.time(),
|
||||
'messageText': '',
|
||||
'messageOffset': None,
|
||||
'cursorOffset': None,
|
||||
}
|
272
src/fenrirscreenreader/core/outputManager.py
Normal file
272
src/fenrirscreenreader/core/outputManager.py
Normal file
@ -0,0 +1,272 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.utils import line_utils
|
||||
import string, time, re
|
||||
|
||||
class outputManager():
|
||||
def __init__(self):
|
||||
self.lastEcho = ''
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
self.env['runtime']['settingsManager'].loadDriver(\
|
||||
self.env['runtime']['settingsManager'].getSetting('speech', 'driver'), 'speechDriver')
|
||||
self.env['runtime']['settingsManager'].loadDriver(\
|
||||
self.env['runtime']['settingsManager'].getSetting('sound', 'driver'), 'soundDriver')
|
||||
self.env['runtime']['settingsManager'].loadDriver(\
|
||||
self.env['runtime']['settingsManager'].getSetting('braille', 'driver'), 'brailleDriver')
|
||||
def shutdown(self):
|
||||
self.env['runtime']['settingsManager'].shutdownDriver('soundDriver')
|
||||
self.env['runtime']['settingsManager'].shutdownDriver('speechDriver')
|
||||
self.env['runtime']['settingsManager'].shutdownDriver('brailleDriver')
|
||||
|
||||
def presentText(self, text, interrupt=True, soundIcon = '', ignorePunctuation=False, announceCapital=False, flush=True):
|
||||
if text == '':
|
||||
return
|
||||
self.env['runtime']['debug'].writeDebugOut("presentText:\nsoundIcon:'"+soundIcon+"'\nText:\n" + text ,debug.debugLevel.INFO)
|
||||
if self.playSoundIcon(soundIcon, interrupt):
|
||||
self.env['runtime']['debug'].writeDebugOut("soundIcon found" ,debug.debugLevel.INFO)
|
||||
return
|
||||
if (len(text) > 1) and (text.strip(string.whitespace) == ''):
|
||||
return
|
||||
toAnnounceCapital = announceCapital and text[0].isupper()
|
||||
if toAnnounceCapital:
|
||||
if self.playSoundIcon('capital', False):
|
||||
toAnnounceCapital = False
|
||||
self.lastEcho = text
|
||||
self.speakText(text, interrupt, ignorePunctuation,toAnnounceCapital)
|
||||
if flush:
|
||||
self.brailleText(text, flush)
|
||||
def getLastEcho(self):
|
||||
return self.lastEcho
|
||||
def speakText(self, text, interrupt=True, ignorePunctuation=False, announceCapital=False):
|
||||
if not self.env['runtime']['settingsManager'].getSettingAsBool('speech', 'enabled'):
|
||||
self.env['runtime']['debug'].writeDebugOut("Speech disabled in outputManager.speakText",debug.debugLevel.INFO)
|
||||
return
|
||||
if self.env['runtime']['speechDriver'] == None:
|
||||
self.env['runtime']['debug'].writeDebugOut("No speechDriver in outputManager.speakText",debug.debugLevel.ERROR)
|
||||
return
|
||||
if interrupt:
|
||||
self.interruptOutput()
|
||||
try:
|
||||
self.env['runtime']['speechDriver'].setLanguage(self.env['runtime']['settingsManager'].getSetting('speech', 'language'))
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut("setting speech language in outputManager.speakText",debug.debugLevel.ERROR)
|
||||
self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR)
|
||||
|
||||
try:
|
||||
self.env['runtime']['speechDriver'].setVoice(self.env['runtime']['settingsManager'].getSetting('speech', 'voice'))
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut("Error while setting speech voice in outputManager.speakText",debug.debugLevel.ERROR)
|
||||
self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR)
|
||||
|
||||
try:
|
||||
if announceCapital:
|
||||
self.env['runtime']['speechDriver'].setPitch(self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'capitalPitch'))
|
||||
else:
|
||||
self.env['runtime']['speechDriver'].setPitch(self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'pitch'))
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut("setting speech pitch in outputManager.speakText",debug.debugLevel.ERROR)
|
||||
self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR)
|
||||
|
||||
try:
|
||||
self.env['runtime']['speechDriver'].setRate(self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'rate'))
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut("setting speech rate in outputManager.speakText",debug.debugLevel.ERROR)
|
||||
self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR)
|
||||
|
||||
try:
|
||||
self.env['runtime']['speechDriver'].setModule(self.env['runtime']['settingsManager'].getSetting('speech', 'module'))
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut("setting speech module in outputManager.speakText",debug.debugLevel.ERROR)
|
||||
self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR)
|
||||
|
||||
try:
|
||||
self.env['runtime']['speechDriver'].setVolume(self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'volume'))
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut("setting speech volume in outputManager.speakText ",debug.debugLevel.ERROR)
|
||||
self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR)
|
||||
|
||||
try:
|
||||
cleanText = text.replace('\n',' , ')
|
||||
cleanText = self.env['runtime']['headLineManager'].replaceHeadLines(cleanText)
|
||||
cleanText = self.env['runtime']['punctuationManager'].proceedPunctuation(cleanText, ignorePunctuation)
|
||||
cleanText = re.sub(' +$',' ', cleanText)
|
||||
self.env['runtime']['speechDriver'].speak(cleanText)
|
||||
self.env['runtime']['debug'].writeDebugOut("Speak: "+ cleanText,debug.debugLevel.INFO)
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut("\"speak\" in outputManager.speakText ",debug.debugLevel.ERROR)
|
||||
self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR)
|
||||
|
||||
def brailleText(self, text='', flush=True):
|
||||
if not self.env['runtime']['settingsManager'].getSettingAsBool('braille', 'enabled'):
|
||||
return
|
||||
if self.env['runtime']['brailleDriver'] == None:
|
||||
return
|
||||
if flush:
|
||||
self.env['output']['nextFlush'] = time.time() + self.getFlushTime(text)
|
||||
self.env['output']['messageOffset'] = {'x':0,'y':0}
|
||||
self.env['output']['messageText'] = text
|
||||
displayText = self.getBrailleTextWithOffset(self.env['output']['messageText'], self.env['output']['messageOffset'])
|
||||
self.env['runtime']['brailleDriver'].writeText('flush '+ displayText)
|
||||
else:
|
||||
if self.env['output']['nextFlush'] < time.time():
|
||||
if self.env['output']['messageText'] != '':
|
||||
self.env['output']['messageText'] = ''
|
||||
if self.env['output']['messageOffset'] != None:
|
||||
self.env['output']['messageOffset'] = None
|
||||
cursor = self.getBrailleCursor()
|
||||
x, y, self.env['output']['brlText'] = \
|
||||
line_utils.getCurrentLine(cursor['x'], cursor['y'], self.env['screen']['newContentText'])
|
||||
displayText = self.getBrailleTextWithOffset(self.env['screen']['newContentText'], self.env['output']['cursorOffset'], cursor)
|
||||
self.env['runtime']['brailleDriver'].writeText('notflush ' + displayText)
|
||||
else:
|
||||
displayText = self.getBrailleTextWithOffset(self.env['output']['messageText'], self.env['output']['messageOffset'])
|
||||
self.env['runtime']['brailleDriver'].writeText('flush'+displayText)
|
||||
|
||||
def getBrailleCursor(self):
|
||||
if self.env['runtime']['settingsManager'].getSetting('braille', 'cursorFollowMode').upper() == 'REVIEW':
|
||||
return self.env['runtime']['cursorManager'].getReviewOrTextCursor()
|
||||
if self.env['runtime']['settingsManager'].getSetting('braille', 'cursorFollowMode').upper() == 'MANUAL':
|
||||
return self.env['runtime']['cursorManager'].getReviewOrTextCursor()
|
||||
if self.env['runtime']['settingsManager'].getSetting('braille', 'cursorFollowMode').upper() == 'LAST':
|
||||
return self.env['runtime']['cursorManager'].getReviewOrTextCursor()
|
||||
return self.env['runtime']['cursorManager'].getReviewOrTextCursor()
|
||||
|
||||
def getFixCursorCell(self):
|
||||
size = self.env['runtime']['brailleDriver'].getDeviceSize()[0]
|
||||
fixCell = self.env['runtime']['settingsManager'].getSettingAsInt('braille', 'fixCursorOnCell')
|
||||
if fixCell <= -1:
|
||||
return size[0]
|
||||
if fixCell >= size[0]:
|
||||
return size[0]
|
||||
return fixCell
|
||||
def getActiveOffsetAndText(self):
|
||||
if self.env['output']['messageOffset']:
|
||||
return self.env['output']['messageOffset'], self.env['output']['messageText']
|
||||
if not self.env['output']['cursorOffset']:
|
||||
return self.getBrailleCursor(), self.env['screen']['newContentText']
|
||||
return self.env['output']['cursorOffset'], self.env['screen']['newContentText']
|
||||
def getHorizontalPanSize(self):
|
||||
size = self.env['runtime']['brailleDriver'].getDeviceSize()
|
||||
if self.env['runtime']['settingsManager'].getSettingAsInt('braille', 'panSizeHorizontal') <= 0:
|
||||
return size[0]
|
||||
if self.env['runtime']['settingsManager'].getSettingAsInt('braille', 'panSizeHorizontal') >= size[0]:
|
||||
return size[0]
|
||||
return self.env['runtime']['settingsManager'].getSettingAsInt('braille', 'panSizeHorizontal')
|
||||
def getHorizontalPanLevel(self,offsetChange = 0):
|
||||
panned = True
|
||||
panSize = self.getHorizontalPanSize()
|
||||
offset, text = self.getActiveOffsetAndText()
|
||||
currline = text.split('\n')[offset['y']]
|
||||
newOffsetStart = (int(offset['x'] / panSize) + offsetChange) * panSize
|
||||
if newOffsetStart < 0:
|
||||
newOffsetStart = 0
|
||||
panned = False
|
||||
if newOffsetStart >= len(text):
|
||||
newOffsetStart = int((len(text) - panSize - 1) / panSize)
|
||||
panned = False
|
||||
return newOffsetStart, panned
|
||||
def setPanLeft(self):
|
||||
newPan, panned = self.getHorizontalPanLevel(-1)
|
||||
if self.env['output']['messageOffset']:
|
||||
self.env['output']['messageOffset'] = newPan.copy()
|
||||
else:
|
||||
self.env['output']['cursorOffset'] = newPan.copy()
|
||||
return panned
|
||||
def setPanRight(self):
|
||||
newPan, panned = self.getHorizontalPanLevel(1)
|
||||
if self.env['output']['messageOffset']:
|
||||
self.env['output']['messageOffset'] = newPan.copy()
|
||||
else:
|
||||
self.env['output']['cursorOffset'] = newPan.copy()
|
||||
return panned
|
||||
def removePanning(self):
|
||||
if self.env['output']['messageOffset']:
|
||||
self.env['output']['messageOffset'] = None
|
||||
else:
|
||||
self.env['output']['cursorOffset'] = None
|
||||
def getBrailleTextWithOffset(self, text, offset = None, cursor = None):
|
||||
if text == '':
|
||||
return ''
|
||||
size = self.env['runtime']['brailleDriver'].getDeviceSize()
|
||||
offsetText = text
|
||||
|
||||
if cursor and not offset:
|
||||
if self.env['runtime']['settingsManager'].getSetting('braille', 'cursorFollowMode').upper() == 'FIXCELL':
|
||||
#fix cell
|
||||
cursorCell = self.getFixCursorCell()
|
||||
offsetStart = cursor['x']
|
||||
if offsetStart < size[0]:
|
||||
if offsetStart <= cursorCell:
|
||||
return offsetText[0: size[0]]
|
||||
|
||||
offsetStart -= cursorCell
|
||||
if offsetStart >= len(offsetText):
|
||||
offsetStart = len(offsetText) - 1
|
||||
else:
|
||||
# page and fallback
|
||||
offsetStart = int(cursor['x'] / size[0]) * size[0]
|
||||
else:
|
||||
if not offset:
|
||||
offset = {'x':0,'y':0}
|
||||
offsetStart = offset['x']
|
||||
if offsetStart >= len(offsetText):
|
||||
offsetStart = len(offsetText) - size[0]
|
||||
|
||||
if offsetStart < 0:
|
||||
offsetStart = 0
|
||||
offsetEnd = offsetStart + size[0]
|
||||
offsetText = offsetText[offsetStart: offsetEnd]
|
||||
return offsetText
|
||||
def interruptOutput(self):
|
||||
self.env['runtime']['speechDriver'].cancel()
|
||||
self.env['runtime']['debug'].writeDebugOut("Interrupt speech",debug.debugLevel.INFO)
|
||||
|
||||
def clearFlushTime(self):
|
||||
self.setFlushTime(0.0)
|
||||
|
||||
def setFlushTime(self,newTime):
|
||||
self.env['output']['nextFlush'] = newTime
|
||||
|
||||
def getFlushTime(self,text=''):
|
||||
if self.env['runtime']['settingsManager'].getSettingAsFloat('braille', 'flushTimeout') < 0 or \
|
||||
self.env['runtime']['settingsManager'].getSetting('braille', 'flushMode').upper() == 'NONE':
|
||||
return 999999999999
|
||||
if self.env['runtime']['settingsManager'].getSetting('braille', 'flushMode').upper() == 'FIX':
|
||||
return self.env['runtime']['settingsManager'].getSettingAsFloat('braille', 'flushTimeout')
|
||||
if self.env['runtime']['settingsManager'].getSetting('braille', 'flushMode').upper() == 'CHAR':
|
||||
return self.env['runtime']['settingsManager'].getSettingAsFloat('braille', 'flushTimeout') * len(text)
|
||||
if self.env['runtime']['settingsManager'].getSetting('braille', 'flushMode').upper() == 'WORD':
|
||||
wordsList = text.split(' ')
|
||||
return self.env['runtime']['settingsManager'].getSettingAsFloat('braille', 'flushTimeout') * len( list( filter(None, wordsList) ) )
|
||||
|
||||
def playSoundIcon(self, soundIcon = '', interrupt=True):
|
||||
if soundIcon == '':
|
||||
return False
|
||||
soundIcon = soundIcon.upper()
|
||||
if not self.env['runtime']['settingsManager'].getSettingAsBool('sound', 'enabled'):
|
||||
self.env['runtime']['debug'].writeDebugOut("Sound disabled in outputManager.speakText",debug.debugLevel.INFO)
|
||||
return False
|
||||
|
||||
if self.env['runtime']['soundDriver'] == None:
|
||||
self.env['runtime']['debug'].writeDebugOut("No speechDriver in outputManager.speakText",debug.debugLevel.ERROR)
|
||||
return False
|
||||
try:
|
||||
self.env['runtime']['soundDriver'].setVolume(self.env['runtime']['settingsManager'].getSettingAsFloat('sound', 'volume'))
|
||||
self.env['runtime']['soundDriver'].playSoundFile(self.env['soundIcons'][soundIcon], interrupt)
|
||||
return True
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut("\"playSoundIcon\" in outputManager.speakText ",debug.debugLevel.ERROR)
|
||||
self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR)
|
||||
return False
|
||||
def announceActiveCursor(self, interrupt_p=False):
|
||||
if self.env['runtime']['cursorManager'].isReviewMode():
|
||||
self.presentText(' review cursor ', interrupt=interrupt_p)
|
||||
else:
|
||||
self.presentText(' text cursor ', interrupt=interrupt_p)
|
||||
|
87
src/fenrirscreenreader/core/processManager.py
Normal file
87
src/fenrirscreenreader/core/processManager.py
Normal file
@ -0,0 +1,87 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.core.eventData import fenrirEventType
|
||||
import time
|
||||
from threading import Thread
|
||||
from multiprocessing import Process
|
||||
|
||||
class processManager():
|
||||
def __init__(self):
|
||||
self._Processes = []
|
||||
self._Threads = []
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
self.running = self.env['runtime']['eventManager'].getRunning()
|
||||
self.addSimpleEventThread(fenrirEventType.HeartBeat, self.heartBeatTimer, multiprocess=True)
|
||||
def shutdown(self):
|
||||
self.terminateAllProcesses()
|
||||
|
||||
def terminateAllProcesses(self):
|
||||
for proc in self._Processes:
|
||||
try:
|
||||
proc.terminate()
|
||||
except Exception as e:
|
||||
print(e)
|
||||
def heartBeatTimer(self, active):
|
||||
try:
|
||||
time.sleep(0.5)
|
||||
except:
|
||||
pass
|
||||
return time.time()
|
||||
def addCustomEventThread(self, function, pargs = None, multiprocess = False, runOnce = False):
|
||||
eventQueue = self.env['runtime']['eventManager'].getEventQueue()
|
||||
if multiprocess:
|
||||
t = Process(target=self.customEventWorkerThread, args=(eventQueue, function, pargs, runOnce))
|
||||
self._Processes.append(t)
|
||||
else:# thread not implemented yet
|
||||
t = Thread(target=self.customEventWorkerThread, args=(eventQueue, function, pargs, runOnce))
|
||||
self._Threads.append(t)
|
||||
t.start()
|
||||
|
||||
def addSimpleEventThread(self, event, function, pargs = None, multiprocess = False, runOnce = False):
|
||||
if multiprocess:
|
||||
t = Process(target=self.simpleEventWorkerThread, args=(event, function, pargs, runOnce))
|
||||
self._Processes.append(t)
|
||||
else:
|
||||
t = Thread(target=self.simpleEventWorkerThread, args=(event, function, pargs, runOnce))
|
||||
self._Threads.append(t)
|
||||
t.start()
|
||||
|
||||
def customEventWorkerThread(self, eventQueue, function, pargs = None, runOnce = False):
|
||||
#if not isinstance(eventQueue, Queue):
|
||||
# return
|
||||
if not callable(function):
|
||||
return
|
||||
while self.running.value:
|
||||
try:
|
||||
if pargs:
|
||||
function(self.running, eventQueue, pargs)
|
||||
else:
|
||||
function(self.running, eventQueue)
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('processManager:customEventWorkerThread:function():' + str(e),debug.debugLevel.ERROR)
|
||||
if runOnce:
|
||||
break
|
||||
|
||||
def simpleEventWorkerThread(self, event, function, pargs = None, runOnce = False):
|
||||
if not isinstance(event, fenrirEventType):
|
||||
return
|
||||
if not callable(function):
|
||||
return
|
||||
while self.running.value:
|
||||
Data = None
|
||||
try:
|
||||
if pargs:
|
||||
Data = function(self.running, pargs)
|
||||
else:
|
||||
Data = function(self.running)
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('processManager:simpleEventWorkerThread:function():' + str(e),debug.debugLevel.ERROR)
|
||||
self.env['runtime']['eventManager'].putToEventQueue(event, Data)
|
||||
if runOnce:
|
||||
break
|
61
src/fenrirscreenreader/core/punctuationData.py
Normal file
61
src/fenrirscreenreader/core/punctuationData.py
Normal file
@ -0,0 +1,61 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
import string
|
||||
|
||||
punctuationData = {
|
||||
'LEVELDICT':{
|
||||
'none': '',
|
||||
'some': '#-$~+*-/\\@',
|
||||
'most': '.,:-$~ +*-/\\@!#%^&*()[]}{<>;',
|
||||
'all': string.punctuation + ' §',
|
||||
},
|
||||
'PUNCTDICT':{
|
||||
' ':'space',
|
||||
'&':'and',
|
||||
"'":"apostrophe",
|
||||
'@':'at',
|
||||
'\\':'backslash',
|
||||
'|':'bar',
|
||||
'!':'bang',
|
||||
'^':'carrot',
|
||||
':':'colon',
|
||||
',':'comma',
|
||||
'-':'dash',
|
||||
'$':'dollar',
|
||||
'.':'dot',
|
||||
'>':'greater',
|
||||
'`':'grave',
|
||||
'#':'hash',
|
||||
'{':'left brace',
|
||||
'[':'left bracket',
|
||||
'(':'left paren',
|
||||
'<':'less',
|
||||
'%':'percent',
|
||||
'+':'plus',
|
||||
'?':'question',
|
||||
'"':'quote',
|
||||
')':'right paren',
|
||||
'}':'right brace',
|
||||
']':'right bracket',
|
||||
';':'semicolon',
|
||||
'/':'slash',
|
||||
'*':'star',
|
||||
'~':'tilde',
|
||||
'_':'line',
|
||||
'=':'equals',
|
||||
},
|
||||
'CUSTOMDICT':{
|
||||
},
|
||||
'EMOTICONDICT':{
|
||||
':)':'smiley',
|
||||
';)':'winking face',
|
||||
'XD':'loool',
|
||||
':@':'angry face',
|
||||
':D':'lought'
|
||||
},
|
||||
}
|
83
src/fenrirscreenreader/core/punctuationManager.py
Normal file
83
src/fenrirscreenreader/core/punctuationManager.py
Normal file
@ -0,0 +1,83 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
import string
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
class punctuationManager():
|
||||
def __init__(self):
|
||||
pass
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
self.allPunctNone = dict.fromkeys(map(ord, string.punctuation +"§ "), ' ')
|
||||
# replace with None:
|
||||
# dot, comma, grave, apostrophe
|
||||
#for char in [ord('`'),ord("'")]:
|
||||
# self.allPunctNone[char] = None
|
||||
# dont restore the following (for announce correct pause)
|
||||
for char in [ord("'"),ord('.'), ord(','), ord(';'), ord(':'), ord('?'), ord('!'), ord('-')]:
|
||||
self.allPunctNone[char] = chr(char)
|
||||
def shutdown(self):
|
||||
pass
|
||||
def removeUnused(self, text, currLevel = ''):
|
||||
# dont translate dot and comma because they create a pause
|
||||
currAllPunctNone = self.allPunctNone.copy()
|
||||
for char in currLevel:
|
||||
try:
|
||||
del currAllPunctNone[ord(char)]
|
||||
except:
|
||||
pass
|
||||
return text.translate(currAllPunctNone)
|
||||
|
||||
def useCustomDict(self, text, customDict, seperator=''):
|
||||
resultText = str(text)
|
||||
if customDict:
|
||||
for key,item in customDict.items():
|
||||
resultText = resultText.replace(str(key),seperator + str(item) + seperator)
|
||||
return resultText
|
||||
|
||||
def usePunctuationDict(self, text, punctuationDict, punctuation):
|
||||
resultText = str(text)
|
||||
|
||||
if punctuationDict and punctuation and punctuation != '':
|
||||
if ' ' in punctuation:
|
||||
resultText = resultText.replace(' ',' ' + punctuationDict[' '] + ' ')
|
||||
for key,item in punctuationDict.items():
|
||||
if key in punctuation and key not in ' ':
|
||||
if self.env['runtime']['settingsManager'].getSetting('general', 'respectPunctuationPause') and \
|
||||
len(key) == 1 and \
|
||||
key in "',.;:?!":
|
||||
resultText = resultText.replace(str(key),' ' +str(item) + str(key) + ' ')
|
||||
else:
|
||||
resultText = resultText.replace(str(key),' ' +str(item) + ' ')
|
||||
return resultText
|
||||
|
||||
def proceedPunctuation(self, text, ignorePunctuation=False):
|
||||
resultText = text
|
||||
resultText = self.useCustomDict(resultText, self.env['punctuation']['CUSTOMDICT'])
|
||||
if self.env['runtime']['settingsManager'].getSettingAsBool('general', 'emoticons'):
|
||||
resultText = self.useCustomDict(resultText, self.env['punctuation']['EMOTICONDICT'], ' ')
|
||||
currPunctLevel = ''
|
||||
if not ignorePunctuation and self.env['runtime']['settingsManager'].getSetting('general', 'punctuationLevel').lower() in self.env['punctuation']['LEVELDICT']:
|
||||
currPunctLevel = self.env['punctuation']['LEVELDICT'][self.env['runtime']['settingsManager'].getSetting('general', 'punctuationLevel').lower()]
|
||||
else:
|
||||
currPunctLevel = string.punctuation +' §'
|
||||
resultText = self.usePunctuationDict(resultText, self.env['punctuation']['PUNCTDICT'], currPunctLevel)
|
||||
resultText = self.removeUnused(resultText, currPunctLevel)
|
||||
return resultText
|
||||
|
||||
def cyclePunctuation(self):
|
||||
punctList = list(self.env['punctuation']['LEVELDICT'].keys())
|
||||
try:
|
||||
currIndex = punctList.index(self.env['runtime']['settingsManager'].getSetting('general', 'punctuationLevel').lower()) # curr punctuation
|
||||
except:
|
||||
return False
|
||||
currIndex += 1
|
||||
if currIndex >= len(punctList):
|
||||
currIndex = 0
|
||||
currLevel = punctList[currIndex]
|
||||
self.env['runtime']['settingsManager'].setSetting('general', 'punctuationLevel', currLevel.lower())
|
||||
return True
|
20
src/fenrirscreenreader/core/runtimeData.py
Normal file
20
src/fenrirscreenreader/core/runtimeData.py
Normal file
@ -0,0 +1,20 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
runtimeData = {
|
||||
'speechDriver': None,
|
||||
'screenDriver': None,
|
||||
'soundDriver': None,
|
||||
'inputDriver': None,
|
||||
'brailleDriver': None,
|
||||
'inputManager': None,
|
||||
'commandManager': None,
|
||||
'screenManager': None,
|
||||
'outputManager': None,
|
||||
'debug':None,
|
||||
}
|
55
src/fenrirscreenreader/core/screenData.py
Normal file
55
src/fenrirscreenreader/core/screenData.py
Normal file
@ -0,0 +1,55 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
import time
|
||||
|
||||
screenData = {
|
||||
'columns': 0,
|
||||
'lines': 0,
|
||||
'oldDelta': '',
|
||||
'oldAttribDelta': '',
|
||||
'oldNegativeDelta': '',
|
||||
'oldCursorReview':None,
|
||||
'oldCursorAttrib':None,
|
||||
'oldCursor':{'x':0,'y':0},
|
||||
'oldContentBytes': b'',
|
||||
'oldContentText': '',
|
||||
'oldContentAttrib': None,
|
||||
'oldApplication': '',
|
||||
'oldTTY':None,
|
||||
'newDelta': '',
|
||||
'newNegativeDelta': '',
|
||||
'newAttribDelta': '',
|
||||
'newCursorReview':None,
|
||||
'newCursorAttrib':None,
|
||||
'newCursor':{'x':0,'y':0},
|
||||
'newContentBytes': b'',
|
||||
'newContentText': '',
|
||||
'newContentAttrib': None,
|
||||
'newTTY':'0',
|
||||
'newApplication': '',
|
||||
'lastScreenUpdate': time.time(),
|
||||
'autoIgnoreScreens':[],
|
||||
}
|
||||
'''
|
||||
screenData = {
|
||||
'columns': 0,
|
||||
'lines': 0,
|
||||
'textDelta': '',
|
||||
'negativeDelta': '',
|
||||
'attribDelta': '',
|
||||
'reviewCursor':None, #{'x':0,'y':0}
|
||||
'attribCursor':None, #{'x':0,'y':0}
|
||||
'textCursor':None, #{'x':0,'y':0}
|
||||
'content': None, #{'x':0,'y':0}
|
||||
'Text': '',
|
||||
'Attrib': None,
|
||||
'screen': None,
|
||||
'application': '',
|
||||
'timestamp': time.time(),
|
||||
}
|
||||
'''
|
48
src/fenrirscreenreader/core/screenDriver.py
Normal file
48
src/fenrirscreenreader/core/screenDriver.py
Normal file
@ -0,0 +1,48 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
#attrib:
|
||||
#http://rampex.ihep.su/Linux/linux_howto/html/tutorials/mini/Colour-ls-6.html
|
||||
#0 = black, 1 = blue, 2 = green, 3 = cyan, 4 = red, 5 = purple, 6 = brown/yellow, 7 = white.
|
||||
#https://github.com/jwilk/vcsapeek/blob/master/linuxvt.py
|
||||
#blink = 5 if attr & 1 else 0
|
||||
#bold = 1 if attr & 16 else 0
|
||||
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
class screenDriver():
|
||||
def __init__(self):
|
||||
self._isInitialized = False
|
||||
self.bgColorNames = {0: _('black'), 1: _('blue'), 2: _('green'), 3: _('cyan'), 4: _('red'), 5: _('Magenta'), 6: _('brown/yellow'), 7: _('white')}
|
||||
self.fgColorNames = {0: _('Black'), 1: _('Blue'), 2: _('Green'), 3: _('Cyan'), 4: _('Red'), 5: _('Magenta'), 6: _('brown/yellow'), 7: _('Light gray'), 8: _('Dark gray'), 9: _('Light blue'), 10: ('Light green'), 11: _('Light cyan'), 12: _('Light red'), 13: _('Light magenta'), 14: _('Light yellow'), 15: _('White')}
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
self._isInitialized = True
|
||||
def shutdown(self):
|
||||
self._isInitialized = False
|
||||
def getCurrScreen(self):
|
||||
pass
|
||||
def getCurrApplication(self):
|
||||
pass
|
||||
def getSessionInformation(self):
|
||||
pass
|
||||
def getFenrirBGColor(self, attribute):
|
||||
return ''
|
||||
def getFenrirFGColor(self, attribute):
|
||||
return ''
|
||||
def getFenrirUnderline(self, attribute):
|
||||
return ''
|
||||
def getFenrirBold(self, attribute):
|
||||
return ''
|
||||
def getFenrirBlink(self, attribute):
|
||||
return ''
|
||||
def getFenrirFont(self, attribute):
|
||||
return ''
|
||||
def getFenrirFontSize(self, attribute):
|
||||
return ''
|
||||
def update(self, trigger='onUpdate'):
|
||||
pass
|
||||
|
116
src/fenrirscreenreader/core/screenManager.py
Normal file
116
src/fenrirscreenreader/core/screenManager.py
Normal file
@ -0,0 +1,116 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
import time, os
|
||||
|
||||
class screenManager():
|
||||
def __init__(self):
|
||||
pass
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
self.env['runtime']['settingsManager'].loadDriver(\
|
||||
self.env['runtime']['settingsManager'].getSetting('screen', 'driver'), 'screenDriver')
|
||||
self.env['runtime']['screenDriver'].getCurrScreen()
|
||||
self.env['runtime']['screenDriver'].getSessionInformation()
|
||||
|
||||
def shutdown(self):
|
||||
self.env['runtime']['settingsManager'].shutdownDriver('screenDriver')
|
||||
def hanldeScreenChange(self, eventData):
|
||||
self.env['runtime']['screenDriver'].getCurrScreen()
|
||||
self.env['runtime']['screenDriver'].getSessionInformation()
|
||||
if self.isScreenChange():
|
||||
self.changeBrailleScreen()
|
||||
if not self.isSuspendingScreen(self.env['screen']['newTTY']):
|
||||
self.env['runtime']['screenDriver'].update(eventData, 'onScreenChange')
|
||||
self.env['screen']['lastScreenUpdate'] = time.time()
|
||||
def handleScreenUpdate(self, eventData):
|
||||
self.env['screen']['oldApplication'] = self.env['screen']['newApplication']
|
||||
if not self.isSuspendingScreen(self.env['screen']['newTTY']):
|
||||
self.env['runtime']['screenDriver'].update(eventData, 'onScreenUpdate')
|
||||
#if trigger == 'onUpdate' or self.isScreenChange() \
|
||||
# or len(self.env['screen']['newDelta']) > 6:
|
||||
# self.env['runtime']['screenDriver'].getCurrApplication()
|
||||
self.env['screen']['lastScreenUpdate'] = time.time()
|
||||
def formatAttributes(self, attribute, attributeFormatString = None):
|
||||
if not attributeFormatString:
|
||||
attributeFormatString = self.env['runtime']['settingsManager'].getSetting('general', 'attributeFormatString')
|
||||
if not attributeFormatString:
|
||||
return ''
|
||||
if attributeFormatString == '':
|
||||
return ''
|
||||
attributeFormatString = attributeFormatString.replace('fenrirBGColor', self.env['runtime']['screenDriver'].getFenrirBGColor(attribute))
|
||||
attributeFormatString = attributeFormatString.replace('fenrirFGColor', self.env['runtime']['screenDriver'].getFenrirFGColor(attribute))
|
||||
attributeFormatString = attributeFormatString.replace('fenrirUnderline', self.env['runtime']['screenDriver'].getFenrirUnderline(attribute))
|
||||
attributeFormatString = attributeFormatString.replace('fenrirBold', self.env['runtime']['screenDriver'].getFenrirBold(attribute))
|
||||
attributeFormatString = attributeFormatString.replace('fenrirBlink', self.env['runtime']['screenDriver'].getFenrirBlink(attribute))
|
||||
attributeFormatString = attributeFormatString.replace('fenrirFontSize', self.env['runtime']['screenDriver'].getFenrirFontSize(attribute))
|
||||
attributeFormatString = attributeFormatString.replace('fenrirFont', self.env['runtime']['screenDriver'].getFenrirFont(attribute))
|
||||
return attributeFormatString
|
||||
def isSuspendingScreen(self, screen = None):
|
||||
if screen == None:
|
||||
screen = self.env['screen']['newTTY']
|
||||
ignoreScreens = []
|
||||
fixIgnoreScreens = self.env['runtime']['settingsManager'].getSetting('screen', 'suspendingScreen')
|
||||
if fixIgnoreScreens != '':
|
||||
ignoreScreens.extend(fixIgnoreScreens.split(','))
|
||||
if self.env['runtime']['settingsManager'].getSettingAsBool('screen', 'autodetectSuspendingScreen'):
|
||||
ignoreScreens.extend(self.env['screen']['autoIgnoreScreens'])
|
||||
self.env['runtime']['debug'].writeDebugOut('screenManager:isSuspendingScreen ' + str(ignoreScreens) + ' '+ str(self.env['screen']['newTTY']),debug.debugLevel.INFO)
|
||||
try:
|
||||
ignoreFileName = self.env['runtime']['settingsManager'].getSetting('screen', 'suspendingScreenFile')
|
||||
if ignoreFileName != '':
|
||||
if os.access(ignoreFileName, os.R_OK):
|
||||
with open(ignoreFileName) as fp:
|
||||
ignoreScreens.extend(fp.read().replace('\n','').split(','))
|
||||
except:
|
||||
pass
|
||||
return (screen in ignoreScreens)
|
||||
|
||||
def isScreenChange(self):
|
||||
if not self.env['screen']['oldTTY']:
|
||||
return False
|
||||
return self.env['screen']['newTTY'] != self.env['screen']['oldTTY']
|
||||
def isDelta(self, ignoreSpace=False):
|
||||
newDelta = self.env['screen']['newDelta']
|
||||
if ignoreSpace:
|
||||
newDelta = newDelta.strip()
|
||||
return newDelta != ''
|
||||
def isNegativeDelta(self):
|
||||
return self.env['screen']['newNegativeDelta'] != ''
|
||||
def getWindowAreaInText(self, text):
|
||||
if not self.env['runtime']['cursorManager'].isApplicationWindowSet():
|
||||
return text
|
||||
windowText = ''
|
||||
windowList = text.split('\n')
|
||||
currApp = self.env['runtime']['applicationManager'].getCurrentApplication()
|
||||
windowList = windowList[self.env['commandBuffer']['windowArea'][currApp]['1']['y']:self.env['commandBuffer']['windowArea'][currApp]['2']['y'] + 1]
|
||||
for line in windowList:
|
||||
windowText += line[self.env['commandBuffer']['windowArea'][currApp]['1']['x']:self.env['commandBuffer']['windowArea'][currApp]['2']['x'] + 1] + '\n'
|
||||
return windowText
|
||||
|
||||
def injectTextToScreen(self, text, screen = None):
|
||||
try:
|
||||
self.env['runtime']['screenDriver'].injectTextToScreen(text, screen)
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('screenManager:injectTextToScreen ' + str(e),debug.debugLevel.ERROR)
|
||||
|
||||
def changeBrailleScreen(self):
|
||||
if not self.env['runtime']['settingsManager'].getSettingAsBool('braille', 'enabled'):
|
||||
return
|
||||
if not self.env['runtime']['brailleDriver']:
|
||||
return
|
||||
if self.env['screen']['oldTTY']:
|
||||
if not self.isSuspendingScreen(self.env['screen']['oldTTY']):
|
||||
try:
|
||||
self.env['runtime']['brailleDriver'].leveScreen()
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('screenManager:changeBrailleScreen:leveScreen ' + str(e),debug.debugLevel.ERROR)
|
||||
if not self.isSuspendingScreen():
|
||||
try:
|
||||
self.env['runtime']['brailleDriver'].enterScreen(self.env['screen']['newTTY'])
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('screenManager:changeBrailleScreen:enterScreen ' + str(e),debug.debugLevel.ERROR)
|
113
src/fenrirscreenreader/core/settingsData.py
Normal file
113
src/fenrirscreenreader/core/settingsData.py
Normal file
@ -0,0 +1,113 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
settingsData = {
|
||||
'sound': {
|
||||
'enabled': True,
|
||||
'driver': 'genericDriver',
|
||||
'theme': 'default',
|
||||
'volume': 1.0,
|
||||
'genericPlayFileCommand': 'play -q -v fenrirVolume fenrirSoundFile',
|
||||
'genericFrequencyCommand': 'play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence'
|
||||
},
|
||||
'speech':{
|
||||
'enabled': True,
|
||||
'driver': 'genericDriver',
|
||||
'serverPath': '',
|
||||
'rate': 0.75,
|
||||
'pitch': 0.5,
|
||||
'capitalPitch':0.8,
|
||||
'volume': 1.0,
|
||||
'module': '',
|
||||
'voice': 'en-us',
|
||||
'language': '',
|
||||
'autoReadIncoming': True,
|
||||
'genericSpeechCommand':'espeak -a fenrirVolume -s fenrirRate -p fenrirPitch -v fenrirVoice "fenrirText"',
|
||||
'fenrirMinVolume':0,
|
||||
'fenrirMaxVolume':200,
|
||||
'fenrirMinPitch':0,
|
||||
'fenrirMaxPitch':99,
|
||||
'fenrirMinRate':80,
|
||||
'fenrirMaxRate':450,
|
||||
},
|
||||
'braille':{
|
||||
'enabled': False,
|
||||
'driver':'brlapiDriver',
|
||||
'layout': 'en',
|
||||
'flushMode': 'word', #NONE,FIX,CHAR,WORD
|
||||
'flushTimeout': 3,
|
||||
'cursorFocusMode':'page', # page,fixCell
|
||||
'fixCursorOnCell': -1,
|
||||
'cursorFollowMode': 'review', # none, review, last, text
|
||||
'panSizeHorizontal': 0 # 0 = display size
|
||||
},
|
||||
'screen':{
|
||||
'driver': 'vcsaDriver',
|
||||
'encoding': 'auto',
|
||||
'screenUpdateDelay': 0.1,
|
||||
'suspendingScreen': '',
|
||||
'suspendingScreenFile': '/tmp/fenrirSuspend',
|
||||
'autodetectSuspendingScreen': False,
|
||||
},
|
||||
'general':{
|
||||
'debugLevel': debug.debugLevel.DEACTIVE,
|
||||
'debugMode': 'FILE',
|
||||
'punctuationProfile':'default',
|
||||
'punctuationLevel': 'some',
|
||||
'respectPunctuationPause':True,
|
||||
'newLinePause':True,
|
||||
'numberOfClipboards': 10,
|
||||
'emoticons': True,
|
||||
'fenrirKeys': 'KEY_KP0,KEY_META',
|
||||
'scriptKeys': 'KEY_COMPOSE',
|
||||
'timeFormat': '%I:%M%P',
|
||||
'dateFormat': '%A, %B %d, %Y',
|
||||
'autoSpellCheck': False,
|
||||
'spellCheckLanguage': 'en_US',
|
||||
'scriptPath': '/usr/share/fenrir/scripts',
|
||||
'commandPath': '/usr/share/fenrir/commands',
|
||||
'attributeFormatString': 'Background fenrirBGColor,Foreground fenrirFGColor,fenrirUnderline,fenrirBold,fenrirBlink, Font fenrirFont,Fontsize fenrirFontSize'
|
||||
},
|
||||
'focus':{
|
||||
'cursor': True,
|
||||
'highlight': False,
|
||||
},
|
||||
'review':{
|
||||
'lineBreak': True,
|
||||
'endOfScreen': True,
|
||||
'leaveReviewOnCursorChange': True,
|
||||
'leaveReviewOnScreenChange': True,
|
||||
},
|
||||
'promote':{
|
||||
'enabled': True,
|
||||
'inactiveTimeoutSec': 120,
|
||||
'list': '',
|
||||
},
|
||||
'time':{
|
||||
'enabled': False,
|
||||
'presentTime': True,
|
||||
'presentDate': True,
|
||||
'delaySec': 0,
|
||||
'onMinutes': '00,30',
|
||||
'announce': True,
|
||||
'interrupt': False,
|
||||
},
|
||||
'keyboard':{
|
||||
'driver': 'evdev',
|
||||
'device': 'all',
|
||||
'grabDevices': True,
|
||||
'ignoreShortcuts': False,
|
||||
'keyboardLayout': "desktop",
|
||||
'charEcho': False,
|
||||
'charDeleteEcho': True,
|
||||
'wordEcho': True,
|
||||
'interruptOnKeyPress': True,
|
||||
'interruptOnKeyPressFilter': '',
|
||||
'doubleTapTimeout': 0.2,
|
||||
}
|
||||
}
|
364
src/fenrirscreenreader/core/settingsManager.py
Normal file
364
src/fenrirscreenreader/core/settingsManager.py
Normal file
@ -0,0 +1,364 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
import os, inspect
|
||||
currentdir = os.path.dirname(os.path.realpath(os.path.abspath(inspect.getfile(inspect.currentframe()))))
|
||||
fenrirPath = os.path.dirname(currentdir)
|
||||
|
||||
from configparser import ConfigParser
|
||||
from fenrirscreenreader.core import debugManager
|
||||
from fenrirscreenreader.core import memoryManager
|
||||
from fenrirscreenreader.core import processManager
|
||||
from fenrirscreenreader.core import eventManager
|
||||
from fenrirscreenreader.core import inputManager
|
||||
from fenrirscreenreader.core import outputManager
|
||||
from fenrirscreenreader.core import commandManager
|
||||
from fenrirscreenreader.core import screenManager
|
||||
from fenrirscreenreader.core import punctuationManager
|
||||
from fenrirscreenreader.core import cursorManager
|
||||
from fenrirscreenreader.core import applicationManager
|
||||
from fenrirscreenreader.core import helpManager
|
||||
from fenrirscreenreader.core import headLineManager
|
||||
from fenrirscreenreader.core import tableManager
|
||||
from fenrirscreenreader.core import environment
|
||||
from fenrirscreenreader.core import inputData
|
||||
from fenrirscreenreader.core.settingsData import settingsData
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.utils import module_utils
|
||||
|
||||
class settingsManager():
|
||||
def __init__(self):
|
||||
self.settings = settingsData
|
||||
self.settingArgDict = {}
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def loadShortcuts(self, kbConfigPath=fenrirPath + '/../../config/keyboard/desktop.conf'):
|
||||
kbConfig = open(kbConfigPath,"r")
|
||||
while(True):
|
||||
invalid = False
|
||||
line = kbConfig.readline()
|
||||
if not line:
|
||||
break
|
||||
line = line.replace('\n','')
|
||||
if line.replace(" ","") == '':
|
||||
continue
|
||||
if line.replace(" ","").startswith("#"):
|
||||
continue
|
||||
if line.count("=") != 1:
|
||||
continue
|
||||
sepLine = line.split('=')
|
||||
commandName = sepLine[1].upper()
|
||||
sepLine[0] = sepLine[0].replace(" ","")
|
||||
sepLine[0] = sepLine[0].replace("'","")
|
||||
sepLine[0] = sepLine[0].replace('"',"")
|
||||
keys = sepLine[0].split(',')
|
||||
shortcutKeys = []
|
||||
shortcutRepeat = 1
|
||||
shortcut = []
|
||||
for key in keys:
|
||||
try:
|
||||
shortcutRepeat = int(key)
|
||||
except:
|
||||
if not self.isValidKey(key.upper()):
|
||||
self.env['runtime']['debug'].writeDebugOut("invalid key : "+ key.upper() + ' command:' +commandName ,debug.debugLevel.WARNING)
|
||||
invalid = True
|
||||
break
|
||||
shortcutKeys.append(key.upper())
|
||||
if invalid:
|
||||
continue
|
||||
shortcut.append(shortcutRepeat)
|
||||
shortcut.append(sorted(shortcutKeys))
|
||||
if len(shortcutKeys) != 1 and not 'KEY_FENRIR' in shortcutKeys:
|
||||
self.env['runtime']['debug'].writeDebugOut("invalid shortcut (missing KEY_FENRIR): "+ str(shortcut) + ' command:' +commandName ,debug.debugLevel.ERROR)
|
||||
continue
|
||||
self.env['runtime']['debug'].writeDebugOut("Shortcut: "+ str(shortcut) + ' command:' +commandName ,debug.debugLevel.INFO, onAnyLevel=True)
|
||||
self.env['bindings'][str(shortcut)] = commandName
|
||||
kbConfig.close()
|
||||
# fix bindings
|
||||
self.env['bindings'][str([1, ['KEY_F1', 'KEY_FENRIR']])] = 'TOGGLE_TUTORIAL_MODE'
|
||||
|
||||
def loadSoundIcons(self, soundIconPath):
|
||||
siConfig = open(soundIconPath + '/soundicons.conf',"r")
|
||||
while(True):
|
||||
line = siConfig.readline()
|
||||
if not line:
|
||||
break
|
||||
line = line.replace('\n','')
|
||||
if line.replace(" ","") == '':
|
||||
continue
|
||||
if line.replace(" ","").startswith("#"):
|
||||
continue
|
||||
if line.count("=") != 1:
|
||||
continue
|
||||
Values = line.split('=')
|
||||
soundIcon = Values[0].upper()
|
||||
Values[1] = Values[1].replace("'","")
|
||||
Values[1] = Values[1].replace('"',"")
|
||||
soundIconFile = ''
|
||||
if os.path.exists(Values[1]):
|
||||
soundIconFile = Values[1]
|
||||
else:
|
||||
if not soundIconPath.endswith("/"):
|
||||
soundIconPath += '/'
|
||||
if os.path.exists(soundIconPath + Values[1]):
|
||||
soundIconFile = soundIconPath + Values[1]
|
||||
self.env['soundIcons'][soundIcon] = soundIconFile
|
||||
self.env['runtime']['debug'].writeDebugOut("SoundIcon: " + soundIcon + '.' + soundIconFile, debug.debugLevel.INFO, onAnyLevel=True)
|
||||
siConfig.close()
|
||||
def isValidKey(self, key):
|
||||
return key in inputData.keyNames
|
||||
|
||||
def loadDicts(self, dictConfigPath=fenrirPath + '/../../config/punctuation/default.conf'):
|
||||
dictConfig = open(dictConfigPath,"r")
|
||||
currDictName = ''
|
||||
while(True):
|
||||
line = dictConfig.readline()
|
||||
if not line:
|
||||
break
|
||||
line = line.replace('\n','')
|
||||
if line.replace(" ","") == '':
|
||||
continue
|
||||
if line.replace(" ","").startswith("#"):
|
||||
continue
|
||||
if line.replace(" ","").upper().startswith("[") and \
|
||||
line.replace(" ","").upper().endswith("DICT]"):
|
||||
currDictName = line[line.find('[') + 1 :line.upper().find('DICT]') + 4].upper()
|
||||
else:
|
||||
if currDictName == '':
|
||||
continue
|
||||
if not ":===:" in line:
|
||||
continue
|
||||
sepLine = line.split(':===:')
|
||||
if len(sepLine) == 1:
|
||||
sepLine.append('')
|
||||
elif len(sepLine) < 1:
|
||||
continue
|
||||
elif len(sepLine) > 2:
|
||||
sepLine[1] = ':===:'
|
||||
self.env['punctuation'][currDictName][sepLine[0]] = sepLine[1]
|
||||
self.env['runtime']['debug'].writeDebugOut("Punctuation: " + currDictName + '.' + str(sepLine[0]) + ' :' + sepLine[1] ,debug.debugLevel.INFO, onAnyLevel=True)
|
||||
dictConfig.close()
|
||||
|
||||
def loadSettings(self, settingConfigPath):
|
||||
if not os.path.exists(settingConfigPath):
|
||||
return False
|
||||
self.env['settings'] = ConfigParser()
|
||||
self.env['settings'].read(settingConfigPath)
|
||||
return True
|
||||
|
||||
def setSetting(self, section, setting, value):
|
||||
self.env['settings'].set(section, setting, value)
|
||||
|
||||
def getSetting(self, section, setting):
|
||||
value = ''
|
||||
try:
|
||||
value = self.settingArgDict[section.lower()][setting.lower()]
|
||||
return value
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
value = self.env['settings'].get(section, setting)
|
||||
except:
|
||||
value = str(self.settings[section][setting])
|
||||
return value
|
||||
|
||||
def getSettingAsInt(self, section, setting):
|
||||
value = 0
|
||||
try:
|
||||
value = int(self.settingArgDict[section.lower()][setting.lower()])
|
||||
return value
|
||||
except Exception as e:
|
||||
pass
|
||||
try:
|
||||
value = self.env['settings'].getint(section, setting)
|
||||
except:
|
||||
value = self.settings[section][setting]
|
||||
return value
|
||||
|
||||
def getSettingAsFloat(self, section, setting):
|
||||
value = 0.0
|
||||
try:
|
||||
value = float(self.settingArgDict[section.lower()][setting.lower()])
|
||||
return value
|
||||
except Exception as e:
|
||||
pass
|
||||
try:
|
||||
value = self.env['settings'].getfloat(section, setting)
|
||||
except:
|
||||
value = self.settings[section][setting]
|
||||
return value
|
||||
|
||||
def getSettingAsBool(self, section, setting):
|
||||
value = False
|
||||
try:
|
||||
value = self.settingArgDict[section.lower()][setting.lower()].upper() in ['1','YES','JA','TRUE']
|
||||
return value
|
||||
except Exception as e:
|
||||
pass
|
||||
try:
|
||||
value = self.env['settings'].getboolean(section, setting)
|
||||
except:
|
||||
value = self.settings[section][setting]
|
||||
return value
|
||||
|
||||
def loadDriver(self, driverName, driverType):
|
||||
try:
|
||||
if self.env['runtime'][driverType] != None:
|
||||
self.env['runtime'][driverType].shutdown(self.env)
|
||||
driver_mod = module_utils.importModule(driverName,
|
||||
fenrirPath + "/" + driverType + '/' + driverName + '.py')
|
||||
self.env['runtime'][driverType] = driver_mod.driver()
|
||||
self.env['runtime'][driverType].initialize(self.env)
|
||||
self.env['runtime']['debug'].writeDebugOut('Loading Driver ' + driverType + ' (' + driverName +") OK",debug.debugLevel.INFO, onAnyLevel=True)
|
||||
except Exception as e:
|
||||
self.env['runtime'][driverType] = None
|
||||
self.env['runtime']['debug'].writeDebugOut('Loading Driver ' + driverType + ' (' + driverName +") FAILED:"+ str(e), debug.debugLevel.ERROR)
|
||||
def shutdownDriver(self, driverType):
|
||||
if self.env['runtime'][driverType] == None:
|
||||
return
|
||||
self.env['runtime'][driverType].shutdown()
|
||||
del self.env['runtime'][driverType]
|
||||
|
||||
def setFenrirKeys(self, keys):
|
||||
keys = keys.upper()
|
||||
keyList = keys.split(',')
|
||||
for key in keyList:
|
||||
if not key in self.env['input']['fenrirKey']:
|
||||
self.env['input']['fenrirKey'].append(key)
|
||||
def setScriptKeys(self, keys):
|
||||
keys = keys.upper()
|
||||
keyList = keys.split(',')
|
||||
for key in keyList:
|
||||
if not key in self.env['input']['scriptKey']:
|
||||
self.env['input']['scriptKey'].append(key)
|
||||
def setOptionArgDict(self, section, option, value):
|
||||
section = section.lower()
|
||||
option = option.lower()
|
||||
try:
|
||||
e = self.settingArgDict[section]
|
||||
except KeyError:
|
||||
self.settingArgDict[section] = {}
|
||||
self.settingArgDict[section][option] = str(value)
|
||||
|
||||
def parseSettingArgs(self, settingArgs):
|
||||
for optionElem in settingArgs.split(';'):
|
||||
if len(optionElem.split('#',1)) != 2:
|
||||
continue
|
||||
if len(optionElem.split('#',1)[1].split('=',1)) != 2:
|
||||
continue
|
||||
section = str(optionElem.split('#',1)[0]).lower()
|
||||
option = str(optionElem.split('#',1)[1].split('=',1)[0]).lower()
|
||||
value = optionElem.split('#',1)[1].split('=',1)[1]
|
||||
self.setOptionArgDict(section, option, value)
|
||||
|
||||
def initFenrirConfig(self, cliArgs, fenrirManager = None, environment = environment.environment):
|
||||
settingsRoot = '/etc/fenrir/'
|
||||
settingsFile = cliArgs.setting
|
||||
soundRoot = '/usr/share/sounds/fenrir/'
|
||||
environment['runtime']['debug'] = debugManager.debugManager()
|
||||
environment['runtime']['debug'].initialize(environment)
|
||||
# get fenrir settings root
|
||||
if not os.path.exists(settingsRoot):
|
||||
if os.path.exists(fenrirPath +'/../../config/'):
|
||||
settingsRoot = fenrirPath +'/../../config/'
|
||||
else:
|
||||
return None
|
||||
# get settings file
|
||||
if not os.path.exists(settingsFile):
|
||||
if os.path.exists(settingsRoot + '/settings/settings.conf'):
|
||||
settingsFile = settingsRoot + '/settings/settings.conf'
|
||||
else:
|
||||
return None
|
||||
# get sound themes root
|
||||
if not os.path.exists(soundRoot):
|
||||
if os.path.exists(fenrirPath + '/../../config/sound/'):
|
||||
soundRoot = fenrirPath + '/../../config/sound/'
|
||||
|
||||
environment['runtime']['settingsManager'] = self
|
||||
environment['runtime']['settingsManager'].initialize(environment)
|
||||
|
||||
validConfig = environment['runtime']['settingsManager'].loadSettings(settingsFile)
|
||||
if not validConfig:
|
||||
return None
|
||||
|
||||
if cliArgs.options != '':
|
||||
self.parseSettingArgs(cliArgs.options)
|
||||
if cliArgs.debug:
|
||||
self.setOptionArgDict('general', 'debugLevel', 3)
|
||||
if cliArgs.print:
|
||||
self.setOptionArgDict('general', 'debugLevel', 3)
|
||||
self.setOptionArgDict('general', 'debugMode', 'PRINT')
|
||||
self.setFenrirKeys(self.getSetting('general','fenrirKeys'))
|
||||
self.setScriptKeys(self.getSetting('general','scriptKeys'))
|
||||
|
||||
if not os.path.exists(self.getSetting('keyboard','keyboardLayout')):
|
||||
if os.path.exists(settingsRoot + 'keyboard/' + self.getSetting('keyboard','keyboardLayout')):
|
||||
self.setSetting('keyboard', 'keyboardLayout', settingsRoot + 'keyboard/' + self.getSetting('keyboard','keyboardLayout'))
|
||||
environment['runtime']['settingsManager'].loadShortcuts(self.getSetting('keyboard','keyboardLayout'))
|
||||
if os.path.exists(settingsRoot + 'keyboard/' + self.getSetting('keyboard','keyboardLayout') + '.conf'):
|
||||
self.setSetting('keyboard', 'keyboardLayout', settingsRoot + 'keyboard/' + self.getSetting('keyboard','keyboardLayout') + '.conf')
|
||||
environment['runtime']['settingsManager'].loadShortcuts(self.getSetting('keyboard','keyboardLayout'))
|
||||
else:
|
||||
environment['runtime']['settingsManager'].loadShortcuts(self.getSetting('keyboard','keyboardLayout'))
|
||||
|
||||
if not os.path.exists(self.getSetting('sound','theme') + '/soundicons.conf'):
|
||||
if os.path.exists(soundRoot + self.getSetting('sound','theme')):
|
||||
self.setSetting('sound', 'theme', soundRoot + self.getSetting('sound','theme'))
|
||||
if os.path.exists(self.getSetting('sound','theme') + '/soundicons.conf'):
|
||||
environment['runtime']['settingsManager'].loadSoundIcons(self.getSetting('sound','theme'))
|
||||
else:
|
||||
environment['runtime']['settingsManager'].loadSoundIcons(self.getSetting('sound','theme'))
|
||||
|
||||
if not os.path.exists(self.getSetting('general','punctuationProfile')):
|
||||
if os.path.exists(settingsRoot + 'punctuation/' + self.getSetting('general','punctuationProfile')):
|
||||
self.setSetting('general', 'punctuationProfile', settingsRoot + 'punctuation/' + self.getSetting('general','punctuationProfile'))
|
||||
environment['runtime']['settingsManager'].loadDicts(self.getSetting('general','punctuationProfile'))
|
||||
if os.path.exists(settingsRoot + 'punctuation/' + self.getSetting('general','punctuationProfile') + '.conf'):
|
||||
self.setSetting('general', 'punctuationProfile', settingsRoot + 'punctuation/' + self.getSetting('general','punctuationProfile') + '.conf')
|
||||
environment['runtime']['settingsManager'].loadDicts(self.getSetting('general','punctuationProfile'))
|
||||
else:
|
||||
environment['runtime']['settingsManager'].loadDicts(self.getSetting('general','punctuationProfile'))
|
||||
|
||||
if fenrirManager:
|
||||
environment['runtime']['fenrirManager'] = fenrirManager
|
||||
environment['runtime']['memoryManager'] = memoryManager.memoryManager()
|
||||
environment['runtime']['memoryManager'].initialize(environment)
|
||||
environment['runtime']['eventManager'] = eventManager.eventManager()
|
||||
environment['runtime']['eventManager'].initialize(environment)
|
||||
environment['runtime']['processManager'] = processManager.processManager()
|
||||
environment['runtime']['processManager'].initialize(environment)
|
||||
environment['runtime']['outputManager'] = outputManager.outputManager()
|
||||
environment['runtime']['outputManager'].initialize(environment)
|
||||
environment['runtime']['commandManager'] = commandManager.commandManager()
|
||||
environment['runtime']['commandManager'].initialize(environment)
|
||||
environment['runtime']['inputManager'] = inputManager.inputManager()
|
||||
environment['runtime']['inputManager'].initialize(environment)
|
||||
environment['runtime']['punctuationManager'] = punctuationManager.punctuationManager()
|
||||
environment['runtime']['punctuationManager'].initialize(environment)
|
||||
environment['runtime']['cursorManager'] = cursorManager.cursorManager()
|
||||
environment['runtime']['cursorManager'].initialize(environment)
|
||||
environment['runtime']['applicationManager'] = applicationManager.applicationManager()
|
||||
environment['runtime']['applicationManager'].initialize(environment)
|
||||
environment['runtime']['helpManager'] = helpManager.helpManager()
|
||||
environment['runtime']['helpManager'].initialize(environment)
|
||||
environment['runtime']['headLineManager'] = headLineManager.headLineManager()
|
||||
environment['runtime']['headLineManager'].initialize(environment)
|
||||
environment['runtime']['tableManager'] = tableManager.tableManager()
|
||||
environment['runtime']['tableManager'].initialize(environment)
|
||||
if environment['runtime']['screenManager'] == None:
|
||||
environment['runtime']['screenManager'] = screenManager.screenManager()
|
||||
environment['runtime']['screenManager'].initialize(environment)
|
||||
|
||||
environment['runtime']['debug'].writeDebugOut('\/-------environment-------\/',debug.debugLevel.INFO, onAnyLevel=True)
|
||||
environment['runtime']['debug'].writeDebugOut(str(environment), debug.debugLevel.INFO, onAnyLevel=True)
|
||||
environment['runtime']['debug'].writeDebugOut('\/-------settings.conf-------\/', debug.debugLevel.INFO, onAnyLevel=True)
|
||||
environment['runtime']['debug'].writeDebugOut(str(environment['settings']._sections) , debug.debugLevel.INFO, onAnyLevel=True)
|
||||
environment['runtime']['debug'].writeDebugOut('\/-------self.settingArgDict-------\/',debug.debugLevel.INFO, onAnyLevel=True)
|
||||
environment['runtime']['debug'].writeDebugOut(str( self.settingArgDict) ,debug.debugLevel.INFO, onAnyLevel=True)
|
||||
return environment
|
||||
|
47
src/fenrirscreenreader/core/soundDriver.py
Normal file
47
src/fenrirscreenreader/core/soundDriver.py
Normal file
@ -0,0 +1,47 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
class soundDriver():
|
||||
def __init__(self):
|
||||
self.volume = None
|
||||
self._initialized = False
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
self._initialized = True
|
||||
|
||||
def shutdown(self):
|
||||
if not self._initialized:
|
||||
return
|
||||
self.cancel()
|
||||
self._isInitialized = False
|
||||
|
||||
def playFrequence(self, frequence = 1000, duration = 0.3, adjustVolume = 0):
|
||||
if not self._initialized:
|
||||
return
|
||||
if interrupt:
|
||||
self.cancel()
|
||||
|
||||
def playSoundFile(self, filePath, interrupt = True):
|
||||
if not self._initialized:
|
||||
return
|
||||
if interrupt:
|
||||
self.cancel()
|
||||
|
||||
def cancel(self):
|
||||
if not self._initialized:
|
||||
return
|
||||
|
||||
def setCallback(self, callback):
|
||||
if not self._initialized:
|
||||
return
|
||||
|
||||
def setVolume(self, volume):
|
||||
if not self._initialized:
|
||||
return
|
||||
self.volume = volume
|
100
src/fenrirscreenreader/core/speechDriver.py
Normal file
100
src/fenrirscreenreader/core/speechDriver.py
Normal file
@ -0,0 +1,100 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
class speechDriver():
|
||||
def __init__(self):
|
||||
self._isInitialized = False
|
||||
self.language = None
|
||||
self.voice = None
|
||||
self.module = None
|
||||
self.pitch = None
|
||||
self.rate = None
|
||||
self.volume = None
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
self._isInitialized = True
|
||||
|
||||
def shutdown(self):
|
||||
if self._isInitialized:
|
||||
self.cancel()
|
||||
self._isInitialized = False
|
||||
|
||||
def speak(self,text, queueable=True):
|
||||
if not self._isInitialized:
|
||||
return
|
||||
if not queueable:
|
||||
self.cancel()
|
||||
|
||||
def cancel(self):
|
||||
if not self._isInitialized:
|
||||
return
|
||||
|
||||
def setCallback(self, callback):
|
||||
if not self._isInitialized:
|
||||
return
|
||||
if not callback:
|
||||
return
|
||||
|
||||
def clear_buffer(self):
|
||||
if not self._isInitialized:
|
||||
return
|
||||
|
||||
def setVoice(self, voice):
|
||||
if not self._isInitialized:
|
||||
return
|
||||
if voice == '':
|
||||
return
|
||||
self.voice = voice
|
||||
|
||||
def setPitch(self, pitch):
|
||||
if not self._isInitialized:
|
||||
return
|
||||
if not isinstance(pitch, float):
|
||||
return
|
||||
if pitch < 0.0:
|
||||
retrun
|
||||
if pitch > 1.0:
|
||||
return
|
||||
self.pitch = pitch
|
||||
def setRate(self, rate):
|
||||
if not self._isInitialized:
|
||||
return
|
||||
if not isinstance(rate, float):
|
||||
return
|
||||
if rate < 0.0:
|
||||
retrun
|
||||
if rate > 1.0:
|
||||
return
|
||||
self.rate = rate
|
||||
def setModule(self, module):
|
||||
if not self._isInitialized:
|
||||
return
|
||||
if not isinstance(module, str):
|
||||
return
|
||||
if module == '':
|
||||
return
|
||||
self.module = module
|
||||
|
||||
def setLanguage(self, language):
|
||||
if not self._isInitialized:
|
||||
return
|
||||
if not isinstance(language, str):
|
||||
return
|
||||
if language == '':
|
||||
return
|
||||
self.language = language
|
||||
def setVolume(self, volume):
|
||||
if not self._isInitialized:
|
||||
return
|
||||
if not isinstance(volume,float):
|
||||
return
|
||||
if volume < 0.0:
|
||||
retrun
|
||||
if volume > 1.0:
|
||||
return
|
||||
self.volume = volume
|
46
src/fenrirscreenreader/core/tableManager.py
Normal file
46
src/fenrirscreenreader/core/tableManager.py
Normal file
@ -0,0 +1,46 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
import re
|
||||
|
||||
class tableManager():
|
||||
def __init__(self):
|
||||
self.headLine = ''
|
||||
self.defaultSeparators = ['+',';','|',' ']
|
||||
self.noOfHeadLineColumns = 0
|
||||
self.headColumnSep = ''
|
||||
self.rowColumnSep = ''
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def resetTableMode(self):
|
||||
self.setHeadLine()
|
||||
def setHeadColumnSep(self, columnSep = ''):
|
||||
self.headColumnSep = columnSep
|
||||
if columnSep == '':
|
||||
self.noOfHeadLineColumns = 0
|
||||
else:
|
||||
self.counNoOfHeadColumns()
|
||||
def counNoOfHeadColumns(self):
|
||||
pass
|
||||
def searchForHeadColumnSep(self, headLine):
|
||||
if ' ' in headLine:
|
||||
return ' '
|
||||
return ''
|
||||
def setRowColumnSep(self, columnSep = ''):
|
||||
self.rowColumnSep = columnSep
|
||||
|
||||
def setHeadLine(self, headLine = ''):
|
||||
self.setHeadColumnSep()
|
||||
self.setRowColumnSep()
|
||||
if headLine != '':
|
||||
sep = self.searchForHeadColumnSep(headLine)
|
||||
if sep != '':
|
||||
self.headLine = headLine
|
||||
self.setHeadColumnSep(sep)
|
||||
|
Reference in New Issue
Block a user