catch nonloadable drivers, debug, cleanup

This commit is contained in:
chrys 2016-12-12 23:39:37 +01:00
parent 55de2f3c38
commit 3f195745e3
8 changed files with 118 additions and 42 deletions

1
TODO
View File

@ -3,6 +3,7 @@ ToDos in Priority order:
Known Bugs: Known Bugs:
- some timing issues for some users that leads to an delay to read incomming messages - some timing issues for some users that leads to an delay to read incomming messages
- for some users fenrir eats the orca key - for some users fenrir eats the orca key
- dont break on non existing python-evdev event.
- in special cases next word skipps a word, "word<12 spaces>word2<12 spaces>word3 (storm_dragon) - in special cases next word skipps a word, "word<12 spaces>word2<12 spaces>word3 (storm_dragon)
- Fenrir key sometimes wents crazy? (maybe this is if fenrir key is released before other keys) - Fenrir key sometimes wents crazy? (maybe this is if fenrir key is released before other keys)
- For example, in screen, it just tells me bell in window, but doesn't tell me which one. (southernprince) - For example, in screen, it just tells me bell in window, but doesn't tell me which one. (southernprince)

View File

@ -4,6 +4,7 @@ enabled=True
# Select the driver used to play sounds, choices are generic and gstreamer. # Select the driver used to play sounds, choices are generic and gstreamer.
# Sox is the default. # Sox is the default.
#driver=gstreamer
driver=generic driver=generic
# Sound themes. This is the pack of sounds used for sound alerts. # Sound themes. This is the pack of sounds used for sound alerts.

View File

@ -47,7 +47,7 @@ class debug():
if not self._fileOpened: if not self._fileOpened:
self.openDebugFile() self.openDebugFile()
if onAnyLevel: if onAnyLevel:
msg = 'ANY '+ str(level) + str(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')) msg = 'ANY '+ str(level) + ' ' + str(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f'))
else: else:
msg = str(level) +' ' + str(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f') msg = str(level) +' ' + str(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')
) )

View File

@ -175,15 +175,18 @@ class settingsManager():
return value return value
def loadDriver(self, driverName, driverType): def loadDriver(self, driverName, driverType):
if self.env['runtime'][driverType] != None: try:
print('shutdown %s',driverType) if self.env['runtime'][driverType] != None:
self.env['runtime'][driverType].shutdown(self.env) self.env['runtime'][driverType].shutdown(self.env)
spec = importlib.util.spec_from_file_location(driverName, os.path.dirname(os.path.realpath(__main__.__file__)) + "/" + driverType + '/' + driverName + '.py') spec = importlib.util.spec_from_file_location(driverName, os.path.dirname(os.path.realpath(__main__.__file__)) + "/" + driverType + '/' + driverName + '.py')
driver_mod = importlib.util.module_from_spec(spec) driver_mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(driver_mod) spec.loader.exec_module(driver_mod)
self.env['runtime'][driverType] = driver_mod.driver() self.env['runtime'][driverType] = driver_mod.driver()
self.env['runtime'][driverType].initialize(self.env) self.env['runtime'][driverType].initialize(self.env)
self.env['runtime']['debug'].writeDebugOut('Loading Driver ' + driverType +" OK",debug.debugLevel.INFO, onAnyLevel=True)
except Exception as e:
self.env['runtime'][driverType] = None
self.env['runtime']['debug'].writeDebugOut("Loading " + driverType + " Driver : "+ str(e), debug.debugLevel.ERROR)
def shutdownDriver(self, driverType): def shutdownDriver(self, driverType):
if self.env['runtime'][driverType] == None: if self.env['runtime'][driverType] == None:
return return

View File

@ -4,11 +4,17 @@
# Fenrir TTY screen reader # Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributers.
import evdev _evdevAvailable = False
import time _evdevAvailableError = ''
from evdev import InputDevice, UInput try:
from select import select import evdev
from evdev import InputDevice, UInput
_evdevAvailable = True
except Exception as e:
_evdevAvailableError = str(e)
import time
from select import select
from core import inputEvent from core import inputEvent
from core import debug from core import debug
@ -16,19 +22,30 @@ class driver():
def __init__(self): def __init__(self):
self.iDevices = {} self.iDevices = {}
self.uDevices = {} self.uDevices = {}
self.ledDevices = {} self.ledDevices = {}
self._initialized = False
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
self.getInputDevices() global _evdevAvailable
self._initialized = _evdevAvailable
if not self._initialized:
global _evdevAvailableError
self.env['runtime']['debug'].writeDebugOut('InputDriver: ' + _evdevAvailableError,debug.debugLevel.ERROR)
return
self.getInputDevices()
def shutdown(self): def shutdown(self):
pass pass
def getInputEvent(self): def getInputEvent(self):
if not self._initialized:
time.sleep(0.005) # dont flood CPU
return None
if not self.iDevices: if not self.iDevices:
return None return None
if self.iDevices == {}: if self.iDevices == {}:
return None return None
event = None event = None
r, w, x = select(self.iDevices, [], [], self.env['runtime']['settingsManager'].getSettingAsFloat('screen', 'screenUpdateDelay')) r, w, x = select(self.iDevices, [], [], self.env['runtime']['settingsManager'].getSettingAsFloat('screen', 'screenUpdateDelay'))
if r != []: if r != []:
@ -47,16 +64,24 @@ class driver():
return None return None
def writeEventBuffer(self): def writeEventBuffer(self):
if not self._initialized:
return
for iDevice, uDevice, event in self.env['input']['eventBuffer']: for iDevice, uDevice, event in self.env['input']['eventBuffer']:
self.writeUInput(uDevice, event) self.writeUInput(uDevice, event)
def clearEventBuffer(self): def clearEventBuffer(self):
if not self._initialized:
return
del self.env['input']['eventBuffer'][:] del self.env['input']['eventBuffer'][:]
def writeUInput(self, uDevice, event): def writeUInput(self, uDevice, event):
if not self._initialized:
return
uDevice.write_event(event) uDevice.write_event(event)
uDevice.syn() uDevice.syn()
def getInputDevices(self): def getInputDevices(self):
if not self._initialized:
return
deviceList = evdev.list_devices() deviceList = evdev.list_devices()
readableDevices = [] readableDevices = []
for dev in deviceList: for dev in deviceList:
@ -83,6 +108,8 @@ class driver():
self.ledDevices = {dev.fd: dev for dev in self.ledDevices if dev.name.upper() in self.env['runtime']['settingsManager'].getSetting('keyboard', 'device').upper().split(',')} self.ledDevices = {dev.fd: dev for dev in self.ledDevices if dev.name.upper() in self.env['runtime']['settingsManager'].getSetting('keyboard', 'device').upper().split(',')}
def mapEvent(self, event): def mapEvent(self, event):
if not self._initialized:
return None
if not event: if not event:
return None return None
mEvent = inputEvent.inputEvent mEvent = inputEvent.inputEvent
@ -97,6 +124,8 @@ class driver():
return None return None
def getLedState(self, led = 0): def getLedState(self, led = 0):
if not self._initialized:
return None
# 0 = Numlock # 0 = Numlock
# 1 = Capslock # 1 = Capslock
# 2 = Rollen # 2 = Rollen
@ -108,6 +137,8 @@ class driver():
return led in dev.leds() return led in dev.leds()
return False return False
def toggleLedState(self, led = 0): def toggleLedState(self, led = 0):
if not self._initialized:
return None
ledState = self.getLedState(led) ledState = self.getLedState(led)
for i in self.ledDevices: for i in self.ledDevices:
if ledState == 1: if ledState == 1:
@ -115,6 +146,8 @@ class driver():
else: else:
self.ledDevices[i].set_led(led , 1) self.ledDevices[i].set_led(led , 1)
def grabDevices(self): def grabDevices(self):
if not self._initialized:
return None
# leve the old code until the new one is better tested # leve the old code until the new one is better tested
# for fd in self.iDevices: # for fd in self.iDevices:
# dev = self.iDevices[fd] # dev = self.iDevices[fd]
@ -137,6 +170,8 @@ class driver():
except Exception as e: except Exception as e:
self.env['runtime']['debug'].writeDebugOut('InputDriver evdev: grabing not possible: ' + str(e),debug.debugLevel.ERROR) self.env['runtime']['debug'].writeDebugOut('InputDriver evdev: grabing not possible: ' + str(e),debug.debugLevel.ERROR)
def releaseDevices(self): def releaseDevices(self):
if not self._initialized:
return None
for fd in self.iDevices: for fd in self.iDevices:
try: try:
self.iDevices[fd].ungrab() self.iDevices[fd].ungrab()
@ -154,7 +189,9 @@ class driver():
self.iDevices.clear() self.iDevices.clear()
self.uDevices.clear() self.uDevices.clear()
def __del__(self): def __del__(self):
self.releaseDevices() if not self._initialized:
return None
self.releaseDevices()

View File

@ -9,19 +9,30 @@ from core import debug
class driver(): class driver():
def __init__(self): def __init__(self):
self.volume = None self.volume = None
self._initialized = False
def initialize(self, environment): def initialize(self, environment):
self.env = environment self.env = environment
def shutdown(self): def shutdown(self):
if not self._initialized:
return
self.cancel() 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:
return
if interrupt: if interrupt:
self.cancel() self.cancel()
def playSoundFile(self, filePath, interrupt = True): def playSoundFile(self, filePath, interrupt = True):
if not self._initialized:
return
if interrupt: if interrupt:
self.cancel() self.cancel()
def cancel(self): def cancel(self):
pass if not self._initialized:
return
def setCallback(self, callback): def setCallback(self, callback):
pass if not self._initialized:
return
def setVolume(self, volume): def setVolume(self, volume):
if not self._initialized:
return
self.volume = volume self.volume = volume

View File

@ -14,6 +14,7 @@ class driver():
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')
@ -22,9 +23,14 @@ class driver():
self.soundFileCommand = 'play -q -v fenrirVolume fenrirSoundFile' self.soundFileCommand = 'play -q -v fenrirVolume fenrirSoundFile'
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
def shutdown(self): def shutdown(self):
if not self._initialized:
return
self.cancel() 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:
return
if interrupt: if interrupt:
self.cancel() self.cancel()
popenFrequenceCommand = self.frequenceCommand.replace('fenrirVolume', str(self.volume + adjustVolume )) popenFrequenceCommand = self.frequenceCommand.replace('fenrirVolume', str(self.volume + adjustVolume ))
@ -33,6 +39,8 @@ class driver():
self.proc = subprocess.Popen(popenFrequenceCommand, shell=True) self.proc = subprocess.Popen(popenFrequenceCommand, shell=True)
self.soundType = 'frequence' self.soundType = 'frequence'
def playSoundFile(self, filePath, interrupt = True): def playSoundFile(self, filePath, interrupt = True):
if not self._initialized:
return
if interrupt: if interrupt:
self.cancel() self.cancel()
popenSoundFileCommand = self.soundFileCommand.replace('fenrirVolume', str(self.volume )) popenSoundFileCommand = self.soundFileCommand.replace('fenrirVolume', str(self.volume ))
@ -40,6 +48,8 @@ class driver():
self.proc = subprocess.Popen(popenSoundFileCommand, shell=True) self.proc = subprocess.Popen(popenSoundFileCommand, shell=True)
self.soundType = 'file' self.soundType = 'file'
def cancel(self): def cancel(self):
if not self._initialized:
return
if self.soundType == '': if self.soundType == '':
return return
if self.soundType == 'file': if self.soundType == 'file':
@ -48,6 +58,9 @@ class driver():
self.proc.kill() self.proc.kill()
self.soundType = '' self.soundType = ''
def setCallback(self, callback): def setCallback(self, callback):
pass if not self._initialized:
return
def setVolume(self, volume): def setVolume(self, volume):
if not self._initialized:
return
self.volume = volume self.volume = volume

View File

@ -5,32 +5,35 @@
# By Chrys, Storm Dragon, and contributers. # By Chrys, Storm Dragon, and contributers.
from core import debug from core import debug
import gi
import time, threading import time, threading
from gi.repository import GLib
_gstreamerAvailable = False
try: try:
import gi
from gi.repository import GLib
gi.require_version('Gst', '1.0') gi.require_version('Gst', '1.0')
from gi.repository import Gst from gi.repository import Gst
except: _gstreamerAvailable, args = Gst.init_check(None)
except Exception as e:
_gstreamerAvailable = False _gstreamerAvailable = False
else: _availableError = str(e)
_gstreamerAvailable, args = Gst.init_check(None)
class driver: class driver:
def __init__(self): def __init__(self):
self._initialized = False
self._source = None self._source = None
self._sink = None self._sink = None
self.volume = 1 self.volume = 1
self._initialized = False
def initialize(self, environment): def initialize(self, environment):
if self._initialized:
return
global _gstreamerAvailable
if not _gstreamerAvailable:
self.environment['runtime']['debug'].writeDebugOut('Gstreamer not available',debug.debugLevel.ERROR)
return
self.env = 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') self._player = Gst.ElementFactory.make('playbin', 'player')
bus = self._player.get_bus() bus = self._player.get_bus()
bus.add_signal_watch() bus.add_signal_watch()
@ -46,21 +49,19 @@ class driver:
self._pipeline.add(self._source) self._pipeline.add(self._source)
self._pipeline.add(self._sink) self._pipeline.add(self._sink)
self._source.link(self._sink) self._source.link(self._sink)
self._initialized = True
self.mainloop = GLib.MainLoop() self.mainloop = GLib.MainLoop()
self.thread = threading.Thread(target=self.mainloop.run) self.thread = threading.Thread(target=self.mainloop.run)
self.thread.start() self.thread.start()
def shutdown(self): def shutdown(self):
global _gstreamerAvailable if not self._initialized:
if not _gstreamerAvailable:
return return
self.cancel() self.cancel()
self.mainloop.quit() self.mainloop.quit()
self._initialized = False
_gstreamerAvailable = False
def _onPlayerMessage(self, bus, message): def _onPlayerMessage(self, bus, message):
if not self._initialized:
return
if message.type == Gst.MessageType.EOS: if message.type == Gst.MessageType.EOS:
self._player.set_state(Gst.State.NULL) self._player.set_state(Gst.State.NULL)
elif message.type == Gst.MessageType.ERROR: elif message.type == Gst.MessageType.ERROR:
@ -69,6 +70,8 @@ class driver:
self.env['runtime']['debug'].writeDebugOut('GSTREAMER: _onPlayerMessage'+ str(error) + str(info),debug.debugLevel.WARNING) self.env['runtime']['debug'].writeDebugOut('GSTREAMER: _onPlayerMessage'+ str(error) + str(info),debug.debugLevel.WARNING)
def _onPipelineMessage(self, bus, message): def _onPipelineMessage(self, bus, message):
if not self._initialized:
return
if message.type == Gst.MessageType.EOS: if message.type == Gst.MessageType.EOS:
self._pipeline.set_state(Gst.State.NULL) self._pipeline.set_state(Gst.State.NULL)
elif message.type == Gst.MessageType.ERROR: elif message.type == Gst.MessageType.ERROR:
@ -77,15 +80,21 @@ class driver:
self.env['runtime']['debug'].writeDebugOut('GSTREAMER: _onPipelineMessage'+ str(error) + str(info),debug.debugLevel.WARNING) self.env['runtime']['debug'].writeDebugOut('GSTREAMER: _onPipelineMessage'+ str(error) + str(info),debug.debugLevel.WARNING)
def _onTimeout(self, element): def _onTimeout(self, element):
if not self._initialized:
return
element.set_state(Gst.State.NULL) element.set_state(Gst.State.NULL)
def playSoundFile(self, fileName, interrupt=True): def playSoundFile(self, fileName, interrupt=True):
if not self._initialized:
return
if interrupt: if interrupt:
self.cancel() self.cancel()
self._player.set_property('uri', 'file://%s' % fileName) self._player.set_property('uri', 'file://%s' % fileName)
self._player.set_state(Gst.State.PLAYING) self._player.set_state(Gst.State.PLAYING)
def playFrequence(self, frequence, duration, adjustVolume, interrupt=True): def playFrequence(self, frequence, duration, adjustVolume, interrupt=True):
if not self._initialized:
return
if interrupt: if interrupt:
self.cancel() self.cancel()
self._source.set_property('volume', tone.volume) self._source.set_property('volume', tone.volume)
@ -96,8 +105,7 @@ class driver:
GLib.timeout_add(duration, self._onTimeout, self._pipeline) GLib.timeout_add(duration, self._onTimeout, self._pipeline)
def cancel(self, element=None): def cancel(self, element=None):
global _gstreamerAvailable if not self._initialized:
if not _gstreamerAvailable:
return return
if element: if element:
element.set_state(Gst.State.NULL) element.set_state(Gst.State.NULL)
@ -105,6 +113,8 @@ class driver:
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): def setVolume(self, volume):
if not self._initialized:
return
self.volume = volume self.volume = volume