Compare commits
153 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bd54ec0edb | |||
| b9518f52ec | |||
| c143c9a561 | |||
| 7e2f927596 | |||
| 788e678ed6 | |||
| ea89e90c2f | |||
| ce43d64e77 | |||
| 618987546a | |||
| 604221a29d | |||
| 89b85c6f17 | |||
| 6e3d7fee94 | |||
| 089850ac18 | |||
| 5b7c08260a | |||
| d4b2fec1db | |||
| 1f7aa99cc0 | |||
| d853e1b24d | |||
| e8bc34eaf5 | |||
| f84167a7fb | |||
| 29a6c3eb42 | |||
| ac7348895f | |||
| 4caef89f6b | |||
| 8467bd74c3 | |||
| f09437ea60 | |||
| 19194e73fc | |||
| 096919a2da | |||
| a8e4d7bb2a | |||
| 8966275071 | |||
| c48a9a6731 | |||
| 6876547590 | |||
| 116f254e11 | |||
| 5dccdd27c4 | |||
| fa63ecadbe | |||
| 96c5184450 | |||
| b599a25945 | |||
| 4022fc4006 | |||
| ab7818fd4c | |||
| 878eef5c5b | |||
| 38ef1c2d72 | |||
| 57980225ad | |||
| 9e2d5a89b3 | |||
| c7d74726da | |||
| be78db0d58 | |||
| 0af7d94014 | |||
| 42ba3fdad2 | |||
| 6fb8298b9f | |||
| 114a7b0da7 | |||
| 90efad362b | |||
| 3c61b6629a | |||
| b6689d93bf | |||
| a60efdbe07 | |||
| b38b0a2dab | |||
| 37e281a1f7 | |||
| 6d4f55ffe5 | |||
| 8638bca1d5 | |||
| 0273f9b956 | |||
| 1670c5711b | |||
| fed8f24126 | |||
| 40120f825c | |||
| 17dea6b026 | |||
| 57c09e0db9 | |||
| 4050c32a16 | |||
| 2e10c1c43b | |||
| 1e67876883 | |||
| 14cf6b6088 | |||
| 900a027643 | |||
| 0e50175463 | |||
| 7283f04778 | |||
| 8d3495f74f | |||
| a6cd47dafc | |||
| 0bb2e52deb | |||
| b8eb815a86 | |||
| beca468338 | |||
| a26fe26c8c | |||
| 508fd11610 | |||
| afe0e71a1d | |||
| 9e8d0b3869 | |||
| d7f86ca0de | |||
| 49a79d2722 | |||
| 4ab024d115 | |||
| c4ae27a01b | |||
| 668d39b444 | |||
| 8b25afbf5a | |||
| efeb040f75 | |||
| 7a17b36d50 | |||
| 047a31b4bf | |||
| 096aef9f08 | |||
| 76472b83b5 | |||
| a52bf624ec | |||
| f4e28a246f | |||
| 560ceb26c9 | |||
| 61868c94e5 | |||
| f462ca7990 | |||
| f0bbcb8a38 | |||
| aed627ec2a | |||
| e62b887e9c | |||
| bf0d134187 | |||
| c66a9ba9c2 | |||
| 2092a3e257 | |||
| d46d8de3ee | |||
| 75a8447759 | |||
| 1650eec768 | |||
| 5bb786ef4c | |||
| 7f7faa17d3 | |||
| 2766f70c5d | |||
| 8d781643bc | |||
| c184cf023a | |||
| 841c221c7b | |||
| 87553bdc38 | |||
| 77a3aae5a4 | |||
| aabc202d83 | |||
| 2f3a114790 | |||
| c797974560 | |||
| af4740d5ad | |||
| 5ef5faaebe | |||
| 7041d2567a | |||
| 2c38bcf5f4 | |||
| 96cdda99c4 | |||
| 0658d37ae8 | |||
| a6bb3e1301 | |||
| 5ff653bd00 | |||
| 356f4b01c1 | |||
| c7ad4d9200 | |||
| d274fe78f3 | |||
| f5344a7227 | |||
| 90ffc2fc08 | |||
| b635f7538b | |||
| 7f473b72a7 | |||
| e255651c28 | |||
| b3d73102fc | |||
| 78c1cbbb6b | |||
| 8c26d93001 | |||
| 98b9c56af7 | |||
| 8bada48a09 | |||
| 0a2c8472c0 | |||
| e9a0101fe7 | |||
| 69eade3327 | |||
| 73f67c2a04 | |||
| 9ef9d762f4 | |||
| 84293db6dc | |||
| 914535d12b | |||
| 94a1acbaca | |||
| 8c233e0385 | |||
| b6a9e1a692 | |||
| d41ea8388f | |||
| 2dd732dc9d | |||
| b68a28e857 | |||
| 8c668cc0cc | |||
| 579bf0f0f0 | |||
| d1bad818cd | |||
| e177c7f486 | |||
| ae4c418323 | |||
| b9abf02b12 | |||
| 0c116adaf2 |
@@ -0,0 +1,128 @@
|
||||
## 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-daemon.sock`
|
||||
TCP: localhost:22447
|
||||
|
||||
```bash
|
||||
echo "command say Hello" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
echo "ls" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
echo "setting set speech#rate=0.8" | nc localhost 22447
|
||||
```
|
||||
|
||||
In `fenrir -x`, each instance has a private socket:
|
||||
`/tmp/fenrirscreenreader-<pid>.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
|
||||
@@ -1,7 +1,6 @@
|
||||
# Fenrir
|
||||
|
||||
A modern, modular, flexible and fast console screen reader.
|
||||
It should run on any operating system. If you want to help, or write drivers to make it work on other systems, just let me know.
|
||||
A modern, modular, flexible and fast console screen reader for Linux.
|
||||
This software is licensed under the LGPL v3.
|
||||
|
||||
**Current maintainer:** Storm Dragon
|
||||
@@ -9,7 +8,7 @@ This software is licensed under the LGPL v3.
|
||||
|
||||
## Key Features
|
||||
|
||||
- **Multiple Interface Support**: Works in Linux TTY, and terminal emulators
|
||||
- **Linux Console Support**: Works as a Linux TTY screen reader, with optional X11 terminal mode
|
||||
- **Flexible Driver System**: Modular architecture with multiple drivers for speech, sound, input, and screen
|
||||
- **Review Mode**: Navigate and review screen content without moving the edit cursor
|
||||
- **Table Navigation**: Advanced table mode with column headers, cell-by-cell navigation, and boundary feedback
|
||||
@@ -24,12 +23,14 @@ This software is licensed under the LGPL v3.
|
||||
- **Tutorial Mode**: Built-in help system for learning keyboard shortcuts
|
||||
|
||||
|
||||
## OS Requirements
|
||||
## Platform Support
|
||||
|
||||
- Linux (ptyDriver, vcsaDriver, evdevDriver) - Primary platform with full support
|
||||
- macOS (ptyDriver) - Limited support
|
||||
- BSD (ptyDriver) - Limited support
|
||||
- Windows (ptyDriver) - Limited support
|
||||
Fenrir is a Linux screen reader. Linux is the only officially supported platform.
|
||||
|
||||
**Other platforms (macOS, BSD, Windows):** Pull requests adding support for other operating systems may be accepted provided they do not break Linux functionality. However, no special care will be taken to preserve functionality on secondary platforms. If changes to Fenrir break support on a non-Linux OS, it is the responsibility of third-party contributors to submit fixes.
|
||||
|
||||
- Linux TTY (`vcsaDriver`, `evdevDriver`) - Full support
|
||||
- X11 terminal emulators (`-x`, `ptyDriver`, `x11Driver`) - Supported
|
||||
|
||||
|
||||
## Core Requirements
|
||||
@@ -49,11 +50,8 @@ This software is licensed under the LGPL v3.
|
||||
- ReadWrite permission:
|
||||
- /dev/input
|
||||
- /dev/uinput
|
||||
2. **ptyDriver** - Terminal emulation input driver (cross-platform)
|
||||
- python-pyte
|
||||
3. **atspiDriver** - AT-SPI input driver for desktop environments
|
||||
- python-pyatspi2
|
||||
|
||||
2. **x11Driver** - X11 terminal-scoped input driver for `fenrir -x`
|
||||
- python-xlib
|
||||
### Remote Drivers:
|
||||
1. **unixDriver** - Unix socket remote control (default)
|
||||
- socat (for command-line interaction)
|
||||
@@ -70,7 +68,7 @@ This software is licensed under the LGPL v3.
|
||||
- /dev/tty[1-64]
|
||||
- /dev/vcsa[1-64]
|
||||
- read logind DBUS
|
||||
2. **ptyDriver** - Terminal emulation driver (cross-platform)
|
||||
2. **ptyDriver** - Terminal emulation screen driver for `fenrir -x`
|
||||
- python-pyte
|
||||
|
||||
|
||||
@@ -81,7 +79,15 @@ This software is licensed under the LGPL v3.
|
||||
- python-speechd
|
||||
2. **genericDriver** - Generic subprocess speech driver
|
||||
- espeak or espeak-ng (or any TTS command)
|
||||
3. **debugDriver** - Debug speech driver for testing
|
||||
3. **dectalkDriver** - Serial DECtalk-compatible hardware speech driver
|
||||
- RPITalk gadget mode or a DECtalk-compatible serial device
|
||||
4. **litetalkDriver** - Serial LiteTalk-compatible hardware speech driver
|
||||
- RPITalk gadget mode or a LiteTalk-compatible serial device
|
||||
5. **doubletalkDriver** - Serial DoubleTalk LT-compatible hardware speech driver
|
||||
- DoubleTalk LT; does not support the internal DoubleTalk PC card
|
||||
6. **tripletalkDriver** - Serial TripleTalk-compatible hardware speech driver
|
||||
- External DB9 serial TripleTalk devices, or USB models that expose a tty serial device
|
||||
7. **debugDriver** - Debug speech driver for testing
|
||||
- No dependencies
|
||||
|
||||
|
||||
@@ -125,14 +131,76 @@ Requires root privileges
|
||||
sudo ./fenrir
|
||||
|
||||
Settings are located in:
|
||||
- **After installation**: `/etc/fenrir/settings/settings.conf`
|
||||
- **System-wide installation**: `/etc/fenrirscreenreader/settings/settings.conf`
|
||||
- **User-local settings**: `~/.local/share/stormux/fenrirscreenreader/settings/settings.conf`
|
||||
- **Development**: `config/settings/settings.conf`
|
||||
|
||||
When Fenrir runs as a regular user, including `fenrir -x`, it loads the
|
||||
user-local settings file if it exists. If it does not exist, Fenrir falls back
|
||||
to the system settings file, but saving settings writes to the user-local path.
|
||||
When Fenrir runs as root, settings save to the system-wide path by default.
|
||||
|
||||
User sound themes are loaded before system themes from
|
||||
`~/.local/stormux/fenrir/sounds/`. User scripts are loaded before configured
|
||||
system scripts from `~/.local/stormux/fenrir/`.
|
||||
|
||||
By default Fenrir uses:
|
||||
- **Sound driver**: genericDriver (via sox)
|
||||
- **Speech driver**: speechdDriver (via speech-dispatcher)
|
||||
- **Input driver**: evdevDriver (Linux) or ptyDriver (other platforms)
|
||||
- **Screen driver**: vcsaDriver (Linux TTY) or ptyDriver (terminal emulation)
|
||||
- **Input driver**: evdevDriver for Linux TTY, x11Driver for `fenrir -x`
|
||||
- **Screen driver**: vcsaDriver for Linux TTY, ptyDriver for `fenrir -x`
|
||||
|
||||
## Audio Configuration
|
||||
|
||||
Both PulseAudio and PipeWire require special configuration to allow console applications running as root (like Fenrir) to route audio to your regular user session. This is normal audio system behavior, not a Fenrir issue.
|
||||
|
||||
### Quick Setup - Direct Script Download
|
||||
|
||||
For non-Fenrir users or quick setup, download and run these scripts directly:
|
||||
|
||||
#### PulseAudio Configuration
|
||||
```bash
|
||||
# Download the script
|
||||
wget https://git.stormux.org/storm/fenrir/raw/branch/master/tools/configure_pulse.sh
|
||||
chmod +x configure_pulse.sh
|
||||
|
||||
# Run twice: once as user, once as root
|
||||
./configure_pulse.sh
|
||||
sudo ./configure_pulse.sh
|
||||
```
|
||||
|
||||
#### PipeWire Configuration
|
||||
```bash
|
||||
# Download the script
|
||||
wget https://git.stormux.org/storm/fenrir/raw/branch/master/tools/configure_pipewire.sh
|
||||
chmod +x configure_pipewire.sh
|
||||
|
||||
# Run twice: once as user, once as root
|
||||
./configure_pipewire.sh
|
||||
sudo ./configure_pipewire.sh
|
||||
```
|
||||
|
||||
**Direct links:**
|
||||
- [configure_pulse.sh](https://git.stormux.org/storm/fenrir/raw/branch/master/tools/configure_pulse.sh)
|
||||
- [configure_pipewire.sh](https://git.stormux.org/storm/fenrir/raw/branch/master/tools/configure_pipewire.sh)
|
||||
|
||||
### Using Installed Scripts
|
||||
|
||||
If you have Fenrir installed, the scripts are available at:
|
||||
|
||||
**PulseAudio:**
|
||||
```bash
|
||||
/usr/share/fenrirscreenreader/tools/configure_pulse.sh
|
||||
sudo /usr/share/fenrirscreenreader/tools/configure_pulse.sh
|
||||
```
|
||||
|
||||
**PipeWire:**
|
||||
```bash
|
||||
/usr/share/fenrirscreenreader/tools/configure_pipewire.sh
|
||||
sudo /usr/share/fenrirscreenreader/tools/configure_pipewire.sh
|
||||
```
|
||||
|
||||
**Note:** These scripts work for any console application that needs root audio access, not just Fenrir.
|
||||
|
||||
## Getting Started
|
||||
|
||||
@@ -148,6 +216,7 @@ By default Fenrir uses:
|
||||
2. **Basic Navigation**:
|
||||
- **Fenrir Key**: By default `Insert`, `Keypad Insert`, or `Meta/Super` key
|
||||
- **Tutorial Mode**: `Fenrir + H` to learn all commands interactively
|
||||
- **Speech History**: `Fenrir + Ctrl + H` to review recent speech
|
||||
- **Quit Fenrir**: `Fenrir + Q`
|
||||
|
||||
3. **Essential Commands**:
|
||||
@@ -167,10 +236,11 @@ Fenrir supports two main keyboard layouts:
|
||||
- **Desktop Layout**: Uses numeric keypad for navigation (recommended for desktop users)
|
||||
- **Laptop Layout**: Alternative bindings for keyboards without numeric keypad
|
||||
|
||||
Configure in `/etc/fenrir/settings/settings.conf`:
|
||||
Configure in `/etc/fenrirscreenreader/settings/settings.conf` or your
|
||||
user-local settings file:
|
||||
```ini
|
||||
[keyboard]
|
||||
keyboardLayout=desktop # or 'laptop'
|
||||
keyboard_layout=desktop # or 'laptop'
|
||||
```
|
||||
|
||||
### First Time Setup
|
||||
@@ -196,22 +266,24 @@ Fenrir includes a powerful remote control system that allows external applicatio
|
||||
|
||||
### Configuration
|
||||
|
||||
Enable remote control in `/etc/fenrir/settings/settings.conf`:
|
||||
Enable remote control in `/etc/fenrirscreenreader/settings/settings.conf` or
|
||||
your user-local settings file:
|
||||
|
||||
```ini
|
||||
[remote]
|
||||
enable=True
|
||||
driver=unixDriver # or tcpDriver
|
||||
port=22447 # for TCP driver
|
||||
socketFile= # custom socket path (optional)
|
||||
enableSettingsRemote=True # allow settings changes
|
||||
enableCommandRemote=True # allow command execution
|
||||
socket_file= # custom socket path (optional)
|
||||
enable_settings_remote=True # allow settings changes
|
||||
enable_command_remote=True # allow command execution
|
||||
```
|
||||
|
||||
### Remote Drivers
|
||||
|
||||
1. **unixDriver** (recommended): Uses Unix domain sockets
|
||||
- Socket location: `/tmp/fenrirscreenreader-deamon.sock` (TTY mode) or `/tmp/fenrirscreenreader-<pid>.sock`
|
||||
- Socket location: `/tmp/fenrirscreenreader-daemon.sock` for the standard control socket
|
||||
- `fenrir -x` instances also create private sockets: `/tmp/fenrirscreenreader-<pid>.sock`
|
||||
- More secure, local-only access
|
||||
- Works with `socat`
|
||||
|
||||
@@ -224,89 +296,105 @@ enableCommandRemote=True # allow command execution
|
||||
|
||||
The `socat` command provides the easiest way to send commands to Fenrir:
|
||||
|
||||
#### Instance Discovery
|
||||
```bash
|
||||
# List registered Fenrir instances and their socket paths
|
||||
echo "ls" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
```
|
||||
|
||||
In X terminal mode (`fenrir -x`), multiple Fenrir instances can run at the same
|
||||
time. Each instance has a private socket, and one instance may also own the
|
||||
standard control socket. Use `ls` or `command ls` on the standard socket to find
|
||||
the private socket for a specific instance. Commands sent to the standard socket
|
||||
are handled by its owner when possible; otherwise they are forwarded to a
|
||||
registered private socket, preferring the sender's Fenrir ancestor when one can
|
||||
be found. Untargeted commands sent through a shared or broadcast path are
|
||||
claimed by one instance so duplicate instances do not all perform the same
|
||||
action.
|
||||
|
||||
#### Basic Speech Control
|
||||
```bash
|
||||
# Interrupt current speech
|
||||
echo "command interrupt" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "command interrupt" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Speak custom text
|
||||
echo "command say Hello, this is a test message" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "command say Hello, this is a test message" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Temporarily disable speech (until next keystroke)
|
||||
echo "command tempdisablespeech" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "command tempdisablespeech" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
```
|
||||
|
||||
#### Settings Control
|
||||
```bash
|
||||
# Enable highlight tracking mode
|
||||
echo "setting set focus#highlight=True" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set focus#highlight=True" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Change speech parameters
|
||||
echo "setting set speech#rate=0.8" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set speech#pitch=0.6" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set speech#volume=0.9" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set speech#rate=0.8" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
echo "setting set speech#pitch=0.6" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
echo "setting set speech#volume=0.9" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Change punctuation level (none/some/most/all)
|
||||
echo "setting set general#punctuationLevel=all" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set general#punctuationLevel=none" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set general#punctuation_level=all" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
echo "setting set general#punctuation_level=none" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Voice and TTS engine control
|
||||
echo "setting set speech#voice=en-us+f3" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set speech#module=espeak-ng" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set speech#voice=en-us+f3" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
echo "setting set speech#module=espeak-ng" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Disable sound temporarily
|
||||
echo "setting set sound#enabled=False" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set sound#volume=0.5" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set sound#enabled=False" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
echo "setting set sound#volume=0.5" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Keyboard and input settings
|
||||
echo "setting set keyboard#charEchoMode=1" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set keyboard#wordEcho=True" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set keyboard#char_echo_mode=1" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
echo "setting set keyboard#word_echo=True" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Screen control (ignore specific TTYs)
|
||||
echo "setting set screen#ignoreScreen=1,2,3" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set screen#ignore_screen=1,2,3" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Multiple settings at once
|
||||
echo "setting set speech#rate=0.8;sound#volume=0.7;general#punctuationLevel=most" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set speech#rate=0.8;sound#volume=0.7;general#punctuation_level=most" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Reset all settings to defaults
|
||||
echo "setting reset" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting reset" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Save current settings
|
||||
echo "setting save" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting saveas /tmp/my-fenrir-settings.conf" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting save" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
echo "setting saveas /tmp/my-fenrir-settings.conf" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
```
|
||||
|
||||
#### Clipboard Operations
|
||||
```bash
|
||||
# Place text into clipboard
|
||||
echo "command clipboard This text will be copied to clipboard" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "command clipboard This text will be copied to clipboard" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Export clipboard to file
|
||||
echo "command exportclipboard" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "command exportclipboard" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
```
|
||||
|
||||
#### Window Management
|
||||
```bash
|
||||
# Define a window area (x1 y1 x2 y2)
|
||||
echo "command window 0 0 80 24" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "command window 0 0 80 24" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Reset window to full screen
|
||||
echo "command resetwindow" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "command resetwindow" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
```
|
||||
|
||||
#### VMenu Control
|
||||
```bash
|
||||
# Set virtual menu context
|
||||
echo "command vmenu nano/file" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "command vmenu nano/file" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Reset virtual menu
|
||||
echo "command resetvmenu" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "command resetvmenu" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
```
|
||||
|
||||
#### Application Control
|
||||
```bash
|
||||
# Quit Fenrir
|
||||
echo "command quitapplication" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "command quitapplication" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
```
|
||||
|
||||
### Using TCP Driver
|
||||
@@ -351,6 +439,9 @@ setting <action> [parameters]
|
||||
**Application Commands:**
|
||||
- `command quitapplication` - Quit Fenrir
|
||||
|
||||
**Instance Commands:**
|
||||
- `ls` / `list` / `command ls` / `command list` - List registered Fenrir instances and their socket paths
|
||||
|
||||
#### Available Settings
|
||||
|
||||
**Settings Commands:**
|
||||
@@ -368,8 +459,16 @@ setting <action> [parameters]
|
||||
- `speech#volume=0.1-1.0` - Speech volume
|
||||
- `speech#voice=voice_name` - Voice selection (e.g., "en-us+f3")
|
||||
- `speech#module=module_name` - TTS module (e.g., "espeak-ng")
|
||||
- `speech#driver=driver_name` - Speech driver (speechdDriver/genericDriver)
|
||||
- `speech#autoReadIncoming=True/False` - Auto-read new text
|
||||
- `speech#driver=driver_name` - Speech driver (speechdDriver/genericDriver/dectalkDriver/litetalkDriver/doubletalkDriver/tripletalkDriver)
|
||||
- `speech#hardware_device=/dev/ttyS0` - Hardware synth serial device for dectalkDriver/litetalkDriver
|
||||
- `speech#hardware_baud_rate=9600` - Hardware synth serial baud rate
|
||||
- `speech#history_size=50` - Number of spoken items kept in runtime speech history
|
||||
|
||||
USB hardware synths are supported only when Linux exposes them as a serial tty
|
||||
such as `/dev/ttyACM0` or `/dev/ttyUSB0`. A USB-only TripleTalk with no tty
|
||||
device would require a separate USB protocol driver. Use an explicit
|
||||
`speech#hardware_device` path for hardware speech.
|
||||
- `speech#auto_read_incoming=True/False` - Auto-read new text
|
||||
|
||||
*Sound Settings:*
|
||||
- `sound#enabled=True/False` - Enable/disable sound
|
||||
@@ -378,32 +477,32 @@ setting <action> [parameters]
|
||||
- `sound#theme=theme_name` - Sound theme
|
||||
|
||||
*General Settings:*
|
||||
- `general#punctuationLevel=none/some/most/all` - Punctuation verbosity
|
||||
- `general#debugLevel=0-3` - Debug level
|
||||
- `general#punctuation_level=none/some/most/all` - Punctuation verbosity
|
||||
- `general#debug_level=0-3` - Debug level
|
||||
- `general#emoticons=True/False` - Enable emoticon replacement
|
||||
- `general#autoSpellCheck=True/False` - Automatic spell checking
|
||||
- `general#auto_spell_check=True/False` - Automatic spell checking
|
||||
|
||||
*Focus Settings:*
|
||||
- `focus#cursor=True/False` - Follow text cursor
|
||||
- `focus#highlight=True/False` - Follow text highlighting
|
||||
|
||||
*Keyboard Settings:*
|
||||
- `keyboard#charEchoMode=0-2` - Character echo (0=none, 1=always, 2=capslock only)
|
||||
- `keyboard#wordEcho=True/False` - Echo complete words
|
||||
- `keyboard#charDeleteEcho=True/False` - Echo deleted characters
|
||||
- `keyboard#interruptOnKeyPress=True/False` - Interrupt speech on key press
|
||||
- `keyboard#char_echo_mode=0-2` - Character echo (0=none, 1=always, 2=capslock only)
|
||||
- `keyboard#word_echo=True/False` - Echo complete words
|
||||
- `keyboard#char_delete_echo=True/False` - Echo deleted characters
|
||||
- `keyboard#interrupt_on_key_press=True/False` - Interrupt speech on key press
|
||||
|
||||
*Screen Settings:*
|
||||
- `screen#ignoreScreen=1,2,3` - TTY screens to ignore
|
||||
- `screen#autodetectIgnoreScreen=True/False` - Auto-detect screens to ignore
|
||||
- `screen#screenUpdateDelay=float` - Screen update delay
|
||||
- `screen#ignore_screen=1,2,3` - TTY screens to ignore
|
||||
- `screen#autodetect_ignore_screen=True/False` - Auto-detect screens to ignore
|
||||
- `screen#screen_update_delay=float` - Screen update delay
|
||||
|
||||
*Time Settings:*
|
||||
- `time#enabled=True/False` - Enable time announcements
|
||||
- `time#presentTime=True/False` - Announce time
|
||||
- `time#presentDate=True/False` - Announce date changes
|
||||
- `time#delaySec=seconds` - Announcement interval
|
||||
- `time#onMinutes=00,30` - Specific minutes to announce
|
||||
- `time#present_time=True/False` - Announce time
|
||||
- `time#present_date=True/False` - Announce date changes
|
||||
- `time#delay_sec=seconds` - Announcement interval
|
||||
- `time#on_minutes=00,30` - Specific minutes to announce
|
||||
|
||||
## Table Navigation
|
||||
|
||||
@@ -497,7 +596,7 @@ Fenrir provides intelligent progress bar detection and audio feedback for variou
|
||||
|
||||
To enable progress monitoring:
|
||||
1. Add a key binding in your keyboard layout file
|
||||
2. Or use the remote control system: `echo "command progress_bar_monitor" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock`
|
||||
2. Or use the remote control system: `echo "command progress_bar_monitor" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock`
|
||||
|
||||
### Progress Detection Patterns
|
||||
|
||||
@@ -558,7 +657,7 @@ Building...
|
||||
|
||||
```bash
|
||||
# Enable progress monitoring
|
||||
echo "command progress_bar_monitor" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "command progress_bar_monitor" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Common scenarios where progress monitoring is useful:
|
||||
wget https://example.com/large-file.zip # Download progress
|
||||
@@ -571,7 +670,7 @@ rsync -av source/ destination/ # File synchronization
|
||||
### Customization
|
||||
|
||||
Progress monitoring can be configured through settings:
|
||||
- **Default enabled**: Set `progressMonitoring=True` in sound section
|
||||
- **Default enabled**: Set `progress_monitoring=True` in sound section
|
||||
- **Sound integration**: Works with all sound drivers (sox, gstreamer)
|
||||
- **Remote control**: Enable/disable through remote commands
|
||||
|
||||
@@ -582,7 +681,7 @@ Progress monitoring can be configured through settings:
|
||||
#!/bin/bash
|
||||
# notify_fenrir.sh - Send notifications to Fenrir
|
||||
|
||||
SOCKET="/tmp/fenrirscreenreader-deamon.sock"
|
||||
SOCKET="/tmp/fenrirscreenreader-daemon.sock"
|
||||
|
||||
fenrir_say() {
|
||||
echo "command say $1" | socat - UNIX-CLIENT:$SOCKET
|
||||
@@ -605,7 +704,7 @@ import os
|
||||
|
||||
def send_fenrir_command(command):
|
||||
"""Send command to Fenrir via Unix socket"""
|
||||
socket_path = "/tmp/fenrirscreenreader-deamon.sock"
|
||||
socket_path = "/tmp/fenrirscreenreader-daemon.sock"
|
||||
if os.path.exists(socket_path):
|
||||
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
try:
|
||||
@@ -625,8 +724,8 @@ send_fenrir_command("setting set speech#rate=0.9")
|
||||
- TCP driver binds only to localhost (127.0.0.1)
|
||||
- Socket file permissions are set to write-only (0o222)
|
||||
- Commands are processed with Fenrir's privileges
|
||||
- Settings changes can be disabled via `enableSettingsRemote=False`
|
||||
- Command execution can be disabled via `enableCommandRemote=False`
|
||||
- Settings changes can be disabled via `enable_settings_remote=False`
|
||||
- Command execution can be disabled via `enable_command_remote=False`
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
@@ -636,34 +735,9 @@ send_fenrir_command("setting set speech#rate=0.9")
|
||||
- Ensure remote driver is enabled in settings
|
||||
|
||||
**Commands not working:**
|
||||
- Verify `enableCommandRemote=True` in settings
|
||||
- Verify `enable_command_remote=True` in settings
|
||||
- Check Fenrir debug logs: `/var/log/fenrir.log`
|
||||
- Test with simple command: `echo "command interrupt" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock`
|
||||
|
||||
## Configure pulseaudio
|
||||
|
||||
Pulseaudio by default only plays sound for the user its currently running for. As fenrir is running as root, your local user does not hear the sound and speech produced by fenrir.
|
||||
for this fenrir provides a script to configure pulseaudio to stream the sound played as root to your local user. This is not a issue of fenrir but this is how pulseaudio works.
|
||||
|
||||
just run the configuration script twice (once as user, once as root):
|
||||
|
||||
/usr/share/fenrirscreenreader/tools/configure_pulse.sh
|
||||
sudo /usr/share/fenrirscreenreader/tools/configure_pulse.sh
|
||||
|
||||
The script is also located in the tools directory in git
|
||||
|
||||
|
||||
## Configure pipewire
|
||||
|
||||
Pipewire by default only plays sound for the user its currently running for. As fenrir is running as root, your local user does not hear the sound and speech produced by fenrir.
|
||||
for this fenrir provides a script to configure pipewire to stream the sound played as root to your local user. This is not a issue of fenrir but this is how pipewire works.
|
||||
|
||||
just run the configuration script twice (once as user, once as root):
|
||||
|
||||
/usr/share/fenrirscreenreader/tools/configure_pipewire.sh
|
||||
sudo /usr/share/fenrirscreenreader/tools/configure_pipewire.sh
|
||||
|
||||
The script is also located in the tools directory in git
|
||||
- Test with simple command: `echo "command interrupt" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock`
|
||||
|
||||
## Command Line Options
|
||||
|
||||
@@ -681,9 +755,9 @@ fenrir [OPTIONS]
|
||||
- `-o, --options SECTION#SETTING=VALUE;..` - Override settings file options
|
||||
- `-d, --debug` - Enable debug mode
|
||||
- `-p, --print` - Print debug messages to screen
|
||||
- `-e, --emulated-pty` - Use PTY emulation with escape sequences for input (enables desktop/X/Wayland usage)
|
||||
- `-E, --emulated-evdev` - Use PTY emulation with evdev for input (single instance)
|
||||
- `-F, --force-all-screens` - Force Fenrir to respond on all screens, ignoring ignoreScreen setting
|
||||
- `-x, --x11` - Use PTY emulation with X11 keyboard input scoped to the terminal window
|
||||
- `--x11-window-id WINDOWID` - X11 window id to use for `--x11` terminal mode
|
||||
- `-F, --force-all-screens` - Force Fenrir to respond on all screens, ignoring ignore_screen setting
|
||||
- `-i, -I, --ignore-screen SCREEN` - Ignore specific screen(s). Can be used multiple times. Combines with existing ignore settings.
|
||||
|
||||
### Examples:
|
||||
@@ -691,13 +765,16 @@ fenrir [OPTIONS]
|
||||
# Run in foreground with debug output
|
||||
sudo fenrir -f -d
|
||||
|
||||
# Use PTY emulation for desktop use
|
||||
sudo fenrir -e
|
||||
# Use PTY emulation with X11 terminal-scoped keybindings
|
||||
fenrir -x
|
||||
|
||||
# Use X11 mode with an explicit terminal window id
|
||||
fenrir -x --x11-window-id 0x123456
|
||||
|
||||
# Override settings via command line
|
||||
sudo fenrir -o "speech#rate=0.8;sound#volume=0.5"
|
||||
|
||||
# Force Fenrir to work on all screens (ignore ignoreScreen setting)
|
||||
# Force Fenrir to work on all screens (ignore ignore_screen setting)
|
||||
sudo fenrir -F
|
||||
|
||||
# Ignore specific screens
|
||||
@@ -705,6 +782,24 @@ sudo fenrir --ignore-screen 1
|
||||
sudo fenrir -i 1 -i 2 # Ignore screens 1 and 2
|
||||
```
|
||||
|
||||
### X11 Terminal Mode
|
||||
|
||||
`fenrir -x` runs Fenrir inside a GUI terminal without root. It uses the PTY screen driver for terminal contents and the X11 input driver for Fenrir keybindings. Unlike evdev mode, it does not listen to the whole desktop; key grabs are scoped to the target terminal window so desktop screen readers can keep their own global bindings outside that terminal.
|
||||
|
||||
By default, Fenrir targets the X11 window from `WINDOWID`, falling back to the active X11 window. If a terminal does not set `WINDOWID`, pass the window explicitly with `--x11-window-id`.
|
||||
|
||||
X11 terminal mode uses the normal keyboard layout files, including desktop and laptop bindings. It supports Fenrir keys such as numpad Insert/`KEY_KP0`, CapsLock/`KEY_CAPSLOCK`, Insert/`KEY_INSERT`, and Super/Windows/`KEY_META`. Script keys such as Compose use `KEY_COMPOSE`.
|
||||
|
||||
In this mode Fenrir runs as a regular user. Settings are loaded from
|
||||
`~/.local/share/stormux/fenrirscreenreader/settings/settings.conf` when present,
|
||||
otherwise from `/etc/fenrirscreenreader/settings/settings.conf`; saving settings
|
||||
creates or updates the user-local file. User sound themes and scripts are read
|
||||
first from `~/.local/stormux/fenrir/sounds/` and `~/.local/stormux/fenrir/`.
|
||||
|
||||
This mode requires `python-xlib`.
|
||||
|
||||
For users who want a dedicated PTY/terminal screen reader instead of Fenrir's Linux console focus, see TDSR: https://github.com/tspivey/tdsr
|
||||
|
||||
## Localization
|
||||
Translation files are located in the `locale/` directory. To install translations:
|
||||
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
# Fenrir Release Validation Checklist
|
||||
|
||||
This checklist ensures thorough validation before releasing Fenrir packages.
|
||||
|
||||
## 🔧 Setup Tools (One-time setup)
|
||||
|
||||
### Install Pre-commit Hook
|
||||
```bash
|
||||
# Safely install composite hook (preserves existing version management)
|
||||
./tools/install_validation_hook.sh
|
||||
|
||||
# Test the hook
|
||||
./.git/hooks/pre-commit
|
||||
```
|
||||
|
||||
### Validation Scripts
|
||||
- `tools/validate_syntax.py` - Python syntax validation
|
||||
- `tools/validate_pep8.py` - PEP8 compliance checking with safe auto-fix
|
||||
- `tools/validate_release.py` - Comprehensive release validation
|
||||
- `tools/cleanup_cache.py` - Remove Python cache files and directories
|
||||
- `tools/pre-commit-hook` - Git pre-commit validation
|
||||
|
||||
## 📋 Pre-Release Checklist
|
||||
|
||||
### 1. Code Quality Validation ✅
|
||||
```bash
|
||||
# Comprehensive release validation (includes syntax, imports, structure)
|
||||
python3 tools/validate_release.py
|
||||
|
||||
# If issues found, try auto-fix
|
||||
python3 tools/validate_release.py --fix
|
||||
|
||||
# Quick validation (skips slow dependency checks)
|
||||
python3 tools/validate_release.py --quick
|
||||
```
|
||||
|
||||
**Expected Result**: All tests pass, no syntax errors
|
||||
|
||||
### 2. Dependency Validation ✅
|
||||
```bash
|
||||
# Validate all dependencies are available
|
||||
python3 check-dependencies.py
|
||||
```
|
||||
|
||||
**Expected Result**: All required dependencies reported as available
|
||||
|
||||
### 3. Core Functionality Test ✅
|
||||
```bash
|
||||
# Test core imports (safe to run without sudo)
|
||||
cd src
|
||||
python3 -c "
|
||||
import fenrirscreenreader.core.fenrirManager
|
||||
import fenrirscreenreader.core.commandManager
|
||||
import fenrirscreenreader.core.eventManager
|
||||
print('Core imports successful')
|
||||
"
|
||||
cd ..
|
||||
```
|
||||
|
||||
**Expected Result**: No import errors
|
||||
|
||||
### 4. Installation Script Validation ✅
|
||||
```bash
|
||||
# Validate setup.py syntax
|
||||
python3 -m py_compile setup.py
|
||||
|
||||
# Check setup.py can be parsed
|
||||
python3 setup.py --help-commands >/dev/null
|
||||
```
|
||||
|
||||
**Expected Result**: No syntax errors, setup.py functional
|
||||
|
||||
### 5. Configuration Validation ✅
|
||||
```bash
|
||||
# Verify config files exist and are parseable
|
||||
ls -la config/settings/settings.conf
|
||||
ls -la config/keyboard/desktop.conf
|
||||
ls -la config/punctuation/default.conf
|
||||
```
|
||||
|
||||
**Expected Result**: All core config files present
|
||||
|
||||
### 6. Manual Testing (User/Package Maintainer) ⚠️
|
||||
|
||||
**Important**: These require user interaction as they need sudo access or specific hardware.
|
||||
|
||||
```bash
|
||||
# Test basic functionality (ask user to run)
|
||||
sudo ./src/fenrir --help
|
||||
|
||||
# Test version output
|
||||
./src/fenrir --version
|
||||
|
||||
# Quick console functionality test (3-5 seconds, ask user to run on a TTY)
|
||||
sudo timeout 5 ./src/fenrir -f || echo "Timeout reached (expected)"
|
||||
```
|
||||
|
||||
**Expected Result**: No immediate crashes, basic help/version output works
|
||||
|
||||
### 7. Package-Specific Validation ✅
|
||||
```bash
|
||||
# Test the same compilation process used by package managers
|
||||
python3 -m compileall src/fenrirscreenreader/ -q
|
||||
|
||||
# Verify no __pycache__ permission issues
|
||||
find src/ -name "*.pyc" -delete
|
||||
find src/ -name "__pycache__" -delete
|
||||
```
|
||||
|
||||
**Expected Result**: Clean compilation, no permission errors
|
||||
|
||||
## 🚨 Known Issue Categories
|
||||
|
||||
### Critical Issues (Block Release)
|
||||
- **Python syntax errors** (SyntaxError, unterminated strings)
|
||||
- **Missing core dependencies** (dbus-python, evdev, etc.)
|
||||
- **Import failures in core modules** (fenrirManager, commandManager)
|
||||
- **Missing critical config files** (settings.conf, desktop.conf)
|
||||
|
||||
### Warning Issues (Address if Possible)
|
||||
- **PEP8 violations** (cosmetic, don't block release)
|
||||
- **Missing optional dependencies** (for specific features)
|
||||
- **Command structure issues** (missing methods in command files)
|
||||
- **Very long lines** (>120 characters)
|
||||
|
||||
## 🔍 Root Cause Analysis
|
||||
|
||||
### Why These Errors Weren't Caught Previously
|
||||
|
||||
1. **No automated syntax validation** - The codebase relied on manual testing
|
||||
2. **No pre-commit hooks** - Syntax errors could be committed
|
||||
3. **No CI/CD pipeline** - Package compilation happens only during release
|
||||
4. **Manual PEP8 cleanup** - F-string refactoring introduced syntax errors during batch cleanup
|
||||
|
||||
## 📖 Usage Instructions
|
||||
|
||||
### For Developers
|
||||
```bash
|
||||
# Before committing changes
|
||||
git add .
|
||||
git commit # Pre-commit hook will run automatically
|
||||
|
||||
# Before creating tags/releases
|
||||
python3 tools/validate_release.py
|
||||
```
|
||||
|
||||
### For Package Maintainers
|
||||
```bash
|
||||
# Before packaging
|
||||
python3 tools/validate_release.py
|
||||
|
||||
# If validation fails
|
||||
python3 tools/validate_release.py --fix
|
||||
|
||||
# Quick check (if dependencies are known good)
|
||||
python3 tools/validate_release.py --quick
|
||||
```
|
||||
|
||||
### For Release Managers
|
||||
```bash
|
||||
# Complete validation before tagging
|
||||
python3 tools/validate_release.py
|
||||
|
||||
# Manual verification (requires sudo)
|
||||
sudo ./src/fenrir --version
|
||||
|
||||
# Tag release only after all validations pass
|
||||
git tag -a v2.x.x -m "Release v2.x.x"
|
||||
```
|
||||
|
||||
## 🎯 Future Improvements
|
||||
|
||||
### Recommended Additions
|
||||
1. **GitHub Actions CI/CD** - Automated validation on every push
|
||||
2. **Automated testing** - Unit tests for core functionality
|
||||
3. **Integration testing** - Test driver interactions
|
||||
4. **Package testing** - Validate actual package installation
|
||||
|
||||
### Modern Python Packaging
|
||||
- Consider migrating to `pyproject.toml` (PEP 621)
|
||||
- Use `build` instead of `setup.py` directly
|
||||
- Add `tox.ini` for multi-environment testing
|
||||
|
||||
## 📞 Support
|
||||
|
||||
If validation fails and auto-fix doesn't resolve issues:
|
||||
|
||||
1. **Check the specific error messages** in validation output
|
||||
2. **Review recent commits** that might have introduced issues
|
||||
3. **Run individual validation steps** to isolate problems
|
||||
|
||||
Remember: **Working code is better than perfect code** - especially for accessibility software where reliability is critical.
|
||||
@@ -4,12 +4,10 @@ Wants=systemd-udev-settle.service
|
||||
After=systemd-udev-settle.service getty.target
|
||||
[Service]
|
||||
Type=forking
|
||||
PIDFile=/var/run/fenrir.pid
|
||||
PIDFile=/run/fenrir.pid
|
||||
ExecStart=/usr/bin/fenrir
|
||||
ExecReload=/usr/bin/kill -HUP $MAINPID
|
||||
Restart=always
|
||||
#Group=fenrirscreenreader
|
||||
#User=fenrirscreenreader
|
||||
|
||||
[Install]
|
||||
WantedBy=getty.target
|
||||
|
||||
@@ -4,7 +4,7 @@ Wants=systemd-udev-settle.service
|
||||
After=systemd-udev-settle.service sound.target
|
||||
[Service]
|
||||
Type=forking
|
||||
PIDFile=/var/run/fenrir.pid
|
||||
PIDFile=/run/fenrir.pid
|
||||
ExecStart=/usr/local/bin/fenrir
|
||||
ExecReload=/usr/bin/kill -HUP $MAINPID
|
||||
Restart=always
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Please report Bugs and feature requests to:
|
||||
https://github.com/chrys87/fenrir/issues
|
||||
Please report bugs and feature requests to:
|
||||
https://git.stormux.org/storm/fenrir/issues
|
||||
|
||||
For bugs, please provide a debug file that shows the issue.
|
||||
How to create a debug file:
|
||||
|
||||
+10
-12
@@ -50,7 +50,13 @@ def check_dependency(dep: Dependency) -> bool:
|
||||
dependencyList = [
|
||||
# Core dependencies
|
||||
Dependency('FenrirCore', 'core', 'core',
|
||||
pythonImports=['daemonize', 'enchant', 'pyperclip', 'setproctitle']),
|
||||
pythonImports=[
|
||||
'daemonize',
|
||||
'enchant',
|
||||
'pyperclip',
|
||||
'setproctitle',
|
||||
'xdg'
|
||||
]),
|
||||
|
||||
# Screen drivers
|
||||
Dependency('DummyScreen', 'screen', 'dummyDriver'),
|
||||
@@ -58,16 +64,13 @@ dependencyList = [
|
||||
pythonImports=['dbus'],
|
||||
devicePaths=['/dev/vcsa']),
|
||||
Dependency('PTY', 'screen', 'ptyDriver',
|
||||
pythonImports=['pyte', 'xdg']),
|
||||
pythonImports=['pyte']),
|
||||
|
||||
# Input drivers
|
||||
Dependency('DummyInput', 'input', 'dummyDriver'),
|
||||
Dependency('DebugInput', 'input', 'debugDriver'),
|
||||
Dependency('Evdev', 'input', 'evdevDriver',
|
||||
pythonImports=['evdev', 'evdev.InputDevice', 'evdev.UInput', 'pyudev']),
|
||||
Dependency('PTYInput', 'input', 'ptyDriver',
|
||||
pythonImports=['pyte']),
|
||||
|
||||
# Sound drivers
|
||||
Dependency('DummySound', 'sound', 'dummyDriver'),
|
||||
Dependency('DebugSound', 'sound', 'debugDriver'),
|
||||
@@ -82,11 +85,7 @@ dependencyList = [
|
||||
Dependency('Speechd', 'speech', 'speechdDriver',
|
||||
pythonImports=['speechd']),
|
||||
Dependency('GenericSpeech', 'speech', 'genericDriver',
|
||||
checkCommands=['espeak-ng']),
|
||||
|
||||
# Additional dependencies
|
||||
Dependency('Pexpect', 'core', 'pexpectDriver',
|
||||
pythonImports=['pexpect'])
|
||||
checkCommands=['espeak-ng'])
|
||||
]
|
||||
|
||||
defaultModules = {
|
||||
@@ -94,8 +93,7 @@ defaultModules = {
|
||||
'VCSA',
|
||||
'Evdev',
|
||||
'GenericSpeech',
|
||||
'GenericSound',
|
||||
'Pexpect'
|
||||
'GenericSound'
|
||||
}
|
||||
|
||||
def check_all_dependencies():
|
||||
|
||||
@@ -7,10 +7,6 @@ This directory contains keyboard layout files for Fenrir screen reader.
|
||||
|
||||
- **desktop.conf** - Desktop layout using numeric keypad (recommended)
|
||||
- **laptop.conf** - Laptop layout for keyboards without numeric keypad
|
||||
- **nvda-desktop.conf** - NVDA-compatible desktop layout
|
||||
- **nvda-laptop.conf** - NVDA-compatible laptop layout
|
||||
- **pty.conf** - PTY emulation layout for terminal use
|
||||
- **pty2.conf** - Alternative PTY emulation layout
|
||||
|
||||
## Key Features
|
||||
|
||||
@@ -30,13 +26,21 @@ This directory contains keyboard layout files for Fenrir screen reader.
|
||||
- **Exit review**: `Fenrir + Keypad .`
|
||||
- **Screen reading**: `Fenrir + Keypad 5` (current screen)
|
||||
|
||||
### Speech History
|
||||
- **Open speech history**: `Fenrir + Ctrl + H`
|
||||
- **Navigate history**: `Up` and `Down`
|
||||
- **Copy current item**: `Enter`
|
||||
- **Exit speech history**: `Escape`
|
||||
|
||||
## Configuration
|
||||
|
||||
To change keyboard layout, edit `/etc/fenrir/settings/settings.conf`:
|
||||
To change keyboard layout, edit `/etc/fenrirscreenreader/settings/settings.conf`
|
||||
or your user-local settings file at
|
||||
`~/.local/share/stormux/fenrirscreenreader/settings/settings.conf`:
|
||||
|
||||
```ini
|
||||
[keyboard]
|
||||
keyboardLayout=desktop # or laptop, nvda-desktop, nvda-laptop, pty, pty2
|
||||
keyboard_layout=desktop # or laptop
|
||||
```
|
||||
|
||||
## Available Key Constants
|
||||
@@ -582,4 +586,3 @@ BTN_TRIGGER_HAPPY37
|
||||
BTN_TRIGGER_HAPPY38
|
||||
BTN_TRIGGER_HAPPY39
|
||||
BTN_TRIGGER_HAPPY40
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
KEY_FENRIR,KEY_H=toggle_tutorial_mode
|
||||
KEY_FENRIR,KEY_CTRL,KEY_H=speech_history
|
||||
KEY_CTRL=shut_up
|
||||
KEY_FENRIR,KEY_KP9=review_bottom
|
||||
KEY_FENRIR,KEY_KP7=review_top
|
||||
@@ -83,6 +84,8 @@ KEY_FENRIR,KEY_CTRL,KEY_P=toggle_punctuation_level
|
||||
KEY_FENRIR,KEY_RIGHTBRACE=toggle_auto_spell_check
|
||||
KEY_FENRIR,KEY_BACKSLASH=toggle_output
|
||||
KEY_FENRIR,KEY_CTRL,KEY_E=toggle_emoticons
|
||||
KEY_FENRIR,KEY_CTRL,KEY_D=toggle_diff_mode
|
||||
KEY_FENRIR,KEY_CTRL,KEY_SHIFT,KEY_E=cycle_key_echo
|
||||
key_FENRIR,KEY_KPENTER=toggle_auto_read
|
||||
KEY_FENRIR,KEY_CTRL,KEY_T=toggle_auto_time
|
||||
KEY_FENRIR,KEY_KPASTERISK=toggle_highlight_tracking
|
||||
@@ -126,7 +129,8 @@ KEY_FENRIR,KEY_CTRL,KEY_S=save_settings
|
||||
# linux specific
|
||||
KEY_FENRIR,KEY_F7=import_clipboard_from_x
|
||||
KEY_FENRIR,KEY_F8=export_clipboard_to_x
|
||||
KEY_FENRIR,KEY_CTRL,KEY_UP=inc_alsa_volume
|
||||
KEY_FENRIR,KEY_CTRL,KEY_DOWN=dec_alsa_volume
|
||||
# Read-all functionality
|
||||
KEY_FENRIR,KEY_CTRL,KEY_DOWN=read_all_by_line
|
||||
KEY_FENRIR,KEY_CTRL,KEY_PAGEDOWN=read_all_by_page
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_V=announce_fenrir_version
|
||||
KEY_F4=cycle_keyboard_layout
|
||||
KEY_FENRIR,KEY_LEFTCTRL,KEY_F4=cycle_keyboard_layout
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
KEY_FENRIR,KEY_H=toggle_tutorial_mode
|
||||
KEY_FENRIR,KEY_CTRL,KEY_H=speech_history
|
||||
KEY_CTRL=shut_up
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_O=review_bottom
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_U=review_top
|
||||
@@ -81,6 +82,8 @@ KEY_FENRIR,KEY_SHIFT,KEY_CTRL,KEY_P=toggle_punctuation_level
|
||||
KEY_FENRIR,KEY_RIGHTBRACE=toggle_auto_spell_check
|
||||
KEY_FENRIR,KEY_CTRL,KEY_SHIFT,KEY_ENTER=toggle_output
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_E=toggle_emoticons
|
||||
KEY_FENRIR,KEY_CTRL,KEY_D=toggle_diff_mode
|
||||
KEY_FENRIR,KEY_CTRL,KEY_SHIFT,KEY_E=cycle_key_echo
|
||||
KEY_FENRIR,KEY_CTRL,KEY_T=toggle_auto_time
|
||||
KEY_FENRIR,KEY_Y=toggle_highlight_tracking
|
||||
#=toggle_barrier
|
||||
@@ -126,7 +129,8 @@ KEY_FENRIR,KEY_CTRL,KEY_S=save_settings
|
||||
# linux specific
|
||||
KEY_FENRIR,KEY_F7=import_clipboard_from_x
|
||||
KEY_FENRIR,KEY_F8=export_clipboard_to_x
|
||||
KEY_FENRIR,KEY_CTRL,KEY_UP=inc_alsa_volume
|
||||
KEY_FENRIR,KEY_CTRL,KEY_DOWN=dec_alsa_volume
|
||||
# Read-all functionality
|
||||
KEY_FENRIR,KEY_CTRL,KEY_DOWN=read_all_by_line
|
||||
KEY_FENRIR,KEY_CTRL,KEY_PAGEDOWN=read_all_by_page
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_V=announce_fenrir_version
|
||||
KEY_F4=cycle_keyboard_layout
|
||||
KEY_FENRIR,KEY_LEFTCTRL,KEY_F4=cycle_keyboard_layout
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
KEY_FENRIR,KEY_F1=toggle_tutorial_mode
|
||||
KEY_FENRIR,KEY_H=toggle_tutorial_mode
|
||||
KEY_CTRL=shut_up
|
||||
KEY_SHIFT,KEY_KP9=review_bottom
|
||||
KEY_SHIFT,KEY_KP7=review_top
|
||||
KEY_KP8=review_curr_line
|
||||
KEY_KP7=review_prev_line
|
||||
KEY_KP9=review_next_line
|
||||
KEY_SHIFT,KEY_KP1=review_line_begin
|
||||
KEY_SHIFT,KEY_KP3=review_line_end
|
||||
KEY_FENRIR,KEY_KP1=review_line_first_char
|
||||
KEY_FENRIR,KEY_KP3=review_line_last_char
|
||||
KEY_FENRIR,KEY_ALT,KEY_1=present_first_line
|
||||
KEY_FENRIR,KEY_ALT,KEY_2=present_last_line
|
||||
KEY_KP5=review_curr_word
|
||||
KEY_KP4=review_prev_word
|
||||
KEY_KP6=review_next_word
|
||||
2,KEY_KP5=review_curr_word_phonetic
|
||||
2,KEY_KP4=review_prev_word_phonetic
|
||||
2,KEY_KP6=review_next_word_phonetic
|
||||
KEY_KP2=review_curr_char
|
||||
KEY_KP1=review_prev_char
|
||||
KEY_KP3=review_next_char
|
||||
2,KEY_KP2=review_curr_char_phonetic
|
||||
2,KEY_KP1=review_prev_char_phonetic
|
||||
2,KEY_KP3=review_next_char_phonetic
|
||||
KEY_FENRIR,KEY_CTRL,KEY_KP8=review_up
|
||||
KEY_FENRIR,KEY_CTRL,KEY_KP2=review_down
|
||||
KEY_FENRIR,KEY_KPDOT=exit_review
|
||||
KEY_KPDOT=cursor_position
|
||||
KEY_FENRIR,KEY_I=indent_curr_line
|
||||
KEY_FENRIR,KEY_B=curr_screen
|
||||
KEY_FENRIR,KEY_KP8=curr_screen_before_cursor
|
||||
KEY_FENRIR,KEY_KP2=curr_screen_after_cursor
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_PAGEDOWN=cursor_read_to_end_of_line
|
||||
#=cursor_column
|
||||
#=cursor_lineno
|
||||
#=braille_flush
|
||||
KEY_FENRIR,KEY_CTRL,KEY_T=braille_return_to_cursor
|
||||
#=braille_pan_left
|
||||
#=braille_pan_right
|
||||
KEY_FENRIR,KEY_CTRL,KEY_1=clear_bookmark_1
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_1=set_bookmark_1
|
||||
KEY_FENRIR,KEY_1=bookmark_1
|
||||
KEY_FENRIR,KEY_K=bookmark_1
|
||||
KEY_FENRIR,KEY_CTRL,KEY_2=clear_bookmark_2
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_2=set_bookmark_2
|
||||
KEY_FENRIR,KEY_2=bookmark_2
|
||||
KEY_FENRIR,KEY_CTRL,KEY_3=clear_bookmark_3
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_3=set_bookmark_3
|
||||
KEY_FENRIR,KEY_3=bookmark_3
|
||||
KEY_FENRIR,KEY_CTRL,KEY_4=clear_bookmark_4
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_4=set_bookmark_4
|
||||
KEY_FENRIR,KEY_4=bookmark_4
|
||||
KEY_FENRIR,KEY_CTRL,KEY_5=clear_bookmark_5
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_5=set_bookmark_5
|
||||
KEY_FENRIR,KEY_5=bookmark_5
|
||||
KEY_FENRIR,KEY_CTRL,KEY_6=clear_bookmark_6
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_6=set_bookmark_6
|
||||
KEY_FENRIR,KEY_6=bookmark_6
|
||||
KEY_FENRIR,KEY_CTRL,KEY_7=clear_bookmark_7
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_7=set_bookmark_7
|
||||
KEY_FENRIR,KEY_7=bookmark_7
|
||||
KEY_FENRIR,KEY_CTRL,KEY_8=clear_bookmark_8
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_8=set_bookmark_8
|
||||
KEY_FENRIR,KEY_8=bookmark_8
|
||||
KEY_FENRIR,KEY_CTRL,KEY_9=clear_bookmark_9
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_9=set_bookmark_9
|
||||
KEY_FENRIR,KEY_9=bookmark_9
|
||||
KEY_FENRIR,KEY_CTRL,KEY_0=clear_bookmark_10
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_0=set_bookmark_10
|
||||
KEY_FENRIR,KEY_0=bookmark_10
|
||||
KEY_FENRIR,KEY_KPSLASH=set_window_application
|
||||
2,KEY_FENRIR,KEY_KPSLASH=clear_window_application
|
||||
KEY_KPPLUS=progress_bar_monitor
|
||||
KEY_FENRIR,KEY_KPPLUS=silence_until_prompt
|
||||
#=toggle_braille
|
||||
KEY_FENRIR,KEY_F3=toggle_sound
|
||||
KEY_FENRIR,KEY_F4=toggle_speech
|
||||
KEY_KPENTER=temp_disable_speech
|
||||
KEY_FENRIR,KEY_P=toggle_punctuation_level
|
||||
KEY_FENRIR,KEY_RIGHTBRACE=toggle_auto_spell_check
|
||||
KEY_FENRIR,KEY_S=toggle_output
|
||||
KEY_FENRIR,KEY_CTRL,KEY_E=toggle_emoticons
|
||||
key_FENRIR,KEY_5=toggle_auto_read
|
||||
KEY_FENRIR,KEY_CTRL,KEY_T=toggle_auto_time
|
||||
KEY_FENRIR,KEY_KPASTERISK=toggle_highlight_tracking
|
||||
KEY_FENRIR,KEY_KPMINUS=toggle_barrier
|
||||
KEY_FENRIR,KEY_Q=quit_fenrir
|
||||
KEY_FENRIR,KEY_T=time
|
||||
KEY_FENRIR,KEY_F12=time
|
||||
2,KEY_FENRIR,KEY_T=date
|
||||
2,KEY_FENRIR,KEY_F12=date
|
||||
KEY_KPSLASH=toggle_auto_indent
|
||||
KEY_FENRIR,KEY_F=attribute_cursor
|
||||
#=toggle_has_attribute
|
||||
KEY_FENRIR,KEY_F7=spell_check
|
||||
2,KEY_FENRIR,KEY_S=add_word_to_spell_check
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_S=remove_word_from_spell_check
|
||||
KEY_FENRIR,KEY_F2=forward_keypress
|
||||
KEY_FENRIR,KEY_ALT,KEY_UP=inc_sound_volume
|
||||
KEY_FENRIR,KEY_ALT,KEY_DOWN=dec_sound_volume
|
||||
#=clear_clipboard
|
||||
KEY_FENRIR,KEY_HOME=first_clipboard
|
||||
KEY_FENRIR,KEY_END=last_clipboard
|
||||
KEY_FENRIR,KEY_PAGEUP=prev_clipboard
|
||||
KEY_FENRIR,KEY_PAGEDOWN=next_clipboard
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_C=curr_clipboard
|
||||
KEY_FENRIR,KEY_C=copy_marked_to_clipboard
|
||||
KEY_FENRIR,KEY_CTRL,KEY_SHIFT,KEY_C=copy_last_echo_to_clipboard
|
||||
KEY_FENRIR,KEY_V=paste_clipboard
|
||||
KEY_FENRIR,KEY_F5=import_clipboard_from_file
|
||||
KEY_FENRIR,KEY_F6=export_clipboard_to_file
|
||||
KEY_FENRIR,KEY_CTRL,KEY_SHIFT,KEY_X=remove_marks
|
||||
KEY_FENRIR,KEY_F9=set_mark
|
||||
KEY_FENRIR,KEY_F10=marked_text
|
||||
KEY_FENRIR,KEY_F10=toggle_vmenu_mode
|
||||
KEY_FENRIR,KEY_SPACE=current_quick_menu_entry
|
||||
KEY_FENRIR,KEY_CTRL,KEY_SPACE=current_quick_menu_value
|
||||
KEY_FENRIR,KEY_CTRL,KEY_RIGHT=next_quick_menu_entry
|
||||
KEY_FENRIR,KEY_CTRL,KEY_UP=next_quick_menu_value
|
||||
KEY_FENRIR,KEY_CTRL,KEY_LEFT=prev_quick_menu_entry
|
||||
KEY_FENRIR,KEY_CTRL,KEY_DOWN=prev_quick_menu_value
|
||||
KEY_FENRIR,KEY_CTRL,KEY_C=save_settings
|
||||
# linux specific
|
||||
#=import_clipboard_from_x
|
||||
KEY_FENRIR,KEY_F8=export_clipboard_to_x
|
||||
KEY_FENRIR,KEY_ALT,KEY_UP=inc_alsa_volume
|
||||
KEY_FENRIR,KEY_ALT,KEY_DOWN=dec_alsa_volume
|
||||
KEY_F4=cycle_keyboard_layout
|
||||
@@ -1,129 +0,0 @@
|
||||
KEY_FENRIR,KEY_F1=toggle_tutorial_mode
|
||||
KEY_FENRIR,KEY_H=toggle_tutorial_mode
|
||||
KEY_CTRL=shut_up
|
||||
KEY_FENRIR,KEY_CTRL,KEY_END=review_bottom
|
||||
KEY_FENRIR,KEY_CTRL,KEY_HOME=review_top
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_DOT=review_curr_line
|
||||
KEY_FENRIR,KEY_U=review_prev_line
|
||||
KEY_FENRIR,KEY_O=review_next_line
|
||||
KEY_FENRIR,KEY_HOME=review_line_begin
|
||||
KEY_FENRIR,KEY_END=review_line_end
|
||||
KEY_FENRIR,KEY_CTRL,KEY_J=review_line_first_char
|
||||
KEY_FENRIR,KEY_CTRL,KEY_L=review_line_last_char
|
||||
KEY_FENRIR,KEY_ALT,KEY_1=present_first_line
|
||||
KEY_FENRIR,KEY_ALT,KEY_2=present_last_line
|
||||
KEY_FENRIR,KEY_CTRL,KEY_DOT=review_curr_word
|
||||
KEY_FENRIR,KEY_J=review_prev_word
|
||||
KEY_FENRIR,KEY_L=review_next_word
|
||||
2,KEY_FENRIR,KEY_CTRL,KEY_DOT=review_curr_word_phonetic
|
||||
2,KEY_FENRIR,KEY_J=review_prev_word_phonetic
|
||||
2,KEY_FENRIR,KEY_L=review_next_word_phonetic
|
||||
KEY_FENRIR,KEY_COMMA=review_curr_char
|
||||
KEY_FENRIR,KEY_M=review_prev_char
|
||||
KEY_FENRIR,KEY_DOT=review_next_char
|
||||
2,KEY_FENRIR,KEY_COMMA=curr_char_phonetic
|
||||
2,KEY_FENRIR,KEY_M=prev_char_phonetic
|
||||
2,KEY_FENRIR,KEY_DOT=next_char_phonetic
|
||||
KEY_FENRIR,KEY_CTRL,KEY_I=review_up
|
||||
KEY_FENRIR,KEY_CTRL,KEY_COMMA=review_down
|
||||
KEY_FENRIR,KEY_SLASH=exit_review
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_DOT=cursor_position
|
||||
2,KEY_FENRIR,KEY_I=indent_curr_line
|
||||
KEY_FENRIR,KEY_B=curr_screen
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_I=curr_screen_before_cursor
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_COMMA=curr_screen_after_cursor
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_PAGEDOWN=cursor_read_to_end_of_line
|
||||
#=cursor_column
|
||||
#=cursor_lineno
|
||||
#=braille_flush
|
||||
KEY_FENRIR,KEY_CTRL,KEY_T=braille_return_to_cursor
|
||||
#=braille_pan_left
|
||||
#=braille_pan_right
|
||||
KEY_FENRIR,KEY_CTRL,KEY_1=clear_bookmark_1
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_1=set_bookmark_1
|
||||
KEY_FENRIR,KEY_1=bookmark_1
|
||||
KEY_FENRIR,KEY_K=bookmark_1
|
||||
KEY_FENRIR,KEY_CTRL,KEY_2=clear_bookmark_2
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_2=set_bookmark_2
|
||||
KEY_FENRIR,KEY_2=bookmark_2
|
||||
KEY_FENRIR,KEY_CTRL,KEY_3=clear_bookmark_3
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_3=set_bookmark_3
|
||||
KEY_FENRIR,KEY_3=bookmark_3
|
||||
KEY_FENRIR,KEY_CTRL,KEY_4=clear_bookmark_4
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_4=set_bookmark_4
|
||||
KEY_FENRIR,KEY_4=bookmark_4
|
||||
KEY_FENRIR,KEY_CTRL,KEY_5=clear_bookmark_5
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_5=set_bookmark_5
|
||||
KEY_FENRIR,KEY_5=bookmark_5
|
||||
KEY_FENRIR,KEY_CTRL,KEY_6=clear_bookmark_6
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_6=set_bookmark_6
|
||||
KEY_FENRIR,KEY_6=bookmark_6
|
||||
KEY_FENRIR,KEY_CTRL,KEY_7=clear_bookmark_7
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_7=set_bookmark_7
|
||||
KEY_FENRIR,KEY_7=bookmark_7
|
||||
KEY_FENRIR,KEY_CTRL,KEY_8=clear_bookmark_8
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_8=set_bookmark_8
|
||||
KEY_FENRIR,KEY_8=bookmark_8
|
||||
KEY_FENRIR,KEY_CTRL,KEY_9=clear_bookmark_9
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_9=set_bookmark_9
|
||||
KEY_FENRIR,KEY_9=bookmark_9
|
||||
KEY_FENRIR,KEY_CTRL,KEY_0=clear_bookmark_10
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_0=set_bookmark_10
|
||||
KEY_FENRIR,KEY_0=bookmark_10
|
||||
KEY_FENRIR,KEY_CTRL,KEY_8=set_window_application
|
||||
2,KEY_FENRIR,KEY_CTRL,KEY_8=clear_window_application
|
||||
KEY_FENRIR,KEY_SEMICOLON=last_incoming
|
||||
#=toggle_braille
|
||||
KEY_FENRIR,KEY_F3=toggle_sound
|
||||
KEY_FENRIR,KEY_F4=toggle_speech
|
||||
KEY_FENRIR,KEY_ENTER=temp_disable_speech
|
||||
KEY_FENRIR,KEY_P=toggle_punctuation_level
|
||||
KEY_FENRIR,KEY_RIGHTBRACE=toggle_auto_spell_check
|
||||
KEY_FENRIR,KEY_S=toggle_output
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_E=toggle_emoticons
|
||||
KEY_FENRIR,KEY_5=toggle_auto_read
|
||||
KEY_FENRIR,KEY_CTRL,KEY_T=toggle_auto_time
|
||||
KEY_FENRIR,KEY_Y=toggle_highlight_tracking
|
||||
#=toggle_barrier
|
||||
KEY_FENRIR,KEY_Q=quit_fenrir
|
||||
KEY_FENRIR,KEY_T=time
|
||||
KEY_FENRIR,KEY_F12=time
|
||||
2,KEY_FENRIR,KEY_T=date
|
||||
2,KEY_FENRIR,KEY_F12=date
|
||||
KEY_FENRIR,KEY_BACKSLASH=toggle_auto_indent
|
||||
KEY_FENRIR,KEY_F=attribute_cursor
|
||||
#=toggle_has_attribute
|
||||
KEY_FENRIR,KEY_F7=spell_check
|
||||
2,KEY_FENRIR,KEY_S=add_word_to_spell_check
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_S=remove_word_from_spell_check
|
||||
KEY_FENRIR,KEY_F2=forward_keypress
|
||||
KEY_FENRIR,KEY_ALT,KEY_UP=inc_sound_volume
|
||||
KEY_FENRIR,KEY_ALT,KEY_DOWN=dec_sound_volume
|
||||
#=clear_clipboard
|
||||
#=first_clipboard
|
||||
#=last_clipboard
|
||||
KEY_FENRIR,KEY_PAGEUP=prev_clipboard
|
||||
KEY_FENRIR,KEY_PAGEDOWN=next_clipboard
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_C=curr_clipboard
|
||||
KEY_FENRIR,KEY_C=copy_marked_to_clipboard
|
||||
KEY_FENRIR,KEY_CTRL,KEY_SHIFT,KEY_C=copy_last_echo_to_clipboard
|
||||
KEY_FENRIR,KEY_V=paste_clipboard
|
||||
KEY_FENRIR,KEY_F5=import_clipboard_from_file
|
||||
KEY_FENRIR,KEY_F6=export_clipboard_to_file
|
||||
KEY_FENRIR,KEY_CTRL,KEY_SHIFT,KEY_X=remove_marks
|
||||
KEY_FENRIR,KEY_F9=set_mark
|
||||
KEY_FENRIR,KEY_F10=marked_text
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_F10=toggle_vmenu_mode
|
||||
KEY_FENRIR,KEY_SPACE=current_quick_menu_entry
|
||||
KEY_FENRIR,KEY_CTRL,KEY_SPACE=current_quick_menu_value
|
||||
KEY_FENRIR,KEY_CTRL,KEY_RIGHT=next_quick_menu_entry
|
||||
KEY_FENRIR,KEY_CTRL,KEY_UP=next_quick_menu_value
|
||||
KEY_FENRIR,KEY_CTRL,KEY_LEFT=prev_quick_menu_entry
|
||||
KEY_FENRIR,KEY_CTRL,KEY_DOWN=prev_quick_menu_value
|
||||
KEY_FENRIR,KEY_CTRL,KEY_C=save_settings
|
||||
# linux specific
|
||||
#=import_clipboard_from_x
|
||||
KEY_FENRIR,KEY_F8=export_clipboard_to_x
|
||||
KEY_FENRIR,KEY_ALT,KEY_UP=inc_alsa_volume
|
||||
KEY_FENRIR,KEY_ALT,KEY_DOWN=dec_alsa_volume
|
||||
KEY_F4=cycle_keyboard_layout
|
||||
@@ -1,89 +0,0 @@
|
||||
# This file contains terminal escape sequences as shortcut
|
||||
# It is used for PTY screen / Input driver (Terminal emulation)
|
||||
# ^[ is used as escape
|
||||
|
||||
# f1 - fenrir help
|
||||
^[OP=toggle_tutorial_mode
|
||||
# double tap control+end read attributes
|
||||
2,^[[1;5F=attribute_cursor
|
||||
#=toggle_has_attribute
|
||||
# escape - stop speech
|
||||
^[=shut_up
|
||||
# context menu key - stop speech
|
||||
^[[29~=shut_up
|
||||
# alt+shift+down - review to bottom
|
||||
^[[1;4B=review_bottom
|
||||
# alt+shift_up - review to top
|
||||
^[[1;4A=review_top
|
||||
# alt+down - review current line
|
||||
^[[1;3B=review_curr_line
|
||||
# alt+left - review previous line
|
||||
^[[1;3D=review_prev_line
|
||||
# alt+right - review next line
|
||||
^[[1;3C=review_next_line
|
||||
# alt+shift+left - beginning of line
|
||||
^[[1;4D=review_line_begin
|
||||
# alt+shift+right - end of line
|
||||
^[[1;4C=review_line_end
|
||||
# control+down - review current word
|
||||
^[[1;5B=review_curr_word
|
||||
# control+left - review previous word
|
||||
^[[1;5D=review_prev_word
|
||||
# control+right - review next word
|
||||
^[[1;5C=review_next_word
|
||||
# shift+down - review current character
|
||||
^[[1;2B=review_curr_char
|
||||
# shift+left - review previous character
|
||||
^[[1;2D=review_prev_char
|
||||
# shift+right - review next character
|
||||
^[[1;2C=review_next_char
|
||||
# control+shift+down - current character phonetic
|
||||
^[[1;6B=curr_char_phonetic
|
||||
# control+shift+left - previous character phonetic
|
||||
^[[1;6D=prev_char_phonetic
|
||||
# control+shift+right - next character phonetic
|
||||
^[[1;6C=next_char_phonetic
|
||||
# f2 - toggle sound
|
||||
^[OQ=toggle_sound
|
||||
# f3 - toggle highlight tracking
|
||||
^[OR=toggle_highlight_tracking
|
||||
alt+f12 - quit fenrir
|
||||
^[[24;3~=quit_fenrir
|
||||
# alt+f12 - time
|
||||
^[[24;3~=time
|
||||
# 2,alt+f12 - date
|
||||
2,^[[24;3~=date
|
||||
# alt+[ - previous clipboard
|
||||
^[[=prev_clipboard
|
||||
# alt+] - next clipboard
|
||||
^[]=next_clipboard
|
||||
# control+f6 - Read current clipboard
|
||||
^[[17;5~=curr_clipboard
|
||||
# f6 - copy to clipboard
|
||||
^[[17~=copy_marked_to_clipboard
|
||||
# shift+f6 - clear clipboard
|
||||
^[[17;2~=clear_clipboard
|
||||
# f7 - paste clipboard
|
||||
^[[18~=paste_clipboard
|
||||
# alt+f8 - export clipboard to X
|
||||
^[[19;3~=export_clipboard_to_x
|
||||
# control+f8 - import clipboard from X
|
||||
^[[19;5~=import_clipboard_from_x
|
||||
# alt+f9 - export clipboard to file
|
||||
^[[20;3~=export_clipboard_to_file
|
||||
# control+f9 - import clipboard from file
|
||||
^[[20;5~=import_clipboard_from_file
|
||||
# shift+f5 - remove marks
|
||||
^[[15;2~=remove_marks
|
||||
# f5 - set mark
|
||||
^[[15~=set_mark
|
||||
# f8 - Last utterance to clipboard
|
||||
^[[19~=copy_last_echo_to_clipboard
|
||||
# lat+\ Toggle auto announcement of indentation
|
||||
^[\=toggle_auto_indent
|
||||
# alt+end - temperarily disable speech
|
||||
^[[1;3F=temp_disable_speech
|
||||
# control+end - toggle auto read
|
||||
^[[1;5F=toggle_auto_read
|
||||
# F12 - cycle keyboard layout
|
||||
^[[24~=cycle_keyboard_layout
|
||||
@@ -1,46 +0,0 @@
|
||||
# This file contains terminal escape sequences as shortcut
|
||||
# It is used for PTY screen / Input driver (Terminal emulation)
|
||||
# ^[ is used as escape
|
||||
|
||||
^[h=toggle_tutorial_mode
|
||||
^[/=shut_up
|
||||
^[[D=shut_up
|
||||
^[O=review_bottom
|
||||
^[U=review_top
|
||||
#^[[1;3B=review_curr_line
|
||||
^[i=review_curr_line
|
||||
^[u=review_prev_line
|
||||
^[o=review_next_line
|
||||
^[J=review_line_begin
|
||||
^[L=review_line_end
|
||||
^[j=review_line_first_char
|
||||
^[L=review_line_last_char
|
||||
^[k=review_curr_word
|
||||
^[j=review_prev_word
|
||||
^[l=review_next_word
|
||||
^[,=review_curr_char
|
||||
^[m=review_prev_char
|
||||
^[.=review_next_char
|
||||
^[<=curr_char_phonetic
|
||||
^[M=prev_char_phonetic
|
||||
^[>=next_char_phonetic
|
||||
^[OR=toggle_sound
|
||||
^[OS=toggle_speech
|
||||
^[8=toggle_highlight_tracking
|
||||
^[Q=quit_fenrir
|
||||
^[t=time
|
||||
^[T=date
|
||||
^[[5~=prev_clipboard
|
||||
^[[6~=next_clipboard
|
||||
^[C=curr_clipboard
|
||||
^[c=copy_marked_to_clipboard
|
||||
^[v=paste_clipboard
|
||||
^[[15~=import_clipboard_from_file
|
||||
^[X=remove_marks
|
||||
^[x=set_mark
|
||||
^[\=toggle_auto_indent
|
||||
^[B=copy_last_echo_to_clipboard
|
||||
# alt+f8 - export clipboard to X
|
||||
# ^[[19;3~=export_clipboard_to_x
|
||||
# # control+f8 - import clipboard from X
|
||||
# ^[[19;5~=import_clipboard_from_x
|
||||
+214
-111
@@ -3,14 +3,14 @@
|
||||
enabled=True
|
||||
|
||||
# Select the driver used to play sounds, choices are genericDriver and gstreamerDriver.
|
||||
# Sox is the default.
|
||||
#driver=gstreamerDriver
|
||||
driver=genericDriver
|
||||
# Generic driver uses fewer dependencies but spawns a process for each sound played including progress bar beeps
|
||||
# Gstreamer is the default.
|
||||
driver=gstreamerDriver
|
||||
#driver=genericDriver
|
||||
|
||||
# Sound themes. These are the pack of sounds used for sound alerts.
|
||||
# Sound packs may be located at /usr/share/sounds
|
||||
# For system wide availability, or ~/.local/share/fenrirscreenreader/sounds
|
||||
# For the current user.
|
||||
# Sound packs may be located at ~/.local/stormux/fenrir/sounds,
|
||||
# /usr/share/sounds/fenrir, or /usr/share/sounds/fenrirscreenreader.
|
||||
theme=default
|
||||
|
||||
# Sound volume controls how loud the sounds for your selected soundpack are.
|
||||
@@ -24,20 +24,25 @@ volume=0.7
|
||||
# fenrirFrequence = the frequency to play
|
||||
# fenrirDuration = the duration of the frequency
|
||||
# the following command is used to play a soundfile
|
||||
genericPlayFileCommand=play -q -v fenrirVolume fenrirSoundFile
|
||||
generic_play_file_command=play -q -v fenrirVolume fenrirSoundFile
|
||||
#the following command is used to generate a frequency beep
|
||||
genericFrequencyCommand=play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence
|
||||
generic_frequency_command=play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence
|
||||
|
||||
# Enable progress bar monitoring with ascending tones by default
|
||||
progressMonitoring=True
|
||||
progress_monitoring=True
|
||||
|
||||
[speech]
|
||||
# Turn speech on or off:
|
||||
enabled=True
|
||||
|
||||
# Select speech driver, options are speechdDriver or genericDriver:
|
||||
# Select speech driver, options are speechdDriver, genericDriver,
|
||||
# dectalkDriver, litetalkDriver, doubletalkDriver, or tripletalkDriver:
|
||||
driver=speechdDriver
|
||||
#driver=genericDriver
|
||||
#driver=dectalkDriver
|
||||
#driver=litetalkDriver
|
||||
#driver=doubletalkDriver
|
||||
#driver=tripletalkDriver
|
||||
|
||||
# The rate selects how fast Fenrir will speak. Options range from 0, slowest, to 1.0, fastest.
|
||||
rate=0.5
|
||||
@@ -45,7 +50,13 @@ rate=0.5
|
||||
# Pitch controls the pitch of the voice, select from 0, lowest, to 1.0, highest.
|
||||
pitch=0.5
|
||||
# Pitch for capital letters
|
||||
capitalPitch=0.9
|
||||
capital_pitch=0.9
|
||||
# How to indicate capital letters:
|
||||
# pitch = change speech pitch (uses capital_pitch value)
|
||||
# beep = play Caps.wav sound icon
|
||||
# both = play beep AND change pitch
|
||||
# none = no special indication
|
||||
capital_indicator=pitch
|
||||
|
||||
# Volume controls the loudness of the voice, select from 0, quietest, to 1.0, loudest.
|
||||
volume=1.0
|
||||
@@ -64,11 +75,44 @@ volume=1.0
|
||||
# Select the language you want Fenrir to use.
|
||||
#language=en
|
||||
|
||||
# Hardware speech synthesizer serial device.
|
||||
# Used by dectalkDriver, litetalkDriver, doubletalkDriver, and tripletalkDriver.
|
||||
# USB serial devices are supported if Linux exposes them as /dev/ttyACM*
|
||||
# or /dev/ttyUSB*. USB-only synths with no tty device need a separate driver.
|
||||
# Set an explicit device for hardware speech.
|
||||
# Examples:
|
||||
# hardware_device=/dev/ttyACM0 # RPITalk USB gadget mode
|
||||
# hardware_device=/dev/ttyUSB0 # USB serial adapter
|
||||
# hardware_device=/dev/ttyS0 # built-in serial port
|
||||
hardware_device=/dev/ttyS0
|
||||
|
||||
# Serial baud rate for hardware speech synthesizers.
|
||||
hardware_baud_rate=9600
|
||||
|
||||
# Read new text as it happens?
|
||||
autoReadIncoming=True
|
||||
auto_read_incoming=True
|
||||
|
||||
# Speak individual numbers instead of whole string.
|
||||
readNumbersAsDigits = False
|
||||
read_numbers_as_digits = False
|
||||
|
||||
# Number of spoken items kept in runtime speech history.
|
||||
history_size=50
|
||||
|
||||
# Flood control: batch rapid updates instead of speaking each one
|
||||
# Number of updates within rapid_update_window to trigger batching
|
||||
rapid_update_threshold=5
|
||||
|
||||
# Time window (seconds) for detecting rapid updates
|
||||
rapid_update_window=0.3
|
||||
|
||||
# How often to speak batched content (seconds)
|
||||
batch_flush_interval=0.5
|
||||
|
||||
# Maximum lines to keep when batching (keeps newest, drops oldest)
|
||||
max_batch_lines=100
|
||||
|
||||
# Only enable flood control if this many new lines appear in the window
|
||||
flood_line_threshold=500
|
||||
|
||||
# genericSpeechCommand is the command that is executed for talking
|
||||
# the following variables are replaced with values
|
||||
@@ -81,106 +125,150 @@ readNumbersAsDigits = False
|
||||
# fenrirVolume = is replaced with the current volume
|
||||
# fenrirPitch = is replaced with the current pitch
|
||||
# fenrirRate = is replaced with the current speed (speech rate)
|
||||
genericSpeechCommand=espeak-ng -a fenrirVolume -s fenrirRate -p fenrirPitch -v fenrirVoice -- "fenrirText"
|
||||
generic_speech_command=espeak-ng -a fenrir_volume -s fenrir_rate -p fenrir_pitch -v fenrir_voice -- "fenrir_text"
|
||||
|
||||
# min and max values of the TTS system that is used in genericSpeechCommand
|
||||
fenrirMinVolume=0
|
||||
fenrirMaxVolume=200
|
||||
fenrirMinPitch=0
|
||||
fenrirMaxPitch=99
|
||||
fenrirMinRate=80
|
||||
fenrirMaxRate=450
|
||||
# min and max values of the TTS system that is used in generic_speech_command
|
||||
fenrir_min_volume=0
|
||||
fenrir_max_volume=200
|
||||
fenrir_min_pitch=0
|
||||
fenrir_max_pitch=99
|
||||
fenrir_min_rate=80
|
||||
fenrir_max_rate=450
|
||||
|
||||
[screen]
|
||||
# Screen driver: vcsaDriver (Linux TTY/virtual console), ptyDriver (terminal emulation)
|
||||
driver=vcsaDriver
|
||||
# Text encoding: auto (auto-detect), utf-8, latin1, etc.
|
||||
encoding=auto
|
||||
screenUpdateDelay=0.05
|
||||
ignoreScreen=7
|
||||
autodetectIgnoreScreen=True
|
||||
# Delay in seconds between screen updates (lower = more responsive, higher = less CPU)
|
||||
# Recommended: 0.05 for most systems
|
||||
screen_update_delay=0.05
|
||||
# TTY number to completely ignore (e.g., 7 for X11/graphical login screen)
|
||||
ignore_screen=7
|
||||
# Automatically detect and ignore graphical TTYs (X11, Wayland sessions)
|
||||
autodetect_ignore_screen=True
|
||||
|
||||
[keyboard]
|
||||
driver=evdevDriver
|
||||
# filter input devices NOMICE, ALL or a DEVICE NAME
|
||||
device=ALL
|
||||
# gives Fenrir exclusive access to the keyboard and lets it control keystrokes.
|
||||
grabDevices=True
|
||||
ignoreShortcuts=False
|
||||
grab_devices=True
|
||||
# Optional X11 target window id for x11Driver. Empty uses WINDOWID or active window.
|
||||
x11_window_id=
|
||||
# Ignore shortcut bindings and pass all keys through without processing Fenrir commands.
|
||||
# When True, Fenrir will only monitor screen content without intercepting keyboard input.
|
||||
# the current shortcut layout located in /etc/fenrirscreenreader/keyboard
|
||||
keyboardLayout=desktop
|
||||
ignore_shortcuts=False
|
||||
keyboard_layout=desktop
|
||||
# echo chars while typing.
|
||||
# 0 = None
|
||||
# 1 = always
|
||||
# 2 = only while capslock
|
||||
charEchoMode=1
|
||||
# 2 = only while capslock (not compatible with capslock as fenrir key)
|
||||
char_echo_mode=1
|
||||
# echo deleted chars
|
||||
charDeleteEcho=True
|
||||
char_delete_echo=True
|
||||
# echo word after pressing space
|
||||
wordEcho=False
|
||||
word_echo=False
|
||||
# interrupt speech on any keypress
|
||||
interruptOnKeyPress=True
|
||||
interrupt_on_key_press=True
|
||||
# you can filter the keys on that the speech should interrupt (empty = all keys, otherwhise the given keys)
|
||||
interruptOnKeyPressFilter=
|
||||
interrupt_on_key_press_filter=
|
||||
# timeout for double tap in sec
|
||||
doubleTapTimeout=0.2
|
||||
double_tap_timeout=0.2
|
||||
|
||||
[general]
|
||||
# Debug levels: 0=DEACTIVE, 1=ERROR, 2=WARNING, 3=INFO (most verbose)
|
||||
# Debug levels: 0=NONE, 1=ERROR, 2=WARNING, 3=INFO (most verbose)
|
||||
# For production use, WARNING (2) provides good balance of useful info without spam
|
||||
debugLevel=2
|
||||
# The default is 0, no logging.
|
||||
debug_level=0
|
||||
# debugMode sets where the debug output should send to:
|
||||
# debugMode=File writes to debugFile (Default:/tmp/fenrir-PID.log)
|
||||
# debugMode=File writes to debug_file (Default:/tmp/fenrir-PID.log)
|
||||
# debugMode=Print just prints on the screen
|
||||
debugMode=File
|
||||
debugFile=
|
||||
punctuationProfile=default
|
||||
punctuationLevel=some
|
||||
respectPunctuationPause=True
|
||||
debug_mode=File
|
||||
debug_file=
|
||||
# Punctuation settings control how punctuation is spoken during text review.
|
||||
# Profile selects a punctuation definition file from config/punctuation/ (e.g., default.conf)
|
||||
punctuation_profile=default
|
||||
punctuation_level=some
|
||||
respect_punctuation_pause=True
|
||||
# Replace undefined punctuation with spaces instead of removing them
|
||||
# This improves readability of text with punctuation like [X]mute, IP addresses, etc.
|
||||
replaceUndefinedPunctuationWithSpace=True
|
||||
newLinePause=True
|
||||
numberOfClipboards=50
|
||||
replace_undefined_punctuation_with_space=True
|
||||
# Pause speech briefly at newline characters for better readability
|
||||
new_line_pause=True
|
||||
number_of_clipboards=50
|
||||
# used path for "export_clipboard_to_file"
|
||||
# $user is replaced by username
|
||||
#clipboardExportPath=/home/$user/fenrirClipboard
|
||||
clipboardExportPath=/tmp/fenrirClipboard
|
||||
clipboard_export_path=/tmp/fenrirClipboard
|
||||
# Convert text emoticons like :) to descriptive text (e.g., "smiling face")
|
||||
emoticons=True
|
||||
# define the current Fenrir key
|
||||
fenrirKeys=KEY_KP0,KEY_META,KEY_INSERT
|
||||
scriptKeys=KEY_COMPOSE
|
||||
timeFormat=%%I:%%M%%P
|
||||
dateFormat=%%A, %%B %%d, %%Y
|
||||
autoSpellCheck=True
|
||||
spellCheckLanguage=en_US
|
||||
# path for your scripts "scriptKeys" functionality
|
||||
scriptPath=/usr/share/fenrirscreenreader/scripts
|
||||
# overload commands, and create new one without changing Fenrir default
|
||||
commandPath=
|
||||
#fenrirBGColor = the backgroundcolor
|
||||
#fenrirFGColor = the foregroundcolor
|
||||
#fenrirUnderline = speak the underline attribute
|
||||
#fenrirBold = speak the bold attribute
|
||||
#fenrirBlink = speak the blink attribute
|
||||
#fenrirFont = the font
|
||||
#fenrirFontSize = the fontsize
|
||||
attributeFormatString=Background fenrirBGColor,Foreground fenrirFGColor,fenrirUnderline,fenrirBold,fenrirBlink, Font fenrirFont,Fontsize fenrirFontSize
|
||||
# present indentation
|
||||
autoPresentIndent=False
|
||||
# speak is only invoked on changeing ident level, sound always
|
||||
# 0 = sound and speak
|
||||
# 1 = sound only
|
||||
# 2 = speak only
|
||||
autoPresentIndentMode=1
|
||||
# play a sound when attributes change
|
||||
hasAttributes=True
|
||||
# shell for PTY emulatiun (empty = default shell)
|
||||
# Define the Fenrir modifier key(s) - used to trigger Fenrir commands
|
||||
# Examples: KEY_KP0 (numpad 0), KEY_META (Super/Windows), KEY_INSERT
|
||||
# Multiple keys: KEY_KP0,KEY_META,KEY_INSERT
|
||||
fenrir_keys=KEY_KP0,KEY_META,KEY_INSERT
|
||||
# Script key - used to execute custom scripts in script_path
|
||||
script_keys=KEY_COMPOSE
|
||||
# Time format using Python strftime codes (https://docs.python.org/3/library/datetime.html#strftime-strptime-behavior)
|
||||
# Default: %%I:%%M%%P (12-hour format, e.g., "06:38pm")
|
||||
# 24-hour format: %%H:%%M (e.g., "18:38")
|
||||
# Common codes: %%I=12hr hour, %%H=24hr hour, %%M=minute, %%S=second, %%P=am/pm lowercase, %%p=AM/PM uppercase
|
||||
time_format=%%I:%%M%%P
|
||||
# Date format using Python strftime codes
|
||||
# Default: %%A, %%B %%d, %%Y (e.g., "Tuesday, December 10, 2024")
|
||||
# ISO format: %%Y-%%m-%%d (e.g., "2024-12-10")
|
||||
# Common codes: %%A=weekday name, %%B=month name, %%d=day, %%Y=year with century, %%m=month number
|
||||
date_format=%%A, %%B %%d, %%Y
|
||||
# Automatically spell check words when reviewing character-by-character
|
||||
auto_spell_check=True
|
||||
# Language for spell checking (format: language_COUNTRY, e.g., en_US, en_GB, es_ES)
|
||||
spell_check_language=en_US
|
||||
# path for your scripts "script_keys" functionality.
|
||||
# User-local scripts in ~/.local/stormux/fenrir are loaded first.
|
||||
script_path=/usr/share/fenrirscreenreader/scripts
|
||||
# Override default commands or add custom commands without modifying Fenrir installation
|
||||
# Leave empty to use default commands only
|
||||
command_path=
|
||||
# Format string for announcing text attributes (colors, formatting)
|
||||
# Available variables:
|
||||
# fenrirBGColor = the background color
|
||||
# fenrirFGColor = the foreground color
|
||||
# fenrirUnderline = speak the underline attribute
|
||||
# fenrirBold = speak the bold attribute
|
||||
# fenrirBlink = speak the blink attribute
|
||||
# fenrirFont = the font name
|
||||
# fenrirFontSize = the font size
|
||||
attribute_format_string=Background fenrirBGColor,Foreground fenrirFGColor,fenrirUnderline,fenrirBold,fenrirBlink, Font fenrirFont,Fontsize fenrirFontSize
|
||||
# Automatically announce indentation level changes (useful for Python, YAML, etc.)
|
||||
auto_present_indent=False
|
||||
# How to present indentation changes:
|
||||
# 0 = sound and speak (both audio feedback and voice announcement)
|
||||
# 1 = sound only (just play a tone)
|
||||
# 2 = speak only (just voice announcement)
|
||||
auto_present_indent_mode=1
|
||||
# Play a sound when text attributes (color, bold, etc.) change
|
||||
has_attributes=True
|
||||
# Shell to use for PTY emulation mode (empty = use system default shell)
|
||||
# Examples: /bin/bash, /bin/zsh, /usr/bin/fish
|
||||
shell=
|
||||
# Diff review presentation mode:
|
||||
# speech = spoken feedback only
|
||||
# sound = sound cues only (falls back to speech when cue is unavailable)
|
||||
# both = speech and sound cues
|
||||
diff_presentation=both
|
||||
# Diff review verbosity:
|
||||
# compact = concise role/location feedback
|
||||
# verbose = include diff line content during navigation
|
||||
diff_verbosity=compact
|
||||
|
||||
[focus]
|
||||
#follow the text cursor
|
||||
# Follow and announce text cursor position changes
|
||||
cursor=True
|
||||
#follow highlighted text changes
|
||||
# Follow and announce highlighted/selected text changes (useful in menus)
|
||||
highlight=False
|
||||
# Suppress generic incoming announcements for full-screen TUIs that redraw often
|
||||
tui=False
|
||||
|
||||
[remote]
|
||||
enable=True
|
||||
@@ -191,33 +279,43 @@ driver=unixDriver
|
||||
# tcp port
|
||||
port=22447
|
||||
# socket filepath
|
||||
socketFile=
|
||||
socket_file=
|
||||
# allow settings to overwrite
|
||||
enableSettingsRemote=True
|
||||
enable_settings_remote=True
|
||||
# allow commands to be executed
|
||||
enableCommandRemote=True
|
||||
enable_command_remote=True
|
||||
|
||||
[barrier]
|
||||
# Enable barrier detection - automatically detects table/box borders for improved navigation
|
||||
enabled=False
|
||||
leftBarriers=│└┌─
|
||||
rightBarriers=│┘┐─
|
||||
# Characters that represent left-side barriers/borders (for table/box detection)
|
||||
left_barriers=│└┌─
|
||||
# Characters that represent right-side barriers/borders (for table/box detection)
|
||||
right_barriers=│┘┐─
|
||||
|
||||
[review]
|
||||
lineBreak=True
|
||||
endOfScreen=True
|
||||
# leave the review when pressing a key
|
||||
leaveReviewOnCursorChange=True
|
||||
# leave the review when changing the screen
|
||||
leaveReviewOnScreenChange=True
|
||||
|
||||
[promote]
|
||||
enabled=True
|
||||
inactiveTimeoutSec=120
|
||||
list=
|
||||
# Announce line breaks during review mode
|
||||
line_break=True
|
||||
# Announce when reaching the end of screen during review
|
||||
end_of_screen=True
|
||||
# Exit review mode when cursor position changes (e.g., when typing)
|
||||
leave_review_on_cursor_change=True
|
||||
# Exit review mode when switching to a different TTY/screen
|
||||
leave_review_on_screen_change=True
|
||||
|
||||
[menu]
|
||||
vmenuPath=
|
||||
quickMenu=speech#rate;speech#pitch;speech#volume
|
||||
# Custom path for VMenu (virtual menu) profiles
|
||||
# Leave empty to use default location (/etc/fenrirscreenreader/vmenu-profiles/)
|
||||
vmenu_path=
|
||||
# Quick menu: Semicolon-separated list of settings for rapid adjustment via VMenu
|
||||
# Access with Fenrir+F10, navigate to "Quick Settings"
|
||||
# Format: section#setting;section#setting;...
|
||||
# Supported settings:
|
||||
# - speech#rate, speech#pitch, speech#volume (0.0-1.0)
|
||||
# - speech#module, speech#voice (speechdDriver only, auto-added)
|
||||
# Note: speech#module and speech#voice are automatically added when
|
||||
# speechdDriver is active. Do not add them manually.
|
||||
quick_menu=speech#rate;speech#pitch;speech#volume
|
||||
|
||||
[prompt]
|
||||
# Custom prompt patterns for silence until prompt feature
|
||||
@@ -235,27 +333,32 @@ quickMenu=speech#rate;speech#pitch;speech#volume
|
||||
# For "[user@hostname ~] $" use: \[.*@.*\s.*\]\s*[$#>]\s*
|
||||
# For custom prompts ending with specific strings, use patterns like: .*your_prompt_ending$
|
||||
# For custom package manager prompts: .*your_package_manager.*\[[YyNn]/[YyNn]\].*
|
||||
customPatterns=
|
||||
custom_patterns=
|
||||
|
||||
# Specific prompt strings to match exactly (useful for very specific custom prompts)
|
||||
# Format: exactMatches=prompt1,prompt2,prompt3
|
||||
# Format: exact_matches=prompt1,prompt2,prompt3
|
||||
# Examples:
|
||||
# exactMatches=[storm@fenrir ~] $,[root@fenrir ~] #,Continue installation? [Y/n]
|
||||
exactMatches=
|
||||
# exact_matches=[storm@fenrir ~] $,[root@fenrir ~] #,Continue installation? [Y/n]
|
||||
exact_matches=
|
||||
|
||||
[time]
|
||||
# automatic time announcement
|
||||
# Enable automatic time announcements
|
||||
enabled=False
|
||||
# present time
|
||||
presentTime=True
|
||||
# present date (on change)
|
||||
presentDate=True
|
||||
# present time after a given period of seconds
|
||||
delaySec=0
|
||||
# present time after to given minutes example every 15 minutes: 00,15,30,45
|
||||
# if delaySec is >0 onMinutes is ignored
|
||||
onMinutes=00,30
|
||||
# announce via soundicon (not interrupting)
|
||||
# Announce the current time
|
||||
present_time=True
|
||||
# Announce the date (only when it changes, e.g., at midnight)
|
||||
present_date=True
|
||||
# Announce time every N seconds (0 = disabled)
|
||||
# If delay_sec > 0, on_minutes is ignored
|
||||
delay_sec=0
|
||||
# Announce time at specific minutes of each hour (comma-separated)
|
||||
# Examples:
|
||||
# 00 = Only on the hour (1:00, 2:00, 3:00, etc.)
|
||||
# 00,30 = On the hour and half-hour (1:00, 1:30, 2:00, 2:30, etc.)
|
||||
# 00,15,30,45 = Every 15 minutes
|
||||
# Note: This is ignored if delay_sec > 0
|
||||
on_minutes=00,30
|
||||
# Play a sound icon before time announcement (non-interrupting)
|
||||
announce=True
|
||||
# interrupt current speech for time announcement
|
||||
# Interrupt current speech to announce time immediately
|
||||
interrupt=False
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,8 +1,6 @@
|
||||
# Screen Reader Turned On or Off
|
||||
ScreenReaderOn='ScreenReaderOn.wav'
|
||||
ScreenReaderOff='ScreenReaderOff.wav'
|
||||
# PTY bypass
|
||||
PTYBypass='PTYBypass.wav'
|
||||
# Cancel the current command
|
||||
Cancel='Cancel.wav'
|
||||
# Accept command
|
||||
@@ -46,8 +44,6 @@ ErrorSpeech='ErrorSpeech.wav'
|
||||
ErrorScreen='ErrorScreen.wav'
|
||||
# If you cursor over an text that has attributs (like color)
|
||||
HasAttributes='has_attribute.wav'
|
||||
# fenrir can promote strings if they appear on the screen.
|
||||
PromotedText='PromotedText.wav'
|
||||
# missspelled indicator
|
||||
mispell='mispell.wav'
|
||||
# the for capital letter
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
# Screen Reader Turned On or Off
|
||||
ScreenReaderOn=''
|
||||
ScreenReaderOff=''
|
||||
# PTY bypass
|
||||
PTYBypass=''
|
||||
# Cancel the current command
|
||||
Cancel=''
|
||||
# Accept command
|
||||
@@ -50,8 +48,6 @@ ErrorBraille=''
|
||||
ErrorScreen=''
|
||||
# If you cursor over an text that has attributs (like color)
|
||||
HasAttributes=''
|
||||
# fenrir can promote strings if they appear on the screen.
|
||||
PromotedText=''
|
||||
# misspelled indicator
|
||||
mispell=''
|
||||
# the for capital letter:
|
||||
|
||||
@@ -22,7 +22,7 @@ src/fenrirscreenreader/
|
||||
│ ├── onKeyInput/ # Key input hooks
|
||||
│ └── help/ # Tutorial system
|
||||
├── drivers/ # Driver implementations
|
||||
│ ├── inputDriver/ # Input drivers (evdev, pty, atspi)
|
||||
│ ├── inputDriver/ # Input drivers (evdev, x11)
|
||||
│ ├── screenDriver/ # Screen drivers (vcsa, pty)
|
||||
│ ├── speechDriver/ # Speech drivers (speechd, generic)
|
||||
│ └── soundDriver/ # Sound drivers (generic, gstreamer)
|
||||
@@ -36,8 +36,7 @@ Fenrir uses a pluggable driver architecture:
|
||||
|
||||
1. **Input Drivers**: Capture keyboard input
|
||||
- evdevDriver: Linux evdev (recommended)
|
||||
- ptyDriver: Terminal emulation
|
||||
- atspiDriver: AT-SPI for desktop
|
||||
- x11Driver: X11 terminal-scoped input
|
||||
|
||||
2. **Screen Drivers**: Read screen content
|
||||
- vcsaDriver: Linux VCSA devices
|
||||
@@ -83,7 +82,6 @@ Fenrir supports various event hooks:
|
||||
- **onCursorChange**: Triggered when cursor moves
|
||||
- **onScreenUpdate**: Triggered on screen content changes
|
||||
- **onKeyInput**: Triggered on key presses
|
||||
- **onByteInput**: Triggered on byte-level input
|
||||
- **onScreenChanged**: Triggered when switching screens
|
||||
|
||||
## Development Setup
|
||||
@@ -386,4 +384,4 @@ current_line = lines[self.env['screen']['newCursor']['y']]
|
||||
- **Wiki**: https://git.stormux.org/storm/fenrir/wiki
|
||||
- **Issues**: Use repository issue tracker
|
||||
- **Community**: IRC irc.stormux.org #stormux
|
||||
- **Email**: stormux+subscribe@groups.io
|
||||
- **Email**: stormux+subscribe@groups.io
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
# Diff Review Mode
|
||||
|
||||
Diff review mode provides read-only navigation for unified and classic diff files with speech-first output.
|
||||
|
||||
## Quick Workflow
|
||||
|
||||
1. Copy the full absolute path of a diff file to the Fenrir clipboard.
|
||||
2. Press `Fenrir + Ctrl + D` to toggle diff mode on.
|
||||
3. Review the diff using the keys below.
|
||||
4. Press `Esc` to leave diff mode.
|
||||
|
||||
If the clipboard does not contain a full absolute file path, Fenrir announces an error and does not enter diff mode.
|
||||
|
||||
## Keys (Active Only In Diff Mode)
|
||||
|
||||
- `h` - Next hunk
|
||||
- `Shift + h` - Previous hunk
|
||||
- `f` - Next file section
|
||||
- `Shift + f` - Previous file section
|
||||
- `a` - Next added line
|
||||
- `Shift + a` - Previous added line
|
||||
- `d` - Next removed line
|
||||
- `Shift + d` - Previous removed line
|
||||
- `Up` - Previous line
|
||||
- `Down` - Next line
|
||||
- `Left` - Previous character
|
||||
- `Right` - Next character
|
||||
- `Ctrl + Left` - Previous word
|
||||
- `Ctrl + Right` - Next word
|
||||
- `s` - Diff summary
|
||||
- `F1` - Speak key help
|
||||
- `Esc` - Exit diff mode
|
||||
|
||||
## Speech Behavior
|
||||
|
||||
- Added and removed content is spoken as `Added:` and `Removed:` lines.
|
||||
- Marker-only lines are normalized for speech:
|
||||
- `+++` is spoken as `added`
|
||||
- `---` is spoken as `removed`
|
||||
- Classic diff markers are spoken in plain language:
|
||||
- `17c17` -> `line 17 changed`
|
||||
- `17d16` -> `line 17 deleted`
|
||||
- `16a17` -> `line 17 added`
|
||||
|
||||
## Notes
|
||||
|
||||
- Diff mode is read-only and does not modify the diff file.
|
||||
- Normal Fenrir key bindings are restored when diff mode exits.
|
||||
+90
-47
@@ -13,13 +13,16 @@ fenrir \- A modern, modular console screen reader for Linux
|
||||
.IR SECTION#SETTING=VALUE;.. ]
|
||||
.RB [ \-d ]
|
||||
.RB [ \-p ]
|
||||
.RB [ \-e ]
|
||||
.RB [ \-E ]
|
||||
.RB [ \-x ]
|
||||
.RB [ \-\-x11-window-id
|
||||
.IR WINDOWID ]
|
||||
.RB [ \-F ]
|
||||
.RB [ \-i
|
||||
.IR SCREEN ]
|
||||
|
||||
.SH DESCRIPTION
|
||||
Fenrir is a modern, modular, flexible and fast console screen reader written in Python 3.
|
||||
It provides spoken feedback for Linux console applications and supports multiple interface types including TTY, terminal emulators, and desktop environments.
|
||||
It provides spoken feedback for Linux console applications and supports Linux TTYs plus X11 terminal mode.
|
||||
|
||||
Fenrir features a modular driver architecture supporting multiple speech synthesizers, sound systems, input methods, and screen reading techniques. It includes advanced features like review mode, multiple clipboards, spell checking, bookmarks, and configurable key bindings.
|
||||
|
||||
@@ -38,7 +41,7 @@ Run Fenrir in the foreground instead of as a daemon. Useful for debugging and te
|
||||
|
||||
.TP
|
||||
.BR \-s ", " \-\-setting " " \fISETTING-FILE\fR
|
||||
Path to a custom settings file. Default is /etc/fenrir/settings/settings.conf.
|
||||
Path to a custom settings file. Default is /etc/fenrirscreenreader/settings/settings.conf for root and ~/.local/share/stormux/fenrirscreenreader/settings/settings.conf for regular-user saves.
|
||||
|
||||
.TP
|
||||
.BR \-o ", " \-\-options " " \fISECTION#SETTING=VALUE;..\fR
|
||||
@@ -53,21 +56,21 @@ Enable debug mode. Debug information will be logged to /var/log/fenrir.log.
|
||||
.BR \-p ", " \-\-print
|
||||
Print debug messages to screen in addition to logging them.
|
||||
|
||||
.TP
|
||||
.BR \-e ", " \-\-emulated-pty
|
||||
Use PTY emulation with escape sequences for input. This enables usage in desktop/X11/Wayland environments and terminal emulators.
|
||||
|
||||
.TP
|
||||
.BR \-E ", " \-\-emulated-evdev
|
||||
Use PTY emulation with evdev for input (single instance mode).
|
||||
|
||||
.TP
|
||||
.BR \-F ", " \-\-force-all-screens
|
||||
Force Fenrir to respond on all screens, ignoring the ignoreScreen setting. This temporarily overrides screen filtering for the current session.
|
||||
Force Fenrir to respond on all screens, ignoring the ignore_screen setting. This temporarily overrides screen filtering for the current session.
|
||||
|
||||
.TP
|
||||
.BR \-i ", " \-I ", " \-\-ignore-screen " \fISCREEN\fR"
|
||||
Ignore specific screen(s). Can be used multiple times to ignore multiple screens. This is equivalent to setting ignoreScreen in the configuration file and will be combined with any existing ignore settings.
|
||||
Ignore specific screen(s). Can be used multiple times to ignore multiple screens. This is equivalent to setting ignore_screen in the configuration file and will be combined with any existing ignore settings.
|
||||
|
||||
.TP
|
||||
.BR \-x ", " \-\-x11
|
||||
Run in X11 terminal mode using PTY screen monitoring and X11 keyboard input scoped to the terminal window.
|
||||
|
||||
.TP
|
||||
.BR \-\-x11-window-id " " \fIWINDOWID\fR
|
||||
Use a specific X11 terminal window id for X11 terminal mode.
|
||||
|
||||
.SH KEY CONCEPTS
|
||||
|
||||
@@ -186,12 +189,24 @@ Announce marked text
|
||||
.SS Settings File
|
||||
The main configuration file is located at:
|
||||
.IP \[bu] 2
|
||||
.B /etc/fenrir/settings/settings.conf
|
||||
.B /etc/fenrirscreenreader/settings/settings.conf
|
||||
(system-wide installation)
|
||||
.IP \[bu] 2
|
||||
.B ~/.local/share/stormux/fenrirscreenreader/settings/settings.conf
|
||||
(user-local settings)
|
||||
.IP \[bu] 2
|
||||
.B config/settings/settings.conf
|
||||
(development/git version)
|
||||
|
||||
When Fenrir runs as a regular user, including fenrir -x, it loads the
|
||||
user-local settings file if it exists. If it does not exist, Fenrir falls back
|
||||
to the system settings file, but saving settings writes to the user-local path.
|
||||
When Fenrir runs as root, settings save to the system-wide path by default.
|
||||
|
||||
User sound themes are loaded before system themes from
|
||||
~/.local/stormux/fenrir/sounds/. User scripts are loaded before configured
|
||||
system scripts from ~/.local/stormux/fenrir/.
|
||||
|
||||
.SS Key Sections
|
||||
.TP
|
||||
.B [speech]
|
||||
@@ -223,6 +238,14 @@ speechdDriver - Speech-dispatcher (recommended)
|
||||
.IP \[bu] 4
|
||||
genericDriver - Command-line TTS (espeak, etc.)
|
||||
.IP \[bu] 4
|
||||
dectalkDriver - DECtalk-compatible serial hardware speech
|
||||
.IP \[bu] 4
|
||||
litetalkDriver - LiteTalk-compatible serial hardware speech
|
||||
.IP \[bu] 4
|
||||
doubletalkDriver - DoubleTalk LT-compatible serial hardware speech
|
||||
.IP \[bu] 4
|
||||
tripletalkDriver - TripleTalk-compatible serial hardware speech
|
||||
.IP \[bu] 4
|
||||
debugDriver - Debug/testing
|
||||
|
||||
.TP
|
||||
@@ -234,14 +257,12 @@ gstreamerDriver - GStreamer-based
|
||||
.IP \[bu] 4
|
||||
debugDriver - Debug/testing
|
||||
|
||||
.TP
|
||||
.TP
|
||||
.B Input Drivers:
|
||||
.IP \[bu] 4
|
||||
evdevDriver - Linux evdev (recommended for Linux)
|
||||
.IP \[bu] 4
|
||||
ptyDriver - Terminal emulation (cross-platform)
|
||||
.IP \[bu] 4
|
||||
atspiDriver - AT-SPI for desktop environments
|
||||
x11Driver - X11 terminal-scoped input for fenrir -x
|
||||
|
||||
.TP
|
||||
.B Screen Drivers:
|
||||
@@ -267,17 +288,13 @@ Start Fenrir as a daemon with default settings.
|
||||
.B fenrir -f -d
|
||||
Run Fenrir in foreground with debug output.
|
||||
|
||||
.TP
|
||||
.B fenrir -e
|
||||
Run Fenrir with PTY emulation for desktop/terminal use.
|
||||
|
||||
.TP
|
||||
.B fenrir -o "speech#rate=0.8;sound#volume=0.5"
|
||||
Override speech rate and sound volume settings.
|
||||
|
||||
.TP
|
||||
.B fenrir -F
|
||||
Force Fenrir to work on all screens, ignoring ignoreScreen settings.
|
||||
Force Fenrir to work on all screens, ignoring ignore_screen settings.
|
||||
|
||||
.TP
|
||||
.B fenrir -s /home/user/my-fenrir.conf
|
||||
@@ -288,61 +305,77 @@ Use a custom configuration file.
|
||||
Fenrir includes a powerful remote control system for automation and integration with external applications.
|
||||
|
||||
.SS Configuration
|
||||
Enable remote control in /etc/fenrir/settings/settings.conf:
|
||||
Enable remote control in /etc/fenrirscreenreader/settings/settings.conf or the user-local settings file:
|
||||
|
||||
.EX
|
||||
[remote]
|
||||
enable=True
|
||||
driver=unixDriver
|
||||
enableSettingsRemote=True
|
||||
enableCommandRemote=True
|
||||
enable_settings_remote=True
|
||||
enable_command_remote=True
|
||||
.EE
|
||||
|
||||
.SS Using socat with Unix Sockets
|
||||
|
||||
.TP
|
||||
.B Instance Discovery:
|
||||
.EX
|
||||
# List registered Fenrir instances and their socket paths
|
||||
echo "ls" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
.EE
|
||||
|
||||
In X terminal mode (fenrir -x), multiple Fenrir instances can run at the
|
||||
same time. Each instance has a private socket at
|
||||
/tmp/fenrirscreenreader-<pid>.sock, and one instance may also own the
|
||||
standard control socket. Use ls or "command ls" on the standard socket to
|
||||
find the private socket for a specific instance. Commands sent to the standard
|
||||
socket are handled by its owner when possible; otherwise they are forwarded to a
|
||||
registered private socket, preferring the sender's Fenrir ancestor when one can
|
||||
be found.
|
||||
|
||||
.TP
|
||||
.B Basic Speech Control:
|
||||
.EX
|
||||
# Interrupt current speech
|
||||
echo "command interrupt" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "command interrupt" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Speak custom text
|
||||
echo "command say Hello, this is a test" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "command say Hello, this is a test" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Temporarily disable speech
|
||||
echo "command tempdisablespeech" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "command tempdisablespeech" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
.EE
|
||||
|
||||
.TP
|
||||
.B Settings Control:
|
||||
.EX
|
||||
# Enable highlight tracking
|
||||
echo "setting set focus#highlight=True" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set focus#highlight=True" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Change speech rate
|
||||
echo "setting set speech#rate=0.8" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set speech#rate=0.8" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Change punctuation level (none/some/most/all)
|
||||
echo "setting set general#punctuationLevel=all" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set general#punctuation_level=all" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Voice and TTS control
|
||||
echo "setting set speech#voice=en-us+f3" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set speech#voice=en-us+f3" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Multiple settings at once
|
||||
echo "setting set speech#rate=0.8;sound#volume=0.7;general#punctuationLevel=most" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set speech#rate=0.8;sound#volume=0.7;general#punctuation_level=most" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Reset all settings
|
||||
echo "setting reset" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting reset" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
.EE
|
||||
|
||||
.TP
|
||||
.B Clipboard Operations:
|
||||
.EX
|
||||
# Add text to clipboard
|
||||
echo "command clipboard Text to copy" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "command clipboard Text to copy" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Export clipboard to file
|
||||
echo "command exportclipboard" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "command exportclipboard" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
.EE
|
||||
|
||||
.SS Command Reference
|
||||
@@ -355,6 +388,8 @@ command say <text> - Speak the specified text
|
||||
command interrupt - Stop current speech
|
||||
.IP \[bu] 2
|
||||
command tempdisablespeech - Disable speech until next key press
|
||||
.IP \[bu] 2
|
||||
ls / list / command ls / command list - List registered Fenrir instances
|
||||
|
||||
.TP
|
||||
.B Settings Commands:
|
||||
@@ -385,7 +420,7 @@ command quitapplication - Quit Fenrir
|
||||
.TP
|
||||
.B Speech Control:
|
||||
.IP \[bu] 2
|
||||
general#punctuationLevel=none/some/most/all - Punctuation verbosity
|
||||
general#punctuation_level=none/some/most/all - Punctuation verbosity
|
||||
.IP \[bu] 2
|
||||
speech#rate=0.1-1.0 - Speech rate
|
||||
.IP \[bu] 2
|
||||
@@ -400,28 +435,32 @@ speech#module=module_name - TTS module
|
||||
.TP
|
||||
.B Screen Control:
|
||||
.IP \[bu] 2
|
||||
screen#ignoreScreen=1,2,3 - TTY screens to ignore
|
||||
screen#ignore_screen=1,2,3 - TTY screens to ignore
|
||||
.IP \[bu] 2
|
||||
focus#highlight=True/False - Follow text highlighting
|
||||
|
||||
.TP
|
||||
.B Input Control:
|
||||
.IP \[bu] 2
|
||||
keyboard#charEchoMode=0-2 - Character echo mode
|
||||
keyboard#char_echo_mode=0-2 - Character echo mode
|
||||
.IP \[bu] 2
|
||||
keyboard#wordEcho=True/False - Word echo
|
||||
keyboard#word_echo=True/False - Word echo
|
||||
|
||||
.SH FILES
|
||||
.TP
|
||||
.B /etc/fenrir/settings/settings.conf
|
||||
.B /etc/fenrirscreenreader/settings/settings.conf
|
||||
Main configuration file
|
||||
|
||||
.TP
|
||||
.B /etc/fenrir/keyboard/
|
||||
.B ~/.local/share/stormux/fenrirscreenreader/settings/settings.conf
|
||||
User-local configuration file
|
||||
|
||||
.TP
|
||||
.B /etc/fenrirscreenreader/keyboard/
|
||||
Keyboard layout definitions
|
||||
|
||||
.TP
|
||||
.B /etc/fenrir/punctuation/
|
||||
.B /etc/fenrirscreenreader/punctuation/
|
||||
Punctuation level definitions
|
||||
|
||||
.TP
|
||||
@@ -429,9 +468,13 @@ Punctuation level definitions
|
||||
System sound themes
|
||||
|
||||
.TP
|
||||
.B ~/.local/share/fenrirscreenreader/sounds/
|
||||
.B ~/.local/stormux/fenrir/sounds/
|
||||
User sound themes
|
||||
|
||||
.TP
|
||||
.B ~/.local/stormux/fenrir/
|
||||
User scripts
|
||||
|
||||
.TP
|
||||
.B /var/log/fenrir.log
|
||||
Debug log file
|
||||
@@ -516,4 +559,4 @@ This software is licensed under the LGPL v3.
|
||||
Full documentation: https://git.stormux.org/storm/fenrir/wiki
|
||||
|
||||
.PP
|
||||
Support: stormux+subscribe@groups.io
|
||||
Support: stormux+subscribe@groups.io
|
||||
|
||||
+115
-122
@@ -7,14 +7,14 @@ configurable and easy to customize and extend.
|
||||
=== Credit and intended audience
|
||||
|
||||
This document is just a customization for Slint of the genuine
|
||||
https://github.com/chrys87/fenrir/blob/master/docu/user.txt[Fenrir User
|
||||
https://git.stormux.org/storm/fenrir/src/branch/master/docs/user.txt[Fenrir User
|
||||
Manual] motly written by Chrys, main developer of Fenrir.
|
||||
|
||||
It has been adapted to its intended audience: end users of Fenrir on
|
||||
Slint where it is already installed, thus concentrates on its setting
|
||||
and usage. You will find more information about its features,
|
||||
installation and how customize and troubleshoot it and contribute to its
|
||||
development on https://github.com/chrys87/fenrir[the Fenrir Git
|
||||
development on https://git.stormux.org/storm/fenrir[the Fenrir Git
|
||||
repository].
|
||||
|
||||
=== Getting started with Fenrir
|
||||
@@ -27,9 +27,12 @@ and voices provided by Speech Dispatcher. +
|
||||
Keyboard shortcuts are bound to commands to read the screen, review it
|
||||
and perform other actions like modify the settings on the fly, switch
|
||||
languages, copy and paste text, provide miscellaneous information. +
|
||||
=== Configuration file === The permanent settings are recorded in the
|
||||
configuration file /etc/fenrirscreenreader/settings.conf, that is
|
||||
heavily commented. +
|
||||
=== Configuration file === The system-wide settings are recorded in the
|
||||
configuration file /etc/fenrirscreenreader/settings/settings.conf, that is
|
||||
heavily commented. Regular-user sessions, including `+fenrir -x+`, load
|
||||
`+~/.local/share/stormux/fenrirscreenreader/settings/settings.conf+` when it
|
||||
exists, otherwise they fall back to the system settings file. Saving settings
|
||||
as a regular user creates or updates the user-local file. +
|
||||
These settings are described in this user guide.
|
||||
|
||||
To start Fenrir once type as root:
|
||||
@@ -1095,23 +1098,6 @@ announce=True
|
||||
interrupt=False
|
||||
....
|
||||
|
||||
==== Promoted List
|
||||
|
||||
Promoted Lists are a nice feature if you are away from your computer or
|
||||
performing more longer tasks. you can define a list of words which you
|
||||
want to hear a sound icon for after a period of inactivity. Example if
|
||||
the word "Chrys" appears after 120 Seconds of inactivity:
|
||||
|
||||
....
|
||||
[promote]
|
||||
enabled=True
|
||||
inactiveTimeoutSec=120
|
||||
list=Chrys
|
||||
....
|
||||
|
||||
See section link:#Promote[Promote] in `+settings.conf+` for more
|
||||
information.
|
||||
|
||||
=== Dictionary
|
||||
|
||||
You can make use of different kinds of built-in dictionary's. A
|
||||
@@ -1231,17 +1217,11 @@ Enable debug mode. Debug information will be logged.
|
||||
`+-p, --print+`::
|
||||
Print debug messages to screen in addition to logging them.
|
||||
|
||||
`+-e, --emulated-pty+`::
|
||||
Use PTY emulation with escape sequences for input. This enables usage in desktop/X11/Wayland environments and terminal emulators.
|
||||
|
||||
`+-E, --emulated-evdev+`::
|
||||
Use PTY emulation with evdev for input (single instance mode).
|
||||
|
||||
`+-F, --force-all-screens+`::
|
||||
Force Fenrir to respond on all screens, ignoring the ignoreScreen setting. This temporarily overrides screen filtering for the current session.
|
||||
Force Fenrir to respond on all screens, ignoring the ignore_screen setting. This temporarily overrides screen filtering for the current session.
|
||||
|
||||
`+-i, -I, --ignore-screen <SCREEN>+`::
|
||||
Ignore specific screen(s). Can be used multiple times to ignore multiple screens. This is equivalent to setting ignoreScreen in the configuration file and will be combined with any existing ignore settings.
|
||||
Ignore specific screen(s). Can be used multiple times to ignore multiple screens. This is equivalent to setting ignore_screen in the configuration file and will be combined with any existing ignore settings.
|
||||
|
||||
==== Set settings options
|
||||
|
||||
@@ -1286,64 +1266,80 @@ Enable remote control in settings.conf:
|
||||
[remote]
|
||||
enable=True
|
||||
driver=unixDriver
|
||||
enableSettingsRemote=True
|
||||
enableCommandRemote=True
|
||||
enable_settings_remote=True
|
||||
enable_command_remote=True
|
||||
....
|
||||
|
||||
==== Using socat with Unix Sockets
|
||||
|
||||
The `+socat+` command provides the easiest way to send commands to Fenrir:
|
||||
|
||||
===== Instance Discovery
|
||||
|
||||
....
|
||||
# List registered Fenrir instances and their socket paths
|
||||
echo "ls" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
....
|
||||
|
||||
In X terminal mode (`+fenrir -x+`), multiple Fenrir instances can run at the
|
||||
same time. Each instance has a private socket at
|
||||
`+/tmp/fenrirscreenreader-<pid>.sock+`, and one instance may also own the
|
||||
standard control socket. Use `+ls+` or `+command ls+` on the standard socket to
|
||||
find the private socket for a specific instance. Commands sent to the standard
|
||||
socket are handled by its owner when possible; otherwise they are forwarded to a
|
||||
registered private socket, preferring the sender's Fenrir ancestor when one can
|
||||
be found.
|
||||
|
||||
===== Basic Speech Control
|
||||
|
||||
....
|
||||
# Interrupt current speech
|
||||
echo "command interrupt" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "command interrupt" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Speak custom text
|
||||
echo "command say Hello, this is a test message" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "command say Hello, this is a test message" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Temporarily disable speech (until next keystroke)
|
||||
echo "command tempdisablespeech" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "command tempdisablespeech" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
....
|
||||
|
||||
===== Settings Control
|
||||
|
||||
....
|
||||
# Enable highlight tracking mode
|
||||
echo "setting set focus#highlight=True" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set focus#highlight=True" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Change speech rate
|
||||
echo "setting set speech#rate=0.8" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set speech#rate=0.8" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Change punctuation level (none/some/most/all)
|
||||
echo "setting set general#punctuationLevel=all" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set general#punctuation_level=all" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Voice and TTS control
|
||||
echo "setting set speech#voice=en-us+f3" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set speech#voice=en-us+f3" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Multiple settings at once
|
||||
echo "setting set speech#rate=0.8;sound#volume=0.7;general#punctuationLevel=most" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set speech#rate=0.8;sound#volume=0.7;general#punctuation_level=most" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Reset all settings to defaults
|
||||
echo "setting reset" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting reset" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
....
|
||||
|
||||
===== Clipboard Operations
|
||||
|
||||
....
|
||||
# Place text into clipboard
|
||||
echo "command clipboard This text will be copied to clipboard" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "command clipboard This text will be copied to clipboard" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Export clipboard to file
|
||||
echo "command exportclipboard" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "command exportclipboard" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
....
|
||||
|
||||
===== Application Control
|
||||
|
||||
....
|
||||
# Quit Fenrir
|
||||
echo "command quitapplication" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "command quitapplication" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
....
|
||||
|
||||
==== Command Reference
|
||||
@@ -1355,6 +1351,7 @@ echo "command quitapplication" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-dea
|
||||
* `+command say <text>+` - Speak the specified text
|
||||
* `+command interrupt+` - Stop current speech
|
||||
* `+command tempdisablespeech+` - Disable speech until next key press
|
||||
* `+ls+` / `+list+` / `+command ls+` / `+command list+` - List registered Fenrir instances
|
||||
|
||||
*Clipboard Commands:*
|
||||
|
||||
@@ -1394,8 +1391,8 @@ echo "command quitapplication" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-dea
|
||||
* `+speech#module=module_name+` - TTS module (e.g., "espeak-ng")
|
||||
|
||||
*General Settings:*
|
||||
* `+general#punctuationLevel=none/some/most/all+` - Punctuation verbosity
|
||||
* `+general#autoSpellCheck=True/False+` - Automatic spell checking
|
||||
* `+general#punctuation_level=none/some/most/all+` - Punctuation verbosity
|
||||
* `+general#auto_spell_check=True/False+` - Automatic spell checking
|
||||
* `+general#emoticons=True/False+` - Enable emoticon replacement
|
||||
|
||||
*Sound Settings:*
|
||||
@@ -1407,11 +1404,11 @@ echo "command quitapplication" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-dea
|
||||
* `+focus#highlight=True/False+` - Follow text highlighting
|
||||
|
||||
*Keyboard Settings:*
|
||||
* `+keyboard#charEchoMode=0-2+` - Character echo (0=none, 1=always, 2=capslock only)
|
||||
* `+keyboard#wordEcho=True/False+` - Echo complete words
|
||||
* `+keyboard#char_echo_mode=0-2+` - Character echo (0=none, 1=always, 2=capslock only)
|
||||
* `+keyboard#word_echo=True/False+` - Echo complete words
|
||||
|
||||
*Screen Settings:*
|
||||
* `+screen#ignoreScreen=1,2,3+` - TTY screens to ignore
|
||||
* `+screen#ignore_screen=1,2,3+` - TTY screens to ignore
|
||||
|
||||
==== settings.conf syntax
|
||||
|
||||
@@ -1492,6 +1489,8 @@ By default we ship two sound packs.
|
||||
. `+default-wav+` wav encoded, just for compatibility
|
||||
|
||||
Sound packs are located at /usr/share/sounds/fenrirscreenreader/
|
||||
User sound packs in `+~/.local/stormux/fenrir/sounds/+` are loaded before
|
||||
system sound packs.
|
||||
|
||||
Sound volume controls how loud the sounds for your selected sound pack
|
||||
are.
|
||||
@@ -1511,14 +1510,14 @@ frequencies.
|
||||
sound file.
|
||||
|
||||
....
|
||||
genericPlayFileCommand=<your command for playing a file>
|
||||
generic_play_file_command=<your command for playing a file>
|
||||
....
|
||||
|
||||
`+genericFrequencyCommand+` defines the command that is used playing
|
||||
frequencies.
|
||||
|
||||
....
|
||||
genericFrequencyCommand=<your command for playing a frequence>
|
||||
generic_frequency_command=<your command for playing a frequence>
|
||||
....
|
||||
|
||||
The following variables are substituted in `+genericPlayFileCommand+`
|
||||
@@ -1532,13 +1531,13 @@ and `+genericFrequencyCommand+`:
|
||||
Example genericPlayFileCommand (default)
|
||||
|
||||
....
|
||||
genericPlayFileCommand=play -q -v fenrirVolume fenrirSoundFile
|
||||
generic_play_file_command=play -q -v fenrirVolume fenrirSoundFile
|
||||
....
|
||||
|
||||
Example genericFrequencyCommand (default)
|
||||
|
||||
....
|
||||
genericFrequencyCommand=play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence
|
||||
generic_frequency_command=play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence
|
||||
....
|
||||
|
||||
==== Speech
|
||||
@@ -1552,8 +1551,12 @@ enabled=True
|
||||
Values: on=`+True+`, off=`+False+`
|
||||
|
||||
# Select speech driver, options are speechdDriver (default),
|
||||
genericDriver or espeakDriver: driver=speechdDriver #driver=espeakDriver
|
||||
genericDriver, dectalkDriver, litetalkDriver, doubletalkDriver or tripletalkDriver: driver=speechdDriver
|
||||
#driver=genericDriver
|
||||
#driver=dectalkDriver
|
||||
#driver=litetalkDriver
|
||||
#driver=doubletalkDriver
|
||||
#driver=tripletalkDriver
|
||||
|
||||
This Selects the driver used to generate speech output.
|
||||
|
||||
@@ -1579,7 +1582,7 @@ Values: Range Minimum:`+0.0+` is lowest, Maximum:`+1.0+` is highest.
|
||||
A Pitch for capital letters can be set.
|
||||
|
||||
....
|
||||
capitalPitch=0.9
|
||||
capital_pitch=0.9
|
||||
....
|
||||
|
||||
Values: Range Minimum:`+0.0+` is lowest, Maximum:`+1.0+` is highest.
|
||||
@@ -1681,13 +1684,34 @@ the pico module:
|
||||
language=de-DE
|
||||
....
|
||||
|
||||
Read new text as it occurs autoReadIncoming=True Values: on=`+True+`,
|
||||
Hardware speech drivers use a serial device. Set an explicit path.
|
||||
|
||||
....
|
||||
hardware_device=/dev/ttyACM0
|
||||
hardware_device=/dev/ttyUSB0
|
||||
hardware_device=/dev/ttyS0
|
||||
....
|
||||
|
||||
Hardware speech drivers use 9600 baud by default.
|
||||
|
||||
....
|
||||
hardware_baud_rate=9600
|
||||
....
|
||||
|
||||
The `+doubletalkDriver+` targets DoubleTalk LT-style serial devices. It does
|
||||
not support the internal DoubleTalk PC ISA card.
|
||||
USB hardware speech synthesizers are supported only when Linux exposes them as
|
||||
a serial tty such as `+/dev/ttyACM0+` or `+/dev/ttyUSB0+`. USB-only TripleTalk
|
||||
models with no tty device need a separate driver.
|
||||
|
||||
Read new text as it occurs auto_read_incoming=True Values: on=`+True+`,
|
||||
off=`+False+`
|
||||
|
||||
==== Screen
|
||||
|
||||
The settings for screens, (TTY, PTY) are configured in the `+[screen]+`
|
||||
section.
|
||||
The settings for screen access are configured in the `+[screen]+`
|
||||
section. `+vcsaDriver+` is used for Linux TTYs, and `+ptyDriver+` is
|
||||
used by X11 terminal mode.
|
||||
|
||||
The driver to get the information from the screen:
|
||||
|
||||
@@ -1711,7 +1735,7 @@ Values:`+cp850+` is used for Western languages like USA or Europe.
|
||||
The driver updates Fenrir with changes on the screen.
|
||||
|
||||
....
|
||||
screenUpdateDelay=0.05
|
||||
screen_update_delay=0.05
|
||||
....
|
||||
|
||||
Values: in Seconds
|
||||
@@ -1776,7 +1800,7 @@ Gives Fenrir exclusive access to the keyboard and lets it control
|
||||
keystrokes. This is needed to intercept Fenrir related shortcuts.
|
||||
|
||||
....
|
||||
grabDevices=True
|
||||
grab_devices=True
|
||||
....
|
||||
|
||||
Values: on=`+True+`, off=`+False+`
|
||||
@@ -1785,7 +1809,7 @@ The following makes sense if you are using a second screenreader and
|
||||
want to have some hooked events. Fenrir ignores all shortcuts then.
|
||||
|
||||
....
|
||||
ignoreShortcuts=False
|
||||
ignore_shortcuts=False
|
||||
....
|
||||
|
||||
Values: on=`+True+`, off=`+False+`
|
||||
@@ -1793,11 +1817,11 @@ Values: on=`+True+`, off=`+False+`
|
||||
The current keyboard layout used for shortcuts.
|
||||
|
||||
....
|
||||
keyboardLayout=desktop
|
||||
keyboard_layout=desktop
|
||||
....
|
||||
|
||||
Values: An absolute Path to a Keyboard definition file or a Filename
|
||||
without extension located in `+/etc/fenrir/keyboard+`
|
||||
without extension located in `+/etc/fenrirscreenreader/keyboard+`
|
||||
|
||||
Announce characters while typing.
|
||||
|
||||
@@ -1810,7 +1834,7 @@ Values: on=`+True+`, off=`+False+`
|
||||
Announce deleted characters
|
||||
|
||||
....
|
||||
charDeleteEcho=True
|
||||
char_delete_echo=True
|
||||
....
|
||||
|
||||
Values: on=`+True+`, off=`+False+`
|
||||
@@ -1818,7 +1842,7 @@ Values: on=`+True+`, off=`+False+`
|
||||
Announce word after pressing space
|
||||
|
||||
....
|
||||
wordEcho=False
|
||||
word_echo=False
|
||||
....
|
||||
|
||||
Values: on=`+True+`, off=`+False+`
|
||||
@@ -1826,7 +1850,7 @@ Values: on=`+True+`, off=`+False+`
|
||||
Interrupt speech on any keypress
|
||||
|
||||
....
|
||||
interruptOnKeyPress=False
|
||||
interrupt_on_key_press=False
|
||||
....
|
||||
|
||||
Values: on=`+True+`, off=`+False+`
|
||||
@@ -1834,7 +1858,7 @@ Values: on=`+True+`, off=`+False+`
|
||||
You can filter the keys that speech should interrupt
|
||||
|
||||
....
|
||||
interruptOnKeyPressFilter=
|
||||
interrupt_on_key_press_filter=
|
||||
....
|
||||
|
||||
Values: (List) empty = all keys, otherwise interrupt with specified keys
|
||||
@@ -1842,7 +1866,7 @@ Values: (List) empty = all keys, otherwise interrupt with specified keys
|
||||
The timeout that is used for double tap shortcuts
|
||||
|
||||
....
|
||||
doubleTapTimeout=0.2
|
||||
double_tap_timeout=0.2
|
||||
....
|
||||
|
||||
Values: Seconds
|
||||
@@ -1862,16 +1886,16 @@ Values: off=0, error=1, warning=2, info=3
|
||||
the current punctuation and dict file in use:
|
||||
|
||||
....
|
||||
punctuationProfile=default
|
||||
punctuation_profile=default
|
||||
....
|
||||
|
||||
Values: Text, see available profiles in `+/etc/fenrir/punctuation+` or
|
||||
Values: Text, see available profiles in `+/etc/fenrirscreenreader/punctuation+` or
|
||||
in `+sourceTree/config/punctuation+`
|
||||
|
||||
The current punctuation level in use:
|
||||
|
||||
....
|
||||
punctuationLevel=some
|
||||
punctuation_level=some
|
||||
....
|
||||
|
||||
Values: Text, See available levels in the used punctuation file.
|
||||
@@ -1879,7 +1903,7 @@ Values: Text, See available levels in the used punctuation file.
|
||||
Respect pause for punctuations:
|
||||
|
||||
....
|
||||
respectPunctuationPause=True
|
||||
respect_punctuation_pause=True
|
||||
....
|
||||
|
||||
Values: on=`+True+`, off=`+False+`
|
||||
@@ -1887,7 +1911,7 @@ Values: on=`+True+`, off=`+False+`
|
||||
Add a pause on Line break:
|
||||
|
||||
....
|
||||
newLinePause=True
|
||||
new_line_pause=True
|
||||
....
|
||||
|
||||
Values: on=`+True+`, off=`+False+`
|
||||
@@ -1905,7 +1929,7 @@ Values: Text, Systemfilepath
|
||||
The number of available clipboards:
|
||||
|
||||
....
|
||||
numberOfClipboards=10
|
||||
number_of_clipboards=10
|
||||
....
|
||||
|
||||
Values: Integer, 1 - 999
|
||||
@@ -1921,7 +1945,7 @@ Values: on=`+True+`, off=`+False+`
|
||||
Define the current Fenrir keys:
|
||||
|
||||
....
|
||||
fenrirKeys=KEY_KP0,KEY_META,KEY_INSERT
|
||||
fenrir_keys=KEY_KP0,KEY_META,KEY_INSERT
|
||||
....
|
||||
|
||||
Values, Text list, separated by comma.
|
||||
@@ -1955,7 +1979,7 @@ https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior[d
|
||||
Enable or Disable spellcheck whilst typing:
|
||||
|
||||
....
|
||||
autoSpellCheck=True
|
||||
auto_spell_check=True
|
||||
....
|
||||
|
||||
Values: on=`+True+`, off=`+False+`
|
||||
@@ -1963,7 +1987,7 @@ Values: on=`+True+`, off=`+False+`
|
||||
The use of the dictionary with spellcheck:
|
||||
|
||||
....
|
||||
spellCheckLanguage=en_US
|
||||
spell_check_language=en_US
|
||||
....
|
||||
|
||||
Values: Text, see aspell dictionary's.
|
||||
@@ -1971,19 +1995,20 @@ Values: Text, see aspell dictionary's.
|
||||
Folder Path for your scripts "scriptKey" functionality:
|
||||
|
||||
....
|
||||
scriptPath=/usr/share/fenrirscreenreader/scripts
|
||||
script_path=/usr/share/fenrirscreenreader/scripts
|
||||
....
|
||||
|
||||
Values: Text, Existing path on file system.
|
||||
Values: Text, Existing path on file system. User scripts in
|
||||
`+~/.local/stormux/fenrir/+` are loaded before this configured path.
|
||||
|
||||
Override commands or create new ones without changing the Fenrir
|
||||
defaults:
|
||||
|
||||
....
|
||||
commandPath=/usr/share/fenrirscreenreader/commands
|
||||
command_path=/usr/share/fenrirscreenreader/commands
|
||||
....
|
||||
|
||||
Values: Text, Existing path on file system. Subfolders in commandPath
|
||||
Values: Text, Existing path on file system. Subfolders in command_path
|
||||
are:
|
||||
|
||||
* `+commands+` = to create shortcut commands
|
||||
@@ -2044,44 +2069,11 @@ Values: on=`+True+`, off=`+False+`
|
||||
Leave the review mode when changing the screen (From TTY3 to TTY4):
|
||||
|
||||
....
|
||||
leaveReviewOnScreenChange=True
|
||||
leave_review_on_screen_change=True
|
||||
....
|
||||
|
||||
Values: on=`+True+`, off=`+False+`
|
||||
|
||||
==== Promote
|
||||
|
||||
"Promoted Lists" are configured in the section `+[promote]+`. Turn
|
||||
Promoted Lists" on or off:
|
||||
|
||||
....
|
||||
enabled=True
|
||||
....
|
||||
|
||||
Values: on=`+True+`, off=`+False+`
|
||||
|
||||
The minimum time interval of inactivity to activate promoting. By
|
||||
default it promotes after 120 Seconds inactivity:
|
||||
|
||||
....
|
||||
inactiveTimeoutSec=120
|
||||
....
|
||||
|
||||
Values: in Seconds
|
||||
|
||||
Define a list of promoted words comma seperated:
|
||||
|
||||
....
|
||||
list=
|
||||
....
|
||||
|
||||
Values: text (comma seperated) Example to promote the word "nickname" or
|
||||
a bash prompt:
|
||||
|
||||
....
|
||||
list=nickname,$:,#:
|
||||
....
|
||||
|
||||
==== Time
|
||||
|
||||
The automated time announcement is configured in the section `+[time]+`.
|
||||
@@ -2152,14 +2144,15 @@ Values: on=`+True+`, off=`+False+`
|
||||
=== Scripting
|
||||
|
||||
Scripts can be in any language, bash, python, sh or others. Place your
|
||||
scripts in the directory /usr/share/fenrirscreenreader/scripts/ (the
|
||||
path is configurable in settings.conf). The script key is the
|
||||
personal scripts in `+~/.local/stormux/fenrir/+`, or place system scripts in
|
||||
the directory /usr/share/fenrirscreenreader/scripts/ (the path is configurable
|
||||
in settings.conf). The script key is the
|
||||
applications key. Usually this key can be found on the keyboard located
|
||||
just left of the right most control key. When you name a script, the key
|
||||
name appears in the script seperated by the sequence [.underline]#-#.
|
||||
So, for example, if you have a python weather script you want assigned
|
||||
to the script key plus the letter w you would name the script
|
||||
/usr/share/fenrirscreenreader/scripts/weather[.underline]##-##key_w.py
|
||||
~/.local/stormux/fenrir/weather[.underline]##-##key_w.py
|
||||
Then, to access the script, simply press the script key and the letter
|
||||
w. Scripts must be executable. So, make sure to chmod 755 your script
|
||||
when you place it in the scripts directory. The script gets some
|
||||
@@ -2193,9 +2186,9 @@ settings.conf). Commands are python files with a special scheme. You can
|
||||
assign them to a shortcut using the filename without an extension or
|
||||
place them in a hook trigger like OnInput or OnScreenChange. For further
|
||||
information see developer guide. Good Examples:
|
||||
https://github.com/chrys87/fenrir/blob/master/src/fenrir/commands/commands/date.py["date.py"]
|
||||
https://git.stormux.org/storm/fenrir/src/branch/master/src/fenrirscreenreader/commands/commands/date.py["date.py"]
|
||||
(announce the Date),
|
||||
https://github.com/chrys87/fenrir/blob/master/src/fenrir/commands/commands/shut_up.py["shut_up.py"]
|
||||
https://git.stormux.org/storm/fenrir/src/branch/master/src/fenrirscreenreader/commands/commands/shut_up.py["shut_up.py"]
|
||||
(interrupt output) the basic scheme for a command is as follows:
|
||||
|
||||
....
|
||||
@@ -2218,7 +2211,7 @@ class command():
|
||||
pass
|
||||
....
|
||||
|
||||
* https://github.com/chrys87/fenrir/blob/master/src/fenrir/commands/command_template.py[Template
|
||||
* https://git.stormux.org/storm/fenrir/src/branch/master/src/fenrirscreenreader/commands/command_template.py[Template
|
||||
lives here]
|
||||
* The class needs to have the name "command".
|
||||
* "initialize" is running once whilst loading the command.
|
||||
@@ -2276,7 +2269,7 @@ root.
|
||||
=== Bugreports and feature requests
|
||||
|
||||
Please report Bugs and feature requests to:
|
||||
https://github.com/chrys87/fenrir/issues
|
||||
https://git.stormux.org/storm/fenrir/issues
|
||||
|
||||
for bugs please provide a link:#Howto create a debug file[debug] file
|
||||
that shows the issue.
|
||||
|
||||
+97
-34
@@ -38,6 +38,7 @@ Navigate the screen without moving the text cursor. Essential for examining cont
|
||||
### Navigation (Desktop Layout)
|
||||
- `Ctrl` - Stop speech (shut up)
|
||||
- `Fenrir + H` - Tutorial mode
|
||||
- `Fenrir + Ctrl + H` - Speech history
|
||||
- `Fenrir + Q` - Quit Fenrir
|
||||
- `Fenrir + Keypad 5` - Read current screen
|
||||
- `Keypad 8` - Read current line
|
||||
@@ -77,7 +78,13 @@ Navigate the screen without moving the text cursor. Essential for examining cont
|
||||
## Configuration
|
||||
|
||||
### Settings File
|
||||
Main configuration: `/etc/fenrir/settings/settings.conf`
|
||||
Main configuration:
|
||||
- **System-wide**: `/etc/fenrirscreenreader/settings/settings.conf`
|
||||
- **User-local**: `~/.local/share/stormux/fenrirscreenreader/settings/settings.conf`
|
||||
|
||||
When Fenrir runs as a regular user, including `fenrir -x`, it loads the user-local settings file if it exists. If it does not exist, Fenrir falls back to the system settings file, but saving settings creates or updates the user-local file. When Fenrir runs as root, settings save to the system-wide file by default.
|
||||
|
||||
User sound themes are loaded before system themes from `~/.local/stormux/fenrir/sounds/`. User scripts are loaded before configured system scripts from `~/.local/stormux/fenrir/`.
|
||||
|
||||
### Key Sections
|
||||
- `[speech]` - Speech synthesis settings
|
||||
@@ -94,6 +101,9 @@ driver=speechdDriver
|
||||
rate=0.5
|
||||
pitch=0.5
|
||||
volume=1.0
|
||||
hardware_device=/dev/ttyS0
|
||||
hardware_baud_rate=9600
|
||||
history_size=50
|
||||
|
||||
[sound]
|
||||
enabled=True
|
||||
@@ -102,17 +112,17 @@ volume=0.7
|
||||
|
||||
[keyboard]
|
||||
driver=evdevDriver
|
||||
keyboardLayout=desktop
|
||||
keyboard_layout=desktop
|
||||
|
||||
[screen]
|
||||
driver=vcsaDriver
|
||||
ignoreScreen=
|
||||
ignore_screen=
|
||||
|
||||
[remote]
|
||||
enable=True
|
||||
driver=unixDriver
|
||||
enableSettingsRemote=True
|
||||
enableCommandRemote=True
|
||||
enable_settings_remote=True
|
||||
enable_command_remote=True
|
||||
```
|
||||
|
||||
## Remote Control
|
||||
@@ -126,65 +136,79 @@ Enable remote control in settings:
|
||||
enable=True
|
||||
driver=unixDriver # or tcpDriver
|
||||
port=22447 # for TCP driver
|
||||
enableSettingsRemote=True # allow settings changes
|
||||
enableCommandRemote=True # allow command execution
|
||||
enable_settings_remote=True # allow settings changes
|
||||
enable_command_remote=True # allow command execution
|
||||
```
|
||||
|
||||
### Basic Usage with socat
|
||||
|
||||
#### Instance Discovery
|
||||
```bash
|
||||
# List registered Fenrir instances and their socket paths
|
||||
echo "ls" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
```
|
||||
|
||||
In X terminal mode (`fenrir -x`), multiple Fenrir instances can run at the same
|
||||
time. Each instance has a private socket at `/tmp/fenrirscreenreader-<pid>.sock`,
|
||||
and one instance may also own the standard control socket. Use `ls` or
|
||||
`command ls` on the standard socket to find the private socket for a specific
|
||||
instance. Commands sent to the standard socket are handled by its owner when
|
||||
possible; otherwise they are forwarded to a registered private socket,
|
||||
preferring the sender's Fenrir ancestor when one can be found.
|
||||
|
||||
#### Speech Control
|
||||
```bash
|
||||
# Interrupt current speech
|
||||
echo "command interrupt" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "command interrupt" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Speak custom text
|
||||
echo "command say Hello, this is a test" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "command say Hello, this is a test" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Temporarily disable speech
|
||||
echo "command tempdisablespeech" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "command tempdisablespeech" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
```
|
||||
|
||||
#### Settings Control
|
||||
```bash
|
||||
# Enable highlight tracking
|
||||
echo "setting set focus#highlight=True" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set focus#highlight=True" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Change speech parameters
|
||||
echo "setting set speech#rate=0.8" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set speech#pitch=0.6" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set speech#volume=0.9" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set speech#rate=0.8" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
echo "setting set speech#pitch=0.6" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
echo "setting set speech#volume=0.9" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Change punctuation level (none/some/most/all)
|
||||
echo "setting set general#punctuationLevel=all" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set general#punctuation_level=all" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Voice and TTS control
|
||||
echo "setting set speech#voice=en-us+f3" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set speech#module=espeak-ng" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set speech#voice=en-us+f3" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
echo "setting set speech#module=espeak-ng" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Multiple settings at once
|
||||
echo "setting set speech#rate=0.8;sound#volume=0.7;general#punctuationLevel=most" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting set speech#rate=0.8;sound#volume=0.7;general#punctuation_level=most" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Reset all settings
|
||||
echo "setting reset" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting reset" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Save settings
|
||||
echo "setting save" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting saveas /tmp/my-settings.conf" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "setting save" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
echo "setting saveas /tmp/my-settings.conf" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
```
|
||||
|
||||
#### Clipboard Operations
|
||||
```bash
|
||||
# Add text to clipboard
|
||||
echo "command clipboard Text to copy" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "command clipboard Text to copy" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
|
||||
# Export clipboard to file
|
||||
echo "command exportclipboard" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "command exportclipboard" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
```
|
||||
|
||||
#### Application Control
|
||||
```bash
|
||||
# Quit Fenrir
|
||||
echo "command quitapplication" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "command quitapplication" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
```
|
||||
|
||||
### Command Reference
|
||||
@@ -193,6 +217,7 @@ echo "command quitapplication" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-dea
|
||||
- `command say <text>` - Speak text
|
||||
- `command interrupt` - Stop speech
|
||||
- `command tempdisablespeech` - Disable until next key
|
||||
- `ls` / `list` / `command ls` / `command list` - List registered Fenrir instances
|
||||
|
||||
**Settings Commands:**
|
||||
- `setting set <section>#<key>=<value>` - Change setting
|
||||
@@ -208,18 +233,18 @@ echo "command quitapplication" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-dea
|
||||
- `command resetvmenu` - Reset virtual menu
|
||||
|
||||
**Key Settings You Can Change:**
|
||||
- Punctuation level: `setting set general#punctuationLevel=all`
|
||||
- Punctuation level: `setting set general#punctuation_level=all`
|
||||
- Speech parameters: `setting set speech#rate=0.8;speech#pitch=0.6`
|
||||
- Voice selection: `setting set speech#voice=en-us+f3`
|
||||
- Character echo: `setting set keyboard#charEchoMode=1`
|
||||
- Screen ignore: `setting set screen#ignoreScreen=1,2,3`
|
||||
- Character echo: `setting set keyboard#char_echo_mode=1`
|
||||
- Screen ignore: `setting set screen#ignore_screen=1,2,3`
|
||||
|
||||
### Scripting Integration
|
||||
|
||||
#### Bash Helper Function
|
||||
```bash
|
||||
fenrir_say() {
|
||||
echo "command say $1" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
|
||||
echo "command say $1" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
|
||||
}
|
||||
|
||||
# Usage
|
||||
@@ -232,7 +257,7 @@ import socket
|
||||
import os
|
||||
|
||||
def send_fenrir_command(command):
|
||||
socket_path = "/tmp/fenrirscreenreader-deamon.sock"
|
||||
socket_path = "/tmp/fenrirscreenreader-daemon.sock"
|
||||
if os.path.exists(socket_path):
|
||||
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
try:
|
||||
@@ -311,6 +336,19 @@ Fenrir automatically detects and provides audio feedback for progress indicators
|
||||
### Speech Drivers
|
||||
- **speechdDriver** - Speech-dispatcher (recommended)
|
||||
- **genericDriver** - Command-line TTS (espeak, etc.)
|
||||
- **dectalkDriver** - Serial DECtalk-compatible hardware speech
|
||||
- **litetalkDriver** - Serial LiteTalk-compatible hardware speech
|
||||
- **doubletalkDriver** - Serial DoubleTalk LT-compatible hardware speech
|
||||
- **tripletalkDriver** - Serial TripleTalk-compatible hardware speech
|
||||
|
||||
For hardware speech, set `speech#hardware_device` to an explicit serial path.
|
||||
RPITalk gadget mode usually appears as `/dev/ttyACM0`; USB serial adapters
|
||||
usually appear as `/dev/ttyUSB0`; built-in serial ports may be `/dev/ttyS0`.
|
||||
The default baud rate is `9600`. `doubletalkDriver` targets
|
||||
DoubleTalk LT-style serial devices, not the internal DoubleTalk PC ISA card.
|
||||
USB TripleTalk devices work only if Linux exposes them as a serial tty such as
|
||||
`/dev/ttyACM0` or `/dev/ttyUSB0`; USB-only models with no tty device need a
|
||||
separate driver.
|
||||
|
||||
### Sound Drivers
|
||||
- **genericDriver** - Sox-based (default)
|
||||
@@ -318,7 +356,7 @@ Fenrir automatically detects and provides audio feedback for progress indicators
|
||||
|
||||
### Input Drivers
|
||||
- **evdevDriver** - Linux evdev (recommended for Linux)
|
||||
- **ptyDriver** - Terminal emulation (cross-platform)
|
||||
- **x11Driver** - X11 terminal-scoped input for `fenrir -x`
|
||||
|
||||
### Screen Drivers
|
||||
- **vcsaDriver** - Linux VCSA devices (TTY)
|
||||
@@ -341,11 +379,35 @@ fenrir [OPTIONS]
|
||||
- `-o, --options SECTION#SETTING=VALUE;..` - Override settings
|
||||
- `-d, --debug` - Enable debug mode
|
||||
- `-p, --print` - Print debug to screen
|
||||
- `-e, --emulated-pty` - PTY emulation for desktop use
|
||||
- `-E, --emulated-evdev` - PTY + evdev emulation
|
||||
- `-F, --force-all-screens` - Ignore ignoreScreen setting
|
||||
- `-x, --x11` - PTY + X11 keyboard input scoped to the terminal window
|
||||
- `--x11-window-id WINDOWID` - X11 window id to use for `--x11` terminal mode
|
||||
- `-F, --force-all-screens` - Ignore ignore_screen setting
|
||||
- `-i, -I, --ignore-screen SCREEN` - Ignore specific screen(s), can be used multiple times
|
||||
|
||||
### X11 Terminal Mode
|
||||
|
||||
Use `fenrir -x` to run Fenrir in an X11 terminal as a normal user:
|
||||
|
||||
```bash
|
||||
fenrir -x
|
||||
```
|
||||
|
||||
This mode uses PTY screen monitoring and X11 keyboard input. It is intended for GUI terminals such as xterm and VTE-based terminals, while keeping Fenrir key handling scoped to that terminal window. Desktop screen readers keep their global bindings outside the focused terminal.
|
||||
|
||||
Fenrir normally detects the target terminal from `WINDOWID` or the active X11 window. If needed, pass a window id explicitly:
|
||||
|
||||
```bash
|
||||
fenrir -x --x11-window-id 0x123456
|
||||
```
|
||||
|
||||
X11 terminal mode uses the same keyboard layout files as TTY Fenrir. Supported Fenrir keys include numpad Insert/`KEY_KP0`, CapsLock/`KEY_CAPSLOCK`, Insert/`KEY_INSERT`, and Super/Windows/`KEY_META`. Compose script keys are exposed as `KEY_COMPOSE`.
|
||||
|
||||
In this mode Fenrir runs as a regular user. Settings are loaded from `~/.local/share/stormux/fenrirscreenreader/settings/settings.conf` when present, otherwise from `/etc/fenrirscreenreader/settings/settings.conf`; saving settings creates or updates the user-local file. User sound themes and scripts are read first from `~/.local/stormux/fenrir/sounds/` and `~/.local/stormux/fenrir/`.
|
||||
|
||||
This mode requires `python-xlib`.
|
||||
|
||||
For a dedicated PTY/terminal screen reader, see TDSR: https://github.com/tspivey/tdsr
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### No Speech
|
||||
@@ -379,5 +441,6 @@ sudo fenrir -f -d
|
||||
## See Also
|
||||
|
||||
- [README.md](../README.md) - Installation and basic setup
|
||||
- [diff_review_mode.md](./diff_review_mode.md) - Diff review workflow and key bindings
|
||||
- [settings.conf](../config/settings/settings.conf) - Configuration reference
|
||||
- `man fenrir` - Manual page
|
||||
- `man fenrir` - Manual page
|
||||
|
||||
+58
-66
@@ -160,7 +160,7 @@ For Arch there are PKGBUILDs in the AUR:
|
||||
|
||||
- Download the latest stable version from the [[https://linux-a11y.org/index.php?page=fenrir-screenreader|Fenrir-Project]] site.
|
||||
- Unpack the archive
|
||||
- Check the needed Dependencys by running [[https://github.com/chrys87/fenrir/blob/master/check-dependencies.py|check-dependencys.py]] script
|
||||
- Check the needed Dependencys by running [[https://git.stormux.org/storm/fenrir/src/branch/master/check-dependencies.py|check-dependencys.py]] script
|
||||
- install the missing dependencies an standard installation requires the following:
|
||||
* python3 >= 3.3 (and all the following is needed for python3 )
|
||||
* python3-speechd (screen)
|
||||
@@ -171,7 +171,7 @@ For Arch there are PKGBUILDs in the AUR:
|
||||
* python3-pyenchant (spellchecker)
|
||||
* your language for aspell (aspell-<lang>) (spellchecker)
|
||||
* sox (sound)
|
||||
* For an individual installation see [[#Support and Requirements|Support and Requirements]] or consult the [[https://github.com/chrys87/fenrir/blob/master/README.md|Readme]])
|
||||
* For an individual installation see [[#Support and Requirements|Support and Requirements]] or consult the [[https://git.stormux.org/storm/fenrir/src/branch/master/README.md|Readme]])
|
||||
- run "install.sh" as root
|
||||
|
||||
this installs Fenrir as the following
|
||||
@@ -185,7 +185,7 @@ to remove Fenrir just run uninstall.sh as root
|
||||
|
||||
if you want to get the latest code you can use git to get a development snapshot:
|
||||
|
||||
git clone https://github.com/chrys87/fenrir.git
|
||||
git clone https://git.stormux.org/storm/fenrir.git
|
||||
|
||||
===== Auto Start =====
|
||||
|
||||
@@ -729,15 +729,6 @@ Example on fix minutes in an hour. example every quarter "delaySec=0" and "onMin
|
||||
onMinutes=00,15,30,45
|
||||
announce=True
|
||||
interrupt=False
|
||||
==== Promoted List ====
|
||||
Promoted Lists are a nice feature if you are away from your computer or performing more longer tasks.
|
||||
you can define a list of words which you want to hear a sound icon for after a period of inactivity.
|
||||
Example if the word "Chrys" appears after 120 Seconds of inactivity:
|
||||
[promote]
|
||||
enabled=True
|
||||
inactiveTimeoutSec=120
|
||||
list=Chrys
|
||||
See section [[#Promote|Promote]] in ''settings.conf'' for more information.
|
||||
==== Punctuation ====
|
||||
Fenrir handles punctuation levels and names for you with several provided dictionaries.
|
||||
|
||||
@@ -867,9 +858,9 @@ Values: ''0.0'' is quietest, ''1.0'' is loudest.
|
||||
The generic sound driver uses shell commands for play sound and frequencies.
|
||||
|
||||
''genericPlayFileCommand'' defines the command that is used to play a sound file.
|
||||
genericPlayFileCommand=<your command for playing a file>
|
||||
generic_play_file_command=<your command for playing a file>
|
||||
''genericFrequencyCommand'' defines the command that is used playing frequencies.
|
||||
genericFrequencyCommand=<your command for playing a frequence>
|
||||
generic_frequency_command=<your command for playing a frequence>
|
||||
|
||||
The following variables are substituted in ''genericPlayFileCommand'' and ''genericFrequencyCommand'':
|
||||
* ''fenrirVolume'' = the current volume setting
|
||||
@@ -878,19 +869,22 @@ The following variables are substituted in ''genericPlayFileCommand'' and ''gene
|
||||
* ''fenrirDuration'' = the duration of the frequency
|
||||
|
||||
Example genericPlayFileCommand (default)
|
||||
genericPlayFileCommand=play -q -v fenrirVolume fenrirSoundFile
|
||||
generic_play_file_command=play -q -v fenrirVolume fenrirSoundFile
|
||||
Example genericFrequencyCommand (default)
|
||||
genericFrequencyCommand=play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence
|
||||
generic_frequency_command=play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence
|
||||
==== Speech ====
|
||||
Speech is configured in section ''[speech]''.
|
||||
Turn speech on or off:
|
||||
enabled=True
|
||||
Values: on=''True'', off=''False''
|
||||
|
||||
# Select speech driver, options are speechdDriver (default), genericDriver or espeakDriver:
|
||||
# Select speech driver, options are speechdDriver (default), genericDriver, dectalkDriver, litetalkDriver, doubletalkDriver or tripletalkDriver:
|
||||
driver=speechdDriver
|
||||
#driver=espeakDriver
|
||||
#driver=genericDriver
|
||||
#driver=dectalkDriver
|
||||
#driver=litetalkDriver
|
||||
#driver=doubletalkDriver
|
||||
#driver=tripletalkDriver
|
||||
|
||||
Select the driver used to generate speech output.
|
||||
|
||||
@@ -899,7 +893,10 @@ Select the driver used to generate speech output.
|
||||
Available Drivers:
|
||||
* ''genericDriver'' using the generic driver, for Fenrir <1.5 this is not available
|
||||
* ''speechdDriver'' using speech-dispatcher, for Fenrir <1.5 just use ''speechd''
|
||||
* ''espeakDriver'' using the espeak directly, for Fenrir <1.5 just use ''espeak''
|
||||
* ''dectalkDriver'' using DECtalk-compatible serial hardware or RPITalk
|
||||
* ''litetalkDriver'' using LiteTalk-compatible serial hardware or RPITalk
|
||||
* ''doubletalkDriver'' using DoubleTalk LT-compatible serial hardware
|
||||
* ''tripletalkDriver'' using TripleTalk-compatible serial hardware
|
||||
|
||||
The rate selects how fast Fenrir will speak.
|
||||
rate=0.65
|
||||
@@ -910,7 +907,7 @@ Pitch controls the pitch of the voice.
|
||||
Values: Range Minimum:''0.0'' is lowest, Maximum:''1.0'' is highest.
|
||||
|
||||
A Pitch for capital letters can be set.
|
||||
capitalPitch=0.9
|
||||
capital_pitch=0.9
|
||||
Values: Range Minimum:''0.0'' is lowest, Maximum:''1.0'' is highest.
|
||||
|
||||
The Volume controls the loudness of the voice.
|
||||
@@ -930,8 +927,19 @@ Select the language you want Fenrir to use.
|
||||
language=english-us
|
||||
Values: Text, see your TTS synths documentation what is available.
|
||||
|
||||
Hardware speech drivers use a serial device. Set an explicit path.
|
||||
hardware_device=/dev/ttyACM0
|
||||
hardware_device=/dev/ttyUSB0
|
||||
hardware_device=/dev/ttyS0
|
||||
|
||||
Hardware speech drivers use 9600 baud by default.
|
||||
hardware_baud_rate=9600
|
||||
|
||||
The doubletalkDriver targets DoubleTalk LT-style serial devices. It does not support the internal DoubleTalk PC ISA card.
|
||||
USB hardware speech synthesizers are supported only when Linux exposes them as a serial tty such as /dev/ttyACM0 or /dev/ttyUSB0. USB-only TripleTalk models with no tty device need a separate driver.
|
||||
|
||||
Read new text as it occurs
|
||||
autoReadIncoming=True
|
||||
auto_read_incoming=True
|
||||
Values: on=''True'', off=''False''
|
||||
|
||||
=== Generic Driver ===
|
||||
@@ -948,16 +956,16 @@ The following variables are substituted in ''genericSpeechCommand'':
|
||||
* ''fenrirRate'' = is replaced with the current speed (speech rate)
|
||||
|
||||
Example genericSpeechCommand (default):
|
||||
genericSpeechCommand=espeak -a fenrirVolume -s fenrirRate -p fenrirPitch -v fenrirVoice "fenrirText"
|
||||
generic_speech_command=espeak -a fenrirVolume -s fenrirRate -p fenrirPitch -v fenrirVoice "fenrirText"
|
||||
|
||||
These are the minimum and maximum values of the TTS system used in genericSpeechCommand. They are needed to calculate the abstract range in volume, rate and pitch 0.0 - 1.0.
|
||||
|
||||
FenrirMinVolume=0
|
||||
fenrirMaxVolume=200
|
||||
fenrirMinPitch=0
|
||||
fenrirMaxPitch=99
|
||||
fenrirMinRate=80
|
||||
fenrirMaxRate=450
|
||||
fenrir_max_volume=200
|
||||
fenrir_min_pitch=0
|
||||
fenrir_max_pitch=99
|
||||
fenrir_min_rate=80
|
||||
fenrir_max_rate=450
|
||||
|
||||
The current volume, pitch and rate is calculated like this
|
||||
value = min + [volume,pitch,rate] * (min - max )
|
||||
@@ -1022,7 +1030,8 @@ Values: Integer,
|
||||
* ''0'' = display size
|
||||
* ''>0'' number of cells
|
||||
==== Screen ====
|
||||
The settings for screens, (TTY, PTY) are configured in the ''[screen]'' section.
|
||||
The settings for screen access are configured in the ''[screen]'' section.
|
||||
''vcsaDriver'' is used for Linux TTYs, and ''ptyDriver'' is used by X11 terminal mode.
|
||||
|
||||
The driver to get the information from the screen:
|
||||
driver=vcsaDriver
|
||||
@@ -1033,7 +1042,7 @@ The encoding of the screen
|
||||
Values:''cp850'' is used for Western languages like USA or Europe.
|
||||
|
||||
The driver updates Fenrir with changes on the screen.
|
||||
screenUpdateDelay=0.05
|
||||
screen_update_delay=0.05
|
||||
Values: in Seconds
|
||||
|
||||
If you want Fenrir to not be active on any screen for various reasons. Maybe an X server or Wayland is running on that screen. You can make Fenrir ignore it or multiple screens seperated by '','' with:
|
||||
@@ -1064,15 +1073,15 @@ Values:
|
||||
* ''<Device Name>'' just use the device with the given name.
|
||||
|
||||
Gives Fenrir exclusive access to the keyboard and lets it control keystrokes. This is needed to intercept Fenrir related shortcuts.
|
||||
grabDevices=True
|
||||
grab_devices=True
|
||||
Values: on=''True'', off=''False''
|
||||
|
||||
The following makes sense if you are using a second screenreader and want to have some hooked events. Fenrir ignores all shortcuts then.
|
||||
ignoreShortcuts=False
|
||||
ignore_shortcuts=False
|
||||
Values: on=''True'', off=''False''
|
||||
|
||||
The current keyboard layout used for shortcuts.
|
||||
keyboardLayout=desktop
|
||||
keyboard_layout=desktop
|
||||
Values: An absolute Path to a Keyboard definition file or a Filename without extension located in ''/etc/fenrir/keyboard''
|
||||
|
||||
Announce characters while typing.
|
||||
@@ -1080,23 +1089,23 @@ Announce characters while typing.
|
||||
Values: on=''True'', off=''False''
|
||||
|
||||
Announce deleted characters
|
||||
charDeleteEcho=True
|
||||
char_delete_echo=True
|
||||
Values: on=''True'', off=''False''
|
||||
|
||||
Announce word after pressing space
|
||||
wordEcho=False
|
||||
word_echo=False
|
||||
Values: on=''True'', off=''False''
|
||||
|
||||
Interrupt speech on any keypress
|
||||
interruptOnKeyPress=False
|
||||
interrupt_on_key_press=False
|
||||
Values: on=''True'', off=''False''
|
||||
|
||||
You can filter the keys that speech should interrupt
|
||||
interruptOnKeyPressFilter=
|
||||
interrupt_on_key_press_filter=
|
||||
Values: (List) empty = all keys, otherwise interrupt with specified keys
|
||||
|
||||
The timeout that is used for double tap shortcuts
|
||||
doubleTapTimeout=0.2
|
||||
double_tap_timeout=0.2
|
||||
Values: Seconds
|
||||
==== General ====
|
||||
Overall settings can be configured from the section ''[general]''.
|
||||
@@ -1106,19 +1115,19 @@ Set the current debug level:
|
||||
Values: off=0, error=1, warning=2, info=3
|
||||
|
||||
the current punctuation and dict file in use:
|
||||
punctuationProfile=default
|
||||
punctuation_profile=default
|
||||
Values: Text, see available profiles in ''/etc/fenrir/punctuation'' or in ''sourceTree/config/punctuation''
|
||||
|
||||
The current punctuation level in use:
|
||||
punctuationLevel=some
|
||||
punctuation_level=some
|
||||
Values: Text, See available levels in the used punctuation file.
|
||||
|
||||
Respect pause for punctuations:
|
||||
respectPunctuationPause=True
|
||||
respect_punctuation_pause=True
|
||||
Values: on=''True'', off=''False''
|
||||
|
||||
Add a pause on Line break:
|
||||
newLinePause=True
|
||||
new_line_pause=True
|
||||
Values: on=''True'', off=''False''
|
||||
|
||||
Specify the path where the clipboard should be exported to.
|
||||
@@ -1128,7 +1137,7 @@ The variable ''$user'' is replaced by the current logged username.
|
||||
Values: Text, Systemfilepath
|
||||
|
||||
The number of available clipboards:
|
||||
numberOfClipboards=10
|
||||
number_of_clipboards=10
|
||||
Values: Integer, 1 - 999
|
||||
|
||||
Replace emoticons like :) or ;) with text insertions:
|
||||
@@ -1136,7 +1145,7 @@ Replace emoticons like :) or ;) with text insertions:
|
||||
Values: on=''True'', off=''False''
|
||||
|
||||
Define the current Fenrir keys:
|
||||
fenrirKeys=KEY_KP0,KEY_META,KEY_INSERT
|
||||
fenrir_keys=KEY_KP0,KEY_META,KEY_INSERT
|
||||
Values, Text list, separated by comma.
|
||||
|
||||
Define the current script keys:
|
||||
@@ -1152,11 +1161,11 @@ The date format to be used for (date command) output:
|
||||
Values: see python specification for [[https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior|datetime.strftime]]
|
||||
|
||||
Enable or Disable spellcheck whilst typing:
|
||||
autoSpellCheck=True
|
||||
auto_spell_check=True
|
||||
Values: on=''True'', off=''False''
|
||||
|
||||
The use of the dictionary with spellcheck:
|
||||
spellCheckLanguage=en_US
|
||||
spell_check_language=en_US
|
||||
Values: Text, see aspell dictionary's.
|
||||
|
||||
Folder Path for your scripts "scriptKey" functionality:
|
||||
@@ -1197,25 +1206,8 @@ Leave the review mode when pressing a key:
|
||||
Values: on=''True'', off=''False''
|
||||
|
||||
Leave the review mode when changing the screen (From TTY3 to TTY4):
|
||||
leaveReviewOnScreenChange=True
|
||||
leave_review_on_screen_change=True
|
||||
Values: on=''True'', off=''False''
|
||||
==== Promote ====
|
||||
"Promoted Lists" are configured in the section ''[promote]''.
|
||||
Turn Promoted Lists" on or off:
|
||||
enabled=True
|
||||
Values: on=''True'', off=''False''
|
||||
|
||||
The minimum time interval of inactivity to activate promoting.
|
||||
By default it promotes after 120 Seconds inactivity:
|
||||
inactiveTimeoutSec=120
|
||||
Values: in Seconds
|
||||
|
||||
Define a list of promoted words comma seperated:
|
||||
list=
|
||||
Values: text (comma seperated)
|
||||
Example to promote the word "nickname" or a bash prompt:
|
||||
list=nickname,$:,#:
|
||||
|
||||
==== Time ====
|
||||
The automated time announcement is configured in the section ''[time]''.
|
||||
Time announcement is disabled by default.
|
||||
@@ -1270,7 +1262,7 @@ File: ''/usr/share/fenrirscreenreader/scripts/helloWorld__-__key_h.sh'':
|
||||
===== Commands =====
|
||||
You can place your own commands in "/usr/share/fenrirscreenreader/commands" (path is configurable in settings.conf).
|
||||
Commands are python files with a special scheme. You can assign them to a shortcut using the filename without an extension or place them in a hook trigger like OnInput or OnScreenChange. For further information see developer guide.
|
||||
Good Examples: [[https://github.com/chrys87/fenrir/blob/master/src/fenrir/commands/commands/date.py|"date.py"]] (announce the Date), [[https://github.com/chrys87/fenrir/blob/master/src/fenrir/commands/commands/shut_up.py|"shut_up.py"]] (interrupt output)
|
||||
Good Examples: [[https://git.stormux.org/storm/fenrir/src/branch/master/src/fenrirscreenreader/commands/commands/date.py|"date.py"]] (announce the Date), [[https://git.stormux.org/storm/fenrir/src/branch/master/src/fenrirscreenreader/commands/commands/shut_up.py|"shut_up.py"]] (interrupt output)
|
||||
the basic scheme for a command is as follows:
|
||||
|
||||
from core import debug
|
||||
@@ -1289,7 +1281,7 @@ the basic scheme for a command is as follows:
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
|
||||
* [[https://github.com/chrys87/fenrir/blob/master/src/fenrir/commands/command_template.py|Template lives here]]
|
||||
* [[https://git.stormux.org/storm/fenrir/src/branch/master/src/fenrirscreenreader/commands/command_template.py|Template lives here]]
|
||||
* The class needs to have the name "command".
|
||||
* "initialize" is running once whilst loading the command.
|
||||
* "shutdown" is running on unload like the command (quit fenrir)
|
||||
@@ -1319,7 +1311,7 @@ the basic scheme for a command is as follows:
|
||||
- You can test if speech-dispatcher works by invoking it as root\\ ''sudo spd-say "hello world"''
|
||||
===== Bugreports and feature requests =====
|
||||
Please report Bugs and feature requests to:
|
||||
[[https://github.com/chrys87/fenrir/issues|https://github.com/chrys87/fenrir/issues]]
|
||||
[[https://git.stormux.org/storm/fenrir/issues|https://git.stormux.org/storm/fenrir/issues]]
|
||||
|
||||
for bugs please provide a [[#Howto create a debug file|debug]] file that shows the issue.
|
||||
==== How-to create a debug file ====
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ To test Fenrir:
|
||||
sudo fenrir
|
||||
|
||||
To have Fenrir start on system boot using systemd:
|
||||
download service file: https://raw.githubusercontent.com/chrys87/fenrir/master/autostart/systemd/Arch/fenrir.service
|
||||
download service file: https://git.stormux.org/storm/fenrir/raw/branch/master/autostart/systemd/Arch/fenrir.service
|
||||
move the service file to: /etc/systemd/system/fenrir.service
|
||||
sudo systemctl enable fenrir
|
||||
|
||||
|
||||
@@ -744,7 +744,6 @@ msgid "Script file is not executable"
|
||||
msgstr "Файл скрипта не исполняемый"
|
||||
|
||||
#: ../src/fenrirscreenreader/commands/commands/temp_disable_speech.py:17
|
||||
#: ../src/fenrirscreenreader/commands/onByteInput/15000-enable_temp_speech.py:17
|
||||
#: ../src/fenrirscreenreader/commands/onKeyInput/15000-enable_temp_speech.py:17
|
||||
msgid "disables speech until next keypress"
|
||||
msgstr "Отключить речь пока не нажата следующая клавиша"
|
||||
@@ -898,7 +897,6 @@ msgid "speech disabled"
|
||||
msgstr "Речь выключена"
|
||||
|
||||
#: ../src/fenrirscreenreader/commands/commands/toggle_speech.py:25
|
||||
#: ../src/fenrirscreenreader/commands/onByteInput/15000-enable_temp_speech.py:24
|
||||
#: ../src/fenrirscreenreader/commands/onKeyInput/15000-enable_temp_speech.py:28
|
||||
msgid "speech enabled"
|
||||
msgstr "Речь включена"
|
||||
@@ -1089,15 +1087,6 @@ msgstr "Мерцание"
|
||||
msgid "default"
|
||||
msgstr "По умолчанию"
|
||||
|
||||
#: ../src/fenrirscreenreader/core/byteManager.py:103
|
||||
#: ../src/fenrirscreenreader/core/byteManager.py:105
|
||||
msgid "Sticky Mode On"
|
||||
msgstr "Режим залипания включен"
|
||||
|
||||
#: ../src/fenrirscreenreader/core/byteManager.py:109
|
||||
msgid "bypass"
|
||||
msgstr ""
|
||||
|
||||
#: ../src/fenrirscreenreader/core/fenrirManager.py:26
|
||||
msgid "Start Fenrir"
|
||||
msgstr "fenrir запущен"
|
||||
@@ -1216,4 +1205,3 @@ msgstr "Меню"
|
||||
#: ../src/fenrirscreenreader/core/vmenuManager.py:234
|
||||
msgid "Action"
|
||||
msgstr "Действие"
|
||||
|
||||
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
[pytest]
|
||||
# Pytest configuration for Fenrir screen reader
|
||||
|
||||
# Test discovery patterns
|
||||
python_files = test_*.py *_test.py
|
||||
python_classes = Test*
|
||||
python_functions = test_*
|
||||
|
||||
# Test paths
|
||||
testpaths = tests
|
||||
|
||||
# Minimum Python version
|
||||
minversion = 3.7
|
||||
|
||||
# Output options
|
||||
addopts =
|
||||
# Verbose output with test names
|
||||
-v
|
||||
# Show extra test summary info
|
||||
-ra
|
||||
# Enable strict markers (only registered markers allowed)
|
||||
--strict-markers
|
||||
# Show local variables in tracebacks
|
||||
--showlocals
|
||||
# Warnings configuration
|
||||
-W ignore::DeprecationWarning
|
||||
# Optional plugins (uncomment if installed):
|
||||
# --timeout=30 # Requires pytest-timeout
|
||||
# --cov-report=term-missing # Requires pytest-cov
|
||||
# -x # Stop on first failure
|
||||
|
||||
# Register custom markers
|
||||
markers =
|
||||
unit: Unit tests (fast, no mocking)
|
||||
integration: Integration tests (require mocking)
|
||||
driver: Driver tests (require root access)
|
||||
slow: Tests that take more than 1 second
|
||||
remote: Tests for remote control functionality
|
||||
settings: Tests for settings and configuration
|
||||
commands: Tests for command system
|
||||
vmenu: Tests for VMenu system
|
||||
|
||||
# Coverage configuration
|
||||
[coverage:run]
|
||||
source = src/fenrirscreenreader
|
||||
omit =
|
||||
*/tests/*
|
||||
*/vmenu-profiles/*
|
||||
*/__pycache__/*
|
||||
*/site-packages/*
|
||||
|
||||
[coverage:report]
|
||||
# Fail if coverage falls below this percentage
|
||||
# fail_under = 70
|
||||
exclude_lines =
|
||||
# Standard pragma
|
||||
pragma: no cover
|
||||
# Don't complain about missing debug code
|
||||
def __repr__
|
||||
# Don't complain if tests don't hit defensive assertion code
|
||||
raise AssertionError
|
||||
raise NotImplementedError
|
||||
# Don't complain about abstract methods
|
||||
@abstractmethod
|
||||
# Don't complain about initialization
|
||||
if __name__ == .__main__.:
|
||||
|
||||
[coverage:html]
|
||||
directory = htmlcov
|
||||
@@ -1,7 +1,6 @@
|
||||
daemonize
|
||||
dbus-python
|
||||
evdev
|
||||
pexpect
|
||||
pyenchant
|
||||
pyperclip
|
||||
pyte
|
||||
|
||||
@@ -103,9 +103,11 @@ setup(
|
||||
"pyudev>=0.21.0",
|
||||
"setuptools",
|
||||
"setproctitle",
|
||||
"pexpect",
|
||||
"pyte>=0.7.0",
|
||||
],
|
||||
extras_require={
|
||||
"x11": ["python-xlib>=0.33"],
|
||||
},
|
||||
)
|
||||
|
||||
if not forceSettingsFlag:
|
||||
|
||||
+19
-11
@@ -41,7 +41,7 @@ def create_argument_parser():
|
||||
argumentParser.add_argument(
|
||||
'-s', '--setting',
|
||||
metavar='SETTING-FILE',
|
||||
default='/etc/fenrir/settings/settings.conf',
|
||||
default=None,
|
||||
help='Path to custom settings file'
|
||||
)
|
||||
argumentParser.add_argument(
|
||||
@@ -61,14 +61,15 @@ def create_argument_parser():
|
||||
help='Print debug messages to screen'
|
||||
)
|
||||
argumentParser.add_argument(
|
||||
'-e', '--emulated-pty',
|
||||
'-x', '--x11',
|
||||
action='store_true',
|
||||
help='Use PTY emulation with escape sequences for input (enables desktop/X/Wayland usage)'
|
||||
help='Use PTY emulation with X11 keyboard input scoped to the terminal window'
|
||||
)
|
||||
argumentParser.add_argument(
|
||||
'-E', '--emulated-evdev',
|
||||
action='store_true',
|
||||
help='Use PTY emulation with evdev for input (single instance)'
|
||||
'--x11-window-id',
|
||||
metavar='WINDOWID',
|
||||
default='',
|
||||
help='X11 window id to use for --x11 terminal mode'
|
||||
)
|
||||
argumentParser.add_argument(
|
||||
'-F',
|
||||
@@ -91,8 +92,8 @@ def validate_arguments(cliArgs):
|
||||
if option and ('#' not in option or '=' not in option):
|
||||
return False, f"Invalid option format: {option}\nExpected format: SECTION#SETTING=VALUE"
|
||||
|
||||
if cliArgs.emulated_pty and cliArgs.emulated_evdev:
|
||||
return False, "Cannot use both --emulated-pty and --emulated-evdev simultaneously"
|
||||
if cliArgs.x11_window_id and not cliArgs.x11:
|
||||
return False, "--x11-window-id requires --x11"
|
||||
|
||||
return True, None
|
||||
|
||||
@@ -105,14 +106,17 @@ def run_fenrir():
|
||||
fenrirApp.proceed()
|
||||
except Exception as e:
|
||||
print(f"Error starting Fenrir: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
except KeyboardInterrupt:
|
||||
print("Interrupted", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
finally:
|
||||
if fenrirApp and hasattr(fenrirApp, 'cleanup_on_error'):
|
||||
try:
|
||||
fenrirApp.cleanup_on_error()
|
||||
except Exception as cleanup_error:
|
||||
print(
|
||||
f"Error during cleanup: {cleanup_error}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
finally:
|
||||
if fenrirApp:
|
||||
del fenrirApp
|
||||
# Clean up PID file if it exists
|
||||
@@ -124,6 +128,10 @@ def run_fenrir():
|
||||
pass
|
||||
|
||||
|
||||
def should_run_foreground(cliArgs):
|
||||
return cliArgs.foreground or cliArgs.x11
|
||||
|
||||
|
||||
def main():
|
||||
global cliArgs
|
||||
argumentParser = create_argument_parser()
|
||||
@@ -135,7 +143,7 @@ def main():
|
||||
argumentParser.error(errorMsg)
|
||||
sys.exit(1)
|
||||
|
||||
if cliArgs.foreground or cliArgs.emulated_pty:
|
||||
if should_run_foreground(cliArgs):
|
||||
# Run directly in foreground
|
||||
run_fenrir()
|
||||
else:
|
||||
|
||||
@@ -22,7 +22,7 @@ class command:
|
||||
self.env["runtime"]["MemoryManager"].add_index_list(
|
||||
"clipboardHistory",
|
||||
self.env["runtime"]["SettingsManager"].get_setting_as_int(
|
||||
"general", "numberOfClipboards"
|
||||
"general", "number_of_clipboards"
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -36,11 +36,11 @@ class command:
|
||||
def update_spell_language(self):
|
||||
self.spellChecker = enchant.Dict(
|
||||
self.env["runtime"]["SettingsManager"].get_setting(
|
||||
"general", "spellCheckLanguage"
|
||||
"general", "spell_check_language"
|
||||
)
|
||||
)
|
||||
self.language = self.env["runtime"]["SettingsManager"].get_setting(
|
||||
"general", "spellCheckLanguage"
|
||||
"general", "spell_check_language"
|
||||
)
|
||||
|
||||
def run(self):
|
||||
@@ -48,7 +48,7 @@ class command:
|
||||
return
|
||||
if (
|
||||
self.env["runtime"]["SettingsManager"].get_setting(
|
||||
"general", "spellCheckLanguage"
|
||||
"general", "spell_check_language"
|
||||
)
|
||||
!= self.language
|
||||
):
|
||||
|
||||
@@ -24,9 +24,8 @@ class command:
|
||||
def run(self):
|
||||
try:
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
f"Fenrir screen reader version {
|
||||
fenrirVersion.version}-{
|
||||
fenrirVersion.code_name}",
|
||||
f"Fenrir screen reader version "
|
||||
f"{fenrirVersion.version}-{fenrirVersion.code_name}",
|
||||
interrupt=True,
|
||||
)
|
||||
except Exception as e:
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("Cycle through key echo modes: character, word, off")
|
||||
|
||||
def run(self):
|
||||
settings_manager = self.env["runtime"]["SettingsManager"]
|
||||
output_manager = self.env["runtime"]["OutputManager"]
|
||||
|
||||
# Get current settings
|
||||
char_echo_mode = settings_manager.get_setting("keyboard", "char_echo_mode")
|
||||
word_echo = settings_manager.get_setting_as_bool("keyboard", "word_echo")
|
||||
|
||||
# Determine current state and cycle to next
|
||||
# States: character (char=1, word=False) -> word (char=0, word=True) -> off (char=0, word=False)
|
||||
if char_echo_mode == "1" and not word_echo:
|
||||
# Currently character echo, switch to word echo
|
||||
settings_manager.set_setting("keyboard", "char_echo_mode", "0")
|
||||
settings_manager.set_setting("keyboard", "word_echo", "True")
|
||||
output_manager.present_text(
|
||||
_("Echo by word"), interrupt=True
|
||||
)
|
||||
elif word_echo:
|
||||
# Currently word echo, switch to off
|
||||
settings_manager.set_setting("keyboard", "char_echo_mode", "0")
|
||||
settings_manager.set_setting("keyboard", "word_echo", "False")
|
||||
output_manager.present_text(
|
||||
_("Echo off"), interrupt=True
|
||||
)
|
||||
else:
|
||||
# Currently off (or caps mode), switch to character echo
|
||||
settings_manager.set_setting("keyboard", "char_echo_mode", "1")
|
||||
settings_manager.set_setting("keyboard", "word_echo", "False")
|
||||
output_manager.present_text(
|
||||
_("Echo by character"), interrupt=True
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -59,7 +59,7 @@ class command:
|
||||
|
||||
def run(self):
|
||||
current_layout = self.env["runtime"]["SettingsManager"].get_setting(
|
||||
"keyboard", "keyboardLayout"
|
||||
"keyboard", "keyboard_layout"
|
||||
)
|
||||
|
||||
# Extract layout name from full path if needed
|
||||
@@ -83,7 +83,7 @@ class command:
|
||||
|
||||
# Update setting and reload shortcuts
|
||||
self.env["runtime"]["SettingsManager"].set_setting(
|
||||
"keyboard", "keyboardLayout", next_layout
|
||||
"keyboard", "keyboard_layout", next_layout
|
||||
)
|
||||
|
||||
# Reload shortcuts with new layout
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
import importlib.util
|
||||
import os
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
_base_path = os.path.join(os.path.dirname(__file__), "adjustment_base.py")
|
||||
_spec = importlib.util.spec_from_file_location("adjustment_base", _base_path)
|
||||
_module = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(_module)
|
||||
adjustment_command = _module.adjustment_command
|
||||
|
||||
|
||||
class command(adjustment_command):
|
||||
def __init__(self):
|
||||
super().__init__("alsa", "volume", "dec")
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("speak diff review key help")
|
||||
|
||||
def run(self):
|
||||
self.env["runtime"]["DiffReviewManager"].present_key_help()
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("move to next added diff line")
|
||||
|
||||
def run(self):
|
||||
self.env["runtime"]["DiffReviewManager"].next_added()
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("move to next character in diff line")
|
||||
|
||||
def run(self):
|
||||
self.env["runtime"]["DiffReviewManager"].next_char()
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("move to next diff file section")
|
||||
|
||||
def run(self):
|
||||
self.env["runtime"]["DiffReviewManager"].next_file_section()
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("move to next diff hunk")
|
||||
|
||||
def run(self):
|
||||
self.env["runtime"]["DiffReviewManager"].next_hunk()
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("move to next diff line")
|
||||
|
||||
def run(self):
|
||||
self.env["runtime"]["DiffReviewManager"].next_line()
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("move to next removed diff line")
|
||||
|
||||
def run(self):
|
||||
self.env["runtime"]["DiffReviewManager"].next_removed()
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("move to next word in diff line")
|
||||
|
||||
def run(self):
|
||||
self.env["runtime"]["DiffReviewManager"].next_word()
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("move to previous added diff line")
|
||||
|
||||
def run(self):
|
||||
self.env["runtime"]["DiffReviewManager"].prev_added()
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("move to previous character in diff line")
|
||||
|
||||
def run(self):
|
||||
self.env["runtime"]["DiffReviewManager"].prev_char()
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("move to previous diff file section")
|
||||
|
||||
def run(self):
|
||||
self.env["runtime"]["DiffReviewManager"].prev_file_section()
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("move to previous diff hunk")
|
||||
|
||||
def run(self):
|
||||
self.env["runtime"]["DiffReviewManager"].prev_hunk()
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("move to previous diff line")
|
||||
|
||||
def run(self):
|
||||
self.env["runtime"]["DiffReviewManager"].prev_line()
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("move to previous removed diff line")
|
||||
|
||||
def run(self):
|
||||
self.env["runtime"]["DiffReviewManager"].prev_removed()
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("move to previous word in diff line")
|
||||
|
||||
def run(self):
|
||||
self.env["runtime"]["DiffReviewManager"].prev_word()
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("speak diff summary")
|
||||
|
||||
def run(self):
|
||||
self.env["runtime"]["DiffReviewManager"].present_summary()
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("exit diff review mode")
|
||||
|
||||
def run(self):
|
||||
if not self.env["runtime"]["DiffReviewManager"].is_active():
|
||||
return
|
||||
self.env["runtime"]["DiffReviewManager"].disable_mode()
|
||||
self.env["runtime"]["DiffReviewManager"].present_mode_message(
|
||||
_("Diff review mode disabled."),
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -26,7 +26,7 @@ class command:
|
||||
def run(self):
|
||||
clipboard_file_path = self.env["runtime"][
|
||||
"SettingsManager"
|
||||
].get_setting("general", "clipboardExportPath")
|
||||
].get_setting("general", "clipboard_export_path")
|
||||
clipboard_file_path = clipboard_file_path.replace(
|
||||
"$user", self.env["general"]["curr_user"]
|
||||
)
|
||||
|
||||
@@ -22,7 +22,10 @@ class command:
|
||||
return _("sends the following keypress to the terminal or application")
|
||||
|
||||
def run(self):
|
||||
self.env["input"]["keyForeward"] = 3
|
||||
if self.env["runtime"]["InputManager"].no_key_pressed():
|
||||
self.env["input"]["key_forward"] = 1
|
||||
else:
|
||||
self.env["input"]["key_forward"] = -1
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("Forward next keypress"), interrupt=True
|
||||
)
|
||||
|
||||
@@ -26,7 +26,7 @@ class command:
|
||||
def run(self):
|
||||
clipboard_file_path = self.env["runtime"][
|
||||
"SettingsManager"
|
||||
].get_setting("general", "clipboardExportPath")
|
||||
].get_setting("general", "clipboard_export_path")
|
||||
clipboard_file_path = clipboard_file_path.replace(
|
||||
"$user", self.env["general"]["curr_user"]
|
||||
)
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
import importlib.util
|
||||
import os
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
_base_path = os.path.join(os.path.dirname(__file__), "adjustment_base.py")
|
||||
_spec = importlib.util.spec_from_file_location("adjustment_base", _base_path)
|
||||
_module = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(_module)
|
||||
adjustment_command = _module.adjustment_command
|
||||
|
||||
|
||||
class command(adjustment_command):
|
||||
def __init__(self):
|
||||
super().__init__("alsa", "volume", "inc")
|
||||
@@ -18,7 +18,7 @@ class command:
|
||||
self.env["runtime"]["MemoryManager"].add_index_list(
|
||||
"clipboardHistory",
|
||||
self.env["runtime"]["SettingsManager"].get_setting_as_int(
|
||||
"general", "numberOfClipboards"
|
||||
"general", "number_of_clipboards"
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -18,17 +18,17 @@ class command:
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
# Use commandBuffer like other commands
|
||||
if "progressMonitoring" not in self.env["commandBuffer"]:
|
||||
if "progress_monitoring" not in self.env["commandBuffer"]:
|
||||
# Check if progress monitoring should be enabled by default from
|
||||
# settings
|
||||
try:
|
||||
default_enabled = self.env["runtime"][
|
||||
"SettingsManager"
|
||||
].get_setting_as_bool("sound", "progressMonitoring")
|
||||
].get_setting_as_bool("sound", "progress_monitoring")
|
||||
except Exception as e:
|
||||
# If setting doesn't exist, default to False
|
||||
default_enabled = False
|
||||
self.env["commandBuffer"]["progressMonitoring"] = default_enabled
|
||||
self.env["commandBuffer"]["progress_monitoring"] = default_enabled
|
||||
self.env["commandBuffer"]["lastProgressTime"] = 0
|
||||
self.env["commandBuffer"]["lastProgressValue"] = -1
|
||||
|
||||
@@ -40,12 +40,12 @@ class command:
|
||||
|
||||
def run(self):
|
||||
# Check if commandBuffer exists
|
||||
if "progressMonitoring" not in self.env["commandBuffer"]:
|
||||
self.env["commandBuffer"]["progressMonitoring"] = False
|
||||
if "progress_monitoring" not in self.env["commandBuffer"]:
|
||||
self.env["commandBuffer"]["progress_monitoring"] = False
|
||||
self.env["commandBuffer"]["lastProgressTime"] = 0
|
||||
self.env["commandBuffer"]["lastProgressValue"] = -1
|
||||
|
||||
if self.env["commandBuffer"]["progressMonitoring"]:
|
||||
if self.env["commandBuffer"]["progress_monitoring"]:
|
||||
self.stop_progress_monitoring()
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("Progress monitoring disabled"), interrupt=True
|
||||
@@ -57,17 +57,17 @@ class command:
|
||||
)
|
||||
|
||||
def start_progress_monitoring(self):
|
||||
self.env["commandBuffer"]["progressMonitoring"] = True
|
||||
self.env["commandBuffer"]["progress_monitoring"] = True
|
||||
self.env["commandBuffer"]["lastProgressTime"] = time.time()
|
||||
self.env["commandBuffer"]["lastProgressValue"] = -1
|
||||
# Don't control speech - let user decide with silence_until_prompt
|
||||
|
||||
def stop_progress_monitoring(self):
|
||||
self.env["commandBuffer"]["progressMonitoring"] = False
|
||||
self.env["commandBuffer"]["progress_monitoring"] = False
|
||||
# Don't control speech - progress monitor is beep-only
|
||||
|
||||
def detect_progress(self, text):
|
||||
if not self.env["commandBuffer"]["progressMonitoring"]:
|
||||
if not self.env["commandBuffer"]["progress_monitoring"]:
|
||||
return
|
||||
|
||||
# Skip progress detection if current screen looks like a prompt
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("Read all text line by line from current position")
|
||||
|
||||
def run(self):
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
"Read-all functionality temporarily disabled",
|
||||
interrupt=True
|
||||
)
|
||||
return
|
||||
# Check if speechd is available for callbacks
|
||||
try:
|
||||
speech_driver = self.env['runtime']['SpeechDriver']
|
||||
if not (hasattr(speech_driver, '_sd') and speech_driver._sd):
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("Read all requires speech-dispatcher - not available with current speech driver"),
|
||||
interrupt=True
|
||||
)
|
||||
return
|
||||
except Exception as e:
|
||||
self.env["runtime"]["DebugManager"].write_debug_out(
|
||||
f"ReadAllByLine run: Error checking speech driver: {e}",
|
||||
debug.DebugLevel.ERROR
|
||||
)
|
||||
return
|
||||
|
||||
# Check if ReadAllManager is available
|
||||
if "ReadAllManager" not in self.env["runtime"]:
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("Read all manager not in runtime"),
|
||||
interrupt=True
|
||||
)
|
||||
return
|
||||
elif not self.env["runtime"]["ReadAllManager"]:
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("Read all manager is None"),
|
||||
interrupt=True
|
||||
)
|
||||
return
|
||||
|
||||
# Start continuous line-by-line reading
|
||||
if self.env["runtime"]["ReadAllManager"].is_active():
|
||||
# Stop if already active
|
||||
self.env["runtime"]["ReadAllManager"].stop_read_all()
|
||||
else:
|
||||
# Start line-by-line reading
|
||||
self.env["runtime"]["ReadAllManager"].start_read_all('line')
|
||||
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("Read all text page by page from current position")
|
||||
|
||||
def run(self):
|
||||
# Check if speechd is available for callbacks
|
||||
try:
|
||||
speech_driver = self.env['runtime']['SpeechDriver']
|
||||
if not (hasattr(speech_driver, '_sd') and speech_driver._sd):
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("Read all requires speech-dispatcher - not available with current speech driver"),
|
||||
interrupt=True
|
||||
)
|
||||
return
|
||||
except Exception as e:
|
||||
self.env["runtime"]["DebugManager"].write_debug_out(
|
||||
f"ReadAllByPage run: Error checking speech driver: {e}",
|
||||
debug.DebugLevel.ERROR
|
||||
)
|
||||
return
|
||||
|
||||
# Check if ReadAllManager is available
|
||||
if "ReadAllManager" not in self.env["runtime"]:
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("Read all manager not in runtime"),
|
||||
interrupt=True
|
||||
)
|
||||
return
|
||||
elif not self.env["runtime"]["ReadAllManager"]:
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("Read all manager is None"),
|
||||
interrupt=True
|
||||
)
|
||||
return
|
||||
|
||||
# Start continuous page-by-page reading
|
||||
if self.env["runtime"]["ReadAllManager"].is_active():
|
||||
# Stop if already active
|
||||
self.env["runtime"]["ReadAllManager"].stop_read_all()
|
||||
else:
|
||||
# Start page-by-page reading
|
||||
self.env["runtime"]["ReadAllManager"].start_read_all('page')
|
||||
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -36,11 +36,11 @@ class command:
|
||||
def update_spell_language(self):
|
||||
self.spellChecker = enchant.Dict(
|
||||
self.env["runtime"]["SettingsManager"].get_setting(
|
||||
"general", "spellCheckLanguage"
|
||||
"general", "spell_check_language"
|
||||
)
|
||||
)
|
||||
self.language = self.env["runtime"]["SettingsManager"].get_setting(
|
||||
"general", "spellCheckLanguage"
|
||||
"general", "spell_check_language"
|
||||
)
|
||||
|
||||
def run(self):
|
||||
@@ -51,7 +51,7 @@ class command:
|
||||
return
|
||||
if (
|
||||
self.env["runtime"]["SettingsManager"].get_setting(
|
||||
"general", "spellCheckLanguage"
|
||||
"general", "spell_check_language"
|
||||
)
|
||||
!= self.language
|
||||
):
|
||||
|
||||
@@ -22,10 +22,7 @@ class command:
|
||||
return _("Saves your current Fenrir settings so they are the default.")
|
||||
|
||||
def run(self):
|
||||
settings_file = self.env["runtime"][
|
||||
"SettingsManager"
|
||||
].get_settings_file()
|
||||
self.env["runtime"]["SettingsManager"].save_settings(settings_file)
|
||||
self.env["runtime"]["SettingsManager"].save_settings()
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("Settings saved."), interrupt=True
|
||||
)
|
||||
|
||||
@@ -22,8 +22,8 @@ class command:
|
||||
return _("Interrupts the current presentation")
|
||||
|
||||
def run(self):
|
||||
if len(self.env["input"]["prevDeepestInput"]) > len(
|
||||
self.env["input"]["currInput"]
|
||||
if len(self.env["input"]["prev_deepest_input"]) > len(
|
||||
self.env["input"]["curr_input"]
|
||||
):
|
||||
return
|
||||
self.env["runtime"]["OutputManager"].interrupt_output()
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("opens speech history")
|
||||
|
||||
def run(self):
|
||||
self.env["runtime"]["SpeechHistoryManager"].open_history()
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -36,11 +36,11 @@ class command:
|
||||
return
|
||||
self.spellChecker = enchant.Dict(
|
||||
self.env["runtime"]["SettingsManager"].get_setting(
|
||||
"general", "spellCheckLanguage"
|
||||
"general", "spell_check_language"
|
||||
)
|
||||
)
|
||||
self.language = self.env["runtime"]["SettingsManager"].get_setting(
|
||||
"general", "spellCheckLanguage"
|
||||
"general", "spell_check_language"
|
||||
)
|
||||
|
||||
def run(self):
|
||||
@@ -51,7 +51,7 @@ class command:
|
||||
return
|
||||
if (
|
||||
self.env["runtime"]["SettingsManager"].get_setting(
|
||||
"general", "spellCheckLanguage"
|
||||
"general", "spell_check_language"
|
||||
)
|
||||
!= self.language
|
||||
):
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
import _thread
|
||||
import os
|
||||
import subprocess
|
||||
from subprocess import PIPE
|
||||
from subprocess import Popen
|
||||
|
||||
@@ -53,10 +52,11 @@ class command:
|
||||
|
||||
def _thread_run(self):
|
||||
try:
|
||||
callstring = (
|
||||
self.script_path + " " + self.env["general"]["curr_user"]
|
||||
p = Popen(
|
||||
[self.script_path, self.env["general"]["curr_user"]],
|
||||
stdout=PIPE,
|
||||
stderr=PIPE,
|
||||
)
|
||||
p = Popen(callstring, stdout=PIPE, stderr=PIPE, shell=True)
|
||||
stdout, stderr = p.communicate()
|
||||
stdout = stdout.decode("utf-8")
|
||||
stderr = stderr.decode("utf-8")
|
||||
|
||||
@@ -25,15 +25,15 @@ class command:
|
||||
def run(self):
|
||||
self.env["runtime"]["SettingsManager"].set_setting(
|
||||
"general",
|
||||
"autoPresentIndent",
|
||||
"auto_present_indent",
|
||||
str(
|
||||
not self.env["runtime"]["SettingsManager"].get_setting_as_bool(
|
||||
"general", "autoPresentIndent"
|
||||
"general", "auto_present_indent"
|
||||
)
|
||||
),
|
||||
)
|
||||
if self.env["runtime"]["SettingsManager"].get_setting_as_bool(
|
||||
"general", "autoPresentIndent"
|
||||
"general", "auto_present_indent"
|
||||
):
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("autoindent enabled"), sound_icon="", interrupt=True
|
||||
|
||||
@@ -25,15 +25,15 @@ class command:
|
||||
def run(self):
|
||||
self.env["runtime"]["SettingsManager"].set_setting(
|
||||
"speech",
|
||||
"autoReadIncoming",
|
||||
"auto_read_incoming",
|
||||
str(
|
||||
not self.env["runtime"]["SettingsManager"].get_setting_as_bool(
|
||||
"speech", "autoReadIncoming"
|
||||
"speech", "auto_read_incoming"
|
||||
)
|
||||
),
|
||||
)
|
||||
if self.env["runtime"]["SettingsManager"].get_setting_as_bool(
|
||||
"speech", "autoReadIncoming"
|
||||
"speech", "auto_read_incoming"
|
||||
):
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("autoread enabled"), sound_icon="", interrupt=True
|
||||
|
||||
@@ -24,15 +24,15 @@ class command:
|
||||
def run(self):
|
||||
self.env["runtime"]["SettingsManager"].set_setting(
|
||||
"general",
|
||||
"autoSpellCheck",
|
||||
"auto_spell_check",
|
||||
str(
|
||||
not self.env["runtime"]["SettingsManager"].get_setting_as_bool(
|
||||
"general", "autoSpellCheck"
|
||||
"general", "auto_spell_check"
|
||||
)
|
||||
),
|
||||
)
|
||||
if self.env["runtime"]["SettingsManager"].get_setting_as_bool(
|
||||
"general", "autoSpellCheck"
|
||||
"general", "auto_spell_check"
|
||||
):
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("auto spellcheck enabled"), sound_icon="", interrupt=True
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("toggle diff review mode")
|
||||
|
||||
def run(self):
|
||||
self.env["runtime"]["DiffReviewManager"].toggle_mode()
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -25,7 +25,7 @@ class command:
|
||||
if self.env["runtime"]["PunctuationManager"].cycle_punctuation():
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
self.env["runtime"]["SettingsManager"].get_setting(
|
||||
"general", "punctuationLevel"
|
||||
"general", "punctuation_level"
|
||||
),
|
||||
interrupt=True,
|
||||
ignore_punctuation=True,
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return ""
|
||||
|
||||
def run(self):
|
||||
if not self.env["runtime"]["SettingsManager"].get_setting_as_bool(
|
||||
"keyboard", "interruptOnKeyPress"
|
||||
):
|
||||
return
|
||||
if self.env["runtime"]["InputManager"].no_key_pressed():
|
||||
return
|
||||
if self.env["runtime"]["ScreenManager"].is_screen_change():
|
||||
return
|
||||
if len(self.env["input"]["currInput"]) <= len(
|
||||
self.env["input"]["prevInput"]
|
||||
):
|
||||
return
|
||||
# if the filter is set
|
||||
if (
|
||||
self.env["runtime"]["SettingsManager"]
|
||||
.get_setting("keyboard", "interruptOnKeyPressFilter")
|
||||
.strip()
|
||||
!= ""
|
||||
):
|
||||
filter_list = (
|
||||
self.env["runtime"]["SettingsManager"]
|
||||
.get_setting("keyboard", "interruptOnKeyPressFilter")
|
||||
.split(",")
|
||||
)
|
||||
for currInput in self.env["input"]["currInput"]:
|
||||
if currInput not in filter_list:
|
||||
return
|
||||
self.env["runtime"]["OutputManager"].interrupt_output()
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -1,41 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("disables speech until next keypress")
|
||||
|
||||
def run(self):
|
||||
if not self.env["commandBuffer"]["enableSpeechOnKeypress"]:
|
||||
return
|
||||
self.env["runtime"]["SettingsManager"].set_setting(
|
||||
"speech",
|
||||
"enabled",
|
||||
str(self.env["commandBuffer"]["enableSpeechOnKeypress"]),
|
||||
)
|
||||
self.env["commandBuffer"]["enableSpeechOnKeypress"] = False
|
||||
# Also disable prompt watching since speech was manually re-enabled
|
||||
if "silenceUntilPrompt" in self.env["commandBuffer"]:
|
||||
self.env["commandBuffer"]["silenceUntilPrompt"] = False
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("speech enabled"), sound_icon="SpeechOn", interrupt=True
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -24,14 +24,14 @@ class command:
|
||||
def run(self):
|
||||
# enabled?
|
||||
active = self.env["runtime"]["SettingsManager"].get_setting_as_int(
|
||||
"keyboard", "charEchoMode"
|
||||
"keyboard", "char_echo_mode"
|
||||
)
|
||||
# 0 = off
|
||||
if active == 0:
|
||||
return
|
||||
# 2 = caps only
|
||||
if active == 2:
|
||||
if not self.env["input"]["newCapsLock"]:
|
||||
if not self.env["input"]["new_caps_lock"]:
|
||||
return
|
||||
# big changes are no char (but the value is bigger than one maybe the
|
||||
# differ needs longer than you can type, so a little strange random
|
||||
@@ -42,19 +42,10 @@ class command:
|
||||
)
|
||||
if x_move > 3:
|
||||
return
|
||||
if self.env["runtime"]["InputManager"].get_shortcut_type() in ["KEY"]:
|
||||
if self.env["runtime"][
|
||||
"InputManager"
|
||||
].get_last_deepest_input() in [["KEY_TAB"]]:
|
||||
return
|
||||
elif self.env["runtime"]["InputManager"].get_shortcut_type() in [
|
||||
"BYTE"
|
||||
]:
|
||||
if self.env["runtime"]["ByteManager"].get_last_byte_key() in [
|
||||
b" ",
|
||||
b"\t",
|
||||
]:
|
||||
return
|
||||
if self.env["runtime"][
|
||||
"InputManager"
|
||||
].get_last_deepest_input() in [["KEY_TAB"]]:
|
||||
return
|
||||
# detect deletion or chilling
|
||||
if (
|
||||
self.env["screen"]["new_cursor"]["x"]
|
||||
|
||||
@@ -26,7 +26,7 @@ class command:
|
||||
def run(self):
|
||||
# is it enabled?
|
||||
if not self.env["runtime"]["SettingsManager"].get_setting_as_bool(
|
||||
"keyboard", "wordEcho"
|
||||
"keyboard", "word_echo"
|
||||
):
|
||||
return
|
||||
# is navigation?
|
||||
|
||||
@@ -39,23 +39,23 @@ class command:
|
||||
return
|
||||
self.spellChecker = enchant.Dict(
|
||||
self.env["runtime"]["SettingsManager"].get_setting(
|
||||
"general", "spellCheckLanguage"
|
||||
"general", "spell_check_language"
|
||||
)
|
||||
)
|
||||
self.language = self.env["runtime"]["SettingsManager"].get_setting(
|
||||
"general", "spellCheckLanguage"
|
||||
"general", "spell_check_language"
|
||||
)
|
||||
|
||||
def run(self):
|
||||
if not initialized:
|
||||
return
|
||||
if not self.env["runtime"]["SettingsManager"].get_setting_as_bool(
|
||||
"general", "autoSpellCheck"
|
||||
"general", "auto_spell_check"
|
||||
):
|
||||
return
|
||||
if (
|
||||
self.env["runtime"]["SettingsManager"].get_setting(
|
||||
"general", "spellCheckLanguage"
|
||||
"general", "spell_check_language"
|
||||
)
|
||||
!= self.language
|
||||
):
|
||||
|
||||
@@ -23,7 +23,7 @@ class command:
|
||||
|
||||
def run(self):
|
||||
if not self.env["runtime"]["SettingsManager"].get_setting_as_bool(
|
||||
"keyboard", "charDeleteEcho"
|
||||
"keyboard", "char_delete_echo"
|
||||
):
|
||||
return
|
||||
# detect typing or chilling
|
||||
|
||||
+14
-8
@@ -46,7 +46,7 @@ class command:
|
||||
|
||||
# echo word insteed of char
|
||||
if self.env["runtime"]["SettingsManager"].get_setting_as_bool(
|
||||
"keyboard", "wordEcho"
|
||||
"keyboard", "word_echo"
|
||||
):
|
||||
if (
|
||||
abs(
|
||||
@@ -71,14 +71,20 @@ class command:
|
||||
self.env["screen"]["new_cursor"]["y"],
|
||||
self.env["screen"]["new_content_text"],
|
||||
)
|
||||
# Don't interrupt ongoing auto-read announcements
|
||||
do_interrupt = True
|
||||
if self.env["runtime"]["SettingsManager"].get_setting_as_bool(
|
||||
"speech", "auto_read_incoming"
|
||||
):
|
||||
do_interrupt = False
|
||||
|
||||
if curr_char.isspace():
|
||||
# Only announce spaces during pure navigation (arrow keys)
|
||||
# Check if this is really navigation by looking at input history
|
||||
if self.env["runtime"]["InputManager"].get_shortcut_type() in [
|
||||
"KEY"
|
||||
] and self.env["runtime"]["InputManager"].get_last_deepest_input()[
|
||||
0
|
||||
] in [
|
||||
last_input = self.env["runtime"][
|
||||
"InputManager"
|
||||
].get_last_deepest_input()
|
||||
if last_input and last_input[0] in [
|
||||
"KEY_LEFT",
|
||||
"KEY_RIGHT",
|
||||
"KEY_UP",
|
||||
@@ -87,14 +93,14 @@ class command:
|
||||
char_utils.present_char_for_review(
|
||||
self.env,
|
||||
curr_char,
|
||||
interrupt=True,
|
||||
interrupt=do_interrupt,
|
||||
announce_capital=True,
|
||||
flush=False,
|
||||
)
|
||||
else:
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
curr_char,
|
||||
interrupt=True,
|
||||
interrupt=do_interrupt,
|
||||
ignore_punctuation=True,
|
||||
announce_capital=True,
|
||||
flush=False,
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
from fenrirscreenreader.core.tabCompletionManager import TabCompletionManager
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
self.manager = TabCompletionManager()
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
self.manager.initialize(environment)
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("Announces tab completions on cursor movement")
|
||||
|
||||
def run(self):
|
||||
text = self.manager.process_update()
|
||||
if not text:
|
||||
return
|
||||
|
||||
do_interrupt = True
|
||||
if self.env["runtime"]["SettingsManager"].get_setting_as_bool(
|
||||
"speech", "auto_read_incoming"
|
||||
):
|
||||
do_interrupt = False
|
||||
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
text,
|
||||
interrupt=do_interrupt,
|
||||
announce_capital=True,
|
||||
flush=False,
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
import time
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("Announces large text insertions at the cursor")
|
||||
|
||||
def run(self):
|
||||
if self.env["runtime"]["ScreenManager"].is_screen_change():
|
||||
return
|
||||
if not self.env["runtime"]["ScreenManager"].is_delta():
|
||||
return
|
||||
|
||||
x_move = (
|
||||
self.env["screen"]["new_cursor"]["x"]
|
||||
- self.env["screen"]["old_cursor"]["x"]
|
||||
)
|
||||
if x_move < 5:
|
||||
return
|
||||
if self._is_recent_tab_input():
|
||||
return
|
||||
|
||||
delta_text = self.env["screen"]["new_delta"]
|
||||
if not self._matches_cursor_insert(x_move, delta_text):
|
||||
return
|
||||
|
||||
curr_delta = delta_text
|
||||
if (
|
||||
len(curr_delta.strip()) != len(curr_delta)
|
||||
and curr_delta.strip() != ""
|
||||
):
|
||||
curr_delta = curr_delta.strip()
|
||||
if not curr_delta:
|
||||
return
|
||||
|
||||
do_interrupt = True
|
||||
if self.env["runtime"]["SettingsManager"].get_setting_as_bool(
|
||||
"speech", "auto_read_incoming"
|
||||
):
|
||||
do_interrupt = False
|
||||
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
curr_delta,
|
||||
interrupt=do_interrupt,
|
||||
announce_capital=True,
|
||||
flush=False,
|
||||
)
|
||||
|
||||
def _is_recent_tab_input(self):
|
||||
input_manager = self.env["runtime"].get("InputManager")
|
||||
if not input_manager:
|
||||
return False
|
||||
if input_manager.get_last_deepest_input() in [["KEY_TAB"]]:
|
||||
return True
|
||||
|
||||
last_event = input_manager.get_last_event()
|
||||
if not last_event or last_event.get("event_name") != "KEY_TAB":
|
||||
return False
|
||||
try:
|
||||
return time.time() - input_manager.get_last_input_time() <= 0.5
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
def _matches_cursor_insert(self, x_move, delta_text):
|
||||
if not delta_text or "\n" in delta_text:
|
||||
return False
|
||||
|
||||
delta_len = len(delta_text)
|
||||
if x_move == delta_len:
|
||||
return True
|
||||
if abs(x_move - delta_len) <= 2:
|
||||
return True
|
||||
return delta_len > 10 and abs(x_move - delta_len) <= (delta_len * 0.2)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -1,68 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return "No Description found"
|
||||
|
||||
def run(self):
|
||||
# try to detect the tab completion by cursor change
|
||||
x_move = (
|
||||
self.env["screen"]["new_cursor"]["x"]
|
||||
- self.env["screen"]["old_cursor"]["x"]
|
||||
)
|
||||
if x_move <= 0:
|
||||
return
|
||||
if self.env["runtime"]["InputManager"].get_shortcut_type() in ["KEY"]:
|
||||
if not (
|
||||
self.env["runtime"]["InputManager"].get_last_deepest_input()
|
||||
in [["KEY_TAB"]]
|
||||
):
|
||||
if x_move < 5:
|
||||
return
|
||||
elif self.env["runtime"]["InputManager"].get_shortcut_type() in [
|
||||
"BYTE"
|
||||
]:
|
||||
found = False
|
||||
for currByte in self.env["runtime"][
|
||||
"ByteManager"
|
||||
].get_last_byte_key():
|
||||
if currByte == 9:
|
||||
found = True
|
||||
if not found:
|
||||
if x_move < 5:
|
||||
return
|
||||
# is there any change?
|
||||
if not self.env["runtime"]["ScreenManager"].is_delta():
|
||||
return
|
||||
if not x_move == len(self.env["screen"]["new_delta"]):
|
||||
return
|
||||
# filter unneded space on word begin
|
||||
curr_delta = self.env["screen"]["new_delta"]
|
||||
if (
|
||||
len(curr_delta.strip()) != len(curr_delta)
|
||||
and curr_delta.strip() != ""
|
||||
):
|
||||
curr_delta = curr_delta.strip()
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
curr_delta, interrupt=True, announce_capital=True, flush=False
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -66,8 +66,15 @@ class command:
|
||||
):
|
||||
return
|
||||
|
||||
# Don't interrupt ongoing auto-read announcements
|
||||
do_interrupt = True
|
||||
if self.env["runtime"]["SettingsManager"].get_setting_as_bool(
|
||||
"speech", "auto_read_incoming"
|
||||
):
|
||||
do_interrupt = False
|
||||
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
curr_word, interrupt=True, flush=False
|
||||
curr_word, interrupt=do_interrupt, flush=False
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
|
||||
+17
-10
@@ -30,8 +30,8 @@ class command:
|
||||
if self.env["runtime"]["ScreenManager"].is_screen_change():
|
||||
self.lastIdent = 0
|
||||
return
|
||||
# this leads to problems in vim -> status line change -> no
|
||||
# announcement, so we do check the lengh as hack
|
||||
# Don't announce cursor movements when auto-read is handling incoming text
|
||||
# This prevents interrupting ongoing auto-read announcements
|
||||
if self.env["runtime"]["ScreenManager"].is_delta():
|
||||
return
|
||||
|
||||
@@ -44,27 +44,34 @@ class command:
|
||||
self.env["screen"]["new_cursor"]["y"],
|
||||
self.env["screen"]["new_content_text"],
|
||||
)
|
||||
# Don't interrupt ongoing auto-read announcements with cursor movement
|
||||
do_interrupt = True
|
||||
if self.env["runtime"]["SettingsManager"].get_setting_as_bool(
|
||||
"speech", "auto_read_incoming"
|
||||
):
|
||||
do_interrupt = False
|
||||
|
||||
if curr_line.isspace():
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("blank"), sound_icon="EmptyLine", interrupt=True, flush=False
|
||||
_("blank"), sound_icon="EmptyLine", interrupt=do_interrupt, flush=False
|
||||
)
|
||||
else:
|
||||
# ident
|
||||
curr_ident = len(curr_line) - len(curr_line.lstrip())
|
||||
if self.lastIdent == -1:
|
||||
self.lastIdent = curr_ident
|
||||
do_interrupt = True
|
||||
if self.env["runtime"]["SettingsManager"].get_setting_as_bool(
|
||||
"general", "autoPresentIndent"
|
||||
"general", "auto_present_indent"
|
||||
):
|
||||
if self.env["runtime"]["SettingsManager"].get_setting_as_int(
|
||||
"general", "autoPresentIndentMode"
|
||||
"general", "auto_present_indent_mode"
|
||||
) in [0, 1]:
|
||||
self.env["runtime"]["OutputManager"].play_frequence(
|
||||
curr_ident * 50, 0.1, interrupt=do_interrupt
|
||||
)
|
||||
if self.lastIdent != curr_ident:
|
||||
self.env["runtime"]["OutputManager"].play_frequence(
|
||||
curr_ident * 50, 0.1, interrupt=do_interrupt
|
||||
)
|
||||
if self.env["runtime"]["SettingsManager"].get_setting_as_int(
|
||||
"general", "autoPresentIndentMode"
|
||||
"general", "auto_present_indent_mode"
|
||||
) in [0, 2]:
|
||||
if self.lastIdent != curr_ident:
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
|
||||
+37
-30
@@ -31,10 +31,9 @@ class command:
|
||||
self.lastIdent = 0
|
||||
return
|
||||
|
||||
# is a vertical change?
|
||||
if not self.env["runtime"][
|
||||
"CursorManager"
|
||||
].is_cursor_horizontal_move():
|
||||
# Skip if no cursor movement at all
|
||||
if (not self.env["runtime"]["CursorManager"].is_cursor_horizontal_move() and
|
||||
not self.env["runtime"]["CursorManager"].is_cursor_vertical_move()):
|
||||
return
|
||||
x, y, curr_line = line_utils.get_current_line(
|
||||
self.env["screen"]["new_cursor"]["x"],
|
||||
@@ -43,42 +42,50 @@ class command:
|
||||
)
|
||||
curr_ident = self.env["screen"]["new_cursor"]["x"]
|
||||
|
||||
if not curr_line.isspace():
|
||||
# ident
|
||||
lastIdent, lastY, last_line = line_utils.get_current_line(
|
||||
self.env["screen"]["new_cursor"]["x"],
|
||||
self.env["screen"]["new_cursor"]["y"],
|
||||
self.env["screen"]["old_content_text"],
|
||||
)
|
||||
if curr_line.strip() != last_line.strip():
|
||||
return
|
||||
if len(curr_line.lstrip()) == len(last_line.lstrip()):
|
||||
return
|
||||
if curr_line.isspace():
|
||||
# Don't beep for lines with only spaces - no meaningful indentation
|
||||
return
|
||||
|
||||
# Lines with actual content - calculate proper indentation
|
||||
lastIdent, lastY, last_line = line_utils.get_current_line(
|
||||
self.env["screen"]["new_cursor"]["x"],
|
||||
self.env["screen"]["new_cursor"]["y"],
|
||||
self.env["screen"]["old_content_text"],
|
||||
)
|
||||
if curr_line.strip() != last_line.strip():
|
||||
return
|
||||
if len(curr_line.lstrip()) == len(last_line.lstrip()):
|
||||
return
|
||||
|
||||
curr_ident = len(curr_line) - len(curr_line.lstrip())
|
||||
curr_ident = len(curr_line) - len(curr_line.lstrip())
|
||||
|
||||
if self.lastIdent == -1:
|
||||
self.lastIdent = curr_ident
|
||||
if curr_ident <= 0:
|
||||
return
|
||||
if curr_ident <= 0:
|
||||
return
|
||||
|
||||
# Initialize lastIdent if needed
|
||||
if self.lastIdent == -1:
|
||||
self.lastIdent = curr_ident
|
||||
|
||||
# Only beep/announce if indentation level has changed
|
||||
if self.env["runtime"]["SettingsManager"].get_setting_as_bool(
|
||||
"general", "autoPresentIndent"
|
||||
):
|
||||
"general", "auto_present_indent"
|
||||
) and self.lastIdent != curr_ident:
|
||||
if self.env["runtime"]["SettingsManager"].get_setting_as_int(
|
||||
"general", "autoPresentIndentMode"
|
||||
"general", "auto_present_indent_mode"
|
||||
) in [0, 1]:
|
||||
self.env["runtime"]["OutputManager"].play_frequence(
|
||||
curr_ident * 50, 0.1, interrupt=False
|
||||
)
|
||||
if self.env["runtime"]["SettingsManager"].get_setting_as_int(
|
||||
"general", "autoPresentIndentMode"
|
||||
"general", "autePresentIndentMode"
|
||||
) in [0, 2]:
|
||||
if self.lastIdent != curr_ident:
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("indented ") + str(curr_ident) + " ",
|
||||
interrupt=False,
|
||||
flush=False,
|
||||
)
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("indented ") + str(curr_ident) + " ",
|
||||
interrupt=False,
|
||||
flush=False,
|
||||
)
|
||||
|
||||
# Always update lastIdent for next comparison
|
||||
self.lastIdent = curr_ident
|
||||
|
||||
def set_callback(self, callback):
|
||||
|
||||
@@ -23,7 +23,7 @@ class command:
|
||||
|
||||
def run(self):
|
||||
if not self.env["runtime"]["SettingsManager"].get_setting_as_bool(
|
||||
"review", "leaveReviewOnCursorChange"
|
||||
"review", "leave_review_on_cursor_change"
|
||||
):
|
||||
return
|
||||
if self.env["runtime"]["CursorManager"].is_review_mode():
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
import time
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return ""
|
||||
|
||||
def run(self):
|
||||
if not self.env["runtime"]["SettingsManager"].get_setting_as_bool(
|
||||
"speech", "auto_read_incoming"
|
||||
):
|
||||
return
|
||||
|
||||
if "pendingPromptText" not in self.env["commandBuffer"]:
|
||||
return
|
||||
|
||||
pending_text = self.env["commandBuffer"]["pendingPromptText"]
|
||||
if not pending_text:
|
||||
return
|
||||
|
||||
pending_time = self.env["commandBuffer"].get("pendingPromptTime", 0)
|
||||
delay = self.env["runtime"]["SettingsManager"].get_setting_as_float(
|
||||
"speech", "batch_flush_interval"
|
||||
)
|
||||
if time.time() - pending_time < delay:
|
||||
return
|
||||
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
pending_text, interrupt=False, flush=False
|
||||
)
|
||||
self.env["commandBuffer"]["pendingPromptText"] = ""
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -5,11 +5,17 @@
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
import datetime
|
||||
import fcntl
|
||||
import os
|
||||
import tempfile
|
||||
import time
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
|
||||
|
||||
ANNOUNCEMENT_LOCK_TIMEOUT_SEC = 5.0
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
@@ -26,6 +32,49 @@ class command:
|
||||
def get_description(self):
|
||||
return "No Description found"
|
||||
|
||||
def _get_announcement_lock_path(self):
|
||||
return os.path.join(
|
||||
tempfile.gettempdir(),
|
||||
"fenrirscreenreader-time-announcement.lock",
|
||||
)
|
||||
|
||||
def _read_announcement_lock_slot(self, lock_file):
|
||||
lock_file.seek(0)
|
||||
lock_content = lock_file.readline().strip().split()
|
||||
if len(lock_content) < 2:
|
||||
return ""
|
||||
return lock_content[1]
|
||||
|
||||
def _claim_announcement_lock(self, announcement_slot):
|
||||
now = time.time()
|
||||
lock_path = self._get_announcement_lock_path()
|
||||
try:
|
||||
lock_fd = os.open(lock_path, os.O_CREAT | os.O_RDWR, 0o666)
|
||||
except OSError:
|
||||
return False
|
||||
try:
|
||||
os.chmod(lock_path, 0o666)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
with os.fdopen(lock_fd, "r+", encoding="utf-8") as lock_file:
|
||||
try:
|
||||
fcntl.flock(lock_file.fileno(), fcntl.LOCK_EX)
|
||||
lock_slot = self._read_announcement_lock_slot(lock_file)
|
||||
lock_stat = os.fstat(lock_file.fileno())
|
||||
|
||||
if lock_slot == announcement_slot:
|
||||
return False
|
||||
|
||||
lock_file.seek(0)
|
||||
lock_file.truncate()
|
||||
lock_file.write(f"{os.getpid()} {announcement_slot} {now}\n")
|
||||
lock_file.flush()
|
||||
os.fsync(lock_file.fileno())
|
||||
return True
|
||||
finally:
|
||||
fcntl.flock(lock_file.fileno(), fcntl.LOCK_UN)
|
||||
|
||||
def run(self):
|
||||
if not self.env["runtime"]["SettingsManager"].get_setting_as_bool(
|
||||
"time", "enabled"
|
||||
@@ -50,6 +99,7 @@ class command:
|
||||
if delay_sec > 0:
|
||||
if int((now - self.last_time).total_seconds()) < delay_sec:
|
||||
return
|
||||
announcement_slot = f"delay:{int(now.timestamp()) // delay_sec}"
|
||||
else:
|
||||
# should announce?
|
||||
if not str(now.minute).zfill(2) in on_minutes:
|
||||
@@ -58,6 +108,7 @@ class command:
|
||||
if now.hour == self.last_time.hour:
|
||||
if now.minute == self.last_time.minute:
|
||||
return
|
||||
announcement_slot = f"minute:{datetime.datetime.strftime(now, '%Y%m%d%H%M')}"
|
||||
|
||||
date_format = self.env["runtime"]["SettingsManager"].get_setting(
|
||||
"general", "date_format"
|
||||
@@ -78,6 +129,10 @@ class command:
|
||||
if not (present_date or present_time):
|
||||
return
|
||||
|
||||
if not self._claim_announcement_lock(announcement_slot):
|
||||
self.last_time = now
|
||||
return
|
||||
|
||||
time_format = self.env["runtime"]["SettingsManager"].get_setting(
|
||||
"general", "time_format"
|
||||
)
|
||||
|
||||
@@ -22,33 +22,33 @@ class command:
|
||||
|
||||
def run(self):
|
||||
if not self.env["runtime"]["SettingsManager"].get_setting_as_bool(
|
||||
"keyboard", "interruptOnKeyPress"
|
||||
"keyboard", "interrupt_on_key_press"
|
||||
):
|
||||
return
|
||||
if self.env["runtime"]["InputManager"].no_key_pressed():
|
||||
return
|
||||
if self.env["runtime"]["ScreenManager"].is_screen_change():
|
||||
return
|
||||
if len(self.env["input"]["currInput"]) <= len(
|
||||
self.env["input"]["prevInput"]
|
||||
if len(self.env["input"]["curr_input"]) <= len(
|
||||
self.env["input"]["prev_input"]
|
||||
):
|
||||
return
|
||||
# if the filter is set
|
||||
if (
|
||||
self.env["runtime"]["SettingsManager"]
|
||||
.get_setting("keyboard", "interruptOnKeyPressFilter")
|
||||
.get_setting("keyboard", "interrupt_on_key_press_filter")
|
||||
.strip()
|
||||
!= ""
|
||||
):
|
||||
filter_list = (
|
||||
self.env["runtime"]["SettingsManager"]
|
||||
.get_setting("keyboard", "interruptOnKeyPressFilter")
|
||||
.get_setting("keyboard", "interrupt_on_key_press_filter")
|
||||
.split(",")
|
||||
)
|
||||
for currInput in self.env["input"]["currInput"]:
|
||||
if currInput not in filter_list:
|
||||
for curr_key in self.env["input"]["curr_input"]:
|
||||
if curr_key not in filter_list:
|
||||
return
|
||||
self.env["runtime"]["OutputManager"].interrupt_output()
|
||||
self.env["runtime"]["OutputManager"].interrupt_output_async()
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
@@ -24,7 +24,7 @@ class command:
|
||||
def run(self):
|
||||
if self.env["runtime"]["InputManager"].no_key_pressed():
|
||||
return
|
||||
if len(self.env["input"]["prevInput"]) > 0:
|
||||
if len(self.env["input"]["prev_input"]) > 0:
|
||||
return
|
||||
if not self.env["commandBuffer"]["enableSpeechOnKeypress"]:
|
||||
return
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
from fenrirscreenreader.core.tabCompletionManager import TabCompletionManager
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
self.manager = TabCompletionManager()
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
self.manager.initialize(environment)
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _("Tracks tab keypresses for completion announcements")
|
||||
|
||||
def run(self):
|
||||
self.manager.capture_if_tab()
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -23,11 +23,16 @@ class command:
|
||||
|
||||
def run(self):
|
||||
if (
|
||||
self.env["input"]["oldCapsLock"]
|
||||
== self.env["input"]["newCapsLock"]
|
||||
self.env["input"]["old_caps_lock"]
|
||||
== self.env["input"]["new_caps_lock"]
|
||||
):
|
||||
return
|
||||
if self.env["input"]["newCapsLock"]:
|
||||
current_input = self.env["input"]["curr_input"]
|
||||
previous_input = self.env["input"]["prev_input"]
|
||||
relevant_input = current_input or previous_input
|
||||
if "KEY_CAPSLOCK" not in relevant_input:
|
||||
return
|
||||
if self.env["input"]["new_caps_lock"]:
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("Capslock on"), interrupt=True
|
||||
)
|
||||
|
||||
@@ -23,11 +23,16 @@ class command:
|
||||
|
||||
def run(self):
|
||||
if (
|
||||
self.env["input"]["oldScrollLock"]
|
||||
== self.env["input"]["newScrollLock"]
|
||||
self.env["input"]["old_scroll_lock"]
|
||||
== self.env["input"]["new_scroll_lock"]
|
||||
):
|
||||
return
|
||||
if self.env["input"]["newScrollLock"]:
|
||||
current_input = self.env["input"]["curr_input"]
|
||||
previous_input = self.env["input"]["prev_input"]
|
||||
relevant_input = current_input or previous_input
|
||||
if "KEY_SCROLLLOCK" not in relevant_input:
|
||||
return
|
||||
if self.env["input"]["new_scroll_lock"]:
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("Scrolllock on"), interrupt=True
|
||||
)
|
||||
|
||||
@@ -22,16 +22,38 @@ class command:
|
||||
return "No description found"
|
||||
|
||||
def run(self):
|
||||
if self.env["input"]["oldNumLock"] == self.env["input"]["newNumLock"]:
|
||||
if self.env["input"]["old_num_lock"] == self.env["input"]["new_num_lock"]:
|
||||
return
|
||||
if self.env["input"]["newNumLock"]:
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("Numlock on"), interrupt=True
|
||||
)
|
||||
else:
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("Numlock off"), interrupt=True
|
||||
|
||||
# Only announce numlock changes if an actual numlock key was pressed
|
||||
# AND the LED state actually changed (some numpads send spurious NUMLOCK events)
|
||||
current_input = self.env["input"]["curr_input"]
|
||||
previous_input = self.env["input"]["prev_input"]
|
||||
relevant_input = current_input or previous_input
|
||||
|
||||
# Check if this is a genuine numlock key press by verifying:
|
||||
# 1. KEY_NUMLOCK is in the current input sequence
|
||||
# 2. The LED state has actually changed
|
||||
# 3. This isn't just a side effect from a KP_ key (which some buggy numpads do)
|
||||
is_genuine_numlock = (
|
||||
relevant_input and
|
||||
"KEY_NUMLOCK" in relevant_input and
|
||||
not any(
|
||||
key.startswith("KEY_KP")
|
||||
for key in relevant_input
|
||||
if isinstance(key, str)
|
||||
)
|
||||
)
|
||||
|
||||
if is_genuine_numlock:
|
||||
if self.env["input"]["new_num_lock"]:
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("Numlock on"), interrupt=True
|
||||
)
|
||||
else:
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
_("Numlock off"), interrupt=True
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
@@ -23,7 +23,7 @@ class command:
|
||||
|
||||
def run(self):
|
||||
if not self.env["runtime"]["SettingsManager"].get_setting_as_bool(
|
||||
"review", "leaveReviewOnScreenChange"
|
||||
"review", "leave_review_on_screen_change"
|
||||
):
|
||||
return
|
||||
self.env["runtime"]["CursorManager"].clear_review_cursor()
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
from fenrirscreenreader.core.i18n import _
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
|
||||
class command:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return _(
|
||||
"TUI focus mode handler - suppresses screen update spam "
|
||||
"for interactive TUI applications"
|
||||
)
|
||||
|
||||
def run(self):
|
||||
# Check if TUI mode is enabled
|
||||
if not self.env["runtime"]["SettingsManager"].get_setting_as_bool(
|
||||
"focus", "tui"
|
||||
):
|
||||
return
|
||||
|
||||
# TUI mode is active - set suppression flag for incoming handler
|
||||
# This prevents the 70000-incoming.py command from announcing
|
||||
# screen updates
|
||||
self.env["commandBuffer"]["tuiSuppressIncoming"] = True
|
||||
|
||||
self.env["runtime"]["DebugManager"].write_debug_out(
|
||||
"tui_focus_handler: TUI mode active, suppressing incoming text",
|
||||
debug.DebugLevel.INFO
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
@@ -41,20 +41,11 @@ class command:
|
||||
== self.env["runtime"]["ScreenManager"].get_rows() - 1
|
||||
):
|
||||
return
|
||||
if self.env["runtime"]["InputManager"].get_shortcut_type() in ["KEY"]:
|
||||
if not (
|
||||
self.env["runtime"]["InputManager"].get_last_deepest_input()
|
||||
in [["KEY_UP"], ["KEY_DOWN"]]
|
||||
):
|
||||
return
|
||||
elif self.env["runtime"]["InputManager"].get_shortcut_type() in [
|
||||
"BYTE"
|
||||
]:
|
||||
if not (
|
||||
self.env["runtime"]["ByteManager"].get_last_byte_key()
|
||||
in [b"^[[A", b"^[[B"]
|
||||
):
|
||||
return
|
||||
if not (
|
||||
self.env["runtime"]["InputManager"].get_last_deepest_input()
|
||||
in [["KEY_UP"], ["KEY_DOWN"]]
|
||||
):
|
||||
return
|
||||
|
||||
# Get the current cursor's line from both old and new content
|
||||
prev_line = self.env["screen"]["old_content_text"].split("\n")[
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user