From df834ca372cf3aa46ce1c2ce23cfd46701e45f39 Mon Sep 17 00:00:00 2001 From: Chrys Date: Mon, 12 Jun 2017 17:28:20 +0200 Subject: [PATCH 01/96] add method for custom event handing --- src/fenrir/core/eventManager.py | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/fenrir/core/eventManager.py b/src/fenrir/core/eventManager.py index e81407cb..0f926bbb 100644 --- a/src/fenrir/core/eventManager.py +++ b/src/fenrir/core/eventManager.py @@ -76,9 +76,14 @@ class eventManager(): if Force: self._mainLoopRunning.value = False self._eventQueue.put({"Type":fenrirEventType.StopMainLoop,"Data":None}) - def addEventThread(self, event, function): + def addCustomEventThread(self, function): self._mainLoopRunning.value = True - t = Process(target=self.eventWorkerThread, args=(event, function)) + t = Process(target=self.eventWorkerThread, args=(q, function)) + self._eventProcesses.append(t) + t.start() + def addSimpleEventThread(self, event, function): + self._mainLoopRunning.value = True + t = Process(target=self.SimpleEventWorkerThread, args=(event, function)) self._eventProcesses.append(t) t.start() def cleanEventQueue(self): @@ -94,7 +99,18 @@ class eventManager(): return False self._eventQueue.put({"Type":event,"Data":data}) return True - def eventWorkerThread(self, event, function): + def customEventWorkerThread(self, eventQueue, function): + if not isinstance(eventQueue, Queue): + return + if not callable(function): + return + while self._mainLoopRunning.value: + try: + function(eventQueue) + except Exception as e: + print(e) + + def simpleEventWorkerThread(self, event, function): if not isinstance(event, fenrirEventType): return if not callable(function): From 461e9bb5b36d04ffe92bac3b2248a8e22de4ec3d Mon Sep 17 00:00:00 2001 From: Chrys Date: Wed, 21 Jun 2017 11:40:10 +0200 Subject: [PATCH 02/96] initial use of eventManager using heartbeat --- src/fenrir/core/eventManager.py | 14 +++++++++++--- src/fenrir/core/fenrirManager.py | 12 ++++++------ src/fenrir/core/settingsManager.py | 4 +++- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/fenrir/core/eventManager.py b/src/fenrir/core/eventManager.py index 0f926bbb..e7bb728e 100644 --- a/src/fenrir/core/eventManager.py +++ b/src/fenrir/core/eventManager.py @@ -4,7 +4,7 @@ # Fenrir TTY screen reader # By Chrys, Storm Dragon, and contributers. -#from core import debug +from core import debug from queue import Empty import time from enum import Enum @@ -21,6 +21,7 @@ class fenrirEventType(Enum): PlugInputDevice = 5 BrailleFlush = 6 ScreenChanged = 7 + HeartBeat = 8 # for time based scheduling def __int__(self): return self.value def __str__(self): @@ -34,10 +35,14 @@ class eventManager(): self._eventQueue = Queue() # multiprocessing.Queue() self.cleanEventQueue() def initialize(self, environment): - self.env = environment + self.env = environment + self.addSimpleEventThread(fenrirEventType.HeartBeat, self.timerProcess) def shutdown(self): self.terminateAllProcesses() self.cleanEventQueue() + def timerProcess(self): + time.sleep(0.005) + return time.time() def terminateAllProcesses(self): for proc in self._eventProcesses: try: @@ -68,6 +73,9 @@ class eventManager(): pass elif event['Type'] == fenrirEventType.ScreenChanged: pass + elif event['Type'] == fenrirEventType.HeartBeat: + self.env['runtime']['fenrirManager'].handleProcess() + print('HeartBeat at ' + str(event['Type']) + ' ' +str(event['Data'] )) def startMainEventLoop(self): self._mainLoopRunning.value = True while(self._mainLoopRunning.value): @@ -83,7 +91,7 @@ class eventManager(): t.start() def addSimpleEventThread(self, event, function): self._mainLoopRunning.value = True - t = Process(target=self.SimpleEventWorkerThread, args=(event, function)) + t = Process(target=self.simpleEventWorkerThread, args=(event, function)) self._eventProcesses.append(t) t.start() def cleanEventQueue(self): diff --git a/src/fenrir/core/fenrirManager.py b/src/fenrir/core/fenrirManager.py index cb8ffda8..d8bfff1a 100644 --- a/src/fenrir/core/fenrirManager.py +++ b/src/fenrir/core/fenrirManager.py @@ -22,7 +22,7 @@ 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: @@ -46,11 +46,8 @@ 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): @@ -118,7 +115,10 @@ class fenrirManager(): self.shutdownRequest() def shutdown(self): + self.environment['eventManager'].stopMainEventLoop() self.environment['runtime']['outputManager'].presentText(_("Quit Fenrir"), soundIcon='ScreenReaderOff', interrupt=True) + self.environment['eventManager'].cleanEventQueue() + self.environment['eventManager'].stopMainEventLoop(True) for currManager in self.environment['general']['managerList']: if self.environment['runtime'][currManager]: self.environment['runtime'][currManager].shutdown() diff --git a/src/fenrir/core/settingsManager.py b/src/fenrir/core/settingsManager.py index 5d11e80b..aad79688 100644 --- a/src/fenrir/core/settingsManager.py +++ b/src/fenrir/core/settingsManager.py @@ -242,7 +242,7 @@ class settingsManager(): optionArgDict[section] = {} optionArgDict[section][option] = str(value) return optionArgDict - def initFenrirConfig(self, cliArgs, environment = environment.environment): + def initFenrirConfig(self, cliArgs, fenrirManager = None, environment = environment.environment): settingsRoot = '/etc/fenrir/' settingsFile = cliArgs.setting soundRoot = '/usr/share/sounds/fenrir/' @@ -304,6 +304,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() From c8dd57e4b48b7d83da2df5078f69286368f8343a Mon Sep 17 00:00:00 2001 From: Chrys Date: Wed, 21 Jun 2017 14:22:22 +0200 Subject: [PATCH 03/96] make fenrir quitable with eventloop, remove delay in evdevDriver --- src/fenrir/commands/commands/quit_fenrir.py | 2 +- src/fenrir/core/eventManager.py | 5 ++++- src/fenrir/core/fenrirManager.py | 2 +- src/fenrir/core/generalData.py | 1 - src/fenrir/inputDriver/evdevDriver.py | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/fenrir/commands/commands/quit_fenrir.py b/src/fenrir/commands/commands/quit_fenrir.py index 2ac67484..2ddae36f 100644 --- a/src/fenrir/commands/commands/quit_fenrir.py +++ b/src/fenrir/commands/commands/quit_fenrir.py @@ -17,7 +17,7 @@ class command(): return _('exits Fenrir') def run(self): - self.env['general']['running'] = False + self.env['eventManager'].stopMainEventLoop() def setCallback(self, callback): pass diff --git a/src/fenrir/core/eventManager.py b/src/fenrir/core/eventManager.py index e7bb728e..b6b0e006 100644 --- a/src/fenrir/core/eventManager.py +++ b/src/fenrir/core/eventManager.py @@ -42,6 +42,7 @@ class eventManager(): self.cleanEventQueue() def timerProcess(self): time.sleep(0.005) + #self.env['runtime']['settingsManager'].getSettingAsFloat('screen', 'screenUpdateDelay') return time.time() def terminateAllProcesses(self): for proc in self._eventProcesses: @@ -118,7 +119,7 @@ class eventManager(): except Exception as e: print(e) - def simpleEventWorkerThread(self, event, function): + def simpleEventWorkerThread(self, event, function, runOnce = False): if not isinstance(event, fenrirEventType): return if not callable(function): @@ -130,6 +131,8 @@ class eventManager(): except Exception as e: print(e) self.putToEventQueue(event, Data) + if runOnce: + break ''' def p(): time.sleep(0.02) diff --git a/src/fenrir/core/fenrirManager.py b/src/fenrir/core/fenrirManager.py index d8bfff1a..e22d252e 100644 --- a/src/fenrir/core/fenrirManager.py +++ b/src/fenrir/core/fenrirManager.py @@ -109,7 +109,7 @@ class fenrirManager(): self.environment['runtime']['commandManager'].executeCommand( self.environment['commandInfo']['currCommand'], 'commands') def shutdownRequest(self): - self.environment['general']['running'] = False + self.environment['eventManager'].stopMainEventLoop() def captureSignal(self, siginit, frame): self.shutdownRequest() diff --git a/src/fenrir/core/generalData.py b/src/fenrir/core/generalData.py index 6e4d666b..324099ba 100644 --- a/src/fenrir/core/generalData.py +++ b/src/fenrir/core/generalData.py @@ -7,7 +7,6 @@ from core import debug generalData = { -'running': True, 'args': None, 'tutorialMode': False, 'currUser':'', diff --git a/src/fenrir/inputDriver/evdevDriver.py b/src/fenrir/inputDriver/evdevDriver.py index f63cf3ff..1d91b85a 100644 --- a/src/fenrir/inputDriver/evdevDriver.py +++ b/src/fenrir/inputDriver/evdevDriver.py @@ -42,7 +42,7 @@ class driver(): time.sleep(0.008) # dont flood CPU return None event = None - r, w, x = select(self.iDevices, [], [], self.env['runtime']['settingsManager'].getSettingAsFloat('screen', 'screenUpdateDelay')) + r, w, x = select(self.iDevices, [], [], 0) if r != []: for fd in r: try: From 756d1d9b99984ef27bcca57dd5217fd5298371c3 Mon Sep 17 00:00:00 2001 From: Chrys Date: Wed, 21 Jun 2017 15:05:38 +0200 Subject: [PATCH 04/96] do some ajustments, and fix typos --- src/fenrir/commands/commands/quit_fenrir.py | 2 +- src/fenrir/core/eventManager.py | 18 +++++++++++------- src/fenrir/core/fenrirManager.py | 8 ++++---- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/fenrir/commands/commands/quit_fenrir.py b/src/fenrir/commands/commands/quit_fenrir.py index 2ddae36f..ea633658 100644 --- a/src/fenrir/commands/commands/quit_fenrir.py +++ b/src/fenrir/commands/commands/quit_fenrir.py @@ -17,7 +17,7 @@ class command(): return _('exits Fenrir') def run(self): - self.env['eventManager'].stopMainEventLoop() + self.env['runtime']['eventManager'].stopMainEventLoop() def setCallback(self, callback): pass diff --git a/src/fenrir/core/eventManager.py b/src/fenrir/core/eventManager.py index b6b0e006..ec34570e 100644 --- a/src/fenrir/core/eventManager.py +++ b/src/fenrir/core/eventManager.py @@ -41,7 +41,7 @@ class eventManager(): self.terminateAllProcesses() self.cleanEventQueue() def timerProcess(self): - time.sleep(0.005) + time.sleep(0.04) #self.env['runtime']['settingsManager'].getSettingAsFloat('screen', 'screenUpdateDelay') return time.time() def terminateAllProcesses(self): @@ -60,6 +60,7 @@ class eventManager(): return elif event['Type'] == fenrirEventType.StopMainLoop: self._mainLoopRunning.value = 0 + print('stop') return elif event['Type'] == fenrirEventType.ScreenUpdate: print('do an update') @@ -76,22 +77,25 @@ class eventManager(): pass elif event['Type'] == fenrirEventType.HeartBeat: self.env['runtime']['fenrirManager'].handleProcess() + print(self._eventQueue.qsize()) print('HeartBeat at ' + str(event['Type']) + ' ' +str(event['Data'] )) def startMainEventLoop(self): - self._mainLoopRunning.value = True - while(self._mainLoopRunning.value): + self._mainLoopRunning.value = 1 + while(self._mainLoopRunning.value == 1): + st = time.time() self.proceedEventLoop() + print('loop ' + str(time.time() - st)) def stopMainEventLoop(self, Force = False): if Force: - self._mainLoopRunning.value = False + self._mainLoopRunning.value = 0 self._eventQueue.put({"Type":fenrirEventType.StopMainLoop,"Data":None}) def addCustomEventThread(self, function): - self._mainLoopRunning.value = True + self._mainLoopRunning.value = 1 t = Process(target=self.eventWorkerThread, args=(q, function)) self._eventProcesses.append(t) t.start() def addSimpleEventThread(self, event, function): - self._mainLoopRunning.value = True + self._mainLoopRunning.value = 1 t = Process(target=self.simpleEventWorkerThread, args=(event, function)) self._eventProcesses.append(t) t.start() @@ -124,7 +128,7 @@ class eventManager(): return if not callable(function): return - while self._mainLoopRunning.value: + while self._mainLoopRunning.value == 1: Data = None try: Data = function() diff --git a/src/fenrir/core/fenrirManager.py b/src/fenrir/core/fenrirManager.py index e22d252e..e9a8a874 100644 --- a/src/fenrir/core/fenrirManager.py +++ b/src/fenrir/core/fenrirManager.py @@ -109,16 +109,16 @@ class fenrirManager(): self.environment['runtime']['commandManager'].executeCommand( self.environment['commandInfo']['currCommand'], 'commands') def shutdownRequest(self): - self.environment['eventManager'].stopMainEventLoop() + self.environment['runtime']['eventManager'].stopMainEventLoop() def captureSignal(self, siginit, frame): self.shutdownRequest() def shutdown(self): - self.environment['eventManager'].stopMainEventLoop() + self.environment['runtime']['eventManager'].stopMainEventLoop() self.environment['runtime']['outputManager'].presentText(_("Quit Fenrir"), soundIcon='ScreenReaderOff', interrupt=True) - self.environment['eventManager'].cleanEventQueue() - self.environment['eventManager'].stopMainEventLoop(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() From 900d7c9178921ee5e06df2527bb0786fb2757d8f Mon Sep 17 00:00:00 2001 From: Chrys Date: Wed, 21 Jun 2017 15:10:11 +0200 Subject: [PATCH 05/96] adjust --- src/fenrir/core/eventManager.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/fenrir/core/eventManager.py b/src/fenrir/core/eventManager.py index ec34570e..532b7408 100644 --- a/src/fenrir/core/eventManager.py +++ b/src/fenrir/core/eventManager.py @@ -41,7 +41,7 @@ class eventManager(): self.terminateAllProcesses() self.cleanEventQueue() def timerProcess(self): - time.sleep(0.04) + time.sleep(0.03) #self.env['runtime']['settingsManager'].getSettingAsFloat('screen', 'screenUpdateDelay') return time.time() def terminateAllProcesses(self): @@ -133,7 +133,8 @@ class eventManager(): try: Data = function() except Exception as e: - print(e) + pass + #print(e) self.putToEventQueue(event, Data) if runOnce: break From 42ade1fbf8f7241db11c81aebc9e29d1fc8a4634 Mon Sep 17 00:00:00 2001 From: chrys Date: Thu, 22 Jun 2017 00:04:07 +0200 Subject: [PATCH 06/96] add VCSA watchdog prototype --- play zone/epollScreen.py | 41 +++++++++++++++++++++++++++++++++ src/fenrir/core/eventManager.py | 10 ++++++-- 2 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 play zone/epollScreen.py diff --git a/play zone/epollScreen.py b/play zone/epollScreen.py new file mode 100644 index 00000000..c9f47caf --- /dev/null +++ b/play zone/epollScreen.py @@ -0,0 +1,41 @@ +#!/bin/python + +import select +import time + +vcsa = {} +for i in range(1,7): + vcsa[str(i)] = open('/dev/vcs'+str(i),'rb') + vcsa[str(i)].read() + +tty = open('/sys/devices/virtual/tty/tty0/active','r') + +oldTty = str(tty.read()[3:-1]) +watchdog = select.poll() +watchdog.register(tty, select.EPOLLPRI) +watchdog.register(vcsa[ oldTty ], select.EPOLLPRI) + +while True: + changed = watchdog.poll() + print('-----------------------------') + print(changed,tty.fileno()) + for fileno, event in changed: + if tty.fileno() == fileno: + currTty = tty.seek(0) + #b = open('/sys/devices/virtual/tty/tty0/active','r') + currTty = str(tty.read()[3:-1]) + print('|'+currTty+'|'+oldTty+'|') + if currTty != oldTty: + watchdog.register(vcsa[ currTty ].fileno(), select.EPOLLPRI) + watchdog.unregister(vcsa[ oldTty ].fileno()) + oldTty = currTty + print('new screen ' + currTty) + else: + print('update '+ currTty + ' ' + str(fileno)) + vcsa[currTty].seek(0) + b = vcsa[currTty].read() + #print(b) + time.sleep(0.5) + + + diff --git a/src/fenrir/core/eventManager.py b/src/fenrir/core/eventManager.py index 532b7408..a9a60e12 100644 --- a/src/fenrir/core/eventManager.py +++ b/src/fenrir/core/eventManager.py @@ -41,10 +41,14 @@ class eventManager(): self.terminateAllProcesses() self.cleanEventQueue() def timerProcess(self): - time.sleep(0.03) + try: + time.sleep(0.03) + 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() @@ -52,7 +56,9 @@ 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): if not event: return @@ -84,7 +90,7 @@ class eventManager(): while(self._mainLoopRunning.value == 1): st = time.time() self.proceedEventLoop() - print('loop ' + str(time.time() - st)) + print('ALL loop ' + str(time.time() - st)) def stopMainEventLoop(self, Force = False): if Force: self._mainLoopRunning.value = 0 From b0604a9907cf7dc40ef87517003074eb66adda2b Mon Sep 17 00:00:00 2001 From: chrys Date: Thu, 22 Jun 2017 01:27:31 +0200 Subject: [PATCH 07/96] add VCSA watchdog prototype --- play zone/epollScreen.py | 50 ++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/play zone/epollScreen.py b/play zone/epollScreen.py index c9f47caf..cf406113 100644 --- a/play zone/epollScreen.py +++ b/play zone/epollScreen.py @@ -3,39 +3,35 @@ import select import time +currScreen = '2' vcsa = {} for i in range(1,7): vcsa[str(i)] = open('/dev/vcs'+str(i),'rb') - vcsa[str(i)].read() tty = open('/sys/devices/virtual/tty/tty0/active','r') - -oldTty = str(tty.read()[3:-1]) -watchdog = select.poll() +currScreen = str(tty.read()[3:-1]) +oldScreen = currScreen +watchdog = select.epoll() +watchdog.register(vcsa[currScreen], select.EPOLLPRI) watchdog.register(tty, select.EPOLLPRI) -watchdog.register(vcsa[ oldTty ], select.EPOLLPRI) - + while True: - changed = watchdog.poll() + changes = watchdog.poll() print('-----------------------------') - print(changed,tty.fileno()) - for fileno, event in changed: - if tty.fileno() == fileno: - currTty = tty.seek(0) - #b = open('/sys/devices/virtual/tty/tty0/active','r') - currTty = str(tty.read()[3:-1]) - print('|'+currTty+'|'+oldTty+'|') - if currTty != oldTty: - watchdog.register(vcsa[ currTty ].fileno(), select.EPOLLPRI) - watchdog.unregister(vcsa[ oldTty ].fileno()) - oldTty = currTty - print('new screen ' + currTty) + print(changes) + for change in changes: + fileno = change[0] + event = change[1] + print(change,fileno, tty.fileno()) + if fileno == tty.fileno(): + tty.seek(0) + currScreen = str(tty.read()[3:-1]) + if currScreen != oldScreen: + watchdog.unregister(vcsa[ oldScreen ]) + watchdog.register(vcsa[ currScreen ], select.EPOLLPRI) + oldScreen = currScreen + print('new screen '+ currScreen) else: - print('update '+ currTty + ' ' + str(fileno)) - vcsa[currTty].seek(0) - b = vcsa[currTty].read() - #print(b) - time.sleep(0.5) - - - + vcsa[currScreen].seek(0) + content = vcsa[currScreen].read() + print('update '+ str(time.time())) From a476e730c4c26edd3302c4d2ebb462d88d6a0131 Mon Sep 17 00:00:00 2001 From: chrys Date: Thu, 22 Jun 2017 15:08:15 +0200 Subject: [PATCH 08/96] initial watchdog for VCSA driver --- src/fenrir/core/eventData.py | 23 +++++++++ src/fenrir/core/eventManager.py | 67 +++++++++------------------ src/fenrir/screenDriver/vcsaDriver.py | 40 ++++++++++++++++ 3 files changed, 84 insertions(+), 46 deletions(-) create mode 100755 src/fenrir/core/eventData.py diff --git a/src/fenrir/core/eventData.py b/src/fenrir/core/eventData.py new file mode 100755 index 00000000..c9592c98 --- /dev/null +++ b/src/fenrir/core/eventData.py @@ -0,0 +1,23 @@ +#!/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 + def __int__(self): + return self.value + def __str__(self): + return self.name diff --git a/src/fenrir/core/eventManager.py b/src/fenrir/core/eventManager.py index a9a60e12..86dbcf0b 100644 --- a/src/fenrir/core/eventManager.py +++ b/src/fenrir/core/eventManager.py @@ -5,29 +5,13 @@ # By Chrys, Storm Dragon, and contributers. 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 - HeartBeat = 8 # for time based scheduling - def __int__(self): - return self.value - def __str__(self): - return self.name - - class eventManager(): def __init__(self): self._mainLoopRunning = Value(c_bool, True) @@ -42,7 +26,7 @@ class eventManager(): self.cleanEventQueue() def timerProcess(self): try: - time.sleep(0.03) + time.sleep(1.3) except: pass #self.env['runtime']['settingsManager'].getSettingAsFloat('screen', 'screenUpdateDelay') @@ -69,10 +53,13 @@ class eventManager(): print('stop') return elif event['Type'] == fenrirEventType.ScreenUpdate: - print('do an update') - pass + self.env['runtime']['fenrirManager'].handleProcess() + print(self._eventQueue.qsize()) + print('ScreenUpdate') elif event['Type'] == fenrirEventType.KeyboardInput: - pass + self.env['runtime']['fenrirManager'].handleProcess() + print(self._eventQueue.qsize()) + print('KeyboardInput') elif event['Type'] == fenrirEventType.BrailleInput: pass elif event['Type'] == fenrirEventType.PlugInputDevice: @@ -80,14 +67,19 @@ class eventManager(): elif event['Type'] == fenrirEventType.BrailleFlush: pass elif event['Type'] == fenrirEventType.ScreenChanged: - pass + self.env['runtime']['fenrirManager'].handleProcess() + print(self._eventQueue.qsize()) + print('ScreenChanged') elif event['Type'] == fenrirEventType.HeartBeat: self.env['runtime']['fenrirManager'].handleProcess() print(self._eventQueue.qsize()) - print('HeartBeat at ' + str(event['Type']) + ' ' +str(event['Data'] )) + print('HeartBeat at {0} {1}'.format(event['Type'], event['Data'] )) + + def isMainEventLoopRunning(self): + return self._mainLoopRunning.value == 1 def startMainEventLoop(self): self._mainLoopRunning.value = 1 - while(self._mainLoopRunning.value == 1): + while( self.isMainEventLoopRunning()): st = time.time() self.proceedEventLoop() print('ALL loop ' + str(time.time() - st)) @@ -97,7 +89,7 @@ class eventManager(): self._eventQueue.put({"Type":fenrirEventType.StopMainLoop,"Data":None}) def addCustomEventThread(self, function): self._mainLoopRunning.value = 1 - t = Process(target=self.eventWorkerThread, args=(q, function)) + t = Process(target=self.customEventWorkerThread, args=(self._eventQueue, function)) self._eventProcesses.append(t) t.start() def addSimpleEventThread(self, event, function): @@ -119,11 +111,11 @@ class eventManager(): self._eventQueue.put({"Type":event,"Data":data}) return True def customEventWorkerThread(self, eventQueue, function): - if not isinstance(eventQueue, Queue): - return + #if not isinstance(eventQueue, Queue): + # return if not callable(function): return - while self._mainLoopRunning.value: + while self.isMainEventLoopRunning(): try: function(eventQueue) except Exception as e: @@ -134,7 +126,7 @@ class eventManager(): return if not callable(function): return - while self._mainLoopRunning.value == 1: + while self.isMainEventLoopRunning(): Data = None try: Data = function() @@ -144,20 +136,3 @@ class eventManager(): self.putToEventQueue(event, Data) if runOnce: break -''' -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 ) -''' diff --git a/src/fenrir/screenDriver/vcsaDriver.py b/src/fenrir/screenDriver/vcsaDriver.py index 45f800db..05f8d927 100644 --- a/src/fenrir/screenDriver/vcsaDriver.py +++ b/src/fenrir/screenDriver/vcsaDriver.py @@ -10,8 +10,10 @@ import subprocess import fcntl import termios import time +import select import dbus from core import debug +from core.eventData import fenrirEventType from utils import screen_utils class driver(): @@ -20,6 +22,7 @@ class driver(): self.ListSessions = None def initialize(self, environment): self.env = environment + self.env['runtime']['eventManager'].addCustomEventThread(self.updateWatchdog) def shutdown(self): pass def getCurrScreen(self): @@ -93,7 +96,44 @@ class driver(): except Exception as e: self.env['runtime']['debug'].writeDebugOut('getSessionInformation: Maybe no LoginD:' + str(e),debug.debugLevel.ERROR) self.env['screen']['autoIgnoreScreens'] = [] + + def updateWatchdog(self,eventQueue): + print('init updateWatchdog') + currScreen = '2' + vcsa = {} + for i in range(1,7): + vcsa[str(i)] = open('/dev/vcsa'+str(i),'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) + + while True: + changes = watchdog.poll() + print('-----------------------------') + print(changes) + for change in changes: + fileno = change[0] + event = change[1] + print(change,fileno, tty.fileno()) + if fileno == tty.fileno(): + tty.seek(0) + currScreen = str(tty.read()[3:-1]) + if currScreen != oldScreen: + watchdog.unregister(vcsa[ oldScreen ]) + watchdog.register(vcsa[ currScreen ], select.EPOLLPRI) + oldScreen = currScreen + eventQueue.put({"Type":fenrirEventType.ScreenChanged,"Data":''}) + print('new screen '+ currScreen) + else: + vcsa[currScreen].seek(0) + content = vcsa[currScreen].read() + eventQueue.put({"Type":fenrirEventType.ScreenUpdate,"Data":''}) + print('update '+ str(time.time())) + def update(self, trigger='onUpdate'): newContentBytes = b'' try: From b822d39b9ac373e9b91b35ee74a19fa1a8480635 Mon Sep 17 00:00:00 2001 From: chrys Date: Fri, 23 Jun 2017 02:15:59 +0200 Subject: [PATCH 09/96] add experimental watchdog for input driver --- src/fenrir/core/eventManager.py | 39 ++++++++++++++++++--------- src/fenrir/inputDriver/evdevDriver.py | 24 ++++++++++++++--- src/fenrir/screenDriver/vcsaDriver.py | 2 +- 3 files changed, 49 insertions(+), 16 deletions(-) diff --git a/src/fenrir/core/eventManager.py b/src/fenrir/core/eventManager.py index 86dbcf0b..74ea9857 100644 --- a/src/fenrir/core/eventManager.py +++ b/src/fenrir/core/eventManager.py @@ -20,13 +20,14 @@ class eventManager(): self.cleanEventQueue() def initialize(self, environment): self.env = environment - self.addSimpleEventThread(fenrirEventType.HeartBeat, self.timerProcess) + self.addSimpleEventThread(fenrirEventType.HeartBeat, self.heartBeatTimer) def shutdown(self): self.terminateAllProcesses() self.cleanEventQueue() - def timerProcess(self): + def heartBeatTimer(self): try: - time.sleep(1.3) + time.sleep(0.3) + print('bin auch da') except: pass #self.env['runtime']['settingsManager'].getSettingAsFloat('screen', 'screenUpdateDelay') @@ -87,14 +88,21 @@ class eventManager(): if Force: self._mainLoopRunning.value = 0 self._eventQueue.put({"Type":fenrirEventType.StopMainLoop,"Data":None}) - def addCustomEventThread(self, function): + def addCustomEventThread(self, function, pargs = None, multiprocess=False): self._mainLoopRunning.value = 1 - t = Process(target=self.customEventWorkerThread, args=(self._eventQueue, function)) + + 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): + def addSimpleEventThread(self, event, function, pargs = None, multiprocess=False, runOnce = False): self._mainLoopRunning.value = 1 - t = Process(target=self.simpleEventWorkerThread, args=(event, function)) + if multiprocess: + t = Process(target=self.simpleEventWorkerThread, args=(event, function, pargs)) + else:# thread not implemented yet + t = Process(target=self.simpleEventWorkerThread, args=(event, function, pargs)) self._eventProcesses.append(t) t.start() def cleanEventQueue(self): @@ -110,18 +118,21 @@ class eventManager(): return False self._eventQueue.put({"Type":event,"Data":data}) return True - def customEventWorkerThread(self, eventQueue, function): + def customEventWorkerThread(self, eventQueue, function, args): #if not isinstance(eventQueue, Queue): # return if not callable(function): return while self.isMainEventLoopRunning(): try: - function(eventQueue) + if args: + function(eventQueue, args) + else: + function(eventQueue) except Exception as e: print(e) - def simpleEventWorkerThread(self, event, function, runOnce = False): + def simpleEventWorkerThread(self, event, function, args, runOnce = False): if not isinstance(event, fenrirEventType): return if not callable(function): @@ -129,10 +140,14 @@ class eventManager(): while self.isMainEventLoopRunning(): Data = None try: - Data = function() + if args != None: + Data = function(args) + else: + Data = function() except Exception as e: pass - #print(e) + print(e) self.putToEventQueue(event, Data) + print('jo') if runOnce: break diff --git a/src/fenrir/inputDriver/evdevDriver.py b/src/fenrir/inputDriver/evdevDriver.py index 1d91b85a..fb7a4662 100644 --- a/src/fenrir/inputDriver/evdevDriver.py +++ b/src/fenrir/inputDriver/evdevDriver.py @@ -15,12 +15,16 @@ except Exception as e: import time from select import select +import multiprocessing +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 @@ -33,16 +37,24 @@ class driver(): global _evdevAvailableError self.env['runtime']['debug'].writeDebugOut('InputDriver: ' + _evdevAvailableError,debug.debugLevel.ERROR) return - + self.updateInputDevices() + self.env['runtime']['eventManager'].addSimpleEventThread(fenrirEventType.KeyboardInput, self.inputWatchdog, self.iDevicesFD) def shutdown(self): if not self._initialized: - return + return + def inputWatchdog(self, iDevicesFD): + deviceFd = [] + for fd in iDevicesFD: + deviceFd.append(fd) + print('select', deviceFd, iDevicesFD) + r, w, x = select(deviceFd, [], [], 3) + time.sleep(0.1) def getInputEvent(self): if not self.hasIDevices(): time.sleep(0.008) # dont flood CPU return None event = None - r, w, x = select(self.iDevices, [], [], 0) + r, w, x = select(self.iDevices, [], [], 0.0001) if r != []: for fd in r: try: @@ -145,6 +157,12 @@ 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 + print(self.iDevicesFD[:]) self.iDeviceNo = len(evdev.list_devices()) def mapEvent(self, event): diff --git a/src/fenrir/screenDriver/vcsaDriver.py b/src/fenrir/screenDriver/vcsaDriver.py index 05f8d927..d2b5e57f 100644 --- a/src/fenrir/screenDriver/vcsaDriver.py +++ b/src/fenrir/screenDriver/vcsaDriver.py @@ -98,7 +98,7 @@ class driver(): self.env['screen']['autoIgnoreScreens'] = [] def updateWatchdog(self,eventQueue): - print('init updateWatchdog') + print('init VCSA updateWatchdog') currScreen = '2' vcsa = {} for i in range(1,7): From 3037ad36e0d9c86f0fd9f2d2d86d9c60bba12bc6 Mon Sep 17 00:00:00 2001 From: chrys Date: Fri, 23 Jun 2017 02:46:16 +0200 Subject: [PATCH 10/96] sync select in evdev --- src/fenrir/inputDriver/evdevDriver.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/fenrir/inputDriver/evdevDriver.py b/src/fenrir/inputDriver/evdevDriver.py index fb7a4662..32cdc7b3 100644 --- a/src/fenrir/inputDriver/evdevDriver.py +++ b/src/fenrir/inputDriver/evdevDriver.py @@ -16,10 +16,14 @@ except Exception as 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() @@ -28,7 +32,7 @@ class driver(): self.uDevices = {} self.iDeviceNo = 0 self._initialized = False - + self.watchDog = Value(c_bool, True) def initialize(self, environment): self.env = environment global _evdevAvailable @@ -38,7 +42,7 @@ class driver(): self.env['runtime']['debug'].writeDebugOut('InputDriver: ' + _evdevAvailableError,debug.debugLevel.ERROR) return self.updateInputDevices() - self.env['runtime']['eventManager'].addSimpleEventThread(fenrirEventType.KeyboardInput, self.inputWatchdog, self.iDevicesFD) + self.env['runtime']['eventManager'].addSimpleEventThread(fenrirEventType.KeyboardInput, self.inputWatchdog, {'dev':self.iDevicesFD, 'syn':self.watchDog}) def shutdown(self): if not self._initialized: return @@ -46,12 +50,14 @@ class driver(): deviceFd = [] for fd in iDevicesFD: deviceFd.append(fd) - print('select', deviceFd, iDevicesFD) - r, w, x = select(deviceFd, [], [], 3) - time.sleep(0.1) + while self.watchDog.value == 1: + time.sleep(0.01) + r, w, x = select(deviceFd, [], [], 3) + 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, [], [], 0.0001) @@ -61,6 +67,7 @@ class driver(): event = self.iDevices[fd].read_one() except: self.removeDevice(fd) + self.watchDog.value = 1 return None foreward = False while(event): @@ -78,6 +85,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]: @@ -85,7 +93,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): From 72057cda0e5e9a342a7f16f7fa369e917d704310 Mon Sep 17 00:00:00 2001 From: chrys Date: Sat, 24 Jun 2017 00:36:56 +0200 Subject: [PATCH 11/96] imporove performance --- src/fenrir/core/eventManager.py | 9 ++++----- src/fenrir/inputDriver/evdevDriver.py | 9 ++++----- src/fenrir/screenDriver/vcsaDriver.py | 17 ++++++++--------- 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/fenrir/core/eventManager.py b/src/fenrir/core/eventManager.py index 74ea9857..06713687 100644 --- a/src/fenrir/core/eventManager.py +++ b/src/fenrir/core/eventManager.py @@ -26,8 +26,7 @@ class eventManager(): self.cleanEventQueue() def heartBeatTimer(self): try: - time.sleep(0.3) - print('bin auch da') + time.sleep(8) except: pass #self.env['runtime']['settingsManager'].getSettingAsFloat('screen', 'screenUpdateDelay') @@ -43,8 +42,9 @@ class eventManager(): event = self._eventQueue.get() st = time.time() self.eventDispatcher(event) - print('NET loop ' + str(time.time() - st)) + #print('NET loop ' + str(time.time() - st)) def eventDispatcher(self, event): + print(event['Type']) if not event: return if event['Type'] == fenrirEventType.Ignore: @@ -83,7 +83,7 @@ class eventManager(): while( self.isMainEventLoopRunning()): st = time.time() self.proceedEventLoop() - print('ALL loop ' + str(time.time() - st)) + #print('ALL loop ' + str(time.time() - st)) def stopMainEventLoop(self, Force = False): if Force: self._mainLoopRunning.value = 0 @@ -148,6 +148,5 @@ class eventManager(): pass print(e) self.putToEventQueue(event, Data) - print('jo') if runOnce: break diff --git a/src/fenrir/inputDriver/evdevDriver.py b/src/fenrir/inputDriver/evdevDriver.py index 32cdc7b3..82b7db93 100644 --- a/src/fenrir/inputDriver/evdevDriver.py +++ b/src/fenrir/inputDriver/evdevDriver.py @@ -42,15 +42,15 @@ class driver(): self.env['runtime']['debug'].writeDebugOut('InputDriver: ' + _evdevAvailableError,debug.debugLevel.ERROR) return self.updateInputDevices() - self.env['runtime']['eventManager'].addSimpleEventThread(fenrirEventType.KeyboardInput, self.inputWatchdog, {'dev':self.iDevicesFD, 'syn':self.watchDog}) + self.env['runtime']['eventManager'].addSimpleEventThread(fenrirEventType.KeyboardInput, self.inputWatchdog, {'dev':self.iDevicesFD}) def shutdown(self): if not self._initialized: return def inputWatchdog(self, iDevicesFD): deviceFd = [] - for fd in iDevicesFD: + for fd in iDevicesFD['dev']: deviceFd.append(fd) - while self.watchDog.value == 1: + while self.watchDog.value == 0: time.sleep(0.01) r, w, x = select(deviceFd, [], [], 3) self.watchDog.value = 0 @@ -170,8 +170,7 @@ class driver(): i = 0 for fd in self.iDevices: self.iDevicesFD[i] = fd - i +=1 - print(self.iDevicesFD[:]) + i +=1 self.iDeviceNo = len(evdev.list_devices()) def mapEvent(self, event): diff --git a/src/fenrir/screenDriver/vcsaDriver.py b/src/fenrir/screenDriver/vcsaDriver.py index d2b5e57f..2da4297c 100644 --- a/src/fenrir/screenDriver/vcsaDriver.py +++ b/src/fenrir/screenDriver/vcsaDriver.py @@ -110,15 +110,13 @@ class driver(): watchdog = select.epoll() watchdog.register(vcsa[currScreen], select.EPOLLPRI) watchdog.register(tty, select.EPOLLPRI) - + lastChange = 0 while True: - changes = watchdog.poll() - print('-----------------------------') - print(changes) + + changes = watchdog.poll(3) for change in changes: fileno = change[0] event = change[1] - print(change,fileno, tty.fileno()) if fileno == tty.fileno(): tty.seek(0) currScreen = str(tty.read()[3:-1]) @@ -126,13 +124,14 @@ class driver(): watchdog.unregister(vcsa[ oldScreen ]) watchdog.register(vcsa[ currScreen ], select.EPOLLPRI) oldScreen = currScreen - eventQueue.put({"Type":fenrirEventType.ScreenChanged,"Data":''}) - print('new screen '+ currScreen) + eventQueue.put({"Type":fenrirEventType.ScreenChanged,"Data":''}) else: vcsa[currScreen].seek(0) content = vcsa[currScreen].read() - eventQueue.put({"Type":fenrirEventType.ScreenUpdate,"Data":''}) - print('update '+ str(time.time())) + print(time.time(), lastChange) + if time.time() - lastChange > 0.1: + eventQueue.put({"Type":fenrirEventType.ScreenUpdate,"Data":''}) + lastChange = time.time() def update(self, trigger='onUpdate'): newContentBytes = b'' From 68c6ec0cc472aad2cdfa024851268b4e3c79c661 Mon Sep 17 00:00:00 2001 From: chrys Date: Sat, 24 Jun 2017 00:45:10 +0200 Subject: [PATCH 12/96] update ToDo list --- TODO v2.0 | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/TODO v2.0 b/TODO v2.0 index d0c4607f..3064cf2e 100644 --- a/TODO v2.0 +++ b/TODO v2.0 @@ -4,20 +4,24 @@ Things with not so deep knowledge needed are marekd wiht "(Easy for contribution General: - implement onScreenUpdate commands read highlighted text mode -- try to make it more asynchronus with multpible threads +- try to make it more asynchronus with multpible threads (DONE) - be more event based (vcsa sets POLLPRI) http://scotdoyle.com/python-epoll-howto.html Needed events: - screen update (vcsa sets POLLPRI) + screen update (vcsa sets POLLPRI) (DONE) plug input device (udev event) - screen changed (logind event, collides with screen update) - keyboard input (select, wait forever) + screen changed (logind event, collides with screen update) (DONE) + keyboard input (select, wait forever) (DONE) braille input (brlapi_readKey) - braille flush (timer, sleep) - Each event is watched in an own thread. This improves performance and reduce the load. - The event loop is to be done as "queue" since those are thread safe. - The threads are reading incomming data and add the events and data to the queue - the mainloop just reads the queue in an blocking way and executes the needed codepath with the data. + braille flush (timer, sleep) (DONE) + Each event is watched in an own thread. This improves performance and reduce the load. (DONE) + The event loop is to be done as "queue" since those are thread safe. (DONE) + The threads are reading incomming data and add the events and data to the queue (DONE) + the mainloop just reads the queue in an blocking way and executes the needed codepath with the data. (DONE) + clean up the code for the events so that just the correct codepath is used: + - screen + - input + - new device - leave review on typing - implement commands From aa618cc8f5059d0b80262cb22a455fce294ce3e2 Mon Sep 17 00:00:00 2001 From: chrys Date: Sun, 25 Jun 2017 15:32:47 +0200 Subject: [PATCH 13/96] add different code paths for events; split up mainloop; --- .../commands/onScreenUpdate/76000-time.py | 74 ------------------- .../onScreenUpdate/deactive/70000-incoming.py | 36 --------- src/fenrir/core/eventManager.py | 22 +++--- src/fenrir/core/fenrirManager.py | 45 ++++++----- src/fenrir/inputDriver/evdevDriver.py | 6 +- src/fenrir/screenDriver/vcsaDriver.py | 22 +++--- 6 files changed, 57 insertions(+), 148 deletions(-) delete mode 100644 src/fenrir/commands/onScreenUpdate/76000-time.py delete mode 100644 src/fenrir/commands/onScreenUpdate/deactive/70000-incoming.py diff --git a/src/fenrir/commands/onScreenUpdate/76000-time.py b/src/fenrir/commands/onScreenUpdate/76000-time.py deleted file mode 100644 index 3b9b55b6..00000000 --- a/src/fenrir/commands/onScreenUpdate/76000-time.py +++ /dev/null @@ -1,74 +0,0 @@ -#!/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): - if not self.env['runtime']['settingsManager'].getSettingAsBool('time', 'enabled'): - return - onMinutes = self.env['runtime']['settingsManager'].getSetting('time', 'onMinutes') - delaySec = self.env['runtime']['settingsManager'].getSettingAsInt('time', 'delaySec') - # no need - if onMinutes == '' and delaySec <= 0: - return - onMinutes = onMinutes.split(',') - now = datetime.datetime.now() - # ignore onMinutes if there is a delaySec - if delaySec > 0: - if int((now-self.lastTime).total_seconds()) < delaySec: - return - else: - # shoul announce? - if not str(now.minute) in onMinutes: - return - # already announced? - if now.hour == self.lastTime.hour: - if now.minute == self.lastTime.minute: - return - dateFormat = self.env['runtime']['settingsManager'].getSetting('general', 'dateFormat') - dateString = datetime.datetime.strftime(now, dateFormat) - - presentDate = self.env['runtime']['settingsManager'].getSettingAsBool('time', 'presentDate') and \ - self.lastDateString != dateString - presentTime = self.env['runtime']['settingsManager'].getSettingAsBool('time', 'presentTime') - # no changed value to announce - if not (presentDate or presentTime): - return - timeFormat = self.env['runtime']['settingsManager'].getSetting('general', 'timeFormat') - timeString = datetime.datetime.strftime(now, timeFormat) - - if self.env['runtime']['settingsManager'].getSettingAsBool('time', 'interrupt'): - self.env['runtime']['outputManager'].interruptOutput() - if self.env['runtime']['settingsManager'].getSettingAsBool('time', 'announce'): - self.env['runtime']['outputManager'].playSoundIcon('announce') - - if presentTime: - # present the time - self.env['runtime']['outputManager'].presentText(_('Autotime: {0}').format(timeString), soundIcon='', interrupt=False) - # and date if changes - if presentDate: - self.env['runtime']['outputManager'].presentText(dateString , soundIcon='', interrupt=False) - self.lastDateString = dateString - self.lastTime = datetime.datetime.now() - self.lastTimeString = timeString - def setCallback(self, callback): - pass diff --git a/src/fenrir/commands/onScreenUpdate/deactive/70000-incoming.py b/src/fenrir/commands/onScreenUpdate/deactive/70000-incoming.py deleted file mode 100644 index 1b3ebae0..00000000 --- a/src/fenrir/commands/onScreenUpdate/deactive/70000-incoming.py +++ /dev/null @@ -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 - diff --git a/src/fenrir/core/eventManager.py b/src/fenrir/core/eventManager.py index 06713687..e27778bb 100644 --- a/src/fenrir/core/eventManager.py +++ b/src/fenrir/core/eventManager.py @@ -26,7 +26,7 @@ class eventManager(): self.cleanEventQueue() def heartBeatTimer(self): try: - time.sleep(8) + time.sleep(0.5) except: pass #self.env['runtime']['settingsManager'].getSettingAsFloat('screen', 'screenUpdateDelay') @@ -50,15 +50,15 @@ class eventManager(): if event['Type'] == fenrirEventType.Ignore: return elif event['Type'] == fenrirEventType.StopMainLoop: - self._mainLoopRunning.value = 0 + self.handleStopMainLoop() print('stop') return elif event['Type'] == fenrirEventType.ScreenUpdate: - self.env['runtime']['fenrirManager'].handleProcess() + self.env['runtime']['fenrirManager'].handleScreenUpdate() print(self._eventQueue.qsize()) print('ScreenUpdate') elif event['Type'] == fenrirEventType.KeyboardInput: - self.env['runtime']['fenrirManager'].handleProcess() + self.env['runtime']['fenrirManager'].handleInput() print(self._eventQueue.qsize()) print('KeyboardInput') elif event['Type'] == fenrirEventType.BrailleInput: @@ -68,11 +68,12 @@ class eventManager(): elif event['Type'] == fenrirEventType.BrailleFlush: pass elif event['Type'] == fenrirEventType.ScreenChanged: - self.env['runtime']['fenrirManager'].handleProcess() + self.env['runtime']['fenrirManager'].handleScreenChange() print(self._eventQueue.qsize()) print('ScreenChanged') elif event['Type'] == fenrirEventType.HeartBeat: - self.env['runtime']['fenrirManager'].handleProcess() + # run timer actions + #self.env['runtime']['fenrirManager'].handleProcess() print(self._eventQueue.qsize()) print('HeartBeat at {0} {1}'.format(event['Type'], event['Data'] )) @@ -84,6 +85,9 @@ class eventManager(): st = time.time() self.proceedEventLoop() #print('ALL loop ' + str(time.time() - st)) + def handleStopMainLoop(self): + self._mainLoopRunning.value = 0 + time.sleep(3.5) def stopMainEventLoop(self, Force = False): if Force: self._mainLoopRunning.value = 0 @@ -126,9 +130,9 @@ class eventManager(): while self.isMainEventLoopRunning(): try: if args: - function(eventQueue, args) + function(self._mainLoopRunning, eventQueue, args) else: - function(eventQueue) + function(self._mainLoopRunning, eventQueue) except Exception as e: print(e) @@ -141,7 +145,7 @@ class eventManager(): Data = None try: if args != None: - Data = function(args) + Data = function(self._mainLoopRunning, args) else: Data = function() except Exception as e: diff --git a/src/fenrir/core/fenrirManager.py b/src/fenrir/core/fenrirManager.py index e9a8a874..2e291a55 100644 --- a/src/fenrir/core/fenrirManager.py +++ b/src/fenrir/core/fenrirManager.py @@ -47,15 +47,10 @@ class fenrirManager(): if not self.initialized: return self.environment['runtime']['eventManager'].startMainEventLoop() - self.shutdown() - - def handleProcess(self): + def handleInput(self): eventReceived = self.environment['runtime']['inputManager'].getInputEvent() - startTime = time.time() - if not eventReceived: - if not self.environment['runtime']['screenManager'].isSuspendingScreen(): - self.environment['runtime']['inputManager'].updateInputDevices() + startTime = time.time() if eventReceived: self.prepareCommand() if not (self.wasCommand or self.environment['general']['tutorialMode']) or self.environment['runtime']['screenManager'].isSuspendingScreen(): @@ -69,23 +64,39 @@ class fenrirManager(): 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') + self.handleCommands() + def handleScreenChange(self): + 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()) - if self.environment['runtime']['screenManager'].isScreenChange(): + if not 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) - + + def handleScreenUpdate(self): + 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()) + + if not self.environment['runtime']['screenManager'].isScreenChange(): + self.environment['runtime']['commandManager'].executeDefaultTrigger('onScreenUpdate') + def handlePlugInputDevice(self): + if not self.environment['runtime']['screenManager'].isSuspendingScreen(): # remove if all works + self.environment['runtime']['inputManager'].updateInputDevices() + def handleHeartBeat(self): + self.environment['runtime']['commandManager'].executeDefaultTrigger('onHeartBeat') + self.handlePlugInputDevice() + #self.environment['runtime']['outputManager'].brailleText(flush=False) + def prepareCommand(self): if self.environment['runtime']['screenManager'].isSuspendingScreen(): self.wasCommand = False diff --git a/src/fenrir/inputDriver/evdevDriver.py b/src/fenrir/inputDriver/evdevDriver.py index 82b7db93..de6d7b0d 100644 --- a/src/fenrir/inputDriver/evdevDriver.py +++ b/src/fenrir/inputDriver/evdevDriver.py @@ -46,13 +46,15 @@ class driver(): def shutdown(self): if not self._initialized: return - def inputWatchdog(self, iDevicesFD): + def inputWatchdog(self,active , iDevicesFD): deviceFd = [] for fd in iDevicesFD['dev']: deviceFd.append(fd) while self.watchDog.value == 0: + if active.value == 0: + return time.sleep(0.01) - r, w, x = select(deviceFd, [], [], 3) + r, w, x = select(deviceFd, [], [], 2) self.watchDog.value = 0 def getInputEvent(self): if not self.hasIDevices(): diff --git a/src/fenrir/screenDriver/vcsaDriver.py b/src/fenrir/screenDriver/vcsaDriver.py index 2da4297c..328d90e4 100644 --- a/src/fenrir/screenDriver/vcsaDriver.py +++ b/src/fenrir/screenDriver/vcsaDriver.py @@ -97,7 +97,7 @@ class driver(): self.env['runtime']['debug'].writeDebugOut('getSessionInformation: Maybe no LoginD:' + str(e),debug.debugLevel.ERROR) self.env['screen']['autoIgnoreScreens'] = [] - def updateWatchdog(self,eventQueue): + def updateWatchdog(self,active , eventQueue): print('init VCSA updateWatchdog') currScreen = '2' vcsa = {} @@ -110,10 +110,9 @@ class driver(): watchdog = select.epoll() watchdog.register(vcsa[currScreen], select.EPOLLPRI) watchdog.register(tty, select.EPOLLPRI) - lastChange = 0 - while True: - - changes = watchdog.poll(3) + lastScreenContent = b'' + while active.value == 1: + changes = watchdog.poll(2) for change in changes: fileno = change[0] event = change[1] @@ -124,16 +123,19 @@ class driver(): watchdog.unregister(vcsa[ oldScreen ]) watchdog.register(vcsa[ currScreen ], select.EPOLLPRI) oldScreen = currScreen - eventQueue.put({"Type":fenrirEventType.ScreenChanged,"Data":''}) + eventQueue.put({"Type":fenrirEventType.ScreenChanged,"Data":''}) + vcsa[currScreen].seek(0) + lastScreenContent = vcsa[currScreen].read() else: vcsa[currScreen].seek(0) - content = vcsa[currScreen].read() - print(time.time(), lastChange) - if time.time() - lastChange > 0.1: + screenContent = vcsa[currScreen].read() + if screenContent != lastScreenContent: eventQueue.put({"Type":fenrirEventType.ScreenUpdate,"Data":''}) - lastChange = time.time() + lastScreenContent = screenContent def update(self, trigger='onUpdate'): + if trigger == 'onInput': # no need for an update on input for VCSA + return newContentBytes = b'' try: # read screen From 0aaf916b7d3eb0bfffe824d595b9861d426329c6 Mon Sep 17 00:00:00 2001 From: chrys Date: Sun, 25 Jun 2017 15:33:04 +0200 Subject: [PATCH 14/96] add timer trigger --- src/fenrir/commands/onHeartBeat/76000-time.py | 74 +++++++++++++++++++ src/fenrir/commands/onHeartBeat/__init__.py | 0 2 files changed, 74 insertions(+) create mode 100644 src/fenrir/commands/onHeartBeat/76000-time.py create mode 100755 src/fenrir/commands/onHeartBeat/__init__.py diff --git a/src/fenrir/commands/onHeartBeat/76000-time.py b/src/fenrir/commands/onHeartBeat/76000-time.py new file mode 100644 index 00000000..3b9b55b6 --- /dev/null +++ b/src/fenrir/commands/onHeartBeat/76000-time.py @@ -0,0 +1,74 @@ +#!/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): + if not self.env['runtime']['settingsManager'].getSettingAsBool('time', 'enabled'): + return + onMinutes = self.env['runtime']['settingsManager'].getSetting('time', 'onMinutes') + delaySec = self.env['runtime']['settingsManager'].getSettingAsInt('time', 'delaySec') + # no need + if onMinutes == '' and delaySec <= 0: + return + onMinutes = onMinutes.split(',') + now = datetime.datetime.now() + # ignore onMinutes if there is a delaySec + if delaySec > 0: + if int((now-self.lastTime).total_seconds()) < delaySec: + return + else: + # shoul announce? + if not str(now.minute) in onMinutes: + return + # already announced? + if now.hour == self.lastTime.hour: + if now.minute == self.lastTime.minute: + return + dateFormat = self.env['runtime']['settingsManager'].getSetting('general', 'dateFormat') + dateString = datetime.datetime.strftime(now, dateFormat) + + presentDate = self.env['runtime']['settingsManager'].getSettingAsBool('time', 'presentDate') and \ + self.lastDateString != dateString + presentTime = self.env['runtime']['settingsManager'].getSettingAsBool('time', 'presentTime') + # no changed value to announce + if not (presentDate or presentTime): + return + timeFormat = self.env['runtime']['settingsManager'].getSetting('general', 'timeFormat') + timeString = datetime.datetime.strftime(now, timeFormat) + + if self.env['runtime']['settingsManager'].getSettingAsBool('time', 'interrupt'): + self.env['runtime']['outputManager'].interruptOutput() + if self.env['runtime']['settingsManager'].getSettingAsBool('time', 'announce'): + self.env['runtime']['outputManager'].playSoundIcon('announce') + + if presentTime: + # present the time + self.env['runtime']['outputManager'].presentText(_('Autotime: {0}').format(timeString), soundIcon='', interrupt=False) + # and date if changes + if presentDate: + self.env['runtime']['outputManager'].presentText(dateString , soundIcon='', interrupt=False) + self.lastDateString = dateString + self.lastTime = datetime.datetime.now() + self.lastTimeString = timeString + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/onHeartBeat/__init__.py b/src/fenrir/commands/onHeartBeat/__init__.py new file mode 100755 index 00000000..e69de29b From 9bee489bc737d4403bdde816a48975d7c9058675 Mon Sep 17 00:00:00 2001 From: chrys Date: Sun, 25 Jun 2017 15:37:04 +0200 Subject: [PATCH 15/96] set smaller timeout; unfinished thread handling here; WIP --- src/fenrir/core/eventManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fenrir/core/eventManager.py b/src/fenrir/core/eventManager.py index e27778bb..7c8f7ce8 100644 --- a/src/fenrir/core/eventManager.py +++ b/src/fenrir/core/eventManager.py @@ -87,7 +87,7 @@ class eventManager(): #print('ALL loop ' + str(time.time() - st)) def handleStopMainLoop(self): self._mainLoopRunning.value = 0 - time.sleep(3.5) + time.sleep(0.1) def stopMainEventLoop(self, Force = False): if Force: self._mainLoopRunning.value = 0 From e8c0109267d0b5c531670f50104c87ac34117a27 Mon Sep 17 00:00:00 2001 From: chrys Date: Sun, 25 Jun 2017 21:21:06 +0200 Subject: [PATCH 16/96] no empty input event; make hartbeat work; plugInputDevice trigger --- src/fenrir/commands/onHeartBeat/76000-time.py | 0 src/fenrir/core/commandData.py | 32 ------------------- src/fenrir/core/commandManager.py | 9 +++--- src/fenrir/core/environment.py | 2 -- src/fenrir/core/eventManager.py | 16 ++-------- src/fenrir/core/fenrirManager.py | 6 ++-- src/fenrir/core/generalData.py | 2 +- src/fenrir/inputDriver/evdevDriver.py | 9 +++++- 8 files changed, 19 insertions(+), 57 deletions(-) mode change 100644 => 100755 src/fenrir/commands/onHeartBeat/76000-time.py diff --git a/src/fenrir/commands/onHeartBeat/76000-time.py b/src/fenrir/commands/onHeartBeat/76000-time.py old mode 100644 new mode 100755 diff --git a/src/fenrir/core/commandData.py b/src/fenrir/core/commandData.py index c3ea2fae..50bc072d 100644 --- a/src/fenrir/core/commandData.py +++ b/src/fenrir/core/commandData.py @@ -28,35 +28,3 @@ commandInfo = { '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':{ - }, -} diff --git a/src/fenrir/core/commandManager.py b/src/fenrir/core/commandManager.py index cb198f33..d5dde35c 100644 --- a/src/fenrir/core/commandManager.py +++ b/src/fenrir/core/commandManager.py @@ -15,6 +15,8 @@ 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')) @@ -42,7 +44,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 +65,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 @@ -172,8 +174,7 @@ 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(): diff --git a/src/fenrir/core/environment.py b/src/fenrir/core/environment.py index 0dde4f99..b8838e15 100644 --- a/src/fenrir/core/environment.py +++ b/src/fenrir/core/environment.py @@ -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, diff --git a/src/fenrir/core/eventManager.py b/src/fenrir/core/eventManager.py index 7c8f7ce8..779d079f 100644 --- a/src/fenrir/core/eventManager.py +++ b/src/fenrir/core/eventManager.py @@ -44,23 +44,18 @@ class eventManager(): self.eventDispatcher(event) #print('NET loop ' + str(time.time() - st)) def eventDispatcher(self, event): - print(event['Type']) + print(event['Type'], self._eventQueue.qsize()) if not event: return if event['Type'] == fenrirEventType.Ignore: return elif event['Type'] == fenrirEventType.StopMainLoop: self.handleStopMainLoop() - print('stop') return elif event['Type'] == fenrirEventType.ScreenUpdate: self.env['runtime']['fenrirManager'].handleScreenUpdate() - print(self._eventQueue.qsize()) - print('ScreenUpdate') elif event['Type'] == fenrirEventType.KeyboardInput: self.env['runtime']['fenrirManager'].handleInput() - print(self._eventQueue.qsize()) - print('KeyboardInput') elif event['Type'] == fenrirEventType.BrailleInput: pass elif event['Type'] == fenrirEventType.PlugInputDevice: @@ -69,14 +64,9 @@ class eventManager(): pass elif event['Type'] == fenrirEventType.ScreenChanged: self.env['runtime']['fenrirManager'].handleScreenChange() - print(self._eventQueue.qsize()) - print('ScreenChanged') elif event['Type'] == fenrirEventType.HeartBeat: - # run timer actions - #self.env['runtime']['fenrirManager'].handleProcess() - print(self._eventQueue.qsize()) - print('HeartBeat at {0} {1}'.format(event['Type'], event['Data'] )) - + self.env['runtime']['fenrirManager'].handleHeartBeat() + #print('HeartBeat at {0} {1}'.format(event['Type'], event['Data'] )) def isMainEventLoopRunning(self): return self._mainLoopRunning.value == 1 def startMainEventLoop(self): diff --git a/src/fenrir/core/fenrirManager.py b/src/fenrir/core/fenrirManager.py index 2e291a55..a26bb08e 100644 --- a/src/fenrir/core/fenrirManager.py +++ b/src/fenrir/core/fenrirManager.py @@ -67,7 +67,7 @@ class fenrirManager(): self.environment['runtime']['commandManager'].executeDefaultTrigger('onInput') self.handleCommands() def handleScreenChange(self): - self.environment['runtime']['screenManager'].update('onUpdate') + self.environment['runtime']['screenManager'].update('onScreenChange') if self.environment['runtime']['applicationManager'].isApplicationChange(): self.environment['runtime']['commandManager'].executeDefaultTrigger('onApplicationChange') @@ -90,11 +90,9 @@ class fenrirManager(): if not self.environment['runtime']['screenManager'].isScreenChange(): self.environment['runtime']['commandManager'].executeDefaultTrigger('onScreenUpdate') def handlePlugInputDevice(self): - if not self.environment['runtime']['screenManager'].isSuspendingScreen(): # remove if all works - self.environment['runtime']['inputManager'].updateInputDevices() + self.environment['runtime']['commandManager'].executeDefaultTrigger('PlugInputDevice') def handleHeartBeat(self): self.environment['runtime']['commandManager'].executeDefaultTrigger('onHeartBeat') - self.handlePlugInputDevice() #self.environment['runtime']['outputManager'].brailleText(flush=False) def prepareCommand(self): diff --git a/src/fenrir/core/generalData.py b/src/fenrir/core/generalData.py index 324099ba..261e7379 100644 --- a/src/fenrir/core/generalData.py +++ b/src/fenrir/core/generalData.py @@ -13,6 +13,6 @@ generalData = { 'prevUser':'', 'managerList':['eventManager','punctuationManager','cursorManager','applicationManager','commandManager' ,'screenManager','inputManager','outputManager','debug'], -'commandFolderList':['commands','onInput','onScreenUpdate','onScreenChanged' +'commandFolderList':['commands','onInput','onScreenUpdate','onScreenChanged','onHeartBeat', 'onPlugInputDevice' ,'onApplicationChange','onSwitchApplicationProfile',], } diff --git a/src/fenrir/inputDriver/evdevDriver.py b/src/fenrir/inputDriver/evdevDriver.py index de6d7b0d..84068758 100644 --- a/src/fenrir/inputDriver/evdevDriver.py +++ b/src/fenrir/inputDriver/evdevDriver.py @@ -42,7 +42,12 @@ class driver(): self.env['runtime']['debug'].writeDebugOut('InputDriver: ' + _evdevAvailableError,debug.debugLevel.ERROR) return self.updateInputDevices() + self.env['runtime']['eventManager'].addSimpleEventThread(fenrirEventType.PlugInputDevice, self.plugInputDeviceWatchdog) self.env['runtime']['eventManager'].addSimpleEventThread(fenrirEventType.KeyboardInput, self.inputWatchdog, {'dev':self.iDevicesFD}) + def plugInputDeviceWatchdog(self): + time.sleep(2) + #self.env['runtime']['settingsManager'].getSettingAsFloat('screen', 'screenUpdateDelay') + return time.time() def shutdown(self): if not self._initialized: return @@ -54,7 +59,9 @@ class driver(): if active.value == 0: return time.sleep(0.01) - r, w, x = select(deviceFd, [], [], 2) + r = [] + while r == []: + r, w, x = select(deviceFd, [], [], 2) self.watchDog.value = 0 def getInputEvent(self): if not self.hasIDevices(): From c15cc2df4e4946918aa2ed69e999c4e5ddb8cb66 Mon Sep 17 00:00:00 2001 From: chrys Date: Sun, 25 Jun 2017 21:21:12 +0200 Subject: [PATCH 17/96] no empty input event; make hartbeat work; plugInputDevice trigger --- .../onPlugInputDevice/50000-UpdateDevices.py | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100755 src/fenrir/commands/onPlugInputDevice/50000-UpdateDevices.py diff --git a/src/fenrir/commands/onPlugInputDevice/50000-UpdateDevices.py b/src/fenrir/commands/onPlugInputDevice/50000-UpdateDevices.py new file mode 100755 index 00000000..ffd26e6a --- /dev/null +++ b/src/fenrir/commands/onPlugInputDevice/50000-UpdateDevices.py @@ -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 From 34b74c72d4151b87bb81b780429a262e645fb8cd Mon Sep 17 00:00:00 2001 From: chrys Date: Sun, 25 Jun 2017 21:29:01 +0200 Subject: [PATCH 18/96] time messure --- src/fenrir/core/eventManager.py | 2 +- src/fenrir/core/fenrirManager.py | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/fenrir/core/eventManager.py b/src/fenrir/core/eventManager.py index 779d079f..d083135a 100644 --- a/src/fenrir/core/eventManager.py +++ b/src/fenrir/core/eventManager.py @@ -74,7 +74,7 @@ class eventManager(): while( self.isMainEventLoopRunning()): st = time.time() self.proceedEventLoop() - #print('ALL loop ' + str(time.time() - st)) + print('ALL loop ' + str(time.time() - st)) def handleStopMainLoop(self): self._mainLoopRunning.value = 0 time.sleep(0.1) diff --git a/src/fenrir/core/fenrirManager.py b/src/fenrir/core/fenrirManager.py index a26bb08e..1681ced2 100644 --- a/src/fenrir/core/fenrirManager.py +++ b/src/fenrir/core/fenrirManager.py @@ -79,16 +79,18 @@ class fenrirManager(): self.environment['runtime']['commandManager'].executeDefaultTrigger('onScreenChanged') def handleScreenUpdate(self): + s = time.time() 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()) - - if not self.environment['runtime']['screenManager'].isScreenChange(): - self.environment['runtime']['commandManager'].executeDefaultTrigger('onScreenUpdate') + ''' + #if not self.environment['runtime']['screenManager'].isScreenChange(): + self.environment['runtime']['commandManager'].executeDefaultTrigger('onScreenUpdate') + #print(time.time() -s) def handlePlugInputDevice(self): self.environment['runtime']['commandManager'].executeDefaultTrigger('PlugInputDevice') def handleHeartBeat(self): From 449f149f97418414379ba25b12940f4ad35e3392 Mon Sep 17 00:00:00 2001 From: chrys Date: Mon, 26 Jun 2017 01:41:19 +0200 Subject: [PATCH 19/96] fix -o for camel case options --- src/fenrir/core/fenrirManager.py | 4 ++-- src/fenrir/core/settingsManager.py | 13 +++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/fenrir/core/fenrirManager.py b/src/fenrir/core/fenrirManager.py index 1681ced2..b6a1bddd 100644 --- a/src/fenrir/core/fenrirManager.py +++ b/src/fenrir/core/fenrirManager.py @@ -63,8 +63,8 @@ class fenrirManager(): self.environment['runtime']['inputManager'].clearEventBuffer() if self.environment['input']['keyForeward'] > 0: self.environment['input']['keyForeward'] -=1 - self.environment['runtime']['screenManager'].update('onInput') - self.environment['runtime']['commandManager'].executeDefaultTrigger('onInput') + #self.environment['runtime']['screenManager'].update('onInput') + #self.environment['runtime']['commandManager'].executeDefaultTrigger('onInput') self.handleCommands() def handleScreenChange(self): self.environment['runtime']['screenManager'].update('onScreenChange') diff --git a/src/fenrir/core/settingsManager.py b/src/fenrir/core/settingsManager.py index aad79688..069a8564 100644 --- a/src/fenrir/core/settingsManager.py +++ b/src/fenrir/core/settingsManager.py @@ -147,7 +147,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 +160,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 +173,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 +186,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 @@ -241,6 +241,7 @@ class settingsManager(): except KeyError: optionArgDict[section] = {} optionArgDict[section][option] = str(value) + print(optionArgDict) return optionArgDict def initFenrirConfig(self, cliArgs, fenrirManager = None, environment = environment.environment): settingsRoot = '/etc/fenrir/' From 16f4e3e98126e30931717542128a497fbc30303c Mon Sep 17 00:00:00 2001 From: chrys Date: Tue, 27 Jun 2017 01:35:12 +0200 Subject: [PATCH 20/96] performance improvements --- .../onHeartBeat/2000-GetSessionInfo.py | 74 +++++++++++++++++++ src/fenrir/core/eventManager.py | 2 + src/fenrir/core/fenrirManager.py | 9 ++- src/fenrir/core/screenManager.py | 12 +-- src/fenrir/inputDriver/evdevDriver.py | 4 +- src/fenrir/screenDriver/vcsaDriver.py | 1 - 6 files changed, 90 insertions(+), 12 deletions(-) create mode 100755 src/fenrir/commands/onHeartBeat/2000-GetSessionInfo.py diff --git a/src/fenrir/commands/onHeartBeat/2000-GetSessionInfo.py b/src/fenrir/commands/onHeartBeat/2000-GetSessionInfo.py new file mode 100755 index 00000000..3b9b55b6 --- /dev/null +++ b/src/fenrir/commands/onHeartBeat/2000-GetSessionInfo.py @@ -0,0 +1,74 @@ +#!/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): + if not self.env['runtime']['settingsManager'].getSettingAsBool('time', 'enabled'): + return + onMinutes = self.env['runtime']['settingsManager'].getSetting('time', 'onMinutes') + delaySec = self.env['runtime']['settingsManager'].getSettingAsInt('time', 'delaySec') + # no need + if onMinutes == '' and delaySec <= 0: + return + onMinutes = onMinutes.split(',') + now = datetime.datetime.now() + # ignore onMinutes if there is a delaySec + if delaySec > 0: + if int((now-self.lastTime).total_seconds()) < delaySec: + return + else: + # shoul announce? + if not str(now.minute) in onMinutes: + return + # already announced? + if now.hour == self.lastTime.hour: + if now.minute == self.lastTime.minute: + return + dateFormat = self.env['runtime']['settingsManager'].getSetting('general', 'dateFormat') + dateString = datetime.datetime.strftime(now, dateFormat) + + presentDate = self.env['runtime']['settingsManager'].getSettingAsBool('time', 'presentDate') and \ + self.lastDateString != dateString + presentTime = self.env['runtime']['settingsManager'].getSettingAsBool('time', 'presentTime') + # no changed value to announce + if not (presentDate or presentTime): + return + timeFormat = self.env['runtime']['settingsManager'].getSetting('general', 'timeFormat') + timeString = datetime.datetime.strftime(now, timeFormat) + + if self.env['runtime']['settingsManager'].getSettingAsBool('time', 'interrupt'): + self.env['runtime']['outputManager'].interruptOutput() + if self.env['runtime']['settingsManager'].getSettingAsBool('time', 'announce'): + self.env['runtime']['outputManager'].playSoundIcon('announce') + + if presentTime: + # present the time + self.env['runtime']['outputManager'].presentText(_('Autotime: {0}').format(timeString), soundIcon='', interrupt=False) + # and date if changes + if presentDate: + self.env['runtime']['outputManager'].presentText(dateString , soundIcon='', interrupt=False) + self.lastDateString = dateString + self.lastTime = datetime.datetime.now() + self.lastTimeString = timeString + def setCallback(self, callback): + pass diff --git a/src/fenrir/core/eventManager.py b/src/fenrir/core/eventManager.py index d083135a..69a11455 100644 --- a/src/fenrir/core/eventManager.py +++ b/src/fenrir/core/eventManager.py @@ -53,9 +53,11 @@ class eventManager(): self.handleStopMainLoop() return elif event['Type'] == fenrirEventType.ScreenUpdate: + pass self.env['runtime']['fenrirManager'].handleScreenUpdate() elif event['Type'] == fenrirEventType.KeyboardInput: self.env['runtime']['fenrirManager'].handleInput() + #self.env['runtime']['fenrirManager'].handleScreenUpdate() elif event['Type'] == fenrirEventType.BrailleInput: pass elif event['Type'] == fenrirEventType.PlugInputDevice: diff --git a/src/fenrir/core/fenrirManager.py b/src/fenrir/core/fenrirManager.py index b6a1bddd..32d64fc8 100644 --- a/src/fenrir/core/fenrirManager.py +++ b/src/fenrir/core/fenrirManager.py @@ -63,8 +63,8 @@ class fenrirManager(): self.environment['runtime']['inputManager'].clearEventBuffer() if self.environment['input']['keyForeward'] > 0: self.environment['input']['keyForeward'] -=1 - #self.environment['runtime']['screenManager'].update('onInput') - #self.environment['runtime']['commandManager'].executeDefaultTrigger('onInput') + self.environment['runtime']['screenManager'].update('onInput') + self.environment['runtime']['commandManager'].executeDefaultTrigger('onInput') self.handleCommands() def handleScreenChange(self): self.environment['runtime']['screenManager'].update('onScreenChange') @@ -80,14 +80,15 @@ class fenrirManager(): def handleScreenUpdate(self): s = time.time() + 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()) - ''' + #if not self.environment['runtime']['screenManager'].isScreenChange(): self.environment['runtime']['commandManager'].executeDefaultTrigger('onScreenUpdate') #print(time.time() -s) diff --git a/src/fenrir/core/screenManager.py b/src/fenrir/core/screenManager.py index 0472360a..74dd27b5 100644 --- a/src/fenrir/core/screenManager.py +++ b/src/fenrir/core/screenManager.py @@ -21,16 +21,18 @@ class screenManager(): self.env['runtime']['settingsManager'].shutdownDriver('screenDriver') def update(self, trigger='onUpdate'): - self.env['runtime']['screenDriver'].getCurrScreen() - self.env['runtime']['screenDriver'].getSessionInformation() + + if trigger == 'onScreenChange': + self.env['runtime']['screenDriver'].getCurrScreen() + 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): diff --git a/src/fenrir/inputDriver/evdevDriver.py b/src/fenrir/inputDriver/evdevDriver.py index 84068758..c8d0d07f 100644 --- a/src/fenrir/inputDriver/evdevDriver.py +++ b/src/fenrir/inputDriver/evdevDriver.py @@ -45,7 +45,7 @@ class driver(): self.env['runtime']['eventManager'].addSimpleEventThread(fenrirEventType.PlugInputDevice, self.plugInputDeviceWatchdog) self.env['runtime']['eventManager'].addSimpleEventThread(fenrirEventType.KeyboardInput, self.inputWatchdog, {'dev':self.iDevicesFD}) def plugInputDeviceWatchdog(self): - time.sleep(2) + time.sleep(2.5) #self.env['runtime']['settingsManager'].getSettingAsFloat('screen', 'screenUpdateDelay') return time.time() def shutdown(self): @@ -58,7 +58,7 @@ class driver(): while self.watchDog.value == 0: if active.value == 0: return - time.sleep(0.01) + time.sleep(0.001) r = [] while r == []: r, w, x = select(deviceFd, [], [], 2) diff --git a/src/fenrir/screenDriver/vcsaDriver.py b/src/fenrir/screenDriver/vcsaDriver.py index 328d90e4..2aa835c5 100644 --- a/src/fenrir/screenDriver/vcsaDriver.py +++ b/src/fenrir/screenDriver/vcsaDriver.py @@ -98,7 +98,6 @@ class driver(): self.env['screen']['autoIgnoreScreens'] = [] def updateWatchdog(self,active , eventQueue): - print('init VCSA updateWatchdog') currScreen = '2' vcsa = {} for i in range(1,7): From 98ce582b15319b19b9391131d579c3bbcad12cfd Mon Sep 17 00:00:00 2001 From: chrys Date: Fri, 30 Jun 2017 19:37:50 +0200 Subject: [PATCH 21/96] move some commands to onScreenUpdate (WIP) --- .../onHeartBeat/2000-GetSessionInfo.py | 49 +------ ...resent_char_if_cursor_change_horizontal.py | 43 ------ .../commands/onInput/50000-char_echo.py | 40 ------ ...-present_line_if_cursor_change_vertical.py | 45 ------ .../onInput/56000-highlight_tracking.py | 24 ---- .../commands/onInput/60000-word_echo.py | 57 -------- .../commands/onInput/62000-spell_check.py | 136 ------------------ .../onInput/65000-char_delete_echo.py | 49 ------- src/fenrir/commands/onInput/72000-history.py | 58 -------- .../commands/onScreenUpdate/70000-incoming.py | 41 ------ .../onScreenUpdate/75000-incoming_promote.py | 39 ----- src/fenrir/core/fenrirManager.py | 14 +- src/fenrir/core/screenManager.py | 3 +- 13 files changed, 9 insertions(+), 589 deletions(-) delete mode 100644 src/fenrir/commands/onInput/45000-present_char_if_cursor_change_horizontal.py delete mode 100644 src/fenrir/commands/onInput/50000-char_echo.py delete mode 100644 src/fenrir/commands/onInput/55000-present_line_if_cursor_change_vertical.py delete mode 100644 src/fenrir/commands/onInput/56000-highlight_tracking.py delete mode 100644 src/fenrir/commands/onInput/60000-word_echo.py delete mode 100644 src/fenrir/commands/onInput/62000-spell_check.py delete mode 100644 src/fenrir/commands/onInput/65000-char_delete_echo.py delete mode 100644 src/fenrir/commands/onInput/72000-history.py delete mode 100644 src/fenrir/commands/onScreenUpdate/70000-incoming.py delete mode 100644 src/fenrir/commands/onScreenUpdate/75000-incoming_promote.py diff --git a/src/fenrir/commands/onHeartBeat/2000-GetSessionInfo.py b/src/fenrir/commands/onHeartBeat/2000-GetSessionInfo.py index 3b9b55b6..b4d822a3 100755 --- a/src/fenrir/commands/onHeartBeat/2000-GetSessionInfo.py +++ b/src/fenrir/commands/onHeartBeat/2000-GetSessionInfo.py @@ -23,52 +23,7 @@ class command(): return 'No Description found' def run(self): - if not self.env['runtime']['settingsManager'].getSettingAsBool('time', 'enabled'): - return - onMinutes = self.env['runtime']['settingsManager'].getSetting('time', 'onMinutes') - delaySec = self.env['runtime']['settingsManager'].getSettingAsInt('time', 'delaySec') - # no need - if onMinutes == '' and delaySec <= 0: - return - onMinutes = onMinutes.split(',') - now = datetime.datetime.now() - # ignore onMinutes if there is a delaySec - if delaySec > 0: - if int((now-self.lastTime).total_seconds()) < delaySec: - return - else: - # shoul announce? - if not str(now.minute) in onMinutes: - return - # already announced? - if now.hour == self.lastTime.hour: - if now.minute == self.lastTime.minute: - return - dateFormat = self.env['runtime']['settingsManager'].getSetting('general', 'dateFormat') - dateString = datetime.datetime.strftime(now, dateFormat) - - presentDate = self.env['runtime']['settingsManager'].getSettingAsBool('time', 'presentDate') and \ - self.lastDateString != dateString - presentTime = self.env['runtime']['settingsManager'].getSettingAsBool('time', 'presentTime') - # no changed value to announce - if not (presentDate or presentTime): - return - timeFormat = self.env['runtime']['settingsManager'].getSetting('general', 'timeFormat') - timeString = datetime.datetime.strftime(now, timeFormat) - - if self.env['runtime']['settingsManager'].getSettingAsBool('time', 'interrupt'): - self.env['runtime']['outputManager'].interruptOutput() - if self.env['runtime']['settingsManager'].getSettingAsBool('time', 'announce'): - self.env['runtime']['outputManager'].playSoundIcon('announce') - - if presentTime: - # present the time - self.env['runtime']['outputManager'].presentText(_('Autotime: {0}').format(timeString), soundIcon='', interrupt=False) - # and date if changes - if presentDate: - self.env['runtime']['outputManager'].presentText(dateString , soundIcon='', interrupt=False) - self.lastDateString = dateString - self.lastTime = datetime.datetime.now() - self.lastTimeString = timeString + self.env['runtime']['screenDriver'].getSessionInformation() def setCallback(self, callback): pass + diff --git a/src/fenrir/commands/onInput/45000-present_char_if_cursor_change_horizontal.py b/src/fenrir/commands/onInput/45000-present_char_if_cursor_change_horizontal.py deleted file mode 100644 index 08deef10..00000000 --- a/src/fenrir/commands/onInput/45000-present_char_if_cursor_change_horizontal.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from core import debug -from utils import char_utils - -class command(): - def __init__(self): - pass - def initialize(self, environment): - self.env = environment - def shutdown(self): - pass - def getDescription(self): - return '' - - def run(self): - if not self.env['runtime']['settingsManager'].getSettingAsBool('focus', 'cursor'): - return - if self.env['runtime']['screenManager'].isScreenChange(): - return - if self.env['runtime']['inputManager'].noKeyPressed(): - 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 - if self.env['runtime']['screenManager'].isNegativeDelta(): - return - # is a vertical change? - if self.env['runtime']['cursorManager'].isCursorVerticalMove(): - return - # is it a horizontal change? - if not self.env['runtime']['cursorManager'].isCursorHorizontalMove(): - return - x, y, currChar = char_utils.getCurrentChar(self.env['screen']['newCursor']['x'], self.env['screen']['newCursor']['y'], self.env['screen']['newContentText']) - if not currChar.isspace(): - self.env['runtime']['outputManager'].presentText(currChar, interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) - def setCallback(self, callback): - pass - diff --git a/src/fenrir/commands/onInput/50000-char_echo.py b/src/fenrir/commands/onInput/50000-char_echo.py deleted file mode 100644 index 832263b2..00000000 --- a/src/fenrir/commands/onInput/50000-char_echo.py +++ /dev/null @@ -1,40 +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('keyboard', 'charEcho'): - return - # detect deletion or chilling - if self.env['screen']['newCursor']['x'] <= self.env['screen']['oldCursor']['x']: - return - # is there any change? - if not self.env['runtime']['screenManager'].isDelta(): - return - # big changes are no char (but the value is bigger than one maybe the differ needs longer than you can type, so a little strange random buffer for now) - if len(self.env['screen']['newDelta']) > 3: - return - # filter unneded space on word begin - currDelta = self.env['screen']['newDelta'] - if len(currDelta.strip()) != len(currDelta) and \ - currDelta.strip() != '': - currDelta = currDelta.strip() - self.env['runtime']['outputManager'].presentText(currDelta, interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) - - def setCallback(self, callback): - pass - diff --git a/src/fenrir/commands/onInput/55000-present_line_if_cursor_change_vertical.py b/src/fenrir/commands/onInput/55000-present_line_if_cursor_change_vertical.py deleted file mode 100644 index 905b7daf..00000000 --- a/src/fenrir/commands/onInput/55000-present_line_if_cursor_change_vertical.py +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from core import debug -from utils import line_utils - -class command(): - def __init__(self): - pass - def initialize(self, environment): - self.env = environment - def shutdown(self): - pass - def getDescription(self): - return '' - - def run(self): - if not self.env['runtime']['settingsManager'].getSettingAsBool('focus', 'cursor'): - return - if self.env['runtime']['inputManager'].noKeyPressed(): - 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 - if self.env['runtime']['screenManager'].isDelta(): - if len(self.env['screen']['newDelta']) > 4: - return - - # is a vertical change? - if not self.env['runtime']['cursorManager'].isCursorVerticalMove(): - return - - x, y, currLine = line_utils.getCurrentLine(self.env['screen']['newCursor']['x'], self.env['screen']['newCursor']['y'], self.env['screen']['newContentText']) - - if currLine.isspace(): - self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True, flush=False) - else: - self.env['runtime']['outputManager'].presentText(currLine, interrupt=True, flush=False) - - def setCallback(self, callback): - pass - diff --git a/src/fenrir/commands/onInput/56000-highlight_tracking.py b/src/fenrir/commands/onInput/56000-highlight_tracking.py deleted file mode 100644 index 419966f8..00000000 --- a/src/fenrir/commands/onInput/56000-highlight_tracking.py +++ /dev/null @@ -1,24 +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 _('enables or disables tracking of highlighted') - - def run(self): - if not self.env['runtime']['settingsManager'].getSettingAsBool('focus', 'highlight'): - return - self.env['runtime']['outputManager'].presentText(self.env['screen']['newAttribDelta'], soundIcon='', interrupt=True, flush=False) - - def setCallback(self, callback): - pass diff --git a/src/fenrir/commands/onInput/60000-word_echo.py b/src/fenrir/commands/onInput/60000-word_echo.py deleted file mode 100644 index b0fab071..00000000 --- a/src/fenrir/commands/onInput/60000-word_echo.py +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from core import debug -from utils import word_utils -import string - -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): - # first place could not be the end of a word - if self.env['screen']['newCursor']['x'] == 0: - return - # is it enabled? - if not self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'wordEcho'): - return - - # 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 - # get the word - newContent = self.env['screen']['newContentText'].split('\n')[self.env['screen']['newCursor']['y']] - x, y, currWord, endOfScreen, lineBreak = \ - word_utils.getCurrentWord(self.env['screen']['newCursor']['x'], 0, newContent) - # currently writing - if self.env['runtime']['screenManager'].isDelta(): - return - else: - # at the end of a word - if not newContent[self.env['screen']['newCursor']['x']].isspace(): - return - if (x + len(currWord) != self.env['screen']['newCursor']['x']) and \ - (x + len(currWord) != self.env['screen']['newCursor']['x']-1): - return - - if currWord != '': - self.env['runtime']['outputManager'].presentText(currWord, interrupt=True, flush=False) - - def setCallback(self, callback): - pass - diff --git a/src/fenrir/commands/onInput/62000-spell_check.py b/src/fenrir/commands/onInput/62000-spell_check.py deleted file mode 100644 index 0a73cffd..00000000 --- a/src/fenrir/commands/onInput/62000-spell_check.py +++ /dev/null @@ -1,136 +0,0 @@ -#!/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from core import debug -from utils import word_utils -import os, string - -initialized = False -try: - import enchant - initialized = True -except: - pass - -class command(): - def __init__(self): - self.language = '' - self.spellChecker = '' - def initialize(self, environment): - self.env = environment - self.updateSpellLanguage() - def shutdown(self): - pass - def getDescription(self): - return 'No Description found' - - def updateSpellLanguage(self): - if not initialized: - self.env['runtime']['outputManager'].presentText('pychant is not installed', interrupt=True) - return - self.spellChecker = enchant.Dict(self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage')) - self.language = self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage') - - def run(self): - if not initialized: - 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() - except: - return - - # just when horizontal cursor move worddetection is needed - if not self.env['runtime']['cursorManager'].isCursorHorizontalMove(): - return - - # for now no new line - if self.env['runtime']['cursorManager'].isCursorVerticalMove(): - return - # more than a keyecho? - if len(self.env['screen']['newDelta']) > 1: - return - # deletion - if self.env['runtime']['screenManager'].isNegativeDelta(): - return - # first place could not be the end of a word - if self.env['screen']['newCursor']['x'] == 0: - return - - # get the word (just for speedup only look at current line - newContent = self.env['screen']['newContentText'].split('\n')[self.env['screen']['newCursor']['y']] - x, y, currWord, endOfScreen, lineBreak = word_utils.getCurrentWord(self.env['screen']['newCursor']['x'], 0, newContent) - # was this a typed word? - if self.env['runtime']['screenManager'].isDelta(): - if not(newContent[self.env['screen']['oldCursor']['x']] in string.whitespace + '!"#$%&()*+,-./:;<=>?@[\\]^_{|}~' and x != self.env['screen']['oldCursor']['x']): - return - else: - currWord = currWord.strip(string.whitespace + '!"#$%&()*+,-./:;<=>?@[\\]^_{|}~') - else: - # or just arrow arround? - if not newContent[self.env['screen']['newCursor']['x']].isspace(): - return - if (x + len(currWord) != self.env['screen']['newCursor']['x']) and \ - (x + len(currWord) != self.env['screen']['newCursor']['x']-1): - return - - # just on end of word - if self.env['screen']['newCursor']['x'] > 0: - if not newContent[self.env['screen']['oldCursor']['x'] - 1].lower() in string.ascii_lowercase: - return - - # ignore bash buildins - if currWord in ['cd','fg','bg','alias','bind','dir','caller','buildin','command','declare','echo','enable','help','let','local','logout',\ - 'mapfile','printf','read','readarray','source','type','typeset','ulimit','unalias']: - return - # ignore the application name - if currWord.upper() == 'FENRIR': - return - if currWord[0] =='-': - return - if currWord[0] == '/': - return - if currWord[0] == '#': - return - if currWord.startswith('./'): - return - if '@' in currWord and '.' in currWord: - return - if currWord[0] == '@': - return - if currWord.isnumeric(): - return - if currWord.isdecimal(): - return - if currWord.isspace(): - return - - try: - if os.path.exists("/bin/"+currWord): - return - except: - pass - try: - if os.path.exists("/usr/bin/"+currWord): - return - except: - pass - try: - if os.path.exists("/sbin/"+currWord): - return - except: - pass - - if not self.spellChecker.check(currWord): - self.env['runtime']['outputManager'].presentText(_('misspelled'), soundIcon='mispell', interrupt=False, flush=False) - - def setCallback(self, callback): - pass - diff --git a/src/fenrir/commands/onInput/65000-char_delete_echo.py b/src/fenrir/commands/onInput/65000-char_delete_echo.py deleted file mode 100644 index d64262e0..00000000 --- a/src/fenrir/commands/onInput/65000-char_delete_echo.py +++ /dev/null @@ -1,49 +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('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 - - # too much for a single backspace... - # word begin produce a diff wiht len == 2 |a | others with 1 |a| - if len(self.env['screen']['newNegativeDelta']) > 2: - return - currNegativeDelta = self.env['screen']['newNegativeDelta'] - if len(currNegativeDelta.strip()) != len(currNegativeDelta) and \ - currNegativeDelta.strip() != '': - currNegativeDelta = currNegativeDelta.strip() - self.env['runtime']['outputManager'].presentText(currNegativeDelta, interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) - - def setCallback(self, callback): - pass - diff --git a/src/fenrir/commands/onInput/72000-history.py b/src/fenrir/commands/onInput/72000-history.py deleted file mode 100644 index 7cde4a06..00000000 --- a/src/fenrir/commands/onInput/72000-history.py +++ /dev/null @@ -1,58 +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 '' - - def run(self): - if self.env['runtime']['inputManager'].noKeyPressed(): - return - if self.env['screen']['newAttribDelta'] != '': - return - if self.env['runtime']['screenManager'].isScreenChange(): - return - if self.env['runtime']['cursorManager'].isCursorVerticalMove(): - return - if len(self.env['input']['currInput']) != 1: - return - if not self.env['input']['currInput'][0] in ['KEY_UP','KEY_DOWN']: - return - prevLine = self.env['screen']['oldContentText'].split('\n')[self.env['screen']['newCursor']['y']] - currLine = self.env['screen']['newContentText'].split('\n')[self.env['screen']['newCursor']['y']] - if not currLine.isspace(): - currPrompt = currLine.find('$') - rootPrompt = currLine.find('#') - if currPrompt <= 0: - if rootPrompt > 0: - currPrompt = rootPrompt - else: - announce = currLine - if currPrompt > 0: - remove_digits = str.maketrans('0123456789', ' ') - if prevLine[:currPrompt].translate(remove_digits) == currLine[:currPrompt].translate(remove_digits): - announce = currLine[currPrompt+1:] - else: - announce = currLine - - if currLine.isspace(): - self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True, flush=False) - else: - self.env['runtime']['outputManager'].presentText(announce, interrupt=True, flush=False) - self.env['commandsIgnore']['onScreenUpdate']['CHAR_DELETE_ECHO'] = True - self.env['commandsIgnore']['onScreenUpdate']['CHAR_ECHO'] = True - self.env['commandsIgnore']['onScreenUpdate']['INCOMING_IGNORE'] = True - def setCallback(self, callback): - pass - diff --git a/src/fenrir/commands/onScreenUpdate/70000-incoming.py b/src/fenrir/commands/onScreenUpdate/70000-incoming.py deleted file mode 100644 index d8601913..00000000 --- a/src/fenrir/commands/onScreenUpdate/70000-incoming.py +++ /dev/null @@ -1,41 +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 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']['y'] - self.env['screen']['oldCursor']['y']) == 1: - 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): - pass - diff --git a/src/fenrir/commands/onScreenUpdate/75000-incoming_promote.py b/src/fenrir/commands/onScreenUpdate/75000-incoming_promote.py deleted file mode 100644 index a39b0688..00000000 --- a/src/fenrir/commands/onScreenUpdate/75000-incoming_promote.py +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/python -import time -# -*- 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('promote', 'enabled'): - return - if self.env['runtime']['settingsManager'].getSetting('promote', 'list').strip(" \t\n") == '': - return - if self.env['screen']['newDelta'] == '': - return - if int(time.time() - self.env['input']['lastInputTime']) < self.env['runtime']['settingsManager'].getSettingAsInt('promote', 'inactiveTimeoutSec'): - return - if len(self.env['runtime']['settingsManager'].getSetting('promote', 'list')) == 0: - return - for promote in self.env['runtime']['settingsManager'].getSetting('promote', 'list').split(','): - if promote in self.env['screen']['newDelta']: - self.env['runtime']['outputManager'].playSoundIcon('PromotedText') - self.env['input']['lastInputTime'] = time.time() - return - - def setCallback(self, callback): - pass - diff --git a/src/fenrir/core/fenrirManager.py b/src/fenrir/core/fenrirManager.py index 32d64fc8..8fe5403f 100644 --- a/src/fenrir/core/fenrirManager.py +++ b/src/fenrir/core/fenrirManager.py @@ -63,33 +63,31 @@ class fenrirManager(): self.environment['runtime']['inputManager'].clearEventBuffer() if self.environment['input']['keyForeward'] > 0: self.environment['input']['keyForeward'] -=1 - self.environment['runtime']['screenManager'].update('onInput') + #self.environment['runtime']['screenManager'].update('onInput') self.environment['runtime']['commandManager'].executeDefaultTrigger('onInput') self.handleCommands() def handleScreenChange(self): 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 not self.environment['runtime']['screenManager'].isScreenChange(): - self.environment['runtime']['commandManager'].executeDefaultTrigger('onScreenChanged') + ''' + self.environment['runtime']['commandManager'].executeDefaultTrigger('onScreenChanged') def handleScreenUpdate(self): s = time.time() 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()) - - #if not self.environment['runtime']['screenManager'].isScreenChange(): + ''' self.environment['runtime']['commandManager'].executeDefaultTrigger('onScreenUpdate') #print(time.time() -s) def handlePlugInputDevice(self): diff --git a/src/fenrir/core/screenManager.py b/src/fenrir/core/screenManager.py index 74dd27b5..c7d14c19 100644 --- a/src/fenrir/core/screenManager.py +++ b/src/fenrir/core/screenManager.py @@ -21,9 +21,8 @@ class screenManager(): self.env['runtime']['settingsManager'].shutdownDriver('screenDriver') def update(self, trigger='onUpdate'): - + self.env['runtime']['screenDriver'].getCurrScreen() if trigger == 'onScreenChange': - self.env['runtime']['screenDriver'].getCurrScreen() self.env['runtime']['screenDriver'].getSessionInformation() self.env['screen']['oldApplication'] = self.env['screen']['newApplication'] if self.isScreenChange(): From 8ca676271aad3a68ecf812d0afb12e3b8f93f368 Mon Sep 17 00:00:00 2001 From: chrys Date: Fri, 30 Jun 2017 19:37:55 +0200 Subject: [PATCH 22/96] move some commands to onScreenUpdate (WIP) --- ...resent_char_if_cursor_change_horizontal.py | 41 ++++++ .../onScreenUpdate/50000-char_echo.py | 40 ++++++ ...-present_line_if_cursor_change_vertical.py | 43 ++++++ .../56000-highlight_tracking.py | 24 ++++ .../onScreenUpdate/60000-word_echo.py | 55 +++++++ .../onScreenUpdate/62000-spell_check.py | 134 ++++++++++++++++++ .../onScreenUpdate/65000-char_delete_echo.py | 48 +++++++ .../onScreenUpdate/deactive/70000-incoming.py | 41 ++++++ .../onScreenUpdate/deactive/72000-history.py | 58 ++++++++ .../deactive/75000-incoming_promote.py | 39 +++++ 10 files changed, 523 insertions(+) create mode 100644 src/fenrir/commands/onScreenUpdate/45000-present_char_if_cursor_change_horizontal.py create mode 100644 src/fenrir/commands/onScreenUpdate/50000-char_echo.py create mode 100644 src/fenrir/commands/onScreenUpdate/55000-present_line_if_cursor_change_vertical.py create mode 100644 src/fenrir/commands/onScreenUpdate/56000-highlight_tracking.py create mode 100644 src/fenrir/commands/onScreenUpdate/60000-word_echo.py create mode 100644 src/fenrir/commands/onScreenUpdate/62000-spell_check.py create mode 100644 src/fenrir/commands/onScreenUpdate/65000-char_delete_echo.py create mode 100644 src/fenrir/commands/onScreenUpdate/deactive/70000-incoming.py create mode 100644 src/fenrir/commands/onScreenUpdate/deactive/72000-history.py create mode 100644 src/fenrir/commands/onScreenUpdate/deactive/75000-incoming_promote.py diff --git a/src/fenrir/commands/onScreenUpdate/45000-present_char_if_cursor_change_horizontal.py b/src/fenrir/commands/onScreenUpdate/45000-present_char_if_cursor_change_horizontal.py new file mode 100644 index 00000000..7128b903 --- /dev/null +++ b/src/fenrir/commands/onScreenUpdate/45000-present_char_if_cursor_change_horizontal.py @@ -0,0 +1,41 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +from utils import char_utils + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return '' + + def run(self): + if not self.env['runtime']['settingsManager'].getSettingAsBool('focus', 'cursor'): + return + if self.env['runtime']['screenManager'].isScreenChange(): + 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 + if self.env['runtime']['screenManager'].isNegativeDelta(): + return + # is a vertical change? + if self.env['runtime']['cursorManager'].isCursorVerticalMove(): + return + # is it a horizontal change? + if not self.env['runtime']['cursorManager'].isCursorHorizontalMove(): + return + x, y, currChar = char_utils.getCurrentChar(self.env['screen']['newCursor']['x'], self.env['screen']['newCursor']['y'], self.env['screen']['newContentText']) + if not currChar.isspace(): + self.env['runtime']['outputManager'].presentText(currChar, interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) + def setCallback(self, callback): + pass + diff --git a/src/fenrir/commands/onScreenUpdate/50000-char_echo.py b/src/fenrir/commands/onScreenUpdate/50000-char_echo.py new file mode 100644 index 00000000..832263b2 --- /dev/null +++ b/src/fenrir/commands/onScreenUpdate/50000-char_echo.py @@ -0,0 +1,40 @@ +#!/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('keyboard', 'charEcho'): + return + # detect deletion or chilling + if self.env['screen']['newCursor']['x'] <= self.env['screen']['oldCursor']['x']: + return + # is there any change? + if not self.env['runtime']['screenManager'].isDelta(): + return + # big changes are no char (but the value is bigger than one maybe the differ needs longer than you can type, so a little strange random buffer for now) + if len(self.env['screen']['newDelta']) > 3: + return + # filter unneded space on word begin + currDelta = self.env['screen']['newDelta'] + if len(currDelta.strip()) != len(currDelta) and \ + currDelta.strip() != '': + currDelta = currDelta.strip() + self.env['runtime']['outputManager'].presentText(currDelta, interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) + + def setCallback(self, callback): + pass + diff --git a/src/fenrir/commands/onScreenUpdate/55000-present_line_if_cursor_change_vertical.py b/src/fenrir/commands/onScreenUpdate/55000-present_line_if_cursor_change_vertical.py new file mode 100644 index 00000000..3be96485 --- /dev/null +++ b/src/fenrir/commands/onScreenUpdate/55000-present_line_if_cursor_change_vertical.py @@ -0,0 +1,43 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +from utils import line_utils + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return '' + + def run(self): + if not self.env['runtime']['settingsManager'].getSettingAsBool('focus', 'cursor'): + 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 + if self.env['runtime']['screenManager'].isDelta(): + if len(self.env['screen']['newDelta']) > 4: + return + + # is a vertical change? + if not self.env['runtime']['cursorManager'].isCursorVerticalMove(): + return + + x, y, currLine = line_utils.getCurrentLine(self.env['screen']['newCursor']['x'], self.env['screen']['newCursor']['y'], self.env['screen']['newContentText']) + + if currLine.isspace(): + self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True, flush=False) + else: + self.env['runtime']['outputManager'].presentText(currLine, interrupt=True, flush=False) + + def setCallback(self, callback): + pass + diff --git a/src/fenrir/commands/onScreenUpdate/56000-highlight_tracking.py b/src/fenrir/commands/onScreenUpdate/56000-highlight_tracking.py new file mode 100644 index 00000000..419966f8 --- /dev/null +++ b/src/fenrir/commands/onScreenUpdate/56000-highlight_tracking.py @@ -0,0 +1,24 @@ +#!/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 _('enables or disables tracking of highlighted') + + def run(self): + if not self.env['runtime']['settingsManager'].getSettingAsBool('focus', 'highlight'): + return + self.env['runtime']['outputManager'].presentText(self.env['screen']['newAttribDelta'], soundIcon='', interrupt=True, flush=False) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/onScreenUpdate/60000-word_echo.py b/src/fenrir/commands/onScreenUpdate/60000-word_echo.py new file mode 100644 index 00000000..bbf0eac0 --- /dev/null +++ b/src/fenrir/commands/onScreenUpdate/60000-word_echo.py @@ -0,0 +1,55 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +from utils import word_utils +import string + +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): + # first place could not be the end of a word + if self.env['screen']['newCursor']['x'] == 0: + return + # is it enabled? + if not self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'wordEcho'): + return + + # just when cursor move worddetection is needed + if not self.env['runtime']['cursorManager'].isCursorHorizontalMove(): + return + # for now no new line + if self.env['runtime']['cursorManager'].isCursorVerticalMove(): + return + # get the word + newContent = self.env['screen']['newContentText'].split('\n')[self.env['screen']['newCursor']['y']] + x, y, currWord, endOfScreen, lineBreak = \ + word_utils.getCurrentWord(self.env['screen']['newCursor']['x'], 0, newContent) + # currently writing + if self.env['runtime']['screenManager'].isDelta(): + return + else: + # at the end of a word + if not newContent[self.env['screen']['newCursor']['x']].isspace(): + return + if (x + len(currWord) != self.env['screen']['newCursor']['x']) and \ + (x + len(currWord) != self.env['screen']['newCursor']['x']-1): + return + + if currWord != '': + self.env['runtime']['outputManager'].presentText(currWord, interrupt=True, flush=False) + + def setCallback(self, callback): + pass + diff --git a/src/fenrir/commands/onScreenUpdate/62000-spell_check.py b/src/fenrir/commands/onScreenUpdate/62000-spell_check.py new file mode 100644 index 00000000..2894d274 --- /dev/null +++ b/src/fenrir/commands/onScreenUpdate/62000-spell_check.py @@ -0,0 +1,134 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +from utils import word_utils +import os, string + +initialized = False +try: + import enchant + initialized = True +except: + pass + +class command(): + def __init__(self): + self.language = '' + self.spellChecker = '' + def initialize(self, environment): + self.env = environment + self.updateSpellLanguage() + def shutdown(self): + pass + def getDescription(self): + return 'No Description found' + + def updateSpellLanguage(self): + if not initialized: + self.env['runtime']['outputManager'].presentText('pychant is not installed', interrupt=True) + return + self.spellChecker = enchant.Dict(self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage')) + self.language = self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage') + + def run(self): + if not initialized: + return + if not self.env['runtime']['settingsManager'].getSettingAsBool('general', 'autoSpellCheck'): + return + if self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage') != self.language: + try: + self.updateSpellLanguage() + except: + return + + # just when horizontal cursor move worddetection is needed + if not self.env['runtime']['cursorManager'].isCursorHorizontalMove(): + return + + # for now no new line + if self.env['runtime']['cursorManager'].isCursorVerticalMove(): + return + # more than a keyecho? + if len(self.env['screen']['newDelta']) > 1: + return + # deletion + if self.env['runtime']['screenManager'].isNegativeDelta(): + return + # first place could not be the end of a word + if self.env['screen']['newCursor']['x'] == 0: + return + + # get the word (just for speedup only look at current line + newContent = self.env['screen']['newContentText'].split('\n')[self.env['screen']['newCursor']['y']] + x, y, currWord, endOfScreen, lineBreak = word_utils.getCurrentWord(self.env['screen']['newCursor']['x'], 0, newContent) + # was this a typed word? + if self.env['runtime']['screenManager'].isDelta(): + if not(newContent[self.env['screen']['oldCursor']['x']] in string.whitespace + '!"#$%&()*+,-./:;<=>?@[\\]^_{|}~' and x != self.env['screen']['oldCursor']['x']): + return + else: + currWord = currWord.strip(string.whitespace + '!"#$%&()*+,-./:;<=>?@[\\]^_{|}~') + else: + # or just arrow arround? + if not newContent[self.env['screen']['newCursor']['x']].isspace(): + return + if (x + len(currWord) != self.env['screen']['newCursor']['x']) and \ + (x + len(currWord) != self.env['screen']['newCursor']['x']-1): + return + + # just on end of word + if self.env['screen']['newCursor']['x'] > 0: + if not newContent[self.env['screen']['oldCursor']['x'] - 1].lower() in string.ascii_lowercase: + return + + # ignore bash buildins + if currWord in ['cd','fg','bg','alias','bind','dir','caller','buildin','command','declare','echo','enable','help','let','local','logout',\ + 'mapfile','printf','read','readarray','source','type','typeset','ulimit','unalias']: + return + # ignore the application name + if currWord.upper() == 'FENRIR': + return + if currWord[0] =='-': + return + if currWord[0] == '/': + return + if currWord[0] == '#': + return + if currWord.startswith('./'): + return + if '@' in currWord and '.' in currWord: + return + if currWord[0] == '@': + return + if currWord.isnumeric(): + return + if currWord.isdecimal(): + return + if currWord.isspace(): + return + + try: + if os.path.exists("/bin/"+currWord): + return + except: + pass + try: + if os.path.exists("/usr/bin/"+currWord): + return + except: + pass + try: + if os.path.exists("/sbin/"+currWord): + return + except: + pass + + if not self.spellChecker.check(currWord): + self.env['runtime']['outputManager'].presentText(_('misspelled'), soundIcon='mispell', interrupt=False, flush=False) + + def setCallback(self, callback): + pass + diff --git a/src/fenrir/commands/onScreenUpdate/65000-char_delete_echo.py b/src/fenrir/commands/onScreenUpdate/65000-char_delete_echo.py new file mode 100644 index 00000000..77cce4c0 --- /dev/null +++ b/src/fenrir/commands/onScreenUpdate/65000-char_delete_echo.py @@ -0,0 +1,48 @@ +#!/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): + print('drin') + #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 + + # too much for a single backspace... + # word begin produce a diff wiht len == 2 |a | others with 1 |a| + #if len(self.env['screen']['newNegativeDelta']) > 2: + # return + currNegativeDelta = self.env['screen']['newNegativeDelta'] + #if len(currNegativeDelta.strip()) != len(currNegativeDelta) and \ + # currNegativeDelta.strip() != '': + # currNegativeDelta = currNegativeDelta.strip() + self.env['runtime']['outputManager'].presentText(currNegativeDelta, interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) + print('danach',currNegativeDelta,'d') + def setCallback(self, callback): + pass + diff --git a/src/fenrir/commands/onScreenUpdate/deactive/70000-incoming.py b/src/fenrir/commands/onScreenUpdate/deactive/70000-incoming.py new file mode 100644 index 00000000..ea37193d --- /dev/null +++ b/src/fenrir/commands/onScreenUpdate/deactive/70000-incoming.py @@ -0,0 +1,41 @@ +#!/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 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']['y'] - self.env['screen']['oldCursor']['y']) == 1: + # 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): + pass + diff --git a/src/fenrir/commands/onScreenUpdate/deactive/72000-history.py b/src/fenrir/commands/onScreenUpdate/deactive/72000-history.py new file mode 100644 index 00000000..7cde4a06 --- /dev/null +++ b/src/fenrir/commands/onScreenUpdate/deactive/72000-history.py @@ -0,0 +1,58 @@ +#!/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 '' + + def run(self): + if self.env['runtime']['inputManager'].noKeyPressed(): + return + if self.env['screen']['newAttribDelta'] != '': + return + if self.env['runtime']['screenManager'].isScreenChange(): + return + if self.env['runtime']['cursorManager'].isCursorVerticalMove(): + return + if len(self.env['input']['currInput']) != 1: + return + if not self.env['input']['currInput'][0] in ['KEY_UP','KEY_DOWN']: + return + prevLine = self.env['screen']['oldContentText'].split('\n')[self.env['screen']['newCursor']['y']] + currLine = self.env['screen']['newContentText'].split('\n')[self.env['screen']['newCursor']['y']] + if not currLine.isspace(): + currPrompt = currLine.find('$') + rootPrompt = currLine.find('#') + if currPrompt <= 0: + if rootPrompt > 0: + currPrompt = rootPrompt + else: + announce = currLine + if currPrompt > 0: + remove_digits = str.maketrans('0123456789', ' ') + if prevLine[:currPrompt].translate(remove_digits) == currLine[:currPrompt].translate(remove_digits): + announce = currLine[currPrompt+1:] + else: + announce = currLine + + if currLine.isspace(): + self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True, flush=False) + else: + self.env['runtime']['outputManager'].presentText(announce, interrupt=True, flush=False) + self.env['commandsIgnore']['onScreenUpdate']['CHAR_DELETE_ECHO'] = True + self.env['commandsIgnore']['onScreenUpdate']['CHAR_ECHO'] = True + self.env['commandsIgnore']['onScreenUpdate']['INCOMING_IGNORE'] = True + def setCallback(self, callback): + pass + diff --git a/src/fenrir/commands/onScreenUpdate/deactive/75000-incoming_promote.py b/src/fenrir/commands/onScreenUpdate/deactive/75000-incoming_promote.py new file mode 100644 index 00000000..a39b0688 --- /dev/null +++ b/src/fenrir/commands/onScreenUpdate/deactive/75000-incoming_promote.py @@ -0,0 +1,39 @@ +#!/bin/python +import time +# -*- 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('promote', 'enabled'): + return + if self.env['runtime']['settingsManager'].getSetting('promote', 'list').strip(" \t\n") == '': + return + if self.env['screen']['newDelta'] == '': + return + if int(time.time() - self.env['input']['lastInputTime']) < self.env['runtime']['settingsManager'].getSettingAsInt('promote', 'inactiveTimeoutSec'): + return + if len(self.env['runtime']['settingsManager'].getSetting('promote', 'list')) == 0: + return + for promote in self.env['runtime']['settingsManager'].getSetting('promote', 'list').split(','): + if promote in self.env['screen']['newDelta']: + self.env['runtime']['outputManager'].playSoundIcon('PromotedText') + self.env['input']['lastInputTime'] = time.time() + return + + def setCallback(self, callback): + pass + From d90c6a85e13960e098f65f500cb2551ababbefbd Mon Sep 17 00:00:00 2001 From: chrys Date: Fri, 30 Jun 2017 20:08:38 +0200 Subject: [PATCH 23/96] move some commands to onScreenUpdate (WIP) --- .../onScreenUpdate/deactive/70000-incoming.py | 41 ------------------- .../deactive/75000-incoming_promote.py | 39 ------------------ 2 files changed, 80 deletions(-) delete mode 100644 src/fenrir/commands/onScreenUpdate/deactive/70000-incoming.py delete mode 100644 src/fenrir/commands/onScreenUpdate/deactive/75000-incoming_promote.py diff --git a/src/fenrir/commands/onScreenUpdate/deactive/70000-incoming.py b/src/fenrir/commands/onScreenUpdate/deactive/70000-incoming.py deleted file mode 100644 index ea37193d..00000000 --- a/src/fenrir/commands/onScreenUpdate/deactive/70000-incoming.py +++ /dev/null @@ -1,41 +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 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']['y'] - self.env['screen']['oldCursor']['y']) == 1: - # 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): - pass - diff --git a/src/fenrir/commands/onScreenUpdate/deactive/75000-incoming_promote.py b/src/fenrir/commands/onScreenUpdate/deactive/75000-incoming_promote.py deleted file mode 100644 index a39b0688..00000000 --- a/src/fenrir/commands/onScreenUpdate/deactive/75000-incoming_promote.py +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/python -import time -# -*- 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('promote', 'enabled'): - return - if self.env['runtime']['settingsManager'].getSetting('promote', 'list').strip(" \t\n") == '': - return - if self.env['screen']['newDelta'] == '': - return - if int(time.time() - self.env['input']['lastInputTime']) < self.env['runtime']['settingsManager'].getSettingAsInt('promote', 'inactiveTimeoutSec'): - return - if len(self.env['runtime']['settingsManager'].getSetting('promote', 'list')) == 0: - return - for promote in self.env['runtime']['settingsManager'].getSetting('promote', 'list').split(','): - if promote in self.env['screen']['newDelta']: - self.env['runtime']['outputManager'].playSoundIcon('PromotedText') - self.env['input']['lastInputTime'] = time.time() - return - - def setCallback(self, callback): - pass - From b15efce9d745cbc8533b87bdbf3979fc6b4767d9 Mon Sep 17 00:00:00 2001 From: chrys Date: Fri, 30 Jun 2017 20:08:42 +0200 Subject: [PATCH 24/96] move some commands to onScreenUpdate (WIP) --- .../commands/onScreenUpdate/70000-incoming.py | 42 +++++++++++++++++++ .../onScreenUpdate/75000-incoming_promote.py | 39 +++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 src/fenrir/commands/onScreenUpdate/70000-incoming.py create mode 100644 src/fenrir/commands/onScreenUpdate/75000-incoming_promote.py diff --git a/src/fenrir/commands/onScreenUpdate/70000-incoming.py b/src/fenrir/commands/onScreenUpdate/70000-incoming.py new file mode 100644 index 00000000..ca395c1c --- /dev/null +++ b/src/fenrir/commands/onScreenUpdate/70000-incoming.py @@ -0,0 +1,42 @@ +#!/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 + 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']['y'] - self.env['screen']['oldCursor']['y']) == 1: + # 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): + pass + diff --git a/src/fenrir/commands/onScreenUpdate/75000-incoming_promote.py b/src/fenrir/commands/onScreenUpdate/75000-incoming_promote.py new file mode 100644 index 00000000..e7f4586b --- /dev/null +++ b/src/fenrir/commands/onScreenUpdate/75000-incoming_promote.py @@ -0,0 +1,39 @@ +#!/bin/python +import time +# -*- 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('promote', 'enabled'): + return + if self.env['runtime']['settingsManager'].getSetting('promote', 'list').strip(" \t\n") == '': + return + if len(self.env['screen']['newDelta']) <= 2: + return + if int(time.time() - self.env['input']['lastInputTime']) < self.env['runtime']['settingsManager'].getSettingAsInt('promote', 'inactiveTimeoutSec'): + return + if len(self.env['runtime']['settingsManager'].getSetting('promote', 'list')) == 0: + return + for promote in self.env['runtime']['settingsManager'].getSetting('promote', 'list').split(','): + if promote in self.env['screen']['newDelta']: + self.env['runtime']['outputManager'].playSoundIcon('PromotedText') + self.env['input']['lastInputTime'] = time.time() + return + + def setCallback(self, callback): + pass + From 96a1055ec3b3ade74428b2af176f9c6f16bf649a Mon Sep 17 00:00:00 2001 From: chrys Date: Fri, 30 Jun 2017 20:19:55 +0200 Subject: [PATCH 25/96] adjust onScreenUpdate commands --- .../onScreenUpdate/65000-char_delete_echo.py | 19 ++++++++----------- .../commands/onScreenUpdate/70000-incoming.py | 3 +-- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/fenrir/commands/onScreenUpdate/65000-char_delete_echo.py b/src/fenrir/commands/onScreenUpdate/65000-char_delete_echo.py index 77cce4c0..e56cb644 100644 --- a/src/fenrir/commands/onScreenUpdate/65000-char_delete_echo.py +++ b/src/fenrir/commands/onScreenUpdate/65000-char_delete_echo.py @@ -17,32 +17,29 @@ class command(): return 'No Description found' def run(self): - print('drin') - #if not self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'charDeleteEcho'): - # return - + 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 + 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 not self.env['runtime']['screenManager'].isNegativeDelta(): + return # too much for a single backspace... # word begin produce a diff wiht len == 2 |a | others with 1 |a| - #if len(self.env['screen']['newNegativeDelta']) > 2: - # return + if len(self.env['screen']['newNegativeDelta']) > 2: + return currNegativeDelta = self.env['screen']['newNegativeDelta'] #if len(currNegativeDelta.strip()) != len(currNegativeDelta) and \ # currNegativeDelta.strip() != '': # currNegativeDelta = currNegativeDelta.strip() self.env['runtime']['outputManager'].presentText(currNegativeDelta, interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) - print('danach',currNegativeDelta,'d') def setCallback(self, callback): pass diff --git a/src/fenrir/commands/onScreenUpdate/70000-incoming.py b/src/fenrir/commands/onScreenUpdate/70000-incoming.py index ca395c1c..d632a1cc 100644 --- a/src/fenrir/commands/onScreenUpdate/70000-incoming.py +++ b/src/fenrir/commands/onScreenUpdate/70000-incoming.py @@ -17,13 +17,12 @@ 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: + if len(self.env['screen']['newDelta']) <=2: return # its a cursor movement (experimental) - maybe also check current shortcut string? From ded4e84699794002b3f0ea775dc58f6ca102322f Mon Sep 17 00:00:00 2001 From: chrys Date: Fri, 30 Jun 2017 20:39:06 +0200 Subject: [PATCH 26/96] fix deletion --- .../commands/onScreenUpdate/65000-char_delete_echo.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/fenrir/commands/onScreenUpdate/65000-char_delete_echo.py b/src/fenrir/commands/onScreenUpdate/65000-char_delete_echo.py index e56cb644..1c13002a 100644 --- a/src/fenrir/commands/onScreenUpdate/65000-char_delete_echo.py +++ b/src/fenrir/commands/onScreenUpdate/65000-char_delete_echo.py @@ -36,9 +36,9 @@ class command(): if len(self.env['screen']['newNegativeDelta']) > 2: return currNegativeDelta = self.env['screen']['newNegativeDelta'] - #if len(currNegativeDelta.strip()) != len(currNegativeDelta) and \ - # currNegativeDelta.strip() != '': - # currNegativeDelta = currNegativeDelta.strip() + if len(currNegativeDelta.strip()) != len(currNegativeDelta) and \ + currNegativeDelta.strip() != '': + currNegativeDelta = currNegativeDelta.strip() self.env['runtime']['outputManager'].presentText(currNegativeDelta, interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) def setCallback(self, callback): pass From 826b981aba305e4139cd9775d6411ae905525f86 Mon Sep 17 00:00:00 2001 From: chrys Date: Fri, 30 Jun 2017 21:13:02 +0200 Subject: [PATCH 27/96] sync --- src/fenrir/commands/onScreenUpdate/65000-char_delete_echo.py | 1 - src/fenrir/core/fenrirManager.py | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fenrir/commands/onScreenUpdate/65000-char_delete_echo.py b/src/fenrir/commands/onScreenUpdate/65000-char_delete_echo.py index 1c13002a..8bff19c6 100644 --- a/src/fenrir/commands/onScreenUpdate/65000-char_delete_echo.py +++ b/src/fenrir/commands/onScreenUpdate/65000-char_delete_echo.py @@ -24,7 +24,6 @@ class command(): return # More than just a deletion happend - if self.env['runtime']['screenManager'].isDelta(): return # no deletion diff --git a/src/fenrir/core/fenrirManager.py b/src/fenrir/core/fenrirManager.py index 8fe5403f..4216115b 100644 --- a/src/fenrir/core/fenrirManager.py +++ b/src/fenrir/core/fenrirManager.py @@ -54,6 +54,7 @@ class fenrirManager(): if eventReceived: self.prepareCommand() if not (self.wasCommand or self.environment['general']['tutorialMode']) or self.environment['runtime']['screenManager'].isSuspendingScreen(): + print('ignore screen', self.environment['runtime']['screenManager'].isSuspendingScreen()) self.environment['runtime']['inputManager'].writeEventBuffer() if self.environment['runtime']['inputManager'].noKeyPressed(): if self.wasCommand: From 6d026f23c3b78ae92d11ded12f51343393dbf1c6 Mon Sep 17 00:00:00 2001 From: chrys Date: Fri, 30 Jun 2017 21:26:59 +0200 Subject: [PATCH 28/96] sync --- src/fenrir/core/fenrirManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fenrir/core/fenrirManager.py b/src/fenrir/core/fenrirManager.py index 4216115b..0874fe30 100644 --- a/src/fenrir/core/fenrirManager.py +++ b/src/fenrir/core/fenrirManager.py @@ -64,7 +64,7 @@ class fenrirManager(): self.environment['runtime']['inputManager'].clearEventBuffer() if self.environment['input']['keyForeward'] > 0: self.environment['input']['keyForeward'] -=1 - #self.environment['runtime']['screenManager'].update('onInput') + self.environment['runtime']['screenManager'].update('onInput') self.environment['runtime']['commandManager'].executeDefaultTrigger('onInput') self.handleCommands() def handleScreenChange(self): From f39ea0b14e2fa56c9a31572a2c3f0e52ca6d97b4 Mon Sep 17 00:00:00 2001 From: chrys Date: Fri, 30 Jun 2017 21:27:12 +0200 Subject: [PATCH 29/96] sync --- src/fenrir/core/fenrirManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fenrir/core/fenrirManager.py b/src/fenrir/core/fenrirManager.py index 0874fe30..4216115b 100644 --- a/src/fenrir/core/fenrirManager.py +++ b/src/fenrir/core/fenrirManager.py @@ -64,7 +64,7 @@ class fenrirManager(): self.environment['runtime']['inputManager'].clearEventBuffer() if self.environment['input']['keyForeward'] > 0: self.environment['input']['keyForeward'] -=1 - self.environment['runtime']['screenManager'].update('onInput') + #self.environment['runtime']['screenManager'].update('onInput') self.environment['runtime']['commandManager'].executeDefaultTrigger('onInput') self.handleCommands() def handleScreenChange(self): From b772c0736ee4e838595d37747c66c92a07fce7b4 Mon Sep 17 00:00:00 2001 From: chrys Date: Fri, 30 Jun 2017 21:27:44 +0200 Subject: [PATCH 30/96] sync --- src/fenrir/core/fenrirManager.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/fenrir/core/fenrirManager.py b/src/fenrir/core/fenrirManager.py index 4216115b..0d4f3ab2 100644 --- a/src/fenrir/core/fenrirManager.py +++ b/src/fenrir/core/fenrirManager.py @@ -91,8 +91,10 @@ class fenrirManager(): ''' self.environment['runtime']['commandManager'].executeDefaultTrigger('onScreenUpdate') #print(time.time() -s) + def handlePlugInputDevice(self): self.environment['runtime']['commandManager'].executeDefaultTrigger('PlugInputDevice') + def handleHeartBeat(self): self.environment['runtime']['commandManager'].executeDefaultTrigger('onHeartBeat') #self.environment['runtime']['outputManager'].brailleText(flush=False) From 045539bb4624ae5cd7365faa74f8481884a44655 Mon Sep 17 00:00:00 2001 From: chrys Date: Fri, 30 Jun 2017 22:07:56 +0200 Subject: [PATCH 31/96] add debug flag --- src/fenrir/core/fenrirManager.py | 4 ++-- src/fenrir/core/settingsManager.py | 27 +++++++++++++++++---------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/fenrir/core/fenrirManager.py b/src/fenrir/core/fenrirManager.py index 0d4f3ab2..8ea01b67 100644 --- a/src/fenrir/core/fenrirManager.py +++ b/src/fenrir/core/fenrirManager.py @@ -37,7 +37,8 @@ class fenrirManager(): 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', const=True, default='', nargs='?', help='Turns on Debugmode') try: args = parser.parse_args() except Exception as e: @@ -54,7 +55,6 @@ class fenrirManager(): if eventReceived: self.prepareCommand() if not (self.wasCommand or self.environment['general']['tutorialMode']) or self.environment['runtime']['screenManager'].isSuspendingScreen(): - print('ignore screen', self.environment['runtime']['screenManager'].isSuspendingScreen()) self.environment['runtime']['inputManager'].writeEventBuffer() if self.environment['runtime']['inputManager'].noKeyPressed(): if self.wasCommand: diff --git a/src/fenrir/core/settingsManager.py b/src/fenrir/core/settingsManager.py index 069a8564..df0e65c4 100644 --- a/src/fenrir/core/settingsManager.py +++ b/src/fenrir/core/settingsManager.py @@ -226,8 +226,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 +244,8 @@ 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) - print(optionArgDict) - return optionArgDict + self.setOptionArgDict(section, option, value) + def initFenrirConfig(self, cliArgs, fenrirManager = None, environment = environment.environment): settingsRoot = '/etc/fenrir/' settingsFile = cliArgs.setting @@ -272,11 +275,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')) From 8ddd9f777b10a1a0c59297f1895a421c5e774007 Mon Sep 17 00:00:00 2001 From: chrys Date: Fri, 30 Jun 2017 22:17:04 +0200 Subject: [PATCH 32/96] add self.settingArgDict to debug --- src/fenrir/core/settingsManager.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/fenrir/core/settingsManager.py b/src/fenrir/core/settingsManager.py index df0e65c4..eac42f6f 100644 --- a/src/fenrir/core/settingsManager.py +++ b/src/fenrir/core/settingsManager.py @@ -334,9 +334,10 @@ class settingsManager(): 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 From 089c3265a975d4d434809f1e9a5a2fe6669d7add Mon Sep 17 00:00:00 2001 From: chrys Date: Fri, 30 Jun 2017 22:33:10 +0200 Subject: [PATCH 33/96] improve -d --- src/fenrir/core/fenrirManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fenrir/core/fenrirManager.py b/src/fenrir/core/fenrirManager.py index 8ea01b67..151be8a5 100644 --- a/src/fenrir/core/fenrirManager.py +++ b/src/fenrir/core/fenrirManager.py @@ -38,7 +38,7 @@ class fenrirManager(): parser = argparse.ArgumentParser(description="Fenrir Help") parser.add_argument('-s', '--setting', metavar='SETTING-FILE', default='/etc/fenrir/settings/settings.conf', help='Use a specified settingsfile') parser.add_argument('-o', '--options', metavar='SECTION#SETTING=VALUE,..', default='', help='Overwrite options in given settings file') - parser.add_argument('-d', '--debug', const=True, default='', nargs='?', help='Turns on Debugmode') + parser.add_argument('-d', '--debug', action='store_true', help='Turns on Debugmode') try: args = parser.parse_args() except Exception as e: From c633197b43579da475fdf45dd4669dffaf2a54c5 Mon Sep 17 00:00:00 2001 From: chrys Date: Fri, 30 Jun 2017 23:04:03 +0200 Subject: [PATCH 34/96] add debug for scrreen ignore --- src/fenrir/core/screenManager.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/fenrir/core/screenManager.py b/src/fenrir/core/screenManager.py index c7d14c19..e59ae166 100644 --- a/src/fenrir/core/screenManager.py +++ b/src/fenrir/core/screenManager.py @@ -21,7 +21,7 @@ class screenManager(): self.env['runtime']['settingsManager'].shutdownDriver('screenDriver') def update(self, trigger='onUpdate'): - self.env['runtime']['screenDriver'].getCurrScreen() + self.env['runtime']['screenDriver'].getCurrScreen() if trigger == 'onScreenChange': self.env['runtime']['screenDriver'].getSessionInformation() self.env['screen']['oldApplication'] = self.env['screen']['newApplication'] @@ -43,6 +43,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): From 02b16688155d7b3e274d7ddab0a0632141ed69ec Mon Sep 17 00:00:00 2001 From: chrys Date: Fri, 30 Jun 2017 23:59:05 +0200 Subject: [PATCH 35/96] add more debug --- src/fenrir/core/eventManager.py | 10 +++------- src/fenrir/core/screenManager.py | 4 +++- src/fenrir/screenDriver/vcsaDriver.py | 1 + 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/fenrir/core/eventManager.py b/src/fenrir/core/eventManager.py index 69a11455..d6c06475 100644 --- a/src/fenrir/core/eventManager.py +++ b/src/fenrir/core/eventManager.py @@ -44,7 +44,7 @@ class eventManager(): self.eventDispatcher(event) #print('NET loop ' + str(time.time() - st)) def eventDispatcher(self, event): - print(event['Type'], self._eventQueue.qsize()) + 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 event['Type'] == fenrirEventType.Ignore: @@ -53,11 +53,9 @@ class eventManager(): self.handleStopMainLoop() return elif event['Type'] == fenrirEventType.ScreenUpdate: - pass self.env['runtime']['fenrirManager'].handleScreenUpdate() elif event['Type'] == fenrirEventType.KeyboardInput: self.env['runtime']['fenrirManager'].handleInput() - #self.env['runtime']['fenrirManager'].handleScreenUpdate() elif event['Type'] == fenrirEventType.BrailleInput: pass elif event['Type'] == fenrirEventType.PlugInputDevice: @@ -68,7 +66,6 @@ class eventManager(): self.env['runtime']['fenrirManager'].handleScreenChange() elif event['Type'] == fenrirEventType.HeartBeat: self.env['runtime']['fenrirManager'].handleHeartBeat() - #print('HeartBeat at {0} {1}'.format(event['Type'], event['Data'] )) def isMainEventLoopRunning(self): return self._mainLoopRunning.value == 1 def startMainEventLoop(self): @@ -76,7 +73,7 @@ class eventManager(): while( self.isMainEventLoopRunning()): st = time.time() self.proceedEventLoop() - print('ALL loop ' + str(time.time() - st)) + def handleStopMainLoop(self): self._mainLoopRunning.value = 0 time.sleep(0.1) @@ -141,8 +138,7 @@ class eventManager(): else: Data = function() except Exception as e: - pass - print(e) + self.env['runtime']['debug'].writeDebugOut('eventManager:simpleEventWorkerThread:function():' + st(e),debug.debugLevel.ERROR) self.putToEventQueue(event, Data) if runOnce: break diff --git a/src/fenrir/core/screenManager.py b/src/fenrir/core/screenManager.py index e59ae166..3d159901 100644 --- a/src/fenrir/core/screenManager.py +++ b/src/fenrir/core/screenManager.py @@ -21,9 +21,11 @@ class screenManager(): self.env['runtime']['settingsManager'].shutdownDriver('screenDriver') def update(self, trigger='onUpdate'): - self.env['runtime']['screenDriver'].getCurrScreen() + 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() diff --git a/src/fenrir/screenDriver/vcsaDriver.py b/src/fenrir/screenDriver/vcsaDriver.py index 2aa835c5..dc5cbf41 100644 --- a/src/fenrir/screenDriver/vcsaDriver.py +++ b/src/fenrir/screenDriver/vcsaDriver.py @@ -135,6 +135,7 @@ class driver(): def update(self, trigger='onUpdate'): if trigger == 'onInput': # no need for an update on input for VCSA return + #print(self.env['screen']['newTTY'], self.env['screen']['oldTTY']) newContentBytes = b'' try: # read screen From 099aa2da0dfd03af8fd6ba49a5fd7c7e31bb24a0 Mon Sep 17 00:00:00 2001 From: chrys Date: Sat, 1 Jul 2017 22:54:31 +0200 Subject: [PATCH 36/96] set custom command path to emtpy; load customs after defaults --- config/settings/espeak.settings.conf | 2 +- config/settings/settings.conf | 4 ++-- config/settings/settings.conf.storm | 2 +- src/fenrir/core/commandManager.py | 7 ++++--- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/config/settings/espeak.settings.conf b/config/settings/espeak.settings.conf index eb2b95cd..56f2d781 100644 --- a/config/settings/espeak.settings.conf +++ b/config/settings/espeak.settings.conf @@ -163,7 +163,7 @@ dateFormat=%A, %B %d, %Y autoSpellCheck=True spellCheckLanguage=en_US scriptPath=/usr/share/fenrir/scripts -commandPath=/usr/share/fenrir/commands +commandPath= [focus] cursor=True diff --git a/config/settings/settings.conf b/config/settings/settings.conf index d055a363..9033d4fc 100644 --- a/config/settings/settings.conf +++ b/config/settings/settings.conf @@ -147,7 +147,7 @@ interruptOnKeyPressFilter= doubleTapTimeout=0.2 [general] -debugLevel=1 +debugLevel=0 punctuationProfile=default punctuationLevel=some respectPunctuationPause=True @@ -168,7 +168,7 @@ spellCheckLanguage=en_US # path for your scripts "scriptKey" functionality scriptPath=/usr/share/fenrir/scripts # overload commands, and create new one without changing Fenrir default -commandPath=/usr/share/fenrir/commands +commandPath= [focus] #follow the text cursor diff --git a/config/settings/settings.conf.storm b/config/settings/settings.conf.storm index b4e00d7c..b2f93cb2 100644 --- a/config/settings/settings.conf.storm +++ b/config/settings/settings.conf.storm @@ -116,7 +116,7 @@ autoSpellCheck=True spellCheckLanguage=en_US scriptPath=/usr/share/fenrir/scripts # overload commands, and create new one without changing Fenrir default -commandPath=/usr/share/fenrir/commands +commandPath= [focus] #follow the text cursor diff --git a/src/fenrir/core/commandManager.py b/src/fenrir/core/commandManager.py index d5dde35c..24e361da 100644 --- a/src/fenrir/core/commandManager.py +++ b/src/fenrir/core/commandManager.py @@ -18,9 +18,10 @@ class commandManager(): 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() From 570d800152fe01dc8ca5ac2e93043a11bd8344e0 Mon Sep 17 00:00:00 2001 From: chrys Date: Sat, 1 Jul 2017 23:05:50 +0200 Subject: [PATCH 37/96] clean up --- src/fenrir/screenDriver/vcsaDriver.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/fenrir/screenDriver/vcsaDriver.py b/src/fenrir/screenDriver/vcsaDriver.py index dc5cbf41..b60a7d29 100644 --- a/src/fenrir/screenDriver/vcsaDriver.py +++ b/src/fenrir/screenDriver/vcsaDriver.py @@ -98,7 +98,6 @@ class driver(): self.env['screen']['autoIgnoreScreens'] = [] def updateWatchdog(self,active , eventQueue): - currScreen = '2' vcsa = {} for i in range(1,7): vcsa[str(i)] = open('/dev/vcsa'+str(i),'rb') From 9c137ef27b0d82c5140b1f716d78354a3f097486 Mon Sep 17 00:00:00 2001 From: chrys Date: Sat, 1 Jul 2017 23:10:48 +0200 Subject: [PATCH 38/96] add debug --- src/fenrir/screenDriver/vcsaDriver.py | 66 ++++++++++++++------------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/src/fenrir/screenDriver/vcsaDriver.py b/src/fenrir/screenDriver/vcsaDriver.py index b60a7d29..42d76d11 100644 --- a/src/fenrir/screenDriver/vcsaDriver.py +++ b/src/fenrir/screenDriver/vcsaDriver.py @@ -98,39 +98,41 @@ class driver(): self.env['screen']['autoIgnoreScreens'] = [] def updateWatchdog(self,active , eventQueue): - vcsa = {} - for i in range(1,7): - vcsa[str(i)] = open('/dev/vcsa'+str(i),'rb') + try: + vcsa = {} + for i in range(1,7): + vcsa[str(i)] = open('/dev/vcsa'+str(i),'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(): - tty.seek(0) - currScreen = str(tty.read()[3:-1]) - if currScreen != oldScreen: - watchdog.unregister(vcsa[ oldScreen ]) - watchdog.register(vcsa[ currScreen ], select.EPOLLPRI) - oldScreen = currScreen - eventQueue.put({"Type":fenrirEventType.ScreenChanged,"Data":''}) - vcsa[currScreen].seek(0) - lastScreenContent = vcsa[currScreen].read() - else: - vcsa[currScreen].seek(0) - screenContent = vcsa[currScreen].read() - if screenContent != lastScreenContent: - eventQueue.put({"Type":fenrirEventType.ScreenUpdate,"Data":''}) - lastScreenContent = screenContent - + 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(): + tty.seek(0) + currScreen = str(tty.read()[3:-1]) + if currScreen != oldScreen: + watchdog.unregister(vcsa[ oldScreen ]) + watchdog.register(vcsa[ currScreen ], select.EPOLLPRI) + oldScreen = currScreen + eventQueue.put({"Type":fenrirEventType.ScreenChanged,"Data":''}) + vcsa[currScreen].seek(0) + lastScreenContent = vcsa[currScreen].read() + else: + 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 update(self, trigger='onUpdate'): if trigger == 'onInput': # no need for an update on input for VCSA return From 2c7d3426e5e568fcf72554e9d98d9cec1b3d4dcc Mon Sep 17 00:00:00 2001 From: chrys Date: Sun, 2 Jul 2017 00:41:26 +0200 Subject: [PATCH 39/96] add debug --- src/fenrir/screenDriver/vcsaDriver.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/fenrir/screenDriver/vcsaDriver.py b/src/fenrir/screenDriver/vcsaDriver.py index 42d76d11..dfdaf628 100644 --- a/src/fenrir/screenDriver/vcsaDriver.py +++ b/src/fenrir/screenDriver/vcsaDriver.py @@ -116,6 +116,7 @@ class driver(): fileno = change[0] event = change[1] if fileno == tty.fileno(): + self.env['runtime']['debug'].writeDebugOut('ScreenChange' + str(e),debug.debugLevel.INFO) tty.seek(0) currScreen = str(tty.read()[3:-1]) if currScreen != oldScreen: @@ -126,6 +127,7 @@ class driver(): vcsa[currScreen].seek(0) lastScreenContent = vcsa[currScreen].read() else: + self.env['runtime']['debug'].writeDebugOut('ScreenUpdate',debug.debugLevel.INFO) vcsa[currScreen].seek(0) screenContent = vcsa[currScreen].read() if screenContent != lastScreenContent: From e47af4d30ad9f93625b529d05c3da219e75c3c27 Mon Sep 17 00:00:00 2001 From: chrys Date: Sun, 2 Jul 2017 00:51:56 +0200 Subject: [PATCH 40/96] fix debug --- src/fenrir/screenDriver/vcsaDriver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fenrir/screenDriver/vcsaDriver.py b/src/fenrir/screenDriver/vcsaDriver.py index dfdaf628..8af34aba 100644 --- a/src/fenrir/screenDriver/vcsaDriver.py +++ b/src/fenrir/screenDriver/vcsaDriver.py @@ -116,7 +116,7 @@ class driver(): fileno = change[0] event = change[1] if fileno == tty.fileno(): - self.env['runtime']['debug'].writeDebugOut('ScreenChange' + str(e),debug.debugLevel.INFO) + self.env['runtime']['debug'].writeDebugOut('ScreenChange',debug.debugLevel.INFO) tty.seek(0) currScreen = str(tty.read()[3:-1]) if currScreen != oldScreen: From 2f259d7bf41b8a77908454c742b6d78c241546ee Mon Sep 17 00:00:00 2001 From: chrys Date: Sun, 2 Jul 2017 22:03:17 +0200 Subject: [PATCH 41/96] add initial udev watchdog --- src/fenrir/inputDriver/evdevDriver.py | 32 ++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/fenrir/inputDriver/evdevDriver.py b/src/fenrir/inputDriver/evdevDriver.py index c8d0d07f..32dfad64 100644 --- a/src/fenrir/inputDriver/evdevDriver.py +++ b/src/fenrir/inputDriver/evdevDriver.py @@ -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,6 +15,12 @@ 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 @@ -36,17 +44,35 @@ class driver(): 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() - self.env['runtime']['eventManager'].addSimpleEventThread(fenrirEventType.PlugInputDevice, self.plugInputDeviceWatchdog) + 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 plugInputDeviceWatchdog(self): - time.sleep(2.5) + def plugInputDeviceWatchdogUdev(self,active , eventQueue): + context = pyudev.Context() + monitor = pyudev.Monitor.from_netlink(context) + 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: From da073404b1a3000375cb3101c9f1c8dd9e7e9ea5 Mon Sep 17 00:00:00 2001 From: chrys Date: Sun, 2 Jul 2017 22:19:50 +0200 Subject: [PATCH 42/96] add initial udev watchdog --- src/fenrir/inputDriver/evdevDriver.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/fenrir/inputDriver/evdevDriver.py b/src/fenrir/inputDriver/evdevDriver.py index 32dfad64..99d25af0 100644 --- a/src/fenrir/inputDriver/evdevDriver.py +++ b/src/fenrir/inputDriver/evdevDriver.py @@ -293,7 +293,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 From b7982f1ba12b84ca00fb08f7075923d38f38dee7 Mon Sep 17 00:00:00 2001 From: chrys87 Date: Mon, 3 Jul 2017 16:49:45 +0200 Subject: [PATCH 43/96] update wiki --- docu/user.txt | 244 +++++++++++++++++++++++++++++++------------------- 1 file changed, 150 insertions(+), 94 deletions(-) diff --git a/docu/user.txt b/docu/user.txt index c1940dfd..937e3a90 100644 --- a/docu/user.txt +++ b/docu/user.txt @@ -13,7 +13,7 @@ Fenrir requires several drivers to interact with the operating system. ===== Speech Drivers ===== -A speech driver is for communication with the text to speech system like [[speech-dispatcher|Speech-dispatcher]] or [[espeak|Espeak]]. \\ +A speech driver is for communication with the text to speech system like [[#SpeechDispatcher|Speech-Dispatcher]] or [[http://espeak.sourceforge.net|Espeak]]. \\ See section [[#Speech|Speech]] in ''settings.conf'' for more information. @@ -26,10 +26,18 @@ Dependency's: * speech-dispatcher (installed and configured, [[https://devel.freebsoft.org/speechd#sec2|Documentation]]) * python-speechd + +==== Espeak ==== + +Uses espeak via python bindings. + +Dependency's: + * Espeak or Espeak-ng + * [[https://launchpad.net/python-espeak|python-espeak]] ==== Generic ==== -This invokes speech via a sub-process. This is almost the same as entering the command by commandline. The performance depends on the overhead of the speech syntheses application but it is really flexible. +This invokes speech via a sub-process. This is almost the same as entering the command by commandline. The performance depends on the overhead of the speech synthesis application but it is really flexible. Dependency's: * Espeak or Espeak-ng @@ -132,7 +140,7 @@ Fenrir can run without installation. It just requires the dependencies to be ins We recommend to try it out before installation to be sure everything works and prevent yourself from experiencing a non-talking environment. ===== Try Out ===== -Fenrir does not require installation. You can try out if everything works before you want to install. In this way you can be sure that your system doesnt break or does not talking. +Fenrir does not require installation. You can try it and make sure everything works before you decide to install. In this way you can be sure that your system doesnt break or stop talking. for that you can just grab the code and run as root ''src/fenrir/fenrir'' (in foreground) or ''src/fenrir/fenrir-daemon'' (in background, that one is used by systemd for autostart) ===== Install it ===== @@ -149,7 +157,8 @@ For Arch there are PKGBUILDs in the AUR: - Download the latest stable version from the [[https://linux-a11y.org/index.php?page=fenrir-screenreader|Fenrir-Project]] site. - Unpack the archive - - install the needed Dependencys an standard installation requires the following. + - Check the needed Dependencys by running [[https://github.com/chrys87/fenrir/blob/master/check-dependencys.py|check-dependencys.py]] script + - install the needed missing dependencys an standard installation requires the following: * python3 >= 3.3 (and all the following is needed for python3 ) * python3-speechd (screen) * python3-dbus (screen) @@ -159,7 +168,7 @@ For Arch there are PKGBUILDs in the AUR: * python3-pyenchant (spellchecker) * your language for aspell (aspell-) (spellchecker) * sox (sound) - * For an individual installation see [[#Support and Requirements|Support and Requirements]] or cunsult the [[https://github.com/chrys87/fenrir/blob/master/README.md|Readme]]) + * For an individual installation see [[#Support and Requirements|Support and Requirements]] or consult the [[https://github.com/chrys87/fenrir/blob/master/README.md|Readme]]) - run "install.sh" as root this installs fenrir as the following @@ -186,21 +195,22 @@ To enable auto start on system boot: ====== First Steps ====== If you are using Fenrir for the first time you may want to take a look at these resources: - * [[#Keyindings|Keyindings]] + * [[#Keybindings|Keybindings]] * [[#Tutorial Mode|Tutorial Mode]] ====== Features ====== ===== Commands ===== -==== Keyindings ==== +==== Keybindings ==== -Normal commands can invoked in to ways: +Normal commands can be invoked in two ways: - Using a Metakey ([[#Fenrir Key|FenrirKey]]) - - Shortcuts with an single key - + - Shortcuts with a single key + +See section [[#Keyboard|Keyboard]] in ''settings.conf'' for more information. === Fenrir Key === -The Fenrir Key is for invoking screen reader commands. Fenrir can handle more than one Key as FenrirKey at the same time. +The Fenrir Key is for invoking screen reader commands. Fenrir can utilize more than one FenrirKey at the same time. By default the following keys are used: - Insert - KeyPad Insert @@ -208,7 +218,7 @@ By default the following keys are used: === Script Key === To invoke "Scripts" the Script Key is mandatory. The shortcut is encoded in the filename of the script. See [[#Scripting|Scripting]] -===Desktop Layout=== +=== Desktop Layout === ^Shortcut ^Command ^ |FenrirKey + H|[[#Tutorial Mode|toggle tutorial mode]]| |CTRL|[[#shut up|shut up (interrupts speech)]]| @@ -317,6 +327,8 @@ To invoke "Scripts" the Script Key is mandatory. The shortcut is encoded in the |FenrirKey + Shift + C|[[#read current clipboard|current clipboard]]| |FenrirKey + C|[[#copy marked to clipboard|copy marked text to clipboard]]| |FenrirKey + V|[[#paste clipboard|paste clipboard contents]]| +|FenrirKey + P|[[#import clipboard from file|import clipboard from file]]| +|FenrirKey + Alt + Shift +C|[[#export clipboard to file|export clipboard to file]]| |FenrirKey + CTRL + Shift + X|[[#Remove Marks|remove marks]]| |FenrirKey + X|[[#Set mark|set mark]]| |FenrirKey + Shift + X|[[#Get text between marks|announce marked text]]| @@ -324,8 +336,8 @@ To invoke "Scripts" the Script Key is mandatory. The shortcut is encoded in the ||export clipboard to X| |FenrirKey + CTRL + Up|include Alsa volume| |FenrirKey + CTRL + Down|decrease Alsa volume| - -===Laptop Layout=== + +=== Laptop Layout === ^Shortcut ^Command ^ |FenrirKey + H|[[#Tutorial Mode|toggle tutorial mode]]| |CTRL|[[#shut up|shut up (interrupts speech)]]| @@ -335,7 +347,7 @@ To invoke "Scripts" the Script Key is mandatory. The shortcut is encoded in the |FenrirKey + U|[[#review previous line|reviews previous line]]| |FenrirKey + O|[[#review next line|reviews next line]]| |FenrirKey + Shift + J|[[#review line beginning|reviews line beginning]]| -|FenrirKey + SHFIT + L|[[#review line ending|reviews line ending]]| +|FenrirKey + Shift + L|[[#review line ending|reviews line ending]]| |FenrirKey + CTRL + J|[[#review line first character|reviews line first character]]| |FenrirKey + CTRL + L|[[#review line last character|reviews line last character]]| |FenrirKey + Alt + 1|[[#present first line|presents first line]]| @@ -343,15 +355,15 @@ To invoke "Scripts" the Script Key is mandatory. The shortcut is encoded in the |FenrirKey + K|[[#review current word|reviews current word]]| |FenrirKey + J|[[#review previous word|reviews previous word]]| |FenrirKey + L|[[#review next word|reviews next word]]| -|2 * FenrirKey + K|[[#review current word phonetic|reviews current word phonetic]]| -|2 * FenrirKey + J|[[#review previous word phonetic|reviews previous word phonetic]]| -|2 * FenrirKey + L|[[#review next word phonetic|reviews next word phonetic]]| -|FenrirKey + comma|[[#review current character|reviews current char]]| -|FenrirKey + M|[[#review previous character|reviews previous char]]| -|FenrirKey + dot|[[#review next character|reviews next char]]| -|2 * FenrirKey + comma|[[#review current character phonetic|reviews current character phonetic]]| -|2 * FenrirKey + M|[[#review previous character phonetic|reviews previous character phonetic]]| -|2 * FenrirKey + dot|[[#review next character phonetic|reviews next character phonetic]]| +|FenrirKey + CTRL + ALT + K|[[#review current word phonetic|reviews current word phonetic]]| +|FenrirKey + CTRL + ALT + J|[[#review previous word phonetic|reviews previous word phonetic]]| +|FenrirKey + CTRL + ALT + L|[[#review next word phonetic|reviews next word phonetic]]| +|FenrirKey + comma|[[#review current character|reviews current character]]| +|FenrirKey + M|[[#review previous character|reviews previous character]]| +|FenrirKey + dot|[[#review next character|reviews next character]]| +|FenrirKey + CTRL + ALT + comma|[[#review current character phonetic|reviews current character phonetic]]| +|FenrirKey + CTRL + ALT + M|[[#review previous character phonetic|reviews previous character phonetic]]| +|FenrirKey + CTRL + ALT + dot|[[#review next character phonetic|reviews next character phonetic]]| |FenrirKey + CTRL + I|[[#review up|reviews up]]| |FenrirKey + CTRL + comma|[[#review down|reviews down]]| |FenrirKey + Slash|[[#exit review|exit review]]| @@ -434,6 +446,8 @@ To invoke "Scripts" the Script Key is mandatory. The shortcut is encoded in the |FenrirKey + Shift + C|[[#read current clipboard|current clipboard]]| |FenrirKey + C|[[#copy marked to clipboard|copy marked text to clipboard]]| |FenrirKey + V|[[#paste clipboard|paste clipboard contents]]| +|FenrirKey + F5|[[#import clipboard from file|import clipboard from file]]| +|FenrirKey + Alt + Shift +C|[[#export clipboard to file|export clipboard to file]]| |FenrirKey + CTRL + Shift + X|[[#Remove Marks|remove marks]]| |FenrirKey + X|[[#Set mark|set mark]]| |FenrirKey + Shift + X|[[#Get text between marks|announce marked text]]| @@ -544,6 +558,10 @@ Read the content of the current element of the clipboard list == paste clipboard == Past whatever element is currently selected by first, last, prev or next clipboard commands. if no special clipboard is selected the first one (last copied) is used. +== export clipboard to file == +This allows you to export the current clipboard to an configurable filepath. This is useful to share the clipboard with a graphical desktop. +== import clipboard from file == +Import a clipboard from an configurable file. This is useful to share the clipboard with a graphical desktop. ==== Quick Settings ==== Fenrir provides some shortcuts to change settings temporarily and on the fly without need to permanently change the ''settings.conf'' file. === toggle braille === @@ -768,29 +786,43 @@ speaks an _ as "line". speaks an _ as underscore. for question mark an ? is appended to the word that the TTS system can announce the question correctly. ==== Custom ==== -The dict "[customDict]" is just for your own use. it does just replace the key by the value without any special functionality. This might be used to correct phonetic wrongly spoken words,make words more common or just shorter. Or even just for fun :). +The dict "[customDict]" is just for your own use, it just replace the key with the value without any special functionality. This might be used to fix incorrectly spoken words, make words more common, shorter or just for fun. :) ==== Emoticons ==== -The Emoticons dict "[emoticonDict]" contains by default some emoticons. it replaces ":)" by "smile" or "XD" by "loool". So chatting is a little more colorful. -The special on that dict is that you can toggle the substitution it on or off during run time or in settings.conf. This is useful because while doing programming or other serious work you want here colons and parans not smiles. +The Emoticons dictionary "[emoticonDict]" by default contains some emoticons. it can replace ":)" with "smile" or "XD" with "loool" Making chat more colorful. +A nice feature with this dictionary is that you can toggle the substitution on or off during run time or in settings.conf. This is useful because while doing programming or other serious work you want to hear colons and parans not smiles. ====== Configuration ====== -===== Prepare ===== -===== Settings ===== You can configure Fenrir in the following places (ordered by priority): - - /etc/fenrir/settings/settings.conf - - /config/settings/settings.conf - - run with hard coded defaults. + - Commandline Parameters ''-o'' see [[#Set settings coption|Set settings coption]] + - /etc/fenrir/settings/settings.conf see [[#Settings|Settigns]] + - /config/settings/settings.conf see [[#Settings|Settigns]] + - hard coded defaults +===== Commandline Arguments ===== +==== Set settings coption ==== +You can specify options that overwrites the setting.conf. +This is done with ''-o '' parameter. +The list of options has the following syntax + fenrir -o "section#setting=value;section#setting=value" + +For example change the sound driver to gstreamer and disable braille + fenrir -o "sound#driver=gstreamerDriver;braille#enabled=False=False" +or change debug level to verbose + fenrir -o "general#debugLevel=3" +You can find the available sections and variables here [[#Settings]] +See Syntax [[#settings.conf syntax]] ==== settings.conf syntax ==== -the syntax of the "settings.conf" is really simple and is similar to a "*.ini" file, there are 3 different elements. +the syntax of the [[#Settings|settings.conf]] is really simple and is similar to a "*.ini" file, there are 4 different elements. - Sections - Settings + - Values - Comments +A comment starts with an # and is ignored by fenrir. + # this is a comment +To group settings we have sections. A section can look like this: [Section] A setting looks like this: settingName=Value -A comment starts with an #. - # this is a comment Example: [sound] @@ -800,7 +832,7 @@ Example: # Sox is default. driver=genericDriver - +===== Settings ===== ==== Sound ==== The sound is configured in section ''[sound]''. @@ -836,7 +868,7 @@ The generic sound driver uses shell commands for play sound and frequencies. ''genericFrequencyCommand'' defines the command that is used playing frequencies. genericFrequencyCommand= -The following variable are substituted in ''genericPlayFileCommand'' and ''genericFrequencyCommand'': +The following variables are substituted in ''genericPlayFileCommand'' and ''genericFrequencyCommand'': * ''fenrirVolume'' = the current volume setting * ''fenrirSoundFile'' = the sound file for an sound icon * ''fenrirFrequence'' = the frequency to play @@ -987,9 +1019,9 @@ Values: Integer, * ''0'' = display size * ''>0'' number of cells ==== Screen ==== -The settings for screens, (TTY, PTY) is done in the ''[screen]'' section. +The settings for screens, (TTY, PTY) are configured in the ''[screen]'' section. -The driver that gets the information from a screen: +The driver to get the information from the screen: driver=vcsaDriver Available Drivers: * ''vcsaDriver'' using the VCSA driver (for TTYs), for Fenrir <1.5 just use ''vcsa'' @@ -1001,21 +1033,21 @@ The driver updates Fenrir with changes upon the screen. screenUpdateDelay=0.05 Values: in Seconds -If you want Fenrir to not be active on any screen. That can have different reasons. Maybe an X server or Wayland is running on that screen. You can make Fenrir ignore it or multiple screens seperated by '','' with: +If you want Fenrir to not be active on any screen for various reasons. Maybe an X server or Wayland is running on that screen. You can make Fenrir ignore it or multiple screens seperated by '','' with: suspendingScreen= Values: Depends on driver: * VCSA: the number of the TTY. TTY6 is ''6''. Example ignore TTY1 and TTY2: suspendingScreen=1,2 -There is also the ability to let Fenrir auto detect screens that running an X. So Screens running an GUI are ignored. +There is also the ability to let Fenrir auto detect screens that are running an X server. So Screens running an GUI are ignored. autodetectSuspendingScreen=True Values: on=''True'', off=''False'' ==== Keyboard ==== The settings for keyboard and input related configuration is located in the section ''[keyboard]'' of the ''settings.conf'' file. -Select the driver used to for grabbing the keybord and recieve shortcuts. +Select the driver used for grabbing keybord input and for recieving shortcuts. driver=evdevDriver Values: Text, available Driver Available Drivers: @@ -1028,23 +1060,23 @@ Values: * ''NOMICE'' Exclude mices from handling. * '''' just use the device with the given name. -Gives Fenrir exclusive access to the keyboard and lets it control keystrokes. This is needed to consume the Fenrir related shortcuts. +Gives Fenrir exclusive access to the keyboard and lets it control keystrokes. This is needed to intercept Fenrir related shortcuts. grabDevices=True Values: on=''True'', off=''False'' -The following just make sense if you are using an second screenreader and just wanna have some hooked events. Fenrir ignores all shortcuts then. +The following just make sense if you are using a second screenreader and just wanna have some hooked events. Fenrir ignores all shortcuts then. ignoreShortcuts=False Values: on=''True'', off=''False'' The current keyboard layout used for shortcuts. keyboardLayout=desktop - Values: A absolute Path to an Keyboard definition file or a Filename without extension located in ''/etc/fenrir/keyboard'' + Values: An absolute Path to a Keyboard definition file or a Filename without extension located in ''/etc/fenrir/keyboard'' -Announce chars while typing. +Announce characters while typing. charEcho=False Values: on=''True'', off=''False'' -Announce deleted chars +Announce deleted characters charDeleteEcho=True Values: on=''True'', off=''False'' @@ -1058,71 +1090,77 @@ Values: on=''True'', off=''False'' You can filter the keys on that the speech should interrupt interruptOnKeyPressFilter= -Values: (List) empty = all keys, otherwhise interrupt on given keys +Values: (List) empty = all keys, otherwise interrupt with specified keys The timeout that is used for double tap shortcuts doubleTapTimeout=0.2 Values: Seconds ==== General ==== -Overall stuff can be configured in section ''[general]''. +Overall settings can be configured from the section ''[general]''. Set the current debug level: debugLevel=1 Values: off=0, error=1, warning=2, info=3 -the current used punctuation and dict file: +the current punctuation and dict file in use: punctuationProfile=default Values: Text, see available profiles in ''/etc/fenrir/punctuation'' or in ''sourceTree/config/punctuation'' -The current used punctuation level. +The current punctuation level in use: punctuationLevel=some Values: Text, See available levels in the used punctuation file. -Respect pause for punctuations. +Respect pause for punctuations: respectPunctuationPause=True Values: on=''True'', off=''False'' -Add a pause on Line break. +Add a pause on Line break: newLinePause=True Values: on=''True'', off=''False'' +Specify the path where the clipboard should be exported to. +See [[#export clipboard to file|export clipboard to file]]. +The variable ''$user'' is replaced by the current logged username. + clipboardExportPath=/tmp/fenrirClipboard +Values: Text, Systemfilepath + The number of available cipboards: numberOfClipboards=10 Values: Integer, 1 - 999 -Replace emoticons like :) or ;) with there names. +Replace emoticons like :) or ;) with text insertions: emoticons=True Values: on=''True'', off=''False'' -Define the current fenrir keys. +Define the current fenrir keys: fenrirKeys=KEY_KP0,KEY_META,KEY_INSERT Values, Text list, separated by comma. -Define the current script keys. +Define the current script keys: scriptKey=KEY_COMPOSE Values, Text list, separated by comma. -The timeformat that is used for output (time command) +The time format to be used for (time command) output: timeFormat=%H:%M:%P Values: see python specification for [[https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior|datetime.strftime]] -The date format that is used for output (date command). +The date format to be used for (date command) output: dateFormat=%A, %B %d, %Y Values: see python specification for [[https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior|datetime.strftime]] -Enable or Disable the spellchecker while typing. +Enable or Disable spellcheck whilst typing: autoSpellCheck=True Values: on=''True'', off=''False'' -The used dictionary for the spellchecker. +The use of the dictionary with spellcheck: spellCheckLanguage=en_US Values: Text, see aspell dictionary's. -Folder Path for your scripts "scriptKey" functionality. +Folder Path for your scripts "scriptKey" functionality: scriptPath=/usr/share/fenrir/scripts Values: Text, Existing path on file system. -Overload commands or create new one without changing Fenrir default. +Override commands or create new ones without changing Fenrir defaults: commandPath=/usr/share/fenrir/commands Values: Text, Existing path on file system. Subfolders in commandPath are: @@ -1132,51 +1170,51 @@ Subfolders in commandPath are: * ''onScreenUpdate'' = executed when the screen is captured ==== Focus ==== -The basic focus configuration is done in section ''[focus]''. +The configuration for basic focus is in the section ''[focus]''. Follow the text cursor: cursor=True Values: on=''True'', off=''False'' -Follow highlighted text changes (Highlight Tracking) +Follow highlighted text changes (Highlight Tracking): highlight=False Values: on=''True'', off=''False'' ==== Review ==== -Configurations for the review mode are done in section ''[review]''. +Configurations for the review mode are in the section ''[review]''. -If "next word/ char" or "prev word/char" create an linebreak announce it. +If "next word/ char" or "prev word/char" create a linebreak, announce it: lineBreak=True Values: on=''True'', off=''False'' -If "next word/ char" or "prev word/char" can not be done because you reached the end of the screen announce it. +If "next word/ char" or "prev word/char" cannot be performed because you reached the end of the screen, announce it: endOfScreen=True Values: on=''True'', off=''False'' -Leave the review mode when pressing a key +Leave the review mode when pressing a key: leaveReviewOnKeypress=False Values: on=''True'', off=''False'' -Leave the review mode when changing the screen (From TTY3 to TTY4) +Leave the review mode when changing the screen (From TTY3 to TTY4): leaveReviewOnScreenChange=True Values: on=''True'', off=''False'' ==== Promote ==== -"Promoted Lists" are configured in section ''[promote]''. +"Promoted Lists" are configured in the section ''[promote]''. Turn Promoted Lists" on or off: enabled=True Values: on=''True'', off=''False'' -The minimum time interval for inactivity that activates promoting. -By default it promotes after 120 Seconds inactivity. +The minimum time interval of inactivity to activate promoting. +By default it promotes after 120 Seconds inactivity: inactiveTimeoutSec=120 Values: in Seconds -Define the list of promoted words comma seperated. +Define a list of promoted words comma seperated: list= Values: text (comma seperated) -Example to promote the word "nickname" or an bash prompt: +Example to promote the word "nickname" or a bash prompt: list=nickname,$:,#: ==== Time ==== -The automated time announcement is configured in section ''[time]''. +The automated time announcement is configured in the section ''[time]''. Time announcement is disabled by default. Turn time announcement on or off: enabled=True @@ -1190,20 +1228,20 @@ Should the date be announced (just on date change): presentDate=True Values: on=''True'', off=''False'' -Announce after a given period of seconds +Announce after a given period of seconds: delaySec=0 Value: in Seconds, 0 = Deactivated -Announce after to fix minutes in an hour. if delaySec is >0 onMinutes is ignored. +Announce after to fix minutes in an hour. if delaySec is >0 onMinutes is ignored: onMinutes=00,30 Example every 15 minutes: onMinutes=00,15,30,45 -Just play an soundicon (not interrupting) +Just play a soundicon, (not interrupting): announce=True Values: on=''True'', off=''False'' -Interrupt current speech for time announcement +Interrupt current speech for time announcement: interrupt=False Values: on=''True'', off=''False'' ====== Customization ====== @@ -1213,11 +1251,24 @@ The script key is the applications key. Usually this key can be found on the key When you name a script, the key name appears in the script seperated by the sequence __-__. So, for example, if you have a python weather script you want assigned to the script key plus the letter w you would name the script /usr/share/fenrir/scripts/weather__-__key_w.py Then, to access the script, simply press the script key and the letter w. Scripts must be executable. So, make sure to chmod 755 your script when you place it in the scripts directory. +The script gets some parameter from fenrir when it is executed. So that information is available in your script then. + +==== Parameterlist ==== +^Parameter ^Content ^ +|$1|Username of the current logged in user| + +==== Examples ==== +Script that just speaks the current username when pressing ScriptKey + H.\\ +File: ''/usr/share/fenrir/scripts/helloWorld__-__key_h.sh'': + #!/bin/bash + echo $1 + + ===== Commands ===== You can place your own commands in "/usr/share/fenrir/commands" (path is configurable in settings.conf). -Commands are python files with an special scheme. You can assign them to an shortcut using the filename without extension or place them in an hook trigger like OnInput or OnScreenChange. For deeper information see developer guide. +Commands are python files with a special scheme. You can assign them to a shortcut using the filename without an extension or place them in a hook trigger like OnInput or OnScreenChange. For further information see developer guide. Good Examples: [[https://github.com/chrys87/fenrir/blob/master/src/fenrir/commands/commands/date.py|"date.py"]] (announce the Date), [[https://github.com/chrys87/fenrir/blob/master/src/fenrir/commands/commands/shut_up.py|"shut_up.py"]] (interrupt output) -the basic scheme for an command is the following: +the basic scheme for a command is as follows: from core import debug @@ -1235,23 +1286,28 @@ the basic scheme for an command is the following: def setCallback(self, callback): pass - * [[https://github.com/chrys87/fenrir/blob/master/src/fenrir/commands/command_template.py|Template is here]] + * [[https://github.com/chrys87/fenrir/blob/master/src/fenrir/commands/command_template.py|Template lives here]] * The class needs to have the name "command". - * "initialize" is running once while loading the command. - * "shutdown" is running on unload the command (like quit fenrir) - * "getDescriptsion" just returns an string. That Sting is used in Tutorial Mode. - * "run" is executed when the command is invoked. (shortcut is pressed, or trigger is running) + * "initialize" is running once whilst loading the command. + * "shutdown" is running on unload like the command (quit fenrir) + * "getDescriptsion" just returns an string. That String is used in Tutorial Mode. + * "run" is executed when the command is invoked. (shortcut is pressed, or trigger isn't running) * setCAllback is currently not used. and has no functionality yet. -====== Trouble Shooting ====== +====== Troubleshooting ====== Fenrir does not start - - Did you installed all dependencys - - Try master, i changed many things for make it compatible to more systems -Fenrir does not consume the shortcuts - - make sure you have python3-evdev installed - - use latest Fenrir version + - Have you installed all the dependencies [[#Support and Requirements|Support and Requirements]] + - Try using master, a lot of changes take place there to make Fenrir compatible with more systems +Fenrir does not utilize the shortcuts + - Make sure you have python3-evdev installed + - Use the latest Fenrir version No Sound: - - run script to configure pulse for Fenrir ''tools/configure_pulse.sh'' (once as user and once as root, then restart) + - Run the scripts to configure pulse. found in: ''tools/configure_pulse.sh'' (once as your user and once as root. Then restart Fenrir) - use ALSA - - configure pulse systemwide + - Configure Pulse systemwide +No Speech: + - Run the scripts to configure pulse. found in: ''tools/configure_pulse.sh'' (once as your user and once as root. Then restart Fenrir) + - use ALSA + - Configure Pulse systemwide + - if you are using speech-dispatcher run "spd-conf" as user and as root once. From a2acd14d9db17cbd843481c7c792e03cf6f740c2 Mon Sep 17 00:00:00 2001 From: chrys Date: Fri, 7 Jul 2017 21:44:49 +0200 Subject: [PATCH 44/96] sync udev watchdog --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0c71ab3a..a7dc2cc3 100644 --- a/README.md +++ b/README.md @@ -6,13 +6,14 @@ This software is licensed under the LGPL v3 . # Requirements (core) - linux (currently only screen and input drivers available for that) - python3 >= 3.3 -- python-configargparse +- python-configargparse - screen, input, speech, sound or braille drivers see "Features, Drivers, Extras". # Features, Drivers, Extras, Dependencys # Input Drivers: 1. "evdevDriver" input driver for linux evdev - python-evdev >=0.6.3 + - python-pyudev - This is commonly referred to as python3-evdev by your distribution - loaded uinput kernel module - ReadWrite permission From aacf1f02d1533a7811ead3ad40b209e2c2dd81e7 Mon Sep 17 00:00:00 2001 From: chrys Date: Sat, 8 Jul 2017 02:44:07 +0200 Subject: [PATCH 45/96] fix VCSA watchdog if VCSA device does not exist --- src/fenrir/screenDriver/vcsaDriver.py | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/fenrir/screenDriver/vcsaDriver.py b/src/fenrir/screenDriver/vcsaDriver.py index 8af34aba..9c95fadb 100644 --- a/src/fenrir/screenDriver/vcsaDriver.py +++ b/src/fenrir/screenDriver/vcsaDriver.py @@ -7,6 +7,7 @@ import difflib import re import subprocess +import glob, os import fcntl import termios import time @@ -100,8 +101,10 @@ class driver(): def updateWatchdog(self,active , eventQueue): try: vcsa = {} - for i in range(1,7): - vcsa[str(i)] = open('/dev/vcsa'+str(i),'rb') + 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]) @@ -120,12 +123,21 @@ class driver(): tty.seek(0) currScreen = str(tty.read()[3:-1]) if currScreen != oldScreen: - watchdog.unregister(vcsa[ oldScreen ]) - watchdog.register(vcsa[ currScreen ], select.EPOLLPRI) + try: + watchdog.unregister(vcsa[ oldScreen ]) + except: + pass + try: + watchdog.register(vcsa[ currScreen ], select.EPOLLPRI) + except: + pass oldScreen = currScreen eventQueue.put({"Type":fenrirEventType.ScreenChanged,"Data":''}) - vcsa[currScreen].seek(0) - lastScreenContent = vcsa[currScreen].read() + 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) @@ -135,6 +147,7 @@ class driver(): lastScreenContent = screenContent except Exception as e: self.env['runtime']['debug'].writeDebugOut('VCSA:updateWatchdog:' + str(e),debug.debugLevel.ERROR) + def update(self, trigger='onUpdate'): if trigger == 'onInput': # no need for an update on input for VCSA return From 48a3351b76cbc95d8fbe4dbb274f0678747be770 Mon Sep 17 00:00:00 2001 From: chrys Date: Sat, 8 Jul 2017 02:58:11 +0200 Subject: [PATCH 46/96] add debug --- src/fenrir/screenDriver/vcsaDriver.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/fenrir/screenDriver/vcsaDriver.py b/src/fenrir/screenDriver/vcsaDriver.py index 9c95fadb..059d093c 100644 --- a/src/fenrir/screenDriver/vcsaDriver.py +++ b/src/fenrir/screenDriver/vcsaDriver.py @@ -96,7 +96,8 @@ 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: From 3da0f6b5d8a7e3ee4938623c473aecaec2c7a2a7 Mon Sep 17 00:00:00 2001 From: chrys Date: Sat, 8 Jul 2017 02:59:01 +0200 Subject: [PATCH 47/96] add debug --- src/fenrir/screenDriver/vcsaDriver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fenrir/screenDriver/vcsaDriver.py b/src/fenrir/screenDriver/vcsaDriver.py index 059d093c..333f738e 100644 --- a/src/fenrir/screenDriver/vcsaDriver.py +++ b/src/fenrir/screenDriver/vcsaDriver.py @@ -97,7 +97,7 @@ class driver(): except Exception as e: self.env['runtime']['debug'].writeDebugOut('getSessionInformation: Maybe no LoginD:' + str(e),debug.debugLevel.ERROR) self.env['screen']['autoIgnoreScreens'] = [] - self.env['runtime']['debug'].writeDebugOut('getSessionInformation:' + str(self.env['screen']['autoIgnoreScreens']) + ' ' + str(self.env['general']) + ,debug.debugLevel.INFO) + self.env['runtime']['debug'].writeDebugOut('getSessionInformation:' + str(self.env['screen']['autoIgnoreScreens']) + ' ' + str(self.env['general']) ,debug.debugLevel.INFO) def updateWatchdog(self,active , eventQueue): try: From b29114abeaa5793b0a97a3fe6eba5d32efb19f86 Mon Sep 17 00:00:00 2001 From: chrys Date: Sun, 9 Jul 2017 18:03:29 +0200 Subject: [PATCH 48/96] add onCursorChange trigger; implement auto leave review mode on cursor change --- config/settings/espeak.settings.conf | 2 +- config/settings/settings.conf | 2 +- config/settings/settings.conf.storm | 6 ++-- ...resent_char_if_cursor_change_horizontal.py | 0 .../50000-char_echo.py | 0 ...-present_line_if_cursor_change_vertical.py | 0 .../60000-word_echo.py | 0 .../62000-spell_check.py | 0 .../65000-char_delete_echo.py | 0 .../onCursorChange/66000-exit_review_mode.py | 26 +++++++++++++++ .../onInput/11000-leave_review_mode.py | 33 ------------------- src/fenrir/core/fenrirManager.py | 6 +++- src/fenrir/core/generalData.py | 2 +- src/fenrir/core/settingsData.py | 2 +- 14 files changed, 38 insertions(+), 41 deletions(-) rename src/fenrir/commands/{onScreenUpdate => onCursorChange}/45000-present_char_if_cursor_change_horizontal.py (100%) rename src/fenrir/commands/{onScreenUpdate => onCursorChange}/50000-char_echo.py (100%) rename src/fenrir/commands/{onScreenUpdate => onCursorChange}/55000-present_line_if_cursor_change_vertical.py (100%) rename src/fenrir/commands/{onScreenUpdate => onCursorChange}/60000-word_echo.py (100%) rename src/fenrir/commands/{onScreenUpdate => onCursorChange}/62000-spell_check.py (100%) rename src/fenrir/commands/{onScreenUpdate => onCursorChange}/65000-char_delete_echo.py (100%) create mode 100644 src/fenrir/commands/onCursorChange/66000-exit_review_mode.py delete mode 100644 src/fenrir/commands/onInput/11000-leave_review_mode.py diff --git a/config/settings/espeak.settings.conf b/config/settings/espeak.settings.conf index 56f2d781..923ad0ea 100644 --- a/config/settings/espeak.settings.conf +++ b/config/settings/espeak.settings.conf @@ -173,7 +173,7 @@ highlight=False lineBreak=True endOfScreen=True # leave the review when pressing a key -leaveReviewOnKeypress=False +leaveReviewOnCursorChange=True # leave the review when changing the screen leaveReviewOnScreenChange=True diff --git a/config/settings/settings.conf b/config/settings/settings.conf index 9033d4fc..c9565d06 100644 --- a/config/settings/settings.conf +++ b/config/settings/settings.conf @@ -180,7 +180,7 @@ highlight=False lineBreak=True endOfScreen=True # leave the review when pressing a key -leaveReviewOnKeypress=False +leaveReviewOnCursorChange=True # leave the review when changing the screen leaveReviewOnScreenChange=True diff --git a/config/settings/settings.conf.storm b/config/settings/settings.conf.storm index b2f93cb2..eab9ebed 100644 --- a/config/settings/settings.conf.storm +++ b/config/settings/settings.conf.storm @@ -78,8 +78,8 @@ panSizeHorizontal=0 driver=vcsaDriver encoding=cp850 screenUpdateDelay=0.05 -suspendingScreen=7 -autodetectSuspendingScreen=False +suspendingScreen= +autodetectSuspendingScreen=True [keyboard] driver=evdevDriver @@ -128,7 +128,7 @@ highlight=False lineBreak=True endOfScreen=True # leave the review when pressing a key -leaveReviewOnKeypress=False +leaveReviewOnCursorChange=True # leave the review when changing the screen leaveReviewOnScreenChange=True diff --git a/src/fenrir/commands/onScreenUpdate/45000-present_char_if_cursor_change_horizontal.py b/src/fenrir/commands/onCursorChange/45000-present_char_if_cursor_change_horizontal.py similarity index 100% rename from src/fenrir/commands/onScreenUpdate/45000-present_char_if_cursor_change_horizontal.py rename to src/fenrir/commands/onCursorChange/45000-present_char_if_cursor_change_horizontal.py diff --git a/src/fenrir/commands/onScreenUpdate/50000-char_echo.py b/src/fenrir/commands/onCursorChange/50000-char_echo.py similarity index 100% rename from src/fenrir/commands/onScreenUpdate/50000-char_echo.py rename to src/fenrir/commands/onCursorChange/50000-char_echo.py diff --git a/src/fenrir/commands/onScreenUpdate/55000-present_line_if_cursor_change_vertical.py b/src/fenrir/commands/onCursorChange/55000-present_line_if_cursor_change_vertical.py similarity index 100% rename from src/fenrir/commands/onScreenUpdate/55000-present_line_if_cursor_change_vertical.py rename to src/fenrir/commands/onCursorChange/55000-present_line_if_cursor_change_vertical.py diff --git a/src/fenrir/commands/onScreenUpdate/60000-word_echo.py b/src/fenrir/commands/onCursorChange/60000-word_echo.py similarity index 100% rename from src/fenrir/commands/onScreenUpdate/60000-word_echo.py rename to src/fenrir/commands/onCursorChange/60000-word_echo.py diff --git a/src/fenrir/commands/onScreenUpdate/62000-spell_check.py b/src/fenrir/commands/onCursorChange/62000-spell_check.py similarity index 100% rename from src/fenrir/commands/onScreenUpdate/62000-spell_check.py rename to src/fenrir/commands/onCursorChange/62000-spell_check.py diff --git a/src/fenrir/commands/onScreenUpdate/65000-char_delete_echo.py b/src/fenrir/commands/onCursorChange/65000-char_delete_echo.py similarity index 100% rename from src/fenrir/commands/onScreenUpdate/65000-char_delete_echo.py rename to src/fenrir/commands/onCursorChange/65000-char_delete_echo.py diff --git a/src/fenrir/commands/onCursorChange/66000-exit_review_mode.py b/src/fenrir/commands/onCursorChange/66000-exit_review_mode.py new file mode 100644 index 00000000..2f7a8cfa --- /dev/null +++ b/src/fenrir/commands/onCursorChange/66000-exit_review_mode.py @@ -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 diff --git a/src/fenrir/commands/onInput/11000-leave_review_mode.py b/src/fenrir/commands/onInput/11000-leave_review_mode.py deleted file mode 100644 index 91c91a6b..00000000 --- a/src/fenrir/commands/onInput/11000-leave_review_mode.py +++ /dev/null @@ -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 - diff --git a/src/fenrir/core/fenrirManager.py b/src/fenrir/core/fenrirManager.py index 151be8a5..8d10e4e7 100644 --- a/src/fenrir/core/fenrirManager.py +++ b/src/fenrir/core/fenrirManager.py @@ -88,7 +88,11 @@ class fenrirManager(): 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(time.time() -s) diff --git a/src/fenrir/core/generalData.py b/src/fenrir/core/generalData.py index 261e7379..ff89e64c 100644 --- a/src/fenrir/core/generalData.py +++ b/src/fenrir/core/generalData.py @@ -13,6 +13,6 @@ generalData = { 'prevUser':'', 'managerList':['eventManager','punctuationManager','cursorManager','applicationManager','commandManager' ,'screenManager','inputManager','outputManager','debug'], -'commandFolderList':['commands','onInput','onScreenUpdate','onScreenChanged','onHeartBeat', 'onPlugInputDevice' +'commandFolderList':['commands','onInput', 'onCursorChange', 'onScreenUpdate','onScreenChanged','onHeartBeat', 'onPlugInputDevice' ,'onApplicationChange','onSwitchApplicationProfile',], } diff --git a/src/fenrir/core/settingsData.py b/src/fenrir/core/settingsData.py index 4e849d6a..c94df2cf 100644 --- a/src/fenrir/core/settingsData.py +++ b/src/fenrir/core/settingsData.py @@ -76,7 +76,7 @@ settingsData = { 'review':{ 'lineBreak': True, 'endOfScreen': True, - 'leaveReviewOnKeypress': False, + 'leaveReviewOnCursorChange': True, 'leaveReviewOnScreenChange': True, }, 'promote':{ From 2b8db63e774d155cba2aee6f241484d3bfd0e81c Mon Sep 17 00:00:00 2001 From: chrys Date: Sun, 9 Jul 2017 18:27:31 +0200 Subject: [PATCH 49/96] TODO: Mark auto leave review as done --- TODO v2.0 | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/TODO v2.0 b/TODO v2.0 index 3064cf2e..fb35c5e0 100644 --- a/TODO v2.0 +++ b/TODO v2.0 @@ -4,25 +4,24 @@ Things with not so deep knowledge needed are marekd wiht "(Easy for contribution General: - implement onScreenUpdate commands read highlighted text mode -- try to make it more asynchronus with multpible threads (DONE) +- try to make it more asynchronus with multpible threads - be more event based (vcsa sets POLLPRI) http://scotdoyle.com/python-epoll-howto.html Needed events: - screen update (vcsa sets POLLPRI) (DONE) + screen update (vcsa sets POLLPRI) plug input device (udev event) - screen changed (logind event, collides with screen update) (DONE) - keyboard input (select, wait forever) (DONE) + screen changed (logind event, collides with screen update) + keyboard input (select, wait forever) braille input (brlapi_readKey) - braille flush (timer, sleep) (DONE) - Each event is watched in an own thread. This improves performance and reduce the load. (DONE) - The event loop is to be done as "queue" since those are thread safe. (DONE) - The threads are reading incomming data and add the events and data to the queue (DONE) - the mainloop just reads the queue in an blocking way and executes the needed codepath with the data. (DONE) + braille flush (timer, sleep) + Each event is watched in an own thread. This improves performance and reduce the load. + The event loop is to be done as "queue" since those are thread safe. + The threads are reading incomming data and add the events and data to the queue + the mainloop just reads the queue in an blocking way and executes the needed codepath with the data. clean up the code for the events so that just the correct codepath is used: - screen - input - new device -- leave review on typing - implement commands Tutorial Mode: navigate through a list of bound commands. speak binding and description. @@ -85,6 +84,7 @@ Application Profiles -----------DONE---------------- - initial working setup.py +- leave review on typing - add dependency check (check-dependencys.py) - Add nice dummy drivers as template or for debugging - reimplement detection code for X11 From 69bc01c0179bbf6a966c7bc4f64a5ee66804ccad Mon Sep 17 00:00:00 2001 From: chrys Date: Sun, 9 Jul 2017 23:12:32 +0200 Subject: [PATCH 50/96] adjust todo --- TODO v2.0 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/TODO v2.0 b/TODO v2.0 index fb35c5e0..9726ab7e 100644 --- a/TODO v2.0 +++ b/TODO v2.0 @@ -22,6 +22,10 @@ General: - screen - input - new device + Bugs: + - device detection is broken + - arrow up/down announcement is broken + - let drivers choos between threads and process - implement commands Tutorial Mode: navigate through a list of bound commands. speak binding and description. From 85717371d6f869d2d78459f3c0a266fbb6a6621e Mon Sep 17 00:00:00 2001 From: chrys Date: Sun, 9 Jul 2017 23:27:54 +0200 Subject: [PATCH 51/96] autoencoding WIP --- play zone/charmapTTY.py | 6 +- src/fenrir/screenDriver/vcsaDriver.py | 79 +++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 3 deletions(-) diff --git a/play zone/charmapTTY.py b/play zone/charmapTTY.py index d0ea9296..92831055 100755 --- a/play zone/charmapTTY.py +++ b/play zone/charmapTTY.py @@ -5,7 +5,7 @@ #https://github.com/jwilk/vcsapeek/blob/master/linuxvt.py #blink = 5 if attr & 1 else 0 #bold = 1 if attr & 16 else 0 -from fcntl import ioctl +import fcntl from array import array import struct import errno @@ -23,7 +23,7 @@ cols = int(head[1]) GIO_UNIMAP = 0x4B66 VT_GETHIFONTMASK = 0x560D himask = array("H", (0,)) -ioctl(tty, VT_GETHIFONTMASK, himask) +fcntl.ioctl(tty, VT_GETHIFONTMASK, himask) hichar, = struct.unpack_from("@H", himask) sz = 512 @@ -32,7 +32,7 @@ while True: try: unipairs = array("H", [0]*(2*sz)) unimapdesc = array("B", struct.pack("@HP", sz, unipairs.buffer_info()[0])) - ioctl(tty.fileno(), GIO_UNIMAP, unimapdesc) + fcntl.ioctl(tty.fileno(), GIO_UNIMAP, unimapdesc) break except IOError as e: if e.errno != errno.ENOMEM: diff --git a/src/fenrir/screenDriver/vcsaDriver.py b/src/fenrir/screenDriver/vcsaDriver.py index 333f738e..67d633cf 100644 --- a/src/fenrir/screenDriver/vcsaDriver.py +++ b/src/fenrir/screenDriver/vcsaDriver.py @@ -3,6 +3,13 @@ # 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 @@ -13,10 +20,82 @@ import termios import time import select import dbus +import fcntl +from array import array +import struct +import errno +import sys from core import debug from core.eventData import fenrirEventType from utils import screen_utils + +''' +ttyno = 4 +tty = open('/dev/tty%d' % ttyno, 'rb') +vcs = open('/dev/vcsa%d' % ttyno, 'rb') + +head = vcs.read(4) +rows = int(head[0]) +cols = int(head[1]) + + +GIO_UNIMAP = 0x4B66 +VT_GETHIFONTMASK = 0x560D +himask = array("H", (0,)) +fcntl.ioctl(tty, VT_GETHIFONTMASK, himask) +hichar, = struct.unpack_from("@H", himask) + +sz = 512 +line = '' +while True: + try: + unipairs = array("H", [0]*(2*sz)) + unimapdesc = array("B", struct.pack("@HP", sz, unipairs.buffer_info()[0])) + fcntl.ioctl(tty.fileno(), GIO_UNIMAP, unimapdesc) + break + except IOError as e: + if e.errno != errno.ENOMEM: + raise + sz *= 2 + +tty.close() + +ncodes, = struct.unpack_from("@H", unimapdesc) +utable = struct.unpack_from("@%dH" % (2*ncodes), unipairs) + +charmap = {} +for u, b in zip(utable[::2], utable[1::2]): + if charmap.get(b) is None: + charmap[b] = u + +allText = [] +allAttrib = [] +for y in range(rows): + lineText = '' + lineAttrib = [] + for x in range(cols): + data = vcs.read(2) + (sh,) = struct.unpack("=H", data) + attr = (sh >> 8) & 0xFF + ch = sh & 0xFF + if hichar == 0x100: + attr >>= 1 + lineAttrib.append(attr) + ink = attr & 0x0F + paper = (attr>>4) & 0x0F + if (ink != 7) or (paper != 0): + print(ink,paper) + if sh & hichar: + ch |= 0x100 + lineText += chr(charmap.get(ch, u'?')) + allText.append(lineText) + allAttrib.append(lineAttrib) + +print(allText) +print(allAttrib) +''' + class driver(): def __init__(self): self.vcsaDevicePath = '/dev/vcsa' From d103eef1b955ccf171e1d8440d3be875c7053957 Mon Sep 17 00:00:00 2001 From: chrys Date: Sun, 9 Jul 2017 23:28:03 +0200 Subject: [PATCH 52/96] autoencoding WIP --- src/fenrir/screenDriver/vcsaDriverBak.py | 244 +++++++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 src/fenrir/screenDriver/vcsaDriverBak.py diff --git a/src/fenrir/screenDriver/vcsaDriverBak.py b/src/fenrir/screenDriver/vcsaDriverBak.py new file mode 100644 index 00000000..333f738e --- /dev/null +++ b/src/fenrir/screenDriver/vcsaDriverBak.py @@ -0,0 +1,244 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +import difflib +import re +import subprocess +import glob, os +import fcntl +import termios +import time +import select +import dbus +from core import debug +from core.eventData import fenrirEventType +from utils import screen_utils + +class driver(): + def __init__(self): + self.vcsaDevicePath = '/dev/vcsa' + self.ListSessions = None + def initialize(self, environment): + self.env = environment + self.env['runtime']['eventManager'].addCustomEventThread(self.updateWatchdog) + def shutdown(self): + pass + def getCurrScreen(self): + self.env['screen']['oldTTY'] = self.env['screen']['newTTY'] + try: + currScreenFile = open('/sys/devices/virtual/tty/tty0/active','r') + self.env['screen']['newTTY'] = str(currScreenFile.read()[3:-1]) + currScreenFile.close() + except Exception as e: + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + def injectTextToScreen(self, text, screen = None): + useScreen = "/dev/tty" + self.env['screen']['newTTY'] + if screen != None: + useScreen = screen + with open(useScreen, 'w') as fd: + for c in text: + fcntl.ioctl(fd, termios.TIOCSTI, c) + + def getCurrApplication(self): + apps = [] + try: + currScreen = self.env['screen']['newTTY'] + apps = subprocess.Popen('ps -t tty' + currScreen + ' -o comm,tty,stat', shell=True, stdout=subprocess.PIPE).stdout.read().decode()[:-1].split('\n') + except Exception as e: + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + return + try: + for i in apps: + i = i.upper() + i = i.split() + i[0] = i[0] + i[1] = i[1] + if '+' in i[2]: + if i[0] != '': + if not "GREP" == i[0] and \ + not "SH" == i[0] and \ + not "PS" == i[0]: + if "TTY"+currScreen in i[1]: + if self.env['screen']['newApplication'] != i[0]: + self.env['screen']['newApplication'] = i[0] + return + except Exception as e: + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + + def getSessionInformation(self): + try: + bus = dbus.SystemBus() + if not self.ListSessions: + obj = bus.get_object('org.freedesktop.login1', '/org/freedesktop/login1') + inf = dbus.Interface(obj, 'org.freedesktop.login1.Manager') + self.ListSessions = inf.get_dbus_method('ListSessions') + sessions = self.ListSessions() + self.env['screen']['autoIgnoreScreens'] = [] + for session in sessions: + obj = bus.get_object('org.freedesktop.login1', session[4]) + inf = dbus.Interface(obj, 'org.freedesktop.DBus.Properties') + sessionType = inf.Get('org.freedesktop.login1.Session', 'Type') + screen = str(inf.Get('org.freedesktop.login1.Session', 'VTNr')) + if screen == '': + screen = str(inf.Get('org.freedesktop.login1.Session', 'TTY')) + screen = screen[screen.upper().find('TTY') + 3:] + if screen == '': + self.env['runtime']['debug'].writeDebugOut('No TTY found for session:' + session[4],debug.debugLevel.ERROR) + return + if sessionType.upper() == 'X11': + self.env['screen']['autoIgnoreScreens'].append(screen) + if screen == self.env['screen']['newTTY'] : + if self.env['general']['currUser'] != session[2]: + self.env['general']['prevUser'] = self.env['general']['currUser'] + 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['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 update(self, trigger='onUpdate'): + if trigger == 'onInput': # no need for an update on input for VCSA + return + #print(self.env['screen']['newTTY'], self.env['screen']['oldTTY']) + newContentBytes = b'' + try: + # read screen + vcsa = open(self.vcsaDevicePath + self.env['screen']['newTTY'],'rb',0) + newContentBytes = vcsa.read() + vcsa.close() + if len(newContentBytes) < 5: + return + except Exception as e: + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + return + screenEncoding = self.env['runtime']['settingsManager'].getSetting('screen', 'encoding') + # set new "old" values + self.env['screen']['oldContentBytes'] = self.env['screen']['newContentBytes'] + self.env['screen']['oldContentText'] = self.env['screen']['newContentText'] + self.env['screen']['oldContentAttrib'] = self.env['screen']['newContentAttrib'] + self.env['screen']['oldCursor'] = self.env['screen']['newCursor'].copy() + if self.env['screen']['newCursorAttrib']: + self.env['screen']['oldCursorAttrib'] = self.env['screen']['newCursorAttrib'].copy() + self.env['screen']['oldDelta'] = self.env['screen']['newDelta'] + self.env['screen']['oldAttribDelta'] = self.env['screen']['newAttribDelta'] + self.env['screen']['oldNegativeDelta'] = self.env['screen']['newNegativeDelta'] + self.env['screen']['newContentBytes'] = newContentBytes + # get metadata like cursor or screensize + self.env['screen']['lines'] = int( self.env['screen']['newContentBytes'][0]) + self.env['screen']['columns'] = int( self.env['screen']['newContentBytes'][1]) + 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 self.env['screen']['newTTY'] != self.env['screen']['oldTTY']: + self.env['screen']['oldContentBytes'] = b'' + self.env['screen']['oldContentAttrib'] = b'' + self.env['screen']['oldContentText'] = '' + self.env['screen']['oldCursor']['x'] = 0 + self.env['screen']['oldCursor']['y'] = 0 + self.env['screen']['oldDelta'] = '' + self.env['screen']['oldAttribDelta'] = '' + self.env['screen']['oldCursorAttrib'] = None + self.env['screen']['newCursorAttrib'] = None + self.env['screen']['oldNegativeDelta'] = '' + # initialize current deltas + self.env['screen']['newNegativeDelta'] = '' + self.env['screen']['newDelta'] = '' + self.env['screen']['newAttribDelta'] = '' + + # changes on the screen + oldScreenText = re.sub(' +',' ',self.env['runtime']['screenManager'].getWindowAreaInText(self.env['screen']['oldContentText'])) + newScreenText = re.sub(' +',' ',self.env['runtime']['screenManager'].getWindowAreaInText(self.env['screen']['newContentText'])) + typing = False + if (self.env['screen']['oldContentText'] != self.env['screen']['newContentText']) and \ + (self.env['screen']['newContentText'] != '' ): + if oldScreenText == '' and\ + newScreenText != '': + self.env['screen']['newDelta'] = newScreenText + else: + cursorLineStart = self.env['screen']['newCursor']['y'] * self.env['screen']['columns'] + self.env['screen']['newCursor']['y'] + cursorLineEnd = cursorLineStart + self.env['screen']['columns'] + if self.env['screen']['oldCursor']['x'] != self.env['screen']['newCursor']['x'] and \ + self.env['screen']['oldCursor']['y'] == self.env['screen']['newCursor']['y'] and \ + self.env['screen']['newContentText'][:cursorLineStart] == self.env['screen']['oldContentText'][:cursorLineStart]: + + oldScreenText = self.env['screen']['oldContentText'][cursorLineStart:cursorLineEnd] + oldScreenText = re.sub(' +',' ',oldScreenText) + newScreenText = self.env['screen']['newContentText'][cursorLineStart:cursorLineEnd] + newScreenText = re.sub(' +',' ',newScreenText) + diff = difflib.ndiff(oldScreenText, newScreenText) + typing = True + else: + diff = difflib.ndiff( oldScreenText.split('\n'),\ + newScreenText.split('\n')) + + diffList = list(diff) + + if self.env['runtime']['settingsManager'].getSetting('general', 'newLinePause') and not typing: + self.env['screen']['newDelta'] = '\n'.join(x[2:] for x in diffList if x[0] == '+') + else: + self.env['screen']['newDelta'] = ''.join(x[2:] for x in diffList if x[0] == '+') + self.env['screen']['newNegativeDelta'] = ''.join(x[2:] for x in diffList if x[0] == '-') + + # track highlighted + if self.env['screen']['oldContentAttrib'] != self.env['screen']['newContentAttrib']: + if self.env['runtime']['settingsManager'].getSettingAsBool('focus', 'highlight'): + self.env['screen']['newAttribDelta'], self.env['screen']['newCursorAttrib'] = screen_utils.trackHighlights(self.env['screen']['oldContentAttrib'], self.env['screen']['newContentAttrib'], self.env['screen']['newContentText'], self.env['screen']['columns']) + From 11c97cf95503fed1f4af7a8936ea83eb3dea6767 Mon Sep 17 00:00:00 2001 From: chrys87 Date: Wed, 12 Jul 2017 13:01:05 +0200 Subject: [PATCH 53/96] add pyudev --- check-dependencys.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/check-dependencys.py b/check-dependencys.py index 333017a6..fd900356 100755 --- a/check-dependencys.py +++ b/check-dependencys.py @@ -79,6 +79,12 @@ try: except: print('python3-evdev: FAIL') available = available and False +try: + import pyudev + print('python3-pyudev: OK') +except: + print('python3-pyudev: FAIL') + available = available and False if available: currentInstallation.append('evdevDriver') # SOUND From 6133f100f8e57931d6f513b3c8c280577752a182 Mon Sep 17 00:00:00 2001 From: chrys Date: Wed, 12 Jul 2017 23:13:37 +0200 Subject: [PATCH 54/96] add initial tutorial menu --- play zone/charmapTTY.py | 15 ++-- .../commands/commands/toggle_tutorial_mode.py | 26 ------- src/fenrir/commands/help/Readme.txt | 2 + src/fenrir/commands/help/curr_help.py | 22 ++++++ src/fenrir/commands/help/next_help.py | 23 ++++++ src/fenrir/commands/help/prev_help.py | 23 ++++++ .../commands/help/toggle_tutorial_mode.py | 29 +++++++ src/fenrir/core/commandManager.py | 29 +++++-- src/fenrir/core/fenrirManager.py | 7 +- src/fenrir/core/generalData.py | 4 +- src/fenrir/core/helpManager.py | 75 +++++++++++++++++++ src/fenrir/core/settingsManager.py | 4 +- 12 files changed, 216 insertions(+), 43 deletions(-) delete mode 100644 src/fenrir/commands/commands/toggle_tutorial_mode.py create mode 100644 src/fenrir/commands/help/Readme.txt create mode 100644 src/fenrir/commands/help/curr_help.py create mode 100644 src/fenrir/commands/help/next_help.py create mode 100644 src/fenrir/commands/help/prev_help.py create mode 100644 src/fenrir/commands/help/toggle_tutorial_mode.py create mode 100755 src/fenrir/core/helpManager.py diff --git a/play zone/charmapTTY.py b/play zone/charmapTTY.py index 92831055..3761274d 100755 --- a/play zone/charmapTTY.py +++ b/play zone/charmapTTY.py @@ -10,6 +10,9 @@ from array import array import struct import errno import sys +import time + + ttyno = 4 tty = open('/dev/tty%d' % ttyno, 'rb') @@ -19,7 +22,7 @@ head = vcs.read(4) rows = int(head[0]) cols = int(head[1]) - +s = time.time() GIO_UNIMAP = 0x4B66 VT_GETHIFONTMASK = 0x560D himask = array("H", (0,)) @@ -51,6 +54,7 @@ for u, b in zip(utable[::2], utable[1::2]): allText = [] allAttrib = [] + for y in range(rows): lineText = '' lineAttrib = [] @@ -64,13 +68,14 @@ for y in range(rows): lineAttrib.append(attr) ink = attr & 0x0F paper = (attr>>4) & 0x0F - if (ink != 7) or (paper != 0): - print(ink,paper) + #if (ink != 7) or (paper != 0): + # print(ink,paper) if sh & hichar: ch |= 0x100 lineText += chr(charmap.get(ch, u'?')) allText.append(lineText) allAttrib.append(lineAttrib) -print(allText) -print(allAttrib) +#print(allText) +#print(allAttrib) +print(time.time() -s) diff --git a/src/fenrir/commands/commands/toggle_tutorial_mode.py b/src/fenrir/commands/commands/toggle_tutorial_mode.py deleted file mode 100644 index 0fab4dfa..00000000 --- a/src/fenrir/commands/commands/toggle_tutorial_mode.py +++ /dev/null @@ -1,26 +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): - self.env['general']['tutorialMode'] = False - 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 - - def setCallback(self, callback): - pass diff --git a/src/fenrir/commands/help/Readme.txt b/src/fenrir/commands/help/Readme.txt new file mode 100644 index 00000000..c90f7a6b --- /dev/null +++ b/src/fenrir/commands/help/Readme.txt @@ -0,0 +1,2 @@ +this folder contains help and tutorial related functions. +those are not bindable but hard coded. diff --git a/src/fenrir/commands/help/curr_help.py b/src/fenrir/commands/help/curr_help.py new file mode 100644 index 00000000..1de0abc5 --- /dev/null +++ b/src/fenrir/commands/help/curr_help.py @@ -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 diff --git a/src/fenrir/commands/help/next_help.py b/src/fenrir/commands/help/next_help.py new file mode 100644 index 00000000..0f268aa8 --- /dev/null +++ b/src/fenrir/commands/help/next_help.py @@ -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 diff --git a/src/fenrir/commands/help/prev_help.py b/src/fenrir/commands/help/prev_help.py new file mode 100644 index 00000000..31eccbb6 --- /dev/null +++ b/src/fenrir/commands/help/prev_help.py @@ -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 diff --git a/src/fenrir/commands/help/toggle_tutorial_mode.py b/src/fenrir/commands/help/toggle_tutorial_mode.py new file mode 100644 index 00000000..806f521f --- /dev/null +++ b/src/fenrir/commands/help/toggle_tutorial_mode.py @@ -0,0 +1,29 @@ +#!/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 _('Toggle the Tutorial mode') + def run(self): + print('TM') + text = '' + if self.env['runtime']['helpManager'].isTutorialMode(): + text = _('You are leaving the tutorial mode. Press that shortcut again to enter the tutorial mode again.') + else: + 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']['helpManager'].toggleTutorialMode() + self.env['runtime']['outputManager'].presentText(text, interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/core/commandManager.py b/src/fenrir/core/commandManager.py index 24e361da..d387b0eb 100644 --- a/src/fenrir/core/commandManager.py +++ b/src/fenrir/core/commandManager.py @@ -16,7 +16,7 @@ class commandManager(): self.env = environment # commands self.env['commands'] = {} - self.env['commandsIgnore'] = {} + self.env['commandsIgnore'] = {} for commandFolder in self.env['general']['commandFolderList']: self.env['runtime']['commandManager'].loadCommands(commandFolder) if self.env['runtime']['settingsManager'].getSetting('general', 'commandPath') != '': @@ -182,19 +182,34 @@ class commandManager(): return if self.commandExists(command, section): try: - if self.env['general']['tutorialMode']: + if self.env['runtime']['helpManager'].isTutorialMode(): self.env['runtime']['debug'].writeDebugOut("Tutorial for command:" + section + "." + command ,debug.debugLevel.INFO) - description = self.env['commands'][section][command].getDescription() + description = self.getCommandDescription(section, command) 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.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) + print(command, section) + 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.clearCommandQueued() self.env['commandInfo']['lastCommandExecutionTime'] = time.time() - + + def getCommandDescription(self, command, section = 'commands'): + if self.commandExists(command, section): + try: + return self.env['commands'][section][command].getDescription() + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('commandManager.getCommandDescription:' + str(e),debug.debugLevel.ERROR) + def isCommandQueued(self): return self.env['commandInfo']['currCommand'] != '' diff --git a/src/fenrir/core/fenrirManager.py b/src/fenrir/core/fenrirManager.py index 8d10e4e7..6f12c530 100644 --- a/src/fenrir/core/fenrirManager.py +++ b/src/fenrir/core/fenrirManager.py @@ -54,13 +54,16 @@ class fenrirManager(): startTime = time.time() if eventReceived: self.prepareCommand() - if not (self.wasCommand or self.environment['general']['tutorialMode']) or self.environment['runtime']['screenManager'].isSuspendingScreen(): + if not self.environment['runtime']['screenManager'].isSuspendingScreen(): + if self.environment['runtime']['helpManager'].handleTutorialMode(): + self.wasCommand = True + if not (self.wasCommand or self.environment['runtime']['helpManager'].isTutorialMode()) or self.environment['runtime']['screenManager'].isSuspendingScreen(): 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']: + if self.environment['runtime']['helpManager'].isTutorialMode(): self.environment['runtime']['inputManager'].clearEventBuffer() if self.environment['input']['keyForeward'] > 0: self.environment['input']['keyForeward'] -=1 diff --git a/src/fenrir/core/generalData.py b/src/fenrir/core/generalData.py index ff89e64c..12056612 100644 --- a/src/fenrir/core/generalData.py +++ b/src/fenrir/core/generalData.py @@ -12,7 +12,7 @@ generalData = { 'currUser':'', 'prevUser':'', 'managerList':['eventManager','punctuationManager','cursorManager','applicationManager','commandManager' - ,'screenManager','inputManager','outputManager','debug'], + ,'screenManager','inputManager','outputManager','helpManager','debug'], 'commandFolderList':['commands','onInput', 'onCursorChange', 'onScreenUpdate','onScreenChanged','onHeartBeat', 'onPlugInputDevice' - ,'onApplicationChange','onSwitchApplicationProfile',], + ,'onApplicationChange','onSwitchApplicationProfile','help',], } diff --git a/src/fenrir/core/helpManager.py b/src/fenrir/core/helpManager.py new file mode 100755 index 00000000..bc6f3d92 --- /dev/null +++ b/src/fenrir/core/helpManager.py @@ -0,0 +1,75 @@ +#!/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 = None + self.tutorialListIndex = None + def initialize(self, environment): + self.env = environment + self.createHelpDict() + + def shutdown(self): + pass + def toggleTutorialMode(self): + self.setTutorialMode(not self.env['general']['tutorialMode']) + def setTutorialMode(self, newTutorialMode): + self.env['general']['tutorialMode'] = newTutorialMode + 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('_',' ') + helptext = commandName + ', Shortcut , Description' + self.env['runtime']['commandManager'].getCommandDescription( command, section = 'commands') + 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 + 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 + def handleTutorialMode(self): + if self.env['runtime']['inputManager'].noKeyPressed(): + return + if self.env['input']['currInput'] in [['KEY_F1', 'KEY_FENRIR']]: + self.env['runtime']['commandManager'].runCommand('TOGGLE_TUTORIAL_MODE', 'help') + return True + if not self.isTutorialMode(): + return + if self.env['input']['currInput'] in [['KEY_ESC']]: + self.env['runtime']['commandManager'].runCommand('TOGGLE_TUTORIAL_MODE', 'help') + return True + if self.env['input']['currInput'] in [['KEY_UP']]: + self.env['runtime']['commandManager'].runCommand('PREV_HELP', 'help') + return True + if self.env['input']['currInput'] in [['KEY_DOWN']]: + self.env['runtime']['commandManager'].runCommand('NEXT_HELP', 'help') + return True + if self.env['input']['currInput'] in [['KEY_SPACE']]: + self.env['runtime']['commandManager'].runCommand('CURR_HELP', 'help') + return True + return False diff --git a/src/fenrir/core/settingsManager.py b/src/fenrir/core/settingsManager.py index eac42f6f..910fb356 100644 --- a/src/fenrir/core/settingsManager.py +++ b/src/fenrir/core/settingsManager.py @@ -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 @@ -328,7 +329,8 @@ 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) From 7a460b0d83f228bdb9b8a4003d38cfd0e21d5574 Mon Sep 17 00:00:00 2001 From: chrys Date: Wed, 12 Jul 2017 23:28:23 +0200 Subject: [PATCH 55/96] announce shortct --- src/fenrir/commands/help/toggle_tutorial_mode.py | 1 - src/fenrir/core/commandManager.py | 11 ++++++++--- src/fenrir/core/helpManager.py | 9 ++++++++- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/fenrir/commands/help/toggle_tutorial_mode.py b/src/fenrir/commands/help/toggle_tutorial_mode.py index 806f521f..18d778a3 100644 --- a/src/fenrir/commands/help/toggle_tutorial_mode.py +++ b/src/fenrir/commands/help/toggle_tutorial_mode.py @@ -16,7 +16,6 @@ class command(): def getDescription(self): return _('Toggle the Tutorial mode') def run(self): - print('TM') text = '' if self.env['runtime']['helpManager'].isTutorialMode(): text = _('You are leaving the tutorial mode. Press that shortcut again to enter the tutorial mode again.') diff --git a/src/fenrir/core/commandManager.py b/src/fenrir/core/commandManager.py index d387b0eb..68a99e6c 100644 --- a/src/fenrir/core/commandManager.py +++ b/src/fenrir/core/commandManager.py @@ -126,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 @@ -196,7 +195,6 @@ class commandManager(): if self.commandExists(command, section): try: self.env['runtime']['debug'].writeDebugOut("Executing command:" + section + "." + command ,debug.debugLevel.INFO) - print(command, section) self.env['commands'][section][command].run() except Exception as e: self.env['runtime']['debug'].writeDebugOut("Executing command:" + section + "." + command +' ' + str(e),debug.debugLevel.ERROR) @@ -222,4 +220,11 @@ class commandManager(): self.env['commandInfo']['currCommand'] = command 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 diff --git a/src/fenrir/core/helpManager.py b/src/fenrir/core/helpManager.py index bc6f3d92..ec8c2875 100755 --- a/src/fenrir/core/helpManager.py +++ b/src/fenrir/core/helpManager.py @@ -28,7 +28,14 @@ class helpManager(): commandName = commandName.split('__-__')[0] commandName = commandName.replace('_',' ') commandName = commandName.replace('_',' ') - helptext = commandName + ', Shortcut , Description' + self.env['runtime']['commandManager'].getCommandDescription( command, section = 'commands') + 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_',' ') + if commandShortcut == '': + commandShortcut = 'unbound' + helptext = commandName + ', Shortcut ' + commandShortcut + ', Description' + commandDescription return helptext def createHelpDict(self, section = 'commands'): self.helpDict = {} From 264fa6165628e675493a7ce0100a7b1488f436a0 Mon Sep 17 00:00:00 2001 From: chrys Date: Wed, 12 Jul 2017 23:35:33 +0200 Subject: [PATCH 56/96] fix typo --- src/fenrir/core/commandManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fenrir/core/commandManager.py b/src/fenrir/core/commandManager.py index 68a99e6c..8986dffd 100644 --- a/src/fenrir/core/commandManager.py +++ b/src/fenrir/core/commandManager.py @@ -183,7 +183,7 @@ class commandManager(): try: if self.env['runtime']['helpManager'].isTutorialMode(): self.env['runtime']['debug'].writeDebugOut("Tutorial for command:" + section + "." + command ,debug.debugLevel.INFO) - description = self.getCommandDescription(section, command) + 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) From 3c1405a786fad244ba3b17eb2ee238ce83f23625 Mon Sep 17 00:00:00 2001 From: chrys Date: Wed, 12 Jul 2017 23:36:41 +0200 Subject: [PATCH 57/96] fix typo --- src/fenrir/core/commandManager.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/fenrir/core/commandManager.py b/src/fenrir/core/commandManager.py index 8986dffd..3feadce9 100644 --- a/src/fenrir/core/commandManager.py +++ b/src/fenrir/core/commandManager.py @@ -190,6 +190,7 @@ class commandManager(): self.runCommand(command, section) except Exception as e: self.env['runtime']['debug'].writeDebugOut("Executing command:" + section + "." + command +' ' + str(e),debug.debugLevel.ERROR) + def runCommand(self, command, section = 'commands'): if self.commandExists(command, section): @@ -207,7 +208,9 @@ class commandManager(): return self.env['commands'][section][command].getDescription() except Exception as e: self.env['runtime']['debug'].writeDebugOut('commandManager.getCommandDescription:' + str(e),debug.debugLevel.ERROR) - + self.clearCommandQueued() + self.env['commandInfo']['lastCommandExecutionTime'] = time.time() + def isCommandQueued(self): return self.env['commandInfo']['currCommand'] != '' From 4fe637df9a884786dde894d61ed5ccdcdc2246fd Mon Sep 17 00:00:00 2001 From: chrys Date: Thu, 13 Jul 2017 00:01:10 +0200 Subject: [PATCH 58/96] fix wrongly executed --- src/fenrir/core/fenrirManager.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/fenrir/core/fenrirManager.py b/src/fenrir/core/fenrirManager.py index 6f12c530..deb99916 100644 --- a/src/fenrir/core/fenrirManager.py +++ b/src/fenrir/core/fenrirManager.py @@ -62,7 +62,8 @@ class fenrirManager(): if self.environment['runtime']['inputManager'].noKeyPressed(): if self.wasCommand: self.wasCommand = False - self.environment['runtime']['inputManager'].clearEventBuffer() + self.environment['runtime']['inputManager'].clearEventBuffer() + self.environment['runtime']['commandManager'].clearCommandQueued() if self.environment['runtime']['helpManager'].isTutorialMode(): self.environment['runtime']['inputManager'].clearEventBuffer() if self.environment['input']['keyForeward'] > 0: From 6173fe8a4d1ca788b33242939d9c02a494f6f3f0 Mon Sep 17 00:00:00 2001 From: chrys Date: Thu, 13 Jul 2017 00:14:34 +0200 Subject: [PATCH 59/96] add space to list --- src/fenrir/core/helpManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fenrir/core/helpManager.py b/src/fenrir/core/helpManager.py index ec8c2875..24316dd4 100755 --- a/src/fenrir/core/helpManager.py +++ b/src/fenrir/core/helpManager.py @@ -35,7 +35,7 @@ class helpManager(): commandShortcut = commandShortcut.replace('KEY_',' ') if commandShortcut == '': commandShortcut = 'unbound' - helptext = commandName + ', Shortcut ' + commandShortcut + ', Description' + commandDescription + helptext = commandName + ', Shortcut ' + commandShortcut + ', Description ' + commandDescription return helptext def createHelpDict(self, section = 'commands'): self.helpDict = {} From 629e90938c2be1764c3ceec621431bf4698915d5 Mon Sep 17 00:00:00 2001 From: chrys87 Date: Fri, 14 Jul 2017 13:14:04 +0200 Subject: [PATCH 60/96] Update charmapTTY.py --- play zone/charmapTTY.py | 149 ++++++++++++++++++++-------------------- 1 file changed, 76 insertions(+), 73 deletions(-) diff --git a/play zone/charmapTTY.py b/play zone/charmapTTY.py index 3761274d..c3dca7bc 100755 --- a/play zone/charmapTTY.py +++ b/play zone/charmapTTY.py @@ -1,81 +1,84 @@ -#!/bin/python3 -#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 fcntl +import time +from fcntl import ioctl from array import array import struct import errno import sys -import time - - - -ttyno = 4 -tty = open('/dev/tty%d' % ttyno, 'rb') -vcs = open('/dev/vcsa%d' % ttyno, 'rb') - -head = vcs.read(4) -rows = int(head[0]) -cols = int(head[1]) - -s = time.time() -GIO_UNIMAP = 0x4B66 -VT_GETHIFONTMASK = 0x560D -himask = array("H", (0,)) -fcntl.ioctl(tty, VT_GETHIFONTMASK, himask) -hichar, = struct.unpack_from("@H", himask) - -sz = 512 -line = '' -while True: - try: - unipairs = array("H", [0]*(2*sz)) - unimapdesc = array("B", struct.pack("@HP", sz, unipairs.buffer_info()[0])) - fcntl.ioctl(tty.fileno(), GIO_UNIMAP, unimapdesc) - break - except IOError as e: - if e.errno != errno.ENOMEM: - raise - sz *= 2 - -tty.close() - -ncodes, = struct.unpack_from("@H", unimapdesc) -utable = struct.unpack_from("@%dH" % (2*ncodes), unipairs) - charmap = {} -for u, b in zip(utable[::2], utable[1::2]): - if charmap.get(b) is None: - charmap[b] = u +def updateCharMap(screen): + ttyno = '4' + tty = open('/dev/tty' + screen, 'rb') + GIO_UNIMAP = 0x4B66 + VT_GETHIFONTMASK = 0x560D + himask = array("H", (0,)) + ioctl(tty, VT_GETHIFONTMASK, himask) + hichar, = struct.unpack_from("@H", himask) + sz = 512 + line = '' + while True: + try: + unipairs = array("H", [0]*(2*sz)) + unimapdesc = array("B", struct.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, = struct.unpack_from("@H", unimapdesc) + utable = struct.unpack_from("@%dH" % (2*ncodes), unipairs) + for u, b in zip(utable[::2], utable[1::2]): + if charmap.get(b) is None: + charmap[b] = chr(u) -allText = [] -allAttrib = [] -for y in range(rows): - lineText = '' - lineAttrib = [] - for x in range(cols): - data = vcs.read(2) - (sh,) = struct.unpack("=H", data) - attr = (sh >> 8) & 0xFF - ch = sh & 0xFF - if hichar == 0x100: - attr >>= 1 - lineAttrib.append(attr) - ink = attr & 0x0F - paper = (attr>>4) & 0x0F - #if (ink != 7) or (paper != 0): - # print(ink,paper) - if sh & hichar: - ch |= 0x100 - lineText += chr(charmap.get(ch, u'?')) - allText.append(lineText) - allAttrib.append(lineAttrib) +def autoDecodeVCSA(allData): + allText = [] + allAttrib = [] + print(time.time() -s ) + for y in range(rows): + lineText = '' + lineAttrib = [] + i = 0 + for x in range(cols): + data = allData[i: i + 2] + if data == b' \x07': + attr = 7 + ink = 7 + paper = 0 + lineAttrib.append(7) + lineText += ' ' + continue + (sh,) = struct.unpack("=H", data) + attr = (sh >> 8) & 0xFF + ch = sh & 0xFF + if hichar == 0x100: + attr >>= 1 + lineAttrib.append(attr) + ink = attr & 0x0F + paper = (attr>>4) & 0x0F + #if (ink != 7) or (paper != 0): + # print(ink,paper) + if sh & hichar: + ch |= 0x100 + try: + lineText += charmap[ch] + except: + lineText += chr('?') + i += 2 + allText.append(lineText) + allAttrib.append(lineAttrib) + return allText, allAttrib -#print(allText) -#print(allAttrib) -print(time.time() -s) +def m(): + s = time.time() + updateCharMap('4') + print(time.time() -s ) + vcsa = open('/dev/vcsa' + '4', 'rb') + head = vcsa.read(4) + rows = int(head[0]) + cols = int(head[1]) + text, attrib = autoDecodeVCSA(vcsa.read()) + print(time.time() -s ) + From 4772ebf11a4bd251563a79327bc4924eece69d81 Mon Sep 17 00:00:00 2001 From: chrys87 Date: Fri, 14 Jul 2017 13:16:05 +0200 Subject: [PATCH 61/96] Update charmapTTY.py --- play zone/charmapTTY.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/play zone/charmapTTY.py b/play zone/charmapTTY.py index c3dca7bc..dec7fbab 100755 --- a/play zone/charmapTTY.py +++ b/play zone/charmapTTY.py @@ -36,7 +36,6 @@ def updateCharMap(screen): def autoDecodeVCSA(allData): allText = [] allAttrib = [] - print(time.time() -s ) for y in range(rows): lineText = '' lineAttrib = [] @@ -44,9 +43,10 @@ def autoDecodeVCSA(allData): for x in range(cols): data = allData[i: i + 2] if data == b' \x07': - attr = 7 - ink = 7 - paper = 0 + #attr = 7 + #ink = 7 + #paper = 0 + #ch = ' ' lineAttrib.append(7) lineText += ' ' continue From c97f059775fa67decccaaaefe323faa25431402b Mon Sep 17 00:00:00 2001 From: chrys87 Date: Fri, 14 Jul 2017 13:18:24 +0200 Subject: [PATCH 62/96] Update charmapTTY.py --- play zone/charmapTTY.py | 1 + 1 file changed, 1 insertion(+) diff --git a/play zone/charmapTTY.py b/play zone/charmapTTY.py index dec7fbab..6f69af0a 100755 --- a/play zone/charmapTTY.py +++ b/play zone/charmapTTY.py @@ -49,6 +49,7 @@ def autoDecodeVCSA(allData): #ch = ' ' lineAttrib.append(7) lineText += ' ' + i += 2 continue (sh,) = struct.unpack("=H", data) attr = (sh >> 8) & 0xFF From e6d0d26d84e7d6f31543d18bbdbef1d2146e631f Mon Sep 17 00:00:00 2001 From: chrys87 Date: Fri, 14 Jul 2017 13:19:04 +0200 Subject: [PATCH 63/96] Update charmapTTY.py --- play zone/charmapTTY.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/play zone/charmapTTY.py b/play zone/charmapTTY.py index 6f69af0a..35a9c60b 100755 --- a/play zone/charmapTTY.py +++ b/play zone/charmapTTY.py @@ -42,6 +42,7 @@ def autoDecodeVCSA(allData): i = 0 for x in range(cols): data = allData[i: i + 2] + i += 2 if data == b' \x07': #attr = 7 #ink = 7 @@ -49,7 +50,6 @@ def autoDecodeVCSA(allData): #ch = ' ' lineAttrib.append(7) lineText += ' ' - i += 2 continue (sh,) = struct.unpack("=H", data) attr = (sh >> 8) & 0xFF @@ -67,7 +67,6 @@ def autoDecodeVCSA(allData): lineText += charmap[ch] except: lineText += chr('?') - i += 2 allText.append(lineText) allAttrib.append(lineAttrib) return allText, allAttrib From 5d45d806c12dc2134178430ab268cdc1178aea56 Mon Sep 17 00:00:00 2001 From: chrys Date: Sun, 16 Jul 2017 16:10:37 +0200 Subject: [PATCH 64/96] improve tutorial mode --- config/settings/settings.conf | 2 +- .../commands/help/toggle_tutorial_mode.py | 28 ------------------- src/fenrir/core/commandManager.py | 2 +- src/fenrir/core/fenrirManager.py | 18 ++++++------ src/fenrir/core/helpManager.py | 28 +++++++++++++++++-- src/fenrir/core/settingsManager.py | 4 ++- 6 files changed, 40 insertions(+), 42 deletions(-) delete mode 100644 src/fenrir/commands/help/toggle_tutorial_mode.py diff --git a/config/settings/settings.conf b/config/settings/settings.conf index c9565d06..1dcb5ae6 100644 --- a/config/settings/settings.conf +++ b/config/settings/settings.conf @@ -122,7 +122,7 @@ driver=vcsaDriver encoding=cp850 screenUpdateDelay=0.05 suspendingScreen= -autodetectSuspendingScreen=True +autodetectSuspendingScreen=False [keyboard] driver=evdevDriver diff --git a/src/fenrir/commands/help/toggle_tutorial_mode.py b/src/fenrir/commands/help/toggle_tutorial_mode.py deleted file mode 100644 index 18d778a3..00000000 --- a/src/fenrir/commands/help/toggle_tutorial_mode.py +++ /dev/null @@ -1,28 +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 _('Toggle the Tutorial mode') - def run(self): - text = '' - if self.env['runtime']['helpManager'].isTutorialMode(): - text = _('You are leaving the tutorial mode. Press that shortcut again to enter the tutorial mode again.') - else: - 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']['helpManager'].toggleTutorialMode() - self.env['runtime']['outputManager'].presentText(text, interrupt=True) - - def setCallback(self, callback): - pass diff --git a/src/fenrir/core/commandManager.py b/src/fenrir/core/commandManager.py index 3feadce9..683bea94 100644 --- a/src/fenrir/core/commandManager.py +++ b/src/fenrir/core/commandManager.py @@ -181,7 +181,7 @@ class commandManager(): return if self.commandExists(command, section): try: - if self.env['runtime']['helpManager'].isTutorialMode(): + if self.env['runtime']['helpManager'].isTutorialMode() and section != 'help': self.env['runtime']['debug'].writeDebugOut("Tutorial for command:" + section + "." + command ,debug.debugLevel.INFO) description = self.getCommandDescription(command, section) self.env['runtime']['outputManager'].presentText(description, interrupt=True) diff --git a/src/fenrir/core/fenrirManager.py b/src/fenrir/core/fenrirManager.py index deb99916..5ca2a377 100644 --- a/src/fenrir/core/fenrirManager.py +++ b/src/fenrir/core/fenrirManager.py @@ -54,9 +54,9 @@ class fenrirManager(): startTime = time.time() if eventReceived: self.prepareCommand() - if not self.environment['runtime']['screenManager'].isSuspendingScreen(): - if self.environment['runtime']['helpManager'].handleTutorialMode(): - self.wasCommand = True + #if not self.environment['runtime']['screenManager'].isSuspendingScreen(): + # if self.environment['runtime']['helpManager'].handleTutorialMode(): + # self.wasCommand = True if not (self.wasCommand or self.environment['runtime']['helpManager'].isTutorialMode()) or self.environment['runtime']['screenManager'].isSuspendingScreen(): self.environment['runtime']['inputManager'].writeEventBuffer() if self.environment['runtime']['inputManager'].noKeyPressed(): @@ -70,7 +70,7 @@ class fenrirManager(): self.environment['input']['keyForeward'] -=1 #self.environment['runtime']['screenManager'].update('onInput') self.environment['runtime']['commandManager'].executeDefaultTrigger('onInput') - self.handleCommands() + self.handleCommands() def handleScreenChange(self): self.environment['runtime']['screenManager'].update('onScreenChange') ''' @@ -116,19 +116,21 @@ class fenrirManager(): 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']): + 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) def handleCommands(self): if not self.environment['runtime']['commandManager'].isCommandQueued(): return + if len(self.environment['input']['prevDeepestInput']) > len(self.environment['input']['currInput']): + return + if self.environment['runtime']['helpManager'].isTutorialMode(): + self.environment['runtime']['commandManager'].executeCommand( self.environment['commandInfo']['currCommand'], 'help') self.environment['runtime']['commandManager'].executeCommand( self.environment['commandInfo']['currCommand'], 'commands') - def shutdownRequest(self): self.environment['runtime']['eventManager'].stopMainEventLoop() diff --git a/src/fenrir/core/helpManager.py b/src/fenrir/core/helpManager.py index 24316dd4..57614d4c 100755 --- a/src/fenrir/core/helpManager.py +++ b/src/fenrir/core/helpManager.py @@ -14,13 +14,26 @@ class helpManager(): def initialize(self, environment): self.env = environment self.createHelpDict() - def shutdown(self): pass def toggleTutorialMode(self): self.setTutorialMode(not self.env['general']['tutorialMode']) def setTutorialMode(self, newTutorialMode): - self.env['general']['tutorialMode'] = 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'): @@ -28,11 +41,17 @@ class helpManager(): commandName = commandName.split('__-__')[0] commandName = commandName.replace('_',' ') commandName = commandName.replace('_',' ') - commandDescription = self.env['runtime']['commandManager'].getCommandDescription( command, section = 'commands') + 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 @@ -43,6 +62,8 @@ class helpManager(): 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 '' @@ -60,6 +81,7 @@ class helpManager(): if self.tutorialListIndex < 0: self.tutorialListIndex = len(self.helpDict) - 1 def handleTutorialMode(self): + return if self.env['runtime']['inputManager'].noKeyPressed(): return if self.env['input']['currInput'] in [['KEY_F1', 'KEY_FENRIR']]: diff --git a/src/fenrir/core/settingsManager.py b/src/fenrir/core/settingsManager.py index 910fb356..e0bdca89 100644 --- a/src/fenrir/core/settingsManager.py +++ b/src/fenrir/core/settingsManager.py @@ -70,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") From d21aec4dc70a1cb067f070f9b361545412a61738 Mon Sep 17 00:00:00 2001 From: chrys Date: Sun, 16 Jul 2017 16:10:41 +0200 Subject: [PATCH 65/96] improve tutorial mode --- .../commands/commands/toggle_tutorial_mode.py | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/fenrir/commands/commands/toggle_tutorial_mode.py diff --git a/src/fenrir/commands/commands/toggle_tutorial_mode.py b/src/fenrir/commands/commands/toggle_tutorial_mode.py new file mode 100644 index 00000000..8c89f957 --- /dev/null +++ b/src/fenrir/commands/commands/toggle_tutorial_mode.py @@ -0,0 +1,24 @@ +#!/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): + 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): + 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 From 418a12a93e9d9c5f4ecd91ee41a548c094a090ea Mon Sep 17 00:00:00 2001 From: chrys Date: Sun, 16 Jul 2017 22:27:45 +0200 Subject: [PATCH 66/96] sync WIP --- play zone/charmapTTY.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/play zone/charmapTTY.py b/play zone/charmapTTY.py index 35a9c60b..ab2b5295 100755 --- a/play zone/charmapTTY.py +++ b/play zone/charmapTTY.py @@ -5,7 +5,9 @@ import struct import errno import sys charmap = {} +hichar = None def updateCharMap(screen): + global hichar ttyno = '4' tty = open('/dev/tty' + screen, 'rb') GIO_UNIMAP = 0x4B66 @@ -33,7 +35,7 @@ def updateCharMap(screen): charmap[b] = chr(u) -def autoDecodeVCSA(allData): +def autoDecodeVCSA(allData, rows, cols): allText = [] allAttrib = [] for y in range(rows): @@ -61,8 +63,8 @@ def autoDecodeVCSA(allData): paper = (attr>>4) & 0x0F #if (ink != 7) or (paper != 0): # print(ink,paper) - if sh & hichar: - ch |= 0x100 + #if sh & hichar: + # ch |= 0x100 try: lineText += charmap[ch] except: @@ -79,6 +81,6 @@ def m(): head = vcsa.read(4) rows = int(head[0]) cols = int(head[1]) - text, attrib = autoDecodeVCSA(vcsa.read()) + text, attrib = autoDecodeVCSA(vcsa.read(), rows, cols) print(time.time() -s ) From d6c5c8a7917255a99bad35221cb64ca6b14b3ac9 Mon Sep 17 00:00:00 2001 From: chrys Date: Sun, 16 Jul 2017 22:28:30 +0200 Subject: [PATCH 67/96] sync WIP --- config/settings/settings.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/settings/settings.conf b/config/settings/settings.conf index 1dcb5ae6..c9565d06 100644 --- a/config/settings/settings.conf +++ b/config/settings/settings.conf @@ -122,7 +122,7 @@ driver=vcsaDriver encoding=cp850 screenUpdateDelay=0.05 suspendingScreen= -autodetectSuspendingScreen=False +autodetectSuspendingScreen=True [keyboard] driver=evdevDriver From 06e80017a999807eee38abe2bbf05e296fe48abc Mon Sep 17 00:00:00 2001 From: chrys Date: Tue, 18 Jul 2017 00:58:54 +0200 Subject: [PATCH 68/96] add initial autoEncodeing --- config/settings/espeak.settings.conf | 2 +- config/settings/settings.conf | 2 +- config/settings/settings.conf.storm | 2 +- play zone/charmapTTY.py | 24 ++-- src/fenrir/screenDriver/vcsaDriver.py | 158 +++++++++++++------------- 5 files changed, 98 insertions(+), 90 deletions(-) diff --git a/config/settings/espeak.settings.conf b/config/settings/espeak.settings.conf index 923ad0ea..3c7800e3 100644 --- a/config/settings/espeak.settings.conf +++ b/config/settings/espeak.settings.conf @@ -117,7 +117,7 @@ panSizeHorizontal=0 [screen] driver=vcsaDriver -encoding=UTF-8 +encoding=auto screenUpdateDelay=0.05 suspendingScreen= autodetectSuspendingScreen=True diff --git a/config/settings/settings.conf b/config/settings/settings.conf index c9565d06..f8d78ce7 100644 --- a/config/settings/settings.conf +++ b/config/settings/settings.conf @@ -119,7 +119,7 @@ panSizeHorizontal=0 [screen] driver=vcsaDriver -encoding=cp850 +encoding=auto screenUpdateDelay=0.05 suspendingScreen= autodetectSuspendingScreen=True diff --git a/config/settings/settings.conf.storm b/config/settings/settings.conf.storm index eab9ebed..db5ce8f6 100644 --- a/config/settings/settings.conf.storm +++ b/config/settings/settings.conf.storm @@ -76,7 +76,7 @@ panSizeHorizontal=0 [screen] driver=vcsaDriver -encoding=cp850 +encoding=auto screenUpdateDelay=0.05 suspendingScreen= autodetectSuspendingScreen=True diff --git a/play zone/charmapTTY.py b/play zone/charmapTTY.py index ab2b5295..981331f7 100755 --- a/play zone/charmapTTY.py +++ b/play zone/charmapTTY.py @@ -1,7 +1,9 @@ import time from fcntl import ioctl from array import array -import struct +from struct import unpack_from +from struct import unpack +from struct import pack import errno import sys charmap = {} @@ -14,13 +16,13 @@ def updateCharMap(screen): VT_GETHIFONTMASK = 0x560D himask = array("H", (0,)) ioctl(tty, VT_GETHIFONTMASK, himask) - hichar, = struct.unpack_from("@H", himask) + hichar, = unpack_from("@H", himask) sz = 512 line = '' while True: try: unipairs = array("H", [0]*(2*sz)) - unimapdesc = array("B", struct.pack("@HP", sz, unipairs.buffer_info()[0])) + unimapdesc = array("B", pack("@HP", sz, unipairs.buffer_info()[0])) ioctl(tty.fileno(), GIO_UNIMAP, unimapdesc) break except IOError as e: @@ -28,8 +30,8 @@ def updateCharMap(screen): raise sz *= 2 tty.close() - ncodes, = struct.unpack_from("@H", unimapdesc) - utable = struct.unpack_from("@%dH" % (2*ncodes), unipairs) + ncodes, = unpack_from("@H", unimapdesc) + utable = unpack_from("@%dH" % (2*ncodes), unipairs) for u, b in zip(utable[::2], utable[1::2]): if charmap.get(b) is None: charmap[b] = chr(u) @@ -53,7 +55,7 @@ def autoDecodeVCSA(allData, rows, cols): lineAttrib.append(7) lineText += ' ' continue - (sh,) = struct.unpack("=H", data) + (sh,) = unpack("=H", data) attr = (sh >> 8) & 0xFF ch = sh & 0xFF if hichar == 0x100: @@ -63,8 +65,8 @@ def autoDecodeVCSA(allData, rows, cols): paper = (attr>>4) & 0x0F #if (ink != 7) or (paper != 0): # print(ink,paper) - #if sh & hichar: - # ch |= 0x100 + if sh & hichar: + ch |= 0x100 try: lineText += charmap[ch] except: @@ -73,11 +75,11 @@ def autoDecodeVCSA(allData, rows, cols): allAttrib.append(lineAttrib) return allText, allAttrib -def m(): +def m(screen): s = time.time() - updateCharMap('4') + updateCharMap(str(screen)) print(time.time() -s ) - vcsa = open('/dev/vcsa' + '4', 'rb') + vcsa = open('/dev/vcsa' + str(screen), 'rb') head = vcsa.read(4) rows = int(head[0]) cols = int(head[1]) diff --git a/src/fenrir/screenDriver/vcsaDriver.py b/src/fenrir/screenDriver/vcsaDriver.py index 67d633cf..c6473d1b 100644 --- a/src/fenrir/screenDriver/vcsaDriver.py +++ b/src/fenrir/screenDriver/vcsaDriver.py @@ -15,91 +15,27 @@ import difflib import re import subprocess import glob, os -import fcntl import termios import time import select import dbus import fcntl from array import array -import struct 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 -from utils import screen_utils -''' -ttyno = 4 -tty = open('/dev/tty%d' % ttyno, 'rb') -vcs = open('/dev/vcsa%d' % ttyno, 'rb') - -head = vcs.read(4) -rows = int(head[0]) -cols = int(head[1]) - - -GIO_UNIMAP = 0x4B66 -VT_GETHIFONTMASK = 0x560D -himask = array("H", (0,)) -fcntl.ioctl(tty, VT_GETHIFONTMASK, himask) -hichar, = struct.unpack_from("@H", himask) - -sz = 512 -line = '' -while True: - try: - unipairs = array("H", [0]*(2*sz)) - unimapdesc = array("B", struct.pack("@HP", sz, unipairs.buffer_info()[0])) - fcntl.ioctl(tty.fileno(), GIO_UNIMAP, unimapdesc) - break - except IOError as e: - if e.errno != errno.ENOMEM: - raise - sz *= 2 - -tty.close() - -ncodes, = struct.unpack_from("@H", unimapdesc) -utable = struct.unpack_from("@%dH" % (2*ncodes), unipairs) - -charmap = {} -for u, b in zip(utable[::2], utable[1::2]): - if charmap.get(b) is None: - charmap[b] = u - -allText = [] -allAttrib = [] -for y in range(rows): - lineText = '' - lineAttrib = [] - for x in range(cols): - data = vcs.read(2) - (sh,) = struct.unpack("=H", data) - attr = (sh >> 8) & 0xFF - ch = sh & 0xFF - if hichar == 0x100: - attr >>= 1 - lineAttrib.append(attr) - ink = attr & 0x0F - paper = (attr>>4) & 0x0F - if (ink != 7) or (paper != 0): - print(ink,paper) - if sh & hichar: - ch |= 0x100 - lineText += chr(charmap.get(ch, u'?')) - allText.append(lineText) - allAttrib.append(lineAttrib) - -print(allText) -print(allAttrib) -''' - 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) @@ -227,11 +163,74 @@ class driver(): 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: + 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 - #print(self.env['screen']['newTTY'], self.env['screen']['oldTTY']) newContentBytes = b'' try: # read screen @@ -261,11 +260,18 @@ 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']) - + s = time.time() + 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']) + print(time.time() -s, self.env['screen']['newTTY'] ) if self.env['screen']['newTTY'] != self.env['screen']['oldTTY']: self.env['screen']['oldContentBytes'] = b'' self.env['screen']['oldContentAttrib'] = b'' From 55a5b741a300bcaab0da53a0758b083155ad8c71 Mon Sep 17 00:00:00 2001 From: chrys Date: Tue, 18 Jul 2017 01:04:38 +0200 Subject: [PATCH 69/96] revert fix that breaks more than it helps --- src/fenrir/core/fenrirManager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fenrir/core/fenrirManager.py b/src/fenrir/core/fenrirManager.py index 5ca2a377..6cd078b6 100644 --- a/src/fenrir/core/fenrirManager.py +++ b/src/fenrir/core/fenrirManager.py @@ -117,8 +117,8 @@ class fenrirManager(): 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 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) From 31b074146e93010586d8a005a69dae17b73e573d Mon Sep 17 00:00:00 2001 From: chrys Date: Tue, 18 Jul 2017 01:06:55 +0200 Subject: [PATCH 70/96] update Todo --- TODO v2.0 | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/TODO v2.0 b/TODO v2.0 index 9726ab7e..7c21882e 100644 --- a/TODO v2.0 +++ b/TODO v2.0 @@ -1,6 +1,13 @@ ToDo list for Fenrir Version 2.0 Things with not so deep knowledge needed are marekd wiht "(Easy for contribution)". so just start with that :). +Bugs: +- device detection is broken +- arrow up/down announcement is broken +- let drivers choos between threads and process +- HilightTracking is broken for autoencoding + + General: - implement onScreenUpdate commands read highlighted text mode @@ -22,11 +29,6 @@ General: - screen - input - new device - Bugs: - - device detection is broken - - arrow up/down announcement is broken - - let drivers choos between threads and process - - implement commands Tutorial Mode: navigate through a list of bound commands. speak binding and description. attributes_curr_char (Easy for contribution) @@ -64,8 +66,6 @@ Driver: - implement PTY Input driver - ATK input driver (don't grab on graphical interface) https://git.linux-a11y.org/AIT/pyatspi2/src/master/examples/keypress.py -- try to autodetect encoding (Easy for contribution) (Prototype "charmapTTY" in play zone) - https://stackoverflow.com/questions/6396659/how-do-you-get-the-encoding-of-the-terminal-from-within-a-python-script - Dectalk SpeechDriver https://github.com/tvraman/emacspeak/blob/master/servers/obsolete/python/dectalk.py @@ -100,7 +100,9 @@ Application Profiles http://askubuntu.com/questions/508236/how-can-i-run-code-whenever-a-usb-device-is-unplugged-without-requiring-root https://www.mattfischer.com/blog/?p=182 - implement speechdriver generic (Easy for contribution) - +- try to autodetect encoding (Easy for contribution) (Prototype "charmapTTY" in play zone) + https://stackoverflow.com/questions/6396659/how-do-you-get-the-encoding-of-the-terminal-from-within-a-python-script + Braille Support: initial BrlTTY driver detect device size via driver From 8b53b675e7b666387904090aade266c18da9e993 Mon Sep 17 00:00:00 2001 From: chrys87 Date: Tue, 18 Jul 2017 11:46:51 +0200 Subject: [PATCH 71/96] Update TODO v2.0 --- TODO v2.0 | 7 ------- 1 file changed, 7 deletions(-) diff --git a/TODO v2.0 b/TODO v2.0 index 7c21882e..a06f2756 100644 --- a/TODO v2.0 +++ b/TODO v2.0 @@ -1,13 +1,6 @@ ToDo list for Fenrir Version 2.0 Things with not so deep knowledge needed are marekd wiht "(Easy for contribution)". so just start with that :). -Bugs: -- device detection is broken -- arrow up/down announcement is broken -- let drivers choos between threads and process -- HilightTracking is broken for autoencoding - - General: - implement onScreenUpdate commands read highlighted text mode From e9cced31daf302d1a2e33e8d137ce578eb731cb7 Mon Sep 17 00:00:00 2001 From: chrys87 Date: Tue, 18 Jul 2017 11:48:03 +0200 Subject: [PATCH 72/96] Update known bugs.txt --- known bugs.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/known bugs.txt b/known bugs.txt index 34d04176..379a32e2 100644 --- a/known bugs.txt +++ b/known bugs.txt @@ -7,7 +7,12 @@ Glitches (improve diff results): - whole status line in irssi is spoken insteed of just the changes - whole status line in vim is spoken insteed of just the changes - keys sometimes get stuck +- device detection is broken +- arrow up/down announcement is broken +- let drivers choos between threads and process +- HilightTracking is broken for autoencoding Questions: +schould be done by autoencoding Verify: - what is the correct codepage for cyrillic - cyrillic (see autoencoding prototype) From fa3b0af20a0ef0f9e8e43cad0535209595d66d10 Mon Sep 17 00:00:00 2001 From: chrys87 Date: Tue, 18 Jul 2017 11:53:47 +0200 Subject: [PATCH 73/96] Update known bugs.txt --- known bugs.txt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/known bugs.txt b/known bugs.txt index 379a32e2..f8f1cae7 100644 --- a/known bugs.txt +++ b/known bugs.txt @@ -1,18 +1,18 @@ Known Bugs (Problems with the logic ): - word echo triggers twice if there are two spaces after an word and you arrow over them - spellcheck triggers twice if there are two spaces after an word and you arrow over them -Glitches (improve diff results): -- For example, in screen, it just tells me bell in window, but doesn't tell me which one. (southernprince) -- alpine seems to have problems (southernprince) -- whole status line in irssi is spoken insteed of just the changes -- whole status line in vim is spoken insteed of just the changes - keys sometimes get stuck - device detection is broken - arrow up/down announcement is broken - let drivers choos between threads and process - HilightTracking is broken for autoencoding +- commands are sometimes fired twice (keypress and key release) + +Glitches (improve diff results): +- For example, in screen, it just tells me bell in window, but doesn't tell me which one. (southernprince) +- alpine seems to have problems (southernprince) +- whole status line in irssi is spoken insteed of just the changes +- whole status line in vim is spoken insteed of just the changes Questions: -schould be done by autoencoding Verify: -- what is the correct codepage for cyrillic -- cyrillic (see autoencoding prototype) +- cyrillic (Done (Autoencode), needs testing) From 6e132ae1fba7d4e29198fda2a800200c613468fd Mon Sep 17 00:00:00 2001 From: chrys87 Date: Wed, 19 Jul 2017 11:07:57 +0200 Subject: [PATCH 74/96] Update fenrirManager.py --- src/fenrir/core/fenrirManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fenrir/core/fenrirManager.py b/src/fenrir/core/fenrirManager.py index 6cd078b6..a21ad93b 100644 --- a/src/fenrir/core/fenrirManager.py +++ b/src/fenrir/core/fenrirManager.py @@ -68,7 +68,7 @@ class fenrirManager(): self.environment['runtime']['inputManager'].clearEventBuffer() if self.environment['input']['keyForeward'] > 0: self.environment['input']['keyForeward'] -=1 - #self.environment['runtime']['screenManager'].update('onInput') + self.environment['runtime']['screenManager'].update('onInput') self.environment['runtime']['commandManager'].executeDefaultTrigger('onInput') self.handleCommands() def handleScreenChange(self): From 0d6df688dccb604805e76fd6f4244f485274f12f Mon Sep 17 00:00:00 2001 From: chrys87 Date: Wed, 19 Jul 2017 11:12:18 +0200 Subject: [PATCH 75/96] Update fenrirManager.py --- src/fenrir/core/fenrirManager.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/fenrir/core/fenrirManager.py b/src/fenrir/core/fenrirManager.py index a21ad93b..1dcbb378 100644 --- a/src/fenrir/core/fenrirManager.py +++ b/src/fenrir/core/fenrirManager.py @@ -17,7 +17,6 @@ import argparse class fenrirManager(): def __init__(self): - self.initialized = False cliArgs = self.handleArgs() if not cliArgs: return @@ -27,7 +26,6 @@ class fenrirManager(): 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) @@ -50,8 +48,8 @@ class fenrirManager(): self.environment['runtime']['eventManager'].startMainEventLoop() self.shutdown() def handleInput(self): + startTime = time.time() eventReceived = self.environment['runtime']['inputManager'].getInputEvent() - startTime = time.time() if eventReceived: self.prepareCommand() #if not self.environment['runtime']['screenManager'].isSuspendingScreen(): @@ -71,6 +69,8 @@ class fenrirManager(): self.environment['runtime']['screenManager'].update('onInput') self.environment['runtime']['commandManager'].executeDefaultTrigger('onInput') self.handleCommands() + print('handleInput:',time.time() - startTime) + def handleScreenChange(self): self.environment['runtime']['screenManager'].update('onScreenChange') ''' @@ -83,7 +83,7 @@ class fenrirManager(): self.environment['runtime']['commandManager'].executeDefaultTrigger('onScreenChanged') def handleScreenUpdate(self): - s = time.time() + startTime = time.time() self.environment['runtime']['screenManager'].update('onUpdate') ''' @@ -98,7 +98,7 @@ class fenrirManager(): self.environment['runtime']['cursorManager'].isCursorHorizontalMove(): self.environment['runtime']['commandManager'].executeDefaultTrigger('onCursorChange') self.environment['runtime']['commandManager'].executeDefaultTrigger('onScreenUpdate') - #print(time.time() -s) + print('handleScreenUpdate:',time.time() - startTime) def handlePlugInputDevice(self): self.environment['runtime']['commandManager'].executeDefaultTrigger('PlugInputDevice') From 70156493ff9eb316461b72f80b34d3fb2820f2f4 Mon Sep 17 00:00:00 2001 From: chrys Date: Wed, 19 Jul 2017 18:21:46 +0200 Subject: [PATCH 76/96] fix --- src/fenrir/core/fenrirManager.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/fenrir/core/fenrirManager.py b/src/fenrir/core/fenrirManager.py index 1dcbb378..0010d8b9 100644 --- a/src/fenrir/core/fenrirManager.py +++ b/src/fenrir/core/fenrirManager.py @@ -17,6 +17,7 @@ import argparse class fenrirManager(): def __init__(self): + self.initialized = False cliArgs = self.handleArgs() if not cliArgs: return @@ -29,6 +30,7 @@ class fenrirManager(): self.environment['runtime']['outputManager'].presentText(_("Start Fenrir"), soundIcon='ScreenReaderOn', interrupt=True) signal.signal(signal.SIGINT, self.captureSignal) signal.signal(signal.SIGTERM, self.captureSignal) + self.initialized = True self.wasCommand = False def handleArgs(self): From 7dcff82cf5261d9ef1f325bc9ee6ce42be5fcd76 Mon Sep 17 00:00:00 2001 From: chrys Date: Thu, 20 Jul 2017 00:41:12 +0200 Subject: [PATCH 77/96] intial rewrite of command detection; move command execution to event --- src/fenrir/core/commandManager.py | 13 --- src/fenrir/core/eventData.py | 1 + src/fenrir/core/eventManager.py | 17 ++-- src/fenrir/core/fenrirManager.py | 116 +++++++++++++++----------- src/fenrir/core/inputManager.py | 22 ++--- src/fenrir/screenDriver/vcsaDriver.py | 4 +- 6 files changed, 93 insertions(+), 80 deletions(-) diff --git a/src/fenrir/core/commandManager.py b/src/fenrir/core/commandManager.py index 683bea94..fc238d51 100644 --- a/src/fenrir/core/commandManager.py +++ b/src/fenrir/core/commandManager.py @@ -199,7 +199,6 @@ class commandManager(): 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.clearCommandQueued() self.env['commandInfo']['lastCommandExecutionTime'] = time.time() def getCommandDescription(self, command, section = 'commands'): @@ -208,19 +207,7 @@ class commandManager(): return self.env['commands'][section][command].getDescription() except Exception as e: self.env['runtime']['debug'].writeDebugOut('commandManager.getCommandDescription:' + 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]) diff --git a/src/fenrir/core/eventData.py b/src/fenrir/core/eventData.py index c9592c98..be5db45a 100755 --- a/src/fenrir/core/eventData.py +++ b/src/fenrir/core/eventData.py @@ -17,6 +17,7 @@ class fenrirEventType(Enum): BrailleFlush = 6 ScreenChanged = 7 HeartBeat = 8 # for time based scheduling + ExecuteCommand = 9 def __int__(self): return self.value def __str__(self): diff --git a/src/fenrir/core/eventManager.py b/src/fenrir/core/eventManager.py index d6c06475..945c6a16 100644 --- a/src/fenrir/core/eventManager.py +++ b/src/fenrir/core/eventManager.py @@ -47,15 +47,17 @@ class eventManager(): self.env['runtime']['debug'].writeDebugOut('eventManager:eventDispatcher:start: event:' + str(event['Type']) + ' QueueSize:' + str( self._eventQueue.qsize()),debug.debugLevel.INFO) if not event: return + if not event['Type']: + return if event['Type'] == fenrirEventType.Ignore: return elif event['Type'] == fenrirEventType.StopMainLoop: - self.handleStopMainLoop() + self.handleStopMainLoop(event) return elif event['Type'] == fenrirEventType.ScreenUpdate: - self.env['runtime']['fenrirManager'].handleScreenUpdate() + self.env['runtime']['fenrirManager'].handleScreenUpdate(event) elif event['Type'] == fenrirEventType.KeyboardInput: - self.env['runtime']['fenrirManager'].handleInput() + self.env['runtime']['fenrirManager'].handleInput(event) elif event['Type'] == fenrirEventType.BrailleInput: pass elif event['Type'] == fenrirEventType.PlugInputDevice: @@ -63,18 +65,19 @@ class eventManager(): elif event['Type'] == fenrirEventType.BrailleFlush: pass elif event['Type'] == fenrirEventType.ScreenChanged: - self.env['runtime']['fenrirManager'].handleScreenChange() + self.env['runtime']['fenrirManager'].handleScreenChange(event) elif event['Type'] == fenrirEventType.HeartBeat: - self.env['runtime']['fenrirManager'].handleHeartBeat() + 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 = 1 while( self.isMainEventLoopRunning()): - st = time.time() self.proceedEventLoop() - def handleStopMainLoop(self): + def handleStopMainLoop(self, event): self._mainLoopRunning.value = 0 time.sleep(0.1) def stopMainEventLoop(self, Force = False): diff --git a/src/fenrir/core/fenrirManager.py b/src/fenrir/core/fenrirManager.py index 0010d8b9..8d99ff50 100644 --- a/src/fenrir/core/fenrirManager.py +++ b/src/fenrir/core/fenrirManager.py @@ -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(): @@ -31,8 +32,9 @@ class fenrirManager(): signal.signal(signal.SIGINT, self.captureSignal) signal.signal(signal.SIGTERM, self.captureSignal) self.initialized = True - self.wasCommand = False - + self.modifierInput = False + self.singleKeyCommand = False + self.command = '' def handleArgs(self): args = None parser = argparse.ArgumentParser(description="Fenrir Help") @@ -49,31 +51,44 @@ class fenrirManager(): return self.environment['runtime']['eventManager'].startMainEventLoop() self.shutdown() - def handleInput(self): - startTime = time.time() + def handleInput(self, event): + #startTime = time.time() eventReceived = self.environment['runtime']['inputManager'].getInputEvent() if eventReceived: - self.prepareCommand() - #if not self.environment['runtime']['screenManager'].isSuspendingScreen(): - # if self.environment['runtime']['helpManager'].handleTutorialMode(): - # self.wasCommand = True - if not (self.wasCommand or self.environment['runtime']['helpManager'].isTutorialMode()) or self.environment['runtime']['screenManager'].isSuspendingScreen(): - self.environment['runtime']['inputManager'].writeEventBuffer() - if self.environment['runtime']['inputManager'].noKeyPressed(): - if self.wasCommand: - self.wasCommand = False - self.environment['runtime']['inputManager'].clearEventBuffer() - self.environment['runtime']['commandManager'].clearCommandQueued() + + if self.environment['runtime']['screenManager'].isSuspendingScreen(): + self.environment['runtime']['inputManager'].writeEventBuffer() + else: if self.environment['runtime']['helpManager'].isTutorialMode(): - self.environment['runtime']['inputManager'].clearEventBuffer() - if self.environment['input']['keyForeward'] > 0: - self.environment['input']['keyForeward'] -=1 + self.environment['runtime']['inputManager'].clearEventBuffer() + + self.detectCommand() + + if self.modifierInput: + self.environment['runtime']['inputManager'].clearEventBuffer() + if self.singleKeyCommand: + if self.environment['runtime']['inputManager'].noKeyPressed(): + self.environment['runtime']['inputManager'].clearEventBuffer() + else: + self.environment['runtime']['inputManager'].writeEventBuffer() + if self.environment['runtime']['inputManager'].noKeyPressed(): + self.modifierInput = False + self.singleKeyCommand = False + if self.environment['input']['keyForeward'] > 0: + self.environment['input']['keyForeward'] -=1 self.environment['runtime']['screenManager'].update('onInput') self.environment['runtime']['commandManager'].executeDefaultTrigger('onInput') - self.handleCommands() - print('handleInput:',time.time() - startTime) - - def handleScreenChange(self): + #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(): @@ -84,8 +99,8 @@ class fenrirManager(): ''' self.environment['runtime']['commandManager'].executeDefaultTrigger('onScreenChanged') - def handleScreenUpdate(self): - startTime = time.time() + def handleScreenUpdate(self, event): + #startTime = time.time() self.environment['runtime']['screenManager'].update('onUpdate') ''' @@ -100,39 +115,46 @@ class fenrirManager(): self.environment['runtime']['cursorManager'].isCursorHorizontalMove(): self.environment['runtime']['commandManager'].executeDefaultTrigger('onCursorChange') self.environment['runtime']['commandManager'].executeDefaultTrigger('onScreenUpdate') - print('handleScreenUpdate:',time.time() - startTime) + #print('handleScreenUpdate:',time.time() - startTime) - def handlePlugInputDevice(self): + def handlePlugInputDevice(self, event): self.environment['runtime']['commandManager'].executeDefaultTrigger('PlugInputDevice') - def handleHeartBeat(self): + def handleHeartBeat(self, event): self.environment['runtime']['commandManager'].executeDefaultTrigger('onHeartBeat') #self.environment['runtime']['outputManager'].brailleText(flush=False) - def prepareCommand(self): - if self.environment['runtime']['screenManager'].isSuspendingScreen(): - self.wasCommand = False - return - if self.environment['runtime']['inputManager'].noKeyPressed(): - return + 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 - if len(self.environment['input']['prevDeepestInput']) > len(self.environment['input']['currInput']): - return - if self.environment['runtime']['helpManager'].isTutorialMode(): - self.environment['runtime']['commandManager'].executeCommand( self.environment['commandInfo']['currCommand'], 'help') - 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['runtime']['eventManager'].stopMainEventLoop() diff --git a/src/fenrir/core/inputManager.py b/src/fenrir/core/inputManager.py index fd5d3e2b..33a6bc59 100644 --- a/src/fenrir/core/inputManager.py +++ b/src/fenrir/core/inputManager.py @@ -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,7 +148,6 @@ 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']: @@ -172,7 +164,8 @@ class inputManager(): 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 +178,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,6 +194,10 @@ 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): diff --git a/src/fenrir/screenDriver/vcsaDriver.py b/src/fenrir/screenDriver/vcsaDriver.py index c6473d1b..003c68e4 100644 --- a/src/fenrir/screenDriver/vcsaDriver.py +++ b/src/fenrir/screenDriver/vcsaDriver.py @@ -260,7 +260,7 @@ 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 - s = time.time() + if screenEncoding.upper() == 'AUTO': self.updateCharMap(str(self.env['screen']['newTTY'])) self.env['screen']['newContentText'], \ @@ -271,7 +271,7 @@ class driver(): 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']) - print(time.time() -s, self.env['screen']['newTTY'] ) + if self.env['screen']['newTTY'] != self.env['screen']['oldTTY']: self.env['screen']['oldContentBytes'] = b'' self.env['screen']['oldContentAttrib'] = b'' From 2c11d42677166eb6c139e85de5222e0f72ad70e3 Mon Sep 17 00:00:00 2001 From: chrys87 Date: Thu, 20 Jul 2017 16:10:01 +0200 Subject: [PATCH 78/96] Update known bugs.txt --- known bugs.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/known bugs.txt b/known bugs.txt index f8f1cae7..c93011c7 100644 --- a/known bugs.txt +++ b/known bugs.txt @@ -1,12 +1,10 @@ Known Bugs (Problems with the logic ): - word echo triggers twice if there are two spaces after an word and you arrow over them - spellcheck triggers twice if there are two spaces after an word and you arrow over them -- keys sometimes get stuck - device detection is broken - arrow up/down announcement is broken - let drivers choos between threads and process - HilightTracking is broken for autoencoding -- commands are sometimes fired twice (keypress and key release) Glitches (improve diff results): - For example, in screen, it just tells me bell in window, but doesn't tell me which one. (southernprince) @@ -14,5 +12,7 @@ Glitches (improve diff results): - whole status line in irssi is spoken insteed of just the changes - whole status line in vim is spoken insteed of just the changes -Questions: +Test: - cyrillic (Done (Autoencode), needs testing) +- commands are sometimes fired twice (keypress and key release) +- keys sometimes get stuck From 9e84859326f7879744d7306019c93ebbc9df7e34 Mon Sep 17 00:00:00 2001 From: chrys Date: Thu, 20 Jul 2017 23:19:32 +0200 Subject: [PATCH 79/96] remove ugly hack for read history --- src/fenrir/core/inputManager.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/fenrir/core/inputManager.py b/src/fenrir/core/inputManager.py index 33a6bc59..0038fd78 100644 --- a/src/fenrir/core/inputManager.py +++ b/src/fenrir/core/inputManager.py @@ -149,9 +149,6 @@ class inputManager(): if self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'grabDevices'): self.env['runtime']['inputDriver'].writeEventBuffer() 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) From 96215607d8e588579dae56eeaa096890dc9e40d4 Mon Sep 17 00:00:00 2001 From: chrys Date: Thu, 20 Jul 2017 23:28:53 +0200 Subject: [PATCH 80/96] some cleanups --- src/fenrir/core/inputManager.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/fenrir/core/inputManager.py b/src/fenrir/core/inputManager.py index 0038fd78..1b2fdc55 100644 --- a/src/fenrir/core/inputManager.py +++ b/src/fenrir/core/inputManager.py @@ -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) @@ -153,11 +153,13 @@ class inputManager(): 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 isFenrirKeyPressed(self): + # print('isFenrirKeyPressed') + # return 'KEY_FENRIR' in self.env['input']['prevDeepestInput'] - def isScriptKeyPressed(self): - return 'KEY_SCRIPT' in self.env['input']['prevDeepestInput'] + #def isScriptKeyPressed(self): + # print('isScriptKeyPressed') + # return 'KEY_SCRIPT' in self.env['input']['prevDeepestInput'] def noKeyPressed(self): return self.env['input']['currInput'] == [] @@ -195,10 +197,13 @@ class inputManager(): 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 '' From 9d9f030dba5379a24c4c6be39db7d9f66f28f0af Mon Sep 17 00:00:00 2001 From: chrys Date: Thu, 20 Jul 2017 23:31:52 +0200 Subject: [PATCH 81/96] some cleanups --- src/fenrir/core/commandData.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fenrir/core/commandData.py b/src/fenrir/core/commandData.py index 50bc072d..ed8c1061 100644 --- a/src/fenrir/core/commandData.py +++ b/src/fenrir/core/commandData.py @@ -24,7 +24,7 @@ commandBuffer = { # used by the commandManager commandInfo = { -'currCommand': '', +#'currCommand': '', 'lastCommandExecutionTime': time.time(), 'lastCommandRequestTime': time.time(), } From 6fc6fa6ec2ca108faf3b0932216fc94fb23c3e4a Mon Sep 17 00:00:00 2001 From: chrys Date: Thu, 20 Jul 2017 23:32:14 +0200 Subject: [PATCH 82/96] some cleanups --- src/fenrir/core/commandData.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/fenrir/core/commandData.py b/src/fenrir/core/commandData.py index ed8c1061..987810f0 100644 --- a/src/fenrir/core/commandData.py +++ b/src/fenrir/core/commandData.py @@ -7,7 +7,6 @@ from core import debug import time - # used as shared memory between commands # use this in your own commands commandBuffer = { From fa5f7d384e74a5ce6b39687d5ca8165b98d88240 Mon Sep 17 00:00:00 2001 From: chrys Date: Fri, 21 Jul 2017 00:17:41 +0200 Subject: [PATCH 83/96] todo --- TODO v2.0 | 1 + src/fenrir/core/eventManager.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/TODO v2.0 b/TODO v2.0 index a06f2756..0c285e62 100644 --- a/TODO v2.0 +++ b/TODO v2.0 @@ -4,6 +4,7 @@ Things with not so deep knowledge needed are marekd wiht "(Easy for contribution General: - implement onScreenUpdate commands read highlighted text mode +- Migrate *Data.py to classes and use getter/setter - try to make it more asynchronus with multpible threads - be more event based (vcsa sets POLLPRI) http://scotdoyle.com/python-epoll-howto.html diff --git a/src/fenrir/core/eventManager.py b/src/fenrir/core/eventManager.py index 945c6a16..1861dca7 100644 --- a/src/fenrir/core/eventManager.py +++ b/src/fenrir/core/eventManager.py @@ -97,9 +97,9 @@ class eventManager(): 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)) - self._eventProcesses.append(t) t.start() def cleanEventQueue(self): if self._eventQueue.empty(): From 62714a14c523c50eb9ce741a24735589cd51020b Mon Sep 17 00:00:00 2001 From: chrys87 Date: Fri, 21 Jul 2017 09:28:59 +0200 Subject: [PATCH 84/96] Removed unused Code --- src/fenrir/core/helpManager.py | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/src/fenrir/core/helpManager.py b/src/fenrir/core/helpManager.py index 57614d4c..c6e955c1 100755 --- a/src/fenrir/core/helpManager.py +++ b/src/fenrir/core/helpManager.py @@ -79,26 +79,4 @@ class helpManager(): return self.tutorialListIndex -= 1 if self.tutorialListIndex < 0: - self.tutorialListIndex = len(self.helpDict) - 1 - def handleTutorialMode(self): - return - if self.env['runtime']['inputManager'].noKeyPressed(): - return - if self.env['input']['currInput'] in [['KEY_F1', 'KEY_FENRIR']]: - self.env['runtime']['commandManager'].runCommand('TOGGLE_TUTORIAL_MODE', 'help') - return True - if not self.isTutorialMode(): - return - if self.env['input']['currInput'] in [['KEY_ESC']]: - self.env['runtime']['commandManager'].runCommand('TOGGLE_TUTORIAL_MODE', 'help') - return True - if self.env['input']['currInput'] in [['KEY_UP']]: - self.env['runtime']['commandManager'].runCommand('PREV_HELP', 'help') - return True - if self.env['input']['currInput'] in [['KEY_DOWN']]: - self.env['runtime']['commandManager'].runCommand('NEXT_HELP', 'help') - return True - if self.env['input']['currInput'] in [['KEY_SPACE']]: - self.env['runtime']['commandManager'].runCommand('CURR_HELP', 'help') - return True - return False + self.tutorialListIndex = len(self.helpDict) - 1 From e45979048389e50f23b68760cb23926b3a6da3d9 Mon Sep 17 00:00:00 2001 From: chrys87 Date: Fri, 21 Jul 2017 09:29:49 +0200 Subject: [PATCH 85/96] remove unneded call for creating tutorial list --- src/fenrir/core/helpManager.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/fenrir/core/helpManager.py b/src/fenrir/core/helpManager.py index c6e955c1..7b81ee62 100755 --- a/src/fenrir/core/helpManager.py +++ b/src/fenrir/core/helpManager.py @@ -13,7 +13,6 @@ class helpManager(): self.tutorialListIndex = None def initialize(self, environment): self.env = environment - self.createHelpDict() def shutdown(self): pass def toggleTutorialMode(self): From 550c8b92acc8d0db8f7c56cebabcfb6b10e622e6 Mon Sep 17 00:00:00 2001 From: chrys87 Date: Fri, 21 Jul 2017 09:30:47 +0200 Subject: [PATCH 86/96] Define as Dict --- src/fenrir/core/helpManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fenrir/core/helpManager.py b/src/fenrir/core/helpManager.py index 7b81ee62..0370ed70 100755 --- a/src/fenrir/core/helpManager.py +++ b/src/fenrir/core/helpManager.py @@ -9,7 +9,7 @@ from core import debug class helpManager(): def __init__(self): - self.helpDict = None + self.helpDict = {} self.tutorialListIndex = None def initialize(self, environment): self.env = environment From 41b2b5d05f8d4c76013ce6c5480c09aaad55a989 Mon Sep 17 00:00:00 2001 From: chrys87 Date: Fri, 21 Jul 2017 09:38:10 +0200 Subject: [PATCH 87/96] Mark tutorial list as done --- TODO v2.0 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/TODO v2.0 b/TODO v2.0 index 0c285e62..a04f4b6d 100644 --- a/TODO v2.0 +++ b/TODO v2.0 @@ -24,7 +24,6 @@ General: - input - new device - implement commands - Tutorial Mode: navigate through a list of bound commands. speak binding and description. attributes_curr_char (Easy for contribution) https://github.com/jwilk/vcsapeek/blob/master/linuxvt.py - generic list (convert clipboard management) (Easy for contribution) @@ -118,4 +117,6 @@ Braille Support: - review = priority to review Settings: -- configuration should be overwritable with parameter and alternative paths (Easy for contribution) +- [X] configuration should be overwritable with parameter and alternative paths (Easy for contribution) +Tutorial Mode: +- [X] navigate through a list of bound commands. speak binding and description. From b935525a29fd1c36ccebd037d100dbbf2af6a86a Mon Sep 17 00:00:00 2001 From: chrys87 Date: Fri, 21 Jul 2017 09:40:20 +0200 Subject: [PATCH 88/96] Update TODO v2.0 --- TODO v2.0 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TODO v2.0 b/TODO v2.0 index a04f4b6d..2574eac2 100644 --- a/TODO v2.0 +++ b/TODO v2.0 @@ -26,7 +26,7 @@ General: - implement commands attributes_curr_char (Easy for contribution) https://github.com/jwilk/vcsapeek/blob/master/linuxvt.py -- generic list (convert clipboard management) (Easy for contribution) +- generic list or see Tutorial mode list (convert clipboard management) (Easy for contribution) next item pref item curr item From aad47d0746474af820007612a46ef017fdbcc328 Mon Sep 17 00:00:00 2001 From: chrys87 Date: Fri, 21 Jul 2017 11:03:05 +0200 Subject: [PATCH 89/96] Update vcsaDriver.py --- src/fenrir/screenDriver/vcsaDriver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fenrir/screenDriver/vcsaDriver.py b/src/fenrir/screenDriver/vcsaDriver.py index 003c68e4..c0fc4071 100644 --- a/src/fenrir/screenDriver/vcsaDriver.py +++ b/src/fenrir/screenDriver/vcsaDriver.py @@ -222,7 +222,7 @@ class driver(): ch |= 0x100 try: lineText += self.charmap[ch] - except: + except KeyError: lineText += chr('?') allText += lineText + '\n' allAttrib += lineAttrib From cf118a310cbdadf5158366405f6db930532969c8 Mon Sep 17 00:00:00 2001 From: chrys Date: Sun, 23 Jul 2017 13:08:16 +0200 Subject: [PATCH 90/96] remove unused functions --- src/fenrir/core/inputManager.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/fenrir/core/inputManager.py b/src/fenrir/core/inputManager.py index 1b2fdc55..df82337e 100644 --- a/src/fenrir/core/inputManager.py +++ b/src/fenrir/core/inputManager.py @@ -153,14 +153,6 @@ class inputManager(): self.env['runtime']['debug'].writeDebugOut("Error while writeUInput",debug.debugLevel.ERROR) self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) - #def isFenrirKeyPressed(self): - # print('isFenrirKeyPressed') - # return 'KEY_FENRIR' in self.env['input']['prevDeepestInput'] - - #def isScriptKeyPressed(self): - # print('isScriptKeyPressed') - # return 'KEY_SCRIPT' in self.env['input']['prevDeepestInput'] - def noKeyPressed(self): return self.env['input']['currInput'] == [] def isKeyPress(self): From 41919a90e2c929cd30531cdc0fce12d7551428c5 Mon Sep 17 00:00:00 2001 From: chrys Date: Sun, 23 Jul 2017 19:52:12 +0200 Subject: [PATCH 91/96] mark bugs as fixed --- known bugs.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/known bugs.txt b/known bugs.txt index c93011c7..c4e674bf 100644 --- a/known bugs.txt +++ b/known bugs.txt @@ -12,7 +12,3 @@ Glitches (improve diff results): - whole status line in irssi is spoken insteed of just the changes - whole status line in vim is spoken insteed of just the changes -Test: -- cyrillic (Done (Autoencode), needs testing) -- commands are sometimes fired twice (keypress and key release) -- keys sometimes get stuck From 995fdcae0da6315a689edd3d9cc564ad9dc33bcd Mon Sep 17 00:00:00 2001 From: chrys Date: Sun, 23 Jul 2017 20:32:21 +0200 Subject: [PATCH 92/96] update Todos --- TODO v2.0 | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/TODO v2.0 b/TODO v2.0 index 2574eac2..546eb2e6 100644 --- a/TODO v2.0 +++ b/TODO v2.0 @@ -4,7 +4,18 @@ Things with not so deep knowledge needed are marekd wiht "(Easy for contribution General: - implement onScreenUpdate commands read highlighted text mode -- Migrate *Data.py to classes and use getter/setter + +- Migrate *Data.py to classes and use getter/setter (Easy for contribution) + commandsData.py + eventData.py + generalData.py + inputData.py + outputData.py + punctuationData.py + runtimeData.py + screenData.py + settingsData -> defaultSettings.py + - try to make it more asynchronus with multpible threads - be more event based (vcsa sets POLLPRI) http://scotdoyle.com/python-epoll-howto.html @@ -23,9 +34,11 @@ General: - screen - input - new device + - implement commands attributes_curr_char (Easy for contribution) https://github.com/jwilk/vcsapeek/blob/master/linuxvt.py + - generic list or see Tutorial mode list (convert clipboard management) (Easy for contribution) next item pref item @@ -56,14 +69,18 @@ Driver: https://docs.python.org/3.2/library/pty.html http://sqizit.bartletts.id.au/2011/02/14/pseudo-terminals-in-python/ https://blog.konpat.me/pythons-pseudo-terminal-pty-examples/ + - implement PTY Input driver + - ATK input driver (don't grab on graphical interface) https://git.linux-a11y.org/AIT/pyatspi2/src/master/examples/keypress.py + - Dectalk SpeechDriver https://github.com/tvraman/emacspeak/blob/master/servers/obsolete/python/dectalk.py Settings: - write settings (Easy for contribution) + - menue for settings configuration (Easy for contribution) Application Profiles From 44fd438ced7e349300957b892f617462684f6816 Mon Sep 17 00:00:00 2001 From: chrys Date: Sun, 23 Jul 2017 20:37:48 +0200 Subject: [PATCH 93/96] update Todos --- TODO v1.5 | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ TODO v2.0 | 75 ++++--------------------------------------------------- 2 files changed, 79 insertions(+), 70 deletions(-) create mode 100644 TODO v1.5 diff --git a/TODO v1.5 b/TODO v1.5 new file mode 100644 index 00000000..02db67cf --- /dev/null +++ b/TODO v1.5 @@ -0,0 +1,74 @@ +ToDo list for Fenrir Version 1.5 +Things with not so deep knowledge needed are marekd wiht "(Easy for contribution)". so just start with that :). + +General: +- Migrate *Data.py to classes and use getter/setter (Easy for contribution) + commandsData.py + eventData.py + generalData.py + inputData.py + outputData.py + punctuationData.py + runtimeData.py + screenData.py + settingsData -> defaultSettings.py + +- try to make it more asynchronus with multpible threads +- be more event based (vcsa sets POLLPRI) + http://scotdoyle.com/python-epoll-howto.html + Needed events: + screen update (vcsa sets POLLPRI) + plug input device (udev event) + screen changed (logind event, collides with screen update) + keyboard input (select, wait forever) + braille input (brlapi_readKey) + braille flush (timer, sleep) + Each event is watched in an own thread. This improves performance and reduce the load. + The event loop is to be done as "queue" since those are thread safe. + The threads are reading incomming data and add the events and data to the queue + the mainloop just reads the queue in an blocking way and executes the needed codepath with the data. + clean up the code for the events so that just the correct codepath is used: + - screen + - input + - new device +-----------DONE---------------- +- initial working setup.py +- leave review on typing +- add dependency check (check-dependencys.py) +- Add nice dummy drivers as template or for debugging +- reimplement detection code for X11 +- initial translate structure (manuelcortez Thanks!) + http://www.supernifty.org/blog/2011/09/16/python-localization-made-easy/ +- add a configurable place where you can place own commands or overwrite existing commands without need to change default code +- implement autodetection of plugged and unplugged input devices (python-pyudev) for evdev driver + http://stackoverflow.com/questions/22678686/python-script-to-detect-hot-plug-event + http://askubuntu.com/questions/508236/how-can-i-run-code-whenever-a-usb-device-is-unplugged-without-requiring-root + https://www.mattfischer.com/blog/?p=182 +- implement speechdriver generic (Easy for contribution) +- try to autodetect encoding (Easy for contribution) (Prototype "charmapTTY" in play zone) + https://stackoverflow.com/questions/6396659/how-do-you-get-the-encoding-of-the-terminal-from-within-a-python-script + +Braille Support: + initial BrlTTY driver + detect device size via driver + output to braille device + make flushMode configurable + make flushTimeout configurable + flush message after X seconds and show current line (review over text) + tweak current commands and output + command flush_braille + command for scroll left + command for scroll right + create offset for scrolling + respect scrolling + make cursor following configurable (brailleCursorTrackingMode) + - cell + - page + follow cursor while typing + brailleFocusMode: + - review = priority to review + +Settings: +- [X] configuration should be overwritable with parameter and alternative paths (Easy for contribution) +Tutorial Mode: +- [X] navigate through a list of bound commands. speak binding and description. diff --git a/TODO v2.0 b/TODO v2.0 index 546eb2e6..daa7b542 100644 --- a/TODO v2.0 +++ b/TODO v2.0 @@ -5,36 +5,6 @@ General: - implement onScreenUpdate commands read highlighted text mode -- Migrate *Data.py to classes and use getter/setter (Easy for contribution) - commandsData.py - eventData.py - generalData.py - inputData.py - outputData.py - punctuationData.py - runtimeData.py - screenData.py - settingsData -> defaultSettings.py - -- try to make it more asynchronus with multpible threads -- be more event based (vcsa sets POLLPRI) - http://scotdoyle.com/python-epoll-howto.html - Needed events: - screen update (vcsa sets POLLPRI) - plug input device (udev event) - screen changed (logind event, collides with screen update) - keyboard input (select, wait forever) - braille input (brlapi_readKey) - braille flush (timer, sleep) - Each event is watched in an own thread. This improves performance and reduce the load. - The event loop is to be done as "queue" since those are thread safe. - The threads are reading incomming data and add the events and data to the queue - the mainloop just reads the queue in an blocking way and executes the needed codepath with the data. - clean up the code for the events so that just the correct codepath is used: - - screen - - input - - new device - - implement commands attributes_curr_char (Easy for contribution) https://github.com/jwilk/vcsapeek/blob/master/linuxvt.py @@ -75,7 +45,7 @@ Driver: - ATK input driver (don't grab on graphical interface) https://git.linux-a11y.org/AIT/pyatspi2/src/master/examples/keypress.py -- Dectalk SpeechDriver +- Dectalk SpeechDriver (Easy for contribution, device needed - i dont own one) https://github.com/tvraman/emacspeak/blob/master/servers/obsolete/python/dectalk.py Settings: @@ -83,7 +53,7 @@ Settings: - menue for settings configuration (Easy for contribution) -Application Profiles +Application Profiles (low priority): - reimplement process detection without subprocessing // this is started by chrys - fenrir is not able to detect the current application inside of screen. ps -e -H -o pid,pgrp,ppid,tty,cmd @@ -97,43 +67,8 @@ Application Profiles - per application shortcuts -----------DONE---------------- -- initial working setup.py -- leave review on typing -- add dependency check (check-dependencys.py) -- Add nice dummy drivers as template or for debugging -- reimplement detection code for X11 -- initial translate structure (manuelcortez Thanks!) - http://www.supernifty.org/blog/2011/09/16/python-localization-made-easy/ -- add a configurable place where you can place own commands or overwrite existing commands without need to change default code -- implement autodetection of plugged and unplugged input devices (python-pyudev) for evdev driver - http://stackoverflow.com/questions/22678686/python-script-to-detect-hot-plug-event - http://askubuntu.com/questions/508236/how-can-i-run-code-whenever-a-usb-device-is-unplugged-without-requiring-root - https://www.mattfischer.com/blog/?p=182 -- implement speechdriver generic (Easy for contribution) -- try to autodetect encoding (Easy for contribution) (Prototype "charmapTTY" in play zone) - https://stackoverflow.com/questions/6396659/how-do-you-get-the-encoding-of-the-terminal-from-within-a-python-script - +General: Braille Support: - initial BrlTTY driver - detect device size via driver - output to braille device - make flushMode configurable - make flushTimeout configurable - flush message after X seconds and show current line (review over text) - tweak current commands and output - command flush_braille - command for scroll left - command for scroll right - create offset for scrolling - respect scrolling - make cursor following configurable (brailleCursorTrackingMode) - - cell - - page - follow cursor while typing - brailleFocusMode: - - review = priority to review - +Driver: Settings: -- [X] configuration should be overwritable with parameter and alternative paths (Easy for contribution) -Tutorial Mode: -- [X] navigate through a list of bound commands. speak binding and description. +Application Profiles: From e275d8d22afddc32057ae4435003d55f3ccc0a00 Mon Sep 17 00:00:00 2001 From: chrys Date: Sun, 23 Jul 2017 20:53:23 +0200 Subject: [PATCH 94/96] fix nongrabbing mode; remove bak --- src/fenrir/inputDriver/evdevDriver.py | 8 +- src/fenrir/screenDriver/vcsaDriverBak.py | 244 ----------------------- 2 files changed, 5 insertions(+), 247 deletions(-) delete mode 100644 src/fenrir/screenDriver/vcsaDriverBak.py diff --git a/src/fenrir/inputDriver/evdevDriver.py b/src/fenrir/inputDriver/evdevDriver.py index 99d25af0..c09cd42e 100644 --- a/src/fenrir/inputDriver/evdevDriver.py +++ b/src/fenrir/inputDriver/evdevDriver.py @@ -59,6 +59,7 @@ class driver(): 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) @@ -84,14 +85,12 @@ class driver(): while self.watchDog.value == 0: if active.value == 0: return - time.sleep(0.001) 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 @@ -148,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: @@ -252,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: diff --git a/src/fenrir/screenDriver/vcsaDriverBak.py b/src/fenrir/screenDriver/vcsaDriverBak.py deleted file mode 100644 index 333f738e..00000000 --- a/src/fenrir/screenDriver/vcsaDriverBak.py +++ /dev/null @@ -1,244 +0,0 @@ -#!/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -import difflib -import re -import subprocess -import glob, os -import fcntl -import termios -import time -import select -import dbus -from core import debug -from core.eventData import fenrirEventType -from utils import screen_utils - -class driver(): - def __init__(self): - self.vcsaDevicePath = '/dev/vcsa' - self.ListSessions = None - def initialize(self, environment): - self.env = environment - self.env['runtime']['eventManager'].addCustomEventThread(self.updateWatchdog) - def shutdown(self): - pass - def getCurrScreen(self): - self.env['screen']['oldTTY'] = self.env['screen']['newTTY'] - try: - currScreenFile = open('/sys/devices/virtual/tty/tty0/active','r') - self.env['screen']['newTTY'] = str(currScreenFile.read()[3:-1]) - currScreenFile.close() - except Exception as e: - self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) - def injectTextToScreen(self, text, screen = None): - useScreen = "/dev/tty" + self.env['screen']['newTTY'] - if screen != None: - useScreen = screen - with open(useScreen, 'w') as fd: - for c in text: - fcntl.ioctl(fd, termios.TIOCSTI, c) - - def getCurrApplication(self): - apps = [] - try: - currScreen = self.env['screen']['newTTY'] - apps = subprocess.Popen('ps -t tty' + currScreen + ' -o comm,tty,stat', shell=True, stdout=subprocess.PIPE).stdout.read().decode()[:-1].split('\n') - except Exception as e: - self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) - return - try: - for i in apps: - i = i.upper() - i = i.split() - i[0] = i[0] - i[1] = i[1] - if '+' in i[2]: - if i[0] != '': - if not "GREP" == i[0] and \ - not "SH" == i[0] and \ - not "PS" == i[0]: - if "TTY"+currScreen in i[1]: - if self.env['screen']['newApplication'] != i[0]: - self.env['screen']['newApplication'] = i[0] - return - except Exception as e: - self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) - - def getSessionInformation(self): - try: - bus = dbus.SystemBus() - if not self.ListSessions: - obj = bus.get_object('org.freedesktop.login1', '/org/freedesktop/login1') - inf = dbus.Interface(obj, 'org.freedesktop.login1.Manager') - self.ListSessions = inf.get_dbus_method('ListSessions') - sessions = self.ListSessions() - self.env['screen']['autoIgnoreScreens'] = [] - for session in sessions: - obj = bus.get_object('org.freedesktop.login1', session[4]) - inf = dbus.Interface(obj, 'org.freedesktop.DBus.Properties') - sessionType = inf.Get('org.freedesktop.login1.Session', 'Type') - screen = str(inf.Get('org.freedesktop.login1.Session', 'VTNr')) - if screen == '': - screen = str(inf.Get('org.freedesktop.login1.Session', 'TTY')) - screen = screen[screen.upper().find('TTY') + 3:] - if screen == '': - self.env['runtime']['debug'].writeDebugOut('No TTY found for session:' + session[4],debug.debugLevel.ERROR) - return - if sessionType.upper() == 'X11': - self.env['screen']['autoIgnoreScreens'].append(screen) - if screen == self.env['screen']['newTTY'] : - if self.env['general']['currUser'] != session[2]: - self.env['general']['prevUser'] = self.env['general']['currUser'] - 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['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 update(self, trigger='onUpdate'): - if trigger == 'onInput': # no need for an update on input for VCSA - return - #print(self.env['screen']['newTTY'], self.env['screen']['oldTTY']) - newContentBytes = b'' - try: - # read screen - vcsa = open(self.vcsaDevicePath + self.env['screen']['newTTY'],'rb',0) - newContentBytes = vcsa.read() - vcsa.close() - if len(newContentBytes) < 5: - return - except Exception as e: - self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) - return - screenEncoding = self.env['runtime']['settingsManager'].getSetting('screen', 'encoding') - # set new "old" values - self.env['screen']['oldContentBytes'] = self.env['screen']['newContentBytes'] - self.env['screen']['oldContentText'] = self.env['screen']['newContentText'] - self.env['screen']['oldContentAttrib'] = self.env['screen']['newContentAttrib'] - self.env['screen']['oldCursor'] = self.env['screen']['newCursor'].copy() - if self.env['screen']['newCursorAttrib']: - self.env['screen']['oldCursorAttrib'] = self.env['screen']['newCursorAttrib'].copy() - self.env['screen']['oldDelta'] = self.env['screen']['newDelta'] - self.env['screen']['oldAttribDelta'] = self.env['screen']['newAttribDelta'] - self.env['screen']['oldNegativeDelta'] = self.env['screen']['newNegativeDelta'] - self.env['screen']['newContentBytes'] = newContentBytes - # get metadata like cursor or screensize - self.env['screen']['lines'] = int( self.env['screen']['newContentBytes'][0]) - self.env['screen']['columns'] = int( self.env['screen']['newContentBytes'][1]) - 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 self.env['screen']['newTTY'] != self.env['screen']['oldTTY']: - self.env['screen']['oldContentBytes'] = b'' - self.env['screen']['oldContentAttrib'] = b'' - self.env['screen']['oldContentText'] = '' - self.env['screen']['oldCursor']['x'] = 0 - self.env['screen']['oldCursor']['y'] = 0 - self.env['screen']['oldDelta'] = '' - self.env['screen']['oldAttribDelta'] = '' - self.env['screen']['oldCursorAttrib'] = None - self.env['screen']['newCursorAttrib'] = None - self.env['screen']['oldNegativeDelta'] = '' - # initialize current deltas - self.env['screen']['newNegativeDelta'] = '' - self.env['screen']['newDelta'] = '' - self.env['screen']['newAttribDelta'] = '' - - # changes on the screen - oldScreenText = re.sub(' +',' ',self.env['runtime']['screenManager'].getWindowAreaInText(self.env['screen']['oldContentText'])) - newScreenText = re.sub(' +',' ',self.env['runtime']['screenManager'].getWindowAreaInText(self.env['screen']['newContentText'])) - typing = False - if (self.env['screen']['oldContentText'] != self.env['screen']['newContentText']) and \ - (self.env['screen']['newContentText'] != '' ): - if oldScreenText == '' and\ - newScreenText != '': - self.env['screen']['newDelta'] = newScreenText - else: - cursorLineStart = self.env['screen']['newCursor']['y'] * self.env['screen']['columns'] + self.env['screen']['newCursor']['y'] - cursorLineEnd = cursorLineStart + self.env['screen']['columns'] - if self.env['screen']['oldCursor']['x'] != self.env['screen']['newCursor']['x'] and \ - self.env['screen']['oldCursor']['y'] == self.env['screen']['newCursor']['y'] and \ - self.env['screen']['newContentText'][:cursorLineStart] == self.env['screen']['oldContentText'][:cursorLineStart]: - - oldScreenText = self.env['screen']['oldContentText'][cursorLineStart:cursorLineEnd] - oldScreenText = re.sub(' +',' ',oldScreenText) - newScreenText = self.env['screen']['newContentText'][cursorLineStart:cursorLineEnd] - newScreenText = re.sub(' +',' ',newScreenText) - diff = difflib.ndiff(oldScreenText, newScreenText) - typing = True - else: - diff = difflib.ndiff( oldScreenText.split('\n'),\ - newScreenText.split('\n')) - - diffList = list(diff) - - if self.env['runtime']['settingsManager'].getSetting('general', 'newLinePause') and not typing: - self.env['screen']['newDelta'] = '\n'.join(x[2:] for x in diffList if x[0] == '+') - else: - self.env['screen']['newDelta'] = ''.join(x[2:] for x in diffList if x[0] == '+') - self.env['screen']['newNegativeDelta'] = ''.join(x[2:] for x in diffList if x[0] == '-') - - # track highlighted - if self.env['screen']['oldContentAttrib'] != self.env['screen']['newContentAttrib']: - if self.env['runtime']['settingsManager'].getSettingAsBool('focus', 'highlight'): - self.env['screen']['newAttribDelta'], self.env['screen']['newCursorAttrib'] = screen_utils.trackHighlights(self.env['screen']['oldContentAttrib'], self.env['screen']['newContentAttrib'], self.env['screen']['newContentText'], self.env['screen']['columns']) - From 58e045135082fff972cf11f5fc72d6c72ccf9b4c Mon Sep 17 00:00:00 2001 From: chrys Date: Sun, 23 Jul 2017 20:58:30 +0200 Subject: [PATCH 95/96] restructure Todos --- TODO v1.5 | 43 +++++++++++++++++++++++++------------------ known bugs.txt | 4 ---- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/TODO v1.5 b/TODO v1.5 index 02db67cf..a32df009 100644 --- a/TODO v1.5 +++ b/TODO v1.5 @@ -13,24 +13,12 @@ General: screenData.py settingsData -> defaultSettings.py -- try to make it more asynchronus with multpible threads -- be more event based (vcsa sets POLLPRI) - http://scotdoyle.com/python-epoll-howto.html - Needed events: - screen update (vcsa sets POLLPRI) - plug input device (udev event) - screen changed (logind event, collides with screen update) - keyboard input (select, wait forever) - braille input (brlapi_readKey) - braille flush (timer, sleep) - Each event is watched in an own thread. This improves performance and reduce the load. - The event loop is to be done as "queue" since those are thread safe. - The threads are reading incomming data and add the events and data to the queue - the mainloop just reads the queue in an blocking way and executes the needed codepath with the data. - clean up the code for the events so that just the correct codepath is used: - - screen - - input - - new device +Fix Bugs: +- device detection is broken +- arrow up/down announcement is broken +- let drivers choos between threads and process +- HilightTracking is broken for autoencoding + -----------DONE---------------- - initial working setup.py - leave review on typing @@ -68,6 +56,25 @@ Braille Support: brailleFocusMode: - review = priority to review +- initial try to make it more asynchronus with multpible threads +- be more event based (vcsa sets POLLPRI) + http://scotdoyle.com/python-epoll-howto.html + Needed events: + screen update (vcsa sets POLLPRI) + plug input device (udev event) + screen changed (logind event, collides with screen update) + keyboard input (select, wait forever) + braille input (brlapi_readKey) + braille flush (timer, sleep) + Each event is watched in an own thread. This improves performance and reduce the load. + The event loop is to be done as "queue" since those are thread safe. + The threads are reading incomming data and add the events and data to the queue + the mainloop just reads the queue in an blocking way and executes the needed codepath with the data. + clean up the code for the events so that just the correct codepath is used: + - screen + - input + - new device + Settings: - [X] configuration should be overwritable with parameter and alternative paths (Easy for contribution) Tutorial Mode: diff --git a/known bugs.txt b/known bugs.txt index c4e674bf..64a5b86b 100644 --- a/known bugs.txt +++ b/known bugs.txt @@ -1,10 +1,6 @@ Known Bugs (Problems with the logic ): - word echo triggers twice if there are two spaces after an word and you arrow over them - spellcheck triggers twice if there are two spaces after an word and you arrow over them -- device detection is broken -- arrow up/down announcement is broken -- let drivers choos between threads and process -- HilightTracking is broken for autoencoding Glitches (improve diff results): - For example, in screen, it just tells me bell in window, but doesn't tell me which one. (southernprince) From b25229f554ecd02f09427753ff72c9ad7fde7727 Mon Sep 17 00:00:00 2001 From: chrys Date: Sun, 23 Jul 2017 21:01:14 +0200 Subject: [PATCH 96/96] also wiki is done --- TODO v1.5 | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/TODO v1.5 b/TODO v1.5 index a32df009..267934f5 100644 --- a/TODO v1.5 +++ b/TODO v1.5 @@ -20,23 +20,35 @@ Fix Bugs: - HilightTracking is broken for autoencoding -----------DONE---------------- +- Doku: Write a user wiki + https://wiki.linux-a11y.org/doku.php?id=fenrir_user_manual&s[]=fenrir + - initial working setup.py + - leave review on typing + - add dependency check (check-dependencys.py) + - Add nice dummy drivers as template or for debugging + - reimplement detection code for X11 + - initial translate structure (manuelcortez Thanks!) http://www.supernifty.org/blog/2011/09/16/python-localization-made-easy/ + - add a configurable place where you can place own commands or overwrite existing commands without need to change default code + - implement autodetection of plugged and unplugged input devices (python-pyudev) for evdev driver http://stackoverflow.com/questions/22678686/python-script-to-detect-hot-plug-event http://askubuntu.com/questions/508236/how-can-i-run-code-whenever-a-usb-device-is-unplugged-without-requiring-root https://www.mattfischer.com/blog/?p=182 + - implement speechdriver generic (Easy for contribution) + - try to autodetect encoding (Easy for contribution) (Prototype "charmapTTY" in play zone) https://stackoverflow.com/questions/6396659/how-do-you-get-the-encoding-of-the-terminal-from-within-a-python-script -Braille Support: +Braille Support (WIP): initial BrlTTY driver detect device size via driver output to braille device @@ -57,6 +69,7 @@ Braille Support: - review = priority to review - initial try to make it more asynchronus with multpible threads + - be more event based (vcsa sets POLLPRI) http://scotdoyle.com/python-epoll-howto.html Needed events: @@ -76,6 +89,6 @@ Braille Support: - new device Settings: -- [X] configuration should be overwritable with parameter and alternative paths (Easy for contribution) +- configuration should be overwritable with parameter and alternative paths (Easy for contribution) Tutorial Mode: -- [X] navigate through a list of bound commands. speak binding and description. +- navigate through a list of bound commands. speak binding and description.