sync with master
This commit is contained in:
commit
ad8589d9a5
@ -21,6 +21,7 @@ ReadWrite permission
|
|||||||
- brltty, python-brlapi [using braille] # (not implemented yet)
|
- brltty, python-brlapi [using braille] # (not implemented yet)
|
||||||
- gstreamer [soundicons via gstreamer] # not working yet
|
- gstreamer [soundicons via gstreamer] # not working yet
|
||||||
- python-pyenchant [spell check functionality]
|
- python-pyenchant [spell check functionality]
|
||||||
|
- aspell-<language> [your languagedata for spellchecker, english support "aspell-en"]
|
||||||
- python-daemonize [use fenrir as background service on Unix like systems]
|
- python-daemonize [use fenrir as background service on Unix like systems]
|
||||||
|
|
||||||
# installation
|
# installation
|
||||||
|
50
TODO
50
TODO
@ -7,8 +7,19 @@ ToDos in Priority order:
|
|||||||
For example, in screen, it just tells me bell in window, but doesn't tell me which one. (southernprince)
|
For example, in screen, it just tells me bell in window, but doesn't tell me which one. (southernprince)
|
||||||
in special cases next word skipps a word, "word<12 spaces>word2<12 spaces>word3 (storm_dragon)
|
in special cases next word skipps a word, "word<12 spaces>word2<12 spaces>word3 (storm_dragon)
|
||||||
spellcheck triggers twice if there are two spaces after an word and you arrow over them
|
spellcheck triggers twice if there are two spaces after an word and you arrow over them
|
||||||
|
fenrir is not able to detect the current application inside of screen.
|
||||||
|
|
||||||
- replace beep with a digital equivalent
|
- implement onScreenUpdate commands
|
||||||
|
read highlighted text mode
|
||||||
|
|
||||||
|
- implement commands
|
||||||
|
attributes_curr_char
|
||||||
|
generic list command (convert clipboard management)
|
||||||
|
next item
|
||||||
|
pref item
|
||||||
|
curr item
|
||||||
|
first item
|
||||||
|
last item
|
||||||
|
|
||||||
- implement braille
|
- implement braille
|
||||||
output to braille device
|
output to braille device
|
||||||
@ -26,35 +37,14 @@ http://mielke.cc/brltty/doc/Manual-BrlAPI/English/BrlAPI.html
|
|||||||
https://git.gnome.org/browse/orca/tree/src/orca/braille.py
|
https://git.gnome.org/browse/orca/tree/src/orca/braille.py
|
||||||
https://wiki.gnome.org/Attic/LSR/ScratchPad/Braille/BrlAPI
|
https://wiki.gnome.org/Attic/LSR/ScratchPad/Braille/BrlAPI
|
||||||
|
|
||||||
|
- implement autodetection of plugged and removed input devices (python-pyudev)
|
||||||
|
http://askubuntu.com/questions/508236/how-can-i-run-code-whenever-a-usb-device-is-unplugged-without-requiring-root
|
||||||
|
|
||||||
- add perApplicationTrigger trigger
|
- add perApplicationTrigger trigger
|
||||||
per application commands
|
per application commands
|
||||||
per application onScreenChange
|
per application onScreenChange
|
||||||
per application onInput
|
per application onInput
|
||||||
- per application shortcuts
|
- per application shortcuts
|
||||||
- implement commands
|
|
||||||
next_char_phonetic
|
|
||||||
prev_char_phonetic
|
|
||||||
next_word_phonetic
|
|
||||||
prev_word_phonetic
|
|
||||||
attributes_curr_char
|
|
||||||
|
|
||||||
toggle_highlighted_mode
|
|
||||||
generic list command (convert clipboard management)
|
|
||||||
next item
|
|
||||||
pref item
|
|
||||||
curr item
|
|
||||||
first item
|
|
||||||
last item
|
|
||||||
|
|
||||||
- implement onScreenUpdate commands
|
|
||||||
read highlighted text mode
|
|
||||||
- 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
|
|
||||||
|
|
||||||
- implement autodetection of plugged and removed input devices (python-pyudev)
|
|
||||||
http://askubuntu.com/questions/508236/how-can-i-run-code-whenever-a-usb-device-is-unplugged-without-requiring-root
|
|
||||||
|
|
||||||
- configuration should be overwriteable with parameter and alternative paths
|
- configuration should be overwriteable with parameter and alternative paths
|
||||||
- write settings
|
- write settings
|
||||||
- menue for settings configuration #storm
|
- menue for settings configuration #storm
|
||||||
@ -201,6 +191,11 @@ ps a -o tty,comm | grep -e Xorg | grep -v "grep -e Xorg"
|
|||||||
"papa", "quebec", "romeo", "sierra", "tango",
|
"papa", "quebec", "romeo", "sierra", "tango",
|
||||||
"uniform", "victor", "whisky", "x ray",
|
"uniform", "victor", "whisky", "x ray",
|
||||||
"yankee", "zulu"
|
"yankee", "zulu"
|
||||||
|
next_char_phonetic
|
||||||
|
prev_char_phonetic
|
||||||
|
next_word_phonetic
|
||||||
|
prev_word_phonetic
|
||||||
|
toggle_highlighted_mode
|
||||||
|
|
||||||
- implement onInput commands
|
- implement onInput commands
|
||||||
read_line_if_cursor_change_vertical (needed if you arrow up and down, we want to announce the line)
|
read_line_if_cursor_change_vertical (needed if you arrow up and down, we want to announce the line)
|
||||||
@ -208,6 +203,7 @@ ps a -o tty,comm | grep -e Xorg | grep -v "grep -e Xorg"
|
|||||||
echo_char (echos the last char on pressing space or return)
|
echo_char (echos the last char on pressing space or return)
|
||||||
echo_word (echos the last word)
|
echo_word (echos the last word)
|
||||||
echo_deleted_char (echos deleted char on screen
|
echo_deleted_char (echos deleted char on screen
|
||||||
|
read highlighted
|
||||||
|
|
||||||
- implement onScreenChange commands
|
- implement onScreenChange commands
|
||||||
promoted text
|
promoted text
|
||||||
@ -256,3 +252,7 @@ https://web.archive.org/web/20131017130434/http://www.jejik.com/articles/2007/02
|
|||||||
- announce capslock
|
- announce capslock
|
||||||
- anounce numlock
|
- anounce numlock
|
||||||
- anounce scroll
|
- 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
|
||||||
|
@ -75,6 +75,7 @@ KEY_FENRIR,KEY_RIGHTBRACE=toggle_auto_spell_check
|
|||||||
KEY_FENRIR,KEY_BACKSLASH=toggle_output
|
KEY_FENRIR,KEY_BACKSLASH=toggle_output
|
||||||
KEY_FENRIR,KEY_CTRL,KEY_E=toggle_emoticons
|
KEY_FENRIR,KEY_CTRL,KEY_E=toggle_emoticons
|
||||||
key_FENRIR,KEY_KPENTER=toggle_auto_read
|
key_FENRIR,KEY_KPENTER=toggle_auto_read
|
||||||
|
KEY_FENRIR,KEY_KPASTERISK=toggle_highlight_tracking
|
||||||
KEY_FENRIR,KEY_Q=quit_fenrir
|
KEY_FENRIR,KEY_Q=quit_fenrir
|
||||||
KEY_FENRIR,KEY_T=time
|
KEY_FENRIR,KEY_T=time
|
||||||
2,KEY_FENRIR,KEY_T=date
|
2,KEY_FENRIR,KEY_T=date
|
||||||
|
@ -75,6 +75,7 @@ KEY_FENRIR,KEY_RIGHTBRACE=toggle_auto_spell_check
|
|||||||
KEY_FENRIR,KEY_SHIFT,KEY_ENTER=toggle_output
|
KEY_FENRIR,KEY_SHIFT,KEY_ENTER=toggle_output
|
||||||
KEY_FENRIR,KEY_SHIFT,KEY_E=toggle_emoticons
|
KEY_FENRIR,KEY_SHIFT,KEY_E=toggle_emoticons
|
||||||
KEY_FENRIR,KEY_ENTER=toggle_auto_read
|
KEY_FENRIR,KEY_ENTER=toggle_auto_read
|
||||||
|
KEY_FENRIR,KEY_Y=toggle_highlight_tracking
|
||||||
KEY_FENRIR,KEY_Q=quit_fenrir
|
KEY_FENRIR,KEY_Q=quit_fenrir
|
||||||
KEY_FENRIR,KEY_T=time
|
KEY_FENRIR,KEY_T=time
|
||||||
2,KEY_FENRIR,KEY_T=date
|
2,KEY_FENRIR,KEY_T=date
|
||||||
|
@ -75,6 +75,7 @@ KEY_FENRIR,KEY_RIGHTBRACE=toggle_auto_spell_check
|
|||||||
KEY_FENRIR,KEY_BACKSLASH=toggle_output
|
KEY_FENRIR,KEY_BACKSLASH=toggle_output
|
||||||
#=toggle_emoticons
|
#=toggle_emoticons
|
||||||
key_FENRIR,KEY_KPENTER=toggle_auto_read
|
key_FENRIR,KEY_KPENTER=toggle_auto_read
|
||||||
|
#=toggle_highlight_tracking
|
||||||
KEY_FENRIR,KEY_Q=quit_fenrir
|
KEY_FENRIR,KEY_Q=quit_fenrir
|
||||||
KEY_FENRIR,KEY_T=time
|
KEY_FENRIR,KEY_T=time
|
||||||
2,KEY_FENRIR,KEY_T=date
|
2,KEY_FENRIR,KEY_T=date
|
||||||
|
@ -77,9 +77,9 @@ autodetectSuspendingScreen=True
|
|||||||
|
|
||||||
[keyboard]
|
[keyboard]
|
||||||
driver=evdev
|
driver=evdev
|
||||||
# filter input devices AUTO, ALL or a DEVICE NAME
|
# filter input devices NOMICE, ALL or a DEVICE NAME
|
||||||
device=AUTO
|
device=ALL
|
||||||
# gives fenrir exclusive access to the keyboard and let consume keystrokes. just disable on problems.
|
# gives fenrir exclusive access to the keyboard and let consume keystrokes.
|
||||||
grabDevices=True
|
grabDevices=True
|
||||||
ignoreShortcuts=False
|
ignoreShortcuts=False
|
||||||
# the current shortcut layout located in /etc/fenrir/keyboard
|
# the current shortcut layout located in /etc/fenrir/keyboard
|
||||||
@ -110,7 +110,13 @@ timeFormat=%H:%M:%P
|
|||||||
dateFormat=%A, %B %d, %Y
|
dateFormat=%A, %B %d, %Y
|
||||||
autoSpellCheck=True
|
autoSpellCheck=True
|
||||||
spellCheckLanguage=en_US
|
spellCheckLanguage=en_US
|
||||||
scriptPath=/etc/fenrir/scripts
|
scriptPath=/usr/share/fenrir/scripts
|
||||||
|
|
||||||
|
[focus]
|
||||||
|
#follow the text cursor
|
||||||
|
cursor=True
|
||||||
|
#follow highlighted text changes
|
||||||
|
highlight=False
|
||||||
|
|
||||||
[promote]
|
[promote]
|
||||||
enabled=True
|
enabled=True
|
||||||
|
@ -77,8 +77,8 @@ autodetectSuspendingScreen=True
|
|||||||
|
|
||||||
[keyboard]
|
[keyboard]
|
||||||
driver=evdev
|
driver=evdev
|
||||||
# filter input devices AUTO, ALL or a DEVICE NAME
|
# filter input devices NOMICE, ALL or a DEVICE NAME
|
||||||
device=AUTO
|
device=ALL
|
||||||
# gives fenrir exclusive access to the keyboard and let consume keystrokes. just disable on problems.
|
# gives fenrir exclusive access to the keyboard and let consume keystrokes. just disable on problems.
|
||||||
grabDevices=True
|
grabDevices=True
|
||||||
ignoreShortcuts=False
|
ignoreShortcuts=False
|
||||||
@ -110,7 +110,13 @@ timeFormat=%H:%M:%P
|
|||||||
dateFormat=%A, %B %d, %Y
|
dateFormat=%A, %B %d, %Y
|
||||||
autoSpellCheck=True
|
autoSpellCheck=True
|
||||||
spellCheckLanguage=en_US
|
spellCheckLanguage=en_US
|
||||||
scriptPath=/etc/fenrir/scripts
|
scriptPath=/usr/share/fenrir/scripts
|
||||||
|
|
||||||
|
[focus]
|
||||||
|
#follow the text cursor
|
||||||
|
cursor=True
|
||||||
|
#follow highlighted text changes
|
||||||
|
highlight=False
|
||||||
|
|
||||||
[promote]
|
[promote]
|
||||||
enabled=True
|
enabled=True
|
||||||
|
@ -34,8 +34,8 @@ autodetectSuspendingScreen=False
|
|||||||
|
|
||||||
[keyboard]
|
[keyboard]
|
||||||
driver=evdev
|
driver=evdev
|
||||||
# filter input devices AUTO, ALL or a DEVICE NAME
|
# filter input devices NOMICE, ALL or a DEVICE NAME
|
||||||
device=AUTO
|
device=ALL
|
||||||
grabDevices=True
|
grabDevices=True
|
||||||
ignoreShortcuts=False
|
ignoreShortcuts=False
|
||||||
keyboardLayout=desktop
|
keyboardLayout=desktop
|
||||||
@ -60,7 +60,14 @@ timeFormat=%H:%M:%P
|
|||||||
dateFormat="%A, %B %d, %Y"
|
dateFormat="%A, %B %d, %Y"
|
||||||
autoSpellCheck=True
|
autoSpellCheck=True
|
||||||
spellCheckLanguage=en_US
|
spellCheckLanguage=en_US
|
||||||
scriptPath=/etc/fenrir/scripts
|
scriptPath=/usr/share/fenrir/scripts
|
||||||
|
|
||||||
|
[focus]
|
||||||
|
#follow the text cursor
|
||||||
|
cursor=True
|
||||||
|
#follow highlighted text changes
|
||||||
|
highlight=False
|
||||||
|
|
||||||
|
|
||||||
[promote]
|
[promote]
|
||||||
enabled=True
|
enabled=True
|
||||||
|
@ -3,17 +3,19 @@
|
|||||||
|
|
||||||
_gitname='fenrir'
|
_gitname='fenrir'
|
||||||
pkgname="${_gitname}-git"
|
pkgname="${_gitname}-git"
|
||||||
pkgver=v0.1.2.gb72614a
|
pkgver=v0.2.5.g33af5b6
|
||||||
pkgrel=1
|
pkgrel=3
|
||||||
pkgdesc='A user space console screen reader written in python3'
|
pkgdesc='A user space console screen reader written in python3'
|
||||||
arch=('any')
|
arch=('any')
|
||||||
url='https://github.com/chrys87/${_pkgname}'
|
url='https://github.com/chrys87/${_pkgname}'
|
||||||
license=('MIT')
|
license=('MIT')
|
||||||
depends=('python' 'python-espeak' 'python-evdev')
|
depends=('python' 'python-daemonize' 'python-evdev')
|
||||||
optdepends=('brltty: For Braille support'
|
optdepends=('brltty: For Braille support'
|
||||||
'gstreamer: for soundicons via gstreamer'
|
'gstreamer: for soundicons via gstreamer'
|
||||||
'sox: The default sound driver'
|
'sox: The default sound driver'
|
||||||
'python-enchant: for spell check functionality')
|
'python-espeak: TTS support'
|
||||||
|
'python-pyenchant: for spell check functionality'
|
||||||
|
'speech-dispatcher: TTS support')
|
||||||
makedepends=('git')
|
makedepends=('git')
|
||||||
provides=('fenrir')
|
provides=('fenrir')
|
||||||
conflicts=('fenrir')
|
conflicts=('fenrir')
|
||||||
@ -21,7 +23,7 @@ install="$pkgname".install
|
|||||||
source=("git+https://github.com/chrys87/${_gitname}.git"
|
source=("git+https://github.com/chrys87/${_gitname}.git"
|
||||||
'fenrir-git.install')
|
'fenrir-git.install')
|
||||||
md5sums=('SKIP'
|
md5sums=('SKIP'
|
||||||
'9d1e82fce2e02ae2a1216a18ca576bfb')
|
'1387fd3851040d03816e2fb6b8fa631f')
|
||||||
|
|
||||||
pkgver()
|
pkgver()
|
||||||
{
|
{
|
||||||
@ -33,17 +35,19 @@ pkgver()
|
|||||||
package()
|
package()
|
||||||
{
|
{
|
||||||
cd "$srcdir/$_gitname"
|
cd "$srcdir/$_gitname"
|
||||||
install -d "$pkgdir/usr/bin"
|
install -m755 -d "$pkgdir/opt/fenrir"
|
||||||
install -d "$pkgdir/etc/fenrir/keyboard"
|
install -m755 -d "$pkgdir/usr/share/fenrir/scripts"
|
||||||
install -d "$pkgdir/etc/fenrir/settings"
|
install -m755 -d "$pkgdir/usr/share/fenrir/tools"
|
||||||
install -d "$pkgdir/etc/fenrir/substitution"
|
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 -d "$pkgdir/usr/share/sounds/fenrir"
|
||||||
install -m644 -D "autostart/systemd/fenrir.service" "$pkgdir/usr/lib/systemd/system/fenrir.service"
|
install -m644 -D "autostart/systemd/fenrir.service" "$pkgdir/usr/lib/systemd/system/fenrir.service"
|
||||||
python setup.py install --root="${pkgdir}/" --optimize=1
|
cp -a src/fenrir/* "$pkgdir/opt/fenrir"
|
||||||
cp -a config/keyboard/* "$pkgdir/etc/fenrir/keyboard"
|
cp -a config/scripts/* "$pkgdir/usr/share/fenrir/scripts"
|
||||||
cp -a config/settings/* "$pkgdir/etc/fenrir/settings"
|
cp -a tools/* "$pkgdir/usr/share/fenrir/tools"
|
||||||
cp -a config/sound/* "$pkgdir/usr/share/sounds/fenrir"
|
cp -a config/sound/* "$pkgdir/usr/share/sounds/fenrir"
|
||||||
cp -a config/substitution/* "$pkgdir/etc/fenrir/substitution"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# vim: set ts=2 sw=2 et:
|
# vim: set ts=2 sw=2 et:
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
post_install() {
|
post_install() {
|
||||||
|
ln -s /opt/fenrir/fenrir-daemon /usr/bin/fenrir
|
||||||
_alert
|
_alert
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6,6 +7,9 @@ _alert() {
|
|||||||
cat << EOF
|
cat << EOF
|
||||||
To have fenrir start at boot:
|
To have fenrir start at boot:
|
||||||
sudo systemctl enable fenrir
|
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
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
install.sh
Normal file → Executable file
2
install.sh
Normal file → Executable file
@ -3,7 +3,7 @@
|
|||||||
read -p "This will install fenrir. Press ctrl+c to cancil, or enter to continue." continue
|
read -p "This will install fenrir. Press ctrl+c to cancil, or enter to continue." continue
|
||||||
install -m755 -d /opt/fenrir
|
install -m755 -d /opt/fenrir
|
||||||
install -m755 -d /usr/share/fenrir/scripts
|
install -m755 -d /usr/share/fenrir/scripts
|
||||||
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/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/punctuation/default.conf" /etc/fenrir/punctuation/default.conf
|
||||||
install -m644 -D "config/settings/settings.conf" /etc/fenrir/settings/settings.conf
|
install -m644 -D "config/settings/settings.conf" /etc/fenrir/settings/settings.conf
|
||||||
|
29
src/fenrir/commands/commands/toggle_highlight_tracking.py
Normal file
29
src/fenrir/commands/commands/toggle_highlight_tracking.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#!/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):
|
||||||
|
currMode=self.env['runtime']['settingsManager'].getSettingAsBool('focus', 'highlight')
|
||||||
|
|
||||||
|
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)
|
||||||
|
else:
|
||||||
|
self.env['runtime']['outputManager'].presentText("cursor tracking", soundIcon='', interrupt=True)
|
||||||
|
|
||||||
|
def setCallback(self, callback):
|
||||||
|
pass
|
@ -18,6 +18,8 @@ class command():
|
|||||||
return ''
|
return ''
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
if not self.env['runtime']['settingsManager'].getSettingAsBool('focus', 'cursor'):
|
||||||
|
return
|
||||||
if self.env['runtime']['screenManager'].isScreenChange():
|
if self.env['runtime']['screenManager'].isScreenChange():
|
||||||
return
|
return
|
||||||
if self.env['runtime']['inputManager'].noKeyPressed():
|
if self.env['runtime']['inputManager'].noKeyPressed():
|
||||||
|
@ -18,6 +18,8 @@ class command():
|
|||||||
return ''
|
return ''
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
if not self.env['runtime']['settingsManager'].getSettingAsBool('focus', 'cursor'):
|
||||||
|
return
|
||||||
if self.env['runtime']['inputManager'].noKeyPressed():
|
if self.env['runtime']['inputManager'].noKeyPressed():
|
||||||
return
|
return
|
||||||
if self.env['runtime']['screenManager'].isScreenChange():
|
if self.env['runtime']['screenManager'].isScreenChange():
|
||||||
|
24
src/fenrir/commands/onInput/56000-highlight_tracking.py
Normal file
24
src/fenrir/commands/onInput/56000-highlight_tracking.py
Normal file
@ -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['screenData']['newAttribDelta'], soundIcon='', interrupt=True)
|
||||||
|
|
||||||
|
def setCallback(self, callback):
|
||||||
|
pass
|
@ -19,6 +19,8 @@ class command():
|
|||||||
def run(self):
|
def run(self):
|
||||||
if self.env['runtime']['inputManager'].noKeyPressed():
|
if self.env['runtime']['inputManager'].noKeyPressed():
|
||||||
return
|
return
|
||||||
|
if self.env['screenData']['newAttribDelta'] != '':
|
||||||
|
return
|
||||||
if self.env['runtime']['screenManager'].isScreenChange():
|
if self.env['runtime']['screenManager'].isScreenChange():
|
||||||
return
|
return
|
||||||
if self.env['runtime']['cursorManager'].isCursorVerticalMove():
|
if self.env['runtime']['cursorManager'].isCursorVerticalMove():
|
||||||
@ -29,9 +31,7 @@ class command():
|
|||||||
return
|
return
|
||||||
prevLine = self.env['screenData']['oldContentText'].split('\n')[self.env['screenData']['newCursor']['y']]
|
prevLine = self.env['screenData']['oldContentText'].split('\n')[self.env['screenData']['newCursor']['y']]
|
||||||
currLine = self.env['screenData']['newContentText'].split('\n')[self.env['screenData']['newCursor']['y']]
|
currLine = self.env['screenData']['newContentText'].split('\n')[self.env['screenData']['newCursor']['y']]
|
||||||
if currLine.isspace():
|
if not currLine.isspace():
|
||||||
self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True)
|
|
||||||
else:
|
|
||||||
currPrompt = currLine.find('$')
|
currPrompt = currLine.find('$')
|
||||||
rootPrompt = currLine.find('#')
|
rootPrompt = currLine.find('#')
|
||||||
if currPrompt <= 0:
|
if currPrompt <= 0:
|
||||||
|
@ -63,6 +63,11 @@ class cursorManager():
|
|||||||
self.env['screenData']['oldCursorReview'] = self.env['screenData']['newCursorReview']
|
self.env['screenData']['oldCursorReview'] = self.env['screenData']['newCursorReview']
|
||||||
if not self.env['screenData']['newCursorReview']:
|
if not self.env['screenData']['newCursorReview']:
|
||||||
self.env['screenData']['newCursorReview'] = self.env['screenData']['newCursor'].copy()
|
self.env['screenData']['newCursorReview'] = self.env['screenData']['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()
|
||||||
|
|
||||||
def setReviewCursorPosition(self, x, y):
|
def setReviewCursorPosition(self, x, y):
|
||||||
if not self.isReviewMode():
|
if not self.isReviewMode():
|
||||||
|
@ -43,7 +43,7 @@ class inputManager():
|
|||||||
if len(self.env['input']['currInput']) == 0:
|
if len(self.env['input']['currInput']) == 0:
|
||||||
self.env['input']['prevDeepestInput'] = []
|
self.env['input']['prevDeepestInput'] = []
|
||||||
self.env['input']['shortcutRepeat'] = 1
|
self.env['input']['shortcutRepeat'] = 1
|
||||||
self.handleLedStates(mEvent)
|
self.setLedState = self.handleLedStates(mEvent)
|
||||||
self.env['input']['lastInputTime'] = time.time()
|
self.env['input']['lastInputTime'] = time.time()
|
||||||
elif mEvent['EventState'] == 1:
|
elif mEvent['EventState'] == 1:
|
||||||
if not mEvent['EventName'] in self.env['input']['currInput']:
|
if not mEvent['EventName'] in self.env['input']['currInput']:
|
||||||
@ -57,7 +57,7 @@ class inputManager():
|
|||||||
self.env['input']['shortcutRepeat'] += 1
|
self.env['input']['shortcutRepeat'] += 1
|
||||||
else:
|
else:
|
||||||
self.env['input']['shortcutRepeat'] = 1
|
self.env['input']['shortcutRepeat'] = 1
|
||||||
self.handleLedStates(mEvent)
|
self.setLedState = self.handleLedStates(mEvent)
|
||||||
self.env['input']['lastInputTime'] = time.time()
|
self.env['input']['lastInputTime'] = time.time()
|
||||||
elif mEvent['EventState'] == 2:
|
elif mEvent['EventState'] == 2:
|
||||||
self.env['input']['lastInputTime'] = time.time()
|
self.env['input']['lastInputTime'] = time.time()
|
||||||
@ -77,34 +77,29 @@ class inputManager():
|
|||||||
|
|
||||||
def handleLedStates(self, mEvent):
|
def handleLedStates(self, mEvent):
|
||||||
if not self.setLedState:
|
if not self.setLedState:
|
||||||
return
|
return self.setLedState
|
||||||
if mEvent['EventName'] == 'KEY_NUMLOCK':
|
if mEvent['EventName'] == 'KEY_NUMLOCK':
|
||||||
if mEvent['EventState'] == 1 and not self.env['input']['newNumLock'] == 1:
|
if mEvent['EventState'] == 1 and not self.env['input']['newNumLock'] == 1:
|
||||||
self.env['runtime']['inputDriver'].toggleLedState()
|
self.env['runtime']['inputDriver'].toggleLedState()
|
||||||
self.setLedState = False
|
return False
|
||||||
return
|
|
||||||
if mEvent['EventState'] == 0 and not self.env['input']['newNumLock'] == 0:
|
if mEvent['EventState'] == 0 and not self.env['input']['newNumLock'] == 0:
|
||||||
self.env['runtime']['inputDriver'].toggleLedState()
|
self.env['runtime']['inputDriver'].toggleLedState()
|
||||||
self.setLedState = False
|
return False
|
||||||
return
|
|
||||||
if mEvent['EventName'] == 'KEY_CAPSLOCK':
|
if mEvent['EventName'] == 'KEY_CAPSLOCK':
|
||||||
if mEvent['EventState'] == 1 and not self.env['input']['newCapsLock'] == 1:
|
if mEvent['EventState'] == 1 and not self.env['input']['newCapsLock'] == 1:
|
||||||
self.env['runtime']['inputDriver'].toggleLedState(1)
|
self.env['runtime']['inputDriver'].toggleLedState(1)
|
||||||
self.setLedState = False
|
return False
|
||||||
return
|
|
||||||
if mEvent['EventState'] == 0 and not self.env['input']['newCapsLock'] == 0:
|
if mEvent['EventState'] == 0 and not self.env['input']['newCapsLock'] == 0:
|
||||||
self.env['runtime']['inputDriver'].toggleLedState(1)
|
self.env['runtime']['inputDriver'].toggleLedState(1)
|
||||||
self.setLedState = False
|
return False
|
||||||
return
|
|
||||||
if mEvent['EventName'] == 'KEY_SCROLLLOCK':
|
if mEvent['EventName'] == 'KEY_SCROLLLOCK':
|
||||||
if mEvent['EventState'] == 1 and not self.env['input']['newScrollLock'] == 1:
|
if mEvent['EventState'] == 1 and not self.env['input']['newScrollLock'] == 1:
|
||||||
self.env['runtime']['inputDriver'].toggleLedState(2)
|
self.env['runtime']['inputDriver'].toggleLedState(2)
|
||||||
self.setLedState = False
|
return False
|
||||||
return
|
|
||||||
if mEvent['EventState'] == 0 and not self.env['input']['newScrollLock'] == 0:
|
if mEvent['EventState'] == 0 and not self.env['input']['newScrollLock'] == 0:
|
||||||
self.env['runtime']['inputDriver'].toggleLedState(2)
|
self.env['runtime']['inputDriver'].toggleLedState(2)
|
||||||
self.setLedState = False
|
return False
|
||||||
return
|
return self.setLedState
|
||||||
|
|
||||||
def grabDevices(self):
|
def grabDevices(self):
|
||||||
if self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'grabDevices'):
|
if self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'grabDevices'):
|
||||||
@ -168,10 +163,10 @@ class inputManager():
|
|||||||
self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR)
|
self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR)
|
||||||
|
|
||||||
def isFenrirKeyPressed(self):
|
def isFenrirKeyPressed(self):
|
||||||
return 'KEY_FENRIR' in self.env['input']['currInput']
|
return 'KEY_FENRIR' in self.env['input']['prevDeepestInput']
|
||||||
|
|
||||||
def isScriptKeyPressed(self):
|
def isScriptKeyPressed(self):
|
||||||
return 'KEY_SCRIPT' in self.env['input']['currInput']
|
return 'KEY_SCRIPT' in self.env['input']['prevDeepestInput']
|
||||||
|
|
||||||
def noKeyPressed(self):
|
def noKeyPressed(self):
|
||||||
return self.env['input']['currInput'] == []
|
return self.env['input']['currInput'] == []
|
||||||
|
@ -11,8 +11,10 @@ screenData = {
|
|||||||
'columns': 0,
|
'columns': 0,
|
||||||
'lines': 0,
|
'lines': 0,
|
||||||
'oldDelta': '',
|
'oldDelta': '',
|
||||||
|
'oldAttribDelta': '',
|
||||||
'oldNegativeDelta': '',
|
'oldNegativeDelta': '',
|
||||||
'oldCursorReview':None,
|
'oldCursorReview':None,
|
||||||
|
'oldCursorAttrib':None,
|
||||||
'oldCursor':{'x':0,'y':0},
|
'oldCursor':{'x':0,'y':0},
|
||||||
'oldContentBytes': b'',
|
'oldContentBytes': b'',
|
||||||
'oldContentText': '',
|
'oldContentText': '',
|
||||||
@ -21,7 +23,9 @@ screenData = {
|
|||||||
'oldTTY':None,
|
'oldTTY':None,
|
||||||
'newDelta': '',
|
'newDelta': '',
|
||||||
'newNegativeDelta': '',
|
'newNegativeDelta': '',
|
||||||
|
'newAttribDelta': '',
|
||||||
'newCursorReview':None,
|
'newCursorReview':None,
|
||||||
|
'newCursorAttrib':None,
|
||||||
'newCursor':{'x':0,'y':0},
|
'newCursor':{'x':0,'y':0},
|
||||||
'newContentBytes': b'',
|
'newContentBytes': b'',
|
||||||
'newContentText': '',
|
'newContentText': '',
|
||||||
|
@ -55,6 +55,10 @@ settings = {
|
|||||||
'spellCheckLanguage': 'en_US',
|
'spellCheckLanguage': 'en_US',
|
||||||
'scriptPath':'/etc/fenrir/scripts',
|
'scriptPath':'/etc/fenrir/scripts',
|
||||||
},
|
},
|
||||||
|
'focus':{
|
||||||
|
'cursor': True,
|
||||||
|
'highlight': False,
|
||||||
|
},
|
||||||
'promote':{
|
'promote':{
|
||||||
'enabled': True,
|
'enabled': True,
|
||||||
'inactiveTimeoutSec': 120,
|
'inactiveTimeoutSec': 120,
|
||||||
|
@ -43,8 +43,6 @@ class driver():
|
|||||||
return currMapEvent
|
return currMapEvent
|
||||||
if currMapEvent['EventState'] in [0,1,2]:
|
if currMapEvent['EventState'] in [0,1,2]:
|
||||||
return currMapEvent
|
return currMapEvent
|
||||||
|
|
||||||
|
|
||||||
event = self.iDevices[fd].read_one()
|
event = self.iDevices[fd].read_one()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -77,7 +75,7 @@ class driver():
|
|||||||
if self.env['runtime']['settingsManager'].getSetting('keyboard', 'device').upper() == 'ALL':
|
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.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()}
|
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() == 'AUTO':
|
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.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()}
|
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:
|
else:
|
||||||
@ -102,10 +100,10 @@ class driver():
|
|||||||
# 0 = Numlock
|
# 0 = Numlock
|
||||||
# 1 = Capslock
|
# 1 = Capslock
|
||||||
# 2 = Rollen
|
# 2 = Rollen
|
||||||
if self.ledDevices == {}:
|
|
||||||
return False
|
|
||||||
if self.ledDevices == None:
|
if self.ledDevices == None:
|
||||||
return False
|
return False
|
||||||
|
if self.ledDevices == {}:
|
||||||
|
return False
|
||||||
for fd, dev in self.ledDevices.items():
|
for fd, dev in self.ledDevices.items():
|
||||||
return led in dev.leds()
|
return led in dev.leds()
|
||||||
return False
|
return False
|
||||||
|
@ -8,6 +8,7 @@ import difflib
|
|||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
from core import debug
|
from core import debug
|
||||||
|
from utils import screen_utils
|
||||||
|
|
||||||
class driver():
|
class driver():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -16,9 +17,6 @@ class driver():
|
|||||||
self.env = environment
|
self.env = environment
|
||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
pass
|
pass
|
||||||
def insert_newlines(self, string, every=64):
|
|
||||||
return '\n'.join(string[i:i+every] for i in range(0, len(string), every))
|
|
||||||
|
|
||||||
def getCurrScreen(self):
|
def getCurrScreen(self):
|
||||||
self.env['screenData']['oldTTY'] = self.env['screenData']['newTTY']
|
self.env['screenData']['oldTTY'] = self.env['screenData']['newTTY']
|
||||||
try:
|
try:
|
||||||
@ -85,10 +83,12 @@ class driver():
|
|||||||
# set new "old" values
|
# set new "old" values
|
||||||
self.env['screenData']['oldContentBytes'] = self.env['screenData']['newContentBytes']
|
self.env['screenData']['oldContentBytes'] = self.env['screenData']['newContentBytes']
|
||||||
self.env['screenData']['oldContentText'] = self.env['screenData']['newContentText']
|
self.env['screenData']['oldContentText'] = self.env['screenData']['newContentText']
|
||||||
self.env['screenData']['oldContentTextAttrib'] = self.env['screenData']['newContentAttrib']
|
self.env['screenData']['oldContentAttrib'] = self.env['screenData']['newContentAttrib']
|
||||||
self.env['screenData']['oldCursor']['x'] = self.env['screenData']['newCursor']['x']
|
self.env['screenData']['oldCursor'] = self.env['screenData']['newCursor'].copy()
|
||||||
self.env['screenData']['oldCursor']['y'] = self.env['screenData']['newCursor']['y']
|
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']['oldDelta'] = self.env['screenData']['newDelta']
|
||||||
|
self.env['screenData']['oldAttribDelta'] = self.env['screenData']['newAttribDelta']
|
||||||
self.env['screenData']['oldNegativeDelta'] = self.env['screenData']['newNegativeDelta']
|
self.env['screenData']['oldNegativeDelta'] = self.env['screenData']['newNegativeDelta']
|
||||||
self.env['screenData']['newContentBytes'] = newContentBytes
|
self.env['screenData']['newContentBytes'] = newContentBytes
|
||||||
# get metadata like cursor or screensize
|
# get metadata like cursor or screensize
|
||||||
@ -98,8 +98,9 @@ class driver():
|
|||||||
self.env['screenData']['newCursor']['y'] = int( self.env['screenData']['newContentBytes'][3])
|
self.env['screenData']['newCursor']['y'] = int( self.env['screenData']['newContentBytes'][3])
|
||||||
# analyze content
|
# 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'] = 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']['newContentAttrib'] = self.env['screenData']['newContentBytes'][5:][::2]
|
||||||
self.env['screenData']['newContentText'] = self.insert_newlines(self.env['screenData']['newContentText'], self.env['screenData']['columns'])
|
self.env['screenData']['newContentText'] = screen_utils.insertNewlines(self.env['screenData']['newContentText'], self.env['screenData']['columns'])
|
||||||
|
|
||||||
if self.env['screenData']['newTTY'] != self.env['screenData']['oldTTY']:
|
if self.env['screenData']['newTTY'] != self.env['screenData']['oldTTY']:
|
||||||
self.env['screenData']['oldContentBytes'] = b''
|
self.env['screenData']['oldContentBytes'] = b''
|
||||||
@ -108,10 +109,15 @@ class driver():
|
|||||||
self.env['screenData']['oldCursor']['x'] = 0
|
self.env['screenData']['oldCursor']['x'] = 0
|
||||||
self.env['screenData']['oldCursor']['y'] = 0
|
self.env['screenData']['oldCursor']['y'] = 0
|
||||||
self.env['screenData']['oldDelta'] = ''
|
self.env['screenData']['oldDelta'] = ''
|
||||||
|
self.env['screenData']['oldAttribDelta'] = ''
|
||||||
|
self.env['screenData']['oldCursorAttrib'] = None
|
||||||
|
self.env['screenData']['newCursorAttrib'] = None
|
||||||
self.env['screenData']['oldNegativeDelta'] = ''
|
self.env['screenData']['oldNegativeDelta'] = ''
|
||||||
# always clear current deltas
|
# initialize current deltas
|
||||||
self.env['screenData']['newNegativeDelta'] = ''
|
self.env['screenData']['newNegativeDelta'] = ''
|
||||||
self.env['screenData']['newDelta'] = ''
|
self.env['screenData']['newDelta'] = ''
|
||||||
|
self.env['screenData']['newAttribDelta'] = ''
|
||||||
|
|
||||||
# changes on the screen
|
# changes on the screen
|
||||||
oldScreenText = re.sub(' +',' ',self.env['runtime']['screenManager'].getWindowAreaInText(self.env['screenData']['oldContentText']))
|
oldScreenText = re.sub(' +',' ',self.env['runtime']['screenManager'].getWindowAreaInText(self.env['screenData']['oldContentText']))
|
||||||
newScreenText = re.sub(' +',' ',self.env['runtime']['screenManager'].getWindowAreaInText(self.env['screenData']['newContentText']))
|
newScreenText = re.sub(' +',' ',self.env['runtime']['screenManager'].getWindowAreaInText(self.env['screenData']['newContentText']))
|
||||||
@ -146,3 +152,8 @@ class driver():
|
|||||||
self.env['screenData']['newDelta'] = ''.join(x[2:] for x in diffList if x[0] == '+')
|
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] == '-')
|
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'])
|
||||||
|
|
||||||
|
@ -21,12 +21,10 @@ class driver():
|
|||||||
if self.soundFileCommand == '':
|
if self.soundFileCommand == '':
|
||||||
self.soundFileCommand = 'play -q -v fenrirVolume fenrirSoundFile'
|
self.soundFileCommand = 'play -q -v fenrirVolume fenrirSoundFile'
|
||||||
if self.frequenceCommand == '':
|
if self.frequenceCommand == '':
|
||||||
self.frequenceCommand = '=play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence'
|
self.frequenceCommand = 'play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence'
|
||||||
return
|
|
||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
self.cancel()
|
self.cancel()
|
||||||
return
|
def playFrequence(self, frequence = 1000, duration = 0.3, adjustVolume = 0):
|
||||||
def playFrequence(self, frequence, duration, adjustVolume):
|
|
||||||
if interrupt:
|
if interrupt:
|
||||||
self.cancel()
|
self.cancel()
|
||||||
popenFrequenceCommand = self.frequenceCommand.replace('fenrirVolume', str(self.volume + adjustVolume ))
|
popenFrequenceCommand = self.frequenceCommand.replace('fenrirVolume', str(self.volume + adjustVolume ))
|
||||||
|
@ -33,6 +33,8 @@ class driver():
|
|||||||
return
|
return
|
||||||
|
|
||||||
def speak(self,text, queueable=True):
|
def speak(self,text, queueable=True):
|
||||||
|
if not self._isInitialized:
|
||||||
|
self.initialize(self.env)
|
||||||
if not self._isInitialized:
|
if not self._isInitialized:
|
||||||
return False
|
return False
|
||||||
if queueable == False: self.cancel()
|
if queueable == False: self.cancel()
|
||||||
@ -40,7 +42,7 @@ class driver():
|
|||||||
self._sd.set_synthesis_voice(self._language)
|
self._sd.set_synthesis_voice(self._language)
|
||||||
self._sd.set_punctuation(self._punct.NONE)
|
self._sd.set_punctuation(self._punct.NONE)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
pass
|
self._isInitialized = False
|
||||||
self._sd.speak(text)
|
self._sd.speak(text)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
# By Chrys, Storm Dragon, and contributers.
|
# By Chrys, Storm Dragon, and contributers.
|
||||||
|
|
||||||
from core import debug
|
from core import debug
|
||||||
|
from collections import Counter
|
||||||
|
|
||||||
def getPrevLine(currX,currY, currText):
|
def getPrevLine(currX,currY, currText):
|
||||||
endOfScreen = False
|
endOfScreen = False
|
||||||
|
54
src/fenrir/utils/screen_utils.py
Normal file
54
src/fenrir/utils/screen_utils.py
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#!/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Fenrir TTY screen reader
|
||||||
|
# By Chrys, Storm Dragon, and contributers.
|
||||||
|
|
||||||
|
from core import debug
|
||||||
|
from collections import Counter
|
||||||
|
import string
|
||||||
|
|
||||||
|
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)
|
||||||
|
# Use translate to remove all non-printable characters
|
||||||
|
return text.translate({ord(character):None for character in nonprintable})
|
||||||
|
|
||||||
|
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 trackHighlights(oldAttr, newAttr, text, lenght):
|
||||||
|
result = ''
|
||||||
|
currCursor = None
|
||||||
|
if oldAttr == newAttr:
|
||||||
|
return result, currCursor
|
||||||
|
if len(newAttr) == 0:
|
||||||
|
return result, currCursor
|
||||||
|
if len(oldAttr) != len(newAttr):
|
||||||
|
return result, currCursor
|
||||||
|
old = splitEvery(oldAttr,lenght)
|
||||||
|
new = splitEvery(newAttr,lenght)
|
||||||
|
textLines = text.split('\n')
|
||||||
|
if len(textLines) != len(new):
|
||||||
|
return result, currCursor
|
||||||
|
|
||||||
|
try:
|
||||||
|
background = Counter(newAttr).most_common(1)
|
||||||
|
background = background[0][0]
|
||||||
|
except Exception as e:
|
||||||
|
background = chr(7)
|
||||||
|
for line in range(len(new)):
|
||||||
|
if old[line] != new[line]:
|
||||||
|
for column in range(len(new[line])):
|
||||||
|
if old[line][column] != new[line][column]:
|
||||||
|
if new[line][column] != background:
|
||||||
|
if not currCursor:
|
||||||
|
currCursor = {}
|
||||||
|
currCursor['x'] = column
|
||||||
|
currCursor['y'] = line
|
||||||
|
result += textLines[line][column]
|
||||||
|
result += ' '
|
||||||
|
return result, currCursor
|
@ -1,112 +0,0 @@
|
|||||||
#!/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# Fenrir TTY screen reader
|
|
||||||
# By Chrys, Storm Dragon, and contributers.
|
|
||||||
|
|
||||||
from core import debug
|
|
||||||
|
|
||||||
def getPrevWord(currX,currY, currText):
|
|
||||||
if currText == '':
|
|
||||||
return -1, -1, ''
|
|
||||||
x, y, currWord = getCurrentWord(currX,currY,currText)
|
|
||||||
wrappedLines = currText.split('\n')
|
|
||||||
if (currWord == ''):
|
|
||||||
return currX, currY, ''
|
|
||||||
while True:
|
|
||||||
if x < 2:
|
|
||||||
if y != 0:
|
|
||||||
y -= 1
|
|
||||||
else:
|
|
||||||
return currX, currY, ''
|
|
||||||
x = len(wrappedLines[y]) - 1
|
|
||||||
else:
|
|
||||||
x -= 1
|
|
||||||
if wrappedLines[y] != '':
|
|
||||||
break
|
|
||||||
x, y, currWord = getCurrentWord(x, y, currText)
|
|
||||||
if currWord == '':
|
|
||||||
return currX, currY, ''
|
|
||||||
return x, y, currWord
|
|
||||||
|
|
||||||
def getCurrentWord(currX,currY, currText):
|
|
||||||
if currText == '':
|
|
||||||
return -1, -1, ''
|
|
||||||
x = currX
|
|
||||||
y = currY
|
|
||||||
wrappedLines = currText.split('\n')
|
|
||||||
wordFound = False
|
|
||||||
currWord = ''
|
|
||||||
currLine = wrappedLines[y].replace("\t"," ")
|
|
||||||
if currLine[x] == ' ' and x > 1:
|
|
||||||
x = x - 2
|
|
||||||
while not wordFound:
|
|
||||||
x = currLine[:x].rfind(" ")
|
|
||||||
if x == -1:
|
|
||||||
x = 0
|
|
||||||
else:
|
|
||||||
x += 1
|
|
||||||
wordEnd = currLine[x + 1:].find(" ")
|
|
||||||
if wordEnd == -1:
|
|
||||||
wordEnd = len(currLine)
|
|
||||||
else:
|
|
||||||
wordEnd += x + 1
|
|
||||||
currWord = currLine[x:wordEnd]
|
|
||||||
wordFound = currWord.strip(" \t\n") != ''
|
|
||||||
if wordFound:
|
|
||||||
break
|
|
||||||
if x == 0:
|
|
||||||
if y != 0:
|
|
||||||
y -= 1
|
|
||||||
currLine = wrappedLines[y].replace("\t"," ")
|
|
||||||
else:
|
|
||||||
return currX, currY, ''
|
|
||||||
x = len(wrappedLines[y]) - 1
|
|
||||||
else:
|
|
||||||
x -= 1
|
|
||||||
return x, y, currWord
|
|
||||||
|
|
||||||
def getNextWord(currX,currY, currText):
|
|
||||||
if currText == '':
|
|
||||||
return -1, -1, ''
|
|
||||||
x = currX
|
|
||||||
y = currY
|
|
||||||
wrappedLines = currText.split('\n')
|
|
||||||
wordFound = False
|
|
||||||
currWord = ''
|
|
||||||
currLine = wrappedLines[y].replace("\t"," ")
|
|
||||||
while not wordFound:
|
|
||||||
xtmp = 0
|
|
||||||
if x + 1 >= len(currLine):
|
|
||||||
if y < len(wrappedLines):
|
|
||||||
y += 1
|
|
||||||
currLine = wrappedLines[y].replace("\t"," ")
|
|
||||||
else:
|
|
||||||
return currX, currY, ''
|
|
||||||
x = 0
|
|
||||||
else:
|
|
||||||
x += 1
|
|
||||||
xtmp = x
|
|
||||||
x = currLine[x:].find(" ")
|
|
||||||
if x == -1:
|
|
||||||
x = len(currLine)
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
if xtmp != 0:
|
|
||||||
xtmp += 1
|
|
||||||
x += xtmp
|
|
||||||
if x + 1 < len(currLine):
|
|
||||||
wordEnd = currLine[x + 1:].find(" ")
|
|
||||||
else:
|
|
||||||
wordEnd = -1
|
|
||||||
if wordEnd == -1:
|
|
||||||
wordEnd = len(currLine)
|
|
||||||
else:
|
|
||||||
wordEnd += x + 1
|
|
||||||
if wordEnd >= len(currLine) and y + 1 >= len(wrappedLines):
|
|
||||||
return currX, currY, ''
|
|
||||||
currWord = currLine[x:wordEnd]
|
|
||||||
wordFound = currWord.strip(" \t\n") != ''
|
|
||||||
if not wordFound:
|
|
||||||
x = wordEnd
|
|
||||||
return x, y, currWord
|
|
Loading…
Reference in New Issue
Block a user