Renamed fenrir-package to fenrir to satisfy packaging deps.

This commit is contained in:
Jeremiah Ticket
2016-10-04 10:52:39 -08:00
parent 8ee30abab4
commit 33edce7c82
174 changed files with 6554 additions and 0 deletions

0
src/fenrir/core/__init__.py Executable file
View File

View File

@@ -0,0 +1,31 @@
#!/bin/python
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from 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['screenData']['newApplication'].upper()
if not currApp:
currApp == 'DEFAULT'
if currApp == '':
currApp == 'DEFAULT'
return currApp
def getPrevApplication(self):
prevApp = self.env['screenData']['oldApplication'].upper()
if not prevApp:
prevApp == 'DEFAULT'
if prevApp == '':
prevApp == 'DEFAULT'
return prevApp
def isApplicationChange(self):
return self.env['screenData']['oldApplication'] != self.env['screenData']['newApplication']

View File

@@ -0,0 +1,127 @@
#!/bin/python
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
import importlib.util
import glob, os, time
from core import debug
class commandManager():
def __init__(self):
pass
def initialize(self, environment):
self.env = environment
self.env['runtime']['commandManager'].loadCommands('commands')
self.env['runtime']['commandManager'].loadCommands('onInput')
self.env['runtime']['commandManager'].loadCommands('onScreenUpdate')
self.env['runtime']['commandManager'].loadCommands('onScreenChanged')
self.env['runtime']['commandManager'].loadCommands('onApplicationChange')
self.env['runtime']['commandManager'].loadCommands('onSwitchApplicationProfile')
def shutdown(self):
self.env['runtime']['commandManager'].shutdownCommands('commands')
self.env['runtime']['commandManager'].shutdownCommands('onInput')
self.env['runtime']['commandManager'].shutdownCommands('onScreenUpdate')
self.env['runtime']['commandManager'].shutdownCommands('onScreenChanged')
self.env['runtime']['commandManager'].shutdownCommands('onApplicationChange')
self.env['runtime']['commandManager'].shutdownCommands('onSwitchApplicationProfile')
def loadCommands(self, section='commands'):
commandFolder = "commands/" + section +"/"
commandList = glob.glob(commandFolder+'*')
for command in commandList:
try:
fileName, fileExtension = os.path.splitext(command)
fileName = fileName.split('/')[-1]
if fileName in ['__init__','__pycache__']:
continue
if fileExtension.lower() == '.py':
spec = importlib.util.spec_from_file_location(fileName, command)
command_mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(command_mod)
self.env['commands'][section][fileName.upper()] = command_mod.command()
self.env['commands'][section][fileName.upper()].initialize(self.env)
self.env['runtime']['debug'].writeDebugOut("Load command:" + section + "." + fileName.upper() ,debug.debugLevel.INFO)
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 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):
if self.env['runtime']['screenManager'].isSuspendingScreen():
return
for command in sorted(self.env['commands'][trigger]):
if self.commandExists(command, trigger):
try:
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 ,debug.debugLevel.ERROR)
self.env['runtime']['debug'].writeDebugOut(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['generalInformation']['tutorialMode']:
self.env['runtime']['debug'].writeDebugOut("Tutorial for command:" + section + "." + command ,debug.debugLevel.INFO)
description = self.env['commands'][section][command].getDescription()
self.env['runtime']['outputManager'].presentText(description, interrupt=True)
else:
self.env['runtime']['debug'].writeDebugOut("Executing command:" + section + "." + command ,debug.debugLevel.INFO)
self.env['commands'][section][command].run()
except Exception as e:
self.env['runtime']['debug'].writeDebugOut("Executing command:" + section + "." + command ,debug.debugLevel.ERROR)
self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR)
self.clearCommandQueued()
self.env['commandInfo']['lastCommandExecutionTime'] = time.time()
def isCommandQueued(self):
return self.env['commandInfo']['currCommand'] != ''
def clearCommandQueued(self):
self.env['commandInfo']['currCommand'] = ''
def queueCommand(self, command):
if command == '':
return
self.env['commandInfo']['currCommand'] = command
def commandExists(self, command, section = 'commands'):
return( command in self.env['commands'][section])

View File

@@ -0,0 +1,45 @@
#!/bin/python
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from core import debug
import time
# used as shared memory between commands
# use this in your own commands
commandBuffer = {
'genericList':[],
'genericListSource':'',
'genericListSelection': 0,
'clipboard':[],
'currClipboard': 0,
'Marks':{'1':None, '2':None},
'bookMarks':{},
'windowArea':{},
}
# used by the commandManager
commandInfo = {
'currCommand': '',
'lastCommandExecutionTime': time.time(),
'lastCommandRequestTime': time.time(),
}
# used by the commandManager
commands = {
'onInput':{
},
'onScreenChanged':{
},
'onScreenUpdate':{
},
'onApplicationChange':{
},
'commands':{
},
'onSwitchApplicationProfile':{
},
}

View File

@@ -0,0 +1,87 @@
#!/bin/python
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from 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):
if not self.env['commandBuffer']['Marks']['1']:
self.env['commandBuffer']['Marks']['1'] = self.env['screenData']['newCursorReview'].copy()
else:
self.env['commandBuffer']['Marks']['2'] = self.env['screenData']['newCursorReview'].copy()
def getReviewOrTextCursor(self):
if self.env['screenData']['newCursorReview']:
return self.env['screenData']['newCursorReview'].copy()
else:
return self.env['screenData']['newCursor'].copy()
def clearReviewCursor(self):
if not self.isReviewMode():
return
self.env['screenData']['oldCursorReview'] = None
self.env['screenData']['newCursorReview'] = None
def isReviewMode(self):
return self.env['screenData']['newCursorReview'] != None
def enterReviewModeCurrTextCursor(self, overwrite=False):
if self.isReviewMode() and not overwrite:
return
self.env['screenData']['oldCursorReview'] = self.env['screenData']['newCursorReview']
if not self.env['screenData']['newCursorReview']:
self.env['screenData']['newCursorReview'] = self.env['screenData']['newCursor'].copy()
def setReviewCursorPosition(self, x, y):
if not self.isReviewMode():
self.enterReviewModeCurrTextCursor()
self.env['screenData']['oldCursorReview'] = self.env['screenData']['newCursorReview']
self.env['screenData']['newCursorReview']['x'] = x
self.env['screenData']['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

67
src/fenrir/core/debug.py Normal file
View File

@@ -0,0 +1,67 @@
#!/usr/bin/python
# Debugger module for the Fenrir screen reader.
from enum import Enum
from datetime import datetime
class debugLevel(Enum):
DEACTIVE = 0
ERROR = 1
WARNING = 2
INFO = 3
def __int__(self):
return self.value
def __str__(self):
return self.name
class debug():
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 = debugLevel.DEACTIVE):
if self.env['runtime']['settingsManager'].getSettingAsInt('general','debugLevel') < int(level):
if self._fileOpened:
self.closeDebugFile()
return
else:
if not self._fileOpened:
self.openDebugFile()
msg = str(level) +' ' + str(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')
) + ': ' + text
print(msg)
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

View File

@@ -0,0 +1,26 @@
#!/bin/python
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from core import debug
from core import settings
from core import runtime
from core import screenData
from core import generalInformation
from core import commands
from core import inputEvent
environment = {
'screenData': screenData.screenData,
'runtime': runtime.runtime,
'generalInformation': generalInformation.generalInformation,
'settings': settings.settings,
'commands': commands.commands,
'commandInfo': commands.commandInfo,
'commandBuffer': commands.commandBuffer,
'input': inputEvent.input,
'soundIcons': {},
'bindings': {},
}

View File

@@ -0,0 +1,12 @@
#!/bin/python
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from core import debug
generalInformation = {
'running': True,
'tutorialMode': False,
}

View File

@@ -0,0 +1,32 @@
#!/bin/python
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from core import debug
import time
input = {
'currInput': [],
'prevDeepestInput': [],
'eventBuffer': [],
'shortcutRepeat': 0,
'fenrirKey': ['KEY_KP0'],
'keyForeward': 0,
'lastInputTime':time.time(),
'oldNumLock': True,
'newNumLock':True,
'oldScrollLock': True,
'newScrollLock':True,
'oldCapsLock':False,
'newCapsLock':False
}
inputEvent = {
'EventName': '',
'EventValue': '',
'EventSec': 0,
'EventUsec': 0,
'EventState': 0,
}

View File

@@ -0,0 +1,156 @@
#!/bin/python
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
import time
from core import debug
from core import inputEvent
class inputManager():
def __init__(self):
pass
def initialize(self, environment):
self.env = environment
self.env['runtime']['settingsManager'].loadDriver(\
self.env['runtime']['settingsManager'].getSetting('keyboard', 'driver'), 'inputDriver')
# init LEDs with current state
self.env['input']['newNumLock'] = self.env['runtime']['inputDriver'].getNumlock()
self.env['input']['oldNumLock'] = self.env['input']['newNumLock']
self.env['input']['newCapsLock'] = self.env['runtime']['inputDriver'].getCapslock()
self.env['input']['oldCapsLock'] = self.env['input']['newCapsLock']
self.env['input']['newScrollLock'] = self.env['runtime']['inputDriver'].getScrollLock()
self.env['input']['oldScrollLock'] = self.env['input']['newScrollLock']
self.grabDevices()
def shutdown(self):
self.env['runtime']['inputManager'].releaseDevices()
self.env['runtime']['settingsManager'].shutdownDriver('inputDriver')
def getInputEvent(self):
eventReceived = False
mEvent = self.env['runtime']['inputDriver'].getInputEvent()
if mEvent:
mEvent['EventName'] = self.convertEventName(mEvent['EventName'])
eventReceived = True
if mEvent['EventState'] == 0:
if mEvent['EventName'] in self.env['input']['currInput']:
self.env['input']['currInput'].remove(mEvent['EventName'])
if len(self.env['input']['currInput']) > 1:
self.env['input']['currInput'] = sorted(self.env['input']['currInput'])
if len(self.env['input']['currInput']) == 0:
self.env['input']['prevDeepestInput'] = []
self.env['input']['shortcutRepeat'] = 1
elif mEvent['EventState'] == 1:
if not mEvent['EventName'] in self.env['input']['currInput']:
self.env['input']['currInput'].append(mEvent['EventName'])
if len(self.env['input']['currInput']) > 1:
self.env['input']['currInput'] = sorted(self.env['input']['currInput'])
if len(self.env['input']['prevDeepestInput']) < len(self.env['input']['currInput']):
self.env['input']['prevDeepestInput'] = self.env['input']['currInput'].copy()
elif self.env['input']['prevDeepestInput'] == self.env['input']['currInput']:
self.env['input']['shortcutRepeat'] += 1
elif mEvent['EventState'] == 2:
pass
else:
pass
self.env['input']['oldNumLock'] = self.env['input']['newNumLock']
self.env['input']['newNumLock'] = self.env['runtime']['inputDriver'].getNumlock()
self.env['input']['oldCapsLock'] = self.env['input']['newCapsLock']
self.env['input']['newCapsLock'] = self.env['runtime']['inputDriver'].getCapslock()
self.env['input']['oldScrollLock'] = self.env['input']['newScrollLock']
self.env['input']['newScrollLock'] = self.env['runtime']['inputDriver'].getScrollLock()
self.env['input']['lastInputTime'] = time.time()
return eventReceived
def grabDevices(self):
if self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'grabDevices'):
self.env['runtime']['inputDriver'].grabDevices()
def releaseDevices(self):
try:
self.env['runtime']['inputDriver'].releaseDevices()
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'
return eventName
def isConsumeInput(self):
return self.env['runtime']['commandManager'].isCommandQueued() and \
not self.env['input']['keyForeward']
#and
# not (self.env['input']['keyForeward'] or \
# self.env['runtime']['settingsManager'].getSettingAsBool(, 'keyboard', 'grabDevices'))
def clearEventBuffer(self):
self.env['runtime']['inputDriver'].clearEventBuffer()
def writeEventBuffer(self):
try:
if self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'grabDevices'):
self.env['runtime']['inputDriver'].writeEventBuffer()
time.sleep(0.005)
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 isFenrirKeyPressed(self):
return 'KEY_FENRIR' in self.env['input']['currInput']
def noKeyPressed(self):
return self.env['input']['currInput'] == []
def getPrevDeepestInput(self):
shortcut = []
shortcut.append(self.env['input']['shortcutRepeat'])
shortcut.append(self.env['input']['prevDeepestInput'])
def getPrevShortcut(self):
shortcut = []
shortcut.append(self.env['input']['shortcutRepeat'])
shortcut.append(self.env['input']['prevInput'])
return str(shortcut)
def getCurrShortcut(self):
shortcut = []
shortcut.append(self.env['input']['shortcutRepeat'])
shortcut.append(self.env['input']['currInput'])
return str(shortcut)
def isFenrirKey(self, eventName):
return eventName in self.env['input']['fenrirKey']
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'])

View File

@@ -0,0 +1,123 @@
#!/bin/python
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from core import debug
import string
class outputManager():
def __init__(self):
pass
def initialize(self, environment):
self.env = environment
self.env['runtime']['settingsManager'].loadDriver(\
self.env['runtime']['settingsManager'].getSetting('speech', 'driver'), 'speechDriver')
self.env['runtime']['settingsManager'].loadDriver(\
self.env['runtime']['settingsManager'].getSetting('sound', 'driver'), 'soundDriver')
def shutdown(self):
self.env['runtime']['settingsManager'].shutdownDriver('soundDriver')
self.env['runtime']['settingsManager'].shutdownDriver('speechDriver')
def presentText(self, text, interrupt=True, soundIcon = '', ignorePunctuation=False, announceCapital=False):
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
toAnnounceCapital = announceCapital and len(text.strip(' \n\t')) == 1 and text.strip(' \n\t').isupper()
if toAnnounceCapital:
if self.playSoundIcon('capital', False):
toAnnounceCapital = False
self.speakText(text, interrupt, ignorePunctuation,toAnnounceCapital)
self.brailleText(text, interrupt)
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:
text = self.env['runtime']['punctuationManager'].proceedPunctuation(text,ignorePunctuation)
self.env['runtime']['speechDriver'].speak(text)
self.env['runtime']['debug'].writeDebugOut("Speak: "+ text,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, interrupt=True):
if not self.env['runtime']['settingsManager'].getSettingAsBool('braille', 'enabled'):
return
if self.env['runtime']['brailleDriver'] == None:
return
print('braille:'+text)
def interruptOutput(self):
self.env['runtime']['speechDriver'].cancel()
self.env['runtime']['debug'].writeDebugOut("Interrupt speech",debug.debugLevel.INFO)
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

View File

@@ -0,0 +1,110 @@
#!/bin/python
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
import string
from 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 space:
# dot, comma, grave, apostrophe
for char in [ord('.'),ord(','),ord('`'),ord("'")]:
self.allPunctNone[char] = None
self.punctuation = {
'levels':{
'none': '',
'some': '#-$~+*-/\\@',
'most': '.,:-$~+*-/\\@!#%^&*()[]}{<>;',
'all': string.punctuation,
},
'punctuationDict':{
'&':'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':{
':)':'smiley',
';)':'winking face',
'XD':'loool',
':@':'angry face',
':D':'lought'
}
}
def shutdown(self):
pass
def removeUnused(self, text):
return text.translate(self.allPunctNone)
def useCustomDict(self, text, customDict):
resultText = str(text)
if customDict:
for key,item in customDict.items():
resultText = resultText.replace(str(key),str(item))
return resultText
def usePunctuationDict(self, text, punctuationDict, punctuation):
resultText = str(text)
if punctuationDict and punctuation and punctuation != '':
for key,item in punctuationDict.items():
if key in punctuation:
resultText = resultText.replace(str(key),' ' +str(item) +' ')
return resultText
def proceedPunctuation(self, text, ignorePunctuation=False):
resultText = self.useCustomDict(text, self.punctuation['customDict'])
currPunctLevel = ''
if not ignorePunctuation and self.env['runtime']['settingsManager'].getSetting('general', 'punctuationLevel').lower() in self.punctuation['levels']:
currPunctLevel = self.punctuation['levels'][self.env['runtime']['settingsManager'].getSetting('general', 'punctuationLevel').lower()]
else:
currPunctLevel = string.punctuation
resultText = self.usePunctuationDict(resultText, self.punctuation['punctuationDict'], currPunctLevel)
resultText = self.removeUnused(resultText)
return resultText
def cyclePunctuation(self):
punctList = list(self.punctuation['levels'].keys())
try:
currIndex = punctList.index(self.env['runtime']['settingsManager'].getSetting('general', 'punctuationLevel').lower()) # curr punctuation
except:
return
currIndex += 1
if currIndex >= len(punctList):
currIndex = 0
currLevel = punctList[currIndex]
self.env['runtime']['settingsManager'].setSetting('general', currLevel.lower())

View File

@@ -0,0 +1,20 @@
#!/bin/python
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from core import debug
runtime = {
'speechDriver': None,
'screenDriver': None,
'soundDriver': None,
'inputDriver': None,
'brailleDriver': None,
'inputManager': None,
'commandManager': None,
'screenManager': None,
'outputManager': None,
'debug':None,
}

View File

@@ -0,0 +1,32 @@
#!/bin/python
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from core import debug
import time
screenData = {
'columns': 0,
'lines': 0,
'oldDelta': '',
'oldNegativeDelta': '',
'oldCursorReview':None,
'oldCursor':{'x':0,'y':0},
'oldContentBytes': b'',
'oldContentText': '',
'oldContentAttrib': b'',
'oldApplication': '',
'oldTTY':'-1',
'newDelta': '',
'newNegativeDelta': '',
'newCursorReview':None,
'newCursor':{'x':0,'y':0},
'newContentBytes': b'',
'newContentText': '',
'newContentAttrib': b'',
'newTTY':'0',
'newApplication': '',
'lastScreenUpdate': time.time()
}

View File

@@ -0,0 +1,51 @@
#!/bin/python
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from core import debug
import time
class screenManager():
def __init__(self):
self.autoIgnoreScreens = []
def initialize(self, environment):
self.env = environment
self.env['runtime']['settingsManager'].loadDriver(\
self.env['runtime']['settingsManager'].getSetting('screen', 'driver'), 'screenDriver')
if self.env['runtime']['settingsManager'].getSettingAsBool('screen', 'autodetectSuspendingScreen'):
self.autoIgnoreScreens = self.env['runtime']['screenDriver'].getIgnoreScreens()
def shutdown(self):
self.env['runtime']['settingsManager'].shutdownDriver('screenDriver')
def update(self, trigger='onUpdate'):
self.env['runtime']['screenDriver'].getCurrScreen()
self.env['screenData']['oldApplication'] = self.env['screenData']['newApplication']
if not self.isSuspendingScreen():
self.env['runtime']['screenDriver'].update(trigger)
if trigger == 'onUpdate' or self.isScreenChange() or len(self.env['screenData']['newDelta']) > 6:
self.env['runtime']['screenDriver'].getCurrApplication()
self.env['screenData']['lastScreenUpdate'] = time.time()
def isSuspendingScreen(self):
return ((self.env['screenData']['newTTY'] in \
self.env['runtime']['settingsManager'].getSetting('screen', 'suspendingScreen').split(',')) or
(self.env['screenData']['newTTY'] in self.autoIgnoreScreens))
def isScreenChange(self):
return self.env['screenData']['newTTY'] != self.env['screenData']['oldTTY']
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

View File

@@ -0,0 +1,68 @@
#!/bin/python
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from core import debug
settings = {
'sound': {
'enabled': True,
'driver': 'generic',
'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': 'speechd',
'rate': 0.75,
'pitch': 0.5,
'capitalPitch':0.8,
'volume': 1.0,
'module': '',
'voice': 'de',
'language': 'de',
'autoReadIncoming': True,
},
'braille':{
'enabled': False,
'layout': 'en',
},
'screen':{
'driver': 'linux',
'encoding': 'cp850',
'screenUpdateDelay': 0.4,
'suspendingScreen': '',
'autodetectSuspendingScreen': False,
},
'general':{
'debugLevel': debug.debugLevel.DEACTIVE,
'punctuationLevel': 1,
'numberOfClipboards': 10,
'fenrirKeys': ['KEY_KP0'],
'timeFormat': '%I:%M%P',
'dateFormat': '%A, %B %d, %Y',
'autoSpellCheck': False,
'spellCheckLanguage': 'en_US',
},
'promote':{
'enabled': True,
'inactiveTimeoutSec': 120,
'list': '',
},
'keyboard':{
'driver': 'evdev',
'device': 'all',
'grabDevices': True,
'ignoreShortcuts': False,
'keyboardLayout': "desktop",
'charEcho': False,
'charDeleteEcho': True,
'wordEcho': True,
'interruptOnKeyPress': True,
'doubleTapDelay': 0.2,
}
}

View File

@@ -0,0 +1,214 @@
#!/bin/python
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
import importlib.util
import os
from configparser import ConfigParser
from core import inputManager
from core import outputManager
from core import commandManager
from core import screenManager
from core import punctuationManager
from core import cursorManager
from core import applicationManager
from core import environment
from core.settings import settings
from core import debug
class settingsManager():
def __init__(self):
self.settings = settings
def initialize(self, environment):
self.env = environment
def shutdown(self):
pass
def loadShortcuts(self, kbConfigPath='../../config/keyboard/desktop.conf'):
kbConfig = open(kbConfigPath,"r")
while(True):
line = kbConfig.readline()
if not line:
break
line = line.replace('\n','')
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:
shortcutKeys.append(key.upper())
shortcut.append(shortcutRepeat)
shortcut.append(sorted(shortcutKeys))
self.env['runtime']['debug'].writeDebugOut("Shortcut: "+ str(shortcut) + ' command:' +commandName ,debug.debugLevel.INFO)
self.env['bindings'][str(shortcut)] = commandName
kbConfig.close()
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(" ","").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
siConfig.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.env['settings'].get(section, setting)
except:
value = str(self.settings[section][setting])
return value
def getSettingAsInt(self, section, setting):
value = 0
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 = self.env['settings'].getfloat(section, setting)
except:
value = self.settings[section][setting]
return value
def getSettingAsBool(self, section, setting):
value = False
try:
value = self.env['settings'].getboolean(section, setting)
except:
value = self.settings[section][setting]
return value
def loadDriver(self, driverName, driverType):
if self.env['runtime'][driverType] != None:
print('shutdown %s',driverType)
self.env['runtime'][driverType].shutdown(self.env)
spec = importlib.util.spec_from_file_location(driverName, driverType + '/' + driverName + '.py')
driver_mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(driver_mod)
self.env['runtime'][driverType] = driver_mod.driver()
self.env['runtime'][driverType].initialize(self.env)
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 keyIDasString(self, key):
try:
KeyID = self.getCodeForKeyID(key)
return str(KeyID)
except:
return ''
def initFenrirConfig(self, environment = environment.environment, settingsRoot = '/etc/fenrir/', settingsFile='settings.conf'):
environment['runtime']['debug'] = debug.debug()
environment['runtime']['debug'].initialize(environment)
if not os.path.exists(settingsRoot):
if os.path.exists('../../config/'):
settingsRoot = '../../config/'
else:
return None
environment['runtime']['settingsManager'] = self
environment['runtime']['settingsManager'].initialize(environment)
validConfig = environment['runtime']['settingsManager'].loadSettings(settingsRoot + '/settings/' + settingsFile)
if not validConfig:
return None
self.setFenrirKeys(self.getSetting('general','fenrirKeys'))
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(settingsRoot + 'sound/'+ self.getSetting('sound','theme')):
self.setSetting('sound', 'theme', settingsRoot + 'sound/'+ 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'))
environment['runtime']['inputManager'] = inputManager.inputManager()
environment['runtime']['inputManager'].initialize(environment)
environment['runtime']['outputManager'] = outputManager.outputManager()
environment['runtime']['outputManager'].initialize(environment)
environment['runtime']['commandManager'] = commandManager.commandManager()
environment['runtime']['commandManager'].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)
if environment['runtime']['screenManager'] == None:
environment['runtime']['screenManager'] = screenManager.screenManager()
environment['runtime']['screenManager'].initialize(environment)
environment['runtime']['debug'].writeDebugOut('\/-------environment-------\/',debug.debugLevel.ERROR)
environment['runtime']['debug'].writeDebugOut(str(environment),debug.debugLevel.ERROR)
environment['runtime']['debug'].writeDebugOut('\/-------settings.conf-------\/',debug.debugLevel.ERROR)
environment['runtime']['debug'].writeDebugOut(str(environment['settings']._sections
),debug.debugLevel.ERROR)
return environment