#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Fenrir TTY screen reader # By Chrys, Storm Dragon, and contributors. import time from fenrirscreenreader.core import debug from fenrirscreenreader.core.inputDriver import InputDriver as inputDriver class driver(inputDriver): """PTY (Pseudo-terminal) input driver for Fenrir screen reader. This driver provides input handling for terminal emulation environments where direct device access (evdev) is not available or appropriate. It uses byte-based input processing instead of key event processing. This is primarily used when running Fenrir in terminal emulators, desktop environments, or other contexts where traditional TTY device access is not available. Features: - Byte-based input processing - Terminal emulation compatibility - Simplified input handling for non-TTY environments """ def __init__(self): self._is_initialized = False inputDriver.__init__(self) def initialize(self, environment): """Initialize the PTY input driver. Sets the input manager to use byte-based shortcuts instead of key-based shortcuts, enabling proper operation in terminal emulation environments. Args: environment: Fenrir environment dictionary Returns: bool: True if initialization successful, False otherwise """ try: if environment is None: raise ValueError("Environment cannot be None") self.env = environment # Validate required managers are available if "runtime" not in self.env: raise ValueError("Runtime environment missing") if "InputManager" not in self.env["runtime"]: raise ValueError("InputManager not available") self.env["runtime"]["InputManager"].set_shortcut_type("BYTE") self._is_initialized = True self.env["runtime"]["DebugManager"].write_debug_out( "PTY inputDriver: Initialized with byte-based shortcuts", debug.DebugLevel.INFO ) return True except Exception as e: # Log error if possible, otherwise fallback to print try: if hasattr(self, 'env') and self.env and "runtime" in self.env: self.env["runtime"]["DebugManager"].write_debug_out( f"PTY inputDriver: Initialization failed: {e}", debug.DebugLevel.ERROR ) else: print(f"PTY inputDriver initialization error: {e}") except: print(f"PTY inputDriver initialization error: {e}") self._is_initialized = False return False def shutdown(self): """Shutdown the PTY input driver. Performs cleanup operations when the driver is being stopped. For PTY driver, this involves cleaning up any resources and logging the shutdown. """ if not self._is_initialized: return try: self.env["runtime"]["DebugManager"].write_debug_out( "PTY inputDriver: Shutting down", debug.DebugLevel.INFO ) except Exception as e: # Fallback logging if debug manager is unavailable print(f"PTY inputDriver shutdown error: {e}") finally: self._is_initialized = False def get_input_event(self): """Get input event from PTY. For PTY driver, input events are handled through the byte-based shortcut system rather than direct device events. This method returns None as PTY input is processed through the screen driver and InputManager's byte processing. Returns: None: PTY driver uses byte-based processing, not event-based """ return None def is_device_connected(self): """Check if PTY input device is connected. For PTY driver, the "device" is the terminal interface itself, which is considered connected if the driver is initialized. Returns: bool: True if driver is initialized, False otherwise """ return self._is_initialized def get_device_name(self): """Get the name of the PTY input device. Returns: str: Human-readable name of the PTY input device """ return "PTY (Pseudo-terminal) Input" def grab_devices(self, grab=True): """Grab or release input devices. For PTY driver, device grabbing is not applicable since input is processed through terminal emulation rather than direct device access. Args: grab (bool): Whether to grab (True) or release (False) devices Returns: bool: Always returns True for PTY driver (no-op success) """ if not self._is_initialized: return False action = "grab" if grab else "release" self.env["runtime"]["DebugManager"].write_debug_out( f"PTY inputDriver: {action} devices (no-op for PTY)", debug.DebugLevel.INFO ) return True def has_device_detection(self): """Check if driver supports device detection. PTY driver does not support dynamic device detection since it operates on the terminal interface directly. Returns: bool: Always False for PTY driver """ return False def get_device_list(self): """Get list of available input devices. For PTY driver, there is only one logical device - the terminal interface itself. Returns: list: Single-item list containing PTY device info """ if not self._is_initialized: return [] return [{ 'name': 'PTY Terminal', 'path': '/dev/pts/*', 'type': 'terminal', 'connected': True }] def get_led_state(self, led_mask=None): """Get LED state information. PTY driver cannot access LED states since it operates through terminal emulation rather than direct hardware access. Args: led_mask: LED mask parameter (ignored for PTY) Returns: dict: Empty dict (no LED access for PTY) """ return {} def set_led_state(self, led_dict): """Set LED states. PTY driver cannot control LEDs since it operates through terminal emulation rather than direct hardware access. Args: led_dict (dict): LED state dictionary (ignored for PTY) Returns: bool: Always False (LED control not supported) """ return False