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:
- some timing issues for some users that leads to an delay to read incomming messages
- 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)
- 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)

View File

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

View File

@ -47,7 +47,7 @@ class debug():
if not self._fileOpened:
self.openDebugFile()
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:
msg = str(level) +' ' + str(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')
)

View File

@ -175,15 +175,18 @@ class settingsManager():
return value
def loadDriver(self, driverName, driverType):
if self.env['runtime'][driverType] != None:
print('shutdown %s',driverType)
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')
driver_mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(driver_mod)
self.env['runtime'][driverType] = driver_mod.driver()
self.env['runtime'][driverType].initialize(self.env)
try:
if self.env['runtime'][driverType] != None:
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')
driver_mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(driver_mod)
self.env['runtime'][driverType] = driver_mod.driver()
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):
if self.env['runtime'][driverType] == None:
return

View File

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

View File

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

View File

@ -14,6 +14,7 @@ class driver():
self.soundType = ''
self.soundFileCommand = ''
self.frequenceCommand = ''
self._initialized = False
def initialize(self, environment):
self.env = environment
self.soundFileCommand = self.env['runtime']['settingsManager'].getSetting('sound', 'genericPlayFileCommand')
@ -22,9 +23,14 @@ class driver():
self.soundFileCommand = 'play -q -v fenrirVolume fenrirSoundFile'
if self.frequenceCommand == '':
self.frequenceCommand = 'play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence'
self._initialized = True
def shutdown(self):
if not self._initialized:
return
self.cancel()
def playFrequence(self, frequence = 1000, duration = 0.3, adjustVolume = 0):
if not self._initialized:
return
if interrupt:
self.cancel()
popenFrequenceCommand = self.frequenceCommand.replace('fenrirVolume', str(self.volume + adjustVolume ))
@ -33,6 +39,8 @@ class driver():
self.proc = subprocess.Popen(popenFrequenceCommand, shell=True)
self.soundType = 'frequence'
def playSoundFile(self, filePath, interrupt = True):
if not self._initialized:
return
if interrupt:
self.cancel()
popenSoundFileCommand = self.soundFileCommand.replace('fenrirVolume', str(self.volume ))
@ -40,6 +48,8 @@ class driver():
self.proc = subprocess.Popen(popenSoundFileCommand, shell=True)
self.soundType = 'file'
def cancel(self):
if not self._initialized:
return
if self.soundType == '':
return
if self.soundType == 'file':
@ -48,6 +58,9 @@ class driver():
self.proc.kill()
self.soundType = ''
def setCallback(self, callback):
pass
if not self._initialized:
return
def setVolume(self, volume):
if not self._initialized:
return
self.volume = volume

View File

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