More work on sockets attempt to get socket command to standard daemon.sock to a running instance. Also, fixed a long standing misspelling in daemon, was deamon, so if your scripts that self-voice or whatever with fenrir no longer work, this is why, please update scripts to the new, correct, daemon.sock.

This commit is contained in:
Storm Dragon
2026-05-20 20:11:21 -04:00
parent 8467bd74c3
commit 4caef89f6b
10 changed files with 461 additions and 96 deletions
+3 -3
View File
@@ -88,12 +88,12 @@ Application-specific menus in `vmenu-profiles/KEY/{app}/`:
## Remote Control
Unix socket: `/tmp/fenrirscreenreader-deamon.sock`
Unix socket: `/tmp/fenrirscreenreader-daemon.sock`
TCP: localhost:22447
```bash
echo "command say Hello" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
echo "ls" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
echo "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
```
+40 -37
View File
@@ -281,7 +281,7 @@ enable_command_remote=True # allow command execution
### Remote Drivers
1. **unixDriver** (recommended): Uses Unix domain sockets
- Socket location: `/tmp/fenrirscreenreader-deamon.sock` for the standard control socket
- 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`
@@ -298,99 +298,102 @@ 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-deamon.sock
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. Untargeted commands sent through a
shared or broadcast path are claimed by one instance so duplicate instances do
not all perform the same action.
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#punctuation_level=all" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
echo "setting set general#punctuation_level=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#char_echo_mode=1" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
echo "setting set keyboard#word_echo=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#ignore_screen=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#punctuation_level=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
@@ -590,7 +593,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
@@ -651,7 +654,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
@@ -675,7 +678,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
@@ -698,7 +701,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:
@@ -731,7 +734,7 @@ send_fenrir_command("setting set speech#rate=0.9")
**Commands not working:**
- 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`
- Test with simple command: `echo "command interrupt" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock`
## Command Line Options
+16 -13
View File
@@ -321,58 +321,61 @@ enable_command_remote=True
.B Instance Discovery:
.EX
# List registered Fenrir instances and their socket paths
echo "ls" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
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.
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#punctuation_level=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#punctuation_level=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
+17 -14
View File
@@ -1278,65 +1278,68 @@ The `+socat+` command provides the easiest way to send commands to Fenrir:
....
# List registered Fenrir instances and their socket paths
echo "ls" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
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.
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#punctuation_level=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#punctuation_level=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
+23 -21
View File
@@ -143,68 +143,70 @@ enable_command_remote=True # allow command execution
#### Instance Discovery
```bash
# List registered Fenrir instances and their socket paths
echo "ls" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
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.
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#punctuation_level=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#punctuation_level=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
@@ -240,7 +242,7 @@ echo "command quitapplication" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-dea
#### 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
@@ -253,7 +255,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:
+1 -1
View File
@@ -485,7 +485,7 @@ class FenrirManager:
os.unlink(pid_socket_file)
# Clean up main socket only if it is stale (not active)
main_socket_file = "/tmp/fenrirscreenreader-deamon.sock"
main_socket_file = "/tmp/fenrirscreenreader-daemon.sock"
if os.path.exists(main_socket_file):
try:
test_sock = socket.socket(
@@ -8,6 +8,7 @@ import os
import os.path
import select
import socket
import struct
import time
from fenrirscreenreader.core import debug
@@ -16,7 +17,7 @@ from fenrirscreenreader.core.eventData import FenrirEventType
from fenrirscreenreader.core.remoteDriver import RemoteDriver as remoteDriver
MAIN_SOCKET_FILE = "/tmp/fenrirscreenreader-deamon.sock"
MAIN_SOCKET_FILE = "/tmp/fenrirscreenreader-daemon.sock"
class driver(remoteDriver):
@@ -132,6 +133,131 @@ class driver(remoteDriver):
return False
return False
def _socket_file_for_socket(self, fenrir_sock):
for bound_sock, socket_file in self.bound_sockets:
if bound_sock == fenrir_sock:
return socket_file
return ""
def _get_peer_pid(self, client_sock):
so_peercred = getattr(socket, "SO_PEERCRED", 17)
try:
creds = client_sock.getsockopt(
socket.SOL_SOCKET, so_peercred, struct.calcsize("3i")
)
pid, _uid, _gid = struct.unpack("3i", creds)
return pid
except OSError:
return 0
def _get_parent_pid(self, pid):
try:
with open(f"/proc/{pid}/stat", "r", encoding="utf-8") as proc_file:
stat_text = proc_file.read()
except OSError:
return 0
end_command = stat_text.rfind(")")
if end_command == -1:
return 0
stat_fields = stat_text[end_command + 2 :].split()
if len(stat_fields) < 2:
return 0
try:
return int(stat_fields[1])
except ValueError:
return 0
def _find_ancestor_private_socket(self, pid):
seen_pids = set()
while pid > 1 and pid not in seen_pids:
seen_pids.add(pid)
socket_file = f"/tmp/fenrirscreenreader-{pid}.sock"
if self._is_registered_private_socket(socket_file):
return socket_file
pid = self._get_parent_pid(pid)
return ""
def _is_registered_private_socket(self, socket_file):
for instance in remoteInstanceRegistry.list_instances():
if socket_file in instance.get("socket_files", []):
return True
return False
def _get_registered_private_sockets(self):
socket_files = []
for instance in remoteInstanceRegistry.list_instances():
for socket_file in instance.get("socket_files", []):
if socket_file == MAIN_SOCKET_FILE:
continue
if socket_file in socket_files:
continue
socket_files.append(socket_file)
return socket_files
def _find_available_private_socket(self, preferred_socket=""):
socket_files = self._get_registered_private_sockets()
if preferred_socket and preferred_socket in socket_files:
socket_files.remove(preferred_socket)
socket_files.insert(0, preferred_socket)
for socket_file in socket_files:
if self._is_own_socket_file(socket_file):
return socket_file
if self._is_socket_active(socket_file):
return socket_file
return ""
def _is_own_socket_file(self, socket_file):
return any(
socket_file == bound_socket_file
for _bound_sock, bound_socket_file in self.bound_sockets
)
def _has_own_private_socket(self):
return any(
bound_socket_file != MAIN_SOCKET_FILE
for _bound_sock, bound_socket_file in self.bound_sockets
)
def _forward_remote_to_socket(self, data, socket_file):
forward_sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
try:
forward_sock.settimeout(0.2)
forward_sock.connect(socket_file)
forward_sock.sendall((data + "\n").encode("utf-8"))
return True
except OSError as e:
self.env["runtime"]["DebugManager"].write_debug_out(
"unixDriver watch_dog: Error forwarding remote data to "
+ socket_file
+ ": "
+ str(e),
debug.DebugLevel.ERROR,
)
return False
finally:
forward_sock.close()
def _route_main_socket_command(self, data, client_sock, socket_file):
if socket_file != MAIN_SOCKET_FILE:
return False
if not self._has_own_private_socket():
return False
peer_pid = self._get_peer_pid(client_sock)
ancestor_socket = ""
if peer_pid > 1:
ancestor_socket = self._find_ancestor_private_socket(peer_pid)
target_socket = self._find_available_private_socket(ancestor_socket)
if not target_socket:
return False
if self._is_own_socket_file(target_socket):
return False
return self._forward_remote_to_socket(data, target_socket)
def _cleanup(self):
for fenrir_sock in self.fenrirSocks:
try:
@@ -152,7 +278,7 @@ class driver(remoteDriver):
self.bound_sockets = []
remoteInstanceRegistry.remove_instance()
def _handle_client(self, client_sock, event_queue):
def _handle_client(self, client_sock, event_queue, socket_file=""):
try:
rawdata = client_sock.recv(8129)
except Exception as e:
@@ -173,6 +299,9 @@ class driver(remoteDriver):
client_sock.sendall((response["message"] + "\n").encode("utf-8"))
return
if self._route_main_socket_command(data, client_sock, socket_file):
return
event_queue.put(
{
"Type": FenrirEventType.remote_incomming,
@@ -188,7 +317,7 @@ class driver(remoteDriver):
def watch_dog(self, active, event_queue):
# echo "command say this is a test" | socat -
# UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
# UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
for socket_file, optional in self._get_socket_candidates():
fenrir_sock = self._bind_socket(socket_file, optional)
if fenrir_sock is None:
@@ -215,10 +344,11 @@ class driver(remoteDriver):
continue
for fenrir_sock in r:
client_sock, client_addr = fenrir_sock.accept()
socket_file = self._socket_file_for_socket(fenrir_sock)
# Ensure client socket is always closed to prevent resource
# leaks
try:
self._handle_client(client_sock, event_queue)
self._handle_client(client_sock, event_queue, socket_file)
finally:
# Always close client socket, even if data processing fails
try:
+1 -1
View File
@@ -232,7 +232,7 @@ class TestRemoteDataFormat:
"x11_window_id": "0x123",
"socket_files": [
"/tmp/fenrirscreenreader-123.sock",
"/tmp/fenrirscreenreader-deamon.sock",
"/tmp/fenrirscreenreader-daemon.sock",
],
}
],
+223
View File
@@ -0,0 +1,223 @@
from unittest.mock import Mock, mock_open, patch
from fenrirscreenreader.remoteDriver import unixDriver
class FakeClientSocket:
def __init__(self, data):
self.data = data
self.sent = b""
def recv(self, _size):
return self.data
def sendall(self, data):
self.sent += data
def test_main_socket_routes_to_ancestor_private_socket(mock_environment):
driver = unixDriver.driver()
driver.env = mock_environment
driver.bound_sockets = [
(Mock(), "/tmp/fenrirscreenreader-999.sock"),
(Mock(), unixDriver.MAIN_SOCKET_FILE),
]
client_sock = FakeClientSocket(b"command say routed")
event_queue = Mock()
with patch.object(driver, "_get_peer_pid", return_value=1234), patch.object(
driver,
"_find_ancestor_private_socket",
return_value="/tmp/fenrirscreenreader-222.sock",
), patch.object(
driver,
"_find_available_private_socket",
return_value="/tmp/fenrirscreenreader-222.sock",
), patch.object(
driver, "_forward_remote_to_socket", return_value=True
) as forward:
driver._handle_client(
client_sock, event_queue, unixDriver.MAIN_SOCKET_FILE
)
forward.assert_called_once_with(
"command say routed", "/tmp/fenrirscreenreader-222.sock"
)
event_queue.put.assert_not_called()
def test_main_socket_routes_to_first_available_private_socket(
mock_environment,
):
driver = unixDriver.driver()
driver.env = mock_environment
driver.bound_sockets = [
(Mock(), "/tmp/fenrirscreenreader-999.sock"),
(Mock(), unixDriver.MAIN_SOCKET_FILE),
]
client_sock = FakeClientSocket(b"command say fallback")
event_queue = Mock()
with patch.object(driver, "_get_peer_pid", return_value=1234), patch.object(
driver,
"_find_ancestor_private_socket",
return_value="",
), patch.object(
driver,
"_find_available_private_socket",
return_value="/tmp/fenrirscreenreader-333.sock",
), patch.object(
driver, "_forward_remote_to_socket", return_value=True
) as forward:
driver._handle_client(
client_sock, event_queue, unixDriver.MAIN_SOCKET_FILE
)
forward.assert_called_once_with(
"command say fallback", "/tmp/fenrirscreenreader-333.sock"
)
event_queue.put.assert_not_called()
def test_main_socket_handles_command_locally_without_available_target(
mock_environment,
):
driver = unixDriver.driver()
driver.env = mock_environment
client_sock = FakeClientSocket(b"command say local")
event_queue = Mock()
with patch.object(driver, "_get_peer_pid", return_value=1234), patch.object(
driver,
"_find_available_private_socket",
return_value="",
):
driver._handle_client(
client_sock, event_queue, unixDriver.MAIN_SOCKET_FILE
)
event_queue.put.assert_called_once_with(
{
"Type": unixDriver.FenrirEventType.remote_incomming,
"data": "command say local",
}
)
def test_vcsa_main_socket_owner_handles_command_locally(mock_environment):
driver = unixDriver.driver()
driver.env = mock_environment
driver.bound_sockets = [(Mock(), unixDriver.MAIN_SOCKET_FILE)]
client_sock = FakeClientSocket(b"command say root")
event_queue = Mock()
with patch.object(driver, "_find_available_private_socket") as find_available:
driver._handle_client(
client_sock, event_queue, unixDriver.MAIN_SOCKET_FILE
)
find_available.assert_not_called()
event_queue.put.assert_called_once_with(
{
"Type": unixDriver.FenrirEventType.remote_incomming,
"data": "command say root",
}
)
def test_private_socket_handles_command_locally(mock_environment):
driver = unixDriver.driver()
driver.env = mock_environment
client_sock = FakeClientSocket(b"command say private")
event_queue = Mock()
driver._handle_client(
client_sock, event_queue, "/tmp/fenrirscreenreader-222.sock"
)
event_queue.put.assert_called_once_with(
{
"Type": unixDriver.FenrirEventType.remote_incomming,
"data": "command say private",
}
)
def test_list_command_still_returns_response_from_main_socket(mock_environment):
driver = unixDriver.driver()
driver.env = mock_environment
mock_environment["runtime"]["RemoteManager"] = Mock()
client_sock = FakeClientSocket(b"command list")
event_queue = Mock()
mock_environment["runtime"][
"RemoteManager"
].handle_remote_incomming_with_response.return_value = {
"success": True,
"message": "pid=1",
}
driver._handle_client(client_sock, event_queue, unixDriver.MAIN_SOCKET_FILE)
assert client_sock.sent == b"pid=1\n"
event_queue.put.assert_not_called()
def test_get_parent_pid_parses_process_names_with_spaces():
driver = unixDriver.driver()
stat_file = mock_open(
read_data="1234 (name with spaces) S 567 1 1 0 -1 0\n"
)
with patch("builtins.open", stat_file):
assert driver._get_parent_pid(1234) == 567
def test_find_available_private_socket_prefers_ancestor_socket(
mock_environment,
):
driver = unixDriver.driver()
driver.env = mock_environment
with patch(
"fenrirscreenreader.remoteDriver.unixDriver.remoteInstanceRegistry.list_instances",
return_value=[
{
"pid": 111,
"socket_files": ["/tmp/fenrirscreenreader-111.sock"],
},
{
"pid": 222,
"socket_files": ["/tmp/fenrirscreenreader-222.sock"],
},
],
), patch.object(driver, "_is_socket_active", return_value=True):
assert (
driver._find_available_private_socket(
"/tmp/fenrirscreenreader-222.sock"
)
== "/tmp/fenrirscreenreader-222.sock"
)
def test_find_available_private_socket_skips_main_socket(
mock_environment,
):
driver = unixDriver.driver()
driver.env = mock_environment
with patch(
"fenrirscreenreader.remoteDriver.unixDriver.remoteInstanceRegistry.list_instances",
return_value=[
{
"pid": 111,
"socket_files": [
unixDriver.MAIN_SOCKET_FILE,
"/tmp/fenrirscreenreader-111.sock",
],
}
],
), patch.object(driver, "_is_socket_active", return_value=True):
assert (
driver._find_available_private_socket()
== "/tmp/fenrirscreenreader-111.sock"
)
+3 -2
View File
@@ -1,8 +1,9 @@
#!/bin/bash
# shellcheck disable=SC2329
cleanup() {
# Make sure Fenrir is restored on exit of this script
echo -n "setting set screen#suspendingScreen=" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
echo -n "setting set screen#suspendingScreen=" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
}
# Call the cleanup function on exit of this script
@@ -20,7 +21,7 @@ if ! [[ "$term" =~ ^[1-9]+$ ]]; then
fi
# Suspend the current terminal for Fenrir
echo -n "setting set screen#suspendingScreen=$term" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
echo -n "setting set screen#suspendingScreen=$term" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-daemon.sock
# Start the x session
command startx