Compare commits

..

No commits in common. "master" and "2025.02.26" have entirely different histories.

28 changed files with 224 additions and 345 deletions

View File

@ -4,7 +4,7 @@
# the entrys are seperated with :===: in words colon tripple equal colon ( to not collide with substitutions)
[levelDict]
none:===:
some:===:-$~+*-/\@#_
some:===:-$~+*-/\@#
most:===:.,:-$~+*-/\@!#%^&*()[]}{<>;
all:===:!"#$%& \'()*+,-./:;<=>?@[\\]^_`{|}~

View File

@ -4,7 +4,7 @@
# the entrys are seperated with :===: in words colon tripple equal colon ( to not collide with substitutions)
[levelDict]
none:===:
some:===:-$~+*-/\@_
some:===:-$~+*-/\@
most:===:.,:-$~+*-/\@!#%^&*()[]}{<>;
all:===:!"#$%& \'()*+,-./:;<=>?@[\\]^_`{|}~

View File

@ -4,7 +4,7 @@
# the entrys are seperated with :===: in words colon tripple equal colon ( to not collide with substitutions)
[levelDict]
none:===:
some:===:-$~+*-/\@_
some:===:-$~+*-/\@
most:===:.,:-$~+*-/\@!#%^&*()[]}{<>;
all:===:!"#$%& \'()*+,-./:;<=>?@[\\]^_`{|}~

View File

@ -15,7 +15,7 @@ theme=default
# Sound volume controls how loud the sounds for your selected soundpack are.
# 0 is quietest, 1.0 is loudest.
volume=0.7
volume=1.0
# shell commands for generic sound driver
# the folowing variable are substituted
@ -92,8 +92,8 @@ fenrirMaxRate=450
driver=vcsaDriver
encoding=auto
screenUpdateDelay=0.05
ignoreScreen=
autodetectIgnoreScreen=True
suspendingScreen=
autodetectSuspendingScreen=True
[keyboard]
driver=evdevDriver
@ -131,7 +131,7 @@ punctuationProfile=default
punctuationLevel=some
respectPunctuationPause=True
newLinePause=True
numberOfClipboards=50
numberOfClipboards=10
# used path for "export_clipboard_to_file"
# $user is replaced by username
#clipboardExportPath=/home/$user/fenrirClipboard
@ -190,7 +190,7 @@ enableSettingsRemote=True
enableCommandRemote=True
[barrier]
enabled=False
enabled=True
leftBarriers=│└┌─
rightBarriers=│┘┐─

View File

@ -1,11 +1,12 @@
#!/usr/bin/env bash
#!/bin/bash
#Basic install script for Fenrir.
read -rp "This will install Fenrir. Press ctrl+C to cancel, or enter to continue."
read -p "This will install Fenrir. Press ctrl+C to cancel, or enter to continue." continue
# Fenrir main application
install -m755 -d /opt/fenrirscreenreader
cp -af src/* /opt/fenrirscreenreader
ln -fs /opt/fenrirscreenreader/fenrir-daemon /usr/bin/fenrir-daemon
ln -fs /opt/fenrirscreenreader/fenrir /usr/bin/fenrir
# tools
install -m755 -d /usr/share/fenrirscreenreader/tools
@ -32,9 +33,8 @@ cp -af config/sound/template /usr/share/sounds/fenrirscreenreader/template
# config
if [ -f "/etc/fenrirscreenreader/settings/settings.conf" ]; then
echo "Do you want to overwrite your current global settings? (y/n)"
read -r yn
yn="${yn:0:1}"
if [[ "${yn^}" == "Y" ]]; then
read yn
if [ $yn = "Y" -o $yn = "y" ]; then
mv /etc/fenrirscreenreader/settings/settings.conf /etc/fenrirscreenreader/settings/settings.conf.bak
echo "Your old settings.conf has been backed up to settings.conf.bak."
install -m644 -D "config/settings/settings.conf" /etc/fenrirscreenreader/settings/settings.conf

View File

@ -1,9 +1,7 @@
daemonize
evdev
evdev>=1.1.2
daemonize>=2.5.0
dbus-python>=1.2.8
pyudev>=0.21.0
pexpect
pyenchant
pyperclip
pyte
pyudev
pyxdg
setproctitle
pyttsx3
pyte>=0.7.0

View File

@ -99,10 +99,8 @@ setup(
"evdev>=1.1.2",
"daemonize>=2.5.0",
"dbus-python>=1.2.8",
"pyperclip",
"pyudev>=0.21.0",
"setuptools",
"setproctitle",
"pexpect",
"pyte>=0.7.0",
],
@ -113,10 +111,10 @@ if not forceSettingsFlag:
# create settings file from example if not exist
if not os.path.isfile('/etc/fenrirscreenreader/settings/settings.conf'):
try:
copyfile('config/fenrirscreenreader/settings/settings.conf', '/etc/fenrirscreenreader/settings/settings.conf')
copyfile('/etc/fenrirscreenreader/settings/settings.conf.example', '/etc/fenrirscreenreader/settings/settings.conf')
print('create settings file in /etc/fenrirscreenreader/settings/settings.conf')
except OSError as e:
print(f"Could not copy settings file to destination: {e}")
except:
pass
else:
print('settings.conf file found. It is not overwritten automatical')

View File

@ -5,17 +5,15 @@
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
import os
import importlib
import subprocess, os
from subprocess import Popen, PIPE
import _thread
import pyperclip
class command():
def __init__(self):
pass
def initialize(self, environment, scriptPath=''):
def initialize(self, environment):
self.env = environment
self.scriptPath = scriptPath
def shutdown(self):
pass
def getDescription(self):
@ -24,48 +22,56 @@ class command():
_thread.start_new_thread(self._threadRun , ())
def _threadRun(self):
try:
# Check if clipboard is empty
if self.env['runtime']['memoryManager'].isIndexListEmpty('clipboardHistory'):
self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True)
return
# Get current clipboard content
clipboard = self.env['runtime']['memoryManager'].getIndexListElement('clipboardHistory')
user = self.env['general']['currUser']
# Remember original display environment variable if it exists
originalDisplay = os.environ.get('DISPLAY', '')
success = False
# First try to find xclip in common locations
xclip_paths = [
'/usr/bin/xclip',
'/bin/xclip',
'/usr/local/bin/xclip'
]
# Try different display options
for i in range(10):
display = f":{i}"
try:
# Set display environment variable
os.environ['DISPLAY'] = display
# Attempt to set clipboard content
importlib.reload(pyperclip) # Weird workaround for some distros
pyperclip.copy(clipboard)
# If we get here without exception, we found a working display
success = True
xclip_path = None
for path in xclip_paths:
if os.path.isfile(path) and os.access(path, os.X_OK):
xclip_path = path
break
except Exception:
# Failed for this display, try next one
continue
# Restore original display setting
if originalDisplay:
os.environ['DISPLAY'] = originalDisplay
else:
os.environ.pop('DISPLAY', None)
if not xclip_path:
self.env['runtime']['outputManager'].presentText(
'xclip not found in common locations',
interrupt=True
)
return
# Notify the user of the result
if success:
self.env['runtime']['outputManager'].presentText(_('exported to the X session.'), interrupt=True)
for display in range(10):
p = Popen(
['su', user, '-p', '-c', f"{xclip_path} -d :{display} -selection clipboard"],
stdin=PIPE, stdout=PIPE, stderr=PIPE, preexec_fn=os.setpgrp
)
stdout, stderr = p.communicate(input=clipboard.encode('utf-8'))
self.env['runtime']['outputManager'].interruptOutput()
stderr = stderr.decode('utf-8')
stdout = stdout.decode('utf-8')
if stderr == '':
break
if stderr != '':
self.env['runtime']['outputManager'].presentText(stderr, soundIcon='', interrupt=False)
else:
self.env['runtime']['outputManager'].presentText(_('failed to export to X clipboard. No available display found.'), interrupt=True)
self.env['runtime']['outputManager'].presentText('exported to the X session.', interrupt=True)
except Exception as e:
self.env['runtime']['outputManager'].presentText(str(e), soundIcon='', interrupt=False)
def setCallback(self, callback):
pass

View File

@ -5,11 +5,9 @@
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
import importlib
import subprocess, os
from subprocess import Popen, PIPE
import _thread
import pyperclip
import os
class command():
def __init__(self):
pass
@ -24,41 +22,33 @@ class command():
_thread.start_new_thread(self._threadRun , ())
def _threadRun(self):
try:
# Remember original display environment variable if it exists
originalDisplay = os.environ.get('DISPLAY', '')
clipboardContent = None
# Try different display options
for i in range(10):
display = f":{i}"
try:
# Set display environment variable
os.environ['DISPLAY'] = display
# Attempt to get clipboard content
importlib.reload(pyperclip) # Weird workaround for some distros
clipboardContent = pyperclip.paste()
# If we get here without exception, we found a working display
if clipboardContent:
# Find xclip path
xclip_paths = ['/usr/bin/xclip', '/bin/xclip', '/usr/local/bin/xclip']
xclip_path = None
for path in xclip_paths:
if os.path.isfile(path) and os.access(path, os.X_OK):
xclip_path = path
break
except Exception:
# Failed for this display, try next one
continue
# Restore original display setting
if originalDisplay:
os.environ['DISPLAY'] = originalDisplay
if not xclip_path:
self.env['runtime']['outputManager'].presentText('xclip not found in common locations', interrupt=True)
return
xClipboard = ''
for display in range(10):
p = Popen('su ' + self.env['general']['currUser'] + ' -p -c "' + xclip_path + ' -d :' + str(display) + ' -o"', stdout=PIPE, stderr=PIPE, shell=True)
stdout, stderr = p.communicate()
self.env['runtime']['outputManager'].interruptOutput()
stderr = stderr.decode('utf-8')
xClipboard = stdout.decode('utf-8')
if (stderr == ''):
break
if stderr != '':
self.env['runtime']['outputManager'].presentText(stderr , soundIcon='', interrupt=False)
else:
os.environ.pop('DISPLAY', None)
# Process the clipboard content if we found any
if clipboardContent and isinstance(clipboardContent, str):
self.env['runtime']['memoryManager'].addValueToFirstIndex('clipboardHistory', clipboardContent)
self.env['runtime']['memoryManager'].addValueToFirstIndex('clipboardHistory', xClipboard)
self.env['runtime']['outputManager'].presentText('Import to Clipboard', soundIcon='CopyToClipboard', interrupt=True)
self.env['runtime']['outputManager'].presentText(clipboardContent, soundIcon='', interrupt=False)
else:
self.env['runtime']['outputManager'].presentText('No text found in clipboard or no accessible display', interrupt=True)
self.env['runtime']['outputManager'].presentText(xClipboard, soundIcon='', interrupt=False)
except Exception as e:
self.env['runtime']['outputManager'].presentText(str(e), soundIcon='', interrupt=False)
self.env['runtime']['outputManager'].presentText(e , soundIcon='', interrupt=False)
def setCallback(self, callback):
pass

View File

@ -35,18 +35,12 @@ class command():
if not (self.env['runtime']['byteManager'].getLastByteKey() in [b'^[[A',b'^[[B']):
return
# Get the current cursor's line from both old and new content
prevLine = self.env['screen']['oldContentText'].split('\n')[self.env['screen']['newCursor']['y']]
currLine = self.env['screen']['newContentText'].split('\n')[self.env['screen']['newCursor']['y']]
is_blank = currLine.strip() == ''
if prevLine == currLine:
if self.env['screen']['newDelta'] != '':
return
announce = currLine
if not is_blank:
if not currLine.isspace():
currPrompt = currLine.find('$')
rootPrompt = currLine.find('#')
if currPrompt <= 0:
@ -61,13 +55,13 @@ class command():
else:
announce = currLine
if is_blank:
if currLine.isspace():
self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True, flush=False)
else:
self.env['runtime']['outputManager'].presentText(announce, interrupt=True, flush=False)
self.env['commandsIgnore']['onScreenUpdate']['CHAR_DELETE_ECHO'] = True
self.env['commandsIgnore']['onScreenUpdate']['CHAR_ECHO'] = True
self.env['commandsIgnore']['onScreenUpdate']['INCOMING_IGNORE'] = True
def setCallback(self, callback):
pass

View File

@ -159,13 +159,7 @@ class commandManager():
self.env['runtime']['debug'].writeDebugOut("Loading script:" + fileName ,debug.debugLevel.ERROR)
self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR)
continue
def shutdownCommands(self, section):
# Check if the section exists in the commands dictionary
if section not in self.env['commands']:
self.env['runtime']['debug'].writeDebugOut("shutdownCommands: section not found:" + section, debug.debugLevel.WARNING)
return
for command in sorted(self.env['commands'][section]):
try:
self.env['commands'][section][command].shutdown()
@ -176,7 +170,7 @@ class commandManager():
continue
def executeSwitchTrigger(self, trigger, unLoadScript, loadScript):
if self.env['runtime']['screenManager'].isIgnoredScreen():
if self.env['runtime']['screenManager'].isSuspendingScreen():
return
#unload
oldScript = unLoadScript
@ -199,7 +193,7 @@ class commandManager():
def executeDefaultTrigger(self, trigger, force=False):
if not force:
if self.env['runtime']['screenManager'].isIgnoredScreen():
if self.env['runtime']['screenManager'].isSuspendingScreen():
return
for command in sorted(self.env['commands'][trigger]):
if self.commandExists(command, trigger):
@ -214,7 +208,7 @@ class commandManager():
self.env['runtime']['debug'].writeDebugOut("Executing trigger:" + trigger + "." + command + str(e) ,debug.debugLevel.ERROR)
def executeCommand(self, command, section = 'commands'):
if self.env['runtime']['screenManager'].isIgnoredScreen():
if self.env['runtime']['screenManager'].isSuspendingScreen():
return
if self.commandExists(command, section):
try:

View File

@ -11,14 +11,6 @@ class cursorManager():
pass
def initialize(self, environment):
self.env = environment
def shouldProcessNumpadCommands(self):
"""
Check if numpad commands should be processed based on numlock state
Return True if numlock is OFF (commands should work)
Return False if numlock is ON (let keys type numbers)
"""
# Return False if numlock is ON
return not self.env['input']['newNumLock']
def shutdown(self):
pass
def clearMarks(self):

View File

@ -52,15 +52,12 @@ class debugManager():
else:
if not self._fileOpened and fileMode:
self.openDebugFile()
timestamp = str(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f'))
if onAnyLevel:
levelInfo = 'INFO ANY'
msg = 'ANY '+ str(level) + ' ' + str(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f'))
else:
levelInfo = str(level)
# Changed order: text comes first, then level and timestamp
msg = text + ' - ' + levelInfo + ' ' + timestamp
msg = str(level) +' ' + str(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')
)
msg += ': ' + text
if printMode:
print(msg)
if fileMode:

View File

@ -55,7 +55,7 @@ class fenrirManager():
if self.environment['runtime']['inputManager'].noKeyPressed():
self.environment['runtime']['inputManager'].clearLastDeepInput()
if self.environment['runtime']['screenManager'].isIgnoredScreen():
if self.environment['runtime']['screenManager'].isSuspendingScreen():
self.environment['runtime']['inputManager'].writeEventBuffer()
else:
if self.environment['runtime']['helpManager'].isTutorialMode():

View File

@ -42,25 +42,6 @@ class inputDriver():
if not self._initialized:
return True
return True
def forceUngrab(self):
"""Emergency method to release grabbed devices in case of failure"""
if not self._initialized:
return True
try:
# Try standard ungrab first
return self.ungrabAllDevices()
except Exception as e:
# Just log the failure and inform the user
if hasattr(self, 'env') and 'runtime' in self.env and 'debug' in self.env['runtime']:
self.env['runtime']['debug'].writeDebugOut(
f"Emergency device release failed: {str(e)}",
debug.debugLevel.ERROR
)
else:
print(f"Emergency device release failed: {str(e)}")
return False
def hasIDevices(self):
if not self._initialized:
return False

View File

@ -49,7 +49,6 @@ class inputManager():
return event
def setExecuteDeviceGrab(self, newExecuteDeviceGrab = True):
self.executeDeviceGrab = newExecuteDeviceGrab
def handleDeviceGrab(self, force = False):
if force:
self.setExecuteDeviceGrab()
@ -62,38 +61,17 @@ class inputManager():
if not self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'grabDevices'):
self.executeDeviceGrab = False
return
# Add maximum retries to prevent infinite loops
maxRetries = 5
retryCount = 0
grabTimeout = 3 # Timeout in seconds
startTime = time.time()
if self.env['runtime']['screenManager'].getCurrScreenIgnored():
while not self.ungrabAllDevices():
retryCount += 1
if retryCount >= maxRetries or (time.time() - startTime) > grabTimeout:
self.env['runtime']['debug'].writeDebugOut("Failed to ungrab devices after multiple attempts", debug.debugLevel.ERROR)
# Force a release of devices if possible through alternative means
try:
self.env['runtime']['inputDriver'].forceUngrab()
except:
pass
break
time.sleep(0.25)
self.env['runtime']['debug'].writeDebugOut(f"retry ungrabAllDevices {retryCount}/{maxRetries}", debug.debugLevel.WARNING)
self.env['runtime']['debug'].writeDebugOut("retry ungrabAllDevices " ,debug.debugLevel.WARNING)
self.env['runtime']['debug'].writeDebugOut("All devices ungrabbed" ,debug.debugLevel.INFO)
else:
while not self.grabAllDevices():
retryCount += 1
if retryCount >= maxRetries or (time.time() - startTime) > grabTimeout:
self.env['runtime']['debug'].writeDebugOut("Failed to grab devices after multiple attempts", debug.debugLevel.ERROR)
# Continue without grabbing input - limited functionality but not locked
break
time.sleep(0.25)
self.env['runtime']['debug'].writeDebugOut(f"retry grabAllDevices {retryCount}/{maxRetries}", debug.debugLevel.WARNING)
self.env['runtime']['debug'].writeDebugOut("retry grabAllDevices" ,debug.debugLevel.WARNING)
self.env['runtime']['debug'].writeDebugOut("All devices grabbed" ,debug.debugLevel.INFO)
self.executeDeviceGrab = False
def sendKeys(self, keyMacro):
for e in keyMacro:
key = ''
@ -274,32 +252,10 @@ class inputManager():
def getCurrShortcut(self, inputSequence = None):
shortcut = []
shortcut.append(self.env['input']['shortcutRepeat'])
numpadKeys = ['KEY_KP0', 'KEY_KP1', 'KEY_KP2', 'KEY_KP3', 'KEY_KP4',
'KEY_KP5', 'KEY_KP6', 'KEY_KP7', 'KEY_KP8', 'KEY_KP9',
'KEY_KPDOT', 'KEY_KPPLUS', 'KEY_KPMINUS', 'KEY_KPASTERISK',
'KEY_KPSLASH', 'KEY_KPENTER', 'KEY_KPEQUAL']
if inputSequence:
# Check if any key in the sequence is a numpad key and numlock is ON
# If numlock is ON and any key in the sequence is a numpad key, return an empty shortcut
if not self.env['runtime']['cursorManager'].shouldProcessNumpadCommands():
for key in inputSequence:
if key in numpadKeys:
# Return an empty/invalid shortcut that won't match any command
return "[]"
shortcut.append(inputSequence)
else:
# Same check for current input
if not self.env['runtime']['cursorManager'].shouldProcessNumpadCommands():
for key in self.env['input']['currInput']:
if key in numpadKeys:
# Return an empty/invalid shortcut that won't match any command
return "[]"
shortcut.append(self.env['input']['currInput'])
if len(self.env['input']['prevInput']) < len(self.env['input']['currInput']):
if self.env['input']['shortcutRepeat'] > 1 and not self.shortcutExists(str(shortcut)):
shortcut = []

View File

@ -59,7 +59,7 @@ class screenManager():
if self.isCurrScreenIgnoredChanged():
self.env['runtime']['inputManager'].setExecuteDeviceGrab()
self.env['runtime']['inputManager'].handleDeviceGrab()
if not self.isIgnoredScreen(self.env['screen']['newTTY']):
if not self.isSuspendingScreen(self.env['screen']['newTTY']):
self.update(eventData, 'onScreenChange')
self.env['screen']['lastScreenUpdate'] = time.time()
else:
@ -81,7 +81,7 @@ class screenManager():
return self.prevScreenIgnored
def updateScreenIgnored(self):
self.prevScreenIgnored = self.currScreenIgnored
self.currScreenIgnored = self.isIgnoredScreen(self.env['screen']['newTTY'])
self.currScreenIgnored = self.isSuspendingScreen(self.env['screen']['newTTY'])
def update(self, eventData, trigger='onUpdate'):
# set new "old" values
self.env['screen']['oldContentBytes'] = self.env['screen']['newContentBytes']
@ -174,16 +174,16 @@ class screenManager():
except Exception as e:
self.env['runtime']['debug'].writeDebugOut('screenManager:update:highlight: ' + str(e),debug.debugLevel.ERROR)
def isIgnoredScreen(self, screen = None):
def isSuspendingScreen(self, screen = None):
if screen == None:
screen = self.env['screen']['newTTY']
ignoreScreens = []
fixIgnoreScreens = self.env['runtime']['settingsManager'].getSetting('screen', 'ignoreScreen')
fixIgnoreScreens = self.env['runtime']['settingsManager'].getSetting('screen', 'suspendingScreen')
if fixIgnoreScreens != '':
ignoreScreens.extend(fixIgnoreScreens.split(','))
if self.env['runtime']['settingsManager'].getSettingAsBool('screen', 'autodetectIgnoreScreen'):
if self.env['runtime']['settingsManager'].getSettingAsBool('screen', 'autodetectSuspendingScreen'):
ignoreScreens.extend(self.env['screen']['autoIgnoreScreens'])
self.env['runtime']['debug'].writeDebugOut('screenManager:isIgnoredScreen ignore:' + str(ignoreScreens) + ' current:'+ str(screen ), debug.debugLevel.INFO)
self.env['runtime']['debug'].writeDebugOut('screenManager:isSuspendingScreen ignore:' + str(ignoreScreens) + ' current:'+ str(screen ), debug.debugLevel.INFO)
return (screen in ignoreScreens)
def isScreenChange(self):

View File

@ -40,8 +40,8 @@ settingsData = {
'driver': 'vcsaDriver',
'encoding': 'auto',
'screenUpdateDelay': 0.1,
'ignoreScreen': '',
'autodetectIgnoreScreen': False,
'suspendingScreen': '',
'autodetectSuspendingScreen': False,
},
'general':{
'debugLevel': debug.debugLevel.DEACTIVE,

View File

@ -4,5 +4,5 @@
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
version = "2025.04.28"
version = "2025.02.26"
codeName = "master"

View File

@ -72,16 +72,14 @@ class driver(inputDriver):
self.env['runtime']['debug'].writeDebugOut('plugInputDeviceWatchdogUdev:' + str(device), debug.debugLevel.INFO)
try:
try:
# FIX: Check if attributes exist before accessing them
if hasattr(device, 'name') and device.name and device.name.upper() in ['','SPEAKUP','FENRIR-UINPUT']:
if device.name.upper() in ['','SPEAKUP','FENRIR-UINPUT']:
ignorePlug = True
if hasattr(device, 'phys') and device.phys and device.phys.upper() in ['','SPEAKUP','FENRIR-UINPUT']:
if device.phys.upper() in ['','SPEAKUP','FENRIR-UINPUT']:
ignorePlug = True
if hasattr(device, 'name') and device.name and 'BRLTTY' in device.name.upper():
if 'BRLTTY' in device.name.upper():
ignorePlug = True
except Exception as e:
self.env['runtime']['debug'].writeDebugOut("plugInputDeviceWatchdogUdev CHECK NAME CRASH: " + str(e),debug.debugLevel.ERROR)
if not ignorePlug:
virtual = '/sys/devices/virtual/input/' in device.sys_path
if device.device_node:
@ -91,7 +89,7 @@ class driver(inputDriver):
try:
pollTimeout = 1
device = monitor.poll(pollTimeout)
except Exception:
except:
device = None
ignorePlug = False
if validDevices:
@ -148,7 +146,7 @@ class driver(inputDriver):
if uDevice:
if self.gDevices[iDevice.fd]:
self.writeUInput(uDevice, event)
except Exception:
except Exception as e:
pass
def writeUInput(self, uDevice, event):
@ -193,7 +191,7 @@ class driver(inputDriver):
try:
with open(deviceFile) as f:
pass
except Exception:
except Exception as e:
continue
# 3 pos absolute
# 2 pos relative
@ -203,12 +201,11 @@ class driver(inputDriver):
except:
continue
try:
# FIX: Check if attributes exist before accessing them
if hasattr(currDevice, 'name') and currDevice.name and currDevice.name.upper() in ['', 'SPEAKUP', 'FENRIR-UINPUT']:
if currDevice.name.upper() in ['','SPEAKUP','FENRIR-UINPUT']:
continue
if hasattr(currDevice, 'phys') and currDevice.phys and currDevice.phys.upper() in ['', 'SPEAKUP', 'FENRIR-UINPUT']:
if currDevice.phys.upper() in ['','SPEAKUP','FENRIR-UINPUT']:
continue
if hasattr(currDevice, 'name') and currDevice.name and 'BRLTTY' in currDevice.name.upper():
if 'BRLTTY' in currDevice.name.upper():
continue
except:
pass
@ -236,11 +233,7 @@ class driver(inputDriver):
self.addDevice(currDevice)
self.env['runtime']['debug'].writeDebugOut('Device added (Name):' + self.iDevices[currDevice.fd].name,debug.debugLevel.INFO)
except Exception as e:
try:
device_name = currDevice.name if hasattr(currDevice, 'name') else "unknown"
self.env['runtime']['debug'].writeDebugOut("Device Skipped (Exception): " + deviceFile + ' ' + device_name + ' ' + str(e), debug.debugLevel.INFO)
except:
self.env['runtime']['debug'].writeDebugOut("Device Skipped (Exception): " + deviceFile + ' ' + str(e), debug.debugLevel.INFO)
self.env['runtime']['debug'].writeDebugOut("Device Skipped (Exception): " + deviceFile +' ' + currDevice.name +' '+ str(e),debug.debugLevel.INFO)
self.iDeviceNo = len(evdev.list_devices())
self.updateMPiDevicesFD()
@ -254,7 +247,6 @@ class driver(inputDriver):
self.iDevicesFD.remove(fd)
except:
pass
def mapEvent(self, event):
if not self._initialized:
return None
@ -276,7 +268,7 @@ class driver(inputDriver):
mEvent['EventState'] = event.value
mEvent['EventType'] = event.type
return mEvent
except Exception:
except Exception as e:
return None
def getLedState(self, led = 0):
@ -289,7 +281,6 @@ class driver(inputDriver):
if led in dev.leds():
return True
return False
def toggleLedState(self, led = 0):
if not self.hasIDevices():
return False
@ -302,7 +293,6 @@ class driver(inputDriver):
self.iDevices[i].set_led(led , 0)
else:
self.iDevices[i].set_led(led , 1)
def grabAllDevices(self):
if not self._initialized:
return True
@ -311,7 +301,6 @@ class driver(inputDriver):
if not self.gDevices[fd]:
ok = ok and self.grabDevice(fd)
return ok
def ungrabAllDevices(self):
if not self._initialized:
return True
@ -320,7 +309,6 @@ class driver(inputDriver):
if self.gDevices[fd]:
ok = ok and self.ungrabDevice(fd)
return ok
def createUInputDev(self, fd):
if not self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'grabDevices'):
self.uDevices[fd] = None
@ -348,7 +336,6 @@ class driver(inputDriver):
except Exception as e:
self.env['runtime']['debug'].writeDebugOut('InputDriver evdev: init Uinput not possible: ' + str(e),debug.debugLevel.ERROR)
return
def addDevice(self, newDevice):
self.env['runtime']['debug'].writeDebugOut('InputDriver evdev: device added: ' + str(newDevice.fd) + ' ' +str(newDevice),debug.debugLevel.INFO)
try:
@ -373,9 +360,6 @@ class driver(inputDriver):
def grabDevice(self, fd):
if not self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'grabDevices'):
return True
# FIX: Handle exception variable scope correctly
grab_error = None
try:
self.iDevices[fd].grab()
self.gDevices[fd] = True
@ -387,26 +371,19 @@ class driver(inputDriver):
try:
self.uDevices[fd].write(e.EV_KEY, key, 0) # 0 = key up
self.uDevices[fd].syn()
except Exception as mod_error:
self.env['runtime']['debug'].writeDebugOut('Failed to reset modifier key: ' + str(mod_error), debug.debugLevel.WARNING)
except Exception as e:
self.env['runtime']['debug'].writeDebugOut('Failed to reset modifier key: ' + str(e), debug.debugLevel.WARNING)
except IOError:
if not self.gDevices[fd]:
return False
except Exception as ex:
grab_error = ex
if grab_error:
self.env['runtime']['debug'].writeDebugOut('InputDriver evdev: grabing not possible: ' + str(grab_error), debug.debugLevel.ERROR)
except Exception as e:
self.env['runtime']['debug'].writeDebugOut('InputDriver evdev: grabing not possible: ' + str(e),debug.debugLevel.ERROR)
return False
return True
def ungrabDevice(self,fd):
if not self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'grabDevices'):
return True
# FIX: Handle exception variable scope correctly
ungrab_error = None
try:
self.iDevices[fd].ungrab()
self.gDevices[fd] = False
@ -414,15 +391,11 @@ class driver(inputDriver):
except IOError:
if self.gDevices[fd]:
return False
except Exception as ex:
ungrab_error = ex
if ungrab_error:
self.env['runtime']['debug'].writeDebugOut('InputDriver evdev: ungrabing not possible: ' + str(ungrab_error), debug.debugLevel.ERROR)
# self.gDevices[fd] = False
# #self.removeDevice(fd)
except Exception as e:
return False
return True
def removeDevice(self,fd):
self.env['runtime']['debug'].writeDebugOut('InputDriver evdev: device removed: ' + str(fd) + ' ' +str(self.iDevices[fd]),debug.debugLevel.INFO)
self.clearEventBuffer()