Merge branch 'master' into storm

This commit is contained in:
Storm Dragon 2024-03-12 23:52:17 -04:00
commit a7b28af947
34 changed files with 1718 additions and 550 deletions

View File

@ -1,19 +1,26 @@
# Fenrir
A modern, modular, flexible and fast console screenreader.
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.
This software is licensed under the LGPL v3.
# OS Requirements
- Linux (ptyDriver, vcsaDriver, evdevDriver)
- macOS (ptyDriver)
- BSD (ptyDriver)
- Windows (ptyDriver)
# Core Requirements
- python3 >= 3.3
- screen, input, speech, sound or braille drivers dependencies see "Features, Drivers, Extras".
# Features, Drivers, Extras, Dependencies
# 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)
@ -25,7 +32,9 @@ This software is licensed under the LGPL v3.
2. "ptyDriver" terminal emulation input driver
- python-pyte
# Screen Drivers:
1. "vcsaDriver" screen driver for linux VCSA devices
- python-dbus
- Read permission to the following files and services:
@ -36,7 +45,9 @@ This software is licensed under the LGPL v3.
2. "ptyDriver" terminal emulation driver
- python-pyte
# Speech Drivers:
1. "genericDriver" (default) speech driver for sound as subprocess:
- espeak or espeak-ng
2. "espeakDriver" speech driver for Espeak or Espeak-NG:
@ -47,19 +58,25 @@ This software is licensed under the LGPL v3.
4. "emacspeakDriver" speech driver for emacspeak
- emacspeak
# Braille Drivers:
1. "BrlttyDriver" braille driver (WIP):
- brltty (configured and running)
- python-brlapi
# Sound Drivers:
1. "genericDriver" (default) sound driver for sound as subprocess:
- Sox
2. "gstreamerDriver" sound driver for gstreamer
- gstreamer >=1.0
- GLib
# Extras:
1. spellchecker
- python-pyenchant
- aspell-YourLanguageCode (example aspell-en for us English)
@ -68,18 +85,29 @@ This software is licensed under the LGPL v3.
3. Modify system volume:
- pyalsaaudio (needs libasound2's headers).
# installation
- Archlinux: PKGBUILD in AUR
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
- Manual:
- install "espeak" and "sox" with your package manager
- sudo pip install -r requirements.txt
- run install.sh and uninstall.sh as root
- 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:
cd src/fenrir/
sudo ./fenrir
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:
@ -87,21 +115,37 @@ By default it uses:
- speech driver: genericDriver (via espeak or espeak-ng, could configured in settings.conf)
- braille driver: brlttyDriver (WIP)
- input driver: evdevDriver
# Configure pulseaudio
Pulseaudio by default does only play 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. Last is playing the sound then. This is not a issue of fenrir but this is how pulseaudio works.
just run the configuration scipt twice (once as user, once as root).
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.
Run:
configure_pulse.sh
sudo configure_pulse.sh
just run the configuration script twice (once as user, once as root):
The script could also be found at /tools/ in git
/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
# 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
You can see all information on the Wiki:
https://wiki.linux-a11y.org/doku.php?id=fenrir_user_manual
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.

View File

@ -32,12 +32,15 @@ KEY_FENRIR,KEY_KP5=curr_screen
KEY_FENRIR,KEY_KP8=curr_screen_before_cursor
KEY_FENRIR,KEY_KP2=curr_screen_after_cursor
#=cursor_read_to_end_of_line
#=review_screen_last_char
#=review_screen_first_char
#=cursor_column
#=cursor_lineno
#=braille_flush
#=braille_return_to_cursor
#=braille_pan_left
#=braille_pan_right
#=cursor_read_line_to_cursor
KEY_FENRIR,KEY_CTRL,KEY_1=clear_bookmark_1
KEY_FENRIR,KEY_SHIFT,KEY_1=set_bookmark_1
KEY_FENRIR,KEY_1=bookmark_1

View File

@ -6,7 +6,7 @@ KEY_FENRIR,KEY_I=review_curr_line
KEY_FENRIR,KEY_U=review_prev_line
KEY_FENRIR,KEY_O=review_next_line
KEY_FENRIR,KEY_SHIFT,KEY_J=review_line_begin
KEY_FENRIR,KEY_SHFIT,KEY_L=review_line_end
KEY_FENRIR,KEY_SHIFT,KEY_L=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
@ -83,6 +83,7 @@ KEY_FENRIR,KEY_ENTER=toggle_auto_read
KEY_FENRIR,KEY_CTRL,KEY_T=toggle_auto_time
KEY_FENRIR,KEY_Y=toggle_highlight_tracking
#=toggle_barrier
#=cursor_read_line_to_cursor
KEY_FENRIR,KEY_Q=quit_fenrir
KEY_FENRIR,KEY_T=time
2,KEY_FENRIR,KEY_T=date

View File

@ -0,0 +1,218 @@
# Fenrir comment: copy of speakup DefaultKeyAssignments converted to fenrir syntax
# Fenrir comment: https://android.googlesource.com/kernel/msm/+/android-7.1.0_r0.2/drivers/staging/speakup/DefaultKeyAssignments
# Fenrir comment: The insert or shift key named below is the fenrir key
# This file is intended to give you an overview of the default keys used
# by speakup for it's review functions. You may change them to be
# anything you want but that will take some familiarity with key
# mapping.
# We have remapped the insert or zero key on the keypad to act as a
# shift key. Well, actually as an altgr key. So in the following list
# InsKeyPad-period means hold down the insert key like a shift key and
# hit the keypad period.
# KeyPad-8 Say current Line
KEY_KP8=review_curr_line
# InsKeyPad-8 say from top of screen to reading cursor.
KEY_FENRIR,KEY_KP8=curr_screen_before_cursor
# KeyPad-7 Say Previous Line (UP one line)
KEY_KP7=review_prev_line
# KeyPad-9 Say Next Line (down one line)
KEY_KP9=review_next_line
# KeyPad-5 Say Current Word
KEY_KP5=review_curr_word
# InsKeyPad-5 Spell Current Word
KEY_FENRIR,KEY_KP5=review_curr_word_phonetic
# KeyPad-4 Say Previous Word (left one word)
KEY_KP4=review_prev_word
# InsKeyPad-4 say from left edge of line to reading cursor.
KEY_FENRIR,KEY_KP4=cursor_read_line_to_cursor
# KeyPad-6 Say Next Word (right one word)
KEY_KP6=review_next_word
# InsKeyPad-6 Say from reading cursor to right edge of line.
KEY_FENRIR,KEY_KP6=cursor_read_to_end_of_line
# KeyPad-2 Say Current Letter
KEY_KP2=review_curr_char
# InsKeyPad-2 say current letter phonetically
KEY_FENRIR,KEY_KP2=review_curr_char_phonetic
# KeyPad-1 Say Previous Character (left one letter)
KEY_KP1=review_prev_char
# KeyPad-3 Say Next Character (right one letter)
KEY_KP3=review_next_char
# KeyPad-plus Say Entire Screen
KEY_KPPLUS=curr_screen
# InsKeyPad-plus Say from reading cursor line to bottom of screen.
KEY_FENRIR,KEY_KPPLUS=curr_screen_after_cursor
# KeyPad-Minus Park reading cursor (toggle)
# TODO
# InsKeyPad-minus Say character hex and decimal value.
# TODO
# KeyPad-period Say Position (current line, position and console)
KEY_KPDOT=cursor_position
# InsKeyPad-period say colour attributes of current position.
KEY_FENRIR,KEY_KPDOT=attribute_cursor
# InsKeyPad-9 Move reading cursor to top of screen (insert pgup)
KEY_FENRIR,KEY_KP9=review_bottom
# InsKeyPad-3 Move reading cursor to bottom of screen (insert pgdn)
KEY_FENRIR,KEY_KP3=review_top
# InsKeyPad-7 Move reading cursor to left edge of screen (insert home)
KEY_FENRIR,KEY_KP7=review_screen_first_char
# InsKeyPad-1 Move reading cursor to right edge of screen (insert end)
KEY_FENRIR,KEY_KP1=review_screen_last_char
# ControlKeyPad-1 Move reading cursor to last character on current line.
KEY_CTRL,KEY_KP1=review_line_end
# KeyPad-Enter Shut Up (until another key is hit) and sync reading cursor
KEY_KPENTER=temp_disable_speech
# InsKeyPad-Enter Shut Up (until toggled back on).
KEY_FENRIR,KEY_KPENTER=toggle_speech
# InsKeyPad-star n<x|y> go to line (y) or column (x). Where 'n' is any
# allowed value for the row or column for your current screen.
# TODO
# KeyPad-/ Mark and Cut screen region.
KEY_KPSLASH=copy_marked_to_clipboard
# InsKeyPad-/ Paste screen region into any console.
KEY_FENRIR,KEY_KPSLASH=paste_clipboard
# Hitting any key while speakup is outputting speech will quiet the
# synth until it has caught up with what is being printed on the
# console.
# following by other fenrir commands
KEY_FENRIR,KEY_H=toggle_tutorial_mode
KEY_CTRL=shut_up
KEY_FENRIR,KEY_KP4=review_line_begin
#=review_line_end
#=review_line_first_char
#=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_SHIFT,KEY_KP4=review_prev_word_phonetic
KEY_FENRIR,KEY_SHIFT,KEY_KP6=review_next_word_phonetic
KEY_FENRIR,KEY_SHIFT,KEY_KP1=review_prev_char_phonetic
KEY_FENRIR,KEY_SHIFT,KEY_KP3=review_next_char_phonetic
KEY_FENRIR,KEY_CTRL,KEY_KP8=review_up
KEY_FENRIR,KEY_CTRL,KEY_KP2=review_down
#=exit_review
KEY_FENRIR,KEY_I=indent_curr_line
KEY_KPPLUS=curr_screen
#=cursor_column
#=cursor_lineno
#=braille_flush
#=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_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
#=last_incoming
KEY_FENRIR,KEY_F2=toggle_braille
KEY_FENRIR,KEY_F3=toggle_sound
KEY_FENRIR,KEY_F9=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_KPENTER=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
2,KEY_FENRIR,KEY_T=date
KEY_KPSLASH=toggle_auto_indent
#=toggle_has_attribute
KEY_FENRIR,KEY_S=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_BACKSPACE=forward_keypress
KEY_FENRIR,KEY_ALT,KEY_UP=inc_sound_volume
KEY_FENRIR,KEY_ALT,KEY_DOWN=dec_sound_volume
KEY_FENRIR,KEY_CTRL,KEY_SHIFT,KEY_C=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_CTRL,KEY_C=copy_last_echo_to_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_X=set_mark
KEY_FENRIR,KEY_SHIFT,KEY_X=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_RIGHT=next_quick_menu_entry
KEY_FENRIR,KEY_UP=next_quick_menu_value
KEY_FENRIR,KEY_LEFT=prev_quick_menu_entry
KEY_FENRIR,KEY_DOWN=prev_quick_menu_value
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

View File

@ -0,0 +1,78 @@
# how to use this file?
# the # on the beginning of the line is a comment
# the different sections are seperated by [<name>Dict] <name> is the section name. Dict is a keyword
# the entrys are seperated with :===: in words colon tripple equal colon ( to not collide with substitutions)
[levelDict]
none:===:
some:===:-$~+*-/\@
most:===:.,:-$~+*-/\@!#%^&*()[]}{<>;
all:===:!"#$%& \'()*+,-./:;<=>?@[\\]^_`{|}~
[punctDict]
:===:space
&:===:and
':===:apostrophe
@:===:at
\:===:backslash
|:===:bar
!:===:bang
^:===:carrot
::===:colon
,:===:comma
-:===:dash
$:===:dollar
.:===:dot
>:===:greater
`:===:grave
#:===:hash
{:===:left brace
[:===:left bracket
(:===:left paren
<:===:less
%:===:percent
+:===:plus
?:===:question?
":===:quote
):===:right paren
}:===:right brace
]:===:right bracket
;:===:semicolon
/:===:slash
*:===:star
~:===:tilde
_:===:line
=:===:equals
[customDict]
regex;(?i)certificates:===:certiffikets
regex;(?i)certificate:===:certifficate
regex;(?i)lowblow:===:LowBlow
regex;(?i)nginx:===:EngineX
regex;(?i)shit:===:shitt
regex;(?i)slither:===:slitther
[emoticonDict]
# This dictionary uses regexp when prefixed with "regex;", so be sure to escape anything that would be parsed by regexp, e.g. *, ., ^, $, etc.
regex;[\s*|'|"][\s*|'|"]<{-.-}>:===:Raves
regex;[\s*|'|"][\s*|'|"]8-\):===:smile with sunglasses
regex;[\s*|'|"][\s*|'|"]:-/:===:confused
regex;[\s*|'|"][\s*|'|"]-\.-:===:bugged
regex;[\s*|'|"][\s*|'|"]>\.<:===:laughing
regex;[\s*|'|"][\s*|'|"]8-X:===:skull
regex;[\s*|'|"][\s*|'|"]>:\):===:evil smile
regex;[\s*|'|"][\s*|'|"]>:-\):===:evil smile
regex;[\s*|'|"][\s*|'|"]\\o/:===:Hurray
regex;[\s*|'|"][\s*|'|"]:/:===:confused
regex;[\s*|'|"]:D[\s*|'|"]:===:laugh
regex;[\s*|'|"];\)[\s*|'|"]:===:wink
regex;[\s*|'|"]XD[\s*|'|"]:===:LOL
regex;[\s*|'|"]:-\)[\s*|'|"]:===:smile
regex;[\s*|'|"]:\)[\s*|'|"]:===:smile
regex;[\s*|'|"]->[\s*|'|"]:===:arrow right
# example for arrow left
#(?:[ |^])(<-)(?:[ ,.!?$]):===:arrow left
# or
#([ |^])<-([ ,.!?$]):===:arrow left\2
regex;[\s*|'|"]<-[\s*|'|"]:===:arrow left
regex;[\s+|'|"][O|o][O|o][\s+|'|"]:===:WTF?
regex;[\s*|'|"]\^\^[\s*|'|"]:===:enjoy smile

View File

@ -134,7 +134,10 @@ ignoreShortcuts=False
# the current shortcut layout located in /etc/fenrirscreenreader/keyboard
keyboardLayout=desktop
# echo chars while typing.
charEcho=True
# 0 = None
# 1 = always
# 2 = only while capslock
charEchoMode=2
## echo deleted chars
charDeleteEcho=True
# echo word after pressing space

View File

@ -0,0 +1,265 @@
[sound]
# Turn sound on or off:
enabled=True
# Select the driver used to play sounds, choices are genericDriver and gstreamerDriver.
# Sox 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.
theme=default
# Sound volume controls how loud the sounds for your selected soundpack are.
# 0 is quietest, 1.0 is loudest.
volume=1.0
# shell commands for generic sound driver
# the folowing variable are substituted
# fenrirVolume = the current volume setting
# fenrirSoundFile = the soundfile for an soundicon
# 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
#the following command is used to generate a frequency beep
genericFrequencyCommand=play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence
[speech]
# Turn speech on or off:
enabled=True
# Select speech driver, options are speechdDriver (default), genericDriver or espeakDriver:
# chrys: comment out genericDriver, uncomment speechdDriver
driver=speechdDriver
#driver=espeakDriver
#driver=genericDriver
# server path for emacspeak
serverPath=/home/chrys/Projekte/emacspeak/servers/espeak
# The rate selects how fast Fenrir will speak. Options range from 0, slowest, to 1.0, fastest.
rate=0.65
# 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
# Volume controls the loudness of the voice, select from 0, quietest, to 1.0, loudest.
volume=1.0
# Module is used for Speech-dispatcher, to select the speech module you want to use.
# Consult Speech-dispatcher's configuration and help Fenrir find out which modules are available.
# The default is specified in speechd.conf.
# chrys: uncomment module, set it to voxin (default espeak-ng)
module=voxin
# Voice selects the voice you want to use, for example, en-GB-scotland will use the Scotish English voice in Espeak,
# To find out which voices are available, consult the documentation provided with your selected synthesizer.
# This also sets the voice used in the generic driver.
# You can add a variant by adding +name onto the end.
# chrys: set voice (default was en-us)
voice=allison-embedded-high
# Select the language you want Fenrir to use.
# chrys: uncomment language and set language to en-US (default was en)
language=en
# Read new text as it happens?
autoReadIncoming=True
# genericSpeechCommand is the command that is executed for talking
# the following variables are replaced with values
# fenrirText = is the text that should be spoken
# fenrirModule = may be the speech module like used in speech-dispatcher, not every TTY need this
# fenrirLanguage = the language
# fenrirVoice = is the current voice that should be used. Set the voice variable above.
# the current volume, pitch and rate is calculated like this
# value = min + settingValue * (min - max )
# 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"
# those are the 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
[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
screenUpdateDelay=0.05
suspendingScreen=
autodetectSuspendingScreen=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
# the current shortcut layout located in /etc/fenrirscreenreader/keyboard
keyboardLayout=desktop
# echo chars while typing.
# 0 = None
# 1 = always
# 2 = only while capslock
charEchoMode=2
# echo deleted chars
charDeleteEcho=True
# echo word after pressing space
wordEcho=False
# interrupt speech on any keypress
interruptOnKeyPress=True
# you can filter the keys on that the speech should interrupt (empty = all keys, otherwhise the given keys)
interruptOnKeyPressFilter=
# timeout for double tap in sec
doubleTapTimeout=0.2
[general]
debugLevel=0
# debugMode sets where the debug output should send to:
# debugMode=File writes to debugFile (Default:/tmp/fenrir-PID.log)
# debugMode=Print just prints on the screen
debugMode=File
debugFile=
punctuationProfile=default
punctuationLevel=some
respectPunctuationPause=True
newLinePause=True
numberOfClipboards=10
# used path for "export_clipboard_to_file"
# $user is replaced by username
#clipboardExportPath=/home/$user/fenrirClipboard
clipboardExportPath=/tmp/fenrirClipboard
emoticons=True
# define the current Fenrir key
fenrirKeys=KEY_KP0,KEY_META,KEY_INSERT
scriptKeys=KEY_COMPOSE
timeFormat=%H:%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 are changeing
hasAttributes=True
# shell for PTY emulatiun (empty = default shell)
shell=
[focus]
#follow the text cursor
cursor=True
#follow highlighted text changes
highlight=False
[remote]
enable=True
# driver
# unixDriver = unix sockets
# tcpDriver = tcp (localhost only)
driver=unixDriver
# tcp port
port=22447
# socket filepath
socketFile=
# allow settings to overwrite
enableSettingsRemote=True
# allow commands to be executed
enableCommandRemote=True
[barrier]
enabled=True
leftBarriers=│└┌─
rightBarriers=│┘┐─
[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=
[menu]
vmenuPath=
quickMenu=speech#rate;speech#pitch;speech#volume
[time]
# automatic time anouncement
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=True
# interrupt current speech for time announcement
interrupt=False

View File

@ -136,7 +136,10 @@ ignoreShortcuts=False
# the current shortcut layout located in /etc/fenrirscreenreader/keyboard
keyboardLayout=desktop
# echo chars while typing.
charEcho=False
# 0 = None
# 1 = always
# 2 = only while capslock
charEchoMode=2
# echo deleted chars
charDeleteEcho=True
# echo word after pressing space

View File

@ -136,7 +136,10 @@ ignoreShortcuts=False
# the current shortcut layout located in /etc/fenrirscreenreader/keyboard
keyboardLayout=desktop
# echo chars while typing.
charEcho=False
# 0 = None
# 1 = always
# 2 = only while capslock
charEchoMode=2
# echo deleted chars
charDeleteEcho=True
# echo word after pressing space

View File

@ -137,7 +137,10 @@ ignoreShortcuts=False
# the current shortcut layout located in /etc/fenrirscreenreader/keyboard
keyboardLayout=desktop
# echo chars while typing.
charEcho=False
# 0 = None
# 1 = always
# 2 = only while capslock
charEchoMode=1
# echo deleted chars
charDeleteEcho=True
# echo word after pressing space

View File

@ -0,0 +1,261 @@
[sound]
# Turn sound on or off:
enabled=True
# Select the driver used to play sounds, choices are genericDriver and gstreamerDriver.
# Sox 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.
theme=default
# Sound volume controls how loud the sounds for your selected soundpack are.
# 0 is quietest, 1.0 is loudest.
volume=1.0
# shell commands for generic sound driver
# the folowing variable are substituted
# fenrirVolume = the current volume setting
# fenrirSoundFile = the soundfile for an soundicon
# 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
#the following command is used to generate a frequency beep
genericFrequencyCommand=play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence
[speech]
# Turn speech on or off:
enabled=True
# Select speech driver, options are speechdDriver (default), genericDriver or espeakDriver:
#driver=speechdDriver
#driver=espeakDriver
driver=genericDriver
# server path for emacspeak
serverPath=/home/chrys/Projekte/emacspeak/servers/espeak
# The rate selects how fast Fenrir will speak. Options range from 0, slowest, to 1.0, fastest.
rate=0.2
# 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
# Volume controls the loudness of the voice, select from 0, quietest, to 1.0, loudest.
volume=1.0
# Module is used for Speech-dispatcher, to select the speech module you want to use.
# Consult Speech-dispatcher's configuration and help Fenrir find out which modules are available.
# The default is specified in speechd.conf.
#module=espeak-ng
# Voice selects the voice you want to use, for example, en-GB-scotland will use the Scotish English voice in Espeak,
# To find out which voices are available, consult the documentation provided with your selected synthesizer.
# This also sets the voice used in the generic driver.
# You can add a variant by adding +name onto the end.
voice=0
# Select the language you want Fenrir to use.
#language=en
# Read new text as it happens?
autoReadIncoming=True
# genericSpeechCommand is the command that is executed for talking
# the following variables are replaced with values
# fenrirText = is the text that should be spoken
# fenrirModule = may be the speech module like used in speech-dispatcher, not every TTY need this
# fenrirLanguage = the language
# fenrirVoice = is the current voice that should be used. Set the voice variable above.
# the current volume, pitch and rate is calculated like this
# value = min + settingValue * (min - max )
# fenrirVolume = is replaced with the current volume
# fenrirPitch = is replaced with the current pitch
# fenrirRate = is replaced with the current speed (speech rate)
genericSpeechCommand=/opt/dectalk/say -v fenrirVolume -r fenrirRate -s fenrirVoice -a "fenrirText"
# those are the min and max values of the TTS system that is used in genericSpeechCommand
fenrirMinVolume=0
fenrirMaxVolume=100
fenrirMinPitch=0
fenrirMaxPitch=99
fenrirMinRate=75
fenrirMaxRate=600
[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
screenUpdateDelay=0.05
suspendingScreen=
autodetectSuspendingScreen=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
# the current shortcut layout located in /etc/fenrirscreenreader/keyboard
keyboardLayout=desktop
# echo chars while typing.
# 0 = None
# 1 = always
# 2 = only while capslock
charEchoMode=1
# echo deleted chars
charDeleteEcho=True
# echo word after pressing space
wordEcho=False
# interrupt speech on any keypress
interruptOnKeyPress=True
# you can filter the keys on that the speech should interrupt (empty = all keys, otherwhise the given keys)
interruptOnKeyPressFilter=
# timeout for double tap in sec
doubleTapTimeout=0.2
[general]
debugLevel=0
# debugMode sets where the debug output should send to:
# debugMode=File writes to debugFile (Default:/tmp/fenrir-PID.log)
# debugMode=Print just prints on the screen
debugMode=File
debugFile=
punctuationProfile=default
punctuationLevel=some
respectPunctuationPause=True
newLinePause=True
numberOfClipboards=10
# used path for "export_clipboard_to_file"
# $user is replaced by username
#clipboardExportPath=/home/$user/fenrirClipboard
clipboardExportPath=/tmp/fenrirClipboard
emoticons=True
# define the current Fenrir key
fenrirKeys=KEY_KP0,KEY_META,KEY_INSERT
scriptKeys=KEY_COMPOSE
timeFormat=%H:%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 are changeing
hasAttributes=True
# shell for PTY emulatiun (empty = default shell)
shell=
[focus]
#follow the text cursor
cursor=True
#follow highlighted text changes
highlight=False
[remote]
enable=True
# driver
# unixDriver = unix sockets
# tcpDriver = tcp (localhost only)
driver=unixDriver
# tcp port
port=22447
# socket filepath
socketFile=
# allow settings to overwrite
enableSettingsRemote=True
# allow commands to be executed
enableCommandRemote=True
[barrier]
enabled=True
leftBarriers=│└┌─
rightBarriers=│┘┐─
[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=
[menu]
vmenuPath=
quickMenu=speech#rate;speech#pitch;speech#volume
[time]
# automatic time anouncement
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=True
# interrupt current speech for time announcement
interrupt=False

View File

@ -137,7 +137,10 @@ ignoreShortcuts=False
# the current shortcut layout located in /etc/fenrirscreenreader/keyboard
keyboardLayout=desktop
# echo chars while typing.
charEcho=False
# 0 = None
# 1 = always
# 2 = only while capslock
charEchoMode=2
# echo deleted chars
charDeleteEcho=True
# echo word after pressing space

View File

@ -88,7 +88,10 @@ device=ALL
grabDevices=True
ignoreShortcuts=False
keyboardLayout=desktop
charEcho=False
# 0 = None
# 1 = always
# 2 = only while capslock
charEchoMode=2
charDeleteEcho=True
wordEcho=False
interruptOnKeyPress=True

View File

@ -136,7 +136,10 @@ ignoreShortcuts=False
# the current shortcut layout located in /etc/fenrirscreenreader/keyboard
keyboardLayout=desktop
# echo chars while typing.
charEcho=False
# 0 = None
# 1 = always
# 2 = only while capslock
charEchoMode=2
# echo deleted chars
charDeleteEcho=True
# echo word after pressing space

File diff suppressed because it is too large Load Diff

11
play zone/pasteClipboardDemo.py Executable file
View File

@ -0,0 +1,11 @@
#!/bin/python3
import termios
import fcntl
def injectTextToScreen(text):
useScreen = "/dev/tty5"
with open(useScreen, 'w') as fd:
for c in text:
fcntl.ioctl(fd, termios.TIOCSTI, c)
injectTextToScreen('this is a test that works')

View File

@ -1,4 +1,4 @@
#!/bin/python
#!/usr/bin/env python3
#https://python-packaging.readthedocs.io/en/latest/minimal.html
import os, glob, sys
import os.path

View File

@ -0,0 +1,33 @@
#!/bin/python
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import line_utils
class command():
def __init__(self):
pass
def initialize(self, environment):
self.env = environment
def shutdown(self):
pass
def getDescription(self):
return _('read line to cursor pos, use review cursor if you are in review mode, otherwhise use text cursor')
def run(self):
cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor()
x, y, currLine = \
line_utils.getCurrentLine(cursorPos['x'], cursorPos['y'], self.env['screen']['newContentText'])
if currLine.isspace():
self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True)
else:
self.env['runtime']['outputManager'].presentText(currLine[:cursorPos['x']], interrupt=True)
self.env['runtime']['outputManager'].announceActiveCursor()
def setCallback(self, callback):
pass

View File

@ -26,7 +26,7 @@ class command():
if currLine.isspace():
self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True)
else:
self.env['runtime']['outputManager'].presentText(currLine[cursorPos['x']], interrupt=True)
self.env['runtime']['outputManager'].presentText(currLine[cursorPos['x']:], interrupt=True)
self.env['runtime']['outputManager'].announceActiveCursor()
def setCallback(self, callback):
pass

View File

@ -20,30 +20,37 @@ class command():
return _('Export current fenrir clipboard to X or GUI clipboard')
def run(self):
_thread.start_new_thread(self._threadRun , ())
def _threadRun(self):
try:
if self.env['runtime']['memoryManager'].isIndexListEmpty('clipboardHistory'):
self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True)
return
clipboard = self.env['runtime']['memoryManager'].getIndexListElement('clipboardHistory')
user = self.env['general']['currUser']
for display in range(10):
p = Popen('su ' + self.env['general']['currUser'] + ' -c "cat << \\\"EOF\\\" | xclip -d :' + str(display) + ' -selection clipboard\n' + clipboard + '\nEOF\n"', stdout=PIPE, stderr=PIPE, shell=True)
stdout, stderr = p.communicate()
p = Popen(
['su', user, '-c', f"xclip -d :{display} -selection clipboard"],
stdin=PIPE, stdout=PIPE, stderr=PIPE, preexec_fn=os.setpgrp
)
stdout, stderr = p.communicate(input=clipboard.encode('utf-8'))
self.env['runtime']['outputManager'].interruptOutput()
#screenEncoding = self.env['runtime']['settingsManager'].getSetting('screen', 'encoding')
stderr = stderr.decode('utf-8')
stdout = stdout.decode('utf-8')
if (stderr == ''):
if stderr == '':
break
#stderr = stderr.decode(screenEncoding, "replace").encode('utf-8').decode('utf-8')
#stdout = stdout.decode(screenEncoding, "replace").encode('utf-8').decode('utf-8')
if stderr != '':
self.env['runtime']['outputManager'].presentText(stderr , soundIcon='', interrupt=False)
self.env['runtime']['outputManager'].presentText(stderr, soundIcon='', interrupt=False)
else:
self.env['runtime']['outputManager'].presentText('exported to the X session.', interrupt=True)
except Exception as e:
self.env['runtime']['outputManager'].presentText(e , soundIcon='', interrupt=False)
self.env['runtime']['outputManager'].presentText(str(e), soundIcon='', interrupt=False)
def setCallback(self, callback):
pass

View File

@ -0,0 +1,30 @@
#!/bin/python
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import char_utils
class command():
def __init__(self):
pass
def initialize(self, environment):
self.env = environment
def shutdown(self):
pass
def getDescription(self):
return _('Move Review to the first character on the screen (left top)')
def run(self):
cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor()
self.env['runtime']['cursorManager'].setReviewCursorPosition(0 ,0)
self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], lastChar = \
char_utils.getLastCharInLine(self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText'])
self.env['runtime']['outputManager'].presentText(lastChar ,interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False)
self.env['runtime']['outputManager'].presentText(_("first character in screen"), interrupt=False)
def setCallback(self, callback):
pass

View File

@ -0,0 +1,30 @@
#!/bin/python
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
from fenrirscreenreader.core import debug
from fenrirscreenreader.utils import char_utils
class command():
def __init__(self):
pass
def initialize(self, environment):
self.env = environment
def shutdown(self):
pass
def getDescription(self):
return _('Move Review to the last character on the screen (right bottom)')
def run(self):
cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor()
self.env['runtime']['cursorManager'].setReviewCursorPosition(self.env['screen']['columns']-1 ,self.env['screen']['lines']-1)
self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], lastChar = \
char_utils.getLastCharInLine(self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText'])
self.env['runtime']['outputManager'].presentText(lastChar ,interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False)
self.env['runtime']['outputManager'].presentText(_("last character in screen"), interrupt=False)
def setCallback(self, callback):
pass

View File

@ -18,8 +18,14 @@ class command():
def run(self):
# enabled?
if not self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'charEcho'):
active = self.env['runtime']['settingsManager'].getSettingAsInt('keyboard', 'charEchoMode')
# 0 = off
if active == 0:
return
# 2 = caps only
if active == 2:
if not self.env['input']['newCapsLock']:
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 buffer for now)
xMove = abs(self.env['screen']['newCursor']['x'] - self.env['screen']['oldCursor']['x'])
if xMove > 3:
@ -42,6 +48,7 @@ class command():
currDelta.strip() != '':
currDelta = currDelta.strip()
self.env['runtime']['outputManager'].presentText(currDelta, interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False)
print(currDelta)
def setCallback(self, callback):
pass

View File

@ -1,5 +1,4 @@
#!/bin/python
import time
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
@ -12,47 +11,57 @@ import datetime
class command():
def __init__(self):
pass
def initialize(self, environment):
self.env = environment
self.lastTime = datetime.datetime.now()
self.lastDateString = ''
self.lastTimeString = ''
def shutdown(self):
pass
def getDescription(self):
return 'No Description found'
def run(self):
if not self.env['runtime']['settingsManager'].getSettingAsBool('time', 'enabled'):
return
onMinutes = self.env['runtime']['settingsManager'].getSetting('time', 'onMinutes')
delaySec = self.env['runtime']['settingsManager'].getSettingAsInt('time', 'delaySec')
# no need
if onMinutes == '' and delaySec <= 0:
return
onMinutes = onMinutes.split(',')
now = datetime.datetime.now()
# ignore onMinutes if there is a delaySec
if delaySec > 0:
if int((now-self.lastTime).total_seconds()) < delaySec:
return
if int((now - self.lastTime).total_seconds()) < delaySec:
return
else:
# shoul announce?
# should announce?
if not str(now.minute).zfill(2) in onMinutes:
return
# already announced?
if now.hour == self.lastTime.hour:
if now.minute == self.lastTime.minute:
return
dateFormat = self.env['runtime']['settingsManager'].getSetting('general', 'dateFormat')
dateString = datetime.datetime.strftime(now, dateFormat)
presentDate = self.env['runtime']['settingsManager'].getSettingAsBool('time', 'presentDate') and \
self.lastDateString != dateString
self.lastDateString != dateString
presentTime = self.env['runtime']['settingsManager'].getSettingAsBool('time', 'presentTime')
# no changed value to announce
if not (presentDate or presentTime):
return
timeFormat = self.env['runtime']['settingsManager'].getSetting('general', 'timeFormat')
timeString = datetime.datetime.strftime(now, timeFormat)
@ -64,11 +73,13 @@ class command():
if presentTime:
# present the time
self.env['runtime']['outputManager'].presentText(_("It's {0}").format(timeString.replace(':00', " O'clock ").lstrip('0')), soundIcon='', interrupt=False)
# and date if changes
if presentDate:
self.env['runtime']['outputManager'].presentText(dateString , soundIcon='', interrupt=False)
self.lastDateString = dateString
# Check if it's 12:00 AM
if now.hour == 0 and now.minute == 0:
# present the date
self.env['runtime']['outputManager'].presentText(dateString, soundIcon='', interrupt=False)
self.lastTime = datetime.datetime.now()
self.lastTimeString = timeString
def setCallback(self, callback):
pass

View File

@ -85,7 +85,9 @@ class fenrirManager():
if self.environment['runtime']['inputManager'].noKeyPressed():
self.modifierInput = False
self.singleKeyCommand = False
self.environment['runtime']['inputManager'].writeEventBuffer()
self.environment['runtime']['inputManager'].handleDeviceGrab()
if self.environment['input']['keyForeward'] > 0:
self.environment['input']['keyForeward'] -=1
self.environment['runtime']['commandManager'].executeDefaultTrigger('onKeyInput')

View File

@ -139,6 +139,8 @@ class inputManager():
self.env['input']['prevInput'] = []
def handleLedStates(self, mEvent):
if self.currKeyIsModifier():
return
try:
if mEvent['EventName'] == 'KEY_NUMLOCK':
self.env['runtime']['inputDriver'].toggleLedState()

View File

@ -124,7 +124,7 @@ settingsData = {
'grabDevices': True,
'ignoreShortcuts': False,
'keyboardLayout': "desktop",
'charEcho': False,
'charEchoMode': 2, # while capslock
'charDeleteEcho': True,
'wordEcho': True,
'interruptOnKeyPress': True,

View File

@ -34,6 +34,11 @@ class driver(screenDriver):
self.bgColorValues = {0: 'black', 1: 'blue', 2: 'green', 3: 'cyan', 4: 'red', 5: 'magenta', 6: 'brown/yellow', 7: 'white'}
self.fgColorValues = {0: 'black', 1: 'blue', 2: 'green', 3: 'cyan', 4: 'red', 5: 'magenta', 6: 'brown/yellow', 7: 'light gray', 8: 'dark gray', 9: 'light blue', 10: 'light green', 11: 'light cyan', 12: 'light red', 13: 'light magenta', 14: 'light yellow', 15: 'white'}
self.hichar = None
try:
# set workaround for paste clipboard -> injectTextToScreen
os.system('sysctl dev.tty.legacy_tiocsti=1')
except:
pass
def initialize(self, environment):
self.env = environment
self.env['runtime']['attributeManager'].appendDefaultAttributes([
@ -95,8 +100,23 @@ class driver(screenDriver):
except Exception as e:
self.env['runtime']['debug'].writeDebugOut('getSessionInformation: Maybe no LoginD:' + str(e),debug.debugLevel.ERROR)
#self.env['runtime']['debug'].writeDebugOut('getSessionInformation:' + str(self.env['screen']['autoIgnoreScreens']) + ' ' + str(self.env['general']) ,debug.debugLevel.INFO)
def updateWatchdog(self,active , eventQueue):
def readFile(self, file):
d = b''
file.seek(0)
try:
d = file.read()
except:
file.seek(0)
while True:
# Read from file
try:
d += file.readline(1)
if not d:
break
except Exception as e:
break
return d
def updateWatchdog(self, active , eventQueue):
try:
useVCSU = os.access('/dev/vcsu', os.R_OK)
vcsa = {}
@ -111,7 +131,7 @@ class driver(screenDriver):
index = str(vcsaDev[9:])
vcsa[index] = open(vcsaDev,'rb')
if index == currScreen:
lastScreenContent = vcsa[index].read()
lastScreenContent = self.readFile(vcsa[index])
if useVCSU:
vcsuDevices = glob.glob('/dev/vcsu*')
for vcsuDev in vcsuDevices:
@ -143,13 +163,13 @@ class driver(screenDriver):
oldScreen = currScreen
try:
vcsa[currScreen].seek(0)
lastScreenContent = vcsa[currScreen].read()
lastScreenContent = self.readFile(vcsa[currScreen])
except:
pass
vcsuContent = None
if useVCSU:
vcsu[currScreen].seek(0)
vcsuContent = vcsu[currScreen].read()
vcsuContent = self.readFile(vcsu[currScreen])
eventQueue.put({"Type":fenrirEventType.ScreenChanged,
"Data":self.createScreenEventData(currScreen, lastScreenContent, vcsuContent)
})
@ -157,7 +177,7 @@ class driver(screenDriver):
self.env['runtime']['debug'].writeDebugOut('ScreenUpdate',debug.debugLevel.INFO)
vcsa[currScreen].seek(0)
time.sleep(0.01)
dirtyContent = vcsa[currScreen].read()
dirtyContent = self.readFile(vcsa[currScreen])
screenContent = dirtyContent
vcsuContent = None
timeout = time.time()
@ -183,7 +203,7 @@ class driver(screenDriver):
#if not vcsa[currScreen] in r:
# break
vcsa[currScreen].seek(0)
dirtyContent = vcsa[currScreen].read()
dirtyContent = self.readFile(vcsa[currScreen])
if screenContent == dirtyContent:
break
if time.time() - timeout >= 0.1:
@ -191,7 +211,7 @@ class driver(screenDriver):
break
if useVCSU:
vcsu[currScreen].seek(0)
vcsuContent = vcsu[currScreen].read()
vcsuContent = self.readFile(vcsu[currScreen])
lastScreenContent = screenContent
eventQueue.put({"Type":fenrirEventType.ScreenUpdate,
"Data":self.createScreenEventData(currScreen, screenContent, vcsuContent)

275
tools/configure_pipewire.sh Executable file
View File

@ -0,0 +1,275 @@
#!/bin/bash
# This script configures pipewire to work both in the graphical environment and in the console with root apps.
if [[ $(whoami) != "root" ]]; then
# Get the current user's XDG_HOME
xdgPath="${XDG_CONFIG_HOME:-$HOME/.config}"
mkdir -p "$xdgPath/pipewire"
mkdir -p "$xdgPath/wireplumber/main.lua.d"
mkdir -p "$xdgPath/wireplumber/bluetooth.lua.d"
#create the file that tells the pipewire-pulse server to use a second socket located at /tmp/pulse.sock
# Warn user if we are going to overwrite an existing pipewire-pulse.conf
if [ -f "$xdgPath/pipewire/pipewire-pulse.conf" ]; then
read -p "This will replace the current file located at $xdgPath/pipewire/pipewire-pulse.conf, press enter to continue or control+c to abort. " continue
fi
cat << "EOF" > "$xdgPath/pipewire/pipewire-pulse.conf"
# PulseAudio config file for PipeWire version "0.3.49" #
#
# Copy and edit this file in /etc/pipewire for system-wide changes
# or in ~/.config/pipewire for local changes.
#
# It is also possible to place a file with an updated section in
# /etc/pipewire/pipewire-pulse.conf.d/ for system-wide changes or in
# ~/.config/pipewire/pipewire-pulse.conf.d/ for local changes.
#
context.properties = {
## Configure properties in the system.
#mem.warn-mlock = false
#mem.allow-mlock = true
#mem.mlock-all = false
#log.level = 2
#default.clock.quantum-limit = 8192
}
context.spa-libs = {
audio.convert.* = audioconvert/libspa-audioconvert
support.* = support/libspa-support
}
context.modules = [
{ name = libpipewire-module-rt
args = {
nice.level = -11
#rt.prio = 88
#rt.time.soft = -1
#rt.time.hard = -1
}
flags = [ ifexists nofail ]
}
{ name = libpipewire-module-protocol-native }
{ name = libpipewire-module-client-node }
{ name = libpipewire-module-adapter }
{ name = libpipewire-module-metadata }
{ name = libpipewire-module-protocol-pulse
args = {
# contents of pulse.properties can also be placed here
# to have config per server.
}
}
]
# Extra modules can be loaded here. Setup in default.pa can be moved here
context.exec = [
{ path = "pactl" args = "load-module module-always-sink" }
{ path = "pactl" args = "load-module module-switch-on-connect" }
#{ path = "/usr/bin/sh" args = "~/.config/pipewire/default.pw" }
]
stream.properties = {
#node.latency = 1024/48000
#node.autoconnect = true
#resample.quality = 4
#channelmix.normalize = false
#channelmix.mix-lfe = false
#channelmix.upmix = true
#channelmix.upmix-method = simple # none, psd
#channelmix.lfe-cutoff = 120
#channelmix.fc-cutoff = 6000
#channelmix.rear-delay = 12.0
#channelmix.stereo-widen = 0.1
#channelmix.hilbert-taps = 0
}
pulse.properties = {
# the addresses this server listens on
server.address = [
"unix:native"
"unix:/tmp/pulse.sock" # absolute paths may be used
#"tcp:4713" # IPv4 and IPv6 on all addresses
#"tcp:[::]:9999" # IPv6 on all addresses
#"tcp:127.0.0.1:8888" # IPv4 on a single address
#
#{ address = "tcp:4713" # address
# max-clients = 64 # maximum number of clients
# listen-backlog = 32 # backlog in the server listen queue
# client.access = "restricted" # permissions for clients
#}
]
#pulse.min.req = 256/48000 # 5ms
#pulse.default.req = 960/48000 # 20 milliseconds
#pulse.min.frag = 256/48000 # 5ms
#pulse.default.frag = 96000/48000 # 2 seconds
#pulse.default.tlength = 96000/48000 # 2 seconds
#pulse.min.quantum = 256/48000 # 5ms
#pulse.default.format = F32
#pulse.default.position = [ FL FR ]
# These overrides are only applied when running in a vm.
vm.overrides = {
pulse.min.quantum = 1024/48000 # 22ms
}
}
# client/stream specific properties
pulse.rules = [
{
matches = [
{
# all keys must match the value. ~ starts regex.
#client.name = "Firefox"
#application.process.binary = "teams"
#application.name = "~speech-dispatcher.*"
}
]
actions = {
update-props = {
#node.latency = 512/48000
}
# Possible quirks:"
# force-s16-info forces sink and source info as S16 format
# remove-capture-dont-move removes the capture DONT_MOVE flag
#quirks = [ ]
}
}
{
# skype does not want to use devices that don't have an S16 sample format.
matches = [
{ application.process.binary = "teams" }
{ application.process.binary = "skypeforlinux" }
]
actions = { quirks = [ force-s16-info ] }
}
{
# firefox marks the capture streams as don't move and then they
# can't be moved with pavucontrol or other tools.
matches = [ { application.process.binary = "firefox" } ]
actions = { quirks = [ remove-capture-dont-move ] }
}
{
# speech dispatcher asks for too small latency and then underruns.
matches = [ { application.name = "~speech-dispatcher*" } ]
actions = {
update-props = {
pulse.min.req = 1024/48000 # 21ms
pulse.min.quantum = 1024/48000 # 21ms
}
}
}
]
EOF
#Creates the file that tells pipewire not to suspend any sinks for all devices. This makes sure audio doesn't die after switching to the console.
# Warn user if we are going to overwrite an existing 50-do-not-suspend.lua
if [ -f "$xdgPath/wireplumber/main.lua.d/50-do-not-suspend.lua" ]; then
read -p "This will replace the current file located at $xdgPath/wireplumber/main.lua.d/50-do-not-suspend.lua, press enter to continue or control+c to abort. " continue
fi
echo 'alsa_monitor.rules = {
{
matches = {
{
{ "device.name", "matches", "alsa_card.*" },
},
},
apply_properties = {
["api.alsa.use-acp"] = true,
["api.acp.auto-profile"] = false,
["api.acp.auto-port"] = false,
["session.suspend-timeout-seconds"] = 0
},
},
{
matches = {
{
{ "node.name", "matches", "alsa_input.*" },
},
{
{ "node.name", "matches", "alsa_output.*" },
},
},
apply_properties = {
["session.suspend-timeout-seconds"] = 0
},
},
}' > $xdgPath/wireplumber/main.lua.d/50-do-not-suspend.lua
#Creates the file that disables the logind module for wireplumber which causes bluetooth to disconnect when switching tty
# Warn user if we are going to overwrite an existing 30-bluez-monitor.lua
if [ -f "$xdgPath/wireplumber/bluetooth.lua.d/30-bluez-monitor.lua" ]; then
read -p "This will replace the current file located at $xdgPath/wireplumber/bluetooth.lua.d/30-bluez-monitor.lua, press enter to continue or control+c to abort. " continue
fi
echo 'bluez_monitor = {}
bluez_monitor.properties = {}
bluez_monitor.rules = {}
function bluez_monitor.enable()
load_monitor("bluez", {
properties = bluez_monitor.properties,
rules = bluez_monitor.rules,
})
end' > $xdgPath/wireplumber/bluetooth.lua.d/30-bluez-monitor.lua
echo "Please ensure that your user is added to the audio group."
echo "If you have not yet done so, please run this script as root to write the client.conf file."
else
# This section does the root part:
xdgPath="/root/.config"
mkdir -p "$xdgPath/pulse"
# Warn user if we are going to overwrite an existing default.pa
if [ -f "$xdgPath/pulse/default.pa" ]; then
read -p "This will replace the current file located at $xdgPath/pulse/default.pa, press enter to continue or control+c to abort. " continue
fi
cat << EOF > "$xdgPath/pulse/client.conf"
# This file is part of PulseAudio.
#
# PulseAudio is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# PulseAudio is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
## Configuration file for PulseAudio clients. See pulse-client.conf(5) for
## more information. Default values are commented out. Use either ; or # for
## commenting.
; default-sink =
; default-source =
default-server = unix:/tmp/pulse.sock
; default-dbus-server =
autospawn = no
; autospawn = yes
; daemon-binary = /usr/bin/pulseaudio
; extra-arguments = --log-target=syslog
; cookie-file =
; enable-shm = yes
; shm-size-bytes = 0 # setting this 0 will use the system-default, usually 64 MiB
; auto-connect-localhost = no
; auto-connect-display = no
EOF
echo "If you have not yet done so, run this script as your normal user to write the user configs"
fi
# If there were no errors tell user to restart, else warn them errors happened.
if [ $? -eq 0 ]; then
echo "Configuration created successfully, please restart both Pipewire-pulseaudio and Wireplumber or your system, for changes to take affect."
else
echo "Errors were encountered whilst writing the configuration, please correct them manually."
fi
exit 0

View File

@ -5,6 +5,7 @@
if [[ $(whoami) != "root" ]]; then
# Get the current user's XDG_HOME
xdgPath="${XDG_CONFIG_HOME:-$HOME/.config}"
mkdir -p "$xdgPath/pulse"
# Warn user if we are going to overwrite an existing default.pa
if [ -f "$xdgPath/pulse/default.pa" ]; then

250
tools/fenrir-conf Normal file → Executable file
View File

@ -1,216 +1,66 @@
#!/bin/bash
#!/usr/bin/env python3
# Get user input args are return variable, question, options
get_input()
{
# Variable names are long, because we want absolutely no name conflicts.
local __get_input_input=$1
shift
local __get_input_question="$1"
shift
local __get_input_answer=""
local __get_input_i=""
local __get_input_continue=false
for __get_input_i in $@; do
if [ "${__get_input_i:0:1}" = "-" ]; then
local __get_input_default="${__get_input_i:1}"
fi
done
while [ $__get_input_continue = false ]; do
echo -n "$__get_input_question (${@/#-/}) "
if [ -n "$__get_input_default" ]; then
read -e -i "$__get_input_default" __get_input_answer
else
read -e __get_input_answer
fi
for __get_input_i in $@; do
if [ "$__get_input_answer" = "${__get_input_i/#-/}" ]; then
__get_input_continue=true
break
fi
done
done
__get_input_answer="${__get_input_answer//no/False}"
__get_input_answer="${__get_input_answer//yes/True}"
eval $__get_input_input="'$__get_input_answer'"
}
configFile="/etc/fenrirscreenreader/settings/settings.conf"
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributers.
if [ "$(whoami)" != "root" ]; then
echo "Please run $0 as root."
exit 1
fi
import os
import configparser
import dialog
if [ -f "$configFile" ]; then
read -p "This will replace your current settings, press enter to continue or control+C to abort." continue
fi
# Make sure dialog is accessible
os.environ['DIALOGOPTS'] = '--no-lines --visit-items'
# Initialize the dialog
tui = dialog.Dialog(dialog="dialog")
get_input sound "Enable sound?" -yes no
if [ "$sound" = "true" ]; then
get_input soundDriver "Select sound driver:" -generic gstreamer
else
soundDriver="generic"
fi
get_input speech "Enable speech?" -yes no
if [ "$speech" = "true" ]; then
get_input speechDriver "Select speech driver:" espeak -speechd
else
speechDriver="speechd"
fi
get_input charEcho "enable character echo?" -yes no
get_input wordEcho "enable word echo?" yes -no
# Define the path to the settings file
settings_file = '/etc/fenrirscreenreader/settings/settings.conf'
cat << EOF > "$configFile"
[sound]
# Turn sound on or off:
enabled=$sound
# Check write permissions for the settings file
if not os.access(settings_file, os.W_OK):
tui.msgbox("Error: Insufficient permissions to modify the settings file. Please run as root or with sudo.")
exit()
# Select the driver used to play sounds, choices are generic and gstreamer.
# Sox is the default.
driver=$soundDriver
while True:
# Load the settings file
config = configparser.ConfigParser()
config.read(settings_file)
# 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/fenrir/sounds
# For the current user.
theme=default
# Get a list of sections in the settings file
sections = config.sections()
# Sound volume controls how loud the sounds for your chosen soundpack are.
# 0 is quietest, 1.0 is loudest.
volume=1.0
# Select a section.
code, section = tui.menu("Select a section:", choices=[(s, "") for s in sections] + [("Exit", " ")])
# shell commands for generic sound driver
# the folowing variables are substituted
# fenrirVolume = the current volume setting
# fenrirSoundFile = the soundfile for an soundicon
# fenrirFrequence = the frequence to play
# fenrirDuration = the duration of the frequency
# the following command is used for play a soundfile
genericPlayFileCommand=play -q -v fenrirVolume fenrirSoundFile
#the following command is used for generating a frequency beep
genericFrequencyCommand=play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence
# Exit if the "Exit" option is chosen
if section == "Exit":
break
[speech]
# Turn speech on or off:
enabled=$speech
while True:
# Get the options in the selected section
options = config.options(section)
# Select speech driver, options are speechd (default) or espeak:
driver=$speechDriver
# Select a value to edit using dialog
code, option = tui.menu(f"Select a value to edit in '{section}':", choices=[(o, "") for o in options] + [("Go Back", " ")])
# Go back to the section menu if the "Go Back" option is chosen
if option == "Go Back":
break
# The rate selects how fast Fenrir will speak. Options range from 0, slowest, to 1.0, fastest.
rate=0.45
# If something is selected, prompt for a new value.
if code == tui.OK:
value = config.get(section, option)
code, new_value = tui.inputbox(f"Enter a new value for '{option}':", init=value)
# 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
# If a new setting is provided, update the configuration
if code == tui.OK:
config.set(section, option, new_value)
# Volume controls the loudness of the voice, select from 0, quietest, to 1.0, loudest.
volume=1.0
# Save changes.
with open(settings_file, 'w') as configfile:
config.write(configfile)
# Module is used for Speech-dispatcher, to select the speech module you want to use.
# Consult Speech-dispatcher's configuration and help to find out which modules are available.
# The default is Espeak.
module=espeak
# Voice selects the varient you want to use, for example, f5 will use the female voice #5 in espeak,
# or if using the espeak module in Speech-dispatcher. To find out which voices are available, consult the documentation provided with your selected synthesizer.
voice=
# Select the language you want Fenrir to use.
language=english-us
# Read new text as it happens?
autoReadIncoming=True
[braille]
#Braille is not implemented yet
enabled=False
driver=brlapi
layout=en
[screen]
driver=vcsa
encoding=auto
autodetectSuspendingScreen=True
[keyboard]
driver=evdev
# filter input devices NOMICE, ALL or a DEVICE NAME
device=ALL
# gives Fenrir exclusive access to the keyboard and lets it absorb keystrokes.
grabDevices=True
ignoreShortcuts=False
# the current shortcut layout located in /etc/fenrir/keyboard
keyboardLayout=$keyboard
# echo chars while typing.
charEcho=$charEcho
# echo deleted chars
charDeleteEcho=True
# echo word after pressing space
wordEcho=$wordEcho
# interrupt speech on any keypress
interruptOnKeyPress=$enterupt
# you can filter the keys that the speech should interrupt (empty = all keys, otherwise the given keys)
interruptOnKeyPressFilter=
# timeout for double tap in sec
doubleTapTimeout=0.2
[general]
debugLevel=0
# debugMode sets where the debug output should send to:
# debugMode=File writes to /var/log/fenrir.log
# debugMode=Print just prints on the screen
debugMode=File
punctuationProfile=default
punctuationLevel=some
respectPunctuationPause=True
newLinePause=True
numberOfClipboards=10
emoticons=True
# define the current Fenrir key
fenrirKeys=KEY_KP0,KEY_META,KEY_INSERT
scriptKey=KEY_COMPOSE
timeFormat=%H:%M:%P
dateFormat=%A, %B %d, %Y
autoSpellCheck=True
spellCheckLanguage=en_US
scriptPath=/usr/share/fenrirscreenreader/scripts
[focus]
#follow the text cursor
cursor=True
#follow highlighted text changes
highlight=False
[review]
lineBreak=True
endOfScreen=True
[promote]
enabled=True
inactiveTimeoutSec=120
list=
[time]
# automatic time anouncement
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=True
# interrupt current speech for time announcement
interrupt=False
EOF
echo "Settings saved to $configFile."
exit 0
tui.msgbox("Fenrir settings saved.")
else:
tui.msgbox("Changes discarded. Your Fenrir configuration has not been modified.")
else:
tui.msgbox("Canceled.")

View File

@ -6,8 +6,54 @@ if [[ "$(whoami)" != "root" ]]; then
exit 1
fi
write_pulse() {
sudo -u fenrirscreenreader cat << EOF > "/var/fenrirscreenreader/.config/pulse/client.conf"
# This script checks for, and creates if needed, the fenrirscreenreader user.
# Find out which group to use for uinput
uinput="$(stat -c '%G' /dev/uinput | grep -v root)"
if ! [[ "$uinput" =~ ^[a-zA-Z]+$ ]]; then
groupadd -r uinput
chown root:uinput /dev/uinput
fi
# find out which group to use for /dev/input.
input="$(stat -c '%G' /dev/input/* | grep -v root | head -1)"
if ! [[ "$input" =~ ^[a-zA-Z]+$ ]]; then
# Create the input group
groupadd --system input
echo 'KERNEL=="event*", NAME="input/%k", MODE="660", GROUP="input"' >> /etc/udev/rules.d/99-input.rules
input="input"
fi
# find out which group to use for /dev/tty.
tty="$(stat -c '%G' /dev/tty | grep -v root)"
if ! [[ "$tty" =~ ^[a-zA-Z]+$ ]]; then
# Create the tty group
groupadd --system tty
echo 'KERNEL=="event*", NAME="tty/%k", MODE="660", GROUP="tty"' >> /etc/udev/rules.d/99-tty.rules
tty="tty"
fi
# Add fenrirscreenreader
id fenrirscreenreader &> /dev/null ||
useradd -m -d /var/fenrirscreenreader -r -G $input,$tty,$uinput -s /bin/nologin -U fenrirscreenreader
#configure directory structure.
mkdir -p /var/log/fenrirscreenreader /etc/fenrirscreenreader
# Set directory ownership
chown -R fenrirscreenreader:fenrirscreenreader /var/log/fenrirscreenreader
chmod -R 755 /var/log/fenrirscreenreader
chown -R root:fenrirscreenreader /etc/fenrirscreenreader
# Fix permissions on tty#s
for i in /dev/tty[0-9]* ; do
chmod 660 "$i"
done
sudo -Hu fenrirscreenreader mkdir /var/fenrirscreenreader/.config/pulse
# Set up sound
cat << EOF > /var/fenrirscreenreader/.config/pulse/client.conf
# This file is part of PulseAudio.
#
# PulseAudio is free software; you can redistribute it and/or modify
@ -45,54 +91,6 @@ autospawn = no
; auto-connect-localhost = no
; auto-connect-display = no
EOF
}
# This script checks for, and creates if needed, the fenrirscreenreader user.
# Find out which group to use for uinput
uinput="$(stat -c '%G' /dev/uinput | grep -v root)"
if ! [[ "$uinput" =~ ^[a-zA-Z]+$ ]]; then
groupadd -r uinput
chown root:uinput /dev/uinput
fi
# find out which group to use for /dev/input.
input="$(stat -c '%G' /dev/input/* | grep -v root | head -1)"
if ! [[ "$input" =~ ^[a-zA-Z]+$ ]]; then
# Create the input group
groupadd --system input
echo 'KERNEL=="event*", NAME="input/%k", MODE="660", GROUP="input"' >> /etc/udev/rules.d/99-input.rules
input="input"
fi
# find out which group to use for /dev/tty.
tty="$(stat -c '%G' /dev/tty | grep -v root)"
if ! [[ "$tty" =~ ^[a-zA-Z]+$ ]]; then
# Create the tty group
groupadd --system tty
echo 'KERNEL=="event*", NAME="tty/%k", MODE="660", GROUP="tty"' >> /etc/udev/rules.d/99-tty.rules
tty="tty"
fi
# Add fenrirscreenreader
id fenrirscreenreader &> /dev/null || {
useradd -m -d /var/fenrirscreenreader -r -G $input,$tty,$uinput -s /bin/nologin -U fenrirscreenreader;
sleep 1;
sudo -u fenrirscreenreader mkdir -p /var/fenrirscreenreader/.config/pulse;
write_pulse;
}
#configure directory structure.
mkdir -p /var/log/fenrirscreenreader /etc/fenrirscreenreader
# Set directory ownership
chown -R fenrirscreenreader:fenrirscreenreader /var/log/fenrirscreenreader
chmod -R 755 /var/log/fenrirscreenreader
chown -R root:fenrirscreenreader /etc/fenrirscreenreader
# Fix permissions on tty#s
for i in /dev/tty[0-9]* ; do
chmod 660 "$i"
done
exit 0