Merge branch 'event'
- use eventLoop - add watchdogs - add list in tutorial mode - rewrite command detection - cleanups - autoencoding - a lot of other stuff i forgott
This commit is contained in:
@ -17,7 +17,7 @@ class command():
|
||||
return _('exits Fenrir')
|
||||
|
||||
def run(self):
|
||||
self.env['general']['running'] = False
|
||||
self.env['runtime']['eventManager'].stopMainEventLoop()
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
|
@ -14,13 +14,11 @@ class command():
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
self.env['general']['tutorialMode'] = False
|
||||
self.env['runtime']['helpManager'].toggleTutorialMode()
|
||||
#self.env['runtime']['outputManager'].presentText(, interrupt=True)
|
||||
return _('You are leaving the tutorial mode. Press that shortcut again to enter the tutorial mode again.')
|
||||
|
||||
def run(self):
|
||||
text = _('you entered the tutorial mode. In that mode the commands are not executed. but you get a description of what the shortcut does. To leave the tutorial mode, press that shortcut again.')
|
||||
self.env['runtime']['outputManager'].presentText(text, interrupt=True)
|
||||
self.env['general']['tutorialMode'] = True
|
||||
|
||||
self.env['runtime']['helpManager'].toggleTutorialMode()
|
||||
self.env['runtime']['outputManager'].presentText( _('you entered the tutorial mode. In that mode the commands are not executed. but you get a description of what the shortcut does. To leave the tutorial mode, press that shortcut again.'), interrupt=True)
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
|
2
src/fenrir/commands/help/Readme.txt
Normal file
2
src/fenrir/commands/help/Readme.txt
Normal file
@ -0,0 +1,2 @@
|
||||
this folder contains help and tutorial related functions.
|
||||
those are not bindable but hard coded.
|
22
src/fenrir/commands/help/curr_help.py
Normal file
22
src/fenrir/commands/help/curr_help.py
Normal file
@ -0,0 +1,22 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from core import debug
|
||||
|
||||
class command():
|
||||
def __init__(self):
|
||||
pass
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('get current help message')
|
||||
def run(self):
|
||||
text = self.env['runtime']['helpManager'].getHelpForCurrentIndex()
|
||||
self.env['runtime']['outputManager'].presentText(text, interrupt=True)
|
||||
def setCallback(self, callback):
|
||||
pass
|
23
src/fenrir/commands/help/next_help.py
Normal file
23
src/fenrir/commands/help/next_help.py
Normal file
@ -0,0 +1,23 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from core import debug
|
||||
|
||||
class command():
|
||||
def __init__(self):
|
||||
pass
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('get next help message')
|
||||
def run(self):
|
||||
self.env['runtime']['helpManager'].nextIndex()
|
||||
text = self.env['runtime']['helpManager'].getHelpForCurrentIndex()
|
||||
self.env['runtime']['outputManager'].presentText(text, interrupt=True)
|
||||
def setCallback(self, callback):
|
||||
pass
|
23
src/fenrir/commands/help/prev_help.py
Normal file
23
src/fenrir/commands/help/prev_help.py
Normal file
@ -0,0 +1,23 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from core import debug
|
||||
|
||||
class command():
|
||||
def __init__(self):
|
||||
pass
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('get prev help message')
|
||||
def run(self):
|
||||
self.env['runtime']['helpManager'].prevIndex()
|
||||
text = self.env['runtime']['helpManager'].getHelpForCurrentIndex()
|
||||
self.env['runtime']['outputManager'].presentText(text, interrupt=True)
|
||||
def setCallback(self, callback):
|
||||
pass
|
@ -21,9 +21,7 @@ class command():
|
||||
if not self.env['runtime']['settingsManager'].getSettingAsBool('focus', 'cursor'):
|
||||
return
|
||||
if self.env['runtime']['screenManager'].isScreenChange():
|
||||
return
|
||||
if self.env['runtime']['inputManager'].noKeyPressed():
|
||||
return
|
||||
return
|
||||
# detect an change on the screen, we just want to cursor arround, so no change should appear
|
||||
if self.env['runtime']['screenManager'].isDelta():
|
||||
return
|
@ -19,9 +19,7 @@ class command():
|
||||
|
||||
def run(self):
|
||||
if not self.env['runtime']['settingsManager'].getSettingAsBool('focus', 'cursor'):
|
||||
return
|
||||
if self.env['runtime']['inputManager'].noKeyPressed():
|
||||
return
|
||||
return
|
||||
if self.env['runtime']['screenManager'].isScreenChange():
|
||||
return
|
||||
# this leads to problems in vim -> status line change -> no announcement, so we do check the lengh as hack
|
@ -29,8 +29,6 @@ class command():
|
||||
# just when cursor move worddetection is needed
|
||||
if not self.env['runtime']['cursorManager'].isCursorHorizontalMove():
|
||||
return
|
||||
if self.env['runtime']['inputManager'].noKeyPressed():
|
||||
return
|
||||
# for now no new line
|
||||
if self.env['runtime']['cursorManager'].isCursorVerticalMove():
|
||||
return
|
@ -39,8 +39,6 @@ class command():
|
||||
return
|
||||
if not self.env['runtime']['settingsManager'].getSettingAsBool('general', 'autoSpellCheck'):
|
||||
return
|
||||
if self.env['runtime']['inputManager'].noKeyPressed():
|
||||
return
|
||||
if self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage') != self.language:
|
||||
try:
|
||||
self.updateSpellLanguage()
|
@ -19,20 +19,16 @@ class command():
|
||||
def run(self):
|
||||
if not self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'charDeleteEcho'):
|
||||
return
|
||||
|
||||
# detect typing or chilling
|
||||
if self.env['screen']['newCursor']['x'] >= self.env['screen']['oldCursor']['x']:
|
||||
return
|
||||
|
||||
# More than just a deletion happend
|
||||
|
||||
if self.env['runtime']['screenManager'].isDelta():
|
||||
return
|
||||
# no deletion
|
||||
if not self.env['runtime']['screenManager'].isNegativeDelta():
|
||||
return
|
||||
if self.env['runtime']['inputManager'].noKeyPressed():
|
||||
return
|
||||
return
|
||||
|
||||
# too much for a single backspace...
|
||||
# word begin produce a diff wiht len == 2 |a | others with 1 |a|
|
||||
@ -43,7 +39,6 @@ class command():
|
||||
currNegativeDelta.strip() != '':
|
||||
currNegativeDelta = currNegativeDelta.strip()
|
||||
self.env['runtime']['outputManager'].presentText(currNegativeDelta, interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
|
26
src/fenrir/commands/onCursorChange/66000-exit_review_mode.py
Normal file
26
src/fenrir/commands/onCursorChange/66000-exit_review_mode.py
Normal file
@ -0,0 +1,26 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from core import debug
|
||||
|
||||
class command():
|
||||
def __init__(self):
|
||||
pass
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('exits review mode')
|
||||
|
||||
def run(self):
|
||||
if not self.env['runtime']['settingsManager'].getSettingAsBool('review', 'leaveReviewOnCursorChange'):
|
||||
return
|
||||
if self.env['runtime']['cursorManager'].isReviewMode():
|
||||
self.env['runtime']['cursorManager'].clearReviewCursor()
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
29
src/fenrir/commands/onHeartBeat/2000-GetSessionInfo.py
Executable file
29
src/fenrir/commands/onHeartBeat/2000-GetSessionInfo.py
Executable file
@ -0,0 +1,29 @@
|
||||
#!/bin/python
|
||||
import time
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from core import debug
|
||||
import time
|
||||
import datetime
|
||||
|
||||
class command():
|
||||
def __init__(self):
|
||||
pass
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
self.lastTime = datetime.datetime.now()
|
||||
self.lastDateString = ''
|
||||
self.lastTimeString = ''
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return 'No Description found'
|
||||
|
||||
def run(self):
|
||||
self.env['runtime']['screenDriver'].getSessionInformation()
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
|
0
src/fenrir/commands/onScreenUpdate/76000-time.py → src/fenrir/commands/onHeartBeat/76000-time.py
Normal file → Executable file
0
src/fenrir/commands/onScreenUpdate/76000-time.py → src/fenrir/commands/onHeartBeat/76000-time.py
Normal file → Executable file
0
src/fenrir/commands/onHeartBeat/__init__.py
Executable file
0
src/fenrir/commands/onHeartBeat/__init__.py
Executable file
@ -1,33 +0,0 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from core import debug
|
||||
|
||||
class command():
|
||||
def __init__(self):
|
||||
pass
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return 'No Description found'
|
||||
|
||||
def run(self):
|
||||
return
|
||||
if not self.env['runtime']['settingsManager'].getSettingAsBool('review', 'leaveReviewOnKeypress'):
|
||||
return
|
||||
if not self.env['runtime']['inputManager'].noKeyPressed():
|
||||
return
|
||||
if self.env['runtime']['screenManager'].isScreenChange():
|
||||
return
|
||||
if len(self.env['input']['prevDeepestInput']) > len(self.env['input']['currInput']):
|
||||
return
|
||||
self.env['runtime']['cursorManager'].clearReviewCursor()
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
|
22
src/fenrir/commands/onPlugInputDevice/50000-UpdateDevices.py
Executable file
22
src/fenrir/commands/onPlugInputDevice/50000-UpdateDevices.py
Executable file
@ -0,0 +1,22 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from core import debug
|
||||
|
||||
class command():
|
||||
def __init__(self):
|
||||
pass
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return 'No description found'
|
||||
def run(self):
|
||||
if not self.env['runtime']['screenManager'].isSuspendingScreen(): # remove if all works
|
||||
self.env['runtime']['inputManager'].updateInputDevices()
|
||||
def setCallback(self, callback):
|
||||
pass
|
@ -17,23 +17,23 @@ class command():
|
||||
return 'No Description found'
|
||||
|
||||
def run(self):
|
||||
|
||||
if not self.env['runtime']['settingsManager'].getSettingAsBool('speech', 'autoReadIncoming'):
|
||||
return
|
||||
# is there something to read?
|
||||
if not self.env['runtime']['screenManager'].isDelta():
|
||||
return
|
||||
|
||||
if len(self.env['screen']['newDelta']) <=2:
|
||||
return
|
||||
# its a cursor movement (experimental) - maybe also check current shortcut string?
|
||||
|
||||
#if not '$' in self.env['screen']['newDelta'] and
|
||||
# not '#' in self.env['screen']['newDelta']:
|
||||
if abs(self.env['screen']['newCursor']['x'] - self.env['screen']['oldCursor']['x']) >= 1:
|
||||
if len(self.env['screen']['newDelta'].strip(' \n\t0123456789')) <= 2:
|
||||
return
|
||||
if abs(self.env['screen']['newCursor']['x'] - self.env['screen']['oldCursor']['x']) == 1:
|
||||
# if len(self.env['screen']['newDelta'].strip(' \n\t0123456789')) <= 2:
|
||||
return
|
||||
if abs(self.env['screen']['newCursor']['y'] - self.env['screen']['oldCursor']['y']) == 1:
|
||||
if len(self.env['screen']['newDelta'].strip(' \n\t0123456789')) <= 2:
|
||||
return
|
||||
# if len(self.env['screen']['newDelta'].strip(' \n\t0123456789')) <= 2:
|
||||
return
|
||||
self.env['runtime']['outputManager'].presentText(self.env['screen']['newDelta'], interrupt=False, flush=False)
|
||||
|
||||
def setCallback(self, callback):
|
||||
|
@ -22,7 +22,7 @@ class command():
|
||||
return
|
||||
if self.env['runtime']['settingsManager'].getSetting('promote', 'list').strip(" \t\n") == '':
|
||||
return
|
||||
if self.env['screen']['newDelta'] == '':
|
||||
if len(self.env['screen']['newDelta']) <= 2:
|
||||
return
|
||||
if int(time.time() - self.env['input']['lastInputTime']) < self.env['runtime']['settingsManager'].getSettingAsInt('promote', 'inactiveTimeoutSec'):
|
||||
return
|
||||
|
@ -1,36 +0,0 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from core import debug
|
||||
|
||||
class command():
|
||||
def __init__(self):
|
||||
pass
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return 'No Description found'
|
||||
|
||||
def run(self):
|
||||
if not self.env['runtime']['settingsManager'].getSettingAsBool('speech', 'autoReadIncoming'):
|
||||
return
|
||||
# is there something to read?
|
||||
#if not self.env['runtime']['screenManager'].isDelta():
|
||||
# return
|
||||
|
||||
# its a cursor movement (experimental) - maybe also check current shortcut string?
|
||||
if abs(self.env['screen']['newCursor']['x'] - self.env['screen']['oldCursor']['x']) >= 1:
|
||||
if len(self.env['screen']['newDelta'].strip(' \n\t')) <= 2:
|
||||
return
|
||||
#if abs(self.env['screen']['newCursor']['y'] - self.env['screen']['oldCursor']['y']) = 1:
|
||||
# return
|
||||
self.env['runtime']['outputManager'].presentText(self.env['screen']['newDelta'], interrupt=False, flush=False)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
|
@ -7,7 +7,6 @@
|
||||
from core import debug
|
||||
import time
|
||||
|
||||
|
||||
# used as shared memory between commands
|
||||
# use this in your own commands
|
||||
commandBuffer = {
|
||||
@ -24,39 +23,7 @@ commandBuffer = {
|
||||
|
||||
# used by the commandManager
|
||||
commandInfo = {
|
||||
'currCommand': '',
|
||||
#'currCommand': '',
|
||||
'lastCommandExecutionTime': time.time(),
|
||||
'lastCommandRequestTime': time.time(),
|
||||
}
|
||||
|
||||
# used by the commandManager
|
||||
commands = {
|
||||
'onInput':{
|
||||
},
|
||||
'onScreenChanged':{
|
||||
},
|
||||
'onScreenUpdate':{
|
||||
},
|
||||
'onApplicationChange':{
|
||||
},
|
||||
'commands':{
|
||||
},
|
||||
'onSwitchApplicationProfile':{
|
||||
},
|
||||
}
|
||||
|
||||
# used by the commandManager
|
||||
commandsIgnore = {
|
||||
'onInput':{
|
||||
},
|
||||
'onScreenChanged':{
|
||||
},
|
||||
'onScreenUpdate':{
|
||||
},
|
||||
'onApplicationChange':{
|
||||
},
|
||||
'commands':{
|
||||
},
|
||||
'onSwitchApplicationProfile':{
|
||||
},
|
||||
}
|
||||
|
@ -15,10 +15,13 @@ class commandManager():
|
||||
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,
|
||||
self.env['runtime']['settingsManager'].getSetting('general', 'commandPath'))
|
||||
self.env['runtime']['commandManager'].loadCommands(commandFolder)
|
||||
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()
|
||||
@ -42,7 +45,8 @@ class commandManager():
|
||||
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:
|
||||
@ -62,7 +66,6 @@ class commandManager():
|
||||
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:
|
||||
print(command+str(e))
|
||||
self.env['runtime']['debug'].writeDebugOut("Loading command:" + command ,debug.debugLevel.ERROR)
|
||||
self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR)
|
||||
continue
|
||||
@ -123,7 +126,6 @@ class commandManager():
|
||||
shortcut.append(sorted(shortcutKeys))
|
||||
self.env['bindings'][str(shortcut)] = fileName.upper()
|
||||
except Exception as e:
|
||||
print(e)
|
||||
self.env['runtime']['debug'].writeDebugOut("Loading script:" + command ,debug.debugLevel.ERROR)
|
||||
self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR)
|
||||
continue
|
||||
@ -172,37 +174,47 @@ class commandManager():
|
||||
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)
|
||||
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['general']['tutorialMode']:
|
||||
if self.env['runtime']['helpManager'].isTutorialMode() and section != 'help':
|
||||
self.env['runtime']['debug'].writeDebugOut("Tutorial for command:" + section + "." + command ,debug.debugLevel.INFO)
|
||||
description = self.env['commands'][section][command].getDescription()
|
||||
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.env['commands'][section][command].run()
|
||||
self.runCommand(command, section)
|
||||
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['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("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 +' ' + str(e),debug.debugLevel.ERROR)
|
||||
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 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])
|
||||
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
|
||||
|
@ -19,8 +19,6 @@ environment = {
|
||||
'runtime': runtimeData,
|
||||
'general': generalData,
|
||||
'settings': settingsData,
|
||||
'commands': commandData.commands,
|
||||
'commandsIgnore': commandData.commandsIgnore,
|
||||
'commandInfo': commandData.commandInfo,
|
||||
'commandBuffer': commandData.commandBuffer,
|
||||
'input': inputData,
|
||||
|
24
src/fenrir/core/eventData.py
Executable file
24
src/fenrir/core/eventData.py
Executable file
@ -0,0 +1,24 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from 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
|
@ -4,29 +4,14 @@
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
#from core import debug
|
||||
from core import debug
|
||||
from core.eventData import fenrirEventType
|
||||
from queue import Empty
|
||||
import time
|
||||
from enum import Enum
|
||||
from multiprocessing import Process, Queue
|
||||
from multiprocessing.sharedctypes import Value
|
||||
from ctypes import c_bool
|
||||
|
||||
class fenrirEventType(Enum):
|
||||
Ignore = 0
|
||||
StopMainLoop = 1
|
||||
ScreenUpdate = 2
|
||||
KeyboardInput = 3
|
||||
BrailleInput = 4
|
||||
PlugInputDevice = 5
|
||||
BrailleFlush = 6
|
||||
ScreenChanged = 7
|
||||
def __int__(self):
|
||||
return self.value
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class eventManager():
|
||||
def __init__(self):
|
||||
self._mainLoopRunning = Value(c_bool, True)
|
||||
@ -34,11 +19,20 @@ class eventManager():
|
||||
self._eventQueue = Queue() # multiprocessing.Queue()
|
||||
self.cleanEventQueue()
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
self.env = environment
|
||||
self.addSimpleEventThread(fenrirEventType.HeartBeat, self.heartBeatTimer)
|
||||
def shutdown(self):
|
||||
self.terminateAllProcesses()
|
||||
self.cleanEventQueue()
|
||||
def heartBeatTimer(self):
|
||||
try:
|
||||
time.sleep(0.5)
|
||||
except:
|
||||
pass
|
||||
#self.env['runtime']['settingsManager'].getSettingAsFloat('screen', 'screenUpdateDelay')
|
||||
return time.time()
|
||||
def terminateAllProcesses(self):
|
||||
time.sleep(1)
|
||||
for proc in self._eventProcesses:
|
||||
try:
|
||||
proc.terminate()
|
||||
@ -46,20 +40,24 @@ class eventManager():
|
||||
print(e)
|
||||
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._mainLoopRunning.value = 0
|
||||
self.handleStopMainLoop(event)
|
||||
return
|
||||
elif event['Type'] == fenrirEventType.ScreenUpdate:
|
||||
print('do an update')
|
||||
pass
|
||||
self.env['runtime']['fenrirManager'].handleScreenUpdate(event)
|
||||
elif event['Type'] == fenrirEventType.KeyboardInput:
|
||||
pass
|
||||
self.env['runtime']['fenrirManager'].handleInput(event)
|
||||
elif event['Type'] == fenrirEventType.BrailleInput:
|
||||
pass
|
||||
elif event['Type'] == fenrirEventType.PlugInputDevice:
|
||||
@ -67,20 +65,42 @@ class eventManager():
|
||||
elif event['Type'] == fenrirEventType.BrailleFlush:
|
||||
pass
|
||||
elif event['Type'] == fenrirEventType.ScreenChanged:
|
||||
pass
|
||||
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._mainLoopRunning.value == 1
|
||||
def startMainEventLoop(self):
|
||||
self._mainLoopRunning.value = True
|
||||
while(self._mainLoopRunning.value):
|
||||
self._mainLoopRunning.value = 1
|
||||
while( self.isMainEventLoopRunning()):
|
||||
self.proceedEventLoop()
|
||||
|
||||
def handleStopMainLoop(self, event):
|
||||
self._mainLoopRunning.value = 0
|
||||
time.sleep(0.1)
|
||||
def stopMainEventLoop(self, Force = False):
|
||||
if Force:
|
||||
self._mainLoopRunning.value = False
|
||||
self._mainLoopRunning.value = 0
|
||||
self._eventQueue.put({"Type":fenrirEventType.StopMainLoop,"Data":None})
|
||||
def addEventThread(self, event, function):
|
||||
self._mainLoopRunning.value = True
|
||||
t = Process(target=self.eventWorkerThread, args=(event, function))
|
||||
def addCustomEventThread(self, function, pargs = None, multiprocess=False):
|
||||
self._mainLoopRunning.value = 1
|
||||
|
||||
if multiprocess:
|
||||
t = Process(target=self.customEventWorkerThread, args=(self._eventQueue, function, pargs))
|
||||
else:# thread not implemented yet
|
||||
t = Process(target=self.customEventWorkerThread, args=(self._eventQueue, function, pargs))
|
||||
self._eventProcesses.append(t)
|
||||
t.start()
|
||||
def addSimpleEventThread(self, event, function, pargs = None, multiprocess=False, runOnce = False):
|
||||
self._mainLoopRunning.value = 1
|
||||
if multiprocess:
|
||||
t = Process(target=self.simpleEventWorkerThread, args=(event, function, pargs))
|
||||
self._eventProcesses.append(t)
|
||||
else:# thread not implemented yet
|
||||
t = Process(target=self.simpleEventWorkerThread, args=(event, function, pargs))
|
||||
t.start()
|
||||
def cleanEventQueue(self):
|
||||
if self._eventQueue.empty():
|
||||
return
|
||||
@ -94,32 +114,34 @@ class eventManager():
|
||||
return False
|
||||
self._eventQueue.put({"Type":event,"Data":data})
|
||||
return True
|
||||
def eventWorkerThread(self, event, function):
|
||||
def customEventWorkerThread(self, eventQueue, function, args):
|
||||
#if not isinstance(eventQueue, Queue):
|
||||
# return
|
||||
if not callable(function):
|
||||
return
|
||||
while self.isMainEventLoopRunning():
|
||||
try:
|
||||
if args:
|
||||
function(self._mainLoopRunning, eventQueue, args)
|
||||
else:
|
||||
function(self._mainLoopRunning, eventQueue)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
def simpleEventWorkerThread(self, event, function, args, runOnce = False):
|
||||
if not isinstance(event, fenrirEventType):
|
||||
return
|
||||
if not callable(function):
|
||||
return
|
||||
while self._mainLoopRunning.value:
|
||||
while self.isMainEventLoopRunning():
|
||||
Data = None
|
||||
try:
|
||||
Data = function()
|
||||
if args != None:
|
||||
Data = function(self._mainLoopRunning, args)
|
||||
else:
|
||||
Data = function()
|
||||
except Exception as e:
|
||||
print(e)
|
||||
self.env['runtime']['debug'].writeDebugOut('eventManager:simpleEventWorkerThread:function():' + st(e),debug.debugLevel.ERROR)
|
||||
self.putToEventQueue(event, Data)
|
||||
'''
|
||||
def p():
|
||||
time.sleep(0.02)
|
||||
return("p")
|
||||
|
||||
i = 1
|
||||
e = eventManager()
|
||||
e.addEventThread(fenrirEventType.ScreenUpdate,p)
|
||||
e.addEventThread(fenrirEventType.BrailleInput,p)
|
||||
e.addEventThread(fenrirEventType.PlugInputDevice,p)
|
||||
e.addEventThread(fenrirEventType.ScreenChanged,p)
|
||||
time.sleep(1.5)
|
||||
e.addEventThread(fenrirEventType.StopMainLoop,e.stopMainEventLoop)
|
||||
s = time.time()
|
||||
e.startMainEventLoop()
|
||||
print(time.time() - s )
|
||||
'''
|
||||
if runOnce:
|
||||
break
|
||||
|
@ -13,6 +13,7 @@ if not os.path.dirname(os.path.realpath(fenrirVersion.__file__)) in sys.path:
|
||||
from core import i18n
|
||||
from core import settingsManager
|
||||
from core import debug
|
||||
from core.eventData import fenrirEventType
|
||||
import argparse
|
||||
|
||||
class fenrirManager():
|
||||
@ -22,22 +23,24 @@ class fenrirManager():
|
||||
if not cliArgs:
|
||||
return
|
||||
try:
|
||||
self.environment = settingsManager.settingsManager().initFenrirConfig(cliArgs)
|
||||
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.initialized = True
|
||||
self.environment['runtime']['outputManager'].presentText(_("Start Fenrir"), soundIcon='ScreenReaderOn', interrupt=True)
|
||||
signal.signal(signal.SIGINT, self.captureSignal)
|
||||
signal.signal(signal.SIGTERM, self.captureSignal)
|
||||
self.wasCommand = False
|
||||
|
||||
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('-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')
|
||||
try:
|
||||
args = parser.parse_args()
|
||||
except Exception as e:
|
||||
@ -46,79 +49,123 @@ class fenrirManager():
|
||||
def proceed(self):
|
||||
if not self.initialized:
|
||||
return
|
||||
while(self.environment['general']['running']):
|
||||
try:
|
||||
self.handleProcess()
|
||||
except Exception as e:
|
||||
self.environment['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR)
|
||||
self.environment['runtime']['eventManager'].startMainEventLoop()
|
||||
self.shutdown()
|
||||
|
||||
def handleProcess(self):
|
||||
def handleInput(self, event):
|
||||
#startTime = time.time()
|
||||
eventReceived = self.environment['runtime']['inputManager'].getInputEvent()
|
||||
startTime = time.time()
|
||||
if not eventReceived:
|
||||
if not self.environment['runtime']['screenManager'].isSuspendingScreen():
|
||||
self.environment['runtime']['inputManager'].updateInputDevices()
|
||||
if eventReceived:
|
||||
self.prepareCommand()
|
||||
if not (self.wasCommand or self.environment['general']['tutorialMode']) or self.environment['runtime']['screenManager'].isSuspendingScreen():
|
||||
self.environment['runtime']['inputManager'].writeEventBuffer()
|
||||
|
||||
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():
|
||||
if self.wasCommand:
|
||||
self.wasCommand = False
|
||||
self.environment['runtime']['inputManager'].clearEventBuffer()
|
||||
if self.environment['general']['tutorialMode']:
|
||||
self.environment['runtime']['inputManager'].clearEventBuffer()
|
||||
if self.environment['input']['keyForeward'] > 0:
|
||||
self.environment['input']['keyForeward'] -=1
|
||||
self.modifierInput = False
|
||||
self.singleKeyCommand = False
|
||||
if self.environment['input']['keyForeward'] > 0:
|
||||
self.environment['input']['keyForeward'] -=1
|
||||
self.environment['runtime']['screenManager'].update('onInput')
|
||||
self.environment['runtime']['commandManager'].executeDefaultTrigger('onInput')
|
||||
else:
|
||||
self.environment['runtime']['screenManager'].update('onUpdate')
|
||||
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'].update('onScreenChange')
|
||||
'''
|
||||
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())
|
||||
|
||||
if self.environment['runtime']['screenManager'].isScreenChange():
|
||||
self.environment['runtime']['commandManager'].executeDefaultTrigger('onScreenChanged')
|
||||
else:
|
||||
self.environment['runtime']['commandManager'].executeDefaultTrigger('onScreenUpdate')
|
||||
#self.environment['runtime']['outputManager'].brailleText(flush=False)
|
||||
self.handleCommands()
|
||||
#print(time.time()-startTime)
|
||||
'''
|
||||
self.environment['runtime']['commandManager'].executeDefaultTrigger('onScreenChanged')
|
||||
|
||||
def handleScreenUpdate(self, event):
|
||||
#startTime = time.time()
|
||||
|
||||
def prepareCommand(self):
|
||||
if self.environment['runtime']['screenManager'].isSuspendingScreen():
|
||||
self.wasCommand = False
|
||||
return
|
||||
if self.environment['runtime']['inputManager'].noKeyPressed():
|
||||
return
|
||||
self.environment['runtime']['screenManager'].update('onUpdate')
|
||||
'''
|
||||
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())
|
||||
'''
|
||||
# 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')
|
||||
#print('handleScreenUpdate:',time.time() - startTime)
|
||||
|
||||
def handlePlugInputDevice(self, event):
|
||||
self.environment['runtime']['commandManager'].executeDefaultTrigger('PlugInputDevice')
|
||||
|
||||
def handleHeartBeat(self, event):
|
||||
self.environment['runtime']['commandManager'].executeDefaultTrigger('onHeartBeat')
|
||||
#self.environment['runtime']['outputManager'].brailleText(flush=False)
|
||||
|
||||
def detectCommand(self):
|
||||
if self.environment['input']['keyForeward'] > 0:
|
||||
return
|
||||
shortcut = self.environment['runtime']['inputManager'].getCurrShortcut()
|
||||
command = self.environment['runtime']['inputManager'].getCommandForShortcut(shortcut)
|
||||
if len(self.environment['input']['prevDeepestInput']) <= len(self.environment['input']['currInput']):
|
||||
self.wasCommand = command != '' or self.environment['runtime']['inputManager'].isFenrirKeyPressed() or self.environment['runtime']['inputManager'].isScriptKeyPressed()
|
||||
if command == '':
|
||||
return
|
||||
|
||||
self.environment['runtime']['commandManager'].queueCommand(command)
|
||||
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['input']['prevDeepestInput']) == 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
|
||||
|
||||
def handleCommands(self):
|
||||
if not self.environment['runtime']['commandManager'].isCommandQueued():
|
||||
if not (self.singleKeyCommand or self.modifierInput):
|
||||
return
|
||||
self.environment['runtime']['commandManager'].executeCommand( self.environment['commandInfo']['currCommand'], 'commands')
|
||||
|
||||
|
||||
# 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):
|
||||
self.environment['general']['running'] = False
|
||||
self.environment['runtime']['eventManager'].stopMainEventLoop()
|
||||
|
||||
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()
|
||||
self.environment['runtime']['eventManager'].stopMainEventLoop(True)
|
||||
for currManager in self.environment['general']['managerList']:
|
||||
if self.environment['runtime'][currManager]:
|
||||
self.environment['runtime'][currManager].shutdown()
|
||||
|
@ -7,13 +7,12 @@
|
||||
from core import debug
|
||||
|
||||
generalData = {
|
||||
'running': True,
|
||||
'args': None,
|
||||
'tutorialMode': False,
|
||||
'currUser':'',
|
||||
'prevUser':'',
|
||||
'managerList':['eventManager','punctuationManager','cursorManager','applicationManager','commandManager'
|
||||
,'screenManager','inputManager','outputManager','debug'],
|
||||
'commandFolderList':['commands','onInput','onScreenUpdate','onScreenChanged'
|
||||
,'onApplicationChange','onSwitchApplicationProfile',],
|
||||
,'screenManager','inputManager','outputManager','helpManager','debug'],
|
||||
'commandFolderList':['commands','onInput', 'onCursorChange', 'onScreenUpdate','onScreenChanged','onHeartBeat', 'onPlugInputDevice'
|
||||
,'onApplicationChange','onSwitchApplicationProfile','help',],
|
||||
}
|
||||
|
81
src/fenrir/core/helpManager.py
Executable file
81
src/fenrir/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 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
|
@ -39,7 +39,7 @@ class inputManager():
|
||||
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:
|
||||
elif len(self.env['input']['currInput']) == 0:
|
||||
self.env['input']['prevDeepestInput'] = []
|
||||
self.env['input']['shortcutRepeat'] = 1
|
||||
self.setLedState = self.handleLedStates(mEvent)
|
||||
@ -141,13 +141,6 @@ class inputManager():
|
||||
eventName = 'KEY_SCRIPT'
|
||||
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()
|
||||
|
||||
@ -155,24 +148,15 @@ class inputManager():
|
||||
try:
|
||||
if self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'grabDevices'):
|
||||
self.env['runtime']['inputDriver'].writeEventBuffer()
|
||||
time.sleep(0.008)
|
||||
self.clearEventBuffer()
|
||||
if len(self.env['input']['currInput']) == 1:
|
||||
if self.env['input']['currInput'][0] in ['KEY_UP','KEY_DOWN']:
|
||||
time.sleep(0.08) # hack for tintin history because it needs more time
|
||||
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']['prevDeepestInput']
|
||||
|
||||
def isScriptKeyPressed(self):
|
||||
return 'KEY_SCRIPT' in self.env['input']['prevDeepestInput']
|
||||
|
||||
def noKeyPressed(self):
|
||||
return self.env['input']['currInput'] == []
|
||||
|
||||
def isKeyPress(self):
|
||||
return (self.env['input']['prevInput'] == []) and (self.env['input']['currInput'] != [])
|
||||
def getPrevDeepestInput(self):
|
||||
shortcut = []
|
||||
shortcut.append(self.env['input']['shortcutRepeat'])
|
||||
@ -185,10 +169,13 @@ class inputManager():
|
||||
shortcut.append(self.env['input']['prevInput'])
|
||||
return str(shortcut)
|
||||
|
||||
def getCurrShortcut(self):
|
||||
def getCurrShortcut(self, inputSequence = None):
|
||||
shortcut = []
|
||||
shortcut.append(self.env['input']['shortcutRepeat'])
|
||||
shortcut.append(self.env['input']['currInput'])
|
||||
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 = []
|
||||
@ -198,10 +185,17 @@ class inputManager():
|
||||
self.env['runtime']['debug'].writeDebugOut("currShortcut " + str(shortcut) ,debug.debugLevel.INFO)
|
||||
return str(shortcut)
|
||||
|
||||
def currKeyIsModifier(self):
|
||||
if len(self.env['input']['prevDeepestInput']) != 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 ''
|
||||
|
@ -21,16 +21,19 @@ class screenManager():
|
||||
self.env['runtime']['settingsManager'].shutdownDriver('screenDriver')
|
||||
|
||||
def update(self, trigger='onUpdate'):
|
||||
self.env['runtime']['screenDriver'].getCurrScreen()
|
||||
self.env['runtime']['screenDriver'].getSessionInformation()
|
||||
self.env['runtime']['screenDriver'].getCurrScreen()
|
||||
|
||||
if trigger == 'onScreenChange':
|
||||
self.env['runtime']['screenDriver'].getSessionInformation()
|
||||
|
||||
self.env['screen']['oldApplication'] = self.env['screen']['newApplication']
|
||||
if self.isScreenChange():
|
||||
self.changeBrailleScreen()
|
||||
if not self.isSuspendingScreen(self.env['screen']['newTTY']):
|
||||
self.env['runtime']['screenDriver'].update(trigger)
|
||||
if trigger == 'onUpdate' or self.isScreenChange() \
|
||||
or len(self.env['screen']['newDelta']) > 6:
|
||||
self.env['runtime']['screenDriver'].getCurrApplication()
|
||||
#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 isSuspendingScreen(self, screen = None):
|
||||
@ -42,6 +45,7 @@ class screenManager():
|
||||
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)
|
||||
return (screen in ignoreScreens)
|
||||
|
||||
def isScreenChange(self):
|
||||
|
@ -76,7 +76,7 @@ settingsData = {
|
||||
'review':{
|
||||
'lineBreak': True,
|
||||
'endOfScreen': True,
|
||||
'leaveReviewOnKeypress': False,
|
||||
'leaveReviewOnCursorChange': True,
|
||||
'leaveReviewOnScreenChange': True,
|
||||
},
|
||||
'promote':{
|
||||
|
@ -15,6 +15,7 @@ from core import screenManager
|
||||
from core import punctuationManager
|
||||
from core import cursorManager
|
||||
from core import applicationManager
|
||||
from core import helpManager
|
||||
from core import environment
|
||||
from core import inputData
|
||||
from core.settingsData import settingsData
|
||||
@ -69,8 +70,10 @@ class settingsManager():
|
||||
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
|
||||
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")
|
||||
@ -147,7 +150,7 @@ class settingsManager():
|
||||
def getSetting(self, section, setting):
|
||||
value = ''
|
||||
try:
|
||||
value = self.settingArgDict[section][setting]
|
||||
value = self.settingArgDict[section.lower()][setting.lower()]
|
||||
return value
|
||||
except:
|
||||
pass
|
||||
@ -160,10 +163,10 @@ class settingsManager():
|
||||
def getSettingAsInt(self, section, setting):
|
||||
value = 0
|
||||
try:
|
||||
value = int(self.settingArgDict[section][setting])
|
||||
value = int(self.settingArgDict[section.lower()][setting.lower()])
|
||||
return value
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
pass
|
||||
try:
|
||||
value = self.env['settings'].getint(section, setting)
|
||||
except:
|
||||
@ -173,7 +176,7 @@ class settingsManager():
|
||||
def getSettingAsFloat(self, section, setting):
|
||||
value = 0.0
|
||||
try:
|
||||
value = float(self.settingArgDict[section][setting])
|
||||
value = float(self.settingArgDict[section.lower()][setting.lower()])
|
||||
return value
|
||||
except Exception as e:
|
||||
pass
|
||||
@ -186,7 +189,7 @@ class settingsManager():
|
||||
def getSettingAsBool(self, section, setting):
|
||||
value = False
|
||||
try:
|
||||
value = self.settingArgDict[section][setting].upper() in ['1','YES','JA','TRUE']
|
||||
value = self.settingArgDict[section.lower()][setting.lower()].upper() in ['1','YES','JA','TRUE']
|
||||
return value
|
||||
except Exception as e:
|
||||
pass
|
||||
@ -226,8 +229,16 @@ class settingsManager():
|
||||
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):
|
||||
optionArgDict = {}
|
||||
for optionElem in settingArgs.split(';'):
|
||||
if len(optionElem.split('#',1)) != 2:
|
||||
continue
|
||||
@ -236,13 +247,9 @@ class settingsManager():
|
||||
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]
|
||||
try:
|
||||
e = optionArgDict[section]
|
||||
except KeyError:
|
||||
optionArgDict[section] = {}
|
||||
optionArgDict[section][option] = str(value)
|
||||
return optionArgDict
|
||||
def initFenrirConfig(self, cliArgs, environment = environment.environment):
|
||||
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/'
|
||||
@ -271,11 +278,15 @@ class settingsManager():
|
||||
validConfig = environment['runtime']['settingsManager'].loadSettings(settingsFile)
|
||||
if not validConfig:
|
||||
return None
|
||||
|
||||
if cliArgs.options != '':
|
||||
self.settingArgDict = self.parseSettingArgs(cliArgs.options)
|
||||
self.parseSettingArgs(cliArgs.options)
|
||||
if cliArgs.debug:
|
||||
self.setOptionArgDict('general', 'debugLevel', 3)
|
||||
|
||||
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'))
|
||||
@ -304,6 +315,8 @@ class settingsManager():
|
||||
else:
|
||||
environment['runtime']['settingsManager'].loadDicts(self.getSetting('general','punctuationProfile'))
|
||||
|
||||
if fenrirManager:
|
||||
environment['runtime']['fenrirManager'] = fenrirManager
|
||||
environment['runtime']['eventManager'] = eventManager.eventManager()
|
||||
environment['runtime']['eventManager'].initialize(environment)
|
||||
environment['runtime']['inputManager'] = inputManager.inputManager()
|
||||
@ -318,15 +331,17 @@ class settingsManager():
|
||||
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)
|
||||
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(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
|
||||
|
||||
|
@ -5,7 +5,9 @@
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
_evdevAvailable = False
|
||||
_udevAvailable = False
|
||||
_evdevAvailableError = ''
|
||||
_udevAvailableError = ''
|
||||
try:
|
||||
import evdev
|
||||
from evdev import InputDevice, UInput
|
||||
@ -13,42 +15,93 @@ try:
|
||||
except Exception as e:
|
||||
_evdevAvailableError = str(e)
|
||||
|
||||
try:
|
||||
import pyudev
|
||||
_udevAvailable = True
|
||||
except Exception as e:
|
||||
_udevAvailableError = str(e)
|
||||
|
||||
import time
|
||||
from select import select
|
||||
import multiprocessing
|
||||
from multiprocessing.sharedctypes import Value
|
||||
from ctypes import c_bool
|
||||
|
||||
from core.eventData import fenrirEventType
|
||||
from core import inputData
|
||||
from core import debug
|
||||
|
||||
|
||||
class driver():
|
||||
def __init__(self):
|
||||
self._manager = multiprocessing.Manager()
|
||||
self.iDevices = {}
|
||||
self.iDevicesFD = None
|
||||
self.uDevices = {}
|
||||
self.iDeviceNo = 0
|
||||
self._initialized = False
|
||||
|
||||
self.watchDog = Value(c_bool, True)
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
global _evdevAvailable
|
||||
global _udevAvailable
|
||||
self._initialized = _evdevAvailable
|
||||
if not self._initialized:
|
||||
global _evdevAvailableError
|
||||
self.env['runtime']['debug'].writeDebugOut('InputDriver: ' + _evdevAvailableError,debug.debugLevel.ERROR)
|
||||
return
|
||||
self.updateInputDevices()
|
||||
if _udevAvailable:
|
||||
self.env['runtime']['eventManager'].addCustomEventThread(self.plugInputDeviceWatchdogUdev)
|
||||
else:
|
||||
self.env['runtime']['eventManager'].addSimpleEventThread(fenrirEventType.PlugInputDevice, self.plugInputDeviceWatchdogTimer)
|
||||
self.env['runtime']['eventManager'].addSimpleEventThread(fenrirEventType.KeyboardInput, self.inputWatchdog, {'dev':self.iDevicesFD})
|
||||
def plugInputDeviceWatchdogUdev(self,active , eventQueue):
|
||||
context = pyudev.Context()
|
||||
monitor = pyudev.Monitor.from_netlink(context)
|
||||
monitor.filter_by(subsystem='input')
|
||||
monitor.start()
|
||||
while active:
|
||||
devices = monitor.poll(2)
|
||||
if devices:
|
||||
for device in devices:
|
||||
if not active:
|
||||
return
|
||||
print('drin')
|
||||
eventQueue.put({"Type":fenrirEventType.PlugInputDevice,"Data":''})
|
||||
|
||||
#self.env['runtime']['settingsManager'].getSettingAsFloat('screen', 'screenUpdateDelay')
|
||||
return time.time()
|
||||
def plugInputDeviceWatchdogTimer(self):
|
||||
time.sleep(2.5)
|
||||
return time.time()
|
||||
def shutdown(self):
|
||||
if not self._initialized:
|
||||
return
|
||||
return
|
||||
def inputWatchdog(self,active , iDevicesFD):
|
||||
deviceFd = []
|
||||
for fd in iDevicesFD['dev']:
|
||||
deviceFd.append(fd)
|
||||
while self.watchDog.value == 0:
|
||||
if active.value == 0:
|
||||
return
|
||||
r = []
|
||||
while r == []:
|
||||
r, w, x = select(deviceFd, [], [], 2)
|
||||
self.watchDog.value = 0
|
||||
def getInputEvent(self):
|
||||
if not self.hasIDevices():
|
||||
time.sleep(0.008) # dont flood CPU
|
||||
self.watchDog.value = 1
|
||||
return None
|
||||
event = None
|
||||
r, w, x = select(self.iDevices, [], [], self.env['runtime']['settingsManager'].getSettingAsFloat('screen', 'screenUpdateDelay'))
|
||||
r, w, x = select(self.iDevices, [], [], 0.0001)
|
||||
if r != []:
|
||||
for fd in r:
|
||||
try:
|
||||
event = self.iDevices[fd].read_one()
|
||||
except:
|
||||
self.removeDevice(fd)
|
||||
self.watchDog.value = 1
|
||||
return None
|
||||
foreward = False
|
||||
while(event):
|
||||
@ -66,6 +119,7 @@ class driver():
|
||||
continue
|
||||
if not foreward:
|
||||
if currMapEvent['EventState'] in [0,1,2]:
|
||||
self.watchDog.value = 1
|
||||
return currMapEvent
|
||||
else:
|
||||
if not event.type in [0,1,4]:
|
||||
@ -73,7 +127,8 @@ class driver():
|
||||
event = self.iDevices[fd].read_one()
|
||||
if foreward:
|
||||
self.writeEventBuffer()
|
||||
self.clearEventBuffer()
|
||||
self.clearEventBuffer()
|
||||
self.watchDog.value = 1
|
||||
return None
|
||||
|
||||
def writeEventBuffer(self):
|
||||
@ -92,7 +147,7 @@ class driver():
|
||||
return
|
||||
uDevice.write_event(event)
|
||||
uDevice.syn()
|
||||
time.sleep(0.01)
|
||||
time.sleep(0.0001)
|
||||
|
||||
def updateInputDevices(self, force = False, init = False):
|
||||
if init:
|
||||
@ -145,6 +200,11 @@ class driver():
|
||||
self.env['runtime']['debug'].writeDebugOut('Device added (Name):' + self.iDevices[currDevice.fd].name,debug.debugLevel.INFO)
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut("Skip Inputdevice : " + deviceFile +' ' + str(e),debug.debugLevel.ERROR)
|
||||
self.iDevicesFD = multiprocessing.Array('i', len(self.iDevices))
|
||||
i = 0
|
||||
for fd in self.iDevices:
|
||||
self.iDevicesFD[i] = fd
|
||||
i +=1
|
||||
self.iDeviceNo = len(evdev.list_devices())
|
||||
|
||||
def mapEvent(self, event):
|
||||
@ -191,6 +251,9 @@ class driver():
|
||||
self.grabDevice(fd)
|
||||
|
||||
def grabDevice(self, fd):
|
||||
if not self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'grabDevices'):
|
||||
self.uDevices[fd] = None
|
||||
return
|
||||
try:
|
||||
self.uDevices[fd] = UInput.from_device(self.iDevices[fd].fn)
|
||||
except Exception as e:
|
||||
@ -232,7 +295,12 @@ class driver():
|
||||
try:
|
||||
del(self.uDevices[fd])
|
||||
except:
|
||||
pass
|
||||
pass
|
||||
self.iDevicesFD = multiprocessing.Array('i', len(self.iDevices))
|
||||
i = 0
|
||||
for fd in self.iDevices:
|
||||
self.iDevicesFD[i] = fd
|
||||
i +=1
|
||||
def hasIDevices(self):
|
||||
if not self._initialized:
|
||||
return False
|
||||
|
@ -3,23 +3,42 @@
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
import difflib
|
||||
import re
|
||||
import subprocess
|
||||
import fcntl
|
||||
import glob, os
|
||||
import termios
|
||||
import time
|
||||
import select
|
||||
import dbus
|
||||
from core import debug
|
||||
import fcntl
|
||||
from array import array
|
||||
import errno
|
||||
import sys
|
||||
from utils import screen_utils
|
||||
from fcntl import ioctl
|
||||
from struct import unpack_from, unpack, pack
|
||||
from core import debug
|
||||
from core.eventData import fenrirEventType
|
||||
|
||||
|
||||
class driver():
|
||||
def __init__(self):
|
||||
self.vcsaDevicePath = '/dev/vcsa'
|
||||
self.ListSessions = None
|
||||
self.charmap = {}
|
||||
self.hichar = None
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
self.env['runtime']['eventManager'].addCustomEventThread(self.updateWatchdog)
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getCurrScreen(self):
|
||||
@ -92,9 +111,126 @@ class driver():
|
||||
self.env['general']['currUser'] = session[2]
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('getSessionInformation: Maybe no LoginD:' + str(e),debug.debugLevel.ERROR)
|
||||
self.env['screen']['autoIgnoreScreens'] = []
|
||||
self.env['screen']['autoIgnoreScreens'] = []
|
||||
self.env['runtime']['debug'].writeDebugOut('getSessionInformation:' + str(self.env['screen']['autoIgnoreScreens']) + ' ' + str(self.env['general']) ,debug.debugLevel.INFO)
|
||||
|
||||
def updateWatchdog(self,active , eventQueue):
|
||||
try:
|
||||
vcsa = {}
|
||||
vcsaDevices = glob.glob('/dev/vcsa*')
|
||||
for vcsaDev in vcsaDevices:
|
||||
index = vcsaDev[9:]
|
||||
vcsa[str(index)] = open(vcsaDev,'rb')
|
||||
|
||||
tty = open('/sys/devices/virtual/tty/tty0/active','r')
|
||||
currScreen = str(tty.read()[3:-1])
|
||||
oldScreen = currScreen
|
||||
watchdog = select.epoll()
|
||||
watchdog.register(vcsa[currScreen], select.EPOLLPRI)
|
||||
watchdog.register(tty, select.EPOLLPRI)
|
||||
lastScreenContent = b''
|
||||
while active.value == 1:
|
||||
changes = watchdog.poll(2)
|
||||
for change in changes:
|
||||
fileno = change[0]
|
||||
event = change[1]
|
||||
if fileno == tty.fileno():
|
||||
self.env['runtime']['debug'].writeDebugOut('ScreenChange',debug.debugLevel.INFO)
|
||||
tty.seek(0)
|
||||
currScreen = str(tty.read()[3:-1])
|
||||
if currScreen != oldScreen:
|
||||
try:
|
||||
watchdog.unregister(vcsa[ oldScreen ])
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
watchdog.register(vcsa[ currScreen ], select.EPOLLPRI)
|
||||
except:
|
||||
pass
|
||||
oldScreen = currScreen
|
||||
eventQueue.put({"Type":fenrirEventType.ScreenChanged,"Data":''})
|
||||
try:
|
||||
vcsa[currScreen].seek(0)
|
||||
lastScreenContent = vcsa[currScreen].read()
|
||||
except:
|
||||
lastScreenContent = b''
|
||||
else:
|
||||
self.env['runtime']['debug'].writeDebugOut('ScreenUpdate',debug.debugLevel.INFO)
|
||||
vcsa[currScreen].seek(0)
|
||||
screenContent = vcsa[currScreen].read()
|
||||
if screenContent != lastScreenContent:
|
||||
eventQueue.put({"Type":fenrirEventType.ScreenUpdate,"Data":''})
|
||||
lastScreenContent = screenContent
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('VCSA:updateWatchdog:' + str(e),debug.debugLevel.ERROR)
|
||||
|
||||
def updateCharMap(self, screen):
|
||||
tty = open('/dev/tty' + screen, 'rb')
|
||||
GIO_UNIMAP = 0x4B66
|
||||
VT_GETHIFONTMASK = 0x560D
|
||||
himask = array("H", (0,))
|
||||
ioctl(tty, VT_GETHIFONTMASK, himask)
|
||||
self.hichar, = unpack_from("@H", himask)
|
||||
sz = 512
|
||||
line = ''
|
||||
while True:
|
||||
try:
|
||||
unipairs = array("H", [0]*(2*sz))
|
||||
unimapdesc = array("B", pack("@HP", sz, unipairs.buffer_info()[0]))
|
||||
ioctl(tty.fileno(), GIO_UNIMAP, unimapdesc)
|
||||
break
|
||||
except IOError as e:
|
||||
if e.errno != errno.ENOMEM:
|
||||
raise
|
||||
sz *= 2
|
||||
tty.close()
|
||||
ncodes, = unpack_from("@H", unimapdesc)
|
||||
utable = unpack_from("@%dH" % (2*ncodes), unipairs)
|
||||
for u, b in zip(utable[::2], utable[1::2]):
|
||||
if self.charmap.get(b) is None:
|
||||
self.charmap[b] = chr(u)
|
||||
|
||||
def autoDecodeVCSA(self, allData, rows, cols):
|
||||
allText = ''
|
||||
allAttrib = b''
|
||||
i = 0
|
||||
for y in range(rows):
|
||||
lineText = ''
|
||||
lineAttrib = b''
|
||||
for x in range(cols):
|
||||
data = allData[i: i + 2]
|
||||
i += 2
|
||||
if data == b' \x07':
|
||||
#attr = 7
|
||||
#ink = 7
|
||||
#paper = 0
|
||||
#ch = ' '
|
||||
lineAttrib += b'7'
|
||||
lineText += ' '
|
||||
continue
|
||||
(sh,) = unpack("=H", data)
|
||||
attr = (sh >> 8) & 0xFF
|
||||
ch = sh & 0xFF
|
||||
if self.hichar == 0x100:
|
||||
attr >>= 1
|
||||
lineAttrib += bytes(attr)
|
||||
ink = attr & 0x0F
|
||||
paper = (attr>>4) & 0x0F
|
||||
#if (ink != 7) or (paper != 0):
|
||||
# print(ink,paper)
|
||||
if sh & self.hichar:
|
||||
ch |= 0x100
|
||||
try:
|
||||
lineText += self.charmap[ch]
|
||||
except KeyError:
|
||||
lineText += chr('?')
|
||||
allText += lineText + '\n'
|
||||
allAttrib += lineAttrib
|
||||
return str(allText), allAttrib
|
||||
|
||||
def update(self, trigger='onUpdate'):
|
||||
if trigger == 'onInput': # no need for an update on input for VCSA
|
||||
return
|
||||
newContentBytes = b''
|
||||
try:
|
||||
# read screen
|
||||
@ -124,10 +260,17 @@ class driver():
|
||||
self.env['screen']['newCursor']['x'] = int( self.env['screen']['newContentBytes'][2])
|
||||
self.env['screen']['newCursor']['y'] = int( self.env['screen']['newContentBytes'][3])
|
||||
# analyze content
|
||||
self.env['screen']['newContentText'] = self.env['screen']['newContentBytes'][4:][::2].decode(screenEncoding, "replace").encode('utf-8').decode('utf-8')
|
||||
self.env['screen']['newContentText'] = screen_utils.removeNonprintable(self.env['screen']['newContentText'])
|
||||
self.env['screen']['newContentAttrib'] = self.env['screen']['newContentBytes'][5:][::2]
|
||||
self.env['screen']['newContentText'] = screen_utils.insertNewlines(self.env['screen']['newContentText'], self.env['screen']['columns'])
|
||||
|
||||
if screenEncoding.upper() == 'AUTO':
|
||||
self.updateCharMap(str(self.env['screen']['newTTY']))
|
||||
self.env['screen']['newContentText'], \
|
||||
self.env['screen']['newContentAttrib'] =\
|
||||
self.autoDecodeVCSA(self.env['screen']['newContentBytes'][4:], self.env['screen']['lines'], self.env['screen']['columns'])
|
||||
else:
|
||||
self.env['screen']['newContentText'] = self.env['screen']['newContentBytes'][4:][::2].decode(screenEncoding, "replace").encode('utf-8').decode('utf-8')
|
||||
self.env['screen']['newContentText'] = screen_utils.removeNonprintable(self.env['screen']['newContentText'])
|
||||
self.env['screen']['newContentAttrib'] = self.env['screen']['newContentBytes'][5:][::2]
|
||||
self.env['screen']['newContentText'] = screen_utils.insertNewlines(self.env['screen']['newContentText'], self.env['screen']['columns'])
|
||||
|
||||
if self.env['screen']['newTTY'] != self.env['screen']['oldTTY']:
|
||||
self.env['screen']['oldContentBytes'] = b''
|
||||
|
Reference in New Issue
Block a user