Latest changes and bug fixes.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
daemonize
|
||||
dbus-python
|
||||
evdev
|
||||
pexpect
|
||||
pyenchant
|
||||
|
||||
@@ -37,7 +37,7 @@ for directory in directories:
|
||||
if not forceSettingsFlag:
|
||||
try:
|
||||
files = [f for f in files if not f.endswith('settings.conf')]
|
||||
except:
|
||||
except Exception as e:
|
||||
pass
|
||||
elif 'config/scripts' in directory:
|
||||
destDir = '/usr/share/fenrirscreenreader/scripts'
|
||||
|
||||
@@ -10,7 +10,7 @@ initialized = False
|
||||
try:
|
||||
import enchant
|
||||
initialized = True
|
||||
except:
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
class command():
|
||||
|
||||
@@ -30,7 +30,7 @@ class command():
|
||||
clipboard = self.env['runtime']['memoryManager'].getIndexListElement('clipboardHistory')
|
||||
clipboardFile.write(clipboard)
|
||||
clipboardFile.close()
|
||||
os.chmod(clipboardFilePath, 0o666)
|
||||
os.chmod(clipboardFilePath, 0o644)
|
||||
self.env['runtime']['outputManager'].presentText(_('clipboard exported to file'), interrupt=True)
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('export_clipboard_to_file:run: Filepath:'+ clipboardFile +' trace:' + str(e),debug.debugLevel.ERROR)
|
||||
|
||||
@@ -19,7 +19,7 @@ class command():
|
||||
# Check if progress monitoring should be enabled by default from settings
|
||||
try:
|
||||
defaultEnabled = self.env['runtime']['settingsManager'].getSettingAsBool('sound', 'progressMonitoring')
|
||||
except:
|
||||
except Exception as e:
|
||||
# If setting doesn't exist, default to False
|
||||
defaultEnabled = False
|
||||
self.env['commandBuffer']['progressMonitoring'] = defaultEnabled
|
||||
@@ -201,7 +201,7 @@ class command():
|
||||
|
||||
return False
|
||||
|
||||
except Exception:
|
||||
except Exception as e:
|
||||
# If anything fails, assume it's not a prompt to be safe
|
||||
return False
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ initialized = False
|
||||
try:
|
||||
import enchant
|
||||
initialized = True
|
||||
except:
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
class command():
|
||||
@@ -35,7 +35,7 @@ class command():
|
||||
if self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage') != self.language:
|
||||
try:
|
||||
self.updateSpellLanguage()
|
||||
except:
|
||||
except Exception as e:
|
||||
return
|
||||
|
||||
cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor()
|
||||
|
||||
@@ -56,7 +56,7 @@ class command():
|
||||
self.env['runtime']['debug'].writeDebugOut("Found exact prompt match: " + exactMatch, debug.debugLevel.INFO)
|
||||
self.disableSilence()
|
||||
return True
|
||||
except:
|
||||
except Exception as e:
|
||||
# Prompt section doesn't exist in settings, skip custom exact matches
|
||||
pass
|
||||
|
||||
@@ -68,7 +68,7 @@ class command():
|
||||
if customPatterns:
|
||||
customList = [pattern.strip() for pattern in customPatterns.split(',') if pattern.strip()]
|
||||
promptPatterns.extend(customList)
|
||||
except:
|
||||
except Exception as e:
|
||||
# Prompt section doesn't exist in settings, skip custom patterns
|
||||
pass
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ initialized = False
|
||||
try:
|
||||
import enchant
|
||||
initialized = True
|
||||
except:
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
class command():
|
||||
@@ -36,7 +36,7 @@ class command():
|
||||
if self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage') != self.language:
|
||||
try:
|
||||
self.updateSpellLanguage()
|
||||
except:
|
||||
except Exception as e:
|
||||
return
|
||||
|
||||
cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor()
|
||||
|
||||
@@ -11,7 +11,7 @@ initialized = False
|
||||
try:
|
||||
import enchant
|
||||
initialized = True
|
||||
except:
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
class command():
|
||||
@@ -40,7 +40,7 @@ class command():
|
||||
if self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage') != self.language:
|
||||
try:
|
||||
self.updateSpellLanguage()
|
||||
except:
|
||||
except Exception as e:
|
||||
return
|
||||
|
||||
# just when horizontal cursor move worddetection is needed
|
||||
@@ -111,17 +111,17 @@ class command():
|
||||
try:
|
||||
if os.path.exists("/bin/"+currWord):
|
||||
return
|
||||
except:
|
||||
except Exception as e:
|
||||
pass
|
||||
try:
|
||||
if os.path.exists("/usr/bin/"+currWord):
|
||||
return
|
||||
except:
|
||||
except Exception as e:
|
||||
pass
|
||||
try:
|
||||
if os.path.exists("/sbin/"+currWord):
|
||||
return
|
||||
except:
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
if not self.spellChecker.check(currWord):
|
||||
|
||||
@@ -23,7 +23,7 @@ class command():
|
||||
for deviceEntry in deviceList:
|
||||
# dont play sounds for virtual devices
|
||||
playSound = playSound or not deviceEntry['virtual']
|
||||
except:
|
||||
except Exception as e:
|
||||
playSound = True
|
||||
if playSound:
|
||||
if time.time() - self.lastTime > 5:
|
||||
|
||||
@@ -31,7 +31,7 @@ class command():
|
||||
self.checkForPrompt(currentLine)
|
||||
except Exception as e:
|
||||
# Silently ignore errors to avoid disrupting normal operation
|
||||
pass
|
||||
self.env['runtime']['debug'].writeDebugOut('prompt_detector run: Error in prompt detection: ' + str(e), debug.debugLevel.ERROR)
|
||||
|
||||
def checkForPrompt(self, text):
|
||||
"""Check if the current line contains a shell prompt pattern"""
|
||||
@@ -50,7 +50,7 @@ class command():
|
||||
self.env['runtime']['debug'].writeDebugOut("Found exact prompt match: " + exactMatch, debug.debugLevel.INFO)
|
||||
self._restoreSpeech()
|
||||
return True
|
||||
except:
|
||||
except Exception as e:
|
||||
# Prompt section doesn't exist in settings, skip custom exact matches
|
||||
pass
|
||||
|
||||
@@ -62,7 +62,7 @@ class command():
|
||||
if customPatterns:
|
||||
customList = [pattern.strip() for pattern in customPatterns.split(',') if pattern.strip()]
|
||||
promptPatterns.extend(customList)
|
||||
except:
|
||||
except Exception as e:
|
||||
# Prompt section doesn't exist in settings, skip custom patterns
|
||||
pass
|
||||
|
||||
|
||||
@@ -4,7 +4,12 @@
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from fenrirscreenreader.commands.vmenu_navigation.vmenu_search_base import VMenuSearchCommand
|
||||
import importlib.util
|
||||
import os
|
||||
_spec = importlib.util.spec_from_file_location("vmenu_search_base", os.path.join(os.path.dirname(__file__), "vmenu_search_base.py"))
|
||||
_module = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(_module)
|
||||
VMenuSearchCommand = _module.VMenuSearchCommand
|
||||
|
||||
class command(VMenuSearchCommand):
|
||||
def __init__(self):
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
import configparser
|
||||
from datetime import datetime
|
||||
|
||||
class ConfigCommand():
|
||||
"""Base class for configuration management commands"""
|
||||
|
||||
def __init__(self):
|
||||
self.env = None
|
||||
self.settingsFile = None
|
||||
self.config = None
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
self.settingsFile = self.env['runtime']['settingsManager'].settingsFile
|
||||
self.config = self.env['runtime']['settingsManager'].settings
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
|
||||
def presentText(self, text, interrupt=True, flush=True):
|
||||
"""Present text to user with proper speech handling"""
|
||||
self.env['runtime']['outputManager'].presentText(text, interrupt=interrupt, flush=flush)
|
||||
|
||||
def playSound(self, soundName):
|
||||
"""Play system sound"""
|
||||
soundIcon = ''
|
||||
if soundName == 'Accept':
|
||||
soundIcon = 'Accept'
|
||||
elif soundName == 'Error':
|
||||
soundIcon = 'ErrorSound'
|
||||
elif soundName == 'Cancel':
|
||||
soundIcon = 'Cancel'
|
||||
|
||||
if soundIcon:
|
||||
self.env['runtime']['outputManager'].presentText('', soundIcon=soundIcon, interrupt=False)
|
||||
|
||||
def backupConfig(self, announce=True):
|
||||
"""Create backup of current configuration file"""
|
||||
try:
|
||||
if not os.path.exists(self.settingsFile):
|
||||
message = "Configuration file not found"
|
||||
if announce:
|
||||
self.presentText(message)
|
||||
return False, message
|
||||
|
||||
# Create backup with timestamp
|
||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
backup_path = f"{self.settingsFile}.backup_{timestamp}"
|
||||
|
||||
shutil.copy2(self.settingsFile, backup_path)
|
||||
|
||||
message = f"Configuration backed up to {backup_path}"
|
||||
if announce:
|
||||
self.presentText("Configuration backup created successfully")
|
||||
return True, message
|
||||
|
||||
except Exception as e:
|
||||
message = f"Failed to backup configuration: {str(e)}"
|
||||
if announce:
|
||||
self.presentText(message)
|
||||
return False, message
|
||||
|
||||
def reloadConfig(self):
|
||||
"""Reload configuration from file"""
|
||||
try:
|
||||
# Force settings manager to reload from file
|
||||
self.env['runtime']['settingsManager'].loadSettings()
|
||||
self.config = self.env['runtime']['settingsManager'].settings
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
self.presentText(f"Failed to reload configuration: {str(e)}")
|
||||
return False
|
||||
|
||||
def findDefaultConfig(self):
|
||||
"""Find default configuration file path"""
|
||||
# Look for default config in multiple locations
|
||||
default_paths = [
|
||||
'/etc/fenrir/settings/settings.conf.default',
|
||||
'/usr/share/fenrir/settings/settings.conf',
|
||||
os.path.join(os.path.dirname(self.settingsFile), 'settings.conf.default'),
|
||||
os.path.join(os.path.dirname(os.path.dirname(self.settingsFile)), 'settings', 'settings.conf.default')
|
||||
]
|
||||
|
||||
for path in default_paths:
|
||||
if os.path.exists(path):
|
||||
return path
|
||||
|
||||
return None
|
||||
|
||||
def createBasicDefaults(self):
|
||||
"""Create basic default configuration manually"""
|
||||
try:
|
||||
# Create a new config with basic defaults
|
||||
self.config = configparser.ConfigParser()
|
||||
|
||||
# Add basic sections and settings
|
||||
self.config.add_section('speech')
|
||||
self.config.set('speech', 'driver', 'speechdDriver')
|
||||
self.config.set('speech', 'rate', '0.75')
|
||||
self.config.set('speech', 'pitch', '0.5')
|
||||
self.config.set('speech', 'volume', '1.0')
|
||||
|
||||
self.config.add_section('sound')
|
||||
self.config.set('sound', 'driver', 'genericDriver')
|
||||
self.config.set('sound', 'volume', '0.7')
|
||||
|
||||
self.config.add_section('keyboard')
|
||||
self.config.set('keyboard', 'driver', 'evdevDriver')
|
||||
self.config.set('keyboard', 'keyboardLayout', 'desktop')
|
||||
|
||||
self.config.add_section('screen')
|
||||
self.config.set('screen', 'driver', 'vcsaDriver')
|
||||
|
||||
self.config.add_section('general')
|
||||
self.config.set('general', 'debugMode', 'Off')
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
self.presentText(f"Failed to create basic defaults: {str(e)}")
|
||||
return False
|
||||
+4
-4
@@ -27,8 +27,8 @@ class command():
|
||||
speechDriver = self.env['runtime']['speechDriver']
|
||||
speechDriver.shutdown()
|
||||
speechDriver.initialize(self.env)
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
print(f'revert_to_saved speechDriver: Error reinitializing speech driver: {str(e)}')
|
||||
|
||||
# Reinitialize sound system with restored settings
|
||||
if 'soundDriver' in self.env['runtime']:
|
||||
@@ -36,8 +36,8 @@ class command():
|
||||
soundDriver = self.env['runtime']['soundDriver']
|
||||
soundDriver.shutdown()
|
||||
soundDriver.initialize(self.env)
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
print(f'revert_to_saved soundDriver: Error reinitializing sound driver: {str(e)}')
|
||||
|
||||
self.env['runtime']['outputManager'].presentText("Successfully reverted to saved settings", interrupt=False, flush=False)
|
||||
self.env['runtime']['outputManager'].presentText("All temporary changes have been discarded", interrupt=False, flush=False)
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ class command():
|
||||
runtimeValue = runtimeSettings[section][option]
|
||||
try:
|
||||
fileValue = fileConfig[section][option]
|
||||
except:
|
||||
except Exception as e:
|
||||
fileValue = ""
|
||||
|
||||
if runtimeValue != fileValue:
|
||||
|
||||
@@ -17,7 +17,7 @@ class command():
|
||||
try:
|
||||
# Get current pitch
|
||||
currentPitch = float(self.env['runtime']['settingsManager'].getSetting('speech', 'pitch'))
|
||||
except:
|
||||
except Exception as e:
|
||||
currentPitch = 0.5
|
||||
|
||||
# Present current pitch
|
||||
|
||||
@@ -17,7 +17,7 @@ class command():
|
||||
try:
|
||||
# Get current rate
|
||||
currentRate = float(self.env['runtime']['settingsManager'].getSetting('speech', 'rate'))
|
||||
except:
|
||||
except Exception as e:
|
||||
currentRate = 0.5
|
||||
|
||||
# Present current rate
|
||||
|
||||
+3
-3
@@ -18,7 +18,7 @@ class command():
|
||||
# Get current rate from runtime settings (may be temporary)
|
||||
settingsManager = self.env['runtime']['settingsManager']
|
||||
currentRate = float(settingsManager.getSetting('speech', 'rate'))
|
||||
except:
|
||||
except Exception as e:
|
||||
currentRate = 0.5
|
||||
|
||||
# Present current rate
|
||||
@@ -38,8 +38,8 @@ class command():
|
||||
if 'speechDriver' in self.env['runtime']:
|
||||
try:
|
||||
self.env['runtime']['speechDriver'].setRate(newRate)
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
print(f'adjust_speech_rate setRate: Error setting speech rate: {str(e)}')
|
||||
|
||||
newPercent = int(newRate * 100)
|
||||
self.env['runtime']['outputManager'].presentText(f"Speech rate temporarily set to {newPercent} percent", interrupt=False, flush=False)
|
||||
|
||||
@@ -17,7 +17,7 @@ class command():
|
||||
try:
|
||||
# Get current volume
|
||||
currentVolume = float(self.env['runtime']['settingsManager'].getSetting('speech', 'volume'))
|
||||
except:
|
||||
except Exception as e:
|
||||
currentVolume = 1.0
|
||||
|
||||
# Present current volume
|
||||
|
||||
+3
-3
@@ -38,19 +38,19 @@ class command():
|
||||
try:
|
||||
ratePercent = int(float(rate) * 100)
|
||||
self.env['runtime']['outputManager'].presentText(f"Rate: {ratePercent} percent", interrupt=True)
|
||||
except:
|
||||
except Exception as e:
|
||||
self.env['runtime']['outputManager'].presentText(f"Rate: {rate}", interrupt=True)
|
||||
|
||||
try:
|
||||
pitchPercent = int(float(pitch) * 100)
|
||||
self.env['runtime']['outputManager'].presentText(f"Pitch: {pitchPercent} percent", interrupt=True)
|
||||
except:
|
||||
except Exception as e:
|
||||
self.env['runtime']['outputManager'].presentText(f"Pitch: {pitch}", interrupt=True)
|
||||
|
||||
try:
|
||||
volumePercent = int(float(volume) * 100)
|
||||
self.env['runtime']['outputManager'].presentText(f"Volume: {volumePercent} percent", interrupt=True)
|
||||
except:
|
||||
except Exception as e:
|
||||
self.env['runtime']['outputManager'].presentText(f"Volume: {volume}", interrupt=True)
|
||||
|
||||
self.env['runtime']['outputManager'].playSound('Accept')
|
||||
|
||||
@@ -74,8 +74,8 @@ class attributeManager():
|
||||
except KeyError:
|
||||
try:
|
||||
return self.defaultAttributes[0]
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('attributeManager getAttributeByXY: Error accessing default attributes: ' + str(e), debug.debugLevel.ERROR)
|
||||
return None
|
||||
def appendDefaultAttributes(self, attribute):
|
||||
if not attribute:
|
||||
@@ -214,12 +214,12 @@ class attributeManager():
|
||||
try:
|
||||
try:
|
||||
attributeFormatString = attributeFormatString.replace('fenrirFontSize', int(attribute[8]))
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('attributeManager formatAttributeToString: Error formatting font size as int: ' + str(e), debug.debugLevel.ERROR)
|
||||
try:
|
||||
attributeFormatString = attributeFormatString.replace('fenrirFontSize', str(attribute[8]))
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('attributeManager formatAttributeToString: Error formatting font size as string: ' + str(e), debug.debugLevel.ERROR)
|
||||
except Exception as e:
|
||||
pass
|
||||
attributeFormatString = attributeFormatString.replace('fenrirFontSize', _('default'))
|
||||
|
||||
@@ -58,8 +58,8 @@ class byteManager():
|
||||
return
|
||||
try:
|
||||
self.env['runtime']['debug'].writeDebugOut("handleByteInput " + eventData.decode('utf8') ,debug.debugLevel.INFO)
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('byteManager handleByteInput: Error decoding byte data: ' + str(e), debug.debugLevel.ERROR)
|
||||
self.handleByteStream(eventData)
|
||||
def handleSingleByteSequence(self, eventData):
|
||||
convertedEscapeSequence = self.unifyEscapeSeq(eventData)
|
||||
@@ -140,7 +140,8 @@ class byteManager():
|
||||
try:
|
||||
repeat = int(chr(cleanShortcut[0]))
|
||||
cleanShortcut = cleanShortcut[2:]
|
||||
except:
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('byteManager loadByteShortcuts: Error parsing repeat count: ' + str(e), debug.debugLevel.ERROR)
|
||||
repeat = 1
|
||||
cleanShortcut = cleanShortcut
|
||||
shortcut = b''
|
||||
|
||||
@@ -84,11 +84,12 @@ class commandManager():
|
||||
fileName = fileName.split('/')[-1]
|
||||
if fileName.startswith('__'):
|
||||
continue
|
||||
try:
|
||||
if self.env['commands'][section][fileName.upper()] != None:
|
||||
continue
|
||||
except:
|
||||
pass
|
||||
# Skip base classes that shouldn't be loaded as commands
|
||||
if fileName.endswith('_base'):
|
||||
continue
|
||||
# Check if command already exists to prevent duplicate loading
|
||||
if fileName.upper() in self.env['commands'][section] and self.env['commands'][section][fileName.upper()] is not None:
|
||||
continue
|
||||
if fileExtension.lower() == '.py':
|
||||
command_mod = module_utils.importModule(fileName, command)
|
||||
self.env['commands'][section][fileName.upper()] = command_mod.command()
|
||||
@@ -249,7 +250,7 @@ class commandManager():
|
||||
def commandExists(self, command, section = 'commands'):
|
||||
try:
|
||||
return( command in self.env['commands'][section])
|
||||
except:
|
||||
except Exception as e:
|
||||
return False
|
||||
def getShortcutForCommand(self, command, formatKeys = False):
|
||||
shortcut = []
|
||||
@@ -282,6 +283,6 @@ class commandManager():
|
||||
formattedKey = formattedKey.replace('key_kp', ' keypad ')
|
||||
formattedKey = formattedKey.replace('key_', ' ')
|
||||
shortcut.append(formattedKey)
|
||||
except:
|
||||
except Exception as e:
|
||||
pass
|
||||
return shortcut
|
||||
|
||||
@@ -87,8 +87,8 @@ class cursorManager():
|
||||
currApp = self.env['runtime']['applicationManager'].getCurrentApplication()
|
||||
if self.env['commandBuffer']['windowArea'][currApp]['1'] != None:
|
||||
return True
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('cursorManager isApplicationWindowSet: Error checking window area: ' + str(e), debug.debugLevel.ERROR)
|
||||
return False
|
||||
def setWindowForApplication(self, start = None, end = None):
|
||||
x1 = 0
|
||||
@@ -129,6 +129,7 @@ class cursorManager():
|
||||
currApp = self.env['runtime']['applicationManager'].getCurrentApplication()
|
||||
try:
|
||||
del self.env['commandBuffer']['windowArea'][currApp]
|
||||
except:
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('cursorManager clearWindowForApplication: Error clearing window area: ' + str(e), debug.debugLevel.ERROR)
|
||||
return False
|
||||
return True
|
||||
|
||||
@@ -19,8 +19,9 @@ class debugManager():
|
||||
def __del__(self):
|
||||
try:
|
||||
self.shutdown()
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
# Cannot use debug manager to log its own shutdown errors
|
||||
print(f'debugManager shutdown: Error during shutdown: {e}')
|
||||
|
||||
def openDebugFile(self, fileName = ''):
|
||||
self._fileOpened = False
|
||||
|
||||
@@ -159,8 +159,8 @@ class DynamicApplyVoiceCommand:
|
||||
speechDriver = self.env['runtime']['speechDriver']
|
||||
speechDriver.shutdown()
|
||||
speechDriver.initialize(self.env)
|
||||
except:
|
||||
pass # If this fails, at least we tried
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('dynamicVoiceMenu: Error reinitializing speech driver: ' + str(e), debug.debugLevel.ERROR)
|
||||
|
||||
self.env['runtime']['outputManager'].presentText(f"Failed to apply voice, reverted: {str(e)}", interrupt=False, flush=False)
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ from ctypes import c_bool
|
||||
class eventManager():
|
||||
def __init__(self):
|
||||
self.running = Value(c_bool, True)
|
||||
self._eventQueue = Queue() # multiprocessing.Queue()
|
||||
self._eventQueue = Queue(maxsize=100) # Bounded queue to prevent memory exhaustion
|
||||
self.cleanEventQueue()
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
@@ -85,8 +85,16 @@ class eventManager():
|
||||
return False
|
||||
if event == fenrirEventType.Ignore:
|
||||
return False
|
||||
if self.getEventQueueSize() > 50:
|
||||
if not event in [fenrirEventType.ScreenUpdate, fenrirEventType.HeartBeat]:
|
||||
self.cleanEventQueue()
|
||||
self._eventQueue.put({"Type":event,"Data":data})
|
||||
# Use bounded queue - if full, this will block briefly or drop older events
|
||||
try:
|
||||
self._eventQueue.put({"Type":event,"Data":data}, timeout=0.1)
|
||||
except Exception as e:
|
||||
# Queue full - drop oldest event and add new one for critical events
|
||||
if event in [fenrirEventType.ScreenUpdate, fenrirEventType.KeyboardInput]:
|
||||
try:
|
||||
self._eventQueue.get_nowait() # Remove oldest
|
||||
self._eventQueue.put({"Type":event,"Data":data}, timeout=0.1)
|
||||
except:
|
||||
pass # If still can't add, drop the event
|
||||
# For non-critical events, just drop them if queue is full
|
||||
return True
|
||||
|
||||
@@ -138,8 +138,8 @@ class fenrirManager():
|
||||
def handlePlugInputDevice(self, event):
|
||||
try:
|
||||
self.environment['runtime']['inputManager'].setLastDetectedDevices(event['Data'])
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.environment['runtime']['debug'].writeDebugOut('handlePlugInputDevice: Error setting last detected devices: ' + str(e), debug.debugLevel.ERROR)
|
||||
self.environment['runtime']['inputManager'].handlePlugInputDevice(event['Data'])
|
||||
self.environment['runtime']['commandManager'].executeDefaultTrigger('onPlugInputDevice', force=True)
|
||||
self.environment['runtime']['inputManager'].setLastDetectedDevices(None)
|
||||
@@ -200,16 +200,16 @@ class fenrirManager():
|
||||
stringBuffer.value = bytes(name, 'UTF-8')
|
||||
libc.prctl(15, byref(stringBuffer), 0, 0, 0)
|
||||
return True
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.environment['runtime']['debug'].writeDebugOut('setProcName: Error setting process name: ' + str(e), debug.debugLevel.ERROR)
|
||||
|
||||
return False
|
||||
|
||||
def shutdownRequest(self):
|
||||
try:
|
||||
self.environment['runtime']['eventManager'].stopMainEventLoop()
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.environment['runtime']['debug'].writeDebugOut('shutdownRequest: Error stopping main event loop: ' + str(e), debug.debugLevel.ERROR)
|
||||
|
||||
def captureSignal(self, sigInit, frame):
|
||||
self.shutdownRequest()
|
||||
|
||||
@@ -30,8 +30,8 @@ class helpManager():
|
||||
else:
|
||||
try:
|
||||
self.env['bindings'] = self.env['runtime']['settingsManager'].getBindingBackup()
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('helpManager setTutorialMode: Error restoring binding backup: ' + str(e), debug.debugLevel.ERROR)
|
||||
def isTutorialMode(self):
|
||||
return self.env['general']['tutorialMode']
|
||||
def getFormattedShortcutForCommand(self, command):
|
||||
|
||||
@@ -76,5 +76,5 @@ class inputDriver():
|
||||
return
|
||||
try:
|
||||
self.removeAllDevices()
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
print(f'inputDriver __del__: Error removing devices: {str(e)}')
|
||||
|
||||
@@ -44,8 +44,8 @@ class inputManager():
|
||||
event = None
|
||||
try:
|
||||
event = self.env['runtime']['inputDriver'].getInputEvent()
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('inputManager getInputEvent: Error getting input event: ' + str(e), debug.debugLevel.ERROR)
|
||||
return event
|
||||
def setExecuteDeviceGrab(self, newExecuteDeviceGrab = True):
|
||||
self.executeDeviceGrab = newExecuteDeviceGrab
|
||||
@@ -77,8 +77,8 @@ class inputManager():
|
||||
# Force a release of devices if possible through alternative means
|
||||
try:
|
||||
self.env['runtime']['inputDriver'].forceUngrab()
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('inputManager handleDeviceGrab: Error forcing ungrab: ' + str(e), debug.debugLevel.ERROR)
|
||||
break
|
||||
time.sleep(0.25)
|
||||
self.env['runtime']['debug'].writeDebugOut(f"retry ungrabAllDevices {retryCount}/{maxRetries}", debug.debugLevel.WARNING)
|
||||
@@ -170,8 +170,8 @@ class inputManager():
|
||||
self.env['runtime']['inputDriver'].toggleLedState(1)
|
||||
elif mEvent['EventName'] == 'KEY_SCROLLLOCK':
|
||||
self.env['runtime']['inputDriver'].toggleLedState(2)
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('inputManager handleLedStates: Error toggling LED state: ' + str(e), debug.debugLevel.ERROR)
|
||||
def grabAllDevices(self):
|
||||
if self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'grabDevices'):
|
||||
try:
|
||||
@@ -192,18 +192,18 @@ class inputManager():
|
||||
def updateInputDevices(self, newDevice = None):
|
||||
try:
|
||||
self.env['runtime']['inputDriver'].updateInputDevices(newDevice)
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('inputManager updateInputDevices: Error updating input devices: ' + str(e), debug.debugLevel.ERROR)
|
||||
try:
|
||||
if self.env['runtime']['screenManager']:
|
||||
self.handleDeviceGrab(force = True)
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('inputManager updateInputDevices: Error handling device grab: ' + str(e), debug.debugLevel.ERROR)
|
||||
def removeAllDevices(self):
|
||||
try:
|
||||
self.env['runtime']['inputDriver'].removeAllDevices()
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('inputManager removeAllDevices: Error removing devices: ' + str(e), debug.debugLevel.ERROR)
|
||||
|
||||
def convertEventName(self, eventName):
|
||||
if not eventName:
|
||||
@@ -364,7 +364,7 @@ class inputManager():
|
||||
for key in keys:
|
||||
try:
|
||||
shortcutRepeat = int(key)
|
||||
except:
|
||||
except Exception as e:
|
||||
if not self.isValidKey(key.upper()):
|
||||
self.env['runtime']['debug'].writeDebugOut("invalid key : "+ key.upper() + ' command:' +commandName ,debug.debugLevel.WARNING)
|
||||
invalid = True
|
||||
|
||||
@@ -30,11 +30,12 @@ class memoryManager():
|
||||
if not self.listStorageValid(name):
|
||||
return
|
||||
if self.listStorage[name]['maxLength'] == None:
|
||||
self.listStorage[name]['list'] = [value] + self.listStorage[name]['list']
|
||||
# Fallback: if maxLength is still None, apply default limit of 1000
|
||||
self.listStorage[name]['list'] = [value] + self.listStorage[name]['list'][:999]
|
||||
else:
|
||||
self.listStorage[name]['list'] = [value] + self.listStorage[name]['list'][:self.listStorage[name]['maxLength'] -1]
|
||||
self.listStorage[name]['index'] = 0
|
||||
def addIndexList(self, name, maxLength = None, currList = [], currIndex = -1):
|
||||
def addIndexList(self, name, maxLength = 1000, currList = [], currIndex = -1):
|
||||
if len(currList) != 0 and (currIndex == -1):
|
||||
currIndex = 0
|
||||
self.listStorage[name] = {'list': currList, 'index': currIndex, 'maxLength': maxLength}
|
||||
@@ -102,7 +103,8 @@ class memoryManager():
|
||||
return False
|
||||
try:
|
||||
return self.listStorage[name]['index']
|
||||
except:
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('memoryManager getCurrentIndex: Error accessing index for ' + name + ': ' + str(e), debug.debugLevel.ERROR)
|
||||
return -1
|
||||
def isIndexListEmpty(self, name):
|
||||
if not self.listStorageValid(name):
|
||||
@@ -119,5 +121,6 @@ class memoryManager():
|
||||
return None
|
||||
try:
|
||||
return self.listStorage[name]['list'][currIndex]
|
||||
except:
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('memoryManager getIndexListElement: Error accessing element for ' + name + ': ' + str(e), debug.debugLevel.ERROR)
|
||||
return None
|
||||
|
||||
@@ -111,8 +111,8 @@ class outputManager():
|
||||
try:
|
||||
self.env['runtime']['speechDriver'].cancel()
|
||||
self.env['runtime']['debug'].writeDebugOut("Interrupt speech", debug.debugLevel.INFO)
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('outputManager interruptOutput: Error canceling speech: ' + str(e), debug.debugLevel.ERROR)
|
||||
|
||||
def playSoundIcon(self, soundIcon='', interrupt=True):
|
||||
if soundIcon == '':
|
||||
@@ -124,8 +124,8 @@ class outputManager():
|
||||
|
||||
try:
|
||||
e = self.env['soundIcons'][soundIcon]
|
||||
except:
|
||||
self.env['runtime']['debug'].writeDebugOut("SoundIcon doesnt exist: " + soundIcon, debug.debugLevel.WARNING)
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('outputManager playSoundIcon: SoundIcon does not exist ' + soundIcon + ': ' + str(e), debug.debugLevel.WARNING)
|
||||
return False
|
||||
|
||||
if self.env['runtime']['soundDriver'] == None:
|
||||
@@ -166,8 +166,8 @@ class outputManager():
|
||||
adjustVolume = 0.0
|
||||
try:
|
||||
adjustVolume = 1.0 - (frequence / 20000)
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('outputManager playFrequence: Error calculating adjust volume: ' + str(e), debug.debugLevel.ERROR)
|
||||
if adjustVolume > 9.0:
|
||||
adjustVolume = 9.0
|
||||
|
||||
|
||||
@@ -29,14 +29,14 @@ class processManager():
|
||||
# pass
|
||||
#except:
|
||||
# pass
|
||||
proc.join()
|
||||
proc.join(timeout=5.0) # Timeout to prevent hanging shutdown
|
||||
for t in self._Threads:
|
||||
t.join()
|
||||
t.join(timeout=5.0) # Timeout to prevent hanging shutdown
|
||||
def heartBeatTimer(self, active):
|
||||
try:
|
||||
time.sleep(0.5)
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('processManager heartBeatTimer: Error during sleep: ' + str(e), debug.debugLevel.ERROR)
|
||||
return time.time()
|
||||
def addCustomEventThread(self, function, pargs = None, multiprocess = False, runOnce = False):
|
||||
eventQueue = self.env['runtime']['eventManager'].getEventQueue()
|
||||
|
||||
@@ -31,7 +31,7 @@ class punctuationManager():
|
||||
for char in currLevel:
|
||||
try:
|
||||
del currAllPunctNone[ord(char)]
|
||||
except:
|
||||
except Exception as e:
|
||||
pass
|
||||
return text.translate(currAllPunctNone)
|
||||
def useCustomDict(self, text, customDict, seperator=''):
|
||||
@@ -84,7 +84,7 @@ class punctuationManager():
|
||||
punctList = list(self.env['punctuation']['LEVELDICT'].keys())
|
||||
try:
|
||||
currIndex = punctList.index(self.env['runtime']['settingsManager'].getSetting('general', 'punctuationLevel').lower()) # curr punctuation
|
||||
except:
|
||||
except Exception as e:
|
||||
return False
|
||||
currIndex += 1
|
||||
if currIndex >= len(punctList):
|
||||
|
||||
@@ -30,7 +30,8 @@ class quickMenuManager():
|
||||
continue
|
||||
try:
|
||||
t = self.settings[entry[0]][entry[1]]
|
||||
except:
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('quickMenuManager loadMenu: Setting not found ' + str(entry) + ': ' + str(e), debug.debugLevel.ERROR)
|
||||
print(entry[0],entry[1], 'not found')
|
||||
continue
|
||||
self.quickMenu.append({'section': entry[0], 'setting': entry[1]})
|
||||
@@ -56,7 +57,8 @@ class quickMenuManager():
|
||||
valueString = ''
|
||||
try:
|
||||
valueString = self.env['runtime']['settingsManager'].getSetting(section, setting)
|
||||
except:
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('quickMenuManager nextValue: Error getting setting value: ' + str(e), debug.debugLevel.ERROR)
|
||||
return False
|
||||
|
||||
try:
|
||||
@@ -89,7 +91,8 @@ class quickMenuManager():
|
||||
valueString = ''
|
||||
try:
|
||||
valueString = self.env['runtime']['settingsManager'].getSetting(section, setting)
|
||||
except:
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('quickMenuManager prevValue: Error getting setting value: ' + str(e), debug.debugLevel.ERROR)
|
||||
return False
|
||||
try:
|
||||
if isinstance(self.settings[section][setting], str):
|
||||
@@ -120,12 +123,14 @@ class quickMenuManager():
|
||||
return ''
|
||||
try:
|
||||
return _(self.quickMenu[self.position]['section']) + ' ' + _(self.quickMenu[self.position]['setting'])
|
||||
except:
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('quickMenuManager getCurrentEntry: Error formatting entry: ' + str(e), debug.debugLevel.ERROR)
|
||||
return _('setting invalid')
|
||||
def getCurrentValue(self):
|
||||
if len(self.quickMenu) == 0:
|
||||
return ''
|
||||
try:
|
||||
return self.env['runtime']['settingsManager'].getSetting(self.quickMenu[self.position]['section'], self.quickMenu[self.position]['setting'])
|
||||
except:
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('quickMenuManager getCurrentValue: Error getting setting value: ' + str(e), debug.debugLevel.ERROR)
|
||||
return _('setting value invalid')
|
||||
|
||||
@@ -252,7 +252,7 @@ class remoteManager():
|
||||
else:
|
||||
clipboardFile.write('')
|
||||
clipboardFile.close()
|
||||
os.chmod(clipboardFilePath, 0o666)
|
||||
os.chmod(clipboardFilePath, 0o644)
|
||||
self.env['runtime']['outputManager'].presentText(_('clipboard exported to file'), interrupt=True)
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('export_clipboard_to_file:run: Filepath:'+ clipboardFile +' trace:' + str(e),debug.debugLevel.ERROR)
|
||||
|
||||
@@ -41,13 +41,13 @@ class screenManager():
|
||||
def getCurrScreen(self):
|
||||
try:
|
||||
self.env['runtime']['screenDriver'].getCurrScreen()
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('screenManager getCurrScreen: Error getting current screen: ' + str(e), debug.debugLevel.ERROR)
|
||||
def getSessionInformation(self):
|
||||
try:
|
||||
self.env['runtime']['screenDriver'].getSessionInformation()
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('screenManager getSessionInformation: Error getting session info: ' + str(e), debug.debugLevel.ERROR)
|
||||
def shutdown(self):
|
||||
self.env['runtime']['settingsManager'].shutdownDriver('screenDriver')
|
||||
def isCurrScreenIgnoredChanged(self):
|
||||
|
||||
@@ -94,7 +94,8 @@ class settingsManager():
|
||||
self.env['settings'] = ConfigParser()
|
||||
try:
|
||||
self.env['settings'].read(settingConfigPath)
|
||||
except:
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('settingsManager loadSettings: Error reading config file: ' + str(e), debug.debugLevel.ERROR)
|
||||
return False
|
||||
self.setSettingsFile(settingConfigPath)
|
||||
return True
|
||||
@@ -112,7 +113,7 @@ class settingsManager():
|
||||
configFile = open(settingConfigPath, 'w')
|
||||
self.env['settings'].write(configFile)
|
||||
configFile.close()
|
||||
os.chmod(settingConfigPath, 0o666)
|
||||
os.chmod(settingConfigPath, 0o644)
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('saveSettings: save settingsfile:' + settingConfigPath + 'failed. Error:' + str(e), debug.debugLevel.ERROR)
|
||||
def setSetting(self, section, setting, value):
|
||||
@@ -124,11 +125,11 @@ class settingsManager():
|
||||
try:
|
||||
value = self.settingArgDict[section][setting]
|
||||
return value
|
||||
except:
|
||||
except Exception as e:
|
||||
pass
|
||||
try:
|
||||
value = self.env['settings'].get(section, setting)
|
||||
except:
|
||||
except Exception as e:
|
||||
value = str(self.settings[section][setting])
|
||||
return value
|
||||
|
||||
@@ -141,7 +142,7 @@ class settingsManager():
|
||||
pass
|
||||
try:
|
||||
value = self.env['settings'].getint(section, setting)
|
||||
except:
|
||||
except Exception as e:
|
||||
value = self.settings[section][setting]
|
||||
return value
|
||||
|
||||
@@ -154,7 +155,7 @@ class settingsManager():
|
||||
pass
|
||||
try:
|
||||
value = self.env['settings'].getfloat(section, setting)
|
||||
except:
|
||||
except Exception as e:
|
||||
value = self.settings[section][setting]
|
||||
return value
|
||||
|
||||
@@ -167,15 +168,16 @@ class settingsManager():
|
||||
pass
|
||||
try:
|
||||
value = self.env['settings'].getboolean(section, setting)
|
||||
except:
|
||||
except Exception as e:
|
||||
value = self.settings[section][setting]
|
||||
return value
|
||||
|
||||
def loadDriver(self, driverName, driverType):
|
||||
try:
|
||||
self.env['runtime'][driverType].shutdown(self.env)
|
||||
except:
|
||||
pass
|
||||
if self.env['runtime'][driverType] is not None:
|
||||
self.env['runtime'][driverType].shutdown(self.env)
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('settingsManager loadDriver: Error shutting down driver: ' + str(e), debug.debugLevel.ERROR)
|
||||
try:
|
||||
driver_mod = module_utils.importModule(driverName,
|
||||
fenrirPath + "/" + driverType + '/' + driverName + '.py')
|
||||
@@ -223,7 +225,7 @@ class settingsManager():
|
||||
self.settingArgDict[section] = {}
|
||||
try:
|
||||
t = self.settings[section][setting]
|
||||
except:
|
||||
except Exception as e:
|
||||
print(section,setting, 'not found')
|
||||
return
|
||||
try:
|
||||
|
||||
@@ -147,8 +147,8 @@ class vmenuManager():
|
||||
try:
|
||||
self.currIndex = None
|
||||
self.env['bindings'] = self.env['runtime']['settingsManager'].getBindingBackup()
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('vmenuManager setActive: Error loading binding backup: ' + str(e), debug.debugLevel.ERROR)
|
||||
def createMenuTree(self, resetIndex = True):
|
||||
if resetIndex:
|
||||
self.currIndex = None
|
||||
@@ -169,7 +169,8 @@ class vmenuManager():
|
||||
r = self.getValueByPath(self.menuDict, self.currIndex)
|
||||
if r == {}:
|
||||
self.currIndex = None
|
||||
except:
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('vmenuManager createMenuTree: Error checking menu index validity: ' + str(e), debug.debugLevel.ERROR)
|
||||
self.currIndex = None
|
||||
def executeMenu(self):
|
||||
if self.currIndex == None:
|
||||
@@ -185,8 +186,8 @@ class vmenuManager():
|
||||
self.incLevel()
|
||||
text = self.getCurrentEntry()
|
||||
self.env['runtime']['outputManager'].presentText(text, interrupt=True)
|
||||
except:
|
||||
print(e)
|
||||
except Exception as ex:
|
||||
self.env['runtime']['debug'].writeDebugOut('vmenuManager executeMenu: Error presenting menu text: ' + str(ex), debug.debugLevel.ERROR)
|
||||
|
||||
def incLevel(self):
|
||||
if self.currIndex == None:
|
||||
@@ -195,7 +196,8 @@ class vmenuManager():
|
||||
r = self.getValueByPath(self.menuDict, self.currIndex +[0])
|
||||
if r == {}:
|
||||
return False
|
||||
except:
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('vmenuManager incLevel: Error accessing menu path: ' + str(e), debug.debugLevel.ERROR)
|
||||
return False
|
||||
self.currIndex.append(0)
|
||||
return True
|
||||
@@ -267,6 +269,9 @@ class vmenuManager():
|
||||
fileName = fileName.split('/')[-1]
|
||||
if fileName.startswith('__'):
|
||||
continue
|
||||
# Skip base classes that shouldn't be loaded as commands
|
||||
if fileName.endswith('_base'):
|
||||
continue
|
||||
command = self.env['runtime']['commandManager'].loadFile(root + '/' + f)
|
||||
tree.update({fileName + ' ' + _('Action'): command})
|
||||
except Exception as e:
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
version = "2025.06.20"
|
||||
version = "2025.06.27"
|
||||
codeName = "master"
|
||||
|
||||
@@ -126,7 +126,8 @@ class driver(inputDriver):
|
||||
|
||||
try:
|
||||
event = device.read_one()
|
||||
except:
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('evdevDriver handleInputEvent: Error reading event: ' + str(e), debug.debugLevel.ERROR)
|
||||
self.removeDevice(fd)
|
||||
continue
|
||||
while(event):
|
||||
@@ -166,8 +167,8 @@ class driver(inputDriver):
|
||||
if uDevice:
|
||||
if self.gDevices[iDevice.fd]:
|
||||
self.writeUInput(uDevice, event)
|
||||
except Exception:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('evdevDriver writeEventBuffer: Error writing event: ' + str(e), debug.debugLevel.ERROR)
|
||||
|
||||
def writeUInput(self, uDevice, event):
|
||||
if not self._initialized:
|
||||
@@ -211,14 +212,16 @@ class driver(inputDriver):
|
||||
try:
|
||||
with open(deviceFile) as f:
|
||||
pass
|
||||
except Exception:
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('evdevDriver updateInputDevices: Error opening device file: ' + str(e), debug.debugLevel.ERROR)
|
||||
continue
|
||||
# 3 pos absolute
|
||||
# 2 pos relative
|
||||
# 1 Keys
|
||||
try:
|
||||
currDevice = evdev.InputDevice(deviceFile)
|
||||
except:
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('evdevDriver createDeviceType: Error creating device: ' + str(e), debug.debugLevel.ERROR)
|
||||
continue
|
||||
try:
|
||||
# FIX: Check if attributes exist before accessing them
|
||||
@@ -228,8 +231,8 @@ class driver(inputDriver):
|
||||
continue
|
||||
if hasattr(currDevice, 'name') and currDevice.name and 'BRLTTY' in currDevice.name.upper():
|
||||
continue
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('evdevDriver: Error checking device capabilities: ' + str(e), debug.debugLevel.ERROR)
|
||||
cap = currDevice.capabilities()
|
||||
if mode in ['ALL', 'NOMICE']:
|
||||
if eventType.EV_KEY in cap:
|
||||
@@ -257,8 +260,8 @@ class driver(inputDriver):
|
||||
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)
|
||||
except Exception as ex:
|
||||
self.env['runtime']['debug'].writeDebugOut("Device Skipped (Exception): " + deviceFile + ' ' + str(ex), debug.debugLevel.INFO)
|
||||
self.iDeviceNo = len(evdev.list_devices())
|
||||
self.updateMPiDevicesFD()
|
||||
|
||||
@@ -270,8 +273,8 @@ class driver(inputDriver):
|
||||
for fd in self.iDevicesFD:
|
||||
if not fd in self.iDevices:
|
||||
self.iDevicesFD.remove(fd)
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('evdevDriver updateMPiDevicesFD: Error updating device file descriptors: ' + str(e), debug.debugLevel.ERROR)
|
||||
|
||||
def mapEvent(self, event):
|
||||
if not self._initialized:
|
||||
@@ -294,7 +297,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):
|
||||
@@ -379,16 +382,16 @@ class driver(inputDriver):
|
||||
# if it doesnt work clean up
|
||||
try:
|
||||
del(self.iDevices[newDevice.fd])
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('evdevDriver removeDevice: Error removing iDevice: ' + str(e), debug.debugLevel.ERROR)
|
||||
try:
|
||||
del(self.uDevices[newDevice.fd])
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('evdevDriver removeDevice: Error removing uDevice: ' + str(e), debug.debugLevel.ERROR)
|
||||
try:
|
||||
del(self.gDevices[newDevice.fd])
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('evdevDriver addDevice: Error cleaning up gDevice: ' + str(e), debug.debugLevel.ERROR)
|
||||
|
||||
def grabDevice(self, fd):
|
||||
if not self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'grabDevices'):
|
||||
@@ -447,33 +450,33 @@ class driver(inputDriver):
|
||||
with self._deviceLock:
|
||||
try:
|
||||
self.env['runtime']['debug'].writeDebugOut('InputDriver evdev: device removed: ' + str(fd) + ' ' + str(self.iDevices[fd]), debug.debugLevel.INFO)
|
||||
except:
|
||||
self.env['runtime']['debug'].writeDebugOut('InputDriver evdev: device removed: ' + str(fd), debug.debugLevel.INFO)
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('InputDriver evdev: device removed: ' + str(fd) + ' Error: ' + str(e), debug.debugLevel.INFO)
|
||||
self.clearEventBuffer()
|
||||
try:
|
||||
self.ungrabDevice(fd)
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('evdevDriver removeDevice: Error ungrabbing device ' + str(fd) + ': ' + str(e), debug.debugLevel.ERROR)
|
||||
try:
|
||||
self.iDevices[fd].close()
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('evdevDriver removeDevice: Error closing iDevice ' + str(fd) + ': ' + str(e), debug.debugLevel.ERROR)
|
||||
try:
|
||||
self.uDevices[fd].close()
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('evdevDriver removeDevice: Error closing uDevice ' + str(fd) + ': ' + str(e), debug.debugLevel.ERROR)
|
||||
try:
|
||||
del(self.iDevices[fd])
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('evdevDriver removeDevice: Error deleting iDevice ' + str(fd) + ': ' + str(e), debug.debugLevel.ERROR)
|
||||
try:
|
||||
del(self.uDevices[fd])
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('evdevDriver removeDevice: Error deleting uDevice ' + str(fd) + ': ' + str(e), debug.debugLevel.ERROR)
|
||||
try:
|
||||
del(self.gDevices[fd])
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('evdevDriver removeDevice: Error deleting gDevice ' + str(fd) + ': ' + str(e), debug.debugLevel.ERROR)
|
||||
self.updateMPiDevicesFD()
|
||||
|
||||
def hasIDevices(self):
|
||||
@@ -491,8 +494,8 @@ class driver(inputDriver):
|
||||
try:
|
||||
self.UInputinject.write(e.EV_KEY, e.ecodes[key], state)
|
||||
self.UInputinject.syn()
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('evdevDriver sendKey: Error sending key ' + str(key) + ': ' + str(e), debug.debugLevel.ERROR)
|
||||
|
||||
def removeAllDevices(self):
|
||||
if not self.hasIDevices():
|
||||
|
||||
@@ -35,19 +35,19 @@ class driver(remoteDriver):
|
||||
client_sock, client_addr = self.fenrirSock.accept()
|
||||
try:
|
||||
rawdata = client_sock.recv(8129)
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('tcpDriver watchDog: Error receiving data from client: ' + str(e), debug.debugLevel.ERROR)
|
||||
try:
|
||||
data = rawdata.decode("utf-8").rstrip().lstrip()
|
||||
eventQueue.put({"Type":fenrirEventType.RemoteIncomming,
|
||||
"Data": data
|
||||
})
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('tcpDriver watchDog: Error decoding/queuing data: ' + str(e), debug.debugLevel.ERROR)
|
||||
try:
|
||||
client_sock.close()
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('tcpDriver watchDog: Error closing client socket: ' + str(e), debug.debugLevel.ERROR)
|
||||
if self.fenrirSock:
|
||||
self.fenrirSock.close()
|
||||
self.fenrirSock = None
|
||||
|
||||
@@ -22,8 +22,8 @@ class driver(remoteDriver):
|
||||
socketFile = ''
|
||||
try:
|
||||
socketFile = self.env['runtime']['settingsManager'].getSetting('remote', 'socketFile')
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('unixDriver watchDog: Error getting socket file setting: ' + str(e), debug.debugLevel.ERROR)
|
||||
if socketFile == '':
|
||||
if self.env['runtime']['settingsManager'].getSetting('screen', 'driver') =='vcsaDriver':
|
||||
socketFile = '/tmp/fenrirscreenreader-deamon.sock'
|
||||
@@ -45,21 +45,27 @@ class driver(remoteDriver):
|
||||
continue
|
||||
if self.fenrirSock in r:
|
||||
client_sock, client_addr = self.fenrirSock.accept()
|
||||
try:
|
||||
rawdata = client_sock.recv(8129)
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
data = rawdata.decode("utf-8").rstrip().lstrip()
|
||||
eventQueue.put({"Type":fenrirEventType.RemoteIncomming,
|
||||
"Data": data
|
||||
})
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
client_sock.close()
|
||||
except:
|
||||
pass
|
||||
# Ensure client socket is always closed to prevent resource leaks
|
||||
try:
|
||||
try:
|
||||
rawdata = client_sock.recv(8129)
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('unixDriver watchDog: Error receiving data from client: ' + str(e), debug.debugLevel.ERROR)
|
||||
rawdata = b'' # Set default empty data if recv fails
|
||||
|
||||
try:
|
||||
data = rawdata.decode("utf-8").rstrip().lstrip()
|
||||
eventQueue.put({"Type":fenrirEventType.RemoteIncomming,
|
||||
"Data": data
|
||||
})
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('unixDriver watchDog: Error decoding/queuing data: ' + str(e), debug.debugLevel.ERROR)
|
||||
finally:
|
||||
# Always close client socket, even if data processing fails
|
||||
try:
|
||||
client_sock.close()
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('unixDriver watchDog: Error closing client socket: ' + str(e), debug.debugLevel.ERROR)
|
||||
if self.fenrirSock:
|
||||
self.fenrirSock.close()
|
||||
self.fenrirSock = None
|
||||
|
||||
@@ -40,7 +40,9 @@ class Terminal:
|
||||
for y in lines:
|
||||
try:
|
||||
t = self.attributes[y]
|
||||
except:
|
||||
except Exception as e:
|
||||
# Terminal class doesn't have access to env, use fallback logging
|
||||
print(f'ptyDriver Terminal updateAttributes: Error accessing attributes: {e}')
|
||||
self.attributes.append([])
|
||||
|
||||
self.attributes[y] = [list(attribute[1:]) + [False, 'default', 'default'] for attribute in (buffer[y].values())]
|
||||
@@ -135,7 +137,9 @@ class driver(screenDriver):
|
||||
try:
|
||||
if env["TERM"] == '':
|
||||
env["TERM"] = 'linux'
|
||||
except:
|
||||
except Exception as e:
|
||||
# Child process doesn't have access to env, use fallback logging
|
||||
print(f'ptyDriver spawnTerminal: Error checking TERM environment: {e}')
|
||||
env["TERM"] = 'linux'
|
||||
os.execvpe(argv[0], argv, env)
|
||||
# File-like object for I/O with the child process aka command.
|
||||
@@ -184,7 +188,8 @@ class driver(screenDriver):
|
||||
if self.shortcutType == 'KEY':
|
||||
try:
|
||||
self.injectTextToScreen(msgBytes)
|
||||
except:
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('ptyDriver getInputData: Error injecting text to screen: ' + str(e), debug.debugLevel.ERROR)
|
||||
eventQueue.put({"Type":fenrirEventType.StopMainLoop,"Data":None})
|
||||
break
|
||||
else:
|
||||
|
||||
@@ -38,8 +38,8 @@ class driver(screenDriver):
|
||||
# set workaround for paste clipboard -> injectTextToScreen
|
||||
subprocess.run(['sysctl', 'dev.tty.legacy_tiocsti=1'],
|
||||
check=False, capture_output=True, timeout=5)
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('vcsaDriver shutdown: Error running fgconsole: ' + str(e), debug.debugLevel.ERROR)
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
self.env['runtime']['attributeManager'].appendDefaultAttributes([
|
||||
@@ -105,7 +105,8 @@ class driver(screenDriver):
|
||||
file.seek(0)
|
||||
try:
|
||||
d = file.read()
|
||||
except:
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('vcsaDriver getScreenText: Error reading file: ' + str(e), debug.debugLevel.ERROR)
|
||||
file.seek(0)
|
||||
while True:
|
||||
# Read from file
|
||||
@@ -162,19 +163,19 @@ class driver(screenDriver):
|
||||
if currScreen != oldScreen:
|
||||
try:
|
||||
watchdog.unregister(vcsa[oldScreen])
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('vcsaDriver updateWatchdog: Error unregistering watchdog: ' + str(e), debug.debugLevel.ERROR)
|
||||
try:
|
||||
watchdog.register(vcsa[currScreen], select.POLLPRI | select.POLLERR)
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('vcsaDriver updateWatchdog: Error registering watchdog: ' + str(e), debug.debugLevel.ERROR)
|
||||
self.updateCharMap(currScreen)
|
||||
oldScreen = currScreen
|
||||
try:
|
||||
vcsa[currScreen].seek(0)
|
||||
lastScreenContent = self.readFile(vcsa[currScreen])
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('vcsaDriver updateWatchdog: Error reading screen content: ' + str(e), debug.debugLevel.ERROR)
|
||||
vcsuContent = None
|
||||
if useVCSU:
|
||||
vcsu[currScreen].seek(0)
|
||||
@@ -233,23 +234,23 @@ class driver(screenDriver):
|
||||
try:
|
||||
if watchdog:
|
||||
watchdog.close()
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('vcsaDriver updateWatchdog: Error closing watchdog: ' + str(e), debug.debugLevel.ERROR)
|
||||
try:
|
||||
if tty:
|
||||
tty.close()
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('vcsaDriver shutdown: Error closing TTY: ' + str(e), debug.debugLevel.ERROR)
|
||||
for handle in vcsa.values():
|
||||
try:
|
||||
handle.close()
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('vcsaDriver shutdown: Error closing VCSA handle: ' + str(e), debug.debugLevel.ERROR)
|
||||
for handle in vcsu.values():
|
||||
try:
|
||||
handle.close()
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('vcsaDriver shutdown: Error closing VCSU handle: ' + str(e), debug.debugLevel.ERROR)
|
||||
|
||||
def createScreenEventData(self, screen, vcsaContent, vcsuContent = None):
|
||||
eventData = {
|
||||
@@ -269,15 +270,15 @@ class driver(screenDriver):
|
||||
try:
|
||||
eventData['text'], eventData['attributes'] =\
|
||||
self.autoDecodeVCSA(vcsaContent[4:], eventData['lines'], eventData['columns'])
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('vcsaDriver createScreenEventData: Error decoding VCSA content: ' + str(e), debug.debugLevel.ERROR)
|
||||
# VCSU seems to give b' ' instead of b'\x00\x00\x00' (tsp), deactivated until its fixed
|
||||
if vcsuContent != None:
|
||||
try:
|
||||
vcsuContentAsText = vcsuContent.decode('UTF-32')
|
||||
eventData['text'] = screen_utils.insertNewlines(vcsuContentAsText, eventData['columns'])
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('vcsaDriver createScreenEventData: Error decoding VCSU content: ' + str(e), debug.debugLevel.ERROR)
|
||||
return eventData.copy()
|
||||
def updateCharMap(self, screen):
|
||||
self.charmap = {}
|
||||
@@ -349,7 +350,8 @@ class driver(screenDriver):
|
||||
try:
|
||||
if sh & self.hichar:
|
||||
ch |= 0x100
|
||||
except:
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('vcsaDriver autoDecodeVCSA: Error processing character: ' + str(e), debug.debugLevel.ERROR)
|
||||
ch = None
|
||||
if self.hichar == 0x100:
|
||||
attr >>= 1
|
||||
@@ -364,8 +366,8 @@ class driver(screenDriver):
|
||||
bold = 1
|
||||
#if (ink != 7) or (paper != 0):
|
||||
# print(ink,paper)
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('vcsaDriver autoDecodeVCSA: Error processing attributes: ' + str(e), debug.debugLevel.ERROR)
|
||||
try:
|
||||
lineText += self.charmap[ch]
|
||||
except KeyError:
|
||||
|
||||
@@ -62,6 +62,18 @@ class driver(soundDriver):
|
||||
return
|
||||
if self.soundType == 'file':
|
||||
self.proc.kill()
|
||||
try:
|
||||
self.proc.wait(timeout=1.0) # Wait for process to finish to prevent zombies
|
||||
except subprocess.TimeoutExpired:
|
||||
pass # Process already terminated
|
||||
except Exception as e:
|
||||
pass # Handle any other wait errors
|
||||
if self.soundType == 'frequence':
|
||||
self.proc.kill()
|
||||
try:
|
||||
self.proc.wait(timeout=1.0) # Wait for process to finish to prevent zombies
|
||||
except subprocess.TimeoutExpired:
|
||||
pass # Process already terminated
|
||||
except Exception as e:
|
||||
pass # Handle any other wait errors
|
||||
self.soundType = ''
|
||||
|
||||
@@ -57,6 +57,9 @@ class driver(soundDriver):
|
||||
return
|
||||
self.cancel()
|
||||
self.mainloop.quit()
|
||||
# Wait for the GLib MainLoop thread to finish to prevent shutdown races
|
||||
if hasattr(self, 'thread') and self.thread.is_alive():
|
||||
self.thread.join(timeout=2.0) # 2 second timeout to prevent hanging
|
||||
|
||||
def _onPlayerMessage(self, bus, message):
|
||||
if not self._initialized:
|
||||
|
||||
@@ -10,6 +10,7 @@ from threading import Thread, Lock
|
||||
from queue import Queue, Empty
|
||||
import shlex
|
||||
from subprocess import Popen
|
||||
import subprocess
|
||||
from fenrirscreenreader.core.speechDriver import speechDriver
|
||||
|
||||
class speakQueue(Queue):
|
||||
@@ -73,17 +74,28 @@ class driver(speechDriver):
|
||||
return
|
||||
self.clear_buffer()
|
||||
self.lock.acquire(True)
|
||||
if self.proc:
|
||||
try:
|
||||
self.proc.terminate()
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('speechDriver:Cancel:self.proc.terminate():' + str(e),debug.debugLevel.WARNING)
|
||||
try:
|
||||
if self.proc:
|
||||
try:
|
||||
self.proc.kill()
|
||||
self.proc.terminate()
|
||||
# Wait for process to finish to prevent zombies
|
||||
try:
|
||||
self.proc.wait(timeout=1.0)
|
||||
except subprocess.TimeoutExpired:
|
||||
# If terminate didn't work, force kill
|
||||
self.proc.kill()
|
||||
self.proc.wait(timeout=1.0)
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('speechDriver:Cancel:self.proc.kill():' + str(e),debug.debugLevel.WARNING)
|
||||
self.proc = None
|
||||
self.lock.release()
|
||||
self.env['runtime']['debug'].writeDebugOut('speechDriver:Cancel:self.proc.terminate():' + str(e),debug.debugLevel.WARNING)
|
||||
try:
|
||||
self.proc.kill()
|
||||
self.proc.wait(timeout=1.0) # Wait after kill to prevent zombies
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('speechDriver:Cancel:self.proc.kill():' + str(e),debug.debugLevel.WARNING)
|
||||
self.proc = None
|
||||
finally:
|
||||
# Ensure lock is always released, even if process termination fails
|
||||
self.lock.release()
|
||||
def setCallback(self, callback):
|
||||
print('SpeechDummyDriver: setCallback')
|
||||
|
||||
|
||||
@@ -117,7 +117,8 @@ def getPhonetic(currChar):
|
||||
if currChar.isupper():
|
||||
phonChar = phonChar[0].upper() + phonChar[1:]
|
||||
return phonChar
|
||||
except:
|
||||
except Exception as e:
|
||||
# Utility function, no env access - return fallback
|
||||
return currChar
|
||||
|
||||
def presentCharForReview(env, char, interrupt=True, announceCapital=True, flush=False):
|
||||
|
||||
@@ -58,8 +58,10 @@ def isValidShell(shell = ''):
|
||||
return False
|
||||
if not os.access(shell,os.X_OK):
|
||||
return False
|
||||
except:
|
||||
return False
|
||||
except Exception as e:
|
||||
# Utility function, no env access - use fallback logging
|
||||
print(f'screen_utils isValidShell: Error checking shell {shell}: {e}')
|
||||
return False
|
||||
return True
|
||||
|
||||
def getShell():
|
||||
@@ -67,13 +69,15 @@ def getShell():
|
||||
shell = os.environ["FENRIRSHELL"]
|
||||
if isValidShell(shell):
|
||||
return shell
|
||||
except:
|
||||
except Exception as e:
|
||||
# Utility function, no env access - continue silently
|
||||
pass
|
||||
try:
|
||||
shell = os.environ["SHELL"]
|
||||
if isValidShell(shell):
|
||||
return shell
|
||||
except:
|
||||
except Exception as e:
|
||||
# Utility function, no env access - continue silently
|
||||
pass
|
||||
try:
|
||||
if os.access('/etc/passwd', os.R_OK):
|
||||
@@ -85,7 +89,8 @@ def getShell():
|
||||
if username == getpass.getuser():
|
||||
if isValidShell(shell):
|
||||
return shell
|
||||
except:
|
||||
except Exception as e:
|
||||
# Utility function, no env access - continue silently
|
||||
pass
|
||||
if isValidShell('/bin/bash'):
|
||||
return '/bin/bash'
|
||||
|
||||
Reference in New Issue
Block a user