diff --git a/src/fenrir b/src/fenrir new file mode 100755 index 00000000..735e09e6 --- /dev/null +++ b/src/fenrir @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +import os, sys, inspect +fenrirPath = os.path.dirname(os.path.realpath(os.path.abspath(inspect.getfile(inspect.currentframe())))) + +if not fenrirPath in sys.path: + sys.path.append(fenrirPath) + +from fenrirscreenreader.core import fenrirManager + +def main(): + app = fenrirManager.fenrirManager() + app.proceed() + del app + +if __name__ == "__main__": + main() diff --git a/src/fenrir-daemon b/src/fenrir-daemon new file mode 100755 index 00000000..80a618a5 --- /dev/null +++ b/src/fenrir-daemon @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +import os, sys, inspect +fenrirPath = os.path.dirname(os.path.realpath(os.path.abspath(inspect.getfile(inspect.currentframe())))) + +if not fenrirPath in sys.path: + sys.path.append(fenrirPath) + +from fenrirscreenreader.core import fenrirManager +from daemonize import Daemonize + +pidFile = "/run/fenrir.pid" + +def main(): + app = fenrirManager.fenrirManager() + app.proceed() + del app + +if __name__ == "__main__": + # for debug in foreground + #daemon = Daemonize(app="fenrir-daemon", pid=pidFile, action=main, foreground=True,chdir=os.path.dirname(os.path.realpath(fenrirVersion.__file__))) + daemon = Daemonize(app="fenrir-daemon", pid=pidFile, action=main, chdir=fenrirPath) + daemon.start() + diff --git a/src/fenrirscreenreader/__init__.py b/src/fenrirscreenreader/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/src/fenrirscreenreader/brailleDriver/__init__.py b/src/fenrirscreenreader/brailleDriver/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/src/fenrirscreenreader/brailleDriver/brlapiDriver.py b/src/fenrirscreenreader/brailleDriver/brlapiDriver.py new file mode 100644 index 00000000..0958fa9b --- /dev/null +++ b/src/fenrirscreenreader/brailleDriver/brlapiDriver.py @@ -0,0 +1,66 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.core.brailleDriver import brailleDriver + +class driver(brailleDriver): + def __init__(self): + brailleDriver.__init__(self) + self._brl = None + + def initialize(self, environment): + self.env = environment + try: + import brlapi + self._brl = brlapi.Connection() + self._deviceSize = self._brl.displaySize + except Exception as e: + print(e) + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + return + self._isInitialized = True + + def getDeviceSize(self): + if not self._isInitialized: + return (0,0) + if not self._deviceSize: + return (0,0) + return self._deviceSize + + def flush(self): + if not self._isInitialized: + return + try: + self._brl.writeText('',0) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('BRAILLE.flush '+str(e),debug.debugLevel.ERROR) + + def writeText(self,text): + if not self._isInitialized: + return + try: + self._brl.writeText(text) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('BRAILLE.writeText '+str(e),debug.debugLevel.ERROR) + + def connectDevice(self): + self._brl = brlapi.Connection() + + def enterScreen(self, screen): + if not self._isInitialized: + return + self._brl.enterTtyMode(int(screen)) + + def leveScreen(self): + if not self._isInitialized: + return + self._brl.leaveTtyMode() + + def shutdown(self): + if not self._isInitialized: + return + self.leveScreen() diff --git a/src/fenrirscreenreader/brailleDriver/debugDriver.py b/src/fenrirscreenreader/brailleDriver/debugDriver.py new file mode 100644 index 00000000..116cd7d3 --- /dev/null +++ b/src/fenrirscreenreader/brailleDriver/debugDriver.py @@ -0,0 +1,49 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.core.brailleDriver import brailleDriver + +class driver(brailleDriver): + def __init__(self): + brailleDriver.__init__(self) + + def initialize(self, environment): + self.env = environment + self._isInitialized = True + self.deviceSize = (40,0) + print('Braille Debug Driver: Initialized') + + def getDeviceSize(self): + if not self._isInitialized: + return (0,0) + print('Braille Debug Driver: getDeviceSize ' + str(self.deviceSize)) + return self.deviceSize + + def writeText(self,text): + if not self._isInitialized: + return + print('Braille Debug Driver: writeText:' + str(text)) + print('Braille Debug Driver: -----------------------------------') + + def connectDevice(self): + print('Braille Debug Driver: connectDevice') + + def enterScreen(self, screen): + if not self._isInitialized: + return + print('Braille Debug Driver: enterScreen') + + def leveScreen(self): + if not self._isInitialized: + return + print('Braille Debug Driver: leveScreen') + + def shutdown(self): + if self._isInitialized: + self.leveScreen() + self._isInitialized = False + print('Braille Debug Driver: Shutdown') diff --git a/src/fenrirscreenreader/brailleDriver/dummyDriver.py b/src/fenrirscreenreader/brailleDriver/dummyDriver.py new file mode 100644 index 00000000..d8f69e56 --- /dev/null +++ b/src/fenrirscreenreader/brailleDriver/dummyDriver.py @@ -0,0 +1,12 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.core.brailleDriver import brailleDriver + +class driver(brailleDriver): + def __init__(self): + brailleDriver.__init__(self) diff --git a/src/fenrirscreenreader/commands/__init__.py b/src/fenrirscreenreader/commands/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/src/fenrirscreenreader/commands/command_template.py b/src/fenrirscreenreader/commands/command_template.py new file mode 100644 index 00000000..f1101b9f --- /dev/null +++ b/src/fenrirscreenreader/commands/command_template.py @@ -0,0 +1,21 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.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): + pass + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/00_init_commands.py b/src/fenrirscreenreader/commands/commands/00_init_commands.py new file mode 100644 index 00000000..1383be41 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/00_init_commands.py @@ -0,0 +1,26 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +# this command is just to initialize stuff. +# like init index lists in memoryManager +# it is not useful to execute it +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + # clipboard + self.env['runtime']['memoryManager'].addIndexList('clipboardHistory', self.env['runtime']['settingsManager'].getSettingAsInt('general', 'numberOfClipboards')) + def shutdown(self): + pass + def getDescription(self): + return 'No description found' + def run(self): + pass + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/__init__.py b/src/fenrirscreenreader/commands/commands/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/src/fenrirscreenreader/commands/commands/add_word_to_spell_check.py b/src/fenrirscreenreader/commands/commands/add_word_to_spell_check.py new file mode 100644 index 00000000..24c24cd9 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/add_word_to_spell_check.py @@ -0,0 +1,55 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import word_utils +import string +initialized = False +try: + import enchant + initialized = True +except: + pass + +class command(): + def __init__(self): + self.language = '' + self.spellChecker = None + def initialize(self, environment): + self.env = environment + self.updateSpellLanguage() + def shutdown(self): + pass + def getDescription(self): + return _('adds the current word to the exceptions dictionary') + def updateSpellLanguage(self): + 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: + self.env['runtime']['outputManager'].presentText(_('pyenchant is not installed'), interrupt=True) + return + if self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage') != self.language: + try: + self.updateSpellLanguage() + except Exception as e: + return + cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() + # get the word + newContent = self.env['screen']['newContentText'].split('\n')[cursorPos['y']] + x, y, currWord, endOfScreen, lineBreak = word_utils.getCurrentWord(cursorPos['x'], 0, newContent) + currWord = currWord.strip(string.whitespace + '!"#$%&\()*+,-./:;<=ยง>?@[\\]^_{|}~') + + if currWord != '': + if self.spellChecker.is_added(currWord): + self.env['runtime']['outputManager'].presentText(_('{0} is already in dict').format(currWord,), soundIcon='Cancel', interrupt=True) + else: + self.spellChecker.add(currWord) + self.env['runtime']['outputManager'].presentText(_('{0} added').format(currWord,), soundIcon='Accept', interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/attribute_cursor.py b/src/fenrirscreenreader/commands/commands/attribute_cursor.py new file mode 100644 index 00000000..9cdca590 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/attribute_cursor.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import screen_utils + +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): + cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() + attributes = screen_utils.splitEvery(self.env['screen']['newContentAttrib'], self.env['screen']['columns']) + attributes = attributes[cursorPos['y']][cursorPos['x']] + attributeFormatString = self.env['runtime']['settingsManager'].getSetting('general', 'attributeFormatString') + attributeFormatString = self.env['runtime']['screenManager'].formatAttributes(attributes, attributeFormatString) + self.env['runtime']['outputManager'].presentText(attributeFormatString, soundIcon='', interrupt=True) + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/bookmark_1.py b/src/fenrirscreenreader/commands/commands/bookmark_1.py new file mode 100644 index 00000000..ce56fc38 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/bookmark_1.py @@ -0,0 +1,48 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import mark_utils +from fenrirscreenreader.utils import line_utils + +class command(): + def __init__(self): + self.ID = '1' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('read Bookmark {0}').format(self.ID,) + + def run(self): + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + if not self.env['commandBuffer']['bookMarks'][self.ID]: + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set').format(self.ID,), interrupt=True) + return + if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]: + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) + return + if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1']: + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) + return + + # set marks + marked = '' + startMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'].copy() + if self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2']: + endMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'].copy() + marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText']) + else: + x, y, marked = \ + line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screen']['newContentText']) + if marked.isspace(): + self.env['runtime']['outputManager'].presentText(_('blank'), soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(marked, interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/bookmark_10.py b/src/fenrirscreenreader/commands/commands/bookmark_10.py new file mode 100644 index 00000000..b8a1c097 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/bookmark_10.py @@ -0,0 +1,48 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import mark_utils +from fenrirscreenreader.utils import line_utils + +class command(): + def __init__(self): + self.ID = '10' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('read Bookmark {0}').format(self.ID,) + + def run(self): + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + if not self.env['commandBuffer']['bookMarks'][self.ID]: + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set').format(self.ID,), interrupt=True) + return + if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]: + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) + return + if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1']: + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) + return + + # set marks + marked = '' + startMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'].copy() + if self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2']: + endMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'].copy() + marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText']) + else: + x, y, marked = \ + line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screen']['newContentText']) + if marked.isspace(): + self.env['runtime']['outputManager'].presentText(_('blank'), soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(marked, interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/bookmark_2.py b/src/fenrirscreenreader/commands/commands/bookmark_2.py new file mode 100644 index 00000000..bfc42ae3 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/bookmark_2.py @@ -0,0 +1,48 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import mark_utils +from fenrirscreenreader.utils import line_utils + +class command(): + def __init__(self): + self.ID = '2' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('read Bookmark {0}').format(self.ID,) + + def run(self): + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + if not self.env['commandBuffer']['bookMarks'][self.ID]: + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set').format(self.ID,), interrupt=True) + return + if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]: + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) + return + if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1']: + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) + return + + # set marks + marked = '' + startMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'].copy() + if self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2']: + endMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'].copy() + marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText']) + else: + x, y, marked = \ + line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screen']['newContentText']) + if marked.isspace(): + self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(marked, interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/bookmark_3.py b/src/fenrirscreenreader/commands/commands/bookmark_3.py new file mode 100644 index 00000000..7f5afc31 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/bookmark_3.py @@ -0,0 +1,48 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import mark_utils +from fenrirscreenreader.utils import line_utils + +class command(): + def __init__(self): + self.ID = '3' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('read Bookmark {0}').format(self.ID,) + + def run(self): + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + if not self.env['commandBuffer']['bookMarks'][self.ID]: + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set').format(self.ID,), interrupt=True) + return + if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]: + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) + return + if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1']: + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) + return + + # set marks + marked = '' + startMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'].copy() + if self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2']: + endMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'].copy() + marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText']) + else: + x, y, marked = \ + line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screen']['newContentText']) + if marked.isspace(): + self.env['runtime']['outputManager'].presentText(_('blank'), soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(marked, interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/bookmark_4.py b/src/fenrirscreenreader/commands/commands/bookmark_4.py new file mode 100644 index 00000000..bba45d29 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/bookmark_4.py @@ -0,0 +1,48 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import mark_utils +from fenrirscreenreader.utils import line_utils + +class command(): + def __init__(self): + self.ID = '4' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('read Bookmark {0}').format(self.ID,) + + def run(self): + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + if not self.env['commandBuffer']['bookMarks'][self.ID]: + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set').format(self.ID,), interrupt=True) + return + if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]: + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) + return + if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1']: + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) + return + + # set marks + marked = '' + startMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'].copy() + if self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2']: + endMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'].copy() + marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText']) + else: + x, y, marked = \ + line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screen']['newContentText']) + if marked.isspace(): + self.env['runtime']['outputManager'].presentText(_('blank'), soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(marked, interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/bookmark_5.py b/src/fenrirscreenreader/commands/commands/bookmark_5.py new file mode 100644 index 00000000..6ef60817 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/bookmark_5.py @@ -0,0 +1,48 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import mark_utils +from fenrirscreenreader.utils import line_utils + +class command(): + def __init__(self): + self.ID = '5' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('read Bookmark {0}').format(self.ID,) + + def run(self): + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + if not self.env['commandBuffer']['bookMarks'][self.ID]: + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set').format(self.ID,), interrupt=True) + return + if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]: + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) + return + if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1']: + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) + return + + # set marks + marked = '' + startMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'].copy() + if self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2']: + endMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'].copy() + marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText']) + else: + x, y, marked = \ + line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screen']['newContentText']) + if marked.isspace(): + self.env['runtime']['outputManager'].presentText(_('blank'), soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(marked, interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/bookmark_6.py b/src/fenrirscreenreader/commands/commands/bookmark_6.py new file mode 100644 index 00000000..e5c6b466 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/bookmark_6.py @@ -0,0 +1,48 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import mark_utils +from fenrirscreenreader.utils import line_utils + +class command(): + def __init__(self): + self.ID = '6' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('read Bookmark {0}').format(self.ID,) + + def run(self): + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + if not self.env['commandBuffer']['bookMarks'][self.ID]: + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set').format(self.ID,), interrupt=True) + return + if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]: + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) + return + if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1']: + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) + return + + # set marks + marked = '' + startMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'].copy() + if self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2']: + endMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'].copy() + marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText']) + else: + x, y, marked = \ + line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screen']['newContentText']) + if marked.isspace(): + self.env['runtime']['outputManager'].presentText(_('blank'), soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(marked, interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/bookmark_7.py b/src/fenrirscreenreader/commands/commands/bookmark_7.py new file mode 100644 index 00000000..0254c63c --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/bookmark_7.py @@ -0,0 +1,48 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import mark_utils +from fenrirscreenreader.utils import line_utils + +class command(): + def __init__(self): + self.ID = '7' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('read Bookmark {0}').format(self.ID,) + + def run(self): + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + if not self.env['commandBuffer']['bookMarks'][self.ID]: + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set').format(self.ID,), interrupt=True) + return + if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]: + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) + return + if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1']: + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) + return + + # set marks + marked = '' + startMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'].copy() + if self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2']: + endMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'].copy() + marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText']) + else: + x, y, marked = \ + line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screen']['newContentText']) + if marked.isspace(): + self.env['runtime']['outputManager'].presentText(_('blank'), soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(marked, interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/bookmark_8.py b/src/fenrirscreenreader/commands/commands/bookmark_8.py new file mode 100644 index 00000000..f0831dbc --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/bookmark_8.py @@ -0,0 +1,48 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import mark_utils +from fenrirscreenreader.utils import line_utils + +class command(): + def __init__(self): + self.ID = '8' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('read Bookmark {0}').format(self.ID,) + + def run(self): + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + if not self.env['commandBuffer']['bookMarks'][self.ID]: + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set').format(self.ID,), interrupt=True) + return + if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]: + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) + return + if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1']: + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) + return + + # set marks + marked = '' + startMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'].copy() + if self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2']: + endMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'].copy() + marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText']) + else: + x, y, marked = \ + line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screen']['newContentText']) + if marked.isspace(): + self.env['runtime']['outputManager'].presentText(_('blank'), soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(marked, interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/bookmark_9.py b/src/fenrirscreenreader/commands/commands/bookmark_9.py new file mode 100644 index 00000000..5127617e --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/bookmark_9.py @@ -0,0 +1,48 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import mark_utils +from fenrirscreenreader.utils import line_utils + +class command(): + def __init__(self): + self.ID = '9' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('read Bookmark {0}').format(self.ID,) + + def run(self): + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + if not self.env['commandBuffer']['bookMarks'][self.ID]: + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set').format(self.ID,), interrupt=True) + return + if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]: + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) + return + if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1']: + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) + return + + # set marks + marked = '' + startMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'].copy() + if self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2']: + endMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'].copy() + marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText']) + else: + x, y, marked = \ + line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screen']['newContentText']) + if marked.isspace(): + self.env['runtime']['outputManager'].presentText(_('blank'), soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(marked, interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/braille_flush.py b/src/fenrirscreenreader/commands/commands/braille_flush.py new file mode 100644 index 00000000..5a6bb6ba --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/braille_flush.py @@ -0,0 +1,21 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('flush the braille device if a message is written on') + def run(self): + self.env['runtime']['outputManager'].clearFlushTime() + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/braille_pan_left.py b/src/fenrirscreenreader/commands/commands/braille_pan_left.py new file mode 100644 index 00000000..ffc94375 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/braille_pan_left.py @@ -0,0 +1,21 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('Move braille view to the left.') + def run(self): + panned = self.env['runtime']['outputManager'].setPanLeft() + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/braille_pan_right.py b/src/fenrirscreenreader/commands/commands/braille_pan_right.py new file mode 100644 index 00000000..144befa9 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/braille_pan_right.py @@ -0,0 +1,21 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('Move braille view to the right.') + def run(self): + panned = self.env['runtime']['outputManager'].setPanRight() + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/braille_return_to_cursor.py b/src/fenrirscreenreader/commands/commands/braille_return_to_cursor.py new file mode 100644 index 00000000..65863d71 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/braille_return_to_cursor.py @@ -0,0 +1,21 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('Set the braille view back to cursor.') + def run(self): + self.env['runtime']['outputManager'].removePanning() + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/clear_bookmark_1.py b/src/fenrirscreenreader/commands/commands/clear_bookmark_1.py new file mode 100644 index 00000000..62c47741 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/clear_bookmark_1.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + self.ID = '1' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('remove Bookmark {0}').format(self.ID,) + + def run(self): + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + + del self.env['commandBuffer']['bookMarks'][self.ID][currApp] + + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} removed for application {1}').format(self.ID, currApp), interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/clear_bookmark_10.py b/src/fenrirscreenreader/commands/commands/clear_bookmark_10.py new file mode 100644 index 00000000..47c63d72 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/clear_bookmark_10.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + self.ID = '10' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('remove Bookmark {0}').format(self.ID,) + + def run(self): + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + + del self.env['commandBuffer']['bookMarks'][self.ID][currApp] + + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} removed for application {1}').format(self.ID, currApp), interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/clear_bookmark_2.py b/src/fenrirscreenreader/commands/commands/clear_bookmark_2.py new file mode 100644 index 00000000..93b49ba4 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/clear_bookmark_2.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + self.ID = '2' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('remove Bookmark {0}').format(self.ID,) + + def run(self): + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + + del self.env['commandBuffer']['bookMarks'][self.ID][currApp] + + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} removed for application {1}').format(self.ID, currApp), interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/clear_bookmark_3.py b/src/fenrirscreenreader/commands/commands/clear_bookmark_3.py new file mode 100644 index 00000000..ce8bce1a --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/clear_bookmark_3.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + self.ID = '3' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('remove Bookmark {0}').format(self.ID,) + + def run(self): + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + + del self.env['commandBuffer']['bookMarks'][self.ID][currApp] + + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} removed for application {1}').format(self.ID, currApp), interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/clear_bookmark_4.py b/src/fenrirscreenreader/commands/commands/clear_bookmark_4.py new file mode 100644 index 00000000..089f4ccc --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/clear_bookmark_4.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + self.ID = '4' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('remove Bookmark {0}').format(self.ID,) + + def run(self): + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + + del self.env['commandBuffer']['bookMarks'][self.ID][currApp] + + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} removed for application {1}').format(self.ID, currApp), interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/clear_bookmark_5.py b/src/fenrirscreenreader/commands/commands/clear_bookmark_5.py new file mode 100644 index 00000000..f4376d50 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/clear_bookmark_5.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + self.ID = '5' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('remove Bookmark {0}').format(self.ID,) + + def run(self): + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + + del self.env['commandBuffer']['bookMarks'][self.ID][currApp] + + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} removed for application {1}').format(self.ID, currApp), interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/clear_bookmark_6.py b/src/fenrirscreenreader/commands/commands/clear_bookmark_6.py new file mode 100644 index 00000000..d397e7cd --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/clear_bookmark_6.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + self.ID = '6' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('remove Bookmark {0}').format(self.ID,) + + def run(self): + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + + del self.env['commandBuffer']['bookMarks'][self.ID][currApp] + + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} removed for application {1}').format(self.ID, currApp), interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/clear_bookmark_7.py b/src/fenrirscreenreader/commands/commands/clear_bookmark_7.py new file mode 100644 index 00000000..9003dd2a --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/clear_bookmark_7.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + self.ID = '7' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('remove Bookmark {0}').format(self.ID,) + + def run(self): + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + + del self.env['commandBuffer']['bookMarks'][self.ID][currApp] + + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} removed for application {1}').format(self.ID, currApp), interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/clear_bookmark_8.py b/src/fenrirscreenreader/commands/commands/clear_bookmark_8.py new file mode 100644 index 00000000..e39cfafe --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/clear_bookmark_8.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + self.ID = '8' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('remove Bookmark {0}').format(self.ID,) + + def run(self): + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + + del self.env['commandBuffer']['bookMarks'][self.ID][currApp] + + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} removed for application {1}').format(self.ID, currApp), interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/clear_bookmark_9.py b/src/fenrirscreenreader/commands/commands/clear_bookmark_9.py new file mode 100644 index 00000000..4371cc29 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/clear_bookmark_9.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + self.ID = '9' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('remove Bookmark {0}').format(self.ID,) + + def run(self): + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + + del self.env['commandBuffer']['bookMarks'][self.ID][currApp] + + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} removed for application {1}').format(self.ID, currApp), interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/clear_clipboard.py b/src/fenrirscreenreader/commands/commands/clear_clipboard.py new file mode 100644 index 00000000..6c237347 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/clear_clipboard.py @@ -0,0 +1,24 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('clears the currently selected clipboard') + + def run(self): + self.env['runtime']['memoryManager'].clearCurrentIndexList('clipboardHistory') + self.env['runtime']['outputManager'].presentText(_('clipboard cleared'), interrupt=True) + return + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/clear_window_application.py b/src/fenrirscreenreader/commands/commands/clear_window_application.py new file mode 100644 index 00000000..50cc9800 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/clear_window_application.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('Turn off window mode for application') + + def run(self): + if self.env['runtime']['cursorManager'].clearWindowForApplication(): + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + self.env['runtime']['outputManager'].presentText(_('Window Mode off for application {0}').format(currApp,), interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(_("Not in window Mode"), interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/copy_last_echo_to_clipboard.py b/src/fenrirscreenreader/commands/commands/copy_last_echo_to_clipboard.py new file mode 100644 index 00000000..d6918a4a --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/copy_last_echo_to_clipboard.py @@ -0,0 +1,26 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import mark_utils + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('copies last presented text to the clipboard') + + def run(self): + lastEcho = self.env['runtime']['outputManager'].getLastEcho() + self.env['runtime']['memoryManager'].addValueToFirstIndex('clipboardHistory', lastEcho) + self.env['runtime']['outputManager'].presentText(lastEcho, soundIcon='CopyToClipboard', interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/copy_marked_to_clipboard.py b/src/fenrirscreenreader/commands/commands/copy_marked_to_clipboard.py new file mode 100644 index 00000000..8d6c8c4e --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/copy_marked_to_clipboard.py @@ -0,0 +1,39 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import mark_utils + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('copies marked text to the currently selected clipboard') + + def run(self): + if not self.env['commandBuffer']['Marks']['1']: + self.env['runtime']['outputManager'].presentText(_("one or two marks needed"), interrupt=True) + return + if not self.env['commandBuffer']['Marks']['2']: + self.env['runtime']['cursorManager'].setMark() + + # use the last first and the last setted mark as range + startMark = self.env['commandBuffer']['Marks']['1'].copy() + endMark = self.env['commandBuffer']['Marks']['2'].copy() + + marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText']) + self.env['runtime']['memoryManager'].addValueToFirstIndex('clipboardHistory', marked) + # reset marks + self.env['runtime']['cursorManager'].clearMarks() + + self.env['runtime']['outputManager'].presentText(marked, soundIcon='CopyToClipboard', interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/curr_clipboard.py b/src/fenrirscreenreader/commands/commands/curr_clipboard.py new file mode 100644 index 00000000..29ef97f0 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/curr_clipboard.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('speaks the contents of the currently selected clipboard') + + def run(self): + if self.env['runtime']['memoryManager'].isIndexListEmpty('clipboardHistory'): + self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) + return + clipboard = self.env['runtime']['memoryManager'].getIndexListElement('clipboardHistory') + self.env['runtime']['outputManager'].presentText(clipboard , interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/curr_screen.py b/src/fenrirscreenreader/commands/commands/curr_screen.py new file mode 100644 index 00000000..8543d078 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/curr_screen.py @@ -0,0 +1,26 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('reads the contents of the current screen') + + def run(self): + if self.env['screen']['newContentText'].isspace(): + self.env['runtime']['outputManager'].presentText(_("screen is empty"), soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(self.env['screen']['newContentText'],interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/curr_screen_after_cursor.py b/src/fenrirscreenreader/commands/commands/curr_screen_after_cursor.py new file mode 100644 index 00000000..792bfaf0 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/curr_screen_after_cursor.py @@ -0,0 +1,32 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import mark_utils + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('reads from the cursor to the bottom of the screen') + + def run(self): + # Prefer review cursor over text cursor + cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() + + textAfterCursor = mark_utils.getTextAfterMark(cursorPos, self.env['screen']['newContentText']) + + if textAfterCursor.isspace(): + self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(textAfterCursor, interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/curr_screen_before_cursor.py b/src/fenrirscreenreader/commands/commands/curr_screen_before_cursor.py new file mode 100644 index 00000000..6571480d --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/curr_screen_before_cursor.py @@ -0,0 +1,36 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import mark_utils + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('Reads from the top of the screen to the cursor position') + + def run(self): + # Prefer review cursor over text cursor + if self.env['screen']['newCursorReview']: + cursorPos = self.env['screen']['newCursorReview'].copy() + else: + cursorPos = self.env['screen']['newCursor'].copy() + + textBeforeCursor = mark_utils.getTextBeforeMark(cursorPos, self.env['screen']['newContentText']) + + if textBeforeCursor.isspace(): + self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(textBeforeCursor, interrupt=True) + + def setCallback(self, callback): + pass + diff --git a/src/fenrirscreenreader/commands/commands/cursor_column.py b/src/fenrirscreenreader/commands/commands/cursor_column.py new file mode 100644 index 00000000..9b738626 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/cursor_column.py @@ -0,0 +1,25 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('presents the current column number for review cursor in review mode or the text cursor if not. Starts with 1') + def run(self): + cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() + self.env['runtime']['outputManager'].presentText(str(cursorPos['x'] + 1) , interrupt=True) + self.env['runtime']['outputManager'].announceActiveCursor() + self.env['runtime']['outputManager'].presentText(' column number' , interrupt=False) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/cursor_lineno.py b/src/fenrirscreenreader/commands/commands/cursor_lineno.py new file mode 100644 index 00000000..cf926dd0 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/cursor_lineno.py @@ -0,0 +1,25 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('presents the current line number for review cursor in review mode or the text cursor if not. Starts with 1') + def run(self): + cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() + self.env['runtime']['outputManager'].presentText(str(cursorPos['y'] + 1), interrupt=True) + self.env['runtime']['outputManager'].announceActiveCursor() + self.env['runtime']['outputManager'].presentText(' line number' , interrupt=False) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/cursor_position.py b/src/fenrirscreenreader/commands/commands/cursor_position.py new file mode 100644 index 00000000..bbb1208f --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/cursor_position.py @@ -0,0 +1,26 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('displays the position of the review cursor') + + def run(self): + # Prefer review cursor over text cursor + cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() + + self.env['runtime']['outputManager'].presentText(_("line {0}, column {1}").format(cursorPos['y']+1, cursorPos['x']+1), interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/cursor_read_to_end_of_line.py b/src/fenrirscreenreader/commands/commands/cursor_read_to_end_of_line.py new file mode 100644 index 00000000..3e72819b --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/cursor_read_to_end_of_line.py @@ -0,0 +1,33 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import line_utils + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('read to end of line, use review cursor if you are in review mode, otherwhise use text cursor') + + def run(self): + cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() + + x, y, currLine = \ + line_utils.getCurrentLine(cursorPos['x'], cursorPos['y'], self.env['screen']['newContentText']) + + if currLine.isspace(): + self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(currLine[cursorPos['x']], interrupt=True) + self.env['runtime']['outputManager'].announceActiveCursor() + def setCallback(self, callback): + pass + diff --git a/src/fenrirscreenreader/commands/commands/date.py b/src/fenrirscreenreader/commands/commands/date.py new file mode 100644 index 00000000..e754a03f --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/date.py @@ -0,0 +1,30 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +import datetime + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('presents the date') + + def run(self): + dateFormat = self.env['runtime']['settingsManager'].getSetting('general', 'dateFormat') + + # get the time formatted + dateString = datetime.datetime.strftime(datetime.datetime.now(), dateFormat) + + # present the time via speak and braile, there is no soundicon, interrupt the current speech + self.env['runtime']['outputManager'].presentText(dateString , soundIcon='', interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/dec_alsa_volume.py b/src/fenrirscreenreader/commands/commands/dec_alsa_volume.py new file mode 100644 index 00000000..0dea50e7 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/dec_alsa_volume.py @@ -0,0 +1,39 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +initialized = False +try: + import alsaaudio + initialized = True +except: + pass + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _("Decrease system volume") + + def run(self): + if not initialized: + self.env['runtime']['outputManager'].presentText(_('alsaaudio is not installed'), interrupt=True) + return + mixer = alsaaudio.Mixer() + value = mixer.getvolume()[0] + value = value - 5 + if value < 5: + value = 5 + mixer.setvolume(value) + self.env['runtime']['outputManager'].presentText(_("{0} percent system volume").format(value), interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/dec_sound_volume.py b/src/fenrirscreenreader/commands/commands/dec_sound_volume.py new file mode 100644 index 00000000..435c2c62 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/dec_sound_volume.py @@ -0,0 +1,33 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +import math + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('decrease sound volume') + + def run(self): + + value = self.env['runtime']['settingsManager'].getSettingAsFloat('sound', 'volume') + + value = round((math.ceil(10 * value) / 10) - 0.1, 2) + if value < 0.1: + value = 0.1 + self.env['runtime']['settingsManager'].setSetting('sound', 'volume', str(value)) + + self.env['runtime']['outputManager'].presentText(_("{0} percent sound volume").format(int(value * 100)), soundIcon='SoundOff', interrupt=True) + + def setCallback(self, callback): + pass + diff --git a/src/fenrirscreenreader/commands/commands/dec_speech_pitch.py b/src/fenrirscreenreader/commands/commands/dec_speech_pitch.py new file mode 100644 index 00000000..e7e6fe06 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/dec_speech_pitch.py @@ -0,0 +1,29 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +import math + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('decreases the pitch of the speech') + + def run(self): + value = self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'pitch') + value = round((math.ceil(10 * value) / 10) - 0.1, 2) + if value < 0.0: + value = 0.0 + self.env['runtime']['settingsManager'].setSetting('speech', 'pitch', str(value)) + self.env['runtime']['outputManager'].presentText(_('{0} percent speech pitch').format(int(value * 100)), soundIcon='', interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/dec_speech_rate.py b/src/fenrirscreenreader/commands/commands/dec_speech_rate.py new file mode 100644 index 00000000..f42d4e95 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/dec_speech_rate.py @@ -0,0 +1,30 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +import math + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('decreases the rate of the speech') + + def run(self): + value = self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'rate') + value = round((math.ceil(10 * value) / 10) - 0.1, 2) + if value < 0.0: + value = 0.0 + self.env['runtime']['settingsManager'].setSetting('speech', 'rate', str(value)) + + self.env['runtime']['outputManager'].presentText(_("{0} percent speech rate").format(int(value * 100)), soundIcon='', interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/dec_speech_volume.py b/src/fenrirscreenreader/commands/commands/dec_speech_volume.py new file mode 100644 index 00000000..5c5f60c5 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/dec_speech_volume.py @@ -0,0 +1,31 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +import math + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('decreases the volume of the speech') + + def run(self): + value = self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'volume') + value = round((math.ceil(10 * value) / 10) - 0.1, 2) + if value < 0.1: + value = 0.1 + self.env['runtime']['settingsManager'].setSetting('speech', 'volume', str(value)) + + self.env['runtime']['outputManager'].presentText(_("{0} percent speech volume").format(int(value * 100)), soundIcon='', interrupt=True) + + def setCallback(self, callback): + pass + diff --git a/src/fenrirscreenreader/commands/commands/exit_review.py b/src/fenrirscreenreader/commands/commands/exit_review.py new file mode 100644 index 00000000..0ac3854b --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/exit_review.py @@ -0,0 +1,28 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.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']['cursorManager'].isReviewMode(): + self.env['runtime']['outputManager'].presentText(_("Not in review mode"), interrupt=True) + return + + self.env['runtime']['cursorManager'].clearReviewCursor() + self.env['runtime']['outputManager'].presentText(_("leave review mode"), interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/export_clipboard_to_file.py b/src/fenrirscreenreader/commands/commands/export_clipboard_to_file.py new file mode 100644 index 00000000..25095051 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/export_clipboard_to_file.py @@ -0,0 +1,39 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +import os + +class command(): + def __init__(self): + pass + def initialize(self, environment, scriptPath=''): + self.env = environment + + def shutdown(self): + pass + def getDescription(self): + return _('export the current fenrir clipboard to a file') + def run(self): + clipboardFilePath = self.env['runtime']['settingsManager'].getSetting('general', 'clipboardExportPath') + clipboardFilePath = clipboardFilePath.replace('$user',self.env['general']['currUser']) + clipboardFilePath = clipboardFilePath.replace('$USER',self.env['general']['currUser']) + clipboardFilePath = clipboardFilePath.replace('$User',self.env['general']['currUser']) + clipboardFile = open(clipboardFilePath,'w') + try: + if self.env['runtime']['memoryManager'].isIndexListEmpty('clipboardHistory'): + self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) + return + clipboard = self.env['runtime']['memoryManager'].getIndexListElement('clipboardHistory') + clipboardFile.write(clipboard) + clipboardFile.close() + os.chmod(clipboardFilePath, 0o666) + self.env['runtime']['outputManager'].presentText(_('clipboard exported to file'), interrupt=True) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('export_clipboard_to_file:run: Filepath:'+ clipboardFile +' trace:' + str(e),debug.debugLevel.ERROR) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/export_clipboard_to_x.py b/src/fenrirscreenreader/commands/commands/export_clipboard_to_x.py new file mode 100644 index 00000000..ce4844cf --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/export_clipboard_to_x.py @@ -0,0 +1,50 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +import subprocess, os +from subprocess import Popen, PIPE +import _thread + +class command(): + def __init__(self): + pass + def initialize(self, environment, scriptPath=''): + self.env = environment + self.scriptPath = scriptPath + def shutdown(self): + pass + def getDescription(self): + return _('export the current fenrir clipboard to X clipboard') + def run(self): + _thread.start_new_thread(self._threadRun , ()) + + def _threadRun(self): + try: + if self.env['runtime']['memoryManager'].isIndexListEmpty('clipboardHistory'): + self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) + return + clipboard = self.env['runtime']['memoryManager'].getIndexListElement('clipboardHistory') + for display in range(10): + p = Popen('su ' + self.env['general']['currUser'] + ' -c "echo -n \\\"' + clipboard.replace('"','\\\\\\"') +'\\\" | xclip -d :' + str(display) + ' -selection c"' , stdout=PIPE, stderr=PIPE, shell=True) + stdout, stderr = p.communicate() + self.env['runtime']['outputManager'].interruptOutput() + #screenEncoding = self.env['runtime']['settingsManager'].getSetting('screen', 'encoding') + stderr = stderr.decode('utf-8') + stdout = stdout.decode('utf-8') + if (stderr == ''): + break + #stderr = stderr.decode(screenEncoding, "replace").encode('utf-8').decode('utf-8') + #stdout = stdout.decode(screenEncoding, "replace").encode('utf-8').decode('utf-8') + if stderr != '': + self.env['runtime']['outputManager'].presentText(stderr , soundIcon='', interrupt=False) + else: + self.env['runtime']['outputManager'].presentText('exported to the X session.', interrupt=True) + except Exception as e: + self.env['runtime']['outputManager'].presentText(e , soundIcon='', interrupt=False) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/first_clipboard.py b/src/fenrirscreenreader/commands/commands/first_clipboard.py new file mode 100644 index 00000000..a15a56bc --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/first_clipboard.py @@ -0,0 +1,28 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('selects the first clipboard') + + def run(self): + if self.env['runtime']['memoryManager'].isIndexListEmpty('clipboardHistory'): + self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) + return + self.env['runtime']['memoryManager'].setFirstIndex('clipboardHistory') + clipboard = self.env['runtime']['memoryManager'].getIndexListElement('clipboardHistory') + self.env['runtime']['outputManager'].presentText(clipboard, interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/forward_keypress.py b/src/fenrirscreenreader/commands/commands/forward_keypress.py new file mode 100644 index 00000000..79d0d367 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/forward_keypress.py @@ -0,0 +1,24 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('sends the following keypress to the terminal') + + def run(self): + self.env['input']['keyForeward'] = 3 + self.env['runtime']['outputManager'].presentText(_('Forward next keypress'), interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/import_clipboard_from_file.py b/src/fenrirscreenreader/commands/commands/import_clipboard_from_file.py new file mode 100644 index 00000000..4e68c6ee --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/import_clipboard_from_file.py @@ -0,0 +1,39 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import mark_utils +import os + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('imports text from clipboard file to the clipboard') + + def run(self): + clipboardFilePath = self.env['runtime']['settingsManager'].getSetting('general', 'clipboardExportPath') + clipboardFilePath = clipboardFilePath.replace('$user',self.env['general']['currUser']) + clipboardFilePath = clipboardFilePath.replace('$USER',self.env['general']['currUser']) + clipboardFilePath = clipboardFilePath.replace('$User',self.env['general']['currUser']) + if not os.path.exists(clipboardFilePath): + self.env['runtime']['outputManager'].presentText(_('File does not exist'), soundIcon='', interrupt=True) + return + clipboardFile = open(clipboardFilePath,'r') + imported = clipboardFile.read() + clipboardFile.close() + self.env['runtime']['memoryManager'].addValueToFirstIndex('clipboardHistory', imported) + + self.env['runtime']['outputManager'].presentText('Import to Clipboard', soundIcon='CopyToClipboard', interrupt=True) + self.env['runtime']['outputManager'].presentText(imported, soundIcon='', interrupt=False) + + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/inc_alsa_volume.py b/src/fenrirscreenreader/commands/commands/inc_alsa_volume.py new file mode 100644 index 00000000..45950a25 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/inc_alsa_volume.py @@ -0,0 +1,39 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +initialized = False +try: + import alsaaudio + initialized = True +except: + pass + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _("Increase system volume") + + def run(self): + if not initialized: + self.env['runtime']['outputManager'].presentText(_('alsaaudio is not installed'), interrupt=True) + return + mixer = alsaaudio.Mixer() + value = mixer.getvolume()[0] + value = value + 5 + if value > 100: + value = 100 + mixer.setvolume(value) + self.env['runtime']['outputManager'].presentText(_("{0} percent system volume").format(value), interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/inc_sound_volume.py b/src/fenrirscreenreader/commands/commands/inc_sound_volume.py new file mode 100644 index 00000000..19438366 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/inc_sound_volume.py @@ -0,0 +1,32 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +import math + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('adjusts the volume for in coming sounds') + + def run(self): + + value = self.env['runtime']['settingsManager'].getSettingAsFloat('sound', 'volume') + + value = round((math.ceil(10 * value) / 10) + 0.1, 2) + if value > 1.0: + value = 1.0 + self.env['runtime']['settingsManager'].setSetting('sound', 'volume', str(value)) + + self.env['runtime']['outputManager'].presentText(_("{0} percent sound volume").format(int(value * 100)), soundIcon='SoundOn', interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/inc_speech_pitch.py b/src/fenrirscreenreader/commands/commands/inc_speech_pitch.py new file mode 100644 index 00000000..db213648 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/inc_speech_pitch.py @@ -0,0 +1,30 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +import math + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('increases the pitch of the speech') + + def run(self): + value = self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'pitch') + value = round((math.ceil(10 * value) / 10) + 0.1, 2) + if value > 1.0: + value = 1.0 + self.env['runtime']['settingsManager'].setSetting('speech', 'pitch', str(value)) + + self.env['runtime']['outputManager'].presentText(_("{0} percent speech pitch").format(int(value * 100)), soundIcon='', interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/inc_speech_rate.py b/src/fenrirscreenreader/commands/commands/inc_speech_rate.py new file mode 100644 index 00000000..a65666b2 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/inc_speech_rate.py @@ -0,0 +1,30 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +import math + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('increase the speech rate') + + def run(self): + value = self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'rate') + value = round((math.ceil(10 * value) / 10) + 0.1, 2) + if value > 1.0: + value = 1.0 + self.env['runtime']['settingsManager'].setSetting('speech', 'rate', str(value)) + + self.env['runtime']['outputManager'].presentText(_("{0} percent speech rate").format(int(value * 100)), soundIcon='', interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/inc_speech_volume.py b/src/fenrirscreenreader/commands/commands/inc_speech_volume.py new file mode 100644 index 00000000..490dfc88 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/inc_speech_volume.py @@ -0,0 +1,30 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +import math + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('increase the speech volume') + + def run(self): + value = self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'volume') + value = round((math.ceil(10 * value) / 10) + 0.1, 2) + if value > 1.0: + value = 1.0 + self.env['runtime']['settingsManager'].setSetting('speech', 'volume', str(value)) + + self.env['runtime']['outputManager'].presentText(_("{0} percent speech volume").format(int(value * 100)), soundIcon='', interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/indent_curr_line.py b/src/fenrirscreenreader/commands/commands/indent_curr_line.py new file mode 100644 index 00000000..ece9c6e0 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/indent_curr_line.py @@ -0,0 +1,36 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import line_utils + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('shows the indention level for the current line') + + def run(self): + # Prefer review cursor over text cursor + + if self.env['screen']['newCursorReview']: + cursorPos = self.env['screen']['newCursorReview'].copy() + else: + cursorPos = self.env['screen']['newCursor'].copy() + x, y, currLine = \ + line_utils.getCurrentLine(cursorPos['x'], cursorPos['y'], self.env['screen']['newContentText']) + + if currLine.isspace(): + self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(_("indent {0}").format(len(currLine) - len(currLine.lstrip())), interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/last_clipboard.py b/src/fenrirscreenreader/commands/commands/last_clipboard.py new file mode 100644 index 00000000..d8de0dd9 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/last_clipboard.py @@ -0,0 +1,28 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('selects the last clipboard') + + def run(self): + if self.env['runtime']['memoryManager'].isIndexListEmpty('clipboardHistory'): + self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) + return + self.env['runtime']['memoryManager'].setLastIndex('clipboardHistory') + clipboard = self.env['runtime']['memoryManager'].getIndexListElement('clipboardHistory') + self.env['runtime']['outputManager'].presentText(clipboard, interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/last_incoming.py b/src/fenrirscreenreader/commands/commands/last_incoming.py new file mode 100644 index 00000000..907144c0 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/last_incoming.py @@ -0,0 +1,23 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('displays the last received text') + + def run(self): + self.env['runtime']['outputManager'].presentText(self.env['screen']['newDelta'], interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/marked_text.py b/src/fenrirscreenreader/commands/commands/marked_text.py new file mode 100644 index 00000000..63a34861 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/marked_text.py @@ -0,0 +1,38 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import mark_utils + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('speaks the currently selected text that will be copied to the clipboard') + + def run(self): + if not (self.env['commandBuffer']['Marks']['1'] and \ + self.env['commandBuffer']['Marks']['2']): + self.env['runtime']['outputManager'].presentText(_("please set begin and endmark"), interrupt=True) + return + + # use the last first and the last setted mark as range + startMark = self.env['commandBuffer']['Marks']['1'].copy() + endMark = self.env['commandBuffer']['Marks']['2'].copy() + + marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText']) + + if marked.isspace(): + self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(marked, interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/next_clipboard.py b/src/fenrirscreenreader/commands/commands/next_clipboard.py new file mode 100644 index 00000000..6564f54c --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/next_clipboard.py @@ -0,0 +1,36 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('selects the next clipboard') + + def run(self): + if self.env['runtime']['memoryManager'].isIndexListEmpty('clipboardHistory'): + self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) + return + self.env['runtime']['memoryManager'].getNextIndex('clipboardHistory') + isFirst = self.env['runtime']['memoryManager'].isFirstIndex('clipboardHistory') + isLast = self.env['runtime']['memoryManager'].isLastIndex('clipboardHistory') + clipboard = self.env['runtime']['memoryManager'].getIndexListElement('clipboardHistory') + if isFirst: + self.env['runtime']['outputManager'].presentText(_('First clipboard '), interrupt=True) + if isLast: + self.env['runtime']['outputManager'].presentText(_('Last clipboard '), interrupt=True) + + speechInterrupt = not(isLast or isFirst) + self.env['runtime']['outputManager'].presentText(clipboard, interrupt = speechInterrupt) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/paste_clipboard.py b/src/fenrirscreenreader/commands/commands/paste_clipboard.py new file mode 100644 index 00000000..caee0c2f --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/paste_clipboard.py @@ -0,0 +1,30 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +import time + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + self.env['runtime']['memoryManager'].addIndexList('clipboardHistory', self.env['runtime']['settingsManager'].getSettingAsInt('general', 'numberOfClipboards')) + def shutdown(self): + pass + def getDescription(self): + return _('pastes the text from the currently selected clipboard') + + def run(self): + if self.env['runtime']['memoryManager'].isIndexListEmpty('clipboardHistory'): + self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) + return + self.env['runtime']['outputManager'].presentText('paste clipboard', soundIcon='PasteClipboardOnScreen', interrupt=True) + clipboard = self.env['runtime']['memoryManager'].getIndexListElement('clipboardHistory') + self.env['runtime']['screenManager'].injectTextToScreen(clipboard) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/present_first_line.py b/src/fenrirscreenreader/commands/commands/present_first_line.py new file mode 100644 index 00000000..6d833ef1 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/present_first_line.py @@ -0,0 +1,30 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import line_utils + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('present first line') + + def run(self): + x, y, firstLine = \ + line_utils.getCurrentLine(0, 0, self.env['screen']['newContentText']) + + if firstLine.isspace(): + self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(firstLine, interrupt=True) + def setCallback(self, callback): + pass + diff --git a/src/fenrirscreenreader/commands/commands/present_last_line.py b/src/fenrirscreenreader/commands/commands/present_last_line.py new file mode 100644 index 00000000..5b4c12fa --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/present_last_line.py @@ -0,0 +1,30 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import line_utils + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('current line') + + def run(self): + x, y, lastLine = \ + line_utils.getCurrentLine(0, self.env['screen']['lines'] -1, self.env['screen']['newContentText']) + + if lastLine.isspace(): + self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(lastLine, interrupt=True) + def setCallback(self, callback): + pass + diff --git a/src/fenrirscreenreader/commands/commands/prev_clipboard.py b/src/fenrirscreenreader/commands/commands/prev_clipboard.py new file mode 100644 index 00000000..7156f24d --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/prev_clipboard.py @@ -0,0 +1,35 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('selects the previous clipboard') + + def run(self): + if self.env['runtime']['memoryManager'].isIndexListEmpty('clipboardHistory'): + self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) + return + self.env['runtime']['memoryManager'].setPrefIndex('clipboardHistory') + isFirst = self.env['runtime']['memoryManager'].isFirstIndex('clipboardHistory') + isLast = self.env['runtime']['memoryManager'].isLastIndex('clipboardHistory') + clipboard = self.env['runtime']['memoryManager'].getIndexListElement('clipboardHistory') + if isFirst: + self.env['runtime']['outputManager'].presentText(_('First clipboard '), interrupt=True) + if isLast: + self.env['runtime']['outputManager'].presentText(_('Last clipboard '), interrupt=True) + speechInterrupt = not(isLast or isFirst) + self.env['runtime']['outputManager'].presentText(clipboard, interrupt = speechInterrupt) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/quit_fenrir.py b/src/fenrirscreenreader/commands/commands/quit_fenrir.py new file mode 100644 index 00000000..80cba02e --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/quit_fenrir.py @@ -0,0 +1,24 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.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 Fenrir') + + def run(self): + self.env['runtime']['eventManager'].stopMainEventLoop() + + def setCallback(self, callback): + pass + diff --git a/src/fenrirscreenreader/commands/commands/remove_marks.py b/src/fenrirscreenreader/commands/commands/remove_marks.py new file mode 100644 index 00000000..7c351415 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/remove_marks.py @@ -0,0 +1,24 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('removes marks from selected text') + + def run(self): + self.env['runtime']['cursorManager'].clearMarks() + self.env['runtime']['outputManager'].presentText(_('Remove marks'), interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/remove_word_from_spell_check.py b/src/fenrirscreenreader/commands/commands/remove_word_from_spell_check.py new file mode 100644 index 00000000..01cf863f --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/remove_word_from_spell_check.py @@ -0,0 +1,55 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import word_utils +import string +initialized = False +try: + import enchant + initialized = True +except: + pass + +class command(): + def __init__(self): + self.language = '' + self.spellChecker = None + def initialize(self, environment): + self.env = environment + self.updateSpellLanguage() + def shutdown(self): + pass + def getDescription(self): + return _('removes the current word from the exceptions dictionary') + def updateSpellLanguage(self): + 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: + self.env['runtime']['outputManager'].presentText(_('pyenchant is not installed'), interrupt=True) + return + if self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage') != self.language: + try: + self.updateSpellLanguage() + except: + return + + cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() + + # get the word + newContent = self.env['screen']['newContentText'].split('\n')[cursorPos['y']] + x, y, currWord, endOfScreen, lineBreak = word_utils.getCurrentWord(cursorPos['x'], 0, newContent) + currWord = currWord.strip(string.whitespace + '!"#$%&\()*+,-./:;<=ยง>?@[\\]^_{|}~') + if not currWord.isspace(): + if self.spellChecker.is_removed(currWord): + self.env['runtime']['outputManager'].presentText(_('{0} is already removed from dict').format(currWord,), soundIcon='Cancel', interrupt=True) + else: + self.spellChecker.remove(currWord) + self.env['runtime']['outputManager'].presentText(_('{0} removed').format(currWord,), soundIcon='Accept', interrupt=True) + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/review_bottom.py b/src/fenrirscreenreader/commands/commands/review_bottom.py new file mode 100644 index 00000000..5e5271b3 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/review_bottom.py @@ -0,0 +1,24 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('move review to bottom of screen') + + def run(self): + self.env['screen']['newCursorReview'] = { 'x': 0, 'y':self.env['screen']['lines'] -1} + self.env['runtime']['outputManager'].presentText(_("Bottom"), interrupt=True, flush=False) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/review_curr_char.py b/src/fenrirscreenreader/commands/commands/review_curr_char.py new file mode 100644 index 00000000..33ba9534 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/review_curr_char.py @@ -0,0 +1,29 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.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 _('presents the current character.') + + def run(self): + self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor() + + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], currChar = \ + char_utils.getCurrentChar(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) + + self.env['runtime']['outputManager'].presentText(currChar ,interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/review_curr_char_phonetic.py b/src/fenrirscreenreader/commands/commands/review_curr_char_phonetic.py new file mode 100644 index 00000000..e4aee550 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/review_curr_char_phonetic.py @@ -0,0 +1,33 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.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 _('set review and phonetically presents the current character') + + def run(self): + self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor() + + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], currChar = \ + char_utils.getCurrentChar(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) + + if currChar.isspace(): + self.env['runtime']['outputManager'].presentText(_("blank"), interrupt=True, flush=False) + else: + currChar = char_utils.getPhonetic(currChar) + self.env['runtime']['outputManager'].presentText(currChar ,interrupt=True, announceCapital=True, flush=False) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/review_curr_line.py b/src/fenrirscreenreader/commands/commands/review_curr_line.py new file mode 100644 index 00000000..2e8d9e00 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/review_curr_line.py @@ -0,0 +1,32 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import line_utils + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('current line') + + def run(self): + self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor() + + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], currLine = \ + line_utils.getCurrentLine(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['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/fenrirscreenreader/commands/commands/review_curr_word.py b/src/fenrirscreenreader/commands/commands/review_curr_word.py new file mode 100644 index 00000000..e2dacf45 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/review_curr_word.py @@ -0,0 +1,37 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import word_utils + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('current word.') + + def run(self): + self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor() + + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], currWord, endOfScreen, lineBreak = \ + word_utils.getCurrentWord(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) + + if currWord.isspace(): + self.env['runtime']['outputManager'].presentText(_("blank"), interrupt=True, flush=False) + else: + self.env['runtime']['outputManager'].presentText(currWord, interrupt=True, flush=False) + if endOfScreen: + if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): + self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') + if lineBreak: + if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'lineBreak'): + self.env['runtime']['outputManager'].presentText(_('line break'), interrupt=False, soundIcon='EndOfLine') + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/review_curr_word_phonetic.py b/src/fenrirscreenreader/commands/commands/review_curr_word_phonetic.py new file mode 100644 index 00000000..7321023f --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/review_curr_word_phonetic.py @@ -0,0 +1,41 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import word_utils +from fenrirscreenreader.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 _('phonetically spells the current word and set review to it') + + def run(self): + self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor() + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], currWord, endOfScreen, lineBreak = \ + word_utils.getCurrentWord(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) + + if currWord.isspace(): + self.env['runtime']['outputManager'].presentText(_("blank"), interrupt=True, flush=False) + else: + firstSequence = True + for c in currWord: + currChar = char_utils.getPhonetic(c) + self.env['runtime']['outputManager'].presentText(currChar, interrupt=firstSequence, announceCapital=True, flush=False) + firstSequence = False + if endOfScreen: + if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): + self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') + if lineBreak: + if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'lineBreak'): + self.env['runtime']['outputManager'].presentText(_('line break'), interrupt=False, soundIcon='EndOfLine') + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/review_down.py b/src/fenrirscreenreader/commands/commands/review_down.py new file mode 100644 index 00000000..58112b43 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/review_down.py @@ -0,0 +1,29 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.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 _('set review cursor to char below the current char and present it.') + + def run(self): + cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], downChar, endOfScreen = \ + char_utils.getDownChar(self.env['screen']['newCursorReview']['x'],self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) + self.env['runtime']['outputManager'].presentText(downChar ,interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) + if endOfScreen: + if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): + self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/review_line_begin.py b/src/fenrirscreenreader/commands/commands/review_line_begin.py new file mode 100644 index 00000000..7c416eee --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/review_line_begin.py @@ -0,0 +1,33 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.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 _('set review cursor to begin of current line and display the content') + + def run(self): + cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() + self.env['runtime']['cursorManager'].setReviewCursorPosition(0 ,cursorPos['y']) + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], currChar = \ + char_utils.getCurrentChar(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) + + if currChar.isspace(): + self.env['runtime']['outputManager'].presentText(_("blank"), interrupt=True, flush=False) + else: + self.env['runtime']['outputManager'].presentText(currChar ,interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) + self.env['runtime']['outputManager'].presentText(_("beginning of line"), interrupt=False) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/review_line_end.py b/src/fenrirscreenreader/commands/commands/review_line_end.py new file mode 100644 index 00000000..cc446543 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/review_line_end.py @@ -0,0 +1,30 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.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 _('set review cursor to end of current line and display the content') + + def run(self): + cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() + self.env['runtime']['cursorManager'].setReviewCursorPosition(self.env['screen']['columns']-1 ,cursorPos['y']) + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], currChar = \ + char_utils.getCurrentChar(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) + + self.env['runtime']['outputManager'].presentText(currChar ,interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) + self.env['runtime']['outputManager'].presentText(_("end of line"), interrupt=False) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/review_line_first_char.py b/src/fenrirscreenreader/commands/commands/review_line_first_char.py new file mode 100644 index 00000000..7d18692c --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/review_line_first_char.py @@ -0,0 +1,36 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import line_utils +from fenrirscreenreader.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 _('set review cursor to end of current line and display the content') + + def run(self): + cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() + x, y, currLine = \ + line_utils.getCurrentLine(cursorPos['x'], cursorPos['y'], self.env['screen']['newContentText']) + if currLine.isspace(): + self.env['runtime']['outputManager'].presentText(_("line is empty"), interrupt=True) + return + self.env['runtime']['cursorManager'].setReviewCursorPosition((len(currLine) - len(currLine.lstrip())), cursorPos['y']) + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], currChar = \ + char_utils.getCurrentChar(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) + + self.env['runtime']['outputManager'].presentText(currChar ,interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) + self.env['runtime']['outputManager'].presentText(_("first char in line indent {0}").format(str(len(currLine) - len(currLine.lstrip()))), interrupt=False) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/review_line_last_char.py b/src/fenrirscreenreader/commands/commands/review_line_last_char.py new file mode 100644 index 00000000..54854b39 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/review_line_last_char.py @@ -0,0 +1,30 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.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 _('set review cursor to end of current line and display the content') + + def run(self): + cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() + self.env['runtime']['cursorManager'].setReviewCursorPosition(self.env['screen']['columns']-1 ,cursorPos['y']) + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], lastChar = \ + char_utils.getLastCharInLine(self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) + + self.env['runtime']['outputManager'].presentText(lastChar ,interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) + self.env['runtime']['outputManager'].presentText(_("last char in line"), interrupt=False) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/review_next_char.py b/src/fenrirscreenreader/commands/commands/review_next_char.py new file mode 100644 index 00000000..e9983370 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/review_next_char.py @@ -0,0 +1,33 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.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 _('moves review to the next character and presents it') + + def run(self): + self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor() + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], nextChar, endOfScreen, lineBreak = \ + char_utils.getNextChar(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) + + self.env['runtime']['outputManager'].presentText(nextChar, interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) + if endOfScreen: + if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): + self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') + if lineBreak: + if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'lineBreak'): + self.env['runtime']['outputManager'].presentText(_('line break'), interrupt=False, soundIcon='EndOfLine') + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/review_next_char_phonetic.py b/src/fenrirscreenreader/commands/commands/review_next_char_phonetic.py new file mode 100644 index 00000000..8cf4cd95 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/review_next_char_phonetic.py @@ -0,0 +1,35 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.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 _('phonetically presents the next character and set review to it') + + def run(self): + self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor() + + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], nextChar, endOfScreen, lineBreak = \ + char_utils.getNextChar(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) + + nextChar = char_utils.getPhonetic(nextChar) + self.env['runtime']['outputManager'].presentText(nextChar ,interrupt=True, announceCapital=True, flush=False) + if endOfScreen: + if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): + self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') + if lineBreak: + if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'lineBreak'): + self.env['runtime']['outputManager'].presentText(_('line break'), interrupt=False, soundIcon='EndOfLine') + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/review_next_line.py b/src/fenrirscreenreader/commands/commands/review_next_line.py new file mode 100644 index 00000000..8cf4a4c3 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/review_next_line.py @@ -0,0 +1,36 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import line_utils + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('moves review to the next line and presents it') + + def run(self): + self.env['screen']['oldCursorReview'] = self.env['screen']['newCursorReview'] + if not self.env['screen']['newCursorReview']: + self.env['screen']['newCursorReview'] = self.env['screen']['newCursor'].copy() + + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], nextLine, endOfScreen = \ + line_utils.getNextLine(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) + + if nextLine.isspace(): + self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True, flush=False) + else: + self.env['runtime']['outputManager'].presentText(nextLine, interrupt=True, flush=False) + if endOfScreen: + if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): + self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/review_next_word.py b/src/fenrirscreenreader/commands/commands/review_next_word.py new file mode 100644 index 00000000..a37a5e06 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/review_next_word.py @@ -0,0 +1,39 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import word_utils + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('moves review to the next word and presents it') + + def run(self): + self.env['screen']['oldCursorReview'] = self.env['screen']['newCursorReview'] + if self.env['screen']['newCursorReview'] == None: + self.env['screen']['newCursorReview'] = self.env['screen']['newCursor'].copy() + + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], nextWord, endOfScreen, lineBreak = \ + word_utils.getNextWord(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) + + if nextWord.isspace(): + self.env['runtime']['outputManager'].presentText(_("blank"), interrupt=True, flush=False) + else: + self.env['runtime']['outputManager'].presentText(nextWord, interrupt=True, flush=False) + if endOfScreen: + if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): + self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') + if lineBreak: + if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'lineBreak'): + self.env['runtime']['outputManager'].presentText(_('line break'), interrupt=False, soundIcon='EndOfLine') + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/review_next_word_phonetic.py b/src/fenrirscreenreader/commands/commands/review_next_word_phonetic.py new file mode 100644 index 00000000..d558b403 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/review_next_word_phonetic.py @@ -0,0 +1,41 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import word_utils +from fenrirscreenreader.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 _('phonetically spells the current word and set review to it') + + def run(self): + self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor() + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], nextWord, endOfScreen, lineBreak = \ + word_utils.getNextWord(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) + + if nextWord.isspace(): + self.env['runtime']['outputManager'].presentText(_("blank"), interrupt=True, flush=False) + else: + firstSequence = True + for c in nextWord: + currChar = char_utils.getPhonetic(c) + self.env['runtime']['outputManager'].presentText(currChar, interrupt=firstSequence, announceCapital=True, flush=False) + firstSequence = False + if endOfScreen: + if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): + self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') + if lineBreak: + if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'lineBreak'): + self.env['runtime']['outputManager'].presentText(_('line break'), interrupt=False, soundIcon='EndOfLine') + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/review_prev_char.py b/src/fenrirscreenreader/commands/commands/review_prev_char.py new file mode 100644 index 00000000..c4038b72 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/review_prev_char.py @@ -0,0 +1,36 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.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 _('moves review to the previous character and presents it') + + def run(self): + self.env['screen']['oldCursorReview'] = self.env['screen']['newCursorReview'] + if not self.env['screen']['newCursorReview']: + self.env['screen']['newCursorReview'] = self.env['screen']['newCursor'].copy() + + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], prevChar, endOfScreen, lineBreak = \ + char_utils.getPrevChar(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) + + self.env['runtime']['outputManager'].presentText(prevChar, interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) + if endOfScreen: + if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): + self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') + if lineBreak: + if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'lineBreak'): + self.env['runtime']['outputManager'].presentText(_('line break'), interrupt=False, soundIcon='EndOfLine') + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/review_prev_char_phonetic.py b/src/fenrirscreenreader/commands/commands/review_prev_char_phonetic.py new file mode 100644 index 00000000..4beabe51 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/review_prev_char_phonetic.py @@ -0,0 +1,35 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.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 _('phonetically presents the previous character and set review to it') + + def run(self): + self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor() + + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], prevChar, endOfScreen, lineBreak = \ + char_utils.getPrevChar(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) + + prevChar = char_utils.getPhonetic(prevChar) + self.env['runtime']['outputManager'].presentText(prevChar ,interrupt=True, announceCapital=True, flush=False) + if endOfScreen: + if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): + self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') + if lineBreak: + if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'lineBreak'): + self.env['runtime']['outputManager'].presentText(_('line break'), interrupt=False, soundIcon='EndOfLine') + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/review_prev_line.py b/src/fenrirscreenreader/commands/commands/review_prev_line.py new file mode 100644 index 00000000..480e4bae --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/review_prev_line.py @@ -0,0 +1,35 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import line_utils + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('moves review to the previous line and presents it') + + def run(self): + self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor() + + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], prevLine, endOfScreen = \ + line_utils.getPrevLine(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) + + if prevLine.isspace(): + self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True, flush=False) + else: + self.env['runtime']['outputManager'].presentText(prevLine, interrupt=True, flush=False) + if endOfScreen: + if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): + self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/review_prev_word.py b/src/fenrirscreenreader/commands/commands/review_prev_word.py new file mode 100644 index 00000000..10ea680b --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/review_prev_word.py @@ -0,0 +1,37 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import word_utils + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('moves review focus to the previous word and presents it') + + def run(self): + self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor() + + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], prevWord, endOfScreen, lineBreak = \ + word_utils.getPrevWord(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) + + if prevWord.isspace(): + self.env['runtime']['outputManager'].presentText(_("blank"), interrupt=True, flush=False) + else: + self.env['runtime']['outputManager'].presentText(prevWord, interrupt=True, flush=False) + if endOfScreen: + if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): + self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=False, soundIcon='EndOfScreen') + if lineBreak: + if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'lineBreak'): + self.env['runtime']['outputManager'].presentText(_('line break'), interrupt=False, soundIcon='EndOfLine') + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/review_prev_word_phonetic.py b/src/fenrirscreenreader/commands/commands/review_prev_word_phonetic.py new file mode 100644 index 00000000..3076e9d3 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/review_prev_word_phonetic.py @@ -0,0 +1,41 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import word_utils +from fenrirscreenreader.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 _('phonetically spells the current word and set review to it') + + def run(self): + self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor() + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], prevWord, endOfScreen, lineBreak = \ + word_utils.getPrevWord(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) + + if prevWord.isspace(): + self.env['runtime']['outputManager'].presentText(_("blank"), interrupt=True, flush=False) + else: + firstSequence = True + for c in prevWord: + currChar = char_utils.getPhonetic(c) + self.env['runtime']['outputManager'].presentText(currChar, interrupt=firstSequence, announceCapital=True, flush=False) + firstSequence = False + if endOfScreen: + if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): + self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') + if lineBreak: + if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'lineBreak'): + self.env['runtime']['outputManager'].presentText(_('line break'), interrupt=False, soundIcon='EndOfLine') + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/review_top.py b/src/fenrirscreenreader/commands/commands/review_top.py new file mode 100644 index 00000000..15e4ee3f --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/review_top.py @@ -0,0 +1,25 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.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 _('move review to top of screen') + + def run(self): + self.env['screen']['newCursorReview'] = {'x':0,'y':0} + self.env['runtime']['outputManager'].presentText(_("Top"), interrupt=True, flush=False) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/review_up.py b/src/fenrirscreenreader/commands/commands/review_up.py new file mode 100644 index 00000000..2affc0da --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/review_up.py @@ -0,0 +1,32 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.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 _('set review cursor to the char in the line below and present it') + + def run(self): + cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], upChar, endOfScreen = \ + char_utils.getUpChar(self.env['screen']['newCursorReview']['x'],self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) + self.env['runtime']['outputManager'].presentText(upChar ,interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) + if endOfScreen: + if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): + self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') + if lineBreak: + if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'lineBreak'): + self.env['runtime']['outputManager'].presentText(_('line break'), interrupt=False, soundIcon='EndOfLine') + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/set_bookmark_1.py b/src/fenrirscreenreader/commands/commands/set_bookmark_1.py new file mode 100644 index 00000000..3a1bdcbe --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/set_bookmark_1.py @@ -0,0 +1,36 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + self.ID = '1' + def initialize(self, environment): + self.env = environment + self.env['commandBuffer']['bookMarks'][self.ID] = {} + def shutdown(self): + pass + def getDescription(self): + return _('set Bookmark {0}').format(self.ID,) + + def run(self): + if not self.env['commandBuffer']['Marks']['1']: + self.env['runtime']['outputManager'].presentText(_("No Mark found"), interrupt=True) + return + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {} + + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'] = self.env['commandBuffer']['Marks']['1'].copy() + if self.env['commandBuffer']['Marks']['2']: + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = self.env['commandBuffer']['Marks']['2'].copy() + else: + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = None + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} set for application {1}').format(self.ID, currApp), interrupt=True) + self.env['commandBuffer']['Marks']['1'] = None + self.env['commandBuffer']['Marks']['2'] = None + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/set_bookmark_10.py b/src/fenrirscreenreader/commands/commands/set_bookmark_10.py new file mode 100644 index 00000000..5dfeea05 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/set_bookmark_10.py @@ -0,0 +1,36 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + self.ID = '10' + def initialize(self, environment): + self.env = environment + self.env['commandBuffer']['bookMarks'][self.ID] = {} + def shutdown(self): + pass + def getDescription(self): + return _('set Bookmark {0}').format(self.ID,) + + def run(self): + if not self.env['commandBuffer']['Marks']['1']: + self.env['runtime']['outputManager'].presentText(_("No Mark found"), interrupt=True) + return + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {} + + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'] = self.env['commandBuffer']['Marks']['1'].copy() + if self.env['commandBuffer']['Marks']['2']: + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = self.env['commandBuffer']['Marks']['2'].copy() + else: + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = None + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} set for application {1}').format(self.ID, currApp), interrupt=True) + self.env['commandBuffer']['Marks']['1'] = None + self.env['commandBuffer']['Marks']['2'] = None + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/set_bookmark_2.py b/src/fenrirscreenreader/commands/commands/set_bookmark_2.py new file mode 100644 index 00000000..9268e21d --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/set_bookmark_2.py @@ -0,0 +1,36 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + self.ID = '2' + def initialize(self, environment): + self.env = environment + self.env['commandBuffer']['bookMarks'][self.ID] = {} + def shutdown(self): + pass + def getDescription(self): + return _('set Bookmark {0}').format(self.ID,) + + def run(self): + if not self.env['commandBuffer']['Marks']['1']: + self.env['runtime']['outputManager'].presentText(_("No Mark found"), interrupt=True) + return + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {} + + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'] = self.env['commandBuffer']['Marks']['1'].copy() + if self.env['commandBuffer']['Marks']['2']: + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = self.env['commandBuffer']['Marks']['2'].copy() + else: + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = None + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} set for application {1}').format(self.ID, currApp), interrupt=True) + self.env['commandBuffer']['Marks']['1'] = None + self.env['commandBuffer']['Marks']['2'] = None + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/set_bookmark_3.py b/src/fenrirscreenreader/commands/commands/set_bookmark_3.py new file mode 100644 index 00000000..5231b3ac --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/set_bookmark_3.py @@ -0,0 +1,36 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + self.ID = '3' + def initialize(self, environment): + self.env = environment + self.env['commandBuffer']['bookMarks'][self.ID] = {} + def shutdown(self): + pass + def getDescription(self): + return _('set Bookmark {0}').format(self.ID,) + + def run(self): + if not self.env['commandBuffer']['Marks']['1']: + self.env['runtime']['outputManager'].presentText(_("No Mark found"), interrupt=True) + return + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {} + + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'] = self.env['commandBuffer']['Marks']['1'].copy() + if self.env['commandBuffer']['Marks']['2']: + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = self.env['commandBuffer']['Marks']['2'].copy() + else: + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = None + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} set for application {1}').format(self.ID, currApp), interrupt=True) + self.env['commandBuffer']['Marks']['1'] = None + self.env['commandBuffer']['Marks']['2'] = None + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/set_bookmark_4.py b/src/fenrirscreenreader/commands/commands/set_bookmark_4.py new file mode 100644 index 00000000..41a2b825 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/set_bookmark_4.py @@ -0,0 +1,36 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + self.ID = '4' + def initialize(self, environment): + self.env = environment + self.env['commandBuffer']['bookMarks'][self.ID] = {} + def shutdown(self): + pass + def getDescription(self): + return _('set Bookmark {0}').format(self.ID,) + + def run(self): + if not self.env['commandBuffer']['Marks']['1']: + self.env['runtime']['outputManager'].presentText(_("No Mark found"), interrupt=True) + return + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {} + + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'] = self.env['commandBuffer']['Marks']['1'].copy() + if self.env['commandBuffer']['Marks']['2']: + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = self.env['commandBuffer']['Marks']['2'].copy() + else: + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = None + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} set for application {1}').format(self.ID, currApp), interrupt=True) + self.env['commandBuffer']['Marks']['1'] = None + self.env['commandBuffer']['Marks']['2'] = None + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/set_bookmark_5.py b/src/fenrirscreenreader/commands/commands/set_bookmark_5.py new file mode 100644 index 00000000..7d82fcf7 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/set_bookmark_5.py @@ -0,0 +1,36 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + self.ID = '5' + def initialize(self, environment): + self.env = environment + self.env['commandBuffer']['bookMarks'][self.ID] = {} + def shutdown(self): + pass + def getDescription(self): + return _('set Bookmark {0}').format(self.ID,) + + def run(self): + if not self.env['commandBuffer']['Marks']['1']: + self.env['runtime']['outputManager'].presentText(_("No Mark found"), interrupt=True) + return + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {} + + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'] = self.env['commandBuffer']['Marks']['1'].copy() + if self.env['commandBuffer']['Marks']['2']: + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = self.env['commandBuffer']['Marks']['2'].copy() + else: + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = None + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} set for application {1}').format(self.ID, currApp), interrupt=True) + self.env['commandBuffer']['Marks']['1'] = None + self.env['commandBuffer']['Marks']['2'] = None + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/set_bookmark_6.py b/src/fenrirscreenreader/commands/commands/set_bookmark_6.py new file mode 100644 index 00000000..806664f5 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/set_bookmark_6.py @@ -0,0 +1,36 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + self.ID = '6' + def initialize(self, environment): + self.env = environment + self.env['commandBuffer']['bookMarks'][self.ID] = {} + def shutdown(self): + pass + def getDescription(self): + return _('set Bookmark {0}').format(self.ID,) + + def run(self): + if not self.env['commandBuffer']['Marks']['1']: + self.env['runtime']['outputManager'].presentText(_("No Mark found"), interrupt=True) + return + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {} + + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'] = self.env['commandBuffer']['Marks']['1'].copy() + if self.env['commandBuffer']['Marks']['2']: + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = self.env['commandBuffer']['Marks']['2'].copy() + else: + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = None + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} set for application {1}').format(self.ID, currApp), interrupt=True) + self.env['commandBuffer']['Marks']['1'] = None + self.env['commandBuffer']['Marks']['2'] = None + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/set_bookmark_7.py b/src/fenrirscreenreader/commands/commands/set_bookmark_7.py new file mode 100644 index 00000000..6f7c73bc --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/set_bookmark_7.py @@ -0,0 +1,36 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + self.ID = '7' + def initialize(self, environment): + self.env = environment + self.env['commandBuffer']['bookMarks'][self.ID] = {} + def shutdown(self): + pass + def getDescription(self): + return _('set Bookmark {0}').format(self.ID,) + + def run(self): + if not self.env['commandBuffer']['Marks']['1']: + self.env['runtime']['outputManager'].presentText(_("No Mark found"), interrupt=True) + return + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {} + + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'] = self.env['commandBuffer']['Marks']['1'].copy() + if self.env['commandBuffer']['Marks']['2']: + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = self.env['commandBuffer']['Marks']['2'].copy() + else: + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = None + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} set for application {1}').format(self.ID, currApp), interrupt=True) + self.env['commandBuffer']['Marks']['1'] = None + self.env['commandBuffer']['Marks']['2'] = None + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/set_bookmark_8.py b/src/fenrirscreenreader/commands/commands/set_bookmark_8.py new file mode 100644 index 00000000..df203fac --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/set_bookmark_8.py @@ -0,0 +1,36 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + self.ID = '8' + def initialize(self, environment): + self.env = environment + self.env['commandBuffer']['bookMarks'][self.ID] = {} + def shutdown(self): + pass + def getDescription(self): + return _('set Bookmark {0}').format(self.ID,) + + def run(self): + if not self.env['commandBuffer']['Marks']['1']: + self.env['runtime']['outputManager'].presentText(_("No Mark found"), interrupt=True) + return + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {} + + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'] = self.env['commandBuffer']['Marks']['1'].copy() + if self.env['commandBuffer']['Marks']['2']: + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = self.env['commandBuffer']['Marks']['2'].copy() + else: + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = None + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} set for application {1}').format(self.ID, currApp), interrupt=True) + self.env['commandBuffer']['Marks']['1'] = None + self.env['commandBuffer']['Marks']['2'] = None + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/set_bookmark_9.py b/src/fenrirscreenreader/commands/commands/set_bookmark_9.py new file mode 100644 index 00000000..7dec75ea --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/set_bookmark_9.py @@ -0,0 +1,36 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + self.ID = '9' + def initialize(self, environment): + self.env = environment + self.env['commandBuffer']['bookMarks'][self.ID] = {} + def shutdown(self): + pass + def getDescription(self): + return _('set Bookmark {0}').format(self.ID,) + + def run(self): + if not self.env['commandBuffer']['Marks']['1']: + self.env['runtime']['outputManager'].presentText(_("No Mark found"), interrupt=True) + return + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {} + + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'] = self.env['commandBuffer']['Marks']['1'].copy() + if self.env['commandBuffer']['Marks']['2']: + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = self.env['commandBuffer']['Marks']['2'].copy() + else: + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = None + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} set for application {1}').format(self.ID, currApp), interrupt=True) + self.env['commandBuffer']['Marks']['1'] = None + self.env['commandBuffer']['Marks']['2'] = None + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/set_mark.py b/src/fenrirscreenreader/commands/commands/set_mark.py new file mode 100644 index 00000000..65e64bb8 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/set_mark.py @@ -0,0 +1,30 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('places marks to select text to copy to the clipboard') + + def run(self): + if not self.env['runtime']['cursorManager'].isReviewMode(): + self.env['runtime']['outputManager'].presentText(_('no review cursor'), interrupt=True) + return + + currMark = self.env['runtime']['cursorManager'].setMark() + if currMark == 1: + self.env['runtime']['outputManager'].presentText(_('set mark'), soundIcon='PlaceStartMark', interrupt=True) + elif currMark == 2: + self.env['runtime']['outputManager'].presentText(_('set mark'),soundIcon='PlaceEndMark', interrupt=True) + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/set_window_application.py b/src/fenrirscreenreader/commands/commands/set_window_application.py new file mode 100644 index 00000000..c9247d3b --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/set_window_application.py @@ -0,0 +1,28 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('set Window Mode, needs 2 marks ') + + def run(self): + if self.env['runtime']['cursorManager'].setWindowForApplication(): + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + self.env['runtime']['outputManager'].presentText(_('Window Mode on for application {0}').format(currApp), interrupt=True) + self.env['runtime']['cursorManager'].clearMarks() + else: + self.env['runtime']['outputManager'].presentText(_("Set window begin and end marks"), interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/shut_up.py b/src/fenrirscreenreader/commands/commands/shut_up.py new file mode 100644 index 00000000..8bdaf78d --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/shut_up.py @@ -0,0 +1,23 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('interrupts the current presentation') + def run(self): + if len(self.env['input']['prevDeepestInput']) > len(self.env['input']['currInput']): + return + self.env['runtime']['outputManager'].interruptOutput() + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/spell_check.py b/src/fenrirscreenreader/commands/commands/spell_check.py new file mode 100644 index 00000000..326ed866 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/spell_check.py @@ -0,0 +1,56 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import word_utils +initialized = False +try: + import enchant + initialized = True +except: + pass + +class command(): + def __init__(self): + self.language = '' + self.spellChecker = None + def initialize(self, environment): + self.env = environment + self.updateSpellLanguage() + def shutdown(self): + pass + def getDescription(self): + return _('checks the spelling of the current word') + def updateSpellLanguage(self): + if not initialized: + self.env['runtime']['outputManager'].presentText(_('pyenchant 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: + self.env['runtime']['outputManager'].presentText(_('pyenchant is not installed'), interrupt=True) + return + if self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage') != self.language: + try: + self.updateSpellLanguage() + except: + return + + cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() + + # get the word + newContent = self.env['screen']['newContentText'].split('\n')[cursorPos['y']] + x, y, currWord, endOfScreen, lineBreak = word_utils.getCurrentWord(cursorPos['x'], 0, newContent) + + if not currWord.isspace(): + if not self.spellChecker.check(currWord): + self.env['runtime']['outputManager'].presentText(_('misspelled'),soundIcon='mispell', interrupt=True) + elif not ignore: + self.env['runtime']['outputManager'].presentText(_('correct'),soundIcon='', interrupt=True) + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/subprocess.py b/src/fenrirscreenreader/commands/commands/subprocess.py new file mode 100644 index 00000000..ddb3a952 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/subprocess.py @@ -0,0 +1,50 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +import subprocess, os +from subprocess import Popen, PIPE +import _thread + +class command(): + def __init__(self): + pass + def initialize(self, environment, scriptPath=''): + self.env = environment + self.scriptPath = scriptPath + def shutdown(self): + pass + def getDescription(self): + return _('script: {0} fullpath: {1}').format(os.path.basename(self.scriptPath), self.scriptPath) + def run(self): + if not os.path.exists(self.scriptPath): + self.env['runtime']['outputManager'].presentText(_('scriptfile does not exist'), soundIcon='', interrupt=False) + return + if not os.path.isfile(self.scriptPath): + self.env['runtime']['outputManager'].presentText(_('scriptfile is not a file'), soundIcon='', interrupt=False) + return + if not os.access(self.scriptPath, os.X_OK): + self.env['runtime']['outputManager'].presentText(_('scriptfile is not executable'), soundIcon='', interrupt=False) + return + _thread.start_new_thread(self._threadRun , ()) + + def _threadRun(self): + try: + callstring = self.scriptPath + ' ' + self.env['general']['currUser'] + p = Popen(callstring , stdout=PIPE, stderr=PIPE, shell=True) + stdout, stderr = p.communicate() + stdout = stdout.decode('utf-8') + stderr = stderr.decode('utf-8') + self.env['runtime']['outputManager'].interruptOutput() + if stderr != '': + self.env['runtime']['outputManager'].presentText(str(stderr) , soundIcon='', interrupt=False) + if stdout != '': + self.env['runtime']['outputManager'].presentText(str(stdout) , soundIcon='', interrupt=False) + except Exception as e: + self.env['runtime']['outputManager'].presentText(e , soundIcon='', interrupt=False) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/temp_disable_speech.py b/src/fenrirscreenreader/commands/commands/temp_disable_speech.py new file mode 100644 index 00000000..da1701ab --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/temp_disable_speech.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('disables speech until next keypress') + + def run(self): + if self.env['runtime']['settingsManager'].getSettingAsBool('speech', 'enabled'): + self.env['runtime']['outputManager'].presentText(_("speech temporary disabled"), soundIcon='SpeechOff', interrupt=True) + self.env['commandBuffer']['enableSpeechOnKeypress'] = True + self.env['runtime']['settingsManager'].setSetting('speech', 'enabled', str(not self.env['runtime']['settingsManager'].getSettingAsBool('speech', 'enabled'))) + self.env['runtime']['outputManager'].interruptOutput() + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/time.py b/src/fenrirscreenreader/commands/commands/time.py new file mode 100644 index 00000000..ffa97760 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/time.py @@ -0,0 +1,30 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +import datetime + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('presents the time') + + def run(self): + timeFormat = self.env['runtime']['settingsManager'].getSetting('general', 'timeFormat') + + # get the time formatted + timeString = datetime.datetime.strftime(datetime.datetime.now(), timeFormat) + + # present the time via speak and braile, there is no soundicon, interrupt the current speech + self.env['runtime']['outputManager'].presentText(timeString , soundIcon='', interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/toggle_auto_read.py b/src/fenrirscreenreader/commands/commands/toggle_auto_read.py new file mode 100644 index 00000000..a94cc3e1 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/toggle_auto_read.py @@ -0,0 +1,26 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.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 automatic reading of new text as it appears') + + def run(self): + self.env['runtime']['settingsManager'].setSetting('speech', 'autoReadIncoming', str(not self.env['runtime']['settingsManager'].getSettingAsBool('speech', 'autoReadIncoming'))) + if self.env['runtime']['settingsManager'].getSettingAsBool('speech', 'autoReadIncoming'): + self.env['runtime']['outputManager'].presentText(_("autoread enabled"), soundIcon='', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(_("autoread disabled"), soundIcon='', interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/toggle_auto_spell_check.py b/src/fenrirscreenreader/commands/commands/toggle_auto_spell_check.py new file mode 100644 index 00000000..1664e70e --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/toggle_auto_spell_check.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.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 automatic spell checking') + + def run(self): + self.env['runtime']['settingsManager'].setSetting('general', 'autoSpellCheck', str(not self.env['runtime']['settingsManager'].getSettingAsBool('general', 'autoSpellCheck'))) + if self.env['runtime']['settingsManager'].getSettingAsBool('general', 'autoSpellCheck'): + self.env['runtime']['outputManager'].presentText(_("auto spellcheck enabled"), soundIcon='', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(_("auto spellcheck disabled"), soundIcon='', interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/toggle_auto_time.py b/src/fenrirscreenreader/commands/commands/toggle_auto_time.py new file mode 100644 index 00000000..bec62b5d --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/toggle_auto_time.py @@ -0,0 +1,26 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.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 automatic reading of time after an period') + + def run(self): + self.env['runtime']['settingsManager'].setSetting('time', 'enabled', str(not self.env['runtime']['settingsManager'].getSettingAsBool('time', 'enabled'))) + if self.env['runtime']['settingsManager'].getSettingAsBool('time', 'enabled'): + self.env['runtime']['outputManager'].presentText(_("autotime enabled"), soundIcon='', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(_("autotime disabled"), soundIcon='', interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/toggle_braille.py b/src/fenrirscreenreader/commands/commands/toggle_braille.py new file mode 100644 index 00000000..04943655 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/toggle_braille.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.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 and disables output in braille') + + def run(self): + if self.env['runtime']['settingsManager'].getSettingAsBool('braille', 'enabled'): + self.env['runtime']['outputManager'].presentText(_('braille disabled'), soundIcon='BrailleOff', interrupt=True) + self.env['runtime']['settingsManager'].setSetting('braille', 'enabled', str(not self.env['runtime']['settingsManager'].getSettingAsBool('braille', 'enabled'))) + if self.env['runtime']['settingsManager'].getSettingAsBool('braille', 'enabled'): + self.env['runtime']['outputManager'].presentText(_('braille enabled'), soundIcon='BrailleOn', interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/toggle_emoticons.py b/src/fenrirscreenreader/commands/commands/toggle_emoticons.py new file mode 100644 index 00000000..9a223817 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/toggle_emoticons.py @@ -0,0 +1,26 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.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 announcement of emoticons instead of chars') + + def run(self): + self.env['runtime']['settingsManager'].setSetting('general', 'emoticons', str(not self.env['runtime']['settingsManager'].getSettingAsBool('general', 'emoticons'))) + if self.env['runtime']['settingsManager'].getSettingAsBool('general', 'emoticons'): + self.env['runtime']['outputManager'].presentText(_('emoticons enabled'), soundIcon='', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(_('emoticons disabled'), soundIcon='', interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/toggle_highlight_tracking.py b/src/fenrirscreenreader/commands/commands/toggle_highlight_tracking.py new file mode 100644 index 00000000..eb0bbec2 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/toggle_highlight_tracking.py @@ -0,0 +1,29 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.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 text') + + def run(self): + currMode = self.env['runtime']['settingsManager'].getSettingAsBool('focus', 'highlight') + + self.env['runtime']['settingsManager'].setSetting('focus', 'highlight', str(not currMode)) + self.env['runtime']['settingsManager'].setSetting('focus', 'cursor', str(currMode)) + if self.env['runtime']['settingsManager'].getSettingAsBool('focus', 'highlight'): + self.env['runtime']['outputManager'].presentText(_('highlight tracking'), soundIcon='', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(_('cursor tracking'), soundIcon='', interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/toggle_output.py b/src/fenrirscreenreader/commands/commands/toggle_output.py new file mode 100644 index 00000000..7e40e682 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/toggle_output.py @@ -0,0 +1,34 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('toggles all output settings') + + def run(self): + if self.env['runtime']['settingsManager'].getSettingAsBool('speech', 'enabled') or \ + self.env['runtime']['settingsManager'].getSettingAsBool('sound', 'enabled') or \ + self.env['runtime']['settingsManager'].getSettingAsBool('braille', 'enabled'): + self.env['runtime']['outputManager'].presentText(_('Fenrir muted'), soundIcon='Accept', interrupt=True) + self.env['runtime']['settingsManager'].setSetting('speech', 'enabled','False') + self.env['runtime']['settingsManager'].setSetting('sound', 'enabled','False') + self.env['runtime']['settingsManager'].setSetting('braille', 'enabled','False') + else: + self.env['runtime']['settingsManager'].setSetting('speech', 'enabled','True') + self.env['runtime']['settingsManager'].setSetting('sound', 'enabled','True') + self.env['runtime']['settingsManager'].setSetting('braille', 'enabled','True') + self.env['runtime']['outputManager'].presentText(_('Fenrir unmuted'), soundIcon='Cancel', interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/toggle_punctuation_level.py b/src/fenrirscreenreader/commands/commands/toggle_punctuation_level.py new file mode 100644 index 00000000..57ca6c6b --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/toggle_punctuation_level.py @@ -0,0 +1,26 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.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']['punctuationManager'].cyclePunctuation(): + self.env['runtime']['outputManager'].presentText(self.env['runtime']['settingsManager'].getSetting('general', 'punctuationLevel'), interrupt=True, ignorePunctuation=True) + else: + self.env['runtime']['outputManager'].presentText(_('No punctuation found.'), interrupt=True, ignorePunctuation=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/toggle_sound.py b/src/fenrirscreenreader/commands/commands/toggle_sound.py new file mode 100644 index 00000000..e599f668 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/toggle_sound.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.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 sound') + + def run(self): + if self.env['runtime']['settingsManager'].getSettingAsBool('sound', 'enabled'): + self.env['runtime']['outputManager'].presentText(_('sound disabled'), soundIcon='SoundOff', interrupt=True) + self.env['runtime']['settingsManager'].setSetting('sound', 'enabled', str(not self.env['runtime']['settingsManager'].getSettingAsBool('sound', 'enabled'))) + if self.env['runtime']['settingsManager'].getSettingAsBool('sound', 'enabled'): + self.env['runtime']['outputManager'].presentText(_('sound enabled'), soundIcon='SoundOn', interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/toggle_speech.py b/src/fenrirscreenreader/commands/commands/toggle_speech.py new file mode 100644 index 00000000..94348750 --- /dev/null +++ b/src/fenrirscreenreader/commands/commands/toggle_speech.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.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 speech') + + def run(self): + if self.env['runtime']['settingsManager'].getSettingAsBool('speech', 'enabled'): + self.env['runtime']['outputManager'].presentText(_('speech disabled'), soundIcon='SpeechOff', interrupt=True) + self.env['runtime']['settingsManager'].setSetting('speech', 'enabled', str(not self.env['runtime']['settingsManager'].getSettingAsBool('speech', 'enabled'))) + if self.env['runtime']['settingsManager'].getSettingAsBool('speech', 'enabled'): + self.env['runtime']['outputManager'].presentText(_('speech enabled'), soundIcon='SpeechOn', interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/commands/toggle_tutorial_mode.py b/src/fenrirscreenreader/commands/commands/toggle_tutorial_mode.py new file mode 100644 index 00000000..f09f70f1 --- /dev/null +++ b/src/fenrirscreenreader/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 fenrirscreenreader.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 diff --git a/src/fenrirscreenreader/commands/help/Readme.txt b/src/fenrirscreenreader/commands/help/Readme.txt new file mode 100644 index 00000000..c90f7a6b --- /dev/null +++ b/src/fenrirscreenreader/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/fenrirscreenreader/commands/help/__init__.py b/src/fenrirscreenreader/commands/help/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/src/fenrirscreenreader/commands/help/curr_help.py b/src/fenrirscreenreader/commands/help/curr_help.py new file mode 100644 index 00000000..4f0ebf31 --- /dev/null +++ b/src/fenrirscreenreader/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 fenrirscreenreader.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/fenrirscreenreader/commands/help/next_help.py b/src/fenrirscreenreader/commands/help/next_help.py new file mode 100644 index 00000000..7ef3993e --- /dev/null +++ b/src/fenrirscreenreader/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 fenrirscreenreader.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/fenrirscreenreader/commands/help/prev_help.py b/src/fenrirscreenreader/commands/help/prev_help.py new file mode 100644 index 00000000..3060ecc2 --- /dev/null +++ b/src/fenrirscreenreader/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 fenrirscreenreader.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/fenrirscreenreader/commands/onApplicationChange/__init__.py b/src/fenrirscreenreader/commands/onApplicationChange/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/fenrirscreenreader/commands/onApplicationChange/inactive/test.py b/src/fenrirscreenreader/commands/onApplicationChange/inactive/test.py new file mode 100644 index 00000000..f17d8160 --- /dev/null +++ b/src/fenrirscreenreader/commands/onApplicationChange/inactive/test.py @@ -0,0 +1,25 @@ +#!/bi[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]/py[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]ho[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']] +# -*- [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]odi[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]g: u[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]f-8 -*- + +# F[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]i[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']] TTY [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']] [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]d[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']] +# By Ch[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]y[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']], S[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]o[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]m [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]go[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']], [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]d [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]o[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]ibu[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]. + +f[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]om [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]o[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']] impo[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']] d[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]bug + +[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]l[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']] [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]omm[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]d(): + d[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]f __i[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]i[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]__([['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]lf): + p[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']] + d[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]f i[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]i[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]i[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]liz[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]([['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]lf, [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]vi[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]o[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]m[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]): + [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]lf.[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]v = [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]vi[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]o[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]m[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']] + d[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]f [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]hu[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]dow[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]([['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]lf): + p[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']] + d[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]f g[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]ip[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]io[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]([['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]lf): + [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]u[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']] [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]No d[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]ip[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]io[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']] fou[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]d[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']] + d[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]f [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]u[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]([['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]lf): + #p[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]i[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]([['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]w [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']], [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]lf.[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]v[[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]][[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]wAppli[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]io[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]]) + #p[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]i[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]([['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]old [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']], [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]lf.[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]v[[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]][[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]oldAppli[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]io[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]]) + #p[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]i[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]([['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]-----------[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]) + p[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']] + + d[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]f [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]C[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]llb[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]k([['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]lf, [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]llb[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]k): + p[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']] diff --git a/src/fenrirscreenreader/commands/onCursorChange/45000-char_echo.py b/src/fenrirscreenreader/commands/onCursorChange/45000-char_echo.py new file mode 100644 index 00000000..926d8ebd --- /dev/null +++ b/src/fenrirscreenreader/commands/onCursorChange/45000-char_echo.py @@ -0,0 +1,42 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.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): + # 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) + xMove = abs(self.env['screen']['newCursor']['x'] - self.env['screen']['oldCursor']['x']) + if xMove > 1: + return + 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 + + # 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/fenrirscreenreader/commands/onCursorChange/46000-tab_completion.py b/src/fenrirscreenreader/commands/onCursorChange/46000-tab_completion.py new file mode 100644 index 00000000..43b91159 --- /dev/null +++ b/src/fenrirscreenreader/commands/onCursorChange/46000-tab_completion.py @@ -0,0 +1,42 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.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): + # try to detect the tab completion by cursor change + xMove = abs(self.env['screen']['newCursor']['x'] - self.env['screen']['oldCursor']['x']) + if xMove == 1: + return + # is there any change? + if not self.env['runtime']['screenManager'].isDelta(): + return + if not( (xMove > 1) and xMove == len(self.env['screen']['newDelta'])): + return + # detect deletion or chilling + if self.env['screen']['newCursor']['x'] <= self.env['screen']['oldCursor']['x']: + 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, announceCapital=True, flush=False) + + def setCallback(self, callback): + pass + diff --git a/src/fenrirscreenreader/commands/onCursorChange/50000-present_char_if_cursor_change_horizontal.py b/src/fenrirscreenreader/commands/onCursorChange/50000-present_char_if_cursor_change_horizontal.py new file mode 100644 index 00000000..ecd32a40 --- /dev/null +++ b/src/fenrirscreenreader/commands/onCursorChange/50000-present_char_if_cursor_change_horizontal.py @@ -0,0 +1,51 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.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 + + # echo word insteed of char + if self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'wordEcho'): + if abs(self.env['screen']['oldCursor']['x'] - self.env['screen']['newCursor']['x']) != 1: + # 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) + if self.env['screen']['newCursor']['x'] == x: + 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/fenrirscreenreader/commands/onCursorChange/55000-present_line_if_cursor_change_vertical.py b/src/fenrirscreenreader/commands/onCursorChange/55000-present_line_if_cursor_change_vertical.py new file mode 100644 index 00000000..6d387c56 --- /dev/null +++ b/src/fenrirscreenreader/commands/onCursorChange/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 fenrirscreenreader.core import debug +from fenrirscreenreader.utils import line_utils +from fenrirscreenreader.utils import word_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(): + 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/fenrirscreenreader/commands/onCursorChange/60000-word_echo_type.py b/src/fenrirscreenreader/commands/onCursorChange/60000-word_echo_type.py new file mode 100644 index 00000000..57a530fd --- /dev/null +++ b/src/fenrirscreenreader/commands/onCursorChange/60000-word_echo_type.py @@ -0,0 +1,58 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.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): + # is it enabled? + if not self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'wordEcho'): + return + # is naviation? + if self.env['screen']['newCursor']['x'] - self.env['screen']['oldCursor']['x'] != 1: + 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 + # currently writing + if self.env['runtime']['screenManager'].isDelta(): + 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) + + # is there a word? + if currWord == '': + return + # at the end of a word + if not newContent[self.env['screen']['newCursor']['x']].isspace(): + return + # at the end of a word + if (x + len(currWord) != self.env['screen']['newCursor']['x']) and \ + (x + len(currWord) != self.env['screen']['newCursor']['x']-1): + return + + self.env['runtime']['outputManager'].presentText(currWord, interrupt=True, flush=False) + + def setCallback(self, callback): + pass + diff --git a/src/fenrirscreenreader/commands/onCursorChange/61000-word_echo_navigation.py b/src/fenrirscreenreader/commands/onCursorChange/61000-word_echo_navigation.py new file mode 100644 index 00000000..08778cee --- /dev/null +++ b/src/fenrirscreenreader/commands/onCursorChange/61000-word_echo_navigation.py @@ -0,0 +1,54 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.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): + # is navigation? + if not abs(self.env['screen']['oldCursor']['x'] - self.env['screen']['newCursor']['x']) > 1: + 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 + # currently writing + if self.env['runtime']['screenManager'].isDelta(): + 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) + + # is there a word? + if currWord == '': + return + + # at the start of a word + if (x + len(currWord) != self.env['screen']['newCursor']['x']) and \ + (self.env['screen']['newCursor']['x'] != x): + return + + self.env['runtime']['outputManager'].presentText(currWord, interrupt=True, flush=False) + + def setCallback(self, callback): + pass + diff --git a/src/fenrirscreenreader/commands/onCursorChange/62000-spell_check.py b/src/fenrirscreenreader/commands/onCursorChange/62000-spell_check.py new file mode 100644 index 00000000..332e5f12 --- /dev/null +++ b/src/fenrirscreenreader/commands/onCursorChange/62000-spell_check.py @@ -0,0 +1,134 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.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/fenrirscreenreader/commands/onCursorChange/65000-char_delete_echo.py b/src/fenrirscreenreader/commands/onCursorChange/65000-char_delete_echo.py new file mode 100644 index 00000000..41281316 --- /dev/null +++ b/src/fenrirscreenreader/commands/onCursorChange/65000-char_delete_echo.py @@ -0,0 +1,46 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.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(ignoreSpace=True): + 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) + def setCallback(self, callback): + pass + diff --git a/src/fenrirscreenreader/commands/onCursorChange/66000-exit_review_mode.py b/src/fenrirscreenreader/commands/onCursorChange/66000-exit_review_mode.py new file mode 100644 index 00000000..d934fb1c --- /dev/null +++ b/src/fenrirscreenreader/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 fenrirscreenreader.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/fenrirscreenreader/commands/onCursorChange/__init__.py b/src/fenrirscreenreader/commands/onCursorChange/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/src/fenrirscreenreader/commands/onHeartBeat/2000-GetSessionInfo.py b/src/fenrirscreenreader/commands/onHeartBeat/2000-GetSessionInfo.py new file mode 100755 index 00000000..10a5c141 --- /dev/null +++ b/src/fenrirscreenreader/commands/onHeartBeat/2000-GetSessionInfo.py @@ -0,0 +1,29 @@ +#!/bin/python +import time +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +import time +import datetime + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + self.lastTime = datetime.datetime.now() + self.lastDateString = '' + self.lastTimeString = '' + def shutdown(self): + pass + def getDescription(self): + return 'No Description found' + + def run(self): + self.env['runtime']['screenDriver'].getSessionInformation() + def setCallback(self, callback): + pass + diff --git a/src/fenrirscreenreader/commands/onHeartBeat/76000-time.py b/src/fenrirscreenreader/commands/onHeartBeat/76000-time.py new file mode 100755 index 00000000..b1bcdeff --- /dev/null +++ b/src/fenrirscreenreader/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 fenrirscreenreader.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/fenrirscreenreader/commands/onHeartBeat/__init__.py b/src/fenrirscreenreader/commands/onHeartBeat/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/src/fenrirscreenreader/commands/onHeartBeat/deactive/1.echo.py b/src/fenrirscreenreader/commands/onHeartBeat/deactive/1.echo.py new file mode 100755 index 00000000..4290b6c7 --- /dev/null +++ b/src/fenrirscreenreader/commands/onHeartBeat/deactive/1.echo.py @@ -0,0 +1,26 @@ +#!/bin/python +import time +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +import time + +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(time.time()) + def setCallback(self, callback): + pass + diff --git a/src/fenrirscreenreader/commands/onInput/10000-shut_up.py b/src/fenrirscreenreader/commands/onInput/10000-shut_up.py new file mode 100644 index 00000000..a22bc341 --- /dev/null +++ b/src/fenrirscreenreader/commands/onInput/10000-shut_up.py @@ -0,0 +1,37 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.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 not self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'interruptOnKeyPress'): + return + if self.env['runtime']['inputManager'].noKeyPressed(): + return + if self.env['runtime']['screenManager'].isScreenChange(): + return + if len(self.env['input']['currInput']) <= len(self.env['input']['prevInput']): + return + # if the filter is set + if self.env['runtime']['settingsManager'].getSetting('keyboard', 'interruptOnKeyPressFilter').strip() != '': + filterList = self.env['runtime']['settingsManager'].getSetting('keyboard', 'interruptOnKeyPressFilter').split(',') + for currInput in self.env['input']['currInput']: + if not currInput in filterList: + return + self.env['runtime']['outputManager'].interruptOutput() + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/onInput/15000-enable_temp_speech.py b/src/fenrirscreenreader/commands/onInput/15000-enable_temp_speech.py new file mode 100644 index 00000000..48836fb8 --- /dev/null +++ b/src/fenrirscreenreader/commands/onInput/15000-enable_temp_speech.py @@ -0,0 +1,31 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('disables speech until next keypress') + + def run(self): + if self.env['runtime']['inputManager'].noKeyPressed(): + return + if len(self.env['input']['prevInput']) >0: + return + if not self.env['commandBuffer']['enableSpeechOnKeypress']: + return + self.env['runtime']['settingsManager'].setSetting('speech', 'enabled', str(self.env['commandBuffer']['enableSpeechOnKeypress'])) + self.env['commandBuffer']['enableSpeechOnKeypress'] = False + self.env['runtime']['outputManager'].presentText(_("speech enabled"), soundIcon='SpeechOn', interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/onInput/80000-capslock.py b/src/fenrirscreenreader/commands/onInput/80000-capslock.py new file mode 100644 index 00000000..10db97e1 --- /dev/null +++ b/src/fenrirscreenreader/commands/onInput/80000-capslock.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.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 self.env['input']['oldCapsLock'] == self.env['input']['newCapsLock']: + return + if self.env['input']['newCapsLock']: + self.env['runtime']['outputManager'].presentText(_("Capslock on"), interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(_("Capslock off"), interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/onInput/80300-scrolllock.py b/src/fenrirscreenreader/commands/onInput/80300-scrolllock.py new file mode 100644 index 00000000..526e67f3 --- /dev/null +++ b/src/fenrirscreenreader/commands/onInput/80300-scrolllock.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.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 self.env['input']['oldScrollLock'] == self.env['input']['newScrollLock']: + return + if self.env['input']['newScrollLock']: + self.env['runtime']['outputManager'].presentText(_("Scrolllock on"), interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(_("Scrolllock off"), interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/onInput/80500-numlock.py b/src/fenrirscreenreader/commands/onInput/80500-numlock.py new file mode 100644 index 00000000..e49356a0 --- /dev/null +++ b/src/fenrirscreenreader/commands/onInput/80500-numlock.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.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 self.env['input']['oldNumLock'] == self.env['input']['newNumLock']: + return + if self.env['input']['newNumLock']: + self.env['runtime']['outputManager'].presentText(_("Numlock on"), interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(_("Numlock off"), interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/onInput/__init__.py b/src/fenrirscreenreader/commands/onInput/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/fenrirscreenreader/commands/onPlugInputDevice/50000-UpdateDevices.py b/src/fenrirscreenreader/commands/onPlugInputDevice/50000-UpdateDevices.py new file mode 100755 index 00000000..fa2d364a --- /dev/null +++ b/src/fenrirscreenreader/commands/onPlugInputDevice/50000-UpdateDevices.py @@ -0,0 +1,21 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.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): + self.env['runtime']['inputManager'].updateInputDevices() + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/onPlugInputDevice/__init__.py b/src/fenrirscreenreader/commands/onPlugInputDevice/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/src/fenrirscreenreader/commands/onScreenChanged/10000-shut_up.py b/src/fenrirscreenreader/commands/onScreenChanged/10000-shut_up.py new file mode 100644 index 00000000..c35f154d --- /dev/null +++ b/src/fenrirscreenreader/commands/onScreenChanged/10000-shut_up.py @@ -0,0 +1,23 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.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): + self.env['runtime']['outputManager'].interruptOutput() + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/onScreenChanged/80000-screen_change_announcement.py b/src/fenrirscreenreader/commands/onScreenChanged/80000-screen_change_announcement.py new file mode 100644 index 00000000..334a87ee --- /dev/null +++ b/src/fenrirscreenreader/commands/onScreenChanged/80000-screen_change_announcement.py @@ -0,0 +1,25 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.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): + self.env['runtime']['outputManager'].presentText(_("screen {0}").format(self.env['screen']['newTTY']),soundIcon='ChangeTTY', interrupt=True, flush=False) + self.env['runtime']['outputManager'].presentText(self.env['screen']['newContentText'], interrupt=False, flush=False) + + def setCallback(self, callback): + pass + diff --git a/src/fenrirscreenreader/commands/onScreenChanged/85000-reset_marks.py b/src/fenrirscreenreader/commands/onScreenChanged/85000-reset_marks.py new file mode 100644 index 00000000..8a3265ad --- /dev/null +++ b/src/fenrirscreenreader/commands/onScreenChanged/85000-reset_marks.py @@ -0,0 +1,24 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.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): + self.env['runtime']['cursorManager'].clearMarks() + + def setCallback(self, callback): + pass + diff --git a/src/fenrirscreenreader/commands/onScreenChanged/89000-leave_review_mode.py b/src/fenrirscreenreader/commands/onScreenChanged/89000-leave_review_mode.py new file mode 100644 index 00000000..f13337b7 --- /dev/null +++ b/src/fenrirscreenreader/commands/onScreenChanged/89000-leave_review_mode.py @@ -0,0 +1,26 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.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('review', 'leaveReviewOnScreenChange'): + return + self.env['runtime']['cursorManager'].clearReviewCursor() + + def setCallback(self, callback): + pass + diff --git a/src/fenrirscreenreader/commands/onScreenChanged/__init__.py b/src/fenrirscreenreader/commands/onScreenChanged/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/fenrirscreenreader/commands/onScreenUpdate/56000-highlight_tracking.py b/src/fenrirscreenreader/commands/onScreenUpdate/56000-highlight_tracking.py new file mode 100644 index 00000000..48be708b --- /dev/null +++ b/src/fenrirscreenreader/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 fenrirscreenreader.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/fenrirscreenreader/commands/onScreenUpdate/60000-history.py b/src/fenrirscreenreader/commands/onScreenUpdate/60000-history.py new file mode 100644 index 00000000..e6366659 --- /dev/null +++ b/src/fenrirscreenreader/commands/onScreenUpdate/60000-history.py @@ -0,0 +1,57 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.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['screen']['newAttribDelta'] != '': + return + if self.env['runtime']['screenManager'].isScreenChange(): + return + if self.env['runtime']['cursorManager'].isCursorVerticalMove(): + return + if not (self.env['runtime']['inputManager'].getLastDeepestInput() 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 prevLine == currLine: + if self.env['screen']['newDelta'] != '': + return + 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/fenrirscreenreader/commands/onScreenUpdate/70000-incoming.py b/src/fenrirscreenreader/commands/onScreenUpdate/70000-incoming.py new file mode 100644 index 00000000..3a79fbd8 --- /dev/null +++ b/src/fenrirscreenreader/commands/onScreenUpdate/70000-incoming.py @@ -0,0 +1,45 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.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(ignoreSpace=True): + return + # this must be a keyecho or something + #if len(self.env['screen']['newDelta'].strip(' \n\t')) <= 1: + xMove = abs(self.env['screen']['newCursor']['x'] - self.env['screen']['oldCursor']['x']) + yMove = abs(self.env['screen']['newCursor']['y'] - self.env['screen']['oldCursor']['y']) + self.env['runtime']['debug'].writeDebugOut('newX:' + str(self.env['screen']['newCursor']['x']) + 'oldX:' + str(self.env['screen']['oldCursor']['x']),debug.debugLevel.INFO) + self.env['runtime']['debug'].writeDebugOut('newY:' + str(self.env['screen']['newCursor']['y']) + 'oldY:' + str(self.env['screen']['oldCursor']['y']),debug.debugLevel.INFO) + self.env['runtime']['debug'].writeDebugOut('xMove:'+ str(xMove)+' yMove:'+str(yMove),debug.debugLevel.INFO) + self.env['runtime']['debug'].writeDebugOut('NewDeltaLen:'+str(len(self.env['screen']['newDelta'])),debug.debugLevel.INFO) + self.env['runtime']['debug'].writeDebugOut(str(self.env['screen']),debug.debugLevel.INFO) + + if (xMove >= 1) and xMove == len(self.env['screen']['newDelta']): + # if len(self.env['screen']['newDelta'].strip(' \n\t0123456789')) <= 2: + return + #if yMove == 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/fenrirscreenreader/commands/onScreenUpdate/75000-incoming_promote.py b/src/fenrirscreenreader/commands/onScreenUpdate/75000-incoming_promote.py new file mode 100644 index 00000000..ed3027d9 --- /dev/null +++ b/src/fenrirscreenreader/commands/onScreenUpdate/75000-incoming_promote.py @@ -0,0 +1,37 @@ +#!/bin/python +import time +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.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 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/fenrirscreenreader/commands/onScreenUpdate/__init__.py b/src/fenrirscreenreader/commands/onScreenUpdate/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/src/fenrirscreenreader/commands/onSwitchApplicationProfile/__init__.py b/src/fenrirscreenreader/commands/onSwitchApplicationProfile/__init__.py new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/src/fenrirscreenreader/commands/onSwitchApplicationProfile/__init__.py @@ -0,0 +1 @@ + diff --git a/src/fenrirscreenreader/commands/onSwitchApplicationProfile/default.py b/src/fenrirscreenreader/commands/onSwitchApplicationProfile/default.py new file mode 100644 index 00000000..2c088db4 --- /dev/null +++ b/src/fenrirscreenreader/commands/onSwitchApplicationProfile/default.py @@ -0,0 +1,33 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.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 load(self): + return + print('--------------') + print('default') + print('load new',self.env['screen']['newApplication']) + print('--------------') + + def unload(self): + return + print('--------------') + print('default') + print('unload old',self.env['screen']['oldApplication']) + print('--------------') + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/onSwitchApplicationProfile/inactive/agetty.py b/src/fenrirscreenreader/commands/onSwitchApplicationProfile/inactive/agetty.py new file mode 100644 index 00000000..92e0c45e --- /dev/null +++ b/src/fenrirscreenreader/commands/onSwitchApplicationProfile/inactive/agetty.py @@ -0,0 +1,31 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'No description found' + def load(self): + print('--------------') + print('agetty') + print('load new',self.env['screen']['newApplication']) + print('--------------') + + def unload(self): + print('--------------') + print('agetty') + print('unload old',self.env['screen']['oldApplication']) + print('--------------') + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/onSwitchApplicationProfile/inactive/bash.py b/src/fenrirscreenreader/commands/onSwitchApplicationProfile/inactive/bash.py new file mode 100644 index 00000000..2089274f --- /dev/null +++ b/src/fenrirscreenreader/commands/onSwitchApplicationProfile/inactive/bash.py @@ -0,0 +1,31 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'No description found' + def load(self): + print('--------------') + print('bash') + print('load new',self.env['screen']['newApplication']) + print('--------------') + + def unload(self): + print('--------------') + print('bash') + print('unload old',self.env['screen']['oldApplication']) + print('--------------') + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/onSwitchApplicationProfile/inactive/vim.py b/src/fenrirscreenreader/commands/onSwitchApplicationProfile/inactive/vim.py new file mode 100644 index 00000000..e743a1af --- /dev/null +++ b/src/fenrirscreenreader/commands/onSwitchApplicationProfile/inactive/vim.py @@ -0,0 +1,31 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'No description found' + def load(self): + print('--------------') + print('vim') + print('load new',self.env['screen']['newApplication']) + print('--------------') + + def unload(self): + print('--------------') + print('vim') + print('unload old',self.env['screen']['oldApplication']) + print('--------------') + + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/commands/switchTrigger_template.py b/src/fenrirscreenreader/commands/switchTrigger_template.py new file mode 100644 index 00000000..a12ea75d --- /dev/null +++ b/src/fenrirscreenreader/commands/switchTrigger_template.py @@ -0,0 +1,23 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.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 unload(self): + pass + def load(self): + pass + def setCallback(self, callback): + pass diff --git a/src/fenrirscreenreader/core/__init__.py b/src/fenrirscreenreader/core/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/fenrirscreenreader/core/applicationManager.py b/src/fenrirscreenreader/core/applicationManager.py new file mode 100644 index 00000000..bd91fb27 --- /dev/null +++ b/src/fenrirscreenreader/core/applicationManager.py @@ -0,0 +1,31 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class applicationManager(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getCurrentApplication(self): + currApp = self.env['screen']['newApplication'].upper() + if not currApp: + currApp == 'DEFAULT' + if currApp == '': + currApp == 'DEFAULT' + return currApp + def getPrevApplication(self): + prevApp = self.env['screen']['oldApplication'].upper() + if not prevApp: + prevApp == 'DEFAULT' + if prevApp == '': + prevApp == 'DEFAULT' + return prevApp + def isApplicationChange(self): + return self.env['screen']['oldApplication'] != self.env['screen']['newApplication'] diff --git a/src/fenrirscreenreader/core/brailleDriver.py b/src/fenrirscreenreader/core/brailleDriver.py new file mode 100644 index 00000000..f66ef054 --- /dev/null +++ b/src/fenrirscreenreader/core/brailleDriver.py @@ -0,0 +1,41 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class brailleDriver(): + def __init__(self): + self._isInitialized = False + self.deviceSize = None + def initialize(self, environment): + self.env = environment + self._isInitialized = True + + def getDeviceSize(self): + if not self._isInitialized: + return (0,0) + return (0,0) + + def writeText(self,text): + if not self._isInitialized: + return + + def connectDevice(self): + pass + + def enterScreen(self, screen): + if not self._isInitialized: + return + + def leveScreen(self): + if not self._isInitialized: + return + + def shutdown(self): + if not self._isInitialized: + return + self.leveScreen() + self._isInitialized = False diff --git a/src/fenrirscreenreader/core/commandData.py b/src/fenrirscreenreader/core/commandData.py new file mode 100644 index 00000000..56dcfff3 --- /dev/null +++ b/src/fenrirscreenreader/core/commandData.py @@ -0,0 +1,24 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +import time + +# used as shared memory between commands +# use this in your own commands +commandBuffer = { +'enableSpeechOnKeypress': False, +'Marks':{'1':None, '2':None}, +'bookMarks':{}, +'windowArea':{}, +} + +# used by the commandManager +commandInfo = { +#'currCommand': '', +'lastCommandExecutionTime': time.time(), +'lastCommandRequestTime': time.time(), +} diff --git a/src/fenrirscreenreader/core/commandManager.py b/src/fenrirscreenreader/core/commandManager.py new file mode 100644 index 00000000..657a28d3 --- /dev/null +++ b/src/fenrirscreenreader/core/commandManager.py @@ -0,0 +1,223 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +import glob, os, time, inspect +currentdir = os.path.dirname(os.path.realpath(os.path.abspath(inspect.getfile(inspect.currentframe())))) +fenrirPath = os.path.dirname(currentdir) + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import module_utils + +class commandManager(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + # commands + self.env['commands'] = {} + self.env['commandsIgnore'] = {} + for commandFolder in self.env['general']['commandFolderList']: + self.env['runtime']['commandManager'].loadCommands(commandFolder) + if self.env['runtime']['settingsManager'].getSetting('general', 'commandPath') != '': + self.env['runtime']['commandManager'].loadCommands(commandFolder, + self.env['runtime']['settingsManager'].getSetting('general', 'commandPath')) + + # scripts for scriptKey + self.env['runtime']['commandManager'].loadScriptCommands() + + def shutdown(self): + for commandFolder in self.env['general']['commandFolderList']: + self.env['runtime']['commandManager'].shutdownCommands(commandFolder) + + def loadCommands(self, section='commands',commandPath=''): + if commandPath =='': + commandPath = fenrirPath+ "/commands/" + if not commandPath.endswith('/'): + commandPath += '/' + commandFolder = commandPath + section +"/" + if not os.path.exists(commandFolder): + self.env['runtime']['debug'].writeDebugOut("commandFolder not exists:" + commandFolder ,debug.debugLevel.WARNING) + return + if not os.path.isdir(commandFolder): + self.env['runtime']['debug'].writeDebugOut("commandFolder not a directory:" + commandFolder ,debug.debugLevel.ERROR) + return + if not os.access(commandFolder, os.R_OK): + self.env['runtime']['debug'].writeDebugOut("commandFolder not readable:" + commandFolder ,debug.debugLevel.ERROR) + return + self.env['commands'][section] = {} + self.env['commandsIgnore'][section] = {} + commandList = glob.glob(commandFolder+'*') + for command in commandList: + try: + fileName, fileExtension = os.path.splitext(command) + fileName = fileName.split('/')[-1] + if fileName.startswith('__'): + continue + try: + if self.env['commands'][section][fileName.upper()] != None: + continue + except: + pass + if fileExtension.lower() == '.py': + command_mod = module_utils.importModule(fileName, command) + self.env['commands'][section][fileName.upper()] = command_mod.command() + self.env['commandsIgnore'][section][fileName.upper()[fileName.upper().find('-')+1:]+'_IGNORE'] = False + self.env['commands'][section][fileName.upper()].initialize(self.env) + self.env['runtime']['debug'].writeDebugOut("Load command:" + section + "." + fileName.upper() ,debug.debugLevel.INFO, onAnyLevel=True) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("Loading command:" + command ,debug.debugLevel.ERROR) + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + continue + + def loadScriptCommands(self, section='commands', scriptPath=''): + if scriptPath =='': + scriptPath = self.env['runtime']['settingsManager'].getSetting('general', 'scriptPath') + if not scriptPath.endswith('/'): + scriptPath += '/' + if not os.path.exists(scriptPath): + if os.path.exists(fenrirPath +'/../../config/scripts/'): + scriptPath = fenrirPath +'/../../config/scripts/' + else: + self.env['runtime']['debug'].writeDebugOut("scriptpath not exists:" + scriptPath ,debug.debugLevel.WARNING) + return + if not os.path.isdir(scriptPath): + self.env['runtime']['debug'].writeDebugOut("scriptpath not a directory:" + scriptPath ,debug.debugLevel.ERROR) + return + if not os.access(scriptPath, os.R_OK): + self.env['runtime']['debug'].writeDebugOut("scriptpath not readable:" + scriptPath ,debug.debugLevel.ERROR) + return + commandList = glob.glob(scriptPath+'*') + subCommand = fenrirPath + '/commands/commands/subprocess.py' + for command in commandList: + invalid = False + try: + fileName, fileExtension = os.path.splitext(command) + fileName = fileName.split('/')[-1] + if fileName.startswith('__'): + continue + if fileName.upper() in self.env['commands'][section]: + continue + command_mod = module_utils.importModule(fileName ,subCommand) + self.env['commands'][section][fileName.upper()] = command_mod.command() + self.env['commands'][section][fileName.upper()].initialize(self.env,command) + self.env['runtime']['debug'].writeDebugOut("Load script:" + section + "." + fileName.upper() ,debug.debugLevel.INFO, onAnyLevel=True) + commSettings = fileName.upper().split('__-__') + if len(commSettings) == 1: + keys = commSettings[0] + elif len(commSettings) == 2: + keys = commSettings[1] + elif len(commSettings) > 2: + continue + keys = keys.split('__+__') + shortcutKeys = [] + shortcut = [] + for key in keys: + if not self.env['runtime']['settingsManager'].isValidKey(key.upper()): + self.env['runtime']['debug'].writeDebugOut("invalid key : "+ key.upper() + ' command:' +commandName ,debug.debugLevel.WARNING) + invalid = True + break + shortcutKeys.append(key.upper()) + if invalid: + continue + if not 'KEY_SCRIPT' in shortcutKeys: + shortcutKeys.append('KEY_SCRIPT') + shortcut.append(1) + shortcut.append(sorted(shortcutKeys)) + self.env['bindings'][str(shortcut)] = fileName.upper() + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("Loading script:" + command ,debug.debugLevel.ERROR) + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + continue + def shutdownCommands(self, section): + for command in sorted(self.env['commands'][section]): + try: + self.env['commands'][section][command].shutdown() + del self.env['commands'][section][command] + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("Shutdown command:" + section + "." + command ,debug.debugLevel.ERROR) + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + continue + + def executeSwitchTrigger(self, trigger, unLoadScript, loadScript): + if self.env['runtime']['screenManager'].isSuspendingScreen(): + return + #unload + oldScript = unLoadScript + if self.commandExists(oldScript, trigger): + try: + self.env['runtime']['debug'].writeDebugOut("Executing switchtrigger.unload:" + trigger + "." + oldScript ,debug.debugLevel.INFO) + self.env['commands'][trigger][oldScript].unload() + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("Executing trigger:" + trigger + "." + oldScript ,debug.debugLevel.ERROR) + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + #load + newScript = loadScript + if self.commandExists(newScript, trigger): + try: + self.env['runtime']['debug'].writeDebugOut("Executing switchtrigger.load:" + trigger + "." + newScript ,debug.debugLevel.INFO) + self.env['commands'][trigger][newScript].load() + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("Executing trigger:" + trigger + "." + newScript ,debug.debugLevel.ERROR) + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + + def executeDefaultTrigger(self, trigger, force=False): + if not force: + if self.env['runtime']['screenManager'].isSuspendingScreen(): + return + for command in sorted(self.env['commands'][trigger]): + if self.commandExists(command, trigger): + try: + if self.env['commandsIgnore'][trigger][command[command.find('-')+1:]+'_IGNORE']: + self.env['commandsIgnore'][trigger][command[command.find('-')+1:]+'_IGNORE'] = False + self.env['runtime']['debug'].writeDebugOut("Ignore trigger.command:" + trigger + "." + command ,debug.debugLevel.INFO) + else: + self.env['runtime']['debug'].writeDebugOut("Executing trigger.command:" + trigger + "." + command ,debug.debugLevel.INFO) + self.env['commands'][trigger][command].run() + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("Executing trigger:" + trigger + "." + command + str(e) ,debug.debugLevel.ERROR) + + def executeCommand(self, command, section = 'commands'): + if self.env['runtime']['screenManager'].isSuspendingScreen(): + return + if self.commandExists(command, section): + try: + if self.env['runtime']['helpManager'].isTutorialMode() and section != 'help': + self.env['runtime']['debug'].writeDebugOut("Tutorial for command:" + section + "." + command ,debug.debugLevel.INFO) + description = self.getCommandDescription(command, section) + self.env['runtime']['outputManager'].presentText(description, interrupt=True) + else: + self.env['runtime']['debug'].writeDebugOut("Executing command:" + section + "." + command ,debug.debugLevel.INFO) + self.runCommand(command, section) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("Executing command:" + section + "." + command +' ' + str(e),debug.debugLevel.ERROR) + + + def runCommand(self, command, section = 'commands'): + if self.commandExists(command, section): + try: + self.env['runtime']['debug'].writeDebugOut("runCommand command:" + section + "." + command ,debug.debugLevel.INFO) + self.env['commands'][section][command].run() + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("runCommand command:" + section + "." + command +' ' + str(e),debug.debugLevel.ERROR) + self.env['commandInfo']['lastCommandExecutionTime'] = time.time() + + def getCommandDescription(self, command, section = 'commands'): + if self.commandExists(command, section): + try: + return self.env['commands'][section][command].getDescription() + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('commandManager.getCommandDescription:' + str(e),debug.debugLevel.ERROR) + self.env['commandInfo']['lastCommandExecutionTime'] = time.time() + + def commandExists(self, command, section = 'commands'): + return( command in self.env['commands'][section]) + def getShortcutForCommand(self, command): + shortcut = '' + try: + shortcut = list(self.env['bindings'].keys())[list(self.env['bindings'].values()).index(command)] + except: + pass + return shortcut diff --git a/src/fenrirscreenreader/core/cursorManager.py b/src/fenrirscreenreader/core/cursorManager.py new file mode 100644 index 00000000..5d44d458 --- /dev/null +++ b/src/fenrirscreenreader/core/cursorManager.py @@ -0,0 +1,109 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class cursorManager(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def clearMarks(self): + self.env['commandBuffer']['Marks']['1'] = None + self.env['commandBuffer']['Marks']['2'] = None + def isMarkSet(self): + return self.env['commandBuffer']['Marks']['1'] != None + def isSingleMark(self): + return self.env['commandBuffer']['Marks']['1'] != None and \ + self.env['commandBuffer']['Marks']['2'] == None + def isMultibleMark(self): + return self.env['commandBuffer']['Marks']['1'] != None and \ + self.env['commandBuffer']['Marks']['2'] != None + def setMark(self): + currCursor = None + if self.env['screen']['newCursorReview']: + currCursor = self.env['screen']['newCursorReview'].copy() + else: + currCursor = self.env['screen']['newCursor'].copy() + if not self.env['commandBuffer']['Marks']['1']: + self.env['commandBuffer']['Marks']['1'] = currCursor.copy() + return 1 + else: + self.env['commandBuffer']['Marks']['2'] = currCursor.copy() + return 2 + return 0 + def getReviewOrTextCursor(self): + if self.env['screen']['newCursorReview']: + return self.env['screen']['newCursorReview'].copy() + else: + return self.env['screen']['newCursor'].copy() + def clearReviewCursor(self): + if not self.isReviewMode(): + return + self.env['screen']['oldCursorReview'] = None + self.env['screen']['newCursorReview'] = None + + def isCursorHorizontalMove(self): + return self.env['screen']['newCursor']['x'] != self.env['screen']['oldCursor']['x'] + + def isCursorVerticalMove(self): + return self.env['screen']['newCursor']['y'] != self.env['screen']['oldCursor']['y'] + + def isReviewMode(self): + return self.env['screen']['newCursorReview'] != None + + def enterReviewModeCurrTextCursor(self, overwrite=False): + if self.isReviewMode() and not overwrite: + return + self.env['screen']['oldCursorReview'] = self.env['screen']['newCursorReview'] + if not self.env['screen']['newCursorReview']: + self.env['screen']['newCursorReview'] = self.env['screen']['newCursor'].copy() + if self.env['runtime']['settingsManager'].getSettingAsBool('focus', 'highlight') and \ + self.env['screen']['newCursorAttrib'] != None: + if self.env['screen']['newCursorAttrib']['x'] != 0 and \ + self.env['screen']['newCursorAttrib']['y'] != 0: + self.env['screen']['newCursorReview'] = self.env['screen']['newCursorAttrib'].copy() + + def setReviewCursorPosition(self, x, y): + if not self.isReviewMode(): + self.enterReviewModeCurrTextCursor() + self.env['screen']['oldCursorReview'] = self.env['screen']['newCursorReview'] + self.env['screen']['newCursorReview']['x'] = x + self.env['screen']['newCursorReview']['y'] = y + + def isApplicationWindowSet(self): + try: + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + if self.env['commandBuffer']['windowArea'][currApp]['1'] != None: + return True + except: + pass + return False + def setWindowForApplication(self): + if not self.env['commandBuffer']['Marks']['1']: + return False + if not self.env['commandBuffer']['Marks']['2']: + return False + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + self.env['commandBuffer']['windowArea'][currApp] = {} + + if self.env['commandBuffer']['Marks']['1']['x'] * self.env['commandBuffer']['Marks']['1']['y'] <= \ + self.env['commandBuffer']['Marks']['2']['x'] * self.env['commandBuffer']['Marks']['2']['y']: + self.env['commandBuffer']['windowArea'][currApp]['1'] = self.env['commandBuffer']['Marks']['1'].copy() + self.env['commandBuffer']['windowArea'][currApp]['2'] = self.env['commandBuffer']['Marks']['2'].copy() + else: + self.env['commandBuffer']['windowArea'][currApp]['1'] = self.env['commandBuffer']['Marks']['2'].copy() + self.env['commandBuffer']['windowArea'][currApp]['2'] = self.env['commandBuffer']['Marks']['1'].copy() + return True + def clearWindowForApplication(self): + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + try: + del self.env['commandBuffer']['windowArea'][currApp] + except: + return False + return True diff --git a/src/fenrirscreenreader/core/debug.py b/src/fenrirscreenreader/core/debug.py new file mode 100644 index 00000000..72b5a61a --- /dev/null +++ b/src/fenrirscreenreader/core/debug.py @@ -0,0 +1,13 @@ +#!/usr/bin/python + +from enum import Enum + +class debugLevel(Enum): + DEACTIVE = 0 + ERROR = 1 + WARNING = 2 + INFO = 3 + def __int__(self): + return self.value + def __str__(self): + return self.name diff --git a/src/fenrirscreenreader/core/debugManager.py b/src/fenrirscreenreader/core/debugManager.py new file mode 100644 index 00000000..ed148be7 --- /dev/null +++ b/src/fenrirscreenreader/core/debugManager.py @@ -0,0 +1,71 @@ +#!/usr/bin/python +# Debugger module for the Fenrir screen reader. + +from fenrirscreenreader.core import debug +from datetime import datetime + +class debugManager(): + def __init__(self, fileName='/var/log/fenrir.log'): + self._fileName = fileName + self._file = None + self._fileOpened = False + def initialize(self, environment): + self.env = environment + def shutdown(self): + self.closeDebugFile() + def __del__(self): + try: + self.shutdown() + except: + pass + + def openDebugFile(self, fileName = ''): + self._fileOpened = False + if fileName != '': + self._fileName = fileName + if self._fileName != '': + self._file = open(self._fileName,'a') + self._fileOpened = True + + def writeDebugOut(self, text, level = debug.debugLevel.DEACTIVE, onAnyLevel=False): + + mode = self.env['runtime']['settingsManager'].getSetting('general','debugMode') + if mode == '': + mode = 'FILE' + mode = mode.upper().split(',') + fileMode = 'FILE' in mode + printMode = 'PRINT' in mode + + if (self.env['runtime']['settingsManager'].getSettingAsInt('general','debugLevel') < int(level)) and \ + not (onAnyLevel and self.env['runtime']['settingsManager'].getSettingAsInt('general','debugLevel') > int(debug.debugLevel.DEACTIVE)) : + if self._fileOpened: + self.closeDebugFile() + return + else: + if not self._fileOpened and fileMode: + self.openDebugFile() + if onAnyLevel: + msg = 'ANY '+ str(level) + ' ' + str(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')) + else: + msg = str(level) +' ' + str(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f') +) + msg += ': ' + text + if printMode: + print(msg) + if fileMode: + self._file.write(msg + '\n') + + def closeDebugFile(self): + if not self._fileOpened: + return False + if self._file != None: + self._file.close() + self._fileOpened = False + return True + + def getDebugFile(self): + return self._fileName + + def setDebugFile(self, fileName): + self.closeDebugFile() + self._fileName = fileName diff --git a/src/fenrirscreenreader/core/environment.py b/src/fenrirscreenreader/core/environment.py new file mode 100644 index 00000000..7b864a28 --- /dev/null +++ b/src/fenrirscreenreader/core/environment.py @@ -0,0 +1,29 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.core.settingsData import settingsData +from fenrirscreenreader.core.runtimeData import runtimeData +from fenrirscreenreader.core.screenData import screenData +from fenrirscreenreader.core.outputData import outputData +from fenrirscreenreader.core.generalData import generalData +from fenrirscreenreader.core import commandData +from fenrirscreenreader.core.inputData import inputData +from fenrirscreenreader.core.punctuationData import punctuationData + +environment = { +'screen': screenData, +'runtime': runtimeData, +'general': generalData, +'settings': settingsData, +'commandInfo': commandData.commandInfo, +'commandBuffer': commandData.commandBuffer, +'input': inputData, +'punctuation': punctuationData, +'output': outputData, +'soundIcons': {}, +'bindings': {}, +} diff --git a/src/fenrirscreenreader/core/eventData.py b/src/fenrirscreenreader/core/eventData.py new file mode 100644 index 00000000..7fb97d96 --- /dev/null +++ b/src/fenrirscreenreader/core/eventData.py @@ -0,0 +1,24 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from enum import Enum + +class fenrirEventType(Enum): + Ignore = 0 + StopMainLoop = 1 + ScreenUpdate = 2 + KeyboardInput = 3 + BrailleInput = 4 + PlugInputDevice = 5 + BrailleFlush = 6 + ScreenChanged = 7 + HeartBeat = 8 # for time based scheduling + ExecuteCommand = 9 + def __int__(self): + return self.value + def __str__(self): + return self.name diff --git a/src/fenrirscreenreader/core/eventManager.py b/src/fenrirscreenreader/core/eventManager.py new file mode 100644 index 00000000..f6b49958 --- /dev/null +++ b/src/fenrirscreenreader/core/eventManager.py @@ -0,0 +1,85 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.core.eventData import fenrirEventType +from queue import Empty +import time +from multiprocessing import Queue +from multiprocessing.sharedctypes import Value +from ctypes import c_bool + +class eventManager(): + def __init__(self): + self.running = Value(c_bool, True) + self._eventQueue = Queue() # multiprocessing.Queue() + self.cleanEventQueue() + def initialize(self, environment): + self.env = environment + def shutdown(self): + self.cleanEventQueue() + + def proceedEventLoop(self): + event = self._eventQueue.get() + st = time.time() + self.eventDispatcher(event) + #print('NET loop ' + str(time.time() - st)) + def eventDispatcher(self, event): + self.env['runtime']['debug'].writeDebugOut('eventManager:eventDispatcher:start: event:' + str(event['Type']) + ' QueueSize:' + str( self._eventQueue.qsize()),debug.debugLevel.INFO) + if not event: + return + if not event['Type']: + return + if event['Type'] == fenrirEventType.Ignore: + return + elif event['Type'] == fenrirEventType.StopMainLoop: + self.handleStopMainLoop(event) + elif event['Type'] == fenrirEventType.ScreenUpdate: + self.env['runtime']['fenrirManager'].handleScreenUpdate(event) + elif event['Type'] == fenrirEventType.KeyboardInput: + self.env['runtime']['fenrirManager'].handleInput(event) + elif event['Type'] == fenrirEventType.BrailleInput: + pass + elif event['Type'] == fenrirEventType.PlugInputDevice: + self.env['runtime']['fenrirManager'].handlePlugInputDevice(event) + pass + elif event['Type'] == fenrirEventType.BrailleFlush: + pass + elif event['Type'] == fenrirEventType.ScreenChanged: + self.env['runtime']['fenrirManager'].handleScreenChange(event) + elif event['Type'] == fenrirEventType.HeartBeat: + self.env['runtime']['fenrirManager'].handleHeartBeat(event) + elif event['Type'] == fenrirEventType.ExecuteCommand: + self.env['runtime']['fenrirManager'].handleExecuteCommand(event) + def isMainEventLoopRunning(self): + return self.running.value == 1 + def startMainEventLoop(self): + self.running.value = 1 + while( self.isMainEventLoopRunning()): + self.proceedEventLoop() + + def handleStopMainLoop(self, event): + self.running.value = 0 + time.sleep(0.1) + def stopMainEventLoop(self): + self._eventQueue.put({"Type":fenrirEventType.StopMainLoop,"Data":None}) + def cleanEventQueue(self): + if self._eventQueue.empty(): + return + try: + while True: + self._eventQueue.get_nowait() + except Empty: + pass + def getEventQueue(self): + return self._eventQueue + def getRunning(self): + return self.running + def putToEventQueue(self,event, data): + if not isinstance(event, fenrirEventType): + return False + self._eventQueue.put({"Type":event,"Data":data}) + return True diff --git a/src/fenrirscreenreader/core/fenrirManager.py b/src/fenrirscreenreader/core/fenrirManager.py new file mode 100644 index 00000000..1b0abc44 --- /dev/null +++ b/src/fenrirscreenreader/core/fenrirManager.py @@ -0,0 +1,185 @@ +#!/bin/env python3 +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +import os, sys, signal, time + +from fenrirscreenreader.core import i18n +from fenrirscreenreader.core import settingsManager +from fenrirscreenreader.core import debug +from fenrirscreenreader.core.eventData import fenrirEventType +import argparse + +class fenrirManager(): + def __init__(self): + self.initialized = False + cliArgs = self.handleArgs() + if not cliArgs: + return + try: + self.environment = settingsManager.settingsManager().initFenrirConfig(cliArgs, self) + if not self.environment: + raise RuntimeError('Cannot Initialize. Maybe the configfile is not available or not parseable') + except RuntimeError: + raise + self.environment['runtime']['outputManager'].presentText(_("Start Fenrir"), soundIcon='ScreenReaderOn', interrupt=True) + signal.signal(signal.SIGINT, self.captureSignal) + signal.signal(signal.SIGTERM, self.captureSignal) + self.initialized = True + self.modifierInput = False + self.singleKeyCommand = False + self.command = '' + def handleArgs(self): + args = None + parser = argparse.ArgumentParser(description="Fenrir Help") + parser.add_argument('-s', '--setting', metavar='SETTING-FILE', default='/etc/fenrir/settings/settings.conf', help='Use a specified settingsfile') + parser.add_argument('-o', '--options', metavar='SECTION#SETTING=VALUE,..', default='', help='Overwrite options in given settings file') + parser.add_argument('-d', '--debug', action='store_true', help='Turns on Debugmode') + parser.add_argument('-p', '--print', action='store_true', help='Print debug messages on screen') + try: + args = parser.parse_args() + except Exception as e: + parser.print_help() + return args + def proceed(self): + if not self.initialized: + return + self.environment['runtime']['eventManager'].startMainEventLoop() + self.shutdown() + def handleInput(self, event): + #startTime = time.time + self.environment['runtime']['debug'].writeDebugOut('DEBUG INPUT fenrirMan:' + str(event),debug.debugLevel.INFO) + if not event['Data']: + event['Data'] = self.environment['runtime']['inputManager'].getInputEvent() + if event['Data']: + event['Data']['EventName'] = self.environment['runtime']['inputManager'].convertEventName(event['Data']['EventName']) + self.environment['runtime']['inputManager'].handleInputEvent(event['Data']) + else: + return + if self.environment['runtime']['inputManager'].noKeyPressed(): + self.environment['runtime']['inputManager'].clearLastDeepInput() + if self.environment['runtime']['screenManager'].isSuspendingScreen(): + self.environment['runtime']['inputManager'].writeEventBuffer() + else: + if self.environment['runtime']['helpManager'].isTutorialMode(): + self.environment['runtime']['inputManager'].clearEventBuffer() + + self.detectCommand() + + if self.modifierInput: + self.environment['runtime']['inputManager'].clearEventBuffer() + if self.singleKeyCommand: + if self.environment['runtime']['inputManager'].noKeyPressed(): + self.environment['runtime']['inputManager'].clearEventBuffer() + else: + self.environment['runtime']['inputManager'].writeEventBuffer() + if self.environment['runtime']['inputManager'].noKeyPressed(): + self.modifierInput = False + self.singleKeyCommand = False + if self.environment['input']['keyForeward'] > 0: + self.environment['input']['keyForeward'] -=1 + self.environment['runtime']['commandManager'].executeDefaultTrigger('onInput') + #print('handleInput:',time.time() - startTime) + def handleExecuteCommand(self, event): + if event['Data'] == '': + return + command = event['Data'] + + if self.environment['runtime']['helpManager'].isTutorialMode(): + if self.environment['runtime']['commandManager'].commandExists( command, 'help'): + self.environment['runtime']['commandManager'].executeCommand( command, 'help') + return + self.environment['runtime']['commandManager'].executeCommand( command, 'commands') + def handleScreenChange(self, event): + self.environment['runtime']['screenManager'].hanldeScreenChange(event['Data']) + ''' + if self.environment['runtime']['applicationManager'].isApplicationChange(): + self.environment['runtime']['commandManager'].executeDefaultTrigger('onApplicationChange') + self.environment['runtime']['commandManager'].executeSwitchTrigger('onSwitchApplicationProfile', \ + self.environment['runtime']['applicationManager'].getPrevApplication(), \ + self.environment['runtime']['applicationManager'].getCurrentApplication()) + ''' + self.environment['runtime']['commandManager'].executeDefaultTrigger('onScreenChanged') + self.environment['runtime']['screenDriver'].getCurrScreen() + def handleScreenUpdate(self, event): + #startTime = time.time() + self.environment['runtime']['screenManager'].handleScreenUpdate(event['Data']) + ''' + if self.environment['runtime']['applicationManager'].isApplicationChange(): + self.environment['runtime']['commandManager'].executeDefaultTrigger('onApplicationChange') + self.environment['runtime']['commandManager'].executeSwitchTrigger('onSwitchApplicationProfile', \ + self.environment['runtime']['applicationManager'].getPrevApplication(), \ + self.environment['runtime']['applicationManager'].getCurrentApplication()) + ''' + # timout for the last keypress + if time.time() - self.environment['runtime']['inputManager'].getLastInputTime() >= 0.3: + self.environment['runtime']['inputManager'].clearLastDeepInput() + # has cursor changed? + if self.environment['runtime']['cursorManager'].isCursorVerticalMove() or \ + self.environment['runtime']['cursorManager'].isCursorHorizontalMove(): + self.environment['runtime']['commandManager'].executeDefaultTrigger('onCursorChange') + self.environment['runtime']['commandManager'].executeDefaultTrigger('onScreenUpdate') + self.environment['runtime']['inputManager'].clearLastDeepInput() + #print('handleScreenUpdate:',time.time() - startTime) + + def handlePlugInputDevice(self, event): + self.environment['runtime']['commandManager'].executeDefaultTrigger('onPlugInputDevice', force=True) + + def handleHeartBeat(self, event): + self.environment['runtime']['commandManager'].executeDefaultTrigger('onHeartBeat',force=True) + #self.environment['runtime']['outputManager'].brailleText(flush=False) + + def detectCommand(self): + if self.environment['input']['keyForeward'] > 0: + return + if self.environment['runtime']['inputManager'].isKeyPress(): + self.modifierInput = self.environment['runtime']['inputManager'].currKeyIsModifier() + else: + if not self.environment['runtime']['inputManager'].noKeyPressed(): + if self.singleKeyCommand: + self.singleKeyCommand = len( self.environment['runtime']['inputManager'].getLastDeepestInput() ) == 1 + # key is already released. we need the old one + if not( self.singleKeyCommand and self.environment['runtime']['inputManager'].noKeyPressed()): + shortcut = self.environment['runtime']['inputManager'].getCurrShortcut() + self.command = self.environment['runtime']['inputManager'].getCommandForShortcut(shortcut) + if not self.modifierInput: + if self.environment['runtime']['inputManager'].isKeyPress(): + if self.command != '': + self.singleKeyCommand = True + + if not (self.singleKeyCommand or self.modifierInput): + return + + # fire event + if self.command != '': + if self.modifierInput: + self.environment['runtime']['eventManager'].putToEventQueue(fenrirEventType.ExecuteCommand, self.command) + self.command = '' + else: + if self.singleKeyCommand: + if self.environment['runtime']['inputManager'].noKeyPressed(): + self.environment['runtime']['eventManager'].putToEventQueue(fenrirEventType.ExecuteCommand, self.command) + self.command = '' + + def shutdownRequest(self): + try: + self.environment['runtime']['eventManager'].stopMainEventLoop() + except: + pass + def captureSignal(self, siginit, frame): + self.shutdownRequest() + + def shutdown(self): + self.environment['runtime']['eventManager'].stopMainEventLoop() + self.environment['runtime']['outputManager'].presentText(_("Quit Fenrir"), soundIcon='ScreenReaderOff', interrupt=True) + self.environment['runtime']['eventManager'].cleanEventQueue() + time.sleep(1) + for currManager in self.environment['general']['managerList']: + if self.environment['runtime'][currManager]: + self.environment['runtime'][currManager].shutdown() + del self.environment['runtime'][currManager] + + self.environment = None + diff --git a/src/fenrirscreenreader/core/generalData.py b/src/fenrirscreenreader/core/generalData.py new file mode 100644 index 00000000..d66d2496 --- /dev/null +++ b/src/fenrirscreenreader/core/generalData.py @@ -0,0 +1,18 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +generalData = { +'args': None, +'tutorialMode': False, +'currUser':'', +'prevUser':'', +'managerList':['processManager', 'punctuationManager', 'cursorManager', 'applicationManager', 'commandManager' + , 'screenManager', 'inputManager','outputManager', 'helpManager', 'memoryManager', 'eventManager', 'debug'], +'commandFolderList':['commands','onInput', 'onCursorChange', 'onScreenUpdate','onScreenChanged','onHeartBeat', 'onPlugInputDevice' + ,'onApplicationChange','onSwitchApplicationProfile','help',], +} diff --git a/src/fenrirscreenreader/core/headLineManager.py b/src/fenrirscreenreader/core/headLineManager.py new file mode 100644 index 00000000..c9a081c5 --- /dev/null +++ b/src/fenrirscreenreader/core/headLineManager.py @@ -0,0 +1,55 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +import re, string + +class headLineManager(): + def __init__(self): + self.regExSingle = re.compile(r'(([^\w\s])\2{5,})') + self.regExDouble = re.compile(r'([^\w\s]{2,}){5,}') + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def replaceHeadLines(self, text): + # fast len check for bigger typing echo + if len(text) < 5: + return text + # more strong check, to not match if not needed: + if len(text.strip(string.ascii_letters+string.digits+string.whitespace)) < 5: + return text + result = '' + newText = '' + lastPos = 0 + for match in self.regExDouble.finditer(text): + span = match.span() + newText += text[lastPos:span[0]] + numberOfChars = len(text[span[0]:span[1]]) + name = text[span[0]:span[1]][:2] + if name[0] == name[1]: + newText += ' ' + str(numberOfChars) + ' ' + self.env['runtime']['punctuationManager'].proceedPunctuation(name[0], True) + ' ' + else: + newText += ' ' + str(int(numberOfChars / 2)) + ' ' + self.env['runtime']['punctuationManager'].proceedPunctuation(name, True) + ' ' + lastPos = span[1] + if lastPos != 0: + newText += ' ' + newText += text[lastPos:] + lastPos = 0 + for match in self.regExSingle.finditer(newText): + span = match.span() + result += text[lastPos:span[0]] + numberOfChars = len(newText[span[0]:span[1]]) + name = newText[span[0]:span[1]][:2] + if name[0] == name[1]: + result += ' ' + str(numberOfChars) + ' ' + self.env['runtime']['punctuationManager'].proceedPunctuation(name[0], True) + ' ' + else: + result += ' ' + str(int(numberOfChars / 2)) + ' ' + self.env['runtime']['punctuationManager'].proceedPunctuation(name, True) + ' ' + lastPos = span[1] + if lastPos != 0: + result += ' ' + result += newText[lastPos:] + return result diff --git a/src/fenrirscreenreader/core/helpManager.py b/src/fenrirscreenreader/core/helpManager.py new file mode 100755 index 00000000..6ec5030c --- /dev/null +++ b/src/fenrirscreenreader/core/helpManager.py @@ -0,0 +1,81 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + + +class helpManager(): + def __init__(self): + self.helpDict = {} + self.tutorialListIndex = None + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def toggleTutorialMode(self): + self.setTutorialMode(not self.env['general']['tutorialMode']) + def setTutorialMode(self, newTutorialMode): + self.env['general']['tutorialMode'] = newTutorialMode + if newTutorialMode: + self.createHelpDict() + self.env['bindings'][str([1, ['KEY_ESC']])] = 'TOGGLE_TUTORIAL_MODE' + self.env['bindings'][str([1, ['KEY_UP']])] = 'PREV_HELP' + self.env['bindings'][str([1, ['KEY_DOWN']])] = 'NEXT_HELP' + self.env['bindings'][str([1, ['KEY_SPACE']])] = 'CURR_HELP' + else: + try: + del(self.env['bindings'][str([1, ['KEY_ESC']])]) + del(self.env['bindings'][str([1, ['KEY_UP']])]) + del(self.env['bindings'][str([1, ['KEY_DOWN']])]) + del(self.env['bindings'][str([1, ['KEY_SPACE']])]) + except: + pass + def isTutorialMode(self): + return self.env['general']['tutorialMode'] + def getCommandHelpText(self, command, section = 'commands'): + commandName = command.lower() + commandName = commandName.split('__-__')[0] + commandName = commandName.replace('_',' ') + commandName = commandName.replace('_',' ') + if command == 'TOGGLE_TUTORIAL_MODE': + commandDescription = _('toggles the tutorial mode') + else: + commandDescription = self.env['runtime']['commandManager'].getCommandDescription( command, section = 'commands') + if commandDescription == '': + commandDescription = 'no Description available' + commandShortcut = self.env['runtime']['commandManager'].getShortcutForCommand( command) + commandShortcut = commandShortcut.replace('KEY_',' ') + commandShortcut = commandShortcut.replace('[','') + commandShortcut = commandShortcut.replace(']','') + commandShortcut = commandShortcut.replace("'",'') + if commandShortcut == '': + commandShortcut = 'unbound' + helptext = commandName + ', Shortcut ' + commandShortcut + ', Description ' + commandDescription + return helptext + def createHelpDict(self, section = 'commands'): + self.helpDict = {} + for command in sorted(self.env['commands'][section].keys()): + self.helpDict[len(self.helpDict)] = self.getCommandHelpText(command, section) + if len(self.helpDict) > 0: + self.tutorialListIndex = 0 + else: + self.tutorialListIndex = None + def getHelpForCurrentIndex(self): + if self.tutorialListIndex == None: + return '' + return self.helpDict[self.tutorialListIndex] + def nextIndex(self): + if self.tutorialListIndex == None: + return + self.tutorialListIndex += 1 + if self.tutorialListIndex >= len(self.helpDict): + self.tutorialListIndex = 0 + def prevIndex(self): + if self.tutorialListIndex == None: + return + self.tutorialListIndex -= 1 + if self.tutorialListIndex < 0: + self.tutorialListIndex = len(self.helpDict) - 1 diff --git a/src/fenrirscreenreader/core/i18n.py b/src/fenrirscreenreader/core/i18n.py new file mode 100644 index 00000000..6f1c3085 --- /dev/null +++ b/src/fenrirscreenreader/core/i18n.py @@ -0,0 +1,11 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +import gettext +import locale + +# the only function we really need to call here is gettext.install. Python3 has simplified this. +gettext.install("fenrir") diff --git a/src/fenrirscreenreader/core/inputData.py b/src/fenrirscreenreader/core/inputData.py new file mode 100644 index 00000000..4eb4fce8 --- /dev/null +++ b/src/fenrirscreenreader/core/inputData.py @@ -0,0 +1,36 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +import time + +inputData = { +'currInput': [], +'prevDeepestInput': [], +'eventBuffer': [], +'shortcutRepeat': 0, +'fenrirKey': [], +'scriptKey': [], +'keyForeward': 0, +'lastInputTime':time.time(), +'oldNumLock': True, +'newNumLock':True, +'oldScrollLock': True, +'newScrollLock':True, +'oldCapsLock':False, +'newCapsLock':False +} + +inputEvent = { +'EventName': '', +'EventValue': '', +'EventSec': 0, +'EventUsec': 0, +'EventState': 0, +} + +keyNames = ['KEY_RESERVED', 'KEY_ESC', 'KEY_1', 'KEY_2', 'KEY_3', 'KEY_4', 'KEY_5', 'KEY_6', 'KEY_7', 'KEY_8', 'KEY_9', 'KEY_0', 'KEY_MINUS', 'KEY_EQUAL', 'KEY_BACKSPACE', 'KEY_TAB', 'KEY_Q', 'KEY_W', 'KEY_E', 'KEY_R', 'KEY_T', 'KEY_Y', 'KEY_U', 'KEY_I', 'KEY_O', 'KEY_P', 'KEY_LEFTBRACE', 'KEY_RIGHTBRACE', 'KEY_ENTER', 'KEY_LEFTCTRL', 'KEY_A', 'KEY_S', 'KEY_D', 'KEY_F', 'KEY_G', 'KEY_H', 'KEY_J', 'KEY_K', 'KEY_L', 'KEY_SEMICOLON', 'KEY_APOSTROPHE', 'KEY_GRAVE', 'KEY_LEFTSHIFT', 'KEY_BACKSLASH', 'KEY_Z', 'KEY_X', 'KEY_C', 'KEY_V', 'KEY_B', 'KEY_N', 'KEY_M', 'KEY_COMMA', 'KEY_DOT', 'KEY_SLASH', 'KEY_RIGHTSHIFT', 'KEY_KPASTERISK', 'KEY_LEFTALT', 'KEY_SPACE', 'KEY_CAPSLOCK', 'KEY_F1', 'KEY_F2', 'KEY_F3', 'KEY_F4', 'KEY_F5', 'KEY_F6', 'KEY_F7', 'KEY_F8', 'KEY_F9', 'KEY_F10', 'KEY_NUMLOCK', 'KEY_SCROLLLOCK', 'KEY_KP7', 'KEY_KP8', 'KEY_KP9', 'KEY_KPMINUS', 'KEY_KP4', 'KEY_KP5', 'KEY_KP6', 'KEY_KPPLUS', 'KEY_KP1', 'KEY_KP2', 'KEY_KP3', 'KEY_KP0', 'KEY_KPDOT', 'KEY_ZENKAKUHANKAKU', 'KEY_102ND', 'KEY_F11', 'KEY_F12', 'KEY_RO', 'KEY_KATAKANA', 'KEY_HIRAGANA', 'KEY_HENKAN', 'KEY_KATAKANAHIRAGANA', 'KEY_MUHENKAN', 'KEY_KPJPCOMMA', 'KEY_KPENTER', 'KEY_RIGHTCTRL', 'KEY_KPSLASH', 'KEY_SYSRQ', 'KEY_RIGHTALT', 'KEY_LINEFEED', 'KEY_HOME', 'KEY_UP', 'KEY_PAGEUP', 'KEY_LEFT', 'KEY_RIGHT', 'KEY_END', 'KEY_DOWN', 'KEY_PAGEDOWN', 'KEY_INSERT', 'KEY_DELETE', 'KEY_MACRO', 'KEY_MIN_INTERESTING', 'KEY_MUTE', 'KEY_VOLUMEDOWN', 'KEY_VOLUMEUP', 'KEY_POWER', 'KEY_KPEQUAL', 'KEY_KPPLUSMINUS', 'KEY_PAUSE', 'KEY_SCALE', 'KEY_KPCOMMA', 'KEY_HANGEUL', 'KEY_HANGUEL', 'KEY_HANJA', 'KEY_YEN', 'KEY_LEFTMETA', 'KEY_RIGHTMETA', 'KEY_COMPOSE', 'KEY_STOP', 'KEY_AGAIN', 'KEY_PROPS', 'KEY_UNDO', 'KEY_FRONT', 'KEY_COPY', 'KEY_OPEN', 'KEY_PASTE', 'KEY_FIND', 'KEY_CUT', 'KEY_HELP', 'KEY_MENU', 'KEY_CALC', 'KEY_SETUP', 'KEY_SLEEP', 'KEY_WAKEUP', 'KEY_FILE', 'KEY_SENDFILE', 'KEY_DELETEFILE', 'KEY_XFER', 'KEY_PROG1', 'KEY_PROG2', 'KEY_WWW', 'KEY_MSDOS', 'KEY_COFFEE', 'KEY_SCREENLOCK', 'KEY_DIRECTION', 'KEY_ROTATE_DISPLAY', 'KEY_CYCLEWINDOWS', 'KEY_MAIL', 'KEY_BOOKMARKS', 'KEY_COMPUTER', 'KEY_BACK', 'KEY_FORWARD', 'KEY_CLOSECD', 'KEY_EJECTCD', 'KEY_EJECTCLOSECD', 'KEY_NEXTSONG', 'KEY_PLAYPAUSE', 'KEY_PREVIOUSSONG', 'KEY_STOPCD', 'KEY_RECORD', 'KEY_REWIND', 'KEY_PHONE', 'KEY_ISO', 'KEY_CONFIG', 'KEY_HOMEPAGE', 'KEY_REFRESH', 'KEY_EXIT', 'KEY_MOVE', 'KEY_EDIT', 'KEY_SCROLLUP', 'KEY_SCROLLDOWN', 'KEY_KPLEFTPAREN', 'KEY_KPRIGHTPAREN', 'KEY_NEW', 'KEY_REDO', 'KEY_F13', 'KEY_F14', 'KEY_F15', 'KEY_F16', 'KEY_F17', 'KEY_F18', 'KEY_F19', 'KEY_F20', 'KEY_F21', 'KEY_F22', 'KEY_F23', 'KEY_F24', 'KEY_PLAYCD', 'KEY_PAUSECD', 'KEY_PROG3', 'KEY_PROG4', 'KEY_DASHBOARD', 'KEY_SUSPEND', 'KEY_CLOSE', 'KEY_PLAY', 'KEY_FASTFORWARD', 'KEY_BASSBOOST', 'KEY_PRINT', 'KEY_HP', 'KEY_CAMERA', 'KEY_SOUND', 'KEY_QUESTION', 'KEY_EMAIL', 'KEY_CHAT', 'KEY_SEARCH', 'KEY_CONNECT', 'KEY_FINANCE', 'KEY_SPORT', 'KEY_SHOP', 'KEY_ALTERASE', 'KEY_CANCEL', 'KEY_BRIGHTNESSDOWN', 'KEY_BRIGHTNESSUP', 'KEY_MEDIA', 'KEY_SWITCHVIDEOMODE', 'KEY_KBDILLUMTOGGLE', 'KEY_KBDILLUMDOWN', 'KEY_KBDILLUMUP', 'KEY_SEND', 'KEY_REPLY', 'KEY_FORWARDMAIL', 'KEY_SAVE', 'KEY_DOCUMENTS', 'KEY_BATTERY', 'KEY_BLUETOOTH', 'KEY_WLAN', 'KEY_UWB', 'KEY_UNKNOWN', 'KEY_VIDEO_NEXT', 'KEY_VIDEO_PREV', 'KEY_BRIGHTNESS_CYCLE', 'KEY_BRIGHTNESS_AUTO', 'KEY_BRIGHTNESS_ZERO', 'KEY_DISPLAY_OFF', 'KEY_WIMAX', 'KEY_WWAN', 'KEY_RFKILL', 'KEY_MICMUTE', 'BTN_0', 'BTN_MISC', 'BTN_1', 'BTN_2', 'BTN_3', 'BTN_4', 'BTN_5', 'BTN_6', 'BTN_7', 'BTN_8', 'BTN_9', 'BTN_LEFT', 'BTN_MOUSE', 'BTN_RIGHT', 'BTN_MIDDLE', 'BTN_SIDE', 'BTN_EXTRA', 'BTN_FORWARD', 'BTN_BACK', 'BTN_TASK', 'BTN_JOYSTICK', 'BTN_TRIGGER', 'BTN_THUMB', 'BTN_THUMB2', 'BTN_TOP', 'BTN_TOP2', 'BTN_PINKIE', 'BTN_BASE', 'BTN_BASE2', 'BTN_BASE3', 'BTN_BASE4', 'BTN_BASE5', 'BTN_BASE6', 'BTN_DEAD', 'BTN_A', 'BTN_GAMEPAD', 'BTN_SOUTH', 'BTN_B', 'BTN_EAST', 'BTN_C', 'BTN_NORTH', 'BTN_X', 'BTN_WEST', 'BTN_Y', 'BTN_Z', 'BTN_TL', 'BTN_TR', 'BTN_TL2', 'BTN_TR2', 'BTN_SELECT', 'BTN_START', 'BTN_MODE', 'BTN_THUMBL', 'BTN_THUMBR', 'BTN_DIGI', 'BTN_TOOL_PEN', 'BTN_TOOL_RUBBER', 'BTN_TOOL_BRUSH', 'BTN_TOOL_PENCIL', 'BTN_TOOL_AIRBRUSH', 'BTN_TOOL_FINGER', 'BTN_TOOL_MOUSE', 'BTN_TOOL_LENS', 'BTN_TOOL_QUINTTAP', 'BTN_TOUCH', 'BTN_STYLUS', 'BTN_STYLUS2', 'BTN_TOOL_DOUBLETAP', 'BTN_TOOL_TRIPLETAP', 'BTN_TOOL_QUADTAP', 'BTN_GEAR_DOWN', 'BTN_WHEEL', 'BTN_GEAR_UP', 'KEY_OK', 'KEY_SELECT', 'KEY_GOTO', 'KEY_CLEAR', 'KEY_POWER2', 'KEY_OPTION', 'KEY_INFO', 'KEY_TIME', 'KEY_VENDOR', 'KEY_ARCHIVE', 'KEY_PROGRAM', 'KEY_CHANNEL', 'KEY_FAVORITES', 'KEY_EPG', 'KEY_PVR', 'KEY_MHP', 'KEY_LANGUAGE', 'KEY_TITLE', 'KEY_SUBTITLE', 'KEY_ANGLE', 'KEY_ZOOM', 'KEY_MODE', 'KEY_KEYBOARD', 'KEY_SCREEN', 'KEY_PC', 'KEY_TV', 'KEY_TV2', 'KEY_VCR', 'KEY_VCR2', 'KEY_SAT', 'KEY_SAT2', 'KEY_CD', 'KEY_TAPE', 'KEY_RADIO', 'KEY_TUNER', 'KEY_PLAYER', 'KEY_TEXT', 'KEY_DVD', 'KEY_AUX', 'KEY_MP3', 'KEY_AUDIO', 'KEY_VIDEO', 'KEY_DIRECTORY', 'KEY_LIST', 'KEY_MEMO', 'KEY_CALENDAR', 'KEY_RED', 'KEY_GREEN', 'KEY_YELLOW', 'KEY_BLUE', 'KEY_CHANNELUP', 'KEY_CHANNELDOWN', 'KEY_FIRST', 'KEY_LAST', 'KEY_AB', 'KEY_NEXT', 'KEY_RESTART', 'KEY_SLOW', 'KEY_SHUFFLE', 'KEY_BREAK', 'KEY_PREVIOUS', 'KEY_DIGITS', 'KEY_TEEN', 'KEY_TWEN', 'KEY_VIDEOPHONE', 'KEY_GAMES', 'KEY_ZOOMIN', 'KEY_ZOOMOUT', 'KEY_ZOOMRESET', 'KEY_WORDPROCESSOR', 'KEY_EDITOR', 'KEY_SPREADSHEET', 'KEY_GRAPHICSEDITOR', 'KEY_PRESENTATION', 'KEY_DATABASE', 'KEY_NEWS', 'KEY_VOICEMAIL', 'KEY_ADDRESSBOOK', 'KEY_MESSENGER', 'KEY_BRIGHTNESS_TOGGLE', 'KEY_DISPLAYTOGGLE', 'KEY_SPELLCHECK', 'KEY_LOGOFF', 'KEY_DOLLAR', 'KEY_EURO', 'KEY_FRAMEBACK', 'KEY_FRAMEFORWARD', 'KEY_CONTEXT_MENU', 'KEY_MEDIA_REPEAT', 'KEY_10CHANNELSUP', 'KEY_10CHANNELSDOWN', 'KEY_IMAGES', 'KEY_DEL_EOL', 'KEY_DEL_EOS', 'KEY_INS_LINE', 'KEY_DEL_LINE', 'KEY_FN', 'KEY_FN_ESC', 'KEY_FN_F1', 'KEY_FN_F2', 'KEY_FN_F3', 'KEY_FN_F4', 'KEY_FN_F5', 'KEY_FN_F6', 'KEY_FN_F7', 'KEY_FN_F8', 'KEY_FN_F9', 'KEY_FN_F10', 'KEY_FN_F11', 'KEY_FN_F12', 'KEY_FN_1', 'KEY_FN_2', 'KEY_FN_D', 'KEY_FN_E', 'KEY_FN_F', 'KEY_FN_S', 'KEY_FN_B', 'KEY_BRL_DOT1', 'KEY_BRL_DOT2', 'KEY_BRL_DOT3', 'KEY_BRL_DOT4', 'KEY_BRL_DOT5', 'KEY_BRL_DOT6', 'KEY_BRL_DOT7', 'KEY_BRL_DOT8', 'KEY_BRL_DOT9', 'KEY_BRL_DOT10', 'KEY_NUMERIC_0', 'KEY_NUMERIC_1', 'KEY_NUMERIC_2', 'KEY_NUMERIC_3', 'KEY_NUMERIC_4', 'KEY_NUMERIC_5', 'KEY_NUMERIC_6', 'KEY_NUMERIC_7', 'KEY_NUMERIC_8', 'KEY_NUMERIC_9', 'KEY_NUMERIC_STAR', 'KEY_NUMERIC_POUND', 'KEY_NUMERIC_A', 'KEY_NUMERIC_B', 'KEY_NUMERIC_C', 'KEY_NUMERIC_D', 'KEY_CAMERA_FOCUS', 'KEY_WPS_BUTTON', 'KEY_TOUCHPAD_TOGGLE', 'KEY_TOUCHPAD_ON', 'KEY_TOUCHPAD_OFF', 'KEY_CAMERA_ZOOMIN', 'KEY_CAMERA_ZOOMOUT', 'KEY_CAMERA_UP', 'KEY_CAMERA_DOWN', 'KEY_CAMERA_LEFT', 'KEY_CAMERA_RIGHT', 'KEY_ATTENDANT_ON', 'KEY_ATTENDANT_OFF', 'KEY_ATTENDANT_TOGGLE', 'KEY_LIGHTS_TOGGLE', 'BTN_DPAD_UP', 'BTN_DPAD_DOWN', 'BTN_DPAD_LEFT', 'BTN_DPAD_RIGHT', 'KEY_ALS_TOGGLE', 'KEY_BUTTONCONFIG', 'KEY_TASKMANAGER', 'KEY_JOURNAL', 'KEY_CONTROLPANEL', 'KEY_APPSELECT', 'KEY_SCREENSAVER', 'KEY_VOICECOMMAND', 'KEY_BRIGHTNESS_MIN', 'KEY_BRIGHTNESS_MAX', 'KEY_KBDINPUTASSIST_PREV', 'KEY_KBDINPUTASSIST_NEXT', 'KEY_KBDINPUTASSIST_PREVGROUP', 'KEY_KBDINPUTASSIST_NEXTGROUP', 'KEY_KBDINPUTASSIST_ACCEPT', 'KEY_KBDINPUTASSIST_CANCEL', 'KEY_RIGHT_UP', 'KEY_RIGHT_DOWN', 'KEY_LEFT_UP', 'KEY_LEFT_DOWN', 'KEY_ROOT_MENU', 'KEY_MEDIA_TOP_MENU', 'KEY_NUMERIC_11', 'KEY_NUMERIC_12', 'KEY_AUDIO_DESC', 'KEY_3D_MODE', 'KEY_NEXT_FAVORITE', 'KEY_STOP_RECORD', 'KEY_PAUSE_RECORD', 'KEY_VOD', 'KEY_UNMUTE', 'KEY_DATA', 'KEY_FASTREVERSE', 'KEY_SLOWREVERSE', 'BTN_TRIGGER_HAPPY', 'BTN_TRIGGER_HAPPY1', 'BTN_TRIGGER_HAPPY2', 'BTN_TRIGGER_HAPPY3', 'BTN_TRIGGER_HAPPY4', 'BTN_TRIGGER_HAPPY5', 'BTN_TRIGGER_HAPPY6', 'BTN_TRIGGER_HAPPY7', 'BTN_TRIGGER_HAPPY8', 'BTN_TRIGGER_HAPPY9', 'BTN_TRIGGER_HAPPY10', 'BTN_TRIGGER_HAPPY11', 'BTN_TRIGGER_HAPPY12', 'BTN_TRIGGER_HAPPY13', 'BTN_TRIGGER_HAPPY14', 'BTN_TRIGGER_HAPPY15', 'BTN_TRIGGER_HAPPY16', 'BTN_TRIGGER_HAPPY17', 'BTN_TRIGGER_HAPPY18', 'BTN_TRIGGER_HAPPY19', 'BTN_TRIGGER_HAPPY20', 'BTN_TRIGGER_HAPPY21', 'BTN_TRIGGER_HAPPY22', 'BTN_TRIGGER_HAPPY23', 'BTN_TRIGGER_HAPPY24', 'BTN_TRIGGER_HAPPY25', 'BTN_TRIGGER_HAPPY26', 'BTN_TRIGGER_HAPPY27', 'BTN_TRIGGER_HAPPY28', 'BTN_TRIGGER_HAPPY29', 'BTN_TRIGGER_HAPPY30', 'BTN_TRIGGER_HAPPY31', 'BTN_TRIGGER_HAPPY32', 'BTN_TRIGGER_HAPPY33', 'BTN_TRIGGER_HAPPY34', 'BTN_TRIGGER_HAPPY35', 'BTN_TRIGGER_HAPPY36', 'BTN_TRIGGER_HAPPY37', 'BTN_TRIGGER_HAPPY38', 'BTN_TRIGGER_HAPPY39', 'BTN_TRIGGER_HAPPY40', 'KEY_FENRIR', 'KEY_SCRIPT', 'KEY_ALT', 'KEY_CTRL', 'KEY_META', 'KEY_SHIFT'] + diff --git a/src/fenrirscreenreader/core/inputDriver.py b/src/fenrirscreenreader/core/inputDriver.py new file mode 100644 index 00000000..15a9e63e --- /dev/null +++ b/src/fenrirscreenreader/core/inputDriver.py @@ -0,0 +1,52 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class inputDriver(): + def __init__(self): + self._initialized = False + def initialize(self, environment): + self.env = environment + self._isInitialized = True + def shutdown(self): + if self._initialized: + self.releaseDevices() + self._isInitialized = False + def getInputEvent(self): + time.sleep(0.05) + return None + def handleInputEvent(self, event): + time.sleep(0.05) + if not self._initialized: + return + def writeEventBuffer(self): + if not self._initialized: + return + def clearEventBuffer(self): + if not self._initialized: + return + del self.env['input']['eventBuffer'][:] + def updateInputDevices(self, force = False, init = False): + if not self._initialized: + return + def getLedState(self, led = 0): + if not self._initialized: + return False + return False + def toggleLedState(self, led = 0): + if not self._initialized: + return None + def grabDevices(self): + if not self._initialized: + return None + def releaseDevices(self): + if not self._initialized: + return None + def __del__(self): + if not self._initialized: + return None + self.releaseDevices() diff --git a/src/fenrirscreenreader/core/inputManager.py b/src/fenrirscreenreader/core/inputManager.py new file mode 100644 index 00000000..d08280d8 --- /dev/null +++ b/src/fenrirscreenreader/core/inputManager.py @@ -0,0 +1,212 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +import time +from fenrirscreenreader.core import debug + +class inputManager(): + def __init__(self): + self.setLedState = True + def initialize(self, environment): + self.env = environment + self.env['runtime']['settingsManager'].loadDriver(\ + self.env['runtime']['settingsManager'].getSetting('keyboard', 'driver'), 'inputDriver') + self.updateInputDevices() + # init LEDs with current state + self.env['input']['newNumLock'] = self.env['runtime']['inputDriver'].getLedState() + self.env['input']['oldNumLock'] = self.env['input']['newNumLock'] + self.env['input']['newCapsLock'] = self.env['runtime']['inputDriver'].getLedState(1) + self.env['input']['oldCapsLock'] = self.env['input']['newCapsLock'] + self.env['input']['newScrollLock'] = self.env['runtime']['inputDriver'].getLedState(2) + self.env['input']['oldScrollLock'] = self.env['input']['newScrollLock'] + self.lastDeepestInput = [] + self.lastInputTime = time.time() + def shutdown(self): + self.removeAllDevices() + self.env['runtime']['settingsManager'].shutdownDriver('inputDriver') + def getInputEvent(self): + return self.env['runtime']['inputDriver'].getInputEvent() + def handleInputEvent(self, eventData): + self.env['runtime']['debug'].writeDebugOut('DEBUG INPUT inputMan:' + str(eventData),debug.debugLevel.INFO) + if not eventData: + return + self.env['input']['prevInput'] = self.env['input']['currInput'].copy() + if eventData['EventState'] == 0: + if eventData['EventName'] in self.env['input']['currInput']: + self.env['input']['currInput'].remove(eventData['EventName']) + if len(self.env['input']['currInput']) > 1: + self.env['input']['currInput'] = sorted(self.env['input']['currInput']) + elif len(self.env['input']['currInput']) == 0: + self.env['input']['shortcutRepeat'] = 1 + self.setLedState = self.handleLedStates(eventData) + self.lastInputTime = time.time() + elif eventData['EventState'] == 1: + if not eventData['EventName'] in self.env['input']['currInput']: + self.env['input']['currInput'].append(eventData['EventName']) + if len(self.env['input']['currInput']) > 1: + self.env['input']['currInput'] = sorted(self.env['input']['currInput']) + if len(self.lastDeepestInput) < len(self.env['input']['currInput']): + self.setLastDeepestInput( self.env['input']['currInput'].copy()) + elif self.lastDeepestInput == self.env['input']['currInput']: + if time.time() - self.lastInputTime <= self.env['runtime']['settingsManager'].getSettingAsFloat('keyboard','doubleTapTimeout'): + self.env['input']['shortcutRepeat'] += 1 + else: + self.env['input']['shortcutRepeat'] = 1 + self.setLedState = self.handleLedStates(eventData) + self.lastInputTime = time.time() + elif eventData['EventState'] == 2: + self.lastInputTime = time.time() + + self.env['input']['oldNumLock'] = self.env['input']['newNumLock'] + self.env['input']['newNumLock'] = self.env['runtime']['inputDriver'].getLedState() + self.env['input']['oldCapsLock'] = self.env['input']['newCapsLock'] + self.env['input']['newCapsLock'] = self.env['runtime']['inputDriver'].getLedState(1) + self.env['input']['oldScrollLock'] = self.env['input']['newScrollLock'] + self.env['input']['newScrollLock'] = self.env['runtime']['inputDriver'].getLedState(2) + self.env['runtime']['debug'].writeDebugOut("currInput " + str(self.env['input']['currInput'] ) ,debug.debugLevel.INFO) + if self.noKeyPressed(): + self.env['input']['prevInput'] = [] + self.setLedState = True + + def handleLedStates(self, mEvent): + if not self.setLedState: + return self.setLedState + if mEvent['EventName'] == 'KEY_NUMLOCK': + if mEvent['EventState'] == 1 and not self.env['input']['newNumLock'] == 1: + self.env['runtime']['inputDriver'].toggleLedState() + return False + if mEvent['EventState'] == 0 and not self.env['input']['newNumLock'] == 0: + self.env['runtime']['inputDriver'].toggleLedState() + return False + if mEvent['EventName'] == 'KEY_CAPSLOCK': + if mEvent['EventState'] == 1 and not self.env['input']['newCapsLock'] == 1: + self.env['runtime']['inputDriver'].toggleLedState(1) + return False + if mEvent['EventState'] == 0 and not self.env['input']['newCapsLock'] == 0: + self.env['runtime']['inputDriver'].toggleLedState(1) + return False + if mEvent['EventName'] == 'KEY_SCROLLLOCK': + if mEvent['EventState'] == 1 and not self.env['input']['newScrollLock'] == 1: + self.env['runtime']['inputDriver'].toggleLedState(2) + return False + if mEvent['EventState'] == 0 and not self.env['input']['newScrollLock'] == 0: + self.env['runtime']['inputDriver'].toggleLedState(2) + return False + return self.setLedState + + def grabAllDevices(self): + if self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'grabDevices'): + self.env['runtime']['inputDriver'].grabAllDevices() + + def updateInputDevices(self): + try: + self.env['runtime']['inputDriver'].updateInputDevices() + except: + pass + + def removeAllDevices(self): + try: + self.env['runtime']['inputDriver'].removeAllDevices() + except: + pass + + def convertEventName(self, eventName): + if not eventName: + return '' + if eventName == '': + return '' + eventName = eventName.upper() + if eventName == 'KEY_LEFTCTRL': + eventName = 'KEY_CTRL' + elif eventName == 'KEY_RIGHTCTRL': + eventName = 'KEY_CTRL' + elif eventName == 'KEY_LEFTSHIFT': + eventName = 'KEY_SHIFT' + elif eventName == 'KEY_RIGHTSHIFT': + eventName = 'KEY_SHIFT' + elif eventName == 'KEY_LEFTALT': + eventName = 'KEY_ALT' + elif eventName == 'KEY_RIGHTALT': + eventName = 'KEY_ALT' + elif eventName == 'KEY_LEFTMETA': + eventName = 'KEY_META' + elif eventName == 'KEY_RIGHTMETA': + eventName = 'KEY_META' + if self.isFenrirKey(eventName): + eventName = 'KEY_FENRIR' + if self.isScriptKey(eventName): + eventName = 'KEY_SCRIPT' + return eventName + + def clearEventBuffer(self): + self.env['runtime']['inputDriver'].clearEventBuffer() + def setLastDeepestInput(self, currentDeepestInput): + self.lastDeepestInput = currentDeepestInput + def clearLastDeepInput(self): + self.lastDeepestInput = [] + def getLastInputTime(self): + return self.lastInputTime + def getLastDeepestInput(self): + return self.lastDeepestInput + def writeEventBuffer(self): + try: + if self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'grabDevices'): + self.env['runtime']['inputDriver'].writeEventBuffer() + self.clearEventBuffer() + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("Error while writeUInput",debug.debugLevel.ERROR) + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + + def noKeyPressed(self): + return self.env['input']['currInput'] == [] + def isKeyPress(self): + return (self.env['input']['prevInput'] == []) and (self.env['input']['currInput'] != []) + def getPrevDeepestShortcut(self): + shortcut = [] + shortcut.append(self.env['input']['shortcutRepeat']) + shortcut.append(self.getLastDeepestInput()) + return str(shortcut) + + def getPrevShortcut(self): + shortcut = [] + shortcut.append(self.env['input']['shortcutRepeat']) + shortcut.append(self.env['input']['prevInput']) + return str(shortcut) + + def getCurrShortcut(self, inputSequence = None): + shortcut = [] + shortcut.append(self.env['input']['shortcutRepeat']) + if inputSequence: + shortcut.append(inputSequence) + else: + shortcut.append(self.env['input']['currInput']) + if len(self.env['input']['prevInput']) < len(self.env['input']['currInput']): + if self.env['input']['shortcutRepeat'] > 1 and not self.shortcutExists(str(shortcut)): + shortcut = [] + self.env['input']['shortcutRepeat'] = 1 + shortcut.append(self.env['input']['shortcutRepeat']) + shortcut.append(self.env['input']['currInput']) + self.env['runtime']['debug'].writeDebugOut("currShortcut " + str(shortcut) ,debug.debugLevel.INFO) + return str(shortcut) + + def currKeyIsModifier(self): + if len(self.getLastDeepestInput()) != 1: + return False + return (self.env['input']['currInput'][0] =='KEY_FENRIR') or (self.env['input']['currInput'][0] == 'KEY_SCRIPT') + + def isFenrirKey(self, eventName): + return eventName in self.env['input']['fenrirKey'] + + def isScriptKey(self, eventName): + return eventName in self.env['input']['scriptKey'] + + def getCommandForShortcut(self, shortcut): + if not self.shortcutExists(shortcut): + return '' + return self.env['bindings'][shortcut] + + def shortcutExists(self, shortcut): + return(shortcut in self.env['bindings']) diff --git a/src/fenrirscreenreader/core/memoryManager.py b/src/fenrirscreenreader/core/memoryManager.py new file mode 100644 index 00000000..50940ead --- /dev/null +++ b/src/fenrirscreenreader/core/memoryManager.py @@ -0,0 +1,123 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +import time +from fenrirscreenreader.core import debug + +class memoryManager(): + def __init__(self): + self.listStorage = {} + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def listStorageValid(self,name, checkIndex = False): + try: + if checkIndex: + index = self.listStorage[name]['index'] + if index == -1: + return self.listStorage[name]['list'] == [] + return self.listStorage[name]['list'][index] != None + else: + return isinstance(self.listStorage[name]['list'],list) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("listStorageValid " + str(e),debug.debugLevel.ERROR) + return False + def addValueToFirstIndex(self, name, value): + if not self.listStorageValid(name): + return + if self.listStorage[name]['maxLength'] == None: + self.listStorage[name]['list'] = [value] + self.listStorage[name]['list'] + else: + self.listStorage[name]['list'] = [value] + self.listStorage[name]['list'][:self.listStorage[name]['maxLength'] -1] + self.listStorage[name]['index'] = 0 + def addIndexList(self, name, maxLength = None, currList = [], currIndex = -1): + if len(currList) != 0 and (currIndex == -1): + currIndex = 0 + self.listStorage[name] = {'list': currList, 'index': currIndex, 'maxLength': maxLength} + def isLastIndex(self, name): + if not self.listStorageValid(name): + return False + return self.listStorage[name]['index'] == len(self.listStorage[name]['list']) - 1 + def isFirstIndex(self, name): + if not self.listStorageValid(name): + return False + return self.listStorage[name]['index'] == 0 + def getNextIndex(self, name): + if not self.listStorageValid(name): + return False + if self.isIndexListEmpty(name): + self.listStorage[name]['index'] = -1 + return False + self.listStorage[name]['index'] += 1 + if self.listStorage[name]['index'] > len(self.listStorage[name]['list']) -1: + self.listStorage[name]['index'] = 0 + return True + def setPrefIndex(self, name): + if not self.listStorageValid(name): + return False + if self.isIndexListEmpty(name): + self.listStorage[name]['index'] = -1 + return False + self.listStorage[name]['index'] -= 1 + if self.listStorage[name]['index'] < 0: + self.listStorage[name]['index'] = len(self.listStorage[name]['list']) -1 + return True + def setFirstIndex(self, name): + if not self.listStorageValid(name): + return False + if self.isIndexListEmpty(name): + self.listStorage[name]['index'] = -1 + return False + self.listStorage[name]['index'] = 0 + return True + def getIndexListLen(self, name): + if not self.listStorageValid(name): + return 0 + if self.isIndexListEmpty(name): + self.listStorage[name]['index'] = -1 + return 0 + return len(self.listStorage[name]) + def setLastIndex(self, name): + if not self.listStorageValid(name): + return False + if self.isIndexListEmpty(name): + self.listStorage[name]['index'] = -1 + return False + self.listStorage[name]['index'] = len(self.listStorage[name]['list']) -1 + return True + def clearCurrentIndexList(self, name): + if not self.listStorageValid(name): + return False + self.listStorage[name]['index'] = [] + self.listStorage[name]['index'] = -1 + def getCurrentIndex(self,name): + if not self.listStorageValid(name): + return False + if self.isIndexListEmpty(name): + self.listStorage[name]['index'] = -1 + return False + try: + return self.listStorage[name]['index'] + except: + retrun -1 + def isIndexListEmpty(self, name): + if not self.listStorageValid(name): + return False + return len(self.listStorage[name]['list']) == 0 + def getIndexListElement(self, name): + if not self.listStorageValid(name): + return None + if self.isIndexListEmpty(name): + self.listStorage[name]['index'] = -1 + return None + currIndex = self.getCurrentIndex(name) + if currIndex == -1: + return None + try: + return self.listStorage[name]['list'][currIndex] + except: + return None diff --git a/src/fenrirscreenreader/core/outputData.py b/src/fenrirscreenreader/core/outputData.py new file mode 100644 index 00000000..bf926f24 --- /dev/null +++ b/src/fenrirscreenreader/core/outputData.py @@ -0,0 +1,15 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +import time +from fenrirscreenreader.core import debug + +outputData = { +'nextFlush': time.time(), +'messageText': '', +'messageOffset': None, +'cursorOffset': None, +} diff --git a/src/fenrirscreenreader/core/outputManager.py b/src/fenrirscreenreader/core/outputManager.py new file mode 100644 index 00000000..2e9e125d --- /dev/null +++ b/src/fenrirscreenreader/core/outputManager.py @@ -0,0 +1,272 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import line_utils +import string, time, re + +class outputManager(): + def __init__(self): + self.lastEcho = '' + def initialize(self, environment): + self.env = environment + self.env['runtime']['settingsManager'].loadDriver(\ + self.env['runtime']['settingsManager'].getSetting('speech', 'driver'), 'speechDriver') + self.env['runtime']['settingsManager'].loadDriver(\ + self.env['runtime']['settingsManager'].getSetting('sound', 'driver'), 'soundDriver') + self.env['runtime']['settingsManager'].loadDriver(\ + self.env['runtime']['settingsManager'].getSetting('braille', 'driver'), 'brailleDriver') + def shutdown(self): + self.env['runtime']['settingsManager'].shutdownDriver('soundDriver') + self.env['runtime']['settingsManager'].shutdownDriver('speechDriver') + self.env['runtime']['settingsManager'].shutdownDriver('brailleDriver') + + def presentText(self, text, interrupt=True, soundIcon = '', ignorePunctuation=False, announceCapital=False, flush=True): + if text == '': + return + self.env['runtime']['debug'].writeDebugOut("presentText:\nsoundIcon:'"+soundIcon+"'\nText:\n" + text ,debug.debugLevel.INFO) + if self.playSoundIcon(soundIcon, interrupt): + self.env['runtime']['debug'].writeDebugOut("soundIcon found" ,debug.debugLevel.INFO) + return + if (len(text) > 1) and (text.strip(string.whitespace) == ''): + return + toAnnounceCapital = announceCapital and text[0].isupper() + if toAnnounceCapital: + if self.playSoundIcon('capital', False): + toAnnounceCapital = False + self.lastEcho = text + self.speakText(text, interrupt, ignorePunctuation,toAnnounceCapital) + if flush: + self.brailleText(text, flush) + def getLastEcho(self): + return self.lastEcho + def speakText(self, text, interrupt=True, ignorePunctuation=False, announceCapital=False): + if not self.env['runtime']['settingsManager'].getSettingAsBool('speech', 'enabled'): + self.env['runtime']['debug'].writeDebugOut("Speech disabled in outputManager.speakText",debug.debugLevel.INFO) + return + if self.env['runtime']['speechDriver'] == None: + self.env['runtime']['debug'].writeDebugOut("No speechDriver in outputManager.speakText",debug.debugLevel.ERROR) + return + if interrupt: + self.interruptOutput() + try: + self.env['runtime']['speechDriver'].setLanguage(self.env['runtime']['settingsManager'].getSetting('speech', 'language')) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("setting speech language in outputManager.speakText",debug.debugLevel.ERROR) + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + + try: + self.env['runtime']['speechDriver'].setVoice(self.env['runtime']['settingsManager'].getSetting('speech', 'voice')) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("Error while setting speech voice in outputManager.speakText",debug.debugLevel.ERROR) + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + + try: + if announceCapital: + self.env['runtime']['speechDriver'].setPitch(self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'capitalPitch')) + else: + self.env['runtime']['speechDriver'].setPitch(self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'pitch')) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("setting speech pitch in outputManager.speakText",debug.debugLevel.ERROR) + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + + try: + self.env['runtime']['speechDriver'].setRate(self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'rate')) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("setting speech rate in outputManager.speakText",debug.debugLevel.ERROR) + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + + try: + self.env['runtime']['speechDriver'].setModule(self.env['runtime']['settingsManager'].getSetting('speech', 'module')) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("setting speech module in outputManager.speakText",debug.debugLevel.ERROR) + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + + try: + self.env['runtime']['speechDriver'].setVolume(self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'volume')) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("setting speech volume in outputManager.speakText ",debug.debugLevel.ERROR) + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + + try: + cleanText = text.replace('\n',' , ') + cleanText = self.env['runtime']['headLineManager'].replaceHeadLines(cleanText) + cleanText = self.env['runtime']['punctuationManager'].proceedPunctuation(cleanText, ignorePunctuation) + cleanText = re.sub(' +$',' ', cleanText) + self.env['runtime']['speechDriver'].speak(cleanText) + self.env['runtime']['debug'].writeDebugOut("Speak: "+ cleanText,debug.debugLevel.INFO) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("\"speak\" in outputManager.speakText ",debug.debugLevel.ERROR) + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + + def brailleText(self, text='', flush=True): + if not self.env['runtime']['settingsManager'].getSettingAsBool('braille', 'enabled'): + return + if self.env['runtime']['brailleDriver'] == None: + return + if flush: + self.env['output']['nextFlush'] = time.time() + self.getFlushTime(text) + self.env['output']['messageOffset'] = {'x':0,'y':0} + self.env['output']['messageText'] = text + displayText = self.getBrailleTextWithOffset(self.env['output']['messageText'], self.env['output']['messageOffset']) + self.env['runtime']['brailleDriver'].writeText('flush '+ displayText) + else: + if self.env['output']['nextFlush'] < time.time(): + if self.env['output']['messageText'] != '': + self.env['output']['messageText'] = '' + if self.env['output']['messageOffset'] != None: + self.env['output']['messageOffset'] = None + cursor = self.getBrailleCursor() + x, y, self.env['output']['brlText'] = \ + line_utils.getCurrentLine(cursor['x'], cursor['y'], self.env['screen']['newContentText']) + displayText = self.getBrailleTextWithOffset(self.env['screen']['newContentText'], self.env['output']['cursorOffset'], cursor) + self.env['runtime']['brailleDriver'].writeText('notflush ' + displayText) + else: + displayText = self.getBrailleTextWithOffset(self.env['output']['messageText'], self.env['output']['messageOffset']) + self.env['runtime']['brailleDriver'].writeText('flush'+displayText) + + def getBrailleCursor(self): + if self.env['runtime']['settingsManager'].getSetting('braille', 'cursorFollowMode').upper() == 'REVIEW': + return self.env['runtime']['cursorManager'].getReviewOrTextCursor() + if self.env['runtime']['settingsManager'].getSetting('braille', 'cursorFollowMode').upper() == 'MANUAL': + return self.env['runtime']['cursorManager'].getReviewOrTextCursor() + if self.env['runtime']['settingsManager'].getSetting('braille', 'cursorFollowMode').upper() == 'LAST': + return self.env['runtime']['cursorManager'].getReviewOrTextCursor() + return self.env['runtime']['cursorManager'].getReviewOrTextCursor() + + def getFixCursorCell(self): + size = self.env['runtime']['brailleDriver'].getDeviceSize()[0] + fixCell = self.env['runtime']['settingsManager'].getSettingAsInt('braille', 'fixCursorOnCell') + if fixCell <= -1: + return size[0] + if fixCell >= size[0]: + return size[0] + return fixCell + def getActiveOffsetAndText(self): + if self.env['output']['messageOffset']: + return self.env['output']['messageOffset'], self.env['output']['messageText'] + if not self.env['output']['cursorOffset']: + return self.getBrailleCursor(), self.env['screen']['newContentText'] + return self.env['output']['cursorOffset'], self.env['screen']['newContentText'] + def getHorizontalPanSize(self): + size = self.env['runtime']['brailleDriver'].getDeviceSize() + if self.env['runtime']['settingsManager'].getSettingAsInt('braille', 'panSizeHorizontal') <= 0: + return size[0] + if self.env['runtime']['settingsManager'].getSettingAsInt('braille', 'panSizeHorizontal') >= size[0]: + return size[0] + return self.env['runtime']['settingsManager'].getSettingAsInt('braille', 'panSizeHorizontal') + def getHorizontalPanLevel(self,offsetChange = 0): + panned = True + panSize = self.getHorizontalPanSize() + offset, text = self.getActiveOffsetAndText() + currline = text.split('\n')[offset['y']] + newOffsetStart = (int(offset['x'] / panSize) + offsetChange) * panSize + if newOffsetStart < 0: + newOffsetStart = 0 + panned = False + if newOffsetStart >= len(text): + newOffsetStart = int((len(text) - panSize - 1) / panSize) + panned = False + return newOffsetStart, panned + def setPanLeft(self): + newPan, panned = self.getHorizontalPanLevel(-1) + if self.env['output']['messageOffset']: + self.env['output']['messageOffset'] = newPan.copy() + else: + self.env['output']['cursorOffset'] = newPan.copy() + return panned + def setPanRight(self): + newPan, panned = self.getHorizontalPanLevel(1) + if self.env['output']['messageOffset']: + self.env['output']['messageOffset'] = newPan.copy() + else: + self.env['output']['cursorOffset'] = newPan.copy() + return panned + def removePanning(self): + if self.env['output']['messageOffset']: + self.env['output']['messageOffset'] = None + else: + self.env['output']['cursorOffset'] = None + def getBrailleTextWithOffset(self, text, offset = None, cursor = None): + if text == '': + return '' + size = self.env['runtime']['brailleDriver'].getDeviceSize() + offsetText = text + + if cursor and not offset: + if self.env['runtime']['settingsManager'].getSetting('braille', 'cursorFollowMode').upper() == 'FIXCELL': + #fix cell + cursorCell = self.getFixCursorCell() + offsetStart = cursor['x'] + if offsetStart < size[0]: + if offsetStart <= cursorCell: + return offsetText[0: size[0]] + + offsetStart -= cursorCell + if offsetStart >= len(offsetText): + offsetStart = len(offsetText) - 1 + else: + # page and fallback + offsetStart = int(cursor['x'] / size[0]) * size[0] + else: + if not offset: + offset = {'x':0,'y':0} + offsetStart = offset['x'] + if offsetStart >= len(offsetText): + offsetStart = len(offsetText) - size[0] + + if offsetStart < 0: + offsetStart = 0 + offsetEnd = offsetStart + size[0] + offsetText = offsetText[offsetStart: offsetEnd] + return offsetText + def interruptOutput(self): + self.env['runtime']['speechDriver'].cancel() + self.env['runtime']['debug'].writeDebugOut("Interrupt speech",debug.debugLevel.INFO) + + def clearFlushTime(self): + self.setFlushTime(0.0) + + def setFlushTime(self,newTime): + self.env['output']['nextFlush'] = newTime + + def getFlushTime(self,text=''): + if self.env['runtime']['settingsManager'].getSettingAsFloat('braille', 'flushTimeout') < 0 or \ + self.env['runtime']['settingsManager'].getSetting('braille', 'flushMode').upper() == 'NONE': + return 999999999999 + if self.env['runtime']['settingsManager'].getSetting('braille', 'flushMode').upper() == 'FIX': + return self.env['runtime']['settingsManager'].getSettingAsFloat('braille', 'flushTimeout') + if self.env['runtime']['settingsManager'].getSetting('braille', 'flushMode').upper() == 'CHAR': + return self.env['runtime']['settingsManager'].getSettingAsFloat('braille', 'flushTimeout') * len(text) + if self.env['runtime']['settingsManager'].getSetting('braille', 'flushMode').upper() == 'WORD': + wordsList = text.split(' ') + return self.env['runtime']['settingsManager'].getSettingAsFloat('braille', 'flushTimeout') * len( list( filter(None, wordsList) ) ) + + def playSoundIcon(self, soundIcon = '', interrupt=True): + if soundIcon == '': + return False + soundIcon = soundIcon.upper() + if not self.env['runtime']['settingsManager'].getSettingAsBool('sound', 'enabled'): + self.env['runtime']['debug'].writeDebugOut("Sound disabled in outputManager.speakText",debug.debugLevel.INFO) + return False + + if self.env['runtime']['soundDriver'] == None: + self.env['runtime']['debug'].writeDebugOut("No speechDriver in outputManager.speakText",debug.debugLevel.ERROR) + return False + try: + self.env['runtime']['soundDriver'].setVolume(self.env['runtime']['settingsManager'].getSettingAsFloat('sound', 'volume')) + self.env['runtime']['soundDriver'].playSoundFile(self.env['soundIcons'][soundIcon], interrupt) + return True + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("\"playSoundIcon\" in outputManager.speakText ",debug.debugLevel.ERROR) + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + return False + def announceActiveCursor(self, interrupt_p=False): + if self.env['runtime']['cursorManager'].isReviewMode(): + self.presentText(' review cursor ', interrupt=interrupt_p) + else: + self.presentText(' text cursor ', interrupt=interrupt_p) + diff --git a/src/fenrirscreenreader/core/processManager.py b/src/fenrirscreenreader/core/processManager.py new file mode 100644 index 00000000..4617cdcb --- /dev/null +++ b/src/fenrirscreenreader/core/processManager.py @@ -0,0 +1,87 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.core.eventData import fenrirEventType +import time +from threading import Thread +from multiprocessing import Process + +class processManager(): + def __init__(self): + self._Processes = [] + self._Threads = [] + def initialize(self, environment): + self.env = environment + self.running = self.env['runtime']['eventManager'].getRunning() + self.addSimpleEventThread(fenrirEventType.HeartBeat, self.heartBeatTimer, multiprocess=True) + def shutdown(self): + self.terminateAllProcesses() + + def terminateAllProcesses(self): + for proc in self._Processes: + try: + proc.terminate() + except Exception as e: + print(e) + def heartBeatTimer(self, active): + try: + time.sleep(0.5) + except: + pass + return time.time() + def addCustomEventThread(self, function, pargs = None, multiprocess = False, runOnce = False): + eventQueue = self.env['runtime']['eventManager'].getEventQueue() + if multiprocess: + t = Process(target=self.customEventWorkerThread, args=(eventQueue, function, pargs, runOnce)) + self._Processes.append(t) + else:# thread not implemented yet + t = Thread(target=self.customEventWorkerThread, args=(eventQueue, function, pargs, runOnce)) + self._Threads.append(t) + t.start() + + def addSimpleEventThread(self, event, function, pargs = None, multiprocess = False, runOnce = False): + if multiprocess: + t = Process(target=self.simpleEventWorkerThread, args=(event, function, pargs, runOnce)) + self._Processes.append(t) + else: + t = Thread(target=self.simpleEventWorkerThread, args=(event, function, pargs, runOnce)) + self._Threads.append(t) + t.start() + + def customEventWorkerThread(self, eventQueue, function, pargs = None, runOnce = False): + #if not isinstance(eventQueue, Queue): + # return + if not callable(function): + return + while self.running.value: + try: + if pargs: + function(self.running, eventQueue, pargs) + else: + function(self.running, eventQueue) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('processManager:customEventWorkerThread:function():' + str(e),debug.debugLevel.ERROR) + if runOnce: + break + + def simpleEventWorkerThread(self, event, function, pargs = None, runOnce = False): + if not isinstance(event, fenrirEventType): + return + if not callable(function): + return + while self.running.value: + Data = None + try: + if pargs: + Data = function(self.running, pargs) + else: + Data = function(self.running) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('processManager:simpleEventWorkerThread:function():' + str(e),debug.debugLevel.ERROR) + self.env['runtime']['eventManager'].putToEventQueue(event, Data) + if runOnce: + break diff --git a/src/fenrirscreenreader/core/punctuationData.py b/src/fenrirscreenreader/core/punctuationData.py new file mode 100644 index 00000000..2d55c951 --- /dev/null +++ b/src/fenrirscreenreader/core/punctuationData.py @@ -0,0 +1,61 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +import string + +punctuationData = { +'LEVELDICT':{ + 'none': '', + 'some': '#-$~+*-/\\@', + 'most': '.,:-$~ +*-/\\@!#%^&*()[]}{<>;', + 'all': string.punctuation + ' ยง', + }, +'PUNCTDICT':{ + ' ':'space', + '&':'and', + "'":"apostrophe", + '@':'at', + '\\':'backslash', + '|':'bar', + '!':'bang', + '^':'carrot', + ':':'colon', + ',':'comma', + '-':'dash', + '$':'dollar', + '.':'dot', + '>':'greater', + '`':'grave', + '#':'hash', + '{':'left brace', + '[':'left bracket', + '(':'left paren', + '<':'less', + '%':'percent', + '+':'plus', + '?':'question', + '"':'quote', + ')':'right paren', + '}':'right brace', + ']':'right bracket', + ';':'semicolon', + '/':'slash', + '*':'star', + '~':'tilde', + '_':'line', + '=':'equals', + }, +'CUSTOMDICT':{ + }, +'EMOTICONDICT':{ + ':)':'smiley', + ';)':'winking face', + 'XD':'loool', + ':@':'angry face', + ':D':'lought' + }, +} diff --git a/src/fenrirscreenreader/core/punctuationManager.py b/src/fenrirscreenreader/core/punctuationManager.py new file mode 100644 index 00000000..90c4d02a --- /dev/null +++ b/src/fenrirscreenreader/core/punctuationManager.py @@ -0,0 +1,83 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +import string +from fenrirscreenreader.core import debug + +class punctuationManager(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + self.allPunctNone = dict.fromkeys(map(ord, string.punctuation +"ยง "), ' ') + # replace with None: + # dot, comma, grave, apostrophe + #for char in [ord('`'),ord("'")]: + # self.allPunctNone[char] = None + # dont restore the following (for announce correct pause) + for char in [ord("'"),ord('.'), ord(','), ord(';'), ord(':'), ord('?'), ord('!'), ord('-')]: + self.allPunctNone[char] = chr(char) + def shutdown(self): + pass + def removeUnused(self, text, currLevel = ''): + # dont translate dot and comma because they create a pause + currAllPunctNone = self.allPunctNone.copy() + for char in currLevel: + try: + del currAllPunctNone[ord(char)] + except: + pass + return text.translate(currAllPunctNone) + + def useCustomDict(self, text, customDict, seperator=''): + resultText = str(text) + if customDict: + for key,item in customDict.items(): + resultText = resultText.replace(str(key),seperator + str(item) + seperator) + return resultText + + def usePunctuationDict(self, text, punctuationDict, punctuation): + resultText = str(text) + + if punctuationDict and punctuation and punctuation != '': + if ' ' in punctuation: + resultText = resultText.replace(' ',' ' + punctuationDict[' '] + ' ') + for key,item in punctuationDict.items(): + if key in punctuation and key not in ' ': + if self.env['runtime']['settingsManager'].getSetting('general', 'respectPunctuationPause') and \ + len(key) == 1 and \ + key in "',.;:?!": + resultText = resultText.replace(str(key),' ' +str(item) + str(key) + ' ') + else: + resultText = resultText.replace(str(key),' ' +str(item) + ' ') + return resultText + + def proceedPunctuation(self, text, ignorePunctuation=False): + resultText = text + resultText = self.useCustomDict(resultText, self.env['punctuation']['CUSTOMDICT']) + if self.env['runtime']['settingsManager'].getSettingAsBool('general', 'emoticons'): + resultText = self.useCustomDict(resultText, self.env['punctuation']['EMOTICONDICT'], ' ') + currPunctLevel = '' + if not ignorePunctuation and self.env['runtime']['settingsManager'].getSetting('general', 'punctuationLevel').lower() in self.env['punctuation']['LEVELDICT']: + currPunctLevel = self.env['punctuation']['LEVELDICT'][self.env['runtime']['settingsManager'].getSetting('general', 'punctuationLevel').lower()] + else: + currPunctLevel = string.punctuation +' ยง' + resultText = self.usePunctuationDict(resultText, self.env['punctuation']['PUNCTDICT'], currPunctLevel) + resultText = self.removeUnused(resultText, currPunctLevel) + return resultText + + def cyclePunctuation(self): + punctList = list(self.env['punctuation']['LEVELDICT'].keys()) + try: + currIndex = punctList.index(self.env['runtime']['settingsManager'].getSetting('general', 'punctuationLevel').lower()) # curr punctuation + except: + return False + currIndex += 1 + if currIndex >= len(punctList): + currIndex = 0 + currLevel = punctList[currIndex] + self.env['runtime']['settingsManager'].setSetting('general', 'punctuationLevel', currLevel.lower()) + return True diff --git a/src/fenrirscreenreader/core/runtimeData.py b/src/fenrirscreenreader/core/runtimeData.py new file mode 100644 index 00000000..e0384619 --- /dev/null +++ b/src/fenrirscreenreader/core/runtimeData.py @@ -0,0 +1,20 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +runtimeData = { +'speechDriver': None, +'screenDriver': None, +'soundDriver': None, +'inputDriver': None, +'brailleDriver': None, +'inputManager': None, +'commandManager': None, +'screenManager': None, +'outputManager': None, +'debug':None, +} diff --git a/src/fenrirscreenreader/core/screenData.py b/src/fenrirscreenreader/core/screenData.py new file mode 100644 index 00000000..a21469ad --- /dev/null +++ b/src/fenrirscreenreader/core/screenData.py @@ -0,0 +1,55 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +import time + +screenData = { +'columns': 0, +'lines': 0, +'oldDelta': '', +'oldAttribDelta': '', +'oldNegativeDelta': '', +'oldCursorReview':None, +'oldCursorAttrib':None, +'oldCursor':{'x':0,'y':0}, +'oldContentBytes': b'', +'oldContentText': '', +'oldContentAttrib': None, +'oldApplication': '', +'oldTTY':None, +'newDelta': '', +'newNegativeDelta': '', +'newAttribDelta': '', +'newCursorReview':None, +'newCursorAttrib':None, +'newCursor':{'x':0,'y':0}, +'newContentBytes': b'', +'newContentText': '', +'newContentAttrib': None, +'newTTY':'0', +'newApplication': '', +'lastScreenUpdate': time.time(), +'autoIgnoreScreens':[], +} +''' +screenData = { +'columns': 0, +'lines': 0, +'textDelta': '', +'negativeDelta': '', +'attribDelta': '', +'reviewCursor':None, #{'x':0,'y':0} +'attribCursor':None, #{'x':0,'y':0} +'textCursor':None, #{'x':0,'y':0} +'content': None, #{'x':0,'y':0} +'Text': '', +'Attrib': None, +'screen': None, +'application': '', +'timestamp': time.time(), +} +''' diff --git a/src/fenrirscreenreader/core/screenDriver.py b/src/fenrirscreenreader/core/screenDriver.py new file mode 100644 index 00000000..e16108a9 --- /dev/null +++ b/src/fenrirscreenreader/core/screenDriver.py @@ -0,0 +1,48 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. +#attrib: +#http://rampex.ihep.su/Linux/linux_howto/html/tutorials/mini/Colour-ls-6.html +#0 = black, 1 = blue, 2 = green, 3 = cyan, 4 = red, 5 = purple, 6 = brown/yellow, 7 = white. +#https://github.com/jwilk/vcsapeek/blob/master/linuxvt.py +#blink = 5 if attr & 1 else 0 +#bold = 1 if attr & 16 else 0 + + +from fenrirscreenreader.core import debug + +class screenDriver(): + def __init__(self): + self._isInitialized = False + self.bgColorNames = {0: _('black'), 1: _('blue'), 2: _('green'), 3: _('cyan'), 4: _('red'), 5: _('Magenta'), 6: _('brown/yellow'), 7: _('white')} + self.fgColorNames = {0: _('Black'), 1: _('Blue'), 2: _('Green'), 3: _('Cyan'), 4: _('Red'), 5: _('Magenta'), 6: _('brown/yellow'), 7: _('Light gray'), 8: _('Dark gray'), 9: _('Light blue'), 10: ('Light green'), 11: _('Light cyan'), 12: _('Light red'), 13: _('Light magenta'), 14: _('Light yellow'), 15: _('White')} + def initialize(self, environment): + self.env = environment + self._isInitialized = True + def shutdown(self): + self._isInitialized = False + def getCurrScreen(self): + pass + def getCurrApplication(self): + pass + def getSessionInformation(self): + pass + def getFenrirBGColor(self, attribute): + return '' + def getFenrirFGColor(self, attribute): + return '' + def getFenrirUnderline(self, attribute): + return '' + def getFenrirBold(self, attribute): + return '' + def getFenrirBlink(self, attribute): + return '' + def getFenrirFont(self, attribute): + return '' + def getFenrirFontSize(self, attribute): + return '' + def update(self, trigger='onUpdate'): + pass + diff --git a/src/fenrirscreenreader/core/screenManager.py b/src/fenrirscreenreader/core/screenManager.py new file mode 100644 index 00000000..8a21c263 --- /dev/null +++ b/src/fenrirscreenreader/core/screenManager.py @@ -0,0 +1,116 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +import time, os + +class screenManager(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + self.env['runtime']['settingsManager'].loadDriver(\ + self.env['runtime']['settingsManager'].getSetting('screen', 'driver'), 'screenDriver') + self.env['runtime']['screenDriver'].getCurrScreen() + self.env['runtime']['screenDriver'].getSessionInformation() + + def shutdown(self): + self.env['runtime']['settingsManager'].shutdownDriver('screenDriver') + def hanldeScreenChange(self, eventData): + self.env['runtime']['screenDriver'].getCurrScreen() + self.env['runtime']['screenDriver'].getSessionInformation() + if self.isScreenChange(): + self.changeBrailleScreen() + if not self.isSuspendingScreen(self.env['screen']['newTTY']): + self.env['runtime']['screenDriver'].update(eventData, 'onScreenChange') + self.env['screen']['lastScreenUpdate'] = time.time() + def handleScreenUpdate(self, eventData): + self.env['screen']['oldApplication'] = self.env['screen']['newApplication'] + if not self.isSuspendingScreen(self.env['screen']['newTTY']): + self.env['runtime']['screenDriver'].update(eventData, 'onScreenUpdate') + #if trigger == 'onUpdate' or self.isScreenChange() \ + # or len(self.env['screen']['newDelta']) > 6: + # self.env['runtime']['screenDriver'].getCurrApplication() + self.env['screen']['lastScreenUpdate'] = time.time() + def formatAttributes(self, attribute, attributeFormatString = None): + if not attributeFormatString: + attributeFormatString = self.env['runtime']['settingsManager'].getSetting('general', 'attributeFormatString') + if not attributeFormatString: + return '' + if attributeFormatString == '': + return '' + attributeFormatString = attributeFormatString.replace('fenrirBGColor', self.env['runtime']['screenDriver'].getFenrirBGColor(attribute)) + attributeFormatString = attributeFormatString.replace('fenrirFGColor', self.env['runtime']['screenDriver'].getFenrirFGColor(attribute)) + attributeFormatString = attributeFormatString.replace('fenrirUnderline', self.env['runtime']['screenDriver'].getFenrirUnderline(attribute)) + attributeFormatString = attributeFormatString.replace('fenrirBold', self.env['runtime']['screenDriver'].getFenrirBold(attribute)) + attributeFormatString = attributeFormatString.replace('fenrirBlink', self.env['runtime']['screenDriver'].getFenrirBlink(attribute)) + attributeFormatString = attributeFormatString.replace('fenrirFontSize', self.env['runtime']['screenDriver'].getFenrirFontSize(attribute)) + attributeFormatString = attributeFormatString.replace('fenrirFont', self.env['runtime']['screenDriver'].getFenrirFont(attribute)) + return attributeFormatString + def isSuspendingScreen(self, screen = None): + if screen == None: + screen = self.env['screen']['newTTY'] + ignoreScreens = [] + fixIgnoreScreens = self.env['runtime']['settingsManager'].getSetting('screen', 'suspendingScreen') + if fixIgnoreScreens != '': + ignoreScreens.extend(fixIgnoreScreens.split(',')) + if self.env['runtime']['settingsManager'].getSettingAsBool('screen', 'autodetectSuspendingScreen'): + ignoreScreens.extend(self.env['screen']['autoIgnoreScreens']) + self.env['runtime']['debug'].writeDebugOut('screenManager:isSuspendingScreen ' + str(ignoreScreens) + ' '+ str(self.env['screen']['newTTY']),debug.debugLevel.INFO) + try: + ignoreFileName = self.env['runtime']['settingsManager'].getSetting('screen', 'suspendingScreenFile') + if ignoreFileName != '': + if os.access(ignoreFileName, os.R_OK): + with open(ignoreFileName) as fp: + ignoreScreens.extend(fp.read().replace('\n','').split(',')) + except: + pass + return (screen in ignoreScreens) + + def isScreenChange(self): + if not self.env['screen']['oldTTY']: + return False + return self.env['screen']['newTTY'] != self.env['screen']['oldTTY'] + def isDelta(self, ignoreSpace=False): + newDelta = self.env['screen']['newDelta'] + if ignoreSpace: + newDelta = newDelta.strip() + return newDelta != '' + def isNegativeDelta(self): + return self.env['screen']['newNegativeDelta'] != '' + def getWindowAreaInText(self, text): + if not self.env['runtime']['cursorManager'].isApplicationWindowSet(): + return text + windowText = '' + windowList = text.split('\n') + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + windowList = windowList[self.env['commandBuffer']['windowArea'][currApp]['1']['y']:self.env['commandBuffer']['windowArea'][currApp]['2']['y'] + 1] + for line in windowList: + windowText += line[self.env['commandBuffer']['windowArea'][currApp]['1']['x']:self.env['commandBuffer']['windowArea'][currApp]['2']['x'] + 1] + '\n' + return windowText + + def injectTextToScreen(self, text, screen = None): + try: + self.env['runtime']['screenDriver'].injectTextToScreen(text, screen) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('screenManager:injectTextToScreen ' + str(e),debug.debugLevel.ERROR) + + def changeBrailleScreen(self): + if not self.env['runtime']['settingsManager'].getSettingAsBool('braille', 'enabled'): + return + if not self.env['runtime']['brailleDriver']: + return + if self.env['screen']['oldTTY']: + if not self.isSuspendingScreen(self.env['screen']['oldTTY']): + try: + self.env['runtime']['brailleDriver'].leveScreen() + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('screenManager:changeBrailleScreen:leveScreen ' + str(e),debug.debugLevel.ERROR) + if not self.isSuspendingScreen(): + try: + self.env['runtime']['brailleDriver'].enterScreen(self.env['screen']['newTTY']) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('screenManager:changeBrailleScreen:enterScreen ' + str(e),debug.debugLevel.ERROR) diff --git a/src/fenrirscreenreader/core/settingsData.py b/src/fenrirscreenreader/core/settingsData.py new file mode 100644 index 00000000..109d38ae --- /dev/null +++ b/src/fenrirscreenreader/core/settingsData.py @@ -0,0 +1,113 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +settingsData = { +'sound': { + 'enabled': True, + 'driver': 'genericDriver', + 'theme': 'default', + 'volume': 1.0, + 'genericPlayFileCommand': 'play -q -v fenrirVolume fenrirSoundFile', + 'genericFrequencyCommand': 'play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence' +}, +'speech':{ + 'enabled': True, + 'driver': 'genericDriver', + 'serverPath': '', + 'rate': 0.75, + 'pitch': 0.5, + 'capitalPitch':0.8, + 'volume': 1.0, + 'module': '', + 'voice': 'en-us', + 'language': '', + 'autoReadIncoming': True, + 'genericSpeechCommand':'espeak -a fenrirVolume -s fenrirRate -p fenrirPitch -v fenrirVoice "fenrirText"', + 'fenrirMinVolume':0, + 'fenrirMaxVolume':200, + 'fenrirMinPitch':0, + 'fenrirMaxPitch':99, + 'fenrirMinRate':80, + 'fenrirMaxRate':450, +}, +'braille':{ + 'enabled': False, + 'driver':'brlapiDriver', + 'layout': 'en', + 'flushMode': 'word', #NONE,FIX,CHAR,WORD + 'flushTimeout': 3, + 'cursorFocusMode':'page', # page,fixCell + 'fixCursorOnCell': -1, + 'cursorFollowMode': 'review', # none, review, last, text + 'panSizeHorizontal': 0 # 0 = display size +}, +'screen':{ + 'driver': 'vcsaDriver', + 'encoding': 'auto', + 'screenUpdateDelay': 0.1, + 'suspendingScreen': '', + 'suspendingScreenFile': '/tmp/fenrirSuspend', + 'autodetectSuspendingScreen': False, +}, +'general':{ + 'debugLevel': debug.debugLevel.DEACTIVE, + 'debugMode': 'FILE', + 'punctuationProfile':'default', + 'punctuationLevel': 'some', + 'respectPunctuationPause':True, + 'newLinePause':True, + 'numberOfClipboards': 10, + 'emoticons': True, + 'fenrirKeys': 'KEY_KP0,KEY_META', + 'scriptKeys': 'KEY_COMPOSE', + 'timeFormat': '%I:%M%P', + 'dateFormat': '%A, %B %d, %Y', + 'autoSpellCheck': False, + 'spellCheckLanguage': 'en_US', + 'scriptPath': '/usr/share/fenrir/scripts', + 'commandPath': '/usr/share/fenrir/commands', + 'attributeFormatString': 'Background fenrirBGColor,Foreground fenrirFGColor,fenrirUnderline,fenrirBold,fenrirBlink, Font fenrirFont,Fontsize fenrirFontSize' +}, +'focus':{ + 'cursor': True, + 'highlight': False, +}, +'review':{ + 'lineBreak': True, + 'endOfScreen': True, + 'leaveReviewOnCursorChange': True, + 'leaveReviewOnScreenChange': True, +}, +'promote':{ + 'enabled': True, + 'inactiveTimeoutSec': 120, + 'list': '', +}, +'time':{ + 'enabled': False, + 'presentTime': True, + 'presentDate': True, + 'delaySec': 0, + 'onMinutes': '00,30', + 'announce': True, + 'interrupt': False, +}, +'keyboard':{ + 'driver': 'evdev', + 'device': 'all', + 'grabDevices': True, + 'ignoreShortcuts': False, + 'keyboardLayout': "desktop", + 'charEcho': False, + 'charDeleteEcho': True, + 'wordEcho': True, + 'interruptOnKeyPress': True, + 'interruptOnKeyPressFilter': '', + 'doubleTapTimeout': 0.2, +} +} diff --git a/src/fenrirscreenreader/core/settingsManager.py b/src/fenrirscreenreader/core/settingsManager.py new file mode 100644 index 00000000..99ae8fb9 --- /dev/null +++ b/src/fenrirscreenreader/core/settingsManager.py @@ -0,0 +1,364 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +import os, inspect +currentdir = os.path.dirname(os.path.realpath(os.path.abspath(inspect.getfile(inspect.currentframe())))) +fenrirPath = os.path.dirname(currentdir) + +from configparser import ConfigParser +from fenrirscreenreader.core import debugManager +from fenrirscreenreader.core import memoryManager +from fenrirscreenreader.core import processManager +from fenrirscreenreader.core import eventManager +from fenrirscreenreader.core import inputManager +from fenrirscreenreader.core import outputManager +from fenrirscreenreader.core import commandManager +from fenrirscreenreader.core import screenManager +from fenrirscreenreader.core import punctuationManager +from fenrirscreenreader.core import cursorManager +from fenrirscreenreader.core import applicationManager +from fenrirscreenreader.core import helpManager +from fenrirscreenreader.core import headLineManager +from fenrirscreenreader.core import tableManager +from fenrirscreenreader.core import environment +from fenrirscreenreader.core import inputData +from fenrirscreenreader.core.settingsData import settingsData +from fenrirscreenreader.core import debug +from fenrirscreenreader.utils import module_utils + +class settingsManager(): + def __init__(self): + self.settings = settingsData + self.settingArgDict = {} + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def loadShortcuts(self, kbConfigPath=fenrirPath + '/../../config/keyboard/desktop.conf'): + kbConfig = open(kbConfigPath,"r") + while(True): + invalid = False + line = kbConfig.readline() + if not line: + break + line = line.replace('\n','') + if line.replace(" ","") == '': + continue + if line.replace(" ","").startswith("#"): + continue + if line.count("=") != 1: + continue + sepLine = line.split('=') + commandName = sepLine[1].upper() + sepLine[0] = sepLine[0].replace(" ","") + sepLine[0] = sepLine[0].replace("'","") + sepLine[0] = sepLine[0].replace('"',"") + keys = sepLine[0].split(',') + shortcutKeys = [] + shortcutRepeat = 1 + shortcut = [] + for key in keys: + try: + shortcutRepeat = int(key) + except: + if not self.isValidKey(key.upper()): + self.env['runtime']['debug'].writeDebugOut("invalid key : "+ key.upper() + ' command:' +commandName ,debug.debugLevel.WARNING) + invalid = True + break + shortcutKeys.append(key.upper()) + if invalid: + continue + shortcut.append(shortcutRepeat) + shortcut.append(sorted(shortcutKeys)) + if len(shortcutKeys) != 1 and not 'KEY_FENRIR' in shortcutKeys: + self.env['runtime']['debug'].writeDebugOut("invalid shortcut (missing KEY_FENRIR): "+ str(shortcut) + ' command:' +commandName ,debug.debugLevel.ERROR) + continue + self.env['runtime']['debug'].writeDebugOut("Shortcut: "+ str(shortcut) + ' command:' +commandName ,debug.debugLevel.INFO, onAnyLevel=True) + self.env['bindings'][str(shortcut)] = commandName + kbConfig.close() + # fix bindings + self.env['bindings'][str([1, ['KEY_F1', 'KEY_FENRIR']])] = 'TOGGLE_TUTORIAL_MODE' + + def loadSoundIcons(self, soundIconPath): + siConfig = open(soundIconPath + '/soundicons.conf',"r") + while(True): + line = siConfig.readline() + if not line: + break + line = line.replace('\n','') + if line.replace(" ","") == '': + continue + if line.replace(" ","").startswith("#"): + continue + if line.count("=") != 1: + continue + Values = line.split('=') + soundIcon = Values[0].upper() + Values[1] = Values[1].replace("'","") + Values[1] = Values[1].replace('"',"") + soundIconFile = '' + if os.path.exists(Values[1]): + soundIconFile = Values[1] + else: + if not soundIconPath.endswith("/"): + soundIconPath += '/' + if os.path.exists(soundIconPath + Values[1]): + soundIconFile = soundIconPath + Values[1] + self.env['soundIcons'][soundIcon] = soundIconFile + self.env['runtime']['debug'].writeDebugOut("SoundIcon: " + soundIcon + '.' + soundIconFile, debug.debugLevel.INFO, onAnyLevel=True) + siConfig.close() + def isValidKey(self, key): + return key in inputData.keyNames + + def loadDicts(self, dictConfigPath=fenrirPath + '/../../config/punctuation/default.conf'): + dictConfig = open(dictConfigPath,"r") + currDictName = '' + while(True): + line = dictConfig.readline() + if not line: + break + line = line.replace('\n','') + if line.replace(" ","") == '': + continue + if line.replace(" ","").startswith("#"): + continue + if line.replace(" ","").upper().startswith("[") and \ + line.replace(" ","").upper().endswith("DICT]"): + currDictName = line[line.find('[') + 1 :line.upper().find('DICT]') + 4].upper() + else: + if currDictName == '': + continue + if not ":===:" in line: + continue + sepLine = line.split(':===:') + if len(sepLine) == 1: + sepLine.append('') + elif len(sepLine) < 1: + continue + elif len(sepLine) > 2: + sepLine[1] = ':===:' + self.env['punctuation'][currDictName][sepLine[0]] = sepLine[1] + self.env['runtime']['debug'].writeDebugOut("Punctuation: " + currDictName + '.' + str(sepLine[0]) + ' :' + sepLine[1] ,debug.debugLevel.INFO, onAnyLevel=True) + dictConfig.close() + + def loadSettings(self, settingConfigPath): + if not os.path.exists(settingConfigPath): + return False + self.env['settings'] = ConfigParser() + self.env['settings'].read(settingConfigPath) + return True + + def setSetting(self, section, setting, value): + self.env['settings'].set(section, setting, value) + + def getSetting(self, section, setting): + value = '' + try: + value = self.settingArgDict[section.lower()][setting.lower()] + return value + except: + pass + try: + value = self.env['settings'].get(section, setting) + except: + value = str(self.settings[section][setting]) + return value + + def getSettingAsInt(self, section, setting): + value = 0 + try: + value = int(self.settingArgDict[section.lower()][setting.lower()]) + return value + except Exception as e: + pass + try: + value = self.env['settings'].getint(section, setting) + except: + value = self.settings[section][setting] + return value + + def getSettingAsFloat(self, section, setting): + value = 0.0 + try: + value = float(self.settingArgDict[section.lower()][setting.lower()]) + return value + except Exception as e: + pass + try: + value = self.env['settings'].getfloat(section, setting) + except: + value = self.settings[section][setting] + return value + + def getSettingAsBool(self, section, setting): + value = False + try: + value = self.settingArgDict[section.lower()][setting.lower()].upper() in ['1','YES','JA','TRUE'] + return value + except Exception as e: + pass + try: + value = self.env['settings'].getboolean(section, setting) + except: + value = self.settings[section][setting] + return value + + def loadDriver(self, driverName, driverType): + try: + if self.env['runtime'][driverType] != None: + self.env['runtime'][driverType].shutdown(self.env) + driver_mod = module_utils.importModule(driverName, + fenrirPath + "/" + driverType + '/' + driverName + '.py') + self.env['runtime'][driverType] = driver_mod.driver() + self.env['runtime'][driverType].initialize(self.env) + self.env['runtime']['debug'].writeDebugOut('Loading Driver ' + driverType + ' (' + driverName +") OK",debug.debugLevel.INFO, onAnyLevel=True) + except Exception as e: + self.env['runtime'][driverType] = None + self.env['runtime']['debug'].writeDebugOut('Loading Driver ' + driverType + ' (' + driverName +") FAILED:"+ str(e), debug.debugLevel.ERROR) + def shutdownDriver(self, driverType): + if self.env['runtime'][driverType] == None: + return + self.env['runtime'][driverType].shutdown() + del self.env['runtime'][driverType] + + def setFenrirKeys(self, keys): + keys = keys.upper() + keyList = keys.split(',') + for key in keyList: + if not key in self.env['input']['fenrirKey']: + self.env['input']['fenrirKey'].append(key) + def setScriptKeys(self, keys): + keys = keys.upper() + keyList = keys.split(',') + for key in keyList: + if not key in self.env['input']['scriptKey']: + self.env['input']['scriptKey'].append(key) + def setOptionArgDict(self, section, option, value): + section = section.lower() + option = option.lower() + try: + e = self.settingArgDict[section] + except KeyError: + self.settingArgDict[section] = {} + self.settingArgDict[section][option] = str(value) + + def parseSettingArgs(self, settingArgs): + for optionElem in settingArgs.split(';'): + if len(optionElem.split('#',1)) != 2: + continue + if len(optionElem.split('#',1)[1].split('=',1)) != 2: + continue + section = str(optionElem.split('#',1)[0]).lower() + option = str(optionElem.split('#',1)[1].split('=',1)[0]).lower() + value = optionElem.split('#',1)[1].split('=',1)[1] + self.setOptionArgDict(section, option, value) + + def initFenrirConfig(self, cliArgs, fenrirManager = None, environment = environment.environment): + settingsRoot = '/etc/fenrir/' + settingsFile = cliArgs.setting + soundRoot = '/usr/share/sounds/fenrir/' + environment['runtime']['debug'] = debugManager.debugManager() + environment['runtime']['debug'].initialize(environment) + # get fenrir settings root + if not os.path.exists(settingsRoot): + if os.path.exists(fenrirPath +'/../../config/'): + settingsRoot = fenrirPath +'/../../config/' + else: + return None + # get settings file + if not os.path.exists(settingsFile): + if os.path.exists(settingsRoot + '/settings/settings.conf'): + settingsFile = settingsRoot + '/settings/settings.conf' + else: + return None + # get sound themes root + if not os.path.exists(soundRoot): + if os.path.exists(fenrirPath + '/../../config/sound/'): + soundRoot = fenrirPath + '/../../config/sound/' + + environment['runtime']['settingsManager'] = self + environment['runtime']['settingsManager'].initialize(environment) + + validConfig = environment['runtime']['settingsManager'].loadSettings(settingsFile) + if not validConfig: + return None + + if cliArgs.options != '': + self.parseSettingArgs(cliArgs.options) + if cliArgs.debug: + self.setOptionArgDict('general', 'debugLevel', 3) + if cliArgs.print: + self.setOptionArgDict('general', 'debugLevel', 3) + self.setOptionArgDict('general', 'debugMode', 'PRINT') + self.setFenrirKeys(self.getSetting('general','fenrirKeys')) + self.setScriptKeys(self.getSetting('general','scriptKeys')) + + if not os.path.exists(self.getSetting('keyboard','keyboardLayout')): + if os.path.exists(settingsRoot + 'keyboard/' + self.getSetting('keyboard','keyboardLayout')): + self.setSetting('keyboard', 'keyboardLayout', settingsRoot + 'keyboard/' + self.getSetting('keyboard','keyboardLayout')) + environment['runtime']['settingsManager'].loadShortcuts(self.getSetting('keyboard','keyboardLayout')) + if os.path.exists(settingsRoot + 'keyboard/' + self.getSetting('keyboard','keyboardLayout') + '.conf'): + self.setSetting('keyboard', 'keyboardLayout', settingsRoot + 'keyboard/' + self.getSetting('keyboard','keyboardLayout') + '.conf') + environment['runtime']['settingsManager'].loadShortcuts(self.getSetting('keyboard','keyboardLayout')) + else: + environment['runtime']['settingsManager'].loadShortcuts(self.getSetting('keyboard','keyboardLayout')) + + if not os.path.exists(self.getSetting('sound','theme') + '/soundicons.conf'): + if os.path.exists(soundRoot + self.getSetting('sound','theme')): + self.setSetting('sound', 'theme', soundRoot + self.getSetting('sound','theme')) + if os.path.exists(self.getSetting('sound','theme') + '/soundicons.conf'): + environment['runtime']['settingsManager'].loadSoundIcons(self.getSetting('sound','theme')) + else: + environment['runtime']['settingsManager'].loadSoundIcons(self.getSetting('sound','theme')) + + if not os.path.exists(self.getSetting('general','punctuationProfile')): + if os.path.exists(settingsRoot + 'punctuation/' + self.getSetting('general','punctuationProfile')): + self.setSetting('general', 'punctuationProfile', settingsRoot + 'punctuation/' + self.getSetting('general','punctuationProfile')) + environment['runtime']['settingsManager'].loadDicts(self.getSetting('general','punctuationProfile')) + if os.path.exists(settingsRoot + 'punctuation/' + self.getSetting('general','punctuationProfile') + '.conf'): + self.setSetting('general', 'punctuationProfile', settingsRoot + 'punctuation/' + self.getSetting('general','punctuationProfile') + '.conf') + environment['runtime']['settingsManager'].loadDicts(self.getSetting('general','punctuationProfile')) + else: + environment['runtime']['settingsManager'].loadDicts(self.getSetting('general','punctuationProfile')) + + if fenrirManager: + environment['runtime']['fenrirManager'] = fenrirManager + environment['runtime']['memoryManager'] = memoryManager.memoryManager() + environment['runtime']['memoryManager'].initialize(environment) + environment['runtime']['eventManager'] = eventManager.eventManager() + environment['runtime']['eventManager'].initialize(environment) + environment['runtime']['processManager'] = processManager.processManager() + environment['runtime']['processManager'].initialize(environment) + environment['runtime']['outputManager'] = outputManager.outputManager() + environment['runtime']['outputManager'].initialize(environment) + environment['runtime']['commandManager'] = commandManager.commandManager() + environment['runtime']['commandManager'].initialize(environment) + environment['runtime']['inputManager'] = inputManager.inputManager() + environment['runtime']['inputManager'].initialize(environment) + environment['runtime']['punctuationManager'] = punctuationManager.punctuationManager() + environment['runtime']['punctuationManager'].initialize(environment) + environment['runtime']['cursorManager'] = cursorManager.cursorManager() + environment['runtime']['cursorManager'].initialize(environment) + environment['runtime']['applicationManager'] = applicationManager.applicationManager() + environment['runtime']['applicationManager'].initialize(environment) + environment['runtime']['helpManager'] = helpManager.helpManager() + environment['runtime']['helpManager'].initialize(environment) + environment['runtime']['headLineManager'] = headLineManager.headLineManager() + environment['runtime']['headLineManager'].initialize(environment) + environment['runtime']['tableManager'] = tableManager.tableManager() + environment['runtime']['tableManager'].initialize(environment) + if environment['runtime']['screenManager'] == None: + environment['runtime']['screenManager'] = screenManager.screenManager() + environment['runtime']['screenManager'].initialize(environment) + + environment['runtime']['debug'].writeDebugOut('\/-------environment-------\/',debug.debugLevel.INFO, onAnyLevel=True) + environment['runtime']['debug'].writeDebugOut(str(environment), debug.debugLevel.INFO, onAnyLevel=True) + environment['runtime']['debug'].writeDebugOut('\/-------settings.conf-------\/', debug.debugLevel.INFO, onAnyLevel=True) + environment['runtime']['debug'].writeDebugOut(str(environment['settings']._sections) , debug.debugLevel.INFO, onAnyLevel=True) + environment['runtime']['debug'].writeDebugOut('\/-------self.settingArgDict-------\/',debug.debugLevel.INFO, onAnyLevel=True) + environment['runtime']['debug'].writeDebugOut(str( self.settingArgDict) ,debug.debugLevel.INFO, onAnyLevel=True) + return environment + diff --git a/src/fenrirscreenreader/core/soundDriver.py b/src/fenrirscreenreader/core/soundDriver.py new file mode 100644 index 00000000..1c94ba1d --- /dev/null +++ b/src/fenrirscreenreader/core/soundDriver.py @@ -0,0 +1,47 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class soundDriver(): + def __init__(self): + self.volume = None + self._initialized = False + + def initialize(self, environment): + self.env = environment + self._initialized = True + + def shutdown(self): + if not self._initialized: + return + self.cancel() + self._isInitialized = False + + def playFrequence(self, frequence = 1000, duration = 0.3, adjustVolume = 0): + if not self._initialized: + return + if interrupt: + self.cancel() + + def playSoundFile(self, filePath, interrupt = True): + if not self._initialized: + return + if interrupt: + self.cancel() + + def cancel(self): + if not self._initialized: + return + + def setCallback(self, callback): + if not self._initialized: + return + + def setVolume(self, volume): + if not self._initialized: + return + self.volume = volume diff --git a/src/fenrirscreenreader/core/speechDriver.py b/src/fenrirscreenreader/core/speechDriver.py new file mode 100644 index 00000000..ca4df1d4 --- /dev/null +++ b/src/fenrirscreenreader/core/speechDriver.py @@ -0,0 +1,100 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +class speechDriver(): + def __init__(self): + self._isInitialized = False + self.language = None + self.voice = None + self.module = None + self.pitch = None + self.rate = None + self.volume = None + def initialize(self, environment): + self.env = environment + self._isInitialized = True + + def shutdown(self): + if self._isInitialized: + self.cancel() + self._isInitialized = False + + def speak(self,text, queueable=True): + if not self._isInitialized: + return + if not queueable: + self.cancel() + + def cancel(self): + if not self._isInitialized: + return + + def setCallback(self, callback): + if not self._isInitialized: + return + if not callback: + return + + def clear_buffer(self): + if not self._isInitialized: + return + + def setVoice(self, voice): + if not self._isInitialized: + return + if voice == '': + return + self.voice = voice + + def setPitch(self, pitch): + if not self._isInitialized: + return + if not isinstance(pitch, float): + return + if pitch < 0.0: + retrun + if pitch > 1.0: + return + self.pitch = pitch + def setRate(self, rate): + if not self._isInitialized: + return + if not isinstance(rate, float): + return + if rate < 0.0: + retrun + if rate > 1.0: + return + self.rate = rate + def setModule(self, module): + if not self._isInitialized: + return + if not isinstance(module, str): + return + if module == '': + return + self.module = module + + def setLanguage(self, language): + if not self._isInitialized: + return + if not isinstance(language, str): + return + if language == '': + return + self.language = language + def setVolume(self, volume): + if not self._isInitialized: + return + if not isinstance(volume,float): + return + if volume < 0.0: + retrun + if volume > 1.0: + return + self.volume = volume diff --git a/src/fenrirscreenreader/core/tableManager.py b/src/fenrirscreenreader/core/tableManager.py new file mode 100644 index 00000000..6580ce8b --- /dev/null +++ b/src/fenrirscreenreader/core/tableManager.py @@ -0,0 +1,46 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +import re + +class tableManager(): + def __init__(self): + self.headLine = '' + self.defaultSeparators = ['+',';','|',' '] + self.noOfHeadLineColumns = 0 + self.headColumnSep = '' + self.rowColumnSep = '' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def resetTableMode(self): + self.setHeadLine() + def setHeadColumnSep(self, columnSep = ''): + self.headColumnSep = columnSep + if columnSep == '': + self.noOfHeadLineColumns = 0 + else: + self.counNoOfHeadColumns() + def counNoOfHeadColumns(self): + pass + def searchForHeadColumnSep(self, headLine): + if ' ' in headLine: + return ' ' + return '' + def setRowColumnSep(self, columnSep = ''): + self.rowColumnSep = columnSep + + def setHeadLine(self, headLine = ''): + self.setHeadColumnSep() + self.setRowColumnSep() + if headLine != '': + sep = self.searchForHeadColumnSep(headLine) + if sep != '': + self.headLine = headLine + self.setHeadColumnSep(sep) + diff --git a/src/fenrirscreenreader/fenrirVersion.py b/src/fenrirscreenreader/fenrirVersion.py new file mode 100644 index 00000000..f070cefd --- /dev/null +++ b/src/fenrirscreenreader/fenrirVersion.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +import os, sys +import __main__ + +version = 1.5 +codename = 'gampert' diff --git a/src/fenrirscreenreader/inputDriver/__init__.py b/src/fenrirscreenreader/inputDriver/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/fenrirscreenreader/inputDriver/debugDriver.py b/src/fenrirscreenreader/inputDriver/debugDriver.py new file mode 100644 index 00000000..abea3c66 --- /dev/null +++ b/src/fenrirscreenreader/inputDriver/debugDriver.py @@ -0,0 +1,66 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +import time +from fenrirscreenreader.core import debug +from fenrirscreenreader.core.inputDriver import inputDriver + +class driver(inputDriver): + def __init__(self): + inputDriver.__init__(self) + + def initialize(self, environment): + self.env = environment + self._initialized = True + print('Input Debug Driver: Initialized') + + def shutdown(self): + if self._initialized: + self.releaseDevices() + self._initialized = False + print('Input Debug Driver: Shutdown') + + def getInputEvent(self): + time.sleep(0.05) + if not self._initialized: + return None + print('Input Debug Driver: getInputEvent') + return None + def writeEventBuffer(self): + if not self._initialized: + return + print('Input Debug Driver: writeEventBuffer') + def clearEventBuffer(self): + if not self._initialized: + return + del self.env['input']['eventBuffer'][:] + print('Input Debug Driver: clearEventBuffer') + def updateInputDevices(self, force = False, init = False): + if not self._initialized: + return + print('Input Debug Driver: updateInputDevices') + def getLedState(self, led = 0): + if not self._initialized: + return False + return False + def toggleLedState(self, led = 0): + if not self._initialized: + return + print('Input Debug Driver: toggleLedState') + def grabDevices(self): + if not self._initialized: + return + print('Input Debug Driver: grabDevices') + def releaseDevices(self): + if not self._initialized: + return + print('Input Debug Driver: releaseDevices') + def __del__(self): + if self._initialized: + self.releaseDevices() + print('Input Debug Driver: __del__') + + diff --git a/src/fenrirscreenreader/inputDriver/dummyDriver.py b/src/fenrirscreenreader/inputDriver/dummyDriver.py new file mode 100644 index 00000000..22175126 --- /dev/null +++ b/src/fenrirscreenreader/inputDriver/dummyDriver.py @@ -0,0 +1,13 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +import time +from fenrirscreenreader.core import debug +from fenrirscreenreader.core.inputDriver import inputDriver + +class driver(inputDriver): + def __init__(self): + inputDriver.__init__(self) diff --git a/src/fenrirscreenreader/inputDriver/evdevDriver.py b/src/fenrirscreenreader/inputDriver/evdevDriver.py new file mode 100644 index 00000000..b847a301 --- /dev/null +++ b/src/fenrirscreenreader/inputDriver/evdevDriver.py @@ -0,0 +1,308 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +_evdevAvailable = False +_udevAvailable = False +_evdevAvailableError = '' +_udevAvailableError = '' +try: + import evdev + from evdev import InputDevice, UInput + _evdevAvailable = True + +except Exception as e: + _evdevAvailableError = str(e) + +try: + import pyudev + _udevAvailable = True +except Exception as e: + _udevAvailableError = str(e) + +import time +from select import select +import multiprocessing +from multiprocessing.sharedctypes import Value +from ctypes import c_bool + +from fenrirscreenreader.core.eventData import fenrirEventType +from fenrirscreenreader.core import inputData +from fenrirscreenreader.core import debug +from fenrirscreenreader.core.inputDriver import inputDriver + +class driver(inputDriver): + def __init__(self): + inputDriver.__init__(self) + self._manager = multiprocessing.Manager() + self.iDevices = {} + self.iDevicesFD = self._manager.list() + self.uDevices = {} + self.iDeviceNo = 0 + self.watchDog = Value(c_bool, True) + def initialize(self, environment): + self.env = environment + global _evdevAvailable + global _udevAvailable + self._initialized = _evdevAvailable + if not self._initialized: + global _evdevAvailableError + self.env['runtime']['debug'].writeDebugOut('InputDriver: ' + _evdevAvailableError,debug.debugLevel.ERROR) + return + if _udevAvailable: + self.env['runtime']['processManager'].addCustomEventThread(self.plugInputDeviceWatchdogUdev) + else: + self.env['runtime']['processManager'].addSimpleEventThread(fenrirEventType.PlugInputDevice, self.plugInputDeviceWatchdogTimer) + self.env['runtime']['processManager'].addCustomEventThread(self.inputWatchdog) + def plugInputDeviceWatchdogUdev(self,active , eventQueue): + context = pyudev.Context() + monitor = pyudev.Monitor.from_netlink(context) + monitor.filter_by(subsystem='input') + monitor.start() + while active.value: + devices = monitor.poll(2) + if devices: + while monitor.poll(0.5): + time.sleep(0.2) + eventQueue.put({"Type":fenrirEventType.PlugInputDevice,"Data":None}) + return time.time() + def plugInputDeviceWatchdogTimer(self, active): + time.sleep(2.5) + return time.time() + + def inputWatchdog(self,active , eventQueue): + while active.value: + r, w, x = select(self.iDevices, [], [], 0.5) + for fd in r: + event = None + foreward = False + eventFired = False + try: + event = self.iDevices[fd].read_one() + except: + self.removeDevice(fd) + while(event): + self.env['input']['eventBuffer'].append( [self.iDevices[fd], self.uDevices[fd], event]) + if event.type == evdev.events.EV_KEY: + if event.code != 0: + currMapEvent = self.mapEvent(event) + if not currMapEvent: + foreward = True + if not isinstance(currMapEvent['EventName'], str): + foreward = True + if not foreward or eventFired: + if currMapEvent['EventState'] in [0,1,2]: + eventQueue.put({"Type":fenrirEventType.KeyboardInput,"Data":currMapEvent.copy()}) + eventFired = True + else: + if not event.type in [0,4]: + foreward = True + + event = self.iDevices[fd].read_one() + if foreward and not eventFired: + self.writeEventBuffer() + self.clearEventBuffer() + + def handleInputEvent(self, event): + return + + def writeEventBuffer(self): + if not self._initialized: + return + for iDevice, uDevice, event in self.env['input']['eventBuffer']: + self.writeUInput(uDevice, event) + + def clearEventBuffer(self): + if not self._initialized: + return + del self.env['input']['eventBuffer'][:] + + def writeUInput(self, uDevice, event): + if not self._initialized: + return + uDevice.write_event(event) + uDevice.syn() + time.sleep(0.00001) + + def updateInputDevices(self, force = False, init = False): + if init: + self.removeAllDevices() + deviceFileList = evdev.list_devices() + if not force and False: + if len(deviceFileList) == self.iDeviceNo: + return + mode = self.env['runtime']['settingsManager'].getSetting('keyboard', 'device').upper() + iDevicesFiles = [] + for device in self.iDevices: + iDevicesFiles.append(self.iDevices[device].fn) + if len(iDevicesFiles) == len(deviceFileList): + return + eventType = evdev.events + for deviceFile in deviceFileList: + try: + if deviceFile in iDevicesFiles: + continue + try: + open(deviceFile) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("Not readable Inputdevice : " + deviceFile +' ' + str(e),debug.debugLevel.ERROR) + continue + # 3 pos absolute + # 2 pos relative + # 1 Keys + currDevice = evdev.InputDevice(deviceFile) + if currDevice.name.upper() in ['','SPEAKUP','PY-EVDEV-UINPUT']: + continue + if 'BRLTTY' in currDevice.name.upper(): + continue + cap = currDevice.capabilities() + if mode in ['ALL','NOMICE']: + if eventType.EV_KEY in cap: + if 116 in cap[eventType.EV_KEY] and len(cap[eventType.EV_KEY]) < 10: + self.env['runtime']['debug'].writeDebugOut('Device Skipped (has 116):' + currDevice.name,debug.debugLevel.INFO) + continue + if len(cap[eventType.EV_KEY]) < 30: + self.env['runtime']['debug'].writeDebugOut('Device Skipped (< 30 keys):' + currDevice.name,debug.debugLevel.INFO) + continue + if mode == 'ALL': + self.iDevices[currDevice.fd] = currDevice + self.grabDevice(currDevice.fd) + self.env['runtime']['debug'].writeDebugOut('Device added (ALL):' + self.iDevices[currDevice.fd].name, debug.debugLevel.INFO) + elif mode == 'NOMICE': + if not ((eventType.EV_REL in cap) or (eventType.EV_ABS in cap)): + self.iDevices[currDevice.fd] = currDevice + self.grabDevice(currDevice.fd) + self.env['runtime']['debug'].writeDebugOut('Device added (NOMICE):' + self.iDevices[currDevice.fd].name,debug.debugLevel.INFO) + else: + self.env['runtime']['debug'].writeDebugOut('Device Skipped (NOMICE):' + currDevice.name,debug.debugLevel.INFO) + elif currDevice.name.upper() in mode.split(','): + self.iDevices[currDevice.fd] = currDevice + self.grabDevice(currDevice.fd) + self.env['runtime']['debug'].writeDebugOut('Device added (Name):' + self.iDevices[currDevice.fd].name,debug.debugLevel.INFO) + except Exception as e: + print(e) + self.env['runtime']['debug'].writeDebugOut("Device Skipped (Exception): " + deviceFile +' ' + currDevice.name +' '+ str(e),debug.debugLevel.INFO) + self.iDeviceNo = len(evdev.list_devices()) + self.updateMPiDevicesFD() + + def updateMPiDevicesFD(self): + for fd in self.iDevices: + if not fd in self.iDevicesFD: + self.iDevicesFD.append(fd) + for fd in self.iDevicesFD: + if not fd in self.iDevices: + self.iDevicesFD.remove(fd) + def mapEvent(self, event): + if not self._initialized: + return None + if not event: + return None + mEvent = inputData.inputEvent + try: + mEvent['EventName'] = evdev.ecodes.keys[event.code] + mEvent['EventValue'] = event.code + mEvent['EventSec'] = event.sec + mEvent['EventUsec'] = event.usec + mEvent['EventState'] = event.value + mEvent['EventType'] = event.type + return mEvent + except Exception as e: + return None + + def getLedState(self, led = 0): + if not self.hasIDevices(): + return False + # 0 = Numlock + # 1 = Capslock + # 2 = Rollen + for fd, dev in self.iDevices.items(): + if led in dev.leds(): + return True + return False + def toggleLedState(self, led = 0): + if not self.hasIDevices(): + return False + ledState = self.getLedState(led) + for i in self.iDevices: + # 17 LEDs + if 17 in self.iDevices[i].capabilities(): + if ledState == 1: + self.iDevices[i].set_led(led , 0) + else: + self.iDevices[i].set_led(led , 1) + def grabAllDevices(self): + if not self._initialized: + return + for fd in self.iDevices: + 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: + try: + self.env['runtime']['debug'].writeDebugOut('InputDriver evdev: compat fallback: ' + str(e),debug.debugLevel.WARNING) + dev = self.iDevices[fd] + cap = dev.capabilities() + del cap[0] + self.uDevices[fd] = UInput( + cap, + dev.name, + ) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('InputDriver evdev: init Uinput not possible: ' + str(e),debug.debugLevel.ERROR) + return + try: + self.iDevices[fd].grab() + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('InputDriver evdev: grabing not possible: ' + str(e),debug.debugLevel.ERROR) + + def removeDevice(self,fd): + self.clearEventBuffer() + try: + self.iDevices[fd].ungrab() + except: + pass + try: + self.iDevices[fd].close() + except: + pass + try: + self.uDevices[fd].close() + except: + pass + try: + del(self.iDevices[fd]) + except: + pass + try: + del(self.uDevices[fd]) + except: + pass + self.updateMPiDevicesFD() + + def hasIDevices(self): + if not self._initialized: + return False + if not self.iDevices: + return False + if len(self.iDevices) == 0: + return False + return True + + def removeAllDevices(self): + if not self.hasIDevices(): + return + devices = self.iDevices.copy() + for fd in devices: + self.removeDevice(fd) + self.iDevices.clear() + self.uDevices.clear() + self.iDeviceNo = 0 + + diff --git a/src/fenrirscreenreader/screenDriver/BAKvcsaDriver.py b/src/fenrirscreenreader/screenDriver/BAKvcsaDriver.py new file mode 100644 index 00000000..dfe10737 --- /dev/null +++ b/src/fenrirscreenreader/screenDriver/BAKvcsaDriver.py @@ -0,0 +1,379 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. +#attrib: +#http://rampex.ihep.su/Linux/linux_howto/html/tutorials/mini/Colour-ls-6.html +#0 = black, 1 = blue, 2 = green, 3 = cyan, 4 = red, 5 = purple, 6 = brown/yellow, 7 = white. +#https://github.com/jwilk/vcsapeek/blob/master/linuxvt.py +#blink = 5 if attr & 1 else 0 +#bold = 1 if attr & 16 else 0 + + +import difflib +import re +import subprocess +import glob, os +import termios +import time +import select +import dbus +import fcntl +from array import array +import errno +import sys +from fenrirscreenreader.utils import screen_utils +from fcntl import ioctl +from struct import unpack_from, unpack, pack +from fenrirscreenreader.core import debug +from fenrirscreenreader.core.eventData import fenrirEventType +from fenrirscreenreader.core.screenDriver import screenDriver + +class driver(screenDriver): + def __init__(self): + screenDriver.__init__(self) + self.vcsaDevicePath = '/dev/vcsa' + self.ListSessions = None + self.charmap = {} + self.bgColorNames = {0: _('black'), 1: _('blue'), 2: _('green'), 3: _('cyan'), 4: _('red'), 5: _('Magenta'), 6: _('brown/yellow'), 7: _('white')} + self.fgColorNames = {0: _('Black'), 1: _('Blue'), 2: _('Green'), 3: _('Cyan'), 4: _('Red'), 5: _('Magenta'), 6: _('brown/yellow'), 7: _('Light gray'), 8: _('Dark gray'), 9: _('Light blue'), 10: ('Light green'), 11: _('Light cyan'), 12: _('Light red'), 13: _('Light magenta'), 14: _('Light yellow'), 15: _('White')} + self.hichar = None + def initialize(self, environment): + self.env = environment + self.env['runtime']['processManager'].addCustomEventThread(self.updateWatchdog) + 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.POLLPRI | select.POLLERR) + watchdog.register(tty, select.POLLPRI | select.POLLERR) + 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.POLLPRI | select.POLLERR) + except: + pass + oldScreen = currScreen + eventQueue.put({"Type":fenrirEventType.ScreenChanged,"Data":''}) + try: + vcsa[currScreen].seek(0) + lastScreenContent = vcsa[currScreen].read() + except: + pass + else: + self.env['runtime']['debug'].writeDebugOut('ScreenUpdate',debug.debugLevel.INFO) + vcsa[currScreen].seek(0) + dirtyContent = vcsa[currScreen].read() + screenContent = b'' + timeout = time.time() + while screenContent != dirtyContent: + screenContent = dirtyContent + if time.time() - timeout >= 0.4: + break + time.sleep(0.008) + vcsa[currScreen].seek(0) + dirtyContent = vcsa[currScreen].read() + eventQueue.put({"Type":fenrirEventType.ScreenUpdate,"Data":None}) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('VCSA:updateWatchdog:' + str(e),debug.debugLevel.ERROR) + + def updateCharMap(self, screen): + self.charmap = {} + try: + tty = open('/dev/tty' + screen, 'rb') + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('VCSA:updateCharMap:' + str(e),debug.debugLevel.ERROR) + return + 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 Exception as e: + self.env['runtime']['debug'].writeDebugOut('VCSA:updateCharMap:scaling up sz=' + str(sz) + ' ' + str(e),debug.debugLevel.WARNING) + 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 = [] + i = 0 + for y in range(rows): + lineText = '' + lineAttrib = [] + for x in range(cols): + data = allData[i: i + 2] + i += 2 + if data == b' \x07': + #attr = 7 + #ink = 7 + #paper = 0 + #ch = ' ' + lineAttrib.append((7,15,0,0,0,0)) # attribute, ink, paper, blink, bold, underline + lineText += ' ' + continue + (sh,) = unpack("=H", data) + attr = (sh >> 8) & 0xFF + ch = sh & 0xFF + if self.hichar == 0x100: + attr >>= 1 + ink = attr & 0x0F + paper = (attr>>4) & 0x0F + blink = 0 + #if attr & 1: + # blink = 1 + bold = 0 + #if attr & 16: + # bold = 1 + #if (ink != 7) or (paper != 0): + # print(ink,paper) + if sh & self.hichar: + ch |= 0x100 + try: + lineText += self.charmap[ch] + except KeyError: + lineText += '?' + lineAttrib.append((attr,ink, paper,blink,bold,0)) # attribute, ink, paper, blink, bold, underline + allText += lineText + '\n' + allAttrib += lineAttrib + return str(allText), allAttrib + def getFenrirBGColor(self, attribute): + try: + return self.bgColorNames[attribute[2]] + except Exception as e: + print(e) + return '' + def getFenrirFGColor(self, attribute): + try: + return self.fgColorNames[attribute[1]] + except Exception as e: + print(e) + return '' + def getFenrirUnderline(self, attribute): + if attribute[5] == 1: + return _('underlined') + return '' + def getFenrirBold(self, attribute): + if attribute[4] == 1: + return _('bold') + return '' + def getFenrirBlink(self, attribute): + if attribute[3] == 1: + return _('blink') + return '' + def getFenrirFont(self, attribute): + return _('Default') + def getFenrirFontSize(self, attribute): + return _('Default') + def update(self, trigger='onUpdate'): + if trigger == 'onInput': # no need for an update on input for VCSA + return + 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 + # 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.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']) + + if self.env['screen']['newTTY'] != self.env['screen']['oldTTY']: + self.env['screen']['oldContentBytes'] = b'' + self.env['screen']['oldContentAttrib'] = None + 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 + diffList = [] + if (self.env['screen']['oldContentText'] != self.env['screen']['newContentText']): + if self.env['screen']['newContentText'] != '' and self.env['screen']['oldContentText'] == '': + 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 abs(self.env['screen']['oldCursor']['x'] - self.env['screen']['newCursor']['x']) >= 1 and \ + self.env['screen']['oldCursor']['y'] == self.env['screen']['newCursor']['y'] and \ + self.env['screen']['newContentText'][:cursorLineStart] == self.env['screen']['oldContentText'][:cursorLineStart] and \ + self.env['screen']['newContentText'][cursorLineEnd:] == self.env['screen']['oldContentText'][cursorLineEnd:]: + cursorLineStartOffset = cursorLineStart + cursorLineEndOffset = cursorLineEnd + #if cursorLineStart < cursorLineStart + self.env['screen']['newCursor']['x'] - 4: + # cursorLineStartOffset = cursorLineStart + self.env['screen']['newCursor']['x'] - 4 + if cursorLineEnd > cursorLineStart + self.env['screen']['newCursor']['x'] + 3: + cursorLineEndOffset = cursorLineStart + self.env['screen']['newCursor']['x'] + 3 + oldScreenText = self.env['screen']['oldContentText'][cursorLineStartOffset:cursorLineEndOffset] + # oldScreenText = re.sub(' +',' ',oldScreenText) + newScreenText = self.env['screen']['newContentText'][cursorLineStartOffset:cursorLineEndOffset] + #newScreenText = re.sub(' +',' ',newScreenText) + diff = difflib.ndiff(oldScreenText, newScreenText) + diffList = list(diff) + tempNewDelta = ''.join(x[2:] for x in diffList if x[0] == '+') + if tempNewDelta.strip() != '': + if tempNewDelta != ''.join(newScreenText[self.env['screen']['oldCursor']['x']:self.env['screen']['newCursor']['x']].rstrip()): + diffList = ['+ ' + self.env['screen']['newContentText'].split('\n')[self.env['screen']['newCursor']['y']]] + + 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']) + diff --git a/src/fenrirscreenreader/screenDriver/__init__.py b/src/fenrirscreenreader/screenDriver/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/src/fenrirscreenreader/screenDriver/dummyDriver.py b/src/fenrirscreenreader/screenDriver/dummyDriver.py new file mode 100644 index 00000000..60cb2d6b --- /dev/null +++ b/src/fenrirscreenreader/screenDriver/dummyDriver.py @@ -0,0 +1,12 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.core.screenDriver import screenDriver + +class driver(screenDriver): + def __init__(self): + screenDriver.__init__(self) diff --git a/src/fenrirscreenreader/screenDriver/ptyDriver.py b/src/fenrirscreenreader/screenDriver/ptyDriver.py new file mode 100644 index 00000000..585c6d8c --- /dev/null +++ b/src/fenrirscreenreader/screenDriver/ptyDriver.py @@ -0,0 +1,372 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. +#attrib: +#http://rampex.ihep.su/Linux/linux_howto/html/tutorials/mini/Colour-ls-6.html +#0 = black, 1 = blue, 2 = green, 3 = cyan, 4 = red, 5 = purple, 6 = brown/yellow, 7 = white. +#https://github.com/jwilk/vcsapeek/blob/master/linuxvt.py +#blink = 5 if attr & 1 else 0 +#bold = 1 if attr & 16 else 0 + + +import difflib +import re +import subprocess +import glob, os +import termios +import time +import select +import dbus +import fcntl +from array import array +import errno +import sys +from fenrirscreenreader.utils import screen_utils +from fcntl import ioctl +from struct import unpack_from, unpack, pack +from fenrirscreenreader.core import debug +from fenrirscreenreader.core.eventData import fenrirEventType +from fenrirscreenreader.core.screenDriver import screenDriver + +class driver(screenDriver): + def __init__(self): + screenDriver.__init__(self) + self.vcsaDevicePath = '/dev/vcsa' + self.ListSessions = None + self.charmap = {} + self.bgColorNames = {0: _('black'), 1: _('blue'), 2: _('green'), 3: _('cyan'), 4: _('red'), 5: _('Magenta'), 6: _('brown/yellow'), 7: _('white')} + self.fgColorNames = {0: _('Black'), 1: _('Blue'), 2: _('Green'), 3: _('Cyan'), 4: _('Red'), 5: _('Magenta'), 6: _('brown/yellow'), 7: _('Light gray'), 8: _('Dark gray'), 9: _('Light blue'), 10: ('Light green'), 11: _('Light cyan'), 12: _('Light red'), 13: _('Light magenta'), 14: _('Light yellow'), 15: _('White')} + self.hichar = None + def initialize(self, environment): + self.env = environment + self.env['runtime']['processManager'].addCustomEventThread(self.updateWatchdog) + 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.POLLPRI | select.POLLERR) + watchdog.register(tty, select.POLLPRI | select.POLLERR) + 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.POLLPRI | select.POLLERR) + except: + pass + oldScreen = currScreen + eventQueue.put({"Type":fenrirEventType.ScreenChanged,"Data":''}) + try: + vcsa[currScreen].seek(0) + lastScreenContent = vcsa[currScreen].read() + except: + pass + else: + self.env['runtime']['debug'].writeDebugOut('ScreenUpdate',debug.debugLevel.INFO) + vcsa[currScreen].seek(0) + dirtyContent = vcsa[currScreen].read() + screenContent = b'' + timeout = time.time() + while screenContent != dirtyContent: + screenContent = dirtyContent + if time.time() - timeout >= 0.4: + break + time.sleep(0.007) + vcsa[currScreen].seek(0) + dirtyContent = vcsa[currScreen].read() + eventQueue.put({"Type":fenrirEventType.ScreenUpdate,"Data":None}) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('VCSA:updateWatchdog:' + str(e),debug.debugLevel.ERROR) + + def updateCharMap(self, screen): + self.charmap = {} + try: + tty = open('/dev/tty' + screen, 'rb') + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('VCSA:updateCharMap:' + str(e),debug.debugLevel.ERROR) + return + 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 Exception as e: + self.env['runtime']['debug'].writeDebugOut('VCSA:updateCharMap:scaling up sz=' + str(sz) + ' ' + str(e),debug.debugLevel.WARNING) + 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 = [] + i = 0 + for y in range(rows): + lineText = '' + lineAttrib = [] + for x in range(cols): + data = allData[i: i + 2] + i += 2 + if data == b' \x07': + #attr = 7 + #ink = 7 + #paper = 0 + #ch = ' ' + lineAttrib.append((7,15,0,0,0,0)) # attribute, ink, paper, blink, bold, underline + lineText += ' ' + continue + (sh,) = unpack("=H", data) + attr = (sh >> 8) & 0xFF + ch = sh & 0xFF + if self.hichar == 0x100: + attr >>= 1 + ink = attr & 0x0F + paper = (attr>>4) & 0x0F + blink = 0 + #if attr & 1: + # blink = 1 + bold = 0 + #if attr & 16: + # bold = 1 + #if (ink != 7) or (paper != 0): + # print(ink,paper) + if sh & self.hichar: + ch |= 0x100 + try: + lineText += self.charmap[ch] + except KeyError: + lineText += '?' + lineAttrib.append((attr,ink, paper,blink,bold,0)) # attribute, ink, paper, blink, bold, underline + allText += lineText + '\n' + allAttrib += lineAttrib + return str(allText), allAttrib + def getFenrirBGColor(self, attribute): + try: + return self.bgColorNames[attribute[2]] + except Exception as e: + print(e) + return '' + def getFenrirFGColor(self, attribute): + try: + return self.fgColorNames[attribute[1]] + except Exception as e: + print(e) + return '' + def getFenrirUnderline(self, attribute): + if attribute[5] == 1: + return _('underlined') + return '' + def getFenrirBold(self, attribute): + if attribute[4] == 1: + return _('bold') + return '' + def getFenrirBlink(self, attribute): + if attribute[3] == 1: + return _('blink') + return '' + def getFenrirFont(self, attribute): + return _('Default') + def getFenrirFontSize(self, attribute): + return _('Default') + def update(self, trigger='onUpdate'): + if trigger == 'onInput': # no need for an update on input for VCSA + return + 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 + # 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.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']) + + if self.env['screen']['newTTY'] != self.env['screen']['oldTTY']: + self.env['screen']['oldContentBytes'] = b'' + self.env['screen']['oldContentAttrib'] = None + 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']): + if self.env['screen']['newContentText'] != '' and self.env['screen']['oldContentText'] == '': + 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 abs(self.env['screen']['oldCursor']['x'] - self.env['screen']['newCursor']['x']) == 1 and \ + self.env['screen']['oldCursor']['y'] == self.env['screen']['newCursor']['y'] and \ + self.env['screen']['newContentText'][:cursorLineStart] == self.env['screen']['oldContentText'][:cursorLineStart] and \ + self.env['screen']['newContentText'][cursorLineEnd:] == self.env['screen']['oldContentText'][cursorLineEnd:]: + cursorLineStartOffset = cursorLineStart + cursorLineEndOffset = cursorLineEnd + #if cursorLineStart < cursorLineStart + self.env['screen']['newCursor']['x'] - 4: + # cursorLineStartOffset = cursorLineStart + self.env['screen']['newCursor']['x'] - 4 + if cursorLineEnd > cursorLineStart + self.env['screen']['newCursor']['x'] + 3: + cursorLineEndOffset = cursorLineStart + self.env['screen']['newCursor']['x'] + 3 + oldScreenText = self.env['screen']['oldContentText'][cursorLineStartOffset:cursorLineEndOffset] + oldScreenText = re.sub(' +',' ',oldScreenText) + newScreenText = self.env['screen']['newContentText'][cursorLineStartOffset:cursorLineEndOffset] + 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']) + diff --git a/src/fenrirscreenreader/screenDriver/vcsaDriver.py b/src/fenrirscreenreader/screenDriver/vcsaDriver.py new file mode 100644 index 00000000..a91812b6 --- /dev/null +++ b/src/fenrirscreenreader/screenDriver/vcsaDriver.py @@ -0,0 +1,384 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. +#attrib: +#http://rampex.ihep.su/Linux/linux_howto/html/tutorials/mini/Colour-ls-6.html +#0 = black, 1 = blue, 2 = green, 3 = cyan, 4 = red, 5 = purple, 6 = brown/yellow, 7 = white. +#https://github.com/jwilk/vcsapeek/blob/master/linuxvt.py +#blink = 5 if attr & 1 else 0 +#bold = 1 if attr & 16 else 0 + + +import difflib +import re +import subprocess +import glob, os +import termios +import time +import select +import dbus +import fcntl +from array import array +import errno +import sys +from fenrirscreenreader.utils import screen_utils +from fcntl import ioctl +from struct import unpack_from, unpack, pack +from fenrirscreenreader.core import debug +from fenrirscreenreader.core.eventData import fenrirEventType +from fenrirscreenreader.core.screenDriver import screenDriver + +class driver(screenDriver): + def __init__(self): + screenDriver.__init__(self) + self.vcsaDevicePath = '/dev/vcsa' + self.ListSessions = None + self.charmap = {} + self.bgColorNames = {0: _('black'), 1: _('blue'), 2: _('green'), 3: _('cyan'), 4: _('red'), 5: _('Magenta'), 6: _('brown/yellow'), 7: _('white')} + self.fgColorNames = {0: _('Black'), 1: _('Blue'), 2: _('Green'), 3: _('Cyan'), 4: _('Red'), 5: _('Magenta'), 6: _('brown/yellow'), 7: _('Light gray'), 8: _('Dark gray'), 9: _('Light blue'), 10: ('Light green'), 11: _('Light cyan'), 12: _('Light red'), 13: _('Light magenta'), 14: _('Light yellow'), 15: _('White')} + self.hichar = None + def initialize(self, environment): + self.env = environment + self.env['runtime']['processManager'].addCustomEventThread(self.updateWatchdog) + 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() != 'TTY': + 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): + screenData = { + 'columns': 0, + 'lines': 0, + 'delta': '', + 'negativeDelta': '', + 'attribDelta': '', + 'cursorAttrib':None, + 'cursor':{'x':0,'y':0}, + 'Bytes': b'', + 'Text': '', + 'Attributes': None, + 'Scren':'0', + 'Application': '', + 'screenUpdateTime': time.time(), + } + 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.POLLPRI | select.POLLERR) + watchdog.register(tty, select.POLLPRI | select.POLLERR) + 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.POLLPRI | select.POLLERR) + except: + pass + oldScreen = currScreen + try: + vcsa[currScreen].seek(0) + lastScreenContent = vcsa[currScreen].read() + except: + pass + eventQueue.put({"Type":fenrirEventType.ScreenChanged,"Data":lastScreenContent}) + else: + self.env['runtime']['debug'].writeDebugOut('ScreenUpdate',debug.debugLevel.INFO) + vcsa[currScreen].seek(0) + dirtyContent = vcsa[currScreen].read() + screenContent = b'' + timeout = time.time() + while screenContent != dirtyContent: + screenContent = dirtyContent + if time.time() - timeout >= 0.4: + break + time.sleep(0.02) + vcsa[currScreen].seek(0) + dirtyContent = vcsa[currScreen].read() + eventQueue.put({"Type":fenrirEventType.ScreenUpdate,"Data":screenContent}) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('VCSA:updateWatchdog:' + str(e),debug.debugLevel.ERROR) + + def updateCharMap(self, screen): + self.charmap = {} + try: + tty = open('/dev/tty' + screen, 'rb') + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('VCSA:updateCharMap:' + str(e),debug.debugLevel.ERROR) + return + 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 Exception as e: + self.env['runtime']['debug'].writeDebugOut('VCSA:updateCharMap:scaling up sz=' + str(sz) + ' ' + str(e),debug.debugLevel.WARNING) + 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 = [] + i = 0 + for y in range(rows): + lineText = '' + lineAttrib = [] + for x in range(cols): + data = allData[i: i + 2] + i += 2 + if data == b' \x07': + #attr = 7 + #ink = 7 + #paper = 0 + #ch = ' ' + lineAttrib.append((7,15,0,0,0,0)) # attribute, ink, paper, blink, bold, underline + lineText += ' ' + continue + (sh,) = unpack("=H", data) + attr = (sh >> 8) & 0xFF + ch = sh & 0xFF + if self.hichar == 0x100: + attr >>= 1 + ink = attr & 0x0F + paper = (attr>>4) & 0x0F + blink = 0 + #if attr & 1: + # blink = 1 + bold = 0 + #if attr & 16: + # bold = 1 + #if (ink != 7) or (paper != 0): + # print(ink,paper) + if sh & self.hichar: + ch |= 0x100 + try: + lineText += self.charmap[ch] + except KeyError: + lineText += '?' + lineAttrib.append((attr,ink, paper,blink,bold,0)) # attribute, ink, paper, blink, bold, underline + allText += lineText + '\n' + allAttrib += lineAttrib + return str(allText), allAttrib + def getFenrirBGColor(self, attribute): + try: + return self.bgColorNames[attribute[2]] + except Exception as e: + print(e) + return '' + def getFenrirFGColor(self, attribute): + try: + return self.fgColorNames[attribute[1]] + except Exception as e: + print(e) + return '' + def getFenrirUnderline(self, attribute): + if attribute[5] == 1: + return _('underlined') + return '' + def getFenrirBold(self, attribute): + if attribute[4] == 1: + return _('bold') + return '' + def getFenrirBlink(self, attribute): + if attribute[3] == 1: + return _('blink') + return '' + def getFenrirFont(self, attribute): + return _('Default') + def getFenrirFontSize(self, attribute): + return _('Default') + def update(self, text, trigger='onUpdate'): + newContentBytes = text + # 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.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']) + + if self.env['screen']['newTTY'] != self.env['screen']['oldTTY']: + self.env['screen']['oldContentBytes'] = b'' + self.env['screen']['oldContentAttrib'] = None + 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 + if self.env['screen']['oldTTY'] == None: + self.env['screen']['oldTTY'] = self.env['screen']['newTTY'] + 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 + diffList = [] + if (self.env['screen']['oldContentText'] != self.env['screen']['newContentText']): + if self.env['screen']['newContentText'] != '' and self.env['screen']['oldContentText'] == '': + 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 abs(self.env['screen']['oldCursor']['x'] - self.env['screen']['newCursor']['x']) >= 1 and \ + self.env['screen']['oldCursor']['y'] == self.env['screen']['newCursor']['y'] and \ + self.env['screen']['newContentText'][:cursorLineStart] == self.env['screen']['oldContentText'][:cursorLineStart] and \ + self.env['screen']['newContentText'][cursorLineEnd:] == self.env['screen']['oldContentText'][cursorLineEnd:]: + cursorLineStartOffset = cursorLineStart + cursorLineEndOffset = cursorLineEnd + #if cursorLineStart < cursorLineStart + self.env['screen']['newCursor']['x'] - 4: + # cursorLineStartOffset = cursorLineStart + self.env['screen']['newCursor']['x'] - 4 + if cursorLineEnd > cursorLineStart + self.env['screen']['newCursor']['x'] + 3: + cursorLineEndOffset = cursorLineStart + self.env['screen']['newCursor']['x'] + 3 + oldScreenText = self.env['screen']['oldContentText'][cursorLineStartOffset:cursorLineEndOffset] + # oldScreenText = re.sub(' +',' ',oldScreenText) + newScreenText = self.env['screen']['newContentText'][cursorLineStartOffset:cursorLineEndOffset] + #newScreenText = re.sub(' +',' ',newScreenText) + diff = difflib.ndiff(oldScreenText, newScreenText) + diffList = list(diff) + tempNewDelta = ''.join(x[2:] for x in diffList if x[0] == '+') + if tempNewDelta.strip() != '': + if tempNewDelta != ''.join(newScreenText[self.env['screen']['oldCursor']['x']:self.env['screen']['newCursor']['x']].rstrip()): + diffList = ['+ ' + self.env['screen']['newContentText'].split('\n')[self.env['screen']['newCursor']['y']]] + + 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']) + diff --git a/src/fenrirscreenreader/soundDriver/__init__.py b/src/fenrirscreenreader/soundDriver/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/src/fenrirscreenreader/soundDriver/debugDriver.py b/src/fenrirscreenreader/soundDriver/debugDriver.py new file mode 100644 index 00000000..33c17481 --- /dev/null +++ b/src/fenrirscreenreader/soundDriver/debugDriver.py @@ -0,0 +1,56 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.core.soundDriver import soundDriver + +class driver(soundDriver): + def __init__(self): + soundDriver.__init__(self) + + def initialize(self, environment): + self.env = environment + self._initialized = True + print('Sound Debug Driver: Initialized') + + def shutdown(self): + if not self._initialized: + return + self.cancel() + self._initialized = False + print('Sound Debug Driver: Shutdown') + + def playFrequence(self, frequence = 1000, duration = 0.3, adjustVolume = 0): + if not self._initialized: + return + if interrupt: + self.cancel() + print('Sound Debug Driver: playFrequence:' + ' freq:' + str(frequence) + ' duration:' + str(duration) + ' adjustVolume:' + str(adjustVolume) ) + print('Sound Debug Driver: -----------------------------------') + + def playSoundFile(self, filePath, interrupt = True): + if not self._initialized: + return + if interrupt: + self.cancel() + print('Sound Debug Driver: playSoundFile:' + str(filePath)) + print('Sound Debug Driver: -----------------------------------') + + def cancel(self): + if not self._initialized: + return + print('Sound Debug Driver: Cancel') + + def setCallback(self, callback): + if not self._initialized: + return + print('Sound Debug Driver: setCallback') + + def setVolume(self, volume): + if not self._initialized: + return + self.volume = volume + print('Sound Debug Driver: setVolume:' + str(self.volume)) diff --git a/src/fenrirscreenreader/soundDriver/dummyDriver.py b/src/fenrirscreenreader/soundDriver/dummyDriver.py new file mode 100644 index 00000000..5f296755 --- /dev/null +++ b/src/fenrirscreenreader/soundDriver/dummyDriver.py @@ -0,0 +1,12 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from fenrirscreenreader.core.soundDriver import soundDriver + +class driver(soundDriver): + def __init__(self): + soundDriver.__init__(self) diff --git a/src/fenrirscreenreader/soundDriver/genericDriver.py b/src/fenrirscreenreader/soundDriver/genericDriver.py new file mode 100644 index 00000000..d3eec5f6 --- /dev/null +++ b/src/fenrirscreenreader/soundDriver/genericDriver.py @@ -0,0 +1,63 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +import subprocess +import shlex +from fenrirscreenreader.core.soundDriver import soundDriver + +class driver(soundDriver): + def __init__(self): + soundDriver.__init__(self) + self.proc = None + self.soundType = '' + self.soundFileCommand = '' + self.frequenceCommand = '' + def initialize(self, environment): + self.env = environment + self.soundFileCommand = self.env['runtime']['settingsManager'].getSetting('sound', 'genericPlayFileCommand') + self.frequenceCommand = self.env['runtime']['settingsManager'].getSetting('sound', 'genericFrequencyCommand') + if self.soundFileCommand == '': + self.soundFileCommand = 'play -q -v fenrirVolume fenrirSoundFile' + if self.frequenceCommand == '': + self.frequenceCommand = 'play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence' + self._initialized = True + + def playFrequence(self, frequence = 1000, duration = 0.3, adjustVolume = 0): + if not self._initialized: + return + if interrupt: + self.cancel() + popenFrequenceCommand = shlex.split(self.frequenceCommand) + for idx, word in enumerate(popenFrequenceCommand): + word = word.replace('fenrirVolume', str(self.volume + adjustVolume )) + word = word.replace('fenrirFreqDuration', str(duration)) + word = word.replace('fenrirFrequence', str(frequence)) + popenFrequenceCommand[idx] = word + self.proc = subprocess.Popen(popenFrequenceCommand, shell=False) + self.soundType = 'frequence' + def playSoundFile(self, filePath, interrupt = True): + if not self._initialized: + return + if interrupt: + self.cancel() + popenSoundFileCommand = shlex.split(self.soundFileCommand) + for idx, word in enumerate(popenSoundFileCommand): + word = word.replace('fenrirVolume', str(self.volume )) + word = word.replace('fenrirSoundFile', str(filePath)) + popenSoundFileCommand[idx] = word + self.proc = subprocess.Popen(popenSoundFileCommand, shell=False) + self.soundType = 'file' + def cancel(self): + if not self._initialized: + return + if self.soundType == '': + return + if self.soundType == 'file': + self.proc.kill() + if self.soundType == 'frequence': + self.proc.kill() + self.soundType = '' diff --git a/src/fenrirscreenreader/soundDriver/gstreamerDriver.py b/src/fenrirscreenreader/soundDriver/gstreamerDriver.py new file mode 100644 index 00000000..9f441cd6 --- /dev/null +++ b/src/fenrirscreenreader/soundDriver/gstreamerDriver.py @@ -0,0 +1,113 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +import time, threading +from fenrirscreenreader.core.soundDriver import soundDriver + +_gstreamerAvailable = False +try: + import gi + from gi.repository import GLib + gi.require_version('Gst', '1.0') + from gi.repository import Gst + _gstreamerAvailable, args = Gst.init_check(None) +except Exception as e: + _gstreamerAvailable = False + _availableError = str(e) + +class driver(soundDriver): + def __init__(self): + soundDriver.__init__(self) + self._source = None + self._sink = None + + def initialize(self, environment): + self.env = environment + global _gstreamerAvailable + self._initialized = _gstreamerAvailable + if not self._initialized: + global _availableError + self.environment['runtime']['debug'].writeDebugOut('Gstreamer not available ' + _availableError,debug.debugLevel.ERROR) + return + self._player = Gst.ElementFactory.make('playbin', 'player') + bus = self._player.get_bus() + bus.add_signal_watch() + bus.connect("message", self._onPlayerMessage) + + self._pipeline = Gst.Pipeline(name='fenrir-pipeline') + bus = self._pipeline.get_bus() + bus.add_signal_watch() + bus.connect("message", self._onPipelineMessage) + + self._source = Gst.ElementFactory.make('audiotestsrc', 'src') + self._sink = Gst.ElementFactory.make('autoaudiosink', 'output') + self._pipeline.add(self._source) + self._pipeline.add(self._sink) + self._source.link(self._sink) + self.mainloop = GLib.MainLoop() + self.thread = threading.Thread(target=self.mainloop.run) + self.thread.start() + + def shutdown(self): + if not self._initialized: + return + self.cancel() + self.mainloop.quit() + + def _onPlayerMessage(self, bus, message): + if not self._initialized: + return + if message.type == Gst.MessageType.EOS: + self._player.set_state(Gst.State.NULL) + elif message.type == Gst.MessageType.ERROR: + self._player.set_state(Gst.State.NULL) + error, info = message.parse_error() + self.env['runtime']['debug'].writeDebugOut('GSTREAMER: _onPlayerMessage'+ str(error) + str(info),debug.debugLevel.WARNING) + + def _onPipelineMessage(self, bus, message): + if not self._initialized: + return + if message.type == Gst.MessageType.EOS: + self._pipeline.set_state(Gst.State.NULL) + elif message.type == Gst.MessageType.ERROR: + self._pipeline.set_state(Gst.State.NULL) + error, info = message.parse_error() + self.env['runtime']['debug'].writeDebugOut('GSTREAMER: _onPipelineMessage'+ str(error) + str(info),debug.debugLevel.WARNING) + + def _onTimeout(self, element): + if not self._initialized: + return + element.set_state(Gst.State.NULL) + + def playSoundFile(self, fileName, interrupt=True): + if not self._initialized: + return + if interrupt: + self.cancel() + self._player.set_property('uri', 'file://%s' % fileName) + self._player.set_state(Gst.State.PLAYING) + + def playFrequence(self, frequence, duration, adjustVolume, interrupt=True): + if not self._initialized: + return + if interrupt: + self.cancel() + self._source.set_property('volume', tone.volume) + self._source.set_property('freq', tone.frequency) + self._source.set_property('wave', tone.wave) + self._pipeline.set_state(Gst.State.PLAYING) + duration = int(1000 * tone.duration) + GLib.timeout_add(duration, self._onTimeout, self._pipeline) + + def cancel(self, element=None): + if not self._initialized: + return + if element: + element.set_state(Gst.State.NULL) + return + self._player.set_state(Gst.State.NULL) + self._pipeline.set_state(Gst.State.NULL) diff --git a/src/fenrirscreenreader/speechDriver/Readme.md b/src/fenrirscreenreader/speechDriver/Readme.md new file mode 100644 index 00000000..de077fd4 --- /dev/null +++ b/src/fenrirscreenreader/speechDriver/Readme.md @@ -0,0 +1,3 @@ +espeak = espeak driver +speechd = speech-dispatcher driver +generic = generic driver via /bin/say diff --git a/src/fenrirscreenreader/speechDriver/__init__.py b/src/fenrirscreenreader/speechDriver/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/src/fenrirscreenreader/speechDriver/debugDriver.py b/src/fenrirscreenreader/speechDriver/debugDriver.py new file mode 100644 index 00000000..47bea182 --- /dev/null +++ b/src/fenrirscreenreader/speechDriver/debugDriver.py @@ -0,0 +1,74 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. +# generic driver + +from fenrirscreenreader.core import debug +from fenrirscreenreader.core.speechDriver import speechDriver + +class driver(speechDriver): + def __init__(self): + speechDriver.__init__(self + def initialize(self, environment): + self._isInitialized = True + self.env = environment + print('Speech Debug Driver: Iitialized') + + def shutdown(self): + if self._isInitialized: + self.cancel() + self._isInitialized = False + print('Speech Debug Driver: Shutdown') + + def speak(self,text, queueable=True): + if not self._isInitialized: + return + if not queueable: + self.cancel() + print('Speech Debug Driver: Speak:'+text) + print('Speech Debug Driver: -----------------------------------') + + def cancel(self): + if not self._isInitialized: + return + print('Speech Debug Driver: Cancel') + + def setCallback(self, callback): + print('Speech Debug Driver: setCallback') + + def clear_buffer(self): + if not self._isInitialized: + return + print('Speech Debug Driver: clear_buffer') + + def setVoice(self, voice): + if not self._isInitialized: + return + print('Speech Debug Driver: setVoice:' + str(voice)) + + def setPitch(self, pitch): + if not self._isInitialized: + return + print('Speech Debug Driver: setPitch:' + str(pitch)) + + def setRate(self, rate): + if not self._isInitialized: + return + print('Speech Debug Driver: setRate:' + str(rate)) + + def setModule(self, module): + if not self._isInitialized: + return + print('Speech Debug Driver: setModule:' + str(module)) + + def setLanguage(self, language): + if not self._isInitialized: + return + print('Speech Debug Driver: setLanguage:' + str(language)) + + def setVolume(self, volume): + if not self._isInitialized: + return + print('Speech Debug Driver: setVolume:' + str(volume)) diff --git a/src/fenrirscreenreader/speechDriver/dummyDriver.py b/src/fenrirscreenreader/speechDriver/dummyDriver.py new file mode 100644 index 00000000..32e893d4 --- /dev/null +++ b/src/fenrirscreenreader/speechDriver/dummyDriver.py @@ -0,0 +1,13 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. +# generic driver + +from fenrirscreenreader.core import debug +from fenrirscreenreader.core.speechDriver import speechDriver + +class driver(speechDriver): + def __init__(self): + speechDriver.__init__(self) diff --git a/src/fenrirscreenreader/speechDriver/emacspeakDriver.py b/src/fenrirscreenreader/speechDriver/emacspeakDriver.py new file mode 100644 index 00000000..414d225f --- /dev/null +++ b/src/fenrirscreenreader/speechDriver/emacspeakDriver.py @@ -0,0 +1,82 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. +# generic driver + +from subprocess import Popen, PIPE +import pexpect +import ptyprocess +import shlex +import sys +import time +from fenrirscreenreader.core import debug +from fenrirscreenreader.core.speechDriver import speechDriver + +class driver(speechDriver): + def __init__(self): + speechDriver.__init__(self) + def initialize(self, environment): + self.env = environment + try: + #self.server = ptyprocess.PtyProcessUnicode.spawn(['/usr/bin/tclsh', self.env['runtime']['settingsManager'].getSetting('speech', 'serverPath')]) + self.server = pexpect.spawn('tclsh ' + self.env['runtime']['settingsManager'].getSetting('speech', 'serverPath')) + self._isInitialized = True + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('speechDriver:initialize:' + str(e),debug.debugLevel.ERROR) + print(e) + + def shutdown(self): + if self.server: + try: + self.server.terminate() + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('speechDriver:shutdown:self.server.terminate():' + str(e),debug.debugLevel.ERROR) + + def speak(self,text, queueable=True): + if not self._isInitialized: + return + if not queueable: + self.cancel() + try: + cleanText = shlex.split('tts_say "'+text.replace(',','')+'"') + for idx, word in enumerate(cleanText): + cleanText[idx] = word + cleanText = ' '.join(cleanText) + #print(cleanText[0]) + #self.server.write('tts_say ' + '"' + cleanText[0] +'"\n') + #print(self.server.read(1000)) + #self.server.sendline('tts_say ' + '"' + cleanText + '"') + self.server.sendline(cleanText) + print(cleanText) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('speechDriver:speak:self.server.sendline():' + str(e),debug.debugLevel.ERROR) + + def cancel(self): + if not self._isInitialized: + return + try: + pass + #self.server.write('s\n') + #print(self.server.read(1000)) + #self.server.sendline('stop') + except Exception as e: + print(e) + self.env['runtime']['debug'].writeDebugOut('speechDriver:cancel:self.server.sendline():' + str(e),debug.debugLevel.ERROR) + + def setRate(self, rate): + if not self._isInitialized: + return + try: + pass + #self.server.write('tts_set_speech_rate ' + str(int(rate * 400)) + '\n') + #self.server.sendline('tts_set_speech_rate ' + str(int(rate * 400)) + '') + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('speechDriver:setRate:self.server.sendline():' + str(e),debug.debugLevel.ERROR) + + def setLanguage(self, language): + if not self._isInitialized: + return + #self.server.write('set_lang ' + language + '\n') + #self.server.sendline('set_lang ' + language + '') diff --git a/src/fenrirscreenreader/speechDriver/espeakDriver.py b/src/fenrirscreenreader/speechDriver/espeakDriver.py new file mode 100644 index 00000000..4a85f060 --- /dev/null +++ b/src/fenrirscreenreader/speechDriver/espeakDriver.py @@ -0,0 +1,58 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. +# Espeak driver + +from fenrirscreenreader.core import debug +from fenrirscreenreader.core.speechDriver import speechDriver + +class driver(speechDriver): + def __init__(self): + speechDriver.__init__(self) + self._es = None + + def initialize(self, environment): + self.env = environment + try: + from espeak import espeak + self._es = espeak + self._isInitialized = True + except Exception as e: + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + self._initialized = False + + def speak(self,text, interrupt=True): + if not self._isInitialized: + return + if not interrupt: + self.cancel() + if self.language != None: + if self.language != '': + self._es.set_voice(self.language) + elif self.voice != None: + if self.voice != '': + self._es.set_voice(self.voice) + self._es.synth(text) + + def cancel(self): + if not self._isInitialized: + return + self._es.cancel() + return + + def setPitch(self, pitch): + if not self._isInitialized: + return + return self._es.set_parameter(self._es.Parameter().Pitch, int(pitch * 99)) + + def setRate(self, rate): + if not self._isInitialized: + return + return self._es.set_parameter(self._es.Parameter().Rate, int(rate * 899 + 100)) + + def setVolume(self, volume): + if not self._isInitialized: + return + return self._es.set_parameter(self._es.Parameter().Volume, int(volume * 200)) diff --git a/src/fenrirscreenreader/speechDriver/genericDriver.py b/src/fenrirscreenreader/speechDriver/genericDriver.py new file mode 100644 index 00000000..31f16db9 --- /dev/null +++ b/src/fenrirscreenreader/speechDriver/genericDriver.py @@ -0,0 +1,192 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. +# generic driver + +from fenrirscreenreader.core import debug +from threading import Thread, Lock +from queue import Queue, Empty +import shlex +from subprocess import Popen +from fenrirscreenreader.core.speechDriver import speechDriver + +class speakQueue(Queue): + def clear(self): + try: + while True: + self.get_nowait() + except Empty: + pass + +class driver(speechDriver): + def __init__(self): + speechDriver.__init__(self) + self.proc = None + self.speechThread = Thread(target=self.worker) + self.lock = Lock() + self.textQueue = speakQueue() + def initialize(self, environment): + self.env = environment + self.minVolume = self.env['runtime']['settingsManager'].getSettingAsInt('speech', 'fenrirMinVolume') + self.maxVolume = self.env['runtime']['settingsManager'].getSettingAsInt('speech', 'fenrirMaxVolume') + self.minPitch = self.env['runtime']['settingsManager'].getSettingAsInt('speech', 'fenrirMinPitch') + self.maxPitch = self.env['runtime']['settingsManager'].getSettingAsInt('speech', 'fenrirMaxPitch') + self.minRate = self.env['runtime']['settingsManager'].getSettingAsInt('speech', 'fenrirMinRate') + self.maxRate = self.env['runtime']['settingsManager'].getSettingAsInt('speech', 'fenrirMaxRate') + + self.speechCommand = self.env['runtime']['settingsManager'].getSetting('speech', 'genericSpeechCommand') + if self.speechCommand == '': + self.speechCommand = 'espeak -a fenrirVolume -s fenrirRate -p fenrirPitch -v fenrirVoice -- "fenrirText"' + if False: #for debugging overwrite here + #self.speechCommand = 'spd-say --wait -r 100 -i 100 "fenrirText"' + self.speechCommand = 'flite -t "fenrirText"' + + self._isInitialized = True + if self._isInitialized: + self.speechThread.start() + def shutdown(self): + if not self._isInitialized: + return + self.cancel() + self.textQueue.put(-1) + + def speak(self,text, queueable=True): + if not self._isInitialized: + return + if not queueable: + self.cancel() + utterance = { + 'text': text, + 'volume': self.volume, + 'rate': self.rate, + 'pitch': self.pitch, + 'module': self.module, + 'language': self.language, + 'voice': self.voice, + } + self.textQueue.put(utterance.copy()) + + def cancel(self): + if not self._isInitialized: + return + self.clear_buffer() + self.lock.acquire(True) + if self.proc: + try: + self.proc.terminate() + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('speechDriver:Cancel:self.proc.terminate():' + str(e),debug.debugLevel.WARNING) + try: + self.proc.kill() + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('speechDriver:Cancel:self.proc.kill():' + str(e),debug.debugLevel.WARNING) + self.proc = None + self.lock.release() + def setCallback(self, callback): + print('SpeechDummyDriver: setCallback') + + def clear_buffer(self): + if not self._isInitialized: + return + self.textQueue.clear() + + def setVoice(self, voice): + if not self._isInitialized: + return + self.voice = str(voice) + + def setPitch(self, pitch): + if not self._isInitialized: + return + self.pitch = str(self.minPitch + pitch * (self.maxPitch - self.minPitch )) + + def setRate(self, rate): + if not self._isInitialized: + return + self.rate = str(self.minRate + rate * (self.maxRate - self.minRate )) + + def setModule(self, module): + if not self._isInitialized: + return + self.module = str(module) + + def setLanguage(self, language): + if not self._isInitialized: + return + self.language = str(language) + + def setVolume(self, volume): + if not self._isInitialized: + return + self.volume = str(self.minVolume + volume * (self.maxVolume - self.minVolume )) + + def worker(self): + while True: + utterance = self.textQueue.get() + + if isinstance(utterance, int): + if utterance == -1: + return + else: + continue + elif not isinstance(utterance, dict): + continue + # no text means nothing to speak + if not 'text' in utterance: + continue + if not isinstance(utterance['text'],str): + continue + if utterance['text'] == '': + continue + # check for valid data fields + if not 'volume' in utterance: + utterance['volume'] = '' + if not isinstance(utterance['volume'],str): + utterance['volume'] = '' + if not 'module' in utterance: + utterance['module'] = '' + if not isinstance(utterance['module'],str): + utterance['module'] = '' + if not 'language' in utterance: + utterance['language'] = '' + if not isinstance(utterance['language'],str): + utterance['language'] = '' + if not 'voice' in utterance: + utterance['voice'] = '' + if not isinstance(utterance['voice'],str): + utterance['voice'] = '' + if not 'pitch' in utterance: + utterance['pitch'] = '' + if not isinstance(utterance['pitch'],str): + utterance['pitch'] = '' + if not 'rate' in utterance: + utterance['rate'] = '' + if not isinstance(utterance['rate'],str): + utterance['rate'] = '' + + popenSpeechCommand = shlex.split(self.speechCommand) + for idx, word in enumerate(popenSpeechCommand): + word = word.replace('fenrirVolume', str(utterance['volume'] )) + word = word.replace('fenrirModule', str(utterance['module'])) + word = word.replace('fenrirLanguage', str(utterance['language'])) + word = word.replace('fenrirVoice', str(utterance['voice'])) + word = word.replace('fenrirPitch', str(utterance['pitch'])) + word = word.replace('fenrirRate', str(utterance['rate'])) + word = word.replace('fenrirText', str(utterance['text'])) + popenSpeechCommand[idx] = word + + try: + self.env['runtime']['debug'].writeDebugOut('speechDriver:worker:' + ' '.join(popenSpeechCommand),debug.debugLevel.INFO) + self.lock.acquire(True) + self.proc = Popen(popenSpeechCommand, shell=False) + self.lock.release() + self.proc.wait() + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('speechDriver:worker:' + str(e),debug.debugLevel.ERROR) + + self.lock.acquire(True) + self.proc = None + self.lock.release() + diff --git a/src/fenrirscreenreader/speechDriver/pyttsxDriver.py b/src/fenrirscreenreader/speechDriver/pyttsxDriver.py new file mode 100644 index 00000000..e9635f7a --- /dev/null +++ b/src/fenrirscreenreader/speechDriver/pyttsxDriver.py @@ -0,0 +1,86 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. +# Espeak driver + +from threading import Thread, Lock +from fenrirscreenreader.core import debug +from fenrirscreenreader.core.speechDriver import speechDriver + +class driver(speechDriver): + def __init__(self): + speechDriver.__init__(self) + self._engine = None + def initialize(self, environment): + self.env = environment + def shutdown(self): + if self._isInitialized: + self.cancel() + self._engine.endLoop() + self._initialized = False + def eventLoop(self): + self._engine.startLoop() + def startEngine(self): + try: + import pyttsx3 + if self.module != '': + self._engine = pyttsx3.init(self.module) + else: + self._engine = pyttsx3.init() + self.eventLoopThread = Thread(target=self.eventLoop) + self._isInitialized = True + self.eventLoopThread.start() + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('SpeechDriver:initialize:' + str(e),debug.debugLevel.ERROR) + + def speak(self,text, interrupt=True): + if not self._isInitialized: + self.startEngine() + if not self._isInitialized: + return + if not interrupt: + self.cancel() + try: + self._engine.setProperty('volume', self.volume) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('SpeechDriver:speak:volume:' + str(e),debug.debugLevel.ERROR) + try: + self._engine.setProperty('rate', self.rate) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('SpeechDriver:speak:rate:' + str(e),debug.debugLevel.ERROR) + try: + self._engine.setProperty('pitch', self.pitch) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('SpeechDriver:speak:pitch:' + str(e),debug.debugLevel.ERROR) + if self.language != None: + if self.language != '': + try: + self._engine.setProperty('voice', self.language) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('SpeechDriver:speak:language:' + str(e),debug.debugLevel.ERROR) + + elif self.voice != None: + if self.voice != '': + try: + self._engine.setProperty('voice', self.voice) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('SpeechDriver:speak:voice:' + str(e),debug.debugLevel.ERROR) + self._engine.say(text) + + def cancel(self): + if not self._isInitialized: + return + self._engine.stop() + self._engine.proxy.stop() + + def setPitch(self, pitch): + if not self._isInitialized: + return + self.pitch = pitch + + def setRate(self, rate): + if not self._isInitialized: + return + self.rate = rate diff --git a/src/fenrirscreenreader/speechDriver/speechdDriver.py b/src/fenrirscreenreader/speechDriver/speechdDriver.py new file mode 100644 index 00000000..b8181a95 --- /dev/null +++ b/src/fenrirscreenreader/speechDriver/speechdDriver.py @@ -0,0 +1,94 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. +# speech-dispatcher driver + +from fenrirscreenreader.core import debug +from fenrirscreenreader.core.speechDriver import speechDriver + +class driver(speechDriver): + def __init__(self): + speechDriver.__init__(self) + self._sd = None + + def initialize(self, environment): + self.env = environment + try: + import speechd + self._sd = speechd.SSIPClient('fenrir') + self._punct = speechd.PunctuationMode() + self._isInitialized = True + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('speechDriver initialize:' + str(e),debug.debugLevel.ERROR) + + def shutdown(self): + if not self._isInitialized: + return + self.cancel() + try: + self._sd.close() + except: + pass + self._isInitialized = False + + def speak(self,text, queueable=True): + if not queueable: + self.cancel() + if not self._isInitialized: + self.initialize(self.env) + if not self._isInitialized: + return + try: + self._sd.set_output_module(self.module) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('speechDriver setModule:' + str(e),debug.debugLevel.ERROR) + + try: + if self.voice: + if self.voice != '': + self._sd.set_voice(self.voice) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('speechDriver setVoice:' + str(e),debug.debugLevel.ERROR) + try: + if self.language != '': + self._sd.set_synthesis_voice(self.language) + self._sd.set_punctuation(self._punct.NONE) + self._sd.speak(text) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('speechDriver speak:' + str(e),debug.debugLevel.ERROR) + self._isInitialized = False + + def cancel(self): + if not self._isInitialized: + return + try: + self._sd.cancel() + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('speechDriver cancel:' + str(e),debug.debugLevel.ERROR) + self._isInitialized = False + + def setPitch(self, pitch): + if not self._isInitialized: + return + try: + self._sd.set_pitch(int(-100 + pitch * 200)) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('speechDriver setPitch:' + str(e),debug.debugLevel.ERROR) + + def setRate(self, rate): + if not self._isInitialized: + return + try: + self._sd.set_rate(int(-100 + rate * 200)) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('speechDriver setRate:' + str(e),debug.debugLevel.ERROR) + + def setVolume(self, volume): + if not self._isInitialized: + return + try: + self._sd.set_volume(int(-100 + volume * 200)) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('speechDriver setVolume:' + str(e),debug.debugLevel.ERROR) diff --git a/src/fenrirscreenreader/utils/__init__.py b/src/fenrirscreenreader/utils/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/src/fenrirscreenreader/utils/char_utils.py b/src/fenrirscreenreader/utils/char_utils.py new file mode 100644 index 00000000..a41163c8 --- /dev/null +++ b/src/fenrirscreenreader/utils/char_utils.py @@ -0,0 +1,121 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +def getPrevChar(currX,currY, currText): + lineBreak = False + endOfScreen = False + if currText == '': + return -1, -1, '', endOfScreen, lineBreak + wrappedLines = currText.split('\n') + x = currX + y = currY + if x - 1 < 0: + if y - 1 >= 0: + y -= 1 + x = len(wrappedLines[y]) - 1 + lineBreak = True + else: + lineBreak = False + endOfScreen = True + else: + x -= 1 + currChar = '' + if not endOfScreen: + currChar = wrappedLines[y][x] + return x, y, currChar, endOfScreen, lineBreak + +def getCurrentChar(currX,currY, currText): + if currText == '': + return -1, -1, '' + wrappedLines = currText.split('\n') + currChar = wrappedLines[currY][currX] + return currX, currY, currChar + +def getUpChar(currX,currY, currText): + endOfScreen = False + if currText == '': + return -1, -1, '', endOfScreen + wrappedLines = currText.split('\n') + currY -= 1 + if currY < 0: + currY = 0 + else: + endOfScreen = True + currChar = '' + if not endOfScreen: + currChar = wrappedLines[currY][currX] + return currX, currY, currChar, endOfScreen + +def getDownChar(currX,currY, currText): + endOfScreen = False + if currText == '': + return -1, -1, '', endOfScreen + wrappedLines = currText.split('\n') + currY += 1 + if currY >= len(wrappedLines): + currY = len(wrappedLines) -1 + else: + endOfScreen = True + currChar = '' + if not endOfScreen: + currChar = wrappedLines[currY][currX] + return currX, currY, currChar, endOfScreen + +def getLastCharInLine(currY, currText): + endOfScreen = False + if currText == '': + return -1, -1, '' + wrappedLines = currText.split('\n') + currX = len(wrappedLines[currY].rstrip())-1 + if currX < 0: + currX = 0 + currChar = wrappedLines[currY][currX] + return currX, currY, currChar + +def getNextChar(currX,currY, currText): + lineBreak = False + endOfScreen = False + if currText == '': + return -1, -1, '', endOfScreen, lineBreak + wrappedLines = currText.split('\n') + x = currX + y = currY + if x + 1 == len(wrappedLines[y]): + if y + 1 < len(wrappedLines) - 1: + y += 1 + x = 0 + lineBreak = True + else: + lineBreak = False + endOfScreen = True + else: + x += 1 + currChar = '' + if not endOfScreen: + currChar = wrappedLines[y][x] + return x, y, currChar, endOfScreen, lineBreak + +def getPhonetic(currChar): + if len(currChar) != 1: + return currChar + phoneticsDict = { + "A":"alpha", "B":"bravo", "C":"charlie", "D":"delta", "E":"echo", + "F":"foxtrot", "G":"golf", "H":"hotel", "I":"india", "J":"juliet", + "K":"kilo", "L":"lima", "M":"mike", "N":"november", "O":"oscar", + "P":"papa", "Q":"quebec", "R":"romeo", "S":"sierra", "T":"tango", + "U":"uniform", "V":"victor", "W":"whisky", "X":"x ray", + "Y":"yankee", "Z":"zulu" + } + try: + phonChar = phoneticsDict[currChar.upper()] + if currChar.isupper(): + phonChar = phonChar[0].upper() + phonChar[1:] + return phonChar + except: + return currChar + diff --git a/src/fenrirscreenreader/utils/fenrir-config.py b/src/fenrirscreenreader/utils/fenrir-config.py new file mode 100644 index 00000000..d512ba67 --- /dev/null +++ b/src/fenrirscreenreader/utils/fenrir-config.py @@ -0,0 +1,23 @@ +#!/usr/bin/python + +import configparser +import os +import sys +from os import listdir +from os.path import isfile, join +from inspect import isfunction +from xdg import BaseDirectory + +# Get configuration directory +if len(sys.argv) > 1: + configPath = sys.argv[1] +elif os.geteuid() == 0: + # Save settings system wide + configPath = "/etc/fenrir.conf" +else: + # Use local settings + configPath = BaseDirectory.xdg_data_home + "/fenrir" + if not os.path.exists(configPath): os.makedirs(configPath) + configPath = configPath + "/fenrir.conf" + + diff --git a/src/fenrirscreenreader/utils/line_utils.py b/src/fenrirscreenreader/utils/line_utils.py new file mode 100644 index 00000000..51fa3f37 --- /dev/null +++ b/src/fenrirscreenreader/utils/line_utils.py @@ -0,0 +1,52 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from collections import Counter + +def getPrevLine(currX,currY, currText): + endOfScreen = False + if currText == '': + return -1, -1, '', endOfScreen + wrappedLines = currText.split('\n') + x = currX + y = currY + if y - 1 >= 0: + y -= 1 + else: + endOfScreen = True + x = 0 + currLine = '' + if not endOfScreen: + currLine = wrappedLines[y] + return x, y, currLine, endOfScreen + +def getCurrentLine(currX,currY, currText): + if currText == '': + return -1, -1, '' + wrappedLines = currText.split('\n') + x = currX + y = currY + x = 0 + currLine = wrappedLines[y] + return x, y, currLine + +def getNextLine(currX,currY, currText): + endOfScreen = False + if currText == '': + return -1, -1, '', endOfScreen + wrappedLines = currText.split('\n') + x = currX + y = currY + if y + 1 < len(wrappedLines): + y += 1 + else: + endOfScreen = True + x = 0 + currLine = '' + if not endOfScreen: + currLine = wrappedLines[y] + return x, y, currLine, endOfScreen diff --git a/src/fenrirscreenreader/utils/mark_utils.py b/src/fenrirscreenreader/utils/mark_utils.py new file mode 100644 index 00000000..3a341b48 --- /dev/null +++ b/src/fenrirscreenreader/utils/mark_utils.py @@ -0,0 +1,60 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + +def getTextBetweenMarks(firstMark, secondMark, inText): + if inText == None: + return '' + if not isinstance(inText, list): + inText = inText.split('\n') + if len(inText) < 1: + return '' + if firstMark == None: + return '' + if secondMark == None: + return '' + if (firstMark['y'] + 1) * (firstMark['x'] + 1) <= (secondMark['y'] + 1) * (secondMark['x'] + 1): + startMark = firstMark.copy() + endMark = secondMark.copy() + else: + endMark = firstMark.copy() + startMark = secondMark.copy() + textPart = '' + if startMark['y'] == endMark['y']: + textPart += inText[startMark['y']][startMark['x']:endMark['x'] + 1] + else: + currY = startMark['y'] + while currY <= endMark['y']: + if currY < endMark['y']: + if currY == startMark['y']: + textPart += inText[currY][startMark['x']:] + else: + textPart += inText[currY] + if len(inText[currY].strip()) != 0: + if len(textPart) - len(textPart.rstrip()) > 0: + textPart = textPart[:len(textPart.rstrip())] + "\n" + else: + textPart += '\n' + else: + textPart += inText[currY][:endMark['x'] + 1] + currY += 1 + return textPart + +def getTextBeforeMark(mark, inText): + if inText == None: + return '' + if mark == None: + return '' + return getTextBetweenMarks({'x':0,'y':0}, mark, inText) + +def getTextAfterMark(mark, inText): + if inText == None: + return '' + if mark == None: + return '' + inText = inText.split('\n') + return getTextBetweenMarks(mark, {'x':len(inText[0])-1,'y':len(inText)-1}, inText) diff --git a/src/fenrirscreenreader/utils/module_utils.py b/src/fenrirscreenreader/utils/module_utils.py new file mode 100644 index 00000000..5b141e83 --- /dev/null +++ b/src/fenrirscreenreader/utils/module_utils.py @@ -0,0 +1,19 @@ +#!/bin/python +# -*- coding: utf-8 -*- +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. +import sys +version = sys.version[:3] # we only need major.minor version. +if version in ["3.3","3.4"]: + from importlib.machinery import SourceFileLoader +else: # Python 3.5+, no support for python < 3.3. + import importlib.util + +def importModule(moduleName, moduleLocation): + if version in ["3.3","3.4"]: + return SourceFileLoader(moduleName, moduleLocation).load_module() + else: + spec = importlib.util.spec_from_file_location(moduleName, moduleLocation) + driver_mod = importlib.util.module_from_spec(spec) + spec.loader.exec_module(driver_mod) + return driver_mod diff --git a/src/fenrirscreenreader/utils/review_utils.py b/src/fenrirscreenreader/utils/review_utils.py new file mode 100644 index 00000000..61a21325 --- /dev/null +++ b/src/fenrirscreenreader/utils/review_utils.py @@ -0,0 +1,8 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug + diff --git a/src/fenrirscreenreader/utils/screen_utils.py b/src/fenrirscreenreader/utils/screen_utils.py new file mode 100644 index 00000000..f8c87b38 --- /dev/null +++ b/src/fenrirscreenreader/utils/screen_utils.py @@ -0,0 +1,117 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +from collections import Counter +import string +from select import select +from select import epoll +import select +import re + +def removeNonprintable(text): + # Get the difference of all ASCII characters from the set of printable characters + nonprintable = set([chr(i) for i in range(128)]).difference(string.printable) + # Use translate to remove all non-printable characters + return text.translate({ord(character):None for character in nonprintable}) + +def insertNewlines(string, every=64): + return '\n'.join(string[i:i+every] for i in range(0, len(string), every)) + +def splitEvery(toSplit, every=64): + return list(toSplit[i:i+every] for i in range(0, len(toSplit), every)) + +def hasMoreRead(fd): + r, w, e = select([fd], [], [], 0) + return (fd in r) + +def hasMorePollPri(fd): + p = epoll() + p.register(fd, select.POLLPRI | select.POLLERR) + r = p.poll(0) + return (fd in r) + +def trackHighlights(oldAttr, newAttr, text, lenght): + result = '' + currCursor = None + if oldAttr == newAttr: + return result, currCursor + if len(newAttr) == 0: + return result, currCursor + if len(oldAttr) != len(newAttr): + return result, currCursor + + old = splitEvery(oldAttr,lenght) + new = splitEvery(newAttr,lenght) + textLines = text.split('\n') + background = [] + + if len(textLines) - 1 != len(new): + return result, currCursor + try: + bgStat = Counter(newAttr).most_common(3) + background.append(bgStat[0][0]) + # if there is a third color add a secondary background (for dialogs for example) + if len(bgStat) > 2: + if bgStat[1][1] > 40: + background.append(bgStat[1][0]) + except Exception as e: + background.append((7,7,0,0,0,0)) + for line in range(len(new)): + if old[line] != new[line]: + for column in range(len(new[line])): + print(new[line][column]) + if old[line][column] != new[line][column]: + if not new[line][column] in background: + if not currCursor: + currCursor = {} + currCursor['x'] = column + currCursor['y'] = line + result += textLines[line][column] + result += ' ' + return result, currCursor + +''' +t = 'hallo\nwelt!' +old = ((1,1,0,0),(1,1,0,0),(1,1,0,0),(1,1,0,0),(1,1,0,0),(1,1,0,0),(1,1,0,0),(1,1,0,0),(1,1,0,0),(1,1,0,0)) +new = ((0,1,1,1),(1,1,1,1),(1,1,1,1),(1,1,1,1),(1,1,1,1),(1,1,0,0),(1,1,0,0),(1,1,0,0),(1,1,0,0),(1,1,0,0)) + +trackHighlights(old,new,t,5) +''' + +class headLineManipulation: + def __init__(self): + self.regExSingle = re.compile(r'(([^\w\s])\2{5,})') + self.regExDouble = re.compile(r'([^\w\s]{2,}){5,}') + def replaceHeadLines(self, text): + result = '' + newText = '' + lastPos = 0 + for match in self.regExDouble.finditer(text): + span = match.span() + newText += text[lastPos:span[0]] + numberOfChars = len(text[span[0]:span[1]]) + name = text[span[0]:span[1]][:2] + if name.strip(name[0]) == '': + newText += ' ' + str(numberOfChars) + ' ' + name[0] + ' ' + else: + newText += ' ' + str(int(numberOfChars / 2)) + ' ' + name + ' ' + lastPos = span[1] + newText += ' ' + text[lastPos:] + lastPos = 0 + for match in self.regExSingle.finditer(newText): + span = match.span() + result += text[lastPos:span[0]] + numberOfChars = len(newText[span[0]:span[1]]) + name = newText[span[0]:span[1]][:2] + if name.strip(name[0]) == '': + result += ' ' + str(numberOfChars) + ' ' + name[0] + ' ' + else: + result += ' ' + str(int(numberOfChars / 2)) + ' ' + name + ' ' + lastPos = span[1] + result += ' ' + newText[lastPos:] + return result + diff --git a/src/fenrirscreenreader/utils/word_utils.py b/src/fenrirscreenreader/utils/word_utils.py new file mode 100644 index 00000000..dd712ea0 --- /dev/null +++ b/src/fenrirscreenreader/utils/word_utils.py @@ -0,0 +1,122 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from fenrirscreenreader.core import debug +import string + +def getCurrentWord(currX,currY, currText): + lineBreak = False + endOfScreen = False + if currText == '': + return -1, -1, '', endOfScreen, lineBreak + if currText.strip( string.whitespace) == '': + return currX, currY, '', endOfScreen, lineBreak + x = currX + y = currY + currWord = '' + wrappedLines = currText.split('\n') + currLine = wrappedLines[y] + Found = False + while(not Found): + if not currLine[x] in string.whitespace: + if x == 0: + Found = True + else: + if currLine[x - 1] in string.whitespace: + Found = True + if not Found: + if x - 1 < 0: + if y - 1 < 0: + lineBreak = False + endOfScreen = True + return currX, currY, '', endOfScreen, lineBreak + else: + y -= 1 + currLine = wrappedLines[y] + x = len( currLine) - 1 + lineBreak = True + else: + x -= 1 + if Found: + currWord = currLine[x:] + for d in string.whitespace: + delimiterPos = currWord.find(d) + if delimiterPos != -1: + currWord = currWord[:delimiterPos] + return x, y, currWord, endOfScreen, lineBreak + return currX, currY, '', False, False + +def getPrevWord(currX,currY, currText): + lineBreak = False + endOfScreen = False + if currText == '': + return -1, -1, '', endOfScreen, lineBreak + if currText.strip( string.whitespace) == '': + return currX, currY, '', endOfScreen, lineBreak + x, y, currWord, endOfScreen, lineBreakCurrWord = getCurrentWord(currX,currY,currText) + if endOfScreen: + return x, y, currWord, endOfScreen, lineBreak + wrappedLines = currText.split('\n') + currLine = wrappedLines[y] + if x - 1 < 0: + if y - 1 < 0: + lineBreak = False + endOfScreen = True + return currX, currY, '', endOfScreen, lineBreak + else: + y -= 1 + currLine = wrappedLines[y] + x = len( currLine) - 1 + lineBreak = True + else: + x -= 1 + lineBreakCurrWord = lineBreak or lineBreakCurrWord + x, y, currWord, endOfScreen, lineBreak = getCurrentWord(x,y,currText) + lineBreak = lineBreak or lineBreakCurrWord + return x, y, currWord, endOfScreen, lineBreak + +def getNextWord(currX,currY, currText): + lineBreak = False + endOfScreen = False + if currText == '': + return -1, -1, '', endOfScreen, lineBreak + if currText.strip( string.whitespace) == '': + return currX, currY, '', endOfScreen, lineBreak + x = currX + y = currY + currWord = '' + wrappedLines = currText.split('\n') + currLine = wrappedLines[y] + Found = False + while(not Found): + if not Found: + if x + 1 > len( currLine ) - 1: + if y + 1 > len( wrappedLines ) - 1: + lineBreak = False + endOfScreen = True + return currX, currY, '', endOfScreen, lineBreak + else: + y += 1 + currLine = wrappedLines[y] + x = 0 + lineBreak = True + else: + x += 1 + if not currLine[x] in string.whitespace: + if x == 0: + Found = True + else: + if currLine[x - 1] in string.whitespace: + Found = True + if Found: + currWord = currLine[x:] + for d in string.whitespace: + delimiterPos = currWord.find(d) + if delimiterPos != -1: + currWord = currWord[:delimiterPos] + return x, y, currWord, endOfScreen, lineBreak + return currX, currY, '', False, False +