## Development Philosophy **Clean code over backward compatibility.** Breaking changes are acceptable in major versions. - PEP8 compliance (snake_case for all variables/functions/settings) - Remove deprecated code completely - no compatibility hacks - Trust users to update configs when upgrading **Exception**: Never break core accessibility (speech output, basic navigation). ## Core Architecture ### Drivers - **Screen**: `vcsaDriver` (TTY), `ptyDriver` (terminal emulation) - **Input**: `evdevDriver` (evdev), `x11Driver` (X11 terminal mode) - **Speech**: `speechdDriver` (speech-dispatcher), `genericDriver` (subprocess) - **Sound**: `gstreamerDriver` (GStreamer), `genericDriver` (Sox subprocess) - **Remote**: `unixDriver` (Unix sockets), `tcpDriver` ### Command System Commands in trigger folders execute automatically: - `onKeyInput/`, `onCursorChange/`, `onScreenUpdate/`, `onScreenChanged/`, `onHeartBeat/` - Numeric prefixes control priority (lower = higher priority): `15000-char_echo.py` - Manual commands in `commands/commands/` ### Core Managers (in `src/fenrirscreenreader/core/`) `fenrirManager.py`, `commandManager.py`, `eventManager.py`, `screenManager.py`, `inputManager.py`, `outputManager.py` ### Configuration - Main: `config/settings/settings.conf` - Keyboards: `config/keyboard/` (desktop.conf, laptop.conf) - Sounds: `config/sound/` - Punctuation: `config/punctuation/` ## 🚨 CRITICAL: Files to NEVER Modify **These are timing-critical - only fix critical bugs, never refactor:** - `evdevDriver.py` - Input event processing - `vcsaDriver.py` - Screen monitoring Symptoms of breakage: echo changes, input lag, missing screen updates, sync issues. ## Development Commands ```bash # Run from source (requires root) cd src/ && sudo ./fenrir -f -d # foreground with debug # Validation before commit python3 tools/validate_syntax.py --fix python3 tools/validate_release.py --quick # Tests pytest tests/ pytest tests/ --cov=src/fenrirscreenreader --cov-report=html ``` **Note**: Standard TTY Fenrir blocks - only one instance at a time. `fenrir -x` can run multiple foreground X terminal instances. Ask user to run tests that need real Fenrir instances or root access. ## Creating Commands Use `commands/command_template.py` as base. Required methods: - `initialize(self, environment)`, `shutdown()`, `run()`, `get_description()` ### Import Pattern (Required) Fenrir's command loader doesn't support relative imports: ```python import os, importlib.util _base_path = os.path.join(os.path.dirname(__file__), 'base_file.py') _spec = importlib.util.spec_from_file_location("base_module", _base_path) _module = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(_module) BaseClass = _module.BaseClass ``` ### Consolidated Base Classes - **Bookmarks**: `bookmark_base.py` - `BookmarkCommand(id, 'read'|'set'|'clear')` - **Adjustments**: `adjustment_base.py` - `AdjustmentCommand('speech'|'sound', 'rate'|'pitch'|'volume', 'inc'|'dec')` - **VMenu Search**: `vmenu_search_base.py` - `VMenuSearchCommand('a'-'z')` ## VMenu System Application-specific menus in `vmenu-profiles/KEY/{app}/`: - Directories = submenus, `.py` files = actions - Activate: `Fenrir+F10`, navigate with arrows, Enter to execute ## Remote Control Unix socket: `/tmp/fenrirscreenreader-deamon.sock` TCP: localhost:22447 ```bash echo "command say Hello" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock echo "ls" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock echo "setting set speech#rate=0.8" | nc localhost 22447 ``` In `fenrir -x`, each instance has a private socket: `/tmp/fenrirscreenreader-.sock`. One instance may also own the standard socket. Use `ls`/`list` on the standard socket to discover registered instances and their socket paths. Untargeted remote commands use a short cross-process claim lock so only one instance handles the same broadcast command; direct commands to a private instance socket still run on that instance. Disable in untrusted environments: `[remote] enable=False` ## Key Implementation Details - Commands via `command_mod.command()` instantiation - Bookmark structure: `env['commandBuffer']['bookMarks'][ID][app]['1'/'2']` - VMenu search: `env['runtime']['vmenuManager'].searchEntry(char)` ## Recent Fixes (Reference) - Enhanced application detection for screen/tmux sessions - Table navigation consistency (sound feedback) - Blank line detection in 22 command files - Character/space review during navigation ## Safe vs Risky Changes **Safe**: Commands, VMenu profiles, config handling, sound/speech drivers, docs **Risky (extra testing)**: Core managers, event processing **Avoid**: evdevDriver, vcsaDriver, timing-critical code