Merge branch 'bleed'
This commit is contained in:
commit
2230a45fac
58
TODO v2.0
58
TODO v2.0
@ -5,10 +5,16 @@ Things needing little knowledge are marked with "(Easy for contribution)". so ju
|
|||||||
[X] = Done
|
[X] = Done
|
||||||
|
|
||||||
Cleanups:
|
Cleanups:
|
||||||
- split oldValues := newValues out to helper function (Easy for contribution)
|
- generic list or see Tutorial mode list (convert clipboard management) (Easy for contribution)
|
||||||
|
[] next item
|
||||||
|
[] prev item
|
||||||
|
[] curr item
|
||||||
|
[] first item
|
||||||
|
[] last item
|
||||||
|
- split oldValues := newValues out to helper function
|
||||||
[] split it out
|
[] split it out
|
||||||
[] use it in vcsa driver
|
[] use it in vcsa driver
|
||||||
[] Migrate *Data.py to classes and use getter/setter (Easy for contribution)
|
- Migrate *Data.py to classes and use getter/setter (Easy for contribution)
|
||||||
[] commandsData.py
|
[] commandsData.py
|
||||||
[] eventData.py
|
[] eventData.py
|
||||||
[] generalData.py
|
[] generalData.py
|
||||||
@ -21,29 +27,22 @@ Cleanups:
|
|||||||
|
|
||||||
General:
|
General:
|
||||||
- commands
|
- commands
|
||||||
[] place last spoken to clipboard
|
[] place last spoken to clipboard (Easy for contribution)
|
||||||
- imporove attribute handling
|
- imporove attribute handling
|
||||||
[] improve attributes_curr_char
|
[] improve attributes_curr_char
|
||||||
[] add an attribute sound
|
[] add an attribute sound (Easy for contribution)
|
||||||
[] beep on cursor/ review by char (capital wins)
|
[] beep on cursor/ review by char (capital wins)
|
||||||
[] beep on review by word (once for multiple, capital wins)
|
[] beep on review by word (once for multiple, capital wins)
|
||||||
[] configurable (by char, by word, none)
|
[] configurable (by char, by word, none)
|
||||||
https://github.com/jwilk/vcsapeek/blob/master/linuxvt.py
|
https://github.com/jwilk/vcsapeek/blob/master/linuxvt.py
|
||||||
|
|
||||||
- Improved Say all
|
- Improved Say all
|
||||||
[] all the text of all pages
|
[] speech callbacks
|
||||||
[] command to stop and place review cursor at this position
|
[] speech process by word
|
||||||
[] command to slow down speech on keypress
|
[] all the text of all pages
|
||||||
|
[] command to stop and place review cursor at this position
|
||||||
- generic list or see Tutorial mode list (convert clipboard management) (Easy for contribution)
|
[] command to slow down speech on keypress
|
||||||
[] next item
|
|
||||||
[] prev item
|
|
||||||
[] curr item
|
|
||||||
[] first item
|
|
||||||
[] last item
|
|
||||||
|
|
||||||
- make it runnable via pypy3
|
- make it runnable via pypy3
|
||||||
[] wrapper script for running Fenrir to check if pypy exists, use python3 as fallback.
|
[] wrapper script for running Fenrir to check if pypy exists, use python3 as fallback.
|
||||||
|
|
||||||
Braille Support:
|
Braille Support:
|
||||||
[] brailleFocusMode:
|
[] brailleFocusMode:
|
||||||
@ -77,11 +76,11 @@ Driver:
|
|||||||
https://github.com/tvraman/emacspeak/blob/master/servers/obsolete/python/dectalk.py
|
https://github.com/tvraman/emacspeak/blob/master/servers/obsolete/python/dectalk.py
|
||||||
|
|
||||||
Settings:
|
Settings:
|
||||||
[] write settings (Easy for contribution)
|
[] write settings (Easy for contribution)
|
||||||
[] menue for settings configuration (Easy for contribution)
|
[] menue for settings configuration (Easy for contribution)
|
||||||
|
|
||||||
Application Profiles (low priority):
|
Application Profiles (low priority):
|
||||||
- reimplement process detection without subprocessing // this is started by chrys
|
- reimplement process detection without subprocessing
|
||||||
- fenrir is not able to detect the current application inside of screen.
|
- fenrir is not able to detect the current application inside of screen.
|
||||||
ps -e -H -o pid,pgrp,ppid,tty,cmd
|
ps -e -H -o pid,pgrp,ppid,tty,cmd
|
||||||
http://stackoverflow.com/questions/24861351/how-to-detect-if-python-script-is-being-run-as-a-background-process/24862213
|
http://stackoverflow.com/questions/24861351/how-to-detect-if-python-script-is-being-run-as-a-background-process/24862213
|
||||||
@ -94,7 +93,14 @@ Application Profiles (low priority):
|
|||||||
- per application shortcuts
|
- per application shortcuts
|
||||||
|
|
||||||
-----------DONE----------------
|
-----------DONE----------------
|
||||||
General:
|
Cleanups:
|
||||||
|
- inheritation for drivers
|
||||||
|
[Done] Speech (All)
|
||||||
|
[Done] Braille (All)
|
||||||
|
[Done] Sound (All)
|
||||||
|
[Done] Input (All)
|
||||||
|
[Done] Screen (All)
|
||||||
|
General:
|
||||||
Braille Support:
|
Braille Support:
|
||||||
Driver:
|
Driver:
|
||||||
Settings:
|
Settings:
|
||||||
|
@ -105,6 +105,7 @@ KEY_FENRIR,KEY_PAGEUP=prev_clipboard
|
|||||||
KEY_FENRIR,KEY_PAGEDOWN=next_clipboard
|
KEY_FENRIR,KEY_PAGEDOWN=next_clipboard
|
||||||
KEY_FENRIR,KEY_SHIFT,KEY_C=curr_clipboard
|
KEY_FENRIR,KEY_SHIFT,KEY_C=curr_clipboard
|
||||||
KEY_FENRIR,KEY_C=copy_marked_to_clipboard
|
KEY_FENRIR,KEY_C=copy_marked_to_clipboard
|
||||||
|
KEY_FENRIR,KEY_CTRL,KEY_U=copy_last_echo_to_clipboard
|
||||||
KEY_FENRIR,KEY_V=paste_clipboard
|
KEY_FENRIR,KEY_V=paste_clipboard
|
||||||
KEY_FENRIR,KEY_F5=import_clipboard_from_file
|
KEY_FENRIR,KEY_F5=import_clipboard_from_file
|
||||||
KEY_FENRIR,KEY_F6=export_clipboard_to_file
|
KEY_FENRIR,KEY_F6=export_clipboard_to_file
|
||||||
|
@ -105,6 +105,7 @@ KEY_FENRIR,KEY_PAGEUP=prev_clipboard
|
|||||||
KEY_FENRIR,KEY_PAGEDOWN=next_clipboard
|
KEY_FENRIR,KEY_PAGEDOWN=next_clipboard
|
||||||
KEY_FENRIR,KEY_SHIFT,KEY_C=curr_clipboard
|
KEY_FENRIR,KEY_SHIFT,KEY_C=curr_clipboard
|
||||||
KEY_FENRIR,KEY_C=copy_marked_to_clipboard
|
KEY_FENRIR,KEY_C=copy_marked_to_clipboard
|
||||||
|
KEY_FENRIR,KEY_CTRL,KEY_U=copy_last_echo_to_clipboard
|
||||||
KEY_FENRIR,KEY_V=paste_clipboard
|
KEY_FENRIR,KEY_V=paste_clipboard
|
||||||
KEY_FENRIR,KEY_F5=import_clipboard_from_file
|
KEY_FENRIR,KEY_F5=import_clipboard_from_file
|
||||||
KEY_FENRIR,KEY_F6=export_clipboard_to_file
|
KEY_FENRIR,KEY_F6=export_clipboard_to_file
|
||||||
|
3
setup.py
3
setup.py
@ -7,7 +7,7 @@ from setuptools import find_packages
|
|||||||
from setuptools import setup
|
from setuptools import setup
|
||||||
|
|
||||||
fenrirVersion = '1.5'
|
fenrirVersion = '1.5'
|
||||||
packageVersion = 'post10'
|
packageVersion = 'post11'
|
||||||
|
|
||||||
# handle flags for package manager like yaourt and pacaur.
|
# handle flags for package manager like yaourt and pacaur.
|
||||||
forceSettings = False
|
forceSettings = False
|
||||||
@ -97,6 +97,7 @@ setup(
|
|||||||
"pyudev",
|
"pyudev",
|
||||||
"setuptools",
|
"setuptools",
|
||||||
"pexpect",
|
"pexpect",
|
||||||
|
"pyttsx3",
|
||||||
],
|
],
|
||||||
|
|
||||||
)
|
)
|
||||||
|
@ -5,10 +5,11 @@
|
|||||||
# By Chrys, Storm Dragon, and contributers.
|
# By Chrys, Storm Dragon, and contributers.
|
||||||
|
|
||||||
from core import debug
|
from core import debug
|
||||||
|
from core.brailleDriver import brailleDriver
|
||||||
|
|
||||||
class driver():
|
class driver(brailleDriver):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._isInitialized = False
|
brailleDriver.__init__(self)
|
||||||
self._brl = None
|
self._brl = None
|
||||||
|
|
||||||
def initialize(self, environment):
|
def initialize(self, environment):
|
||||||
|
49
src/fenrir/brailleDriver/debugDriver.py
Normal file
49
src/fenrir/brailleDriver/debugDriver.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#!/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Fenrir TTY screen reader
|
||||||
|
# By Chrys, Storm Dragon, and contributers.
|
||||||
|
|
||||||
|
from core import debug
|
||||||
|
from 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')
|
@ -5,51 +5,8 @@
|
|||||||
# By Chrys, Storm Dragon, and contributers.
|
# By Chrys, Storm Dragon, and contributers.
|
||||||
|
|
||||||
from core import debug
|
from core import debug
|
||||||
|
from core.brailleDriver import brailleDriver
|
||||||
|
|
||||||
class driver():
|
class driver(brailleDriver):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.printMessages = False
|
brailleDriver.__init__(self)
|
||||||
|
|
||||||
def initialize(self, environment):
|
|
||||||
self.env = environment
|
|
||||||
self._isInitialized = True
|
|
||||||
self.deviceSize = (40,0)
|
|
||||||
if self.printMessages:
|
|
||||||
print('BrailleDummyDriver: Initialize')
|
|
||||||
|
|
||||||
|
|
||||||
def getDeviceSize(self):
|
|
||||||
if not self._isInitialized:
|
|
||||||
return (0,0)
|
|
||||||
if self.printMessages:
|
|
||||||
print('BrailleDummyDriver: getDeviceSize ' + str(self.deviceSize))
|
|
||||||
return self.deviceSize
|
|
||||||
|
|
||||||
def writeText(self,text):
|
|
||||||
if not self._isInitialized:
|
|
||||||
return
|
|
||||||
if self.printMessages:
|
|
||||||
print('BrailleDummyDriver: writeText:' + str(text))
|
|
||||||
print('BrailleDummyDriver: -----------------------------------')
|
|
||||||
|
|
||||||
def connectDevice(self):
|
|
||||||
if self.printMessages:
|
|
||||||
print('BrailleDummyDriver: connectDevice')
|
|
||||||
|
|
||||||
def enterScreen(self, screen):
|
|
||||||
if not self._isInitialized:
|
|
||||||
return
|
|
||||||
if self.printMessages:
|
|
||||||
print('BrailleDummyDriver: enterScreen')
|
|
||||||
|
|
||||||
def leveScreen(self):
|
|
||||||
if not self._isInitialized:
|
|
||||||
return
|
|
||||||
if self.printMessages:
|
|
||||||
print('BrailleDummyDriver: leveScreen')
|
|
||||||
|
|
||||||
def shutdown(self):
|
|
||||||
if not self._isInitialized:
|
|
||||||
return
|
|
||||||
if self.printMessages:
|
|
||||||
print('BrailleDummyDriver: Shutdown')
|
|
||||||
|
28
src/fenrir/commands/commands/copy_last_echo_to_clipboard.py
Normal file
28
src/fenrir/commands/commands/copy_last_echo_to_clipboard.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#!/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Fenrir TTY screen reader
|
||||||
|
# By Chrys, Storm Dragon, and contributers.
|
||||||
|
|
||||||
|
from core import debug
|
||||||
|
from 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 currently selected clipboard')
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
lastEcho = self.env['runtime']['outputManager'].getLastEcho()
|
||||||
|
self.env['commandBuffer']['clipboard'] = [lastEcho] + self.env['commandBuffer']['clipboard'][:self.env['runtime']['settingsManager'].getSettingAsInt('general', 'numberOfClipboards') -1]
|
||||||
|
self.env['commandBuffer']['currClipboard'] = 0
|
||||||
|
|
||||||
|
self.env['runtime']['outputManager'].presentText(lastEcho, soundIcon='CopyToClipboard', interrupt=True)
|
||||||
|
|
||||||
|
def setCallback(self, callback):
|
||||||
|
pass
|
41
src/fenrir/core/brailleDriver.py
Normal file
41
src/fenrir/core/brailleDriver.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#!/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Fenrir TTY screen reader
|
||||||
|
# By Chrys, Storm Dragon, and contributers.
|
||||||
|
|
||||||
|
from 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
|
49
src/fenrir/core/inputDriver.py
Normal file
49
src/fenrir/core/inputDriver.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#!/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Fenrir TTY screen reader
|
||||||
|
# By Chrys, Storm Dragon, and contributers.
|
||||||
|
|
||||||
|
from 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)
|
||||||
|
if not self._initialized:
|
||||||
|
return None
|
||||||
|
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()
|
@ -10,7 +10,7 @@ import string, time
|
|||||||
|
|
||||||
class outputManager():
|
class outputManager():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
self.lastEcho = ''
|
||||||
def initialize(self, environment):
|
def initialize(self, environment):
|
||||||
self.env = environment
|
self.env = environment
|
||||||
self.env['runtime']['settingsManager'].loadDriver(\
|
self.env['runtime']['settingsManager'].loadDriver(\
|
||||||
@ -37,11 +37,12 @@ class outputManager():
|
|||||||
if toAnnounceCapital:
|
if toAnnounceCapital:
|
||||||
if self.playSoundIcon('capital', False):
|
if self.playSoundIcon('capital', False):
|
||||||
toAnnounceCapital = False
|
toAnnounceCapital = False
|
||||||
|
self.lastEcho = text
|
||||||
self.speakText(text, interrupt, ignorePunctuation,toAnnounceCapital)
|
self.speakText(text, interrupt, ignorePunctuation,toAnnounceCapital)
|
||||||
if flush:
|
if flush:
|
||||||
self.brailleText(text, flush)
|
self.brailleText(text, flush)
|
||||||
|
def getLastEcho(self):
|
||||||
|
return self.lastEcho
|
||||||
def speakText(self, text, interrupt=True, ignorePunctuation=False, announceCapital=False):
|
def speakText(self, text, interrupt=True, ignorePunctuation=False, announceCapital=False):
|
||||||
if not self.env['runtime']['settingsManager'].getSettingAsBool('speech', 'enabled'):
|
if not self.env['runtime']['settingsManager'].getSettingAsBool('speech', 'enabled'):
|
||||||
self.env['runtime']['debug'].writeDebugOut("Speech disabled in outputManager.speakText",debug.debugLevel.INFO)
|
self.env['runtime']['debug'].writeDebugOut("Speech disabled in outputManager.speakText",debug.debugLevel.INFO)
|
||||||
@ -110,7 +111,7 @@ class outputManager():
|
|||||||
self.env['output']['messageOffset'] = {'x':0,'y':0}
|
self.env['output']['messageOffset'] = {'x':0,'y':0}
|
||||||
self.env['output']['messageText'] = text
|
self.env['output']['messageText'] = text
|
||||||
displayText = self.getBrailleTextWithOffset(self.env['output']['messageText'], self.env['output']['messageOffset'])
|
displayText = self.getBrailleTextWithOffset(self.env['output']['messageText'], self.env['output']['messageOffset'])
|
||||||
self.env['runtime']['brailleDriver'].writeText('flush'+displayText)
|
self.env['runtime']['brailleDriver'].writeText('flush '+ displayText)
|
||||||
else:
|
else:
|
||||||
if self.env['output']['nextFlush'] < time.time():
|
if self.env['output']['nextFlush'] < time.time():
|
||||||
if self.env['output']['messageText'] != '':
|
if self.env['output']['messageText'] != '':
|
||||||
@ -121,7 +122,7 @@ class outputManager():
|
|||||||
x, y, self.env['output']['brlText'] = \
|
x, y, self.env['output']['brlText'] = \
|
||||||
line_utils.getCurrentLine(cursor['x'], cursor['y'], self.env['screen']['newContentText'])
|
line_utils.getCurrentLine(cursor['x'], cursor['y'], self.env['screen']['newContentText'])
|
||||||
displayText = self.getBrailleTextWithOffset(self.env['screen']['newContentText'], self.env['output']['cursorOffset'], cursor)
|
displayText = self.getBrailleTextWithOffset(self.env['screen']['newContentText'], self.env['output']['cursorOffset'], cursor)
|
||||||
self.env['runtime']['brailleDriver'].writeText('notflush'+displayText)
|
self.env['runtime']['brailleDriver'].writeText('notflush ' + displayText)
|
||||||
else:
|
else:
|
||||||
displayText = self.getBrailleTextWithOffset(self.env['output']['messageText'], self.env['output']['messageOffset'])
|
displayText = self.getBrailleTextWithOffset(self.env['output']['messageText'], self.env['output']['messageOffset'])
|
||||||
self.env['runtime']['brailleDriver'].writeText('flush'+displayText)
|
self.env['runtime']['brailleDriver'].writeText('flush'+displayText)
|
||||||
|
48
src/fenrir/core/screenDriver.py
Normal file
48
src/fenrir/core/screenDriver.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#!/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Fenrir TTY screen reader
|
||||||
|
# By Chrys, Storm Dragon, and contributers.
|
||||||
|
#attrib:
|
||||||
|
#http://rampex.ihep.su/Linux/linux_howto/html/tutorials/mini/Colour-ls-6.html
|
||||||
|
#0 = black, 1 = blue, 2 = green, 3 = cyan, 4 = red, 5 = purple, 6 = brown/yellow, 7 = white.
|
||||||
|
#https://github.com/jwilk/vcsapeek/blob/master/linuxvt.py
|
||||||
|
#blink = 5 if attr & 1 else 0
|
||||||
|
#bold = 1 if attr & 16 else 0
|
||||||
|
|
||||||
|
|
||||||
|
from 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
|
||||||
|
|
47
src/fenrir/core/soundDriver.py
Normal file
47
src/fenrir/core/soundDriver.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#!/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Fenrir TTY screen reader
|
||||||
|
# By Chrys, Storm Dragon, and contributers.
|
||||||
|
|
||||||
|
from 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
|
102
src/fenrir/core/speechDriver.py
Normal file
102
src/fenrir/core/speechDriver.py
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Fenrir TTY screen reader
|
||||||
|
# By Chrys, Storm Dragon, and contributers.
|
||||||
|
|
||||||
|
from 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 not isinstance(voice, float):
|
||||||
|
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
|
66
src/fenrir/inputDriver/debugDriver.py
Normal file
66
src/fenrir/inputDriver/debugDriver.py
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#!/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Fenrir TTY screen reader
|
||||||
|
# By Chrys, Storm Dragon, and contributers.
|
||||||
|
|
||||||
|
import time
|
||||||
|
from core import debug
|
||||||
|
from 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__')
|
||||||
|
|
||||||
|
|
@ -6,55 +6,13 @@
|
|||||||
|
|
||||||
import time
|
import time
|
||||||
from core import debug
|
from core import debug
|
||||||
|
from core.inputDriver import inputDriver
|
||||||
|
|
||||||
class driver():
|
class driver(inputDriver):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._initialized = False
|
inputDriver.__init__(self)
|
||||||
|
|
||||||
def initialize(self, environment):
|
|
||||||
self.env = environment
|
|
||||||
|
|
||||||
def shutdown(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def getInputEvent(self):
|
def getInputEvent(self):
|
||||||
time.sleep(0.05)
|
time.sleep(0.1)
|
||||||
if not self._initialized:
|
if not self._initialized:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
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()
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,16 +30,16 @@ from ctypes import c_bool
|
|||||||
from core.eventData import fenrirEventType
|
from core.eventData import fenrirEventType
|
||||||
from core import inputData
|
from core import inputData
|
||||||
from core import debug
|
from core import debug
|
||||||
|
from core.inputDriver import inputDriver
|
||||||
|
|
||||||
|
class driver(inputDriver):
|
||||||
class driver():
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
inputDriver.__init__(self)
|
||||||
self._manager = multiprocessing.Manager()
|
self._manager = multiprocessing.Manager()
|
||||||
self.iDevices = {}
|
self.iDevices = {}
|
||||||
self.iDevicesFD = self._manager.list()
|
self.iDevicesFD = self._manager.list()
|
||||||
self.uDevices = {}
|
self.uDevices = {}
|
||||||
self.iDeviceNo = 0
|
self.iDeviceNo = 0
|
||||||
self._initialized = False
|
|
||||||
self.watchDog = Value(c_bool, True)
|
self.watchDog = Value(c_bool, True)
|
||||||
def initialize(self, environment):
|
def initialize(self, environment):
|
||||||
self.env = environment
|
self.env = environment
|
||||||
@ -70,9 +70,6 @@ class driver():
|
|||||||
def plugInputDeviceWatchdogTimer(self, active):
|
def plugInputDeviceWatchdogTimer(self, active):
|
||||||
time.sleep(2.5)
|
time.sleep(2.5)
|
||||||
return time.time()
|
return time.time()
|
||||||
def shutdown(self):
|
|
||||||
if not self._initialized:
|
|
||||||
return
|
|
||||||
def inputWatchdog(self,active , params):
|
def inputWatchdog(self,active , params):
|
||||||
try:
|
try:
|
||||||
deviceFd = []
|
deviceFd = []
|
||||||
@ -323,10 +320,6 @@ class driver():
|
|||||||
self.removeDevice(fd)
|
self.removeDevice(fd)
|
||||||
self.iDevices.clear()
|
self.iDevices.clear()
|
||||||
self.uDevices.clear()
|
self.uDevices.clear()
|
||||||
self.iDeviceNo = 0
|
self.iDeviceNo = 0
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
if not self._initialized:
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
|
12
src/fenrir/screenDriver/dummyDriver.py
Normal file
12
src/fenrir/screenDriver/dummyDriver.py
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Fenrir TTY screen reader
|
||||||
|
# By Chrys, Storm Dragon, and contributers.
|
||||||
|
|
||||||
|
from core import debug
|
||||||
|
from core.screenDriver import screenDriver
|
||||||
|
|
||||||
|
class driver(screenDriver):
|
||||||
|
def __init__(self):
|
||||||
|
screenDriver.__init__(self)
|
372
src/fenrir/screenDriver/ptyDriver.py
Normal file
372
src/fenrir/screenDriver/ptyDriver.py
Normal file
@ -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 utils import screen_utils
|
||||||
|
from fcntl import ioctl
|
||||||
|
from struct import unpack_from, unpack, pack
|
||||||
|
from core import debug
|
||||||
|
from core.eventData import fenrirEventType
|
||||||
|
from 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'])
|
||||||
|
|
@ -28,10 +28,11 @@ from fcntl import ioctl
|
|||||||
from struct import unpack_from, unpack, pack
|
from struct import unpack_from, unpack, pack
|
||||||
from core import debug
|
from core import debug
|
||||||
from core.eventData import fenrirEventType
|
from core.eventData import fenrirEventType
|
||||||
|
from core.screenDriver import screenDriver
|
||||||
|
|
||||||
|
class driver(screenDriver):
|
||||||
class driver():
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
screenDriver.__init__(self)
|
||||||
self.vcsaDevicePath = '/dev/vcsa'
|
self.vcsaDevicePath = '/dev/vcsa'
|
||||||
self.ListSessions = None
|
self.ListSessions = None
|
||||||
self.charmap = {}
|
self.charmap = {}
|
||||||
@ -41,8 +42,6 @@ class driver():
|
|||||||
def initialize(self, environment):
|
def initialize(self, environment):
|
||||||
self.env = environment
|
self.env = environment
|
||||||
self.env['runtime']['processManager'].addCustomEventThread(self.updateWatchdog)
|
self.env['runtime']['processManager'].addCustomEventThread(self.updateWatchdog)
|
||||||
def shutdown(self):
|
|
||||||
pass
|
|
||||||
def getCurrScreen(self):
|
def getCurrScreen(self):
|
||||||
self.env['screen']['oldTTY'] = self.env['screen']['newTTY']
|
self.env['screen']['oldTTY'] = self.env['screen']['newTTY']
|
||||||
try:
|
try:
|
||||||
|
56
src/fenrir/soundDriver/debugDriver.py
Normal file
56
src/fenrir/soundDriver/debugDriver.py
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#!/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Fenrir TTY screen reader
|
||||||
|
# By Chrys, Storm Dragon, and contributers.
|
||||||
|
|
||||||
|
from core import debug
|
||||||
|
from 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))
|
@ -5,51 +5,8 @@
|
|||||||
# By Chrys, Storm Dragon, and contributers.
|
# By Chrys, Storm Dragon, and contributers.
|
||||||
|
|
||||||
from core import debug
|
from core import debug
|
||||||
|
from core.soundDriver import soundDriver
|
||||||
|
|
||||||
class driver():
|
class driver(soundDriver):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.volume = None
|
soundDriver.__init__(self)
|
||||||
self._initialized = False
|
|
||||||
|
|
||||||
def initialize(self, environment):
|
|
||||||
self.env = environment
|
|
||||||
self._initialized = True
|
|
||||||
print('SoundDummyDriver: Initialize')
|
|
||||||
|
|
||||||
def shutdown(self):
|
|
||||||
if not self._initialized:
|
|
||||||
return
|
|
||||||
self.cancel()
|
|
||||||
print('SoundDummyDriver: Shutdown')
|
|
||||||
|
|
||||||
def playFrequence(self, frequence = 1000, duration = 0.3, adjustVolume = 0):
|
|
||||||
if not self._initialized:
|
|
||||||
return
|
|
||||||
if interrupt:
|
|
||||||
self.cancel()
|
|
||||||
print('SoundDummyDriver: playFrequence:' + ' freq:' + str(frequence) + ' duration:' + str(duration) + ' adjustVolume:' + str(adjustVolume) )
|
|
||||||
print('SoundDummyDriver: -----------------------------------')
|
|
||||||
|
|
||||||
def playSoundFile(self, filePath, interrupt = True):
|
|
||||||
if not self._initialized:
|
|
||||||
return
|
|
||||||
if interrupt:
|
|
||||||
self.cancel()
|
|
||||||
print('SoundDummyDriver: playSoundFile:' + str(filePath))
|
|
||||||
print('SoundDummyDriver: -----------------------------------')
|
|
||||||
|
|
||||||
def cancel(self):
|
|
||||||
if not self._initialized:
|
|
||||||
return
|
|
||||||
print('SoundDummyDriver: Cancel')
|
|
||||||
|
|
||||||
def setCallback(self, callback):
|
|
||||||
if not self._initialized:
|
|
||||||
return
|
|
||||||
print('SoundDummyDriver: setCallback')
|
|
||||||
|
|
||||||
def setVolume(self, volume):
|
|
||||||
if not self._initialized:
|
|
||||||
return
|
|
||||||
self.volume = volume
|
|
||||||
print('SoundDummyDriver: setVolume:' + str(self.volume))
|
|
||||||
|
@ -6,15 +6,15 @@
|
|||||||
|
|
||||||
from core import debug
|
from core import debug
|
||||||
import subprocess
|
import subprocess
|
||||||
|
from core.soundDriver import soundDriver
|
||||||
|
|
||||||
class driver():
|
class driver(soundDriver):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
soundDriver.__init__(self)
|
||||||
self.proc = None
|
self.proc = None
|
||||||
self.volume = 1.0
|
|
||||||
self.soundType = ''
|
self.soundType = ''
|
||||||
self.soundFileCommand = ''
|
self.soundFileCommand = ''
|
||||||
self.frequenceCommand = ''
|
self.frequenceCommand = ''
|
||||||
self._initialized = False
|
|
||||||
def initialize(self, environment):
|
def initialize(self, environment):
|
||||||
self.env = environment
|
self.env = environment
|
||||||
self.soundFileCommand = self.env['runtime']['settingsManager'].getSetting('sound', 'genericPlayFileCommand')
|
self.soundFileCommand = self.env['runtime']['settingsManager'].getSetting('sound', 'genericPlayFileCommand')
|
||||||
@ -24,10 +24,7 @@ class driver():
|
|||||||
if self.frequenceCommand == '':
|
if self.frequenceCommand == '':
|
||||||
self.frequenceCommand = 'play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence'
|
self.frequenceCommand = 'play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence'
|
||||||
self._initialized = True
|
self._initialized = True
|
||||||
def shutdown(self):
|
|
||||||
if not self._initialized:
|
|
||||||
return
|
|
||||||
self.cancel()
|
|
||||||
def playFrequence(self, frequence = 1000, duration = 0.3, adjustVolume = 0):
|
def playFrequence(self, frequence = 1000, duration = 0.3, adjustVolume = 0):
|
||||||
if not self._initialized:
|
if not self._initialized:
|
||||||
return
|
return
|
||||||
@ -56,11 +53,4 @@ class driver():
|
|||||||
self.proc.kill()
|
self.proc.kill()
|
||||||
if self.soundType == 'frequence':
|
if self.soundType == 'frequence':
|
||||||
self.proc.kill()
|
self.proc.kill()
|
||||||
self.soundType = ''
|
self.soundType = ''
|
||||||
def setCallback(self, callback):
|
|
||||||
if not self._initialized:
|
|
||||||
return
|
|
||||||
def setVolume(self, volume):
|
|
||||||
if not self._initialized:
|
|
||||||
return
|
|
||||||
self.volume = volume
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
from core import debug
|
from core import debug
|
||||||
import time, threading
|
import time, threading
|
||||||
|
from core.soundDriver import soundDriver
|
||||||
|
|
||||||
_gstreamerAvailable = False
|
_gstreamerAvailable = False
|
||||||
try:
|
try:
|
||||||
@ -19,12 +19,11 @@ except Exception as e:
|
|||||||
_gstreamerAvailable = False
|
_gstreamerAvailable = False
|
||||||
_availableError = str(e)
|
_availableError = str(e)
|
||||||
|
|
||||||
class driver:
|
class driver(soundDriver):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
soundDriver.__init__(self)
|
||||||
self._source = None
|
self._source = None
|
||||||
self._sink = None
|
self._sink = None
|
||||||
self.volume = 1
|
|
||||||
self._initialized = False
|
|
||||||
|
|
||||||
def initialize(self, environment):
|
def initialize(self, environment):
|
||||||
self.env = environment
|
self.env = environment
|
||||||
@ -112,10 +111,3 @@ class driver:
|
|||||||
return
|
return
|
||||||
self._player.set_state(Gst.State.NULL)
|
self._player.set_state(Gst.State.NULL)
|
||||||
self._pipeline.set_state(Gst.State.NULL)
|
self._pipeline.set_state(Gst.State.NULL)
|
||||||
def setVolume(self, volume):
|
|
||||||
if not self._initialized:
|
|
||||||
return
|
|
||||||
self.volume = volume
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
74
src/fenrir/speechDriver/debugDriver.py
Normal file
74
src/fenrir/speechDriver/debugDriver.py
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Fenrir TTY screen reader
|
||||||
|
# By Chrys, Storm Dragon, and contributers.
|
||||||
|
# generic driver
|
||||||
|
|
||||||
|
from core import debug
|
||||||
|
from 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))
|
@ -6,65 +6,8 @@
|
|||||||
# generic driver
|
# generic driver
|
||||||
|
|
||||||
from core import debug
|
from core import debug
|
||||||
|
from core.speechDriver import speechDriver
|
||||||
|
|
||||||
class driver():
|
class driver(speechDriver):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
speechDriver.__init__(self)
|
||||||
def initialize(self, environment):
|
|
||||||
self._isInitialized = True
|
|
||||||
self.env = environment
|
|
||||||
print('SpeechDummyDriver: Iitialize')
|
|
||||||
|
|
||||||
def shutdown(self):
|
|
||||||
print('SpeechDummyDriver: Shutdown')
|
|
||||||
|
|
||||||
def speak(self,text, queueable=True):
|
|
||||||
if not self._isInitialized:
|
|
||||||
return
|
|
||||||
if not queueable:
|
|
||||||
self.cancel()
|
|
||||||
print('SpeechDummyDriver: Speak:'+text)
|
|
||||||
print('SpeechDummyDriver: -----------------------------------')
|
|
||||||
|
|
||||||
def cancel(self):
|
|
||||||
if not self._isInitialized:
|
|
||||||
return
|
|
||||||
print('SpeechDummyDriver: Cancel')
|
|
||||||
|
|
||||||
def setCallback(self, callback):
|
|
||||||
print('SpeechDummyDriver: setCallback')
|
|
||||||
|
|
||||||
def clear_buffer(self):
|
|
||||||
if not self._isInitialized:
|
|
||||||
return
|
|
||||||
print('SpeechDummyDriver: clear_buffer')
|
|
||||||
|
|
||||||
def setVoice(self, voice):
|
|
||||||
if not self._isInitialized:
|
|
||||||
return
|
|
||||||
print('SpeechDummyDriver: setVoice:' + str(voice))
|
|
||||||
|
|
||||||
def setPitch(self, pitch):
|
|
||||||
if not self._isInitialized:
|
|
||||||
return
|
|
||||||
print('SpeechDummyDriver: setPitch:' + str(pitch))
|
|
||||||
|
|
||||||
def setRate(self, rate):
|
|
||||||
if not self._isInitialized:
|
|
||||||
return
|
|
||||||
print('SpeechDummyDriver: setRate:' + str(rate))
|
|
||||||
|
|
||||||
def setModule(self, module):
|
|
||||||
if not self._isInitialized:
|
|
||||||
return
|
|
||||||
print('SpeechDummyDriver: setModule:' + str(module))
|
|
||||||
|
|
||||||
def setLanguage(self, language):
|
|
||||||
if not self._isInitialized:
|
|
||||||
return
|
|
||||||
print('SpeechDummyDriver: setLanguage:' + str(language))
|
|
||||||
|
|
||||||
def setVolume(self, volume):
|
|
||||||
if not self._isInitialized:
|
|
||||||
return
|
|
||||||
print('SpeechDummyDriver: setVolume:' + str(volume))
|
|
||||||
|
@ -10,12 +10,12 @@ from subprocess import Popen, PIPE
|
|||||||
import pexpect
|
import pexpect
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
from core.speechDriver import speechDriver
|
||||||
|
|
||||||
class driver():
|
class driver(speechDriver):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
speechDriver.__init__(self)
|
||||||
def initialize(self, environment):
|
def initialize(self, environment):
|
||||||
self._isInitialized = False
|
|
||||||
self.env = environment
|
self.env = environment
|
||||||
try:
|
try:
|
||||||
self.server = pexpect.spawnu('tclsh ' + self.env['runtime']['settingsManager'].getSetting('speech', 'serverPath'))
|
self.server = pexpect.spawnu('tclsh ' + self.env['runtime']['settingsManager'].getSetting('speech', 'serverPath'))
|
||||||
@ -55,20 +55,6 @@ class driver():
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.env['runtime']['debug'].writeDebugOut('speechDriver:cancel:self.server.sendline():' + str(e),debug.debugLevel.ERROR)
|
self.env['runtime']['debug'].writeDebugOut('speechDriver:cancel:self.server.sendline():' + str(e),debug.debugLevel.ERROR)
|
||||||
|
|
||||||
def setCallback(self, callback):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def clear_buffer(self):
|
|
||||||
if not self._isInitialized:
|
|
||||||
return
|
|
||||||
|
|
||||||
def setVoice(self, voice):
|
|
||||||
if not self._isInitialized:
|
|
||||||
return
|
|
||||||
|
|
||||||
def setPitch(self, pitch):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def setRate(self, rate):
|
def setRate(self, rate):
|
||||||
if not self._isInitialized:
|
if not self._isInitialized:
|
||||||
return
|
return
|
||||||
@ -77,11 +63,7 @@ class driver():
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.env['runtime']['debug'].writeDebugOut('speechDriver:setRate:self.server.sendline():' + str(e),debug.debugLevel.ERROR)
|
self.env['runtime']['debug'].writeDebugOut('speechDriver:setRate:self.server.sendline():' + str(e),debug.debugLevel.ERROR)
|
||||||
|
|
||||||
def setModule(self, module):
|
|
||||||
pass
|
|
||||||
def setLanguage(self, language):
|
def setLanguage(self, language):
|
||||||
if not self._isInitialized:
|
if not self._isInitialized:
|
||||||
return
|
return
|
||||||
self.server.sendline('set_lang ' + language + '')
|
self.server.sendline('set_lang ' + language + '')
|
||||||
def setVolume(self, volume):
|
|
||||||
pass
|
|
||||||
|
@ -6,11 +6,12 @@
|
|||||||
# Espeak driver
|
# Espeak driver
|
||||||
|
|
||||||
from core import debug
|
from core import debug
|
||||||
|
from core.speechDriver import speechDriver
|
||||||
|
|
||||||
class driver():
|
class driver(speechDriver):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
speechDriver.__init__(self)
|
||||||
self._es = None
|
self._es = None
|
||||||
self._isInitialized = False
|
|
||||||
|
|
||||||
def initialize(self, environment):
|
def initialize(self, environment):
|
||||||
self.env = environment
|
self.env = environment
|
||||||
@ -21,15 +22,18 @@ class driver():
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR)
|
self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR)
|
||||||
self._initialized = False
|
self._initialized = False
|
||||||
|
|
||||||
def shutdown(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def speak(self,text, interrupt=True):
|
def speak(self,text, interrupt=True):
|
||||||
if not self._isInitialized:
|
if not self._isInitialized:
|
||||||
return
|
return
|
||||||
if not interrupt:
|
if not interrupt:
|
||||||
self.cancel()
|
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)
|
self._es.synth(text)
|
||||||
|
|
||||||
def cancel(self):
|
def cancel(self):
|
||||||
@ -38,20 +42,6 @@ class driver():
|
|||||||
self._es.cancel()
|
self._es.cancel()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def setCallback(self, callback):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def clear_buffer(self):
|
|
||||||
if not self._isInitialized:
|
|
||||||
return
|
|
||||||
|
|
||||||
def setVoice(self, voice):
|
|
||||||
if not self._isInitialized:
|
|
||||||
return
|
|
||||||
if voice =='':
|
|
||||||
return
|
|
||||||
return self._es.set_voice(voice)
|
|
||||||
|
|
||||||
def setPitch(self, pitch):
|
def setPitch(self, pitch):
|
||||||
if not self._isInitialized:
|
if not self._isInitialized:
|
||||||
return
|
return
|
||||||
@ -62,17 +52,6 @@ class driver():
|
|||||||
return
|
return
|
||||||
return self._es.set_parameter(self._es.Parameter().Rate, int(rate * 500 + 100))
|
return self._es.set_parameter(self._es.Parameter().Rate, int(rate * 500 + 100))
|
||||||
|
|
||||||
def setModule(self, module):
|
|
||||||
if not self._isInitialized:
|
|
||||||
return
|
|
||||||
|
|
||||||
def setLanguage(self, language):
|
|
||||||
if not self._isInitialized:
|
|
||||||
return
|
|
||||||
if language =='':
|
|
||||||
return
|
|
||||||
return self._es.set_voice(language)
|
|
||||||
|
|
||||||
def setVolume(self, volume):
|
def setVolume(self, volume):
|
||||||
if not self._isInitialized:
|
if not self._isInitialized:
|
||||||
return
|
return
|
||||||
|
@ -9,6 +9,7 @@ from core import debug
|
|||||||
from threading import Thread, Lock
|
from threading import Thread, Lock
|
||||||
from queue import Queue, Empty
|
from queue import Queue, Empty
|
||||||
from subprocess import Popen
|
from subprocess import Popen
|
||||||
|
from core.speechDriver import speechDriver
|
||||||
|
|
||||||
class speakQueue(Queue):
|
class speakQueue(Queue):
|
||||||
def clear(self):
|
def clear(self):
|
||||||
@ -18,18 +19,13 @@ class speakQueue(Queue):
|
|||||||
except Empty:
|
except Empty:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class driver():
|
class driver(speechDriver):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
speechDriver.__init__(self)
|
||||||
self.proc = None
|
self.proc = None
|
||||||
self.speechThread = Thread(target=self.worker)
|
self.speechThread = Thread(target=self.worker)
|
||||||
self.lock = Lock()
|
self.lock = Lock()
|
||||||
self.textQueue = speakQueue()
|
self.textQueue = speakQueue()
|
||||||
self.volume = ''
|
|
||||||
self.rate = ''
|
|
||||||
self.pitch = ''
|
|
||||||
self.module = ''
|
|
||||||
self.language = ''
|
|
||||||
self.voice = ''
|
|
||||||
def initialize(self, environment):
|
def initialize(self, environment):
|
||||||
self.env = environment
|
self.env = environment
|
||||||
self.minVolume = self.env['runtime']['settingsManager'].getSettingAsInt('speech', 'fenrirMinVolume')
|
self.minVolume = self.env['runtime']['settingsManager'].getSettingAsInt('speech', 'fenrirMinVolume')
|
||||||
|
86
src/fenrir/speechDriver/pyttsxDriver.py
Normal file
86
src/fenrir/speechDriver/pyttsxDriver.py
Normal file
@ -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 core import debug
|
||||||
|
from 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
|
@ -6,12 +6,12 @@
|
|||||||
# speech-dispatcher driver
|
# speech-dispatcher driver
|
||||||
|
|
||||||
from core import debug
|
from core import debug
|
||||||
|
from core.speechDriver import speechDriver
|
||||||
|
|
||||||
class driver():
|
class driver(speechDriver):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
speechDriver.__init__(self)
|
||||||
self._sd = None
|
self._sd = None
|
||||||
self._isInitialized = False
|
|
||||||
self._language = ''
|
|
||||||
|
|
||||||
def initialize(self, environment):
|
def initialize(self, environment):
|
||||||
self.env = environment
|
self.env = environment
|
||||||
@ -22,7 +22,6 @@ class driver():
|
|||||||
self._isInitialized = True
|
self._isInitialized = True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.env['runtime']['debug'].writeDebugOut('speechDriver initialize:' + str(e),debug.debugLevel.ERROR)
|
self.env['runtime']['debug'].writeDebugOut('speechDriver initialize:' + str(e),debug.debugLevel.ERROR)
|
||||||
self._initialized = False
|
|
||||||
|
|
||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
if not self._isInitialized:
|
if not self._isInitialized:
|
||||||
@ -42,7 +41,18 @@ class driver():
|
|||||||
if not self._isInitialized:
|
if not self._isInitialized:
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
self._sd.set_synthesis_voice(self._language)
|
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 != '':
|
||||||
|
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.set_punctuation(self._punct.NONE)
|
||||||
self._sd.speak(text)
|
self._sd.speak(text)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -57,23 +67,7 @@ class driver():
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.env['runtime']['debug'].writeDebugOut('speechDriver cancel:' + str(e),debug.debugLevel.ERROR)
|
self.env['runtime']['debug'].writeDebugOut('speechDriver cancel:' + str(e),debug.debugLevel.ERROR)
|
||||||
self._isInitialized = False
|
self._isInitialized = False
|
||||||
|
|
||||||
def setCallback(self, callback):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def clear_buffer(self):
|
|
||||||
if not self._isInitialized:
|
|
||||||
return
|
|
||||||
|
|
||||||
def setVoice(self, voice):
|
|
||||||
if not self._isInitialized:
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
if voice != '':
|
|
||||||
self._sd.set_voice(voice)
|
|
||||||
except Exception as e:
|
|
||||||
self.env['runtime']['debug'].writeDebugOut('speechDriver setVoice:' + str(e),debug.debugLevel.ERROR)
|
|
||||||
|
|
||||||
def setPitch(self, pitch):
|
def setPitch(self, pitch):
|
||||||
if not self._isInitialized:
|
if not self._isInitialized:
|
||||||
return
|
return
|
||||||
@ -88,20 +82,7 @@ class driver():
|
|||||||
try:
|
try:
|
||||||
self._sd.set_rate(int(-100 + rate * 200))
|
self._sd.set_rate(int(-100 + rate * 200))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.env['runtime']['debug'].writeDebugOut('speechDriver setRate:' + str(e),debug.debugLevel.ERROR)
|
self.env['runtime']['debug'].writeDebugOut('speechDriver setRate:' + str(e),debug.debugLevel.ERROR)
|
||||||
|
|
||||||
def setModule(self, module):
|
|
||||||
if not self._isInitialized:
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
self._sd.set_output_module(module)
|
|
||||||
except Exception as e:
|
|
||||||
self.env['runtime']['debug'].writeDebugOut('speechDriver setModule:' + str(e),debug.debugLevel.ERROR)
|
|
||||||
|
|
||||||
def setLanguage(self, language):
|
|
||||||
if not self._isInitialized:
|
|
||||||
return
|
|
||||||
self._language = language
|
|
||||||
|
|
||||||
def setVolume(self, volume):
|
def setVolume(self, volume):
|
||||||
if not self._isInitialized:
|
if not self._isInitialized:
|
||||||
|
Loading…
Reference in New Issue
Block a user