Compare commits
31 Commits
af857d7976
...
2024.12.10
| Author | SHA1 | Date | |
|---|---|---|---|
| 8ef3d2856b | |||
| 8f28ee360a | |||
| 8782d53d03 | |||
| 7d276c95ea | |||
| d70073274b | |||
| f6d3baebc1 | |||
| 5a59ef6325 | |||
| baa4c9a937 | |||
| 3757a1ceeb | |||
| 1696d62526 | |||
| 84514edc96 | |||
| 0e787c21ab | |||
| 9cdf80b313 | |||
| 24e82936a9 | |||
| 0f932fb93a | |||
| 4c9e0bfd36 | |||
| 353f9d3676 | |||
| 064172648f | |||
| 95170e7d39 | |||
| a93df78ffc | |||
| 9758c072b5 | |||
| 4054cb2732 | |||
| e3a9937778 | |||
| ee7baf5314 | |||
| 8e4cbc2fd5 | |||
| 5904c9cf6c | |||
| 5249f13be9 | |||
| 1d91c62c67 | |||
| bc72765544 | |||
| b54a226833 | |||
| 295167c865 |
@@ -5,7 +5,7 @@ It should run on any operating system. If you want to help, or write drivers to
|
||||
This software is licensed under the LGPL v3.
|
||||
|
||||
|
||||
# OS Requirements
|
||||
## OS Requirements
|
||||
|
||||
- Linux (ptyDriver, vcsaDriver, evdevDriver)
|
||||
- macOS (ptyDriver)
|
||||
@@ -13,15 +13,15 @@ This software is licensed under the LGPL v3.
|
||||
- Windows (ptyDriver)
|
||||
|
||||
|
||||
# Core Requirements
|
||||
## Core Requirements
|
||||
|
||||
- python3 >= 3.3
|
||||
- screen, input, speech, sound or braille drivers dependencies see "Features, Drivers, Extras".
|
||||
- screen, input, speech, sound drivers dependencies see "Features, Drivers, Extras".
|
||||
|
||||
|
||||
# Features, Drivers, Extras, Dependencies
|
||||
## Features, Drivers, Extras, Dependencies
|
||||
|
||||
# Input Drivers:
|
||||
### Input Drivers:
|
||||
1. "evdevDriver" input driver for linux evdev
|
||||
- python-evdev >=0.6.3 (This is commonly referred to as python3-evdev by your distribution)
|
||||
- python-pyudev
|
||||
@@ -33,7 +33,7 @@ This software is licensed under the LGPL v3.
|
||||
- python-pyte
|
||||
|
||||
|
||||
# Screen Drivers:
|
||||
### Screen Drivers:
|
||||
|
||||
1. "vcsaDriver" screen driver for linux VCSA devices
|
||||
- python-dbus
|
||||
@@ -46,27 +46,18 @@ This software is licensed under the LGPL v3.
|
||||
- python-pyte
|
||||
|
||||
|
||||
# Speech Drivers:
|
||||
### Speech Drivers:
|
||||
|
||||
1. "genericDriver" (default) speech driver for sound as subprocess:
|
||||
- espeak or espeak-ng
|
||||
2. "espeakDriver" speech driver for Espeak or Espeak-NG:
|
||||
- python-espeak
|
||||
3. "speechdDriver" speech driver for Speech-dispatcher:
|
||||
2. "speechdDriver" speech driver for Speech-dispatcher:
|
||||
- Speech-dispatcher
|
||||
- python-speechd
|
||||
4. "emacspeakDriver" speech driver for emacspeak
|
||||
3. "emacspeakDriver" speech driver for emacspeak
|
||||
- emacspeak
|
||||
|
||||
|
||||
# Braille Drivers:
|
||||
|
||||
1. "BrlttyDriver" braille driver (WIP):
|
||||
- brltty (configured and running)
|
||||
- python-brlapi
|
||||
|
||||
|
||||
# Sound Drivers:
|
||||
### Sound Drivers:
|
||||
|
||||
1. "genericDriver" (default) sound driver for sound as subprocess:
|
||||
- Sox
|
||||
@@ -75,7 +66,7 @@ This software is licensed under the LGPL v3.
|
||||
- GLib
|
||||
|
||||
|
||||
# Extras:
|
||||
## Extras:
|
||||
|
||||
1. spellchecker
|
||||
- python-pyenchant
|
||||
@@ -86,38 +77,32 @@ This software is licensed under the LGPL v3.
|
||||
- pyalsaaudio (needs libasound2's headers).
|
||||
|
||||
|
||||
# installation
|
||||
## installation
|
||||
|
||||
If there is a package for your distrobution of choice, please let us know so we can add it here.
|
||||
|
||||
- Archlinux: PKGBUILD in AUR (fenrir-git recommended)
|
||||
- PIP: sudo pip install fenrir-screenreader
|
||||
- Archlinux: PKGBUILD in AUR
|
||||
- fenrir: stable release
|
||||
- fenrir-git: Bleeding edge release
|
||||
- Manual:
|
||||
- install "espeak" and "sox" with your package manager
|
||||
- sudo pip install -r requirements.txt
|
||||
- run install.sh or uninstall.sh as root
|
||||
- you also can just run it from Git without installing:
|
||||
You can just run the following as root:
|
||||
if you are in Fenrir Git rootfolder:
|
||||
- install "espeak" and "sox" with your package manager
|
||||
- sudo pip install -r requirements.txt
|
||||
- run install.sh or uninstall.sh as root
|
||||
- You can also just run it from Git without installing:
|
||||
Requires root privileges
|
||||
|
||||
cd src/fenrir/
|
||||
sudo ./fenrir
|
||||
|
||||
Same thing, but use the daemon so the terminal is not blocked:
|
||||
|
||||
cd src/fenrir/
|
||||
sudo ./fenrir-daemon
|
||||
|
||||
Settings "settings.conf" is located in the "config" directory or after installation in /etc/fenrir/settings.
|
||||
Take care to use drivers from the config matching your installed drivers.
|
||||
By default it uses:
|
||||
- sound driver: genericDriver (via sox, could configured in settings.conf)
|
||||
- speech driver: genericDriver (via espeak or espeak-ng, could configured in settings.conf)
|
||||
- braille driver: brlttyDriver (WIP)
|
||||
- input driver: evdevDriver
|
||||
|
||||
|
||||
# Configure pulseaudio
|
||||
## 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.
|
||||
@@ -130,7 +115,7 @@ just run the configuration script twice (once as user, once as root):
|
||||
The script is also located in the tools directory in git
|
||||
|
||||
|
||||
# Configure pipewire
|
||||
## 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.
|
||||
@@ -142,10 +127,12 @@ just run the configuration script twice (once as user, once as root):
|
||||
|
||||
The script is also located in the tools directory in git
|
||||
|
||||
# localization
|
||||
## localization
|
||||
copy fenrir.mo translations file from fenrir/locale/your_language/LC_MESSAGES/fenrir.mo to /usr/share/locale/your_language/LC_MESSAGES/fenrir.mo
|
||||
|
||||
|
||||
# Documentation
|
||||
## Documentation and Support
|
||||
|
||||
Here is the [Fenrir Wiki](https://github.com/chrys87/fenrir/wiki). It is currently being updated, so keep checking back. Feel free to help with documentation.
|
||||
- Email list: [stormux+subscribe@groups.io](mailto:stormux+subscribe@groups.io?subject=subscribe) with the subject subscribe.
|
||||
- [Fenrir Wiki](https://git.stormux.org/storm/fenrir/wiki)
|
||||
- IRC: irc.stormux.org #stormux
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
#!/bin/sh
|
||||
[ -r ./conf ] && . ./conf
|
||||
exec fenrir
|
||||
exec fenrir -f
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
[Unit]
|
||||
Description=Fenrir screenreader
|
||||
Wants=systemd-udev-settle.service
|
||||
After=systemd-udev-settle.service sound.target
|
||||
After=systemd-udev-settle.service getty.target
|
||||
[Service]
|
||||
Type=forking
|
||||
PIDFile=/var/run/fenrir.pid
|
||||
ExecStart=/usr/bin/fenrir-daemon
|
||||
ExecStart=/usr/bin/fenrir
|
||||
ExecReload=/usr/bin/kill -HUP $MAINPID
|
||||
Restart=always
|
||||
#Group=fenrirscreenreader
|
||||
#User=fenrirscreenreader
|
||||
|
||||
[Install]
|
||||
# start as early as possible in boot process
|
||||
#WantedBy=sound.target
|
||||
# start as soon the login prompt is available
|
||||
WantedBy=getty.target
|
||||
|
||||
@@ -5,7 +5,7 @@ After=systemd-udev-settle.service sound.target
|
||||
[Service]
|
||||
Type=forking
|
||||
PIDFile=/var/run/fenrir.pid
|
||||
ExecStart=/usr/local/bin/fenrir-daemon
|
||||
ExecStart=/usr/local/bin/fenrir
|
||||
ExecReload=/usr/bin/kill -HUP $MAINPID
|
||||
Restart=always
|
||||
#Group=fenrirscreenreader
|
||||
|
||||
+125
-223
@@ -1,232 +1,134 @@
|
||||
#!/bin/env python3
|
||||
import os, sys
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# default installation
|
||||
# core
|
||||
# speech: speech-dispatcher
|
||||
# sound: sox
|
||||
# braille: brltty:
|
||||
defaultInstallation = ['FenrirCore','vcsaDriver','dummyDriver (braille)','evdevDriver','genericDriver (speech)', 'genericDriver (sound)']
|
||||
currentInstallation = []
|
||||
import os
|
||||
import sys
|
||||
from dataclasses import dataclass
|
||||
from typing import List, Optional
|
||||
|
||||
print('checking dependencys...')
|
||||
# CORE
|
||||
print('')
|
||||
print('fenrir core:')
|
||||
available = True
|
||||
try:
|
||||
from daemonize import Daemonize
|
||||
print('python3-daemonize: OK')
|
||||
except:
|
||||
print('python3-daemonize: FAIL')
|
||||
available = available and False
|
||||
@dataclass
|
||||
class Dependency:
|
||||
name: str
|
||||
depType: str # screen, input, sound, speech, core
|
||||
moduleName: str
|
||||
checkCommands: Optional[List[str]] = None # Command-line tools to check
|
||||
pythonImports: Optional[List[str]] = None # Python packages to check
|
||||
devicePaths: Optional[List[str]] = None # Device files to check
|
||||
|
||||
def check_dependency(dep: Dependency) -> bool:
|
||||
"""Check if a single dependency is satisfied."""
|
||||
isAvailable = True
|
||||
|
||||
try:
|
||||
import enchant
|
||||
print('pyenchant: OK')
|
||||
except:
|
||||
print('pyenchant: FAIL')
|
||||
available = available and False
|
||||
|
||||
if available:
|
||||
currentInstallation.append('FenrirCore')
|
||||
|
||||
# SCREEN
|
||||
print('--------------------')
|
||||
print('screen driver')
|
||||
# dummy and debug
|
||||
print('dummyDriver (screen): OK')
|
||||
currentInstallation.append('dummyDriver (screen)')
|
||||
if dep.pythonImports:
|
||||
for package in dep.pythonImports:
|
||||
try:
|
||||
moduleName = package.split('.')[0]
|
||||
__import__(moduleName)
|
||||
print(f'{package}: OK')
|
||||
except ImportError:
|
||||
print(f'{package}: FAIL')
|
||||
isAvailable = False
|
||||
|
||||
# VCSA (screen driver)
|
||||
print('vcsaDriver')
|
||||
available = True
|
||||
try:
|
||||
import dbus
|
||||
print('python3-dbus: OK')
|
||||
except:
|
||||
print('python3-dbus: FAIL')
|
||||
available = available and False
|
||||
if os.path.exists('/dev/vcsa'):
|
||||
print('VCSA Device: OK')
|
||||
else:
|
||||
print('VCSA Device: FAIL')
|
||||
available = available and False
|
||||
if available:
|
||||
currentInstallation.append('vcsaDriver')
|
||||
print('')
|
||||
# pty emulation (screen driver)
|
||||
print('ptyDriver')
|
||||
available = True
|
||||
try:
|
||||
import pyte
|
||||
print('pyte: OK')
|
||||
except:
|
||||
print('pyte: FAIL')
|
||||
available = available and False
|
||||
if available:
|
||||
currentInstallation.append('ptyDriver (screen)')
|
||||
if dep.checkCommands:
|
||||
for cmd in dep.checkCommands:
|
||||
if os.path.exists(f'/usr/bin/{cmd}') or os.path.exists(f'/bin/{cmd}'):
|
||||
print(f'{cmd}: OK')
|
||||
else:
|
||||
print(f'{cmd}: FAIL')
|
||||
isAvailable = False
|
||||
|
||||
if dep.devicePaths:
|
||||
for path in dep.devicePaths:
|
||||
if os.path.exists(path):
|
||||
print(f'{path}: OK')
|
||||
else:
|
||||
print(f'{path}: FAIL')
|
||||
isAvailable = False
|
||||
|
||||
return isAvailable
|
||||
|
||||
# Define all dependencies
|
||||
dependencyList = [
|
||||
# Core dependencies
|
||||
Dependency('FenrirCore', 'core', 'core',
|
||||
pythonImports=['daemonize', 'enchant']),
|
||||
|
||||
# BRAILLE
|
||||
print('--------------------')
|
||||
print('braille driver')
|
||||
# dummy and debug
|
||||
print('dummyDriver (braille): OK')
|
||||
currentInstallation.append('dummyDriver (braille)')
|
||||
print('debugDriver (braille): OK')
|
||||
currentInstallation.append('debugDriver (braille)')
|
||||
# brltty (braille driver)
|
||||
print('brlapiDriver')
|
||||
available = True
|
||||
try:
|
||||
import brlapi
|
||||
print('python3-brlapi: OK')
|
||||
except:
|
||||
print('python3-brlapi: FAIL')
|
||||
available = available and False
|
||||
# Screen drivers
|
||||
Dependency('DummyScreen', 'screen', 'dummyDriver'),
|
||||
Dependency('VCSA', 'screen', 'vcsaDriver',
|
||||
pythonImports=['dbus'],
|
||||
devicePaths=['/dev/vcsa']),
|
||||
Dependency('PTY', 'screen', 'ptyDriver',
|
||||
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'),
|
||||
Dependency('GenericSound', 'sound', 'genericDriver',
|
||||
checkCommands=['play', 'sox']),
|
||||
Dependency('GStreamer', 'sound', 'gstreamerDriver',
|
||||
pythonImports=['gi', 'gi.repository.GLib', 'gi.repository.Gst']),
|
||||
|
||||
# Speech drivers
|
||||
Dependency('DummySpeech', 'speech', 'dummyDriver'),
|
||||
Dependency('DebugSpeech', 'speech', 'debugDriver'),
|
||||
Dependency('Speechd', 'speech', 'speechdDriver',
|
||||
pythonImports=['speechd']),
|
||||
Dependency('GenericSpeech', 'speech', 'genericDriver',
|
||||
checkCommands=['espeak-ng'])
|
||||
]
|
||||
|
||||
defaultModules = {
|
||||
'FenrirCore',
|
||||
'VCSA',
|
||||
'Evdev',
|
||||
'GenericSpeech',
|
||||
'GenericSound'
|
||||
}
|
||||
|
||||
def check_all_dependencies():
|
||||
print('Checking dependencies...\n')
|
||||
availableModules = []
|
||||
|
||||
if available:
|
||||
currentInstallation.append('brlapiDriver')
|
||||
# INPUT
|
||||
print('--------------------')
|
||||
print('input driver')
|
||||
# dummy and debug
|
||||
print('dummyDriver (input): OK')
|
||||
currentInstallation.append('dummyDriver (input)')
|
||||
print('debugDriver (input): OK')
|
||||
currentInstallation.append('debugDriver (input)')
|
||||
# evdev (input driver)
|
||||
print('evdevDriver')
|
||||
available = True
|
||||
try:
|
||||
import evdev
|
||||
from evdev import InputDevice, UInput
|
||||
print('python3-evdev: OK')
|
||||
except:
|
||||
print('python3-evdev: FAIL')
|
||||
available = available and False
|
||||
try:
|
||||
import pyudev
|
||||
print('python3-pyudev: OK')
|
||||
except:
|
||||
print('python3-pyudev: FAIL')
|
||||
available = available and False
|
||||
if available:
|
||||
currentInstallation.append('evdevDriver')
|
||||
# pty emulation (input driver)
|
||||
print('')
|
||||
print('ptyDriver')
|
||||
available = True
|
||||
try:
|
||||
import pyte
|
||||
print('pyte: OK')
|
||||
except:
|
||||
print('pyte: FAIL')
|
||||
available = available and False
|
||||
if available:
|
||||
currentInstallation.append('ptyDriver (Input)')
|
||||
# SOUND
|
||||
print('--------------------')
|
||||
print('sound driver')
|
||||
# dummy and debug
|
||||
print('dummyDriver (sound): OK')
|
||||
currentInstallation.append('dummyDriver (sound)')
|
||||
print('debugDriver (sound): OK')
|
||||
currentInstallation.append('debugDriver (sound)')
|
||||
print('genericDriver (uses sox by default)')
|
||||
available = True
|
||||
if os.path.exists('/usr/bin/play') and os.path.exists('/usr/bin/sox'):
|
||||
print('sox: OK')
|
||||
else:
|
||||
print('sox: FAIL')
|
||||
available = available and False
|
||||
if available:
|
||||
currentInstallation.append('genericDriver (sound)')
|
||||
print('')
|
||||
# gstreamer (sound driver)
|
||||
print('gstreamerDriver')
|
||||
available = True
|
||||
try:
|
||||
import gi
|
||||
print('gi: OK')
|
||||
except:
|
||||
print('gi: FAIL')
|
||||
available = available and False
|
||||
try:
|
||||
from gi.repository import GLib
|
||||
print('gi GLib: OK')
|
||||
except:
|
||||
print('gi GLib: FAIL')
|
||||
available = available and False
|
||||
try:
|
||||
gi.require_version('Gst', '1.0')
|
||||
from gi.repository import Gst
|
||||
print('gi Gst: OK')
|
||||
except:
|
||||
print('gi Gst: FAIL')
|
||||
available = available and False
|
||||
if available:
|
||||
currentInstallation.append('gstreamerDriver')
|
||||
# Group dependencies by type for organized output
|
||||
for depType in ['core', 'screen', 'input', 'sound', 'speech']:
|
||||
print(f'{depType.upper()} DRIVERS')
|
||||
print('-' * 20)
|
||||
|
||||
depsOfType = [d for d in dependencyList if d.depType == depType]
|
||||
for dep in depsOfType:
|
||||
print(f'\nChecking {dep.name}:')
|
||||
if check_dependency(dep):
|
||||
availableModules.append(dep.name)
|
||||
print('')
|
||||
|
||||
# SPEECH
|
||||
print('--------------------')
|
||||
print('speech driver')
|
||||
# dummy and debug
|
||||
print('dummyDriver (speech): OK')
|
||||
currentInstallation.append('dummyDriver (speech)')
|
||||
print('debugDriver (speech): OK')
|
||||
currentInstallation.append('debugDriver (speech)')
|
||||
# speechd (speech driver)
|
||||
print('speechdDriver')
|
||||
available = True
|
||||
try:
|
||||
import speechd
|
||||
print('python3-speechd: OK')
|
||||
except:
|
||||
print('python3-speechd: FAIL')
|
||||
available = available and False
|
||||
if available:
|
||||
currentInstallation.append('speechdDriver')
|
||||
print('')
|
||||
# espeak (speech driver)
|
||||
print('espeakDriver')
|
||||
available = True
|
||||
try:
|
||||
from espeak import espeak
|
||||
print('python3-espeak: OK')
|
||||
except:
|
||||
print('python3-espeak: FAIL')
|
||||
available = available and False
|
||||
if available:
|
||||
currentInstallation.append('espeakDriver')
|
||||
print('genericDriver (uses espeak-ng by default)')
|
||||
available = True
|
||||
if os.path.exists('/usr/bin/espeak-ng') or os.path.exists('/bin/espeak-ng'):
|
||||
print('espeak-ng: OK')
|
||||
else:
|
||||
print('espeak-ng: FAIL')
|
||||
available = available and False
|
||||
if available:
|
||||
currentInstallation.append('genericDriver (speech)')
|
||||
print_summary(availableModules)
|
||||
|
||||
# SUMMERY
|
||||
print('====================')
|
||||
available = True
|
||||
missing = []
|
||||
for element in defaultInstallation:
|
||||
if not element in currentInstallation:
|
||||
available = False
|
||||
missing.append(element)
|
||||
if available:
|
||||
print('Default Setup: OK')
|
||||
else:
|
||||
print('Default Setup: FAIL')
|
||||
print('Unavailable Default Modules:')
|
||||
for e in missing:
|
||||
print(e)
|
||||
print('you may need to install the missing dependencys for the modules above or reconfigure fenrir to not use them')
|
||||
print('')
|
||||
print('Available Modules:')
|
||||
for element in currentInstallation:
|
||||
print(element)
|
||||
def print_summary(availableModules: List[str]):
|
||||
print('=' * 20)
|
||||
print('SUMMARY')
|
||||
print('=' * 20)
|
||||
|
||||
missingModules = defaultModules - set(availableModules)
|
||||
if missingModules:
|
||||
print('Default Setup: FAIL')
|
||||
print('\nUnavailable Default Modules:')
|
||||
for module in missingModules:
|
||||
print(f'- {module}')
|
||||
print('\nYou may need to install the missing dependencies for the modules above or reconfigure fenrir to not use them.')
|
||||
else:
|
||||
print('Default Setup: OK')
|
||||
|
||||
print('\nAvailable Modules:')
|
||||
for module in availableModules:
|
||||
print(f'- {module}')
|
||||
|
||||
if __name__ == '__main__':
|
||||
check_all_dependencies()
|
||||
|
||||
@@ -125,3 +125,4 @@ 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
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_V=announce_fenrir_version
|
||||
|
||||
@@ -125,3 +125,4 @@ 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
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_V=announce_fenrir_version
|
||||
|
||||
@@ -91,37 +91,6 @@ fenrirMaxPitch=99
|
||||
fenrirMinRate=80
|
||||
fenrirMaxRate=450
|
||||
|
||||
[braille]
|
||||
enabled=False
|
||||
driver=dummyDriver
|
||||
layout=en
|
||||
# to what should the flush timeout relate to
|
||||
# word = flush after (number of words to display) * seconds
|
||||
# char = flush after (number of chars to display) * seconds
|
||||
# fix = flush after X seconds
|
||||
# none = no automatic flush (manual via shortcut)
|
||||
flushMode=word
|
||||
# seconds to flush or
|
||||
# -1 = no automatic flush (manual via shortcut)
|
||||
flushTimeout=3
|
||||
# how should the cursor be focused?
|
||||
# page = if cursor cross the border move to next page and start at beginn
|
||||
# fixCell = ajust the cursor on an special cell where it is always placed. the display scroll here more smooth.
|
||||
cursorFocusMode=page
|
||||
# define the cell on the Braille device where fenrir should scroll and keep the cursor
|
||||
# 0 = first cell on device
|
||||
# -1 = last cell on device
|
||||
# >0 = fix cell number
|
||||
fixCursorOnCell=-1
|
||||
#How should the braille follow the focus
|
||||
# none = no automatic toggle command used
|
||||
# review = priority to review
|
||||
# last = follow last used cursor
|
||||
cursorFollowMode=review
|
||||
# number of cells in panning (horizontal)
|
||||
# 0 = display size, >0 number of cells
|
||||
panSizeHorizontal=0
|
||||
|
||||
[screen]
|
||||
driver=vcsaDriver
|
||||
encoding=auto
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
# needs pandoc and php installed
|
||||
|
||||
# remove old files
|
||||
|
||||
@@ -76,7 +76,7 @@ setup(
|
||||
# Packages
|
||||
packages=find_packages('src/'),
|
||||
package_dir={'': 'src/'},
|
||||
scripts=['src/fenrir','src/fenrir-daemon'],
|
||||
scripts=['src/fenrir'],
|
||||
|
||||
# Include additional files into the package
|
||||
include_package_data=True,
|
||||
@@ -119,5 +119,4 @@ print('once as their user account and once as root to configure Pulseaudio.')
|
||||
print('Please install the following packages manually:')
|
||||
print('- Speech-dispatcher: for the default speech driver')
|
||||
print('- Espeak: as basic TTS engine')
|
||||
print('- BrlTTY: for Braille')
|
||||
print('- sox: is a player for the generic sound driver')
|
||||
|
||||
+102
-7
@@ -2,20 +2,115 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
import os, sys, inspect
|
||||
import os
|
||||
import sys
|
||||
import inspect
|
||||
import argparse
|
||||
from daemonize import Daemonize
|
||||
|
||||
# Get the fenrir installation path
|
||||
fenrirPath = os.path.dirname(os.path.realpath(os.path.abspath(inspect.getfile(inspect.currentframe()))))
|
||||
|
||||
if not fenrirPath in sys.path:
|
||||
sys.path.append(fenrirPath)
|
||||
|
||||
from fenrirscreenreader.core import fenrirManager
|
||||
from fenrirscreenreader import fenrirVersion
|
||||
|
||||
def create_argument_parser():
|
||||
"""Create and return the argument parser for Fenrir"""
|
||||
argumentParser = argparse.ArgumentParser(
|
||||
description="Fenrir - A console screen reader for Linux",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter
|
||||
)
|
||||
argumentParser.add_argument(
|
||||
'-v', '--version',
|
||||
action='version',
|
||||
version=f'Fenrir screen reader version {fenrirVersion.version}-{fenrirVersion.codeName}',
|
||||
help='Show version information and exit'
|
||||
)
|
||||
argumentParser.add_argument(
|
||||
'-f', '--foreground',
|
||||
action='store_true',
|
||||
help='Run Fenrir in the foreground (default: run as daemon)'
|
||||
)
|
||||
argumentParser.add_argument(
|
||||
'-s', '--setting',
|
||||
metavar='SETTING-FILE',
|
||||
default='/etc/fenrir/settings/settings.conf',
|
||||
help='Path to custom settings file'
|
||||
)
|
||||
argumentParser.add_argument(
|
||||
'-o', '--options',
|
||||
metavar='SECTION#SETTING=VALUE;..',
|
||||
default='',
|
||||
help='Override settings file options. Format: SECTION#SETTING=VALUE;... (case sensitive)'
|
||||
)
|
||||
argumentParser.add_argument(
|
||||
'-d', '--debug',
|
||||
action='store_true',
|
||||
help='Enable debug mode'
|
||||
)
|
||||
argumentParser.add_argument(
|
||||
'-p', '--print',
|
||||
action='store_true',
|
||||
help='Print debug messages to screen'
|
||||
)
|
||||
argumentParser.add_argument(
|
||||
'-e', '--emulated-pty',
|
||||
action='store_true',
|
||||
help='Use PTY emulation with escape sequences for input (enables desktop/X/Wayland usage)'
|
||||
)
|
||||
argumentParser.add_argument(
|
||||
'-E', '--emulated-evdev',
|
||||
action='store_true',
|
||||
help='Use PTY emulation with evdev for input (single instance)'
|
||||
)
|
||||
return argumentParser
|
||||
|
||||
def validate_arguments(cliArgs):
|
||||
"""Validate command line arguments"""
|
||||
if cliArgs.options:
|
||||
for option in cliArgs.options.split(';'):
|
||||
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"
|
||||
|
||||
return True, None
|
||||
|
||||
def run_fenrir():
|
||||
"""Main function that runs Fenrir"""
|
||||
fenrirApp = fenrirManager.fenrirManager(cliArgs)
|
||||
fenrirApp.proceed()
|
||||
del fenrirApp
|
||||
|
||||
def main():
|
||||
app = fenrirManager.fenrirManager()
|
||||
app.proceed()
|
||||
del app
|
||||
global cliArgs
|
||||
argumentParser = create_argument_parser()
|
||||
cliArgs = argumentParser.parse_args()
|
||||
|
||||
# Validate arguments
|
||||
isValid, errorMsg = validate_arguments(cliArgs)
|
||||
if not isValid:
|
||||
argumentParser.error(errorMsg)
|
||||
sys.exit(1)
|
||||
|
||||
if cliArgs.foreground:
|
||||
# Run directly in foreground
|
||||
run_fenrir()
|
||||
else:
|
||||
# Run as daemon
|
||||
pidFile = "/run/fenrir.pid"
|
||||
daemonProcess = Daemonize(
|
||||
app="fenrir",
|
||||
pid=pidFile,
|
||||
action=run_fenrir,
|
||||
chdir=fenrirPath
|
||||
)
|
||||
daemonProcess.start()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
main()
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
import os, sys, inspect
|
||||
fenrirPath = os.path.dirname(os.path.realpath(os.path.abspath(inspect.getfile(inspect.currentframe()))))
|
||||
|
||||
if not fenrirPath in sys.path:
|
||||
sys.path.append(fenrirPath)
|
||||
|
||||
from fenrirscreenreader.core import fenrirManager
|
||||
from daemonize import Daemonize
|
||||
|
||||
pidFile = "/run/fenrir.pid"
|
||||
|
||||
def main():
|
||||
app = fenrirManager.fenrirManager()
|
||||
app.proceed()
|
||||
del app
|
||||
|
||||
if __name__ == "__main__":
|
||||
# for debug in foreground
|
||||
#daemon = Daemonize(app="fenrir-daemon", pid=pidFile, action=main, foreground=True,chdir=fenrirPath)
|
||||
daemon = Daemonize(app="fenrir-daemon", pid=pidFile, action=main, chdir=fenrirPath)
|
||||
daemon.start()
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
#!/usr/bin/env pypy3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
import os, sys, inspect
|
||||
fenrirPath = os.path.dirname(os.path.realpath(os.path.abspath(inspect.getfile(inspect.currentframe()))))
|
||||
|
||||
if not fenrirPath in sys.path:
|
||||
sys.path.append(fenrirPath)
|
||||
|
||||
from fenrirscreenreader.core import fenrirManager
|
||||
from daemonize import Daemonize
|
||||
|
||||
pidFile = "/run/fenrir.pid"
|
||||
|
||||
def main():
|
||||
app = fenrirManager.fenrirManager()
|
||||
app.proceed()
|
||||
del app
|
||||
|
||||
if __name__ == "__main__":
|
||||
# for debug in foreground
|
||||
#daemon = Daemonize(app="fenrir-daemon", pid=pidFile, action=main, foreground=True,chdir=os.path.dirname(os.path.realpath(fenrirVersion.__file__)))
|
||||
daemon = Daemonize(app="fenrir-daemon", pid=pidFile, action=main, chdir=fenrirPath)
|
||||
daemon.start()
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
#!/usr/bin/env pypy3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
import os, sys, inspect
|
||||
fenrirPath = os.path.dirname(os.path.realpath(os.path.abspath(inspect.getfile(inspect.currentframe()))))
|
||||
|
||||
if not fenrirPath in sys.path:
|
||||
sys.path.append(fenrirPath)
|
||||
|
||||
from fenrirscreenreader.core import fenrirManager
|
||||
|
||||
def main():
|
||||
app = fenrirManager.fenrirManager()
|
||||
app.proceed()
|
||||
del app
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,66 +0,0 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.core.brailleDriver import brailleDriver
|
||||
|
||||
class driver(brailleDriver):
|
||||
def __init__(self):
|
||||
brailleDriver.__init__(self)
|
||||
self._brl = None
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
try:
|
||||
import brlapi
|
||||
self._brl = brlapi.Connection()
|
||||
self._deviceSize = self._brl.displaySize
|
||||
except Exception as e:
|
||||
print(e)
|
||||
self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR)
|
||||
return
|
||||
self._isInitialized = True
|
||||
|
||||
def getDeviceSize(self):
|
||||
if not self._isInitialized:
|
||||
return (0,0)
|
||||
if not self._deviceSize:
|
||||
return (0,0)
|
||||
return self._deviceSize
|
||||
|
||||
def flush(self):
|
||||
if not self._isInitialized:
|
||||
return
|
||||
try:
|
||||
self._brl.writeText('',0)
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('BRAILLE.flush '+str(e),debug.debugLevel.ERROR)
|
||||
|
||||
def writeText(self,text):
|
||||
if not self._isInitialized:
|
||||
return
|
||||
try:
|
||||
self._brl.writeText(text)
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut('BRAILLE.writeText '+str(e),debug.debugLevel.ERROR)
|
||||
|
||||
def connectDevice(self):
|
||||
self._brl = brlapi.Connection()
|
||||
|
||||
def enterScreen(self, screen):
|
||||
if not self._isInitialized:
|
||||
return
|
||||
self._brl.enterTtyMode(int(screen))
|
||||
|
||||
def leveScreen(self):
|
||||
if not self._isInitialized:
|
||||
return
|
||||
self._brl.leaveTtyMode()
|
||||
|
||||
def shutdown(self):
|
||||
if not self._isInitialized:
|
||||
return
|
||||
self.leveScreen()
|
||||
@@ -1,49 +0,0 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.core.brailleDriver import brailleDriver
|
||||
|
||||
class driver(brailleDriver):
|
||||
def __init__(self):
|
||||
brailleDriver.__init__(self)
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
self._isInitialized = True
|
||||
self.deviceSize = (40,0)
|
||||
print('Braille Debug Driver: Initialized')
|
||||
|
||||
def getDeviceSize(self):
|
||||
if not self._isInitialized:
|
||||
return (0,0)
|
||||
print('Braille Debug Driver: getDeviceSize ' + str(self.deviceSize))
|
||||
return self.deviceSize
|
||||
|
||||
def writeText(self,text):
|
||||
if not self._isInitialized:
|
||||
return
|
||||
print('Braille Debug Driver: writeText:' + str(text))
|
||||
print('Braille Debug Driver: -----------------------------------')
|
||||
|
||||
def connectDevice(self):
|
||||
print('Braille Debug Driver: connectDevice')
|
||||
|
||||
def enterScreen(self, screen):
|
||||
if not self._isInitialized:
|
||||
return
|
||||
print('Braille Debug Driver: enterScreen')
|
||||
|
||||
def leveScreen(self):
|
||||
if not self._isInitialized:
|
||||
return
|
||||
print('Braille Debug Driver: leveScreen')
|
||||
|
||||
def shutdown(self):
|
||||
if self._isInitialized:
|
||||
self.leveScreen()
|
||||
self._isInitialized = False
|
||||
print('Braille Debug Driver: Shutdown')
|
||||
@@ -1,12 +0,0 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader.core.brailleDriver import brailleDriver
|
||||
|
||||
class driver(brailleDriver):
|
||||
def __init__(self):
|
||||
brailleDriver.__init__(self)
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
from fenrirscreenreader import fenrirVersion
|
||||
|
||||
class command():
|
||||
def __init__(self):
|
||||
pass
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('Present the version of Fenrir currrrently in use.')
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
self.env['runtime']['outputManager'].presentText(f'Fenrir screen reader version {fenrirVersion.version}-{fenrirVersion.codeName}', interrupt=True)
|
||||
except exception as e:
|
||||
self.env['runtime']['outputManager'].presentText(_('Version information is unavailable.'), interrupt=True)
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
class command():
|
||||
def __init__(self):
|
||||
pass
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('Clear the Braille device if it is displaying a message')
|
||||
def run(self):
|
||||
self.env['runtime']['outputManager'].clearFlushTime()
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
@@ -1,21 +0,0 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
class command():
|
||||
def __init__(self):
|
||||
pass
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('Move braille view to the left.')
|
||||
def run(self):
|
||||
panned = self.env['runtime']['outputManager'].setPanLeft()
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
@@ -1,21 +0,0 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
class command():
|
||||
def __init__(self):
|
||||
pass
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('Move braille view to the right.')
|
||||
def run(self):
|
||||
panned = self.env['runtime']['outputManager'].setPanRight()
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
@@ -1,21 +0,0 @@
|
||||
#!/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
class command():
|
||||
def __init__(self):
|
||||
pass
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
def shutdown(self):
|
||||
pass
|
||||
def getDescription(self):
|
||||
return _('Set the braille view back to cursor.')
|
||||
def run(self):
|
||||
self.env['runtime']['outputManager'].removePanning()
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Fenrir TTY screen reader
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user