diff --git a/.gitignore b/.gitignore index 926a6fc..44dcf25 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ __pycache__/ *\.pyc fenrir.egg-info/ +fenrir_screenreader.egg-info/ dist/ +build/ diff --git a/Changelog v1.0.txt b/Changelog v1.0.txt deleted file mode 100644 index 1a4a0f7..0000000 --- a/Changelog v1.0.txt +++ /dev/null @@ -1,204 +0,0 @@ -- move from VCS to VCSA and parese the Attributes -http://linux.die.net/man/4/vcsa -http://man.cx/vcsa(4)/de -http://manpages.org/display-vcsa/7 -https://en.wikipedia.org/wiki/Virtual_console -every second byte is a attribute others are text. fast way: c[::2],c[1::2] -http://manpages.ubuntu.com/manpages/precise/de/man4/vcs.4.html -https://docs.python.org/3/library/fcntl.html -http://rodrigorivas.serveblog.net/en/imagenes-desde-vt-con-vcsa/ -good doku: -http://angband.oook.cz/d/eyangband-052/src/main-vcs.c -http://manpages.ubuntu.com/manpages/trusty/man1/screader.1.html - -- implement speechdriver espeak -https://github.com/relsi/python-espeak - -- detect collumns in TTYs automaticaly. -it seems we have this info in vcsa - -- get current cursor -- shortcut handling -https://docs.python.org/2/library/termios.html -http://stackoverflow.com/questions/287757/pythons-configparser-unique-keys-per-section -0=down, 1=press, 2=hold -2KEY_SHIFT, 1KEY_A = say_current_line_cursor -- implement command structure -- implement speechdriver speechd -https://git.gnome.org/browse/orca/tree/src/orca/speech.py -https://git.gnome.org/browse/orca/tree/src/orca/speechdispatcherfactory.py -http://devel.freebsoft.org/doc/speechd/speech-dispatcher.html#Client-Programming - -- autodetect current TTY maybe with (PAM or a sys folder) -cat /sys/devices/virtual/tty/tty0/active -http://serverfault.com/questions/306854/how-to-find-out-the-currently-active-linux-virtual-terminal-while-connected-via - -- Input -http://python-evdev.readthedocs.io/en/latest/tutorial.html -http://stackoverflow.com/questions/12384772/how-can-i-capture-mouseevents-and-keyevents-using-python-in-background-on-linux -maybe TTY in RAW MODE - -- Settings (make it configureable) -- improve differ speed -- lock mechanism for threads -- restructure loops to listen for events - inputloop -> does block with an select - commands -> a new thread should spawned from inputloop - updatescreen -> maybe we could watch it with inotify vsca should support polling COMMENT: sadly not possible, poll events not fired as expected - https://github.com/seb-m/pyinotify/wiki/Tutorial - -import pyinotify -import glob -class Identity(pyinotify.ProcessEvent): - def process_default(self, event): - p = event.pathname - print(p) - -wm = pyinotify.WatchManager() - -notifier = pyinotify.Notifier(wm, default_proc_fun=Identity(), timeout=5) -wm.add_watch('/sys/devices/virtual/tty/tty0/active', pyinotify.IN_CLOSE_WRITE) -for file in list(glob.glob('/dev/vcsa[0-64]')): - wm.add_watch(file, pyinotify.IN_CLOSE_WRITE) - print(file) - -try: - while 1: - notifier.process_events() - if notifier.check_events( timeout=1000): - notifier.read_events() - print('events') - else: - print('timeout') -except KeyboardInterrupt: - notifier.stop() - print('fin') - - - https://www.infoq.com/articles/inotify-linux-file-system-event-monitoring - https://github.com/seb-m/pyinotify/wiki/Tutorial - http://www.saltycrane.com/blog/2010/04/monitoring-filesystem-python-and-pyinotify/ - -- add setting for ignore screens ( dont grab shortcuts from X or orca) -- soundIcons -- performance tuning -- add sound volume -- convert volume to percent in config -- convert pitch to percent in config -- convert rate to percent in config -- make screenUpdate rate configurable -- default soundIcon theme (soundfiles) -- debugging -- threading ReadContent, ReadShortcuts, executeCommands, listenNewTTYsForListen, controllThread (main) -- autoload plugins while starting -- implement sounddriver generic (use current sox and make it configurable) -- add setting for autodetect X -ps a -o tty,comm | grep -e Xorg | grep -v "grep -e Xorg" -- respect window mode in differ (getwindow code is already in place) -- parse punctuation setting file in conf/substitution - -- implement commands - curr_word - curr_char - next_word - next_char - prev_word - prev_char - enable_disable_speech #enable, disable speech - enable_disable_braile #enable, disable braile - enable_disable_sound #enable, disable sound - enable_disable_output #enable, disable speech, braile and sound - next_clipboard - prev_clipboard - first_clipboard - last_clipboard - curr_clipboard - paste_clipboard - define_window - remove_window - reset_review_on_screen_change - remove_clipboard_marks - copy_marked - set_mark (this could also used for area?) - read_clipboard_mark_text - curr_screen - curr_screen_before_cursor - curr_screen_after_cursor - cursor_position - indention - add_bookmark (per application) - remove_bookmark - present_bookmark - say_char_phonetic - spell_word_phonetic - "alpha", "bravo", "charlie", "delta", "echo", - "foxtrot", "golf", "hotel", "india", "juliet", - "kilo", "lima", "mike", "november", "oscar", - "papa", "quebec", "romeo", "sierra", "tango", - "uniform", "victor", "whisky", "x ray", - "yankee", "zulu" - next_char_phonetic - prev_char_phonetic - next_word_phonetic - prev_word_phonetic - toggle_highlighted_mode - -- implement onInput commands - read_line_if_cursor_change_vertical (needed if you arrow up and down, we want to announce the line) - read_char_if_cursur_change_horizontal (needed if you arrow left and right, we want to announce the char under the cursor) - echo_char (echos the last char on pressing space or return) - echo_word (echos the last word) - echo_deleted_char (echos deleted char on screen - read highlighted - -- implement onScreenChange commands - promoted text - clear_marks_on_screen_change - leve_review_mode_on_screen_change - window mode (define a area and just read that changes) - -- add screenManager - abstract screen driver -- pass environment instance in init and remove it from function calls - -- New Triggers - onAppChange - onAppProfileChange - onScreenChange - rename current onScreenChange to onScreenUpdate - -- rework inputManager - try to consume shortcuts - grab keyboard exclusive - release keyboard on error or quit - grab shortcuts with fenrir key - grab "singel key shortcuts" like numpad navigation for review - forwart nonshortcuts to system - make grabbing configuarble - possiblity to forewart shortcut [proxyshortcut] - possiblity to forewart shortcut (or use them as shortcut) [pressing twice while timeout] - cleanup inputManager - split input driver out of the handler - -- dictonary for special chars and string replacements -- punctuation -- beep on cursor to capital letters in cursor and review -- add pause handling - create pause - make it configurable when the pause the pause happens -- external scripting - load scripts from a folder as subprocess - create thread - load key definition of keybindings like SOPS did - -- add an daemonize mode -https://github.com/thesharp/daemonize -https://web.archive.org/web/20131017130434/http://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python/ - -- announce capslock -- anounce numlock -- anounce scroll -- add the debugging to core - -- autostart systemd -https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/System_Administrators_Guide/sect-Managing_Services_with_systemd-Unit_Files.html diff --git a/Changelog.txt b/Changelog.txt new file mode 100644 index 0000000..e04ea62 --- /dev/null +++ b/Changelog.txt @@ -0,0 +1,265 @@ +# Version 1.5 +- Doku: Write a user wiki + https://wiki.linux-a11y.org/doku.php?id=fenrir_user_manual&s[]=fenrir + +- initial working setup.py + +- available via pip (python packet manager) +sudo pip3 install fenrir-screenreader +https://pypi.python.org/pypi/fenrir-screenreader/1.5.post5 + +- leave review on typing + +- add dependency check (check-dependencys.py) + +- Add nice dummy drivers as template or for debugging + +- reimplement detection code for X11 + +- initial translate structure (manuelcortez Thanks!) + +- add a configurable place where you can place own commands or overwrite existing commands without need to change default code + +- implement autodetection of plugged and unplugged input devices + +- implement speechdriver generic + +- try to autodetect encoding (Easy for contribution) (Prototype "charmapTTY" in play zone) + +Braille Support (WIP): + - initial BrlTTY driver + - detect device size via driver + - output to braille device + - make flushMode configurable + - make flushTimeout configurable + - flush message after X seconds and show current line (review over text) + - tweak current commands and output + - command flush_braille + - command for scroll left + - command for scroll right + - create offset for scrolling + - respect scrolling + make cursor following configurable (brailleCursorTrackingMode) + - cell + - page + follow cursor while typing + brailleFocusMode: + - review = priority to review + +- move to an event based system + +- add initial multithreading/ multiprocessing support + +- support cli parameters + - add cli parameter for debugging "-d" + - add cli parameter to overwrite options "-o" + - add cli parameter to specify an settings.conf "-s" + +- list of bound commands in Tutorial Mode. speak name, binding and description. + +# Version: 1.00 + +- move from VCS to VCSA and parese the Attributes +http://linux.die.net/man/4/vcsa +http://man.cx/vcsa(4)/de +http://manpages.org/display-vcsa/7 +https://en.wikipedia.org/wiki/Virtual_console +every second byte is a attribute others are text. fast way: c[::2],c[1::2] +http://manpages.ubuntu.com/manpages/precise/de/man4/vcs.4.html +https://docs.python.org/3/library/fcntl.html +http://rodrigorivas.serveblog.net/en/imagenes-desde-vt-con-vcsa/ +good doku: +http://angband.oook.cz/d/eyangband-052/src/main-vcs.c +http://manpages.ubuntu.com/manpages/trusty/man1/screader.1.html + +- implement speechdriver espeak +https://github.com/relsi/python-espeak + +- detect collumns in TTYs automaticaly. +it seems we have this info in vcsa + +- get current cursor +- shortcut handling +https://docs.python.org/2/library/termios.html +http://stackoverflow.com/questions/287757/pythons-configparser-unique-keys-per-section +0=down, 1=press, 2=hold +2KEY_SHIFT, 1KEY_A = say_current_line_cursor +- implement command structure +- implement speechdriver speechd +https://git.gnome.org/browse/orca/tree/src/orca/speech.py +https://git.gnome.org/browse/orca/tree/src/orca/speechdispatcherfactory.py +http://devel.freebsoft.org/doc/speechd/speech-dispatcher.html#Client-Programming + +- autodetect current TTY maybe with (PAM or a sys folder) +cat /sys/devices/virtual/tty/tty0/active +http://serverfault.com/questions/306854/how-to-find-out-the-currently-active-linux-virtual-terminal-while-connected-via + +- Input +http://python-evdev.readthedocs.io/en/latest/tutorial.html +http://stackoverflow.com/questions/12384772/how-can-i-capture-mouseevents-and-keyevents-using-python-in-background-on-linux +maybe TTY in RAW MODE + +- Settings (make it configureable) +- improve differ speed +- lock mechanism for threads +- restructure loops to listen for events + inputloop -> does block with an select + commands -> a new thread should spawned from inputloop + updatescreen -> maybe we could watch it with inotify vsca should support polling COMMENT: sadly not possible, poll events not fired as expected + https://github.com/seb-m/pyinotify/wiki/Tutorial + +import pyinotify +import glob +class Identity(pyinotify.ProcessEvent): + def process_default(self, event): + p = event.pathname + print(p) + +wm = pyinotify.WatchManager() + +notifier = pyinotify.Notifier(wm, default_proc_fun=Identity(), timeout=5) +wm.add_watch('/sys/devices/virtual/tty/tty0/active', pyinotify.IN_CLOSE_WRITE) +for file in list(glob.glob('/dev/vcsa[0-64]')): + wm.add_watch(file, pyinotify.IN_CLOSE_WRITE) + print(file) + +try: + while 1: + notifier.process_events() + if notifier.check_events( timeout=1000): + notifier.read_events() + print('events') + else: + print('timeout') +except KeyboardInterrupt: + notifier.stop() + print('fin') + + + https://www.infoq.com/articles/inotify-linux-file-system-event-monitoring + https://github.com/seb-m/pyinotify/wiki/Tutorial + http://www.saltycrane.com/blog/2010/04/monitoring-filesystem-python-and-pyinotify/ + +- add setting for ignore screens ( dont grab shortcuts from X or orca) +- soundIcons +- performance tuning +- add sound volume +- convert volume to percent in config +- convert pitch to percent in config +- convert rate to percent in config +- make screenUpdate rate configurable +- default soundIcon theme (soundfiles) +- debugging +- threading ReadContent, ReadShortcuts, executeCommands, listenNewTTYsForListen, controllThread (main) +- autoload plugins while starting +- implement sounddriver generic (use current sox and make it configurable) +- add setting for autodetect X +ps a -o tty,comm | grep -e Xorg | grep -v "grep -e Xorg" +- respect window mode in differ (getwindow code is already in place) +- parse punctuation setting file in conf/substitution + +- implement commands + curr_word + curr_char + next_word + next_char + prev_word + prev_char + enable_disable_speech #enable, disable speech + enable_disable_braile #enable, disable braile + enable_disable_sound #enable, disable sound + enable_disable_output #enable, disable speech, braile and sound + next_clipboard + prev_clipboard + first_clipboard + last_clipboard + curr_clipboard + paste_clipboard + define_window + remove_window + reset_review_on_screen_change + remove_clipboard_marks + copy_marked + set_mark (this could also used for area?) + read_clipboard_mark_text + curr_screen + curr_screen_before_cursor + curr_screen_after_cursor + cursor_position + indention + add_bookmark (per application) + remove_bookmark + present_bookmark + say_char_phonetic + spell_word_phonetic + "alpha", "bravo", "charlie", "delta", "echo", + "foxtrot", "golf", "hotel", "india", "juliet", + "kilo", "lima", "mike", "november", "oscar", + "papa", "quebec", "romeo", "sierra", "tango", + "uniform", "victor", "whisky", "x ray", + "yankee", "zulu" + next_char_phonetic + prev_char_phonetic + next_word_phonetic + prev_word_phonetic + toggle_highlighted_mode + +- implement onInput commands + read_line_if_cursor_change_vertical (needed if you arrow up and down, we want to announce the line) + read_char_if_cursur_change_horizontal (needed if you arrow left and right, we want to announce the char under the cursor) + echo_char (echos the last char on pressing space or return) + echo_word (echos the last word) + echo_deleted_char (echos deleted char on screen + read highlighted + +- implement onScreenChange commands + promoted text + clear_marks_on_screen_change + leve_review_mode_on_screen_change + window mode (define a area and just read that changes) + +- add screenManager + abstract screen driver +- pass environment instance in init and remove it from function calls + +- New Triggers + onAppChange + onAppProfileChange + onScreenChange + rename current onScreenChange to onScreenUpdate + +- rework inputManager + try to consume shortcuts + grab keyboard exclusive + release keyboard on error or quit + grab shortcuts with fenrir key + grab "singel key shortcuts" like numpad navigation for review + forwart nonshortcuts to system + make grabbing configuarble + possiblity to forewart shortcut [proxyshortcut] + possiblity to forewart shortcut (or use them as shortcut) [pressing twice while timeout] + cleanup inputManager + split input driver out of the handler + +- dictonary for special chars and string replacements +- punctuation +- beep on cursor to capital letters in cursor and review +- add pause handling + create pause + make it configurable when the pause the pause happens +- external scripting + load scripts from a folder as subprocess + create thread + load key definition of keybindings like SOPS did + +- add an daemonize mode +https://github.com/thesharp/daemonize +https://web.archive.org/web/20131017130434/http://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python/ + +- announce capslock +- anounce numlock +- anounce scroll +- add the debugging to core + +- autostart systemd +https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/System_Administrators_Guide/sect-Managing_Services_with_systemd-Unit_Files.html diff --git a/README.md b/README.md index a466960..b1a07a8 100644 --- a/README.md +++ b/README.md @@ -1,51 +1,81 @@ -# fenrir 1.0 -An TTY screenreader for Linux. -Its an early alpha version. You can test it. It is not recommended for production use. In theorie its not limited to linux. but i currently only provide drivers for that because I have no ohter system here. If you want to help or write drivers to make it work on other systems, just let me know. +# Fenrir +A TTY screenreader for Linux. +In theory it's not just limited to Linux. but i currently only provide drivers for that since I do not have another system here. 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 . -# requirements (core) -- linux -- python3 -- python-evdev >=0.6.3 -- loaded uinput kernel module -- Read permission to the following files: - - /sys/devices/virtual/tty/tty0/active - - /dev/vcsa[1-64] -- ReadWrite permission - - /dev/input - - /dev/uinput -- speech, sound or braille drivers see "optional (features, drivers)". +# Requirements (core) +- Linux (currently only screen and input drivers available) +- python3 >= 3.3 +- python-configargparse +- screen, input, speech, sound or braille drivers see "Features, Drivers, Extras". -# optional (features, drivers) -- "espeak" speech driver: +# Features, Drivers, Extras, Dependencies +# Input Drivers: +1. "evdevDriver" input driver for linux evdev + - python-evdev >=0.6.3 + - python-pyudev +- This is commonly referred to as python3-evdev by your distribution + - loaded uinput kernel module + - ReadWrite permission + - /dev/input + - /dev/uinput + +# Screen Drivers: +1. "vcsaDriver" screen driver for linux VCSA devices + - python-dbus + - Read permission to the following files and services: + - /sys/devices/virtual/tty/tty0/active + - /dev/tty[1-64] + - /dev/vcsa[1-64] + - read logind DBUS + +# Speech Drivers: +1. "EspeakDriver" speech driver for Espeak: - python-espeak -- "speechd" speech driver: - - speech-dispatcher +- "speechdDriver" speech driver for Speech-dispatcher: + - Speech-dispatcher - python-speechd -- brltty braille driver (not implemented yet, WIP): +2. "dummyDriver" speech driver for debugging + +# Braille Drivers: +1. "BrlttyDriver" braille driver (WIP): - brltty (configured and running) - python-brlapi -- "generic" sound driver: - - sox -- "gstreamer" sound driver - - gstreamer 1.x +2. "dummyDriver" Braille driver for debugging + +# Sound Drivers: +1. "genericDriver" sound driver for sound as subprocess: + - Sox +2. "gstreamerDriver" sound driver for gstreamer + - gstreamer >=1.0 - GLib -- spellchecker +3. "dummyDriver" sound driver for debugging + +# Extras: +1. spellchecker - python-pyenchant - - aspell-YourLanguageCode (example aspell-en for us english) -- unix daemon: + - aspell-YourLanguageCode (example aspell-en for us English) +2. Unix daemon (also needed for Systemd): - python-daemonize +3. Modify system volume: + - pyalsaaudio (needs libasound2's headers). # installation - Archlinux: PKGBUILD in AUR -- install.sh (there is currently no uninstall) -- run from git: +- Manual: run install.sh and uninstall.sh as root +- you also can just run it from Git without installing: You can just run the following as root: -cd src/fenrir-package/ +if you are in Fenrir Git rootfolder: +cd src/fenrir/ sudo ./fenrir -Settings "settings.conf" is located in the "config" directory. -Take care that the used drivers in the config matching your installed drivers. +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: generic (via sox, could configured in settings.conf) -- speech driver: speechd -- braille driver: brltty (WIP) +- sound driver: genericDriver (via sox, could configured in settings.conf) +- speech driver: speechdDriver +- braille driver: brlttyDriver (WIP) +- input driver: evdevDriver + +# Documentation +You can see all information on the Wiki: +https://wiki.linux-a11y.org/doku.php?id=fenrir_user_manual&s[]=fenrir diff --git a/TODO v2.0 b/TODO v2.0 index bee4819..069557e 100644 --- a/TODO v2.0 +++ b/TODO v2.0 @@ -1,53 +1,87 @@ ToDo list for Fenrir Version 2.0 - +Things needing little knowledge are marked with "(Easy for contribution)". so just start with those :). +[] = ToDo +[W] = WIP +[X] = Done + +Cleanups: +- split oldValues := newValues out to helper function (Easy for contribution) + [] split it out + [] use it in vcsa driver +[] Migrate *Data.py to classes and use getter/setter (Easy for contribution) + [] commandsData.py + [] eventData.py + [] generalData.py + [] inputData.py + [] outputData.py + [] punctuationData.py + [] runtimeData.py + [] screenData.py + [] settingsData -> defaultSettings.py + General: -- implement onScreenUpdate commands - read highlighted text mode -- translateable -- be more event based -- try to make it more asynchronus -- multpible threads - -- implement commands - attributes_curr_char - generic list command (convert clipboard management) - next item - pref item - curr item - first item - last item +- commands +[] place last spoken to clipboard +- imporove attribute handling +[] improve attributes_curr_char +[] add an attribute sound +[] beep on cursor/ review by char (capital wins) +[] beep on review by word (once for multiple, capital wins) +[] configurable (by char, by word, none) + https://github.com/jwilk/vcsapeek/blob/master/linuxvt.py + +- Improved Say all +[] all the text of all pages +[] command to stop and place review cursor at this position +[] command to slow down speech on keypress + +- generic list or see Tutorial mode list (convert clipboard management) (Easy for contribution) +[] next item +[] prev item +[] curr item +[] first item +[] last item + +- make it runnable via pypy3 +[] wrapper script for running Fenrir to check if pypy exists, use python3 as fallback. Braille Support: - output to braille device - virtual buffer area for scroll left/right if the line is to long for device - commands for scroll left/right - print cursor in review - print cursor in textmode - flush message after X seconds and show current line (review over text) - make flush configurable - leve review mode on typing (show current textline) - capture input from braile - make routing keys assignable in keyboard - tweak current commands and output - http://mielke.cc/brltty/doc/Manual-BrlAPI/English/BrlAPI.html - https://git.gnome.org/browse/orca/tree/src/orca/braille.py - https://wiki.gnome.org/Attic/LSR/ScratchPad/Braille/BrlAPI + [] brailleFocusMode: + [] manual = no automatic toggle command used + [] last = follow last used cursor + [] print cursor in review + [] print cursor in textmode + [] word wrapping (if word does not fit print it at next page) + [] command toggle used cursor (in manual brailleFocusMode) + [] capture input from braile + [] make routing keys assignable by keyboard + [] make brailleTable configurable + [] pkg-config --variable=tablesdir liblouis + returns on Arch:/usr/share/liblouis/tables + http://mielke.cc/brltty/doc/Manual-BrlAPI/English/BrlAPI.html + https://git.gnome.org/browse/orca/tree/src/orca/braille.py + https://wiki.gnome.org/Attic/LSR/ScratchPad/Braille/BrlAPI + https://github.com/google/brailleback/blob/master/third_party/brltty/Bindings/Python/brlapi.pyx Driver: -- implement PTY Screen driver (to use gnome-terminal and other terminal emulators) -- ATK input driver (dont grab on graphical interface) -- BrlTTY driver +[W] PTY Screen driver (to use gnome-terminal and other terminal emulators) https://docs.python.org/3.2/library/pty.html -- implement speechdriver generic -- implement autodetection of plugged and removed input devices (python-pyudev) for evdev driver - http://askubuntu.com/questions/508236/how-can-i-run-code-whenever-a-usb-device-is-unplugged-without-requiring-root + http://sqizit.bartletts.id.au/2011/02/14/pseudo-terminals-in-python/ + https://blog.konpat.me/pythons-pseudo-terminal-pty-examples/ +[] talkey driver +[W] emacspeak driver +[W] PTY Input driver +[] ATK input driver (don't grab on graphical interface) + https://git.linux-a11y.org/AIT/pyatspi2/src/master/examples/keypress.py +[] Dectalk SpeechDriver (Easy for contribution, device needed - i dont own one) + https://github.com/tvraman/emacspeak/blob/master/servers/obsolete/python/dectalk.py Settings: -- configuration should be overwriteable with parameter and alternative paths -- write settings -- menue for settings configuration #storm +[] write settings (Easy for contribution) +[] menue for settings configuration (Easy for contribution) -Application Profiles +Application Profiles (low priority): +- reimplement process detection without subprocessing // this is started by chrys - fenrir is not able to detect the current application inside of screen. ps -e -H -o pid,pgrp,ppid,tty,cmd http://stackoverflow.com/questions/24861351/how-to-detect-if-python-script-is-being-run-as-a-background-process/24862213 @@ -57,4 +91,11 @@ per application commands per application onScreenChange per application onInput -- per application shortcuts +- per application shortcuts + +-----------DONE---------------- +General: +Braille Support: +Driver: +Settings: +Application Profiles: diff --git a/autostart/runit/fenrir/run b/autostart/runit/fenrir/run new file mode 100644 index 0000000..9364299 --- /dev/null +++ b/autostart/runit/fenrir/run @@ -0,0 +1,2 @@ +#!/bin/sh +exec fenrir diff --git a/bugs b/bugs new file mode 100644 index 0000000..25c7db6 --- /dev/null +++ b/bugs @@ -0,0 +1,15 @@ +Please report Bugs and feature requests to: +https://github.com/chrys87/fenrir/issues + +For bugs, please provide a debug file that shows the issue. +How to create a debug file: +1. first delete old stuff: +sudo rm /var/log/fenrir.log +2. start fenrir in debug mode +sudo fenrir -d + +3. +stop fenrir (fenrirKey + q) +the debug file is in /var/log/fenrir.log + +plese be as precise as possible to make it easy to solve the problem. diff --git a/check-dependencies.py b/check-dependencies.py new file mode 100755 index 0000000..fd90035 --- /dev/null +++ b/check-dependencies.py @@ -0,0 +1,173 @@ +#!/bin/env python3 +import os, sys + +# default installation +# core +# speech: speech-dispatcher +# sound: sox +# braille: brltty: +defaultInstallation = ['FenrirCore','vcsaDriver','brlapiDriver','evdevDriver','speechdDriver', 'genericDriver'] +currentInstallation = [] + +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 + +try: + import enchant + print('pyenchant: OK') +except: + print('pyenchant: FAIL') + available = available and False + +if available: + currentInstallation.append('FenrirCore') + +# SCREEN +print('') +print('screen driver') +# 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') + +# BRAILLE +print('') +print('braille driver') +# brltty (braille driver) +print('brlapiDriver') +available = True +try: + import brlapi + print('python3-brlapi: OK') +except: + print('python3-brlapi: FAIL') + available = available and False + +if available: + currentInstallation.append('brlapiDriver') +# INPUT +print('') +print('input driver') +# 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') +# SOUND +print('') +print('sound driver') +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') +# 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') + +# SPEECH +print('') +print('speech driver') +# 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') +# 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') + +# 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) + diff --git a/config/keyboard/Readme.md b/config/keyboard/Readme.md index 7e35dee..7b9d045 100644 --- a/config/keyboard/Readme.md +++ b/config/keyboard/Readme.md @@ -1,5 +1,5 @@ -Keymap for fenrir +Keymap for Fenrir KEY_RESERVED KEY_ESC KEY_1 diff --git a/config/keyboard/desktop.conf b/config/keyboard/desktop.conf index c2a90c7..8ae5e7a 100644 --- a/config/keyboard/desktop.conf +++ b/config/keyboard/desktop.conf @@ -1,106 +1,117 @@ -KEY_FENRIR,KEY_H=toggle_tutorial_mode -KEY_CTRL=shut_up -KEY_FENRIR,KEY_KP9=review_bottom -KEY_FENRIR,KEY_KP7=review_top -KEY_KP8=review_curr_line -KEY_KP7=review_prev_line -KEY_KP9=review_next_line -KEY_FENRIR,KEY_KP4=review_line_begin -KEY_FENRIR,KEY_KP6=review_line_end -KEY_FENRIR,KEY_KP1=review_line_first_char -KEY_FENRIR,KEY_KP3=review_line_last_char -KEY_FENRIR,KEY_ALT,KEY_1=present_first_line -KEY_FENRIR,KEY_ALT,KEY_2=present_last_line -KEY_KP5=review_curr_word -KEY_KP4=review_prev_word -KEY_KP6=review_next_word -KEY_FENRIR,KEY_SHIFT,KEY_KP5=review_curr_word_phonetic -KEY_FENRIR,KEY_SHIFT,KEY_KP4=review_prev_word_phonetic -KEY_FENRIR,KEY_SHIFT,KEY_KP6=review_next_word_phonetic -KEY_KP2=review_curr_char -KEY_KP1=review_prev_char -KEY_KP3=review_next_char -KEY_FENRIR,KEY_SHIFT,KEY_KP2=review_curr_char_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 -KEY_KPDOT=cursor_position -KEY_FENRIR,KEY_I=indent_curr_line -KEY_FENRIR,KEY_KPDOT=exit_review -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 -#=cursor_column -#=cursor_lineno -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 -KEY_KPPLUS=last_incoming -KEY_FENRIR,KEY_F2=toggle_braille -KEY_FENRIR,KEY_F3=toggle_sound -KEY_FENRIR,KEY_F4=toggle_speech -KEY_KPENTER=temp_disable_speech -KEY_FENRIR,KEY_CTRL,KEY_P=toggle_punctuation_level -KEY_FENRIR,KEY_RIGHTBRACE=toggle_auto_spell_check -KEY_FENRIR,KEY_BACKSLASH=toggle_output -KEY_FENRIR,KEY_CTRL,KEY_E=toggle_emoticons -key_FENRIR,KEY_KPENTER=toggle_auto_read -KEY_FENRIR,KEY_CTRL,KEY_T=toggle_auto_time -KEY_FENRIR,KEY_KPASTERISK=toggle_highlight_tracking -KEY_FENRIR,KEY_Q=quit_fenrir -KEY_FENRIR,KEY_T=time -2,KEY_FENRIR,KEY_T=date -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_UP=inc_speech_volume -KEY_FENRIR,KEY_DOWN=dec_speech_volume -KEY_FENRIR,KEY_RIGHT=inc_speech_rate -KEY_FENRIR,KEY_LEFT=dec_speech_rate -KEY_FENRIR,KEY_ALT,KEY_RIGHT=inc_speech_pitch -KEY_FENRIR,KEY_ALT,KEY_LEFT=dec_speech_pitch -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_CTRL,KEY_SHIFT,KEY_X=remove_marks -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_X=set_mark -KEY_FENRIR,KEY_SHIFT,KEY_X=marked_text -KEY_FENRIR,KEY_C=copy_marked_to_clipboard -KEY_FENRIR,KEY_V=paste_clipboard +KEY_FENRIR,KEY_H=toggle_tutorial_mode +KEY_CTRL=shut_up +KEY_FENRIR,KEY_KP9=review_bottom +KEY_FENRIR,KEY_KP7=review_top +KEY_KP8=review_curr_line +KEY_KP7=review_prev_line +KEY_KP9=review_next_line +KEY_FENRIR,KEY_KP4=review_line_begin +KEY_FENRIR,KEY_KP6=review_line_end +KEY_FENRIR,KEY_KP1=review_line_first_char +KEY_FENRIR,KEY_KP3=review_line_last_char +KEY_FENRIR,KEY_ALT,KEY_1=present_first_line +KEY_FENRIR,KEY_ALT,KEY_2=present_last_line +KEY_KP5=review_curr_word +KEY_KP4=review_prev_word +KEY_KP6=review_next_word +KEY_FENRIR,KEY_SHIFT,KEY_KP5=review_curr_word_phonetic +KEY_FENRIR,KEY_SHIFT,KEY_KP4=review_prev_word_phonetic +KEY_FENRIR,KEY_SHIFT,KEY_KP6=review_next_word_phonetic +KEY_KP2=review_curr_char +KEY_KP1=review_prev_char +KEY_KP3=review_next_char +KEY_FENRIR,KEY_SHIFT,KEY_KP2=review_curr_char_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 +KEY_FENRIR,KEY_KPDOT=exit_review +KEY_KPDOT=cursor_position +KEY_FENRIR,KEY_I=indent_curr_line +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 +#=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 +KEY_KPPLUS=last_incoming +KEY_FENRIR,KEY_F2=toggle_braille +KEY_FENRIR,KEY_F3=toggle_sound +KEY_FENRIR,KEY_F4=toggle_speech +KEY_KPENTER=temp_disable_speech +KEY_FENRIR,KEY_CTRL,KEY_P=toggle_punctuation_level +KEY_FENRIR,KEY_RIGHTBRACE=toggle_auto_spell_check +KEY_FENRIR,KEY_BACKSLASH=toggle_output +KEY_FENRIR,KEY_CTRL,KEY_E=toggle_emoticons +key_FENRIR,KEY_KPENTER=toggle_auto_read +KEY_FENRIR,KEY_CTRL,KEY_T=toggle_auto_time +KEY_FENRIR,KEY_KPASTERISK=toggle_highlight_tracking +KEY_FENRIR,KEY_Q=quit_fenrir +KEY_FENRIR,KEY_T=time +2,KEY_FENRIR,KEY_T=date +KEY_KPMINUS=attribute_cursor +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_UP=inc_speech_volume +KEY_FENRIR,KEY_DOWN=dec_speech_volume +KEY_FENRIR,KEY_RIGHT=inc_speech_rate +KEY_FENRIR,KEY_LEFT=dec_speech_rate +KEY_FENRIR,KEY_ALT,KEY_RIGHT=inc_speech_pitch +KEY_FENRIR,KEY_ALT,KEY_LEFT=dec_speech_pitch +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_C=copy_marked_to_clipboard +KEY_FENRIR,KEY_V=paste_clipboard +KEY_FENRIR,KEY_F5=import_clipboard_from_file +KEY_FENRIR,KEY_F6=export_clipboard_to_file +KEY_FENRIR,KEY_CTRL,KEY_SHIFT,KEY_X=remove_marks +KEY_FENRIR,KEY_X=set_mark +KEY_FENRIR,KEY_SHIFT,KEY_X=marked_text +# linux specific +KEY_FENRIR,KEY_F7=export_clipboard_to_x +KEY_FENRIR,KEY_CTRL,KEY_UP=inc_alsa_volume +KEY_FENRIR,KEY_CTRL,KEY_DOWN=dec_alsa_volume diff --git a/config/keyboard/laptop.conf b/config/keyboard/laptop.conf index 65d5398..45345da 100644 --- a/config/keyboard/laptop.conf +++ b/config/keyboard/laptop.conf @@ -1,106 +1,117 @@ -KEY_FENRIR,KEY_H=toggle_tutorial_mode -KEY_CTRL=shut_up -KEY_FENRIR,KEY_SHIFT,KEY_O=review_bottom -KEY_FENRIR,KEY_SHIFT,KEY_U=review_top -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_CTRL,KEY_J=review_line_first_char -KEY_FENRIR,KEY_CTRL,KEY_L=review_line_last_char -KEY_FENRIR,KEY_ALT,KEY_1=present_first_line -KEY_FENRIR,KEY_ALT,KEY_2=present_last_line -KEY_FENRIR,KEY_K=review_curr_word -KEY_FENRIR,KEY_J=review_prev_word -KEY_FENRIR,KEY_L=review_next_word -2,KEY_FENRIR,KEY_K=review_curr_word_phonetic -2,KEY_FENRIR,KEY_J=review_prev_word_phonetic -2,KEY_FENRIR,KEY_L=review_next_word_phonetic -KEY_FENRIR,KEY_COMMA=review_curr_char -KEY_FENRIR,KEY_M=review_prev_char -KEY_FENRIR,KEY_DOT=review_next_char -2,KEY_FENRIR,KEY_COMMA=curr_char_phonetic -2,KEY_FENRIR,KEY_M=prev_char_phonetic -2,KEY_FENRIR,KEY_DOT=prev_char_phonetic -KEY_FENRIR,KEY_CTRL,KEY_I=review_up -KEY_FENRIR,KEY_CTRL,KEY_COMMA=review_down -KEY_FENRIR,KEY_SLASH=exit_review -KEY_FENRIR,KEY_SHIFT,KEY_DOT=cursor_position -KEY_FENRIR,KEY_SHIFT,KEY_K=curr_screen -KEY_FENRIR,KEY_SHIFT,KEY_I=curr_screen_before_cursor -KEY_FENRIR,KEY_SHIFT,KEY_COMMA=curr_screen_after_cursor -#=cursor_read_to_end_of_line -#=cursor_column -#=cursor_lineno -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_CTRL,KEY_8=set_window_application -2,KEY_FENRIR,KEY_CTRL,KEY_8=clear_window_application -2,KEY_FENRIR,KEY_I=indent_curr_line -KEY_FENRIR,KEY_SEMICOLON=last_incoming -KEY_FENRIR,KEY_F2=toggle_braille -KEY_FENRIR,KEY_F3=toggle_sound -KEY_FENRIR,KEY_F4=toggle_speech -KEY_FENRIR,KEY_ENTER=temp_disable_speech -KEY_FENRIR,KEY_SHIFT,KEY_CTRL,KEY_P=toggle_punctuation_level -KEY_FENRIR,KEY_RIGHTBRACE=toggle_auto_spell_check -KEY_FENRIR,KEY_SHIFT,KEY_ENTER=toggle_output -KEY_FENRIR,KEY_SHIFT,KEY_E=toggle_emoticons -KEY_FENRIR,KEY_ENTER=toggle_auto_read -KEY_FENRIR,KEY_CTRL,KEY_T=toggle_auto_time -KEY_FENRIR,KEY_Y=toggle_highlight_tracking -KEY_FENRIR,KEY_Q=quit_fenrir -KEY_FENRIR,KEY_T=time -2,KEY_FENRIR,KEY_T=date -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_UP=inc_speech_volume -KEY_FENRIR,KEY_DOWN=dec_speech_volume -KEY_FENRIR,KEY_RIGHT=inc_speech_rate -KEY_FENRIR,KEY_LEFT=dec_speech_rate -KEY_FENRIR,KEY_ALT,KEY_RIGHT=inc_speech_pitch -KEY_FENRIR,KEY_ALT,KEY_LEFT=dec_speech_pitch -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_CTRL,KEY_SHIFTDict] 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] + :===:Leer +&:===:Und +':===:Apostroph +@:===:At +\:===:Backslash +|:===:Pipe +!:===:Ausrufezeichen +^:===:Hoch +::===:Doppelpunkt +,:===:Komma +-:===:Minus +$:===:Dollar +.:===:Punkt +>:===:Größer als +`:===:Grave +#:===:Hash +{:===:Geschweifte Klammer auf +[:===:eckige Klammer auf +(:===:Klammer auf +<:===:Kleiner als +%:===:Prozent ++:===:Plus +?:===:Fragezeichen? +":===:Gänsefüßchen +):===:Klammer zu +}:===:Geschweifte Klammer zu +]:===:Eckige Klammer zu +;:===:Semikolon +/:===:Geteilt durch +*:===:Mal +~:===:Tilde +_:===:Lienie unten +=:===:Istgleich + +[customDict] + +[emoticonDict] +:):===:Grins +;):===:Zwinker +XD:===:loool +:D:===:Lach +<{-.-}>:===:Raves diff --git a/config/punctuation/default.conf b/config/punctuation/default.conf index 610e7bb..f290a80 100644 --- a/config/punctuation/default.conf +++ b/config/punctuation/default.conf @@ -4,7 +4,7 @@ # the entrys are seperated with :===: in words colon tripple equal colon ( to not collide with substitutions) [levelDict] none:===: -some:===:.-$~+*-/\@ +some:===:-$~+*-/\@ most:===:.,:-$~+*-/\@!#%^&*()[]}{<>; all:===:!"#$%& \'()*+,-./:;<=>?@[\\]^_`{|}~ @@ -47,6 +47,8 @@ [emoticonDict] :):===:smile -;):===:twinker -XD:===:loool -:D:===:lought +;):===:wink +XD:===:LOL +:D:===:laugh +<{-.-}>:===:Raves +\o/:===:Hurray diff --git a/config/punctuation/en.conf b/config/punctuation/en.conf new file mode 100644 index 0000000..21e51c0 --- /dev/null +++ b/config/punctuation/en.conf @@ -0,0 +1,53 @@ +# how to use this file? +# the # on the beginning of the line is a comment +# the different sections are seperated by [Dict] 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] + +[emoticonDict] +:):===:smile +;):===:twinker +XD:===:loool +:D:===:lought +<{-.-}>:===:Raves diff --git a/config/punctuation/es.conf b/config/punctuation/es.conf new file mode 100644 index 0000000..f95d3c7 --- /dev/null +++ b/config/punctuation/es.conf @@ -0,0 +1,53 @@ +# how to use this file? +# the # on the beginning of the line is a comment +# the different sections are seperated by [Dict] 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] + :===:espacio +&:===:et +':===:apóstrofo +@:===:arroba +\:===:barra inversa +|:===:barra vertical +!:===:Cerrar exclamación +^:===:circumplejo +::===:dos puntos +,:===:coma +-:===:guion +$:===:dólar +.:===:punto +>:===:mayor que +`:===:grave +#:===:signo de número +{:===:abrir yave +[:===:abrir corchete +(:===:abrir paréntesis +<:===:menor que +%:===:porciento ++:===:más +?:===:cerrar interrogación? +":===:comillas +):===:cerrar paréntesis +}:===:cerrar yave +]:===:cerrar corchete +;:===:punto y coma +/:===:barra +*:===:asterisco +~:===:tilde +_:===:subrayado +=:===:igual + +[customDict] + +[emoticonDict] +:):===:sonrisa +;):===:twinker +XD:===:loool +:D:===:lought +<{-.-}>:===:Raves diff --git a/config/punctuation/fr.conf b/config/punctuation/fr.conf new file mode 100644 index 0000000..ff36dff --- /dev/null +++ b/config/punctuation/fr.conf @@ -0,0 +1,53 @@ +# how to use this file? +# the # on the beginning of the line is a comment +# the different sections are seperated by [Dict] 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] + :===:espace +&:===:et +':===:apostrophe +@:===:arobase +\:===:barre oblique inversée +|:===:barre verticale +!:===:point d'exclamation +^:===:accent circonflexe +::===:deux points +,:===:virgule +-:===:tiret +$:===:dollar +.:===:point +>:===:suppérieur à +`:===:accent grave +#:===:dièse +{:===:accolade ouvrante +[:===:crochet ouvrant +(:===:parenthèse ouvrante +<:===:inférieur à +%:===:pourcent ++:===:plus +?:===:point d'interrogation +":===:guillemet +):===:parenthèse fermante +}:===:accolade fermante +]:===:crochet fermant +;:===:point virgule +/:===:barre oblique +*:===:astérisque +~:===:tildé +_:===:souligné +=:===:égale à + +[customDict] + +[emoticonDict] +:):===:sourire +;):===:clin d'oeil +XD:===:explosé de rire +:D:===:rire +<{-.-}>:===:Raves diff --git a/config/punctuation/pl.conf b/config/punctuation/pl.conf new file mode 100644 index 0000000..5935640 --- /dev/null +++ b/config/punctuation/pl.conf @@ -0,0 +1,53 @@ +# how to use this file? +# the # on the beginning of the line is a comment +# the different sections are seperated by [Dict] 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] + :===:spacja +&:===:ampersant +':===:apostrof +@:===:małpa +\:===:bekslesz +|:===:pionowa kreska +!:===:wykrzyknik +^:===:daszek +::===:dwukropek +,:===:przecinek +-:===:myślnik +$:===:dolar +.:===:kropka +>:===:większe +`:===:akcent +#:===:hasz +{:===:lewa klamra +[:===:lewy nawias kwadratowy +(:===:lewy nawias +<:===:mniejsze +%:===:procent ++:===:plus +?:===:pytajnik +":===:cudzysłów +):===:prawy nawias +}:===:prawa klamra +]:===:prawy nawias kwadratowy +;:===:średnik +/:===:slesz +*:===:gwiazdka +~:===:tylda +_:===:podkreślnik +=:===:równa się + +[customDict] + +[emoticonDict] +:):===:smile +;):===:twinker +XD:===:loool +:D:===:lought +<{-.-}>:===:Raves diff --git a/config/settings/espeak.settings.conf b/config/settings/espeak.settings.conf index 0b43b53..f2cae1b 100644 --- a/config/settings/espeak.settings.conf +++ b/config/settings/espeak.settings.conf @@ -4,13 +4,13 @@ # Select the driver used to play sounds, choices are generic and gstreamer. # Sox is the default. -driver=generic - -# Sound themes. This is the pack of sounds used for sound alerts. +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/fenrir/sounds # For the current user. -theme=default +theme=default-wav # Sound volume controls how loud the sounds for your chosen soundpack are. # 0 is quietest, 1.0 is loudest. @@ -24,19 +24,22 @@ # fenrirDuration = the duration of the frequence # the following command is used for play a soundfile genericPlayFileCommand=play -q -v fenrirVolume fenrirSoundFile 2>/dev/null -#the following command is used for generating a frequence beep +#the following command is used for generating a frequency beep genericFrequencyCommand=play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence 2>/dev/null [speech] # Turn speech on or off: enabled=True -# Select speech driver, options are speechd (default) or espeak: -#driver=speechd -driver=espeak - - -# The rate selects how fast fenrir will speak. Options range from 0, slowest, to 1.0, fastest. +# Select speech driver, options are speechdDriver (default), genericDriver or espeakDriver: +#driver=speechdDriver +#driver=genericDriver +driver=espeakDriver + +# server path for emacspeak +serverPath= + +# The rate selects how fast Fenrir will speak. Options range from 0, slowest, to 1.0, fastest. rate=0.35 # Pitch controls the pitch of the voice, select from 0, lowest, to 1.0, highest. @@ -47,39 +50,85 @@ # 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 ti find out which modules are available. -# The default is espeak. +# Module is used for Speech-dispatcher, to select the speech module you want to use. +# Consult Speech-dispatcher's configuration and help ti 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 chosen synthesizer. +# 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=f3 -# Select the language you want fenrir to use. +# Select the language you want Fenrir to use. language=en_US # 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 used in Speech-dispatcher, not every TTY needs this +# fenrirLanguage = the language +# fenrirVoice = is the current voice that should be used +# 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 -a fenrirVolume -s fenrirRate -p fenrirPitch -v fenrirVoice "fenrirText" + +# these are the minimum and maximum values of the TTS system used in genericSpeechCommand +fenrirMinVolume=0 +fenrirMaxVolume=200 +fenrirMinPitch=0 +fenrirMaxPitch=99 +fenrirMinRate=80 +fenrirMaxRate=450 + [braille] -#braille is not implemented yet enabled=False -driver=brlapi +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=vcsa -encoding=UTF-8 +driver=vcsaDriver +encoding=auto screenUpdateDelay=0.05 suspendingScreen= autodetectSuspendingScreen=True [keyboard] -driver=evdev +driver=evdevDriver # filter input devices NOMICE, ALL or a DEVICE NAME device=ALL -# gives fenrir exclusive access to the keyboard and let consume keystrokes. +# gives Fenrir exclusive access to the keyboard and let consume keystrokes. grabDevices=True ignoreShortcuts=False # the current shortcut layout located in /etc/fenrir/keyboard @@ -99,13 +148,17 @@ [general] debugLevel=0 +debugMode=File punctuationProfile=default punctuationLevel=some respectPunctuationPause=True newLinePause=True numberOfClipboards=10 +# used path for "export_clipboard_to_file" +# $user is replaced by username +clipboardExportPath=/tmp/fenrirClipboard emoticons=True -# define the current fenrir key +# define the current Fenrir key fenrirKeys=KEY_KP0,KEY_META scriptKey=KEY_COMPOSE timeFormat=%H:%M:%P @@ -113,6 +166,15 @@ autoSpellCheck=True spellCheckLanguage=en_US scriptPath=/usr/share/fenrir/scripts +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 [focus] cursor=True @@ -121,6 +183,10 @@ [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 diff --git a/config/settings/settings.conf b/config/settings/settings.conf index 019fff6..29ea299 100644 --- a/config/settings/settings.conf +++ b/config/settings/settings.conf @@ -1,148 +1,221 @@ -[sound] -# Turn sound on or off: -enabled=True - -# Select the driver used to play sounds, choices are generic and gstreamer. -# Sox is the default. -#driver=gstreamer -driver=generic - -# Sound themes. This is 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 - -# Sound volume controls how loud the sounds for your chosen soundpack are. -# 0 is quietest, 1.0 is loudest. -volume=1.0 - -# shell commands for generic sound driver -# the folowing variable are substituded -# fenrirVolume = the current volume setting -# fenrirSoundFile = the soundfile for an soundicon -# fenrirFrequence = the frequence to play -# fenrirDuration = the duration of the frequence -# the following command is used for play a soundfile -genericPlayFileCommand=play -q -v fenrirVolume fenrirSoundFile -#the following command is used for generating a frequence 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 speechd (default) or espeak: -driver=speechd -#driver=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 ti 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 chosen 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=cp850 -screenUpdateDelay=0.05 -suspendingScreen= -autodetectSuspendingScreen=True - -[keyboard] -driver=evdev -# filter input devices NOMICE, ALL or a DEVICE NAME -device=ALL -# gives fenrir exclusive access to the keyboard and let consume keystrokes. -grabDevices=True -ignoreShortcuts=False -# the current shortcut layout located in /etc/fenrir/keyboard -keyboardLayout=desktop -# echo chars while typing. -charEcho=False -# echo deleted chars -charDeleteEcho=True -# echo word after pressing space -wordEcho=False -# interrupt speech on any keypress -interruptOnKeyPress=False -# 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=1 -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/fenrir/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 +[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/fenrir/sounds +# For the current user. +theme=default-wav + +# 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.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 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. +# This also sets the voice used in the generic driver. +voice= + +# Select the language you want Fenrir to use. +language=english-us + +# 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 -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/fenrir/keyboard +keyboardLayout=desktop +# echo chars while typing. +charEcho=False +# echo deleted chars +charDeleteEcho=True +# echo word after pressing space +wordEcho=False +# interrupt speech on any keypress +interruptOnKeyPress=False +# 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 /var/log/fenrir.log +# debugMode=Print just prints on the screen +debugMode=File +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 +scriptKey=KEY_COMPOSE +timeFormat=%H:%M:%P +dateFormat=%A, %B %d, %Y +autoSpellCheck=True +spellCheckLanguage=en_US +# path for your scripts "scriptKey" functionality +scriptPath=/usr/share/fenrir/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 + +[focus] +#follow the text cursor +cursor=True +#follow highlighted text changes +highlight=False + +[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= + +[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 diff --git a/config/settings/settings.conf.chrys b/config/settings/settings.conf.chrys deleted file mode 100644 index a9c7678..0000000 --- a/config/settings/settings.conf.chrys +++ /dev/null @@ -1,147 +0,0 @@ -[sound] -# Turn sound on or off: -enabled=True - -# Select the driver used to play sounds, choices are generic and gstreamer. -# Sox is the default. -driver=generic - -# Sound themes. This is 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 - -# Sound volume controls how loud the sounds for your chosen soundpack are. -# 0 is quietest, 1.0 is loudest. -volume=1.0 - -# shell commands for generic sound driver -# the folowing variable are substituded -# fenrirVolume = the current volume setting -# fenrirSoundFile = the soundfile for an soundicon -# fenrirFrequence = the frequence to play -# fenrirDuration = the duration of the frequence -# the following command is used for play a soundfile -genericPlayFileCommand=play -q -v fenrirVolume fenrirSoundFile -#the following command is used for generating a frequence 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 speechd (default) or espeak: -driver=speechd -#driver=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 ti 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 chosen synthesizer. -voice= - -# Select the language you want fenrir to use. -language=de - -# Read new text as it happens? -autoReadIncoming=True - -[braille] -#braille is not implemented yet -enabled=True -driver=brlapi -layout=en - -[screen] -driver=vcsa -encoding=cp850 -screenUpdateDelay=0.05 -suspendingScreen= -autodetectSuspendingScreen=True - -[keyboard] -driver=evdev -# filter input devices NOMICE, ALL or a DEVICE NAME -device=ALL -# gives fenrir exclusive access to the keyboard and let consume keystrokes. just disable on problems. -grabDevices=True -ignoreShortcuts=False -# the current shortcut layout located in /etc/fenrir/keyboard -keyboardLayout=test -# echo chars while typing. -charEcho=False -# echo deleted chars -charDeleteEcho=True -# echo word after pressing space -wordEcho=False -# interrupt speech on any keypress -interruptOnKeyPress=False -# 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=2 -punctuationProfile=default -punctuationLevel=some -respectPunctuationPause=True -newLinePause=True -numberOfClipboards=10 -emoticons=True -# define the current fenrir key -fenrirKeys=KEY_KP0,KEY_META -scriptKey=KEY_COMPOSE -timeFormat=%H:%M:%P -dateFormat=%A, %B %d, %Y -autoSpellCheck=True -spellCheckLanguage=en_US -scriptPath=/usr/share/fenrir/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 x 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 -announce=True -# interrupt current speech for time announcement -interrupt=False diff --git a/config/settings/settings.conf.example b/config/settings/settings.conf.example new file mode 100644 index 0000000..47244b3 --- /dev/null +++ b/config/settings/settings.conf.example @@ -0,0 +1,222 @@ +[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/fenrir/sounds +# For the current user. +theme=default-wav + +# 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, emacspeak or espeakDriver: +driver=speechdDriver +#driver=espeakDriver +#driver=genericDriver +#driver=emacspeakDriver + +# 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 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. +# This also sets the voice used in the generic driver. +voice= + +# Select the language you want Fenrir to use. +language=english-us + +# 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 -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/fenrir/keyboard +keyboardLayout=desktop +# echo chars while typing. +charEcho=False +# echo deleted chars +charDeleteEcho=True +# echo word after pressing space +wordEcho=False +# interrupt speech on any keypress +interruptOnKeyPress=False +# 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 /var/log/fenrir.log +# debugMode=Print just prints on the screen +debugMode=File +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 +scriptKey=KEY_COMPOSE +timeFormat=%H:%M:%P +dateFormat=%A, %B %d, %Y +autoSpellCheck=True +spellCheckLanguage=en_US +# path for your scripts "scriptKey" functionality +scriptPath=/usr/share/fenrir/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 + +[focus] +#follow the text cursor +cursor=True +#follow highlighted text changes +highlight=False + +[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= + +[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 diff --git a/config/settings/settings.conf.storm b/config/settings/settings.conf.storm index 6f4f2e4..a51ca8e 100644 --- a/config/settings/settings.conf.storm +++ b/config/settings/settings.conf.storm @@ -1,97 +1,167 @@ -[sound] -enabled=True -driver=generic -theme=default -volume=1.0 -# shell commands for generic sound driver -genericPlayFileCommand=play -q -v fenrirVolume fenrirSoundFile -genericFrequencyCommand=play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence - -[speech] -enabled=True -driver=speechd -rate=0.85 -pitch=0.5 -# Pitch for capital letters -capitalPitch=0.9 -module=espeak -voice= -language=english-us -volume=1.0 -autoReadIncoming=True - -[braille] -enabled=False -driver=brlapi -layout=en - -[screen] -driver=vcsa -encoding=cp850 -screenUpdateDelay=0.05 -suspendingScreen=7 -autodetectSuspendingScreen=False - -[keyboard] -driver=evdev -# filter input devices NOMICE, ALL or a DEVICE NAME -device=ALL -grabDevices=True -ignoreShortcuts=False -keyboardLayout=desktop -charEcho=False -charDeleteEcho=True -wordEcho=False -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 -punctuationProfile=default -punctuationLevel=some -respectPunctuationPause=True -newLinePause=True -numberOfClipboards=10 -emoticons=True -fenrirKeys=KEY_KP0,KEY_META -scriptKey=KEY_COMPOSE -timeFormat=%H:%M:%P -dateFormat="%A, %B %d, %Y" -autoSpellCheck=True -spellCheckLanguage=en_US -scriptPath=/usr/share/fenrir/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 x 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 -announce=True -# interrupt current speech for time announcement -interrupt=False +[sound] +enabled=True +driver=genericDriver +theme=default +volume=1.0 +# shell commands for generic sound driver +genericPlayFileCommand=play -q -v fenrirVolume fenrirSoundFile +genericFrequencyCommand=play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence + +[speech] +enabled=True +driver=speechdDriver +#driver=genericDriver +serverPath= +rate=0.95 +pitch=0.5 +# Pitch for capital letters +capitalPitch=0.9 +module=espeak +voice=en-us +language=english-us +volume=1.0 +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 +# 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 -a fenrirVolume -s fenrirRate -p fenrirPitch -v fenrirVoice "fenrirText" + +# these 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=890 + +[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 +grabDevices=True +ignoreShortcuts=False +keyboardLayout=desktop +charEcho=False +charDeleteEcho=True +wordEcho=False +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=1 +# 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 +# used path for "export_clipboard_to_file" +# $user is replaced by username +clipboardExportPath=/tmp/fenrirClipboard +emoticons=True +fenrirKeys=KEY_KP0,KEY_META +scriptKey=KEY_COMPOSE +timeFormat=%H:%M:%P +dateFormat="%A, %B %d, %Y" +autoSpellCheck=True +spellCheckLanguage=en_US +scriptPath=/usr/share/fenrir/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 + +[focus] +#follow the text cursor +cursor=True +#follow highlighted text changes +highlight=False + +[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= + +[time] +# automatic time anouncement +enabled=False +# present time +presentTime=True +# present date (on change) +presentDate=True +# present time after x 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 +announce=True +# interrupt current speech for time announcement +interrupt=False diff --git a/contrib/fenrir-git/PKGBUILD b/contrib/fenrir-git/PKGBUILD deleted file mode 100644 index 73c7104..0000000 --- a/contrib/fenrir-git/PKGBUILD +++ /dev/null @@ -1,53 +0,0 @@ -# Maintainer: Storm Dragon -# Maintainer: Chrys - -_gitname='fenrir' -pkgname="${_gitname}-git" -pkgver=v0.2.5.g33af5b6 -pkgrel=3 -pkgdesc='A user space console screen reader written in python3' -arch=('any') -url='https://github.com/chrys87/${_pkgname}' -license=('MIT') -depends=('python' 'python-daemonize' 'python-evdev') -optdepends=('brltty: For Braille support' -'gstreamer: for soundicons via gstreamer' - 'sox: The default sound driver' - 'python-espeak: TTS support' - 'python-pyenchant: for spell check functionality' - 'speech-dispatcher: TTS support') -makedepends=('git') -provides=('fenrir') -conflicts=('fenrir') -install="$pkgname".install -source=("git+https://github.com/chrys87/${_gitname}.git" - 'fenrir-git.install') -md5sums=('SKIP' - '1387fd3851040d03816e2fb6b8fa631f') - -pkgver() -{ - cd "$srcdir/$_gitname" - local ver="$(git describe --tags)" - echo "${ver//-/.}" -} - -package() -{ - cd "$srcdir/$_gitname" - install -m755 -d "$pkgdir/opt/fenrir" - install -m755 -d "$pkgdir/usr/share/fenrir/scripts" - install -m755 -d "$pkgdir/usr/share/fenrir/tools" - install -m644 -D "config/keyboard/desktop.conf" "$pkgdir/etc/fenrir/keyboard/desktop.conf" - install -m644 -D "config/keyboard/laptop.conf" "$pkgdir/etc/fenrir/keyboard/laptop.conf" - install -m644 -D "config/punctuation/default.conf" "$pkgdir/etc/fenrir/punctuation/default.conf" - install -m644 -D "config/settings/settings.conf" "$pkgdir/etc/fenrir/settings/settings.conf" - install -d "$pkgdir/usr/share/sounds/fenrir" - install -m644 -D "autostart/systemd/fenrir.service" "$pkgdir/usr/lib/systemd/system/fenrir.service" - cp -a src/fenrir/* "$pkgdir/opt/fenrir" - cp -a config/scripts/* "$pkgdir/usr/share/fenrir/scripts" - cp -a tools/* "$pkgdir/usr/share/fenrir/tools" - cp -a config/sound/* "$pkgdir/usr/share/sounds/fenrir" -} - -# vim: set ts=2 sw=2 et: diff --git a/contrib/fenrir-git/fenrir-git.install b/contrib/fenrir-git/fenrir-git.install deleted file mode 100644 index 8d6d987..0000000 --- a/contrib/fenrir-git/fenrir-git.install +++ /dev/null @@ -1,15 +0,0 @@ -post_install() { -ln -s /opt/fenrir/fenrir-daemon /usr/bin/fenrir -_alert -} - -_alert() { -cat << EOF -To have fenrir start at boot: -sudo systemctl enable fenrir -Pulseaudio users may want to run -/usr/share/fenrir/tools/configure-pulseaudio -once as their user account and once as root. -EOF -} - diff --git a/contrib/rpm/howto.txt b/contrib/rpm/howto.txt new file mode 100644 index 0000000..397cd4b --- /dev/null +++ b/contrib/rpm/howto.txt @@ -0,0 +1 @@ +https://stackoverflow.com/questions/880227/what-is-the-minimum-i-have-to-do-to-create-an-rpm-file diff --git a/docu/create_manpage.sh b/docu/create_manpage.sh new file mode 100755 index 0000000..30bb538 --- /dev/null +++ b/docu/create_manpage.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# needs pandoc and php installed + +# remove old files +rm fenrir.1 +rm user.md + +# convert to markdown +php DokuWiki-to-Markdown-Converter/convert.php user.txt + +# convert markdown to manpage +pandoc user.md -f markdown -t man -s -o fenrir.1 + diff --git a/docu/fenrir.1 b/docu/fenrir.1 new file mode 100644 index 0000000..520360a --- /dev/null +++ b/docu/fenrir.1 @@ -0,0 +1,2764 @@ +.\"t +.\" Automatically generated by Pandoc 1.19.2.1 +.\" +.TH "" "" "" "" "" +.hy +.SH Fenrir User Manual +.PP +Fenrir is a modern command line screen reader written in Python3. +.PP +It has a modular structure, a flexible based driver model, is highly +configurable and easy to customize and extend (see Developer +Manual (fenrir_development_manual)). +.PP +Please see the following pages for the current (fenrir_current_version) +and Git (fenrir_git_version) version of Fenrir. +.SH Support and Requirements +.PP +Fenrir requires several drivers to interact with the operating system. +.SS Speech Drivers +.PP +A speech driver is for communication with the text to speech system like +Speech\-Dispatcher (#SpeechDispatcher) or +Espeak (http://espeak.sourceforge.net). +\\ See section Speech (#Speech) in \[aq]\[aq]settings.conf\[aq]\[aq] for +more information. +.SS SpeechDispatcher +.PP +This driver is used by default. +It uses Speech\-dispatcher as its backend. +.PP +Dependencies: +.IP \[bu] 2 +Speech\-dispatcher (installed and configured, +Documentation (https///devel.freebsoft.org/speechd#sec2)) +.IP \[bu] 2 +Python\-speechd +.SS Espeak +.PP +Uses Espeak via Python bindings. +.PP +Dependencies: +.IP \[bu] 2 +Espeak or Espeak\-ng +.IP \[bu] 2 +python\-espeak (https///launchpad.net/python-espeak) +.SS Generic +.PP +This invokes speech via a sub\-process. +This is almost the same as using the commandline. +The performance depends on the overhead of the speech synthesis +application but it is really flexible. +.PP +Dependencies: +.IP \[bu] 2 +Espeak or Espeak\-ng +.PP +The Requirements are flexible, they depend on the configuration in +settings.conf. +.SS Dummy +.PP +this is just for debugging, logs are output to the screen and logged as +well. +.SS Sound Drivers +.PP +To play sound icons and similar.\\ See section Sound (#Sound) in +\[aq]\[aq]settings.conf\[aq]\[aq] for more information. +.SS Generic +.PP +This driver is used by default. +.PP +Dependencies: +.IP \[bu] 2 +Sox (http://sox.sourceforge.net/) with opus support The Requirements are +flexible, they depend on the configuration in settings.conf. +.SS Gstreamer +.PP +if you prefer to use Gstreamer for sound output. +.PP +Dependencies: +.IP \[bu] 2 +Gstreamer >= 1.x +.IP \[bu] 2 +Glibc +.SS Dummy +.PP +this is just for debugging, logs are output to the screen and logged as +well. +.SS Input Drivers +.PP +Input drivers are to capture keyboard shortcuts issued to the screen +reader +.PD 0 +.P +.PD +See section Keyboard (#Keyboard) in \[aq]\[aq]settings.conf\[aq]\[aq] +for more information. +.SS Evdev +.PP +This driver is used by default. +.PP +Evdev is the low level input device framework for Linux. +.PP +Dependencies: +.IP \[bu] 2 +python\-evdev >=0.6.3 +.IP \[bu] 2 +pyudev +.IP \[bu] 2 +loaded uinput kernel module +.IP \[bu] 2 +exclusive access to the input devices Read permission to the following +files and services: +.IP \[bu] 2 +/dev/input +.IP \[bu] 2 +/dev/uinput +.SS Screen Drivers +.PP +The job of a screen driver is to get the information of current screen +content.\\ See section Screen (#Screen) in +\[aq]\[aq]settings.conf\[aq]\[aq] for more information. +.SS VCSA +.PP +This driver is used by default. +For Linux VCSA devices. +These exist on any current standard installation of Linux. +.PP +Dependencie s: +.IP \[bu] 2 +python\-dbus Read permission to the following files and services (or run +as root): +.IP \[bu] 2 +/sys/devices/virtual/tty/tty0/active +.IP \[bu] 2 +/dev/tty[1 \- 64] +.IP \[bu] 2 +/dev/vcsa[1 \- 64] (VCSA manpage (https///linux.die.net/man/4/vcsa)) +.IP \[bu] 2 +read Logind DBUS +.SS Braille Drivers +.PP +This is for Braille support. +Braille is currently a work in progress and is planned for the Fenrir +2.0 release.\\ See section Braille (#Braille) in +\[aq]\[aq]settings.conf\[aq]\[aq] for more information. +.SS BRLTTY +.PP +This driver is used by default. +It uses BrlTTY (brltty) to communicate with with a Braille device. +.PP +Dependencies: +.IP \[bu] 2 +BrlTTY (configured and running, +Documentation (http://mielke.cc/brltty/doc/Manual-BRLTTY/English/BRLTTY.html)) +.IP \[bu] 2 +python\-brlapi (configured, +Documentation (http://mielke.cc/brltty/doc/Manual-BrlAPI/English/BrlAPI.html)) +## Currently supported platforms +.PP +Currently Fenrir completely supports the following Platforms: +.IP \[bu] 2 +Linux TTY Support for further Systems are planned. +.SH Installation +.PP +Fenrir can run without installation. +It just requires the dependencies are installed first. +.PP +We recommend to try it out before installation to be sure everything +works and prevent yourself from experiencing a non\-talking environment. +.SS Try Out +.PP +Fenrir does not require installation. +You can try it and make sure everything works before you decide to +install. +In this way you can be sure that your system doesnt break or stop +talking. +for that you can just grab the code and run as root +\[aq]\[aq]src/fenrir/fenrir\[aq]\[aq] (in foreground) or +\[aq]\[aq]src/fenrir/fenrir\-daemon\[aq]\[aq] (in background, used by +systemd for autostart) +.SS Install it +.SS Documented operating systems +.SS Arch Linux +.PP +For Arch there are PKGBUILDs in the AUR: +.IP \[bu] 2 +fenrir (https///aur.archlinux.org/packages/fenrir/) +.IP \[bu] 2 +fenrir\-git (https///aur.archlinux.org/packages/fenrir-git/) +.SS Manual +.IP "1." 3 +Download the latest stable version from the +Fenrir\-Project (https///linux-a11y.org/index.php?page=fenrir-screenreader) +site. +.IP "2." 3 +Unpack the archive +.IP "3." 3 +Check the needed Dependencys by running +check\-dependencys.py (https///github.com/chrys87/fenrir/blob/master/check-dependencies.py) +script +.IP "4." 3 +install the missing dependencies an standard installation requires the +following: +.RS 4 +.IP \[bu] 2 +python3 >= 3.3 (and all the following is needed for python3 ) +.IP \[bu] 2 +python3\-speechd (screen) +.IP \[bu] 2 +python3\-dbus (screen) +.IP \[bu] 2 +python3\-evdev >= 0.6.4(input) +.IP \[bu] 2 +python3\-daemonize (background service) +.IP \[bu] 2 +python3\-brlapi (braille) +.IP \[bu] 2 +python3\-pyenchant (spellchecker) +.IP \[bu] 2 +your language for aspell (aspell\-\f[C]\f[]) (spellchecker) +.IP \[bu] 2 +sox (sound) +.IP \[bu] 2 +For an individual installation see Support and +Requirements (#Support%20and%20Requirements) or consult the +Readme (https///github.com/chrys87/fenrir/blob/master/README.md)) +.RE +.IP "5." 3 +run "install.sh" as root +.PP +this installs Fenrir as the following +.IP +.nf +\f[C] +*\ Application:\[aq]\[aq]/opt/fenrir\[aq]\[aq] +*\ Settings:\[aq]\[aq]/etc/fenrir\[aq]\[aq] +*\ Sound\ Icons:\[aq]\[aq]/usr/share/fenrir/\[aq]\[aq] +\f[] +.fi +.PP +to remove Fenrir just run uninstall.sh as root +.SS Git +.PP +if you want to get the latest code you can use git to get a development +snapshot: +.IP +.nf +\f[C] +git\ clone\ https://github.com/chrys87/fenrir.git +\f[] +.fi +.SS Auto Start +.PP +To start Fenrir once: systemctl start fenrir +.PP +To enable auto start on system boot: systemctl enable fenrir +.SH First Steps +.PP +If you are using Fenrir for the first time you may want to take a look +at these resources: +.IP \[bu] 2 +Keybindings (#Keybindings) +.IP \[bu] 2 +Tutorial Mode (#Tutorial%20Mode) +.SH Features +.SS Commands +.SS Keybindings +.PP +Normal commands can be invoked in two ways: 1. +Using a Metakey (FenrirKey (#Fenrir%20Key)) 2. +Shortcuts with a single key +.PP +See section Keyboard (#Keyboard) in \[aq]\[aq]settings.conf\[aq]\[aq] +for more information. +#### Fenrir Key +.PP +The Fenrir Key is for invoking screen reader commands. +Fenrir can utilize more than one FenrirKey at the same time. +By default the following keys are used: 1. +Insert 2. +KeyPad Insert 3. +Meta (Super, Windows) +.SS Script Key +.PP +To invoke "Scripts" the Script Key is mandatory. +The shortcut is encoded in the filename of the script. +See Scripting (#Scripting) #### Desktop Layout +.PP +.TS +tab(@); +l l. +T{ +Shortcut +T}@T{ +Command +T} +_ +T{ +FenrirKey + H +T}@T{ +toggle tutorial mode (#Tutorial%20Mode) +T} +T{ +CTRL +T}@T{ +shut up (interrupts speech) (#shut%20up) +T} +T{ +FenrirKey + KeyPad 9 +T}@T{ +reviews bottom (#review%20bottom) +T} +T{ +FenrirKey + KeyPad 7 +T}@T{ +reviews top (#review%20top) +T} +T{ +KeyPad 8 +T}@T{ +reviews current line (#review%20current%20line) +T} +T{ +KeyPad 7 +T}@T{ +reviews previous line (#review%20previous%20line) +T} +T{ +KeyPad 9 +T}@T{ +reviews next line (#review%20next%20line) +T} +T{ +FenrirKey + KeyPad 4 +T}@T{ +reviews line beginning (#review%20line%20beginning) +T} +T{ +FenrirKey + KeyPad 6 +T}@T{ +reviews line ending (#review%20line%20ending) +T} +T{ +FenrirKey + KeyPad 1 +T}@T{ +reviews line first character (#review%20line%20first%20character) +T} +T{ +FenrirKey + KeyPad 3 +T}@T{ +reviews line last character (#review%20line%20last%20character) +T} +T{ +FenrirKey + Alt + 1 +T}@T{ +presents first line (#present%20first%20line) +T} +T{ +FenrirKey + Alt + 2 +T}@T{ +presents last line (#present%20last%20line) +T} +T{ +KeyPad 5 +T}@T{ +reviews current word (#review%20current%20word) +T} +T{ +KeyPad 4 +T}@T{ +reviews previous word (#review%20previous%20word) +T} +T{ +KeyPad 6 +T}@T{ +reviews next word (#review%20next%20word) +T} +T{ +FenrirKey + Shift + KeyPad 5 +T}@T{ +reviews current word phonetic (#review%20current%20word%20phonetic) +T} +T{ +FenrirKey + Shift + KeyPad 4 +T}@T{ +reviews previous word phonetic (#review%20previous%20word%20phonetic) +T} +T{ +FenrirKey + Shift + KeyPad 6 +T}@T{ +reviews next word phonetic (#review%20next%20word%20phonetic) +T} +T{ +KeyPad 2 +T}@T{ +reviews current char (#review%20current%20character) +T} +T{ +KeyPad 1 +T}@T{ +reviews previous char (#review%20previous%20character) +T} +T{ +KeyPad 3 +T}@T{ +reviews next char (#review%20next%20character) +T} +T{ +FenrirKey + Shift + KeyPad 2 +T}@T{ +reviews current character +phonetic (#review%20current%20character%20phonetic) +T} +T{ +FenrirKey + Shift + KeyPad 1 +T}@T{ +reviews previous character +phonetic (#review%20previous%20character%20phonetic) +T} +T{ +FenrirKey + Shift + KeyPad 3 +T}@T{ +reviews next character phonetic (#review%20next%20character%20phonetic) +T} +T{ +FenrirKey + CTRL + KeyPad 8 +T}@T{ +reviews up (#review%20up) +T} +T{ +FenrirKey + CTRL + KeyPad 2 +T}@T{ +reviews down (#review%20down) +T} +T{ +FenrirKey + KeyPad dot +T}@T{ +exit review (#exit%20review) +T} +T{ +KeyPad dot +T}@T{ +cursor position (#cursor%20position) +T} +T{ +FenrirKey + I +T}@T{ +indent curr line (#indent%20current%20line) +T} +T{ +FenrirKey + KeyPad 5 +T}@T{ +current screen (#current%20screen) +T} +T{ +FenrirKey + KeyPad 8 +T}@T{ +current screen before cursor (#current%20screen%20before%20cursor) +T} +T{ +FenrirKey + KeyPad 2 +T}@T{ +current screen after cursor (#current%20screen%20after%20cursor) +T} +T{ +\f[C]\f[] +T}@T{ +cursor read to end of line (#cursor%20read%20to%20end%20of%20line) +T} +T{ +\f[C]\f[] +T}@T{ +cursor column (#cursor%20column) +T} +T{ +\f[C]\f[] +T}@T{ +cursor line number (#cursor%20line%20number) +T} +T{ +\f[C]\f[] +T}@T{ +Braille flush (#braille%20flush) +T} +T{ +\f[C]\f[] +T}@T{ +Braille pan left (#braille%20pan%20left) +T} +T{ +\f[C]\f[] +T}@T{ +Braille pan right (#braille%20pan%20right) +T} +T{ +\f[C]\f[] +T}@T{ +Braille return to cursor (#braille%20return%20to%20cursor) +T} +T{ +FenrirKey + CTRL + 1 +T}@T{ +clear bookmark 1 (#clear%20Bookmark%20X) +T} +T{ +FenrirKey + Shift + 1 +T}@T{ +set bookmark 1 (#set%20Bookmark%20X) +T} +T{ +FenrirKey + 1 +T}@T{ +bookmark 1 (#read%20Bookmark%20X) +T} +T{ +FenrirKey + CTRL + 2 +T}@T{ +clear bookmark 2 (#clear%20Bookmark%20X) +T} +T{ +FenrirKey + Shift + 2 +T}@T{ +set bookmark 2 (#set%20Bookmark%20X) +T} +T{ +FenrirKey + 2 +T}@T{ +bookmark 2 (#read%20Bookmark%20X) +T} +T{ +FenrirKey + CTRL + 3 +T}@T{ +clear bookmark 3 (#clear%20Bookmark%20X) +T} +T{ +FenrirKey + Shift + 3 +T}@T{ +set bookmark 3 (#set%20Bookmark%20X) +T} +T{ +FenrirKey + 3 +T}@T{ +bookmark 3 (#read%20Bookmark%20X) +T} +T{ +FenrirKey + CTRL + 4 +T}@T{ +clear bookmark 4 (#clear%20Bookmark%20X) +T} +T{ +FenrirKey + Shift + 4 +T}@T{ +set bookmark 4 (#set%20Bookmark%20X) +T} +T{ +FenrirKey + 4 +T}@T{ +bookmark 4 (#read%20Bookmark%20X) +T} +T{ +FenrirKey + CTRL + 5 +T}@T{ +clear bookmark 5 (#clear%20Bookmark%20X) +T} +T{ +FenrirKey + Shift + 5 +T}@T{ +set bookmark 5 (#set%20Bookmark%20X) +T} +T{ +FenrirKey + 5 +T}@T{ +bookmark 5 (#read%20Bookmark%20X) +T} +T{ +FenrirKey + CTRL + 6 +T}@T{ +clear bookmark 6 (#clear%20Bookmark%20X) +T} +T{ +FenrirKey + Shift + 6 +T}@T{ +set bookmark 6 (#set%20Bookmark%20X) +T} +T{ +FenrirKey + 6 +T}@T{ +bookmark 6 (#read%20Bookmark%20X) +T} +T{ +FenrirKey + CTRL + 7 +T}@T{ +clear bookmark 7 (#clear%20Bookmark%20X) +T} +T{ +FenrirKey + Shift + 7 +T}@T{ +set bookmark 7 (#set%20Bookmark%20X) +T} +T{ +FenrirKey + 7 +T}@T{ +bookmark 7 (#read%20Bookmark%20X) +T} +T{ +FenrirKey + CTRL + 8 +T}@T{ +clear bookmark 8 (#clear%20Bookmark%20X) +T} +T{ +FenrirKey + Shift + 8 +T}@T{ +set bookmark 8 (#set%20Bookmark%20X) +T} +T{ +FenrirKey + 8 +T}@T{ +bookmark 8 (#read%20Bookmark%20X) +T} +T{ +FenrirKey + CTRL + 9 +T}@T{ +clear bookmark 9 (#clear%20Bookmark%20X) +T} +T{ +FenrirKey + Shift + 9 +T}@T{ +set bookmark 9 (#set%20Bookmark%20X) +T} +T{ +FenrirKey + 9 +T}@T{ +bookmark 9 (#read%20Bookmark%20X) +T} +T{ +FenrirKey + CTRL + 0 +T}@T{ +clear bookmark 10 (#clear%20Bookmark%20X) +T} +T{ +FenrirKey + Shift + 0 +T}@T{ +set bookmark 10 (#set%20Bookmark%20X) +T} +T{ +FenrirKey + 0 +T}@T{ +bookmark 10 (#read%20Bookmark%20X) +T} +T{ +FenrirKey + KeyPad Slash +T}@T{ +set window application (#Create%20Window) +T} +T{ +2 * FenrirKey + KeyPad Slash +T}@T{ +clear window application (#Remove%20Window) +T} +T{ +KeyPad Plus +T}@T{ +read last incoming (#last%20incoming) +T} +T{ +FenrirKey + F2 +T}@T{ +toggles braille (#toggle%20braille) +T} +T{ +FenrirKey + F3 +T}@T{ +toggles sound (#toggle%20sound) +T} +T{ +FenrirKey + F4 +T}@T{ +toggles speech (#toggle%20speech) +T} +T{ +KeyPad Enter +T}@T{ +temporarily disables speech (#disable%20speech%20temporarily) +T} +T{ +FenrirKey + CTRL + P +T}@T{ +toggles punctuation level (#toggle%20punctuation%20level) +T} +T{ +FenrirKey + RightBrace +T}@T{ +toggle auto spell check (#toggle%20auto%20spell%20check) +T} +T{ +FenrirKey + Backslash +T}@T{ +toggles output (#toggle%20output) +T} +T{ +FenrirKey + CTRL + E +T}@T{ +toggles emoticons (#toggle%20emoticons) +T} +T{ +FenrirKey + KeyPad Enter +T}@T{ +toggles auto read (#toggle%20auto%20read) +T} +T{ +FenrirKey + CTRL + T +T}@T{ +toggles auto time (#toggle%20auto%20time) +T} +T{ +FenrirKey + KeyPad ASTERISK +T}@T{ +toggles highlight tracking (#toggle%20highlight%20tracking) +T} +T{ +FenrirKey + Q +T}@T{ +quits fenrir (#quit%20Fenrir) +T} +T{ +FenrirKey + T +T}@T{ +Announce time (#Time) +T} +T{ +2 * FenrirKey + T +T}@T{ +Announce date (#Date) +T} +T{ +FenrirKey + S +T}@T{ +spell check (#spell%20check) +T} +T{ +2 * FenrirKey + S +T}@T{ +add word to spell check (#add%20word%20to%20spell%20check) +T} +T{ +FenrirKey + Shift + S +T}@T{ +removes word from spell check (#removes%20word%20from%20spell%20check) +T} +T{ +FenrirKey + Backspace +T}@T{ +forward keypress (#forward%20keypress) +T} +T{ +FenrirKey + Up +T}@T{ +increase speech volume (#increase%20speech%20volume) +T} +T{ +FenrirKey + Down +T}@T{ +decrease speech volume (#decrease%20speech%20volume) +T} +T{ +FenrirKey + Right +T}@T{ +increase speech rate (#increase%20speech%20rate) +T} +T{ +FenrirKey + Left +T}@T{ +decrease speech rate (#decrease%20speech%20rate) +T} +T{ +FenrirKey + Alt + Right +T}@T{ +increase speech pitch (#increase%20speech%20pitch) +T} +T{ +FenrirKey + Alt + Left +T}@T{ +decrease speech pitch (#decrease%20speech%20pitch) +T} +T{ +FenrirKey + Alt + Up +T}@T{ +increase sound volume (#increase%20sound%20volume) +T} +T{ +FenrirKey + Alt + Down +T}@T{ +decrease sound volume (#decrease%20sound%20volume) +T} +T{ +FenrirKey + CTRL + Shift + C +T}@T{ +clears clipboard (#clear%20clipboard) +T} +T{ +FenrirKey + Home +T}@T{ +first clipboard (#first%20clipboard) +T} +T{ +FenrirKey + End +T}@T{ +last clipboard (#last%20clipboard) +T} +T{ +FenrirKey + PageUp +T}@T{ +previous clipboard (#previous%20clipboard) +T} +T{ +FenrirKey + PageDown +T}@T{ +next clipboard (#next%20clipboard) +T} +T{ +FenrirKey + Shift + C +T}@T{ +current clipboard (#read%20current%20clipboard) +T} +T{ +FenrirKey + C +T}@T{ +copy marked text to clipboard (#copy%20marked%20to%20clipboard) +T} +T{ +FenrirKey + V +T}@T{ +paste clipboard contents (#paste%20clipboard) +T} +T{ +FenrirKey + P +T}@T{ +import clipboard from file (#import%20clipboard%20from%20file) +T} +T{ +FenrirKey + Alt + Shift +C +T}@T{ +export clipboard to file (#export%20clipboard%20to%20file) +T} +T{ +FenrirKey + CTRL + Shift + X +T}@T{ +remove marks (#Remove%20Marks) +T} +T{ +FenrirKey + X +T}@T{ +set mark (#Set%20mark) +T} +T{ +FenrirKey + Shift + X +T}@T{ +announce marked text (#Get%20text%20between%20marks) +T} +T{ +Linux specific +T}@T{ +T} +T{ +\f[C]\f[] +T}@T{ +export clipboard to X +T} +T{ +FenrirKey + CTRL + Up +T}@T{ +include Alsa volume +T} +T{ +FenrirKey + CTRL + Down +T}@T{ +decrease Alsa volume +T} +.TE +.SS Laptop Layout +.PP +.TS +tab(@); +l l. +T{ +Shortcut +T}@T{ +Command +T} +_ +T{ +FenrirKey + H +T}@T{ +toggle tutorial mode (#Tutorial%20Mode) +T} +T{ +CTRL +T}@T{ +shut up (interrupts speech) (#shut%20up) +T} +T{ +FenrirKey + Shift + O +T}@T{ +reviews bottom (#review%20bottom) +T} +T{ +FenrirKey + Shift + U +T}@T{ +reviews top (#review%20top) +T} +T{ +FenrirKey + I +T}@T{ +reviews current line (#review%20current%20line) +T} +T{ +FenrirKey + U +T}@T{ +reviews previous line (#review%20previous%20line) +T} +T{ +FenrirKey + O +T}@T{ +reviews next line (#review%20next%20line) +T} +T{ +FenrirKey + Shift + J +T}@T{ +reviews line beginning (#review%20line%20beginning) +T} +T{ +FenrirKey + Shift + L +T}@T{ +reviews line ending (#review%20line%20ending) +T} +T{ +FenrirKey + CTRL + J +T}@T{ +reviews line first character (#review%20line%20first%20character) +T} +T{ +FenrirKey + CTRL + L +T}@T{ +reviews line last character (#review%20line%20last%20character) +T} +T{ +FenrirKey + Alt + 1 +T}@T{ +presents first line (#present%20first%20line) +T} +T{ +FenrirKey + Alt + 2 +T}@T{ +presents last line (#present%20last%20line) +T} +T{ +FenrirKey + K +T}@T{ +reviews current word (#review%20current%20word) +T} +T{ +FenrirKey + J +T}@T{ +reviews previous word (#review%20previous%20word) +T} +T{ +FenrirKey + L +T}@T{ +reviews next word (#review%20next%20word) +T} +T{ +FenrirKey + CTRL + ALT + K +T}@T{ +reviews current word phonetic (#review%20current%20word%20phonetic) +T} +T{ +FenrirKey + CTRL + ALT + J +T}@T{ +reviews previous word phonetic (#review%20previous%20word%20phonetic) +T} +T{ +FenrirKey + CTRL + ALT + L +T}@T{ +reviews next word phonetic (#review%20next%20word%20phonetic) +T} +T{ +FenrirKey + comma +T}@T{ +reviews current character (#review%20current%20character) +T} +T{ +FenrirKey + M +T}@T{ +reviews previous character (#review%20previous%20character) +T} +T{ +FenrirKey + dot +T}@T{ +reviews next character (#review%20next%20character) +T} +T{ +FenrirKey + CTRL + ALT + comma +T}@T{ +reviews current character +phonetic (#review%20current%20character%20phonetic) +T} +T{ +FenrirKey + CTRL + ALT + M +T}@T{ +reviews previous character +phonetic (#review%20previous%20character%20phonetic) +T} +T{ +FenrirKey + CTRL + ALT + dot +T}@T{ +reviews next character phonetic (#review%20next%20character%20phonetic) +T} +T{ +FenrirKey + CTRL + I +T}@T{ +reviews up (#review%20up) +T} +T{ +FenrirKey + CTRL + comma +T}@T{ +reviews down (#review%20down) +T} +T{ +FenrirKey + Slash +T}@T{ +exit review (#exit%20review) +T} +T{ +FenrirKey + Shift + dot +T}@T{ +cursor position (#cursor%20position) +T} +T{ +2 * FenrirKey + I +T}@T{ +indent curr line (#indent%20current%20line) +T} +T{ +FenrirKey + Shift + K +T}@T{ +current screen (#current%20screen) +T} +T{ +FenrirKey + Shift + I +T}@T{ +current screen before cursor (#current%20screen%20before%20cursor) +T} +T{ +FenrirKey + Shift + comma +T}@T{ +current screen after cursor (#current%20screen%20after%20cursor) +T} +T{ +\f[C]\f[] +T}@T{ +cursor read to end of line (#cursor%20read%20to%20end%20of%20line) +T} +T{ +\f[C]\f[] +T}@T{ +cursor column (#cursor%20column) +T} +T{ +\f[C]\f[] +T}@T{ +cursor line number (#cursor%20line%20number) +T} +T{ +\f[C]\f[] +T}@T{ +Braille flush (#braille%20flush) +T} +T{ +\f[C]\f[] +T}@T{ +Braille pan left (#braille%20pan%20left) +T} +T{ +\f[C]\f[] +T}@T{ +Braille pan right (#braille%20pan%20right) +T} +T{ +\f[C]\f[] +T}@T{ +Braille return to cursor (#braille%20return%20to%20cursor) +T} +T{ +FenrirKey + CTRL + 1 +T}@T{ +clear bookmark 1 (#clear%20Bookmark%20X) +T} +T{ +FenrirKey + Shift + 1 +T}@T{ +set bookmark 1 (#set%20Bookmark%20X) +T} +T{ +FenrirKey + 1 +T}@T{ +bookmark 1 (#read%20Bookmark%20X) +T} +T{ +FenrirKey + CTRL + 2 +T}@T{ +clear bookmark 2 (#clear%20Bookmark%20X) +T} +T{ +FenrirKey + Shift + 2 +T}@T{ +set bookmark 2 (#set%20Bookmark%20X) +T} +T{ +FenrirKey + 2 +T}@T{ +bookmark 2 (#read%20Bookmark%20X) +T} +T{ +FenrirKey + CTRL + 3 +T}@T{ +clear bookmark 3 (#clear%20Bookmark%20X) +T} +T{ +FenrirKey + Shift + 3 +T}@T{ +set bookmark 3 (#set%20Bookmark%20X) +T} +T{ +FenrirKey + 3 +T}@T{ +bookmark 3 (#read%20Bookmark%20X) +T} +T{ +FenrirKey + CTRL + 4 +T}@T{ +clear bookmark 4 (#clear%20Bookmark%20X) +T} +T{ +FenrirKey + Shift + 4 +T}@T{ +set bookmark 4 (#set%20Bookmark%20X) +T} +T{ +FenrirKey + 4 +T}@T{ +bookmark 4 (#read%20Bookmark%20X) +T} +T{ +FenrirKey + CTRL + 5 +T}@T{ +clear bookmark 5 (#clear%20Bookmark%20X) +T} +T{ +FenrirKey + Shift + 5 +T}@T{ +set bookmark 5 (#set%20Bookmark%20X) +T} +T{ +FenrirKey + 5 +T}@T{ +bookmark 5 (#read%20Bookmark%20X) +T} +T{ +FenrirKey + CTRL + 6 +T}@T{ +clear bookmark 6 (#clear%20Bookmark%20X) +T} +T{ +FenrirKey + Shift + 6 +T}@T{ +set bookmark 6 (#set%20Bookmark%20X) +T} +T{ +FenrirKey + 6 +T}@T{ +bookmark 6 (#read%20Bookmark%20X) +T} +T{ +FenrirKey + CTRL + 7 +T}@T{ +clear bookmark 7 (#clear%20Bookmark%20X) +T} +T{ +FenrirKey + Shift + 7 +T}@T{ +set bookmark 7 (#set%20Bookmark%20X) +T} +T{ +FenrirKey + 7 +T}@T{ +bookmark 7 (#read%20Bookmark%20X) +T} +T{ +FenrirKey + CTRL + 8 +T}@T{ +clear bookmark 8 (#clear%20Bookmark%20X) +T} +T{ +FenrirKey + Shift + 8 +T}@T{ +set bookmark 8 (#set%20Bookmark%20X) +T} +T{ +FenrirKey + 8 +T}@T{ +bookmark 8 (#read%20Bookmark%20X) +T} +T{ +FenrirKey + CTRL + 9 +T}@T{ +clear bookmark 9 (#clear%20Bookmark%20X) +T} +T{ +FenrirKey + Shift + 9 +T}@T{ +set bookmark 9 (#set%20Bookmark%20X) +T} +T{ +FenrirKey + 9 +T}@T{ +bookmark 9 (#read%20Bookmark%20X) +T} +T{ +FenrirKey + CTRL + 0 +T}@T{ +clear bookmark 10 (#clear%20Bookmark%20X) +T} +T{ +FenrirKey + Shift + 0 +T}@T{ +set bookmark 10 (#set%20Bookmark%20X) +T} +T{ +FenrirKey + 0 +T}@T{ +bookmark 10 (#read%20Bookmark%20X) +T} +T{ +FenrirKey + CTRL + 8 +T}@T{ +set window application (#Create%20Window) +T} +T{ +2 * FenrirKey + CTRL + 8 +T}@T{ +clear window application (#Remove%20Window) +T} +T{ +FenrirKey + Semicolon +T}@T{ +read last incoming (#last%20incoming) +T} +T{ +FenrirKey + F2 +T}@T{ +toggles braille (#toggle%20braille) +T} +T{ +FenrirKey + F3 +T}@T{ +toggles sound (#toggle%20sound) +T} +T{ +FenrirKey + F4 +T}@T{ +toggles speech (#toggle%20speech) +T} +T{ +FenrirKey + Enter +T}@T{ +temporarily disables speech (#disable%20speech%20temporarily) +T} +T{ +FenrirKey + Shift + CTRL + P +T}@T{ +toggles punctuation level (#toggle%20punctuation%20level) +T} +T{ +FenrirKey + RightBrace +T}@T{ +toggle auto spell check (#toggle%20auto%20spell%20check) +T} +T{ +FenrirKey + Shift + Enter +T}@T{ +toggles output (#toggle%20output) +T} +T{ +FenrirKey + Shift + E +T}@T{ +toggles emoticons (#toggle%20emoticons) +T} +T{ +FenrirKey + Enter +T}@T{ +toggles auto read (#toggle%20auto%20read) +T} +T{ +FenrirKey + CTRL + T +T}@T{ +toggles auto time (#toggle%20auto%20time) +T} +T{ +FenrirKey + Y +T}@T{ +toggles highlight tracking (#toggle%20highlight%20tracking) +T} +T{ +FenrirKey + Q +T}@T{ +quits fenrir (#quit%20Fenrir) +T} +T{ +FenrirKey + T +T}@T{ +Announce time (#Time) +T} +T{ +2 * FenrirKey + T +T}@T{ +Announce date (#Date) +T} +T{ +FenrirKey + S +T}@T{ +spell check (#spell%20check) +T} +T{ +2 * FenrirKey + S +T}@T{ +add word to spell check (#add%20word%20to%20spell%20check) +T} +T{ +FenrirKey + Shift + S +T}@T{ +removes word from spell check (#removes%20word%20from%20spell%20check) +T} +T{ +FenrirKey + Backspace +T}@T{ +forward keypress (#forward%20keypress) +T} +T{ +FenrirKey + Up +T}@T{ +increase speech volume (#increase%20speech%20volume) +T} +T{ +FenrirKey + Down +T}@T{ +decrease speech volume (#decrease%20speech%20volume) +T} +T{ +FenrirKey + Right +T}@T{ +increase speech rate (#increase%20speech%20rate) +T} +T{ +FenrirKey + Left +T}@T{ +decrease speech rate (#decrease%20speech%20rate) +T} +T{ +FenrirKey + Alt + Right +T}@T{ +increase speech pitch (#increase%20speech%20pitch) +T} +T{ +FenrirKey + Alt + Left +T}@T{ +decrease speech pitch (#decrease%20speech%20pitch) +T} +T{ +FenrirKey + Alt + Up +T}@T{ +increase sound volume (#increase%20sound%20volume) +T} +T{ +FenrirKey + Alt + Down +T}@T{ +decrease sound volume (#decrease%20sound%20volume) +T} +T{ +FenrirKey + CTRL + Shift + C +T}@T{ +clears clipboard (#clear%20clipboard) +T} +T{ +FenrirKey + Home +T}@T{ +first clipboard (#first%20clipboard) +T} +T{ +FenrirKey + End +T}@T{ +last clipboard (#last%20clipboard) +T} +T{ +FenrirKey + PageUp +T}@T{ +previous clipboard (#previous%20clipboard) +T} +T{ +FenrirKey + PageDown +T}@T{ +next clipboard (#next%20clipboard) +T} +T{ +FenrirKey + Shift + C +T}@T{ +current clipboard (#read%20current%20clipboard) +T} +T{ +FenrirKey + C +T}@T{ +copy marked text to clipboard (#copy%20marked%20to%20clipboard) +T} +T{ +FenrirKey + V +T}@T{ +paste clipboard contents (#paste%20clipboard) +T} +T{ +FenrirKey + F5 +T}@T{ +import clipboard from file (#import%20clipboard%20from%20file) +T} +T{ +FenrirKey + Alt + Shift +C +T}@T{ +export clipboard to file (#export%20clipboard%20to%20file) +T} +T{ +FenrirKey + CTRL + Shift + X +T}@T{ +remove marks (#Remove%20Marks) +T} +T{ +FenrirKey + X +T}@T{ +set mark (#Set%20mark) +T} +T{ +FenrirKey + Shift + X +T}@T{ +announce marked text (#Get%20text%20between%20marks) +T} +T{ +Linux specific +T}@T{ +T} +T{ +\f[C]\f[] +T}@T{ +export clipboard to X +T} +T{ +FenrirKey + CTRL + Up +T}@T{ +increases Alsa volume +T} +T{ +FenrirKey + CTRL + Down +T}@T{ +decreases Alsa volume +T} +.TE +.SS General +.SS quit Fenrir +.PP +Just stops fenrir. +#### shut up +.PP +Interrupt the current spoken. +### Review Modes +.PP +Fenrir provides a virtual cursor, with it you can navigate all over the +screen without changing the text cursor. +.PP +Using the review feature will open the review mode automatically. +.PP +The review cursor always starts from the text cursor. +Attention: after using the review mode, the review cursor will stay open +until you use the \[aq]\[aq]exit review\[aq]\[aq] shortcut. +.PP +Think when using clipboard operations and similar. +The review cursor is always prefered over the text cursor. +.PP +Fenrir sounds a bell sound if the used review command jumps to another +line or end of screen. +#### exit review +.PP +You can leave the review mode by pressing the \[aq]\[aq]exit +review\[aq]\[aq] shortcut. +#### review bottom +.PP +Set the review cursor to first column in the last line. +#### review top +.PP +Set the review cursor to the first column in the first line #### review +current line +.PP +Set the review cursor to the beginn of the the current line and review +it. +#### review previous line +.PP +Set the review cursor to the previous line and review it. +#### review next line +.PP +Set the review cursor to the next line and review it. +#### review line beginning +.PP +Set the review cursor to the begin of the current line #### review line +ending +.PP +Set the review cursor to the end of the current line #### review line +first character +.PP +Set the review cursor the first char (that is not space) in the current +line and review it. +#### review line last character +.PP +Set the review cursor the last char (that is not space) in the current +line and review it. +#### review current word +.PP +Sets the review cursor to the beginning of the current word and review +it. +#### review previous word +.PP +Sets the review cursor to the beginning of the previous word and review +it. +#### review next word +.PP +Sets the review cursor to the beginning of the next word and review it. +#### review current word phonetic +.PP +Sets the review cursor to the beginning of the current word and spell it +phonetic. +#### review previous word phonetic +.PP +Sets the review cursor to the beginning of the previous word and spell +it phonetic. +#### review next word phonetic +.PP +Sets the review cursor to the beginning of the next word and spell it +phonetic. +#### review current character +.PP +Does not change the review cursor. +Just announce the current char. +#### review previous character +.PP +Sets review cursor to the previous column and review it #### review next +character +.PP +Sets review cursor to the next column and review it #### review current +character phonetic +.PP +Does not change the review cursor. +Just announce the current char phonetic. +#### review previous character phonetic +.PP +Sets review cursor to the previous column and announce the char +phonetic. +#### review next character phonetic +.PP +Sets review cursor to the next column and announce the char phonetic. +#### review up +.PP +Set the review cursor in the same column one line above the current one +and review it. +#### review down +.PP +Set the review cursor in the same column one line below the current one +and review it. +### Handling marking +.PP +A mark defines a point of origin or end to prepare to copy or paste a +block of text. +\\ Examples where you need marks are: +.IP \[bu] 2 +copy to clipboard +.IP \[bu] 2 +set window application +.IP \[bu] 2 +set bookmark 1 \- X #### Set mark +.PP +How to set a mark: 1. +navigate with review or textcursor to the position you want to set the +mark. +Attention: if a review cursor is set, that is the prefered. +If you want to use text cursor, be sure that you are not in review mode. +2. +press shortcut for \[aq]\[aq]set mark\[aq]\[aq] you can set two marks +(begin and end). +Some commands allow some simpler usecases just using the whole line if +only one mark is set. +you may want to try this out. +#### Get text between marks +.PP +To get the text that is currently between your marks press shortcut for +\[aq]\[aq]marked text\[aq]\[aq].\\ #### Remove Marks +.PP +You can remove all current marks by pressing the shortcut for +\[aq]\[aq]remove marks\[aq]\[aq]. +Changing the screen also removes the marks. +### Screen Interaction +.PP +Fenrir provides several methods to interact with the current screen. +#### forward keypress +.PP +This just forwards the next shortcut to the screen Fenrir shortcut or +not. +This is useful if the currently pressed shortcut is also in use by +Fenrir. +#### Clipboard +.PP +Fenrir provides a clipboard with multible items represented by a list. +You navigate throught the list and paste the selected clipboard. +##### copy marked to clipboard +.PP +To copy something to the clipboard you need to set one or two marks. +if you set one mark, the text between the mark and your current cursor +is copied to clipboard. +Setting two marks just copies the text between the marks into the +clipboard. +If you copy something it is always placed as the first item on your +clipboard. +##### clear clipboard +.PP +You can remove all items from the current clipboard by \[aq]\[aq]clear +clipboard\[aq]\[aq] functionality. +##### first clipboard +.PP +This moves quick to the first item of the clipboard. +##### last clipboard +.PP +This moves quick to the last item of the clipboard. +##### previous clipboard +.PP +Go to previous item in the clipboard. +##### next clipboard +.PP +Go to next item on the clipboard. +##### read current clipboard +.PP +Read the content of the current item of the clipboard. +##### paste clipboard +.PP +Pass whatever item is currently selected by first, last, prev or next +clipboard commands. +if no special clipboard is selected the (last copied) is used. +##### export clipboard to file +.PP +This allows you to export the current clipboard to a configurable +filepath. +This is useful to share the clipboard with a graphical desktop. +##### import clipboard from file +.PP +Import a clipboard from a configurable file. +This is useful to share the clipboard with a graphical desktop. +### Quick Settings +.PP +Fenrir provides shortcuts to change settings temporarily and on the fly +without the need to permanently change the +\[aq]\[aq]settings.conf\[aq]\[aq] file. +#### toggle braille +.PP +Enables and disables Braille. +This is not persistent stored in your \[aq]\[aq]settings.conf\[aq]\[aq] +but during run time. +#### toggle sound +.PP +Enables and disables sound. +This is not persistent stored in your \[aq]\[aq]settings.conf\[aq]\[aq] +but during run time. +#### toggle speech +.PP +Enables and disables speech. +This is not persistent stored in your \[aq]\[aq]settings.conf\[aq]\[aq] +but during run time. +#### disable speech temporarily +.PP +Disables the speech until next key press. +it might be useful if you want to listen to music or similar. +As soon as a key is pressed it is going to be enabled again. +#### toggle punctuation level +.PP +Cycle between all available punctuation levels. +This is not persistent stored in your \[aq]\[aq]settings.conf\[aq]\[aq] +but during run time. +#### toggle auto spell check +.PP +Enables and disables automatic spellchecker (when typing). +This is not persistent stored in your \[aq]\[aq]settings.conf\[aq]\[aq] +but during run time. +#### toggle emoticons +.PP +Enables and disables emoticons. +This is not persistent stored in your \[aq]\[aq]settings.conf\[aq]\[aq] +but during runtime. +#### toggle output +.PP +Enables and disables all output at once (sound, Braille, speech). +This is not persistent stored in your \[aq]\[aq]settings.conf\[aq]\[aq] +but during run time. +#### toggle auto read +.PP +Enables and disables what is automatically spoken. +This is not persistent stored in your \[aq]\[aq]settings.conf\[aq]\[aq] +but during run time. +#### toggle auto time +.PP +Enables and disables auto time functionality. +This is not persistent stored in your \[aq]\[aq]settings.conf\[aq]\[aq] +but during run time. +#### toggle highlight tracking +.PP +Enables and disables highlight tracking. +This is not persistent stored in your \[aq]\[aq]settings.conf\[aq]\[aq] +but during run time. +#### increase speech volume +.PP +Increase the volume of the speech. +This is not persistent stored in your \[aq]\[aq]settings.conf\[aq]\[aq] +but during runtime. +#### decrease speech volume +.PP +Decrease the volume of the speech. +This is not persistent stored in your \[aq]\[aq]settings.conf\[aq]\[aq] +but during runtime. +#### increase speech rate +.PP +Increase the rate of the speech. +This is not persistent stored in your \[aq]\[aq]settings.conf\[aq]\[aq] +but during runtime. +#### decrease speech rate +.PP +Decrease the rate of the speech. +This is not persistent stored in your \[aq]\[aq]settings.conf\[aq]\[aq] +but during runtime. +#### increase speech pitch +.PP +Increase the pitch of the speech. +This is not persistent stored in your \[aq]\[aq]settings.conf\[aq]\[aq] +but during runtime. +#### decrease speech pitch +.PP +Decrease the pitch of the speech. +This is not persistent stored in your \[aq]\[aq]settings.conf\[aq]\[aq] +but during runtime. +#### increase sound volume +.PP +Increase the volume of the sound. +This is not persistent stored in your \[aq]\[aq]settings.conf\[aq]\[aq] +but during runtime. +#### decrease sound volume +.PP +Decrease the volume of the sound. +This is not persistent stored in your \[aq]\[aq]settings.conf\[aq]\[aq] +but during runtime. +### Window Mode +.PP +Fenrir supports window mode, a window is a partial area of the screen. +#### Create Window +.PP +To create a window you need to do the following: 1. +set a beginning mark (as the start of the window) 2. +set an end mark (where the window should end) 3. +press \[aq]\[aq]set window application\[aq]\[aq] shortcut. +Now Fenrir ignores anything outside of the window.\\ #### Remove Window +.PP +You can remove the window by pressing \[aq]\[aq]the clear window +application\[aq]\[aq] shortcut. +Now Fenrir will read everything on the screen again. +### Tracking Modes +.PP +Different types of tracking are currently supported See section +Focus (#Focus) in \[aq]\[aq]settings.conf\[aq]\[aq] for more +information. +#### Cursor Tracking +.PP +This follows the text cursor. +This is the typical way an application works. +This is used by: +.IP \[bu] 2 +almost any shell such as (Bash, Zsh, sh) +.IP \[bu] 2 +vim +.IP \[bu] 2 +nano +.IP \[bu] 2 +emacs +.IP \[bu] 2 +mutt +.IP \[bu] 2 +tintin++ #### Highlight Tracking +.PP +In some applications there are no text cursors. +In those applications cursor changes are represented by different colors +or attributes (underlined or bold). +This mode tracks and announces these changes for you. +This is used by: +.IP +.nf +\f[C] +*\ wifi\-menu +*\ dialog +*\ alpine +\f[] +.fi +.SS Tutorial Mode +.PP +Fenrir provides a Tutorial mode. +When you enter tutorial mode, screen reader commands are intercepted and +explained instead of executing them. +\[aq]\[aq]Arrow up\[aq]\[aq] and \[aq]\[aq]Arrow Down\[aq]\[aq] let you +navigate through a list of all available commands with shortcuts and +description. +Pressing escape leaves the tutorial mode. +.SS Information +.SS Time +.PP +Announces the current Time. +#### Date +.PP +Announces the current Date. +#### Bookmarks +.PP +Bookmarks provide quick access to part of the screen without the need to +navigate to the area. +By default Fenrir provides 10 bookmarks. +Those can be set and accessed via shortcut. +This is useful for status lines or other information where the position +does not change. +##### set Bookmark X +.PP +You need to set the bookmark first. +For that you have to set one or two lines for use. +1. +Set marks (one or two) 2. +press shortcut for \[aq]\[aq]set bookmark X\[aq]\[aq]. +X represents the number 1 \- 10. +##### read Bookmark X +.PP +If a bookmark is set you can access the area just by pressing the +\[aq]\[aq]bookmark X\[aq]\[aq] shortcut. +X represents the number 1 \- 10. +Bookmarks are dynamic. +That means the content changes with the screen. +##### clear Bookmark X +.PP +to remove a bookmark just press the \[aq]\[aq]clear bookmark X\[aq]\[aq] +shortcut. +X represents the number 1 \- 10. +Afterward the bookmark is no longer available. +#### cursor position +.PP +You can get information about the current cursor and its position by +using the "cursor position" functionality. +#### indent current line +.PP +Announce the current indent level of the current line. +It represents the number of trailing spaces of the line. +#### current screen +.PP +Reads all the current screen from the beginning to the end. +#### current screen before cursor +.PP +Reads current screen from the beginning of the screen to the current +cursor position. +#### current screen after cursor +.PP +Read anything after current cursor position to the end. +#### cursor read to end of line +.PP +Read from the current cursor position to the end of the current line. +#### cursor column +.PP +Read the current X position of a cursor (column of the current line). +#### cursor line number +.PP +Read the current Y position of a cursor (line number). +#### present first line +.PP +Reads just the first line. +this is maybe useful for status information. +#### present last line +.PP +Presets the last line. +This is maybe useful for status information. +#### last incoming +.PP +Repeat the last automatically incoming text. +## Input +.SS Echo +.PP +Fenrir provides different methods of echoing content: +.IP \[bu] 2 +Word: Will speak each word after you push space +.IP \[bu] 2 +Character: speak any letter you type on the screen +.IP \[bu] 2 +Delete Character: speaks the character prior to the cursor when you push +backspace ### Silence on Key press +.SS Spellchecker +.PP +Fenrir has a built\-in spellchecker, it can invoke automatically while +typing or be called by a shortcut. +Commands to add or remove the current word to the dictionary are +included. +As using the spellchecker is enhanced usage. +You will need dictionary aspell\-\f[C]\f[]. +See section General (#General) in \[aq]\[aq]settings.conf\[aq]\[aq] for +more information. +#### spell check +.PP +Invokes the spellcheck on the word that contains the Review or text +cursor. +#### add word to spell check +.PP +Adds the word under the Review or Text cursor to the dictionary. +#### removes word from spell check +.PP +Removes the word under the Review or Text cursor from the dictionary. +## Announcements +.SS Emoticons +.PP +If you want to replace ":)" emoticons with "smile" in speech you can use +this feature. +It can be toggled on or off. +You can define emoticons in a dictionary, please see Emoticon +Dictionary. +See section General (#General) in \[aq]\[aq]settings.conf\[aq]\[aq] to +see how to enable or disable this feature. +.SS Time +.PP +Announce the time at periodical increments, To track the time easily. +You can define 2 different ways of time announcements. +1. +periodic 2. +on fix minutes +.PP +Example periodic, every 20 minutes "delaySec=20": +.IP +.nf +\f[C] +[time] +enabled=True +presentTime=True +presentDate=True +delaySec=20 +onMinutes= +announce=True +interrupt=False\ \ \ \ +\f[] +.fi +.PP +Example on fix minutes in an hour. +example every quarter "delaySec=0" and "onMinutes=00,15,30,45": +.IP +.nf +\f[C] +[time] +enabled=True +presentTime=True +presentDate=True +#delaySec\ is\ repected\ bevore\ onMinutes\ so\ it\ need\ to\ be\ set\ to\ 0 +delaySec=0\ +onMinutes=00,15,30,45 +announce=True +interrupt=False\ \ \ \ \ \ +\f[] +.fi +.SS Promoted List +.PP +Promoted Lists are a nice feature if you are away from your computer or +performing more longer tasks. +you can define a list of words which you want to hear a sound icon for +after a period of inactivity. +Example if the word "Chrys" appears after 120 Seconds of inactivity: +[promote] enabled=True +.PD 0 +.P +.PD +inactiveTimeoutSec=120 list=Chrys See section Promote (#Promote) in +\[aq]\[aq]settings.conf\[aq]\[aq] for more information. +### Punctuation +.PP +Fenrir handles punctuation levels and names for you with several +provided dictionaries. +.PP +See levelDict See punctuationDict ## Braille +.PP +Fenrir provides Braille support in Version >= 2.0. +See section Braille (#Braille) in \[aq]\[aq]settings.conf\[aq]\[aq] for +more information. +### braille flush +.PP +If a message appears on the Braille device you can flush it to get back +to the review\- or system cursor ### Braille pan left +.PP +If a line is longer than your Braille devices you can move the view +(called panning) to the left. +So you can read stuff without the need to move the review\- or system +cursor. +### Braille pan right +.PP +If a line is longer than your Braille devices you can move the view +(called panning) to the right. +So you can read stuff without the need to move the review\- or system +cursor. +### braille return to cursor +.PP +When you have finished reading the line on the Braille device using +panning, the focus can be returned to the current used cursor by using +"return to cursor" command. +## Dictionary +.PP +You can make use of different kinds of built\-in dictionary\[aq]s. +A dictionary has a name and list of keys and values separated by :===: +Example: [customDict] Chrys:===:Chrys is cool lollipop:===:lolli that +means that every instance "chrys" is displayed, speech will say Chrys is +cool. +"lollipop" is spoken as "lolli". +Before making changes to a dictionary we recommend making a backup of +your current dictionary in case future updates overwrite your local +changes. +### Punctuation +.SS Level +.PP +The punctuation level dict contains lists with "what punctuation is +spoken in what level". +the default one looks like this: [levelDict] none:===: +some:===:.\-$~+*\-/\\\@ most:===:.,:\-$~+*\-/\@!#%^&\f[I]()[]}{\f[C]<>\f[]; +all:===:!"#$%& \[aq]()\f[]+,\-./:;\f[C]<=>\f[]?\@[\\]^_`{|}~ the level +"none" has no values. +so it should not speak any punctuation (sadly this is not respected by +every TTS system) if "some" is the current level the following are +spoken: dot dash dollar tilde plus star slash backslash at. +same for most and all, you can add new levels. +if you cycle punctuation levels they are recognized. +the default punctuation level is set in settings.conf. +The default is "some". +#### Punctuation +.PP +The punctuation dictionary "[punctDict]" contains how the punctuation is +spoken. +Example: [punctDict] \f[I]:===:line +.PD 0 +.P +.PD +speaks an \f[] as "line". +.PD 0 +.P +.PD +[punctDict] \f[I]:===:underscore speaks an \f[] as underscore. +for question mark an ? +is appended to the word that the TTS system can announce the question +correctly. +.PD 0 +.P +.PD +### Custom +.PP +The dict "[customDict]" is just for your own use, it just replace the +key with the value without any special functionality. +This might be used to fix incorrectly spoken words, make words more +common, shorter or just for fun. +:) ### Emoticons +.PP +The Emoticons dictionary "[emoticonDict]" by default contains some +emoticons. +it can replace ":)" with "smile" or "XD" with "loool" Making chat more +colorful. +A nice feature with this dictionary is that you can toggle the +substitution on or off during run time or in settings.conf. +This is useful because while doing programming or other serious work you +want to hear colons and perryns not smiles. +# Configuration +.PP +You can configure Fenrir in the following places (ordered by priority): +1. +Commandline Parameters \[aq]\[aq]\-o\[aq]\[aq] see Set settings +coption (#Set%20settings%20coption) 2. +/etc/fenrir/settings/settings.conf see Settigns (#Settings) 3. +\f[C]\f[]/config/settings/settings.conf see +Settigns (#Settings) 4. +hard coded defaults ## Commandline Arguments +.SS Set settings option +.PP +You can specify options that overwrite the setting.conf. +This is done with \[aq]\[aq]\-o \f[C]\f[] parameter. +The list of options have the following syntax fenrir \-o +"section#setting=value;section#setting=value" +.PP +For example changing the sound driver to gstreamer and disabling Braille +.PD 0 +.P +.PD +fenrir \-o "sound#driver=gstreamerDriver;braille#enabled=False=False" or +change the debug level to verbose fenrir \-o "general#debugLevel=3" You +can find the available sections and variables here <#Settings> See +Syntax #settings.conf syntax (#settings.conf%20syntax) ### settings.conf +syntax +.PP +the syntax of the settings.conf (#Settings) is quite simple and similar +to a "*.ini" file, there are 4 different elements. +1. +Sections 2. +Settings 3. +Values 4. +Comments +.PP +A comment starts with a # and is ignored by Fenrir. +# this is a comment To group settings we have sections. +A section can look like this: [Section] A setting looks like this: +settingName=Value +.PP +Example: sound (#sound) # Turn sound on or off: enabled=True # Select +the driver used to play sounds, choices are genericDriver and +gstreamerDriver. +# Sox is default. +driver=genericDriver +.SS Settings +.SS Sound +.PP +The sound is configured in section \[aq]\[aq]sound (#sound)\[aq]\[aq]. +.PP +Turn sound on or off: enabled=True Values: on=\[aq]\[aq]True\[aq]\[aq], +off=\[aq]\[aq]False\[aq]\[aq] +.PP +Select the driver used to play sounds. +The genericDriver using Sox is the default. +.IP +.nf +\f[C] +driver=genericDriver +\f[] +.fi +.PP +Available Drivers: +.IP \[bu] 2 +\[aq]\[aq]genericDriver\[aq]\[aq] using the generic driver, for Fenrir +<1.5 just use \[aq]\[aq]generic\[aq]\[aq] +.IP \[bu] 2 +\[aq]\[aq]gstreamerDriver\[aq]\[aq] using the gstreamer, for Fenrir <1.5 +just use \[aq]\[aq]gstreamer\[aq]\[aq] +.PP +These are the pack of sounds used for sound icons. +theme=default By default we ship two sound packs. +1. +\[aq]\[aq]default\[aq]\[aq] opus encoded, for newer Sox versions 2. +\[aq]\[aq]default\-wav\[aq]\[aq] wav encoded, just for compatibility +Sound packs are located at /usr/share/sounds/fenrir/ +.PP +Sound volume controls how loud the sounds for your selected sound pack +are. +volume=1.0 Values: \[aq]\[aq]0.0\[aq]\[aq] is quietest, +\[aq]\[aq]1.0\[aq]\[aq] is loudest. +.SS Generic Driver +.PP +The generic sound driver uses shell commands for play sound and +frequencies. +.PP +\[aq]\[aq]genericPlayFileCommand\[aq]\[aq] defines the command that is +used to play a sound file. +genericPlayFileCommand=\f[C]\f[] +\[aq]\[aq]genericFrequencyCommand\[aq]\[aq] defines the command that is +used playing frequencies. +genericFrequencyCommand=\f[C]\f[] +.PP +The following variables are substituted in +\[aq]\[aq]genericPlayFileCommand\[aq]\[aq] and +\[aq]\[aq]genericFrequencyCommand\[aq]\[aq]: +.IP \[bu] 2 +\[aq]\[aq]fenrirVolume\[aq]\[aq] = the current volume setting +.IP \[bu] 2 +\[aq]\[aq]fenrirSoundFile\[aq]\[aq] = the sound file for an sound icon +.IP \[bu] 2 +\[aq]\[aq]fenrirFrequence\[aq]\[aq] = the frequency to play +.IP \[bu] 2 +\[aq]\[aq]fenrirDuration\[aq]\[aq] = the duration of the frequency +.PP +Example genericPlayFileCommand (default) genericPlayFileCommand=play \-q +\-v fenrirVolume fenrirSoundFile Example genericFrequencyCommand +(default) genericFrequencyCommand=play \-q \-v fenrirVolume \-n \-c1 +synth fenrirDuration sine fenrirFrequence ### Speech +.PP +Speech is configured in section \[aq]\[aq][speech]\[aq]\[aq]. +Turn speech on or off: enabled=True Values: on=\[aq]\[aq]True\[aq]\[aq], +off=\[aq]\[aq]False\[aq]\[aq] +.SH Select speech driver, options are speechdDriver (default), +genericDriver or espeakDriver: +.PP +driver=speechdDriver #driver=espeakDriver +.SH driver=genericDriver +.PP +Select the driver used to generate speech output. +.IP +.nf +\f[C] +driver=speechdDriver +\f[] +.fi +.PP +Available Drivers: +.IP \[bu] 2 +\[aq]\[aq]genericDriver\[aq]\[aq] using the generic driver, for Fenrir +<1.5 this is not available +.IP \[bu] 2 +\[aq]\[aq]speechdDriver\[aq]\[aq] using speech\-dispatcher, for Fenrir +<1.5 just use \[aq]\[aq]speechd\[aq]\[aq] +.IP \[bu] 2 +\[aq]\[aq]espeakDriver\[aq]\[aq] using the espeak directly, for Fenrir +<1.5 just use \[aq]\[aq]espeak\[aq]\[aq] +.PP +The rate selects how fast Fenrir will speak. +rate=0.65 Values: Range Minimum:\[aq]\[aq]0.0\[aq]\[aq] is slowest, +Maximum:\[aq]\[aq]1.0\[aq]\[aq] is fastest. +.PP +Pitch controls the pitch of the voice. +pitch=0.5 Values: Range Minimum:\[aq]\[aq]0.0\[aq]\[aq] is lowest, +Maximum:\[aq]\[aq]1.0\[aq]\[aq] is highest. +.PP +A Pitch for capital letters can be set. +capitalPitch=0.9 Values: Range Minimum:\[aq]\[aq]0.0\[aq]\[aq] is +lowest, Maximum:\[aq]\[aq]1.0\[aq]\[aq] is highest. +.PP +The Volume controls the loudness of the voice. +volume=1.0 Values: Range Minimum:\[aq]\[aq]0.0\[aq]\[aq] is quietest, +Maximum:\[aq]\[aq]1.0\[aq]\[aq] is loudest. +.PP +Some speech drivers like speechdDriver can support various modules. +these can be set here. +module=espeak Values: Text, Consult speech\-dispatcher\[aq]s +configuration to see what modules are available. +.PP +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= Values: Text, see your TTS synths documentation what is +available. +.PP +Select the language you want Fenrir to use. +language=english\-us Values: Text, see your TTS synths documentation +what is available. +.PP +Read new text as it occurs autoReadIncoming=True Values: +on=\[aq]\[aq]True\[aq]\[aq], off=\[aq]\[aq]False\[aq]\[aq] +.SS Generic Driver +.PP +The generic speech driver uses shell commands for speech synthisus. +.PP +\[aq]\[aq]genericSpeechCommand\[aq]\[aq] defines the command that is +executed for creating speech The following variables are substituted in +\[aq]\[aq]genericSpeechCommand\[aq]\[aq]: +.IP \[bu] 2 +\[aq]\[aq]FenrirText\[aq]\[aq] = is the text that should be spoken +.IP \[bu] 2 +\[aq]\[aq]fenrirModule\[aq]\[aq] = may be the speech module like used in +speech\-dispatcher, not every TTY needs this +.IP \[bu] 2 +\[aq]\[aq]fenrirLanguage\[aq]\[aq] = the language to speak in +.IP \[bu] 2 +\[aq]\[aq]fenrirVoice\[aq]\[aq] = is the current voice that should be +used +.IP \[bu] 2 +\[aq]\[aq]fenrirVolume\[aq]\[aq] = is replaced with the current volume +.IP \[bu] 2 +\[aq]\[aq]fenrirPitch\[aq]\[aq] = is replaced with the current pitch +.IP \[bu] 2 +\[aq]\[aq]fenrirRate\[aq]\[aq] = is replaced with the current speed +(speech rate) +.PP +Example genericSpeechCommand (default): genericSpeechCommand=espeak \-a +fenrirVolume \-s fenrirRate \-p fenrirPitch \-v fenrirVoice "fenrirText" +.PP +These are the minimum and maximum values of the TTS system used in +genericSpeechCommand. +They are needed to calculate the abstract range in volume, rate and +pitch 0.0 \- 1.0. +.IP +.nf +\f[C] +FenrirMinVolume=0 +fenrirMaxVolume=200 +fenrirMinPitch=0 +fenrirMaxPitch=99 +fenrirMinRate=80 +fenrirMaxRate=450 +\f[] +.fi +.PP +The current volume, pitch and rate is calculated like this value = min + +[volume,pitch,rate] * (min \- max ) ### Braille +.PP +Braille is a WIP and not ready yet. +Braille support can be configured in section +\[aq]\[aq][braille]\[aq]\[aq]. +.PP +Turn braille on or off: enabled=False Values: +on=\[aq]\[aq]True\[aq]\[aq], off=\[aq]\[aq]False\[aq]\[aq] +.PP +Select the driver used for communication with a braille device. +driver=brlapiDriver Values: Text, available Driver Available Drivers: +.IP \[bu] 2 +\[aq]\[aq]brlttyDriver\[aq]\[aq] using brltty for braille communication, +for Fenrir <1.5 just use \[aq]\[aq]brltty\[aq]\[aq] +.PP +The Braille layout can be configured here layout=en Values: Text, see +braille driver for layouts. +.PP +What should the flush timeout relate to flushMode=word Values: Text, an +flushMode Existing flushModes: +.IP \[bu] 2 +\[aq]\[aq]word\[aq]\[aq] = flush after (number of words to display) * +seconds +.IP \[bu] 2 +\[aq]\[aq]char\[aq]\[aq] = flush after (number of chars to display) * +seconds +.IP \[bu] 2 +\[aq]\[aq]fix\[aq]\[aq] = flush after X seconds +.IP \[bu] 2 +\[aq]\[aq]none\[aq]\[aq] = no automatic flush (manual via shortcut) +.PP +Seconds to flush (see flushMode) flushTimeout=3 Values: Integer, in +Seconds or \[aq]\[aq]\-1\[aq]\[aq] = no automatic flush (manual via +shortcut) The total flush time calculates in relation to flushMode. +.PP +How should the Braille cursor focus be tracked? +cursorFocusMode=page Values: Text, an existing cursor focus mode +Available cursor focus modes: +.IP \[bu] 2 +\[aq]\[aq]page\[aq]\[aq] = if the cursor crosses the border move to next +page and start at begin +.IP \[bu] 2 +\[aq]\[aq]fixCell\[aq]\[aq] = ajust the cursor on a special cell where +it is always placed. +the display scroll here more smooth. +.PP +Define the cell on the Braille device where Fenrir should scroll and +keep the cursor fixCursorOnCell=\-1 Values: Integer +.IP \[bu] 2 +\[aq]\[aq]0\[aq]\[aq] = first cell on device, +.IP \[bu] 2 +\[aq]\[aq]\-1\[aq]\[aq] = last cell on device +.IP \[bu] 2 +\[aq]\[aq]>0\[aq]\[aq] = fix cell number +.PP +What cursor should Fenrir show on the Braille device +cursorFollowMode=review Values: Text, an exsiting cursor following mode. +Existing cursor following mode: +.IP \[bu] 2 +\[aq]\[aq]none\[aq]\[aq] = no automatic toggle command used +.IP \[bu] 2 +\[aq]\[aq]review\[aq]\[aq] = priority to review +.IP \[bu] 2 +\[aq]\[aq]last\[aq]\[aq] = follow last used cursor +.PP +number of cells in panning (horizontal). +How many cell should be panned on press the routing key? +panSizeHorizontal=0 Values: Integer, +.IP \[bu] 2 +\[aq]\[aq]0\[aq]\[aq] = display size +.IP \[bu] 2 +\[aq]\[aq]>0\[aq]\[aq] number of cells ### Screen +.PP +The settings for screens, (TTY, PTY) are configured in the +\[aq]\[aq][screen]\[aq]\[aq] section. +.PP +The driver to get the information from the screen: driver=vcsaDriver +Available Drivers: +.IP \[bu] 2 +\[aq]\[aq]vcsaDriver\[aq]\[aq] using the VCSA driver (for TTYs), for +Fenrir <1.5 just use \[aq]\[aq]vcsa\[aq]\[aq] The encoding of the screen +encoding=cp850 Values:\[aq]\[aq]cp850\[aq]\[aq] is used for Western +languages like USA or Europe. +.PP +The driver updates Fenrir with changes on the screen. +screenUpdateDelay=0.05 Values: in Seconds +.PP +If you want Fenrir to not be active on any screen for various reasons. +Maybe an X server or Wayland is running on that screen. +You can make Fenrir ignore it or multiple screens seperated by +\[aq]\[aq],\[aq]\[aq] with: suspendingScreen= Values: Depends on driver: +.IP \[bu] 2 +VCSA: the number of the TTY. +TTY6 is \[aq]\[aq]6\[aq]\[aq]. +Example ignore TTY1 and TTY2: suspendingScreen=1,2 +.PP +There is also the ability to let Fenrir auto detect screens that are +running an X server. +So Screens running an GUI can be ignored. +autodetectSuspendingScreen=True Values: on=\[aq]\[aq]True\[aq]\[aq], +off=\[aq]\[aq]False\[aq]\[aq] +.SS Keyboard +.PP +The settings for keyboard and input related configuration is located in +the section \[aq]\[aq]keyboard (#keyboard)\[aq]\[aq] of the +\[aq]\[aq]settings.conf\[aq]\[aq] file. +.PP +Select the driver used for grabbing keybord input and for recieving +shortcuts. +driver=evdevDriver Values: Text, available Driver Available Drivers: +.IP \[bu] 2 +\[aq]\[aq]evdevDriver\[aq]\[aq] uses the evdev input system of linux, +for Fenrir <1.5 just use \[aq]\[aq]evdev\[aq]\[aq] +.PP +You can let Fenrir know about what input devices are to be used. +device=ALL Values: +.IP \[bu] 2 +\[aq]\[aq]ALL\[aq]\[aq] use all devices with key capabilities. +.IP \[bu] 2 +\[aq]\[aq]NOMICE\[aq]\[aq] Exclude mices from handling. +.IP \[bu] 2 +\f[C]\f[] just use the device with the given name. +.PP +Gives Fenrir exclusive access to the keyboard and lets it control +keystrokes. +This is needed to intercept Fenrir related shortcuts. +grabDevices=True Values: on=\[aq]\[aq]True\[aq]\[aq], +off=\[aq]\[aq]False\[aq]\[aq] +.PP +The following makes sense if you are using a second screenreader and +want to have some hooked events. +Fenrir ignores all shortcuts then. +ignoreShortcuts=False Values: on=\[aq]\[aq]True\[aq]\[aq], +off=\[aq]\[aq]False\[aq]\[aq] +.PP +The current keyboard layout used for shortcuts. +keyboardLayout=desktop Values: An absolute Path to a Keyboard definition +file or a Filename without extension located in +\[aq]\[aq]/etc/fenrir/keyboard\[aq]\[aq] +.PP +Announce characters while typing. +charEcho=False Values: on=\[aq]\[aq]True\[aq]\[aq], +off=\[aq]\[aq]False\[aq]\[aq] +.PP +Announce deleted characters charDeleteEcho=True Values: +on=\[aq]\[aq]True\[aq]\[aq], off=\[aq]\[aq]False\[aq]\[aq] +.PP +Announce word after pressing space wordEcho=False Values: +on=\[aq]\[aq]True\[aq]\[aq], off=\[aq]\[aq]False\[aq]\[aq] +.PP +Interrupt speech on any keypress interruptOnKeyPress=False Values: +on=\[aq]\[aq]True\[aq]\[aq], off=\[aq]\[aq]False\[aq]\[aq] +.PP +You can filter the keys that speech should interrupt +interruptOnKeyPressFilter= Values: (List) empty = all keys, otherwise +interrupt with specified keys +.PP +The timeout that is used for double tap shortcuts doubleTapTimeout=0.2 +Values: Seconds ### General +.PP +Overall settings can be configured from the section +\[aq]\[aq]general (#general)\[aq]\[aq]. +.PP +Set the current debug level: debugLevel=1 Values: off=0, error=1, +warning=2, info=3 +.PP +the current punctuation and dict file in use: punctuationProfile=default +Values: Text, see available profiles in +\[aq]\[aq]/etc/fenrir/punctuation\[aq]\[aq] or in +\[aq]\[aq]sourceTree/config/punctuation\[aq]\[aq] +.PP +The current punctuation level in use: punctuationLevel=some Values: +Text, See available levels in the used punctuation file. +.PP +Respect pause for punctuations: respectPunctuationPause=True Values: +on=\[aq]\[aq]True\[aq]\[aq], off=\[aq]\[aq]False\[aq]\[aq] +.PP +Add a pause on Line break: newLinePause=True Values: +on=\[aq]\[aq]True\[aq]\[aq], off=\[aq]\[aq]False\[aq]\[aq] +.PP +Specify the path where the clipboard should be exported to. +See export clipboard to file (#export%20clipboard%20to%20file). +The variable \[aq]\[aq]$user\[aq]\[aq] is replaced by the current logged +username. +clipboardExportPath=/tmp/fenrirClipboard Values: Text, Systemfilepath +.PP +The number of available clipboards: numberOfClipboards=10 Values: +Integer, 1 \- 999 +.PP +Replace emoticons like :) or ;) with text insertions: emoticons=True +Values: on=\[aq]\[aq]True\[aq]\[aq], off=\[aq]\[aq]False\[aq]\[aq] +.PP +Define the current Fenrir keys: fenrirKeys=KEY_KP0,KEY_META,KEY_INSERT +Values, Text list, separated by comma. +.PP +Define the current script keys: scriptKey=KEY_COMPOSE Values, Text list, +separated by comma. +.PP +The time format to be used for (time command) output: +timeFormat=%H:%M:%P Values: see python specification for +datetime.strftime (https///docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior) +.PP +The date format to be used for (date command) output: dateFormat=%A, %B +%d, %Y Values: see python specification for +datetime.strftime (https///docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior) +.PP +Enable or Disable spellcheck whilst typing: autoSpellCheck=True Values: +on=\[aq]\[aq]True\[aq]\[aq], off=\[aq]\[aq]False\[aq]\[aq] +.PP +The use of the dictionary with spellcheck: spellCheckLanguage=en_US +Values: Text, see aspell dictionary\[aq]s. +.PP +Folder Path for your scripts "scriptKey" functionality: +scriptPath=/usr/share/fenrir/scripts Values: Text, Existing path on file +system. +.PP +Override commands or create new ones without changing the Fenrir +defaults: commandPath=/usr/share/fenrir/commands Values: Text, Existing +path on file system. +Subfolders in commandPath are: +.IP \[bu] 2 +\[aq]\[aq]commands\[aq]\[aq] = to create shortcut commands +.IP \[bu] 2 +\[aq]\[aq]onInput\[aq]\[aq] = executed while typing +.IP \[bu] 2 +\[aq]\[aq]onScreenChange\[aq]\[aq] = executed on change the screen +(change from TTY4 to TTY6) +.IP \[bu] 2 +\[aq]\[aq]onScreenUpdate\[aq]\[aq] = executed when the screen is +captured +.SS Focus +.PP +The configuration for basic focus is in the section +\[aq]\[aq]focus (#focus)\[aq]\[aq]. +Follow the text cursor: cursor=True Values: on=\[aq]\[aq]True\[aq]\[aq], +off=\[aq]\[aq]False\[aq]\[aq] +.PP +Follow highlighted text changes (Highlight Tracking): highlight=False +Values: on=\[aq]\[aq]True\[aq]\[aq], off=\[aq]\[aq]False\[aq]\[aq] ### +Review +.PP +Configurations for the review mode are in the section +\[aq]\[aq][review]\[aq]\[aq]. +.PP +If "next word/ char" or "prev word/char" create a linebreak, announce +it: lineBreak=True Values: on=\[aq]\[aq]True\[aq]\[aq], +off=\[aq]\[aq]False\[aq]\[aq] +.PP +If "next word/ char" or "prev word/char" cannot be performed because you +reached the end of the screen, announce it: endOfScreen=True Values: +on=\[aq]\[aq]True\[aq]\[aq], off=\[aq]\[aq]False\[aq]\[aq] +.PP +Leave the review mode when pressing a key: leaveReviewOnKeypress=False +Values: on=\[aq]\[aq]True\[aq]\[aq], off=\[aq]\[aq]False\[aq]\[aq] +.PP +Leave the review mode when changing the screen (From TTY3 to TTY4): +leaveReviewOnScreenChange=True Values: on=\[aq]\[aq]True\[aq]\[aq], +off=\[aq]\[aq]False\[aq]\[aq] ### Promote +.PP +"Promoted Lists" are configured in the section +\[aq]\[aq][promote]\[aq]\[aq]. +Turn Promoted Lists" on or off: enabled=True Values: +on=\[aq]\[aq]True\[aq]\[aq], off=\[aq]\[aq]False\[aq]\[aq] +.PP +The minimum time interval of inactivity to activate promoting. +By default it promotes after 120 Seconds inactivity: +inactiveTimeoutSec=120 Values: in Seconds +.PP +Define a list of promoted words comma seperated: list= Values: text +(comma seperated) Example to promote the word "nickname" or a bash +prompt: list=nickname,$:,#: +.SS Time +.PP +The automated time announcement is configured in the section +\[aq]\[aq]time (#time-2)\[aq]\[aq]. +Time announcement is disabled by default. +Turn time announcement on or off: enabled=True Values: +on=\[aq]\[aq]True\[aq]\[aq], off=\[aq]\[aq]False\[aq]\[aq] +.PP +Should the time be announced: presentTime=True Values: +on=\[aq]\[aq]True\[aq]\[aq], off=\[aq]\[aq]False\[aq]\[aq] +.PP +Should the date be announced (just on date change): presentDate=True +Values: on=\[aq]\[aq]True\[aq]\[aq], off=\[aq]\[aq]False\[aq]\[aq] +.PP +Announce after a given period of seconds: delaySec=0 Value: in Seconds, +0 = Deactivated +.PP +Announce after fixed minutes in an hour. +if delaySec is >0 onMinutes is ignored: onMinutes=00,30 Example every 15 +minutes: onMinutes=00,15,30,45 +.PP +Just play a soundicon, (not interrupting): announce=True Values: +on=\[aq]\[aq]True\[aq]\[aq], off=\[aq]\[aq]False\[aq]\[aq] +.PP +Interrupt current speech for time announcement: interrupt=False Values: +on=\[aq]\[aq]True\[aq]\[aq], off=\[aq]\[aq]False\[aq]\[aq] # +Customization +.SS Scripting +.PP +Scripts can be in any language, bash, python, sh or others. +Place your scripts in the directory /usr/share/fenrir/scripts/ (the path +is configurable in settings.conf). +The script key is the applications key. +Usually this key can be found on the keyboard located just left of the +right most control key. +When you name a script, the key name appears in the script seperated by +the sequence \f[B]\-\f[]. +So, for example, if you have a python weather script you want assigned +to the script key plus the letter w you would name the script +/usr/share/fenrir/scripts/weather__\-__key_w.py Then, to access the +script, simply press the script key and the letter w. +Scripts must be executable. +So, make sure to chmod 755 your script when you place it in the scripts +directory. +The script gets some parameters from fenrir when it is executed. +So that information is available in your script then. +.SS Parameterlist +.PP +.TS +tab(@); +l l. +T{ +Parameter +T}@T{ +Content +T} +_ +T{ +$1 +T}@T{ +Username of the current logged in user +T} +.TE +.SS Examples +.PP +Script that just speaks the current username when pressing ScriptKey + +H.\\ File: +\[aq]\[aq]/usr/share/fenrir/scripts/helloWorld__\-__key_h.sh\[aq]\[aq]: +#!/bin/bash echo $1 +.SS Commands +.PP +You can place your own commands in "/usr/share/fenrir/commands" (path is +configurable in settings.conf). +Commands are python files with a special scheme. +You can assign them to a shortcut using the filename without an +extension or place them in a hook trigger like OnInput or +OnScreenChange. +For further information see developer guide. +Good Examples: +"date.py" (https///github.com/chrys87/fenrir/blob/master/src/fenrir/commands/commands/date.py) +(announce the Date), +"shut_up.py" (https///github.com/chrys87/fenrir/blob/master/src/fenrir/commands/commands/shut_up.py) +(interrupt output) the basic scheme for a command is as follows: +.IP +.nf +\f[C] +from\ core\ import\ debug + +class\ command(): +\ \ def\ __init__(self): +\ \ \ \ \ \ pass +\ \ def\ initialize(self,\ environment): +\ \ \ \ \ \ self.env\ =\ environment +\ \ def\ shutdown(self): +\ \ \ \ \ \ pass +\ \ def\ getDescription(self): +\ \ \ \ \ \ return\ _(\[aq]No\ description\ found\[aq]) +\ \ def\ run(self): +\ \ \ \ \ \ pass +\ \ def\ setCallback(self,\ callback): +\ \ \ \ \ \ pass +\f[] +.fi +.IP \[bu] 2 +Template lives +here (https///github.com/chrys87/fenrir/blob/master/src/fenrir/commands/command_template.py) +.IP \[bu] 2 +The class needs to have the name "command". +.IP \[bu] 2 +"initialize" is running once whilst loading the command. +.IP \[bu] 2 +"shutdown" is running on unload like the command (quit fenrir) +.IP \[bu] 2 +"getDescriptsion" just returns an string. +That String is used in Tutorial Mode. +.IP \[bu] 2 +"run" is executed when the command is invoked. +(shortcut is pressed, or trigger isn\[aq]t running) +.IP \[bu] 2 +setCAllback is currently not used. +and has no functionality yet. +.SH Troubleshooting +.SS Fenrir does not start +.IP " 1." 4 +Have you installed all the dependencies Support and +Requirements (#Support%20and%20Requirements) +.IP " 2." 4 +Try using master, a lot of changes take place there to make Fenrir +compatible with more systems ## Fenrir does not utilize the shortcuts +.IP " 3." 4 +Make sure you have python3\-evdev installed +.IP " 4." 4 +Use the latest Fenrir version +.IP " 5." 4 +Make sure that Fenrir has permission to /dev/input/* and /dev/uinput (or +run it as root) ## No sound at all +.IP " 6." 4 +Run the script to configure Pulseaudio once as root and once as your +user. +This will setup Pulseaudio but require a restart of Pulseaudio. +The script is located in \[aq]\[aq]tools/configure_pulse.sh\[aq]\[aq] +.IP " 7." 4 +Use ALSA +.IP " 8." 4 +Configure Pulse system +wide (https///www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/SystemWide/) +(Not recommended) +.IP " 9." 4 +Use gstreamerDriver: change \[aq]\[aq]settings.conf\[aq]\[aq] in the +section \[aq]\[aq]sound\[aq]\[aq] the line +\[aq]\[aq]driver=genericDriver\[aq]\[aq] to +\[aq]\[aq]driver=gstreamerDriver\[aq]\[aq] +.IP "10." 4 +Use wave sound\-icons: change \[aq]\[aq]settings.conf\[aq]\[aq] in the +section \[aq]\[aq]sound\[aq]\[aq] the line +\[aq]\[aq]theme=default\[aq]\[aq] to +\[aq]\[aq]theme=default\-wav\[aq]\[aq] +.IP "11." 4 +Use most current version of sox (http://sox.sourceforge.net/) with opus +support +.IP "12." 4 +Try apulse (https///github.com/i-rinat/apulse) (not tested by myself but +might work). +Please give me feedback if you try it out. +## You get sound\-icons but no speech +.IP "13." 4 +If you are using speech\-dispatcher run "spd\-conf" once as user and as +root. +.IP "14." 4 +You can test if speech\-dispatcher works by invoking it as root\\ +\[aq]\[aq]sudo spd\-say "hello world"\[aq]\[aq] ## Bugreports and +feature requests +.PP +Please report Bugs and feature requests to: +https://github.com/chrys87/fenrir/issues (https///github.com/chrys87/fenrir/issues) +.PP +for bugs please provide a debug (#Howto%20create%20a%20debug%20file) +file that shows the issue. +### How\-to create a debug file +.IP "1." 3 +Delete old debug stuff\\ \[aq]\[aq]sudo rm /var/log/fenrir.log\[aq]\[aq] +.IP "2." 3 +Start fenrir in debug mode\\ \[aq]\[aq]sudo fenrir \-d\[aq]\[aq] +.IP "3." 3 +Do your stuff to reproduce the problem +.IP "4." 3 +Stop fenrir (\[aq]\[aq]fenrirKey + q\[aq]\[aq]) the debug file is +located in \[aq]\[aq]/var/log/fenrir.log\[aq]\[aq] +.PP +Please be as precise as possible to make it easy to solve the problem. diff --git a/docu/user.md b/docu/user.md new file mode 100644 index 0000000..6091716 --- /dev/null +++ b/docu/user.md @@ -0,0 +1,1590 @@ +# Fenrir User Manual + +Fenrir is a modern command line screen reader written in Python3. + +It has a modular structure, a flexible based driver model, is highly configurable and easy to customize and extend ([see Developer Manual](fenrir_development_manual)). + +Please see the following pages for the [current](fenrir_current_version) and [Git](fenrir_git_version) version of Fenrir. + + +# Support and Requirements + + +Fenrir requires several drivers to interact with the operating system. + +## Speech Drivers + + +A speech driver is for communication with the text to speech system like [Speech-Dispatcher](#SpeechDispatcher) or [Espeak](http://espeak.sourceforge.net). \\ +See section [Speech](#Speech) in ''settings.conf'' for more information. + + +### SpeechDispatcher + + +This driver is used by default. +It uses Speech-dispatcher as its backend. + +Dependencies: + + +* Speech-dispatcher (installed and configured, [Documentation](https///devel.freebsoft.org/speechd#sec2)) + +* Python-speechd + +### Espeak + + +Uses Espeak via Python bindings. + +Dependencies: + +* Espeak or Espeak-ng + +* [python-espeak](https///launchpad.net/python-espeak) + +### Generic + + +This invokes speech via a sub-process. This is almost the same as using the commandline. The performance depends on the overhead of the speech synthesis application but it is really flexible. + +Dependencies: + +* Espeak or Espeak-ng + +The Requirements are flexible, they depend on the configuration in settings.conf. + +### Dummy + + +this is just for debugging, logs are output to the screen and logged as well. + +## Sound Drivers + + +To play sound icons and similar.\\ +See section [Sound](#Sound) in ''settings.conf'' for more information. + +### Generic + + +This driver is used by default. + +Dependencies: + + +* [Sox](http://sox.sourceforge.net/) with opus support +The Requirements are flexible, they depend on the configuration in settings.conf. + +### Gstreamer + +if you prefer to use Gstreamer for sound output. + +Dependencies: + +* Gstreamer >= 1.x + +* Glibc + +### Dummy + + +this is just for debugging, logs are output to the screen and logged as well. + +## Input Drivers + + +Input drivers are to capture keyboard shortcuts issued to the screen reader \ +See section [Keyboard](#Keyboard) in ''settings.conf'' for more information. + +### Evdev + + +This driver is used by default. + +Evdev is the low level input device framework for Linux. + +Dependencies: + + +* python-evdev >=0.6.3 + +* pyudev + +* loaded uinput kernel module + +* exclusive access to the input devices +Read permission to the following files and services: + +* /dev/input + +* /dev/uinput + +## Screen Drivers + + +The job of a screen driver is to get the information of current screen content.\\ +See section [Screen](#Screen) in ''settings.conf'' for more information. + +### VCSA + + +This driver is used by default. +For Linux VCSA devices. These exist on any current standard installation of Linux. + +Dependencie +s: + + +* python-dbus +Read permission to the following files and services (or run as root): + +* /sys/devices/virtual/tty/tty0/active + +* /dev/tty[1 - 64] + +* /dev/vcsa[1 - 64] ([VCSA manpage](https///linux.die.net/man/4/vcsa)) + +* read Logind DBUS + +## Braille Drivers + +This is for Braille support. +Braille is currently a work in progress and is planned for the Fenrir 2.0 release.\\ +See section [Braille](#Braille) in ''settings.conf'' for more information. + + +### BRLTTY + + +This driver is used by default. +It uses [BrlTTY](brltty) to communicate with with a Braille device. + +Dependencies: + + +* BrlTTY (configured and running, [Documentation](http://mielke.cc/brltty/doc/Manual-BRLTTY/English/BRLTTY.html)) + +* python-brlapi (configured, [Documentation](http://mielke.cc/brltty/doc/Manual-BrlAPI/English/BrlAPI.html)) +## Currently supported platforms + + +Currently Fenrir completely supports the following Platforms: + +* Linux TTY +Support for further Systems are planned. + +# Installation + + +Fenrir can run without installation. It just requires the dependencies are installed first. + +We recommend to try it out before installation to be sure everything works and prevent yourself from experiencing a non-talking environment. + +## Try Out + +Fenrir does not require installation. You can try it and make sure everything works before you decide to install. In this way you can be sure that your system doesnt break or stop talking. +for that you can just grab the code and run as root ''src/fenrir/fenrir'' (in foreground) or ''src/fenrir/fenrir-daemon'' (in background, used by systemd for autostart) + +## Install it + +### Documented operating systems + + +### Arch Linux + + +For Arch there are PKGBUILDs in the AUR: + +* [fenrir](https///aur.archlinux.org/packages/fenrir/) + +* [fenrir-git](https///aur.archlinux.org/packages/fenrir-git/) + +### Manual + + + 1. Download the latest stable version from the [Fenrir-Project](https///linux-a11y.org/index.php?page=fenrir-screenreader) site. + 2. Unpack the archive + 3. Check the needed Dependencys by running [check-dependencys.py](https///github.com/chrys87/fenrir/blob/master/check-dependencies.py) script + 4. install the missing dependencies an standard installation requires the following: + + * python3 >= 3.3 (and all the following is needed for python3 ) + * python3-speechd (screen) + * python3-dbus (screen) + * python3-evdev >= 0.6.4(input) + * python3-daemonize (background service) + * python3-brlapi (braille) + * python3-pyenchant (spellchecker) + * your language for aspell (aspell-``) (spellchecker) + * sox (sound) + * For an individual installation see [Support and Requirements](#Support and Requirements) or consult the [Readme](https///github.com/chrys87/fenrir/blob/master/README.md)) + 5. run "install.sh" as root + +this installs Fenrir as the following + + * Application:''/opt/fenrir'' + * Settings:''/etc/fenrir'' + * Sound Icons:''/usr/share/fenrir/'' + +to remove Fenrir just run uninstall.sh as root + +### Git + + +if you want to get the latest code you can use git to get a development snapshot: + + git clone https://github.com/chrys87/fenrir.git + +## Auto Start + + +To start Fenrir once: + systemctl start fenrir + +To enable auto start on system boot: + systemctl enable fenrir + +# First Steps + + +If you are using Fenrir for the first time you may want to take a look at these resources: + +* [Keybindings](#Keybindings) + +* [Tutorial Mode](#Tutorial Mode) + +# Features + + +## Commands + + +### Keybindings + + +Normal commands can be invoked in two ways: + 1. Using a Metakey ([FenrirKey](#Fenrir Key)) + 2. Shortcuts with a single key + +See section [Keyboard](#Keyboard) in ''settings.conf'' for more information. +#### Fenrir Key + +The Fenrir Key is for invoking screen reader commands. Fenrir can utilize more than one FenrirKey at the same time. +By default the following keys are used: + 1. Insert + 2. KeyPad Insert + 3. Meta (Super, Windows) + +#### Script Key + +To invoke "Scripts" the Script Key is mandatory. The shortcut is encoded in the filename of the script. See [Scripting](#Scripting) +#### Desktop Layout + + | Shortcut | Command | + | -------- | ------- | + | FenrirKey + H | [toggle tutorial mode](#Tutorial Mode) | + | CTRL | [shut up (interrupts speech)](#shut up) | + | FenrirKey + KeyPad 9 | [reviews bottom](#review bottom) | + | FenrirKey + KeyPad 7 | [reviews top](#review top) | + | KeyPad 8 | [reviews current line](#review current line) | + | KeyPad 7 | [reviews previous line](#review previous line) | + | KeyPad 9 | [reviews next line](#review next line) | + | FenrirKey + KeyPad 4 | [reviews line beginning](#review line beginning) | + | FenrirKey + KeyPad 6 | [reviews line ending](#review line ending) | + | FenrirKey + KeyPad 1 | [reviews line first character](#review line first character) | + | FenrirKey + KeyPad 3 | [reviews line last character](#review line last character) | + | FenrirKey + Alt + 1 | [presents first line](#present first line) | + | FenrirKey + Alt + 2 | [presents last line](#present last line) | + | KeyPad 5 | [reviews current word](#review current word) | + | KeyPad 4 | [reviews previous word](#review previous word) | + | KeyPad 6 | [reviews next word](#review next word) | + | FenrirKey + Shift + KeyPad 5 | [reviews current word phonetic](#review current word phonetic) | + | FenrirKey + Shift + KeyPad 4 | [reviews previous word phonetic](#review previous word phonetic) | + | FenrirKey + Shift + KeyPad 6 | [reviews next word phonetic](#review next word phonetic) | + | KeyPad 2 | [reviews current char](#review current character) | + | KeyPad 1 | [reviews previous char](#review previous character) | + | KeyPad 3 | [reviews next char](#review next character) | + | FenrirKey + Shift + KeyPad 2 | [reviews current character phonetic](#review current character phonetic) | + | FenrirKey + Shift + KeyPad 1 | [reviews previous character phonetic](#review previous character phonetic) | + | FenrirKey + Shift + KeyPad 3 | [reviews next character phonetic](#review next character phonetic) | + | FenrirKey + CTRL + KeyPad 8 | [reviews up](#review up) | + | FenrirKey + CTRL + KeyPad 2 | [reviews down](#review down) | + | FenrirKey + KeyPad dot | [exit review](#exit review) | + | KeyPad dot | [cursor position](#cursor position) | + | FenrirKey + I | [indent curr line](#indent current line) | + | FenrirKey + KeyPad 5 | [current screen](#current screen) | + | FenrirKey + KeyPad 8 | [current screen before cursor](#current screen before cursor) | + | FenrirKey + KeyPad 2 | [current screen after cursor](#current screen after cursor) | + | `` | [cursor read to end of line](#cursor read to end of line) | + | `` | [cursor column](#cursor column) | + | `` | [cursor line number](#cursor line number) | + | `` | [Braille flush](#braille flush) | + | `` | [Braille pan left](#braille pan left) | + | `` | [Braille pan right](#braille pan right) | + | `` | [Braille return to cursor](#braille return to cursor) | + | FenrirKey + CTRL + 1 | [clear bookmark 1](#clear Bookmark X) | + | FenrirKey + Shift + 1 | [set bookmark 1](#set Bookmark X) | + | FenrirKey + 1 | [bookmark 1](#read Bookmark X) | + | FenrirKey + CTRL + 2 | [clear bookmark 2](#clear Bookmark X) | + | FenrirKey + Shift + 2 | [set bookmark 2](#set Bookmark X) | + | FenrirKey + 2 | [bookmark 2](#read Bookmark X) | + | FenrirKey + CTRL + 3 | [clear bookmark 3](#clear Bookmark X) | + | FenrirKey + Shift + 3 | [set bookmark 3](#set Bookmark X) | + | FenrirKey + 3 | [bookmark 3](#read Bookmark X) | + | FenrirKey + CTRL + 4 | [clear bookmark 4](#clear Bookmark X) | + | FenrirKey + Shift + 4 | [set bookmark 4](#set Bookmark X) | + | FenrirKey + 4 | [bookmark 4](#read Bookmark X) | + | FenrirKey + CTRL + 5 | [clear bookmark 5](#clear Bookmark X) | + | FenrirKey + Shift + 5 | [set bookmark 5](#set Bookmark X) | + | FenrirKey + 5 | [bookmark 5](#read Bookmark X) | + | FenrirKey + CTRL + 6 | [clear bookmark 6](#clear Bookmark X) | + | FenrirKey + Shift + 6 | [set bookmark 6](#set Bookmark X) | + | FenrirKey + 6 | [bookmark 6](#read Bookmark X) | + | FenrirKey + CTRL + 7 | [clear bookmark 7](#clear Bookmark X) | + | FenrirKey + Shift + 7 | [set bookmark 7](#set Bookmark X) | + | FenrirKey + 7 | [bookmark 7](#read Bookmark X) | + | FenrirKey + CTRL + 8 | [clear bookmark 8](#clear Bookmark X) | + | FenrirKey + Shift + 8 | [set bookmark 8](#set Bookmark X) | + | FenrirKey + 8 | [bookmark 8](#read Bookmark X) | + | FenrirKey + CTRL + 9 | [clear bookmark 9](#clear Bookmark X) | + | FenrirKey + Shift + 9 | [set bookmark 9](#set Bookmark X) | + | FenrirKey + 9 | [bookmark 9](#read Bookmark X) | + | FenrirKey + CTRL + 0 | [clear bookmark 10](#clear Bookmark X) | + | FenrirKey + Shift + 0 | [set bookmark 10](#set Bookmark X) | + | FenrirKey + 0 | [bookmark 10](#read Bookmark X) | + | FenrirKey + KeyPad Slash | [set window application](#Create Window) | + | 2 * FenrirKey + KeyPad Slash | [clear window application](#Remove Window) | + | KeyPad Plus | [read last incoming](#last incoming) | + | FenrirKey + F2 | [toggles braille](#toggle braille) | + | FenrirKey + F3 | [toggles sound](#toggle sound) | + | FenrirKey + F4 | [toggles speech](#toggle speech) | + | KeyPad Enter | [temporarily disables speech](#disable speech temporarily) | + | FenrirKey + CTRL + P | [toggles punctuation level](#toggle punctuation level) | + | FenrirKey + RightBrace | [toggle auto spell check](#toggle auto spell check) | + | FenrirKey + Backslash | [toggles output](#toggle output) | + | FenrirKey + CTRL + E | [toggles emoticons](#toggle emoticons) | + | FenrirKey + KeyPad Enter | [toggles auto read](#toggle auto read) | + | FenrirKey + CTRL + T | [toggles auto time](#toggle auto time) | + | FenrirKey + KeyPad ASTERISK | [toggles highlight tracking](#toggle highlight tracking) | + | FenrirKey + Q | [quits fenrir](#quit Fenrir) | + | FenrirKey + T | [Announce time](#Time) | + | 2 * FenrirKey + T | [Announce date](#Date) | + | FenrirKey + S | [spell check](#spell check) | + | 2 * FenrirKey + S | [add word to spell check](#add word to spell check) | + | FenrirKey + Shift + S | [removes word from spell check](#removes word from spell check) | + | FenrirKey + Backspace | [forward keypress](#forward keypress) | + | FenrirKey + Up | [increase speech volume](#increase speech volume) | + | FenrirKey + Down | [decrease speech volume](#decrease speech volume) | + | FenrirKey + Right | [increase speech rate](#increase speech rate) | + | FenrirKey + Left | [decrease speech rate](#decrease speech rate) | + | FenrirKey + Alt + Right | [increase speech pitch](#increase speech pitch) | + | FenrirKey + Alt + Left | [decrease speech pitch](#decrease speech pitch) | + | FenrirKey + Alt + Up | [increase sound volume](#increase sound volume) | + | FenrirKey + Alt + Down | [decrease sound volume](#decrease sound volume) | + | FenrirKey + CTRL + Shift + C | [clears clipboard](#clear clipboard) | + | FenrirKey + Home | [first clipboard](#first clipboard) | + | FenrirKey + End | [last clipboard](#last clipboard) | + | FenrirKey + PageUp | [previous clipboard](#previous clipboard) | + | FenrirKey + PageDown | [next clipboard](#next clipboard) | + | FenrirKey + Shift + C | [current clipboard](#read current clipboard) | + | FenrirKey + C | [copy marked text to clipboard](#copy marked to clipboard) | + | FenrirKey + V | [paste clipboard contents](#paste clipboard) | + | FenrirKey + P | [import clipboard from file](#import clipboard from file) | + | FenrirKey + Alt + Shift +C | [export clipboard to file](#export clipboard to file) | + | FenrirKey + CTRL + Shift + X | [remove marks](#Remove Marks) | + | FenrirKey + X | [set mark](#Set mark) | + | FenrirKey + Shift + X | [announce marked text](#Get text between marks) | + | Linux specific | + | `` | export clipboard to X | + | FenrirKey + CTRL + Up | include Alsa volume | + | FenrirKey + CTRL + Down | decrease Alsa volume | + +#### Laptop Layout + + | Shortcut | Command | + | -------- | ------- | + | FenrirKey + H | [toggle tutorial mode](#Tutorial Mode) | + | CTRL | [shut up (interrupts speech)](#shut up) | + | FenrirKey + Shift + O | [reviews bottom](#review bottom) | + | FenrirKey + Shift + U | [reviews top](#review top) | + | FenrirKey + I | [reviews current line](#review current line) | + | FenrirKey + U | [reviews previous line](#review previous line) | + | FenrirKey + O | [reviews next line](#review next line) | + | FenrirKey + Shift + J | [reviews line beginning](#review line beginning) | + | FenrirKey + Shift + L | [reviews line ending](#review line ending) | + | FenrirKey + CTRL + J | [reviews line first character](#review line first character) | + | FenrirKey + CTRL + L | [reviews line last character](#review line last character) | + | FenrirKey + Alt + 1 | [presents first line](#present first line) | + | FenrirKey + Alt + 2 | [presents last line](#present last line) | + | FenrirKey + K | [reviews current word](#review current word) | + | FenrirKey + J | [reviews previous word](#review previous word) | + | FenrirKey + L | [reviews next word](#review next word) | + | FenrirKey + CTRL + ALT + K | [reviews current word phonetic](#review current word phonetic) | + | FenrirKey + CTRL + ALT + J | [reviews previous word phonetic](#review previous word phonetic) | + | FenrirKey + CTRL + ALT + L | [reviews next word phonetic](#review next word phonetic) | + | FenrirKey + comma | [reviews current character](#review current character) | + | FenrirKey + M | [reviews previous character](#review previous character) | + | FenrirKey + dot | [reviews next character](#review next character) | + | FenrirKey + CTRL + ALT + comma | [reviews current character phonetic](#review current character phonetic) | + | FenrirKey + CTRL + ALT + M | [reviews previous character phonetic](#review previous character phonetic) | + | FenrirKey + CTRL + ALT + dot | [reviews next character phonetic](#review next character phonetic) | + | FenrirKey + CTRL + I | [reviews up](#review up) | + | FenrirKey + CTRL + comma | [reviews down](#review down) | + | FenrirKey + Slash | [exit review](#exit review) | + | FenrirKey + Shift + dot | [cursor position](#cursor position) | + | 2 * FenrirKey + I | [indent curr line](#indent current line) | + | FenrirKey + Shift + K | [current screen](#current screen) | + | FenrirKey + Shift + I | [current screen before cursor](#current screen before cursor) | + | FenrirKey + Shift + comma | [current screen after cursor](#current screen after cursor) | + | `` | [cursor read to end of line](#cursor read to end of line) | + | `` | [cursor column](#cursor column) | + | `` | [cursor line number](#cursor line number) | + | `` | [Braille flush](#braille flush) | + | `` | [Braille pan left](#braille pan left) | + | `` | [Braille pan right](#braille pan right) | + | `` | [Braille return to cursor](#braille return to cursor) | + | FenrirKey + CTRL + 1 | [clear bookmark 1](#clear Bookmark X) | + | FenrirKey + Shift + 1 | [set bookmark 1](#set Bookmark X) | + | FenrirKey + 1 | [bookmark 1](#read Bookmark X) | + | FenrirKey + CTRL + 2 | [clear bookmark 2](#clear Bookmark X) | + | FenrirKey + Shift + 2 | [set bookmark 2](#set Bookmark X) | + | FenrirKey + 2 | [bookmark 2](#read Bookmark X) | + | FenrirKey + CTRL + 3 | [clear bookmark 3](#clear Bookmark X) | + | FenrirKey + Shift + 3 | [set bookmark 3](#set Bookmark X) | + | FenrirKey + 3 | [bookmark 3](#read Bookmark X) | + | FenrirKey + CTRL + 4 | [clear bookmark 4](#clear Bookmark X) | + | FenrirKey + Shift + 4 | [set bookmark 4](#set Bookmark X) | + | FenrirKey + 4 | [bookmark 4](#read Bookmark X) | + | FenrirKey + CTRL + 5 | [clear bookmark 5](#clear Bookmark X) | + | FenrirKey + Shift + 5 | [set bookmark 5](#set Bookmark X) | + | FenrirKey + 5 | [bookmark 5](#read Bookmark X) | + | FenrirKey + CTRL + 6 | [clear bookmark 6](#clear Bookmark X) | + | FenrirKey + Shift + 6 | [set bookmark 6](#set Bookmark X) | + | FenrirKey + 6 | [bookmark 6](#read Bookmark X) | + | FenrirKey + CTRL + 7 | [clear bookmark 7](#clear Bookmark X) | + | FenrirKey + Shift + 7 | [set bookmark 7](#set Bookmark X) | + | FenrirKey + 7 | [bookmark 7](#read Bookmark X) | + | FenrirKey + CTRL + 8 | [clear bookmark 8](#clear Bookmark X) | + | FenrirKey + Shift + 8 | [set bookmark 8](#set Bookmark X) | + | FenrirKey + 8 | [bookmark 8](#read Bookmark X) | + | FenrirKey + CTRL + 9 | [clear bookmark 9](#clear Bookmark X) | + | FenrirKey + Shift + 9 | [set bookmark 9](#set Bookmark X) | + | FenrirKey + 9 | [bookmark 9](#read Bookmark X) | + | FenrirKey + CTRL + 0 | [clear bookmark 10](#clear Bookmark X) | + | FenrirKey + Shift + 0 | [set bookmark 10](#set Bookmark X) | + | FenrirKey + 0 | [bookmark 10](#read Bookmark X) | + | FenrirKey + CTRL + 8 | [set window application](#Create Window) | + | 2 * FenrirKey + CTRL + 8 | [clear window application](#Remove Window) | + | FenrirKey + Semicolon | [read last incoming](#last incoming) | + | FenrirKey + F2 | [toggles braille](#toggle braille) | + | FenrirKey + F3 | [toggles sound](#toggle sound) | + | FenrirKey + F4 | [toggles speech](#toggle speech) | + | FenrirKey + Enter | [temporarily disables speech](#disable speech temporarily) | + | FenrirKey + Shift + CTRL + P | [toggles punctuation level](#toggle punctuation level) | + | FenrirKey + RightBrace | [toggle auto spell check](#toggle auto spell check) | + | FenrirKey + Shift + Enter | [toggles output](#toggle output) | + | FenrirKey + Shift + E | [toggles emoticons](#toggle emoticons) | + | FenrirKey + Enter | [toggles auto read](#toggle auto read) | + | FenrirKey + CTRL + T | [toggles auto time](#toggle auto time) | + | FenrirKey + Y | [toggles highlight tracking](#toggle highlight tracking) | + | FenrirKey + Q | [quits fenrir](#quit Fenrir) | + | FenrirKey + T | [Announce time](#Time) | + | 2 * FenrirKey + T | [Announce date](#Date) | + | FenrirKey + S | [spell check](#spell check) | + | 2 * FenrirKey + S | [add word to spell check](#add word to spell check) | + | FenrirKey + Shift + S | [removes word from spell check](#removes word from spell check) | + | FenrirKey + Backspace | [forward keypress](#forward keypress) | + | FenrirKey + Up | [increase speech volume](#increase speech volume) | + | FenrirKey + Down | [decrease speech volume](#decrease speech volume) | + | FenrirKey + Right | [increase speech rate](#increase speech rate) | + | FenrirKey + Left | [decrease speech rate](#decrease speech rate) | + | FenrirKey + Alt + Right | [increase speech pitch](#increase speech pitch) | + | FenrirKey + Alt + Left | [decrease speech pitch](#decrease speech pitch) | + | FenrirKey + Alt + Up | [increase sound volume](#increase sound volume) | + | FenrirKey + Alt + Down | [decrease sound volume](#decrease sound volume) | + | FenrirKey + CTRL + Shift + C | [clears clipboard](#clear clipboard) | + | FenrirKey + Home | [first clipboard](#first clipboard) | + | FenrirKey + End | [last clipboard](#last clipboard) | + | FenrirKey + PageUp | [previous clipboard](#previous clipboard) | + | FenrirKey + PageDown | [next clipboard](#next clipboard) | + | FenrirKey + Shift + C | [current clipboard](#read current clipboard) | + | FenrirKey + C | [copy marked text to clipboard](#copy marked to clipboard) | + | FenrirKey + V | [paste clipboard contents](#paste clipboard) | + | FenrirKey + F5 | [import clipboard from file](#import clipboard from file) | + | FenrirKey + Alt + Shift +C | [export clipboard to file](#export clipboard to file) | + | FenrirKey + CTRL + Shift + X | [remove marks](#Remove Marks) | + | FenrirKey + X | [set mark](#Set mark) | + | FenrirKey + Shift + X | [announce marked text](#Get text between marks) | + | Linux specific | + | `` | export clipboard to X | + | FenrirKey + CTRL + Up | increases Alsa volume | + | FenrirKey + CTRL + Down | decreases Alsa volume | +### General + +#### quit Fenrir +Just stops fenrir. +#### shut up + +Interrupt the current spoken. +### Review Modes + +Fenrir provides a virtual cursor, with it you can navigate all over the screen without changing the text cursor. + +Using the review feature will open the review mode automatically. + +The review cursor always starts from the text cursor. Attention: after using the review mode, the review cursor will stay open until you use the ''exit review'' shortcut. + +Think when using clipboard operations and similar. The review cursor is always prefered over the text cursor. + +Fenrir sounds a bell sound if the used review command jumps to another line or end of screen. +#### exit review + +You can leave the review mode by pressing the ''exit review'' shortcut. +#### review bottom + +Set the review cursor to first column in the last line. +#### review top + +Set the review cursor to the first column in the first line +#### review current line + +Set the review cursor to the beginn of the the current line and review it. +#### review previous line + +Set the review cursor to the previous line and review it. +#### review next line + +Set the review cursor to the next line and review it. +#### review line beginning + +Set the review cursor to the begin of the current line +#### review line ending + +Set the review cursor to the end of the current line +#### review line first character + +Set the review cursor the first char (that is not space) in the current line and review it. +#### review line last character + +Set the review cursor the last char (that is not space) in the current line and review it. +#### review current word + +Sets the review cursor to the beginning of the current word and review it. +#### review previous word + +Sets the review cursor to the beginning of the previous word and review it. +#### review next word + +Sets the review cursor to the beginning of the next word and review it. +#### review current word phonetic + +Sets the review cursor to the beginning of the current word and spell it phonetic. +#### review previous word phonetic + +Sets the review cursor to the beginning of the previous word and spell it phonetic. +#### review next word phonetic + +Sets the review cursor to the beginning of the next word and spell it phonetic. +#### review current character + +Does not change the review cursor. Just announce the current char. +#### review previous character + +Sets review cursor to the previous column and review it +#### review next character + +Sets review cursor to the next column and review it +#### review current character phonetic + +Does not change the review cursor. Just announce the current char phonetic. +#### review previous character phonetic + +Sets review cursor to the previous column and announce the char phonetic. +#### review next character phonetic + +Sets review cursor to the next column and announce the char phonetic. +#### review up + +Set the review cursor in the same column one line above the current one and review it. +#### review down + +Set the review cursor in the same column one line below the current one and review it. +### Handling marking + +A mark defines a point of origin or end to prepare to copy or paste a block of text. +\\ +Examples where you need marks are: + +* copy to clipboard + +* set window application + +* set bookmark 1 - X +#### Set mark + +How to set a mark: + 1. navigate with review or textcursor to the position you want to set the mark. Attention: if a review cursor is set, that is the prefered. If you want to use text cursor, be sure that you are not in review mode. + 2. press shortcut for ''set mark'' +you can set two marks (begin and end). Some commands allow some simpler usecases just using the whole line if only one mark is set. you may want to try this out. +#### Get text between marks + +To get the text that is currently between your marks press shortcut for ''marked text''.\\ +#### Remove Marks + +You can remove all current marks by pressing the shortcut for ''remove marks''. +Changing the screen also removes the marks. +### Screen Interaction + +Fenrir provides several methods to interact with the current screen. +#### forward keypress + +This just forwards the next shortcut to the screen Fenrir shortcut or not. This is useful if the currently pressed shortcut is also in use by Fenrir. +#### Clipboard + +Fenrir provides a clipboard with multible items represented by a list. You navigate throught the list and paste the selected clipboard. +##### copy marked to clipboard + +To copy something to the clipboard you need to set one or two marks. if you set one mark, the text between the mark and your current cursor is copied to clipboard. Setting two marks just copies the text between the marks into the clipboard. If you copy something it is always placed as the first item on your clipboard. +##### clear clipboard + +You can remove all items from the current clipboard by ''clear clipboard'' functionality. +##### first clipboard + +This moves quick to the first item of the clipboard. +##### last clipboard + +This moves quick to the last item of the clipboard. +##### previous clipboard + +Go to previous item in the clipboard. +##### next clipboard + +Go to next item on the clipboard. +##### read current clipboard + +Read the content of the current item of the clipboard. +##### paste clipboard + +Pass whatever item is currently selected by first, last, prev or next clipboard commands. +if no special clipboard is selected the (last copied) is used. +##### export clipboard to file + +This allows you to export the current clipboard to a configurable filepath. This is useful to share the clipboard with a graphical desktop. +##### import clipboard from file + +Import a clipboard from a configurable file. This is useful to share the clipboard with a graphical desktop. +### Quick Settings + +Fenrir provides shortcuts to change settings temporarily and on the fly without the need to permanently change the ''settings.conf'' file. +#### toggle braille + +Enables and disables Braille. This is not persistent stored in your ''settings.conf'' but during run time. +#### toggle sound + +Enables and disables sound. This is not persistent stored in your ''settings.conf'' but during run time. +#### toggle speech + +Enables and disables speech. This is not persistent stored in your ''settings.conf'' but during run time. +#### disable speech temporarily + +Disables the speech until next key press. it might be useful if you want to listen to music or similar. As soon as a key is pressed it is going to be enabled again. +#### toggle punctuation level + +Cycle between all available punctuation levels. This is not persistent stored in your ''settings.conf'' but during run time. +#### toggle auto spell check + +Enables and disables automatic spellchecker (when typing). This is not persistent stored in your ''settings.conf'' but during run time. +#### toggle emoticons + +Enables and disables emoticons. This is not persistent stored in your ''settings.conf'' but during runtime. +#### toggle output + +Enables and disables all output at once (sound, Braille, speech). This is not persistent stored in your ''settings.conf'' but during run time. +#### toggle auto read + +Enables and disables what is automatically spoken. This is not persistent stored in your ''settings.conf'' but during run time. +#### toggle auto time + +Enables and disables auto time functionality. This is not persistent stored in your ''settings.conf'' but during run time. +#### toggle highlight tracking + +Enables and disables highlight tracking. This is not persistent stored in your ''settings.conf'' but during run time. +#### increase speech volume + +Increase the volume of the speech. This is not persistent stored in your ''settings.conf'' but during runtime. +#### decrease speech volume + +Decrease the volume of the speech. This is not persistent stored in your ''settings.conf'' but during runtime. +#### increase speech rate + +Increase the rate of the speech. This is not persistent stored in your ''settings.conf'' but during runtime. +#### decrease speech rate + +Decrease the rate of the speech. This is not persistent stored in your ''settings.conf'' but during runtime. +#### increase speech pitch + +Increase the pitch of the speech. This is not persistent stored in your ''settings.conf'' but during runtime. +#### decrease speech pitch + +Decrease the pitch of the speech. This is not persistent stored in your ''settings.conf'' but during runtime. +#### increase sound volume + +Increase the volume of the sound. This is not persistent stored in your ''settings.conf'' but during runtime. +#### decrease sound volume + +Decrease the volume of the sound. This is not persistent stored in your ''settings.conf'' but during runtime. +### Window Mode + +Fenrir supports window mode, a window is a partial area of the screen. +#### Create Window + +To create a window you need to do the following: + 1. set a beginning mark (as the start of the window) + 2. set an end mark (where the window should end) + 3. press ''set window application'' shortcut. +Now Fenrir ignores anything outside of the window.\\ +#### Remove Window + +You can remove the window by pressing ''the clear window application'' shortcut. +Now Fenrir will read everything on the screen again. +### Tracking Modes + +Different types of tracking are currently supported +See section [Focus](#Focus) in ''settings.conf'' for more information. +#### Cursor Tracking + +This follows the text cursor. This is the typical way an application works. This is used by: + +* almost any shell such as (Bash, Zsh, sh) + +* vim + +* nano + +* emacs + +* mutt + +* tintin++ +#### Highlight Tracking + +In some applications there are no text cursors. In those applications cursor changes are represented by different colors or attributes (underlined or bold). This mode tracks and announces these changes for you. This is used by: + + * wifi-menu + * dialog + * alpine +### Tutorial Mode + +Fenrir provides a Tutorial mode. +When you enter tutorial mode, screen reader commands are intercepted and explained instead of executing them. ''Arrow up'' and ''Arrow Down'' let you navigate through a list of all available commands with shortcuts and description. Pressing escape leaves the tutorial mode. + +### Information + +#### Time +Announces the current Time. +#### Date + +Announces the current Date. +#### Bookmarks + +Bookmarks provide quick access to part of the screen without the need to navigate to the area. +By default Fenrir provides 10 bookmarks. Those can be set and accessed via shortcut. +This is useful for status lines or other information where the position does not change. +##### set Bookmark X + +You need to set the bookmark first. For that you have to set one or two lines for use. + 1. Set marks (one or two) + 2. press shortcut for ''set bookmark X''. X represents the number 1 - 10. +##### read Bookmark X + +If a bookmark is set you can access the area just by pressing the ''bookmark X'' shortcut. X represents the number 1 - 10. Bookmarks are dynamic. That means the content changes with the screen. +##### clear Bookmark X + +to remove a bookmark just press the ''clear bookmark X'' shortcut. X represents the number 1 - 10. +Afterward the bookmark is no longer available. +#### cursor position + +You can get information about the current cursor and its position by using the "cursor position" functionality. +#### indent current line + +Announce the current indent level of the current line. It represents the number of trailing spaces of the line. +#### current screen + +Reads all the current screen from the beginning to the end. +#### current screen before cursor + +Reads current screen from the beginning of the screen to the current cursor position. +#### current screen after cursor + +Read anything after current cursor position to the end. +#### cursor read to end of line + +Read from the current cursor position to the end of the current line. +#### cursor column + +Read the current X position of a cursor (column of the current line). +#### cursor line number + +Read the current Y position of a cursor (line number). +#### present first line + +Reads just the first line. this is maybe useful for status information. +#### present last line + +Presets the last line. This is maybe useful for status information. +#### last incoming + +Repeat the last automatically incoming text. +## Input + +### Echo +Fenrir provides different methods of echoing content: + +* Word: Will speak each word after you push space + +* Character: speak any letter you type on the screen + +* Delete Character: speaks the character prior to the cursor when you push backspace +### Silence on Key press + +### Spellchecker +Fenrir has a built-in spellchecker, it can invoke automatically while typing or be called by a shortcut. +Commands to add or remove the current word to the dictionary are included. +As using the spellchecker is enhanced usage. You will need dictionary aspell-``. +See section [General](#General) in ''settings.conf'' for more information. +#### spell check + +Invokes the spellcheck on the word that contains the Review or text cursor. +#### add word to spell check + +Adds the word under the Review or Text cursor to the dictionary. +#### removes word from spell check + +Removes the word under the Review or Text cursor from the dictionary. +## Announcements + +### Emoticons +If you want to replace ":)" emoticons with "smile" in speech you can use this feature. +It can be toggled on or off. +You can define emoticons in a dictionary, please see Emoticon Dictionary. +See section [General](#General) in ''settings.conf'' to see how to enable or disable this feature. + +### Time + +Announce the time at periodical increments, To track the time easily. +You can define 2 different ways of time announcements. + 1. periodic + 2. on fix minutes + +Example periodic, every 20 minutes "delaySec=20": + + [time] + enabled=True + presentTime=True + presentDate=True + delaySec=20 + onMinutes= + announce=True + interrupt=False + +Example on fix minutes in an hour. example every quarter "delaySec=0" and "onMinutes=00,15,30,45": + + [time] + enabled=True + presentTime=True + presentDate=True + #delaySec is repected bevore onMinutes so it need to be set to 0 + delaySec=0 + onMinutes=00,15,30,45 + announce=True + interrupt=False +### Promoted List + +Promoted Lists are a nice feature if you are away from your computer or performing more longer tasks. +you can define a list of words which you want to hear a sound icon for after a period of inactivity. +Example if the word "Chrys" appears after 120 Seconds of inactivity: + [promote] + enabled=True + inactiveTimeoutSec=120 + list=Chrys +See section [Promote](#Promote) in ''settings.conf'' for more information. +### Punctuation + +Fenrir handles punctuation levels and names for you with several provided dictionaries. + +See levelDict +See punctuationDict +## Braille + +Fenrir provides Braille support in Version >= 2.0. +See section [Braille](#Braille) in ''settings.conf'' for more information. +### braille flush + +If a message appears on the Braille device you can flush it to get back to the review- or system cursor +### Braille pan left + +If a line is longer than your Braille devices you can move the view (called panning) to the left. +So you can read stuff without the need to move the review- or system cursor. +### Braille pan right + +If a line is longer than your Braille devices you can move the view (called panning) to the right. +So you can read stuff without the need to move the review- or system cursor. +### braille return to cursor + +When you have finished reading the line on the Braille device using panning, the focus can be returned to the current used cursor by using "return to cursor" command. +## Dictionary + +You can make use of different kinds of built-in dictionary's. +A dictionary has a name and list of keys and values separated by :===: +Example: + [customDict] + Chrys:===:Chrys is cool + lollipop:===:lolli +that means that every instance "chrys" is displayed, speech will say Chrys is cool. +"lollipop" is spoken as "lolli". +Before making changes to a dictionary we recommend making a backup of your current dictionary in case future updates overwrite your local changes. +### Punctuation + +#### Level +The punctuation level dict contains lists with "what punctuation is spoken in what level". +the default one looks like this: + [levelDict] + none:===: + some:===:.-$~+*-/\@ + most:===:.,:-$~+*-/\@!#%^&*()[]}{`<>`; + all:===:!"#$%& \'()*+,-./:;`<=>`?@[\\]^_`{|}~ +the level "none" has no values. so it should not speak any punctuation (sadly this is not respected by every TTS system) +if "some" is the current level the following are spoken: dot dash dollar tilde plus star slash backslash at. +same for most and all, you can add new levels. if you cycle punctuation levels they are recognized. the default punctuation level is set in settings.conf. The default is "some". +#### Punctuation + +The punctuation dictionary "[punctDict]" contains how the punctuation is spoken. +Example: + [punctDict] + _:===:line +speaks an _ as "line". + [punctDict] + _:===:underscore +speaks an _ as underscore. +for question mark an ? is appended to the word that the TTS system can announce the question correctly. +### Custom + +The dict "[customDict]" is just for your own use, it just replace the key with the value without any special functionality. This might be used to fix incorrectly spoken words, make words more common, shorter or just for fun. :) +### Emoticons + +The Emoticons dictionary "[emoticonDict]" by default contains some emoticons. it can replace ":)" with "smile" or "XD" with "loool" Making chat more colorful. +A nice feature with this dictionary is that you can toggle the substitution on or off during run time or in settings.conf. This is useful because while doing programming or other serious work you want to hear colons and perryns not smiles. +# Configuration + +You can configure Fenrir in the following places (ordered by priority): + 1. Commandline Parameters ''-o'' see [Set settings coption](#Set settings coption) + 2. /etc/fenrir/settings/settings.conf see [Settigns](#Settings) + 3. ``/config/settings/settings.conf see [Settigns](#Settings) + 4. hard coded defaults +## Commandline Arguments + +### Set settings option +You can specify options that overwrite the setting.conf. +This is done with ''-o `` parameter. +The list of options have the following syntax + fenrir -o "section#setting=value;section#setting=value" + +For example changing the sound driver to gstreamer and disabling Braille + fenrir -o "sound#driver=gstreamerDriver;braille#enabled=False=False" +or change the debug level to verbose + fenrir -o "general#debugLevel=3" +You can find the available sections and variables here [#Settings](#Settings) +See Syntax [#settings.conf syntax](#settings.conf syntax) +### settings.conf syntax + +the syntax of the [settings.conf](#Settings) is quite simple and similar to a "*.ini" file, there are 4 different elements. + 1. Sections + 2. Settings + 3. Values + 4. Comments + +A comment starts with a # and is ignored by Fenrir. + # this is a comment +To group settings we have sections. +A section can look like this: + [Section] +A setting looks like this: + settingName=Value + +Example: + [sound] + # Turn sound on or off: + enabled=True + # Select the driver used to play sounds, choices are genericDriver and gstreamerDriver. + # Sox is default. + driver=genericDriver + +## Settings + +### Sound +The sound is configured in section ''[sound]''. + +Turn sound on or off: + enabled=True +Values: on=''True'', off=''False'' + +Select the driver used to play sounds. +The genericDriver using Sox is the default. + + driver=genericDriver + +Available Drivers: + +* ''genericDriver'' using the generic driver, for Fenrir <1.5 just use ''generic'' + +* ''gstreamerDriver'' using the gstreamer, for Fenrir <1.5 just use ''gstreamer'' + +These are the pack of sounds used for sound icons. + theme=default +By default we ship two sound packs. + 1. ''default'' opus encoded, for newer Sox versions + 2. ''default-wav'' wav encoded, just for compatibility +Sound packs are located at /usr/share/sounds/fenrir/ + +Sound volume controls how loud the sounds for your selected sound pack are. + volume=1.0 +Values: ''0.0'' is quietest, ''1.0'' is loudest. + +#### Generic Driver + +The generic sound driver uses shell commands for play sound and frequencies. + +''genericPlayFileCommand'' defines the command that is used to play a sound file. + genericPlayFileCommand=`` +''genericFrequencyCommand'' defines the command that is used playing frequencies. + genericFrequencyCommand=`` + +The following variables are substituted in ''genericPlayFileCommand'' and ''genericFrequencyCommand'': + +* ''fenrirVolume'' = the current volume setting + +* ''fenrirSoundFile'' = the sound file for an sound icon + +* ''fenrirFrequence'' = the frequency to play + +* ''fenrirDuration'' = the duration of the frequency + +Example genericPlayFileCommand (default) + genericPlayFileCommand=play -q -v fenrirVolume fenrirSoundFile +Example genericFrequencyCommand (default) + genericFrequencyCommand=play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence +### Speech + +Speech is configured in section ''[speech]''. +Turn speech on or off: + enabled=True +Values: on=''True'', off=''False'' + +# Select speech driver, options are speechdDriver (default), genericDriver or espeakDriver: + +driver=speechdDriver +#driver=espeakDriver + +#driver=genericDriver + +Select the driver used to generate speech output. + + driver=speechdDriver + +Available Drivers: + +* ''genericDriver'' using the generic driver, for Fenrir <1.5 this is not available + +* ''speechdDriver'' using speech-dispatcher, for Fenrir <1.5 just use ''speechd'' + +* ''espeakDriver'' using the espeak directly, for Fenrir <1.5 just use ''espeak'' + +The rate selects how fast Fenrir will speak. + rate=0.65 +Values: Range Minimum:''0.0'' is slowest, Maximum:''1.0'' is fastest. + +Pitch controls the pitch of the voice. + pitch=0.5 +Values: Range Minimum:''0.0'' is lowest, Maximum:''1.0'' is highest. + +A Pitch for capital letters can be set. + capitalPitch=0.9 +Values: Range Minimum:''0.0'' is lowest, Maximum:''1.0'' is highest. + +The Volume controls the loudness of the voice. + volume=1.0 +Values: Range Minimum:''0.0'' is quietest, Maximum:''1.0'' is loudest. + +Some speech drivers like speechdDriver can support various modules. these can be set here. + module=espeak +Values: Text, Consult speech-dispatcher's configuration to see what modules are available. + +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= +Values: Text, see your TTS synths documentation what is available. + +Select the language you want Fenrir to use. + language=english-us +Values: Text, see your TTS synths documentation what is available. + +Read new text as it occurs +autoReadIncoming=True +Values: on=''True'', off=''False'' + +#### Generic Driver + +The generic speech driver uses shell commands for speech synthisus. + +''genericSpeechCommand'' defines the command that is executed for creating speech +The following variables are substituted in ''genericSpeechCommand'': + +* ''FenrirText'' = is the text that should be spoken + +* ''fenrirModule'' = may be the speech module like used in speech-dispatcher, not every TTY needs this + +* ''fenrirLanguage'' = the language to speak in + +* ''fenrirVoice'' = is the current voice that should be used + +* ''fenrirVolume'' = is replaced with the current volume + +* ''fenrirPitch'' = is replaced with the current pitch + +* ''fenrirRate'' = is replaced with the current speed (speech rate) + +Example genericSpeechCommand (default): + genericSpeechCommand=espeak -a fenrirVolume -s fenrirRate -p fenrirPitch -v fenrirVoice "fenrirText" + +These are the minimum and maximum values of the TTS system used in genericSpeechCommand. They are needed to calculate the abstract range in volume, rate and pitch 0.0 - 1.0. + + FenrirMinVolume=0 + fenrirMaxVolume=200 + fenrirMinPitch=0 + fenrirMaxPitch=99 + fenrirMinRate=80 + fenrirMaxRate=450 + +The current volume, pitch and rate is calculated like this +value = min + [volume,pitch,rate] * (min - max ) +### Braille + +Braille is a WIP and not ready yet. +Braille support can be configured in section ''[braille]''. + +Turn braille on or off: + enabled=False +Values: on=''True'', off=''False'' + +Select the driver used for communication with a braille device. + driver=brlapiDriver +Values: Text, available Driver +Available Drivers: + +* ''brlttyDriver'' using brltty for braille communication, for Fenrir <1.5 just use ''brltty'' + +The Braille layout can be configured here + layout=en +Values: Text, see braille driver for layouts. + +What should the flush timeout relate to + flushMode=word +Values: Text, an flushMode +Existing flushModes: + +* ''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) + +Seconds to flush (see flushMode) + flushTimeout=3 +Values: Integer, in Seconds or ''-1'' = no automatic flush (manual via shortcut) +The total flush time calculates in relation to flushMode. + +How should the Braille cursor focus be tracked? + cursorFocusMode=page +Values: Text, an existing cursor focus mode +Available cursor focus modes: + +* ''page'' = if the cursor crosses the border move to next page and start at begin + +* ''fixCell'' = ajust the cursor on a special cell where it is always placed. the display scroll here more smooth. + + +Define the cell on the Braille device where Fenrir should scroll and keep the cursor + fixCursorOnCell=-1 +Values: Integer + +* ''0'' = first cell on device, + +* ''-1'' = last cell on device + +* ''>0'' = fix cell number + +What cursor should Fenrir show on the Braille device + cursorFollowMode=review +Values: Text, an exsiting cursor following mode. +Existing cursor following mode: + +* ''none'' = no automatic toggle command used + +* ''review'' = priority to review + +* ''last'' = follow last used cursor + +number of cells in panning (horizontal). How many cell should be panned on press the routing key? + panSizeHorizontal=0 +Values: Integer, + +* ''0'' = display size + +* ''>0'' number of cells +### Screen + +The settings for screens, (TTY, PTY) are configured in the ''[screen]'' section. + +The driver to get the information from the screen: + driver=vcsaDriver +Available Drivers: + +* ''vcsaDriver'' using the VCSA driver (for TTYs), for Fenrir <1.5 just use ''vcsa'' +The encoding of the screen + encoding=cp850 +Values:''cp850'' is used for Western languages like USA or Europe. + +The driver updates Fenrir with changes on the screen. + screenUpdateDelay=0.05 +Values: in Seconds + +If you want Fenrir to not be active on any screen for various reasons. Maybe an X server or Wayland is running on that screen. You can make Fenrir ignore it or multiple screens seperated by '','' with: + suspendingScreen= +Values: Depends on driver: + +* VCSA: the number of the TTY. TTY6 is ''6''. +Example ignore TTY1 and TTY2: + suspendingScreen=1,2 + +There is also the ability to let Fenrir auto detect screens that are running an X server. So Screens running an GUI can be ignored. + autodetectSuspendingScreen=True +Values: on=''True'', off=''False'' + +### Keyboard + +The settings for keyboard and input related configuration is located in the section ''[keyboard]'' of the ''settings.conf'' file. + +Select the driver used for grabbing keybord input and for recieving shortcuts. + driver=evdevDriver +Values: Text, available Driver +Available Drivers: + +* ''evdevDriver'' uses the evdev input system of linux, for Fenrir <1.5 just use ''evdev'' + +You can let Fenrir know about what input devices are to be used. + device=ALL +Values: + +* ''ALL'' use all devices with key capabilities. + +* ''NOMICE'' Exclude mices from handling. + +* `` just use the device with the given name. + +Gives Fenrir exclusive access to the keyboard and lets it control keystrokes. This is needed to intercept Fenrir related shortcuts. + grabDevices=True +Values: on=''True'', off=''False'' + +The following makes sense if you are using a second screenreader and want to have some hooked events. Fenrir ignores all shortcuts then. + ignoreShortcuts=False +Values: on=''True'', off=''False'' + +The current keyboard layout used for shortcuts. + keyboardLayout=desktop + Values: An absolute Path to a Keyboard definition file or a Filename without extension located in ''/etc/fenrir/keyboard'' + +Announce characters while typing. + charEcho=False +Values: on=''True'', off=''False'' + +Announce deleted characters + charDeleteEcho=True +Values: on=''True'', off=''False'' + +Announce word after pressing space + wordEcho=False +Values: on=''True'', off=''False'' + +Interrupt speech on any keypress + interruptOnKeyPress=False +Values: on=''True'', off=''False'' + +You can filter the keys that speech should interrupt + interruptOnKeyPressFilter= +Values: (List) empty = all keys, otherwise interrupt with specified keys + +The timeout that is used for double tap shortcuts + doubleTapTimeout=0.2 +Values: Seconds +### General + +Overall settings can be configured from the section ''[general]''. + +Set the current debug level: + debugLevel=1 +Values: off=0, error=1, warning=2, info=3 + +the current punctuation and dict file in use: + punctuationProfile=default +Values: Text, see available profiles in ''/etc/fenrir/punctuation'' or in ''sourceTree/config/punctuation'' + +The current punctuation level in use: + punctuationLevel=some +Values: Text, See available levels in the used punctuation file. + +Respect pause for punctuations: + respectPunctuationPause=True +Values: on=''True'', off=''False'' + +Add a pause on Line break: + newLinePause=True +Values: on=''True'', off=''False'' + +Specify the path where the clipboard should be exported to. +See [export clipboard to file](#export clipboard to file). +The variable ''$user'' is replaced by the current logged username. + clipboardExportPath=/tmp/fenrirClipboard +Values: Text, Systemfilepath + +The number of available clipboards: + numberOfClipboards=10 +Values: Integer, 1 - 999 + +Replace emoticons like :) or ;) with text insertions: + emoticons=True +Values: on=''True'', off=''False'' + +Define the current Fenrir keys: + fenrirKeys=KEY_KP0,KEY_META,KEY_INSERT +Values, Text list, separated by comma. + +Define the current script keys: + scriptKey=KEY_COMPOSE +Values, Text list, separated by comma. + +The time format to be used for (time command) output: + timeFormat=%H:%M:%P +Values: see python specification for [datetime.strftime](https///docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior) + +The date format to be used for (date command) output: + dateFormat=%A, %B %d, %Y +Values: see python specification for [datetime.strftime](https///docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior) + +Enable or Disable spellcheck whilst typing: + autoSpellCheck=True +Values: on=''True'', off=''False'' + +The use of the dictionary with spellcheck: + spellCheckLanguage=en_US +Values: Text, see aspell dictionary's. + +Folder Path for your scripts "scriptKey" functionality: + scriptPath=/usr/share/fenrir/scripts +Values: Text, Existing path on file system. + +Override commands or create new ones without changing the Fenrir defaults: + commandPath=/usr/share/fenrir/commands +Values: Text, Existing path on file system. +Subfolders in commandPath are: + +* ''commands'' = to create shortcut commands + +* ''onInput'' = executed while typing + +* ''onScreenChange'' = executed on change the screen (change from TTY4 to TTY6) + +* ''onScreenUpdate'' = executed when the screen is captured + +### Focus + +The configuration for basic focus is in the section ''[focus]''. +Follow the text cursor: + cursor=True +Values: on=''True'', off=''False'' + +Follow highlighted text changes (Highlight Tracking): + highlight=False +Values: on=''True'', off=''False'' +### Review + +Configurations for the review mode are in the section ''[review]''. + +If "next word/ char" or "prev word/char" create a linebreak, announce it: + lineBreak=True +Values: on=''True'', off=''False'' + +If "next word/ char" or "prev word/char" cannot be performed because you reached the end of the screen, announce it: + endOfScreen=True +Values: on=''True'', off=''False'' + +Leave the review mode when pressing a key: + leaveReviewOnKeypress=False +Values: on=''True'', off=''False'' + +Leave the review mode when changing the screen (From TTY3 to TTY4): + leaveReviewOnScreenChange=True +Values: on=''True'', off=''False'' +### Promote + +"Promoted Lists" are configured in the section ''[promote]''. +Turn Promoted Lists" on or off: + enabled=True +Values: on=''True'', off=''False'' + +The minimum time interval of inactivity to activate promoting. +By default it promotes after 120 Seconds inactivity: + inactiveTimeoutSec=120 +Values: in Seconds + +Define a list of promoted words comma seperated: + list= +Values: text (comma seperated) +Example to promote the word "nickname" or a bash prompt: + list=nickname,$:,#: + +### Time + +The automated time announcement is configured in the section ''[time]''. +Time announcement is disabled by default. +Turn time announcement on or off: + enabled=True +Values: on=''True'', off=''False'' + +Should the time be announced: + presentTime=True +Values: on=''True'', off=''False'' + +Should the date be announced (just on date change): + presentDate=True +Values: on=''True'', off=''False'' + +Announce after a given period of seconds: + delaySec=0 +Value: in Seconds, 0 = Deactivated + +Announce after fixed minutes in an hour. if delaySec is >0 onMinutes is ignored: + onMinutes=00,30 +Example every 15 minutes: + onMinutes=00,15,30,45 + +Just play a soundicon, (not interrupting): + announce=True +Values: on=''True'', off=''False'' + +Interrupt current speech for time announcement: + interrupt=False +Values: on=''True'', off=''False'' +# Customization + +## Scripting +Scripts can be in any language, bash, python, sh or others. Place your scripts in the directory /usr/share/fenrir/scripts/ (the path is configurable in settings.conf). +The script key is the applications key. Usually this key can be found on the keyboard located just left of the right most control key. +When you name a script, the key name appears in the script seperated by the sequence __-__. So, for example, if you have a python weather script you want assigned to the script key plus the letter w you would name the script /usr/share/fenrir/scripts/weather__-__key_w.py +Then, to access the script, simply press the script key and the letter w. +Scripts must be executable. So, make sure to chmod 755 your script when you place it in the scripts directory. +The script gets some parameters from fenrir when it is executed. So that information is available in your script then. + +### Parameterlist + + | Parameter | Content | + | --------- | ------- | + | $1 | Username of the current logged in user | + +### Examples + +Script that just speaks the current username when pressing ScriptKey + H.\\ +File: ''/usr/share/fenrir/scripts/helloWorld__-__key_h.sh'': + #!/bin/bash + echo $1 + + +## Commands + +You can place your own commands in "/usr/share/fenrir/commands" (path is configurable in settings.conf). +Commands are python files with a special scheme. You can assign them to a shortcut using the filename without an extension or place them in a hook trigger like OnInput or OnScreenChange. For further information see developer guide. +Good Examples: ["date.py"](https///github.com/chrys87/fenrir/blob/master/src/fenrir/commands/commands/date.py) (announce the Date), ["shut_up.py"](https///github.com/chrys87/fenrir/blob/master/src/fenrir/commands/commands/shut_up.py) (interrupt output) +the basic scheme for a command is as follows: + + from core import debug + + class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('No description found') + def run(self): + pass + def setCallback(self, callback): + pass + + +* [Template lives here](https///github.com/chrys87/fenrir/blob/master/src/fenrir/commands/command_template.py) + +* The class needs to have the name "command". + +* "initialize" is running once whilst loading the command. + +* "shutdown" is running on unload like the command (quit fenrir) + +* "getDescriptsion" just returns an string. That String is used in Tutorial Mode. + +* "run" is executed when the command is invoked. (shortcut is pressed, or trigger isn't running) + +* setCAllback is currently not used. and has no functionality yet. + + +# Troubleshooting + +## Fenrir does not start + 1. Have you installed all the dependencies [Support and Requirements](#Support and Requirements) + 2. Try using master, a lot of changes take place there to make Fenrir compatible with more systems +## Fenrir does not utilize the shortcuts + + 1. Make sure you have python3-evdev installed + 2. Use the latest Fenrir version + 3. Make sure that Fenrir has permission to /dev/input/* and /dev/uinput (or run it as root) +## No sound at all + + 1. Run the script to configure Pulseaudio once as root and once as your user. This will setup Pulseaudio but require a restart of Pulseaudio. The script is located in ''tools/configure_pulse.sh'' + 2. Use ALSA + 3. [Configure Pulse system wide](https///www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/SystemWide/) (Not recommended) + 4. Use gstreamerDriver: change ''settings.conf'' in the section ''sound'' the line ''driver=genericDriver'' to ''driver=gstreamerDriver'' + 5. Use wave sound-icons: change ''settings.conf'' in the section ''sound'' the line ''theme=default'' to ''theme=default-wav'' + 6. Use most current version of [sox](http://sox.sourceforge.net/) with opus support + 7. Try [apulse](https///github.com/i-rinat/apulse) (not tested by myself but might work). Please give me feedback if you try it out. +## You get sound-icons but no speech + + 1. If you are using speech-dispatcher run "spd-conf" once as user and as root. + 2. You can test if speech-dispatcher works by invoking it as root\\ ''sudo spd-say "hello world"'' +## Bugreports and feature requests + +Please report Bugs and feature requests to: +[https://github.com/chrys87/fenrir/issues](https///github.com/chrys87/fenrir/issues) + +for bugs please provide a [debug](#Howto create a debug file) file that shows the issue. +### How-to create a debug file + + 1. Delete old debug stuff\\ ''sudo rm /var/log/fenrir.log'' + 2. Start fenrir in debug mode\\ ''sudo fenrir -d'' + 3. Do your stuff to reproduce the problem + 4. Stop fenrir (''fenrirKey + q'') +the debug file is located in ''/var/log/fenrir.log'' + +Please be as precise as possible to make it easy to solve the problem. + diff --git a/docu/user.txt b/docu/user.txt index 8b13789..5c8e1c6 100644 --- a/docu/user.txt +++ b/docu/user.txt @@ -1 +1,1332 @@ - +====== Fenrir User Manual ====== + +Fenrir is a modern command line screen reader written in Python3. + +It has a modular structure, a flexible based driver model, is highly configurable and easy to customize and extend ([[fenrir_development_manual|see Developer Manual]]). + +Please see the following pages for the [[fenrir_current_version|current]] and [[fenrir_git_version|Git]] version of Fenrir. + + +====== Support and Requirements ====== + +Fenrir requires several drivers to interact with the operating system. + +===== Speech Drivers ===== + +A speech driver is for communication with the text to speech system like [[#SpeechDispatcher|Speech-Dispatcher]] or [[http://espeak.sourceforge.net|Espeak]]. \\ +See section [[#Speech|Speech]] in ''settings.conf'' for more information. + + +==== SpeechDispatcher ==== + +This driver is used by default. +It uses Speech-dispatcher as its backend. + +Dependencies: + + * Speech-dispatcher (installed and configured, [[https://devel.freebsoft.org/speechd#sec2|Documentation]]) + * Python-speechd + +==== Espeak ==== + +Uses Espeak via Python bindings. + +Dependencies: + * Espeak or Espeak-ng + * [[https://launchpad.net/python-espeak|python-espeak]] + +==== Generic ==== + +This invokes speech via a sub-process. This is almost the same as using the commandline. The performance depends on the overhead of the speech synthesis application but it is really flexible. + +Dependencies: + * Espeak or Espeak-ng + +The Requirements are flexible, they depend on the configuration in settings.conf. + +==== Dummy ==== + +this is just for debugging, logs are output to the screen and logged as well. + +===== Sound Drivers ===== + +To play sound icons and similar.\\ +See section [[#Sound|Sound]] in ''settings.conf'' for more information. + +==== Generic ==== + +This driver is used by default. + +Dependencies: + + * [[http://sox.sourceforge.net/|Sox]] with opus support +The Requirements are flexible, they depend on the configuration in settings.conf. + +==== Gstreamer ==== + +if you prefer to use Gstreamer for sound output. + +Dependencies: + * Gstreamer >= 1.x + * Glibc + +==== Dummy ==== + +this is just for debugging, logs are output to the screen and logged as well. + +===== Input Drivers ===== + +Input drivers are to capture keyboard shortcuts issued to the screen reader \ +See section [[#Keyboard|Keyboard]] in ''settings.conf'' for more information. + +==== Evdev ==== + +This driver is used by default. + +Evdev is the low level input device framework for Linux. + +Dependencies: + + * python-evdev >=0.6.3 + * pyudev + * loaded uinput kernel module + * exclusive access to the input devices +Read permission to the following files and services: + * /dev/input + * /dev/uinput + +===== Screen Drivers ===== + +The job of a screen driver is to get the information of current screen content.\\ +See section [[#Screen|Screen]] in ''settings.conf'' for more information. + +==== VCSA ==== + +This driver is used by default. +For Linux VCSA devices. These exist on any current standard installation of Linux. + +Dependencie +s: + + * python-dbus +Read permission to the following files and services (or run as root): + * /sys/devices/virtual/tty/tty0/active + * /dev/tty[1 - 64] + * /dev/vcsa[1 - 64] ([[https://linux.die.net/man/4/vcsa|VCSA manpage]]) + * read Logind DBUS + +===== Braille Drivers ===== +This is for Braille support. +Braille is currently a work in progress and is planned for the Fenrir 2.0 release.\\ +See section [[#Braille|Braille]] in ''settings.conf'' for more information. + + +==== BRLTTY ==== + +This driver is used by default. +It uses [[brltty|BrlTTY]] to communicate with with a Braille device. + +Dependencies: + + * BrlTTY (configured and running, [[http://mielke.cc/brltty/doc/Manual-BRLTTY/English/BRLTTY.html|Documentation]]) + * python-brlapi (configured, [[http://mielke.cc/brltty/doc/Manual-BrlAPI/English/BrlAPI.html|Documentation]]) +===== Currently supported platforms ===== + +Currently Fenrir completely supports the following Platforms: + * Linux TTY +Support for further Systems are planned. + +====== Installation ====== + +Fenrir can run without installation. It just requires the dependencies are installed first. + +We recommend to try it out before installation to be sure everything works and prevent yourself from experiencing a non-talking environment. + +===== Try Out ===== +Fenrir does not require installation. You can try it and make sure everything works before you decide to install. In this way you can be sure that your system doesnt break or stop talking. +for that you can just grab the code and run as root ''src/fenrir/fenrir'' (in foreground) or ''src/fenrir/fenrir-daemon'' (in background, used by systemd for autostart) + +===== Install it ===== + +==== Documented operating systems ==== + +==== Arch Linux ==== + +For Arch there are PKGBUILDs in the AUR: + * [[https://aur.archlinux.org/packages/fenrir/|fenrir]] + * [[https://aur.archlinux.org/packages/fenrir-git/|fenrir-git]] + +==== Manual ==== + + - Download the latest stable version from the [[https://linux-a11y.org/index.php?page=fenrir-screenreader|Fenrir-Project]] site. + - Unpack the archive + - Check the needed Dependencys by running [[https://github.com/chrys87/fenrir/blob/master/check-dependencies.py|check-dependencys.py]] script + - install the missing dependencies an standard installation requires the following: + * python3 >= 3.3 (and all the following is needed for python3 ) + * python3-speechd (screen) + * python3-dbus (screen) + * python3-evdev >= 0.6.4(input) + * python3-daemonize (background service) + * python3-brlapi (braille) + * python3-pyenchant (spellchecker) + * your language for aspell (aspell-) (spellchecker) + * sox (sound) + * For an individual installation see [[#Support and Requirements|Support and Requirements]] or consult the [[https://github.com/chrys87/fenrir/blob/master/README.md|Readme]]) + - run "install.sh" as root + +this installs Fenrir as the following + * Application:''/opt/fenrir'' + * Settings:''/etc/fenrir'' + * Sound Icons:''/usr/share/fenrir/'' + +to remove Fenrir just run uninstall.sh as root + +==== Git ==== + +if you want to get the latest code you can use git to get a development snapshot: + + git clone https://github.com/chrys87/fenrir.git + +===== Auto Start ===== + +To start Fenrir once: + systemctl start fenrir + +To enable auto start on system boot: + systemctl enable fenrir + +====== First Steps ====== + +If you are using Fenrir for the first time you may want to take a look at these resources: + * [[#Keybindings|Keybindings]] + * [[#Tutorial Mode|Tutorial Mode]] + +====== Features ====== + +===== Commands ===== + +==== Keybindings ==== + +Normal commands can be invoked in two ways: + - Using a Metakey ([[#Fenrir Key|FenrirKey]]) + - Shortcuts with a single key + +See section [[#Keyboard|Keyboard]] in ''settings.conf'' for more information. +=== Fenrir Key === +The Fenrir Key is for invoking screen reader commands. Fenrir can utilize more than one FenrirKey at the same time. +By default the following keys are used: + - Insert + - KeyPad Insert + - Meta (Super, Windows) + +=== Script Key === +To invoke "Scripts" the Script Key is mandatory. The shortcut is encoded in the filename of the script. See [[#Scripting|Scripting]] +=== Desktop Layout === +^Shortcut ^Command ^ +|FenrirKey + H|[[#Tutorial Mode|toggle tutorial mode]]| +|CTRL|[[#shut up|shut up (interrupts speech)]]| +|FenrirKey + KeyPad 9|[[#review bottom|reviews bottom]]| +|FenrirKey + KeyPad 7|[[#review top|reviews top]]| +|KeyPad 8|[[#review current line|reviews current line]]| +|KeyPad 7|[[#review previous line|reviews previous line]]| +|KeyPad 9|[[#review next line|reviews next line]]| +|FenrirKey + KeyPad 4|[[#review line beginning|reviews line beginning]]| +|FenrirKey + KeyPad 6|[[#review line ending|reviews line ending]]| +|FenrirKey + KeyPad 1|[[#review line first character|reviews line first character]]| +|FenrirKey + KeyPad 3|[[#review line last character|reviews line last character]]| +|FenrirKey + Alt + 1|[[#present first line|presents first line]]| +|FenrirKey + Alt + 2|[[#present last line|presents last line]]| +|KeyPad 5|[[#review current word|reviews current word]]| +|KeyPad 4|[[#review previous word|reviews previous word]]| +|KeyPad 6|[[#review next word|reviews next word]]| +|FenrirKey + Shift + KeyPad 5|[[#review current word phonetic|reviews current word phonetic]]| +|FenrirKey + Shift + KeyPad 4|[[#review previous word phonetic|reviews previous word phonetic]]| +|FenrirKey + Shift + KeyPad 6|[[#review next word phonetic|reviews next word phonetic]]| +|KeyPad 2|[[#review current character|reviews current char]]| +|KeyPad 1|[[#review previous character|reviews previous char]]| +|KeyPad 3|[[#review next character|reviews next char]]| +|FenrirKey + Shift + KeyPad 2|[[#review current character phonetic|reviews current character phonetic]]| +|FenrirKey + Shift + KeyPad 1|[[#review previous character phonetic|reviews previous character phonetic]]| +|FenrirKey + Shift + KeyPad 3|[[#review next character phonetic|reviews next character phonetic]]| +|FenrirKey + CTRL + KeyPad 8|[[#review up|reviews up]]| +|FenrirKey + CTRL + KeyPad 2|[[#review down|reviews down]]| +|FenrirKey + KeyPad dot|[[#exit review|exit review]]| +|KeyPad dot|[[#cursor position|cursor position]]| +|FenrirKey + I|[[#indent current line|indent curr line]]| +|FenrirKey + KeyPad 5|[[#current screen|current screen]]| +|FenrirKey + KeyPad 8|[[#current screen before cursor|current screen before cursor]]| +|FenrirKey + KeyPad 2|[[#current screen after cursor|current screen after cursor]]| +||[[#cursor read to end of line|cursor read to end of line]]| +||[[#cursor column|cursor column]]| +||[[#cursor line number|cursor line number]]| +||[[#braille flush|Braille flush]]| +||[[#braille pan left|Braille pan left]]| +||[[#braille pan right|Braille pan right]]| +||[[#braille return to cursor|Braille return to cursor]]| +|FenrirKey + CTRL + 1|[[#clear Bookmark X|clear bookmark 1]]| +|FenrirKey + Shift + 1|[[#set Bookmark X|set bookmark 1]]| +|FenrirKey + 1|[[#read Bookmark X|bookmark 1]]| +|FenrirKey + CTRL + 2|[[#clear Bookmark X|clear bookmark 2]]| +|FenrirKey + Shift + 2|[[#set Bookmark X|set bookmark 2]]| +|FenrirKey + 2|[[#read Bookmark X|bookmark 2]]| +|FenrirKey + CTRL + 3|[[#clear Bookmark X|clear bookmark 3]]| +|FenrirKey + Shift + 3|[[#set Bookmark X|set bookmark 3]]| +|FenrirKey + 3|[[#read Bookmark X|bookmark 3]]| +|FenrirKey + CTRL + 4|[[#clear Bookmark X|clear bookmark 4]]| +|FenrirKey + Shift + 4|[[#set Bookmark X|set bookmark 4]]| +|FenrirKey + 4|[[#read Bookmark X|bookmark 4]]| +|FenrirKey + CTRL + 5|[[#clear Bookmark X|clear bookmark 5]]| +|FenrirKey + Shift + 5|[[#set Bookmark X|set bookmark 5]]| +|FenrirKey + 5|[[#read Bookmark X|bookmark 5]]| +|FenrirKey + CTRL + 6|[[#clear Bookmark X|clear bookmark 6]]| +|FenrirKey + Shift + 6|[[#set Bookmark X|set bookmark 6]]| +|FenrirKey + 6|[[#read Bookmark X|bookmark 6]]| +|FenrirKey + CTRL + 7|[[#clear Bookmark X|clear bookmark 7]]| +|FenrirKey + Shift + 7|[[#set Bookmark X|set bookmark 7]]| +|FenrirKey + 7|[[#read Bookmark X|bookmark 7]]| +|FenrirKey + CTRL + 8|[[#clear Bookmark X|clear bookmark 8]]| +|FenrirKey + Shift + 8|[[#set Bookmark X|set bookmark 8]]| +|FenrirKey + 8|[[#read Bookmark X|bookmark 8]]| +|FenrirKey + CTRL + 9|[[#clear Bookmark X|clear bookmark 9]]| +|FenrirKey + Shift + 9|[[#set Bookmark X|set bookmark 9]]| +|FenrirKey + 9|[[#read Bookmark X|bookmark 9]]| +|FenrirKey + CTRL + 0|[[#clear Bookmark X|clear bookmark 10]]| +|FenrirKey + Shift + 0|[[#set Bookmark X|set bookmark 10]]| +|FenrirKey + 0|[[#read Bookmark X|bookmark 10]]| +|FenrirKey + KeyPad Slash|[[#Create Window|set window application]]| +|2 * FenrirKey + KeyPad Slash|[[#Remove Window|clear window application]]| +|KeyPad Plus|[[#last incoming|read last incoming]]| +|FenrirKey + F2|[[#toggle braille|toggles braille]]| +|FenrirKey + F3|[[#toggle sound|toggles sound]]| +|FenrirKey + F4|[[#toggle speech|toggles speech]]| +|KeyPad Enter|[[#disable speech temporarily|temporarily disables speech]]| +|FenrirKey + CTRL + P|[[#toggle punctuation level|toggles punctuation level]]| +|FenrirKey + RightBrace|[[#toggle auto spell check|toggle auto spell check]]| +|FenrirKey + Backslash|[[#toggle output|toggles output]]| +|FenrirKey + CTRL + E|[[#toggle emoticons|toggles emoticons]]| +|FenrirKey + KeyPad Enter|[[#toggle auto read|toggles auto read]]| +|FenrirKey + CTRL + T|[[#toggle auto time|toggles auto time]]| +|FenrirKey + KeyPad ASTERISK|[[#toggle highlight tracking|toggles highlight tracking]]| +|FenrirKey + Q|[[#quit Fenrir|quits fenrir]]| +|FenrirKey + T|[[#Time|Announce time]]| +|2 * FenrirKey + T|[[#Date|Announce date]]| +|FenrirKey + S|[[#spell check|spell check]]| +|2 * FenrirKey + S|[[#add word to spell check|add word to spell check]]| +|FenrirKey + Shift + S|[[#removes word from spell check|removes word from spell check]]| +|FenrirKey + Backspace|[[#forward keypress|forward keypress]]| +|FenrirKey + Up|[[#increase speech volume|increase speech volume]]| +|FenrirKey + Down|[[#decrease speech volume|decrease speech volume]]| +|FenrirKey + Right|[[#increase speech rate|increase speech rate]]| +|FenrirKey + Left|[[#decrease speech rate|decrease speech rate]]| +|FenrirKey + Alt + Right|[[#increase speech pitch|increase speech pitch]]| +|FenrirKey + Alt + Left|[[#decrease speech pitch|decrease speech pitch]]| +|FenrirKey + Alt + Up|[[#increase sound volume|increase sound volume]]| +|FenrirKey + Alt + Down|[[#decrease sound volume|decrease sound volume]]| +|FenrirKey + CTRL + Shift + C|[[#clear clipboard|clears clipboard]]| +|FenrirKey + Home|[[#first clipboard|first clipboard]]| +|FenrirKey + End|[[#last clipboard|last clipboard]]| +|FenrirKey + PageUp|[[#previous clipboard|previous clipboard]]| +|FenrirKey + PageDown|[[#next clipboard|next clipboard]]| +|FenrirKey + Shift + C|[[#read current clipboard|current clipboard]]| +|FenrirKey + C|[[#copy marked to clipboard|copy marked text to clipboard]]| +|FenrirKey + V|[[#paste clipboard|paste clipboard contents]]| +|FenrirKey + P|[[#import clipboard from file|import clipboard from file]]| +|FenrirKey + Alt + Shift +C|[[#export clipboard to file|export clipboard to file]]| +|FenrirKey + CTRL + Shift + X|[[#Remove Marks|remove marks]]| +|FenrirKey + X|[[#Set mark|set mark]]| +|FenrirKey + Shift + X|[[#Get text between marks|announce marked text]]| +^Linux specific ^ +||export clipboard to X| +|FenrirKey + CTRL + Up|include Alsa volume| +|FenrirKey + CTRL + Down|decrease Alsa volume| + +=== Laptop Layout === +^Shortcut ^Command ^ +|FenrirKey + H|[[#Tutorial Mode|toggle tutorial mode]]| +|CTRL|[[#shut up|shut up (interrupts speech)]]| +|FenrirKey + Shift + O|[[#review bottom|reviews bottom]]| +|FenrirKey + Shift + U|[[#review top|reviews top]]| +|FenrirKey + I|[[#review current line|reviews current line]]| +|FenrirKey + U|[[#review previous line|reviews previous line]]| +|FenrirKey + O|[[#review next line|reviews next line]]| +|FenrirKey + Shift + J|[[#review line beginning|reviews line beginning]]| +|FenrirKey + Shift + L|[[#review line ending|reviews line ending]]| +|FenrirKey + CTRL + J|[[#review line first character|reviews line first character]]| +|FenrirKey + CTRL + L|[[#review line last character|reviews line last character]]| +|FenrirKey + Alt + 1|[[#present first line|presents first line]]| +|FenrirKey + Alt + 2|[[#present last line|presents last line]]| +|FenrirKey + K|[[#review current word|reviews current word]]| +|FenrirKey + J|[[#review previous word|reviews previous word]]| +|FenrirKey + L|[[#review next word|reviews next word]]| +|FenrirKey + CTRL + ALT + K|[[#review current word phonetic|reviews current word phonetic]]| +|FenrirKey + CTRL + ALT + J|[[#review previous word phonetic|reviews previous word phonetic]]| +|FenrirKey + CTRL + ALT + L|[[#review next word phonetic|reviews next word phonetic]]| +|FenrirKey + comma|[[#review current character|reviews current character]]| +|FenrirKey + M|[[#review previous character|reviews previous character]]| +|FenrirKey + dot|[[#review next character|reviews next character]]| +|FenrirKey + CTRL + ALT + comma|[[#review current character phonetic|reviews current character phonetic]]| +|FenrirKey + CTRL + ALT + M|[[#review previous character phonetic|reviews previous character phonetic]]| +|FenrirKey + CTRL + ALT + dot|[[#review next character phonetic|reviews next character phonetic]]| +|FenrirKey + CTRL + I|[[#review up|reviews up]]| +|FenrirKey + CTRL + comma|[[#review down|reviews down]]| +|FenrirKey + Slash|[[#exit review|exit review]]| +|FenrirKey + Shift + dot|[[#cursor position|cursor position]]| +|2 * FenrirKey + I|[[#indent current line|indent curr line]]| +|FenrirKey + Shift + K|[[#current screen|current screen]]| +|FenrirKey + Shift + I|[[#current screen before cursor|current screen before cursor]]| +|FenrirKey + Shift + comma|[[#current screen after cursor|current screen after cursor]]| +||[[#cursor read to end of line|cursor read to end of line]]| +||[[#cursor column|cursor column]]| +||[[#cursor line number|cursor line number]]| +||[[#braille flush|Braille flush]]| +||[[#braille pan left|Braille pan left]]| +||[[#braille pan right|Braille pan right]]| +||[[#braille return to cursor|Braille return to cursor]]| +|FenrirKey + CTRL + 1|[[#clear Bookmark X|clear bookmark 1]]| +|FenrirKey + Shift + 1|[[#set Bookmark X|set bookmark 1]]| +|FenrirKey + 1|[[#read Bookmark X|bookmark 1]]| +|FenrirKey + CTRL + 2|[[#clear Bookmark X|clear bookmark 2]]| +|FenrirKey + Shift + 2|[[#set Bookmark X|set bookmark 2]]| +|FenrirKey + 2|[[#read Bookmark X|bookmark 2]]| +|FenrirKey + CTRL + 3|[[#clear Bookmark X|clear bookmark 3]]| +|FenrirKey + Shift + 3|[[#set Bookmark X|set bookmark 3]]| +|FenrirKey + 3|[[#read Bookmark X|bookmark 3]]| +|FenrirKey + CTRL + 4|[[#clear Bookmark X|clear bookmark 4]]| +|FenrirKey + Shift + 4|[[#set Bookmark X|set bookmark 4]]| +|FenrirKey + 4|[[#read Bookmark X|bookmark 4]]| +|FenrirKey + CTRL + 5|[[#clear Bookmark X|clear bookmark 5]]| +|FenrirKey + Shift + 5|[[#set Bookmark X|set bookmark 5]]| +|FenrirKey + 5|[[#read Bookmark X|bookmark 5]]| +|FenrirKey + CTRL + 6|[[#clear Bookmark X|clear bookmark 6]]| +|FenrirKey + Shift + 6|[[#set Bookmark X|set bookmark 6]]| +|FenrirKey + 6|[[#read Bookmark X|bookmark 6]]| +|FenrirKey + CTRL + 7|[[#clear Bookmark X|clear bookmark 7]]| +|FenrirKey + Shift + 7|[[#set Bookmark X|set bookmark 7]]| +|FenrirKey + 7|[[#read Bookmark X|bookmark 7]]| +|FenrirKey + CTRL + 8|[[#clear Bookmark X|clear bookmark 8]]| +|FenrirKey + Shift + 8|[[#set Bookmark X|set bookmark 8]]| +|FenrirKey + 8|[[#read Bookmark X|bookmark 8]]| +|FenrirKey + CTRL + 9|[[#clear Bookmark X|clear bookmark 9]]| +|FenrirKey + Shift + 9|[[#set Bookmark X|set bookmark 9]]| +|FenrirKey + 9|[[#read Bookmark X|bookmark 9]]| +|FenrirKey + CTRL + 0|[[#clear Bookmark X|clear bookmark 10]]| +|FenrirKey + Shift + 0|[[#set Bookmark X|set bookmark 10]]| +|FenrirKey + 0|[[#read Bookmark X|bookmark 10]]| +|FenrirKey + CTRL + 8|[[#Create Window|set window application]]| +|2 * FenrirKey + CTRL + 8|[[#Remove Window|clear window application]]| +|FenrirKey + Semicolon|[[#last incoming|read last incoming]]| +|FenrirKey + F2|[[#toggle braille|toggles braille]]| +|FenrirKey + F3|[[#toggle sound|toggles sound]]| +|FenrirKey + F4|[[#toggle speech|toggles speech]]| +|FenrirKey + Enter|[[#disable speech temporarily|temporarily disables speech]]| +|FenrirKey + Shift + CTRL + P|[[#toggle punctuation level|toggles punctuation level]]| +|FenrirKey + RightBrace|[[#toggle auto spell check|toggle auto spell check]]| +|FenrirKey + Shift + Enter|[[#toggle output|toggles output]]| +|FenrirKey + Shift + E|[[#toggle emoticons|toggles emoticons]]| +|FenrirKey + Enter|[[#toggle auto read|toggles auto read]]| +|FenrirKey + CTRL + T|[[#toggle auto time|toggles auto time]]| +|FenrirKey + Y|[[#toggle highlight tracking|toggles highlight tracking]]| +|FenrirKey + Q|[[#quit Fenrir|quits fenrir]]| +|FenrirKey + T|[[#Time|Announce time]]| +|2 * FenrirKey + T|[[#Date|Announce date]]| +|FenrirKey + S|[[#spell check|spell check]]| +|2 * FenrirKey + S|[[#add word to spell check|add word to spell check]]| +|FenrirKey + Shift + S|[[#removes word from spell check|removes word from spell check]]| +|FenrirKey + Backspace|[[#forward keypress|forward keypress]]| +|FenrirKey + Up|[[#increase speech volume|increase speech volume]]| +|FenrirKey + Down|[[#decrease speech volume|decrease speech volume]]| +|FenrirKey + Right|[[#increase speech rate|increase speech rate]]| +|FenrirKey + Left|[[#decrease speech rate|decrease speech rate]]| +|FenrirKey + Alt + Right|[[#increase speech pitch|increase speech pitch]]| +|FenrirKey + Alt + Left|[[#decrease speech pitch|decrease speech pitch]]| +|FenrirKey + Alt + Up|[[#increase sound volume|increase sound volume]]| +|FenrirKey + Alt + Down|[[#decrease sound volume|decrease sound volume]]| +|FenrirKey + CTRL + Shift + C|[[#clear clipboard|clears clipboard]]| +|FenrirKey + Home|[[#first clipboard|first clipboard]]| +|FenrirKey + End|[[#last clipboard|last clipboard]]| +|FenrirKey + PageUp|[[#previous clipboard|previous clipboard]]| +|FenrirKey + PageDown|[[#next clipboard|next clipboard]]| +|FenrirKey + Shift + C|[[#read current clipboard|current clipboard]]| +|FenrirKey + C|[[#copy marked to clipboard|copy marked text to clipboard]]| +|FenrirKey + V|[[#paste clipboard|paste clipboard contents]]| +|FenrirKey + F5|[[#import clipboard from file|import clipboard from file]]| +|FenrirKey + Alt + Shift +C|[[#export clipboard to file|export clipboard to file]]| +|FenrirKey + CTRL + Shift + X|[[#Remove Marks|remove marks]]| +|FenrirKey + X|[[#Set mark|set mark]]| +|FenrirKey + Shift + X|[[#Get text between marks|announce marked text]]| +^Linux specific ^ +||export clipboard to X| +|FenrirKey + CTRL + Up|increases Alsa volume| +|FenrirKey + CTRL + Down|decreases Alsa volume| +==== General ==== +=== quit Fenrir === +Just stops fenrir. +=== shut up === +Interrupt the current spoken. +==== Review Modes ==== +Fenrir provides a virtual cursor, with it you can navigate all over the screen without changing the text cursor. + +Using the review feature will open the review mode automatically. + +The review cursor always starts from the text cursor. Attention: after using the review mode, the review cursor will stay open until you use the ''exit review'' shortcut. + +Think when using clipboard operations and similar. The review cursor is always prefered over the text cursor. + +Fenrir sounds a bell sound if the used review command jumps to another line or end of screen. +=== exit review === +You can leave the review mode by pressing the ''exit review'' shortcut. +=== review bottom === +Set the review cursor to first column in the last line. +=== review top === +Set the review cursor to the first column in the first line +=== review current line === +Set the review cursor to the beginn of the the current line and review it. +=== review previous line === +Set the review cursor to the previous line and review it. +=== review next line === +Set the review cursor to the next line and review it. +=== review line beginning === +Set the review cursor to the begin of the current line +=== review line ending === +Set the review cursor to the end of the current line +=== review line first character === +Set the review cursor the first char (that is not space) in the current line and review it. +=== review line last character === +Set the review cursor the last char (that is not space) in the current line and review it. +=== review current word === +Sets the review cursor to the beginning of the current word and review it. +=== review previous word === +Sets the review cursor to the beginning of the previous word and review it. +=== review next word === +Sets the review cursor to the beginning of the next word and review it. +=== review current word phonetic === +Sets the review cursor to the beginning of the current word and spell it phonetic. +=== review previous word phonetic === +Sets the review cursor to the beginning of the previous word and spell it phonetic. +=== review next word phonetic === +Sets the review cursor to the beginning of the next word and spell it phonetic. +=== review current character === +Does not change the review cursor. Just announce the current char. +=== review previous character === +Sets review cursor to the previous column and review it +=== review next character === +Sets review cursor to the next column and review it +=== review current character phonetic === +Does not change the review cursor. Just announce the current char phonetic. +=== review previous character phonetic === +Sets review cursor to the previous column and announce the char phonetic. +=== review next character phonetic === +Sets review cursor to the next column and announce the char phonetic. +=== review up === +Set the review cursor in the same column one line above the current one and review it. +=== review down === +Set the review cursor in the same column one line below the current one and review it. +==== Handling marking ==== +A mark defines a point of origin or end to prepare to copy or paste a block of text. +\\ +Examples where you need marks are: + * copy to clipboard + * set window application + * set bookmark 1 - X +=== Set mark === +How to set a mark: + - navigate with review or textcursor to the position you want to set the mark. Attention: if a review cursor is set, that is the prefered. If you want to use text cursor, be sure that you are not in review mode. + - press shortcut for ''set mark'' +you can set two marks (begin and end). Some commands allow some simpler usecases just using the whole line if only one mark is set. you may want to try this out. +=== Get text between marks === +To get the text that is currently between your marks press shortcut for ''marked text''.\\ +=== Remove Marks === +You can remove all current marks by pressing the shortcut for ''remove marks''. +Changing the screen also removes the marks. +==== Screen Interaction ==== +Fenrir provides several methods to interact with the current screen. +=== forward keypress === +This just forwards the next shortcut to the screen Fenrir shortcut or not. This is useful if the currently pressed shortcut is also in use by Fenrir. +=== Clipboard === +Fenrir provides a clipboard with multible items represented by a list. You navigate throught the list and paste the selected clipboard. +== copy marked to clipboard == +To copy something to the clipboard you need to set one or two marks. if you set one mark, the text between the mark and your current cursor is copied to clipboard. Setting two marks just copies the text between the marks into the clipboard. If you copy something it is always placed as the first item on your clipboard. +== clear clipboard == +You can remove all items from the current clipboard by ''clear clipboard'' functionality. +== first clipboard == +This moves quick to the first item of the clipboard. +== last clipboard == +This moves quick to the last item of the clipboard. +== previous clipboard == +Go to previous item in the clipboard. +== next clipboard == +Go to next item on the clipboard. +== read current clipboard == +Read the content of the current item of the clipboard. +== paste clipboard == +Pass whatever item is currently selected by first, last, prev or next clipboard commands. +if no special clipboard is selected the (last copied) is used. +== export clipboard to file == +This allows you to export the current clipboard to a configurable filepath. This is useful to share the clipboard with a graphical desktop. +== import clipboard from file == +Import a clipboard from a configurable file. This is useful to share the clipboard with a graphical desktop. +==== Quick Settings ==== +Fenrir provides shortcuts to change settings temporarily and on the fly without the need to permanently change the ''settings.conf'' file. +=== toggle braille === +Enables and disables Braille. This is not persistent stored in your ''settings.conf'' but during run time. +=== toggle sound === +Enables and disables sound. This is not persistent stored in your ''settings.conf'' but during run time. +=== toggle speech === +Enables and disables speech. This is not persistent stored in your ''settings.conf'' but during run time. +=== disable speech temporarily === +Disables the speech until next key press. it might be useful if you want to listen to music or similar. As soon as a key is pressed it is going to be enabled again. +=== toggle punctuation level === +Cycle between all available punctuation levels. This is not persistent stored in your ''settings.conf'' but during run time. +=== toggle auto spell check === +Enables and disables automatic spellchecker (when typing). This is not persistent stored in your ''settings.conf'' but during run time. +=== toggle emoticons === +Enables and disables emoticons. This is not persistent stored in your ''settings.conf'' but during runtime. +=== toggle output === +Enables and disables all output at once (sound, Braille, speech). This is not persistent stored in your ''settings.conf'' but during run time. +=== toggle auto read === +Enables and disables what is automatically spoken. This is not persistent stored in your ''settings.conf'' but during run time. +=== toggle auto time === +Enables and disables auto time functionality. This is not persistent stored in your ''settings.conf'' but during run time. +=== toggle highlight tracking === +Enables and disables highlight tracking. This is not persistent stored in your ''settings.conf'' but during run time. +=== increase speech volume === +Increase the volume of the speech. This is not persistent stored in your ''settings.conf'' but during runtime. +=== decrease speech volume === +Decrease the volume of the speech. This is not persistent stored in your ''settings.conf'' but during runtime. +=== increase speech rate === +Increase the rate of the speech. This is not persistent stored in your ''settings.conf'' but during runtime. +=== decrease speech rate === +Decrease the rate of the speech. This is not persistent stored in your ''settings.conf'' but during runtime. +=== increase speech pitch === +Increase the pitch of the speech. This is not persistent stored in your ''settings.conf'' but during runtime. +=== decrease speech pitch === +Decrease the pitch of the speech. This is not persistent stored in your ''settings.conf'' but during runtime. +=== increase sound volume === +Increase the volume of the sound. This is not persistent stored in your ''settings.conf'' but during runtime. +=== decrease sound volume === +Decrease the volume of the sound. This is not persistent stored in your ''settings.conf'' but during runtime. +==== Window Mode ==== +Fenrir supports window mode, a window is a partial area of the screen. +=== Create Window === +To create a window you need to do the following: + - set a beginning mark (as the start of the window) + - set an end mark (where the window should end) + - press ''set window application'' shortcut. +Now Fenrir ignores anything outside of the window.\\ +=== Remove Window === +You can remove the window by pressing ''the clear window application'' shortcut. +Now Fenrir will read everything on the screen again. +==== Tracking Modes ==== +Different types of tracking are currently supported +See section [[#Focus|Focus]] in ''settings.conf'' for more information. +=== Cursor Tracking === +This follows the text cursor. This is the typical way an application works. This is used by: + * almost any shell such as (Bash, Zsh, sh) + * vim + * nano + * emacs + * mutt + * tintin++ +=== Highlight Tracking === +In some applications there are no text cursors. In those applications cursor changes are represented by different colors or attributes (underlined or bold). This mode tracks and announces these changes for you. This is used by: + * wifi-menu + * dialog + * alpine +==== Tutorial Mode ==== +Fenrir provides a Tutorial mode. +When you enter tutorial mode, screen reader commands are intercepted and explained instead of executing them. ''Arrow up'' and ''Arrow Down'' let you navigate through a list of all available commands with shortcuts and description. Pressing escape leaves the tutorial mode. + +==== Information ==== +=== Time === +Announces the current Time. +=== Date === +Announces the current Date. +=== Bookmarks === +Bookmarks provide quick access to part of the screen without the need to navigate to the area. +By default Fenrir provides 10 bookmarks. Those can be set and accessed via shortcut. +This is useful for status lines or other information where the position does not change. +== set Bookmark X == +You need to set the bookmark first. For that you have to set one or two lines for use. + - Set marks (one or two) + - press shortcut for ''set bookmark X''. X represents the number 1 - 10. +== read Bookmark X == +If a bookmark is set you can access the area just by pressing the ''bookmark X'' shortcut. X represents the number 1 - 10. Bookmarks are dynamic. That means the content changes with the screen. +== clear Bookmark X == +to remove a bookmark just press the ''clear bookmark X'' shortcut. X represents the number 1 - 10. +Afterward the bookmark is no longer available. +=== cursor position === +You can get information about the current cursor and its position by using the "cursor position" functionality. +=== indent current line === +Announce the current indent level of the current line. It represents the number of trailing spaces of the line. +=== current screen === +Reads all the current screen from the beginning to the end. +=== current screen before cursor === +Reads current screen from the beginning of the screen to the current cursor position. +=== current screen after cursor === +Read anything after current cursor position to the end. +=== cursor read to end of line === +Read from the current cursor position to the end of the current line. +=== cursor column === +Read the current X position of a cursor (column of the current line). +=== cursor line number === +Read the current Y position of a cursor (line number). +=== present first line === +Reads just the first line. this is maybe useful for status information. +=== present last line === +Presets the last line. This is maybe useful for status information. +=== last incoming === +Repeat the last automatically incoming text. +===== Input ===== +==== Echo ==== +Fenrir provides different methods of echoing content: + * Word: Will speak each word after you push space + * Character: speak any letter you type on the screen + * Delete Character: speaks the character prior to the cursor when you push backspace +==== Silence on Key press ==== +==== Spellchecker ==== +Fenrir has a built-in spellchecker, it can invoke automatically while typing or be called by a shortcut. +Commands to add or remove the current word to the dictionary are included. +As using the spellchecker is enhanced usage. You will need dictionary aspell-. +See section [[#General|General]] in ''settings.conf'' for more information. +=== spell check === +Invokes the spellcheck on the word that contains the Review or text cursor. +=== add word to spell check === +Adds the word under the Review or Text cursor to the dictionary. +=== removes word from spell check === +Removes the word under the Review or Text cursor from the dictionary. +===== Announcements ===== +==== Emoticons ==== +If you want to replace ":)" emoticons with "smile" in speech you can use this feature. +It can be toggled on or off. +You can define emoticons in a dictionary, please see Emoticon Dictionary. +See section [[#General|General]] in ''settings.conf'' to see how to enable or disable this feature. + +==== Time ==== +Announce the time at periodical increments, To track the time easily. +You can define 2 different ways of time announcements. + - periodic + - on fix minutes + +Example periodic, every 20 minutes "delaySec=20": + + [time] + enabled=True + presentTime=True + presentDate=True + delaySec=20 + onMinutes= + announce=True + interrupt=False + +Example on fix minutes in an hour. example every quarter "delaySec=0" and "onMinutes=00,15,30,45": + + [time] + enabled=True + presentTime=True + presentDate=True + #delaySec is repected bevore onMinutes so it need to be set to 0 + delaySec=0 + onMinutes=00,15,30,45 + announce=True + interrupt=False +==== Promoted List ==== +Promoted Lists are a nice feature if you are away from your computer or performing more longer tasks. +you can define a list of words which you want to hear a sound icon for after a period of inactivity. +Example if the word "Chrys" appears after 120 Seconds of inactivity: + [promote] + enabled=True + inactiveTimeoutSec=120 + list=Chrys +See section [[#Promote|Promote]] in ''settings.conf'' for more information. +==== Punctuation ==== +Fenrir handles punctuation levels and names for you with several provided dictionaries. + +See levelDict +See punctuationDict +===== Braille ===== +Fenrir provides Braille support in Version >= 2.0. +See section [[#Braille|Braille]] in ''settings.conf'' for more information. +==== braille flush ==== +If a message appears on the Braille device you can flush it to get back to the review- or system cursor +==== Braille pan left ==== +If a line is longer than your Braille devices you can move the view (called panning) to the left. +So you can read stuff without the need to move the review- or system cursor. +==== Braille pan right ==== +If a line is longer than your Braille devices you can move the view (called panning) to the right. +So you can read stuff without the need to move the review- or system cursor. +==== braille return to cursor ==== +When you have finished reading the line on the Braille device using panning, the focus can be returned to the current used cursor by using "return to cursor" command. +===== Dictionary ===== +You can make use of different kinds of built-in dictionary's. +A dictionary has a name and list of keys and values separated by :===: +Example: + [customDict] + Chrys:===:Chrys is cool + lollipop:===:lolli +that means that every instance "chrys" is displayed, speech will say Chrys is cool. +"lollipop" is spoken as "lolli". +Before making changes to a dictionary we recommend making a backup of your current dictionary in case future updates overwrite your local changes. +==== Punctuation ==== +=== Level === +The punctuation level dict contains lists with "what punctuation is spoken in what level". +the default one looks like this: + [levelDict] + none:===: + some:===:.-$~+*-/\@ + most:===:.,:-$~+*-/\@!#%^&*()[]}{<>; + all:===:!"#$%& \'()*+,-./:;<=>?@[\\]^_`{|}~ +the level "none" has no values. so it should not speak any punctuation (sadly this is not respected by every TTS system) +if "some" is the current level the following are spoken: dot dash dollar tilde plus star slash backslash at. +same for most and all, you can add new levels. if you cycle punctuation levels they are recognized. the default punctuation level is set in settings.conf. The default is "some". +=== Punctuation === +The punctuation dictionary "[punctDict]" contains how the punctuation is spoken. +Example: + [punctDict] + _:===:line +speaks an _ as "line". + [punctDict] + _:===:underscore +speaks an _ as underscore. +for question mark an ? is appended to the word that the TTS system can announce the question correctly. +==== Custom ==== +The dict "[customDict]" is just for your own use, it just replace the key with the value without any special functionality. This might be used to fix incorrectly spoken words, make words more common, shorter or just for fun. :) +==== Emoticons ==== +The Emoticons dictionary "[emoticonDict]" by default contains some emoticons. it can replace ":)" with "smile" or "XD" with "loool" Making chat more colorful. +A nice feature with this dictionary is that you can toggle the substitution on or off during run time or in settings.conf. This is useful because while doing programming or other serious work you want to hear colons and perryns not smiles. +====== Configuration ====== +You can configure Fenrir in the following places (ordered by priority): + - Commandline Parameters ''-o'' see [[#Set settings coption|Set settings coption]] + - /etc/fenrir/settings/settings.conf see [[#Settings|Settigns]] + - /config/settings/settings.conf see [[#Settings|Settigns]] + - hard coded defaults +===== Commandline Arguments ===== +==== Set settings option ==== +You can specify options that overwrite the setting.conf. +This is done with ''-o '' parameter. +The list of options have the following syntax + fenrir -o "section#setting=value;section#setting=value" + +For example changing the sound driver to gstreamer and disabling Braille + fenrir -o "sound#driver=gstreamerDriver;braille#enabled=False=False" +or change the debug level to verbose + fenrir -o "general#debugLevel=3" +You can find the available sections and variables here [[#Settings]] +See Syntax [[#settings.conf syntax]] +==== settings.conf syntax ==== +the syntax of the [[#Settings|settings.conf]] is quite simple and similar to a "*.ini" file, there are 4 different elements. + - Sections + - Settings + - Values + - Comments + +A comment starts with a # and is ignored by Fenrir. + # this is a comment +To group settings we have sections. +A section can look like this: + [Section] +A setting looks like this: + settingName=Value + +Example: + [sound] + # Turn sound on or off: + enabled=True + # Select the driver used to play sounds, choices are genericDriver and gstreamerDriver. + # Sox is default. + driver=genericDriver + +===== Settings ===== +==== Sound ==== +The sound is configured in section ''[sound]''. + +Turn sound on or off: + enabled=True +Values: on=''True'', off=''False'' + +Select the driver used to play sounds. +The genericDriver using Sox is the default. + + driver=genericDriver + +Available Drivers: + * ''genericDriver'' using the generic driver, for Fenrir <1.5 just use ''generic'' + * ''gstreamerDriver'' using the gstreamer, for Fenrir <1.5 just use ''gstreamer'' + +These are the pack of sounds used for sound icons. + theme=default +By default we ship two sound packs. + - ''default'' opus encoded, for newer Sox versions + - ''default-wav'' wav encoded, just for compatibility +Sound packs are located at /usr/share/sounds/fenrir/ + +Sound volume controls how loud the sounds for your selected sound pack are. + volume=1.0 +Values: ''0.0'' is quietest, ''1.0'' is loudest. + +=== Generic Driver === +The generic sound driver uses shell commands for play sound and frequencies. + +''genericPlayFileCommand'' defines the command that is used to play a sound file. + genericPlayFileCommand= +''genericFrequencyCommand'' defines the command that is used playing frequencies. + genericFrequencyCommand= + +The following variables are substituted in ''genericPlayFileCommand'' and ''genericFrequencyCommand'': + * ''fenrirVolume'' = the current volume setting + * ''fenrirSoundFile'' = the sound file for an sound icon + * ''fenrirFrequence'' = the frequency to play + * ''fenrirDuration'' = the duration of the frequency + +Example genericPlayFileCommand (default) + genericPlayFileCommand=play -q -v fenrirVolume fenrirSoundFile +Example genericFrequencyCommand (default) + genericFrequencyCommand=play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence +==== Speech ==== +Speech is configured in section ''[speech]''. +Turn speech on or off: + enabled=True +Values: on=''True'', off=''False'' + +# Select speech driver, options are speechdDriver (default), genericDriver or espeakDriver: +driver=speechdDriver +#driver=espeakDriver +#driver=genericDriver + +Select the driver used to generate speech output. + + driver=speechdDriver + +Available Drivers: + * ''genericDriver'' using the generic driver, for Fenrir <1.5 this is not available + * ''speechdDriver'' using speech-dispatcher, for Fenrir <1.5 just use ''speechd'' + * ''espeakDriver'' using the espeak directly, for Fenrir <1.5 just use ''espeak'' + +The rate selects how fast Fenrir will speak. + rate=0.65 +Values: Range Minimum:''0.0'' is slowest, Maximum:''1.0'' is fastest. + +Pitch controls the pitch of the voice. + pitch=0.5 +Values: Range Minimum:''0.0'' is lowest, Maximum:''1.0'' is highest. + +A Pitch for capital letters can be set. + capitalPitch=0.9 +Values: Range Minimum:''0.0'' is lowest, Maximum:''1.0'' is highest. + +The Volume controls the loudness of the voice. + volume=1.0 +Values: Range Minimum:''0.0'' is quietest, Maximum:''1.0'' is loudest. + +Some speech drivers like speechdDriver can support various modules. these can be set here. + module=espeak +Values: Text, Consult speech-dispatcher's configuration to see what modules are available. + +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= +Values: Text, see your TTS synths documentation what is available. + +Select the language you want Fenrir to use. + language=english-us +Values: Text, see your TTS synths documentation what is available. + +Read new text as it occurs +autoReadIncoming=True +Values: on=''True'', off=''False'' + +=== Generic Driver === +The generic speech driver uses shell commands for speech synthisus. + +''genericSpeechCommand'' defines the command that is executed for creating speech +The following variables are substituted in ''genericSpeechCommand'': + * ''FenrirText'' = is the text that should be spoken + * ''fenrirModule'' = may be the speech module like used in speech-dispatcher, not every TTY needs this + * ''fenrirLanguage'' = the language to speak in + * ''fenrirVoice'' = is the current voice that should be used + * ''fenrirVolume'' = is replaced with the current volume + * ''fenrirPitch'' = is replaced with the current pitch + * ''fenrirRate'' = is replaced with the current speed (speech rate) + +Example genericSpeechCommand (default): + genericSpeechCommand=espeak -a fenrirVolume -s fenrirRate -p fenrirPitch -v fenrirVoice "fenrirText" + +These are the minimum and maximum values of the TTS system used in genericSpeechCommand. They are needed to calculate the abstract range in volume, rate and pitch 0.0 - 1.0. + + FenrirMinVolume=0 + fenrirMaxVolume=200 + fenrirMinPitch=0 + fenrirMaxPitch=99 + fenrirMinRate=80 + fenrirMaxRate=450 + +The current volume, pitch and rate is calculated like this +value = min + [volume,pitch,rate] * (min - max ) +==== Braille ==== +Braille is a WIP and not ready yet. +Braille support can be configured in section ''[braille]''. + +Turn braille on or off: + enabled=False +Values: on=''True'', off=''False'' + +Select the driver used for communication with a braille device. + driver=brlapiDriver +Values: Text, available Driver +Available Drivers: + * ''brlttyDriver'' using brltty for braille communication, for Fenrir <1.5 just use ''brltty'' + +The Braille layout can be configured here + layout=en +Values: Text, see braille driver for layouts. + +What should the flush timeout relate to + flushMode=word +Values: Text, an flushMode +Existing flushModes: + * ''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) + +Seconds to flush (see flushMode) + flushTimeout=3 +Values: Integer, in Seconds or ''-1'' = no automatic flush (manual via shortcut) +The total flush time calculates in relation to flushMode. + +How should the Braille cursor focus be tracked? + cursorFocusMode=page +Values: Text, an existing cursor focus mode +Available cursor focus modes: + * ''page'' = if the cursor crosses the border move to next page and start at begin + * ''fixCell'' = ajust the cursor on a special cell where it is always placed. the display scroll here more smooth. + + +Define the cell on the Braille device where Fenrir should scroll and keep the cursor + fixCursorOnCell=-1 +Values: Integer + * ''0'' = first cell on device, + * ''-1'' = last cell on device + * ''>0'' = fix cell number + +What cursor should Fenrir show on the Braille device + cursorFollowMode=review +Values: Text, an exsiting cursor following mode. +Existing cursor following mode: + * ''none'' = no automatic toggle command used + * ''review'' = priority to review + * ''last'' = follow last used cursor + +number of cells in panning (horizontal). How many cell should be panned on press the routing key? + panSizeHorizontal=0 +Values: Integer, + * ''0'' = display size + * ''>0'' number of cells +==== Screen ==== +The settings for screens, (TTY, PTY) are configured in the ''[screen]'' section. + +The driver to get the information from the screen: + driver=vcsaDriver +Available Drivers: + * ''vcsaDriver'' using the VCSA driver (for TTYs), for Fenrir <1.5 just use ''vcsa'' +The encoding of the screen + encoding=cp850 +Values:''cp850'' is used for Western languages like USA or Europe. + +The driver updates Fenrir with changes on the screen. + screenUpdateDelay=0.05 +Values: in Seconds + +If you want Fenrir to not be active on any screen for various reasons. Maybe an X server or Wayland is running on that screen. You can make Fenrir ignore it or multiple screens seperated by '','' with: + suspendingScreen= +Values: Depends on driver: + * VCSA: the number of the TTY. TTY6 is ''6''. +Example ignore TTY1 and TTY2: + suspendingScreen=1,2 + +There is also the ability to let Fenrir auto detect screens that are running an X server. So Screens running an GUI can be ignored. + autodetectSuspendingScreen=True +Values: on=''True'', off=''False'' + +==== Keyboard ==== +The settings for keyboard and input related configuration is located in the section ''[keyboard]'' of the ''settings.conf'' file. + +Select the driver used for grabbing keybord input and for recieving shortcuts. + driver=evdevDriver +Values: Text, available Driver +Available Drivers: + * ''evdevDriver'' uses the evdev input system of linux, for Fenrir <1.5 just use ''evdev'' + +You can let Fenrir know about what input devices are to be used. + device=ALL +Values: + * ''ALL'' use all devices with key capabilities. + * ''NOMICE'' Exclude mices from handling. + * '''' just use the device with the given name. + +Gives Fenrir exclusive access to the keyboard and lets it control keystrokes. This is needed to intercept Fenrir related shortcuts. + grabDevices=True +Values: on=''True'', off=''False'' + +The following makes sense if you are using a second screenreader and want to have some hooked events. Fenrir ignores all shortcuts then. + ignoreShortcuts=False +Values: on=''True'', off=''False'' + +The current keyboard layout used for shortcuts. + keyboardLayout=desktop + Values: An absolute Path to a Keyboard definition file or a Filename without extension located in ''/etc/fenrir/keyboard'' + +Announce characters while typing. + charEcho=False +Values: on=''True'', off=''False'' + +Announce deleted characters + charDeleteEcho=True +Values: on=''True'', off=''False'' + +Announce word after pressing space + wordEcho=False +Values: on=''True'', off=''False'' + +Interrupt speech on any keypress + interruptOnKeyPress=False +Values: on=''True'', off=''False'' + +You can filter the keys that speech should interrupt + interruptOnKeyPressFilter= +Values: (List) empty = all keys, otherwise interrupt with specified keys + +The timeout that is used for double tap shortcuts + doubleTapTimeout=0.2 +Values: Seconds +==== General ==== +Overall settings can be configured from the section ''[general]''. + +Set the current debug level: + debugLevel=1 +Values: off=0, error=1, warning=2, info=3 + +the current punctuation and dict file in use: + punctuationProfile=default +Values: Text, see available profiles in ''/etc/fenrir/punctuation'' or in ''sourceTree/config/punctuation'' + +The current punctuation level in use: + punctuationLevel=some +Values: Text, See available levels in the used punctuation file. + +Respect pause for punctuations: + respectPunctuationPause=True +Values: on=''True'', off=''False'' + +Add a pause on Line break: + newLinePause=True +Values: on=''True'', off=''False'' + +Specify the path where the clipboard should be exported to. +See [[#export clipboard to file|export clipboard to file]]. +The variable ''$user'' is replaced by the current logged username. + clipboardExportPath=/tmp/fenrirClipboard +Values: Text, Systemfilepath + +The number of available clipboards: + numberOfClipboards=10 +Values: Integer, 1 - 999 + +Replace emoticons like :) or ;) with text insertions: + emoticons=True +Values: on=''True'', off=''False'' + +Define the current Fenrir keys: + fenrirKeys=KEY_KP0,KEY_META,KEY_INSERT +Values, Text list, separated by comma. + +Define the current script keys: + scriptKey=KEY_COMPOSE +Values, Text list, separated by comma. + +The time format to be used for (time command) output: + timeFormat=%H:%M:%P +Values: see python specification for [[https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior|datetime.strftime]] + +The date format to be used for (date command) output: + dateFormat=%A, %B %d, %Y +Values: see python specification for [[https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior|datetime.strftime]] + +Enable or Disable spellcheck whilst typing: + autoSpellCheck=True +Values: on=''True'', off=''False'' + +The use of the dictionary with spellcheck: + spellCheckLanguage=en_US +Values: Text, see aspell dictionary's. + +Folder Path for your scripts "scriptKey" functionality: + scriptPath=/usr/share/fenrir/scripts +Values: Text, Existing path on file system. + +Override commands or create new ones without changing the Fenrir defaults: + commandPath=/usr/share/fenrir/commands +Values: Text, Existing path on file system. +Subfolders in commandPath are: + * ''commands'' = to create shortcut commands + * ''onInput'' = executed while typing + * ''onScreenChange'' = executed on change the screen (change from TTY4 to TTY6) + * ''onScreenUpdate'' = executed when the screen is captured + +==== Focus ==== +The configuration for basic focus is in the section ''[focus]''. +Follow the text cursor: + cursor=True +Values: on=''True'', off=''False'' + +Follow highlighted text changes (Highlight Tracking): + highlight=False +Values: on=''True'', off=''False'' +==== Review ==== +Configurations for the review mode are in the section ''[review]''. + +If "next word/ char" or "prev word/char" create a linebreak, announce it: + lineBreak=True +Values: on=''True'', off=''False'' + +If "next word/ char" or "prev word/char" cannot be performed because you reached the end of the screen, announce it: + endOfScreen=True +Values: on=''True'', off=''False'' + +Leave the review mode when pressing a key: + leaveReviewOnKeypress=False +Values: on=''True'', off=''False'' + +Leave the review mode when changing the screen (From TTY3 to TTY4): + leaveReviewOnScreenChange=True +Values: on=''True'', off=''False'' +==== Promote ==== +"Promoted Lists" are configured in the section ''[promote]''. +Turn Promoted Lists" on or off: + enabled=True +Values: on=''True'', off=''False'' + +The minimum time interval of inactivity to activate promoting. +By default it promotes after 120 Seconds inactivity: + inactiveTimeoutSec=120 +Values: in Seconds + +Define a list of promoted words comma seperated: + list= +Values: text (comma seperated) +Example to promote the word "nickname" or a bash prompt: + list=nickname,$:,#: + +==== Time ==== +The automated time announcement is configured in the section ''[time]''. +Time announcement is disabled by default. +Turn time announcement on or off: + enabled=True +Values: on=''True'', off=''False'' + +Should the time be announced: + presentTime=True +Values: on=''True'', off=''False'' + +Should the date be announced (just on date change): + presentDate=True +Values: on=''True'', off=''False'' + +Announce after a given period of seconds: + delaySec=0 +Value: in Seconds, 0 = Deactivated + +Announce after fixed minutes in an hour. if delaySec is >0 onMinutes is ignored: + onMinutes=00,30 +Example every 15 minutes: + onMinutes=00,15,30,45 + +Just play a soundicon, (not interrupting): + announce=True +Values: on=''True'', off=''False'' + +Interrupt current speech for time announcement: + interrupt=False +Values: on=''True'', off=''False'' +====== Customization ====== +===== Scripting ===== +Scripts can be in any language, bash, python, sh or others. Place your scripts in the directory /usr/share/fenrir/scripts/ (the path is configurable in settings.conf). +The script key is the applications key. Usually this key can be found on the keyboard located just left of the right most control key. +When you name a script, the key name appears in the script seperated by the sequence __-__. So, for example, if you have a python weather script you want assigned to the script key plus the letter w you would name the script /usr/share/fenrir/scripts/weather__-__key_w.py +Then, to access the script, simply press the script key and the letter w. +Scripts must be executable. So, make sure to chmod 755 your script when you place it in the scripts directory. +The script gets some parameters from fenrir when it is executed. So that information is available in your script then. + +==== Parameterlist ==== +^Parameter ^Content ^ +|$1|Username of the current logged in user| + +==== Examples ==== +Script that just speaks the current username when pressing ScriptKey + H.\\ +File: ''/usr/share/fenrir/scripts/helloWorld__-__key_h.sh'': + #!/bin/bash + echo $1 + + +===== Commands ===== +You can place your own commands in "/usr/share/fenrir/commands" (path is configurable in settings.conf). +Commands are python files with a special scheme. You can assign them to a shortcut using the filename without an extension or place them in a hook trigger like OnInput or OnScreenChange. For further information see developer guide. +Good Examples: [[https://github.com/chrys87/fenrir/blob/master/src/fenrir/commands/commands/date.py|"date.py"]] (announce the Date), [[https://github.com/chrys87/fenrir/blob/master/src/fenrir/commands/commands/shut_up.py|"shut_up.py"]] (interrupt output) +the basic scheme for a command is as follows: + + from core import debug + + class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('No description found') + def run(self): + pass + def setCallback(self, callback): + pass + + * [[https://github.com/chrys87/fenrir/blob/master/src/fenrir/commands/command_template.py|Template lives here]] + * The class needs to have the name "command". + * "initialize" is running once whilst loading the command. + * "shutdown" is running on unload like the command (quit fenrir) + * "getDescriptsion" just returns an string. That String is used in Tutorial Mode. + * "run" is executed when the command is invoked. (shortcut is pressed, or trigger isn't running) + * setCAllback is currently not used. and has no functionality yet. + + +====== Troubleshooting ====== +===== Fenrir does not start ===== + - Have you installed all the dependencies [[#Support and Requirements|Support and Requirements]] + - Try using master, a lot of changes take place there to make Fenrir compatible with more systems +===== Fenrir does not utilize the shortcuts ===== + - Make sure you have python3-evdev installed + - Use the latest Fenrir version + - Make sure that Fenrir has permission to /dev/input/* and /dev/uinput (or run it as root) +===== No sound at all ===== + - Run the script to configure Pulseaudio once as root and once as your user. This will setup Pulseaudio but require a restart of Pulseaudio. The script is located in ''tools/configure_pulse.sh'' + - Use ALSA + - [[https://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/SystemWide/|Configure Pulse system wide]] (Not recommended) + - Use gstreamerDriver: change ''settings.conf'' in the section ''sound'' the line ''driver=genericDriver'' to ''driver=gstreamerDriver'' + - Use wave sound-icons: change ''settings.conf'' in the section ''sound'' the line ''theme=default'' to ''theme=default-wav'' + - Use most current version of [[http://sox.sourceforge.net/|sox]] with opus support + - Try [[https://github.com/i-rinat/apulse|apulse]] (not tested by myself but might work). Please give me feedback if you try it out. +===== You get sound-icons but no speech ===== + - If you are using speech-dispatcher run "spd-conf" once as user and as root. + - You can test if speech-dispatcher works by invoking it as root\\ ''sudo spd-say "hello world"'' +===== Bugreports and feature requests ===== +Please report Bugs and feature requests to: +[[https://github.com/chrys87/fenrir/issues|https://github.com/chrys87/fenrir/issues]] + +for bugs please provide a [[#Howto create a debug file|debug]] file that shows the issue. +==== How-to create a debug file ==== + - Delete old debug stuff\\ ''sudo rm /var/log/fenrir.log'' + - Start fenrir in debug mode\\ ''sudo fenrir -d'' + - Do your stuff to reproduce the problem + - Stop fenrir (''fenrirKey + q'') +the debug file is located in ''/var/log/fenrir.log'' + +Please be as precise as possible to make it easy to solve the problem. diff --git a/experimental/selinux/Readme.md b/experimental/selinux/Readme.md new file mode 100644 index 0000000..7a66a36 --- /dev/null +++ b/experimental/selinux/Readme.md @@ -0,0 +1,12 @@ +install it. +1. build it +make -f /usr/share/selinux/strict/include/Makefile fenrir.pp +2. install it +semodule -i /path/to/fenrir.pp + + +# created with that +# systemctl start fenrir +# ausearch -c '(r-daemon)' --raw | audit2allow -M fenrir +# semodule -X 300 -i fenrir.pp + diff --git a/experimental/selinux/fenrir.te b/experimental/selinux/fenrir.te new file mode 100644 index 0000000..2a3ced1 --- /dev/null +++ b/experimental/selinux/fenrir.te @@ -0,0 +1,10 @@ +module fenrir 1.0; + +require { + type user_home_t; + type init_t; + class file { execute execute_no_trans open read }; +} + +#============= init_t ============== +allow init_t user_home_t:file { execute execute_no_trans open read }; diff --git a/experimental/setup.py b/experimental/setup.py deleted file mode 100755 index 5a47f69..0000000 --- a/experimental/setup.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/python -import os -from setuptools import find_packages -from setuptools import setup -def read(fname): - return open(os.path.join(os.path.dirname(__file__), fname)).read() - - - -setup( - # Application name: - name="fenrir", - # Version number (initial): - version="0.1a", - - # Application author details: - author="Chrys and others", - author_email="chrys87@web.de", - - # Packages - packages=find_packages('src/fenrir'), - package_dir={'': 'src/fenrir'}, - scripts=['src/fenrir/fenrir','src/fenrir/fenrir-daemon'], - #entry_points = { - # "console_scripts": ['fenrir = fenrir:main'] - # }, - - # Include additional files into the package - include_package_data=True, - - # Details - url="https://github.com/chrys87/fenrir/", - zip_safe=False, - # - # license="MIT", - description="An TTY Screen Reader For Linux.", - long_description=read('README.md'), - classifiers=[ - "Development Status :: 3 - Alpha", -], - # Dependent packages (distributions) - install_requires=[ - "evdev", - "sox", - ], - -) - diff --git a/install.sh b/install.sh index 61795eb..1f0d59f 100755 --- a/install.sh +++ b/install.sh @@ -1,22 +1,63 @@ #!/bin/bash -#Basic install script for fenrir. -read -p "This will install fenrir. Press ctrl+c to cancil, or enter to continue." continue +#Basic install script for Fenrir. +read -p "This will install Fenrir. Press ctrl+C to cancel, or enter to continue." continue + +# Fenrir main application install -m755 -d /opt/fenrir +cp -af src/fenrir/* /opt/fenrir +install -m644 -D "autostart/systemd/fenrir.service" /usr/lib/systemd/system/fenrir.service +ln -fs /opt/fenrir/fenrir-daemon /usr/bin/fenrir-daemon +ln -fs /opt/fenrir/fenrir /usr/bin/fenrir +# tools +install -m755 -d /usr/share/fenrir/tools +cp -af tools/* /usr/share/fenrir/tools + +# scripts install -m755 -d /usr/share/fenrir/scripts +cp -af "config/scripts/wlan__-__key_y.sh" /usr/share/fenrir/scripts/ + +# keyboard install -m644 -D "config/keyboard/desktop.conf" /etc/fenrir/keyboard/desktop.conf -install -m644 -D "config/keyboard/desktop.conf" /etc/fenrir/keyboard/desktop.conf -install -m644 -D "config/punctuation/default.conf" /etc/fenrir/punctuation/default.conf -install -m644 -D "config/settings/settings.conf" /etc/fenrir/settings/settings.conf +install -m644 -D "config/keyboard/laptop.conf" /etc/fenrir/keyboard/laptop.conf + +# punctuation +install -m755 -d /etc/fenrir/punctuation +cp -af config/punctuation/* /etc/fenrir/punctuation + +# sound install -d /usr/share/sounds/fenrir -install -m644 -D "autostart/systemd/fenrir.service" /usr/lib/systemd/system/fenrir.service -cp -a src/fenrir/* /opt/fenrir -cp -a config/scripts/* /usr/share/fenrir/scripts -cp -a config/sound/* /usr/share/sounds/fenrir -ln -s /opt/fenrir/fenrir-daemon /usr/bin/fenrir +cp -af config/sound/default /usr/share/sounds/fenrir/default +cp -af config/sound/default-wav /usr/share/sounds/fenrir/default-wav +cp -af config/sound/template /usr/share/sounds/fenrir/template + +# config +if [ -f "/etc/fenrir/settings/settings.conf" ]; then + echo "Do you want to overwrite your current global settings? (y/n)" + read yn + if [ $yn = "Y" -o $yn = "y" ]; then + mv /etc/fenrir/settings/settings.conf /etc/fenrir/settings/settings.conf.bak + echo "Your old settings.conf has been backed up to settings.conf.bak." + install -m644 -D "config/settings/settings.conf" /etc/fenrir/settings/settings.conf + else + install -m644 -D "config/settings/settings.conf" /etc/fenrir/settings/settings.conf.current + fi +else + install -m644 -D "config/settings/settings.conf" /etc/fenrir/settings/settings.conf +fi + + +# end message cat << EOF -To have fenrir start at boot: +Installation complete. +install path:/opt/fenrir +settings path:/etc/fenrir + +To test Fenrir +sudo systemctl start fenrir +To have Fenrir start on system boot: sudo systemctl enable fenrir + Pulseaudio users may want to run -/usr/share/fenrir/tools/configure-pulseaudio -once as their user account and once as root. +/usr/share/fenrir/tools/configure_pulse.sh +once from their user account, then once from the root. EOF diff --git a/known bugs.txt b/known bugs.txt index ddce00f..88580fa 100644 --- a/known bugs.txt +++ b/known bugs.txt @@ -3,5 +3,9 @@ - spellcheck triggers twice if there are two spaces after an word and you arrow over them Glitches (improve diff results): -- For example, in screen, it just tells me bell in window, but doesn't tell me which one. (southernprince) -- alpine seems to have problems (southernprince) +- currently None + +wishes: +- whole status line in irssi is spoken insteed of just the changes (lilmike) +- whole status line in vim is spoken insteed of just the changes (lilmike) + diff --git a/locale/es/LC_MESSAGES/fenrir.mo b/locale/es/LC_MESSAGES/fenrir.mo new file mode 100644 index 0000000..f5255a8 Binary files /dev/null and b/locale/es/LC_MESSAGES/fenrir.mo differ diff --git a/locale/es/LC_MESSAGES/fenrir.po b/locale/es/LC_MESSAGES/fenrir.po new file mode 100644 index 0000000..bcb5e21 --- /dev/null +++ b/locale/es/LC_MESSAGES/fenrir.po @@ -0,0 +1,840 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR ORGANIZATION +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"POT-Creation-Date: 2017-02-26 22:19+UTC\n" +"PO-Revision-Date: 2017-02-26 17:01-0600\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: pygettext.py 1.5\n" +"X-Generator: Poedit 1.6.11\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: ../src/fenrir/commands/commands/add_word_to_spell_check.py:27 +msgid "adds the current word to the exceptions dictionary" +msgstr "añade la palabra actual al diccionario" + +#: ../src/fenrir/commands/commands/add_word_to_spell_check.py:34 +#: ../src/fenrir/commands/commands/remove_word_from_spell_check.py:34 +#: ../src/fenrir/commands/commands/spell_check.py:29 +#: ../src/fenrir/commands/commands/spell_check.py:36 +msgid "pyenchant is not installed" +msgstr "Pyenchant no está instalado" + +#: ../src/fenrir/commands/commands/add_word_to_spell_check.py:49 +msgid "{0} is already in dict" +msgstr "{0} ya se encuentra en el diccionario" + +#: ../src/fenrir/commands/commands/add_word_to_spell_check.py:52 +msgid "{0} added" +msgstr "{0} se ha añadido" + +#: ../src/fenrir/commands/commands/bookmark_1.py:19 +#: ../src/fenrir/commands/commands/bookmark_10.py:19 +#: ../src/fenrir/commands/commands/bookmark_2.py:19 +#: ../src/fenrir/commands/commands/bookmark_3.py:19 +#: ../src/fenrir/commands/commands/bookmark_4.py:19 +#: ../src/fenrir/commands/commands/bookmark_5.py:19 +#: ../src/fenrir/commands/commands/bookmark_6.py:19 +#: ../src/fenrir/commands/commands/bookmark_7.py:19 +#: ../src/fenrir/commands/commands/bookmark_8.py:19 +#: ../src/fenrir/commands/commands/bookmark_9.py:19 +msgid "read Bookmark {0}" +msgstr "Leer marcador {0}" + +#: ../src/fenrir/commands/commands/bookmark_1.py:24 +#: ../src/fenrir/commands/commands/bookmark_10.py:24 +#: ../src/fenrir/commands/commands/bookmark_2.py:24 +#: ../src/fenrir/commands/commands/bookmark_3.py:24 +#: ../src/fenrir/commands/commands/bookmark_4.py:24 +#: ../src/fenrir/commands/commands/bookmark_5.py:24 +#: ../src/fenrir/commands/commands/bookmark_6.py:24 +#: ../src/fenrir/commands/commands/bookmark_7.py:24 +#: ../src/fenrir/commands/commands/bookmark_8.py:24 +#: ../src/fenrir/commands/commands/bookmark_9.py:24 +msgid "Bookmark {0} not set" +msgstr "No se ha establecido el marcador {0}" + +#: ../src/fenrir/commands/commands/bookmark_1.py:27 +#: ../src/fenrir/commands/commands/bookmark_1.py:30 +#: ../src/fenrir/commands/commands/bookmark_10.py:27 +#: ../src/fenrir/commands/commands/bookmark_10.py:30 +#: ../src/fenrir/commands/commands/bookmark_2.py:27 +#: ../src/fenrir/commands/commands/bookmark_2.py:30 +#: ../src/fenrir/commands/commands/bookmark_3.py:27 +#: ../src/fenrir/commands/commands/bookmark_3.py:30 +#: ../src/fenrir/commands/commands/bookmark_4.py:27 +#: ../src/fenrir/commands/commands/bookmark_4.py:30 +#: ../src/fenrir/commands/commands/bookmark_5.py:27 +#: ../src/fenrir/commands/commands/bookmark_5.py:30 +#: ../src/fenrir/commands/commands/bookmark_6.py:27 +#: ../src/fenrir/commands/commands/bookmark_6.py:30 +#: ../src/fenrir/commands/commands/bookmark_7.py:27 +#: ../src/fenrir/commands/commands/bookmark_7.py:30 +#: ../src/fenrir/commands/commands/bookmark_8.py:27 +#: ../src/fenrir/commands/commands/bookmark_8.py:30 +#: ../src/fenrir/commands/commands/bookmark_9.py:27 +#: ../src/fenrir/commands/commands/bookmark_9.py:30 +msgid "Bookmark for application {0} not set" +msgstr "El marcador para la aplicación {0} no se ha establecido" + +#: ../src/fenrir/commands/commands/bookmark_1.py:43 +#: ../src/fenrir/commands/commands/bookmark_10.py:43 +#: ../src/fenrir/commands/commands/bookmark_2.py:43 +#: ../src/fenrir/commands/commands/bookmark_3.py:43 +#: ../src/fenrir/commands/commands/bookmark_4.py:43 +#: ../src/fenrir/commands/commands/bookmark_5.py:43 +#: ../src/fenrir/commands/commands/bookmark_6.py:43 +#: ../src/fenrir/commands/commands/bookmark_7.py:43 +#: ../src/fenrir/commands/commands/bookmark_8.py:43 +#: ../src/fenrir/commands/commands/bookmark_9.py:43 +#: ../src/fenrir/commands/commands/curr_screen_after_cursor.py:27 +#: ../src/fenrir/commands/commands/curr_screen_before_cursor.py:30 +#: ../src/fenrir/commands/commands/cursor_read_to_end_of_line.py:27 +#: ../src/fenrir/commands/commands/indent_curr_line.py:31 +#: ../src/fenrir/commands/commands/marked_text.py:33 +#: ../src/fenrir/commands/commands/present_first_line.py:25 +#: ../src/fenrir/commands/commands/present_last_line.py:25 +#: ../src/fenrir/commands/commands/review_curr_char_phonetic.py:27 +#: ../src/fenrir/commands/commands/review_curr_line.py:27 +#: ../src/fenrir/commands/commands/review_curr_word.py:27 +#: ../src/fenrir/commands/commands/review_curr_word_phonetic.py:27 +#: ../src/fenrir/commands/commands/review_line_begin.py:27 +#: ../src/fenrir/commands/commands/review_next_line.py:29 +#: ../src/fenrir/commands/commands/review_next_word.py:29 +#: ../src/fenrir/commands/commands/review_next_word_phonetic.py:27 +#: ../src/fenrir/commands/commands/review_prev_line.py:27 +#: ../src/fenrir/commands/commands/review_prev_word.py:27 +#: ../src/fenrir/commands/commands/review_prev_word_phonetic.py:27 +#: ../src/fenrir/commands/onInput/55000-present_line_if_cursor_change_vertical.py:38 +#: ../src/fenrir/commands/onInput/72000-history.py:50 +msgid "blank" +msgstr "en blanco" + +#: ../src/fenrir/commands/commands/braille_flush.py:17 +msgid "flush the braille device if a message is written on" +msgstr "Limpia el dispositivo braille al escribir un mensaje en él." + +#: ../src/fenrir/commands/commands/braille_pan_left.py:17 +msgid "Move braille view to the left." +msgstr "Mover la vista Braille a la izquierda" + +#: ../src/fenrir/commands/commands/braille_pan_right.py:17 +msgid "Move braille view to the right." +msgstr "Mover la vista braille a la derecha" + +#: ../src/fenrir/commands/commands/braille_return_to_cursor.py:17 +msgid "Set the braille view back to cursor." +msgstr "Establecer la vista Braille en el cursor" + +#: ../src/fenrir/commands/commands/clear_bookmark_1.py:17 +#: ../src/fenrir/commands/commands/clear_bookmark_10.py:17 +#: ../src/fenrir/commands/commands/clear_bookmark_2.py:17 +#: ../src/fenrir/commands/commands/clear_bookmark_3.py:17 +#: ../src/fenrir/commands/commands/clear_bookmark_4.py:17 +#: ../src/fenrir/commands/commands/clear_bookmark_5.py:17 +#: ../src/fenrir/commands/commands/clear_bookmark_6.py:17 +#: ../src/fenrir/commands/commands/clear_bookmark_7.py:17 +#: ../src/fenrir/commands/commands/clear_bookmark_8.py:17 +#: ../src/fenrir/commands/commands/clear_bookmark_9.py:17 +msgid "remove Bookmark {0}" +msgstr "Eliminar marcador {0}" + +#: ../src/fenrir/commands/commands/clear_bookmark_1.py:24 +#: ../src/fenrir/commands/commands/clear_bookmark_10.py:24 +#: ../src/fenrir/commands/commands/clear_bookmark_2.py:24 +#: ../src/fenrir/commands/commands/clear_bookmark_3.py:24 +#: ../src/fenrir/commands/commands/clear_bookmark_4.py:24 +#: ../src/fenrir/commands/commands/clear_bookmark_5.py:24 +#: ../src/fenrir/commands/commands/clear_bookmark_6.py:24 +#: ../src/fenrir/commands/commands/clear_bookmark_7.py:24 +#: ../src/fenrir/commands/commands/clear_bookmark_8.py:24 +#: ../src/fenrir/commands/commands/clear_bookmark_9.py:24 +msgid "Bookmark {0} removed for application {1}" +msgstr "el marcador {0} de la aplicación {1} ha sido eliminado" + +#: ../src/fenrir/commands/commands/clear_clipboard.py:17 +msgid "clears the currently selected clipboard" +msgstr "Vacía el portapapeles seleccionado" + +#: ../src/fenrir/commands/commands/clear_clipboard.py:22 +msgid "clipboard cleared" +msgstr "Portapapeles vacío" + +#: ../src/fenrir/commands/commands/clear_window_application.py:17 +msgid "Turn off window mode for application" +msgstr "Desactiva el modo de ventana para la aplicación" + +#: ../src/fenrir/commands/commands/clear_window_application.py:22 +msgid "Window Mode off for application {0}" +msgstr "El modo de ventana está desactivado para la aplicación {0}" + +#: ../src/fenrir/commands/commands/clear_window_application.py:24 +msgid "Not in window Mode" +msgstr "No está en modo ventana" + +#: ../src/fenrir/commands/commands/copy_marked_to_clipboard.py:18 +msgid "copies marked text to the currently selected clipboard" +msgstr "Copia el texto marcado al portapapeles en uso" + +#: ../src/fenrir/commands/commands/copy_marked_to_clipboard.py:22 +msgid "one or two marks needed" +msgstr "se necesita una o dos marcas" + +#: ../src/fenrir/commands/commands/curr_clipboard.py:17 +msgid "speaks the contents of the currently selected clipboard" +msgstr "Habla el contenido del portapapeles seleccionado" + +#: ../src/fenrir/commands/commands/curr_clipboard.py:21 +#: ../src/fenrir/commands/commands/export_clipboard_to_x.py:29 +#: ../src/fenrir/commands/commands/export_clipboard_to_x.py:32 +#: ../src/fenrir/commands/commands/export_clipboard_to_x.py:35 +#: ../src/fenrir/commands/commands/export_clipboard_to_x.py:38 +#: ../src/fenrir/commands/commands/first_clipboard.py:21 +#: ../src/fenrir/commands/commands/last_clipboard.py:21 +#: ../src/fenrir/commands/commands/next_clipboard.py:21 +#: ../src/fenrir/commands/commands/paste_clipboard.py:23 +#: ../src/fenrir/commands/commands/paste_clipboard.py:26 +#: ../src/fenrir/commands/commands/paste_clipboard.py:29 +#: ../src/fenrir/commands/commands/paste_clipboard.py:32 +#: ../src/fenrir/commands/commands/prev_clipboard.py:21 +msgid "clipboard empty" +msgstr "Portapapeles vacío" + +#: ../src/fenrir/commands/commands/curr_screen.py:17 +msgid "reads the contents of the current screen" +msgstr "Lee el contenido de la pantalla actual" + +#: ../src/fenrir/commands/commands/curr_screen.py:21 +msgid "screen is empty" +msgstr "La pantalla está vacía" + +#: ../src/fenrir/commands/commands/curr_screen_after_cursor.py:18 +msgid "reads from the cursor to the bottom of the screen" +msgstr "Lee desde el cursor hasta el final de la pantalla" + +#: ../src/fenrir/commands/commands/curr_screen_before_cursor.py:18 +msgid "Reads from the top of the screen to the cursor position" +msgstr "Lee desde el inicio de la pantalla hasta la posición del cursor." + +#: ../src/fenrir/commands/commands/cursor_column.py:17 +msgid "" +"presents the current column number for review cursor in review mode or the " +"text cursor if not. Starts with 1" +msgstr "" +"Indica el número de columna actual para el cursor de revisión si se está en " +"el modo de revisión, o el cursor de texto si no." + +#: ../src/fenrir/commands/commands/cursor_lineno.py:17 +msgid "" +"presents the current line number for review cursor in review mode or the " +"text cursor if not. Starts with 1" +msgstr "" +"Indica el número de línea actual para el cursor de revisión si se está en el " +"modo de revisión, o el cursor de texto si no." + +#: ../src/fenrir/commands/commands/cursor_position.py:17 +msgid "displays the position of the review cursor" +msgstr "Indica la posición del cursor de revisión" + +#: ../src/fenrir/commands/commands/cursor_position.py:23 +msgid "line {0}, column {1}" +msgstr "Línea {0}, columna {1}" + +#: ../src/fenrir/commands/commands/cursor_read_to_end_of_line.py:18 +msgid "" +"read to end of line, use review cursor if you are in review mode, otherwhise " +"use text cursor" +msgstr "" +"Leer hasta el fin de línea, utiliza el cursor de revisión cuando el modo de " +"revisión está activo, de lo contrario utiliza el cursor de texto." + +#: ../src/fenrir/commands/commands/date.py:18 +msgid "presents the date" +msgstr "Lee la fecha" + +#: ../src/fenrir/commands/commands/dec_sound_volume.py:18 +msgid "decrease sound volume" +msgstr "Reduce el volumen del sonido" + +#: ../src/fenrir/commands/commands/dec_sound_volume.py:29 +#: ../src/fenrir/commands/commands/inc_sound_volume.py:29 +msgid "{0} percent sound volume" +msgstr "volumen de sonido al {0} porciento" + +#: ../src/fenrir/commands/commands/dec_speech_pitch.py:18 +msgid "decreases the pitch of the speech" +msgstr "Reduce el tono de voz" + +#: ../src/fenrir/commands/commands/dec_speech_pitch.py:27 +#: ../src/fenrir/commands/commands/inc_speech_pitch.py:27 +msgid "{0} percent speech pitch" +msgstr "Tono de voz al {0} porciento" + +#: ../src/fenrir/commands/commands/dec_speech_rate.py:18 +msgid "decreases the rate of the speech" +msgstr "Reduce la velocidad de voz" + +#: ../src/fenrir/commands/commands/dec_speech_rate.py:27 +#: ../src/fenrir/commands/commands/inc_speech_rate.py:27 +msgid "{0} percent speech rate" +msgstr "Velocidad de voz al {0} porciento" + +#: ../src/fenrir/commands/commands/dec_speech_volume.py:18 +msgid "decreases the volume of the speech" +msgstr "Reduce el volumen de voz" + +#: ../src/fenrir/commands/commands/dec_speech_volume.py:27 +#: ../src/fenrir/commands/commands/inc_speech_volume.py:27 +msgid "{0} percent speech volume" +msgstr "Volumen de voz al {0} porciento" + +#: ../src/fenrir/commands/commands/exit_review.py:17 +msgid "exits review mode" +msgstr "Sale del modo de revisión" + +#: ../src/fenrir/commands/commands/exit_review.py:21 +msgid "Not in review mode" +msgstr "No está en modo de revisión" + +#: ../src/fenrir/commands/commands/exit_review.py:25 +msgid "leave review mode" +msgstr "Saliendo del modo de revisión" + +#: ../src/fenrir/commands/commands/export_clipboard_to_x.py:21 +msgid "export the current fenrir clipboard to X clipboard" +msgstr "Exporta el contenido del portapapeles de Fenrir al servidor X" + +#: ../src/fenrir/commands/commands/first_clipboard.py:17 +msgid "selects the first clipboard" +msgstr "Selecciona el primer portapapeles" + +#: ../src/fenrir/commands/commands/forward_keypress.py:17 +msgid "sends the following keypress to the terminal" +msgstr "Envía la siguiente tecla a la terminal" + +#: ../src/fenrir/commands/commands/forward_keypress.py:21 +msgid "Forward next keypress" +msgstr "Enviar la siguiente tecla" + +#: ../src/fenrir/commands/commands/inc_sound_volume.py:18 +msgid "adjusts the volume for in coming sounds" +msgstr "aumenta el volumen del sonido" + +#: ../src/fenrir/commands/commands/inc_speech_pitch.py:18 +msgid "increases the pitch of the speech" +msgstr "Aumenta el tono de voz" + +#: ../src/fenrir/commands/commands/inc_speech_rate.py:18 +msgid "increase the speech rate" +msgstr "Aumenta la velocidad de voz" + +#: ../src/fenrir/commands/commands/inc_speech_volume.py:18 +msgid "increase the speech volume" +msgstr "Aumenta el volumen de voz" + +#: ../src/fenrir/commands/commands/indent_curr_line.py:18 +msgid "shows the indention level for the current line" +msgstr "Lee el nivel de indentación de la línea actual" + +#: ../src/fenrir/commands/commands/indent_curr_line.py:33 +msgid "indent {0}" +msgstr "" + +#: ../src/fenrir/commands/commands/last_clipboard.py:17 +msgid "selects the last clipboard" +msgstr "Selecciona el último portapapeles" + +#: ../src/fenrir/commands/commands/last_incoming.py:17 +msgid "displays the last received text" +msgstr "Lee el último mensaje recibido" + +#: ../src/fenrir/commands/commands/marked_text.py:18 +msgid "speaks the currently selected text that will be copied to the clipboard" +msgstr "Lee el texto que será copiado al portapapeles" + +#: ../src/fenrir/commands/commands/marked_text.py:23 +msgid "please set begin and endmark" +msgstr "Establece una marca de principio y otra para el final de la selección." + +#: ../src/fenrir/commands/commands/next_clipboard.py:17 +msgid "selects the next clipboard" +msgstr "Selecciona el siguiente portapapeles" + +#: ../src/fenrir/commands/commands/next_clipboard.py:26 +msgid "First clipboard " +msgstr "Primer portapapeles" + +#: ../src/fenrir/commands/commands/paste_clipboard.py:18 +msgid "pastes the text from the currently selected clipboard" +msgstr "Pega el texto del portapapeles en uso" + +#: ../src/fenrir/commands/commands/present_first_line.py:18 +msgid "present first line" +msgstr "lee la primera línea" + +#: ../src/fenrir/commands/commands/present_last_line.py:18 +#: ../src/fenrir/commands/commands/review_curr_line.py:18 +msgid "current line" +msgstr "línea actual" + +#: ../src/fenrir/commands/commands/prev_clipboard.py:17 +msgid "selects the previous clipboard" +msgstr "Selecciona el portapapeles anterior" + +#: ../src/fenrir/commands/commands/prev_clipboard.py:26 +msgid "Last clipboard " +msgstr "Último portapapeles" + +#: ../src/fenrir/commands/commands/quit_fenrir.py:17 +msgid "exits Fenrir" +msgstr "Sale de Fenrir" + +#: ../src/fenrir/commands/commands/remove_marks.py:17 +msgid "removes marks from selected text" +msgstr "Quitar marcas del texto seleccionado" + +#: ../src/fenrir/commands/commands/remove_marks.py:21 +msgid "Remove marks" +msgstr "Marcas eliminadas" + +#: ../src/fenrir/commands/commands/remove_word_from_spell_check.py:27 +msgid "removes the current word from the exceptions dictionary" +msgstr "Quita la palabra actual del diccionario de excepciones" + +#: ../src/fenrir/commands/commands/remove_word_from_spell_check.py:50 +msgid "{0} is already removed from dict" +msgstr "{0} no está en el diccionario" + +#: ../src/fenrir/commands/commands/remove_word_from_spell_check.py:53 +msgid "{0} removed" +msgstr "se ha eliminado {0}" + +#: ../src/fenrir/commands/commands/review_bottom.py:17 +msgid "move review to bottom of screen" +msgstr "Mueve el cursor de revisión al final de la pantalla" + +#: ../src/fenrir/commands/commands/review_bottom.py:21 +msgid "Bottom" +msgstr "Fin" + +#: ../src/fenrir/commands/commands/review_curr_char.py:18 +msgid "presents the current character." +msgstr "Lee el carácter actual" + +#: ../src/fenrir/commands/commands/review_curr_char_phonetic.py:18 +msgid "set review and phonetically presents the current character" +msgstr "Lee fonéticamente el último carácter" + +#: ../src/fenrir/commands/commands/review_curr_word.py:18 +msgid "current word." +msgstr "Palabra actual. " + +#: ../src/fenrir/commands/commands/review_curr_word.py:32 +#: ../src/fenrir/commands/commands/review_curr_word_phonetic.py:36 +#: ../src/fenrir/commands/commands/review_down.py:27 +#: ../src/fenrir/commands/commands/review_next_char.py:28 +#: ../src/fenrir/commands/commands/review_next_char_phonetic.py:30 +#: ../src/fenrir/commands/commands/review_next_line.py:34 +#: ../src/fenrir/commands/commands/review_next_word.py:34 +#: ../src/fenrir/commands/commands/review_next_word_phonetic.py:36 +#: ../src/fenrir/commands/commands/review_prev_char.py:31 +#: ../src/fenrir/commands/commands/review_prev_char_phonetic.py:30 +#: ../src/fenrir/commands/commands/review_prev_line.py:32 +#: ../src/fenrir/commands/commands/review_prev_word.py:32 +#: ../src/fenrir/commands/commands/review_prev_word_phonetic.py:36 +#: ../src/fenrir/commands/commands/review_up.py:27 +msgid "end of screen" +msgstr "Fin de pantalla" + +#: ../src/fenrir/commands/commands/review_curr_word.py:35 +#: ../src/fenrir/commands/commands/review_curr_word_phonetic.py:39 +#: ../src/fenrir/commands/commands/review_next_char.py:31 +#: ../src/fenrir/commands/commands/review_next_char_phonetic.py:33 +#: ../src/fenrir/commands/commands/review_next_word.py:37 +#: ../src/fenrir/commands/commands/review_next_word_phonetic.py:39 +#: ../src/fenrir/commands/commands/review_prev_char.py:34 +#: ../src/fenrir/commands/commands/review_prev_char_phonetic.py:33 +#: ../src/fenrir/commands/commands/review_prev_word.py:35 +#: ../src/fenrir/commands/commands/review_prev_word_phonetic.py:39 +#: ../src/fenrir/commands/commands/review_up.py:30 +msgid "line break" +msgstr "Nueva línea" + +#: ../src/fenrir/commands/commands/review_curr_word_phonetic.py:19 +#: ../src/fenrir/commands/commands/review_next_word_phonetic.py:19 +#: ../src/fenrir/commands/commands/review_prev_word_phonetic.py:19 +msgid "phonetically spells the current word and set review to it" +msgstr "Deletrea fonéticamente la palabra actual" + +#: ../src/fenrir/commands/commands/review_down.py:18 +msgid "set review cursor to char below the current char and present it." +msgstr "Mueve el cursor de revisión al carácter después del actual y lo lee" + +#: ../src/fenrir/commands/commands/review_line_begin.py:18 +msgid "set review cursor to begin of current line and display the content" +msgstr "lee la línea actual desde el principio" + +#: ../src/fenrir/commands/commands/review_line_begin.py:30 +msgid "beginning of line" +msgstr "principio de línea" + +#: ../src/fenrir/commands/commands/review_line_end.py:18 +#: ../src/fenrir/commands/commands/review_line_first_char.py:19 +#: ../src/fenrir/commands/commands/review_line_last_char.py:18 +msgid "set review cursor to end of current line and display the content" +msgstr "Lee el final de la línea" + +#: ../src/fenrir/commands/commands/review_line_end.py:27 +msgid "end of line" +msgstr "Fin de línea" + +#: ../src/fenrir/commands/commands/review_line_first_char.py:26 +msgid "line is empty" +msgstr "Línea en blanco" + +#: ../src/fenrir/commands/commands/review_line_first_char.py:33 +msgid "first char in line indent {0}" +msgstr "" + +#: ../src/fenrir/commands/commands/review_line_last_char.py:27 +msgid "last char in line" +msgstr "último carácter de la línea" + +#: ../src/fenrir/commands/commands/review_next_char.py:18 +msgid "moves review to the next character and presents it" +msgstr "Lee el siguiente carácter" + +#: ../src/fenrir/commands/commands/review_next_char_phonetic.py:18 +msgid "phonetically presents the next character and set review to it" +msgstr "Lee fonéticamente el siguiente carácter" + +#: ../src/fenrir/commands/commands/review_next_line.py:18 +msgid "moves review to the next line and presents it" +msgstr "Lee la siguiente línea" + +#: ../src/fenrir/commands/commands/review_next_word.py:18 +msgid "moves review to the next word and presents it" +msgstr "Lee la siguiente palabra" + +#: ../src/fenrir/commands/commands/review_prev_char.py:18 +msgid "moves review to the previous character and presents it" +msgstr "Lee el carácter anterior" + +#: ../src/fenrir/commands/commands/review_prev_char_phonetic.py:18 +msgid "phonetically presents the previous character and set review to it" +msgstr "Lee fonéticamente el carácter anterior" + +#: ../src/fenrir/commands/commands/review_prev_line.py:18 +msgid "moves review to the previous line and presents it" +msgstr "Lee la línea anterior" + +#: ../src/fenrir/commands/commands/review_prev_word.py:18 +msgid "moves review focus to the previous word and presents it" +msgstr "Lee la palabra anterior" + +#: ../src/fenrir/commands/commands/review_top.py:18 +msgid "move review to top of screen" +msgstr "ir al final de la pantalla" + +#: ../src/fenrir/commands/commands/review_top.py:22 +msgid "Top" +msgstr "Fin" + +#: ../src/fenrir/commands/commands/review_up.py:18 +msgid "set review cursor to the char in the line below and present it" +msgstr "Mueve el cursor de revisión al carácter en la siguiente línea y lo lee" + +#: ../src/fenrir/commands/commands/set_bookmark_1.py:18 +#: ../src/fenrir/commands/commands/set_bookmark_10.py:18 +#: ../src/fenrir/commands/commands/set_bookmark_2.py:18 +#: ../src/fenrir/commands/commands/set_bookmark_3.py:18 +#: ../src/fenrir/commands/commands/set_bookmark_4.py:18 +#: ../src/fenrir/commands/commands/set_bookmark_5.py:18 +#: ../src/fenrir/commands/commands/set_bookmark_6.py:18 +#: ../src/fenrir/commands/commands/set_bookmark_7.py:18 +#: ../src/fenrir/commands/commands/set_bookmark_8.py:18 +#: ../src/fenrir/commands/commands/set_bookmark_9.py:18 +msgid "set Bookmark {0}" +msgstr "Añadir marcador {0}" + +#: ../src/fenrir/commands/commands/set_bookmark_1.py:22 +#: ../src/fenrir/commands/commands/set_bookmark_10.py:22 +#: ../src/fenrir/commands/commands/set_bookmark_2.py:22 +#: ../src/fenrir/commands/commands/set_bookmark_3.py:22 +#: ../src/fenrir/commands/commands/set_bookmark_4.py:22 +#: ../src/fenrir/commands/commands/set_bookmark_5.py:22 +#: ../src/fenrir/commands/commands/set_bookmark_6.py:22 +#: ../src/fenrir/commands/commands/set_bookmark_7.py:22 +#: ../src/fenrir/commands/commands/set_bookmark_8.py:22 +#: ../src/fenrir/commands/commands/set_bookmark_9.py:22 +msgid "No Mark found" +msgstr "No se han encontrado marcas" + +#: ../src/fenrir/commands/commands/set_bookmark_1.py:32 +#: ../src/fenrir/commands/commands/set_bookmark_10.py:32 +#: ../src/fenrir/commands/commands/set_bookmark_2.py:32 +#: ../src/fenrir/commands/commands/set_bookmark_3.py:32 +#: ../src/fenrir/commands/commands/set_bookmark_4.py:32 +#: ../src/fenrir/commands/commands/set_bookmark_5.py:32 +#: ../src/fenrir/commands/commands/set_bookmark_6.py:32 +#: ../src/fenrir/commands/commands/set_bookmark_7.py:32 +#: ../src/fenrir/commands/commands/set_bookmark_8.py:32 +#: ../src/fenrir/commands/commands/set_bookmark_9.py:32 +msgid "Bookmark {0} set for application {1}" +msgstr "Añadido marcador {0} para aplicación {1}" + +#: ../src/fenrir/commands/commands/set_mark.py:17 +msgid "places marks to select text to copy to the clipboard" +msgstr "" +"Establece marcas para seleccionar texto que será copiado al portapapeles" + +#: ../src/fenrir/commands/commands/set_mark.py:21 +msgid "no review cursor" +msgstr "No hay cursor de revisión" + +#: ../src/fenrir/commands/commands/set_mark.py:26 +#: ../src/fenrir/commands/commands/set_mark.py:28 +msgid "set mark" +msgstr "Marcar" + +#: ../src/fenrir/commands/commands/set_window_application.py:17 +msgid "set Window Mode, needs 2 marks " +msgstr "se necesitan dos marcas para establecer el modo ventana" + +#: ../src/fenrir/commands/commands/set_window_application.py:22 +msgid "Window Mode on for application {0}" +msgstr "El modo de ventana está activado para la aplicación {0}" + +#: ../src/fenrir/commands/commands/set_window_application.py:25 +msgid "Set window begin and end marks" +msgstr "Establece una marca de principio y otra para el final de la ventana" + +#: ../src/fenrir/commands/commands/shut_up.py:17 +msgid "interrupts the current presentation" +msgstr "Interrumpe el habla y braille." + +#: ../src/fenrir/commands/commands/spell_check.py:26 +msgid "checks the spelling of the current word" +msgstr "Revisa la ortografía para la palabra actual" + +#: ../src/fenrir/commands/commands/spell_check.py:52 +#: ../src/fenrir/commands/onInput/62000-spell_check.py:132 +msgid "misspelled" +msgstr "mal escrito" + +#: ../src/fenrir/commands/commands/spell_check.py:54 +msgid "correct" +msgstr "Correcto" + +#: ../src/fenrir/commands/commands/subprocess.py:21 +msgid "script: {0} fullpath: {1}" +msgstr "Script: {0} Ruta de archivo: {1}" + +#: ../src/fenrir/commands/commands/subprocess.py:24 +msgid "scriptfile does not exist" +msgstr "el archivo del script no existe" + +#: ../src/fenrir/commands/commands/subprocess.py:27 +msgid "scriptfile is not a file" +msgstr "El script no es un archivo" + +#: ../src/fenrir/commands/commands/subprocess.py:30 +msgid "scriptfile is not executable" +msgstr "el script no es ejecutable" + +#: ../src/fenrir/commands/commands/temp_disable_speech.py:17 +#: ../src/fenrir/commands/onInput/15000-enable_temp_speech.py:17 +msgid "disables speech until next keypress" +msgstr "Desactiva el habla hasta la siguiente pulsación de teclas" + +#: ../src/fenrir/commands/commands/temp_disable_speech.py:21 +msgid "speech temporary disabled" +msgstr "Habla desactivada temporalmente" + +#: ../src/fenrir/commands/commands/time.py:18 +msgid "presents the time" +msgstr "Lee la hora" + +#: ../src/fenrir/commands/commands/toggle_auto_read.py:16 +msgid "enables or disables automatic reading of new text as it appears" +msgstr "" +"Activa o desactiva la lectura de texto cuando hay nuevo contenido en la " +"pantalla" + +#: ../src/fenrir/commands/commands/toggle_auto_read.py:21 +msgid "autoread enabled" +msgstr "Lectura automática activada" + +#: ../src/fenrir/commands/commands/toggle_auto_read.py:23 +msgid "autoread disabled" +msgstr "Lectura automática desactivada" + +#: ../src/fenrir/commands/commands/toggle_auto_spell_check.py:17 +msgid "enables or disables automatic spell checking" +msgstr "Activa o desactiva la corrección ortográfica automática" + +#: ../src/fenrir/commands/commands/toggle_auto_spell_check.py:22 +msgid "auto spellcheck enabled" +msgstr "corrección ortográfica automática activada" + +#: ../src/fenrir/commands/commands/toggle_auto_spell_check.py:24 +msgid "auto spellcheck disabled" +msgstr "corrección ortográfica automática desactivada" + +#: ../src/fenrir/commands/commands/toggle_auto_time.py:16 +msgid "enables or disables automatic reading of time after an period" +msgstr "" +"Activa o desactiva la lectura automática de la hora después de un intervalo " +"de tiempo" + +#: ../src/fenrir/commands/commands/toggle_auto_time.py:21 +msgid "autotime enabled" +msgstr "lectura automática de hora activada" + +#: ../src/fenrir/commands/commands/toggle_auto_time.py:23 +msgid "autotime disabled" +msgstr "Lectura automática de hora desactivada" + +#: ../src/fenrir/commands/commands/toggle_braille.py:17 +msgid "enables and disables output in braille" +msgstr "Activa y desactiva la salida Braille" + +#: ../src/fenrir/commands/commands/toggle_braille.py:21 +msgid "braille disabled" +msgstr "Braille desactivado" + +#: ../src/fenrir/commands/commands/toggle_braille.py:24 +msgid "braille enabled" +msgstr "Braille activado" + +#: ../src/fenrir/commands/commands/toggle_emoticons.py:16 +msgid "enables or disables announcement of emoticons instead of chars" +msgstr "Activa o desactiva el anunciado de emoticonos en lugar de caracteres" + +#: ../src/fenrir/commands/commands/toggle_emoticons.py:21 +msgid "emoticons enabled" +msgstr "Emoticonos activados" + +#: ../src/fenrir/commands/commands/toggle_emoticons.py:23 +msgid "emoticons disabled" +msgstr "Emoticonos desactivados" + +#: ../src/fenrir/commands/commands/toggle_highlight_tracking.py:16 +#: ../src/fenrir/commands/onInput/56000-highlight_tracking.py:16 +msgid "enables or disables tracking of highlighted" +msgstr "Activa o desactiva el seguimiento de texto resaltado" + +#: ../src/fenrir/commands/commands/toggle_highlight_tracking.py:24 +msgid "highlight tracking" +msgstr "Seguimiento del texto resaltado" + +#: ../src/fenrir/commands/commands/toggle_highlight_tracking.py:26 +msgid "cursor tracking" +msgstr "Seguimiento del cursor" + +#: ../src/fenrir/commands/commands/toggle_output.py:17 +msgid "toggles all output settings" +msgstr "Conmuta el silencio del lector de pantalla" + +#: ../src/fenrir/commands/commands/toggle_output.py:23 +msgid "Fenrir muted" +msgstr "Fenrir silenciado" + +#: ../src/fenrir/commands/commands/toggle_output.py:31 +msgid "Fenrir unmuted" +msgstr "Desactivado el silencio" + +#: ../src/fenrir/commands/commands/toggle_punctuation_level.py:23 +msgid "No punctuation found." +msgstr "No se ha encontrado la puntuación" + +#: ../src/fenrir/commands/commands/toggle_sound.py:17 +msgid "enables or disables sound" +msgstr "Activa o desactiva el sonido" + +#: ../src/fenrir/commands/commands/toggle_sound.py:21 +msgid "sound disabled" +msgstr "sonido desactivado" + +#: ../src/fenrir/commands/commands/toggle_sound.py:24 +msgid "sound enabled" +msgstr "Sonido activado" + +#: ../src/fenrir/commands/commands/toggle_speech.py:17 +msgid "enables or disables speech" +msgstr "Activa o desactiva el habla" + +#: ../src/fenrir/commands/commands/toggle_speech.py:21 +msgid "speech disabled" +msgstr "Habla desactivada" + +#: ../src/fenrir/commands/commands/toggle_speech.py:24 +#: ../src/fenrir/commands/onInput/15000-enable_temp_speech.py:28 +msgid "speech enabled" +msgstr "Habla activada" + +#: ../src/fenrir/commands/commands/toggle_tutorial_mode.py:18 +msgid "" +"You are leaving the tutorial mode. Press that shortcut again to enter the " +"tutorial mode again." +msgstr "" +"Has salido del tutorial. Presiona la misma combinación de teclado para " +"entrar al tutorial de nuevo." + +#: ../src/fenrir/commands/commands/toggle_tutorial_mode.py:21 +msgid "" +"you entered the tutorial mode. In that mode the commands are not executed. " +"but you get a description of what the shortcut does. To leave the tutorial " +"mode, press that shortcut again." +msgstr "" +"Has entrado al tutorial. En este modo las combinaciones de teclado no se " +"ejecutarán pero te darán una descripción de lo que hacen. Para salir del " +"tutorial, presiona la misma combinación de teclado de nuevo." + +#: ../src/fenrir/commands/onInput/80000-capslock.py:22 +msgid "Capslock on" +msgstr "Bloqueo mayúsculas activado" + +#: ../src/fenrir/commands/onInput/80000-capslock.py:24 +msgid "Capslock off" +msgstr "Bloqueo mayúsculas desactivado" + +#: ../src/fenrir/commands/onInput/80300-scrolllock.py:22 +msgid "Scrolllock on" +msgstr "Bloqueo de desplazamiento activado" + +#: ../src/fenrir/commands/onInput/80300-scrolllock.py:24 +msgid "Scrolllock off" +msgstr "Bloqueo de desplazamiento desactivado" + +#: ../src/fenrir/commands/onInput/80500-numlock.py:22 +msgid "Numlock on" +msgstr "Bloqueo numérico activado" + +#: ../src/fenrir/commands/onInput/80500-numlock.py:24 +msgid "Numlock off" +msgstr "Bloqueo numérico desactivado" + +#: ../src/fenrir/commands/onScreenChanged/80000-screen_change_announcement.py:20 +msgid "screen {0}" +msgstr "pantalla {0}" + +#: ../src/fenrir/commands/onScreenUpdate/76000-time.py:66 +msgid "Autotime: {0}" +msgstr "Hora automática: {0}" + +#: ../src/fenrir/fenrir.py:24 +msgid "Start Fenrir" +msgstr "Iniciando fenrir" + +#: ../src/fenrir/fenrir.py:99 +msgid "Quit Fenrir" +msgstr "Cerrando Fenrir" diff --git a/play zone/argp.py b/play zone/argp.py new file mode 100755 index 0000000..f97130d --- /dev/null +++ b/play zone/argp.py @@ -0,0 +1,12 @@ +#!/bin/python3 +import argparse + +parser = argparse.ArgumentParser(description="Fenrir Help") + +parser.add_argument('-s', '--setting', metavar='SETTING-FILE', default='/etc/fenrir/settings/settings.conf', help='Use a specified settingsfile') +parser.add_argument('-o', '--options', metavar='SECTION:SETTING=VALUE,..', default='', help='Overwrite options in given settings file') + +args = parser.parse_args() +parser.print_help() + +print(args.setting) diff --git a/play zone/charmapTTY.py b/play zone/charmapTTY.py new file mode 100755 index 0000000..981331f --- /dev/null +++ b/play zone/charmapTTY.py @@ -0,0 +1,88 @@ +import time +from fcntl import ioctl +from array import array +from struct import unpack_from +from struct import unpack +from struct import pack +import errno +import sys +charmap = {} +hichar = None +def updateCharMap(screen): + global hichar + ttyno = '4' + tty = open('/dev/tty' + screen, 'rb') + GIO_UNIMAP = 0x4B66 + VT_GETHIFONTMASK = 0x560D + himask = array("H", (0,)) + ioctl(tty, VT_GETHIFONTMASK, himask) + hichar, = unpack_from("@H", himask) + sz = 512 + line = '' + while True: + try: + unipairs = array("H", [0]*(2*sz)) + unimapdesc = array("B", pack("@HP", sz, unipairs.buffer_info()[0])) + ioctl(tty.fileno(), GIO_UNIMAP, unimapdesc) + break + except IOError as e: + if e.errno != errno.ENOMEM: + raise + sz *= 2 + tty.close() + ncodes, = unpack_from("@H", unimapdesc) + utable = unpack_from("@%dH" % (2*ncodes), unipairs) + for u, b in zip(utable[::2], utable[1::2]): + if charmap.get(b) is None: + charmap[b] = chr(u) + + +def autoDecodeVCSA(allData, rows, cols): + allText = [] + allAttrib = [] + for y in range(rows): + lineText = '' + lineAttrib = [] + i = 0 + for x in range(cols): + data = allData[i: i + 2] + i += 2 + if data == b' \x07': + #attr = 7 + #ink = 7 + #paper = 0 + #ch = ' ' + lineAttrib.append(7) + lineText += ' ' + continue + (sh,) = unpack("=H", data) + attr = (sh >> 8) & 0xFF + ch = sh & 0xFF + if hichar == 0x100: + attr >>= 1 + lineAttrib.append(attr) + ink = attr & 0x0F + paper = (attr>>4) & 0x0F + #if (ink != 7) or (paper != 0): + # print(ink,paper) + if sh & hichar: + ch |= 0x100 + try: + lineText += charmap[ch] + except: + lineText += chr('?') + allText.append(lineText) + allAttrib.append(lineAttrib) + return allText, allAttrib + +def m(screen): + s = time.time() + updateCharMap(str(screen)) + print(time.time() -s ) + vcsa = open('/dev/vcsa' + str(screen), 'rb') + head = vcsa.read(4) + rows = int(head[0]) + cols = int(head[1]) + text, attrib = autoDecodeVCSA(vcsa.read(), rows, cols) + print(time.time() -s ) + diff --git a/play zone/colors.sh b/play zone/colors.sh new file mode 100644 index 0000000..7459faf --- /dev/null +++ b/play zone/colors.sh @@ -0,0 +1,39 @@ +#!/bin/bash +echo "foreground colors" +echo -e "\e[39mDefault" +echo -e "\e[30mBlack" +echo -e "\e[31mRed" +echo -e "\e[32mGreen" +echo -e "\e[33mYellow" +echo -e "\e[34mBlue" +echo -e "\e[35mMagenta" +echo -e "\e[36mCyan" +echo -e "\e[37mLight gray" +echo -e "\e[90mDark gray" +echo -e "\e[91mLight red" +echo -e "\e[92mLight green" +echo -e "\e[93mLight yellow" +echo -e "\e[94mLight blue" +echo -e "\e[95mLight magenta" +echo -e "\e[96mLight cyan" +echo -e "\e[97mWhite" + +echo "background colors" +echo -e "\e[49mDefault" +echo -e "\e[40mBlack" +echo -e "\e[41mRed" +echo -e "\e[42mGreen" +echo -e "\e[43mYellow" +echo -e "\e[44mBlue" +echo -e "\e[45mMagenta" +echo -e "\e[46mCyan" +echo -e "\e[47mLight gray" +echo -e "\e[100mDark gray" +echo -e "\e[101mLight red" +echo -e "\e[102mLight green" +echo -e "\e[103mLight yellow" +echo -e "\e[104mLight blue" +echo -e "\e[105mLight magenta" +echo -e "\e[106mLight cyan" +echo -e "\e[107mWhite" + diff --git a/play zone/consumeEvents.py b/play zone/consumeEvents.py index 3adad63..c2e110b 100755 --- a/play zone/consumeEvents.py +++ b/play zone/consumeEvents.py @@ -5,7 +5,8 @@ import time iDevices = map(evdev.InputDevice, (evdev.list_devices())) -iDevices = {dev.fd: dev for dev in iDevices if 1 in dev.capabilities()} +iDevices = {dev.fd: dev for dev in iDevices if evdev.events.EV_KEY in dev.capabilities()} + uDevices = {} for fd in iDevices: dev = iDevices[fd] diff --git a/play zone/daemon.py b/play zone/daemon.py old file mode 100644 new file mode 100755 index 52a58e3..52a58e3 100755 diff --git a/play zone/detectDevices.py b/play zone/detectDevices.py new file mode 100755 index 0000000..c4ca8ec --- /dev/null +++ b/play zone/detectDevices.py @@ -0,0 +1,48 @@ +#!/bin/python +iDevices = {} +iDeviceNo = 0 +def updateInputDevices(force = False, init = False): + global iDeviceNo + if init: + iDevices = {} + iDeviceNo = 0 + deviceFileList = evdev.list_devices() + if not force: + if len(deviceFileList) == iDeviceNo: + return + iDeviceNo = len(deviceFileList) + mode = 'ALL' + iDevicesFiles = [] + for device in iDevices: + iDevicesFiles.append(iDevices[device].fn) + print(len(iDevicesFiles),len(deviceFileList)) + if len(iDevicesFiles) == len(deviceFileList): + return + for deviceFile in deviceFileList: + try: + if deviceFile in iDevicesFiles: + print('skip') + continue + open(deviceFile) + # 3 pos absolute + # 2 pos relative + # 1 Keys + currDevice = evdev.InputDevice(deviceFile) + cap = currDevice.capabilities() + if mode in ['ALL','NOMICE']: + if 1 in cap: + if 116 in cap[1] and len(cap[1]) < 5: + print('power') + continue + if mode == 'ALL': + iDevices[currDevice.fd] = currDevice + print('Device added:' + iDevices[currDevice.fd].name) + elif mode == 'NOMICE': + if not ((2 in cap) or (3 in cap)): + iDevices[currDevice.fd] = currDevice + print('Device added:' + iDevices[currDevice.fd].name) + elif currDevice.name.upper() in mode.split(','): + iDevices[currDevice.fd] = currDevice + print('Device added:' + iDevices[currDevice.fd].name) + except Exception as e: + print("Skip Inputdevice : " + deviceFile +' ' + str(e)) diff --git a/play zone/epollScreen.py b/play zone/epollScreen.py new file mode 100644 index 0000000..cf40611 --- /dev/null +++ b/play zone/epollScreen.py @@ -0,0 +1,37 @@ +#!/bin/python + +import select +import time + +currScreen = '2' +vcsa = {} +for i in range(1,7): + vcsa[str(i)] = open('/dev/vcs'+str(i),'rb') + +tty = open('/sys/devices/virtual/tty/tty0/active','r') +currScreen = str(tty.read()[3:-1]) +oldScreen = currScreen +watchdog = select.epoll() +watchdog.register(vcsa[currScreen], select.EPOLLPRI) +watchdog.register(tty, select.EPOLLPRI) + +while True: + changes = watchdog.poll() + print('-----------------------------') + print(changes) + for change in changes: + fileno = change[0] + event = change[1] + print(change,fileno, tty.fileno()) + if fileno == tty.fileno(): + tty.seek(0) + currScreen = str(tty.read()[3:-1]) + if currScreen != oldScreen: + watchdog.unregister(vcsa[ oldScreen ]) + watchdog.register(vcsa[ currScreen ], select.EPOLLPRI) + oldScreen = currScreen + print('new screen '+ currScreen) + else: + vcsa[currScreen].seek(0) + content = vcsa[currScreen].read() + print('update '+ str(time.time())) diff --git a/play zone/fg.sh b/play zone/fg.sh new file mode 100755 index 0000000..ebf1511 --- /dev/null +++ b/play zone/fg.sh @@ -0,0 +1,48 @@ +#!/bin/bash +echo "foreground colors" +echo -e "\e[39mDefault" +echo -e "\e[30mBlack" +echo -e "\e[31mRed" +echo -e "\e[32mGreen" +echo -e "\e[33mYellow" +echo -e "\e[34mBlue" +echo -e "\e[35mMagenta" +echo -e "\e[36mCyan" +echo -e "\e[37mLight gray" +echo -e "\e[90mDark gray" +echo -e "\e[91mLight red" +echo -e "\e[92mLight green" +echo -e "\e[93mLight yellow" +echo -e "\e[94mLight blue" +echo -e "\e[95mLight magenta" +echo -e "\e[96mLight cyan" +echo -e "\e[97mWhite" +#7: _('Default'), 0: _('Black'), 4: _('Red'), 2: _('Green'), 6: _('Yellow'), 1: _('Blue'), 5: _('Magenta'), 3: _('Cyan'), 7: _('Light gray'), 8: _('Dark gray'), 12: _('Light red'), 10: , ('Light green'), 14: _('Light yellow'), 9: _('Light blue'), 13: _('Light magenta'), 11: _('Light cyan'), 15: _('White') + +echo "background colors" +echo -e "\e[49mDefault" +echo -e "\e[40mBlack" +echo -e "\e[41mRed" +echo -e "\e[42mGreen" +echo -e "\e[43mYellow" +echo -e "\e[44mBlue" +echo -e "\e[45mMagenta" +echo -e "\e[46mCyan" +echo -e "\e[47mLight gray" +echo -e "\e[100mDark gray" +echo -e "\e[101mLight red" +echo -e "\e[102mLight green" +echo -e "\e[103mLight yellow" +echo -e "\e[104mLight blue" +echo -e "\e[105mLight magenta" +echo -e "\e[106mLight cyan" +echo -e "\e[107mWhite" + +echo "format" +echo -e "\e[1mBold" +echo -e "\e[2mDim" +echo -e "\e[4mUnderlined" +echo -e "\e[5mBlink" +echo -e "\e[7minverted" +echo -e "\e[8mHidden" + diff --git a/play zone/listDevices.py b/play zone/listDevices.py new file mode 100755 index 0000000..9af5a7e --- /dev/null +++ b/play zone/listDevices.py @@ -0,0 +1,21 @@ +#!/bin/python +import evdev +from evdev import InputDevice, UInput +from select import select +import time + +iDevices = map(evdev.InputDevice, (evdev.list_devices())) +iDevices = {dev.fd: dev for dev in iDevices} +print('----------------------') +for fd in iDevices: + dev = iDevices[fd] + cap = dev.capabilities() + print('Name: ' + str(dev.name)) + print('LEDs: ' + str(dev.leds())) + print('Has Keys: '+ str(evdev.events.EV_KEY in cap)) + if evdev.events.EV_KEY in cap: + print('No. of keys: ' + str(len(cap[evdev.events.EV_KEY]))) + print('has Key 116: ' + str(116 in cap[evdev.events.EV_KEY])) + print('Is Mouse: ' + str(((evdev.events.EV_REL in cap) or (evdev.events.EV_ABS in cap)))) + print('----------------------') + diff --git a/play zone/marytts.py b/play zone/marytts.py new file mode 100755 index 0000000..8cbffbc --- /dev/null +++ b/play zone/marytts.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# HTTP + URL packages +import httplib2 +from urllib.parse import urlencode, quote # For URL creation +import time +# To play wave files +import pygame +import math # For ceiling + + +# Mary server informations +mary_host = "127.0.0.1" +mary_port = "59125" + +# Input text +input_text = "das ist ein test das ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testdas ist ein testd" +# Build the query +query_hash = {"INPUT_TEXT":input_text, + "INPUT_TYPE":"TEXT", # Input text + "LOCALE":"de", + "VOICE":"bits3", # Voice informations (need to be compatible) + "OUTPUT_TYPE":"AUDIO", + "AUDIO":"WAVE", # Audio informations (need both) + } +starttime = time.time() +query = urlencode(query_hash) +#print("query = \"http://%s:%s/process?%s\"" % (mary_host, mary_port, query)) + +# Run the query to mary http server +h_mary = httplib2.Http() +#print("http://%s:%s/process?" % (mary_host, mary_port), "POST", query) +resp, content = h_mary.request("http://%s:%s/process?" % (mary_host, mary_port), "POST", query) + +# Decode the wav file or raise an exception if no wav files +if (resp["content-type"] == "audio/x-wav"): + # Write the wav file + f = open("/tmp/output_wav.wav", "wb") + f.write(content) + f.close() + # Play the wav file + pygame.mixer.init(frequency=16000) # Initialise the mixer + #s = pygame.mixer.Sound(content) + s = pygame.mixer.Sound("/tmp/output_wav.wav") + print(str(time.time() -starttime)) + s.play() + print(str(time.time() -starttime)) + pygame.time.wait(int(math.ceil(s.get_length() * 1000))) + +else: + raise Exception(content) diff --git a/play zone/parseProcessTree.py b/play zone/parseProcessTree.py new file mode 100755 index 0000000..1303f46 --- /dev/null +++ b/play zone/parseProcessTree.py @@ -0,0 +1,53 @@ +#!/bin/python +import os +import time +start = time.time() +pids = [pid for pid in os.listdir('/proc') if pid.isdigit()] +#pids = ['5960'] + +tty = os.open('/dev/tty2', os.O_RDWR) +fg = str(os.tcgetpgrp(tty)) +tty.close() +print(fg) +for pid in pids: + try: + currStat = str(open('/proc/' + pid + '/stat', 'rb').read()) + currStat = currStat.split(' ') + if int(currStat[4]) == 0: + continue + #print(currStat) + #print(fg,int(currStat[4])) + if fg == currStat[4]: + print(currStat[1]) + #print( currStat ) + #print(currStat[0]) + major = os.major(int(currStat[6])) + minor = os.minor(int(currStat[6])) + ueventContent = open('/sys/dev/char/' + str(major) + ':' + str(minor) + '/uevent','r').read().split() + #print(ueventContent) + #print(int(currStat[4]),currStat[1]) + except IOError: # proc has already terminated + continue + +print(time.time()-start) + + +''' +Table 1-4: Contents of the stat files (as of 2.6.30-rc7) +.............................................................................. + Field Content + pid process id + tcomm filename of the executable + state state (R is running, S is sleeping, D is sleeping in an + uninterruptible wait, Z is zombie, T is traced or stopped) + ppid process id of the parent process + pgrp pgrp of the process + sid session id + tty_nr tty the process uses + tty_pgrp pgrp of the tty + flags task flags + min_flt number of minor faults + cmin_flt number of minor faults with child's + maj_flt number of major faults + cmaj_flt number of major faults with child's +''' diff --git a/play zone/print_escape.py b/play zone/print_escape.py new file mode 100644 index 0000000..7ccb1e5 --- /dev/null +++ b/play zone/print_escape.py @@ -0,0 +1,41 @@ +#!/bin/python3 +import sys, os +import pty +import pyte + +class FenrirTermStream(pyte.Stream): + def __init__(self): + super().__init__() + def attach(self, screen): + super().attach(screen) + def feed(self, text): + super().feed(text) + +class FenrirTermEmu(): + def __init__(self): + self.shell = '/bin/bash' + if 'SHELL' in os.environ: + self.shell = os.environ['SHELL'] + self.screen = pyte.Screen(80,24) + self.stream = FenrirTermStream() + self.stream.attach(self.screen) + def outputCallback(self, fd): + data = os.read(fd, 1024) + self.stream.feed(data.decode('UTF8')) + # alles + #print(self.screen.display) + # input + #print(data.decode('UTF8')) + return data + def inputCallback(self, fd): + data = os.read(fd, 1024) + print('|'+str(data)+'|') + if data == b'q': + print('quit') + return b'exit\r' + return data + def startEmulator(self): + pty.spawn(self.shell, self.outputCallback, self.inputCallback) + +t = FenrirTermEmu() +t.startEmulator() diff --git a/play zone/pyterm.py b/play zone/pyterm.py new file mode 100755 index 0000000..7be1844 --- /dev/null +++ b/play zone/pyterm.py @@ -0,0 +1,34 @@ +#!/bin/python3 +import sys, os +import pty +import pyte + +class FenrirTermStream(pyte.Stream): + def __init__(self): + super().__init__() + def attach(self, screen): + super().attach(screen) + def feed(self, text): + super().feed(text) + +class FenrirTermEmu(): + def __init__(self): + self.shell = '/bin/bash' + if 'SHELL' in os.environ: + self.shell = os.environ['SHELL'] + self.screen = pyte.Screen(80,24) + self.stream = FenrirTermStream() + self.stream.attach(self.screen) + def outputCallback(self, fd): + data = os.read(fd, 1024) + self.stream.feed(data.decode('UTF8')) + # alles + print(self.screen.display) + # input + print(data.decode('UTF8')) + return data + def inputCallback(self, fd): + data = os.read(fd, 1024) + return data + def startEmulator(self): + pty.spawn(self.shell, self.outputCallback, self.inputCallback) diff --git a/play zone/terminalManagement b/play zone/terminalManagement new file mode 100644 index 0000000..59fdab4 --- /dev/null +++ b/play zone/terminalManagement @@ -0,0 +1,119 @@ +import os +import struct +import sys +import pty +import tty +import termios +import shlex +import signal +import select +import pyte +import time + +class Terminal: + def __init__(self, columns, lines, p_in): + self.screen = pyte.HistoryScreen(columns, lines) + self.screen.set_mode(pyte.modes.LNM) + self.screen.write_process_input = \ + lambda data: p_in.write(data.encode()) + self.stream = pyte.ByteStream() + self.stream.attach(self.screen) + def feed(self, data): + self.stream.feed(data) + def dump(self): + cursor = self.screen.cursor + lines = [] + for y in self.screen.dirty: + line = self.screen.buffer[y] + data = [(char.data, char.reverse, char.fg, char.bg) + for char in (line[x] for x in range(self.screen.columns))] + lines.append((y, data)) + self.screen.dirty.clear() + return {"c": (cursor.x, cursor.y), "lines": lines} + + +def open_terminal(command="bash", columns=80, lines=24): + p_pid, master_fd = pty.fork() + if p_pid == 0: # Child. + argv = shlex.split(command) + env = os.environ.copy() + env["TERM"] = 'vt100' + os.execvpe(argv[0], argv, env) + # File-like object for I/O with the child process aka command. + p_out = os.fdopen(master_fd, "w+b", 0) + return Terminal(columns, lines, p_out), p_pid, p_out + +def HandleTerminal(): + debug = False + running = True + try: + old_attr = termios.tcgetattr(sys.stdin) + tty.setraw(0) + terminal, p_pid, p_out = open_terminal() + std_out = os.fdopen(sys.stdout.fileno(), "w+b", 0) + while running: + r, w, x = select.select([sys.stdin, p_out],[],[]) + if r == []: + continue + if p_out in r: + if debug: + print('pre p_out') + try: + msgBytes = read_all(p_out.fileno()) + except (EOFError, OSError): + running = False + break + terminal.feed(msgBytes) + os.write(sys.stdout.fileno(), msgBytes) + if debug: + print('after p_out') + if sys.stdin in r: + if debug: + print('pre stdin') + try: + msgBytes = read_all(sys.stdin.fileno()) + except (EOFError, OSError): + running = False + break + terminal.feed(msgBytes) + os.write(p_out.fileno(), msgBytes) + if debug: + print('after stdin') + except Exception as e: # Process died? + print(e) + running = False + finally: + os.kill(p_pid, signal.SIGTERM) + p_out.close() + termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_attr) + sys.exit(0) + +def get_terminal_size(fd): + s = struct.pack('HHHH', 0, 0, 0, 0) + rows, cols, _, _ = struct.unpack('HHHH', fcntl.ioctl(fd, termios.TIOCGWINSZ, s)) + return rows, cols + +def resize_terminal(fd): + s = struct.pack('HHHH', 0, 0, 0, 0) + s = fcntl.ioctl(0, termios.TIOCGWINSZ, s) + fcntl.ioctl(fd, termios.TIOCSWINSZ, s) + rows, cols, _, _ = struct.unpack('hhhh', s) + return rows, cols + +def read_all(fd): + bytes = os.read(fd, 65536) + if bytes == b'': + raise EOFError + while has_more(fd): + data = os.read(fd, 65536) + if data == b'': + raise EOFError + bytes += data + return bytes + +def has_more(fd): + r, w, e = select.select([fd], [], [], 0) + return (fd in r) + +if __name__ == "__main__": + HandleTerminal() diff --git a/setup.py b/setup.py new file mode 100755 index 0000000..cb141f3 --- /dev/null +++ b/setup.py @@ -0,0 +1,126 @@ +#!/bin/python +#https://python-packaging.readthedocs.io/en/latest/minimal.html +import os, glob, sys +import os.path +from shutil import copyfile +from setuptools import find_packages +from setuptools import setup + +fenrirVersion = '1.5' +packageVersion = 'post10' + +# handle flags for package manager like yaourt and pacaur. +forceSettings = False +if "--force-settings" in sys.argv: + forceSettings = True + sys.argv.remove("--force-settings") + +data_files = [] +directories = glob.glob('config/*') +for directory in directories: + files = glob.glob(directory+'/*') + destDir = '' + if 'config/punctuation' in directory : + destDir = '/etc/fenrir/punctuation' + elif 'config/keyboard' in directory: + destDir = '/etc/fenrir/keyboard' + elif 'config/settings' in directory: + destDir = '/etc/fenrir/settings' + if not forceSettings: + try: + del(files[files.index('config/settings/settings.conf')]) + except: + pass + elif 'config/scripts' in directory: + destDir = '/usr/share/fenrir/scripts' + if destDir != '': + data_files.append((destDir, files)) + +files = glob.glob('config/sound/default-wav/*') +destDir = '/usr/share/sounds/fenrir/default-wav' +data_files.append((destDir, files)) +files = glob.glob('config/sound/default/*') +destDir = '/usr/share/sounds/fenrir/default' +data_files.append((destDir, files)) +files = glob.glob('config/sound//template/*') +destDir = '/usr/share/sounds/fenrir/template' +data_files.append((destDir, files)) +files = glob.glob('tools/*') +data_files.append(('/usr/share/fenrir/tools', files)) +data_files.append(('/usr/lib/systemd/system', ['autostart/systemd/fenrir.service'])) +data_files.append(('/usr/share/man/man1', ['docu/fenrir.1'])) + +def read(fname): + return open(os.path.join(os.path.dirname(__file__), fname)).read() + +setup( + # Application name: + name="fenrir-screenreader", + # Version number: + version=fenrirVersion + '.' + packageVersion, + # description + description="A TTY Screen Reader for Linux.", + long_description=read('README.md'), + keywords=['screenreader', 'a11y', 'accessibility', 'terminal', 'TTY', 'console'], + license="License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)", + url="https://github.com/chrys87/fenrir/", + download_url = 'https://github.com/chrys87/fenrir/archive/' + fenrirVersion + '.tar.gz', + classifiers=[ + "Programming Language :: Python", + "License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)", + "Development Status :: 5 - Production/Stable", + "Topic :: Multimedia :: Sound/Audio :: Speech", + "Environment :: Console", + ], + + # Application author details: + author="Chrys, Storm_dragon, Jeremiah and others", + author_email="chrysg@linux-a11y.org", + + # Packages + packages=find_packages('src/fenrir'), + package_dir={'': 'src/fenrir'}, + scripts=['src/fenrir/fenrir','src/fenrir/fenrir-daemon'], + + # Include additional files into the package + include_package_data=True, + zip_safe=False, + + data_files=data_files, + + # Dependent packages (distributions) + install_requires=[ + "evdev", + "daemonize", + "dbus-python", + "pyenchant", + "pyudev", + "setuptools", + "pexpect", + ], + +) + +if not forceSettings: + print('') + # create settings file from example if not exist + if not os.path.isfile('/etc/fenrir/settings/settings.conf'): + try: + copyfile('/etc/fenrir/settings/settings.conf.example', '/etc/fenrir/settings/settings.conf') + print('create settings file in /etc/fenrir/settings/settings.conf') + except: + pass + else: + print('settings.conf file found. It is not overwritten automatical') + +print('') +print('To have Fenrir start at boot:') +print('sudo systemctl enable fenrir') +print('Pulseaudio users may want to run:') +print('/usr/share/fenrir/tools/configure_pulse.sh') +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') diff --git a/src/fenrir/brailleDriver/brlapi.py b/src/fenrir/brailleDriver/brlapi.py deleted file mode 100644 index 22d8836..0000000 --- a/src/fenrir/brailleDriver/brlapi.py +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from core import debug - -class driver(): - def __init__(self): - self._isInitialized = False - self._brl = None - - def initialize(self, environment): - self.env = environment - try: - import brlapi - except Exception as e: - print(e) - self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) - return - - try: - self._brl = brlapi.Connection() - except Exception as e: - print(e) - self.env['runtime']['debug'].writeDebugOut('BRAILLE.connectDevice '+str(e),debug.debugLevel.ERROR) - return - self._isInitialized = True - - 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() diff --git a/src/fenrir/brailleDriver/brlapiDriver.py b/src/fenrir/brailleDriver/brlapiDriver.py new file mode 100644 index 0000000..7c61e58 --- /dev/null +++ b/src/fenrir/brailleDriver/brlapiDriver.py @@ -0,0 +1,65 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class driver(): + def __init__(self): + self._isInitialized = False + 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() diff --git a/src/fenrir/brailleDriver/dummyDriver.py b/src/fenrir/brailleDriver/dummyDriver.py new file mode 100644 index 0000000..91a7c2b --- /dev/null +++ b/src/fenrir/brailleDriver/dummyDriver.py @@ -0,0 +1,55 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class driver(): + def __init__(self): + self.printMessages = False + + def initialize(self, environment): + self.env = environment + self._isInitialized = True + self.deviceSize = (40,0) + if self.printMessages: + print('BrailleDummyDriver: Initialize') + + + def getDeviceSize(self): + if not self._isInitialized: + return (0,0) + if self.printMessages: + print('BrailleDummyDriver: getDeviceSize ' + str(self.deviceSize)) + return self.deviceSize + + def writeText(self,text): + if not self._isInitialized: + return + if self.printMessages: + print('BrailleDummyDriver: writeText:' + str(text)) + print('BrailleDummyDriver: -----------------------------------') + + def connectDevice(self): + if self.printMessages: + print('BrailleDummyDriver: connectDevice') + + def enterScreen(self, screen): + if not self._isInitialized: + return + if self.printMessages: + print('BrailleDummyDriver: enterScreen') + + def leveScreen(self): + if not self._isInitialized: + return + if self.printMessages: + print('BrailleDummyDriver: leveScreen') + + def shutdown(self): + if not self._isInitialized: + return + if self.printMessages: + print('BrailleDummyDriver: Shutdown') diff --git a/src/fenrir/commands/commands/add_word_to_spell_check.py b/src/fenrir/commands/commands/add_word_to_spell_check.py index 7b0a627..2eb5c57 100644 --- a/src/fenrir/commands/commands/add_word_to_spell_check.py +++ b/src/fenrir/commands/commands/add_word_to_spell_check.py @@ -24,14 +24,14 @@ def shutdown(self): pass def getDescription(self): - return 'adds the current word to the exceptions dictionary' + return _('adds the current word to the exceptions dictionary') def updateSpellLanguage(self): self.spellChecker = enchant.Dict(self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage')) self.language = self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage') def run(self): if not initialized: - self.env['runtime']['outputManager'].presentText('pychant is not installed', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('pyenchant is not installed'), interrupt=True) return if self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage') != self.language: try: @@ -40,16 +40,16 @@ return cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() # get the word - newContent = self.env['screenData']['newContentText'].split('\n')[cursorPos['y']] + newContent = self.env['screen']['newContentText'].split('\n')[cursorPos['y']] x, y, currWord, endOfScreen, lineBreak = word_utils.getCurrentWord(cursorPos['x'], 0, newContent) currWord = currWord.strip(string.whitespace + '!"#$%&\()*+,-./:;<=§>?@[\\]^_{|}~') if currWord != '': if self.spellChecker.is_added(currWord): - self.env['runtime']['outputManager'].presentText(currWord + ' is already in dict',soundIcon='Cancel', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('{0} is already in dict').format(currWord,), soundIcon='Cancel', interrupt=True) else: self.spellChecker.add(currWord) - self.env['runtime']['outputManager'].presentText(currWord + ' added',soundIcon='Accept', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('{0} added').format(currWord,), soundIcon='Accept', interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/attribute_cursor.py b/src/fenrir/commands/commands/attribute_cursor.py new file mode 100644 index 0000000..86285b1 --- /dev/null +++ b/src/fenrir/commands/commands/attribute_cursor.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +from utils import screen_utils + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'No description found' + def run(self): + cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() + attributes = screen_utils.splitEvery(self.env['screen']['newContentAttrib'], self.env['screen']['columns']) + attributes = attributes[cursorPos['y']][cursorPos['x']] + attributeFormatString = self.env['runtime']['settingsManager'].getSetting('general', 'attributeFormatString') + attributeFormatString = self.env['runtime']['screenManager'].formatAttributes(attributes, attributeFormatString) + self.env['runtime']['outputManager'].presentText(attributeFormatString, soundIcon='', interrupt=True) + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/bookmark_1.py b/src/fenrir/commands/commands/bookmark_1.py index d7426c4..2892362 100644 --- a/src/fenrir/commands/commands/bookmark_1.py +++ b/src/fenrir/commands/commands/bookmark_1.py @@ -16,18 +16,18 @@ def shutdown(self): pass def getDescription(self): - return 'read Bookmark ' + self.ID + return _('read Bookmark {0}').format(self.ID,) def run(self): currApp = self.env['runtime']['applicationManager'].getCurrentApplication() if not self.env['commandBuffer']['bookMarks'][self.ID]: - self.env['runtime']['outputManager'].presentText("Bookmark " + self.ID + "not set", interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set').format(self.ID,), interrupt=True) return if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]: - self.env['runtime']['outputManager'].presentText("Bookmark for application " + currApp + " not set", interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) return if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1']: - self.env['runtime']['outputManager'].presentText("Bookmark for application " + currApp + " not set", interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) return # set marks @@ -35,12 +35,12 @@ startMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'].copy() if self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2']: endMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'].copy() - marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screenData']['newContentText']) + marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText']) else: x, y, marked = \ - line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screenData']['newContentText']) + line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screen']['newContentText']) if marked.isspace(): - self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('blank'), soundIcon='EmptyLine', interrupt=True) else: self.env['runtime']['outputManager'].presentText(marked, interrupt=True) diff --git a/src/fenrir/commands/commands/bookmark_10.py b/src/fenrir/commands/commands/bookmark_10.py index a975772..d85dcf2 100644 --- a/src/fenrir/commands/commands/bookmark_10.py +++ b/src/fenrir/commands/commands/bookmark_10.py @@ -16,18 +16,18 @@ def shutdown(self): pass def getDescription(self): - return 'read Bookmark ' + self.ID + return _('read Bookmark {0}').format(self.ID,) def run(self): currApp = self.env['runtime']['applicationManager'].getCurrentApplication() if not self.env['commandBuffer']['bookMarks'][self.ID]: - self.env['runtime']['outputManager'].presentText("Bookmark " + self.ID + "not set", interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set').format(self.ID,), interrupt=True) return if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]: - self.env['runtime']['outputManager'].presentText("Bookmark for application " + currApp + " not set", interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) return if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1']: - self.env['runtime']['outputManager'].presentText("Bookmark for application " + currApp + " not set", interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) return # set marks @@ -35,12 +35,12 @@ startMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'].copy() if self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2']: endMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'].copy() - marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screenData']['newContentText']) + marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText']) else: x, y, marked = \ - line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screenData']['newContentText']) + line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screen']['newContentText']) if marked.isspace(): - self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('blank'), soundIcon='EmptyLine', interrupt=True) else: self.env['runtime']['outputManager'].presentText(marked, interrupt=True) diff --git a/src/fenrir/commands/commands/bookmark_2.py b/src/fenrir/commands/commands/bookmark_2.py index 5eb9a66..e25c59c 100644 --- a/src/fenrir/commands/commands/bookmark_2.py +++ b/src/fenrir/commands/commands/bookmark_2.py @@ -16,18 +16,18 @@ def shutdown(self): pass def getDescription(self): - return 'read Bookmark ' + self.ID + return _('read Bookmark {0}').format(self.ID,) def run(self): currApp = self.env['runtime']['applicationManager'].getCurrentApplication() if not self.env['commandBuffer']['bookMarks'][self.ID]: - self.env['runtime']['outputManager'].presentText("Bookmark " + self.ID + "not set", interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set').format(self.ID,), interrupt=True) return if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]: - self.env['runtime']['outputManager'].presentText("Bookmark for application " + currApp + " not set", interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) return if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1']: - self.env['runtime']['outputManager'].presentText("Bookmark for application " + currApp + " not set", interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) return # set marks @@ -35,12 +35,12 @@ startMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'].copy() if self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2']: endMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'].copy() - marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screenData']['newContentText']) + marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText']) else: x, y, marked = \ - line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screenData']['newContentText']) + line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screen']['newContentText']) if marked.isspace(): - self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True) else: self.env['runtime']['outputManager'].presentText(marked, interrupt=True) diff --git a/src/fenrir/commands/commands/bookmark_3.py b/src/fenrir/commands/commands/bookmark_3.py index 95c521d..490e49b 100644 --- a/src/fenrir/commands/commands/bookmark_3.py +++ b/src/fenrir/commands/commands/bookmark_3.py @@ -16,18 +16,18 @@ def shutdown(self): pass def getDescription(self): - return 'read Bookmark ' + self.ID + return _('read Bookmark {0}').format(self.ID,) def run(self): currApp = self.env['runtime']['applicationManager'].getCurrentApplication() if not self.env['commandBuffer']['bookMarks'][self.ID]: - self.env['runtime']['outputManager'].presentText("Bookmark " + self.ID + "not set", interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set').format(self.ID,), interrupt=True) return if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]: - self.env['runtime']['outputManager'].presentText("Bookmark for application " + currApp + " not set", interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) return if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1']: - self.env['runtime']['outputManager'].presentText("Bookmark for application " + currApp + " not set", interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) return # set marks @@ -35,12 +35,12 @@ startMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'].copy() if self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2']: endMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'].copy() - marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screenData']['newContentText']) + marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText']) else: x, y, marked = \ - line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screenData']['newContentText']) + line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screen']['newContentText']) if marked.isspace(): - self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('blank'), soundIcon='EmptyLine', interrupt=True) else: self.env['runtime']['outputManager'].presentText(marked, interrupt=True) diff --git a/src/fenrir/commands/commands/bookmark_4.py b/src/fenrir/commands/commands/bookmark_4.py index 7386f99..09543ea 100644 --- a/src/fenrir/commands/commands/bookmark_4.py +++ b/src/fenrir/commands/commands/bookmark_4.py @@ -16,18 +16,18 @@ def shutdown(self): pass def getDescription(self): - return 'read Bookmark ' + self.ID + return _('read Bookmark {0}').format(self.ID,) def run(self): currApp = self.env['runtime']['applicationManager'].getCurrentApplication() if not self.env['commandBuffer']['bookMarks'][self.ID]: - self.env['runtime']['outputManager'].presentText("Bookmark " + self.ID + "not set", interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set').format(self.ID,), interrupt=True) return if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]: - self.env['runtime']['outputManager'].presentText("Bookmark for application " + currApp + " not set", interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) return if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1']: - self.env['runtime']['outputManager'].presentText("Bookmark for application " + currApp + " not set", interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) return # set marks @@ -35,12 +35,12 @@ startMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'].copy() if self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2']: endMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'].copy() - marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screenData']['newContentText']) + marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText']) else: x, y, marked = \ - line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screenData']['newContentText']) + line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screen']['newContentText']) if marked.isspace(): - self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('blank'), soundIcon='EmptyLine', interrupt=True) else: self.env['runtime']['outputManager'].presentText(marked, interrupt=True) diff --git a/src/fenrir/commands/commands/bookmark_5.py b/src/fenrir/commands/commands/bookmark_5.py index 9250b05..4df87ac 100644 --- a/src/fenrir/commands/commands/bookmark_5.py +++ b/src/fenrir/commands/commands/bookmark_5.py @@ -16,18 +16,18 @@ def shutdown(self): pass def getDescription(self): - return 'read Bookmark ' + self.ID + return _('read Bookmark {0}').format(self.ID,) def run(self): currApp = self.env['runtime']['applicationManager'].getCurrentApplication() if not self.env['commandBuffer']['bookMarks'][self.ID]: - self.env['runtime']['outputManager'].presentText("Bookmark " + self.ID + "not set", interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set').format(self.ID,), interrupt=True) return if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]: - self.env['runtime']['outputManager'].presentText("Bookmark for application " + currApp + " not set", interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) return if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1']: - self.env['runtime']['outputManager'].presentText("Bookmark for application " + currApp + " not set", interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) return # set marks @@ -35,12 +35,12 @@ startMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'].copy() if self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2']: endMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'].copy() - marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screenData']['newContentText']) + marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText']) else: x, y, marked = \ - line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screenData']['newContentText']) + line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screen']['newContentText']) if marked.isspace(): - self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('blank'), soundIcon='EmptyLine', interrupt=True) else: self.env['runtime']['outputManager'].presentText(marked, interrupt=True) diff --git a/src/fenrir/commands/commands/bookmark_6.py b/src/fenrir/commands/commands/bookmark_6.py index 0749587..0073e40 100644 --- a/src/fenrir/commands/commands/bookmark_6.py +++ b/src/fenrir/commands/commands/bookmark_6.py @@ -16,18 +16,18 @@ def shutdown(self): pass def getDescription(self): - return 'read Bookmark ' + self.ID + return _('read Bookmark {0}').format(self.ID,) def run(self): currApp = self.env['runtime']['applicationManager'].getCurrentApplication() if not self.env['commandBuffer']['bookMarks'][self.ID]: - self.env['runtime']['outputManager'].presentText("Bookmark " + self.ID + "not set", interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set').format(self.ID,), interrupt=True) return if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]: - self.env['runtime']['outputManager'].presentText("Bookmark for application " + currApp + " not set", interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) return if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1']: - self.env['runtime']['outputManager'].presentText("Bookmark for application " + currApp + " not set", interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) return # set marks @@ -35,12 +35,12 @@ startMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'].copy() if self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2']: endMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'].copy() - marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screenData']['newContentText']) + marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText']) else: x, y, marked = \ - line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screenData']['newContentText']) + line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screen']['newContentText']) if marked.isspace(): - self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('blank'), soundIcon='EmptyLine', interrupt=True) else: self.env['runtime']['outputManager'].presentText(marked, interrupt=True) diff --git a/src/fenrir/commands/commands/bookmark_7.py b/src/fenrir/commands/commands/bookmark_7.py index e680dbd..8275698 100644 --- a/src/fenrir/commands/commands/bookmark_7.py +++ b/src/fenrir/commands/commands/bookmark_7.py @@ -16,18 +16,18 @@ def shutdown(self): pass def getDescription(self): - return 'read Bookmark ' + self.ID + return _('read Bookmark {0}').format(self.ID,) def run(self): currApp = self.env['runtime']['applicationManager'].getCurrentApplication() if not self.env['commandBuffer']['bookMarks'][self.ID]: - self.env['runtime']['outputManager'].presentText("Bookmark " + self.ID + "not set", interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set').format(self.ID,), interrupt=True) return if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]: - self.env['runtime']['outputManager'].presentText("Bookmark for application " + currApp + " not set", interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) return if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1']: - self.env['runtime']['outputManager'].presentText("Bookmark for application " + currApp + " not set", interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) return # set marks @@ -35,12 +35,12 @@ startMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'].copy() if self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2']: endMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'].copy() - marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screenData']['newContentText']) + marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText']) else: x, y, marked = \ - line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screenData']['newContentText']) + line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screen']['newContentText']) if marked.isspace(): - self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('blank'), soundIcon='EmptyLine', interrupt=True) else: self.env['runtime']['outputManager'].presentText(marked, interrupt=True) diff --git a/src/fenrir/commands/commands/bookmark_8.py b/src/fenrir/commands/commands/bookmark_8.py index d540c75..6a5f2e4 100644 --- a/src/fenrir/commands/commands/bookmark_8.py +++ b/src/fenrir/commands/commands/bookmark_8.py @@ -16,18 +16,18 @@ def shutdown(self): pass def getDescription(self): - return 'read Bookmark ' + self.ID + return _('read Bookmark {0}').format(self.ID,) def run(self): currApp = self.env['runtime']['applicationManager'].getCurrentApplication() if not self.env['commandBuffer']['bookMarks'][self.ID]: - self.env['runtime']['outputManager'].presentText("Bookmark " + self.ID + "not set", interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set').format(self.ID,), interrupt=True) return if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]: - self.env['runtime']['outputManager'].presentText("Bookmark for application " + currApp + " not set", interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) return if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1']: - self.env['runtime']['outputManager'].presentText("Bookmark for application " + currApp + " not set", interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) return # set marks @@ -35,12 +35,12 @@ startMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'].copy() if self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2']: endMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'].copy() - marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screenData']['newContentText']) + marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText']) else: x, y, marked = \ - line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screenData']['newContentText']) + line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screen']['newContentText']) if marked.isspace(): - self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('blank'), soundIcon='EmptyLine', interrupt=True) else: self.env['runtime']['outputManager'].presentText(marked, interrupt=True) diff --git a/src/fenrir/commands/commands/bookmark_9.py b/src/fenrir/commands/commands/bookmark_9.py index a6f5338..a86fcd1 100644 --- a/src/fenrir/commands/commands/bookmark_9.py +++ b/src/fenrir/commands/commands/bookmark_9.py @@ -16,18 +16,18 @@ def shutdown(self): pass def getDescription(self): - return 'read Bookmark ' + self.ID + return _('read Bookmark {0}').format(self.ID,) def run(self): currApp = self.env['runtime']['applicationManager'].getCurrentApplication() if not self.env['commandBuffer']['bookMarks'][self.ID]: - self.env['runtime']['outputManager'].presentText("Bookmark " + self.ID + "not set", interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} not set').format(self.ID,), interrupt=True) return if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]: - self.env['runtime']['outputManager'].presentText("Bookmark for application " + currApp + " not set", interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) return if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1']: - self.env['runtime']['outputManager'].presentText("Bookmark for application " + currApp + " not set", interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark for application {0} not set').format(currApp,), interrupt=True) return # set marks @@ -35,12 +35,12 @@ startMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'].copy() if self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2']: endMark = self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'].copy() - marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screenData']['newContentText']) + marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText']) else: x, y, marked = \ - line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screenData']['newContentText']) + line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screen']['newContentText']) if marked.isspace(): - self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('blank'), soundIcon='EmptyLine', interrupt=True) else: self.env['runtime']['outputManager'].presentText(marked, interrupt=True) diff --git a/src/fenrir/commands/commands/braille_flush.py b/src/fenrir/commands/commands/braille_flush.py new file mode 100644 index 0000000..3c0ece3 --- /dev/null +++ b/src/fenrir/commands/commands/braille_flush.py @@ -0,0 +1,21 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('flush the braille device if a message is written on') + def run(self): + self.env['runtime']['outputManager'].clearFlushTime() + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/braille_pan_left.py b/src/fenrir/commands/commands/braille_pan_left.py new file mode 100644 index 0000000..284dacc --- /dev/null +++ b/src/fenrir/commands/commands/braille_pan_left.py @@ -0,0 +1,21 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from 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 diff --git a/src/fenrir/commands/commands/braille_pan_right.py b/src/fenrir/commands/commands/braille_pan_right.py new file mode 100644 index 0000000..c0272fb --- /dev/null +++ b/src/fenrir/commands/commands/braille_pan_right.py @@ -0,0 +1,21 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from 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 diff --git a/src/fenrir/commands/commands/braille_return_to_cursor.py b/src/fenrir/commands/commands/braille_return_to_cursor.py new file mode 100644 index 0000000..01cecbb --- /dev/null +++ b/src/fenrir/commands/commands/braille_return_to_cursor.py @@ -0,0 +1,21 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from 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 diff --git a/src/fenrir/commands/commands/clear_bookmark_1.py b/src/fenrir/commands/commands/clear_bookmark_1.py index 686b7ff..d543a97 100644 --- a/src/fenrir/commands/commands/clear_bookmark_1.py +++ b/src/fenrir/commands/commands/clear_bookmark_1.py @@ -14,14 +14,14 @@ def shutdown(self): pass def getDescription(self): - return 'remove Bookmark ' + self.ID + return _('remove Bookmark {0}').format(self.ID,) def run(self): currApp = self.env['runtime']['applicationManager'].getCurrentApplication() del self.env['commandBuffer']['bookMarks'][self.ID][currApp] - self.env['runtime']['outputManager'].presentText('Bookmark ' + self.ID + " removed for application " + currApp, interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} removed for application {1}').format(self.ID, currApp), interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/clear_bookmark_10.py b/src/fenrir/commands/commands/clear_bookmark_10.py index 335a73b..5e77a22 100644 --- a/src/fenrir/commands/commands/clear_bookmark_10.py +++ b/src/fenrir/commands/commands/clear_bookmark_10.py @@ -14,14 +14,14 @@ def shutdown(self): pass def getDescription(self): - return 'remove Bookmark ' + self.ID + return _('remove Bookmark {0}').format(self.ID,) def run(self): currApp = self.env['runtime']['applicationManager'].getCurrentApplication() - + del self.env['commandBuffer']['bookMarks'][self.ID][currApp] - self.env['runtime']['outputManager'].presentText('Bookmark ' + self.ID + " removed for application " + currApp, interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} removed for application {1}').format(self.ID, currApp), interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/clear_bookmark_2.py b/src/fenrir/commands/commands/clear_bookmark_2.py index 3f6f713..baa3dae 100644 --- a/src/fenrir/commands/commands/clear_bookmark_2.py +++ b/src/fenrir/commands/commands/clear_bookmark_2.py @@ -14,14 +14,14 @@ def shutdown(self): pass def getDescription(self): - return 'remove Bookmark ' + self.ID + return _('remove Bookmark {0}').format(self.ID,) def run(self): currApp = self.env['runtime']['applicationManager'].getCurrentApplication() - + del self.env['commandBuffer']['bookMarks'][self.ID][currApp] - self.env['runtime']['outputManager'].presentText('Bookmark ' + self.ID + " removed for application " + currApp, interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} removed for application {1}').format(self.ID, currApp), interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/clear_bookmark_3.py b/src/fenrir/commands/commands/clear_bookmark_3.py index 22471fa..924ed7d 100644 --- a/src/fenrir/commands/commands/clear_bookmark_3.py +++ b/src/fenrir/commands/commands/clear_bookmark_3.py @@ -14,14 +14,14 @@ def shutdown(self): pass def getDescription(self): - return 'remove Bookmark ' + self.ID + return _('remove Bookmark {0}').format(self.ID,) def run(self): currApp = self.env['runtime']['applicationManager'].getCurrentApplication() - + del self.env['commandBuffer']['bookMarks'][self.ID][currApp] - self.env['runtime']['outputManager'].presentText('Bookmark ' + self.ID + " removed for application " + currApp, interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} removed for application {1}').format(self.ID, currApp), interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/clear_bookmark_4.py b/src/fenrir/commands/commands/clear_bookmark_4.py index 3d440a3..781d8aa 100644 --- a/src/fenrir/commands/commands/clear_bookmark_4.py +++ b/src/fenrir/commands/commands/clear_bookmark_4.py @@ -14,14 +14,14 @@ def shutdown(self): pass def getDescription(self): - return 'remove Bookmark ' + self.ID + return _('remove Bookmark {0}').format(self.ID,) def run(self): currApp = self.env['runtime']['applicationManager'].getCurrentApplication() - + del self.env['commandBuffer']['bookMarks'][self.ID][currApp] - self.env['runtime']['outputManager'].presentText('Bookmark ' + self.ID + " removed for application " + currApp, interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} removed for application {1}').format(self.ID, currApp), interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/clear_bookmark_5.py b/src/fenrir/commands/commands/clear_bookmark_5.py index 17d275b..54a0692 100644 --- a/src/fenrir/commands/commands/clear_bookmark_5.py +++ b/src/fenrir/commands/commands/clear_bookmark_5.py @@ -14,14 +14,14 @@ def shutdown(self): pass def getDescription(self): - return 'remove Bookmark ' + self.ID + return _('remove Bookmark {0}').format(self.ID,) def run(self): currApp = self.env['runtime']['applicationManager'].getCurrentApplication() - + del self.env['commandBuffer']['bookMarks'][self.ID][currApp] - self.env['runtime']['outputManager'].presentText('Bookmark ' + self.ID + " removed for application " + currApp, interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} removed for application {1}').format(self.ID, currApp), interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/clear_bookmark_6.py b/src/fenrir/commands/commands/clear_bookmark_6.py index d7906f0..a79267f 100644 --- a/src/fenrir/commands/commands/clear_bookmark_6.py +++ b/src/fenrir/commands/commands/clear_bookmark_6.py @@ -14,14 +14,14 @@ def shutdown(self): pass def getDescription(self): - return 'remove Bookmark ' + self.ID + return _('remove Bookmark {0}').format(self.ID,) def run(self): currApp = self.env['runtime']['applicationManager'].getCurrentApplication() - + del self.env['commandBuffer']['bookMarks'][self.ID][currApp] - self.env['runtime']['outputManager'].presentText('Bookmark ' + self.ID + " removed for application " + currApp, interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} removed for application {1}').format(self.ID, currApp), interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/clear_bookmark_7.py b/src/fenrir/commands/commands/clear_bookmark_7.py index 3a46a11..39cb143 100644 --- a/src/fenrir/commands/commands/clear_bookmark_7.py +++ b/src/fenrir/commands/commands/clear_bookmark_7.py @@ -14,14 +14,14 @@ def shutdown(self): pass def getDescription(self): - return 'remove Bookmark ' + self.ID + return _('remove Bookmark {0}').format(self.ID,) def run(self): currApp = self.env['runtime']['applicationManager'].getCurrentApplication() - + del self.env['commandBuffer']['bookMarks'][self.ID][currApp] - self.env['runtime']['outputManager'].presentText('Bookmark ' + self.ID + " removed for application " + currApp, interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} removed for application {1}').format(self.ID, currApp), interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/clear_bookmark_8.py b/src/fenrir/commands/commands/clear_bookmark_8.py index f9ce2a3..b5e2241 100644 --- a/src/fenrir/commands/commands/clear_bookmark_8.py +++ b/src/fenrir/commands/commands/clear_bookmark_8.py @@ -14,14 +14,14 @@ def shutdown(self): pass def getDescription(self): - return 'remove Bookmark ' + self.ID + return _('remove Bookmark {0}').format(self.ID,) def run(self): currApp = self.env['runtime']['applicationManager'].getCurrentApplication() - + del self.env['commandBuffer']['bookMarks'][self.ID][currApp] - self.env['runtime']['outputManager'].presentText('Bookmark ' + self.ID + " removed for application " + currApp, interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} removed for application {1}').format(self.ID, currApp), interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/clear_bookmark_9.py b/src/fenrir/commands/commands/clear_bookmark_9.py index 79e47f3..a9fd30a 100644 --- a/src/fenrir/commands/commands/clear_bookmark_9.py +++ b/src/fenrir/commands/commands/clear_bookmark_9.py @@ -14,14 +14,14 @@ def shutdown(self): pass def getDescription(self): - return 'remove Bookmark ' + self.ID + return _('remove Bookmark {0}').format(self.ID,) def run(self): currApp = self.env['runtime']['applicationManager'].getCurrentApplication() - + del self.env['commandBuffer']['bookMarks'][self.ID][currApp] - self.env['runtime']['outputManager'].presentText('Bookmark ' + self.ID + " removed for application " + currApp, interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} removed for application {1}').format(self.ID, currApp), interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/clear_clipboard.py b/src/fenrir/commands/commands/clear_clipboard.py index 8e82bfb..3abe125 100644 --- a/src/fenrir/commands/commands/clear_clipboard.py +++ b/src/fenrir/commands/commands/clear_clipboard.py @@ -14,12 +14,12 @@ def shutdown(self): pass def getDescription(self): - return 'clears the currently selected clipboard' + return _('clears the currently selected clipboard') def run(self): self.env['commandBuffer']['currClipboard'] = -1 del self.env['commandBuffer']['clipboard'][:] - self.env['runtime']['outputManager'].presentText('clipboard cleared', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('clipboard cleared'), interrupt=True) return def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/clear_window_application.py b/src/fenrir/commands/commands/clear_window_application.py index 81d1707..11af304 100644 --- a/src/fenrir/commands/commands/clear_window_application.py +++ b/src/fenrir/commands/commands/clear_window_application.py @@ -14,14 +14,14 @@ def shutdown(self): pass def getDescription(self): - return 'Turn off window mode for application' + return _('Turn off window mode for application') def run(self): if self.env['runtime']['cursorManager'].clearWindowForApplication(): currApp = self.env['runtime']['applicationManager'].getCurrentApplication() - self.env['runtime']['outputManager'].presentText('Window Mode off for application ' + currApp, interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Window Mode off for application {0}').format(currApp,), interrupt=True) else: - self.env['runtime']['outputManager'].presentText("Not in window Mode", interrupt=True) + self.env['runtime']['outputManager'].presentText(_("Not in window Mode"), interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/copy_marked_to_clipboard.py b/src/fenrir/commands/commands/copy_marked_to_clipboard.py index 36d96d3..2a06bbf 100644 --- a/src/fenrir/commands/commands/copy_marked_to_clipboard.py +++ b/src/fenrir/commands/commands/copy_marked_to_clipboard.py @@ -15,11 +15,11 @@ def shutdown(self): pass def getDescription(self): - return 'copies marked text to the currently selected clipboard' + return _('copies marked text to the currently selected clipboard') def run(self): if not self.env['commandBuffer']['Marks']['1']: - self.env['runtime']['outputManager'].presentText("one or two marks needed", interrupt=True) + self.env['runtime']['outputManager'].presentText(_("one or two marks needed"), interrupt=True) return if not self.env['commandBuffer']['Marks']['2']: self.env['runtime']['cursorManager'].setMark() @@ -28,7 +28,7 @@ startMark = self.env['commandBuffer']['Marks']['1'].copy() endMark = self.env['commandBuffer']['Marks']['2'].copy() - marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screenData']['newContentText']) + marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText']) self.env['commandBuffer']['clipboard'] = [marked] + self.env['commandBuffer']['clipboard'][:self.env['runtime']['settingsManager'].getSettingAsInt('general', 'numberOfClipboards') -1] self.env['commandBuffer']['currClipboard'] = 0 diff --git a/src/fenrir/commands/commands/curr_clipboard.py b/src/fenrir/commands/commands/curr_clipboard.py index d47caec..2adfbed 100644 --- a/src/fenrir/commands/commands/curr_clipboard.py +++ b/src/fenrir/commands/commands/curr_clipboard.py @@ -14,11 +14,11 @@ def shutdown(self): pass def getDescription(self): - return 'speaks the contents of the currently selected clipboard' + return _('speaks the contents of the currently selected clipboard') def run(self): if len(self.env['commandBuffer']['clipboard']) == 0: - self.env['runtime']['outputManager'].presentText('clipboard empty', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) return self.env['runtime']['outputManager'].presentText(self.env['commandBuffer']['clipboard'][self.env['commandBuffer']['currClipboard']], interrupt=True) diff --git a/src/fenrir/commands/commands/curr_screen.py b/src/fenrir/commands/commands/curr_screen.py index 8a1d42b..2de3973 100644 --- a/src/fenrir/commands/commands/curr_screen.py +++ b/src/fenrir/commands/commands/curr_screen.py @@ -14,13 +14,13 @@ def shutdown(self): pass def getDescription(self): - return 'reads the contents of the current screen' + return _('reads the contents of the current screen') def run(self): - if self.env['screenData']['newContentText'].isspace(): - self.env['runtime']['outputManager'].presentText("screen is empty", soundIcon='EmptyLine', interrupt=True) + if self.env['screen']['newContentText'].isspace(): + self.env['runtime']['outputManager'].presentText(_("screen is empty"), soundIcon='EmptyLine', interrupt=True) else: - self.env['runtime']['outputManager'].presentText(self.env['screenData']['newContentText'],interrupt=True) + self.env['runtime']['outputManager'].presentText(self.env['screen']['newContentText'],interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/curr_screen_after_cursor.py b/src/fenrir/commands/commands/curr_screen_after_cursor.py index 7b33dff..1e059cc 100644 --- a/src/fenrir/commands/commands/curr_screen_after_cursor.py +++ b/src/fenrir/commands/commands/curr_screen_after_cursor.py @@ -15,16 +15,16 @@ def shutdown(self): pass def getDescription(self): - return 'reads from the cursor to the bottom of the screen' + return _('reads from the cursor to the bottom of the screen') def run(self): # Prefer review cursor over text cursor cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() - textAfterCursor = mark_utils.getTextAfterMark(cursorPos, self.env['screenData']['newContentText']) + textAfterCursor = mark_utils.getTextAfterMark(cursorPos, self.env['screen']['newContentText']) if textAfterCursor.isspace(): - self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True) else: self.env['runtime']['outputManager'].presentText(textAfterCursor, interrupt=True) diff --git a/src/fenrir/commands/commands/curr_screen_before_cursor.py b/src/fenrir/commands/commands/curr_screen_before_cursor.py index e936741..8fd0a85 100644 --- a/src/fenrir/commands/commands/curr_screen_before_cursor.py +++ b/src/fenrir/commands/commands/curr_screen_before_cursor.py @@ -15,19 +15,19 @@ def shutdown(self): pass def getDescription(self): - return 'Reads from the top of the screen to the cursor position' + return _('Reads from the top of the screen to the cursor position') def run(self): # Prefer review cursor over text cursor - if self.env['screenData']['newCursorReview']: - cursorPos = self.env['screenData']['newCursorReview'].copy() + if self.env['screen']['newCursorReview']: + cursorPos = self.env['screen']['newCursorReview'].copy() else: - cursorPos = self.env['screenData']['newCursor'].copy() + cursorPos = self.env['screen']['newCursor'].copy() - textBeforeCursor = mark_utils.getTextBeforeMark(cursorPos, self.env['screenData']['newContentText']) + textBeforeCursor = mark_utils.getTextBeforeMark(cursorPos, self.env['screen']['newContentText']) if textBeforeCursor.isspace(): - self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True) else: self.env['runtime']['outputManager'].presentText(textBeforeCursor, interrupt=True) diff --git a/src/fenrir/commands/commands/cursor_column.py b/src/fenrir/commands/commands/cursor_column.py index 0436545..d3c119a 100644 --- a/src/fenrir/commands/commands/cursor_column.py +++ b/src/fenrir/commands/commands/cursor_column.py @@ -14,7 +14,7 @@ def shutdown(self): pass def getDescription(self): - return 'presents the current column number for review cursor in review mode or the text cursor if not. Starts with 1' + return _('presents the current column number for review cursor in review mode or the text cursor if not. Starts with 1') def run(self): cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() self.env['runtime']['outputManager'].presentText(str(cursorPos['x'] + 1) , interrupt=True) diff --git a/src/fenrir/commands/commands/cursor_lineno.py b/src/fenrir/commands/commands/cursor_lineno.py index 2d76639..a8b39ce 100644 --- a/src/fenrir/commands/commands/cursor_lineno.py +++ b/src/fenrir/commands/commands/cursor_lineno.py @@ -14,7 +14,7 @@ def shutdown(self): pass def getDescription(self): - return 'presents the current line number for review cursor in review mode or the text cursor if not. Starts with 1' + return _('presents the current line number for review cursor in review mode or the text cursor if not. Starts with 1') def run(self): cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() self.env['runtime']['outputManager'].presentText(str(cursorPos['y'] + 1), interrupt=True) diff --git a/src/fenrir/commands/commands/cursor_position.py b/src/fenrir/commands/commands/cursor_position.py index 9acc912..99b13fa 100644 --- a/src/fenrir/commands/commands/cursor_position.py +++ b/src/fenrir/commands/commands/cursor_position.py @@ -14,13 +14,13 @@ def shutdown(self): pass def getDescription(self): - return 'displays the position of the review cursor' + return _('displays the position of the review cursor') def run(self): # Prefer review cursor over text cursor cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() - self.env['runtime']['outputManager'].presentText("line "+ str(cursorPos['y']+1) + " column "+ str(cursorPos['x']+1), interrupt=True) + self.env['runtime']['outputManager'].presentText(_("line {0}, column {1}").format(cursorPos['y']+1, cursorPos['x']+1), interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/cursor_read_to_end_of_line.py b/src/fenrir/commands/commands/cursor_read_to_end_of_line.py index ba4c2eb..93e8a8a 100644 --- a/src/fenrir/commands/commands/cursor_read_to_end_of_line.py +++ b/src/fenrir/commands/commands/cursor_read_to_end_of_line.py @@ -15,16 +15,16 @@ def shutdown(self): pass def getDescription(self): - return 'read to end of line, use review cursor if you are in reviewmode, otherwhise use text cursor' + return _('read to end of line, 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['screenData']['newContentText']) + line_utils.getCurrentLine(cursorPos['x'], cursorPos['y'], self.env['screen']['newContentText']) if currLine.isspace(): - self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + 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() diff --git a/src/fenrir/commands/commands/date.py b/src/fenrir/commands/commands/date.py index cbf3a38..39fc28e 100644 --- a/src/fenrir/commands/commands/date.py +++ b/src/fenrir/commands/commands/date.py @@ -15,7 +15,7 @@ def shutdown(self): pass def getDescription(self): - return 'presents the date' + return _('presents the date') def run(self): dateFormat = self.env['runtime']['settingsManager'].getSetting('general', 'dateFormat') diff --git a/src/fenrir/commands/commands/dec_alsa_volume.py b/src/fenrir/commands/commands/dec_alsa_volume.py new file mode 100644 index 0000000..cd2aee0 --- /dev/null +++ b/src/fenrir/commands/commands/dec_alsa_volume.py @@ -0,0 +1,39 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +initialized = False +try: + import alsaaudio + initialized = True +except: + pass + +from core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _("Decrease system volume") + + def run(self): + if not initialized: + self.env['runtime']['outputManager'].presentText(_('alsaaudio is not installed'), interrupt=True) + return + mixer = alsaaudio.Mixer() + value = mixer.getvolume()[0] + value = value - 5 + if value < 5: + value = 5 + mixer.setvolume(value) + self.env['runtime']['outputManager'].presentText(_("{0} percent system volume").format(value), interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/dec_sound_volume.py b/src/fenrir/commands/commands/dec_sound_volume.py index 1cf1a64..c97414c 100644 --- a/src/fenrir/commands/commands/dec_sound_volume.py +++ b/src/fenrir/commands/commands/dec_sound_volume.py @@ -15,7 +15,7 @@ def shutdown(self): pass def getDescription(self): - return 'decrease sound volume' + return _('decrease sound volume') def run(self): @@ -26,7 +26,7 @@ value = 0.1 self.env['runtime']['settingsManager'].setSetting('sound', 'volume', str(value)) - self.env['runtime']['outputManager'].presentText(str(int(value * 100)) + " percent sound volume", soundIcon='SoundOff', interrupt=True) + self.env['runtime']['outputManager'].presentText(_("{0} percent sound volume").format(int(value * 100)), soundIcon='SoundOff', interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/dec_speech_pitch.py b/src/fenrir/commands/commands/dec_speech_pitch.py index fa818db..09e53b7 100644 --- a/src/fenrir/commands/commands/dec_speech_pitch.py +++ b/src/fenrir/commands/commands/dec_speech_pitch.py @@ -15,7 +15,7 @@ def shutdown(self): pass def getDescription(self): - return 'decreases the pitch of the speech' + return _('decreases the pitch of the speech') def run(self): value = self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'pitch') @@ -23,8 +23,7 @@ if value < 0.0: value = 0.0 self.env['runtime']['settingsManager'].setSetting('speech', 'pitch', str(value)) - - self.env['runtime']['outputManager'].presentText(str(int(value * 100)) + " percent speech pitch", soundIcon='', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('{0} percent speech pitch').format(int(value * 100)), soundIcon='', interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/dec_speech_rate.py b/src/fenrir/commands/commands/dec_speech_rate.py index 244ba9b..a024866 100644 --- a/src/fenrir/commands/commands/dec_speech_rate.py +++ b/src/fenrir/commands/commands/dec_speech_rate.py @@ -15,7 +15,7 @@ def shutdown(self): pass def getDescription(self): - return 'decreases the rate of the speech' + return _('decreases the rate of the speech') def run(self): value = self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'rate') @@ -24,7 +24,7 @@ value = 0.0 self.env['runtime']['settingsManager'].setSetting('speech', 'rate', str(value)) - self.env['runtime']['outputManager'].presentText(str(int(value * 100)) + " percent speech rate", soundIcon='', interrupt=True) + self.env['runtime']['outputManager'].presentText(_("{0} percent speech rate").format(int(value * 100)), soundIcon='', interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/dec_speech_volume.py b/src/fenrir/commands/commands/dec_speech_volume.py index 6ad5ba0..946803c 100644 --- a/src/fenrir/commands/commands/dec_speech_volume.py +++ b/src/fenrir/commands/commands/dec_speech_volume.py @@ -15,7 +15,7 @@ def shutdown(self): pass def getDescription(self): - return 'decreases the volume of the speech' + return _('decreases the volume of the speech') def run(self): value = self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'volume') @@ -24,7 +24,7 @@ value = 0.1 self.env['runtime']['settingsManager'].setSetting('speech', 'volume', str(value)) - self.env['runtime']['outputManager'].presentText(str(int(value * 100)) + " percent speech volume", soundIcon='', interrupt=True) + self.env['runtime']['outputManager'].presentText(_("{0} percent speech volume").format(int(value * 100)), soundIcon='', interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/exit_review.py b/src/fenrir/commands/commands/exit_review.py index 6e9c72c..9c0369c 100644 --- a/src/fenrir/commands/commands/exit_review.py +++ b/src/fenrir/commands/commands/exit_review.py @@ -14,15 +14,15 @@ def shutdown(self): pass def getDescription(self): - return 'exits review mode' + return _('exits review mode') def run(self): if not self.env['runtime']['cursorManager'].isReviewMode(): - self.env['runtime']['outputManager'].presentText("Not in review mode", interrupt=True) + self.env['runtime']['outputManager'].presentText(_("Not in review mode"), interrupt=True) return self.env['runtime']['cursorManager'].clearReviewCursor() - self.env['runtime']['outputManager'].presentText("leve review mode", interrupt=True) + self.env['runtime']['outputManager'].presentText(_("leave review mode"), interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/export_clipboard_to_file.py b/src/fenrir/commands/commands/export_clipboard_to_file.py new file mode 100644 index 0000000..acaa6c9 --- /dev/null +++ b/src/fenrir/commands/commands/export_clipboard_to_file.py @@ -0,0 +1,48 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +import os + +class command(): + def __init__(self): + pass + def initialize(self, environment, scriptPath=''): + self.env = environment + + def shutdown(self): + pass + def getDescription(self): + return _('export the current fenrir clipboard to a file') + def run(self): + clipboardFilePath = self.env['runtime']['settingsManager'].getSetting('general', 'clipboardExportPath') + clipboardFilePath = clipboardFilePath.replace('$user',self.env['general']['currUser']) + clipboardFilePath = clipboardFilePath.replace('$USER',self.env['general']['currUser']) + clipboardFilePath = clipboardFilePath.replace('$User',self.env['general']['currUser']) + clipboardFile = open(clipboardFilePath,'w') + try: + currClipboard = self.env['commandBuffer']['currClipboard'] + if currClipboard < 0: + self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) + return + if not self.env['commandBuffer']['clipboard']: + self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) + return + if not self.env['commandBuffer']['clipboard'][currClipboard]: + self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) + return + if self.env['commandBuffer']['clipboard'][currClipboard] == '': + self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) + return + clipboardFile.write(self.env['commandBuffer']['clipboard'][currClipboard]) + clipboardFile.close() + os.chmod(clipboardFilePath, 0o666) + self.env['runtime']['outputManager'].presentText(_('clipboard exported to file'), interrupt=True) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('export_clipboard_to_file:run: Filepath:'+ clipboardFile +' trace:' + str(e),debug.debugLevel.ERROR) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/export_clipboard_to_x.py b/src/fenrir/commands/commands/export_clipboard_to_x.py new file mode 100644 index 0000000..8c11945 --- /dev/null +++ b/src/fenrir/commands/commands/export_clipboard_to_x.py @@ -0,0 +1,60 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +import subprocess, os +from subprocess import Popen, PIPE +import _thread + +class command(): + def __init__(self): + pass + def initialize(self, environment, scriptPath=''): + self.env = environment + self.scriptPath = scriptPath + def shutdown(self): + pass + def getDescription(self): + return _('export the current fenrir clipboard to X clipboard') + def run(self): + _thread.start_new_thread(self._threadRun , ()) + + def _threadRun(self): + try: + currClipboard = self.env['commandBuffer']['currClipboard'] + + if currClipboard < 0: + self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) + return + if not self.env['commandBuffer']['clipboard']: + self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) + return + if not self.env['commandBuffer']['clipboard'][currClipboard]: + self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) + return + if self.env['commandBuffer']['clipboard'][currClipboard] == '': + self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) + return + for display in range(10): + p = Popen('su ' + self.env['general']['currUser'] + ' -c "echo -n \\\"' + self.env['commandBuffer']['clipboard'][currClipboard].replace('"','\\\\\\"') +'\\\" | xclip -d :' + str(display) + ' -selection c"' , stdout=PIPE, stderr=PIPE, shell=True) + stdout, stderr = p.communicate() + 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 == ''): + 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) + 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) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/first_clipboard.py b/src/fenrir/commands/commands/first_clipboard.py index c6cee34..152f65e 100644 --- a/src/fenrir/commands/commands/first_clipboard.py +++ b/src/fenrir/commands/commands/first_clipboard.py @@ -14,11 +14,11 @@ def shutdown(self): pass def getDescription(self): - return 'selects the first clipboard' + return _('selects the first clipboard') def run(self): if len(self.env['commandBuffer']['clipboard']) == 0: - self.env['runtime']['outputManager'].presentText('clipboard empty', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) return self.env['commandBuffer']['currClipboard'] = 0 self.env['runtime']['outputManager'].presentText(self.env['commandBuffer']['clipboard'][self.env['commandBuffer']['currClipboard']], interrupt=True) diff --git a/src/fenrir/commands/commands/forward_keypress.py b/src/fenrir/commands/commands/forward_keypress.py index 6aed1d6..c3e718f 100644 --- a/src/fenrir/commands/commands/forward_keypress.py +++ b/src/fenrir/commands/commands/forward_keypress.py @@ -14,11 +14,11 @@ def shutdown(self): pass def getDescription(self): - return 'sends the following keypress to the terminal' + return _('sends the following keypress to the terminal') def run(self): self.env['input']['keyForeward'] = 3 - self.env['runtime']['outputManager'].presentText('Foreward next keypress', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Forward next keypress'), interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/import_clipboard_from_file.py b/src/fenrir/commands/commands/import_clipboard_from_file.py new file mode 100644 index 0000000..f9d6e2e --- /dev/null +++ b/src/fenrir/commands/commands/import_clipboard_from_file.py @@ -0,0 +1,40 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +from utils import mark_utils +import os + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('imports text from clipboard file to the clipboard') + + def run(self): + clipboardFilePath = self.env['runtime']['settingsManager'].getSetting('general', 'clipboardExportPath') + clipboardFilePath = clipboardFilePath.replace('$user',self.env['general']['currUser']) + clipboardFilePath = clipboardFilePath.replace('$USER',self.env['general']['currUser']) + clipboardFilePath = clipboardFilePath.replace('$User',self.env['general']['currUser']) + if not os.path.exists(clipboardFilePath): + self.env['runtime']['outputManager'].presentText(_('File does not exist'), soundIcon='', interrupt=True) + return + clipboardFile = open(clipboardFilePath,'r') + imported = clipboardFile.read() + clipboardFile.close() + self.env['commandBuffer']['clipboard'] = [imported] + self.env['commandBuffer']['clipboard'][:self.env['runtime']['settingsManager'].getSettingAsInt('general', 'numberOfClipboards') -1] + self.env['commandBuffer']['currClipboard'] = 0 + + self.env['runtime']['outputManager'].presentText('Import to Clipboard', soundIcon='CopyToClipboard', interrupt=True) + self.env['runtime']['outputManager'].presentText(imported, soundIcon='', interrupt=False) + + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/inc_alsa_volume.py b/src/fenrir/commands/commands/inc_alsa_volume.py new file mode 100644 index 0000000..51f38c7 --- /dev/null +++ b/src/fenrir/commands/commands/inc_alsa_volume.py @@ -0,0 +1,39 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +initialized = False +try: + import alsaaudio + initialized = True +except: + pass + +from core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _("Increase system volume") + + def run(self): + if not initialized: + self.env['runtime']['outputManager'].presentText(_('alsaaudio is not installed'), interrupt=True) + return + mixer = alsaaudio.Mixer() + value = mixer.getvolume()[0] + value = value + 5 + if value > 100: + value = 100 + mixer.setvolume(value) + self.env['runtime']['outputManager'].presentText(_("{0} percent system volume").format(value), interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/inc_sound_volume.py b/src/fenrir/commands/commands/inc_sound_volume.py index f3c3155..78eee84 100644 --- a/src/fenrir/commands/commands/inc_sound_volume.py +++ b/src/fenrir/commands/commands/inc_sound_volume.py @@ -15,7 +15,7 @@ def shutdown(self): pass def getDescription(self): - return 'adjusts the volume for in coming sounds' + return _('adjusts the volume for in coming sounds') def run(self): @@ -26,7 +26,7 @@ value = 1.0 self.env['runtime']['settingsManager'].setSetting('sound', 'volume', str(value)) - self.env['runtime']['outputManager'].presentText(str(int(value * 100)) + " percent sound volume", soundIcon='SoundOn', interrupt=True) + self.env['runtime']['outputManager'].presentText(_("{0} percent sound volume").format(int(value * 100)), soundIcon='SoundOn', interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/inc_speech_pitch.py b/src/fenrir/commands/commands/inc_speech_pitch.py index 3d99df9..cb267b6 100644 --- a/src/fenrir/commands/commands/inc_speech_pitch.py +++ b/src/fenrir/commands/commands/inc_speech_pitch.py @@ -15,7 +15,7 @@ def shutdown(self): pass def getDescription(self): - return 'increases the pitch of the speech' + return _('increases the pitch of the speech') def run(self): value = self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'pitch') @@ -24,7 +24,7 @@ value = 1.0 self.env['runtime']['settingsManager'].setSetting('speech', 'pitch', str(value)) - self.env['runtime']['outputManager'].presentText(str(int(value * 100)) + " percent speech pitch", soundIcon='', interrupt=True) + self.env['runtime']['outputManager'].presentText(_("{0} percent speech pitch").format(int(value * 100)), soundIcon='', interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/inc_speech_rate.py b/src/fenrir/commands/commands/inc_speech_rate.py index 3f20ae6..4db1763 100644 --- a/src/fenrir/commands/commands/inc_speech_rate.py +++ b/src/fenrir/commands/commands/inc_speech_rate.py @@ -15,7 +15,7 @@ def shutdown(self): pass def getDescription(self): - return 'increase the speech rate' + return _('increase the speech rate') def run(self): value = self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'rate') @@ -24,7 +24,7 @@ value = 1.0 self.env['runtime']['settingsManager'].setSetting('speech', 'rate', str(value)) - self.env['runtime']['outputManager'].presentText(str(int(value * 100)) + " percent speech rate", soundIcon='', interrupt=True) + self.env['runtime']['outputManager'].presentText(_("{0} percent speech rate").format(int(value * 100)), soundIcon='', interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/inc_speech_volume.py b/src/fenrir/commands/commands/inc_speech_volume.py index 1ea41d3..1c6716e 100644 --- a/src/fenrir/commands/commands/inc_speech_volume.py +++ b/src/fenrir/commands/commands/inc_speech_volume.py @@ -15,7 +15,7 @@ def shutdown(self): pass def getDescription(self): - return 'increase the speech volume' + return _('increase the speech volume') def run(self): value = self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'volume') @@ -24,7 +24,7 @@ value = 1.0 self.env['runtime']['settingsManager'].setSetting('speech', 'volume', str(value)) - self.env['runtime']['outputManager'].presentText(str(int(value * 100)) + " percent speech volume", soundIcon='', interrupt=True) + self.env['runtime']['outputManager'].presentText(_("{0} percent speech volume").format(int(value * 100)), soundIcon='', interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/indent_curr_line.py b/src/fenrir/commands/commands/indent_curr_line.py index 4cfe3bd..0990769 100644 --- a/src/fenrir/commands/commands/indent_curr_line.py +++ b/src/fenrir/commands/commands/indent_curr_line.py @@ -15,22 +15,22 @@ def shutdown(self): pass def getDescription(self): - return 'shows the indention level for the current line' + return _('shows the indention level for the current line') def run(self): # Prefer review cursor over text cursor - if self.env['screenData']['newCursorReview']: - cursorPos = self.env['screenData']['newCursorReview'].copy() + if self.env['screen']['newCursorReview']: + cursorPos = self.env['screen']['newCursorReview'].copy() else: - cursorPos = self.env['screenData']['newCursor'].copy() + cursorPos = self.env['screen']['newCursor'].copy() x, y, currLine = \ - line_utils.getCurrentLine(cursorPos['x'], cursorPos['y'], self.env['screenData']['newContentText']) + line_utils.getCurrentLine(cursorPos['x'], cursorPos['y'], self.env['screen']['newContentText']) if currLine.isspace(): - self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True) else: - self.env['runtime']['outputManager'].presentText("indent "+ str(len(currLine) - len(currLine.lstrip())), interrupt=True) + self.env['runtime']['outputManager'].presentText(_("indent {0}").format(len(currLine) - len(currLine.lstrip())), interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/last_clipboard.py b/src/fenrir/commands/commands/last_clipboard.py index cf08b29..2d8d2f5 100644 --- a/src/fenrir/commands/commands/last_clipboard.py +++ b/src/fenrir/commands/commands/last_clipboard.py @@ -14,11 +14,11 @@ def shutdown(self): pass def getDescription(self): - return 'selects the last clipboard' + return _('selects the last clipboard') def run(self): if len(self.env['commandBuffer']['clipboard']) == 0: - self.env['runtime']['outputManager'].presentText('clipboard empty', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) return self.env['commandBuffer']['currClipboard'] = len(self.env['commandBuffer']['clipboard']) -1 self.env['runtime']['outputManager'].presentText(self.env['commandBuffer']['clipboard'][self.env['commandBuffer']['currClipboard']], interrupt=True) diff --git a/src/fenrir/commands/commands/last_incoming.py b/src/fenrir/commands/commands/last_incoming.py index 84b2f46..effb7f3 100644 --- a/src/fenrir/commands/commands/last_incoming.py +++ b/src/fenrir/commands/commands/last_incoming.py @@ -14,10 +14,10 @@ def shutdown(self): pass def getDescription(self): - return 'displays the last received text' + return _('displays the last received text') def run(self): - self.env['runtime']['outputManager'].presentText(self.env['screenData']['newDelta'], interrupt=True) + self.env['runtime']['outputManager'].presentText(self.env['screen']['newDelta'], interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/marked_text.py b/src/fenrir/commands/commands/marked_text.py index 7e7bc32..9341382 100644 --- a/src/fenrir/commands/commands/marked_text.py +++ b/src/fenrir/commands/commands/marked_text.py @@ -15,22 +15,22 @@ def shutdown(self): pass def getDescription(self): - return 'speaks the currently selected text that will be copied to the clipboard' + return _('speaks the currently selected text that will be copied to the clipboard') def run(self): if not (self.env['commandBuffer']['Marks']['1'] and \ self.env['commandBuffer']['Marks']['2']): - self.env['runtime']['outputManager'].presentText("please set begin and endmark", interrupt=True) + self.env['runtime']['outputManager'].presentText(_("please set begin and endmark"), interrupt=True) return # use the last first and the last setted mark as range startMark = self.env['commandBuffer']['Marks']['1'].copy() endMark = self.env['commandBuffer']['Marks']['2'].copy() - marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screenData']['newContentText']) + marked = mark_utils.getTextBetweenMarks(startMark, endMark, self.env['screen']['newContentText']) if marked.isspace(): - self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True) else: self.env['runtime']['outputManager'].presentText(marked, interrupt=True) diff --git a/src/fenrir/commands/commands/next_clipboard.py b/src/fenrir/commands/commands/next_clipboard.py index 457bd9b..7e3d207 100644 --- a/src/fenrir/commands/commands/next_clipboard.py +++ b/src/fenrir/commands/commands/next_clipboard.py @@ -14,16 +14,16 @@ def shutdown(self): pass def getDescription(self): - return 'selects the next clipboard' + return _('selects the next clipboard') def run(self): if len(self.env['commandBuffer']['clipboard']) == 0: - self.env['runtime']['outputManager'].presentText('clipboard empty', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) return self.env['commandBuffer']['currClipboard'] += 1 if self.env['commandBuffer']['currClipboard'] > len(self.env['commandBuffer']['clipboard']) -1: self.env['commandBuffer']['currClipboard'] = 0 - self.env['runtime']['outputManager'].presentText('First clipboard ', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('First clipboard '), interrupt=True) self.env['runtime']['outputManager'].presentText(self.env['commandBuffer']['clipboard'][self.env['commandBuffer']['currClipboard']], interrupt=False) else: self.env['runtime']['outputManager'].presentText(self.env['commandBuffer']['clipboard'][self.env['commandBuffer']['currClipboard']], interrupt=True) diff --git a/src/fenrir/commands/commands/paste_clipboard.py b/src/fenrir/commands/commands/paste_clipboard.py index b987913..02a74cc 100644 --- a/src/fenrir/commands/commands/paste_clipboard.py +++ b/src/fenrir/commands/commands/paste_clipboard.py @@ -15,21 +15,21 @@ def shutdown(self): pass def getDescription(self): - return 'pastes the text from the currently selected clipboard' + return _('pastes the text from the currently selected clipboard') def run(self): currClipboard = self.env['commandBuffer']['currClipboard'] if currClipboard < 0: - self.env['runtime']['outputManager'].presentText('clipboard empty', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) return if not self.env['commandBuffer']['clipboard']: - self.env['runtime']['outputManager'].presentText('clipboard empty', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) return if not self.env['commandBuffer']['clipboard'][currClipboard]: - self.env['runtime']['outputManager'].presentText('clipboard empty', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) return if self.env['commandBuffer']['clipboard'][currClipboard] == '': - self.env['runtime']['outputManager'].presentText('clipboard empty', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) return self.env['runtime']['outputManager'].presentText('paste clipboard', soundIcon='PasteClipboardOnScreen', interrupt=True) time.sleep(0.01) diff --git a/src/fenrir/commands/commands/present_first_line.py b/src/fenrir/commands/commands/present_first_line.py index 4095417..9d54e87 100644 --- a/src/fenrir/commands/commands/present_first_line.py +++ b/src/fenrir/commands/commands/present_first_line.py @@ -15,14 +15,14 @@ def shutdown(self): pass def getDescription(self): - return 'present first line' + return _('present first line') def run(self): x, y, firstLine = \ - line_utils.getCurrentLine(0, 0, self.env['screenData']['newContentText']) + line_utils.getCurrentLine(0, 0, self.env['screen']['newContentText']) if firstLine.isspace(): - self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True) else: self.env['runtime']['outputManager'].presentText(firstLine, interrupt=True) def setCallback(self, callback): diff --git a/src/fenrir/commands/commands/present_last_line.py b/src/fenrir/commands/commands/present_last_line.py index f53af17..25316f4 100644 --- a/src/fenrir/commands/commands/present_last_line.py +++ b/src/fenrir/commands/commands/present_last_line.py @@ -15,14 +15,14 @@ def shutdown(self): pass def getDescription(self): - return 'current line' + return _('current line') def run(self): x, y, lastLine = \ - line_utils.getCurrentLine(0, self.env['screenData']['lines'] -1, self.env['screenData']['newContentText']) + line_utils.getCurrentLine(0, self.env['screen']['lines'] -1, self.env['screen']['newContentText']) if lastLine.isspace(): - self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True) else: self.env['runtime']['outputManager'].presentText(lastLine, interrupt=True) def setCallback(self, callback): diff --git a/src/fenrir/commands/commands/prev_clipboard.py b/src/fenrir/commands/commands/prev_clipboard.py index 8659d66..197d34e 100644 --- a/src/fenrir/commands/commands/prev_clipboard.py +++ b/src/fenrir/commands/commands/prev_clipboard.py @@ -14,16 +14,16 @@ def shutdown(self): pass def getDescription(self): - return 'selects the previous clipboard' + return _('selects the previous clipboard') def run(self): if len(self.env['commandBuffer']['clipboard']) == 0: - self.env['runtime']['outputManager'].presentText('clipboard empty', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('clipboard empty'), interrupt=True) return self.env['commandBuffer']['currClipboard'] -= 1 if self.env['commandBuffer']['currClipboard'] < 0: self.env['commandBuffer']['currClipboard'] = len(self.env['commandBuffer']['clipboard']) -1 - self.env['runtime']['outputManager'].presentText('Last clipboard ', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Last clipboard '), interrupt=True) self.env['runtime']['outputManager'].presentText(self.env['commandBuffer']['clipboard'][self.env['commandBuffer']['currClipboard']], interrupt=False) else: self.env['runtime']['outputManager'].presentText(self.env['commandBuffer']['clipboard'][self.env['commandBuffer']['currClipboard']], interrupt=True) diff --git a/src/fenrir/commands/commands/quit_fenrir.py b/src/fenrir/commands/commands/quit_fenrir.py index 0be6540..ea63365 100644 --- a/src/fenrir/commands/commands/quit_fenrir.py +++ b/src/fenrir/commands/commands/quit_fenrir.py @@ -14,10 +14,10 @@ def shutdown(self): pass def getDescription(self): - return 'exits Fenrir' + return _('exits Fenrir') def run(self): - self.env['generalInformation']['running'] = False + self.env['runtime']['eventManager'].stopMainEventLoop() def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/remove_marks.py b/src/fenrir/commands/commands/remove_marks.py index a180d85..0c2547e 100644 --- a/src/fenrir/commands/commands/remove_marks.py +++ b/src/fenrir/commands/commands/remove_marks.py @@ -14,11 +14,11 @@ def shutdown(self): pass def getDescription(self): - return 'removes marks from selected text' + return _('removes marks from selected text') def run(self): self.env['runtime']['cursorManager'].clearMarks() - self.env['runtime']['outputManager'].presentText('Remove marks', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Remove marks'), interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/remove_word_from_spell_check.py b/src/fenrir/commands/commands/remove_word_from_spell_check.py index 3da3e66..f212ee2 100644 --- a/src/fenrir/commands/commands/remove_word_from_spell_check.py +++ b/src/fenrir/commands/commands/remove_word_from_spell_check.py @@ -24,14 +24,14 @@ def shutdown(self): pass def getDescription(self): - return 'removes the current word from the exceptions dictionary' + return _('removes the current word from the exceptions dictionary') def updateSpellLanguage(self): self.spellChecker = enchant.Dict(self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage')) self.language = self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage') def run(self): if not initialized: - self.env['runtime']['outputManager'].presentText('pychant is not installed', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('pyenchant is not installed'), interrupt=True) return if self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage') != self.language: try: @@ -42,14 +42,14 @@ cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() # get the word - newContent = self.env['screenData']['newContentText'].split('\n')[cursorPos['y']] + newContent = self.env['screen']['newContentText'].split('\n')[cursorPos['y']] x, y, currWord, endOfScreen, lineBreak = word_utils.getCurrentWord(cursorPos['x'], 0, newContent) currWord = currWord.strip(string.whitespace + '!"#$%&\()*+,-./:;<=§>?@[\\]^_{|}~') if not currWord.isspace(): if self.spellChecker.is_removed(currWord): - self.env['runtime']['outputManager'].presentText(currWord + ' is already removed from dict',soundIcon='Cancel', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('{0} is already removed from dict').format(currWord,), soundIcon='Cancel', interrupt=True) else: self.spellChecker.remove(currWord) - self.env['runtime']['outputManager'].presentText(currWord + ' removed',soundIcon='Accept', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('{0} removed').format(currWord,), soundIcon='Accept', interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/review_bottom.py b/src/fenrir/commands/commands/review_bottom.py index acc05f8..07a431f 100644 --- a/src/fenrir/commands/commands/review_bottom.py +++ b/src/fenrir/commands/commands/review_bottom.py @@ -14,11 +14,11 @@ def shutdown(self): pass def getDescription(self): - return 'move review to bottom of screen' + return _('move review to bottom of screen') def run(self): - self.env['screenData']['newCursorReview'] = { 'x': 0, 'y':self.env['screenData']['lines'] -1} - self.env['runtime']['outputManager'].presentText("Bottom", interrupt=True) + self.env['screen']['newCursorReview'] = { 'x': 0, 'y':self.env['screen']['lines'] -1} + self.env['runtime']['outputManager'].presentText(_("Bottom"), interrupt=True, flush=False) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/review_curr_char.py b/src/fenrir/commands/commands/review_curr_char.py index d5839d0..6784ba5 100644 --- a/src/fenrir/commands/commands/review_curr_char.py +++ b/src/fenrir/commands/commands/review_curr_char.py @@ -15,15 +15,15 @@ def shutdown(self): pass def getDescription(self): - return 'presents the current character.' + return _('presents the current character.') def run(self): self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor() - self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], currChar = \ - char_utils.getCurrentChar(self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], self.env['screenData']['newContentText']) + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], currChar = \ + char_utils.getCurrentChar(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) - self.env['runtime']['outputManager'].presentText(currChar ,interrupt=True, ignorePunctuation=True, announceCapital=True) + self.env['runtime']['outputManager'].presentText(currChar ,interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/review_curr_char_phonetic.py b/src/fenrir/commands/commands/review_curr_char_phonetic.py index a0ba194..061eec4 100644 --- a/src/fenrir/commands/commands/review_curr_char_phonetic.py +++ b/src/fenrir/commands/commands/review_curr_char_phonetic.py @@ -15,19 +15,19 @@ def shutdown(self): pass def getDescription(self): - return 'set review and phonetically presents the current character' + return _('set review and phonetically presents the current character') def run(self): self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor() - self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], currChar = \ - char_utils.getCurrentChar(self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], self.env['screenData']['newContentText']) + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], currChar = \ + char_utils.getCurrentChar(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) if currChar.isspace(): - self.env['runtime']['outputManager'].presentText("blank" ,interrupt=True) + self.env['runtime']['outputManager'].presentText(_("blank"), interrupt=True, flush=False) else: currChar = char_utils.getPhonetic(currChar) - self.env['runtime']['outputManager'].presentText(currChar ,interrupt=True, announceCapital=True) + self.env['runtime']['outputManager'].presentText(currChar ,interrupt=True, announceCapital=True, flush=False) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/review_curr_line.py b/src/fenrir/commands/commands/review_curr_line.py index 6d8c9c1..af1de98 100644 --- a/src/fenrir/commands/commands/review_curr_line.py +++ b/src/fenrir/commands/commands/review_curr_line.py @@ -15,18 +15,18 @@ def shutdown(self): pass def getDescription(self): - return 'current line' + return _('current line') def run(self): self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor() - self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], currLine = \ - line_utils.getCurrentLine(self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], self.env['screenData']['newContentText']) + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], currLine = \ + line_utils.getCurrentLine(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) if currLine.isspace(): - self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True, flush=False) else: - self.env['runtime']['outputManager'].presentText(currLine, interrupt=True) + self.env['runtime']['outputManager'].presentText(currLine, interrupt=True, flush=False) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/review_curr_word.py b/src/fenrir/commands/commands/review_curr_word.py index c672362..4436cd0 100644 --- a/src/fenrir/commands/commands/review_curr_word.py +++ b/src/fenrir/commands/commands/review_curr_word.py @@ -15,23 +15,23 @@ def shutdown(self): pass def getDescription(self): - return 'current word.' + return _('current word.') def run(self): self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor() - self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], currWord, endOfScreen, lineBreak = \ - word_utils.getCurrentWord(self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], self.env['screenData']['newContentText']) + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], currWord, endOfScreen, lineBreak = \ + word_utils.getCurrentWord(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) if currWord.isspace(): - self.env['runtime']['outputManager'].presentText("blank", interrupt=True) + self.env['runtime']['outputManager'].presentText(_("blank"), interrupt=True, flush=False) else: - self.env['runtime']['outputManager'].presentText(currWord, interrupt=True) + self.env['runtime']['outputManager'].presentText(currWord, interrupt=True, flush=False) if endOfScreen: if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): - self.env['runtime']['outputManager'].presentText('end of screen' ,interrupt=True, soundIcon='EndOfScreen') + self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') if lineBreak: if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'lineBreak'): - self.env['runtime']['outputManager'].presentText('line break' ,interrupt=False, soundIcon='EndOfLine') + self.env['runtime']['outputManager'].presentText(_('line break'), interrupt=False, soundIcon='EndOfLine') def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/review_curr_word_phonetic.py b/src/fenrir/commands/commands/review_curr_word_phonetic.py index 50eba3c..c58568c 100644 --- a/src/fenrir/commands/commands/review_curr_word_phonetic.py +++ b/src/fenrir/commands/commands/review_curr_word_phonetic.py @@ -16,26 +16,26 @@ def shutdown(self): pass def getDescription(self): - return 'phonetically spells the current word and set review to it' + return _('phonetically spells the current word and set review to it') def run(self): self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor() - self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], currWord, endOfScreen, lineBreak = \ - word_utils.getCurrentWord(self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], self.env['screenData']['newContentText']) + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], currWord, endOfScreen, lineBreak = \ + word_utils.getCurrentWord(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) if currWord.isspace(): - self.env['runtime']['outputManager'].presentText("blank", interrupt=True) + self.env['runtime']['outputManager'].presentText(_("blank"), interrupt=True, flush=False) else: firstSequence = True for c in currWord: currChar = char_utils.getPhonetic(c) - self.env['runtime']['outputManager'].presentText(currChar, interrupt=firstSequence, announceCapital=True) + self.env['runtime']['outputManager'].presentText(currChar, interrupt=firstSequence, announceCapital=True, flush=False) firstSequence = False if endOfScreen: if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): - self.env['runtime']['outputManager'].presentText('end of screen' ,interrupt=True, soundIcon='EndOfScreen') + self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') if lineBreak: if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'lineBreak'): - self.env['runtime']['outputManager'].presentText('line break' ,interrupt=False, soundIcon='EndOfLine') + self.env['runtime']['outputManager'].presentText(_('line break'), interrupt=False, soundIcon='EndOfLine') def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/review_down.py b/src/fenrir/commands/commands/review_down.py index 8a28b4b..2428083 100644 --- a/src/fenrir/commands/commands/review_down.py +++ b/src/fenrir/commands/commands/review_down.py @@ -15,15 +15,15 @@ def shutdown(self): pass def getDescription(self): - return 'set review cursor to char below the current char and present it.' + return _('set review cursor to char below the current char and present it.') def run(self): cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() - self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], downChar, endOfScreen = \ - char_utils.getDownChar(self.env['screenData']['newCursorReview']['x'],self.env['screenData']['newCursorReview']['y'], self.env['screenData']['newContentText']) - self.env['runtime']['outputManager'].presentText(downChar ,interrupt=True, ignorePunctuation=True, announceCapital=True) + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], downChar, endOfScreen = \ + char_utils.getDownChar(self.env['screen']['newCursorReview']['x'],self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) + self.env['runtime']['outputManager'].presentText(downChar ,interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) if endOfScreen: if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): - self.env['runtime']['outputManager'].presentText('end of screen' ,interrupt=True, soundIcon='EndOfScreen') + self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/review_line_begin.py b/src/fenrir/commands/commands/review_line_begin.py index e69c0a3..c788a5c 100644 --- a/src/fenrir/commands/commands/review_line_begin.py +++ b/src/fenrir/commands/commands/review_line_begin.py @@ -15,19 +15,19 @@ def shutdown(self): pass def getDescription(self): - return 'set review cursor to begin of current line and display the content' + return _('set review cursor to begin of current line and display the content') def run(self): cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() self.env['runtime']['cursorManager'].setReviewCursorPosition(0 ,cursorPos['y']) - self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], currChar = \ - char_utils.getCurrentChar(self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], self.env['screenData']['newContentText']) + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], currChar = \ + char_utils.getCurrentChar(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) if currChar.isspace(): - self.env['runtime']['outputManager'].presentText("blank" ,interrupt=True) + self.env['runtime']['outputManager'].presentText(_("blank"), interrupt=True, flush=False) else: - self.env['runtime']['outputManager'].presentText(currChar ,interrupt=True, ignorePunctuation=True, announceCapital=True) - self.env['runtime']['outputManager'].presentText("beginning of line", interrupt=False) + self.env['runtime']['outputManager'].presentText(currChar ,interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) + self.env['runtime']['outputManager'].presentText(_("beginning of line"), interrupt=False) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/review_line_end.py b/src/fenrir/commands/commands/review_line_end.py index ec94c14..1af5b55 100644 --- a/src/fenrir/commands/commands/review_line_end.py +++ b/src/fenrir/commands/commands/review_line_end.py @@ -15,16 +15,16 @@ def shutdown(self): pass def getDescription(self): - return 'set review cursor to end of current line and display the content' + return _('set review cursor to end of current line and display the content') def run(self): cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() - self.env['runtime']['cursorManager'].setReviewCursorPosition(self.env['screenData']['columns']-1 ,cursorPos['y']) - self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], currChar = \ - char_utils.getCurrentChar(self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], self.env['screenData']['newContentText']) + self.env['runtime']['cursorManager'].setReviewCursorPosition(self.env['screen']['columns']-1 ,cursorPos['y']) + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], currChar = \ + char_utils.getCurrentChar(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) - self.env['runtime']['outputManager'].presentText(currChar ,interrupt=True, ignorePunctuation=True, announceCapital=True) - self.env['runtime']['outputManager'].presentText("end of line", interrupt=False) + self.env['runtime']['outputManager'].presentText(currChar ,interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) + self.env['runtime']['outputManager'].presentText(_("end of line"), interrupt=False) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/review_line_first_char.py b/src/fenrir/commands/commands/review_line_first_char.py index 6139181..82f687a 100644 --- a/src/fenrir/commands/commands/review_line_first_char.py +++ b/src/fenrir/commands/commands/review_line_first_char.py @@ -16,21 +16,21 @@ def shutdown(self): pass def getDescription(self): - return 'set review cursor to end of current line and display the content' + return _('set review cursor to end of current line and display the content') def run(self): cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() x, y, currLine = \ - line_utils.getCurrentLine(cursorPos['x'], cursorPos['y'], self.env['screenData']['newContentText']) + line_utils.getCurrentLine(cursorPos['x'], cursorPos['y'], self.env['screen']['newContentText']) if currLine.isspace(): - self.env['runtime']['outputManager'].presentText("line is empty" ,interrupt=True) + self.env['runtime']['outputManager'].presentText(_("line is empty"), interrupt=True) return self.env['runtime']['cursorManager'].setReviewCursorPosition((len(currLine) - len(currLine.lstrip())), cursorPos['y']) - self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], currChar = \ - char_utils.getCurrentChar(self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], self.env['screenData']['newContentText']) + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], currChar = \ + char_utils.getCurrentChar(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) - self.env['runtime']['outputManager'].presentText(currChar ,interrupt=True, ignorePunctuation=True, announceCapital=True) - self.env['runtime']['outputManager'].presentText("first char in line indent " + str(len(currLine) - len(currLine.lstrip())), interrupt=False) + self.env['runtime']['outputManager'].presentText(currChar ,interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) + self.env['runtime']['outputManager'].presentText(_("first char in line indent {0}").format(str(len(currLine) - len(currLine.lstrip()))), interrupt=False) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/review_line_last_char.py b/src/fenrir/commands/commands/review_line_last_char.py index 3577e03..f30265e 100644 --- a/src/fenrir/commands/commands/review_line_last_char.py +++ b/src/fenrir/commands/commands/review_line_last_char.py @@ -15,16 +15,16 @@ def shutdown(self): pass def getDescription(self): - return 'set review cursor to end of current line and display the content' + return _('set review cursor to end of current line and display the content') def run(self): cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() - self.env['runtime']['cursorManager'].setReviewCursorPosition(self.env['screenData']['columns']-1 ,cursorPos['y']) - self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], lastChar = \ - char_utils.getLastCharInLine(self.env['screenData']['newCursorReview']['y'], self.env['screenData']['newContentText']) + self.env['runtime']['cursorManager'].setReviewCursorPosition(self.env['screen']['columns']-1 ,cursorPos['y']) + 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) - self.env['runtime']['outputManager'].presentText("last char in line", interrupt=False) + self.env['runtime']['outputManager'].presentText(lastChar ,interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) + self.env['runtime']['outputManager'].presentText(_("last char in line"), interrupt=False) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/review_next_char.py b/src/fenrir/commands/commands/review_next_char.py index 95fc8fa..e3c0a2e 100644 --- a/src/fenrir/commands/commands/review_next_char.py +++ b/src/fenrir/commands/commands/review_next_char.py @@ -15,19 +15,19 @@ def shutdown(self): pass def getDescription(self): - return 'moves review to the next character and presents it' + return _('moves review to the next character and presents it') def run(self): self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor() - self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], nextChar, endOfScreen, lineBreak = \ - char_utils.getNextChar(self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], self.env['screenData']['newContentText']) + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], nextChar, endOfScreen, lineBreak = \ + char_utils.getNextChar(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) - self.env['runtime']['outputManager'].presentText(nextChar, interrupt=True, ignorePunctuation=True, announceCapital=True) + self.env['runtime']['outputManager'].presentText(nextChar, interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) if endOfScreen: if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): - self.env['runtime']['outputManager'].presentText('end of screen' ,interrupt=True, soundIcon='EndOfScreen') + self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') if lineBreak: if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'lineBreak'): - self.env['runtime']['outputManager'].presentText('line break' ,interrupt=False, soundIcon='EndOfLine') + self.env['runtime']['outputManager'].presentText(_('line break'), interrupt=False, soundIcon='EndOfLine') def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/review_next_char_phonetic.py b/src/fenrir/commands/commands/review_next_char_phonetic.py index 8cb8158..f4ae4aa 100644 --- a/src/fenrir/commands/commands/review_next_char_phonetic.py +++ b/src/fenrir/commands/commands/review_next_char_phonetic.py @@ -15,21 +15,21 @@ def shutdown(self): pass def getDescription(self): - return 'phonetically presents the next character and set review to it' + return _('phonetically presents the next character and set review to it') def run(self): self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor() - self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], nextChar, endOfScreen, lineBreak = \ - char_utils.getNextChar(self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], self.env['screenData']['newContentText']) + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], nextChar, endOfScreen, lineBreak = \ + char_utils.getNextChar(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) nextChar = char_utils.getPhonetic(nextChar) - self.env['runtime']['outputManager'].presentText(nextChar ,interrupt=True, announceCapital=True) + self.env['runtime']['outputManager'].presentText(nextChar ,interrupt=True, announceCapital=True, flush=False) if endOfScreen: if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): - self.env['runtime']['outputManager'].presentText('end of screen' ,interrupt=True, soundIcon='EndOfScreen') + self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') if lineBreak: if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'lineBreak'): - self.env['runtime']['outputManager'].presentText('line break' ,interrupt=False, soundIcon='EndOfLine') + self.env['runtime']['outputManager'].presentText(_('line break'), interrupt=False, soundIcon='EndOfLine') def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/review_next_line.py b/src/fenrir/commands/commands/review_next_line.py index 8a54d11..a41550c 100644 --- a/src/fenrir/commands/commands/review_next_line.py +++ b/src/fenrir/commands/commands/review_next_line.py @@ -15,22 +15,22 @@ def shutdown(self): pass def getDescription(self): - return 'moves review to the next line and presents it' + return _('moves review to the next line and presents it') def run(self): - self.env['screenData']['oldCursorReview'] = self.env['screenData']['newCursorReview'] - if not self.env['screenData']['newCursorReview']: - self.env['screenData']['newCursorReview'] = self.env['screenData']['newCursor'].copy() + self.env['screen']['oldCursorReview'] = self.env['screen']['newCursorReview'] + if not self.env['screen']['newCursorReview']: + self.env['screen']['newCursorReview'] = self.env['screen']['newCursor'].copy() - self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], nextLine, endOfScreen = \ - line_utils.getNextLine(self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], self.env['screenData']['newContentText']) + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], nextLine, endOfScreen = \ + line_utils.getNextLine(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) if nextLine.isspace(): - self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True, flush=False) else: - self.env['runtime']['outputManager'].presentText(nextLine, interrupt=True) + self.env['runtime']['outputManager'].presentText(nextLine, interrupt=True, flush=False) if endOfScreen: if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): - self.env['runtime']['outputManager'].presentText('end of screen' ,interrupt=True, soundIcon='EndOfScreen') + self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/review_next_word.py b/src/fenrir/commands/commands/review_next_word.py index b8fad03..c05ca59 100644 --- a/src/fenrir/commands/commands/review_next_word.py +++ b/src/fenrir/commands/commands/review_next_word.py @@ -15,25 +15,25 @@ def shutdown(self): pass def getDescription(self): - return 'moves review to the next word and presents it' + return _('moves review to the next word and presents it') def run(self): - self.env['screenData']['oldCursorReview'] = self.env['screenData']['newCursorReview'] - if self.env['screenData']['newCursorReview'] == None: - self.env['screenData']['newCursorReview'] = self.env['screenData']['newCursor'].copy() + self.env['screen']['oldCursorReview'] = self.env['screen']['newCursorReview'] + if self.env['screen']['newCursorReview'] == None: + self.env['screen']['newCursorReview'] = self.env['screen']['newCursor'].copy() - self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], nextWord, endOfScreen, lineBreak = \ - word_utils.getNextWord(self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], self.env['screenData']['newContentText']) + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], nextWord, endOfScreen, lineBreak = \ + word_utils.getNextWord(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) if nextWord.isspace(): - self.env['runtime']['outputManager'].presentText("blank", interrupt=True) + self.env['runtime']['outputManager'].presentText(_("blank"), interrupt=True, flush=False) else: - self.env['runtime']['outputManager'].presentText(nextWord, interrupt=True) + self.env['runtime']['outputManager'].presentText(nextWord, interrupt=True, flush=False) if endOfScreen: if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): - self.env['runtime']['outputManager'].presentText('end of screen' ,interrupt=True, soundIcon='EndOfScreen') + self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') if lineBreak: if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'lineBreak'): - self.env['runtime']['outputManager'].presentText('line break' ,interrupt=False, soundIcon='EndOfLine') + self.env['runtime']['outputManager'].presentText(_('line break'), interrupt=False, soundIcon='EndOfLine') def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/review_next_word_phonetic.py b/src/fenrir/commands/commands/review_next_word_phonetic.py index 0a89f69..f0e9f90 100644 --- a/src/fenrir/commands/commands/review_next_word_phonetic.py +++ b/src/fenrir/commands/commands/review_next_word_phonetic.py @@ -16,26 +16,26 @@ def shutdown(self): pass def getDescription(self): - return 'phonetically spells the current word and set review to it' + return _('phonetically spells the current word and set review to it') def run(self): self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor() - self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], nextWord, endOfScreen, lineBreak = \ - word_utils.getNextWord(self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], self.env['screenData']['newContentText']) + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], nextWord, endOfScreen, lineBreak = \ + word_utils.getNextWord(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) if nextWord.isspace(): - self.env['runtime']['outputManager'].presentText("blank", interrupt=True) + self.env['runtime']['outputManager'].presentText(_("blank"), interrupt=True, flush=False) else: firstSequence = True for c in nextWord: currChar = char_utils.getPhonetic(c) - self.env['runtime']['outputManager'].presentText(currChar, interrupt=firstSequence, announceCapital=True) + self.env['runtime']['outputManager'].presentText(currChar, interrupt=firstSequence, announceCapital=True, flush=False) firstSequence = False if endOfScreen: if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): - self.env['runtime']['outputManager'].presentText('end of screen' ,interrupt=True, soundIcon='EndOfScreen') + self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') if lineBreak: if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'lineBreak'): - self.env['runtime']['outputManager'].presentText('line break' ,interrupt=False, soundIcon='EndOfLine') + self.env['runtime']['outputManager'].presentText(_('line break'), interrupt=False, soundIcon='EndOfLine') def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/review_prev_char.py b/src/fenrir/commands/commands/review_prev_char.py index 77cbcbf..444eb32 100644 --- a/src/fenrir/commands/commands/review_prev_char.py +++ b/src/fenrir/commands/commands/review_prev_char.py @@ -15,22 +15,22 @@ def shutdown(self): pass def getDescription(self): - return 'moves review to the previous character and presents it' + return _('moves review to the previous character and presents it') def run(self): - self.env['screenData']['oldCursorReview'] = self.env['screenData']['newCursorReview'] - if not self.env['screenData']['newCursorReview']: - self.env['screenData']['newCursorReview'] = self.env['screenData']['newCursor'].copy() + self.env['screen']['oldCursorReview'] = self.env['screen']['newCursorReview'] + if not self.env['screen']['newCursorReview']: + self.env['screen']['newCursorReview'] = self.env['screen']['newCursor'].copy() - self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], prevChar, endOfScreen, lineBreak = \ - char_utils.getPrevChar(self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], self.env['screenData']['newContentText']) + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], prevChar, endOfScreen, lineBreak = \ + char_utils.getPrevChar(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) - self.env['runtime']['outputManager'].presentText(prevChar, interrupt=True, ignorePunctuation=True, announceCapital=True) + self.env['runtime']['outputManager'].presentText(prevChar, interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) if endOfScreen: if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): - self.env['runtime']['outputManager'].presentText('end of screen' ,interrupt=True, soundIcon='EndOfScreen') + self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') if lineBreak: if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'lineBreak'): - self.env['runtime']['outputManager'].presentText('line break' ,interrupt=False, soundIcon='EndOfLine') + self.env['runtime']['outputManager'].presentText(_('line break'), interrupt=False, soundIcon='EndOfLine') def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/review_prev_char_phonetic.py b/src/fenrir/commands/commands/review_prev_char_phonetic.py index b205ad5..e66e088 100644 --- a/src/fenrir/commands/commands/review_prev_char_phonetic.py +++ b/src/fenrir/commands/commands/review_prev_char_phonetic.py @@ -15,21 +15,21 @@ def shutdown(self): pass def getDescription(self): - return 'phonetically presents the previous character and set review to it' + return _('phonetically presents the previous character and set review to it') def run(self): self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor() - self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], prevChar, endOfScreen, lineBreak = \ - char_utils.getPrevChar(self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], self.env['screenData']['newContentText']) + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], prevChar, endOfScreen, lineBreak = \ + char_utils.getPrevChar(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) prevChar = char_utils.getPhonetic(prevChar) - self.env['runtime']['outputManager'].presentText(prevChar ,interrupt=True, announceCapital=True) + self.env['runtime']['outputManager'].presentText(prevChar ,interrupt=True, announceCapital=True, flush=False) if endOfScreen: if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): - self.env['runtime']['outputManager'].presentText('end of screen' ,interrupt=True, soundIcon='EndOfScreen') + self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') if lineBreak: if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'lineBreak'): - self.env['runtime']['outputManager'].presentText('line break' ,interrupt=False, soundIcon='EndOfLine') + self.env['runtime']['outputManager'].presentText(_('line break'), interrupt=False, soundIcon='EndOfLine') def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/review_prev_line.py b/src/fenrir/commands/commands/review_prev_line.py index 8872157..c360195 100644 --- a/src/fenrir/commands/commands/review_prev_line.py +++ b/src/fenrir/commands/commands/review_prev_line.py @@ -15,21 +15,21 @@ def shutdown(self): pass def getDescription(self): - return 'moves review to the previous line and presents it' + return _('moves review to the previous line and presents it') def run(self): self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor() - self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], prevLine, endOfScreen = \ - line_utils.getPrevLine(self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], self.env['screenData']['newContentText']) + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], prevLine, endOfScreen = \ + line_utils.getPrevLine(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) if prevLine.isspace(): - self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True, flush=False) else: - self.env['runtime']['outputManager'].presentText(prevLine, interrupt=True) + self.env['runtime']['outputManager'].presentText(prevLine, interrupt=True, flush=False) if endOfScreen: if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): - self.env['runtime']['outputManager'].presentText('end of screen' ,interrupt=True, soundIcon='EndOfScreen') + self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/review_prev_word.py b/src/fenrir/commands/commands/review_prev_word.py index 1a53e1c..b36f303 100644 --- a/src/fenrir/commands/commands/review_prev_word.py +++ b/src/fenrir/commands/commands/review_prev_word.py @@ -15,23 +15,23 @@ def shutdown(self): pass def getDescription(self): - return 'moves review focus to the previous word and presents it' + return _('moves review focus to the previous word and presents it') def run(self): self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor() - self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], prevWord, endOfScreen, lineBreak = \ - word_utils.getPrevWord(self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], self.env['screenData']['newContentText']) + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], prevWord, endOfScreen, lineBreak = \ + word_utils.getPrevWord(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) if prevWord.isspace(): - self.env['runtime']['outputManager'].presentText("blank", interrupt=True) + self.env['runtime']['outputManager'].presentText(_("blank"), interrupt=True, flush=False) else: - self.env['runtime']['outputManager'].presentText(prevWord, interrupt=True) + self.env['runtime']['outputManager'].presentText(prevWord, interrupt=True, flush=False) if endOfScreen: if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): - self.env['runtime']['outputManager'].presentText('end of screen' ,interrupt=False, soundIcon='EndOfScreen') + self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=False, soundIcon='EndOfScreen') if lineBreak: if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'lineBreak'): - self.env['runtime']['outputManager'].presentText('line break' ,interrupt=False, soundIcon='EndOfLine') + self.env['runtime']['outputManager'].presentText(_('line break'), interrupt=False, soundIcon='EndOfLine') def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/review_prev_word_phonetic.py b/src/fenrir/commands/commands/review_prev_word_phonetic.py index b8abaed..eeddfd3 100644 --- a/src/fenrir/commands/commands/review_prev_word_phonetic.py +++ b/src/fenrir/commands/commands/review_prev_word_phonetic.py @@ -16,26 +16,26 @@ def shutdown(self): pass def getDescription(self): - return 'phonetically spells the current word and set review to it' + return _('phonetically spells the current word and set review to it') def run(self): self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor() - self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], prevWord, endOfScreen, lineBreak = \ - word_utils.getPrevWord(self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], self.env['screenData']['newContentText']) + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], prevWord, endOfScreen, lineBreak = \ + word_utils.getPrevWord(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) if prevWord.isspace(): - self.env['runtime']['outputManager'].presentText("blank", interrupt=True) + self.env['runtime']['outputManager'].presentText(_("blank"), interrupt=True, flush=False) else: firstSequence = True for c in prevWord: currChar = char_utils.getPhonetic(c) - self.env['runtime']['outputManager'].presentText(currChar, interrupt=firstSequence, announceCapital=True) + self.env['runtime']['outputManager'].presentText(currChar, interrupt=firstSequence, announceCapital=True, flush=False) firstSequence = False if endOfScreen: if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): - self.env['runtime']['outputManager'].presentText('end of screen' ,interrupt=True, soundIcon='EndOfScreen') + self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') if lineBreak: if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'lineBreak'): - self.env['runtime']['outputManager'].presentText('line break' ,interrupt=False, soundIcon='EndOfLine') + self.env['runtime']['outputManager'].presentText(_('line break'), interrupt=False, soundIcon='EndOfLine') def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/review_top.py b/src/fenrir/commands/commands/review_top.py index b48f730..aaaed43 100644 --- a/src/fenrir/commands/commands/review_top.py +++ b/src/fenrir/commands/commands/review_top.py @@ -15,11 +15,11 @@ def shutdown(self): pass def getDescription(self): - return 'move review to top of screen' + return _('move review to top of screen') def run(self): - self.env['screenData']['newCursorReview'] = {'x':0,'y':0} - self.env['runtime']['outputManager'].presentText("Top", interrupt=True) + self.env['screen']['newCursorReview'] = {'x':0,'y':0} + self.env['runtime']['outputManager'].presentText(_("Top"), interrupt=True, flush=False) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/review_up.py b/src/fenrir/commands/commands/review_up.py index 66c680c..1867e87 100644 --- a/src/fenrir/commands/commands/review_up.py +++ b/src/fenrir/commands/commands/review_up.py @@ -15,18 +15,18 @@ def shutdown(self): pass def getDescription(self): - return 'set review cursor to the char in the line below and present it' + return _('set review cursor to the char in the line below and present it') def run(self): cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() - self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], upChar, endOfScreen = \ - char_utils.getUpChar(self.env['screenData']['newCursorReview']['x'],self.env['screenData']['newCursorReview']['y'], self.env['screenData']['newContentText']) - self.env['runtime']['outputManager'].presentText(upChar ,interrupt=True, ignorePunctuation=True, announceCapital=True) + self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], upChar, endOfScreen = \ + char_utils.getUpChar(self.env['screen']['newCursorReview']['x'],self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText']) + self.env['runtime']['outputManager'].presentText(upChar ,interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) if endOfScreen: if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'): - self.env['runtime']['outputManager'].presentText('end of screen' ,interrupt=True, soundIcon='EndOfScreen') + self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen') if lineBreak: if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'lineBreak'): - self.env['runtime']['outputManager'].presentText('line break' ,interrupt=False, soundIcon='EndOfLine') + self.env['runtime']['outputManager'].presentText(_('line break'), interrupt=False, soundIcon='EndOfLine') def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/set_bookmark_1.py b/src/fenrir/commands/commands/set_bookmark_1.py index a5582b5..6a59ec7 100644 --- a/src/fenrir/commands/commands/set_bookmark_1.py +++ b/src/fenrir/commands/commands/set_bookmark_1.py @@ -15,11 +15,11 @@ def shutdown(self): pass def getDescription(self): - return 'set Bookmark ' + self.ID + return _('set Bookmark {0}').format(self.ID,) def run(self): if not self.env['commandBuffer']['Marks']['1']: - self.env['runtime']['outputManager'].presentText("No Mark found", interrupt=True) + self.env['runtime']['outputManager'].presentText(_("No Mark found"), interrupt=True) return currApp = self.env['runtime']['applicationManager'].getCurrentApplication() self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {} @@ -29,7 +29,7 @@ self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = self.env['commandBuffer']['Marks']['2'].copy() else: self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = None - self.env['runtime']['outputManager'].presentText('Bookmark ' + self.ID + " set for application " + currApp, interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} set for application {1}').format(self.ID, currApp), interrupt=True) self.env['commandBuffer']['Marks']['1'] = None self.env['commandBuffer']['Marks']['2'] = None def setCallback(self, callback): diff --git a/src/fenrir/commands/commands/set_bookmark_10.py b/src/fenrir/commands/commands/set_bookmark_10.py index 1e51729..4a565c2 100644 --- a/src/fenrir/commands/commands/set_bookmark_10.py +++ b/src/fenrir/commands/commands/set_bookmark_10.py @@ -15,11 +15,11 @@ def shutdown(self): pass def getDescription(self): - return 'set Bookmark ' + self.ID + return _('set Bookmark {0}').format(self.ID,) def run(self): if not self.env['commandBuffer']['Marks']['1']: - self.env['runtime']['outputManager'].presentText("No Mark found", interrupt=True) + self.env['runtime']['outputManager'].presentText(_("No Mark found"), interrupt=True) return currApp = self.env['runtime']['applicationManager'].getCurrentApplication() self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {} @@ -29,7 +29,7 @@ self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = self.env['commandBuffer']['Marks']['2'].copy() else: self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = None - self.env['runtime']['outputManager'].presentText('Bookmark ' + self.ID + " set for application " + currApp, interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} set for application {1}').format(self.ID, currApp), interrupt=True) self.env['commandBuffer']['Marks']['1'] = None self.env['commandBuffer']['Marks']['2'] = None def setCallback(self, callback): diff --git a/src/fenrir/commands/commands/set_bookmark_2.py b/src/fenrir/commands/commands/set_bookmark_2.py index 8087700..26d0263 100644 --- a/src/fenrir/commands/commands/set_bookmark_2.py +++ b/src/fenrir/commands/commands/set_bookmark_2.py @@ -15,11 +15,11 @@ def shutdown(self): pass def getDescription(self): - return 'set Bookmark ' + self.ID + return _('set Bookmark {0}').format(self.ID,) def run(self): if not self.env['commandBuffer']['Marks']['1']: - self.env['runtime']['outputManager'].presentText("No Mark found", interrupt=True) + self.env['runtime']['outputManager'].presentText(_("No Mark found"), interrupt=True) return currApp = self.env['runtime']['applicationManager'].getCurrentApplication() self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {} @@ -29,7 +29,7 @@ self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = self.env['commandBuffer']['Marks']['2'].copy() else: self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = None - self.env['runtime']['outputManager'].presentText('Bookmark ' + self.ID + " set for application " + currApp, interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} set for application {1}').format(self.ID, currApp), interrupt=True) self.env['commandBuffer']['Marks']['1'] = None self.env['commandBuffer']['Marks']['2'] = None def setCallback(self, callback): diff --git a/src/fenrir/commands/commands/set_bookmark_3.py b/src/fenrir/commands/commands/set_bookmark_3.py index ee00d31..8645ee3 100644 --- a/src/fenrir/commands/commands/set_bookmark_3.py +++ b/src/fenrir/commands/commands/set_bookmark_3.py @@ -15,11 +15,11 @@ def shutdown(self): pass def getDescription(self): - return 'set Bookmark ' + self.ID + return _('set Bookmark {0}').format(self.ID,) def run(self): if not self.env['commandBuffer']['Marks']['1']: - self.env['runtime']['outputManager'].presentText("No Mark found", interrupt=True) + self.env['runtime']['outputManager'].presentText(_("No Mark found"), interrupt=True) return currApp = self.env['runtime']['applicationManager'].getCurrentApplication() self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {} @@ -29,7 +29,7 @@ self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = self.env['commandBuffer']['Marks']['2'].copy() else: self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = None - self.env['runtime']['outputManager'].presentText('Bookmark ' + self.ID + " set for application " + currApp, interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} set for application {1}').format(self.ID, currApp), interrupt=True) self.env['commandBuffer']['Marks']['1'] = None self.env['commandBuffer']['Marks']['2'] = None def setCallback(self, callback): diff --git a/src/fenrir/commands/commands/set_bookmark_4.py b/src/fenrir/commands/commands/set_bookmark_4.py index b983b41..b098a50 100644 --- a/src/fenrir/commands/commands/set_bookmark_4.py +++ b/src/fenrir/commands/commands/set_bookmark_4.py @@ -15,11 +15,11 @@ def shutdown(self): pass def getDescription(self): - return 'set Bookmark ' + self.ID + return _('set Bookmark {0}').format(self.ID,) def run(self): if not self.env['commandBuffer']['Marks']['1']: - self.env['runtime']['outputManager'].presentText("No Mark found", interrupt=True) + self.env['runtime']['outputManager'].presentText(_("No Mark found"), interrupt=True) return currApp = self.env['runtime']['applicationManager'].getCurrentApplication() self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {} @@ -29,7 +29,7 @@ self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = self.env['commandBuffer']['Marks']['2'].copy() else: self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = None - self.env['runtime']['outputManager'].presentText('Bookmark ' + self.ID + " set for application " + currApp, interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} set for application {1}').format(self.ID, currApp), interrupt=True) self.env['commandBuffer']['Marks']['1'] = None self.env['commandBuffer']['Marks']['2'] = None def setCallback(self, callback): diff --git a/src/fenrir/commands/commands/set_bookmark_5.py b/src/fenrir/commands/commands/set_bookmark_5.py index 10dbb86..6c082f9 100644 --- a/src/fenrir/commands/commands/set_bookmark_5.py +++ b/src/fenrir/commands/commands/set_bookmark_5.py @@ -15,11 +15,11 @@ def shutdown(self): pass def getDescription(self): - return 'set Bookmark ' + self.ID + return _('set Bookmark {0}').format(self.ID,) def run(self): if not self.env['commandBuffer']['Marks']['1']: - self.env['runtime']['outputManager'].presentText("No Mark found", interrupt=True) + self.env['runtime']['outputManager'].presentText(_("No Mark found"), interrupt=True) return currApp = self.env['runtime']['applicationManager'].getCurrentApplication() self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {} @@ -29,7 +29,7 @@ self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = self.env['commandBuffer']['Marks']['2'].copy() else: self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = None - self.env['runtime']['outputManager'].presentText('Bookmark ' + self.ID + " set for application " + currApp, interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} set for application {1}').format(self.ID, currApp), interrupt=True) self.env['commandBuffer']['Marks']['1'] = None self.env['commandBuffer']['Marks']['2'] = None def setCallback(self, callback): diff --git a/src/fenrir/commands/commands/set_bookmark_6.py b/src/fenrir/commands/commands/set_bookmark_6.py index 4397979..a309d08 100644 --- a/src/fenrir/commands/commands/set_bookmark_6.py +++ b/src/fenrir/commands/commands/set_bookmark_6.py @@ -15,11 +15,11 @@ def shutdown(self): pass def getDescription(self): - return 'set Bookmark ' + self.ID + return _('set Bookmark {0}').format(self.ID,) def run(self): if not self.env['commandBuffer']['Marks']['1']: - self.env['runtime']['outputManager'].presentText("No Mark found", interrupt=True) + self.env['runtime']['outputManager'].presentText(_("No Mark found"), interrupt=True) return currApp = self.env['runtime']['applicationManager'].getCurrentApplication() self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {} @@ -29,7 +29,7 @@ self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = self.env['commandBuffer']['Marks']['2'].copy() else: self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = None - self.env['runtime']['outputManager'].presentText('Bookmark ' + self.ID + " set for application " + currApp, interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} set for application {1}').format(self.ID, currApp), interrupt=True) self.env['commandBuffer']['Marks']['1'] = None self.env['commandBuffer']['Marks']['2'] = None def setCallback(self, callback): diff --git a/src/fenrir/commands/commands/set_bookmark_7.py b/src/fenrir/commands/commands/set_bookmark_7.py index 6fbbcbb..4803487 100644 --- a/src/fenrir/commands/commands/set_bookmark_7.py +++ b/src/fenrir/commands/commands/set_bookmark_7.py @@ -15,11 +15,11 @@ def shutdown(self): pass def getDescription(self): - return 'set Bookmark ' + self.ID + return _('set Bookmark {0}').format(self.ID,) def run(self): if not self.env['commandBuffer']['Marks']['1']: - self.env['runtime']['outputManager'].presentText("No Mark found", interrupt=True) + self.env['runtime']['outputManager'].presentText(_("No Mark found"), interrupt=True) return currApp = self.env['runtime']['applicationManager'].getCurrentApplication() self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {} @@ -29,7 +29,7 @@ self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = self.env['commandBuffer']['Marks']['2'].copy() else: self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = None - self.env['runtime']['outputManager'].presentText('Bookmark ' + self.ID + " set for application " + currApp, interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} set for application {1}').format(self.ID, currApp), interrupt=True) self.env['commandBuffer']['Marks']['1'] = None self.env['commandBuffer']['Marks']['2'] = None def setCallback(self, callback): diff --git a/src/fenrir/commands/commands/set_bookmark_8.py b/src/fenrir/commands/commands/set_bookmark_8.py index dd87c7f..362f61c 100644 --- a/src/fenrir/commands/commands/set_bookmark_8.py +++ b/src/fenrir/commands/commands/set_bookmark_8.py @@ -15,11 +15,11 @@ def shutdown(self): pass def getDescription(self): - return 'set Bookmark ' + self.ID + return _('set Bookmark {0}').format(self.ID,) def run(self): if not self.env['commandBuffer']['Marks']['1']: - self.env['runtime']['outputManager'].presentText("No Mark found", interrupt=True) + self.env['runtime']['outputManager'].presentText(_("No Mark found"), interrupt=True) return currApp = self.env['runtime']['applicationManager'].getCurrentApplication() self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {} @@ -29,7 +29,7 @@ self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = self.env['commandBuffer']['Marks']['2'].copy() else: self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = None - self.env['runtime']['outputManager'].presentText('Bookmark ' + self.ID + " set for application " + currApp, interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} set for application {1}').format(self.ID, currApp), interrupt=True) self.env['commandBuffer']['Marks']['1'] = None self.env['commandBuffer']['Marks']['2'] = None def setCallback(self, callback): diff --git a/src/fenrir/commands/commands/set_bookmark_9.py b/src/fenrir/commands/commands/set_bookmark_9.py index 5136e37..ef53c39 100644 --- a/src/fenrir/commands/commands/set_bookmark_9.py +++ b/src/fenrir/commands/commands/set_bookmark_9.py @@ -15,11 +15,11 @@ def shutdown(self): pass def getDescription(self): - return 'set Bookmark ' + self.ID + return _('set Bookmark {0}').format(self.ID,) def run(self): if not self.env['commandBuffer']['Marks']['1']: - self.env['runtime']['outputManager'].presentText("No Mark found", interrupt=True) + self.env['runtime']['outputManager'].presentText(_("No Mark found"), interrupt=True) return currApp = self.env['runtime']['applicationManager'].getCurrentApplication() self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {} @@ -29,7 +29,7 @@ self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = self.env['commandBuffer']['Marks']['2'].copy() else: self.env['commandBuffer']['bookMarks'][self.ID][currApp]['2'] = None - self.env['runtime']['outputManager'].presentText('Bookmark ' + self.ID + " set for application " + currApp, interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Bookmark {0} set for application {1}').format(self.ID, currApp), interrupt=True) self.env['commandBuffer']['Marks']['1'] = None self.env['commandBuffer']['Marks']['2'] = None def setCallback(self, callback): diff --git a/src/fenrir/commands/commands/set_mark.py b/src/fenrir/commands/commands/set_mark.py index 2c2ddd6..82e1f90 100644 --- a/src/fenrir/commands/commands/set_mark.py +++ b/src/fenrir/commands/commands/set_mark.py @@ -14,17 +14,17 @@ def shutdown(self): pass def getDescription(self): - return 'places marks to select text to copy to the clipboard' + return _('places marks to select text to copy to the clipboard') def run(self): if not self.env['runtime']['cursorManager'].isReviewMode(): - self.env['runtime']['outputManager'].presentText('no review cursor', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('no review cursor'), interrupt=True) return currMark = self.env['runtime']['cursorManager'].setMark() if currMark == 1: - self.env['runtime']['outputManager'].presentText('set mark',soundIcon='PlaceStartMark', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('set mark'), soundIcon='PlaceStartMark', interrupt=True) elif currMark == 2: - self.env['runtime']['outputManager'].presentText('set mark',soundIcon='PlaceEndMark', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('set mark'),soundIcon='PlaceEndMark', interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/set_window_application.py b/src/fenrir/commands/commands/set_window_application.py index 61940b3..9413fcd 100644 --- a/src/fenrir/commands/commands/set_window_application.py +++ b/src/fenrir/commands/commands/set_window_application.py @@ -14,15 +14,15 @@ def shutdown(self): pass def getDescription(self): - return 'set Window Mode, needs 2 marks ' + return _('set Window Mode, needs 2 marks ') def run(self): if self.env['runtime']['cursorManager'].setWindowForApplication(): currApp = self.env['runtime']['applicationManager'].getCurrentApplication() - self.env['runtime']['outputManager'].presentText('Window Mode on for application ' + currApp, interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Window Mode on for application {0}').format(currApp), interrupt=True) self.env['runtime']['cursorManager'].clearMarks() else: - self.env['runtime']['outputManager'].presentText("Set window beginn and end marks", interrupt=True) + self.env['runtime']['outputManager'].presentText(_("Set window begin and end marks"), interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/shut_up.py b/src/fenrir/commands/commands/shut_up.py index f9060ae..aad7226 100644 --- a/src/fenrir/commands/commands/shut_up.py +++ b/src/fenrir/commands/commands/shut_up.py @@ -14,7 +14,7 @@ def shutdown(self): pass def getDescription(self): - return 'interrupts the current presentation' + return _('interrupts the current presentation') def run(self): if len(self.env['input']['prevDeepestInput']) > len(self.env['input']['currInput']): return diff --git a/src/fenrir/commands/commands/spell_check.py b/src/fenrir/commands/commands/spell_check.py index 7d37150..c251ca0 100644 --- a/src/fenrir/commands/commands/spell_check.py +++ b/src/fenrir/commands/commands/spell_check.py @@ -23,14 +23,17 @@ def shutdown(self): pass def getDescription(self): - return 'checks the spelling of the current word' + return _('checks the spelling of the current word') def updateSpellLanguage(self): + if not initialized: + self.env['runtime']['outputManager'].presentText(_('pyenchant is not installed'), interrupt=True) + return self.spellChecker = enchant.Dict(self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage')) self.language = self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage') def run(self): if not initialized: - self.env['runtime']['outputManager'].presentText('pychant is not installed', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('pyenchant is not installed'), interrupt=True) return if self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage') != self.language: try: @@ -41,13 +44,13 @@ cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() # get the word - newContent = self.env['screenData']['newContentText'].split('\n')[cursorPos['y']] + newContent = self.env['screen']['newContentText'].split('\n')[cursorPos['y']] x, y, currWord, endOfScreen, lineBreak = word_utils.getCurrentWord(cursorPos['x'], 0, newContent) if not currWord.isspace(): if not self.spellChecker.check(currWord): - self.env['runtime']['outputManager'].presentText('misspelled',soundIcon='mispell', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('misspelled'),soundIcon='mispell', interrupt=True) elif not ignore: - self.env['runtime']['outputManager'].presentText('correct',soundIcon='', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('correct'),soundIcon='', interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/subprocess.py b/src/fenrir/commands/commands/subprocess.py index 411b3de..ac53e8d 100644 --- a/src/fenrir/commands/commands/subprocess.py +++ b/src/fenrir/commands/commands/subprocess.py @@ -18,31 +18,31 @@ def shutdown(self): pass def getDescription(self): - return 'script: ' + os.path.basename(self.scriptPath) + ' fullpath: '+ self.scriptPath + return _('script: {0} fullpath: {1}').format(os.path.basename(self.scriptPath), self.scriptPath) def run(self): if not os.path.exists(self.scriptPath): - self.env['runtime']['outputManager'].presentText('scriptfile does not exist' , soundIcon='', interrupt=False) + self.env['runtime']['outputManager'].presentText(_('scriptfile does not exist'), soundIcon='', interrupt=False) return if not os.path.isfile(self.scriptPath): - self.env['runtime']['outputManager'].presentText('scriptfile is not a file' , soundIcon='', interrupt=False) + self.env['runtime']['outputManager'].presentText(_('scriptfile is not a file'), soundIcon='', interrupt=False) return if not os.access(self.scriptPath, os.X_OK): - self.env['runtime']['outputManager'].presentText('scriptfile is not executable' , soundIcon='', interrupt=False) + self.env['runtime']['outputManager'].presentText(_('scriptfile is not executable'), soundIcon='', interrupt=False) return _thread.start_new_thread(self._threadRun , ()) def _threadRun(self): try: - p = Popen(self.scriptPath , stdout=PIPE, stderr=PIPE, shell=True) + callstring = self.scriptPath + ' ' + self.env['general']['currUser'] + p = Popen(callstring , stdout=PIPE, stderr=PIPE, shell=True) stdout, stderr = p.communicate() + stdout = stdout.decode('utf-8') + stderr = stderr.decode('utf-8') self.env['runtime']['outputManager'].interruptOutput() - screenEncoding = self.env['runtime']['settingsManager'].getSetting('screen', 'encoding') - 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(stdout , soundIcon='', interrupt=False) + self.env['runtime']['outputManager'].presentText(str(stderr) , soundIcon='', interrupt=False) if stdout != '': - self.env['runtime']['outputManager'].presentText(stdout , soundIcon='', interrupt=False) + self.env['runtime']['outputManager'].presentText(str(stdout) , soundIcon='', interrupt=False) except Exception as e: self.env['runtime']['outputManager'].presentText(e , soundIcon='', interrupt=False) diff --git a/src/fenrir/commands/commands/temp_disable_speech.py b/src/fenrir/commands/commands/temp_disable_speech.py index 9fa577d..c560e78 100644 --- a/src/fenrir/commands/commands/temp_disable_speech.py +++ b/src/fenrir/commands/commands/temp_disable_speech.py @@ -14,11 +14,11 @@ def shutdown(self): pass def getDescription(self): - return 'disables speech until next keypress' + return _('disables speech until next keypress') def run(self): if self.env['runtime']['settingsManager'].getSettingAsBool('speech', 'enabled'): - self.env['runtime']['outputManager'].presentText("speech temporary disabled", soundIcon='SpeechOff', interrupt=True) + self.env['runtime']['outputManager'].presentText(_("speech temporary disabled"), soundIcon='SpeechOff', interrupt=True) self.env['commandBuffer']['enableSpeechOnKeypress'] = True self.env['runtime']['settingsManager'].setSetting('speech', 'enabled', str(not self.env['runtime']['settingsManager'].getSettingAsBool('speech', 'enabled'))) self.env['runtime']['outputManager'].interruptOutput() diff --git a/src/fenrir/commands/commands/time.py b/src/fenrir/commands/commands/time.py index f34e9c0..4c6aa9d 100644 --- a/src/fenrir/commands/commands/time.py +++ b/src/fenrir/commands/commands/time.py @@ -15,7 +15,7 @@ def shutdown(self): pass def getDescription(self): - return 'presents the time' + return _('presents the time') def run(self): timeFormat = self.env['runtime']['settingsManager'].getSetting('general', 'timeFormat') diff --git a/src/fenrir/commands/commands/toggle_auto_read.py b/src/fenrir/commands/commands/toggle_auto_read.py index 3090e2b..d60e9da 100644 --- a/src/fenrir/commands/commands/toggle_auto_read.py +++ b/src/fenrir/commands/commands/toggle_auto_read.py @@ -13,14 +13,14 @@ def shutdown(self): pass def getDescription(self): - return 'enables or disables automatic reading of new text as it appears' + return _('enables or disables automatic reading of new text as it appears') def run(self): self.env['runtime']['settingsManager'].setSetting('speech', 'autoReadIncoming', str(not self.env['runtime']['settingsManager'].getSettingAsBool('speech', 'autoReadIncoming'))) if self.env['runtime']['settingsManager'].getSettingAsBool('speech', 'autoReadIncoming'): - self.env['runtime']['outputManager'].presentText("autoread enabled", soundIcon='', interrupt=True) + self.env['runtime']['outputManager'].presentText(_("autoread enabled"), soundIcon='', interrupt=True) else: - self.env['runtime']['outputManager'].presentText("autoread disabled", soundIcon='', interrupt=True) + self.env['runtime']['outputManager'].presentText(_("autoread disabled"), soundIcon='', interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/toggle_auto_spell_check.py b/src/fenrir/commands/commands/toggle_auto_spell_check.py index 3e6028c..19d1e06 100644 --- a/src/fenrir/commands/commands/toggle_auto_spell_check.py +++ b/src/fenrir/commands/commands/toggle_auto_spell_check.py @@ -14,14 +14,14 @@ def shutdown(self): pass def getDescription(self): - return 'enables or disables automatic spell checking' + return _('enables or disables automatic spell checking') def run(self): self.env['runtime']['settingsManager'].setSetting('general', 'autoSpellCheck', str(not self.env['runtime']['settingsManager'].getSettingAsBool('general', 'autoSpellCheck'))) if self.env['runtime']['settingsManager'].getSettingAsBool('general', 'autoSpellCheck'): - self.env['runtime']['outputManager'].presentText("auto spellcheck enabled", soundIcon='', interrupt=True) + self.env['runtime']['outputManager'].presentText(_("auto spellcheck enabled"), soundIcon='', interrupt=True) else: - self.env['runtime']['outputManager'].presentText("auto spellcheck disabled", soundIcon='', interrupt=True) + self.env['runtime']['outputManager'].presentText(_("auto spellcheck disabled"), soundIcon='', interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/toggle_auto_time.py b/src/fenrir/commands/commands/toggle_auto_time.py index 98f7c5d..831cca4 100644 --- a/src/fenrir/commands/commands/toggle_auto_time.py +++ b/src/fenrir/commands/commands/toggle_auto_time.py @@ -13,14 +13,14 @@ def shutdown(self): pass def getDescription(self): - return 'enables or disables automatic reading of time after an period' + return _('enables or disables automatic reading of time after an period') def run(self): self.env['runtime']['settingsManager'].setSetting('time', 'enabled', str(not self.env['runtime']['settingsManager'].getSettingAsBool('time', 'enabled'))) if self.env['runtime']['settingsManager'].getSettingAsBool('time', 'enabled'): - self.env['runtime']['outputManager'].presentText("autotime enabled", soundIcon='', interrupt=True) + self.env['runtime']['outputManager'].presentText(_("autotime enabled"), soundIcon='', interrupt=True) else: - self.env['runtime']['outputManager'].presentText("autotime disabled", soundIcon='', interrupt=True) + self.env['runtime']['outputManager'].presentText(_("autotime disabled"), soundIcon='', interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/toggle_braille.py b/src/fenrir/commands/commands/toggle_braille.py index 9aed343..0929d48 100644 --- a/src/fenrir/commands/commands/toggle_braille.py +++ b/src/fenrir/commands/commands/toggle_braille.py @@ -14,14 +14,14 @@ def shutdown(self): pass def getDescription(self): - return 'enables and disables output in braille' + return _('enables and disables output in braille') def run(self): if self.env['runtime']['settingsManager'].getSettingAsBool('braille', 'enabled'): - self.env['runtime']['outputManager'].presentText("braille disabled", soundIcon='BrailleOff', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('braille disabled'), soundIcon='BrailleOff', interrupt=True) self.env['runtime']['settingsManager'].setSetting('braille', 'enabled', str(not self.env['runtime']['settingsManager'].getSettingAsBool('braille', 'enabled'))) if self.env['runtime']['settingsManager'].getSettingAsBool('braille', 'enabled'): - self.env['runtime']['outputManager'].presentText("braille enabled", soundIcon='BrailleOn', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('braille enabled'), soundIcon='BrailleOn', interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/toggle_emoticons.py b/src/fenrir/commands/commands/toggle_emoticons.py index fc1872d..e44e6da 100644 --- a/src/fenrir/commands/commands/toggle_emoticons.py +++ b/src/fenrir/commands/commands/toggle_emoticons.py @@ -13,14 +13,14 @@ def shutdown(self): pass def getDescription(self): - return 'enables or disables announcement of emoticons insteed of chars' + return _('enables or disables announcement of emoticons instead of chars') def run(self): self.env['runtime']['settingsManager'].setSetting('general', 'emoticons', str(not self.env['runtime']['settingsManager'].getSettingAsBool('general', 'emoticons'))) if self.env['runtime']['settingsManager'].getSettingAsBool('general', 'emoticons'): - self.env['runtime']['outputManager'].presentText("emoticons enabled", soundIcon='', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('emoticons enabled'), soundIcon='', interrupt=True) else: - self.env['runtime']['outputManager'].presentText("emoticons disabled", soundIcon='', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('emoticons disabled'), soundIcon='', interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/toggle_highlight_tracking.py b/src/fenrir/commands/commands/toggle_highlight_tracking.py index 628e244..bc2f510 100644 --- a/src/fenrir/commands/commands/toggle_highlight_tracking.py +++ b/src/fenrir/commands/commands/toggle_highlight_tracking.py @@ -13,7 +13,7 @@ def shutdown(self): pass def getDescription(self): - return 'enables or disables tracking of highlighted' + return _('enables or disables tracking of highlighted text') def run(self): currMode = self.env['runtime']['settingsManager'].getSettingAsBool('focus', 'highlight') @@ -21,9 +21,9 @@ self.env['runtime']['settingsManager'].setSetting('focus', 'highlight', str(not currMode)) self.env['runtime']['settingsManager'].setSetting('focus', 'cursor', str(currMode)) if self.env['runtime']['settingsManager'].getSettingAsBool('focus', 'highlight'): - self.env['runtime']['outputManager'].presentText("highlight tracking", soundIcon='', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('highlight tracking'), soundIcon='', interrupt=True) else: - self.env['runtime']['outputManager'].presentText("cursor tracking", soundIcon='', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('cursor tracking'), soundIcon='', interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/toggle_output.py b/src/fenrir/commands/commands/toggle_output.py index 9570865..a1b29ce 100644 --- a/src/fenrir/commands/commands/toggle_output.py +++ b/src/fenrir/commands/commands/toggle_output.py @@ -14,13 +14,13 @@ def shutdown(self): pass def getDescription(self): - return 'toggles all output settings' + return _('toggles all output settings') def run(self): if self.env['runtime']['settingsManager'].getSettingAsBool('speech', 'enabled') or \ self.env['runtime']['settingsManager'].getSettingAsBool('sound', 'enabled') or \ self.env['runtime']['settingsManager'].getSettingAsBool('braille', 'enabled'): - self.env['runtime']['outputManager'].presentText("fenrir muted", soundIcon='Accept', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Fenrir muted'), soundIcon='Accept', interrupt=True) self.env['runtime']['settingsManager'].setSetting('speech', 'enabled','False') self.env['runtime']['settingsManager'].setSetting('sound', 'enabled','False') self.env['runtime']['settingsManager'].setSetting('braille', 'enabled','False') @@ -28,7 +28,7 @@ self.env['runtime']['settingsManager'].setSetting('speech', 'enabled','True') self.env['runtime']['settingsManager'].setSetting('sound', 'enabled','True') self.env['runtime']['settingsManager'].setSetting('braille', 'enabled','True') - self.env['runtime']['outputManager'].presentText("fenrir unmuted", soundIcon='Cancel', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('Fenrir unmuted'), soundIcon='Cancel', interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/toggle_punctuation_level.py b/src/fenrir/commands/commands/toggle_punctuation_level.py index b87789b..257ff0f 100644 --- a/src/fenrir/commands/commands/toggle_punctuation_level.py +++ b/src/fenrir/commands/commands/toggle_punctuation_level.py @@ -20,7 +20,7 @@ if self.env['runtime']['punctuationManager'].cyclePunctuation(): self.env['runtime']['outputManager'].presentText(self.env['runtime']['settingsManager'].getSetting('general', 'punctuationLevel'), interrupt=True, ignorePunctuation=True) else: - self.env['runtime']['outputManager'].presentText('No punctuation found.', interrupt=True, ignorePunctuation=True) + self.env['runtime']['outputManager'].presentText(_('No punctuation found.'), interrupt=True, ignorePunctuation=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/toggle_sound.py b/src/fenrir/commands/commands/toggle_sound.py index bc7c5a8..8febec8 100644 --- a/src/fenrir/commands/commands/toggle_sound.py +++ b/src/fenrir/commands/commands/toggle_sound.py @@ -14,14 +14,14 @@ def shutdown(self): pass def getDescription(self): - return 'enables or disables sound' + return _('enables or disables sound') def run(self): if self.env['runtime']['settingsManager'].getSettingAsBool('sound', 'enabled'): - self.env['runtime']['outputManager'].presentText("sound disabled", soundIcon='SoundOff', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('sound disabled'), soundIcon='SoundOff', interrupt=True) self.env['runtime']['settingsManager'].setSetting('sound', 'enabled', str(not self.env['runtime']['settingsManager'].getSettingAsBool('sound', 'enabled'))) if self.env['runtime']['settingsManager'].getSettingAsBool('sound', 'enabled'): - self.env['runtime']['outputManager'].presentText("sound enabled", soundIcon='SoundOn', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('sound enabled'), soundIcon='SoundOn', interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/toggle_speech.py b/src/fenrir/commands/commands/toggle_speech.py index 971c957..83675c0 100644 --- a/src/fenrir/commands/commands/toggle_speech.py +++ b/src/fenrir/commands/commands/toggle_speech.py @@ -14,14 +14,14 @@ def shutdown(self): pass def getDescription(self): - return 'enables or disables speech' + return _('enables or disables speech') def run(self): if self.env['runtime']['settingsManager'].getSettingAsBool('speech', 'enabled'): - self.env['runtime']['outputManager'].presentText("speech disabled", soundIcon='SpeechOff', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('speech disabled'), soundIcon='SpeechOff', interrupt=True) self.env['runtime']['settingsManager'].setSetting('speech', 'enabled', str(not self.env['runtime']['settingsManager'].getSettingAsBool('speech', 'enabled'))) if self.env['runtime']['settingsManager'].getSettingAsBool('speech', 'enabled'): - self.env['runtime']['outputManager'].presentText("speech enabled", soundIcon='SpeechOn', interrupt=True) + self.env['runtime']['outputManager'].presentText(_('speech enabled'), soundIcon='SpeechOn', interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/commands/toggle_tutorial_mode.py b/src/fenrir/commands/commands/toggle_tutorial_mode.py index e5ad15c..8c89f95 100644 --- a/src/fenrir/commands/commands/toggle_tutorial_mode.py +++ b/src/fenrir/commands/commands/toggle_tutorial_mode.py @@ -14,13 +14,11 @@ def shutdown(self): pass def getDescription(self): - self.env['generalInformation']['tutorialMode'] = False - return 'You are leving the tutorial mode. Press that shortcut again to enter the tutorial mode again.' - + self.env['runtime']['helpManager'].toggleTutorialMode() + #self.env['runtime']['outputManager'].presentText(, interrupt=True) + return _('You are leaving the tutorial mode. Press that shortcut again to enter the tutorial mode again.') def run(self): - text = 'you entered the tutorial mode. In that mode the commands are not executed. but you get a description of what the shortcut does. To leve the tutorial mode, press that shortcut again.' - self.env['runtime']['outputManager'].presentText(text, interrupt=True) - self.env['generalInformation']['tutorialMode'] = True - + self.env['runtime']['helpManager'].toggleTutorialMode() + self.env['runtime']['outputManager'].presentText( _('you entered the tutorial mode. In that mode the commands are not executed. but you get a description of what the shortcut does. To leave the tutorial mode, press that shortcut again.'), interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/help/Readme.txt b/src/fenrir/commands/help/Readme.txt new file mode 100644 index 0000000..c90f7a6 --- /dev/null +++ b/src/fenrir/commands/help/Readme.txt @@ -0,0 +1,2 @@ +this folder contains help and tutorial related functions. +those are not bindable but hard coded. diff --git a/src/fenrir/commands/help/__init__.py b/src/fenrir/commands/help/__init__.py new file mode 100755 index 0000000..e69de29 diff --git a/src/fenrir/commands/help/curr_help.py b/src/fenrir/commands/help/curr_help.py new file mode 100644 index 0000000..1de0abc --- /dev/null +++ b/src/fenrir/commands/help/curr_help.py @@ -0,0 +1,22 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('get current help message') + def run(self): + text = self.env['runtime']['helpManager'].getHelpForCurrentIndex() + self.env['runtime']['outputManager'].presentText(text, interrupt=True) + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/help/next_help.py b/src/fenrir/commands/help/next_help.py new file mode 100644 index 0000000..0f268aa --- /dev/null +++ b/src/fenrir/commands/help/next_help.py @@ -0,0 +1,23 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('get next help message') + def run(self): + self.env['runtime']['helpManager'].nextIndex() + text = self.env['runtime']['helpManager'].getHelpForCurrentIndex() + self.env['runtime']['outputManager'].presentText(text, interrupt=True) + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/help/prev_help.py b/src/fenrir/commands/help/prev_help.py new file mode 100644 index 0000000..31eccbb --- /dev/null +++ b/src/fenrir/commands/help/prev_help.py @@ -0,0 +1,23 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('get prev help message') + def run(self): + self.env['runtime']['helpManager'].prevIndex() + text = self.env['runtime']['helpManager'].getHelpForCurrentIndex() + self.env['runtime']['outputManager'].presentText(text, interrupt=True) + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/onApplicationChange/inactive/test.py b/src/fenrir/commands/onApplicationChange/inactive/test.py new file mode 100644 index 0000000..f17d816 --- /dev/null +++ b/src/fenrir/commands/onApplicationChange/inactive/test.py @@ -0,0 +1,25 @@ +#!/bi[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]/py[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]ho[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']] +# -*- [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]odi[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]g: u[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]f-8 -*- + +# F[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]i[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']] TTY [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']] [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]d[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']] +# By Ch[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]y[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']], S[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]o[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]m [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]go[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']], [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]d [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]o[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]ibu[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]. + +f[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]om [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]o[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']] impo[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']] d[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]bug + +[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]l[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']] [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]omm[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]d(): + d[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]f __i[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]i[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]__([['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]lf): + p[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']] + d[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]f i[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]i[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]i[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]liz[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]([['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]lf, [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]vi[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]o[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]m[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]): + [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]lf.[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]v = [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]vi[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]o[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]m[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']] + d[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]f [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]hu[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]dow[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]([['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]lf): + p[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']] + d[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]f g[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]ip[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]io[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]([['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]lf): + [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]u[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']] [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]No d[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]ip[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]io[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']] fou[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]d[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']] + d[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]f [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]u[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]([['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]lf): + #p[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]i[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]([['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]w [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']], [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]lf.[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]v[[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]][[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]wAppli[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]io[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]]) + #p[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]i[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]([['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]old [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']], [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]lf.[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]v[[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]][[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]oldAppli[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]io[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]]) + #p[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]i[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]([['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]-----------[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]) + p[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']] + + d[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]f [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]C[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]llb[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]k([['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]lf, [['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]llb[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']]k): + p[['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']][['screen']['screen']['screen']['screen']['screen']['screen']['screen']['screen']] diff --git a/src/fenrir/commands/onApplicationChange/test.py b/src/fenrir/commands/onApplicationChange/test.py deleted file mode 100644 index ca4d74b..0000000 --- a/src/fenrir/commands/onApplicationChange/test.py +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from core import debug - -class command(): - def __init__(self): - pass - def initialize(self, environment): - self.env = environment - def shutdown(self): - pass - def getDescription(self): - return 'No description found' - def run(self): - #print('new ', self.env['screenData']['newApplication']) - #print('old ', self.env['screenData']['oldApplication']) - #print('-----------') - pass - - def setCallback(self, callback): - pass diff --git a/src/fenrir/commands/onCursorChange/45000-char_echo.py b/src/fenrir/commands/onCursorChange/45000-char_echo.py new file mode 100644 index 0000000..e84eb6e --- /dev/null +++ b/src/fenrir/commands/onCursorChange/45000-char_echo.py @@ -0,0 +1,40 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'No Description found' + + def run(self): + if not self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'charEcho'): + return + # detect deletion or chilling + if self.env['screen']['newCursor']['x'] <= self.env['screen']['oldCursor']['x']: + return + # is there any change? + if not self.env['runtime']['screenManager'].isDelta(): + 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) + if len(self.env['screen']['newDelta'].strip(' \n\t')) > 1: + return + # filter unneded space on word begin + currDelta = self.env['screen']['newDelta'] + if len(currDelta.strip()) != len(currDelta) and \ + currDelta.strip() != '': + currDelta = currDelta.strip() + self.env['runtime']['outputManager'].presentText(currDelta, interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) + + def setCallback(self, callback): + pass + diff --git a/src/fenrir/commands/onCursorChange/50000-present_char_if_cursor_change_horizontal.py b/src/fenrir/commands/onCursorChange/50000-present_char_if_cursor_change_horizontal.py new file mode 100644 index 0000000..1a684f1 --- /dev/null +++ b/src/fenrir/commands/onCursorChange/50000-present_char_if_cursor_change_horizontal.py @@ -0,0 +1,50 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +from 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 '' + + def run(self): + if not self.env['runtime']['settingsManager'].getSettingAsBool('focus', 'cursor'): + return + if self.env['runtime']['screenManager'].isScreenChange(): + return + # detect an change on the screen, we just want to cursor arround, so no change should appear + if self.env['runtime']['screenManager'].isDelta(): + return + if self.env['runtime']['screenManager'].isNegativeDelta(): + return + # is a vertical change? + if self.env['runtime']['cursorManager'].isCursorVerticalMove(): + return + # is it a horizontal change? + if not self.env['runtime']['cursorManager'].isCursorHorizontalMove(): + return + # echo word insteed of char + if self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'wordEcho'): + if abs(self.env['screen']['oldCursor']['x'] - self.env['screen']['newCursor']['x']) != 1: + # get the word + newContent = self.env['screen']['newContentText'].split('\n')[self.env['screen']['newCursor']['y']] + x, y, currWord, endOfScreen, lineBreak = \ + word_utils.getCurrentWord(self.env['screen']['newCursor']['x'], 0, newContent) + if self.env['screen']['newCursor']['x'] == x: + return + x, y, currChar = char_utils.getCurrentChar(self.env['screen']['newCursor']['x'], self.env['screen']['newCursor']['y'], self.env['screen']['newContentText']) + if not currChar.isspace(): + self.env['runtime']['outputManager'].presentText(currChar, interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) + def setCallback(self, callback): + pass + diff --git a/src/fenrir/commands/onCursorChange/55000-present_line_if_cursor_change_vertical.py b/src/fenrir/commands/onCursorChange/55000-present_line_if_cursor_change_vertical.py new file mode 100644 index 0000000..fb0bd72 --- /dev/null +++ b/src/fenrir/commands/onCursorChange/55000-present_line_if_cursor_change_vertical.py @@ -0,0 +1,43 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +from utils import line_utils +from utils import word_utils + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return '' + + def run(self): + if not self.env['runtime']['settingsManager'].getSettingAsBool('focus', 'cursor'): + return + if self.env['runtime']['screenManager'].isScreenChange(): + return + # this leads to problems in vim -> status line change -> no announcement, so we do check the lengh as hack + if self.env['runtime']['screenManager'].isDelta(): + return + + # is a vertical change? + if not self.env['runtime']['cursorManager'].isCursorVerticalMove(): + return + + x, y, currLine = line_utils.getCurrentLine(self.env['screen']['newCursor']['x'], self.env['screen']['newCursor']['y'], self.env['screen']['newContentText']) + + if currLine.isspace(): + self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True, flush=False) + else: + self.env['runtime']['outputManager'].presentText(currLine, interrupt=True, flush=False) + + def setCallback(self, callback): + pass + diff --git a/src/fenrir/commands/onCursorChange/60000-word_echo_type.py b/src/fenrir/commands/onCursorChange/60000-word_echo_type.py new file mode 100644 index 0000000..995dd85 --- /dev/null +++ b/src/fenrir/commands/onCursorChange/60000-word_echo_type.py @@ -0,0 +1,58 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +from utils import word_utils +import string + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'No Description found' + + def run(self): + # is it enabled? + if not self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'wordEcho'): + return + # is naviation? + if self.env['screen']['newCursor']['x'] - self.env['screen']['oldCursor']['x'] != 1: + return + # just when cursor move worddetection is needed + if not self.env['runtime']['cursorManager'].isCursorHorizontalMove(): + return + # for now no new line + if self.env['runtime']['cursorManager'].isCursorVerticalMove(): + return + # currently writing + if self.env['runtime']['screenManager'].isDelta(): + return + + # get the word + newContent = self.env['screen']['newContentText'].split('\n')[self.env['screen']['newCursor']['y']] + x, y, currWord, endOfScreen, lineBreak = \ + word_utils.getCurrentWord(self.env['screen']['newCursor']['x'], 0, newContent) + + # is there a word? + if currWord == '': + return + # at the end of a word + if not newContent[self.env['screen']['newCursor']['x']].isspace(): + return + # at the end of a word + if (x + len(currWord) != self.env['screen']['newCursor']['x']) and \ + (x + len(currWord) != self.env['screen']['newCursor']['x']-1): + return + + self.env['runtime']['outputManager'].presentText(currWord, interrupt=True, flush=False) + + def setCallback(self, callback): + pass + diff --git a/src/fenrir/commands/onCursorChange/61000-word_echo_navigation.py b/src/fenrir/commands/onCursorChange/61000-word_echo_navigation.py new file mode 100644 index 0000000..69963a1 --- /dev/null +++ b/src/fenrir/commands/onCursorChange/61000-word_echo_navigation.py @@ -0,0 +1,54 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +from utils import word_utils +import string + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'No Description found' + + def run(self): + # is navigation? + if not abs(self.env['screen']['oldCursor']['x'] - self.env['screen']['newCursor']['x']) > 1: + return + + # just when cursor move worddetection is needed + if not self.env['runtime']['cursorManager'].isCursorHorizontalMove(): + return + # for now no new line + if self.env['runtime']['cursorManager'].isCursorVerticalMove(): + return + # currently writing + if self.env['runtime']['screenManager'].isDelta(): + return + + # get the word + newContent = self.env['screen']['newContentText'].split('\n')[self.env['screen']['newCursor']['y']] + x, y, currWord, endOfScreen, lineBreak = \ + word_utils.getCurrentWord(self.env['screen']['newCursor']['x'], 0, newContent) + + # is there a word? + if currWord == '': + return + + # at the start of a word + if (x + len(currWord) != self.env['screen']['newCursor']['x']) and \ + (self.env['screen']['newCursor']['x'] != x): + return + + self.env['runtime']['outputManager'].presentText(currWord, interrupt=True, flush=False) + + def setCallback(self, callback): + pass + diff --git a/src/fenrir/commands/onCursorChange/62000-spell_check.py b/src/fenrir/commands/onCursorChange/62000-spell_check.py new file mode 100644 index 0000000..2894d27 --- /dev/null +++ b/src/fenrir/commands/onCursorChange/62000-spell_check.py @@ -0,0 +1,134 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +from utils import word_utils +import os, string + +initialized = False +try: + import enchant + initialized = True +except: + pass + +class command(): + def __init__(self): + self.language = '' + self.spellChecker = '' + def initialize(self, environment): + self.env = environment + self.updateSpellLanguage() + def shutdown(self): + pass + def getDescription(self): + return 'No Description found' + + def updateSpellLanguage(self): + if not initialized: + self.env['runtime']['outputManager'].presentText('pychant is not installed', interrupt=True) + return + self.spellChecker = enchant.Dict(self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage')) + self.language = self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage') + + def run(self): + if not initialized: + return + if not self.env['runtime']['settingsManager'].getSettingAsBool('general', 'autoSpellCheck'): + return + if self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage') != self.language: + try: + self.updateSpellLanguage() + except: + return + + # just when horizontal cursor move worddetection is needed + if not self.env['runtime']['cursorManager'].isCursorHorizontalMove(): + return + + # for now no new line + if self.env['runtime']['cursorManager'].isCursorVerticalMove(): + return + # more than a keyecho? + if len(self.env['screen']['newDelta']) > 1: + return + # deletion + if self.env['runtime']['screenManager'].isNegativeDelta(): + return + # first place could not be the end of a word + if self.env['screen']['newCursor']['x'] == 0: + return + + # get the word (just for speedup only look at current line + newContent = self.env['screen']['newContentText'].split('\n')[self.env['screen']['newCursor']['y']] + x, y, currWord, endOfScreen, lineBreak = word_utils.getCurrentWord(self.env['screen']['newCursor']['x'], 0, newContent) + # was this a typed word? + if self.env['runtime']['screenManager'].isDelta(): + if not(newContent[self.env['screen']['oldCursor']['x']] in string.whitespace + '!"#$%&()*+,-./:;<=>?@[\\]^_{|}~' and x != self.env['screen']['oldCursor']['x']): + return + else: + currWord = currWord.strip(string.whitespace + '!"#$%&()*+,-./:;<=>?@[\\]^_{|}~') + else: + # or just arrow arround? + if not newContent[self.env['screen']['newCursor']['x']].isspace(): + return + if (x + len(currWord) != self.env['screen']['newCursor']['x']) and \ + (x + len(currWord) != self.env['screen']['newCursor']['x']-1): + return + + # just on end of word + if self.env['screen']['newCursor']['x'] > 0: + if not newContent[self.env['screen']['oldCursor']['x'] - 1].lower() in string.ascii_lowercase: + return + + # ignore bash buildins + if currWord in ['cd','fg','bg','alias','bind','dir','caller','buildin','command','declare','echo','enable','help','let','local','logout',\ + 'mapfile','printf','read','readarray','source','type','typeset','ulimit','unalias']: + return + # ignore the application name + if currWord.upper() == 'FENRIR': + return + if currWord[0] =='-': + return + if currWord[0] == '/': + return + if currWord[0] == '#': + return + if currWord.startswith('./'): + return + if '@' in currWord and '.' in currWord: + return + if currWord[0] == '@': + return + if currWord.isnumeric(): + return + if currWord.isdecimal(): + return + if currWord.isspace(): + return + + try: + if os.path.exists("/bin/"+currWord): + return + except: + pass + try: + if os.path.exists("/usr/bin/"+currWord): + return + except: + pass + try: + if os.path.exists("/sbin/"+currWord): + return + except: + pass + + if not self.spellChecker.check(currWord): + self.env['runtime']['outputManager'].presentText(_('misspelled'), soundIcon='mispell', interrupt=False, flush=False) + + def setCallback(self, callback): + pass + diff --git a/src/fenrir/commands/onCursorChange/65000-char_delete_echo.py b/src/fenrir/commands/onCursorChange/65000-char_delete_echo.py new file mode 100644 index 0000000..8bff19c --- /dev/null +++ b/src/fenrir/commands/onCursorChange/65000-char_delete_echo.py @@ -0,0 +1,44 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'No Description found' + + def run(self): + if not self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'charDeleteEcho'): + return + # detect typing or chilling + if self.env['screen']['newCursor']['x'] >= self.env['screen']['oldCursor']['x']: + return + + # More than just a deletion happend + if self.env['runtime']['screenManager'].isDelta(): + return + # no deletion + if not self.env['runtime']['screenManager'].isNegativeDelta(): + return + + # too much for a single backspace... + # word begin produce a diff wiht len == 2 |a | others with 1 |a| + if len(self.env['screen']['newNegativeDelta']) > 2: + return + currNegativeDelta = self.env['screen']['newNegativeDelta'] + if len(currNegativeDelta.strip()) != len(currNegativeDelta) and \ + currNegativeDelta.strip() != '': + currNegativeDelta = currNegativeDelta.strip() + self.env['runtime']['outputManager'].presentText(currNegativeDelta, interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False) + def setCallback(self, callback): + pass + diff --git a/src/fenrir/commands/onCursorChange/66000-exit_review_mode.py b/src/fenrir/commands/onCursorChange/66000-exit_review_mode.py new file mode 100644 index 0000000..2f7a8cf --- /dev/null +++ b/src/fenrir/commands/onCursorChange/66000-exit_review_mode.py @@ -0,0 +1,26 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('exits review mode') + + def run(self): + if not self.env['runtime']['settingsManager'].getSettingAsBool('review', 'leaveReviewOnCursorChange'): + return + if self.env['runtime']['cursorManager'].isReviewMode(): + self.env['runtime']['cursorManager'].clearReviewCursor() + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/onCursorChange/__init__.py b/src/fenrir/commands/onCursorChange/__init__.py new file mode 100755 index 0000000..e69de29 diff --git a/src/fenrir/commands/onHeartBeat/2000-GetSessionInfo.py b/src/fenrir/commands/onHeartBeat/2000-GetSessionInfo.py new file mode 100755 index 0000000..b4d822a --- /dev/null +++ b/src/fenrir/commands/onHeartBeat/2000-GetSessionInfo.py @@ -0,0 +1,29 @@ +#!/bin/python +import time +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +import time +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): + self.env['runtime']['screenDriver'].getSessionInformation() + def setCallback(self, callback): + pass + diff --git a/src/fenrir/commands/onHeartBeat/76000-time.py b/src/fenrir/commands/onHeartBeat/76000-time.py new file mode 100755 index 0000000..3b9b55b --- /dev/null +++ b/src/fenrir/commands/onHeartBeat/76000-time.py @@ -0,0 +1,74 @@ +#!/bin/python +import time +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +import time +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 + else: + # shoul announce? + if not str(now.minute) 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 + 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) + + if self.env['runtime']['settingsManager'].getSettingAsBool('time', 'interrupt'): + self.env['runtime']['outputManager'].interruptOutput() + if self.env['runtime']['settingsManager'].getSettingAsBool('time', 'announce'): + self.env['runtime']['outputManager'].playSoundIcon('announce') + + if presentTime: + # present the time + self.env['runtime']['outputManager'].presentText(_('Autotime: {0}').format(timeString), soundIcon='', interrupt=False) + # and date if changes + if presentDate: + self.env['runtime']['outputManager'].presentText(dateString , soundIcon='', interrupt=False) + self.lastDateString = dateString + self.lastTime = datetime.datetime.now() + self.lastTimeString = timeString + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/onHeartBeat/__init__.py b/src/fenrir/commands/onHeartBeat/__init__.py new file mode 100755 index 0000000..e69de29 diff --git a/src/fenrir/commands/onHeartBeat/deactive/1.echo.py b/src/fenrir/commands/onHeartBeat/deactive/1.echo.py new file mode 100755 index 0000000..678dc9c --- /dev/null +++ b/src/fenrir/commands/onHeartBeat/deactive/1.echo.py @@ -0,0 +1,26 @@ +#!/bin/python +import time +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +import time + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + + def shutdown(self): + pass + def getDescription(self): + return 'No Description found' + + def run(self): + print(time.time()) + def setCallback(self, callback): + pass + diff --git a/src/fenrir/commands/onInput/10000-shut_up.py b/src/fenrir/commands/onInput/10000-shut_up.py index a12c5ba..b3a2dea 100644 --- a/src/fenrir/commands/onInput/10000-shut_up.py +++ b/src/fenrir/commands/onInput/10000-shut_up.py @@ -23,7 +23,7 @@ return if self.env['runtime']['screenManager'].isScreenChange(): return - if len(self.env['input']['prevDeepestInput']) > len(self.env['input']['currInput']): + if len(self.env['input']['currInput']) <= len(self.env['input']['prevInput']): return # if the filter is set if self.env['runtime']['settingsManager'].getSetting('keyboard', 'interruptOnKeyPressFilter').strip() != '': diff --git a/src/fenrir/commands/onInput/15000-enable_temp_speech.py b/src/fenrir/commands/onInput/15000-enable_temp_speech.py index e9d3d85..a6de077 100644 --- a/src/fenrir/commands/onInput/15000-enable_temp_speech.py +++ b/src/fenrir/commands/onInput/15000-enable_temp_speech.py @@ -14,7 +14,7 @@ def shutdown(self): pass def getDescription(self): - return 'disables speech until next keypress' + return _('disables speech until next keypress') def run(self): if self.env['runtime']['inputManager'].noKeyPressed(): @@ -25,7 +25,7 @@ return self.env['runtime']['settingsManager'].setSetting('speech', 'enabled', str(self.env['commandBuffer']['enableSpeechOnKeypress'])) self.env['commandBuffer']['enableSpeechOnKeypress'] = False - self.env['runtime']['outputManager'].presentText("speech enabled", soundIcon='SpeechOn', interrupt=True) + self.env['runtime']['outputManager'].presentText(_("speech enabled"), soundIcon='SpeechOn', interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/onInput/45000-present_char_if_cursor_change_horizontal.py b/src/fenrir/commands/onInput/45000-present_char_if_cursor_change_horizontal.py deleted file mode 100644 index 0926b53..0000000 --- a/src/fenrir/commands/onInput/45000-present_char_if_cursor_change_horizontal.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from core import debug -from 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 '' - - def run(self): - if not self.env['runtime']['settingsManager'].getSettingAsBool('focus', 'cursor'): - return - if self.env['runtime']['screenManager'].isScreenChange(): - return - if self.env['runtime']['inputManager'].noKeyPressed(): - return - # detect an change on the screen, we just want to cursor arround, so no change should appear - if self.env['runtime']['screenManager'].isDelta(): - return - if self.env['runtime']['screenManager'].isNegativeDelta(): - return - # is a vertical change? - if self.env['runtime']['cursorManager'].isCursorVerticalMove(): - return - # is it a horizontal change? - if not self.env['runtime']['cursorManager'].isCursorHorizontalMove(): - return - x, y, currChar = char_utils.getCurrentChar(self.env['screenData']['newCursor']['x'], self.env['screenData']['newCursor']['y'], self.env['screenData']['newContentText']) - if not currChar.isspace(): - self.env['runtime']['outputManager'].presentText(currChar, interrupt=True, ignorePunctuation=True, announceCapital=True) - def setCallback(self, callback): - pass - diff --git a/src/fenrir/commands/onInput/50000-char_echo.py b/src/fenrir/commands/onInput/50000-char_echo.py deleted file mode 100644 index 3e28265..0000000 --- a/src/fenrir/commands/onInput/50000-char_echo.py +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from core import debug - -class command(): - def __init__(self): - pass - def initialize(self, environment): - self.env = environment - def shutdown(self): - pass - def getDescription(self): - return 'No Description found' - - def run(self): - if not self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'charEcho'): - return - # detect deletion or chilling - if self.env['screenData']['newCursor']['x'] <= self.env['screenData']['oldCursor']['x']: - return - # is there any change? - if not self.env['runtime']['screenManager'].isDelta(): - 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) - if len(self.env['screenData']['newDelta']) > 3: - return - # filter unneded space on word begin - currDelta = self.env['screenData']['newDelta'] - if len(currDelta.strip()) != len(currDelta) and \ - currDelta.strip() != '': - currDelta = currDelta.strip() - self.env['runtime']['outputManager'].presentText(currDelta, interrupt=True, ignorePunctuation=True, announceCapital=True) - - def setCallback(self, callback): - pass - diff --git a/src/fenrir/commands/onInput/55000-present_line_if_cursor_change_vertical.py b/src/fenrir/commands/onInput/55000-present_line_if_cursor_change_vertical.py deleted file mode 100644 index 14a840c..0000000 --- a/src/fenrir/commands/onInput/55000-present_line_if_cursor_change_vertical.py +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from core import debug -from 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 '' - - def run(self): - if not self.env['runtime']['settingsManager'].getSettingAsBool('focus', 'cursor'): - return - if self.env['runtime']['inputManager'].noKeyPressed(): - return - if self.env['runtime']['screenManager'].isScreenChange(): - return - if self.env['runtime']['screenManager'].isDelta(): - return - # is a vertical change? - if not self.env['runtime']['cursorManager'].isCursorVerticalMove(): - return - - x, y, currLine = line_utils.getCurrentLine(self.env['screenData']['newCursor']['x'], self.env['screenData']['newCursor']['y'], self.env['screenData']['newContentText']) - - if currLine.isspace(): - self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) - else: - self.env['runtime']['outputManager'].presentText(currLine, interrupt=True) - - def setCallback(self, callback): - pass - diff --git a/src/fenrir/commands/onInput/56000-highlight_tracking.py b/src/fenrir/commands/onInput/56000-highlight_tracking.py deleted file mode 100644 index 4f75f49..0000000 --- a/src/fenrir/commands/onInput/56000-highlight_tracking.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from core import debug -class command(): - def __init__(self): - pass - def initialize(self, environment): - self.env = environment - def shutdown(self): - pass - def getDescription(self): - return 'enables or disables tracking of highlighted' - - def run(self): - if not self.env['runtime']['settingsManager'].getSettingAsBool('focus', 'highlight'): - return - self.env['runtime']['outputManager'].presentText(self.env['screenData']['newAttribDelta'], soundIcon='', interrupt=True) - - def setCallback(self, callback): - pass diff --git a/src/fenrir/commands/onInput/60000-word_echo.py b/src/fenrir/commands/onInput/60000-word_echo.py deleted file mode 100644 index bb03357..0000000 --- a/src/fenrir/commands/onInput/60000-word_echo.py +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from core import debug -from utils import word_utils -import string - -class command(): - def __init__(self): - pass - def initialize(self, environment): - self.env = environment - def shutdown(self): - pass - def getDescription(self): - return 'No Description found' - - def run(self): - # first place could not be the end of a word - if self.env['screenData']['newCursor']['x'] == 0: - return - # is it enabled? - if not self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'wordEcho'): - return - - # just when cursor move worddetection is needed - if not self.env['runtime']['cursorManager'].isCursorHorizontalMove(): - return - if self.env['runtime']['inputManager'].noKeyPressed(): - return - # for now no new line - if self.env['runtime']['cursorManager'].isCursorVerticalMove(): - return - # get the word - newContent = self.env['screenData']['newContentText'].split('\n')[self.env['screenData']['newCursor']['y']] - x, y, currWord, endOfScreen, lineBreak = \ - word_utils.getCurrentWord(self.env['screenData']['newCursor']['x'], 0, newContent) - # currently writing - if self.env['runtime']['screenManager'].isDelta(): - return - else: - # at the end of a word - if not newContent[self.env['screenData']['newCursor']['x']].isspace(): - return - if (x + len(currWord) != self.env['screenData']['newCursor']['x']) and \ - (x + len(currWord) != self.env['screenData']['newCursor']['x']-1): - return - - if currWord != '': - self.env['runtime']['outputManager'].presentText(currWord, interrupt=True) - - def setCallback(self, callback): - pass - diff --git a/src/fenrir/commands/onInput/62000-spell_check.py b/src/fenrir/commands/onInput/62000-spell_check.py deleted file mode 100644 index 53b7aad..0000000 --- a/src/fenrir/commands/onInput/62000-spell_check.py +++ /dev/null @@ -1,133 +0,0 @@ -#!/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from core import debug -from utils import word_utils -import os, string - -initialized = False -try: - import enchant - initialized = True -except: - pass - -class command(): - def __init__(self): - self.language = '' - self.spellChecker = '' - def initialize(self, environment): - self.env = environment - self.updateSpellLanguage() - def shutdown(self): - pass - def getDescription(self): - return 'No Description found' - - def updateSpellLanguage(self): - self.spellChecker = enchant.Dict(self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage')) - self.language = self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage') - - def run(self): - if not initialized: - return - if not self.env['runtime']['settingsManager'].getSettingAsBool('general', 'autoSpellCheck'): - return - if self.env['runtime']['inputManager'].noKeyPressed(): - return - if self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage') != self.language: - try: - self.updateSpellLanguage() - except: - return - - # just when horizontal cursor move worddetection is needed - if not self.env['runtime']['cursorManager'].isCursorHorizontalMove(): - return - - # for now no new line - if self.env['runtime']['cursorManager'].isCursorVerticalMove(): - return - # more than a keyecho? - if len(self.env['screenData']['newDelta']) > 1: - return - # deletion - if self.env['runtime']['screenManager'].isNegativeDelta(): - return - # first place could not be the end of a word - if self.env['screenData']['newCursor']['x'] == 0: - return - - # get the word (just for speedup only look at current line - newContent = self.env['screenData']['newContentText'].split('\n')[self.env['screenData']['newCursor']['y']] - x, y, currWord, endOfScreen, lineBreak = word_utils.getCurrentWord(self.env['screenData']['newCursor']['x'], 0, newContent) - # was this a typed word? - if self.env['runtime']['screenManager'].isDelta(): - if not(newContent[self.env['screenData']['oldCursor']['x']] in string.whitespace + '!"#$%&()*+,-./:;<=>?@[\\]^_{|}~' and x != self.env['screenData']['oldCursor']['x']): - return - else: - currWord = currWord.strip(string.whitespace + '!"#$%&()*+,-./:;<=>?@[\\]^_{|}~') - else: - # or just arrow arround? - if not newContent[self.env['screenData']['newCursor']['x']].isspace(): - return - if (x + len(currWord) != self.env['screenData']['newCursor']['x']) and \ - (x + len(currWord) != self.env['screenData']['newCursor']['x']-1): - return - - # just on end of word - if self.env['screenData']['newCursor']['x'] > 0: - if not newContent[self.env['screenData']['oldCursor']['x'] - 1].lower() in string.ascii_lowercase: - return - - # ignore bash buildins - if currWord in ['cd','fg','bg','alias','bind','dir','caller','buildin','command','declare','echo','enable','help','let','local','logout',\ - 'mapfile','printf','read','readarray','source','type','typeset','ulimit','unalias']: - return - # ignore the application name - if currWord.upper() == 'FENRIR': - return - if currWord[0] =='-': - return - if currWord[0] == '/': - return - if currWord[0] == '#': - return - if currWord.startswith('./'): - return - if '@' in currWord and '.' in currWord: - return - if currWord[0] == '@': - return - if currWord.isnumeric(): - return - if currWord.isdecimal(): - return - if currWord.isspace(): - return - - try: - if os.path.exists("/bin/"+currWord): - return - except: - pass - try: - if os.path.exists("/usr/bin/"+currWord): - return - except: - pass - try: - if os.path.exists("/sbin/"+currWord): - return - except: - pass - - if not self.spellChecker.check(currWord): - self.env['runtime']['outputManager'].presentText('misspelled',soundIcon='mispell', interrupt=False) - - def setCallback(self, callback): - pass - diff --git a/src/fenrir/commands/onInput/65000-char_delete_echo.py b/src/fenrir/commands/onInput/65000-char_delete_echo.py deleted file mode 100644 index ead8360..0000000 --- a/src/fenrir/commands/onInput/65000-char_delete_echo.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from core import debug - -class command(): - def __init__(self): - pass - def initialize(self, environment): - self.env = environment - def shutdown(self): - pass - def getDescription(self): - return 'No Description found' - - def run(self): - if not self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'charDeleteEcho'): - return - - # detect typing or chilling - if self.env['screenData']['newCursor']['x'] >= self.env['screenData']['oldCursor']['x']: - return - - # More than just a deletion happend - - if self.env['runtime']['screenManager'].isDelta(): - return - # no deletion - if not self.env['runtime']['screenManager'].isNegativeDelta(): - return - if self.env['runtime']['inputManager'].noKeyPressed(): - return - - # too much for a single backspace... - # word begin produce a diff wiht len == 2 |a | others with 1 |a| - if len(self.env['screenData']['newNegativeDelta']) > 2: - return - currNegativeDelta = self.env['screenData']['newNegativeDelta'] - if len(currNegativeDelta.strip()) != len(currNegativeDelta) and \ - currNegativeDelta.strip() != '': - currNegativeDelta = currNegativeDelta.strip() - self.env['runtime']['outputManager'].presentText(currNegativeDelta, interrupt=True, ignorePunctuation=True, announceCapital=True) - - def setCallback(self, callback): - pass - diff --git a/src/fenrir/commands/onInput/72000-history.py b/src/fenrir/commands/onInput/72000-history.py deleted file mode 100644 index 4437ce7..0000000 --- a/src/fenrir/commands/onInput/72000-history.py +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from core import debug - -class command(): - def __init__(self): - pass - def initialize(self, environment): - self.env = environment - def shutdown(self): - pass - def getDescription(self): - return '' - - def run(self): - if self.env['runtime']['inputManager'].noKeyPressed(): - return - if self.env['screenData']['newAttribDelta'] != '': - return - if self.env['runtime']['screenManager'].isScreenChange(): - return - if self.env['runtime']['cursorManager'].isCursorVerticalMove(): - return - if len(self.env['input']['currInput']) != 1: - return - if not self.env['input']['currInput'][0] in ['KEY_UP','KEY_DOWN']: - return - prevLine = self.env['screenData']['oldContentText'].split('\n')[self.env['screenData']['newCursor']['y']] - currLine = self.env['screenData']['newContentText'].split('\n')[self.env['screenData']['newCursor']['y']] - if not currLine.isspace(): - currPrompt = currLine.find('$') - rootPrompt = currLine.find('#') - if currPrompt <= 0: - if rootPrompt > 0: - currPrompt = rootPrompt - else: - announce = currLine - if currPrompt > 0: - remove_digits = str.maketrans('0123456789', ' ') - if prevLine[:currPrompt].translate(remove_digits) == currLine[:currPrompt].translate(remove_digits): - announce = currLine[currPrompt+1:] - else: - announce = currLine - - if currLine.isspace(): - self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) - else: - self.env['runtime']['outputManager'].presentText(announce, interrupt=True) - self.env['commandsIgnore']['onScreenUpdate']['CHAR_DELETE_ECHO'] = True - self.env['commandsIgnore']['onScreenUpdate']['CHAR_ECHO'] = True - self.env['commandsIgnore']['onScreenUpdate']['INCOMING_IGNORE'] = True - def setCallback(self, callback): - pass - diff --git a/src/fenrir/commands/onInput/80000-capslock.py b/src/fenrir/commands/onInput/80000-capslock.py index f5ac8c7..84819bc 100644 --- a/src/fenrir/commands/onInput/80000-capslock.py +++ b/src/fenrir/commands/onInput/80000-capslock.py @@ -19,9 +19,9 @@ if self.env['input']['oldCapsLock'] == self.env['input']['newCapsLock']: return if self.env['input']['newCapsLock']: - self.env['runtime']['outputManager'].presentText("Capslock on", interrupt=True) + self.env['runtime']['outputManager'].presentText(_("Capslock on"), interrupt=True) else: - self.env['runtime']['outputManager'].presentText("Capslock off", interrupt=True) + self.env['runtime']['outputManager'].presentText(_("Capslock off"), interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/onInput/80300-scrolllock.py b/src/fenrir/commands/onInput/80300-scrolllock.py index 4203368..f159a4a 100644 --- a/src/fenrir/commands/onInput/80300-scrolllock.py +++ b/src/fenrir/commands/onInput/80300-scrolllock.py @@ -19,9 +19,9 @@ if self.env['input']['oldScrollLock'] == self.env['input']['newScrollLock']: return if self.env['input']['newScrollLock']: - self.env['runtime']['outputManager'].presentText("Scrolllock on", interrupt=True) + self.env['runtime']['outputManager'].presentText(_("Scrolllock on"), interrupt=True) else: - self.env['runtime']['outputManager'].presentText("Scrolllock off", interrupt=True) + self.env['runtime']['outputManager'].presentText(_("Scrolllock off"), interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/onInput/80500-numlock.py b/src/fenrir/commands/onInput/80500-numlock.py index 74283d1..86ab534 100644 --- a/src/fenrir/commands/onInput/80500-numlock.py +++ b/src/fenrir/commands/onInput/80500-numlock.py @@ -19,9 +19,9 @@ if self.env['input']['oldNumLock'] == self.env['input']['newNumLock']: return if self.env['input']['newNumLock']: - self.env['runtime']['outputManager'].presentText("Numlock on", interrupt=True) + self.env['runtime']['outputManager'].presentText(_("Numlock on"), interrupt=True) else: - self.env['runtime']['outputManager'].presentText("Numlock off", interrupt=True) + self.env['runtime']['outputManager'].presentText(_("Numlock off"), interrupt=True) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/onPlugInputDevice/50000-UpdateDevices.py b/src/fenrir/commands/onPlugInputDevice/50000-UpdateDevices.py new file mode 100755 index 0000000..37a392e --- /dev/null +++ b/src/fenrir/commands/onPlugInputDevice/50000-UpdateDevices.py @@ -0,0 +1,21 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'No description found' + def run(self): + self.env['runtime']['inputManager'].updateInputDevices() + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/onPlugInputDevice/__init__.py b/src/fenrir/commands/onPlugInputDevice/__init__.py new file mode 100755 index 0000000..e69de29 diff --git a/src/fenrir/commands/onScreenChanged/80000-screen_change_announcement.py b/src/fenrir/commands/onScreenChanged/80000-screen_change_announcement.py index 39b473b..b59b863 100644 --- a/src/fenrir/commands/onScreenChanged/80000-screen_change_announcement.py +++ b/src/fenrir/commands/onScreenChanged/80000-screen_change_announcement.py @@ -17,8 +17,8 @@ return 'No Description found' def run(self): - self.env['runtime']['outputManager'].presentText("screen " + str(self.env['screenData']['newTTY']),soundIcon='ChangeTTY', interrupt=True) - self.env['runtime']['outputManager'].presentText(self.env['screenData']['newContentText'], interrupt=False) + self.env['runtime']['outputManager'].presentText(_("screen {0}").format(self.env['screen']['newTTY']),soundIcon='ChangeTTY', interrupt=True, flush=False) + self.env['runtime']['outputManager'].presentText(self.env['screen']['newContentText'], interrupt=False, flush=False) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/onScreenChanged/85000-reset_marks.py b/src/fenrir/commands/onScreenChanged/85000-reset_marks.py new file mode 100644 index 0000000..501f7ad --- /dev/null +++ b/src/fenrir/commands/onScreenChanged/85000-reset_marks.py @@ -0,0 +1,24 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'No Description found' + + def run(self): + self.env['runtime']['cursorManager'].clearMarks() + + def setCallback(self, callback): + pass + diff --git a/src/fenrir/commands/onScreenChanged/85000-screen_chnage_reset_marks.py b/src/fenrir/commands/onScreenChanged/85000-screen_chnage_reset_marks.py deleted file mode 100644 index 501f7ad..0000000 --- a/src/fenrir/commands/onScreenChanged/85000-screen_chnage_reset_marks.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from core import debug - -class command(): - def __init__(self): - pass - def initialize(self, environment): - self.env = environment - def shutdown(self): - pass - def getDescription(self): - return 'No Description found' - - def run(self): - self.env['runtime']['cursorManager'].clearMarks() - - def setCallback(self, callback): - pass - diff --git a/src/fenrir/commands/onScreenChanged/89000-leave_review_mode.py b/src/fenrir/commands/onScreenChanged/89000-leave_review_mode.py new file mode 100644 index 0000000..84240eb --- /dev/null +++ b/src/fenrir/commands/onScreenChanged/89000-leave_review_mode.py @@ -0,0 +1,26 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'No Description found' + + def run(self): + if not self.env['runtime']['settingsManager'].getSettingAsBool('review', 'leaveReviewOnScreenChange'): + return + self.env['runtime']['cursorManager'].clearReviewCursor() + + def setCallback(self, callback): + pass + diff --git a/src/fenrir/commands/onScreenChanged/89000-screen_chnage_leve_review_mode.py b/src/fenrir/commands/onScreenChanged/89000-screen_chnage_leve_review_mode.py deleted file mode 100644 index b63b0d5..0000000 --- a/src/fenrir/commands/onScreenChanged/89000-screen_chnage_leve_review_mode.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from core import debug - -class command(): - def __init__(self): - pass - def initialize(self, environment): - self.env = environment - def shutdown(self): - pass - def getDescription(self): - return 'No Description found' - - def run(self): - self.env['runtime']['cursorManager'].clearReviewCursor() - - def setCallback(self, callback): - pass - diff --git a/src/fenrir/commands/onScreenUpdate/56000-highlight_tracking.py b/src/fenrir/commands/onScreenUpdate/56000-highlight_tracking.py new file mode 100644 index 0000000..419966f --- /dev/null +++ b/src/fenrir/commands/onScreenUpdate/56000-highlight_tracking.py @@ -0,0 +1,24 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return _('enables or disables tracking of highlighted') + + def run(self): + if not self.env['runtime']['settingsManager'].getSettingAsBool('focus', 'highlight'): + return + self.env['runtime']['outputManager'].presentText(self.env['screen']['newAttribDelta'], soundIcon='', interrupt=True, flush=False) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/onScreenUpdate/60000-history.py b/src/fenrir/commands/onScreenUpdate/60000-history.py new file mode 100644 index 0000000..0ecea11 --- /dev/null +++ b/src/fenrir/commands/onScreenUpdate/60000-history.py @@ -0,0 +1,57 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return '' + + def run(self): + if self.env['screen']['newAttribDelta'] != '': + return + if self.env['runtime']['screenManager'].isScreenChange(): + return + if self.env['runtime']['cursorManager'].isCursorVerticalMove(): + return + if not (self.env['runtime']['inputManager'].getLastDeepestInput() in [['KEY_UP'],['KEY_DOWN']]): + return + prevLine = self.env['screen']['oldContentText'].split('\n')[self.env['screen']['newCursor']['y']] + currLine = self.env['screen']['newContentText'].split('\n')[self.env['screen']['newCursor']['y']] + if prevLine == currLine: + if self.env['screen']['newDelta'] != '': + return + if not currLine.isspace(): + currPrompt = currLine.find('$') + rootPrompt = currLine.find('#') + if currPrompt <= 0: + if rootPrompt > 0: + currPrompt = rootPrompt + else: + announce = currLine + if currPrompt > 0: + remove_digits = str.maketrans('0123456789', ' ') + if prevLine[:currPrompt].translate(remove_digits) == currLine[:currPrompt].translate(remove_digits): + announce = currLine[currPrompt+1:] + else: + announce = currLine + + if currLine.isspace(): + self.env['runtime']['outputManager'].presentText(_("blank"), soundIcon='EmptyLine', interrupt=True, flush=False) + else: + self.env['runtime']['outputManager'].presentText(announce, interrupt=True, flush=False) + self.env['commandsIgnore']['onScreenUpdate']['CHAR_DELETE_ECHO'] = True + self.env['commandsIgnore']['onScreenUpdate']['CHAR_ECHO'] = True + self.env['commandsIgnore']['onScreenUpdate']['INCOMING_IGNORE'] = True + def setCallback(self, callback): + pass + diff --git a/src/fenrir/commands/onScreenUpdate/70000-incoming.py b/src/fenrir/commands/onScreenUpdate/70000-incoming.py index 83dc00f..1b1ec0d 100644 --- a/src/fenrir/commands/onScreenUpdate/70000-incoming.py +++ b/src/fenrir/commands/onScreenUpdate/70000-incoming.py @@ -20,17 +20,17 @@ if not self.env['runtime']['settingsManager'].getSettingAsBool('speech', 'autoReadIncoming'): return # is there something to read? - if self.env['screenData']['newDelta'] == '': - return - - # its a cursor movement (experimental) - maybe also check current shortcut string? - if abs(self.env['screenData']['newCursor']['x'] - self.env['screenData']['oldCursor']['x']) >= 1: - if len(self.env['screenData']['newDelta'].strip(' \n\t')) <= 2: + if not self.env['runtime']['screenManager'].isDelta(): + return + # this must be a keyecho or something + if len(self.env['screen']['newDelta'].strip(' \n\t')) <= 1: + if abs(self.env['screen']['newCursor']['x'] - self.env['screen']['oldCursor']['x']) >= 1: + # if len(self.env['screen']['newDelta'].strip(' \n\t0123456789')) <= 2: return - if abs(self.env['screenData']['newCursor']['y'] - self.env['screenData']['oldCursor']['y']) == 1: - return - - self.env['runtime']['outputManager'].presentText(self.env['screenData']['newDelta'], interrupt=False) + if abs(self.env['screen']['newCursor']['y'] - self.env['screen']['oldCursor']['y']) == 1: + # if len(self.env['screen']['newDelta'].strip(' \n\t0123456789')) <= 2: + return + self.env['runtime']['outputManager'].presentText(self.env['screen']['newDelta'], interrupt=False, flush=False) def setCallback(self, callback): pass diff --git a/src/fenrir/commands/onScreenUpdate/75000-incoming_promote.py b/src/fenrir/commands/onScreenUpdate/75000-incoming_promote.py index 3ec3f43..63cb2c8 100644 --- a/src/fenrir/commands/onScreenUpdate/75000-incoming_promote.py +++ b/src/fenrir/commands/onScreenUpdate/75000-incoming_promote.py @@ -22,14 +22,12 @@ return if self.env['runtime']['settingsManager'].getSetting('promote', 'list').strip(" \t\n") == '': return - if self.env['screenData']['newDelta'] == '': - return if int(time.time() - self.env['input']['lastInputTime']) < self.env['runtime']['settingsManager'].getSettingAsInt('promote', 'inactiveTimeoutSec'): return if len(self.env['runtime']['settingsManager'].getSetting('promote', 'list')) == 0: return for promote in self.env['runtime']['settingsManager'].getSetting('promote', 'list').split(','): - if promote in self.env['screenData']['newDelta']: + if promote in self.env['screen']['newDelta']: self.env['runtime']['outputManager'].playSoundIcon('PromotedText') self.env['input']['lastInputTime'] = time.time() return diff --git a/src/fenrir/commands/onScreenUpdate/76000-time.py b/src/fenrir/commands/onScreenUpdate/76000-time.py deleted file mode 100644 index 4e9306d..0000000 --- a/src/fenrir/commands/onScreenUpdate/76000-time.py +++ /dev/null @@ -1,74 +0,0 @@ -#!/bin/python -import time -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from core import debug -import time -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 - else: - # shoul announce? - if not str(now.minute) 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 - 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) - - if self.env['runtime']['settingsManager'].getSettingAsBool('time', 'interrupt'): - self.env['runtime']['outputManager'].interruptOutput() - if self.env['runtime']['settingsManager'].getSettingAsBool('time', 'announce'): - self.env['runtime']['outputManager'].playSoundIcon('announce') - - if presentTime: - # present the time - self.env['runtime']['outputManager'].presentText('Autotime: ' + timeString , soundIcon='', interrupt=False) - # and date if changes - if presentDate: - self.env['runtime']['outputManager'].presentText(dateString , soundIcon='', interrupt=False) - self.lastDateString = dateString - self.lastTime = datetime.datetime.now() - self.lastTimeString = timeString - def setCallback(self, callback): - pass diff --git a/src/fenrir/commands/onSwitchApplicationProfile/agetty.py b/src/fenrir/commands/onSwitchApplicationProfile/agetty.py deleted file mode 100644 index dbd5250..0000000 --- a/src/fenrir/commands/onSwitchApplicationProfile/agetty.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from core import debug - -class command(): - def __init__(self): - pass - def initialize(self, environment): - self.env = environment - def shutdown(self): - pass - def getDescription(self): - return 'No description found' - def load(self): - print('--------------') - print('agetty') - print('load new',self.env['screenData']['newApplication']) - print('--------------') - - def unload(self): - print('--------------') - print('agetty') - print('unload old',self.env['screenData']['oldApplication']) - print('--------------') - - def setCallback(self, callback): - pass diff --git a/src/fenrir/commands/onSwitchApplicationProfile/bash.py b/src/fenrir/commands/onSwitchApplicationProfile/bash.py deleted file mode 100644 index d82b6e9..0000000 --- a/src/fenrir/commands/onSwitchApplicationProfile/bash.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from core import debug - -class command(): - def __init__(self): - pass - def initialize(self, environment): - self.env = environment - def shutdown(self): - pass - def getDescription(self): - return 'No description found' - def load(self): - print('--------------') - print('bash') - print('load new',self.env['screenData']['newApplication']) - print('--------------') - - def unload(self): - print('--------------') - print('bash') - print('unload old',self.env['screenData']['oldApplication']) - print('--------------') - - def setCallback(self, callback): - pass diff --git a/src/fenrir/commands/onSwitchApplicationProfile/default.py b/src/fenrir/commands/onSwitchApplicationProfile/default.py index 4025593..04558ae 100644 --- a/src/fenrir/commands/onSwitchApplicationProfile/default.py +++ b/src/fenrir/commands/onSwitchApplicationProfile/default.py @@ -16,15 +16,17 @@ def getDescription(self): return 'No description found' def load(self): + return print('--------------') print('default') - print('load new',self.env['screenData']['newApplication']) + print('load new',self.env['screen']['newApplication']) print('--------------') def unload(self): + return print('--------------') print('default') - print('unload old',self.env['screenData']['oldApplication']) + print('unload old',self.env['screen']['oldApplication']) print('--------------') def setCallback(self, callback): diff --git a/src/fenrir/commands/onSwitchApplicationProfile/inactive/agetty.py b/src/fenrir/commands/onSwitchApplicationProfile/inactive/agetty.py new file mode 100644 index 0000000..1fb59c8 --- /dev/null +++ b/src/fenrir/commands/onSwitchApplicationProfile/inactive/agetty.py @@ -0,0 +1,31 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'No description found' + def load(self): + print('--------------') + print('agetty') + print('load new',self.env['screen']['newApplication']) + print('--------------') + + def unload(self): + print('--------------') + print('agetty') + print('unload old',self.env['screen']['oldApplication']) + print('--------------') + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/onSwitchApplicationProfile/inactive/bash.py b/src/fenrir/commands/onSwitchApplicationProfile/inactive/bash.py new file mode 100644 index 0000000..7a5d754 --- /dev/null +++ b/src/fenrir/commands/onSwitchApplicationProfile/inactive/bash.py @@ -0,0 +1,31 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'No description found' + def load(self): + print('--------------') + print('bash') + print('load new',self.env['screen']['newApplication']) + print('--------------') + + def unload(self): + print('--------------') + print('bash') + print('unload old',self.env['screen']['oldApplication']) + print('--------------') + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/onSwitchApplicationProfile/inactive/vim.py b/src/fenrir/commands/onSwitchApplicationProfile/inactive/vim.py new file mode 100644 index 0000000..78f02af --- /dev/null +++ b/src/fenrir/commands/onSwitchApplicationProfile/inactive/vim.py @@ -0,0 +1,31 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'No description found' + def load(self): + print('--------------') + print('vim') + print('load new',self.env['screen']['newApplication']) + print('--------------') + + def unload(self): + print('--------------') + print('vim') + print('unload old',self.env['screen']['oldApplication']) + print('--------------') + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/onSwitchApplicationProfile/vim.py b/src/fenrir/commands/onSwitchApplicationProfile/vim.py deleted file mode 100644 index 74ae0c4..0000000 --- a/src/fenrir/commands/onSwitchApplicationProfile/vim.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from core import debug - -class command(): - def __init__(self): - pass - def initialize(self, environment): - self.env = environment - def shutdown(self): - pass - def getDescription(self): - return 'No description found' - def load(self): - print('--------------') - print('vim') - print('load new',self.env['screenData']['newApplication']) - print('--------------') - - def unload(self): - print('--------------') - print('vim') - print('unload old',self.env['screenData']['oldApplication']) - print('--------------') - - def setCallback(self, callback): - pass diff --git a/src/fenrir/core/applicationManager.py b/src/fenrir/core/applicationManager.py index 8f127b8..202e6e3 100644 --- a/src/fenrir/core/applicationManager.py +++ b/src/fenrir/core/applicationManager.py @@ -14,18 +14,18 @@ def shutdown(self): pass def getCurrentApplication(self): - currApp = self.env['screenData']['newApplication'].upper() + currApp = self.env['screen']['newApplication'].upper() if not currApp: currApp == 'DEFAULT' if currApp == '': currApp == 'DEFAULT' return currApp def getPrevApplication(self): - prevApp = self.env['screenData']['oldApplication'].upper() + prevApp = self.env['screen']['oldApplication'].upper() if not prevApp: prevApp == 'DEFAULT' if prevApp == '': prevApp == 'DEFAULT' return prevApp def isApplicationChange(self): - return self.env['screenData']['oldApplication'] != self.env['screenData']['newApplication'] + return self.env['screen']['oldApplication'] != self.env['screen']['newApplication'] diff --git a/src/fenrir/core/commandData.py b/src/fenrir/core/commandData.py new file mode 100644 index 0000000..987810f --- /dev/null +++ b/src/fenrir/core/commandData.py @@ -0,0 +1,29 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +import time + +# used as shared memory between commands +# use this in your own commands +commandBuffer = { +'enableSpeechOnKeypress': False, +'genericList':[], +'genericListSource':'', +'genericListSelection': 0, +'clipboard':[], +'currClipboard': 0, +'Marks':{'1':None, '2':None}, +'bookMarks':{}, +'windowArea':{}, +} + +# used by the commandManager +commandInfo = { +#'currCommand': '', +'lastCommandExecutionTime': time.time(), +'lastCommandRequestTime': time.time(), +} diff --git a/src/fenrir/core/commandManager.py b/src/fenrir/core/commandManager.py index a1b1779..fd10c13 100644 --- a/src/fenrir/core/commandManager.py +++ b/src/fenrir/core/commandManager.py @@ -4,33 +4,51 @@ # Fenrir TTY screen reader # By Chrys, Storm Dragon, and contributers. -import importlib.util -import glob, os, time -import __main__ +import glob, os, time, inspect +currentdir = os.path.dirname(os.path.realpath(os.path.abspath(inspect.getfile(inspect.currentframe())))) +fenrirPath = os.path.dirname(currentdir) + from core import debug +from utils import module_utils class commandManager(): def __init__(self): pass def initialize(self, environment): self.env = environment - self.env['runtime']['commandManager'].loadCommands('commands') - self.env['runtime']['commandManager'].loadCommands('onInput') - self.env['runtime']['commandManager'].loadCommands('onScreenUpdate') - self.env['runtime']['commandManager'].loadCommands('onScreenChanged') - self.env['runtime']['commandManager'].loadCommands('onApplicationChange') - self.env['runtime']['commandManager'].loadCommands('onSwitchApplicationProfile') + # commands + self.env['commands'] = {} + self.env['commandsIgnore'] = {} + for commandFolder in self.env['general']['commandFolderList']: + self.env['runtime']['commandManager'].loadCommands(commandFolder) + if self.env['runtime']['settingsManager'].getSetting('general', 'commandPath') != '': + self.env['runtime']['commandManager'].loadCommands(commandFolder, + self.env['runtime']['settingsManager'].getSetting('general', 'commandPath')) + + # scripts for scriptKey self.env['runtime']['commandManager'].loadScriptCommands() + def shutdown(self): - self.env['runtime']['commandManager'].shutdownCommands('commands') - self.env['runtime']['commandManager'].shutdownCommands('onInput') - self.env['runtime']['commandManager'].shutdownCommands('onScreenUpdate') - self.env['runtime']['commandManager'].shutdownCommands('onScreenChanged') - self.env['runtime']['commandManager'].shutdownCommands('onApplicationChange') - self.env['runtime']['commandManager'].shutdownCommands('onSwitchApplicationProfile') + for commandFolder in self.env['general']['commandFolderList']: + self.env['runtime']['commandManager'].shutdownCommands(commandFolder) - def loadCommands(self, section='commands'): - commandFolder = os.path.dirname(os.path.realpath(__main__.__file__)) + "/commands/" + section +"/" + def loadCommands(self, section='commands',commandPath=''): + if commandPath =='': + commandPath = fenrirPath+ "/commands/" + if not commandPath.endswith('/'): + commandPath += '/' + commandFolder = commandPath + section +"/" + if not os.path.exists(commandFolder): + self.env['runtime']['debug'].writeDebugOut("commandFolder not exists:" + commandFolder ,debug.debugLevel.WARNING) + return + if not os.path.isdir(commandFolder): + self.env['runtime']['debug'].writeDebugOut("commandFolder not a directory:" + commandFolder ,debug.debugLevel.ERROR) + return + if not os.access(commandFolder, os.R_OK): + self.env['runtime']['debug'].writeDebugOut("commandFolder not readable:" + commandFolder ,debug.debugLevel.ERROR) + return + self.env['commands'][section] = {} + self.env['commandsIgnore'][section] = {} commandList = glob.glob(commandFolder+'*') for command in commandList: try: @@ -38,27 +56,30 @@ fileName = fileName.split('/')[-1] if fileName.startswith('__'): continue + try: + if self.env['commands'][section][fileName.upper()] != None: + continue + except: + pass if fileExtension.lower() == '.py': - spec = importlib.util.spec_from_file_location(fileName, command) - command_mod = importlib.util.module_from_spec(spec) - spec.loader.exec_module(command_mod) + command_mod = module_utils.importModule(fileName, command) self.env['commands'][section][fileName.upper()] = command_mod.command() self.env['commandsIgnore'][section][fileName.upper()[fileName.upper().find('-')+1:]+'_IGNORE'] = False self.env['commands'][section][fileName.upper()].initialize(self.env) self.env['runtime']['debug'].writeDebugOut("Load command:" + section + "." + fileName.upper() ,debug.debugLevel.INFO, onAnyLevel=True) except Exception as e: - print(e) self.env['runtime']['debug'].writeDebugOut("Loading command:" + command ,debug.debugLevel.ERROR) self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) continue - def loadScriptCommands(self, section='commands'): - scriptPath = self.env['runtime']['settingsManager'].getSetting('general', 'scriptPath') + def loadScriptCommands(self, section='commands', scriptPath=''): + if scriptPath =='': + scriptPath = self.env['runtime']['settingsManager'].getSetting('general', 'scriptPath') if not scriptPath.endswith('/'): scriptPath += '/' - if not os.path.exists(scriptPath) or scriptPath == '/': - if os.path.exists(os.path.dirname(os.path.realpath(__main__.__file__)) +'/../../config/scripts/'): - scriptPath = os.path.dirname(os.path.realpath(__main__.__file__)) +'/../../config/scripts/' + if not os.path.exists(scriptPath): + if os.path.exists(fenrirPath +'/../../config/scripts/'): + scriptPath = fenrirPath +'/../../config/scripts/' else: self.env['runtime']['debug'].writeDebugOut("scriptpath not exists:" + scriptPath ,debug.debugLevel.WARNING) return @@ -69,7 +90,7 @@ self.env['runtime']['debug'].writeDebugOut("scriptpath not readable:" + scriptPath ,debug.debugLevel.ERROR) return commandList = glob.glob(scriptPath+'*') - subCommand = os.path.dirname(os.path.realpath(__main__.__file__)) + '/commands/commands/subprocess.py' + subCommand = fenrirPath + '/commands/commands/subprocess.py' for command in commandList: invalid = False try: @@ -77,9 +98,9 @@ fileName = fileName.split('/')[-1] if fileName.startswith('__'): continue - spec = importlib.util.spec_from_file_location(fileName ,subCommand) - command_mod = importlib.util.module_from_spec(spec) - spec.loader.exec_module(command_mod) + if fileName.upper() in self.env['commands'][section]: + continue + command_mod = module_utils.importModule(fileName ,subCommand) self.env['commands'][section][fileName.upper()] = command_mod.command() self.env['commands'][section][fileName.upper()].initialize(self.env,command) self.env['runtime']['debug'].writeDebugOut("Load script:" + section + "." + fileName.upper() ,debug.debugLevel.INFO, onAnyLevel=True) @@ -107,7 +128,6 @@ shortcut.append(sorted(shortcutKeys)) self.env['bindings'][str(shortcut)] = fileName.upper() except Exception as e: - print(e) self.env['runtime']['debug'].writeDebugOut("Loading script:" + command ,debug.debugLevel.ERROR) self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) continue @@ -143,9 +163,10 @@ self.env['runtime']['debug'].writeDebugOut("Executing trigger:" + trigger + "." + newScript ,debug.debugLevel.ERROR) self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) - def executeDefaultTrigger(self, trigger): - if self.env['runtime']['screenManager'].isSuspendingScreen(): - return + def executeDefaultTrigger(self, trigger, force=False): + if not force: + if self.env['runtime']['screenManager'].isSuspendingScreen(): + return for command in sorted(self.env['commands'][trigger]): if self.commandExists(command, trigger): try: @@ -156,37 +177,47 @@ self.env['runtime']['debug'].writeDebugOut("Executing trigger.command:" + trigger + "." + command ,debug.debugLevel.INFO) self.env['commands'][trigger][command].run() except Exception as e: - self.env['runtime']['debug'].writeDebugOut("Executing trigger:" + trigger + "." + command ,debug.debugLevel.ERROR) - self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + self.env['runtime']['debug'].writeDebugOut("Executing trigger:" + trigger + "." + command + str(e) ,debug.debugLevel.ERROR) def executeCommand(self, command, section = 'commands'): if self.env['runtime']['screenManager'].isSuspendingScreen(): return if self.commandExists(command, section): try: - if self.env['generalInformation']['tutorialMode']: + if self.env['runtime']['helpManager'].isTutorialMode() and section != 'help': self.env['runtime']['debug'].writeDebugOut("Tutorial for command:" + section + "." + command ,debug.debugLevel.INFO) - description = self.env['commands'][section][command].getDescription() + description = self.getCommandDescription(command, section) self.env['runtime']['outputManager'].presentText(description, interrupt=True) else: self.env['runtime']['debug'].writeDebugOut("Executing command:" + section + "." + command ,debug.debugLevel.INFO) - self.env['commands'][section][command].run() - except Exception as e: - self.env['runtime']['debug'].writeDebugOut("Executing command:" + section + "." + command ,debug.debugLevel.ERROR) - self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) - self.clearCommandQueued() + self.runCommand(command, section) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("Executing command:" + section + "." + command +' ' + str(e),debug.debugLevel.ERROR) + + + def runCommand(self, command, section = 'commands'): + if self.commandExists(command, section): + try: + self.env['runtime']['debug'].writeDebugOut("runCommand command:" + section + "." + command ,debug.debugLevel.INFO) + self.env['commands'][section][command].run() + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("runCommand command:" + section + "." + command +' ' + str(e),debug.debugLevel.ERROR) self.env['commandInfo']['lastCommandExecutionTime'] = time.time() - - def isCommandQueued(self): - return self.env['commandInfo']['currCommand'] != '' - - def clearCommandQueued(self): - self.env['commandInfo']['currCommand'] = '' - def queueCommand(self, command): - if command == '': - return - self.env['commandInfo']['currCommand'] = command + def getCommandDescription(self, command, section = 'commands'): + if self.commandExists(command, section): + try: + return self.env['commands'][section][command].getDescription() + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('commandManager.getCommandDescription:' + str(e),debug.debugLevel.ERROR) + self.env['commandInfo']['lastCommandExecutionTime'] = time.time() def commandExists(self, command, section = 'commands'): - return( command in self.env['commands'][section]) + return( command in self.env['commands'][section]) + def getShortcutForCommand(self, command): + shortcut = '' + try: + shortcut = list(self.env['bindings'].keys())[list(self.env['bindings'].values()).index(command)] + except: + pass + return shortcut diff --git a/src/fenrir/core/commands.py b/src/fenrir/core/commands.py deleted file mode 100644 index c3ea2fa..0000000 --- a/src/fenrir/core/commands.py +++ /dev/null @@ -1,62 +0,0 @@ -#!/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from core import debug -import time - - -# used as shared memory between commands -# use this in your own commands -commandBuffer = { -'enableSpeechOnKeypress': False, -'genericList':[], -'genericListSource':'', -'genericListSelection': 0, -'clipboard':[], -'currClipboard': 0, -'Marks':{'1':None, '2':None}, -'bookMarks':{}, -'windowArea':{}, -} - -# used by the commandManager -commandInfo = { -'currCommand': '', -'lastCommandExecutionTime': time.time(), -'lastCommandRequestTime': time.time(), -} - -# used by the commandManager -commands = { -'onInput':{ - }, -'onScreenChanged':{ - }, -'onScreenUpdate':{ - }, -'onApplicationChange':{ - }, -'commands':{ - }, -'onSwitchApplicationProfile':{ - }, -} - -# used by the commandManager -commandsIgnore = { -'onInput':{ - }, -'onScreenChanged':{ - }, -'onScreenUpdate':{ - }, -'onApplicationChange':{ - }, -'commands':{ - }, -'onSwitchApplicationProfile':{ - }, -} diff --git a/src/fenrir/core/cursorManager.py b/src/fenrir/core/cursorManager.py index 4995a16..2a3191e 100644 --- a/src/fenrir/core/cursorManager.py +++ b/src/fenrir/core/cursorManager.py @@ -26,10 +26,10 @@ self.env['commandBuffer']['Marks']['2'] != None def setMark(self): currCursor = None - if self.env['screenData']['newCursorReview']: - currCursor = self.env['screenData']['newCursorReview'].copy() + if self.env['screen']['newCursorReview']: + currCursor = self.env['screen']['newCursorReview'].copy() else: - currCursor = self.env['screenData']['newCursor'].copy() + currCursor = self.env['screen']['newCursor'].copy() if not self.env['commandBuffer']['Marks']['1']: self.env['commandBuffer']['Marks']['1'] = currCursor.copy() return 1 @@ -38,43 +38,43 @@ return 2 return 0 def getReviewOrTextCursor(self): - if self.env['screenData']['newCursorReview']: - return self.env['screenData']['newCursorReview'].copy() + if self.env['screen']['newCursorReview']: + return self.env['screen']['newCursorReview'].copy() else: - return self.env['screenData']['newCursor'].copy() + return self.env['screen']['newCursor'].copy() def clearReviewCursor(self): if not self.isReviewMode(): return - self.env['screenData']['oldCursorReview'] = None - self.env['screenData']['newCursorReview'] = None + self.env['screen']['oldCursorReview'] = None + self.env['screen']['newCursorReview'] = None def isCursorHorizontalMove(self): - return self.env['screenData']['newCursor']['x'] != self.env['screenData']['oldCursor']['x'] + return self.env['screen']['newCursor']['x'] != self.env['screen']['oldCursor']['x'] def isCursorVerticalMove(self): - return self.env['screenData']['newCursor']['y'] != self.env['screenData']['oldCursor']['y'] + return self.env['screen']['newCursor']['y'] != self.env['screen']['oldCursor']['y'] def isReviewMode(self): - return self.env['screenData']['newCursorReview'] != None + return self.env['screen']['newCursorReview'] != None def enterReviewModeCurrTextCursor(self, overwrite=False): if self.isReviewMode() and not overwrite: return - self.env['screenData']['oldCursorReview'] = self.env['screenData']['newCursorReview'] - if not self.env['screenData']['newCursorReview']: - self.env['screenData']['newCursorReview'] = self.env['screenData']['newCursor'].copy() + self.env['screen']['oldCursorReview'] = self.env['screen']['newCursorReview'] + if not self.env['screen']['newCursorReview']: + self.env['screen']['newCursorReview'] = self.env['screen']['newCursor'].copy() if self.env['runtime']['settingsManager'].getSettingAsBool('focus', 'highlight') and \ - self.env['screenData']['newCursorAttrib'] != None: - if self.env['screenData']['newCursorAttrib']['x'] != 0 and \ - self.env['screenData']['newCursorAttrib']['y'] != 0: - self.env['screenData']['newCursorReview'] = self.env['screenData']['newCursorAttrib'].copy() + self.env['screen']['newCursorAttrib'] != None: + if self.env['screen']['newCursorAttrib']['x'] != 0 and \ + self.env['screen']['newCursorAttrib']['y'] != 0: + self.env['screen']['newCursorReview'] = self.env['screen']['newCursorAttrib'].copy() def setReviewCursorPosition(self, x, y): if not self.isReviewMode(): self.enterReviewModeCurrTextCursor() - self.env['screenData']['oldCursorReview'] = self.env['screenData']['newCursorReview'] - self.env['screenData']['newCursorReview']['x'] = x - self.env['screenData']['newCursorReview']['y'] = y + self.env['screen']['oldCursorReview'] = self.env['screen']['newCursorReview'] + self.env['screen']['newCursorReview']['x'] = x + self.env['screen']['newCursorReview']['y'] = y def isApplicationWindowSet(self): try: diff --git a/src/fenrir/core/debug.py b/src/fenrir/core/debug.py index 271c221..72b5a61 100644 --- a/src/fenrir/core/debug.py +++ b/src/fenrir/core/debug.py @@ -1,8 +1,6 @@ #!/usr/bin/python -# Debugger module for the Fenrir screen reader. from enum import Enum -from datetime import datetime class debugLevel(Enum): DEACTIVE = 0 @@ -13,60 +11,3 @@ return self.value def __str__(self): return self.name - -class debug(): - def __init__(self, fileName='/var/log/fenrir.log'): - self._fileName = fileName - self._file = None - self._fileOpened = False - def initialize(self, environment): - self.env = environment - def shutdown(self): - self.closeDebugFile() - def __del__(self): - try: - self.shutdown() - except: - pass - - def openDebugFile(self, fileName = ''): - self._fileOpened = False - if fileName != '': - self._fileName = fileName - if self._fileName != '': - self._file = open(self._fileName,'a') - self._fileOpened = True - - def writeDebugOut(self, text, level = debugLevel.DEACTIVE, onAnyLevel=False): - if (self.env['runtime']['settingsManager'].getSettingAsInt('general','debugLevel') < int(level)) and \ - not (onAnyLevel and self.env['runtime']['settingsManager'].getSettingAsInt('general','debugLevel') > int(debugLevel.DEACTIVE)) : - if self._fileOpened: - self.closeDebugFile() - return - else: - if not self._fileOpened: - self.openDebugFile() - if onAnyLevel: - msg = 'ANY '+ str(level) + ' ' + str(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')) - else: - msg = str(level) +' ' + str(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f') -) - msg += ': ' + text - print(msg) - self._file.write(msg + '\n') - - - def closeDebugFile(self): - if not self._fileOpened: - return False - if self._file != None: - self._file.close() - self._fileOpened = False - return True - - def getDebugFile(self): - return self._fileName - - def setDebugFile(self, fileName): - self.closeDebugFile() - self._fileName = fileName diff --git a/src/fenrir/core/debugManager.py b/src/fenrir/core/debugManager.py new file mode 100644 index 0000000..304ebbd --- /dev/null +++ b/src/fenrir/core/debugManager.py @@ -0,0 +1,71 @@ +#!/usr/bin/python +# Debugger module for the Fenrir screen reader. + +from core import debug +from datetime import datetime + +class debugManager(): + def __init__(self, fileName='/var/log/fenrir.log'): + self._fileName = fileName + self._file = None + self._fileOpened = False + def initialize(self, environment): + self.env = environment + def shutdown(self): + self.closeDebugFile() + def __del__(self): + try: + self.shutdown() + except: + pass + + def openDebugFile(self, fileName = ''): + self._fileOpened = False + if fileName != '': + self._fileName = fileName + if self._fileName != '': + self._file = open(self._fileName,'a') + self._fileOpened = True + + def writeDebugOut(self, text, level = debug.debugLevel.DEACTIVE, onAnyLevel=False): + + mode = self.env['runtime']['settingsManager'].getSetting('general','debugMode') + if mode == '': + mode = 'FILE' + mode = mode.upper().split(',') + fileMode = 'FILE' in mode + printMode = 'PRINT' in mode + + if (self.env['runtime']['settingsManager'].getSettingAsInt('general','debugLevel') < int(level)) and \ + not (onAnyLevel and self.env['runtime']['settingsManager'].getSettingAsInt('general','debugLevel') > int(debug.debugLevel.DEACTIVE)) : + if self._fileOpened: + self.closeDebugFile() + return + else: + if not self._fileOpened and fileMode: + self.openDebugFile() + if onAnyLevel: + msg = 'ANY '+ str(level) + ' ' + str(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')) + else: + msg = str(level) +' ' + str(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f') +) + msg += ': ' + text + if printMode: + print(msg) + if fileMode: + self._file.write(msg + '\n') + + def closeDebugFile(self): + if not self._fileOpened: + return False + if self._file != None: + self._file.close() + self._fileOpened = False + return True + + def getDebugFile(self): + return self._fileName + + def setDebugFile(self, fileName): + self.closeDebugFile() + self._fileName = fileName diff --git a/src/fenrir/core/environment.py b/src/fenrir/core/environment.py index 367305a..b8838e1 100644 --- a/src/fenrir/core/environment.py +++ b/src/fenrir/core/environment.py @@ -5,25 +5,25 @@ # By Chrys, Storm Dragon, and contributers. from core import debug -from core import settings -from core import runtime -from core import screenData -from core import generalInformation -from core import commands -from core import inputEvent -from core import punctuation +from core.settingsData import settingsData +from core.runtimeData import runtimeData +from core.screenData import screenData +from core.outputData import outputData +from core.generalData import generalData +from core import commandData +from core.inputData import inputData +from core.punctuationData import punctuationData environment = { -'screenData': screenData.screenData, -'runtime': runtime.runtime, -'generalInformation': generalInformation.generalInformation, -'settings': settings.settings, -'commands': commands.commands, -'commandsIgnore': commands.commandsIgnore, -'commandInfo': commands.commandInfo, -'commandBuffer': commands.commandBuffer, -'input': inputEvent.input, -'punctuation': punctuation.punctuation, +'screen': screenData, +'runtime': runtimeData, +'general': generalData, +'settings': settingsData, +'commandInfo': commandData.commandInfo, +'commandBuffer': commandData.commandBuffer, +'input': inputData, +'punctuation': punctuationData, +'output': outputData, 'soundIcons': {}, 'bindings': {}, } diff --git a/src/fenrir/core/eventData.py b/src/fenrir/core/eventData.py new file mode 100755 index 0000000..be5db45 --- /dev/null +++ b/src/fenrir/core/eventData.py @@ -0,0 +1,24 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +from enum import Enum + +class fenrirEventType(Enum): + Ignore = 0 + StopMainLoop = 1 + ScreenUpdate = 2 + KeyboardInput = 3 + BrailleInput = 4 + PlugInputDevice = 5 + BrailleFlush = 6 + ScreenChanged = 7 + HeartBeat = 8 # for time based scheduling + ExecuteCommand = 9 + def __int__(self): + return self.value + def __str__(self): + return self.name diff --git a/src/fenrir/core/eventManager.py b/src/fenrir/core/eventManager.py new file mode 100644 index 0000000..d34ac94 --- /dev/null +++ b/src/fenrir/core/eventManager.py @@ -0,0 +1,85 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +from core.eventData import fenrirEventType +from queue import Empty +import time +from multiprocessing import Queue +from multiprocessing.sharedctypes import Value +from ctypes import c_bool + +class eventManager(): + def __init__(self): + self.running = Value(c_bool, True) + self._eventQueue = Queue() # multiprocessing.Queue() + self.cleanEventQueue() + def initialize(self, environment): + self.env = environment + def shutdown(self): + self.cleanEventQueue() + + def proceedEventLoop(self): + event = self._eventQueue.get() + st = time.time() + self.eventDispatcher(event) + #print('NET loop ' + str(time.time() - st)) + def eventDispatcher(self, event): + self.env['runtime']['debug'].writeDebugOut('eventManager:eventDispatcher:start: event:' + str(event['Type']) + ' QueueSize:' + str( self._eventQueue.qsize()),debug.debugLevel.INFO) + if not event: + return + if not event['Type']: + return + if event['Type'] == fenrirEventType.Ignore: + return + elif event['Type'] == fenrirEventType.StopMainLoop: + self.handleStopMainLoop(event) + elif event['Type'] == fenrirEventType.ScreenUpdate: + self.env['runtime']['fenrirManager'].handleScreenUpdate(event) + elif event['Type'] == fenrirEventType.KeyboardInput: + self.env['runtime']['fenrirManager'].handleInput(event) + elif event['Type'] == fenrirEventType.BrailleInput: + pass + elif event['Type'] == fenrirEventType.PlugInputDevice: + self.env['runtime']['fenrirManager'].handlePlugInputDevice(event) + pass + elif event['Type'] == fenrirEventType.BrailleFlush: + pass + elif event['Type'] == fenrirEventType.ScreenChanged: + self.env['runtime']['fenrirManager'].handleScreenChange(event) + elif event['Type'] == fenrirEventType.HeartBeat: + self.env['runtime']['fenrirManager'].handleHeartBeat(event) + elif event['Type'] == fenrirEventType.ExecuteCommand: + self.env['runtime']['fenrirManager'].handleExecuteCommand(event) + def isMainEventLoopRunning(self): + return self.running.value == 1 + def startMainEventLoop(self): + self.running.value = 1 + while( self.isMainEventLoopRunning()): + self.proceedEventLoop() + + def handleStopMainLoop(self, event): + self.running.value = 0 + time.sleep(0.1) + def stopMainEventLoop(self): + self._eventQueue.put({"Type":fenrirEventType.StopMainLoop,"Data":None}) + def cleanEventQueue(self): + if self._eventQueue.empty(): + return + try: + while True: + self._eventQueue.get_nowait() + except Empty: + pass + def getEventQueue(self): + return self._eventQueue + def getRunning(self): + return self.running + def putToEventQueue(self,event, data): + if not isinstance(event, fenrirEventType): + return False + self._eventQueue.put({"Type":event,"Data":data}) + return True diff --git a/src/fenrir/core/fenrirManager.py b/src/fenrir/core/fenrirManager.py new file mode 100644 index 0000000..4ac8ec9 --- /dev/null +++ b/src/fenrir/core/fenrirManager.py @@ -0,0 +1,179 @@ +#!/bin/env python3 +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +import os, sys, signal, time + +from core import i18n +from core import settingsManager +from core import debug +from core.eventData import fenrirEventType +import argparse + +class fenrirManager(): + def __init__(self): + self.initialized = False + cliArgs = self.handleArgs() + if not cliArgs: + return + try: + self.environment = settingsManager.settingsManager().initFenrirConfig(cliArgs, self) + if not self.environment: + raise RuntimeError('Cannot Initialize. Maybe the configfile is not available or not parseable') + except RuntimeError: + raise + self.environment['runtime']['outputManager'].presentText(_("Start Fenrir"), soundIcon='ScreenReaderOn', interrupt=True) + signal.signal(signal.SIGINT, self.captureSignal) + signal.signal(signal.SIGTERM, self.captureSignal) + self.initialized = True + self.modifierInput = False + self.singleKeyCommand = False + self.command = '' + def handleArgs(self): + args = None + parser = argparse.ArgumentParser(description="Fenrir Help") + parser.add_argument('-s', '--setting', metavar='SETTING-FILE', default='/etc/fenrir/settings/settings.conf', help='Use a specified settingsfile') + parser.add_argument('-o', '--options', metavar='SECTION#SETTING=VALUE,..', default='', help='Overwrite options in given settings file') + parser.add_argument('-d', '--debug', action='store_true', help='Turns on Debugmode') + parser.add_argument('-p', '--print', action='store_true', help='Print debug messages on screen') + try: + args = parser.parse_args() + except Exception as e: + parser.print_help() + return args + def proceed(self): + if not self.initialized: + return + self.environment['runtime']['eventManager'].startMainEventLoop() + self.shutdown() + def handleInput(self, event): + #startTime = time.time() + eventReceived = self.environment['runtime']['inputManager'].getInputEvent() + if self.environment['runtime']['inputManager'].noKeyPressed(): + self.environment['runtime']['inputManager'].clearLastDeepInput() + if eventReceived: + + if self.environment['runtime']['screenManager'].isSuspendingScreen(): + self.environment['runtime']['inputManager'].writeEventBuffer() + else: + if self.environment['runtime']['helpManager'].isTutorialMode(): + self.environment['runtime']['inputManager'].clearEventBuffer() + + self.detectCommand() + + if self.modifierInput: + self.environment['runtime']['inputManager'].clearEventBuffer() + if self.singleKeyCommand: + if self.environment['runtime']['inputManager'].noKeyPressed(): + self.environment['runtime']['inputManager'].clearEventBuffer() + else: + self.environment['runtime']['inputManager'].writeEventBuffer() + if self.environment['runtime']['inputManager'].noKeyPressed(): + self.modifierInput = False + self.singleKeyCommand = False + if self.environment['input']['keyForeward'] > 0: + self.environment['input']['keyForeward'] -=1 + self.environment['runtime']['screenManager'].update('onInput') + self.environment['runtime']['commandManager'].executeDefaultTrigger('onInput') + #print('handleInput:',time.time() - startTime) + def handleExecuteCommand(self, event): + if event['Data'] == '': + return + command = event['Data'] + if self.environment['runtime']['helpManager'].isTutorialMode(): + if self.environment['runtime']['commandManager'].commandExists( command, 'help'): + self.environment['runtime']['commandManager'].executeCommand( command, 'help') + return + self.environment['runtime']['commandManager'].executeCommand( command, 'commands') + def handleScreenChange(self, event): + self.environment['runtime']['screenManager'].update('onScreenChange') + ''' + if self.environment['runtime']['applicationManager'].isApplicationChange(): + self.environment['runtime']['commandManager'].executeDefaultTrigger('onApplicationChange') + self.environment['runtime']['commandManager'].executeSwitchTrigger('onSwitchApplicationProfile', \ + self.environment['runtime']['applicationManager'].getPrevApplication(), \ + self.environment['runtime']['applicationManager'].getCurrentApplication()) + ''' + self.environment['runtime']['commandManager'].executeDefaultTrigger('onScreenChanged') + self.environment['runtime']['screenManager'].update('onScreenChange') + def handleScreenUpdate(self, event): + #startTime = time.time() + self.environment['runtime']['screenManager'].update('onUpdate') + ''' + if self.environment['runtime']['applicationManager'].isApplicationChange(): + self.environment['runtime']['commandManager'].executeDefaultTrigger('onApplicationChange') + self.environment['runtime']['commandManager'].executeSwitchTrigger('onSwitchApplicationProfile', \ + self.environment['runtime']['applicationManager'].getPrevApplication(), \ + self.environment['runtime']['applicationManager'].getCurrentApplication()) + ''' + # timout for the last keypress + if time.time() - self.environment['runtime']['inputManager'].getLastInputTime() >= 0.3: + self.environment['runtime']['inputManager'].clearLastDeepInput() + # has cursor changed? + if self.environment['runtime']['cursorManager'].isCursorVerticalMove() or \ + self.environment['runtime']['cursorManager'].isCursorHorizontalMove(): + self.environment['runtime']['commandManager'].executeDefaultTrigger('onCursorChange') + self.environment['runtime']['commandManager'].executeDefaultTrigger('onScreenUpdate') + self.environment['runtime']['inputManager'].clearLastDeepInput() + #print('handleScreenUpdate:',time.time() - startTime) + + def handlePlugInputDevice(self, event): + self.environment['runtime']['commandManager'].executeDefaultTrigger('onPlugInputDevice', force=True) + + def handleHeartBeat(self, event): + self.environment['runtime']['commandManager'].executeDefaultTrigger('onHeartBeat',force=True) + #self.environment['runtime']['outputManager'].brailleText(flush=False) + + def detectCommand(self): + if self.environment['input']['keyForeward'] > 0: + return + if self.environment['runtime']['inputManager'].isKeyPress(): + self.modifierInput = self.environment['runtime']['inputManager'].currKeyIsModifier() + else: + if not self.environment['runtime']['inputManager'].noKeyPressed(): + if self.singleKeyCommand: + self.singleKeyCommand = len( self.environment['runtime']['inputManager'].getLastDeepestInput() ) == 1 + # key is already released. we need the old one + if not( self.singleKeyCommand and self.environment['runtime']['inputManager'].noKeyPressed()): + shortcut = self.environment['runtime']['inputManager'].getCurrShortcut() + self.command = self.environment['runtime']['inputManager'].getCommandForShortcut(shortcut) + if not self.modifierInput: + if self.environment['runtime']['inputManager'].isKeyPress(): + if self.command != '': + self.singleKeyCommand = True + + if not (self.singleKeyCommand or self.modifierInput): + return + + # fire event + if self.command != '': + if self.modifierInput: + self.environment['runtime']['eventManager'].putToEventQueue(fenrirEventType.ExecuteCommand, self.command) + self.command = '' + else: + if self.singleKeyCommand: + if self.environment['runtime']['inputManager'].noKeyPressed(): + self.environment['runtime']['eventManager'].putToEventQueue(fenrirEventType.ExecuteCommand, self.command) + self.command = '' + def shutdownRequest(self): + try: + self.environment['runtime']['eventManager'].stopMainEventLoop() + except: + pass + def captureSignal(self, siginit, frame): + self.shutdownRequest() + + def shutdown(self): + self.environment['runtime']['eventManager'].stopMainEventLoop() + self.environment['runtime']['outputManager'].presentText(_("Quit Fenrir"), soundIcon='ScreenReaderOff', interrupt=True) + self.environment['runtime']['eventManager'].cleanEventQueue() + time.sleep(1) + for currManager in self.environment['general']['managerList']: + if self.environment['runtime'][currManager]: + self.environment['runtime'][currManager].shutdown() + del self.environment['runtime'][currManager] + + self.environment = None + diff --git a/src/fenrir/core/generalData.py b/src/fenrir/core/generalData.py new file mode 100644 index 0000000..a33035e --- /dev/null +++ b/src/fenrir/core/generalData.py @@ -0,0 +1,18 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +generalData = { +'args': None, +'tutorialMode': False, +'currUser':'', +'prevUser':'', +'managerList':['processManager','punctuationManager','cursorManager','applicationManager','commandManager' + ,'screenManager','inputManager','outputManager','helpManager','eventManager','debug'], +'commandFolderList':['commands','onInput', 'onCursorChange', 'onScreenUpdate','onScreenChanged','onHeartBeat', 'onPlugInputDevice' + ,'onApplicationChange','onSwitchApplicationProfile','help',], +} diff --git a/src/fenrir/core/generalInformation.py b/src/fenrir/core/generalInformation.py deleted file mode 100644 index 2a0c601..0000000 --- a/src/fenrir/core/generalInformation.py +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from core import debug - -generalInformation = { -'running': True, -'tutorialMode': False, -} diff --git a/src/fenrir/core/helpManager.py b/src/fenrir/core/helpManager.py new file mode 100755 index 0000000..0370ed7 --- /dev/null +++ b/src/fenrir/core/helpManager.py @@ -0,0 +1,81 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + + +class helpManager(): + def __init__(self): + self.helpDict = {} + self.tutorialListIndex = None + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def toggleTutorialMode(self): + self.setTutorialMode(not self.env['general']['tutorialMode']) + def setTutorialMode(self, newTutorialMode): + self.env['general']['tutorialMode'] = newTutorialMode + if newTutorialMode: + self.createHelpDict() + self.env['bindings'][str([1, ['KEY_ESC']])] = 'TOGGLE_TUTORIAL_MODE' + self.env['bindings'][str([1, ['KEY_UP']])] = 'PREV_HELP' + self.env['bindings'][str([1, ['KEY_DOWN']])] = 'NEXT_HELP' + self.env['bindings'][str([1, ['KEY_SPACE']])] = 'CURR_HELP' + else: + try: + del(self.env['bindings'][str([1, ['KEY_ESC']])]) + del(self.env['bindings'][str([1, ['KEY_UP']])]) + del(self.env['bindings'][str([1, ['KEY_DOWN']])]) + del(self.env['bindings'][str([1, ['KEY_SPACE']])]) + except: + pass + def isTutorialMode(self): + return self.env['general']['tutorialMode'] + def getCommandHelpText(self, command, section = 'commands'): + commandName = command.lower() + commandName = commandName.split('__-__')[0] + commandName = commandName.replace('_',' ') + commandName = commandName.replace('_',' ') + if command == 'TOGGLE_TUTORIAL_MODE': + commandDescription = _('toggles the tutorial mode') + else: + commandDescription = self.env['runtime']['commandManager'].getCommandDescription( command, section = 'commands') + if commandDescription == '': + commandDescription = 'no Description available' + commandShortcut = self.env['runtime']['commandManager'].getShortcutForCommand( command) + commandShortcut = commandShortcut.replace('KEY_',' ') + commandShortcut = commandShortcut.replace('[','') + commandShortcut = commandShortcut.replace(']','') + commandShortcut = commandShortcut.replace("'",'') + if commandShortcut == '': + commandShortcut = 'unbound' + helptext = commandName + ', Shortcut ' + commandShortcut + ', Description ' + commandDescription + return helptext + def createHelpDict(self, section = 'commands'): + self.helpDict = {} + for command in sorted(self.env['commands'][section].keys()): + self.helpDict[len(self.helpDict)] = self.getCommandHelpText(command, section) + if len(self.helpDict) > 0: + self.tutorialListIndex = 0 + else: + self.tutorialListIndex = None + def getHelpForCurrentIndex(self): + if self.tutorialListIndex == None: + return '' + return self.helpDict[self.tutorialListIndex] + def nextIndex(self): + if self.tutorialListIndex == None: + return + self.tutorialListIndex += 1 + if self.tutorialListIndex >= len(self.helpDict): + self.tutorialListIndex = 0 + def prevIndex(self): + if self.tutorialListIndex == None: + return + self.tutorialListIndex -= 1 + if self.tutorialListIndex < 0: + self.tutorialListIndex = len(self.helpDict) - 1 diff --git a/src/fenrir/core/i18n.py b/src/fenrir/core/i18n.py new file mode 100644 index 0000000..6f1c308 --- /dev/null +++ b/src/fenrir/core/i18n.py @@ -0,0 +1,11 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +import gettext +import locale + +# the only function we really need to call here is gettext.install. Python3 has simplified this. +gettext.install("fenrir") diff --git a/src/fenrir/core/inputData.py b/src/fenrir/core/inputData.py new file mode 100644 index 0000000..6b2fdf9 --- /dev/null +++ b/src/fenrir/core/inputData.py @@ -0,0 +1,36 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +import time + +inputData = { +'currInput': [], +'prevDeepestInput': [], +'eventBuffer': [], +'shortcutRepeat': 0, +'fenrirKey': [], +'scriptKey': [], +'keyForeward': 0, +'lastInputTime':time.time(), +'oldNumLock': True, +'newNumLock':True, +'oldScrollLock': True, +'newScrollLock':True, +'oldCapsLock':False, +'newCapsLock':False +} + +inputEvent = { +'EventName': '', +'EventValue': '', +'EventSec': 0, +'EventUsec': 0, +'EventState': 0, +} + +keyNames = ['KEY_RESERVED', 'KEY_ESC', 'KEY_1', 'KEY_2', 'KEY_3', 'KEY_4', 'KEY_5', 'KEY_6', 'KEY_7', 'KEY_8', 'KEY_9', 'KEY_0', 'KEY_MINUS', 'KEY_EQUAL', 'KEY_BACKSPACE', 'KEY_TAB', 'KEY_Q', 'KEY_W', 'KEY_E', 'KEY_R', 'KEY_T', 'KEY_Y', 'KEY_U', 'KEY_I', 'KEY_O', 'KEY_P', 'KEY_LEFTBRACE', 'KEY_RIGHTBRACE', 'KEY_ENTER', 'KEY_LEFTCTRL', 'KEY_A', 'KEY_S', 'KEY_D', 'KEY_F', 'KEY_G', 'KEY_H', 'KEY_J', 'KEY_K', 'KEY_L', 'KEY_SEMICOLON', 'KEY_APOSTROPHE', 'KEY_GRAVE', 'KEY_LEFTSHIFT', 'KEY_BACKSLASH', 'KEY_Z', 'KEY_X', 'KEY_C', 'KEY_V', 'KEY_B', 'KEY_N', 'KEY_M', 'KEY_COMMA', 'KEY_DOT', 'KEY_SLASH', 'KEY_RIGHTSHIFT', 'KEY_KPASTERISK', 'KEY_LEFTALT', 'KEY_SPACE', 'KEY_CAPSLOCK', 'KEY_F1', 'KEY_F2', 'KEY_F3', 'KEY_F4', 'KEY_F5', 'KEY_F6', 'KEY_F7', 'KEY_F8', 'KEY_F9', 'KEY_F10', 'KEY_NUMLOCK', 'KEY_SCROLLLOCK', 'KEY_KP7', 'KEY_KP8', 'KEY_KP9', 'KEY_KPMINUS', 'KEY_KP4', 'KEY_KP5', 'KEY_KP6', 'KEY_KPPLUS', 'KEY_KP1', 'KEY_KP2', 'KEY_KP3', 'KEY_KP0', 'KEY_KPDOT', 'KEY_ZENKAKUHANKAKU', 'KEY_102ND', 'KEY_F11', 'KEY_F12', 'KEY_RO', 'KEY_KATAKANA', 'KEY_HIRAGANA', 'KEY_HENKAN', 'KEY_KATAKANAHIRAGANA', 'KEY_MUHENKAN', 'KEY_KPJPCOMMA', 'KEY_KPENTER', 'KEY_RIGHTCTRL', 'KEY_KPSLASH', 'KEY_SYSRQ', 'KEY_RIGHTALT', 'KEY_LINEFEED', 'KEY_HOME', 'KEY_UP', 'KEY_PAGEUP', 'KEY_LEFT', 'KEY_RIGHT', 'KEY_END', 'KEY_DOWN', 'KEY_PAGEDOWN', 'KEY_INSERT', 'KEY_DELETE', 'KEY_MACRO', 'KEY_MIN_INTERESTING', 'KEY_MUTE', 'KEY_VOLUMEDOWN', 'KEY_VOLUMEUP', 'KEY_POWER', 'KEY_KPEQUAL', 'KEY_KPPLUSMINUS', 'KEY_PAUSE', 'KEY_SCALE', 'KEY_KPCOMMA', 'KEY_HANGEUL', 'KEY_HANGUEL', 'KEY_HANJA', 'KEY_YEN', 'KEY_LEFTMETA', 'KEY_RIGHTMETA', 'KEY_COMPOSE', 'KEY_STOP', 'KEY_AGAIN', 'KEY_PROPS', 'KEY_UNDO', 'KEY_FRONT', 'KEY_COPY', 'KEY_OPEN', 'KEY_PASTE', 'KEY_FIND', 'KEY_CUT', 'KEY_HELP', 'KEY_MENU', 'KEY_CALC', 'KEY_SETUP', 'KEY_SLEEP', 'KEY_WAKEUP', 'KEY_FILE', 'KEY_SENDFILE', 'KEY_DELETEFILE', 'KEY_XFER', 'KEY_PROG1', 'KEY_PROG2', 'KEY_WWW', 'KEY_MSDOS', 'KEY_COFFEE', 'KEY_SCREENLOCK', 'KEY_DIRECTION', 'KEY_ROTATE_DISPLAY', 'KEY_CYCLEWINDOWS', 'KEY_MAIL', 'KEY_BOOKMARKS', 'KEY_COMPUTER', 'KEY_BACK', 'KEY_FORWARD', 'KEY_CLOSECD', 'KEY_EJECTCD', 'KEY_EJECTCLOSECD', 'KEY_NEXTSONG', 'KEY_PLAYPAUSE', 'KEY_PREVIOUSSONG', 'KEY_STOPCD', 'KEY_RECORD', 'KEY_REWIND', 'KEY_PHONE', 'KEY_ISO', 'KEY_CONFIG', 'KEY_HOMEPAGE', 'KEY_REFRESH', 'KEY_EXIT', 'KEY_MOVE', 'KEY_EDIT', 'KEY_SCROLLUP', 'KEY_SCROLLDOWN', 'KEY_KPLEFTPAREN', 'KEY_KPRIGHTPAREN', 'KEY_NEW', 'KEY_REDO', 'KEY_F13', 'KEY_F14', 'KEY_F15', 'KEY_F16', 'KEY_F17', 'KEY_F18', 'KEY_F19', 'KEY_F20', 'KEY_F21', 'KEY_F22', 'KEY_F23', 'KEY_F24', 'KEY_PLAYCD', 'KEY_PAUSECD', 'KEY_PROG3', 'KEY_PROG4', 'KEY_DASHBOARD', 'KEY_SUSPEND', 'KEY_CLOSE', 'KEY_PLAY', 'KEY_FASTFORWARD', 'KEY_BASSBOOST', 'KEY_PRINT', 'KEY_HP', 'KEY_CAMERA', 'KEY_SOUND', 'KEY_QUESTION', 'KEY_EMAIL', 'KEY_CHAT', 'KEY_SEARCH', 'KEY_CONNECT', 'KEY_FINANCE', 'KEY_SPORT', 'KEY_SHOP', 'KEY_ALTERASE', 'KEY_CANCEL', 'KEY_BRIGHTNESSDOWN', 'KEY_BRIGHTNESSUP', 'KEY_MEDIA', 'KEY_SWITCHVIDEOMODE', 'KEY_KBDILLUMTOGGLE', 'KEY_KBDILLUMDOWN', 'KEY_KBDILLUMUP', 'KEY_SEND', 'KEY_REPLY', 'KEY_FORWARDMAIL', 'KEY_SAVE', 'KEY_DOCUMENTS', 'KEY_BATTERY', 'KEY_BLUETOOTH', 'KEY_WLAN', 'KEY_UWB', 'KEY_UNKNOWN', 'KEY_VIDEO_NEXT', 'KEY_VIDEO_PREV', 'KEY_BRIGHTNESS_CYCLE', 'KEY_BRIGHTNESS_AUTO', 'KEY_BRIGHTNESS_ZERO', 'KEY_DISPLAY_OFF', 'KEY_WIMAX', 'KEY_WWAN', 'KEY_RFKILL', 'KEY_MICMUTE', 'BTN_0', 'BTN_MISC', 'BTN_1', 'BTN_2', 'BTN_3', 'BTN_4', 'BTN_5', 'BTN_6', 'BTN_7', 'BTN_8', 'BTN_9', 'BTN_LEFT', 'BTN_MOUSE', 'BTN_RIGHT', 'BTN_MIDDLE', 'BTN_SIDE', 'BTN_EXTRA', 'BTN_FORWARD', 'BTN_BACK', 'BTN_TASK', 'BTN_JOYSTICK', 'BTN_TRIGGER', 'BTN_THUMB', 'BTN_THUMB2', 'BTN_TOP', 'BTN_TOP2', 'BTN_PINKIE', 'BTN_BASE', 'BTN_BASE2', 'BTN_BASE3', 'BTN_BASE4', 'BTN_BASE5', 'BTN_BASE6', 'BTN_DEAD', 'BTN_A', 'BTN_GAMEPAD', 'BTN_SOUTH', 'BTN_B', 'BTN_EAST', 'BTN_C', 'BTN_NORTH', 'BTN_X', 'BTN_WEST', 'BTN_Y', 'BTN_Z', 'BTN_TL', 'BTN_TR', 'BTN_TL2', 'BTN_TR2', 'BTN_SELECT', 'BTN_START', 'BTN_MODE', 'BTN_THUMBL', 'BTN_THUMBR', 'BTN_DIGI', 'BTN_TOOL_PEN', 'BTN_TOOL_RUBBER', 'BTN_TOOL_BRUSH', 'BTN_TOOL_PENCIL', 'BTN_TOOL_AIRBRUSH', 'BTN_TOOL_FINGER', 'BTN_TOOL_MOUSE', 'BTN_TOOL_LENS', 'BTN_TOOL_QUINTTAP', 'BTN_TOUCH', 'BTN_STYLUS', 'BTN_STYLUS2', 'BTN_TOOL_DOUBLETAP', 'BTN_TOOL_TRIPLETAP', 'BTN_TOOL_QUADTAP', 'BTN_GEAR_DOWN', 'BTN_WHEEL', 'BTN_GEAR_UP', 'KEY_OK', 'KEY_SELECT', 'KEY_GOTO', 'KEY_CLEAR', 'KEY_POWER2', 'KEY_OPTION', 'KEY_INFO', 'KEY_TIME', 'KEY_VENDOR', 'KEY_ARCHIVE', 'KEY_PROGRAM', 'KEY_CHANNEL', 'KEY_FAVORITES', 'KEY_EPG', 'KEY_PVR', 'KEY_MHP', 'KEY_LANGUAGE', 'KEY_TITLE', 'KEY_SUBTITLE', 'KEY_ANGLE', 'KEY_ZOOM', 'KEY_MODE', 'KEY_KEYBOARD', 'KEY_SCREEN', 'KEY_PC', 'KEY_TV', 'KEY_TV2', 'KEY_VCR', 'KEY_VCR2', 'KEY_SAT', 'KEY_SAT2', 'KEY_CD', 'KEY_TAPE', 'KEY_RADIO', 'KEY_TUNER', 'KEY_PLAYER', 'KEY_TEXT', 'KEY_DVD', 'KEY_AUX', 'KEY_MP3', 'KEY_AUDIO', 'KEY_VIDEO', 'KEY_DIRECTORY', 'KEY_LIST', 'KEY_MEMO', 'KEY_CALENDAR', 'KEY_RED', 'KEY_GREEN', 'KEY_YELLOW', 'KEY_BLUE', 'KEY_CHANNELUP', 'KEY_CHANNELDOWN', 'KEY_FIRST', 'KEY_LAST', 'KEY_AB', 'KEY_NEXT', 'KEY_RESTART', 'KEY_SLOW', 'KEY_SHUFFLE', 'KEY_BREAK', 'KEY_PREVIOUS', 'KEY_DIGITS', 'KEY_TEEN', 'KEY_TWEN', 'KEY_VIDEOPHONE', 'KEY_GAMES', 'KEY_ZOOMIN', 'KEY_ZOOMOUT', 'KEY_ZOOMRESET', 'KEY_WORDPROCESSOR', 'KEY_EDITOR', 'KEY_SPREADSHEET', 'KEY_GRAPHICSEDITOR', 'KEY_PRESENTATION', 'KEY_DATABASE', 'KEY_NEWS', 'KEY_VOICEMAIL', 'KEY_ADDRESSBOOK', 'KEY_MESSENGER', 'KEY_BRIGHTNESS_TOGGLE', 'KEY_DISPLAYTOGGLE', 'KEY_SPELLCHECK', 'KEY_LOGOFF', 'KEY_DOLLAR', 'KEY_EURO', 'KEY_FRAMEBACK', 'KEY_FRAMEFORWARD', 'KEY_CONTEXT_MENU', 'KEY_MEDIA_REPEAT', 'KEY_10CHANNELSUP', 'KEY_10CHANNELSDOWN', 'KEY_IMAGES', 'KEY_DEL_EOL', 'KEY_DEL_EOS', 'KEY_INS_LINE', 'KEY_DEL_LINE', 'KEY_FN', 'KEY_FN_ESC', 'KEY_FN_F1', 'KEY_FN_F2', 'KEY_FN_F3', 'KEY_FN_F4', 'KEY_FN_F5', 'KEY_FN_F6', 'KEY_FN_F7', 'KEY_FN_F8', 'KEY_FN_F9', 'KEY_FN_F10', 'KEY_FN_F11', 'KEY_FN_F12', 'KEY_FN_1', 'KEY_FN_2', 'KEY_FN_D', 'KEY_FN_E', 'KEY_FN_F', 'KEY_FN_S', 'KEY_FN_B', 'KEY_BRL_DOT1', 'KEY_BRL_DOT2', 'KEY_BRL_DOT3', 'KEY_BRL_DOT4', 'KEY_BRL_DOT5', 'KEY_BRL_DOT6', 'KEY_BRL_DOT7', 'KEY_BRL_DOT8', 'KEY_BRL_DOT9', 'KEY_BRL_DOT10', 'KEY_NUMERIC_0', 'KEY_NUMERIC_1', 'KEY_NUMERIC_2', 'KEY_NUMERIC_3', 'KEY_NUMERIC_4', 'KEY_NUMERIC_5', 'KEY_NUMERIC_6', 'KEY_NUMERIC_7', 'KEY_NUMERIC_8', 'KEY_NUMERIC_9', 'KEY_NUMERIC_STAR', 'KEY_NUMERIC_POUND', 'KEY_NUMERIC_A', 'KEY_NUMERIC_B', 'KEY_NUMERIC_C', 'KEY_NUMERIC_D', 'KEY_CAMERA_FOCUS', 'KEY_WPS_BUTTON', 'KEY_TOUCHPAD_TOGGLE', 'KEY_TOUCHPAD_ON', 'KEY_TOUCHPAD_OFF', 'KEY_CAMERA_ZOOMIN', 'KEY_CAMERA_ZOOMOUT', 'KEY_CAMERA_UP', 'KEY_CAMERA_DOWN', 'KEY_CAMERA_LEFT', 'KEY_CAMERA_RIGHT', 'KEY_ATTENDANT_ON', 'KEY_ATTENDANT_OFF', 'KEY_ATTENDANT_TOGGLE', 'KEY_LIGHTS_TOGGLE', 'BTN_DPAD_UP', 'BTN_DPAD_DOWN', 'BTN_DPAD_LEFT', 'BTN_DPAD_RIGHT', 'KEY_ALS_TOGGLE', 'KEY_BUTTONCONFIG', 'KEY_TASKMANAGER', 'KEY_JOURNAL', 'KEY_CONTROLPANEL', 'KEY_APPSELECT', 'KEY_SCREENSAVER', 'KEY_VOICECOMMAND', 'KEY_BRIGHTNESS_MIN', 'KEY_BRIGHTNESS_MAX', 'KEY_KBDINPUTASSIST_PREV', 'KEY_KBDINPUTASSIST_NEXT', 'KEY_KBDINPUTASSIST_PREVGROUP', 'KEY_KBDINPUTASSIST_NEXTGROUP', 'KEY_KBDINPUTASSIST_ACCEPT', 'KEY_KBDINPUTASSIST_CANCEL', 'KEY_RIGHT_UP', 'KEY_RIGHT_DOWN', 'KEY_LEFT_UP', 'KEY_LEFT_DOWN', 'KEY_ROOT_MENU', 'KEY_MEDIA_TOP_MENU', 'KEY_NUMERIC_11', 'KEY_NUMERIC_12', 'KEY_AUDIO_DESC', 'KEY_3D_MODE', 'KEY_NEXT_FAVORITE', 'KEY_STOP_RECORD', 'KEY_PAUSE_RECORD', 'KEY_VOD', 'KEY_UNMUTE', 'KEY_DATA', 'KEY_FASTREVERSE', 'KEY_SLOWREVERSE', 'BTN_TRIGGER_HAPPY', 'BTN_TRIGGER_HAPPY1', 'BTN_TRIGGER_HAPPY2', 'BTN_TRIGGER_HAPPY3', 'BTN_TRIGGER_HAPPY4', 'BTN_TRIGGER_HAPPY5', 'BTN_TRIGGER_HAPPY6', 'BTN_TRIGGER_HAPPY7', 'BTN_TRIGGER_HAPPY8', 'BTN_TRIGGER_HAPPY9', 'BTN_TRIGGER_HAPPY10', 'BTN_TRIGGER_HAPPY11', 'BTN_TRIGGER_HAPPY12', 'BTN_TRIGGER_HAPPY13', 'BTN_TRIGGER_HAPPY14', 'BTN_TRIGGER_HAPPY15', 'BTN_TRIGGER_HAPPY16', 'BTN_TRIGGER_HAPPY17', 'BTN_TRIGGER_HAPPY18', 'BTN_TRIGGER_HAPPY19', 'BTN_TRIGGER_HAPPY20', 'BTN_TRIGGER_HAPPY21', 'BTN_TRIGGER_HAPPY22', 'BTN_TRIGGER_HAPPY23', 'BTN_TRIGGER_HAPPY24', 'BTN_TRIGGER_HAPPY25', 'BTN_TRIGGER_HAPPY26', 'BTN_TRIGGER_HAPPY27', 'BTN_TRIGGER_HAPPY28', 'BTN_TRIGGER_HAPPY29', 'BTN_TRIGGER_HAPPY30', 'BTN_TRIGGER_HAPPY31', 'BTN_TRIGGER_HAPPY32', 'BTN_TRIGGER_HAPPY33', 'BTN_TRIGGER_HAPPY34', 'BTN_TRIGGER_HAPPY35', 'BTN_TRIGGER_HAPPY36', 'BTN_TRIGGER_HAPPY37', 'BTN_TRIGGER_HAPPY38', 'BTN_TRIGGER_HAPPY39', 'BTN_TRIGGER_HAPPY40', 'KEY_FENRIR', 'KEY_SCRIPT', 'KEY_ALT', 'KEY_CTRL', 'KEY_META', 'KEY_SHIFT'] + diff --git a/src/fenrir/core/inputEvent.py b/src/fenrir/core/inputEvent.py deleted file mode 100644 index c01b48f..0000000 --- a/src/fenrir/core/inputEvent.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from core import debug -import time - -input = { -'currInput': [], -'prevDeepestInput': [], -'eventBuffer': [], -'shortcutRepeat': 0, -'fenrirKey': [], -'scriptKey': [], -'keyForeward': 0, -'lastInputTime':time.time(), -'oldNumLock': True, -'newNumLock':True, -'oldScrollLock': True, -'newScrollLock':True, -'oldCapsLock':False, -'newCapsLock':False -} - -inputEvent = { -'EventName': '', -'EventValue': '', -'EventSec': 0, -'EventUsec': 0, -'EventState': 0, -} - - -keyNames = ['KEY_RESERVED', 'KEY_ESC', 'KEY_1', 'KEY_2', 'KEY_3', 'KEY_4', 'KEY_5', 'KEY_6', 'KEY_7', 'KEY_8', 'KEY_9', 'KEY_0', 'KEY_MINUS', 'KEY_EQUAL', 'KEY_BACKSPACE', 'KEY_TAB', 'KEY_Q', 'KEY_W', 'KEY_E', 'KEY_R', 'KEY_T', 'KEY_Y', 'KEY_U', 'KEY_I', 'KEY_O', 'KEY_P', 'KEY_LEFTBRACE', 'KEY_RIGHTBRACE', 'KEY_ENTER', 'KEY_LEFTCTRL', 'KEY_A', 'KEY_S', 'KEY_D', 'KEY_F', 'KEY_G', 'KEY_H', 'KEY_J', 'KEY_K', 'KEY_L', 'KEY_SEMICOLON', 'KEY_APOSTROPHE', 'KEY_GRAVE', 'KEY_LEFTSHIFT', 'KEY_BACKSLASH', 'KEY_Z', 'KEY_X', 'KEY_C', 'KEY_V', 'KEY_B', 'KEY_N', 'KEY_M', 'KEY_COMMA', 'KEY_DOT', 'KEY_SLASH', 'KEY_RIGHTSHIFT', 'KEY_KPASTERISK', 'KEY_LEFTALT', 'KEY_SPACE', 'KEY_CAPSLOCK', 'KEY_F1', 'KEY_F2', 'KEY_F3', 'KEY_F4', 'KEY_F5', 'KEY_F6', 'KEY_F7', 'KEY_F8', 'KEY_F9', 'KEY_F10', 'KEY_NUMLOCK', 'KEY_SCROLLLOCK', 'KEY_KP7', 'KEY_KP8', 'KEY_KP9', 'KEY_KPMINUS', 'KEY_KP4', 'KEY_KP5', 'KEY_KP6', 'KEY_KPPLUS', 'KEY_KP1', 'KEY_KP2', 'KEY_KP3', 'KEY_KP0', 'KEY_KPDOT', 'KEY_ZENKAKUHANKAKU', 'KEY_102ND', 'KEY_F11', 'KEY_F12', 'KEY_RO', 'KEY_KATAKANA', 'KEY_HIRAGANA', 'KEY_HENKAN', 'KEY_KATAKANAHIRAGANA', 'KEY_MUHENKAN', 'KEY_KPJPCOMMA', 'KEY_KPENTER', 'KEY_RIGHTCTRL', 'KEY_KPSLASH', 'KEY_SYSRQ', 'KEY_RIGHTALT', 'KEY_LINEFEED', 'KEY_HOME', 'KEY_UP', 'KEY_PAGEUP', 'KEY_LEFT', 'KEY_RIGHT', 'KEY_END', 'KEY_DOWN', 'KEY_PAGEDOWN', 'KEY_INSERT', 'KEY_DELETE', 'KEY_MACRO', 'KEY_MIN_INTERESTING', 'KEY_MUTE', 'KEY_VOLUMEDOWN', 'KEY_VOLUMEUP', 'KEY_POWER', 'KEY_KPEQUAL', 'KEY_KPPLUSMINUS', 'KEY_PAUSE', 'KEY_SCALE', 'KEY_KPCOMMA', 'KEY_HANGEUL', 'KEY_HANGUEL', 'KEY_HANJA', 'KEY_YEN', 'KEY_LEFTMETA', 'KEY_RIGHTMETA', 'KEY_COMPOSE', 'KEY_STOP', 'KEY_AGAIN', 'KEY_PROPS', 'KEY_UNDO', 'KEY_FRONT', 'KEY_COPY', 'KEY_OPEN', 'KEY_PASTE', 'KEY_FIND', 'KEY_CUT', 'KEY_HELP', 'KEY_MENU', 'KEY_CALC', 'KEY_SETUP', 'KEY_SLEEP', 'KEY_WAKEUP', 'KEY_FILE', 'KEY_SENDFILE', 'KEY_DELETEFILE', 'KEY_XFER', 'KEY_PROG1', 'KEY_PROG2', 'KEY_WWW', 'KEY_MSDOS', 'KEY_COFFEE', 'KEY_SCREENLOCK', 'KEY_DIRECTION', 'KEY_ROTATE_DISPLAY', 'KEY_CYCLEWINDOWS', 'KEY_MAIL', 'KEY_BOOKMARKS', 'KEY_COMPUTER', 'KEY_BACK', 'KEY_FORWARD', 'KEY_CLOSECD', 'KEY_EJECTCD', 'KEY_EJECTCLOSECD', 'KEY_NEXTSONG', 'KEY_PLAYPAUSE', 'KEY_PREVIOUSSONG', 'KEY_STOPCD', 'KEY_RECORD', 'KEY_REWIND', 'KEY_PHONE', 'KEY_ISO', 'KEY_CONFIG', 'KEY_HOMEPAGE', 'KEY_REFRESH', 'KEY_EXIT', 'KEY_MOVE', 'KEY_EDIT', 'KEY_SCROLLUP', 'KEY_SCROLLDOWN', 'KEY_KPLEFTPAREN', 'KEY_KPRIGHTPAREN', 'KEY_NEW', 'KEY_REDO', 'KEY_F13', 'KEY_F14', 'KEY_F15', 'KEY_F16', 'KEY_F17', 'KEY_F18', 'KEY_F19', 'KEY_F20', 'KEY_F21', 'KEY_F22', 'KEY_F23', 'KEY_F24', 'KEY_PLAYCD', 'KEY_PAUSECD', 'KEY_PROG3', 'KEY_PROG4', 'KEY_DASHBOARD', 'KEY_SUSPEND', 'KEY_CLOSE', 'KEY_PLAY', 'KEY_FASTFORWARD', 'KEY_BASSBOOST', 'KEY_PRINT', 'KEY_HP', 'KEY_CAMERA', 'KEY_SOUND', 'KEY_QUESTION', 'KEY_EMAIL', 'KEY_CHAT', 'KEY_SEARCH', 'KEY_CONNECT', 'KEY_FINANCE', 'KEY_SPORT', 'KEY_SHOP', 'KEY_ALTERASE', 'KEY_CANCEL', 'KEY_BRIGHTNESSDOWN', 'KEY_BRIGHTNESSUP', 'KEY_MEDIA', 'KEY_SWITCHVIDEOMODE', 'KEY_KBDILLUMTOGGLE', 'KEY_KBDILLUMDOWN', 'KEY_KBDILLUMUP', 'KEY_SEND', 'KEY_REPLY', 'KEY_FORWARDMAIL', 'KEY_SAVE', 'KEY_DOCUMENTS', 'KEY_BATTERY', 'KEY_BLUETOOTH', 'KEY_WLAN', 'KEY_UWB', 'KEY_UNKNOWN', 'KEY_VIDEO_NEXT', 'KEY_VIDEO_PREV', 'KEY_BRIGHTNESS_CYCLE', 'KEY_BRIGHTNESS_AUTO', 'KEY_BRIGHTNESS_ZERO', 'KEY_DISPLAY_OFF', 'KEY_WIMAX', 'KEY_WWAN', 'KEY_RFKILL', 'KEY_MICMUTE', 'BTN_0', 'BTN_MISC', 'BTN_1', 'BTN_2', 'BTN_3', 'BTN_4', 'BTN_5', 'BTN_6', 'BTN_7', 'BTN_8', 'BTN_9', 'BTN_LEFT', 'BTN_MOUSE', 'BTN_RIGHT', 'BTN_MIDDLE', 'BTN_SIDE', 'BTN_EXTRA', 'BTN_FORWARD', 'BTN_BACK', 'BTN_TASK', 'BTN_JOYSTICK', 'BTN_TRIGGER', 'BTN_THUMB', 'BTN_THUMB2', 'BTN_TOP', 'BTN_TOP2', 'BTN_PINKIE', 'BTN_BASE', 'BTN_BASE2', 'BTN_BASE3', 'BTN_BASE4', 'BTN_BASE5', 'BTN_BASE6', 'BTN_DEAD', 'BTN_A', 'BTN_GAMEPAD', 'BTN_SOUTH', 'BTN_B', 'BTN_EAST', 'BTN_C', 'BTN_NORTH', 'BTN_X', 'BTN_WEST', 'BTN_Y', 'BTN_Z', 'BTN_TL', 'BTN_TR', 'BTN_TL2', 'BTN_TR2', 'BTN_SELECT', 'BTN_START', 'BTN_MODE', 'BTN_THUMBL', 'BTN_THUMBR', 'BTN_DIGI', 'BTN_TOOL_PEN', 'BTN_TOOL_RUBBER', 'BTN_TOOL_BRUSH', 'BTN_TOOL_PENCIL', 'BTN_TOOL_AIRBRUSH', 'BTN_TOOL_FINGER', 'BTN_TOOL_MOUSE', 'BTN_TOOL_LENS', 'BTN_TOOL_QUINTTAP', 'BTN_TOUCH', 'BTN_STYLUS', 'BTN_STYLUS2', 'BTN_TOOL_DOUBLETAP', 'BTN_TOOL_TRIPLETAP', 'BTN_TOOL_QUADTAP', 'BTN_GEAR_DOWN', 'BTN_WHEEL', 'BTN_GEAR_UP', 'KEY_OK', 'KEY_SELECT', 'KEY_GOTO', 'KEY_CLEAR', 'KEY_POWER2', 'KEY_OPTION', 'KEY_INFO', 'KEY_TIME', 'KEY_VENDOR', 'KEY_ARCHIVE', 'KEY_PROGRAM', 'KEY_CHANNEL', 'KEY_FAVORITES', 'KEY_EPG', 'KEY_PVR', 'KEY_MHP', 'KEY_LANGUAGE', 'KEY_TITLE', 'KEY_SUBTITLE', 'KEY_ANGLE', 'KEY_ZOOM', 'KEY_MODE', 'KEY_KEYBOARD', 'KEY_SCREEN', 'KEY_PC', 'KEY_TV', 'KEY_TV2', 'KEY_VCR', 'KEY_VCR2', 'KEY_SAT', 'KEY_SAT2', 'KEY_CD', 'KEY_TAPE', 'KEY_RADIO', 'KEY_TUNER', 'KEY_PLAYER', 'KEY_TEXT', 'KEY_DVD', 'KEY_AUX', 'KEY_MP3', 'KEY_AUDIO', 'KEY_VIDEO', 'KEY_DIRECTORY', 'KEY_LIST', 'KEY_MEMO', 'KEY_CALENDAR', 'KEY_RED', 'KEY_GREEN', 'KEY_YELLOW', 'KEY_BLUE', 'KEY_CHANNELUP', 'KEY_CHANNELDOWN', 'KEY_FIRST', 'KEY_LAST', 'KEY_AB', 'KEY_NEXT', 'KEY_RESTART', 'KEY_SLOW', 'KEY_SHUFFLE', 'KEY_BREAK', 'KEY_PREVIOUS', 'KEY_DIGITS', 'KEY_TEEN', 'KEY_TWEN', 'KEY_VIDEOPHONE', 'KEY_GAMES', 'KEY_ZOOMIN', 'KEY_ZOOMOUT', 'KEY_ZOOMRESET', 'KEY_WORDPROCESSOR', 'KEY_EDITOR', 'KEY_SPREADSHEET', 'KEY_GRAPHICSEDITOR', 'KEY_PRESENTATION', 'KEY_DATABASE', 'KEY_NEWS', 'KEY_VOICEMAIL', 'KEY_ADDRESSBOOK', 'KEY_MESSENGER', 'KEY_BRIGHTNESS_TOGGLE', 'KEY_DISPLAYTOGGLE', 'KEY_SPELLCHECK', 'KEY_LOGOFF', 'KEY_DOLLAR', 'KEY_EURO', 'KEY_FRAMEBACK', 'KEY_FRAMEFORWARD', 'KEY_CONTEXT_MENU', 'KEY_MEDIA_REPEAT', 'KEY_10CHANNELSUP', 'KEY_10CHANNELSDOWN', 'KEY_IMAGES', 'KEY_DEL_EOL', 'KEY_DEL_EOS', 'KEY_INS_LINE', 'KEY_DEL_LINE', 'KEY_FN', 'KEY_FN_ESC', 'KEY_FN_F1', 'KEY_FN_F2', 'KEY_FN_F3', 'KEY_FN_F4', 'KEY_FN_F5', 'KEY_FN_F6', 'KEY_FN_F7', 'KEY_FN_F8', 'KEY_FN_F9', 'KEY_FN_F10', 'KEY_FN_F11', 'KEY_FN_F12', 'KEY_FN_1', 'KEY_FN_2', 'KEY_FN_D', 'KEY_FN_E', 'KEY_FN_F', 'KEY_FN_S', 'KEY_FN_B', 'KEY_BRL_DOT1', 'KEY_BRL_DOT2', 'KEY_BRL_DOT3', 'KEY_BRL_DOT4', 'KEY_BRL_DOT5', 'KEY_BRL_DOT6', 'KEY_BRL_DOT7', 'KEY_BRL_DOT8', 'KEY_BRL_DOT9', 'KEY_BRL_DOT10', 'KEY_NUMERIC_0', 'KEY_NUMERIC_1', 'KEY_NUMERIC_2', 'KEY_NUMERIC_3', 'KEY_NUMERIC_4', 'KEY_NUMERIC_5', 'KEY_NUMERIC_6', 'KEY_NUMERIC_7', 'KEY_NUMERIC_8', 'KEY_NUMERIC_9', 'KEY_NUMERIC_STAR', 'KEY_NUMERIC_POUND', 'KEY_NUMERIC_A', 'KEY_NUMERIC_B', 'KEY_NUMERIC_C', 'KEY_NUMERIC_D', 'KEY_CAMERA_FOCUS', 'KEY_WPS_BUTTON', 'KEY_TOUCHPAD_TOGGLE', 'KEY_TOUCHPAD_ON', 'KEY_TOUCHPAD_OFF', 'KEY_CAMERA_ZOOMIN', 'KEY_CAMERA_ZOOMOUT', 'KEY_CAMERA_UP', 'KEY_CAMERA_DOWN', 'KEY_CAMERA_LEFT', 'KEY_CAMERA_RIGHT', 'KEY_ATTENDANT_ON', 'KEY_ATTENDANT_OFF', 'KEY_ATTENDANT_TOGGLE', 'KEY_LIGHTS_TOGGLE', 'BTN_DPAD_UP', 'BTN_DPAD_DOWN', 'BTN_DPAD_LEFT', 'BTN_DPAD_RIGHT', 'KEY_ALS_TOGGLE', 'KEY_BUTTONCONFIG', 'KEY_TASKMANAGER', 'KEY_JOURNAL', 'KEY_CONTROLPANEL', 'KEY_APPSELECT', 'KEY_SCREENSAVER', 'KEY_VOICECOMMAND', 'KEY_BRIGHTNESS_MIN', 'KEY_BRIGHTNESS_MAX', 'KEY_KBDINPUTASSIST_PREV', 'KEY_KBDINPUTASSIST_NEXT', 'KEY_KBDINPUTASSIST_PREVGROUP', 'KEY_KBDINPUTASSIST_NEXTGROUP', 'KEY_KBDINPUTASSIST_ACCEPT', 'KEY_KBDINPUTASSIST_CANCEL', 'KEY_RIGHT_UP', 'KEY_RIGHT_DOWN', 'KEY_LEFT_UP', 'KEY_LEFT_DOWN', 'KEY_ROOT_MENU', 'KEY_MEDIA_TOP_MENU', 'KEY_NUMERIC_11', 'KEY_NUMERIC_12', 'KEY_AUDIO_DESC', 'KEY_3D_MODE', 'KEY_NEXT_FAVORITE', 'KEY_STOP_RECORD', 'KEY_PAUSE_RECORD', 'KEY_VOD', 'KEY_UNMUTE', 'KEY_DATA', 'KEY_FASTREVERSE', 'KEY_SLOWREVERSE', 'BTN_TRIGGER_HAPPY', 'BTN_TRIGGER_HAPPY1', 'BTN_TRIGGER_HAPPY2', 'BTN_TRIGGER_HAPPY3', 'BTN_TRIGGER_HAPPY4', 'BTN_TRIGGER_HAPPY5', 'BTN_TRIGGER_HAPPY6', 'BTN_TRIGGER_HAPPY7', 'BTN_TRIGGER_HAPPY8', 'BTN_TRIGGER_HAPPY9', 'BTN_TRIGGER_HAPPY10', 'BTN_TRIGGER_HAPPY11', 'BTN_TRIGGER_HAPPY12', 'BTN_TRIGGER_HAPPY13', 'BTN_TRIGGER_HAPPY14', 'BTN_TRIGGER_HAPPY15', 'BTN_TRIGGER_HAPPY16', 'BTN_TRIGGER_HAPPY17', 'BTN_TRIGGER_HAPPY18', 'BTN_TRIGGER_HAPPY19', 'BTN_TRIGGER_HAPPY20', 'BTN_TRIGGER_HAPPY21', 'BTN_TRIGGER_HAPPY22', 'BTN_TRIGGER_HAPPY23', 'BTN_TRIGGER_HAPPY24', 'BTN_TRIGGER_HAPPY25', 'BTN_TRIGGER_HAPPY26', 'BTN_TRIGGER_HAPPY27', 'BTN_TRIGGER_HAPPY28', 'BTN_TRIGGER_HAPPY29', 'BTN_TRIGGER_HAPPY30', 'BTN_TRIGGER_HAPPY31', 'BTN_TRIGGER_HAPPY32', 'BTN_TRIGGER_HAPPY33', 'BTN_TRIGGER_HAPPY34', 'BTN_TRIGGER_HAPPY35', 'BTN_TRIGGER_HAPPY36', 'BTN_TRIGGER_HAPPY37', 'BTN_TRIGGER_HAPPY38', 'BTN_TRIGGER_HAPPY39', 'BTN_TRIGGER_HAPPY40', 'KEY_FENRIR', 'KEY_SCRIPT', 'KEY_ALT', 'KEY_CTRL', 'KEY_META', 'KEY_SHIFT'] - diff --git a/src/fenrir/core/inputManager.py b/src/fenrir/core/inputManager.py index fbd300d..139ed4c 100644 --- a/src/fenrir/core/inputManager.py +++ b/src/fenrir/core/inputManager.py @@ -6,7 +6,6 @@ import time from core import debug -from core import inputEvent class inputManager(): def __init__(self): @@ -15,6 +14,7 @@ self.env = environment self.env['runtime']['settingsManager'].loadDriver(\ self.env['runtime']['settingsManager'].getSetting('keyboard', 'driver'), 'inputDriver') + self.updateInputDevices() # init LEDs with current state self.env['input']['newNumLock'] = self.env['runtime']['inputDriver'].getLedState() self.env['input']['oldNumLock'] = self.env['input']['newNumLock'] @@ -22,10 +22,10 @@ self.env['input']['oldCapsLock'] = self.env['input']['newCapsLock'] self.env['input']['newScrollLock'] = self.env['runtime']['inputDriver'].getLedState(2) self.env['input']['oldScrollLock'] = self.env['input']['newScrollLock'] - self.grabDevices() - + self.lastDeepestInput = [] + self.lastInputTime = time.time() def shutdown(self): - self.env['runtime']['inputManager'].releaseDevices() + self.removeAllDevices() self.env['runtime']['settingsManager'].shutdownDriver('inputDriver') def getInputEvent(self): @@ -40,27 +40,26 @@ self.env['input']['currInput'].remove(mEvent['EventName']) if len(self.env['input']['currInput']) > 1: self.env['input']['currInput'] = sorted(self.env['input']['currInput']) - if len(self.env['input']['currInput']) == 0: - self.env['input']['prevDeepestInput'] = [] + elif len(self.env['input']['currInput']) == 0: self.env['input']['shortcutRepeat'] = 1 self.setLedState = self.handleLedStates(mEvent) - self.env['input']['lastInputTime'] = time.time() + self.lastInputTime = time.time() elif mEvent['EventState'] == 1: if not mEvent['EventName'] in self.env['input']['currInput']: self.env['input']['currInput'].append(mEvent['EventName']) if len(self.env['input']['currInput']) > 1: self.env['input']['currInput'] = sorted(self.env['input']['currInput']) - if len(self.env['input']['prevDeepestInput']) < len(self.env['input']['currInput']): - self.env['input']['prevDeepestInput'] = self.env['input']['currInput'].copy() - elif self.env['input']['prevDeepestInput'] == self.env['input']['currInput']: - if time.time() - self.env['input']['lastInputTime'] <= self.env['runtime']['settingsManager'].getSettingAsFloat('keyboard','doubleTapTimeout'): + if len(self.lastDeepestInput) < len(self.env['input']['currInput']): + self.setLastDeepestInput( self.env['input']['currInput'].copy()) + elif self.lastDeepestInput == self.env['input']['currInput']: + if time.time() - self.lastInputTime <= self.env['runtime']['settingsManager'].getSettingAsFloat('keyboard','doubleTapTimeout'): self.env['input']['shortcutRepeat'] += 1 else: self.env['input']['shortcutRepeat'] = 1 self.setLedState = self.handleLedStates(mEvent) - self.env['input']['lastInputTime'] = time.time() + self.lastInputTime = time.time() elif mEvent['EventState'] == 2: - self.env['input']['lastInputTime'] = time.time() + self.lastInputTime = time.time() else: pass self.env['input']['oldNumLock'] = self.env['input']['newNumLock'] @@ -101,13 +100,19 @@ return False return self.setLedState - def grabDevices(self): + def grabAllDevices(self): if self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'grabDevices'): - self.env['runtime']['inputDriver'].grabDevices() - - def releaseDevices(self): + self.env['runtime']['inputDriver'].grabAllDevices() + + def updateInputDevices(self): try: - self.env['runtime']['inputDriver'].releaseDevices() + self.env['runtime']['inputDriver'].updateInputDevices() + except: + pass + + def removeAllDevices(self): + try: + self.env['runtime']['inputDriver'].removeAllDevices() except: pass @@ -139,42 +144,33 @@ eventName = 'KEY_SCRIPT' return eventName - def isConsumeInput(self): - return self.env['runtime']['commandManager'].isCommandQueued() and \ - not self.env['input']['keyForeward'] - #and - # not (self.env['input']['keyForeward'] or \ - # self.env['runtime']['settingsManager'].getSettingAsBool(, 'keyboard', 'grabDevices')) - def clearEventBuffer(self): self.env['runtime']['inputDriver'].clearEventBuffer() - + def setLastDeepestInput(self, currentDeepestInput): + self.lastDeepestInput = currentDeepestInput + def clearLastDeepInput(self): + self.lastDeepestInput = [] + def getLastInputTime(self): + return self.lastInputTime + def getLastDeepestInput(self): + return self.lastDeepestInput def writeEventBuffer(self): try: if self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'grabDevices'): self.env['runtime']['inputDriver'].writeEventBuffer() - time.sleep(0.008) self.clearEventBuffer() - if len(self.env['input']['currInput']) == 1: - if self.env['input']['currInput'][0] in ['KEY_UP','KEY_DOWN']: - time.sleep(0.08) # hack for tintin history because it needs more time except Exception as e: self.env['runtime']['debug'].writeDebugOut("Error while writeUInput",debug.debugLevel.ERROR) self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) - def isFenrirKeyPressed(self): - return 'KEY_FENRIR' in self.env['input']['prevDeepestInput'] - - def isScriptKeyPressed(self): - return 'KEY_SCRIPT' in self.env['input']['prevDeepestInput'] - def noKeyPressed(self): return self.env['input']['currInput'] == [] - - def getPrevDeepestInput(self): + def isKeyPress(self): + return (self.env['input']['prevInput'] == []) and (self.env['input']['currInput'] != []) + def getPrevDeepestShortcut(self): shortcut = [] shortcut.append(self.env['input']['shortcutRepeat']) - shortcut.append(self.env['input']['prevDeepestInput']) + shortcut.append(self.getLastDeepestInput()) return str(shortcut) def getPrevShortcut(self): @@ -183,10 +179,13 @@ shortcut.append(self.env['input']['prevInput']) return str(shortcut) - def getCurrShortcut(self): + def getCurrShortcut(self, inputSequence = None): shortcut = [] shortcut.append(self.env['input']['shortcutRepeat']) - shortcut.append(self.env['input']['currInput']) + if inputSequence: + shortcut.append(inputSequence) + else: + shortcut.append(self.env['input']['currInput']) if len(self.env['input']['prevInput']) < len(self.env['input']['currInput']): if self.env['input']['shortcutRepeat'] > 1 and not self.shortcutExists(str(shortcut)): shortcut = [] @@ -196,10 +195,17 @@ self.env['runtime']['debug'].writeDebugOut("currShortcut " + str(shortcut) ,debug.debugLevel.INFO) return str(shortcut) + def currKeyIsModifier(self): + if len(self.getLastDeepestInput()) != 1: + return False + return (self.env['input']['currInput'][0] =='KEY_FENRIR') or (self.env['input']['currInput'][0] == 'KEY_SCRIPT') + def isFenrirKey(self, eventName): return eventName in self.env['input']['fenrirKey'] + def isScriptKey(self, eventName): return eventName in self.env['input']['scriptKey'] + def getCommandForShortcut(self, shortcut): if not self.shortcutExists(shortcut): return '' diff --git a/src/fenrir/core/outputData.py b/src/fenrir/core/outputData.py new file mode 100644 index 0000000..684acd6 --- /dev/null +++ b/src/fenrir/core/outputData.py @@ -0,0 +1,15 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +import time +from core import debug + +outputData = { +'nextFlush': time.time(), +'messageText': '', +'messageOffset': None, +'cursorOffset': None, +} diff --git a/src/fenrir/core/outputManager.py b/src/fenrir/core/outputManager.py index fc108b9..dba0781 100644 --- a/src/fenrir/core/outputManager.py +++ b/src/fenrir/core/outputManager.py @@ -5,7 +5,8 @@ # By Chrys, Storm Dragon, and contributers. from core import debug -import string +from utils import line_utils +import string, time class outputManager(): def __init__(self): @@ -23,7 +24,7 @@ self.env['runtime']['settingsManager'].shutdownDriver('speechDriver') self.env['runtime']['settingsManager'].shutdownDriver('brailleDriver') - def presentText(self, text, interrupt=True, soundIcon = '', ignorePunctuation=False, announceCapital=False): + def presentText(self, text, interrupt=True, soundIcon = '', ignorePunctuation=False, announceCapital=False, flush=True): if text == '': return self.env['runtime']['debug'].writeDebugOut("presentText:\nsoundIcon:'"+soundIcon+"'\nText:\n" + text ,debug.debugLevel.INFO) @@ -38,7 +39,8 @@ toAnnounceCapital = False self.speakText(text, interrupt, ignorePunctuation,toAnnounceCapital) - self.brailleText(text, interrupt) + if flush: + self.brailleText(text, flush) def speakText(self, text, interrupt=True, ignorePunctuation=False, announceCapital=False): if not self.env['runtime']['settingsManager'].getSettingAsBool('speech', 'enabled'): @@ -98,18 +100,149 @@ self.env['runtime']['debug'].writeDebugOut("\"speak\" in outputManager.speakText ",debug.debugLevel.ERROR) self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) - def brailleText(self, text, interrupt=True): + def brailleText(self, text='', flush=True): if not self.env['runtime']['settingsManager'].getSettingAsBool('braille', 'enabled'): return if self.env['runtime']['brailleDriver'] == None: return - self.env['runtime']['brailleDriver'].writeText(text[:35]) - + if flush: + self.env['output']['nextFlush'] = time.time() + self.getFlushTime(text) + self.env['output']['messageOffset'] = {'x':0,'y':0} + self.env['output']['messageText'] = text + displayText = self.getBrailleTextWithOffset(self.env['output']['messageText'], self.env['output']['messageOffset']) + self.env['runtime']['brailleDriver'].writeText('flush'+displayText) + else: + if self.env['output']['nextFlush'] < time.time(): + if self.env['output']['messageText'] != '': + self.env['output']['messageText'] = '' + if self.env['output']['messageOffset'] != None: + self.env['output']['messageOffset'] = None + cursor = self.getBrailleCursor() + x, y, self.env['output']['brlText'] = \ + line_utils.getCurrentLine(cursor['x'], cursor['y'], self.env['screen']['newContentText']) + displayText = self.getBrailleTextWithOffset(self.env['screen']['newContentText'], self.env['output']['cursorOffset'], cursor) + self.env['runtime']['brailleDriver'].writeText('notflush'+displayText) + else: + displayText = self.getBrailleTextWithOffset(self.env['output']['messageText'], self.env['output']['messageOffset']) + self.env['runtime']['brailleDriver'].writeText('flush'+displayText) + + def getBrailleCursor(self): + if self.env['runtime']['settingsManager'].getSetting('braille', 'cursorFollowMode').upper() == 'REVIEW': + return self.env['runtime']['cursorManager'].getReviewOrTextCursor() + if self.env['runtime']['settingsManager'].getSetting('braille', 'cursorFollowMode').upper() == 'MANUAL': + return self.env['runtime']['cursorManager'].getReviewOrTextCursor() + if self.env['runtime']['settingsManager'].getSetting('braille', 'cursorFollowMode').upper() == 'LAST': + return self.env['runtime']['cursorManager'].getReviewOrTextCursor() + return self.env['runtime']['cursorManager'].getReviewOrTextCursor() + + def getFixCursorCell(self): + size = self.env['runtime']['brailleDriver'].getDeviceSize()[0] + fixCell = self.env['runtime']['settingsManager'].getSettingAsInt('braille', 'fixCursorOnCell') + if fixCell <= -1: + return size[0] + if fixCell >= size[0]: + return size[0] + return fixCell + def getActiveOffsetAndText(self): + if self.env['output']['messageOffset']: + return self.env['output']['messageOffset'], self.env['output']['messageText'] + if not self.env['output']['cursorOffset']: + return self.getBrailleCursor(), self.env['screen']['newContentText'] + return self.env['output']['cursorOffset'], self.env['screen']['newContentText'] + def getHorizontalPanSize(self): + size = self.env['runtime']['brailleDriver'].getDeviceSize() + if self.env['runtime']['settingsManager'].getSettingAsInt('braille', 'panSizeHorizontal') <= 0: + return size[0] + if self.env['runtime']['settingsManager'].getSettingAsInt('braille', 'panSizeHorizontal') >= size[0]: + return size[0] + return self.env['runtime']['settingsManager'].getSettingAsInt('braille', 'panSizeHorizontal') + def getHorizontalPanLevel(self,offsetChange = 0): + panned = True + panSize = self.getHorizontalPanSize() + offset, text = self.getActiveOffsetAndText() + currline = text.split('\n')[offset['y']] + newOffsetStart = (int(offset['x'] / panSize) + offsetChange) * panSize + if newOffsetStart < 0: + newOffsetStart = 0 + panned = False + if newOffsetStart >= len(text): + newOffsetStart = int((len(text) - panSize - 1) / panSize) + panned = False + return newOffsetStart, panned + def setPanLeft(self): + newPan, panned = self.getHorizontalPanLevel(-1) + if self.env['output']['messageOffset']: + self.env['output']['messageOffset'] = newPan.copy() + else: + self.env['output']['cursorOffset'] = newPan.copy() + return panned + def setPanRight(self): + newPan, panned = self.getHorizontalPanLevel(1) + if self.env['output']['messageOffset']: + self.env['output']['messageOffset'] = newPan.copy() + else: + self.env['output']['cursorOffset'] = newPan.copy() + return panned + def removePanning(self): + if self.env['output']['messageOffset']: + self.env['output']['messageOffset'] = None + else: + self.env['output']['cursorOffset'] = None + def getBrailleTextWithOffset(self, text, offset = None, cursor = None): + if text == '': + return '' + size = self.env['runtime']['brailleDriver'].getDeviceSize() + offsetText = text + + if cursor and not offset: + if self.env['runtime']['settingsManager'].getSetting('braille', 'cursorFollowMode').upper() == 'FIXCELL': + #fix cell + cursorCell = self.getFixCursorCell() + offsetStart = cursor['x'] + if offsetStart < size[0]: + if offsetStart <= cursorCell: + return offsetText[0: size[0]] + + offsetStart -= cursorCell + if offsetStart >= len(offsetText): + offsetStart = len(offsetText) - 1 + else: + # page and fallback + offsetStart = int(cursor['x'] / size[0]) * size[0] + else: + if not offset: + offset = {'x':0,'y':0} + offsetStart = offset['x'] + if offsetStart >= len(offsetText): + offsetStart = len(offsetText) - size[0] + + if offsetStart < 0: + offsetStart = 0 + offsetEnd = offsetStart + size[0] + offsetText = offsetText[offsetStart: offsetEnd] + return offsetText def interruptOutput(self): self.env['runtime']['speechDriver'].cancel() self.env['runtime']['debug'].writeDebugOut("Interrupt speech",debug.debugLevel.INFO) - - + + def clearFlushTime(self): + self.setFlushTime(0.0) + + def setFlushTime(self,newTime): + self.env['output']['nextFlush'] = newTime + + def getFlushTime(self,text=''): + if self.env['runtime']['settingsManager'].getSettingAsFloat('braille', 'flushTimeout') < 0 or \ + self.env['runtime']['settingsManager'].getSetting('braille', 'flushMode').upper() == 'NONE': + return 999999999999 + if self.env['runtime']['settingsManager'].getSetting('braille', 'flushMode').upper() == 'FIX': + return self.env['runtime']['settingsManager'].getSettingAsFloat('braille', 'flushTimeout') + if self.env['runtime']['settingsManager'].getSetting('braille', 'flushMode').upper() == 'CHAR': + return self.env['runtime']['settingsManager'].getSettingAsFloat('braille', 'flushTimeout') * len(text) + if self.env['runtime']['settingsManager'].getSetting('braille', 'flushMode').upper() == 'WORD': + wordsList = text.split(' ') + return self.env['runtime']['settingsManager'].getSettingAsFloat('braille', 'flushTimeout') * len( list( filter(None, wordsList) ) ) + def playSoundIcon(self, soundIcon = '', interrupt=True): if soundIcon == '': return False diff --git a/src/fenrir/core/processManager.py b/src/fenrir/core/processManager.py new file mode 100644 index 0000000..0f29837 --- /dev/null +++ b/src/fenrir/core/processManager.py @@ -0,0 +1,87 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +from core.eventData import fenrirEventType +import time +from threading import Thread +from multiprocessing import Process + +class processManager(): + def __init__(self): + self._Processes = [] + self._Threads = [] + def initialize(self, environment): + self.env = environment + self.running = self.env['runtime']['eventManager'].getRunning() + self.addSimpleEventThread(fenrirEventType.HeartBeat, self.heartBeatTimer, multiprocess=True) + def shutdown(self): + self.terminateAllProcesses() + + def terminateAllProcesses(self): + for proc in self._Processes: + try: + proc.terminate() + except Exception as e: + print(e) + def heartBeatTimer(self, active): + try: + time.sleep(0.5) + except: + pass + return time.time() + def addCustomEventThread(self, function, pargs = None, multiprocess = False, runOnce = False): + eventQueue = self.env['runtime']['eventManager'].getEventQueue() + if multiprocess: + t = Process(target=self.customEventWorkerThread, args=(eventQueue, function, pargs, runOnce)) + self._Processes.append(t) + else:# thread not implemented yet + t = Thread(target=self.customEventWorkerThread, args=(eventQueue, function, pargs, runOnce)) + self._Threads.append(t) + t.start() + + def addSimpleEventThread(self, event, function, pargs = None, multiprocess = False, runOnce = False): + if multiprocess: + t = Process(target=self.simpleEventWorkerThread, args=(event, function, pargs, runOnce)) + self._Processes.append(t) + else: + t = Thread(target=self.simpleEventWorkerThread, args=(event, function, pargs, runOnce)) + self._Threads.append(t) + t.start() + + def customEventWorkerThread(self, eventQueue, function, pargs = None, runOnce = False): + #if not isinstance(eventQueue, Queue): + # return + if not callable(function): + return + while self.running.value: + try: + if pargs: + function(self.running, eventQueue, pargs) + else: + function(self.running, eventQueue) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('processManager:customEventWorkerThread:function():' + str(e),debug.debugLevel.ERROR) + if runOnce: + break + + def simpleEventWorkerThread(self, event, function, pargs = None, runOnce = False): + if not isinstance(event, fenrirEventType): + return + if not callable(function): + return + while self.running.value: + Data = None + try: + if pargs: + Data = function(self.running, pargs) + else: + Data = function(self.running) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('processManager:simpleEventWorkerThread:function():' + str(e),debug.debugLevel.ERROR) + self.env['runtime']['eventManager'].putToEventQueue(event, Data) + if runOnce: + break diff --git a/src/fenrir/core/punctuation.py b/src/fenrir/core/punctuation.py deleted file mode 100644 index e896b8e..0000000 --- a/src/fenrir/core/punctuation.py +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from core import debug -import string - -punctuation = { -'LEVELDICT':{ - 'none': '', - 'some': '#-$~+*-/\\@', - 'most': '.,:-$~ +*-/\\@!#%^&*()[]}{<>;', - 'all': string.punctuation + ' §', - }, -'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':{ - }, -'EMOTICONDICT':{ - ':)':'smiley', - ';)':'winking face', - 'XD':'loool', - ':@':'angry face', - ':D':'lought' - }, -} diff --git a/src/fenrir/core/punctuationData.py b/src/fenrir/core/punctuationData.py new file mode 100644 index 0000000..1ba130b --- /dev/null +++ b/src/fenrir/core/punctuationData.py @@ -0,0 +1,61 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +import string + +punctuationData = { +'LEVELDICT':{ + 'none': '', + 'some': '#-$~+*-/\\@', + 'most': '.,:-$~ +*-/\\@!#%^&*()[]}{<>;', + 'all': string.punctuation + ' §', + }, +'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':{ + }, +'EMOTICONDICT':{ + ':)':'smiley', + ';)':'winking face', + 'XD':'loool', + ':@':'angry face', + ':D':'lought' + }, +} diff --git a/src/fenrir/core/punctuationManager.py b/src/fenrir/core/punctuationManager.py index bacbe0b..f10dca3 100644 --- a/src/fenrir/core/punctuationManager.py +++ b/src/fenrir/core/punctuationManager.py @@ -32,11 +32,11 @@ pass return text.translate(currAllPunctNone) - def useCustomDict(self, text, customDict): + def useCustomDict(self, text, customDict, seperator=''): resultText = str(text) if customDict: for key,item in customDict.items(): - resultText = resultText.replace(str(key),str(item)) + resultText = resultText.replace(str(key),seperator + str(item) + seperator) return resultText def usePunctuationDict(self, text, punctuationDict, punctuation): @@ -59,7 +59,7 @@ resultText = text resultText = self.useCustomDict(resultText, self.env['punctuation']['CUSTOMDICT']) if self.env['runtime']['settingsManager'].getSettingAsBool('general', 'emoticons'): - resultText = self.useCustomDict(resultText, self.env['punctuation']['EMOTICONDICT']) + resultText = self.useCustomDict(resultText, self.env['punctuation']['EMOTICONDICT'], ' ') currPunctLevel = '' if not ignorePunctuation and self.env['runtime']['settingsManager'].getSetting('general', 'punctuationLevel').lower() in self.env['punctuation']['LEVELDICT']: currPunctLevel = self.env['punctuation']['LEVELDICT'][self.env['runtime']['settingsManager'].getSetting('general', 'punctuationLevel').lower()] diff --git a/src/fenrir/core/runtime.py b/src/fenrir/core/runtime.py deleted file mode 100644 index ad192bf..0000000 --- a/src/fenrir/core/runtime.py +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from core import debug - -runtime = { -'speechDriver': None, -'screenDriver': None, -'soundDriver': None, -'inputDriver': None, -'brailleDriver': None, -'inputManager': None, -'commandManager': None, -'screenManager': None, -'outputManager': None, -'debug':None, -} diff --git a/src/fenrir/core/runtimeData.py b/src/fenrir/core/runtimeData.py new file mode 100644 index 0000000..1041d4e --- /dev/null +++ b/src/fenrir/core/runtimeData.py @@ -0,0 +1,20 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +runtimeData = { +'speechDriver': None, +'screenDriver': None, +'soundDriver': None, +'inputDriver': None, +'brailleDriver': None, +'inputManager': None, +'commandManager': None, +'screenManager': None, +'outputManager': None, +'debug':None, +} diff --git a/src/fenrir/core/screenData.py b/src/fenrir/core/screenData.py index d352150..9f4d0a6 100644 --- a/src/fenrir/core/screenData.py +++ b/src/fenrir/core/screenData.py @@ -18,7 +18,7 @@ 'oldCursor':{'x':0,'y':0}, 'oldContentBytes': b'', 'oldContentText': '', -'oldContentAttrib': b'', +'oldContentAttrib': None, 'oldApplication': '', 'oldTTY':None, 'newDelta': '', @@ -29,8 +29,27 @@ 'newCursor':{'x':0,'y':0}, 'newContentBytes': b'', 'newContentText': '', -'newContentAttrib': b'', +'newContentAttrib': None, 'newTTY':'0', 'newApplication': '', -'lastScreenUpdate': time.time() +'lastScreenUpdate': time.time(), +'autoIgnoreScreens':[], } +''' +screenData = { +'columns': 0, +'lines': 0, +'textDelta': '', +'negativeDelta': '', +'attribDelta': '', +'reviewCursor':None, #{'x':0,'y':0} +'attribCursor':None, #{'x':0,'y':0} +'textCursor':None, #{'x':0,'y':0} +'content': None, #{'x':0,'y':0} +'Text': '', +'Attrib': None, +'screen': None, +'application': '', +'timestamp': time.time(), +} +''' diff --git a/src/fenrir/core/screenManager.py b/src/fenrir/core/screenManager.py index 9ff7e73..80b45c8 100644 --- a/src/fenrir/core/screenManager.py +++ b/src/fenrir/core/screenManager.py @@ -9,49 +9,67 @@ class screenManager(): def __init__(self): - self.autoIgnoreScreens = [] - + pass def initialize(self, environment): self.env = environment self.env['runtime']['settingsManager'].loadDriver(\ self.env['runtime']['settingsManager'].getSetting('screen', 'driver'), 'screenDriver') + self.env['runtime']['screenDriver'].getCurrScreen() self.env['runtime']['screenDriver'].getSessionInformation() def shutdown(self): self.env['runtime']['settingsManager'].shutdownDriver('screenDriver') def update(self, trigger='onUpdate'): - self.env['runtime']['screenDriver'].getCurrScreen() - self.env['runtime']['screenDriver'].getSessionInformation() - self.env['screenData']['oldApplication'] = self.env['screenData']['newApplication'] - if self.isScreenChange(): + self.env['runtime']['screenDriver'].getCurrScreen() + + if trigger == 'onScreenChange': + self.env['runtime']['screenDriver'].getSessionInformation() + + self.env['screen']['oldApplication'] = self.env['screen']['newApplication'] + if self.isScreenChange(): self.changeBrailleScreen() - if not self.isSuspendingScreen(self.env['screenData']['newTTY']): + if not self.isSuspendingScreen(self.env['screen']['newTTY']): self.env['runtime']['screenDriver'].update(trigger) - if trigger == 'onUpdate' or self.isScreenChange() \ - or len(self.env['screenData']['newDelta']) > 6: - self.env['runtime']['screenDriver'].getCurrApplication() - self.env['screenData']['lastScreenUpdate'] = time.time() - + #if trigger == 'onUpdate' or self.isScreenChange() \ + # or len(self.env['screen']['newDelta']) > 6: + # self.env['runtime']['screenDriver'].getCurrApplication() + self.env['screen']['lastScreenUpdate'] = time.time() + def formatAttributes(self, attribute, attributeFormatString = None): + if not attributeFormatString: + attributeFormatString = self.env['runtime']['settingsManager'].getSetting('general', 'attributeFormatString') + if not attributeFormatString: + return '' + if attributeFormatString == '': + return '' + attributeFormatString = attributeFormatString.replace('fenrirBGColor', self.env['runtime']['screenDriver'].getFenrirBGColor(attribute)) + attributeFormatString = attributeFormatString.replace('fenrirFGColor', self.env['runtime']['screenDriver'].getFenrirFGColor(attribute)) + attributeFormatString = attributeFormatString.replace('fenrirUnderline', self.env['runtime']['screenDriver'].getFenrirUnderline(attribute)) + attributeFormatString = attributeFormatString.replace('fenrirBold', self.env['runtime']['screenDriver'].getFenrirBold(attribute)) + attributeFormatString = attributeFormatString.replace('fenrirBlink', self.env['runtime']['screenDriver'].getFenrirBlink(attribute)) + attributeFormatString = attributeFormatString.replace('fenrirFontSize', self.env['runtime']['screenDriver'].getFenrirFontSize(attribute)) + attributeFormatString = attributeFormatString.replace('fenrirFont', self.env['runtime']['screenDriver'].getFenrirFont(attribute)) + return attributeFormatString def isSuspendingScreen(self, screen = None): if screen == None: - screen = self.env['screenData']['newTTY'] + screen = self.env['screen']['newTTY'] ignoreScreens = [] fixIgnoreScreens = self.env['runtime']['settingsManager'].getSetting('screen', 'suspendingScreen') if fixIgnoreScreens != '': - ignoreScreens.append(fixIgnoreScreens.split(',')) + ignoreScreens.extend(fixIgnoreScreens.split(',')) if self.env['runtime']['settingsManager'].getSettingAsBool('screen', 'autodetectSuspendingScreen'): - ignoreScreens.extend(self.env['screenData']['autoIgnoreScreens']) + ignoreScreens.extend(self.env['screen']['autoIgnoreScreens']) + self.env['runtime']['debug'].writeDebugOut('screenManager:isSuspendingScreen ' + str(ignoreScreens) + ' '+ str(self.env['screen']['newTTY']),debug.debugLevel.INFO) return (screen in ignoreScreens) - + def isScreenChange(self): - if not self.env['screenData']['oldTTY']: + if not self.env['screen']['oldTTY']: return False - return self.env['screenData']['newTTY'] != self.env['screenData']['oldTTY'] + return self.env['screen']['newTTY'] != self.env['screen']['oldTTY'] def isDelta(self): - return self.env['screenData']['newDelta'] != '' + return self.env['screen']['newDelta'] != '' def isNegativeDelta(self): - return self.env['screenData']['newNegativeDelta'] != '' + return self.env['screen']['newNegativeDelta'] != '' def getWindowAreaInText(self, text): if not self.env['runtime']['cursorManager'].isApplicationWindowSet(): return text @@ -70,16 +88,18 @@ self.env['runtime']['debug'].writeDebugOut('screenManager:injectTextToScreen ' + str(e),debug.debugLevel.ERROR) def changeBrailleScreen(self): + if not self.env['runtime']['settingsManager'].getSettingAsBool('braille', 'enabled'): + return if not self.env['runtime']['brailleDriver']: return - if self.env['screenData']['oldTTY']: - if not self.isSuspendingScreen(self.env['screenData']['oldTTY']): + if self.env['screen']['oldTTY']: + if not self.isSuspendingScreen(self.env['screen']['oldTTY']): try: self.env['runtime']['brailleDriver'].leveScreen() except Exception as e: self.env['runtime']['debug'].writeDebugOut('screenManager:changeBrailleScreen:leveScreen ' + str(e),debug.debugLevel.ERROR) if not self.isSuspendingScreen(): try: - self.env['runtime']['brailleDriver'].enterScreen(self.env['screenData']['newTTY']) + self.env['runtime']['brailleDriver'].enterScreen(self.env['screen']['newTTY']) except Exception as e: self.env['runtime']['debug'].writeDebugOut('screenManager:changeBrailleScreen:enterScreen ' + str(e),debug.debugLevel.ERROR) diff --git a/src/fenrir/core/settings.py b/src/fenrir/core/settings.py deleted file mode 100644 index 46c26d4..0000000 --- a/src/fenrir/core/settings.py +++ /dev/null @@ -1,93 +0,0 @@ -#!/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from core import debug - -settings = { -'sound': { - 'enabled': True, - 'driver': 'generic', - 'theme': 'default', - 'volume': 1.0, - 'genericPlayFileCommand': 'play -q -v fenrirVolume fenrirSoundFile', - 'genericFrequencyCommand': 'play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence' -}, -'speech':{ - 'enabled': True, - 'driver': 'speechd', - 'rate': 0.75, - 'pitch': 0.5, - 'capitalPitch':0.8, - 'volume': 1.0, - 'module': 'espeak', - 'voice': '', - 'language': 'english-us', - 'autoReadIncoming': True, -}, -'braille':{ - 'enabled': False, - 'driver':'brlapi', - 'layout': 'en', -}, -'screen':{ - 'driver': 'vcsa', - 'encoding': 'cp850', - 'screenUpdateDelay': 0.1, - 'suspendingScreen': '', - 'autodetectSuspendingScreen': False, -}, -'general':{ - 'debugLevel': debug.debugLevel.DEACTIVE, - 'punctuationProfile':'default', - 'punctuationLevel': 'some', - 'respectPunctuationPause':True, - 'newLinePause':True, - 'numberOfClipboards': 10, - 'emoticons': True, - 'fenrirKeys': 'KEY_KP0,KEY_META', - 'scriptKeys': 'KEY_COMPOSE', - 'timeFormat': '%I:%M%P', - 'dateFormat': '%A, %B %d, %Y', - 'autoSpellCheck': False, - 'spellCheckLanguage': 'en_US', - 'scriptPath':'/usr/share/fenrir/scripts', -}, -'focus':{ - 'cursor': True, - 'highlight': False, -}, -'review':{ - 'lineBreak': True, - 'endOfScreen': True, -}, -'promote':{ - 'enabled': True, - 'inactiveTimeoutSec': 120, - 'list': '', -}, -'time':{ - 'enabled': False, - 'presentTime': True, - 'presentDate': True, - 'delaySec': 0, - 'onMinutes': '00,30', - 'announce': True, - 'interrupt': False, -}, -'keyboard':{ - 'driver': 'evdev', - 'device': 'all', - 'grabDevices': True, - 'ignoreShortcuts': False, - 'keyboardLayout': "desktop", - 'charEcho': False, - 'charDeleteEcho': True, - 'wordEcho': True, - 'interruptOnKeyPress': True, - 'interruptOnKeyPressFilter': '', - 'doubleTapTimeout': 0.2, -} -} diff --git a/src/fenrir/core/settingsData.py b/src/fenrir/core/settingsData.py new file mode 100644 index 0000000..fcd107d --- /dev/null +++ b/src/fenrir/core/settingsData.py @@ -0,0 +1,112 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +settingsData = { +'sound': { + 'enabled': True, + 'driver': 'genericDriver', + 'theme': 'default', + 'volume': 1.0, + 'genericPlayFileCommand': 'play -q -v fenrirVolume fenrirSoundFile', + 'genericFrequencyCommand': 'play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence' +}, +'speech':{ + 'enabled': True, + 'driver': 'speechdDriver', + 'serverPath': '', + 'rate': 0.75, + 'pitch': 0.5, + 'capitalPitch':0.8, + 'volume': 1.0, + 'module': 'espeak', + 'voice': '', + 'language': 'english-us', + 'autoReadIncoming': True, + 'genericSpeechCommand':'espeak -a fenrirVolume -s fenrirRate -p fenrirPitch -v fenrirVoice "fenrirText"', + 'fenrirMinVolume':0, + 'fenrirMaxVolume':200, + 'fenrirMinPitch':0, + 'fenrirMaxPitch':99, + 'fenrirMinRate':80, + 'fenrirMaxRate':450, +}, +'braille':{ + 'enabled': False, + 'driver':'brlapiDriver', + 'layout': 'en', + 'flushMode': 'word', #NONE,FIX,CHAR,WORD + 'flushTimeout': 3, + 'cursorFocusMode':'page', # page,fixCell + 'fixCursorOnCell': -1, + 'cursorFollowMode': 'review', # none, review, last, text + 'panSizeHorizontal': 0 # 0 = display size +}, +'screen':{ + 'driver': 'vcsaDriver', + 'encoding': 'cp850', + 'screenUpdateDelay': 0.1, + 'suspendingScreen': '', + 'autodetectSuspendingScreen': False, +}, +'general':{ + 'debugLevel': debug.debugLevel.DEACTIVE, + 'debugMode': 'FILE', + 'punctuationProfile':'default', + 'punctuationLevel': 'some', + 'respectPunctuationPause':True, + 'newLinePause':True, + 'numberOfClipboards': 10, + 'emoticons': True, + 'fenrirKeys': 'KEY_KP0,KEY_META', + 'scriptKeys': 'KEY_COMPOSE', + 'timeFormat': '%I:%M%P', + 'dateFormat': '%A, %B %d, %Y', + 'autoSpellCheck': False, + 'spellCheckLanguage': 'en_US', + 'scriptPath': '/usr/share/fenrir/scripts', + 'commandPath': '/usr/share/fenrir/commands', + 'attributeFormatString': 'Background fenrirBGColor,Foreground fenrirFGColor,fenrirUnderline,fenrirBold,fenrirBlink, Font fenrirFont,Fontsize fenrirFontSize' +}, +'focus':{ + 'cursor': True, + 'highlight': False, +}, +'review':{ + 'lineBreak': True, + 'endOfScreen': True, + 'leaveReviewOnCursorChange': True, + 'leaveReviewOnScreenChange': True, +}, +'promote':{ + 'enabled': True, + 'inactiveTimeoutSec': 120, + 'list': '', +}, +'time':{ + 'enabled': False, + 'presentTime': True, + 'presentDate': True, + 'delaySec': 0, + 'onMinutes': '00,30', + 'announce': True, + 'interrupt': False, +}, +'keyboard':{ + 'driver': 'evdev', + 'device': 'all', + 'grabDevices': True, + 'ignoreShortcuts': False, + 'keyboardLayout': "desktop", + 'charEcho': False, + 'charDeleteEcho': True, + 'wordEcho': True, + 'interruptOnKeyPress': True, + 'interruptOnKeyPressFilter': '', + 'doubleTapTimeout': 0.2, +} +} diff --git a/src/fenrir/core/settingsManager.py b/src/fenrir/core/settingsManager.py index 27c2e61..39f8609 100644 --- a/src/fenrir/core/settingsManager.py +++ b/src/fenrir/core/settingsManager.py @@ -4,10 +4,14 @@ # Fenrir TTY screen reader # By Chrys, Storm Dragon, and contributers. -import importlib.util -import os -import __main__ +import os, inspect +currentdir = os.path.dirname(os.path.realpath(os.path.abspath(inspect.getfile(inspect.currentframe())))) +fenrirPath = os.path.dirname(currentdir) + from configparser import ConfigParser +from core import debugManager +from core import processManager +from core import eventManager from core import inputManager from core import outputManager from core import commandManager @@ -15,19 +19,22 @@ from core import punctuationManager from core import cursorManager from core import applicationManager +from core import helpManager from core import environment -from core import inputEvent -from core.settings import settings +from core import inputData +from core.settingsData import settingsData from core import debug +from utils import module_utils class settingsManager(): def __init__(self): - self.settings = settings + self.settings = settingsData + self.settingArgDict = {} def initialize(self, environment): self.env = environment def shutdown(self): pass - def loadShortcuts(self, kbConfigPath=os.path.dirname(os.path.realpath(__main__.__file__)) + '/../../config/keyboard/desktop.conf'): + def loadShortcuts(self, kbConfigPath=fenrirPath + '/../../config/keyboard/desktop.conf'): kbConfig = open(kbConfigPath,"r") while(True): invalid = False @@ -67,8 +74,10 @@ self.env['runtime']['debug'].writeDebugOut("invalid shortcut (missing KEY_FENRIR): "+ str(shortcut) + ' command:' +commandName ,debug.debugLevel.ERROR) continue self.env['runtime']['debug'].writeDebugOut("Shortcut: "+ str(shortcut) + ' command:' +commandName ,debug.debugLevel.INFO, onAnyLevel=True) - self.env['bindings'][str(shortcut)] = commandName + self.env['bindings'][str(shortcut)] = commandName kbConfig.close() + # fix bindings + self.env['bindings'][str([1, ['KEY_F1', 'KEY_FENRIR']])] = 'TOGGLE_TUTORIAL_MODE' def loadSoundIcons(self, soundIconPath): siConfig = open(soundIconPath + '/soundicons.conf',"r") @@ -99,9 +108,9 @@ self.env['runtime']['debug'].writeDebugOut("SoundIcon: " + soundIcon + '.' + soundIconFile, debug.debugLevel.INFO, onAnyLevel=True) siConfig.close() def isValidKey(self, key): - return key in inputEvent.keyNames + return key in inputData.keyNames - def loadDicts(self, dictConfigPath=os.path.dirname(os.path.realpath(__main__.__file__)) + '/../../config/punctuation/default.conf'): + def loadDicts(self, dictConfigPath=fenrirPath + '/../../config/punctuation/default.conf'): dictConfig = open(dictConfigPath,"r") currDictName = '' while(True): @@ -145,6 +154,11 @@ def getSetting(self, section, setting): value = '' try: + value = self.settingArgDict[section.lower()][setting.lower()] + return value + except: + pass + try: value = self.env['settings'].get(section, setting) except: value = str(self.settings[section][setting]) @@ -153,6 +167,11 @@ def getSettingAsInt(self, section, setting): value = 0 try: + value = int(self.settingArgDict[section.lower()][setting.lower()]) + return value + except Exception as e: + pass + try: value = self.env['settings'].getint(section, setting) except: value = self.settings[section][setting] @@ -161,6 +180,11 @@ def getSettingAsFloat(self, section, setting): value = 0.0 try: + value = float(self.settingArgDict[section.lower()][setting.lower()]) + return value + except Exception as e: + pass + try: value = self.env['settings'].getfloat(section, setting) except: value = self.settings[section][setting] @@ -169,6 +193,11 @@ def getSettingAsBool(self, section, setting): value = False try: + value = self.settingArgDict[section.lower()][setting.lower()].upper() in ['1','YES','JA','TRUE'] + return value + except Exception as e: + pass + try: value = self.env['settings'].getboolean(section, setting) except: value = self.settings[section][setting] @@ -178,15 +207,14 @@ try: if self.env['runtime'][driverType] != None: self.env['runtime'][driverType].shutdown(self.env) - spec = importlib.util.spec_from_file_location(driverName, os.path.dirname(os.path.realpath(__main__.__file__)) + "/" + driverType + '/' + driverName + '.py') - driver_mod = importlib.util.module_from_spec(spec) - spec.loader.exec_module(driver_mod) + driver_mod = module_utils.importModule(driverName, + fenrirPath + "/" + driverType + '/' + driverName + '.py') self.env['runtime'][driverType] = driver_mod.driver() self.env['runtime'][driverType].initialize(self.env) - self.env['runtime']['debug'].writeDebugOut('Loading Driver ' + driverType +" OK",debug.debugLevel.INFO, onAnyLevel=True) + self.env['runtime']['debug'].writeDebugOut('Loading Driver ' + driverType + ' (' + driverName +") OK",debug.debugLevel.INFO, onAnyLevel=True) except Exception as e: self.env['runtime'][driverType] = None - self.env['runtime']['debug'].writeDebugOut("Loading " + driverType + " Driver : "+ str(e), debug.debugLevel.ERROR) + self.env['runtime']['debug'].writeDebugOut('Loading Driver ' + driverType + ' (' + driverName +") FAILED:"+ str(e), debug.debugLevel.ERROR) def shutdownDriver(self, driverType): if self.env['runtime'][driverType] == None: return @@ -205,29 +233,66 @@ for key in keyList: if not key in self.env['input']['scriptKey']: self.env['input']['scriptKey'].append(key) - - def initFenrirConfig(self, environment = environment.environment, settingsRoot = '/etc/fenrir/', settingsFile='settings.conf', soundRoot = '/usr/share/sounds/fenrir/'): - environment['runtime']['debug'] = debug.debug() + def setOptionArgDict(self, section, option, value): + section = section.lower() + option = option.lower() + try: + e = self.settingArgDict[section] + except KeyError: + self.settingArgDict[section] = {} + self.settingArgDict[section][option] = str(value) + + def parseSettingArgs(self, settingArgs): + for optionElem in settingArgs.split(';'): + if len(optionElem.split('#',1)) != 2: + continue + if len(optionElem.split('#',1)[1].split('=',1)) != 2: + continue + section = str(optionElem.split('#',1)[0]).lower() + option = str(optionElem.split('#',1)[1].split('=',1)[0]).lower() + value = optionElem.split('#',1)[1].split('=',1)[1] + self.setOptionArgDict(section, option, value) + + def initFenrirConfig(self, cliArgs, fenrirManager = None, environment = environment.environment): + settingsRoot = '/etc/fenrir/' + settingsFile = cliArgs.setting + soundRoot = '/usr/share/sounds/fenrir/' + environment['runtime']['debug'] = debugManager.debugManager() environment['runtime']['debug'].initialize(environment) + # get fenrir settings root if not os.path.exists(settingsRoot): - if os.path.exists(os.path.dirname(os.path.realpath(__main__.__file__)) +'/../../config/'): - settingsRoot = os.path.dirname(os.path.realpath(__main__.__file__)) +'/../../config/' + if os.path.exists(fenrirPath +'/../../config/'): + settingsRoot = fenrirPath +'/../../config/' else: return None + # get settings file + if not os.path.exists(settingsFile): + if os.path.exists(settingsRoot + '/settings/settings.conf'): + settingsFile = settingsRoot + '/settings/settings.conf' + else: + return None + # get sound themes root if not os.path.exists(soundRoot): - if os.path.exists(os.path.dirname(os.path.realpath(__main__.__file__)) +'/../../config/sound/'): - soundRoot = os.path.dirname(os.path.realpath(__main__.__file__)) +'/../../config/sound/' + if os.path.exists(fenrirPath + '/../../config/sound/'): + soundRoot = fenrirPath + '/../../config/sound/' environment['runtime']['settingsManager'] = self environment['runtime']['settingsManager'].initialize(environment) - validConfig = environment['runtime']['settingsManager'].loadSettings(settingsRoot + '/settings/' + settingsFile) + validConfig = environment['runtime']['settingsManager'].loadSettings(settingsFile) if not validConfig: return None - + + if cliArgs.options != '': + self.parseSettingArgs(cliArgs.options) + if cliArgs.debug: + self.setOptionArgDict('general', 'debugLevel', 3) + if cliArgs.print: + self.setOptionArgDict('general', 'debugLevel', 3) + self.setOptionArgDict('general', 'debugMode', 'PRINT') self.setFenrirKeys(self.getSetting('general','fenrirKeys')) self.setScriptKeys(self.getSetting('general','scriptKeys')) - + if not os.path.exists(self.getSetting('keyboard','keyboardLayout')): if os.path.exists(settingsRoot + 'keyboard/' + self.getSetting('keyboard','keyboardLayout')): self.setSetting('keyboard', 'keyboardLayout', settingsRoot + 'keyboard/' + self.getSetting('keyboard','keyboardLayout')) @@ -255,28 +320,36 @@ environment['runtime']['settingsManager'].loadDicts(self.getSetting('general','punctuationProfile')) else: environment['runtime']['settingsManager'].loadDicts(self.getSetting('general','punctuationProfile')) - - environment['runtime']['inputManager'] = inputManager.inputManager() - environment['runtime']['inputManager'].initialize(environment) + + if fenrirManager: + environment['runtime']['fenrirManager'] = fenrirManager + environment['runtime']['eventManager'] = eventManager.eventManager() + environment['runtime']['eventManager'].initialize(environment) + environment['runtime']['processManager'] = processManager.processManager() + environment['runtime']['processManager'].initialize(environment) environment['runtime']['outputManager'] = outputManager.outputManager() environment['runtime']['outputManager'].initialize(environment) environment['runtime']['commandManager'] = commandManager.commandManager() environment['runtime']['commandManager'].initialize(environment) + environment['runtime']['inputManager'] = inputManager.inputManager() + environment['runtime']['inputManager'].initialize(environment) environment['runtime']['punctuationManager'] = punctuationManager.punctuationManager() environment['runtime']['punctuationManager'].initialize(environment) environment['runtime']['cursorManager'] = cursorManager.cursorManager() environment['runtime']['cursorManager'].initialize(environment) environment['runtime']['applicationManager'] = applicationManager.applicationManager() environment['runtime']['applicationManager'].initialize(environment) - + environment['runtime']['helpManager'] = helpManager.helpManager() + environment['runtime']['helpManager'].initialize(environment) if environment['runtime']['screenManager'] == None: environment['runtime']['screenManager'] = screenManager.screenManager() environment['runtime']['screenManager'].initialize(environment) environment['runtime']['debug'].writeDebugOut('\/-------environment-------\/',debug.debugLevel.INFO, onAnyLevel=True) - environment['runtime']['debug'].writeDebugOut(str(environment),debug.debugLevel.INFO, onAnyLevel=True) - environment['runtime']['debug'].writeDebugOut('\/-------settings.conf-------\/',debug.debugLevel.INFO, onAnyLevel=True) - environment['runtime']['debug'].writeDebugOut(str(environment['settings']._sections -),debug.debugLevel.INFO, onAnyLevel=True) + environment['runtime']['debug'].writeDebugOut(str(environment), debug.debugLevel.INFO, onAnyLevel=True) + environment['runtime']['debug'].writeDebugOut('\/-------settings.conf-------\/', debug.debugLevel.INFO, onAnyLevel=True) + environment['runtime']['debug'].writeDebugOut(str(environment['settings']._sections) , debug.debugLevel.INFO, onAnyLevel=True) + environment['runtime']['debug'].writeDebugOut('\/-------self.settingArgDict-------\/',debug.debugLevel.INFO, onAnyLevel=True) + environment['runtime']['debug'].writeDebugOut(str( self.settingArgDict) ,debug.debugLevel.INFO, onAnyLevel=True) return environment diff --git a/src/fenrir/fenrir b/src/fenrir/fenrir index fce4baa..d8107df 100755 --- a/src/fenrir/fenrir +++ b/src/fenrir/fenrir @@ -4,16 +4,16 @@ # Fenrir TTY screen reader # By Chrys, Storm Dragon, and contributers. -import os, sys -import __main__ +import os, sys, inspect +fenrirPath = os.path.dirname(os.path.realpath(os.path.abspath(inspect.getfile(inspect.currentframe())))) -if not os.path.dirname(os.path.realpath(__main__.__file__)) in sys.path: - sys.path.append(os.path.dirname(os.path.realpath(__main__.__file__))) +if not fenrirPath in sys.path: + sys.path.append(fenrirPath) -import fenrir +from core import fenrirManager def main(): - app = fenrir.fenrir() + app = fenrirManager.fenrirManager() app.proceed() del app diff --git a/src/fenrir/fenrir-daemon b/src/fenrir/fenrir-daemon index 41b3bc2..eefc505 100755 --- a/src/fenrir/fenrir-daemon +++ b/src/fenrir/fenrir-daemon @@ -4,25 +4,25 @@ # Fenrir TTY screen reader # By Chrys, Storm Dragon, and contributers. -import os, sys -import __main__ +import os, sys, inspect +fenrirPath = os.path.dirname(os.path.realpath(os.path.abspath(inspect.getfile(inspect.currentframe())))) -if not os.path.dirname(os.path.realpath(__main__.__file__)) in sys.path: - sys.path.append(os.path.dirname(os.path.realpath(__main__.__file__))) +if not fenrirPath in sys.path: + sys.path.append(fenrirPath) -import fenrir +from core import fenrirManager from daemonize import Daemonize pidFile = "/run/fenrir.pid" def main(): - app = fenrir.fenrir() + 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(__main__.__file__))) - daemon = Daemonize(app="fenrir-daemon", pid=pidFile, action=main, chdir=os.path.dirname(os.path.realpath(__main__.__file__))) + #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() diff --git a/src/fenrir/fenrir.py b/src/fenrir/fenrir.py deleted file mode 100644 index 5be90d9..0000000 --- a/src/fenrir/fenrir.py +++ /dev/null @@ -1,137 +0,0 @@ -#!/bin/python3 -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -import os, sys, signal, time -import __main__ - -if not os.path.dirname(os.path.realpath(__main__.__file__)) in sys.path: - sys.path.append(os.path.dirname(os.path.realpath(__main__.__file__))) - -from core import settingsManager -from core import debug - -class fenrir(): - def __init__(self): - try: - self.environment = settingsManager.settingsManager().initFenrirConfig() - if not self.environment: - raise RuntimeError('Cannot Initialize. Maybe the configfile is not available or not parseable') - except RuntimeError: - raise - self.environment['runtime']['outputManager'].presentText("Start Fenrir", soundIcon='ScreenReaderOn', interrupt=True) - signal.signal(signal.SIGINT, self.captureSignal) - signal.signal(signal.SIGTERM, self.captureSignal) - self.wasCommand = False - - def proceed(self): - while(self.environment['generalInformation']['running']): - try: - self.handleProcess() - except Exception as e: - self.environment['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) - self.shutdown() - - def handleProcess(self): - #startTime = time.time() - eventReceived = self.environment['runtime']['inputManager'].getInputEvent() - if eventReceived: - self.prepareCommand() - if not (self.wasCommand or self.environment['generalInformation']['tutorialMode']) or self.environment['runtime']['screenManager'].isSuspendingScreen(): - self.environment['runtime']['inputManager'].writeEventBuffer() - if self.environment['runtime']['inputManager'].noKeyPressed(): - if self.wasCommand: - self.wasCommand = False - self.environment['runtime']['inputManager'].clearEventBuffer() - if self.environment['generalInformation']['tutorialMode']: - self.environment['runtime']['inputManager'].clearEventBuffer() - if self.environment['input']['keyForeward'] > 0: - self.environment['input']['keyForeward'] -=1 - self.environment['runtime']['screenManager'].update('onInput') - self.environment['runtime']['commandManager'].executeDefaultTrigger('onInput') - else: - self.environment['runtime']['screenManager'].update('onUpdate') - if self.environment['runtime']['applicationManager'].isApplicationChange(): - self.environment['runtime']['commandManager'].executeDefaultTrigger('onApplicationChange') - self.environment['runtime']['commandManager'].executeSwitchTrigger('onSwitchApplicationProfile', \ - self.environment['runtime']['applicationManager'].getPrevApplication(), \ - self.environment['runtime']['applicationManager'].getCurrentApplication()) - - if self.environment['runtime']['screenManager'].isScreenChange(): - self.environment['runtime']['commandManager'].executeDefaultTrigger('onScreenChanged') - else: - self.environment['runtime']['commandManager'].executeDefaultTrigger('onScreenUpdate') - - self.handleCommands() - #print(time.time()-startTime) - - def prepareCommand(self): - if self.environment['runtime']['screenManager'].isSuspendingScreen(): - self.wasCommand = False - return - if self.environment['runtime']['inputManager'].noKeyPressed(): - return - if self.environment['input']['keyForeward'] > 0: - return - shortcut = self.environment['runtime']['inputManager'].getCurrShortcut() - command = self.environment['runtime']['inputManager'].getCommandForShortcut(shortcut) - if len(self.environment['input']['prevDeepestInput']) <= len(self.environment['input']['currInput']): - self.wasCommand = command != '' or self.environment['runtime']['inputManager'].isFenrirKeyPressed() or self.environment['runtime']['inputManager'].isScriptKeyPressed() - if command == '': - return - - self.environment['runtime']['commandManager'].queueCommand(command) - - - def handleCommands(self): - if not self.environment['runtime']['commandManager'].isCommandQueued(): - return - self.environment['runtime']['commandManager'].executeCommand( self.environment['commandInfo']['currCommand'], 'commands') - - def shutdownRequest(self): - self.environment['generalInformation']['running'] = False - - def captureSignal(self, siginit, frame): - self.shutdownRequest() - - def shutdown(self): - if self.environment['runtime']['inputManager']: - self.environment['runtime']['inputManager'].shutdown() - del self.environment['runtime']['inputManager'] - self.environment['runtime']['outputManager'].presentText("Quit Fenrir", soundIcon='ScreenReaderOff', interrupt=True) - time.sleep(0.9) # wait a little for sound - - if self.environment['runtime']['screenManager']: - self.environment['runtime']['screenManager'].shutdown() - del self.environment['runtime']['screenManager'] - if self.environment['runtime']['commandManager']: - self.environment['runtime']['commandManager'].shutdown() - del self.environment['runtime']['commandManager'] - if self.environment['runtime']['outputManager']: - self.environment['runtime']['outputManager'].shutdown() - del self.environment['runtime']['outputManager'] - if self.environment['runtime']['punctuationManager']: - self.environment['runtime']['punctuationManager'].shutdown() - del self.environment['runtime']['punctuationManager'] - if self.environment['runtime']['cursorManager']: - self.environment['runtime']['cursorManager'].shutdown() - del self.environment['runtime']['cursorManager'] - if self.environment['runtime']['applicationManager']: - self.environment['runtime']['applicationManager'].shutdown() - del self.environment['runtime']['applicationManager'] - - if self.environment['runtime']['debug']: - self.environment['runtime']['debug'].shutdown() - del self.environment['runtime']['debug'] - time.sleep(0.2) # wait a little before splatter it :) - self.environment = None - -def main(): - app = fenrir() - app.proceed() - del app - -if __name__ == "__main__": - main() diff --git a/src/fenrir/fenrirVersion.py b/src/fenrir/fenrirVersion.py new file mode 100644 index 0000000..f070cef --- /dev/null +++ b/src/fenrir/fenrirVersion.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +import os, sys +import __main__ + +version = 1.5 +codename = 'gampert' diff --git a/src/fenrir/inputDriver/dummyDriver.py b/src/fenrir/inputDriver/dummyDriver.py new file mode 100644 index 0000000..4a1f4fa --- /dev/null +++ b/src/fenrir/inputDriver/dummyDriver.py @@ -0,0 +1,60 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +import time +from core import debug + +class driver(): + def __init__(self): + self._initialized = False + + def initialize(self, environment): + self.env = environment + + def shutdown(self): + pass + + def getInputEvent(self): + time.sleep(0.05) + if not self._initialized: + return None + + def writeEventBuffer(self): + if not self._initialized: + return + + def clearEventBuffer(self): + if not self._initialized: + return + del self.env['input']['eventBuffer'][:] + + def updateInputDevices(self, force = False, init = False): + if not self._initialized: + return + + def getLedState(self, led = 0): + if not self._initialized: + return False + return False + + def toggleLedState(self, led = 0): + if not self._initialized: + return None + + def grabDevices(self): + if not self._initialized: + return None + + def releaseDevices(self): + if not self._initialized: + return None + + def __del__(self): + if not self._initialized: + return None + self.releaseDevices() + + diff --git a/src/fenrir/inputDriver/evdev.py b/src/fenrir/inputDriver/evdev.py deleted file mode 100644 index 3724faf..0000000 --- a/src/fenrir/inputDriver/evdev.py +++ /dev/null @@ -1,211 +0,0 @@ -#!/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -_evdevAvailable = False -_evdevAvailableError = '' -try: - import evdev - from evdev import InputDevice, UInput - _evdevAvailable = True -except Exception as e: - _evdevAvailableError = str(e) - -import time -from select import select -from core import inputEvent -from core import debug - -class driver(): - def __init__(self): - self.iDevices = {} - self.uDevices = {} - self.ledDevices = {} - self._initialized = False - - def initialize(self, environment): - self.env = environment - global _evdevAvailable - self._initialized = _evdevAvailable - if not self._initialized: - global _evdevAvailableError - self.env['runtime']['debug'].writeDebugOut('InputDriver: ' + _evdevAvailableError,debug.debugLevel.ERROR) - return - self.getInputDevices() - - def shutdown(self): - pass - def getInputEvent(self): - if not self._initialized: - time.sleep(0.005) # dont flood CPU - return None - if not self.iDevices: - return None - if self.iDevices == {}: - return None - - event = None - r, w, x = select(self.iDevices, [], [], self.env['runtime']['settingsManager'].getSettingAsFloat('screen', 'screenUpdateDelay')) - if r != []: - for fd in r: - event = self.iDevices[fd].read_one() - foreward = False - while(event): - self.env['input']['eventBuffer'].append( [self.iDevices[fd], self.uDevices[fd], event]) - if event.type == evdev.events.EV_KEY: - if event.code != 0: - currMapEvent = self.mapEvent(event) - if not currMapEvent: - foreward = True - event = self.iDevices[fd].read_one() - continue - if not isinstance(currMapEvent['EventName'], str): - foreward = True - event = self.iDevices[fd].read_one() - continue - if not foreward: - if currMapEvent['EventState'] in [0,1,2]: - return currMapEvent - else: - if not event.type in [0,1,4]: - foreward = True - event = self.iDevices[fd].read_one() - if foreward: - self.writeEventBuffer() - self.clearEventBuffer() - return None - - def writeEventBuffer(self): - if not self._initialized: - return - for iDevice, uDevice, event in self.env['input']['eventBuffer']: - self.writeUInput(uDevice, event) - - def clearEventBuffer(self): - if not self._initialized: - return - del self.env['input']['eventBuffer'][:] - - def writeUInput(self, uDevice, event): - if not self._initialized: - return - uDevice.write_event(event) - uDevice.syn() - def getInputDevices(self): - if not self._initialized: - return - deviceList = evdev.list_devices() - readableDevices = [] - for dev in deviceList: - try: - open(dev) - readableDevices.append(dev) - except Exception as e: - self.env['runtime']['debug'].writeDebugOut("Skip Inputdevice : " + dev +' ' + str(e),debug.debugLevel.ERROR) - self.iDevices = map(evdev.InputDevice, (readableDevices)) - self.ledDevices = map(evdev.InputDevice, (readableDevices)) - # 3 pos absolute - # 2 pos relative - # 17 LEDs - # 1 Keys - # we try to filter out mices and other stuff here - if self.env['runtime']['settingsManager'].getSetting('keyboard', 'device').upper() == 'ALL': - self.iDevices = {dev.fd: dev for dev in self.iDevices if 1 in dev.capabilities()} - self.ledDevices = {dev.fd: dev for dev in self.ledDevices if 1 in dev.capabilities() and 17 in dev.capabilities()} - elif self.env['runtime']['settingsManager'].getSetting('keyboard', 'device').upper() == 'NOMICE': - self.iDevices = {dev.fd: dev for dev in self.iDevices if 1 in dev.capabilities() and not 3 in dev.capabilities() and not 2 in dev.capabilities()} - self.ledDevices = {dev.fd: dev for dev in self.ledDevices if 1 in dev.capabilities() and 17 in dev.capabilities() and not 3 in dev.capabilities() and not 2 in dev.capabilities()} - else: - self.iDevices = {dev.fd: dev for dev in self.iDevices if dev.name.upper() in self.env['runtime']['settingsManager'].getSetting('keyboard', 'device').upper().split(',')} - self.ledDevices = {dev.fd: dev for dev in self.ledDevices if dev.name.upper() in self.env['runtime']['settingsManager'].getSetting('keyboard', 'device').upper().split(',')} - - def mapEvent(self, event): - if not self._initialized: - return None - if not event: - return None - mEvent = inputEvent.inputEvent - try: - mEvent['EventName'] = evdev.ecodes.keys[event.code] - mEvent['EventValue'] = event.code - mEvent['EventSec'] = event.sec - mEvent['EventUsec'] = event.usec - mEvent['EventState'] = event.value - return mEvent - except Exception as e: - return None - - def getLedState(self, led = 0): - if not self._initialized: - return None - # 0 = Numlock - # 1 = Capslock - # 2 = Rollen - if self.ledDevices == None: - return False - if self.ledDevices == {}: - return False - for fd, dev in self.ledDevices.items(): - return led in dev.leds() - return False - def toggleLedState(self, led = 0): - if not self._initialized: - return None - ledState = self.getLedState(led) - for i in self.ledDevices: - if ledState == 1: - self.ledDevices[i].set_led(led , 0) - else: - self.ledDevices[i].set_led(led , 1) - def grabDevices(self): - if not self._initialized: - return None -# leve the old code until the new one is better tested -# for fd in self.iDevices: -# dev = self.iDevices[fd] -# cap = dev.capabilities() -# del cap[0] -# self.uDevices[fd] = UInput( -# cap, -# dev.name, -# #dev.info.vendor, -# #dev.info.product, -# #dev.version, -# #dev.info.bustype, -# #'/dev/uinput' -# ) -# dev.grab() - for fd in self.iDevices: - try: - self.uDevices[fd] = UInput.from_device(self.iDevices[fd].fn) - self.iDevices[fd].grab() - except Exception as e: - self.env['runtime']['debug'].writeDebugOut('InputDriver evdev: grabing not possible: ' + str(e),debug.debugLevel.ERROR) - def releaseDevices(self): - if not self._initialized: - return None - for fd in self.iDevices: - try: - self.iDevices[fd].ungrab() - except: - pass - try: - self.iDevices[fd].close() - except: - pass - try: - self.uDevices[fd].close() - except: - pass - - self.iDevices.clear() - self.uDevices.clear() - - def __del__(self): - if not self._initialized: - return None - self.releaseDevices() - - diff --git a/src/fenrir/inputDriver/evdevDriver.py b/src/fenrir/inputDriver/evdevDriver.py new file mode 100644 index 0000000..7259604 --- /dev/null +++ b/src/fenrir/inputDriver/evdevDriver.py @@ -0,0 +1,332 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +_evdevAvailable = False +_udevAvailable = False +_evdevAvailableError = '' +_udevAvailableError = '' +try: + import evdev + from evdev import InputDevice, UInput + _evdevAvailable = True +except Exception as e: + _evdevAvailableError = str(e) + +try: + import pyudev + _udevAvailable = True +except Exception as e: + _udevAvailableError = str(e) + +import time +from select import select +import multiprocessing +from multiprocessing.sharedctypes import Value +from ctypes import c_bool + +from core.eventData import fenrirEventType +from core import inputData +from core import debug + + +class driver(): + def __init__(self): + self._manager = multiprocessing.Manager() + self.iDevices = {} + self.iDevicesFD = self._manager.list() + self.uDevices = {} + self.iDeviceNo = 0 + self._initialized = False + self.watchDog = Value(c_bool, True) + def initialize(self, environment): + self.env = environment + global _evdevAvailable + global _udevAvailable + self._initialized = _evdevAvailable + if not self._initialized: + global _evdevAvailableError + self.env['runtime']['debug'].writeDebugOut('InputDriver: ' + _evdevAvailableError,debug.debugLevel.ERROR) + return + if _udevAvailable: + self.env['runtime']['processManager'].addCustomEventThread(self.plugInputDeviceWatchdogUdev) + else: + self.env['runtime']['processManager'].addSimpleEventThread(fenrirEventType.PlugInputDevice, self.plugInputDeviceWatchdogTimer) + self.env['runtime']['processManager'].addSimpleEventThread(fenrirEventType.KeyboardInput, self.inputWatchdog, {'dev':self.iDevicesFD}) + def plugInputDeviceWatchdogUdev(self,active , eventQueue): + context = pyudev.Context() + monitor = pyudev.Monitor.from_netlink(context) + monitor.filter_by(subsystem='input') + monitor.start() + while active.value: + devices = monitor.poll(2) + if devices: + while monitor.poll(0.5): + time.sleep(0.2) + eventQueue.put({"Type":fenrirEventType.PlugInputDevice,"Data":None}) + return time.time() + def plugInputDeviceWatchdogTimer(self, active): + time.sleep(2.5) + return time.time() + def shutdown(self): + if not self._initialized: + return + def inputWatchdog(self,active , params): + try: + deviceFd = [] + while self.watchDog.value == 0: + if active.value == 0: + return + r = [] + while r == []: + if active.value == 0: + return + r, w, x = select(list(params['dev']), [], [], 0.3) + self.watchDog.value = 0 + except: + pass + def getInputEvent(self): + if not self.hasIDevices(): + self.watchDog.value = 1 + return None + event = None + r, w, x = select(self.iDevices, [], [], 0.00001) + if r != []: + for fd in r: + try: + event = self.iDevices[fd].read_one() + except: + self.removeDevice(fd) + self.watchDog.value = 1 + return None + foreward = False + while(event): + self.env['input']['eventBuffer'].append( [self.iDevices[fd], self.uDevices[fd], event]) + if event.type == evdev.events.EV_KEY: + if event.code != 0: + currMapEvent = self.mapEvent(event) + if not currMapEvent: + foreward = True + event = self.iDevices[fd].read_one() + continue + if not isinstance(currMapEvent['EventName'], str): + foreward = True + event = self.iDevices[fd].read_one() + continue + if not foreward: + if currMapEvent['EventState'] in [0,1,2]: + self.watchDog.value = 1 + return currMapEvent + else: + if not event.type in [0,1,4]: + foreward = True + event = self.iDevices[fd].read_one() + if foreward: + self.writeEventBuffer() + self.clearEventBuffer() + self.watchDog.value = 1 + return None + + def writeEventBuffer(self): + if not self._initialized: + return + for iDevice, uDevice, event in self.env['input']['eventBuffer']: + self.writeUInput(uDevice, event) + + def clearEventBuffer(self): + if not self._initialized: + return + del self.env['input']['eventBuffer'][:] + + def writeUInput(self, uDevice, event): + if not self._initialized: + return + uDevice.write_event(event) + uDevice.syn() + time.sleep(0.00001) + + def updateInputDevices(self, force = False, init = False): + if init: + self.removeAllDevices() + deviceFileList = evdev.list_devices() + if not force and False: + if len(deviceFileList) == self.iDeviceNo: + return + mode = self.env['runtime']['settingsManager'].getSetting('keyboard', 'device').upper() + iDevicesFiles = [] + for device in self.iDevices: + iDevicesFiles.append(self.iDevices[device].fn) + if len(iDevicesFiles) == len(deviceFileList): + return + eventType = evdev.events + for deviceFile in deviceFileList: + try: + if deviceFile in iDevicesFiles: + continue + try: + open(deviceFile) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("Not readable Inputdevice : " + deviceFile +' ' + str(e),debug.debugLevel.ERROR) + continue + # 3 pos absolute + # 2 pos relative + # 1 Keys + currDevice = evdev.InputDevice(deviceFile) + if currDevice.name.upper() in ['','SPEAKUP','PY-EVDEV-UINPUT']: + continue + if 'BRLTTY' in currDevice.name.upper(): + continue + cap = currDevice.capabilities() + if mode in ['ALL','NOMICE']: + if eventType.EV_KEY in cap: + if 116 in cap[eventType.EV_KEY] and len(cap[eventType.EV_KEY]) < 10: + self.env['runtime']['debug'].writeDebugOut('Device Skipped (has 116):' + currDevice.name,debug.debugLevel.INFO) + continue + if len(cap[eventType.EV_KEY]) < 30: + self.env['runtime']['debug'].writeDebugOut('Device Skipped (< 30 keys):' + currDevice.name,debug.debugLevel.INFO) + continue + if mode == 'ALL': + self.iDevices[currDevice.fd] = currDevice + self.grabDevice(currDevice.fd) + self.env['runtime']['debug'].writeDebugOut('Device added (ALL):' + self.iDevices[currDevice.fd].name, debug.debugLevel.INFO) + elif mode == 'NOMICE': + if not ((eventType.EV_REL in cap) or (eventType.EV_ABS in cap)): + self.iDevices[currDevice.fd] = currDevice + self.grabDevice(currDevice.fd) + self.env['runtime']['debug'].writeDebugOut('Device added (NOMICE):' + self.iDevices[currDevice.fd].name,debug.debugLevel.INFO) + else: + self.env['runtime']['debug'].writeDebugOut('Device Skipped (NOMICE):' + currDevice.name,debug.debugLevel.INFO) + elif currDevice.name.upper() in mode.split(','): + self.iDevices[currDevice.fd] = currDevice + self.grabDevice(currDevice.fd) + self.env['runtime']['debug'].writeDebugOut('Device added (Name):' + self.iDevices[currDevice.fd].name,debug.debugLevel.INFO) + except Exception as e: + print(e) + self.env['runtime']['debug'].writeDebugOut("Device Skipped (Exception): " + deviceFile +' ' + currDevice.name +' '+ str(e),debug.debugLevel.INFO) + self.iDeviceNo = len(evdev.list_devices()) + self.updateMPiDevicesFD() + + def updateMPiDevicesFD(self): + for fd in self.iDevices: + if not fd in self.iDevicesFD: + self.iDevicesFD.append(fd) + for fd in self.iDevicesFD: + if not fd in self.iDevices: + self.iDevicesFD.remove(fd) + def mapEvent(self, event): + if not self._initialized: + return None + if not event: + return None + mEvent = inputData.inputEvent + try: + mEvent['EventName'] = evdev.ecodes.keys[event.code] + mEvent['EventValue'] = event.code + mEvent['EventSec'] = event.sec + mEvent['EventUsec'] = event.usec + mEvent['EventState'] = event.value + return mEvent + except Exception as e: + return None + + def getLedState(self, led = 0): + if not self.hasIDevices(): + return False + # 0 = Numlock + # 1 = Capslock + # 2 = Rollen + for fd, dev in self.iDevices.items(): + if led in dev.leds(): + return True + return False + def toggleLedState(self, led = 0): + if not self.hasIDevices(): + return False + ledState = self.getLedState(led) + for i in self.iDevices: + # 17 LEDs + if 17 in self.iDevices[i].capabilities(): + if ledState == 1: + self.iDevices[i].set_led(led , 0) + else: + self.iDevices[i].set_led(led , 1) + def grabAllDevices(self): + if not self._initialized: + return + for fd in self.iDevices: + self.grabDevice(fd) + + def grabDevice(self, fd): + if not self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'grabDevices'): + self.uDevices[fd] = None + return + try: + self.uDevices[fd] = UInput.from_device(self.iDevices[fd].fn) + except Exception as e: + try: + self.env['runtime']['debug'].writeDebugOut('InputDriver evdev: compat fallback: ' + str(e),debug.debugLevel.WARNING) + dev = self.iDevices[fd] + cap = dev.capabilities() + del cap[0] + self.uDevices[fd] = UInput( + cap, + dev.name, + ) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('InputDriver evdev: init Uinput not possible: ' + str(e),debug.debugLevel.ERROR) + return + try: + self.iDevices[fd].grab() + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('InputDriver evdev: grabing not possible: ' + str(e),debug.debugLevel.ERROR) + + def removeDevice(self,fd): + self.clearEventBuffer() + try: + self.iDevices[fd].ungrab() + except: + pass + try: + self.iDevices[fd].close() + except: + pass + try: + self.uDevices[fd].close() + except: + pass + try: + del(self.iDevices[fd]) + except: + pass + try: + del(self.uDevices[fd]) + except: + pass + self.updateMPiDevicesFD() + + def hasIDevices(self): + if not self._initialized: + return False + if not self.iDevices: + return False + if len(self.iDevices) == 0: + return False + return True + + def removeAllDevices(self): + if not self.hasIDevices(): + return + devices = self.iDevices.copy() + for fd in devices: + self.removeDevice(fd) + self.iDevices.clear() + self.uDevices.clear() + self.iDeviceNo = 0 + + def __del__(self): + if not self._initialized: + return + + diff --git a/src/fenrir/screenDriver/vcsa.py b/src/fenrir/screenDriver/vcsa.py deleted file mode 100644 index 851a2df..0000000 --- a/src/fenrir/screenDriver/vcsa.py +++ /dev/null @@ -1,179 +0,0 @@ -#!/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -import difflib -import re -import subprocess -import fcntl -import termios -import time -import dbus -from core import debug -from utils import screen_utils - -class driver(): - def __init__(self): - self.vcsaDevicePath = '/dev/vcsa' - def initialize(self, environment): - self.env = environment - def shutdown(self): - pass - def getCurrScreen(self): - self.env['screenData']['oldTTY'] = self.env['screenData']['newTTY'] - try: - currScreenFile = open('/sys/devices/virtual/tty/tty0/active','r') - self.env['screenData']['newTTY'] = str(currScreenFile.read()[3:-1]) - currScreenFile.close() - except Exception as e: - self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) - def injectTextToScreen(self, text, screen = None): - useScreen = "/dev/tty" + self.env['screenData']['newTTY'] - if screen != None: - useScreen = screen - with open(useScreen, 'w') as fd: - for c in text: - fcntl.ioctl(fd, termios.TIOCSTI, c) - - def getCurrApplication(self): - apps = [] - try: - currScreen = self.env['screenData']['newTTY'] - apps = subprocess.Popen('ps -t tty' + currScreen + ' -o comm,tty,stat', shell=True, stdout=subprocess.PIPE).stdout.read().decode()[:-1].split('\n') - except Exception as e: - self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) - return - try: - for i in apps: - i = i.upper() - i = i.split() - i[0] = i[0] - i[1] = i[1] - if '+' in i[2]: - if i[0] != '': - if not "GREP" == i[0] and \ - not "SH" == i[0] and \ - not "PS" == i[0]: - if "TTY"+currScreen in i[1]: - if self.env['screenData']['newApplication'] != i[0]: - self.env['screenData']['newApplication'] = i[0] - return - except Exception as e: - self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) - return - - def getSessionInformation(self): - progname = 'org.freedesktop.login1' - objpath = '/org/freedesktop/login1' - intfname = 'org.freedesktop.login1.Manager' - methname = 'ListSessions' - - bus = dbus.SystemBus() - - obj = bus.get_object(progname, objpath) - inf = dbus.Interface(obj, intfname) - meth = inf.get_dbus_method(methname) - - sessions = meth() - self.env['screenData']['autoIgnoreScreens'] = [] - for session in sessions: - obj = bus.get_object(progname, session[4]) - inf = dbus.Interface(obj, 'org.freedesktop.DBus.Properties') - sessionType = inf.Get('org.freedesktop.login1.Session', 'Type') - screen = str(inf.Get('org.freedesktop.login1.Session', 'TTY')) - screen = screen[screen.upper().find('TTY') + 3:] - if sessionType.upper() == 'X11': - self.env['screenData']['autoIgnoreScreens'].append(screen) - - def update(self, trigger='onUpdate'): - newContentBytes = b'' - try: - # read screen - vcsa = open(self.vcsaDevicePath + self.env['screenData']['newTTY'],'rb',0) - newContentBytes = vcsa.read() - vcsa.close() - if len(newContentBytes) < 5: - return - except Exception as e: - self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) - return - screenEncoding = self.env['runtime']['settingsManager'].getSetting('screen', 'encoding') - # set new "old" values - self.env['screenData']['oldContentBytes'] = self.env['screenData']['newContentBytes'] - self.env['screenData']['oldContentText'] = self.env['screenData']['newContentText'] - self.env['screenData']['oldContentAttrib'] = self.env['screenData']['newContentAttrib'] - self.env['screenData']['oldCursor'] = self.env['screenData']['newCursor'].copy() - if self.env['screenData']['newCursorAttrib']: - self.env['screenData']['oldCursorAttrib'] = self.env['screenData']['newCursorAttrib'].copy() - self.env['screenData']['oldDelta'] = self.env['screenData']['newDelta'] - self.env['screenData']['oldAttribDelta'] = self.env['screenData']['newAttribDelta'] - self.env['screenData']['oldNegativeDelta'] = self.env['screenData']['newNegativeDelta'] - self.env['screenData']['newContentBytes'] = newContentBytes - # get metadata like cursor or screensize - self.env['screenData']['lines'] = int( self.env['screenData']['newContentBytes'][0]) - self.env['screenData']['columns'] = int( self.env['screenData']['newContentBytes'][1]) - self.env['screenData']['newCursor']['x'] = int( self.env['screenData']['newContentBytes'][2]) - self.env['screenData']['newCursor']['y'] = int( self.env['screenData']['newContentBytes'][3]) - # analyze content - self.env['screenData']['newContentText'] = self.env['screenData']['newContentBytes'][4:][::2].decode(screenEncoding, "replace").encode('utf-8').decode('utf-8') - self.env['screenData']['newContentText'] = screen_utils.removeNonprintable(self.env['screenData']['newContentText']) - self.env['screenData']['newContentAttrib'] = self.env['screenData']['newContentBytes'][5:][::2] - self.env['screenData']['newContentText'] = screen_utils.insertNewlines(self.env['screenData']['newContentText'], self.env['screenData']['columns']) - - if self.env['screenData']['newTTY'] != self.env['screenData']['oldTTY']: - self.env['screenData']['oldContentBytes'] = b'' - self.env['screenData']['oldContentAttrib'] = b'' - self.env['screenData']['oldContentText'] = '' - self.env['screenData']['oldCursor']['x'] = 0 - self.env['screenData']['oldCursor']['y'] = 0 - self.env['screenData']['oldDelta'] = '' - self.env['screenData']['oldAttribDelta'] = '' - self.env['screenData']['oldCursorAttrib'] = None - self.env['screenData']['newCursorAttrib'] = None - self.env['screenData']['oldNegativeDelta'] = '' - # initialize current deltas - self.env['screenData']['newNegativeDelta'] = '' - self.env['screenData']['newDelta'] = '' - self.env['screenData']['newAttribDelta'] = '' - - # changes on the screen - oldScreenText = re.sub(' +',' ',self.env['runtime']['screenManager'].getWindowAreaInText(self.env['screenData']['oldContentText'])) - newScreenText = re.sub(' +',' ',self.env['runtime']['screenManager'].getWindowAreaInText(self.env['screenData']['newContentText'])) - typing = False - if (self.env['screenData']['oldContentText'] != self.env['screenData']['newContentText']) and \ - (self.env['screenData']['newContentText'] != '' ): - if oldScreenText == '' and\ - newScreenText != '': - self.env['screenData']['newDelta'] = newScreenText - else: - cursorLineStart = self.env['screenData']['newCursor']['y'] * self.env['screenData']['columns'] + self.env['screenData']['newCursor']['y'] - cursorLineEnd = cursorLineStart + self.env['screenData']['columns'] - if self.env['screenData']['oldCursor']['x'] != self.env['screenData']['newCursor']['x'] and \ - self.env['screenData']['oldCursor']['y'] == self.env['screenData']['newCursor']['y'] and \ - self.env['screenData']['newContentText'][:cursorLineStart] == self.env['screenData']['oldContentText'][:cursorLineStart]: - - oldScreenText = self.env['screenData']['oldContentText'][cursorLineStart:cursorLineEnd] - oldScreenText = re.sub(' +',' ',oldScreenText) - newScreenText = self.env['screenData']['newContentText'][cursorLineStart:cursorLineEnd] - newScreenText = re.sub(' +',' ',newScreenText) - diff = difflib.ndiff(oldScreenText, newScreenText) - typing = True - else: - diff = difflib.ndiff( oldScreenText.split('\n'),\ - newScreenText.split('\n')) - - diffList = list(diff) - - if self.env['runtime']['settingsManager'].getSetting('general', 'newLinePause') and not typing: - self.env['screenData']['newDelta'] = '\n'.join(x[2:] for x in diffList if x[0] == '+') - else: - self.env['screenData']['newDelta'] = ''.join(x[2:] for x in diffList if x[0] == '+') - self.env['screenData']['newNegativeDelta'] = ''.join(x[2:] for x in diffList if x[0] == '-') - - # track highlighted - if self.env['screenData']['oldContentAttrib'] != self.env['screenData']['newContentAttrib']: - if self.env['runtime']['settingsManager'].getSettingAsBool('focus', 'highlight'): - self.env['screenData']['newAttribDelta'], self.env['screenData']['newCursorAttrib'] = screen_utils.trackHighlights(self.env['screenData']['oldContentAttrib'], self.env['screenData']['newContentAttrib'], self.env['screenData']['newContentText'], self.env['screenData']['columns']) - diff --git a/src/fenrir/screenDriver/vcsaDriver.py b/src/fenrir/screenDriver/vcsaDriver.py new file mode 100644 index 0000000..e50ad3d --- /dev/null +++ b/src/fenrir/screenDriver/vcsaDriver.py @@ -0,0 +1,373 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. +#attrib: +#http://rampex.ihep.su/Linux/linux_howto/html/tutorials/mini/Colour-ls-6.html +#0 = black, 1 = blue, 2 = green, 3 = cyan, 4 = red, 5 = purple, 6 = brown/yellow, 7 = white. +#https://github.com/jwilk/vcsapeek/blob/master/linuxvt.py +#blink = 5 if attr & 1 else 0 +#bold = 1 if attr & 16 else 0 + + +import difflib +import re +import subprocess +import glob, os +import termios +import time +import select +import dbus +import fcntl +from array import array +import errno +import sys +from utils import screen_utils +from fcntl import ioctl +from struct import unpack_from, unpack, pack +from core import debug +from core.eventData import fenrirEventType + + +class driver(): + def __init__(self): + self.vcsaDevicePath = '/dev/vcsa' + self.ListSessions = None + self.charmap = {} + self.bgColorNames = {0: _('black'), 1: _('blue'), 2: _('green'), 3: _('cyan'), 4: _('red'), 5: _('Magenta'), 6: _('brown/yellow'), 7: _('white')} + self.fgColorNames = {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 + def initialize(self, environment): + self.env = environment + self.env['runtime']['processManager'].addCustomEventThread(self.updateWatchdog) + def shutdown(self): + pass + def getCurrScreen(self): + self.env['screen']['oldTTY'] = self.env['screen']['newTTY'] + try: + currScreenFile = open('/sys/devices/virtual/tty/tty0/active','r') + self.env['screen']['newTTY'] = str(currScreenFile.read()[3:-1]) + currScreenFile.close() + except Exception as e: + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + def injectTextToScreen(self, text, screen = None): + useScreen = "/dev/tty" + self.env['screen']['newTTY'] + if screen != None: + useScreen = screen + with open(useScreen, 'w') as fd: + for c in text: + fcntl.ioctl(fd, termios.TIOCSTI, c) + + def getCurrApplication(self): + apps = [] + try: + currScreen = self.env['screen']['newTTY'] + apps = subprocess.Popen('ps -t tty' + currScreen + ' -o comm,tty,stat', shell=True, stdout=subprocess.PIPE).stdout.read().decode()[:-1].split('\n') + except Exception as e: + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + return + try: + for i in apps: + i = i.upper() + i = i.split() + i[0] = i[0] + i[1] = i[1] + if '+' in i[2]: + if i[0] != '': + if not "GREP" == i[0] and \ + not "SH" == i[0] and \ + not "PS" == i[0]: + if "TTY"+currScreen in i[1]: + if self.env['screen']['newApplication'] != i[0]: + self.env['screen']['newApplication'] = i[0] + return + except Exception as e: + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + + def getSessionInformation(self): + try: + bus = dbus.SystemBus() + if not self.ListSessions: + obj = bus.get_object('org.freedesktop.login1', '/org/freedesktop/login1') + inf = dbus.Interface(obj, 'org.freedesktop.login1.Manager') + self.ListSessions = inf.get_dbus_method('ListSessions') + sessions = self.ListSessions() + self.env['screen']['autoIgnoreScreens'] = [] + for session in sessions: + obj = bus.get_object('org.freedesktop.login1', session[4]) + inf = dbus.Interface(obj, 'org.freedesktop.DBus.Properties') + sessionType = inf.Get('org.freedesktop.login1.Session', 'Type') + screen = str(inf.Get('org.freedesktop.login1.Session', 'VTNr')) + if screen == '': + screen = str(inf.Get('org.freedesktop.login1.Session', 'TTY')) + screen = screen[screen.upper().find('TTY') + 3:] + if screen == '': + self.env['runtime']['debug'].writeDebugOut('No TTY found for session:' + session[4],debug.debugLevel.ERROR) + return + if sessionType.upper() == 'X11': + self.env['screen']['autoIgnoreScreens'].append(screen) + if screen == self.env['screen']['newTTY'] : + if self.env['general']['currUser'] != session[2]: + self.env['general']['prevUser'] = self.env['general']['currUser'] + self.env['general']['currUser'] = session[2] + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('getSessionInformation: Maybe no LoginD:' + str(e),debug.debugLevel.ERROR) + self.env['screen']['autoIgnoreScreens'] = [] + self.env['runtime']['debug'].writeDebugOut('getSessionInformation:' + str(self.env['screen']['autoIgnoreScreens']) + ' ' + str(self.env['general']) ,debug.debugLevel.INFO) + + def updateWatchdog(self,active , eventQueue): + try: + vcsa = {} + vcsaDevices = glob.glob('/dev/vcsa*') + for vcsaDev in vcsaDevices: + index = vcsaDev[9:] + vcsa[str(index)] = open(vcsaDev,'rb') + + tty = open('/sys/devices/virtual/tty/tty0/active','r') + currScreen = str(tty.read()[3:-1]) + oldScreen = currScreen + watchdog = select.epoll() + watchdog.register(vcsa[currScreen], select.POLLPRI | select.POLLERR) + watchdog.register(tty, select.POLLPRI | select.POLLERR) + while active.value == 1: + changes = watchdog.poll(2) + for change in changes: + fileno = change[0] + event = change[1] + if fileno == tty.fileno(): + self.env['runtime']['debug'].writeDebugOut('ScreenChange',debug.debugLevel.INFO) + tty.seek(0) + currScreen = str(tty.read()[3:-1]) + if currScreen != oldScreen: + try: + watchdog.unregister(vcsa[ oldScreen ]) + except: + pass + try: + watchdog.register(vcsa[ currScreen ], select.POLLPRI | select.POLLERR) + except: + pass + oldScreen = currScreen + eventQueue.put({"Type":fenrirEventType.ScreenChanged,"Data":''}) + try: + vcsa[currScreen].seek(0) + lastScreenContent = vcsa[currScreen].read() + except: + pass + else: + self.env['runtime']['debug'].writeDebugOut('ScreenUpdate',debug.debugLevel.INFO) + vcsa[currScreen].seek(0) + dirtyContent = vcsa[currScreen].read() + screenContent = b'' + timeout = time.time() + while screenContent != dirtyContent: + screenContent = dirtyContent + if time.time() - timeout >= 0.4: + break + time.sleep(0.007) + vcsa[currScreen].seek(0) + dirtyContent = vcsa[currScreen].read() + eventQueue.put({"Type":fenrirEventType.ScreenUpdate,"Data":None}) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('VCSA:updateWatchdog:' + str(e),debug.debugLevel.ERROR) + + def updateCharMap(self, screen): + self.charmap = {} + try: + tty = open('/dev/tty' + screen, 'rb') + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('VCSA:updateCharMap:' + str(e),debug.debugLevel.ERROR) + return + GIO_UNIMAP = 0x4B66 + VT_GETHIFONTMASK = 0x560D + himask = array("H", (0,)) + ioctl(tty, VT_GETHIFONTMASK, himask) + self.hichar, = unpack_from("@H", himask) + sz = 512 + line = '' + while True: + try: + unipairs = array("H", [0]*(2*sz)) + unimapdesc = array("B", pack("@HP", sz, unipairs.buffer_info()[0])) + ioctl(tty.fileno(), GIO_UNIMAP, unimapdesc) + break + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('VCSA:updateCharMap:scaling up sz=' + str(sz) + ' ' + str(e),debug.debugLevel.WARNING) + sz *= 2 + tty.close() + ncodes, = unpack_from("@H", unimapdesc) + utable = unpack_from("@%dH" % (2*ncodes), unipairs) + for u, b in zip(utable[::2], utable[1::2]): + if self.charmap.get(b) is None: + self.charmap[b] = chr(u) + + def autoDecodeVCSA(self, allData, rows, cols): + allText = '' + allAttrib = [] + i = 0 + for y in range(rows): + lineText = '' + lineAttrib = [] + for x in range(cols): + data = allData[i: i + 2] + i += 2 + if data == b' \x07': + #attr = 7 + #ink = 7 + #paper = 0 + #ch = ' ' + lineAttrib.append((7,15,0,0,0,0)) # attribute, ink, paper, blink, bold, underline + lineText += ' ' + continue + (sh,) = unpack("=H", data) + attr = (sh >> 8) & 0xFF + ch = sh & 0xFF + if self.hichar == 0x100: + attr >>= 1 + ink = attr & 0x0F + paper = (attr>>4) & 0x0F + blink = 0 + #if attr & 1: + # blink = 1 + bold = 0 + #if attr & 16: + # bold = 1 + #if (ink != 7) or (paper != 0): + # print(ink,paper) + if sh & self.hichar: + ch |= 0x100 + try: + lineText += self.charmap[ch] + except KeyError: + lineText += '?' + lineAttrib.append((attr,ink, paper,blink,bold,0)) # attribute, ink, paper, blink, bold, underline + allText += lineText + '\n' + allAttrib += lineAttrib + return str(allText), allAttrib + def getFenrirBGColor(self, attribute): + try: + return self.bgColorNames[attribute[2]] + except Exception as e: + print(e) + return '' + def getFenrirFGColor(self, attribute): + try: + return self.fgColorNames[attribute[1]] + except Exception as e: + print(e) + return '' + def getFenrirUnderline(self, attribute): + if attribute[5] == 1: + return _('underlined') + return '' + def getFenrirBold(self, attribute): + if attribute[4] == 1: + return _('bold') + return '' + def getFenrirBlink(self, attribute): + if attribute[3] == 1: + return _('blink') + return '' + def getFenrirFont(self, attribute): + return _('Default') + def getFenrirFontSize(self, attribute): + return _('Default') + def update(self, trigger='onUpdate'): + if trigger == 'onInput': # no need for an update on input for VCSA + return + newContentBytes = b'' + try: + # read screen + vcsa = open(self.vcsaDevicePath + self.env['screen']['newTTY'],'rb',0) + newContentBytes = vcsa.read() + vcsa.close() + if len(newContentBytes) < 5: + return + except Exception as e: + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + return + # set new "old" values + self.env['screen']['oldContentBytes'] = self.env['screen']['newContentBytes'] + self.env['screen']['oldContentText'] = self.env['screen']['newContentText'] + self.env['screen']['oldContentAttrib'] = self.env['screen']['newContentAttrib'] + self.env['screen']['oldCursor'] = self.env['screen']['newCursor'].copy() + if self.env['screen']['newCursorAttrib']: + self.env['screen']['oldCursorAttrib'] = self.env['screen']['newCursorAttrib'].copy() + self.env['screen']['oldDelta'] = self.env['screen']['newDelta'] + self.env['screen']['oldAttribDelta'] = self.env['screen']['newAttribDelta'] + self.env['screen']['oldNegativeDelta'] = self.env['screen']['newNegativeDelta'] + self.env['screen']['newContentBytes'] = newContentBytes + # get metadata like cursor or screensize + self.env['screen']['lines'] = int( self.env['screen']['newContentBytes'][0]) + self.env['screen']['columns'] = int( self.env['screen']['newContentBytes'][1]) + self.env['screen']['newCursor']['x'] = int( self.env['screen']['newContentBytes'][2]) + self.env['screen']['newCursor']['y'] = int( self.env['screen']['newContentBytes'][3]) + + # analyze content + self.updateCharMap(str(self.env['screen']['newTTY'])) + self.env['screen']['newContentText'], \ + self.env['screen']['newContentAttrib'] =\ + self.autoDecodeVCSA(self.env['screen']['newContentBytes'][4:], self.env['screen']['lines'], self.env['screen']['columns']) + + if self.env['screen']['newTTY'] != self.env['screen']['oldTTY']: + self.env['screen']['oldContentBytes'] = b'' + self.env['screen']['oldContentAttrib'] = None + self.env['screen']['oldContentText'] = '' + self.env['screen']['oldCursor']['x'] = 0 + self.env['screen']['oldCursor']['y'] = 0 + self.env['screen']['oldDelta'] = '' + self.env['screen']['oldAttribDelta'] = '' + self.env['screen']['oldCursorAttrib'] = None + self.env['screen']['newCursorAttrib'] = None + self.env['screen']['oldNegativeDelta'] = '' + # initialize current deltas + self.env['screen']['newNegativeDelta'] = '' + self.env['screen']['newDelta'] = '' + self.env['screen']['newAttribDelta'] = '' + + # changes on the screen + oldScreenText = re.sub(' +',' ',self.env['runtime']['screenManager'].getWindowAreaInText(self.env['screen']['oldContentText'])) + newScreenText = re.sub(' +',' ',self.env['runtime']['screenManager'].getWindowAreaInText(self.env['screen']['newContentText'])) + typing = False + if (self.env['screen']['oldContentText'] != self.env['screen']['newContentText']): + if self.env['screen']['newContentText'] != '' and self.env['screen']['oldContentText'] == '': + if oldScreenText == '' and\ + newScreenText != '': + self.env['screen']['newDelta'] = newScreenText + else: + cursorLineStart = self.env['screen']['newCursor']['y'] * self.env['screen']['columns'] + self.env['screen']['newCursor']['y'] + cursorLineEnd = cursorLineStart + self.env['screen']['columns'] + if abs(self.env['screen']['oldCursor']['x'] - self.env['screen']['newCursor']['x']) == 1 and \ + self.env['screen']['oldCursor']['y'] == self.env['screen']['newCursor']['y'] and \ + self.env['screen']['newContentText'][:cursorLineStart] == self.env['screen']['oldContentText'][:cursorLineStart] and \ + self.env['screen']['newContentText'][cursorLineEnd:] == self.env['screen']['oldContentText'][cursorLineEnd:]: + cursorLineStartOffset = cursorLineStart + cursorLineEndOffset = cursorLineEnd + #if cursorLineStart < cursorLineStart + self.env['screen']['newCursor']['x'] - 4: + # cursorLineStartOffset = cursorLineStart + self.env['screen']['newCursor']['x'] - 4 + if cursorLineEnd > cursorLineStart + self.env['screen']['newCursor']['x'] + 3: + cursorLineEndOffset = cursorLineStart + self.env['screen']['newCursor']['x'] + 3 + oldScreenText = self.env['screen']['oldContentText'][cursorLineStartOffset:cursorLineEndOffset] + oldScreenText = re.sub(' +',' ',oldScreenText) + newScreenText = self.env['screen']['newContentText'][cursorLineStartOffset:cursorLineEndOffset] + newScreenText = re.sub(' +',' ',newScreenText) + diff = difflib.ndiff(oldScreenText, newScreenText) + typing = True + else: + diff = difflib.ndiff( oldScreenText.split('\n'),\ + newScreenText.split('\n')) + + diffList = list(diff) + + if self.env['runtime']['settingsManager'].getSetting('general', 'newLinePause') and not typing: + self.env['screen']['newDelta'] = '\n'.join(x[2:] for x in diffList if x[0] == '+') + else: + self.env['screen']['newDelta'] = ''.join(x[2:] for x in diffList if x[0] == '+') + self.env['screen']['newNegativeDelta'] = ''.join(x[2:] for x in diffList if x[0] == '-') + + # track highlighted + if self.env['screen']['oldContentAttrib'] != self.env['screen']['newContentAttrib']: + if self.env['runtime']['settingsManager'].getSettingAsBool('focus', 'highlight'): + self.env['screen']['newAttribDelta'], self.env['screen']['newCursorAttrib'] = screen_utils.trackHighlights(self.env['screen']['oldContentAttrib'], self.env['screen']['newContentAttrib'], self.env['screen']['newContentText'], self.env['screen']['columns']) + diff --git a/src/fenrir/soundDriver/dummy.py b/src/fenrir/soundDriver/dummy.py deleted file mode 100644 index 499730d..0000000 --- a/src/fenrir/soundDriver/dummy.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from core import debug - -class driver(): - def __init__(self): - self.volume = None - self._initialized = False - def initialize(self, environment): - self.env = environment - def shutdown(self): - if not self._initialized: - return - self.cancel() - def playFrequence(self, frequence = 1000, duration = 0.3, adjustVolume = 0): - if not self._initialized: - return - if interrupt: - self.cancel() - def playSoundFile(self, filePath, interrupt = True): - if not self._initialized: - return - if interrupt: - self.cancel() - def cancel(self): - if not self._initialized: - return - def setCallback(self, callback): - if not self._initialized: - return - def setVolume(self, volume): - if not self._initialized: - return - self.volume = volume diff --git a/src/fenrir/soundDriver/dummyDriver.py b/src/fenrir/soundDriver/dummyDriver.py new file mode 100644 index 0000000..4b9079c --- /dev/null +++ b/src/fenrir/soundDriver/dummyDriver.py @@ -0,0 +1,55 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class driver(): + def __init__(self): + self.volume = None + self._initialized = False + + def initialize(self, environment): + self.env = environment + self._initialized = True + print('SoundDummyDriver: Initialize') + + def shutdown(self): + if not self._initialized: + return + self.cancel() + print('SoundDummyDriver: Shutdown') + + def playFrequence(self, frequence = 1000, duration = 0.3, adjustVolume = 0): + if not self._initialized: + return + if interrupt: + self.cancel() + print('SoundDummyDriver: playFrequence:' + ' freq:' + str(frequence) + ' duration:' + str(duration) + ' adjustVolume:' + str(adjustVolume) ) + print('SoundDummyDriver: -----------------------------------') + + def playSoundFile(self, filePath, interrupt = True): + if not self._initialized: + return + if interrupt: + self.cancel() + print('SoundDummyDriver: playSoundFile:' + str(filePath)) + print('SoundDummyDriver: -----------------------------------') + + def cancel(self): + if not self._initialized: + return + print('SoundDummyDriver: Cancel') + + def setCallback(self, callback): + if not self._initialized: + return + print('SoundDummyDriver: setCallback') + + def setVolume(self, volume): + if not self._initialized: + return + self.volume = volume + print('SoundDummyDriver: setVolume:' + str(self.volume)) diff --git a/src/fenrir/soundDriver/generic.py b/src/fenrir/soundDriver/generic.py deleted file mode 100644 index cea0c16..0000000 --- a/src/fenrir/soundDriver/generic.py +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from core import debug -import subprocess - -class driver(): - def __init__(self): - self.proc = None - self.volume = 1.0 - self.soundType = '' - self.soundFileCommand = '' - self.frequenceCommand = '' - self._initialized = False - def initialize(self, environment): - self.env = environment - self.soundFileCommand = self.env['runtime']['settingsManager'].getSetting('sound', 'genericPlayFileCommand') - self.frequenceCommand = self.env['runtime']['settingsManager'].getSetting('sound', 'genericFrequencyCommand') - if self.soundFileCommand == '': - self.soundFileCommand = 'play -q -v fenrirVolume fenrirSoundFile' - if self.frequenceCommand == '': - self.frequenceCommand = 'play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence' - self._initialized = True - def shutdown(self): - if not self._initialized: - return - self.cancel() - def playFrequence(self, frequence = 1000, duration = 0.3, adjustVolume = 0): - if not self._initialized: - return - if interrupt: - self.cancel() - popenFrequenceCommand = self.frequenceCommand.replace('fenrirVolume', str(self.volume + adjustVolume )) - popenFrequenceCommand = popenFrequenceCommand.replace('fenrirFreqDuration', str(duration)) - popenFrequenceCommand = popenFrequenceCommand.replace('fenrirFrequence', str(frequence)) - self.proc = subprocess.Popen(popenFrequenceCommand, shell=True) - self.soundType = 'frequence' - def playSoundFile(self, filePath, interrupt = True): - if not self._initialized: - return - if interrupt: - self.cancel() - popenSoundFileCommand = self.soundFileCommand.replace('fenrirVolume', str(self.volume )) - popenSoundFileCommand = popenSoundFileCommand.replace('fenrirSoundFile', filePath) - self.proc = subprocess.Popen(popenSoundFileCommand, shell=True) - self.soundType = 'file' - def cancel(self): - if not self._initialized: - return - if self.soundType == '': - return - if self.soundType == 'file': - self.proc.kill() - if self.soundType == 'frequence': - self.proc.kill() - self.soundType = '' - def setCallback(self, callback): - if not self._initialized: - return - def setVolume(self, volume): - if not self._initialized: - return - self.volume = volume diff --git a/src/fenrir/soundDriver/genericDriver.py b/src/fenrir/soundDriver/genericDriver.py new file mode 100644 index 0000000..cea0c16 --- /dev/null +++ b/src/fenrir/soundDriver/genericDriver.py @@ -0,0 +1,66 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +import subprocess + +class driver(): + def __init__(self): + self.proc = None + self.volume = 1.0 + self.soundType = '' + self.soundFileCommand = '' + self.frequenceCommand = '' + self._initialized = False + def initialize(self, environment): + self.env = environment + self.soundFileCommand = self.env['runtime']['settingsManager'].getSetting('sound', 'genericPlayFileCommand') + self.frequenceCommand = self.env['runtime']['settingsManager'].getSetting('sound', 'genericFrequencyCommand') + if self.soundFileCommand == '': + self.soundFileCommand = 'play -q -v fenrirVolume fenrirSoundFile' + if self.frequenceCommand == '': + self.frequenceCommand = 'play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence' + self._initialized = True + def shutdown(self): + if not self._initialized: + return + self.cancel() + def playFrequence(self, frequence = 1000, duration = 0.3, adjustVolume = 0): + if not self._initialized: + return + if interrupt: + self.cancel() + popenFrequenceCommand = self.frequenceCommand.replace('fenrirVolume', str(self.volume + adjustVolume )) + popenFrequenceCommand = popenFrequenceCommand.replace('fenrirFreqDuration', str(duration)) + popenFrequenceCommand = popenFrequenceCommand.replace('fenrirFrequence', str(frequence)) + self.proc = subprocess.Popen(popenFrequenceCommand, shell=True) + self.soundType = 'frequence' + def playSoundFile(self, filePath, interrupt = True): + if not self._initialized: + return + if interrupt: + self.cancel() + popenSoundFileCommand = self.soundFileCommand.replace('fenrirVolume', str(self.volume )) + popenSoundFileCommand = popenSoundFileCommand.replace('fenrirSoundFile', filePath) + self.proc = subprocess.Popen(popenSoundFileCommand, shell=True) + self.soundType = 'file' + def cancel(self): + if not self._initialized: + return + if self.soundType == '': + return + if self.soundType == 'file': + self.proc.kill() + if self.soundType == 'frequence': + self.proc.kill() + self.soundType = '' + def setCallback(self, callback): + if not self._initialized: + return + def setVolume(self, volume): + if not self._initialized: + return + self.volume = volume diff --git a/src/fenrir/soundDriver/gstreamer.py b/src/fenrir/soundDriver/gstreamer.py deleted file mode 100644 index b7ed86a..0000000 --- a/src/fenrir/soundDriver/gstreamer.py +++ /dev/null @@ -1,121 +0,0 @@ -#!/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. - -from core import debug -import time, threading - - -_gstreamerAvailable = False -try: - import gi - from gi.repository import GLib - gi.require_version('Gst', '1.0') - from gi.repository import Gst - _gstreamerAvailable, args = Gst.init_check(None) -except Exception as e: - _gstreamerAvailable = False - _availableError = str(e) - -class driver: - def __init__(self): - self._source = None - self._sink = None - self.volume = 1 - self._initialized = False - - def initialize(self, environment): - self.env = environment - global _gstreamerAvailable - self._initialized = _gstreamerAvailable - if not self._initialized: - global _availableError - self.environment['runtime']['debug'].writeDebugOut('Gstreamer not available ' + _availableError,debug.debugLevel.ERROR) - return - self._player = Gst.ElementFactory.make('playbin', 'player') - bus = self._player.get_bus() - bus.add_signal_watch() - bus.connect("message", self._onPlayerMessage) - - self._pipeline = Gst.Pipeline(name='fenrir-pipeline') - bus = self._pipeline.get_bus() - bus.add_signal_watch() - bus.connect("message", self._onPipelineMessage) - - self._source = Gst.ElementFactory.make('audiotestsrc', 'src') - self._sink = Gst.ElementFactory.make('autoaudiosink', 'output') - self._pipeline.add(self._source) - self._pipeline.add(self._sink) - self._source.link(self._sink) - self.mainloop = GLib.MainLoop() - self.thread = threading.Thread(target=self.mainloop.run) - self.thread.start() - - def shutdown(self): - if not self._initialized: - return - self.cancel() - self.mainloop.quit() - - def _onPlayerMessage(self, bus, message): - if not self._initialized: - return - if message.type == Gst.MessageType.EOS: - self._player.set_state(Gst.State.NULL) - elif message.type == Gst.MessageType.ERROR: - self._player.set_state(Gst.State.NULL) - error, info = message.parse_error() - self.env['runtime']['debug'].writeDebugOut('GSTREAMER: _onPlayerMessage'+ str(error) + str(info),debug.debugLevel.WARNING) - - def _onPipelineMessage(self, bus, message): - if not self._initialized: - return - if message.type == Gst.MessageType.EOS: - self._pipeline.set_state(Gst.State.NULL) - elif message.type == Gst.MessageType.ERROR: - self._pipeline.set_state(Gst.State.NULL) - error, info = message.parse_error() - self.env['runtime']['debug'].writeDebugOut('GSTREAMER: _onPipelineMessage'+ str(error) + str(info),debug.debugLevel.WARNING) - - def _onTimeout(self, element): - if not self._initialized: - return - element.set_state(Gst.State.NULL) - - def playSoundFile(self, fileName, interrupt=True): - if not self._initialized: - return - if interrupt: - self.cancel() - self._player.set_property('uri', 'file://%s' % fileName) - self._player.set_state(Gst.State.PLAYING) - - def playFrequence(self, frequence, duration, adjustVolume, interrupt=True): - if not self._initialized: - return - if interrupt: - self.cancel() - self._source.set_property('volume', tone.volume) - self._source.set_property('freq', tone.frequency) - self._source.set_property('wave', tone.wave) - self._pipeline.set_state(Gst.State.PLAYING) - duration = int(1000 * tone.duration) - GLib.timeout_add(duration, self._onTimeout, self._pipeline) - - def cancel(self, element=None): - if not self._initialized: - return - if element: - element.set_state(Gst.State.NULL) - return - self._player.set_state(Gst.State.NULL) - self._pipeline.set_state(Gst.State.NULL) - def setVolume(self, volume): - if not self._initialized: - return - self.volume = volume - - - diff --git a/src/fenrir/soundDriver/gstreamerDriver.py b/src/fenrir/soundDriver/gstreamerDriver.py new file mode 100644 index 0000000..b7ed86a --- /dev/null +++ b/src/fenrir/soundDriver/gstreamerDriver.py @@ -0,0 +1,121 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +import time, threading + + +_gstreamerAvailable = False +try: + import gi + from gi.repository import GLib + gi.require_version('Gst', '1.0') + from gi.repository import Gst + _gstreamerAvailable, args = Gst.init_check(None) +except Exception as e: + _gstreamerAvailable = False + _availableError = str(e) + +class driver: + def __init__(self): + self._source = None + self._sink = None + self.volume = 1 + self._initialized = False + + def initialize(self, environment): + self.env = environment + global _gstreamerAvailable + self._initialized = _gstreamerAvailable + if not self._initialized: + global _availableError + self.environment['runtime']['debug'].writeDebugOut('Gstreamer not available ' + _availableError,debug.debugLevel.ERROR) + return + self._player = Gst.ElementFactory.make('playbin', 'player') + bus = self._player.get_bus() + bus.add_signal_watch() + bus.connect("message", self._onPlayerMessage) + + self._pipeline = Gst.Pipeline(name='fenrir-pipeline') + bus = self._pipeline.get_bus() + bus.add_signal_watch() + bus.connect("message", self._onPipelineMessage) + + self._source = Gst.ElementFactory.make('audiotestsrc', 'src') + self._sink = Gst.ElementFactory.make('autoaudiosink', 'output') + self._pipeline.add(self._source) + self._pipeline.add(self._sink) + self._source.link(self._sink) + self.mainloop = GLib.MainLoop() + self.thread = threading.Thread(target=self.mainloop.run) + self.thread.start() + + def shutdown(self): + if not self._initialized: + return + self.cancel() + self.mainloop.quit() + + def _onPlayerMessage(self, bus, message): + if not self._initialized: + return + if message.type == Gst.MessageType.EOS: + self._player.set_state(Gst.State.NULL) + elif message.type == Gst.MessageType.ERROR: + self._player.set_state(Gst.State.NULL) + error, info = message.parse_error() + self.env['runtime']['debug'].writeDebugOut('GSTREAMER: _onPlayerMessage'+ str(error) + str(info),debug.debugLevel.WARNING) + + def _onPipelineMessage(self, bus, message): + if not self._initialized: + return + if message.type == Gst.MessageType.EOS: + self._pipeline.set_state(Gst.State.NULL) + elif message.type == Gst.MessageType.ERROR: + self._pipeline.set_state(Gst.State.NULL) + error, info = message.parse_error() + self.env['runtime']['debug'].writeDebugOut('GSTREAMER: _onPipelineMessage'+ str(error) + str(info),debug.debugLevel.WARNING) + + def _onTimeout(self, element): + if not self._initialized: + return + element.set_state(Gst.State.NULL) + + def playSoundFile(self, fileName, interrupt=True): + if not self._initialized: + return + if interrupt: + self.cancel() + self._player.set_property('uri', 'file://%s' % fileName) + self._player.set_state(Gst.State.PLAYING) + + def playFrequence(self, frequence, duration, adjustVolume, interrupt=True): + if not self._initialized: + return + if interrupt: + self.cancel() + self._source.set_property('volume', tone.volume) + self._source.set_property('freq', tone.frequency) + self._source.set_property('wave', tone.wave) + self._pipeline.set_state(Gst.State.PLAYING) + duration = int(1000 * tone.duration) + GLib.timeout_add(duration, self._onTimeout, self._pipeline) + + def cancel(self, element=None): + if not self._initialized: + return + if element: + element.set_state(Gst.State.NULL) + return + self._player.set_state(Gst.State.NULL) + self._pipeline.set_state(Gst.State.NULL) + def setVolume(self, volume): + if not self._initialized: + return + self.volume = volume + + + diff --git a/src/fenrir/speechDriver/dummy.py b/src/fenrir/speechDriver/dummy.py deleted file mode 100644 index 085a07d..0000000 --- a/src/fenrir/speechDriver/dummy.py +++ /dev/null @@ -1,67 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. -# generic driver - -from core import debug - -class driver(): - def __init__(self): - pass - def initialize(self, environment): - self._isInitialized = False - self.env = environment - def shutdown(self): - pass - - def speak(self,text, queueable=True): - if not self._isInitialized: - return False - if not queueable: - self.cancel() - return True - - def cancel(self): - if not self._isInitialized: - return False - return True - - def setCallback(self, callback): - pass - - def clear_buffer(self): - if not self._isInitialized: - return False - return True - - def setVoice(self, voice): - if not self._isInitialized: - return False - return True - - def setPitch(self, pitch): - if not self._isInitialized: - return False - return True - - def setRate(self, rate): - if not self._isInitialized: - return False - return True - - def setModule(self, module): - if not self._isInitialized: - return False - return True - - def setLanguage(self, language): - if not self._isInitialized: - return False - return True - - def setVolume(self, volume): - if not self._isInitialized: - return False - return True diff --git a/src/fenrir/speechDriver/dummyDriver.py b/src/fenrir/speechDriver/dummyDriver.py new file mode 100644 index 0000000..312b375 --- /dev/null +++ b/src/fenrir/speechDriver/dummyDriver.py @@ -0,0 +1,70 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. +# generic driver + +from core import debug + +class driver(): + def __init__(self): + pass + def initialize(self, environment): + self._isInitialized = True + self.env = environment + print('SpeechDummyDriver: Iitialize') + + def shutdown(self): + print('SpeechDummyDriver: Shutdown') + + def speak(self,text, queueable=True): + if not self._isInitialized: + return + if not queueable: + self.cancel() + print('SpeechDummyDriver: Speak:'+text) + print('SpeechDummyDriver: -----------------------------------') + + def cancel(self): + if not self._isInitialized: + return + print('SpeechDummyDriver: Cancel') + + def setCallback(self, callback): + print('SpeechDummyDriver: setCallback') + + def clear_buffer(self): + if not self._isInitialized: + return + print('SpeechDummyDriver: clear_buffer') + + def setVoice(self, voice): + if not self._isInitialized: + return + print('SpeechDummyDriver: setVoice:' + str(voice)) + + def setPitch(self, pitch): + if not self._isInitialized: + return + print('SpeechDummyDriver: setPitch:' + str(pitch)) + + def setRate(self, rate): + if not self._isInitialized: + return + print('SpeechDummyDriver: setRate:' + str(rate)) + + def setModule(self, module): + if not self._isInitialized: + return + print('SpeechDummyDriver: setModule:' + str(module)) + + def setLanguage(self, language): + if not self._isInitialized: + return + print('SpeechDummyDriver: setLanguage:' + str(language)) + + def setVolume(self, volume): + if not self._isInitialized: + return + print('SpeechDummyDriver: setVolume:' + str(volume)) diff --git a/src/fenrir/speechDriver/emacspeakDriver.py b/src/fenrir/speechDriver/emacspeakDriver.py new file mode 100644 index 0000000..9139b33 --- /dev/null +++ b/src/fenrir/speechDriver/emacspeakDriver.py @@ -0,0 +1,87 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. +# generic driver + +from core import debug +from subprocess import Popen, PIPE +import pexpect +import sys +import time + +class driver(): + def __init__(self): + pass + def initialize(self, environment): + self._isInitialized = False + self.env = environment + try: + self.server = pexpect.spawnu('tclsh ' + self.env['runtime']['settingsManager'].getSetting('speech', 'serverPath')) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('speechDriver:initialize:' + str(e),debug.debugLevel.ERROR) + self._isInitialized = True + + def shutdown(self): + if self.server: + try: + self.server.terminate() + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('speechDriver:shutdown:self.server.terminate():' + str(e),debug.debugLevel.ERROR) + + def speak(self,text, queueable=True): + if not self._isInitialized: + return + if not queueable: + self.cancel() + try: + cleanText = text.replace('}', '\}') + cleanText = cleanText.replace('{', '\{') + cleanText = cleanText.replace('*', '\*') + cleanText = cleanText.replace('"', '\"') + cleanText = cleanText.replace('\n', ' ') + cleanText = cleanText.replace('[', '\[') + #print(text.replace('"', '\\\"')) + self.server.sendline('tts_say ' + '"' + cleanText +'"') + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('speechDriver:speak:self.server.sendline():' + str(e),debug.debugLevel.ERROR) + + def cancel(self): + if not self._isInitialized: + return + try: + self.server.sendline('s') + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('speechDriver:cancel:self.server.sendline():' + str(e),debug.debugLevel.ERROR) + + def setCallback(self, callback): + pass + + def clear_buffer(self): + if not self._isInitialized: + return + + def setVoice(self, voice): + if not self._isInitialized: + return + + def setPitch(self, pitch): + pass + + def setRate(self, rate): + if not self._isInitialized: + return + try: + self.server.sendline('tts_set_speech_rate ' + str(int(rate * 400)) + '') + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('speechDriver:setRate:self.server.sendline():' + str(e),debug.debugLevel.ERROR) + + def setModule(self, module): + pass + def setLanguage(self, language): + if not self._isInitialized: + return + self.server.sendline('set_lang ' + language + '') + def setVolume(self, volume): + pass diff --git a/src/fenrir/speechDriver/espeak.py b/src/fenrir/speechDriver/espeak.py deleted file mode 100644 index 71f933a..0000000 --- a/src/fenrir/speechDriver/espeak.py +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. -# Espeak driver - -from core import debug - -class driver(): - def __init__(self): - self._es = None - self._isInitialized = False - - def initialize(self, environment): - self.env = environment - try: - from espeak import espeak - self._es = espeak - self._isInitialized = True - except Exception as e: - self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) - self._initialized = False - - def shutdown(self): - pass - - def speak(self,text, interrupt=True): - if not self._isInitialized: - return False - if not interrupt: - self.cancel() - self._es.synth(text) - return True - - def cancel(self): - if not self._isInitialized: - return False - self._es.cancel() - return True - - def setCallback(self, callback): - pass - - def clear_buffer(self): - if not self._isInitialized: - return False - return True - - def setVoice(self, voice): - if not self._isInitialized: - return False - if voice =='': - return False - return self._es.set_voice(voice) - - def setPitch(self, pitch): - if not self._isInitialized: - return False - return self._es.set_parameter(self._es.Parameter().Pitch, int(pitch * 99)) - - def setRate(self, rate): - if not self._isInitialized: - return False - return self._es.set_parameter(self._es.Parameter().Rate, int(rate * 500 + 100)) - - def setModule(self, module): - if not self._isInitialized: - return False - - def setLanguage(self, language): - if not self._isInitialized: - return False - if language =='': - return False - return self._es.set_voice(language) - - def setVolume(self, volume): - if not self._isInitialized: - return False - return self._es.set_parameter(self._es.Parameter().Volume, int(volume * 200)) diff --git a/src/fenrir/speechDriver/espeakDriver.py b/src/fenrir/speechDriver/espeakDriver.py new file mode 100644 index 0000000..5767c3e --- /dev/null +++ b/src/fenrir/speechDriver/espeakDriver.py @@ -0,0 +1,79 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. +# Espeak driver + +from core import debug + +class driver(): + def __init__(self): + self._es = None + self._isInitialized = False + + def initialize(self, environment): + self.env = environment + try: + from espeak import espeak + self._es = espeak + self._isInitialized = True + except Exception as e: + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + self._initialized = False + + def shutdown(self): + pass + + def speak(self,text, interrupt=True): + if not self._isInitialized: + return + if not interrupt: + self.cancel() + self._es.synth(text) + + def cancel(self): + if not self._isInitialized: + return False + self._es.cancel() + return True + + def setCallback(self, callback): + pass + + def clear_buffer(self): + if not self._isInitialized: + return + + def setVoice(self, voice): + if not self._isInitialized: + return + if voice =='': + return + return self._es.set_voice(voice) + + def setPitch(self, pitch): + if not self._isInitialized: + return + return self._es.set_parameter(self._es.Parameter().Pitch, int(pitch * 99)) + + def setRate(self, rate): + if not self._isInitialized: + return + return self._es.set_parameter(self._es.Parameter().Rate, int(rate * 500 + 100)) + + def setModule(self, module): + if not self._isInitialized: + return + + def setLanguage(self, language): + if not self._isInitialized: + return + if language =='': + return + return self._es.set_voice(language) + + def setVolume(self, volume): + if not self._isInitialized: + return + return self._es.set_parameter(self._es.Parameter().Volume, int(volume * 200)) diff --git a/src/fenrir/speechDriver/genericDriver.py b/src/fenrir/speechDriver/genericDriver.py new file mode 100644 index 0000000..0a0912f --- /dev/null +++ b/src/fenrir/speechDriver/genericDriver.py @@ -0,0 +1,168 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. +# generic driver + +from core import debug +from threading import Thread, Lock +from queue import Queue, Empty +from subprocess import Popen + +class speakQueue(Queue): + def clear(self): + try: + while True: + self.get_nowait() + except Empty: + pass + +class driver(): + def __init__(self): + self.proc = None + self.speechThread = Thread(target=self.worker) + self.lock = Lock() + self.textQueue = speakQueue() + self.volume = '' + self.rate = '' + self.pitch = '' + self.module = '' + self.language = '' + self.voice = '' + def initialize(self, environment): + self.env = environment + self.minVolume = self.env['runtime']['settingsManager'].getSettingAsInt('speech', 'fenrirMinVolume') + self.maxVolume = self.env['runtime']['settingsManager'].getSettingAsInt('speech', 'fenrirMaxVolume') + self.minPitch = self.env['runtime']['settingsManager'].getSettingAsInt('speech', 'fenrirMinPitch') + self.maxPitch = self.env['runtime']['settingsManager'].getSettingAsInt('speech', 'fenrirMaxPitch') + self.minRate = self.env['runtime']['settingsManager'].getSettingAsInt('speech', 'fenrirMinRate') + self.maxRate = self.env['runtime']['settingsManager'].getSettingAsInt('speech', 'fenrirMaxRate') + + self.speechCommand = self.env['runtime']['settingsManager'].getSetting('speech', 'genericSpeechCommand') + if self.speechCommand == '': + self.speechCommand = 'espeak -a fenrirVolume -s fenrirRate -p fenrirPitch -v fenrirVoice "fenrirText"' + if False: #for debugging overwrite here + #self.speechCommand = 'spd-say --wait -r 100 -i 100 "fenrirText"' + self.speechCommand = 'flite -t "fenrirText"' + + self._isInitialized = True + if self._isInitialized: + self.speechThread.start() + def shutdown(self): + if not self._isInitialized: + return + self.cancel() + self.textQueue.put(-1) + + def speak(self,text, queueable=True): + if not self._isInitialized: + return + if not queueable: + self.cancel() + utterance = { + 'text': text, + 'volume': self.volume, + 'rate': self.rate, + 'pitch': self.pitch, + 'module': self.module, + 'language': self.language, + 'voice': self.voice, + } + self.textQueue.put(utterance.copy()) + + def cancel(self): + if not self._isInitialized: + return + self.clear_buffer() + self.lock.acquire(True) + if self.proc: + try: + self.proc.terminate() + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('speechDriver:Cancel:self.proc.terminate():' + str(e),debug.debugLevel.WARNING) + try: + self.proc.kill() + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('speechDriver:Cancel:self.proc.kill():' + str(e),debug.debugLevel.WARNING) + self.proc = None + self.lock.release() + def setCallback(self, callback): + print('SpeechDummyDriver: setCallback') + + def clear_buffer(self): + if not self._isInitialized: + return + self.textQueue.clear() + + def setVoice(self, voice): + if not self._isInitialized: + return + self.voice = str(voice) + + def setPitch(self, pitch): + if not self._isInitialized: + return + self.pitch = str(self.minPitch + pitch * (self.maxPitch - self.minPitch )) + + def setRate(self, rate): + if not self._isInitialized: + return + self.rate = str(self.minRate + rate * (self.maxRate - self.minRate )) + + def setModule(self, module): + if not self._isInitialized: + return + self.module = str(module) + + def setLanguage(self, language): + if not self._isInitialized: + return + self.language = str(language) + + def setVolume(self, volume): + if not self._isInitialized: + return + self.volume = str(self.minVolume + volume * (self.maxVolume - self.minVolume )) + + def worker(self): + while True: + utterance = self.textQueue.get() + + if isinstance(utterance, int): + if utterance == -1: + return + elif not isinstance(utterance, dict): + continue + + for key in ['volume','module','language','voice','pitch','rate','text']: + if not key in utterance: + utterance[key] = '' + if not isinstance(utterance[key],str): + utterance[key] = '' + if key == 'text': + if utterance[key] == '': + continue + + popenSpeechCommand = self.speechCommand + popenSpeechCommand = popenSpeechCommand.replace('fenrirVolume', str(utterance['volume'] ).replace('"','')) + popenSpeechCommand = popenSpeechCommand.replace('fenrirModule', str(utterance['module']).replace('"','')) + popenSpeechCommand = popenSpeechCommand.replace('fenrirLanguage', str(utterance['language']).replace('"','')) + popenSpeechCommand = popenSpeechCommand.replace('fenrirVoice', str(utterance['voice']).replace('"','')) + popenSpeechCommand = popenSpeechCommand.replace('fenrirPitch', str(utterance['pitch']).replace('"','')) + popenSpeechCommand = popenSpeechCommand.replace('fenrirRate', str(utterance['rate']).replace('"','')) + popenSpeechCommand = popenSpeechCommand.replace('fenrirText', str(utterance['text']).replace('"','').replace('\n','')) + + try: + self.env['runtime']['debug'].writeDebugOut('speechDriver:worker:' + popenSpeechCommand,debug.debugLevel.INFO) + self.lock.acquire(True) + self.proc = Popen(popenSpeechCommand, shell=True) + self.lock.release() + self.proc.wait() + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('speechDriver:worker:' + str(e),debug.debugLevel.ERROR) + + self.lock.acquire(True) + self.proc = None + self.lock.release() + diff --git a/src/fenrir/speechDriver/speechd.py b/src/fenrir/speechDriver/speechd.py deleted file mode 100644 index 8a7ef85..0000000 --- a/src/fenrir/speechDriver/speechd.py +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Fenrir TTY screen reader -# By Chrys, Storm Dragon, and contributers. -# speech-dispatcher driver - -from core import debug - -class driver(): - def __init__(self): - self._sd = None - self._isInitialized = False - self._language = '' - - def initialize(self, environment): - self.env = environment - try: - import speechd - self._sd = speechd.SSIPClient('fenrir') - self._punct = speechd.PunctuationMode() - self._isInitialized = True - except Exception as e: - self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) - self._initialized = False - - def shutdown(self): - if not self._isInitialized: - return - self._isInitialized = False - self.cancel() - self._sd.close() - return - - def speak(self,text, queueable=True): - if not self._isInitialized: - self.initialize(self.env) - if not self._isInitialized: - return False - if queueable == False: self.cancel() - try: - self._sd.set_synthesis_voice(self._language) - self._sd.set_punctuation(self._punct.NONE) - except Exception as e: - self._isInitialized = False - self._sd.speak(text) - return True - - def cancel(self): - if not self._isInitialized: - return False - self._sd.cancel() - return True - - def setCallback(self, callback): - pass - - def clear_buffer(self): - if not self._isInitialized: - return False - return True - - def setVoice(self, voice): - if not self._isInitialized: - return False - try: - if voice != '': - self._sd.set_voice(voice) - return True - except: - return False - - def setPitch(self, pitch): - if not self._isInitialized: - return False - try: - self._sd.set_pitch(int(-100 + pitch * 200)) - return True - except: - return False - - def setRate(self, rate): - if not self._isInitialized: - return False - try: - self._sd.set_rate(int(-100 + rate * 200)) - return True - except: - return False - - def setModule(self, module): - if not self._isInitialized: - return False - try: - self._sd.set_output_module(module) - return True - except: - return False - - def setLanguage(self, language): - if not self._isInitialized: - return False - self._language = language - - def setVolume(self, volume): - if not self._isInitialized: - return False - self._sd.set_volume(int(-100 + volume * 200)) - diff --git a/src/fenrir/speechDriver/speechdDriver.py b/src/fenrir/speechDriver/speechdDriver.py new file mode 100644 index 0000000..f592bbb --- /dev/null +++ b/src/fenrir/speechDriver/speechdDriver.py @@ -0,0 +1,112 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. +# speech-dispatcher driver + +from core import debug + +class driver(): + def __init__(self): + self._sd = None + self._isInitialized = False + self._language = '' + + def initialize(self, environment): + self.env = environment + try: + import speechd + self._sd = speechd.SSIPClient('fenrir') + self._punct = speechd.PunctuationMode() + self._isInitialized = True + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('speechDriver initialize:' + str(e),debug.debugLevel.ERROR) + self._initialized = False + + def shutdown(self): + if not self._isInitialized: + return + self.cancel() + try: + self._sd.close() + except: + pass + self._isInitialized = False + + def speak(self,text, queueable=True): + if not queueable: + self.cancel() + if not self._isInitialized: + self.initialize(self.env) + if not self._isInitialized: + return + try: + self._sd.set_synthesis_voice(self._language) + self._sd.set_punctuation(self._punct.NONE) + self._sd.speak(text) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('speechDriver speak:' + str(e),debug.debugLevel.ERROR) + self._isInitialized = False + + def cancel(self): + if not self._isInitialized: + return + try: + self._sd.cancel() + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('speechDriver cancel:' + str(e),debug.debugLevel.ERROR) + self._isInitialized = False + + def setCallback(self, callback): + pass + + def clear_buffer(self): + if not self._isInitialized: + return + + def setVoice(self, voice): + if not self._isInitialized: + return + try: + if voice != '': + self._sd.set_voice(voice) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('speechDriver setVoice:' + str(e),debug.debugLevel.ERROR) + + def setPitch(self, pitch): + if not self._isInitialized: + return + try: + self._sd.set_pitch(int(-100 + pitch * 200)) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('speechDriver setPitch:' + str(e),debug.debugLevel.ERROR) + + def setRate(self, rate): + if not self._isInitialized: + return + try: + self._sd.set_rate(int(-100 + rate * 200)) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('speechDriver setRate:' + str(e),debug.debugLevel.ERROR) + + def setModule(self, module): + if not self._isInitialized: + return + try: + self._sd.set_output_module(module) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('speechDriver setModule:' + str(e),debug.debugLevel.ERROR) + + def setLanguage(self, language): + if not self._isInitialized: + return + self._language = language + + def setVolume(self, volume): + if not self._isInitialized: + return + try: + self._sd.set_volume(int(-100 + volume * 200)) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('speechDriver setVolume:' + str(e),debug.debugLevel.ERROR) diff --git a/src/fenrir/utils/module_utils.py b/src/fenrir/utils/module_utils.py new file mode 100644 index 0000000..5b141e8 --- /dev/null +++ b/src/fenrir/utils/module_utils.py @@ -0,0 +1,19 @@ +#!/bin/python +# -*- coding: utf-8 -*- +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. +import sys +version = sys.version[:3] # we only need major.minor version. +if version in ["3.3","3.4"]: + from importlib.machinery import SourceFileLoader +else: # Python 3.5+, no support for python < 3.3. + import importlib.util + +def importModule(moduleName, moduleLocation): + if version in ["3.3","3.4"]: + return SourceFileLoader(moduleName, moduleLocation).load_module() + else: + spec = importlib.util.spec_from_file_location(moduleName, moduleLocation) + driver_mod = importlib.util.module_from_spec(spec) + spec.loader.exec_module(driver_mod) + return driver_mod diff --git a/src/fenrir/utils/screen_utils.py b/src/fenrir/utils/screen_utils.py index 4eb8194..267bcda 100644 --- a/src/fenrir/utils/screen_utils.py +++ b/src/fenrir/utils/screen_utils.py @@ -7,7 +7,10 @@ from core import debug from collections import Counter import string - +from select import select +from select import epoll +import select + def removeNonprintable(text): # Get the difference of all ASCII characters from the set of printable characters nonprintable = set([chr(i) for i in range(128)]).difference(string.printable) @@ -17,8 +20,18 @@ def insertNewlines(string, every=64): return '\n'.join(string[i:i+every] for i in range(0, len(string), every)) -def splitEvery(string, every=64): - return list(string[i:i+every] for i in range(0, len(string), every)) +def splitEvery(toSplit, every=64): + return list(toSplit[i:i+every] for i in range(0, len(toSplit), every)) + +def hasMoreRead(fd): + r, w, e = select([fd], [], [], 0) + return (fd in r) + +def hasMorePollPri(fd): + p = epoll() + p.register(fd, select.POLLPRI | select.POLLERR) + r = p.poll(0) + return (fd in r) def trackHighlights(oldAttr, newAttr, text, lenght): result = '' @@ -29,11 +42,13 @@ return result, currCursor if len(oldAttr) != len(newAttr): return result, currCursor + old = splitEvery(oldAttr,lenght) new = splitEvery(newAttr,lenght) textLines = text.split('\n') background = [] - if len(textLines) != len(new): + + if len(textLines) - 1 != len(new): return result, currCursor try: bgStat = Counter(newAttr).most_common(3) @@ -43,10 +58,11 @@ if bgStat[1][1] > 40: background.append(bgStat[1][0]) except Exception as e: - background.append(chr(7)) + background.append((7,7,0,0,0,0)) for line in range(len(new)): if old[line] != new[line]: for column in range(len(new[line])): + print(new[line][column]) if old[line][column] != new[line][column]: if not new[line][column] in background: if not currCursor: @@ -56,3 +72,11 @@ result += textLines[line][column] result += ' ' return result, currCursor + +''' +t = 'hallo\nwelt!' +old = ((1,1,0,0),(1,1,0,0),(1,1,0,0),(1,1,0,0),(1,1,0,0),(1,1,0,0),(1,1,0,0),(1,1,0,0),(1,1,0,0),(1,1,0,0)) +new = ((0,1,1,1),(1,1,1,1),(1,1,1,1),(1,1,1,1),(1,1,1,1),(1,1,0,0),(1,1,0,0),(1,1,0,0),(1,1,0,0),(1,1,0,0)) + +trackHighlights(old,new,t,5) +''' diff --git a/tools/configure_pulse.sh b/tools/configure_pulse.sh index fbd382f..150ded1 100755 --- a/tools/configure_pulse.sh +++ b/tools/configure_pulse.sh @@ -1,6 +1,6 @@ #!/bin/bash -# This script configures pulse to work both in the graphical invironment and in the console with root apps. +# This script configures Pulse 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 @@ -11,6 +11,7 @@ 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 echo '.include /etc/pulse/default.pa +load-module module-switch-on-connect load-module module-native-protocol-unix auth-anonymous=1 socket=/tmp/pulse.sock' > $xdgPath/pulse/default.pa echo "If you have not yet done so, please run this script as root to write the client.conf file." else @@ -66,8 +67,8 @@ # If there were no errors tell user to restart, else warn them errors happened. if [ $? -eq 0 ]; then -echo "Configuration created succeswsfully, restart pulse, or your system, for changes to take affect." +echo "Configuration created successfully, please restart Pulseaudio or your system, for changes to take affect." else -echo "Errors were encountered while writing the configuration. please correct them manually." +echo "Errors were encountered whilst writing the configuration, please correct them manually." fi exit 0 diff --git a/tools/fenrir-conf b/tools/fenrir-conf index eff1f6d..15499b5 100644 --- a/tools/fenrir-conf +++ b/tools/fenrir-conf @@ -3,7 +3,7 @@ # Get user input args are return variable, question, options get_input() { -# Variable names are long, cause I want absolutely no name conflicts. +# Variable names are long, because we want absolutely no name conflicts. local __get_input_input=$1 shift local __get_input_question="$1" @@ -42,7 +42,7 @@ fi if [ -f "$configFile" ]; then -read -p "This will replace your current settings. Press enter to continue or control+c to abort." continue +read -p "This will replace your current settings, press enter to continue or control+C to abort." continue fi get_input sound "Enable sound?" -yes no @@ -69,7 +69,7 @@ # Sox is the default. driver=$soundDriver -# Sound themes. This is the pack of sounds used for sound alerts. +# 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. @@ -80,14 +80,14 @@ volume=1.0 # shell commands for generic sound driver -# the folowing variable are substituded +# 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 frequence +# 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 frequence beep +#the following command is used for generating a frequency beep genericFrequencyCommand=play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence [speech] @@ -98,7 +98,7 @@ driver=$speechDriver -# The rate selects how fast fenrir will speak. Options range from 0, slowest, to 1.0, fastest. +# The rate selects how fast Fenrir will speak. Options range from 0, slowest, to 1.0, fastest. rate=0.45 # Pitch controls the pitch of the voice, select from 0, lowest, to 1.0, highest. @@ -109,39 +109,37 @@ # 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 ti find out which modules are available. -# The default is espeak. +# 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 chosen synthesizer. +# 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. +# 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 +#Braille is not implemented yet enabled=False driver=brlapi layout=en [screen] driver=vcsa -encoding=cp850 -screenUpdateDelay=0.05 -suspendingScreen= +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 let consume keystrokes. +# 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 @@ -154,20 +152,24 @@ wordEcho=$wordEcho # interrupt speech on any keypress interruptOnKeyPress=$enterupt -# you can filter the keys on that the speech should interrupt (empty = all keys, otherwhise the given keys) +# 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 +# define the current Fenrir key fenrirKeys=KEY_KP0,KEY_META,KEY_INSERT scriptKey=KEY_COMPOSE timeFormat=%H:%M:%P diff --git a/tools/fenrir.pot b/tools/fenrir.pot new file mode 100644 index 0000000..fa90139 --- /dev/null +++ b/tools/fenrir.pot @@ -0,0 +1,813 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR ORGANIZATION +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2017-02-26 22:19+UTC\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: pygettext.py 1.5\n" + + +#: ../src/fenrir/commands/commands/add_word_to_spell_check.py:27 +msgid "adds the current word to the exceptions dictionary" +msgstr "" + +#: ../src/fenrir/commands/commands/add_word_to_spell_check.py:34 +#: ../src/fenrir/commands/commands/remove_word_from_spell_check.py:34 +#: ../src/fenrir/commands/commands/spell_check.py:29 +#: ../src/fenrir/commands/commands/spell_check.py:36 +msgid "pyenchant is not installed" +msgstr "" + +#: ../src/fenrir/commands/commands/add_word_to_spell_check.py:49 +msgid "{0} is already in dict" +msgstr "" + +#: ../src/fenrir/commands/commands/add_word_to_spell_check.py:52 +msgid "{0} added" +msgstr "" + +#: ../src/fenrir/commands/commands/bookmark_1.py:19 +#: ../src/fenrir/commands/commands/bookmark_10.py:19 +#: ../src/fenrir/commands/commands/bookmark_2.py:19 +#: ../src/fenrir/commands/commands/bookmark_3.py:19 +#: ../src/fenrir/commands/commands/bookmark_4.py:19 +#: ../src/fenrir/commands/commands/bookmark_5.py:19 +#: ../src/fenrir/commands/commands/bookmark_6.py:19 +#: ../src/fenrir/commands/commands/bookmark_7.py:19 +#: ../src/fenrir/commands/commands/bookmark_8.py:19 +#: ../src/fenrir/commands/commands/bookmark_9.py:19 +msgid "read Bookmark {0}" +msgstr "" + +#: ../src/fenrir/commands/commands/bookmark_1.py:24 +#: ../src/fenrir/commands/commands/bookmark_10.py:24 +#: ../src/fenrir/commands/commands/bookmark_2.py:24 +#: ../src/fenrir/commands/commands/bookmark_3.py:24 +#: ../src/fenrir/commands/commands/bookmark_4.py:24 +#: ../src/fenrir/commands/commands/bookmark_5.py:24 +#: ../src/fenrir/commands/commands/bookmark_6.py:24 +#: ../src/fenrir/commands/commands/bookmark_7.py:24 +#: ../src/fenrir/commands/commands/bookmark_8.py:24 +#: ../src/fenrir/commands/commands/bookmark_9.py:24 +msgid "Bookmark {0} not set" +msgstr "" + +#: ../src/fenrir/commands/commands/bookmark_1.py:27 +#: ../src/fenrir/commands/commands/bookmark_1.py:30 +#: ../src/fenrir/commands/commands/bookmark_10.py:27 +#: ../src/fenrir/commands/commands/bookmark_10.py:30 +#: ../src/fenrir/commands/commands/bookmark_2.py:27 +#: ../src/fenrir/commands/commands/bookmark_2.py:30 +#: ../src/fenrir/commands/commands/bookmark_3.py:27 +#: ../src/fenrir/commands/commands/bookmark_3.py:30 +#: ../src/fenrir/commands/commands/bookmark_4.py:27 +#: ../src/fenrir/commands/commands/bookmark_4.py:30 +#: ../src/fenrir/commands/commands/bookmark_5.py:27 +#: ../src/fenrir/commands/commands/bookmark_5.py:30 +#: ../src/fenrir/commands/commands/bookmark_6.py:27 +#: ../src/fenrir/commands/commands/bookmark_6.py:30 +#: ../src/fenrir/commands/commands/bookmark_7.py:27 +#: ../src/fenrir/commands/commands/bookmark_7.py:30 +#: ../src/fenrir/commands/commands/bookmark_8.py:27 +#: ../src/fenrir/commands/commands/bookmark_8.py:30 +#: ../src/fenrir/commands/commands/bookmark_9.py:27 +#: ../src/fenrir/commands/commands/bookmark_9.py:30 +msgid "Bookmark for application {0} not set" +msgstr "" + +#: ../src/fenrir/commands/commands/bookmark_1.py:43 +#: ../src/fenrir/commands/commands/bookmark_10.py:43 +#: ../src/fenrir/commands/commands/bookmark_2.py:43 +#: ../src/fenrir/commands/commands/bookmark_3.py:43 +#: ../src/fenrir/commands/commands/bookmark_4.py:43 +#: ../src/fenrir/commands/commands/bookmark_5.py:43 +#: ../src/fenrir/commands/commands/bookmark_6.py:43 +#: ../src/fenrir/commands/commands/bookmark_7.py:43 +#: ../src/fenrir/commands/commands/bookmark_8.py:43 +#: ../src/fenrir/commands/commands/bookmark_9.py:43 +#: ../src/fenrir/commands/commands/curr_screen_after_cursor.py:27 +#: ../src/fenrir/commands/commands/curr_screen_before_cursor.py:30 +#: ../src/fenrir/commands/commands/cursor_read_to_end_of_line.py:27 +#: ../src/fenrir/commands/commands/indent_curr_line.py:31 +#: ../src/fenrir/commands/commands/marked_text.py:33 +#: ../src/fenrir/commands/commands/present_first_line.py:25 +#: ../src/fenrir/commands/commands/present_last_line.py:25 +#: ../src/fenrir/commands/commands/review_curr_char_phonetic.py:27 +#: ../src/fenrir/commands/commands/review_curr_line.py:27 +#: ../src/fenrir/commands/commands/review_curr_word.py:27 +#: ../src/fenrir/commands/commands/review_curr_word_phonetic.py:27 +#: ../src/fenrir/commands/commands/review_line_begin.py:27 +#: ../src/fenrir/commands/commands/review_next_line.py:29 +#: ../src/fenrir/commands/commands/review_next_word.py:29 +#: ../src/fenrir/commands/commands/review_next_word_phonetic.py:27 +#: ../src/fenrir/commands/commands/review_prev_line.py:27 +#: ../src/fenrir/commands/commands/review_prev_word.py:27 +#: ../src/fenrir/commands/commands/review_prev_word_phonetic.py:27 +#: ../src/fenrir/commands/onInput/55000-present_line_if_cursor_change_vertical.py:38 +#: ../src/fenrir/commands/onInput/72000-history.py:50 +msgid "blank" +msgstr "" + +#: ../src/fenrir/commands/commands/braille_flush.py:17 +msgid "flush the braille device if a message is written on" +msgstr "" + +#: ../src/fenrir/commands/commands/braille_pan_left.py:17 +msgid "Move braille view to the left." +msgstr "" + +#: ../src/fenrir/commands/commands/braille_pan_right.py:17 +msgid "Move braille view to the right." +msgstr "" + +#: ../src/fenrir/commands/commands/braille_return_to_cursor.py:17 +msgid "Set the braille view back to cursor." +msgstr "" + +#: ../src/fenrir/commands/commands/clear_bookmark_1.py:17 +#: ../src/fenrir/commands/commands/clear_bookmark_10.py:17 +#: ../src/fenrir/commands/commands/clear_bookmark_2.py:17 +#: ../src/fenrir/commands/commands/clear_bookmark_3.py:17 +#: ../src/fenrir/commands/commands/clear_bookmark_4.py:17 +#: ../src/fenrir/commands/commands/clear_bookmark_5.py:17 +#: ../src/fenrir/commands/commands/clear_bookmark_6.py:17 +#: ../src/fenrir/commands/commands/clear_bookmark_7.py:17 +#: ../src/fenrir/commands/commands/clear_bookmark_8.py:17 +#: ../src/fenrir/commands/commands/clear_bookmark_9.py:17 +msgid "remove Bookmark {0}" +msgstr "" + +#: ../src/fenrir/commands/commands/clear_bookmark_1.py:24 +#: ../src/fenrir/commands/commands/clear_bookmark_10.py:24 +#: ../src/fenrir/commands/commands/clear_bookmark_2.py:24 +#: ../src/fenrir/commands/commands/clear_bookmark_3.py:24 +#: ../src/fenrir/commands/commands/clear_bookmark_4.py:24 +#: ../src/fenrir/commands/commands/clear_bookmark_5.py:24 +#: ../src/fenrir/commands/commands/clear_bookmark_6.py:24 +#: ../src/fenrir/commands/commands/clear_bookmark_7.py:24 +#: ../src/fenrir/commands/commands/clear_bookmark_8.py:24 +#: ../src/fenrir/commands/commands/clear_bookmark_9.py:24 +msgid "Bookmark {0} removed for application {1}" +msgstr "" + +#: ../src/fenrir/commands/commands/clear_clipboard.py:17 +msgid "clears the currently selected clipboard" +msgstr "" + +#: ../src/fenrir/commands/commands/clear_clipboard.py:22 +msgid "clipboard cleared" +msgstr "" + +#: ../src/fenrir/commands/commands/clear_window_application.py:17 +msgid "Turn off window mode for application" +msgstr "" + +#: ../src/fenrir/commands/commands/clear_window_application.py:22 +msgid "Window Mode off for application {0}" +msgstr "" + +#: ../src/fenrir/commands/commands/clear_window_application.py:24 +msgid "Not in window Mode" +msgstr "" + +#: ../src/fenrir/commands/commands/copy_marked_to_clipboard.py:18 +msgid "copies marked text to the currently selected clipboard" +msgstr "" + +#: ../src/fenrir/commands/commands/copy_marked_to_clipboard.py:22 +msgid "one or two marks needed" +msgstr "" + +#: ../src/fenrir/commands/commands/curr_clipboard.py:17 +msgid "speaks the contents of the currently selected clipboard" +msgstr "" + +#: ../src/fenrir/commands/commands/curr_clipboard.py:21 +#: ../src/fenrir/commands/commands/export_clipboard_to_x.py:29 +#: ../src/fenrir/commands/commands/export_clipboard_to_x.py:32 +#: ../src/fenrir/commands/commands/export_clipboard_to_x.py:35 +#: ../src/fenrir/commands/commands/export_clipboard_to_x.py:38 +#: ../src/fenrir/commands/commands/first_clipboard.py:21 +#: ../src/fenrir/commands/commands/last_clipboard.py:21 +#: ../src/fenrir/commands/commands/next_clipboard.py:21 +#: ../src/fenrir/commands/commands/paste_clipboard.py:23 +#: ../src/fenrir/commands/commands/paste_clipboard.py:26 +#: ../src/fenrir/commands/commands/paste_clipboard.py:29 +#: ../src/fenrir/commands/commands/paste_clipboard.py:32 +#: ../src/fenrir/commands/commands/prev_clipboard.py:21 +msgid "clipboard empty" +msgstr "" + +#: ../src/fenrir/commands/commands/curr_screen.py:17 +msgid "reads the contents of the current screen" +msgstr "" + +#: ../src/fenrir/commands/commands/curr_screen.py:21 +msgid "screen is empty" +msgstr "" + +#: ../src/fenrir/commands/commands/curr_screen_after_cursor.py:18 +msgid "reads from the cursor to the bottom of the screen" +msgstr "" + +#: ../src/fenrir/commands/commands/curr_screen_before_cursor.py:18 +msgid "Reads from the top of the screen to the cursor position" +msgstr "" + +#: ../src/fenrir/commands/commands/cursor_column.py:17 +msgid "presents the current column number for review cursor in review mode or the text cursor if not. Starts with 1" +msgstr "" + +#: ../src/fenrir/commands/commands/cursor_lineno.py:17 +msgid "presents the current line number for review cursor in review mode or the text cursor if not. Starts with 1" +msgstr "" + +#: ../src/fenrir/commands/commands/cursor_position.py:17 +msgid "displays the position of the review cursor" +msgstr "" + +#: ../src/fenrir/commands/commands/cursor_position.py:23 +msgid "line {0}, column {1}" +msgstr "" + +#: ../src/fenrir/commands/commands/cursor_read_to_end_of_line.py:18 +msgid "read to end of line, use review cursor if you are in review mode, otherwhise use text cursor" +msgstr "" + +#: ../src/fenrir/commands/commands/date.py:18 +msgid "presents the date" +msgstr "" + +#: ../src/fenrir/commands/commands/dec_sound_volume.py:18 +msgid "decrease sound volume" +msgstr "" + +#: ../src/fenrir/commands/commands/dec_sound_volume.py:29 +#: ../src/fenrir/commands/commands/inc_sound_volume.py:29 +msgid "{0} percent sound volume" +msgstr "" + +#: ../src/fenrir/commands/commands/dec_speech_pitch.py:18 +msgid "decreases the pitch of the speech" +msgstr "" + +#: ../src/fenrir/commands/commands/dec_speech_pitch.py:27 +#: ../src/fenrir/commands/commands/inc_speech_pitch.py:27 +msgid "{0} percent speech pitch" +msgstr "" + +#: ../src/fenrir/commands/commands/dec_speech_rate.py:18 +msgid "decreases the rate of the speech" +msgstr "" + +#: ../src/fenrir/commands/commands/dec_speech_rate.py:27 +#: ../src/fenrir/commands/commands/inc_speech_rate.py:27 +msgid "{0} percent speech rate" +msgstr "" + +#: ../src/fenrir/commands/commands/dec_speech_volume.py:18 +msgid "decreases the volume of the speech" +msgstr "" + +#: ../src/fenrir/commands/commands/dec_speech_volume.py:27 +#: ../src/fenrir/commands/commands/inc_speech_volume.py:27 +msgid "{0} percent speech volume" +msgstr "" + +#: ../src/fenrir/commands/commands/exit_review.py:17 +msgid "exits review mode" +msgstr "" + +#: ../src/fenrir/commands/commands/exit_review.py:21 +msgid "Not in review mode" +msgstr "" + +#: ../src/fenrir/commands/commands/exit_review.py:25 +msgid "leave review mode" +msgstr "" + +#: ../src/fenrir/commands/commands/export_clipboard_to_x.py:21 +msgid "export the current fenrir clipboard to X clipboard" +msgstr "" + +#: ../src/fenrir/commands/commands/first_clipboard.py:17 +msgid "selects the first clipboard" +msgstr "" + +#: ../src/fenrir/commands/commands/forward_keypress.py:17 +msgid "sends the following keypress to the terminal" +msgstr "" + +#: ../src/fenrir/commands/commands/forward_keypress.py:21 +msgid "Forward next keypress" +msgstr "" + +#: ../src/fenrir/commands/commands/inc_sound_volume.py:18 +msgid "adjusts the volume for in coming sounds" +msgstr "" + +#: ../src/fenrir/commands/commands/inc_speech_pitch.py:18 +msgid "increases the pitch of the speech" +msgstr "" + +#: ../src/fenrir/commands/commands/inc_speech_rate.py:18 +msgid "increase the speech rate" +msgstr "" + +#: ../src/fenrir/commands/commands/inc_speech_volume.py:18 +msgid "increase the speech volume" +msgstr "" + +#: ../src/fenrir/commands/commands/indent_curr_line.py:18 +msgid "shows the indention level for the current line" +msgstr "" + +#: ../src/fenrir/commands/commands/indent_curr_line.py:33 +msgid "indent {0}" +msgstr "" + +#: ../src/fenrir/commands/commands/last_clipboard.py:17 +msgid "selects the last clipboard" +msgstr "" + +#: ../src/fenrir/commands/commands/last_incoming.py:17 +msgid "displays the last received text" +msgstr "" + +#: ../src/fenrir/commands/commands/marked_text.py:18 +msgid "speaks the currently selected text that will be copied to the clipboard" +msgstr "" + +#: ../src/fenrir/commands/commands/marked_text.py:23 +msgid "please set begin and endmark" +msgstr "" + +#: ../src/fenrir/commands/commands/next_clipboard.py:17 +msgid "selects the next clipboard" +msgstr "" + +#: ../src/fenrir/commands/commands/next_clipboard.py:26 +msgid "First clipboard " +msgstr "" + +#: ../src/fenrir/commands/commands/paste_clipboard.py:18 +msgid "pastes the text from the currently selected clipboard" +msgstr "" + +#: ../src/fenrir/commands/commands/present_first_line.py:18 +msgid "present first line" +msgstr "" + +#: ../src/fenrir/commands/commands/present_last_line.py:18 +#: ../src/fenrir/commands/commands/review_curr_line.py:18 +msgid "current line" +msgstr "" + +#: ../src/fenrir/commands/commands/prev_clipboard.py:17 +msgid "selects the previous clipboard" +msgstr "" + +#: ../src/fenrir/commands/commands/prev_clipboard.py:26 +msgid "Last clipboard " +msgstr "" + +#: ../src/fenrir/commands/commands/quit_fenrir.py:17 +msgid "exits Fenrir" +msgstr "" + +#: ../src/fenrir/commands/commands/remove_marks.py:17 +msgid "removes marks from selected text" +msgstr "" + +#: ../src/fenrir/commands/commands/remove_marks.py:21 +msgid "Remove marks" +msgstr "" + +#: ../src/fenrir/commands/commands/remove_word_from_spell_check.py:27 +msgid "removes the current word from the exceptions dictionary" +msgstr "" + +#: ../src/fenrir/commands/commands/remove_word_from_spell_check.py:50 +msgid "{0} is already removed from dict" +msgstr "" + +#: ../src/fenrir/commands/commands/remove_word_from_spell_check.py:53 +msgid "{0} removed" +msgstr "" + +#: ../src/fenrir/commands/commands/review_bottom.py:17 +msgid "move review to bottom of screen" +msgstr "" + +#: ../src/fenrir/commands/commands/review_bottom.py:21 +msgid "Bottom" +msgstr "" + +#: ../src/fenrir/commands/commands/review_curr_char.py:18 +msgid "presents the current character." +msgstr "" + +#: ../src/fenrir/commands/commands/review_curr_char_phonetic.py:18 +msgid "set review and phonetically presents the current character" +msgstr "" + +#: ../src/fenrir/commands/commands/review_curr_word.py:18 +msgid "current word." +msgstr "" + +#: ../src/fenrir/commands/commands/review_curr_word.py:32 +#: ../src/fenrir/commands/commands/review_curr_word_phonetic.py:36 +#: ../src/fenrir/commands/commands/review_down.py:27 +#: ../src/fenrir/commands/commands/review_next_char.py:28 +#: ../src/fenrir/commands/commands/review_next_char_phonetic.py:30 +#: ../src/fenrir/commands/commands/review_next_line.py:34 +#: ../src/fenrir/commands/commands/review_next_word.py:34 +#: ../src/fenrir/commands/commands/review_next_word_phonetic.py:36 +#: ../src/fenrir/commands/commands/review_prev_char.py:31 +#: ../src/fenrir/commands/commands/review_prev_char_phonetic.py:30 +#: ../src/fenrir/commands/commands/review_prev_line.py:32 +#: ../src/fenrir/commands/commands/review_prev_word.py:32 +#: ../src/fenrir/commands/commands/review_prev_word_phonetic.py:36 +#: ../src/fenrir/commands/commands/review_up.py:27 +msgid "end of screen" +msgstr "" + +#: ../src/fenrir/commands/commands/review_curr_word.py:35 +#: ../src/fenrir/commands/commands/review_curr_word_phonetic.py:39 +#: ../src/fenrir/commands/commands/review_next_char.py:31 +#: ../src/fenrir/commands/commands/review_next_char_phonetic.py:33 +#: ../src/fenrir/commands/commands/review_next_word.py:37 +#: ../src/fenrir/commands/commands/review_next_word_phonetic.py:39 +#: ../src/fenrir/commands/commands/review_prev_char.py:34 +#: ../src/fenrir/commands/commands/review_prev_char_phonetic.py:33 +#: ../src/fenrir/commands/commands/review_prev_word.py:35 +#: ../src/fenrir/commands/commands/review_prev_word_phonetic.py:39 +#: ../src/fenrir/commands/commands/review_up.py:30 +msgid "line break" +msgstr "" + +#: ../src/fenrir/commands/commands/review_curr_word_phonetic.py:19 +#: ../src/fenrir/commands/commands/review_next_word_phonetic.py:19 +#: ../src/fenrir/commands/commands/review_prev_word_phonetic.py:19 +msgid "phonetically spells the current word and set review to it" +msgstr "" + +#: ../src/fenrir/commands/commands/review_down.py:18 +msgid "set review cursor to char below the current char and present it." +msgstr "" + +#: ../src/fenrir/commands/commands/review_line_begin.py:18 +msgid "set review cursor to begin of current line and display the content" +msgstr "" + +#: ../src/fenrir/commands/commands/review_line_begin.py:30 +msgid "beginning of line" +msgstr "" + +#: ../src/fenrir/commands/commands/review_line_end.py:18 +#: ../src/fenrir/commands/commands/review_line_first_char.py:19 +#: ../src/fenrir/commands/commands/review_line_last_char.py:18 +msgid "set review cursor to end of current line and display the content" +msgstr "" + +#: ../src/fenrir/commands/commands/review_line_end.py:27 +msgid "end of line" +msgstr "" + +#: ../src/fenrir/commands/commands/review_line_first_char.py:26 +msgid "line is empty" +msgstr "" + +#: ../src/fenrir/commands/commands/review_line_first_char.py:33 +msgid "first char in line indent {0}" +msgstr "" + +#: ../src/fenrir/commands/commands/review_line_last_char.py:27 +msgid "last char in line" +msgstr "" + +#: ../src/fenrir/commands/commands/review_next_char.py:18 +msgid "moves review to the next character and presents it" +msgstr "" + +#: ../src/fenrir/commands/commands/review_next_char_phonetic.py:18 +msgid "phonetically presents the next character and set review to it" +msgstr "" + +#: ../src/fenrir/commands/commands/review_next_line.py:18 +msgid "moves review to the next line and presents it" +msgstr "" + +#: ../src/fenrir/commands/commands/review_next_word.py:18 +msgid "moves review to the next word and presents it" +msgstr "" + +#: ../src/fenrir/commands/commands/review_prev_char.py:18 +msgid "moves review to the previous character and presents it" +msgstr "" + +#: ../src/fenrir/commands/commands/review_prev_char_phonetic.py:18 +msgid "phonetically presents the previous character and set review to it" +msgstr "" + +#: ../src/fenrir/commands/commands/review_prev_line.py:18 +msgid "moves review to the previous line and presents it" +msgstr "" + +#: ../src/fenrir/commands/commands/review_prev_word.py:18 +msgid "moves review focus to the previous word and presents it" +msgstr "" + +#: ../src/fenrir/commands/commands/review_top.py:18 +msgid "move review to top of screen" +msgstr "" + +#: ../src/fenrir/commands/commands/review_top.py:22 +msgid "Top" +msgstr "" + +#: ../src/fenrir/commands/commands/review_up.py:18 +msgid "set review cursor to the char in the line below and present it" +msgstr "" + +#: ../src/fenrir/commands/commands/set_bookmark_1.py:18 +#: ../src/fenrir/commands/commands/set_bookmark_10.py:18 +#: ../src/fenrir/commands/commands/set_bookmark_2.py:18 +#: ../src/fenrir/commands/commands/set_bookmark_3.py:18 +#: ../src/fenrir/commands/commands/set_bookmark_4.py:18 +#: ../src/fenrir/commands/commands/set_bookmark_5.py:18 +#: ../src/fenrir/commands/commands/set_bookmark_6.py:18 +#: ../src/fenrir/commands/commands/set_bookmark_7.py:18 +#: ../src/fenrir/commands/commands/set_bookmark_8.py:18 +#: ../src/fenrir/commands/commands/set_bookmark_9.py:18 +msgid "set Bookmark {0}" +msgstr "" + +#: ../src/fenrir/commands/commands/set_bookmark_1.py:22 +#: ../src/fenrir/commands/commands/set_bookmark_10.py:22 +#: ../src/fenrir/commands/commands/set_bookmark_2.py:22 +#: ../src/fenrir/commands/commands/set_bookmark_3.py:22 +#: ../src/fenrir/commands/commands/set_bookmark_4.py:22 +#: ../src/fenrir/commands/commands/set_bookmark_5.py:22 +#: ../src/fenrir/commands/commands/set_bookmark_6.py:22 +#: ../src/fenrir/commands/commands/set_bookmark_7.py:22 +#: ../src/fenrir/commands/commands/set_bookmark_8.py:22 +#: ../src/fenrir/commands/commands/set_bookmark_9.py:22 +msgid "No Mark found" +msgstr "" + +#: ../src/fenrir/commands/commands/set_bookmark_1.py:32 +#: ../src/fenrir/commands/commands/set_bookmark_10.py:32 +#: ../src/fenrir/commands/commands/set_bookmark_2.py:32 +#: ../src/fenrir/commands/commands/set_bookmark_3.py:32 +#: ../src/fenrir/commands/commands/set_bookmark_4.py:32 +#: ../src/fenrir/commands/commands/set_bookmark_5.py:32 +#: ../src/fenrir/commands/commands/set_bookmark_6.py:32 +#: ../src/fenrir/commands/commands/set_bookmark_7.py:32 +#: ../src/fenrir/commands/commands/set_bookmark_8.py:32 +#: ../src/fenrir/commands/commands/set_bookmark_9.py:32 +msgid "Bookmark {0} set for application {1}" +msgstr "" + +#: ../src/fenrir/commands/commands/set_mark.py:17 +msgid "places marks to select text to copy to the clipboard" +msgstr "" + +#: ../src/fenrir/commands/commands/set_mark.py:21 +msgid "no review cursor" +msgstr "" + +#: ../src/fenrir/commands/commands/set_mark.py:26 +#: ../src/fenrir/commands/commands/set_mark.py:28 +msgid "set mark" +msgstr "" + +#: ../src/fenrir/commands/commands/set_window_application.py:17 +msgid "set Window Mode, needs 2 marks " +msgstr "" + +#: ../src/fenrir/commands/commands/set_window_application.py:22 +msgid "Window Mode on for application {0}" +msgstr "" + +#: ../src/fenrir/commands/commands/set_window_application.py:25 +msgid "Set window begin and end marks" +msgstr "" + +#: ../src/fenrir/commands/commands/shut_up.py:17 +msgid "interrupts the current presentation" +msgstr "" + +#: ../src/fenrir/commands/commands/spell_check.py:26 +msgid "checks the spelling of the current word" +msgstr "" + +#: ../src/fenrir/commands/commands/spell_check.py:52 +#: ../src/fenrir/commands/onInput/62000-spell_check.py:132 +msgid "misspelled" +msgstr "" + +#: ../src/fenrir/commands/commands/spell_check.py:54 +msgid "correct" +msgstr "" + +#: ../src/fenrir/commands/commands/subprocess.py:21 +msgid "script: {0} fullpath: {1}" +msgstr "" + +#: ../src/fenrir/commands/commands/subprocess.py:24 +msgid "scriptfile does not exist" +msgstr "" + +#: ../src/fenrir/commands/commands/subprocess.py:27 +msgid "scriptfile is not a file" +msgstr "" + +#: ../src/fenrir/commands/commands/subprocess.py:30 +msgid "scriptfile is not executable" +msgstr "" + +#: ../src/fenrir/commands/commands/temp_disable_speech.py:17 +#: ../src/fenrir/commands/onInput/15000-enable_temp_speech.py:17 +msgid "disables speech until next keypress" +msgstr "" + +#: ../src/fenrir/commands/commands/temp_disable_speech.py:21 +msgid "speech temporary disabled" +msgstr "" + +#: ../src/fenrir/commands/commands/time.py:18 +msgid "presents the time" +msgstr "" + +#: ../src/fenrir/commands/commands/toggle_auto_read.py:16 +msgid "enables or disables automatic reading of new text as it appears" +msgstr "" + +#: ../src/fenrir/commands/commands/toggle_auto_read.py:21 +msgid "autoread enabled" +msgstr "" + +#: ../src/fenrir/commands/commands/toggle_auto_read.py:23 +msgid "autoread disabled" +msgstr "" + +#: ../src/fenrir/commands/commands/toggle_auto_spell_check.py:17 +msgid "enables or disables automatic spell checking" +msgstr "" + +#: ../src/fenrir/commands/commands/toggle_auto_spell_check.py:22 +msgid "auto spellcheck enabled" +msgstr "" + +#: ../src/fenrir/commands/commands/toggle_auto_spell_check.py:24 +msgid "auto spellcheck disabled" +msgstr "" + +#: ../src/fenrir/commands/commands/toggle_auto_time.py:16 +msgid "enables or disables automatic reading of time after an period" +msgstr "" + +#: ../src/fenrir/commands/commands/toggle_auto_time.py:21 +msgid "autotime enabled" +msgstr "" + +#: ../src/fenrir/commands/commands/toggle_auto_time.py:23 +msgid "autotime disabled" +msgstr "" + +#: ../src/fenrir/commands/commands/toggle_braille.py:17 +msgid "enables and disables output in braille" +msgstr "" + +#: ../src/fenrir/commands/commands/toggle_braille.py:21 +msgid "braille disabled" +msgstr "" + +#: ../src/fenrir/commands/commands/toggle_braille.py:24 +msgid "braille enabled" +msgstr "" + +#: ../src/fenrir/commands/commands/toggle_emoticons.py:16 +msgid "enables or disables announcement of emoticons instead of chars" +msgstr "" + +#: ../src/fenrir/commands/commands/toggle_emoticons.py:21 +msgid "emoticons enabled" +msgstr "" + +#: ../src/fenrir/commands/commands/toggle_emoticons.py:23 +msgid "emoticons disabled" +msgstr "" + +#: ../src/fenrir/commands/commands/toggle_highlight_tracking.py:16 +#: ../src/fenrir/commands/onInput/56000-highlight_tracking.py:16 +msgid "enables or disables tracking of highlighted" +msgstr "" + +#: ../src/fenrir/commands/commands/toggle_highlight_tracking.py:24 +msgid "highlight tracking" +msgstr "" + +#: ../src/fenrir/commands/commands/toggle_highlight_tracking.py:26 +msgid "cursor tracking" +msgstr "" + +#: ../src/fenrir/commands/commands/toggle_output.py:17 +msgid "toggles all output settings" +msgstr "" + +#: ../src/fenrir/commands/commands/toggle_output.py:23 +msgid "Fenrir muted" +msgstr "" + +#: ../src/fenrir/commands/commands/toggle_output.py:31 +msgid "Fenrir unmuted" +msgstr "" + +#: ../src/fenrir/commands/commands/toggle_punctuation_level.py:23 +msgid "No punctuation found." +msgstr "" + +#: ../src/fenrir/commands/commands/toggle_sound.py:17 +msgid "enables or disables sound" +msgstr "" + +#: ../src/fenrir/commands/commands/toggle_sound.py:21 +msgid "sound disabled" +msgstr "" + +#: ../src/fenrir/commands/commands/toggle_sound.py:24 +msgid "sound enabled" +msgstr "" + +#: ../src/fenrir/commands/commands/toggle_speech.py:17 +msgid "enables or disables speech" +msgstr "" + +#: ../src/fenrir/commands/commands/toggle_speech.py:21 +msgid "speech disabled" +msgstr "" + +#: ../src/fenrir/commands/commands/toggle_speech.py:24 +#: ../src/fenrir/commands/onInput/15000-enable_temp_speech.py:28 +msgid "speech enabled" +msgstr "" + +#: ../src/fenrir/commands/commands/toggle_tutorial_mode.py:18 +msgid "You are leaving the tutorial mode. Press that shortcut again to enter the tutorial mode again." +msgstr "" + +#: ../src/fenrir/commands/commands/toggle_tutorial_mode.py:21 +msgid "you entered the tutorial mode. In that mode the commands are not executed. but you get a description of what the shortcut does. To leave the tutorial mode, press that shortcut again." +msgstr "" + +#: ../src/fenrir/commands/onInput/80000-capslock.py:22 +msgid "Capslock on" +msgstr "" + +#: ../src/fenrir/commands/onInput/80000-capslock.py:24 +msgid "Capslock off" +msgstr "" + +#: ../src/fenrir/commands/onInput/80300-scrolllock.py:22 +msgid "Scrolllock on" +msgstr "" + +#: ../src/fenrir/commands/onInput/80300-scrolllock.py:24 +msgid "Scrolllock off" +msgstr "" + +#: ../src/fenrir/commands/onInput/80500-numlock.py:22 +msgid "Numlock on" +msgstr "" + +#: ../src/fenrir/commands/onInput/80500-numlock.py:24 +msgid "Numlock off" +msgstr "" + +#: +#: ../src/fenrir/commands/onScreenChanged/80000-screen_change_announcement.py:20 +msgid "screen {0}" +msgstr "" + +#: ../src/fenrir/commands/onScreenUpdate/76000-time.py:66 +msgid "Autotime: {0}" +msgstr "" + +#: ../src/fenrir/fenrir.py:24 +msgid "Start Fenrir" +msgstr "" + +#: ../src/fenrir/fenrir.py:99 +msgid "Quit Fenrir" +msgstr "" + diff --git a/tools/generate_translations.sh b/tools/generate_translations.sh new file mode 100644 index 0000000..e881d32 --- /dev/null +++ b/tools/generate_translations.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +pygettext3 -d fenrir ../src/fenrir/*.py ../src/fenrir/*/*.py ../src/fenrir/*/*/*.py diff --git a/uninstall.sh b/uninstall.sh new file mode 100755 index 0000000..8b820fe --- /dev/null +++ b/uninstall.sh @@ -0,0 +1,23 @@ +#!/bin/bash +#Basic uninstall script for Fenrir. +cat << EOF +Fenrir is going to remove. +All scripts and settings will be lost. +EOF + +# ask +read -p "This will remove Fenrir and its settings from your system,, press ctrl+C to cancel, or enter to continue." continue + +# do it +unlink /usr/bin/fenrir +unlink /usr/bin/fenrir-daemon +rm -rf /opt/fenrir +rm -rf /usr/share/fenrir +rm -rf /etc/fenrir +rm -rf /usr/share/sounds/fenrir +rm -f /usr/lib/systemd/system/fenrir.service + +# success message +cat << EOF +Fenrir has been successfully removed from your system. +EOF