From 33edce7c828ef7756a0611dcbfed721853cc9b9c Mon Sep 17 00:00:00 2001 From: Jeremiah Ticket Date: Tue, 4 Oct 2016 10:52:39 -0800 Subject: [PATCH] Renamed fenrir-package to fenrir to satisfy packaging deps. --- src/fenrir/1ChangeTTY.opus | Bin 0 -> 1403 bytes src/fenrir/1ChangeTTY.wav | Bin 0 -> 28880 bytes src/fenrir/__init__.py | 0 src/fenrir/braille/__init__.py | 0 src/fenrir/braille/braille.py | 15 ++ src/fenrir/commands/__init__.py | 0 src/fenrir/commands/command_template.py | 21 ++ src/fenrir/commands/commands/__init__.py | 0 .../commands/add_word_to_spell_check.py | 55 +++++ src/fenrir/commands/commands/bookmark_1.py | 48 ++++ src/fenrir/commands/commands/bookmark_10.py | 48 ++++ src/fenrir/commands/commands/bookmark_2.py | 48 ++++ src/fenrir/commands/commands/bookmark_3.py | 48 ++++ src/fenrir/commands/commands/bookmark_4.py | 48 ++++ src/fenrir/commands/commands/bookmark_5.py | 48 ++++ src/fenrir/commands/commands/bookmark_6.py | 48 ++++ src/fenrir/commands/commands/bookmark_7.py | 48 ++++ src/fenrir/commands/commands/bookmark_8.py | 48 ++++ src/fenrir/commands/commands/bookmark_9.py | 48 ++++ .../commands/commands/clear_bookmark_1.py | 27 +++ .../commands/commands/clear_bookmark_10.py | 27 +++ .../commands/commands/clear_bookmark_2.py | 27 +++ .../commands/commands/clear_bookmark_3.py | 27 +++ .../commands/commands/clear_bookmark_4.py | 27 +++ .../commands/commands/clear_bookmark_5.py | 27 +++ .../commands/commands/clear_bookmark_6.py | 27 +++ .../commands/commands/clear_bookmark_7.py | 27 +++ .../commands/commands/clear_bookmark_8.py | 27 +++ .../commands/commands/clear_bookmark_9.py | 27 +++ .../commands/commands/clear_clipboard.py | 25 ++ .../commands/clear_window_application.py | 27 +++ .../commands/copy_marked_to_clipboard.py | 43 ++++ .../commands/commands/curr_char_phonetic.py | 33 +++ .../commands/commands/curr_clipboard.py | 26 +++ src/fenrir/commands/commands/curr_screen.py | 26 +++ .../commands/curr_screen_after_cursor.py | 32 +++ .../commands/curr_screen_before_cursor.py | 36 +++ .../commands/commands/curr_word_phonetic.py | 36 +++ .../commands/commands/cursor_position.py | 26 +++ src/fenrir/commands/commands/date.py | 30 +++ .../commands/commands/dec_sound_volume.py | 33 +++ .../commands/commands/dec_speech_pitch.py | 30 +++ .../commands/commands/dec_speech_rate.py | 30 +++ .../commands/commands/dec_speech_volume.py | 31 +++ src/fenrir/commands/commands/exit_review.py | 28 +++ .../commands/commands/first_clipboard.py | 27 +++ .../commands/commands/forward_keypress.py | 24 ++ .../commands/commands/inc_sound_volume.py | 32 +++ .../commands/commands/inc_speech_pitch.py | 30 +++ .../commands/commands/inc_speech_rate.py | 30 +++ .../commands/commands/inc_speech_volume.py | 30 +++ .../commands/commands/indent_curr_line.py | 36 +++ .../commands/commands/last_clipboard.py | 27 +++ src/fenrir/commands/commands/last_incoming.py | 23 ++ .../commands/linux_paste_clipboard.py | 33 +++ src/fenrir/commands/commands/marked_text.py | 38 ++++ .../commands/commands/next_clipboard.py | 32 +++ .../commands/commands/present_first_line.py | 30 +++ .../commands/commands/present_last_line.py | 30 +++ .../commands/commands/prev_clipboard.py | 32 +++ src/fenrir/commands/commands/quit_fenrir.py | 24 ++ src/fenrir/commands/commands/remove_marks.py | 24 ++ .../commands/remove_word_from_spell_check.py | 55 +++++ src/fenrir/commands/commands/review_bottom.py | 24 ++ .../commands/commands/review_curr_char.py | 32 +++ .../commands/commands/review_curr_line.py | 32 +++ .../commands/commands/review_curr_word.py | 32 +++ src/fenrir/commands/commands/review_down.py | 30 +++ .../commands/commands/review_line_begin.py | 33 +++ .../commands/commands/review_line_end.py | 33 +++ .../commands/review_line_last_char.py | 33 +++ .../commands/commands/review_next_char.py | 34 +++ .../commands/commands/review_next_line.py | 34 +++ .../commands/commands/review_next_word.py | 34 +++ .../commands/commands/review_prev_char.py | 34 +++ .../commands/commands/review_prev_line.py | 32 +++ .../commands/commands/review_prev_word.py | 32 +++ src/fenrir/commands/commands/review_top.py | 25 ++ src/fenrir/commands/commands/review_up.py | 30 +++ .../commands/commands/set_bookmark_1.py | 36 +++ .../commands/commands/set_bookmark_10.py | 36 +++ .../commands/commands/set_bookmark_2.py | 36 +++ .../commands/commands/set_bookmark_3.py | 36 +++ .../commands/commands/set_bookmark_4.py | 36 +++ .../commands/commands/set_bookmark_5.py | 36 +++ .../commands/commands/set_bookmark_6.py | 36 +++ .../commands/commands/set_bookmark_7.py | 36 +++ .../commands/commands/set_bookmark_8.py | 36 +++ .../commands/commands/set_bookmark_9.py | 36 +++ src/fenrir/commands/commands/set_mark.py | 28 +++ .../commands/set_window_application.py | 28 +++ src/fenrir/commands/commands/shut_up.py | 23 ++ src/fenrir/commands/commands/spell_check.py | 53 +++++ src/fenrir/commands/commands/time.py | 30 +++ .../commands/commands/toggle_auto_read.py | 26 +++ .../commands/toggle_auto_spell_check.py | 27 +++ .../commands/commands/toggle_braille.py | 27 +++ src/fenrir/commands/commands/toggle_output.py | 34 +++ .../commands/toggle_punctuation_level.py | 23 ++ src/fenrir/commands/commands/toggle_sound.py | 27 +++ src/fenrir/commands/commands/toggle_speech.py | 27 +++ .../commands/commands/toggle_tutorial_mode.py | 26 +++ .../commands/onApplicationChange/test.py | 25 ++ src/fenrir/commands/onInput/10000-shut_up.py | 31 +++ ...resent_char_if_cursor_change_horizontal.py | 38 ++++ .../commands/onInput/50000-char_echo.py | 37 +++ ...-present_line_if_cursor_change_vertical.py | 38 ++++ .../commands/onInput/60000-word_echo.py | 56 +++++ .../commands/onInput/62000-spell_check.py | 122 ++++++++++ .../onInput/65000-char_delete_echo.py | 44 ++++ src/fenrir/commands/onInput/80000-capslock.py | 27 +++ .../commands/onInput/80300-scrolllock.py | 27 +++ src/fenrir/commands/onInput/80500-numlock.py | 27 +++ src/fenrir/commands/onInput/__init__.py | 0 .../commands/onScreenChanged/10000-shut_up.py | 24 ++ .../80000-screen_change_announcement.py | 25 ++ .../85000-screen_chnage_reset_marks.py | 25 ++ .../85000-screen_chnage_reset_review.py | 24 ++ .../89000-screen_chnage_leve_review_mode.py | 23 ++ .../commands/onScreenChanged/__init__.py | 0 .../commands/onScreenUpdate/70000-incoming.py | 35 +++ .../onScreenUpdate/75000-incoming_promote.py | 39 ++++ .../commands/onScreenUpdate/__init__.py | 0 .../onSwitchApplicationProfile/__init__.py | 0 .../onSwitchApplicationProfile/agetty.py | 31 +++ .../onSwitchApplicationProfile/bash.py | 31 +++ .../onSwitchApplicationProfile/default.py | 31 +++ .../onSwitchApplicationProfile/vim.py | 31 +++ src/fenrir/commands/switchTrigger_template.py | 23 ++ src/fenrir/core/__init__.py | 0 src/fenrir/core/applicationManager.py | 31 +++ src/fenrir/core/commandManager.py | 127 +++++++++++ src/fenrir/core/commands.py | 45 ++++ src/fenrir/core/cursorManager.py | 87 +++++++ src/fenrir/core/debug.py | 67 ++++++ src/fenrir/core/environment.py | 26 +++ src/fenrir/core/generalInformation.py | 12 + src/fenrir/core/inputEvent.py | 32 +++ src/fenrir/core/inputManager.py | 156 +++++++++++++ src/fenrir/core/outputManager.py | 123 ++++++++++ src/fenrir/core/punctuationManager.py | 110 +++++++++ src/fenrir/core/runtime.py | 20 ++ src/fenrir/core/screenData.py | 32 +++ src/fenrir/core/screenManager.py | 51 +++++ src/fenrir/core/settings.py | 68 ++++++ src/fenrir/core/settingsManager.py | 214 ++++++++++++++++++ src/fenrir/fenrir.egg-info/PKG-INFO | 39 ++++ src/fenrir/fenrir.egg-info/SOURCES.txt | 168 ++++++++++++++ .../fenrir.egg-info/dependency_links.txt | 1 + src/fenrir/fenrir.egg-info/entry_points.txt | 3 + src/fenrir/fenrir.egg-info/not-zip-safe | 1 + src/fenrir/fenrir.egg-info/requires.txt | 3 + src/fenrir/fenrir.egg-info/top_level.txt | 8 + src/fenrir/fenrir.py | 132 +++++++++++ src/fenrir/inputDriver/__init__.py | 0 src/fenrir/inputDriver/evdev.py | 156 +++++++++++++ src/fenrir/screenDriver/__init__.py | 0 src/fenrir/screenDriver/linux.py | 143 ++++++++++++ src/fenrir/sound.py | 9 + src/fenrir/soundDriver/__init__.py | 0 src/fenrir/soundDriver/generic.py | 55 +++++ src/fenrir/soundDriver/gstreamer.py | 109 +++++++++ src/fenrir/speechDriver/Readme.md | 3 + src/fenrir/speechDriver/__init__.py | 0 src/fenrir/speechDriver/espeak.py | 74 ++++++ src/fenrir/speechDriver/generic.py | 66 ++++++ src/fenrir/speechDriver/speechd.py | 102 +++++++++ src/fenrir/utils/__init__.py | 0 src/fenrir/utils/char_utils.py | 90 ++++++++ src/fenrir/utils/fenrir-config.py | 23 ++ src/fenrir/utils/line_utils.py | 41 ++++ src/fenrir/utils/mark_utils.py | 60 +++++ src/fenrir/utils/review_utils.py | 8 + src/fenrir/utils/word_utils.py | 112 +++++++++ 174 files changed, 6554 insertions(+) create mode 100644 src/fenrir/1ChangeTTY.opus create mode 100644 src/fenrir/1ChangeTTY.wav create mode 100755 src/fenrir/__init__.py create mode 100755 src/fenrir/braille/__init__.py create mode 100644 src/fenrir/braille/braille.py create mode 100755 src/fenrir/commands/__init__.py create mode 100644 src/fenrir/commands/command_template.py create mode 100755 src/fenrir/commands/commands/__init__.py create mode 100644 src/fenrir/commands/commands/add_word_to_spell_check.py create mode 100644 src/fenrir/commands/commands/bookmark_1.py create mode 100644 src/fenrir/commands/commands/bookmark_10.py create mode 100644 src/fenrir/commands/commands/bookmark_2.py create mode 100644 src/fenrir/commands/commands/bookmark_3.py create mode 100644 src/fenrir/commands/commands/bookmark_4.py create mode 100644 src/fenrir/commands/commands/bookmark_5.py create mode 100644 src/fenrir/commands/commands/bookmark_6.py create mode 100644 src/fenrir/commands/commands/bookmark_7.py create mode 100644 src/fenrir/commands/commands/bookmark_8.py create mode 100644 src/fenrir/commands/commands/bookmark_9.py create mode 100644 src/fenrir/commands/commands/clear_bookmark_1.py create mode 100644 src/fenrir/commands/commands/clear_bookmark_10.py create mode 100644 src/fenrir/commands/commands/clear_bookmark_2.py create mode 100644 src/fenrir/commands/commands/clear_bookmark_3.py create mode 100644 src/fenrir/commands/commands/clear_bookmark_4.py create mode 100644 src/fenrir/commands/commands/clear_bookmark_5.py create mode 100644 src/fenrir/commands/commands/clear_bookmark_6.py create mode 100644 src/fenrir/commands/commands/clear_bookmark_7.py create mode 100644 src/fenrir/commands/commands/clear_bookmark_8.py create mode 100644 src/fenrir/commands/commands/clear_bookmark_9.py create mode 100644 src/fenrir/commands/commands/clear_clipboard.py create mode 100644 src/fenrir/commands/commands/clear_window_application.py create mode 100644 src/fenrir/commands/commands/copy_marked_to_clipboard.py create mode 100644 src/fenrir/commands/commands/curr_char_phonetic.py create mode 100644 src/fenrir/commands/commands/curr_clipboard.py create mode 100644 src/fenrir/commands/commands/curr_screen.py create mode 100644 src/fenrir/commands/commands/curr_screen_after_cursor.py create mode 100644 src/fenrir/commands/commands/curr_screen_before_cursor.py create mode 100644 src/fenrir/commands/commands/curr_word_phonetic.py create mode 100644 src/fenrir/commands/commands/cursor_position.py create mode 100644 src/fenrir/commands/commands/date.py create mode 100644 src/fenrir/commands/commands/dec_sound_volume.py create mode 100644 src/fenrir/commands/commands/dec_speech_pitch.py create mode 100644 src/fenrir/commands/commands/dec_speech_rate.py create mode 100644 src/fenrir/commands/commands/dec_speech_volume.py create mode 100644 src/fenrir/commands/commands/exit_review.py create mode 100644 src/fenrir/commands/commands/first_clipboard.py create mode 100644 src/fenrir/commands/commands/forward_keypress.py create mode 100644 src/fenrir/commands/commands/inc_sound_volume.py create mode 100644 src/fenrir/commands/commands/inc_speech_pitch.py create mode 100644 src/fenrir/commands/commands/inc_speech_rate.py create mode 100644 src/fenrir/commands/commands/inc_speech_volume.py create mode 100644 src/fenrir/commands/commands/indent_curr_line.py create mode 100644 src/fenrir/commands/commands/last_clipboard.py create mode 100644 src/fenrir/commands/commands/last_incoming.py create mode 100644 src/fenrir/commands/commands/linux_paste_clipboard.py create mode 100644 src/fenrir/commands/commands/marked_text.py create mode 100644 src/fenrir/commands/commands/next_clipboard.py create mode 100644 src/fenrir/commands/commands/present_first_line.py create mode 100644 src/fenrir/commands/commands/present_last_line.py create mode 100644 src/fenrir/commands/commands/prev_clipboard.py create mode 100644 src/fenrir/commands/commands/quit_fenrir.py create mode 100644 src/fenrir/commands/commands/remove_marks.py create mode 100644 src/fenrir/commands/commands/remove_word_from_spell_check.py create mode 100644 src/fenrir/commands/commands/review_bottom.py create mode 100644 src/fenrir/commands/commands/review_curr_char.py create mode 100644 src/fenrir/commands/commands/review_curr_line.py create mode 100644 src/fenrir/commands/commands/review_curr_word.py create mode 100644 src/fenrir/commands/commands/review_down.py create mode 100644 src/fenrir/commands/commands/review_line_begin.py create mode 100644 src/fenrir/commands/commands/review_line_end.py create mode 100644 src/fenrir/commands/commands/review_line_last_char.py create mode 100644 src/fenrir/commands/commands/review_next_char.py create mode 100644 src/fenrir/commands/commands/review_next_line.py create mode 100644 src/fenrir/commands/commands/review_next_word.py create mode 100644 src/fenrir/commands/commands/review_prev_char.py create mode 100644 src/fenrir/commands/commands/review_prev_line.py create mode 100644 src/fenrir/commands/commands/review_prev_word.py create mode 100644 src/fenrir/commands/commands/review_top.py create mode 100644 src/fenrir/commands/commands/review_up.py create mode 100644 src/fenrir/commands/commands/set_bookmark_1.py create mode 100644 src/fenrir/commands/commands/set_bookmark_10.py create mode 100644 src/fenrir/commands/commands/set_bookmark_2.py create mode 100644 src/fenrir/commands/commands/set_bookmark_3.py create mode 100644 src/fenrir/commands/commands/set_bookmark_4.py create mode 100644 src/fenrir/commands/commands/set_bookmark_5.py create mode 100644 src/fenrir/commands/commands/set_bookmark_6.py create mode 100644 src/fenrir/commands/commands/set_bookmark_7.py create mode 100644 src/fenrir/commands/commands/set_bookmark_8.py create mode 100644 src/fenrir/commands/commands/set_bookmark_9.py create mode 100644 src/fenrir/commands/commands/set_mark.py create mode 100644 src/fenrir/commands/commands/set_window_application.py create mode 100644 src/fenrir/commands/commands/shut_up.py create mode 100644 src/fenrir/commands/commands/spell_check.py create mode 100644 src/fenrir/commands/commands/time.py create mode 100644 src/fenrir/commands/commands/toggle_auto_read.py create mode 100644 src/fenrir/commands/commands/toggle_auto_spell_check.py create mode 100644 src/fenrir/commands/commands/toggle_braille.py create mode 100644 src/fenrir/commands/commands/toggle_output.py create mode 100644 src/fenrir/commands/commands/toggle_punctuation_level.py create mode 100644 src/fenrir/commands/commands/toggle_sound.py create mode 100644 src/fenrir/commands/commands/toggle_speech.py create mode 100644 src/fenrir/commands/commands/toggle_tutorial_mode.py create mode 100644 src/fenrir/commands/onApplicationChange/test.py create mode 100644 src/fenrir/commands/onInput/10000-shut_up.py create mode 100644 src/fenrir/commands/onInput/45000-present_char_if_cursor_change_horizontal.py create mode 100644 src/fenrir/commands/onInput/50000-char_echo.py create mode 100644 src/fenrir/commands/onInput/55000-present_line_if_cursor_change_vertical.py create mode 100644 src/fenrir/commands/onInput/60000-word_echo.py create mode 100644 src/fenrir/commands/onInput/62000-spell_check.py create mode 100644 src/fenrir/commands/onInput/65000-char_delete_echo.py create mode 100644 src/fenrir/commands/onInput/80000-capslock.py create mode 100644 src/fenrir/commands/onInput/80300-scrolllock.py create mode 100644 src/fenrir/commands/onInput/80500-numlock.py create mode 100755 src/fenrir/commands/onInput/__init__.py create mode 100644 src/fenrir/commands/onScreenChanged/10000-shut_up.py create mode 100644 src/fenrir/commands/onScreenChanged/80000-screen_change_announcement.py create mode 100644 src/fenrir/commands/onScreenChanged/85000-screen_chnage_reset_marks.py create mode 100644 src/fenrir/commands/onScreenChanged/85000-screen_chnage_reset_review.py create mode 100644 src/fenrir/commands/onScreenChanged/89000-screen_chnage_leve_review_mode.py create mode 100755 src/fenrir/commands/onScreenChanged/__init__.py create mode 100644 src/fenrir/commands/onScreenUpdate/70000-incoming.py create mode 100644 src/fenrir/commands/onScreenUpdate/75000-incoming_promote.py create mode 100755 src/fenrir/commands/onScreenUpdate/__init__.py create mode 100644 src/fenrir/commands/onSwitchApplicationProfile/__init__.py create mode 100644 src/fenrir/commands/onSwitchApplicationProfile/agetty.py create mode 100644 src/fenrir/commands/onSwitchApplicationProfile/bash.py create mode 100644 src/fenrir/commands/onSwitchApplicationProfile/default.py create mode 100644 src/fenrir/commands/onSwitchApplicationProfile/vim.py create mode 100644 src/fenrir/commands/switchTrigger_template.py create mode 100755 src/fenrir/core/__init__.py create mode 100644 src/fenrir/core/applicationManager.py create mode 100644 src/fenrir/core/commandManager.py create mode 100644 src/fenrir/core/commands.py create mode 100644 src/fenrir/core/cursorManager.py create mode 100644 src/fenrir/core/debug.py create mode 100644 src/fenrir/core/environment.py create mode 100644 src/fenrir/core/generalInformation.py create mode 100644 src/fenrir/core/inputEvent.py create mode 100644 src/fenrir/core/inputManager.py create mode 100644 src/fenrir/core/outputManager.py create mode 100644 src/fenrir/core/punctuationManager.py create mode 100644 src/fenrir/core/runtime.py create mode 100644 src/fenrir/core/screenData.py create mode 100644 src/fenrir/core/screenManager.py create mode 100644 src/fenrir/core/settings.py create mode 100644 src/fenrir/core/settingsManager.py create mode 100644 src/fenrir/fenrir.egg-info/PKG-INFO create mode 100644 src/fenrir/fenrir.egg-info/SOURCES.txt create mode 100644 src/fenrir/fenrir.egg-info/dependency_links.txt create mode 100644 src/fenrir/fenrir.egg-info/entry_points.txt create mode 100644 src/fenrir/fenrir.egg-info/not-zip-safe create mode 100644 src/fenrir/fenrir.egg-info/requires.txt create mode 100644 src/fenrir/fenrir.egg-info/top_level.txt create mode 100755 src/fenrir/fenrir.py create mode 100755 src/fenrir/inputDriver/__init__.py create mode 100644 src/fenrir/inputDriver/evdev.py create mode 100755 src/fenrir/screenDriver/__init__.py create mode 100644 src/fenrir/screenDriver/linux.py create mode 100755 src/fenrir/sound.py create mode 100755 src/fenrir/soundDriver/__init__.py create mode 100644 src/fenrir/soundDriver/generic.py create mode 100644 src/fenrir/soundDriver/gstreamer.py create mode 100644 src/fenrir/speechDriver/Readme.md create mode 100755 src/fenrir/speechDriver/__init__.py create mode 100644 src/fenrir/speechDriver/espeak.py create mode 100644 src/fenrir/speechDriver/generic.py create mode 100644 src/fenrir/speechDriver/speechd.py create mode 100755 src/fenrir/utils/__init__.py create mode 100644 src/fenrir/utils/char_utils.py create mode 100644 src/fenrir/utils/fenrir-config.py create mode 100644 src/fenrir/utils/line_utils.py create mode 100644 src/fenrir/utils/mark_utils.py create mode 100644 src/fenrir/utils/review_utils.py create mode 100644 src/fenrir/utils/word_utils.py diff --git a/src/fenrir/1ChangeTTY.opus b/src/fenrir/1ChangeTTY.opus new file mode 100644 index 0000000000000000000000000000000000000000..e147023bb20ba4ee4b538e052d14cc254d2c0c1d GIT binary patch literal 1403 zcmV->1%&!fXJ=CY0ssI2000000BZdL#{d8T0M|Xr)BzJuaCLJ?Wnp9i0XPAGy8r+H z002*CXHx(G0000000000YW)Jo0RR91LfR2o0X|P~b#qi=UX002s<)W!&;lbDy7mYSjX$^&NZggDVaCW^MAdi76E2ICL8Z-<82x{ z&zbX4M)8I042FaWa$-1TkEF>N4srzAveZdUd>gibW)rRiXbrveCLidkNK{^NfIPO0 zKn#$JcJk)Mn1*cbjHiALqzXEsc~7A@)@L?xY+6J3!=+|qFxz{sIGxIp6lt~o3n|VC zAgELx+rp~MfQ-9fY6tQc9Kh?l#5D&QRt=J-4p(Qw-$fMakHG%H%arobKg0Smf_!Rl zMAOktG~GL#yQLhvAt}SYfzpa?WA!iZ$7`eY_0`IPfSitVp_lx+xG!kKf<*OsdDDFd z5`9xD1=Bw62y#Me9JQ*HKK?!U;A$@`4^%--3LdznOGaY166?UPrWF+! z1-Lz?QGX?|qBKLY`%!F|t{HqH%&xWp%2sdSAKFQXS9rD_Sz1kEr+HEE-w;d-H2G`j zIo9(WbDyhz4u9Fw2f;t9fy4MTBRBvHNAlH2&jUK%d%IXB4?WyUn6IowMs0%fHq+P zP!A$14?GS#!qT(W{tP`e2 zYO(wmHJO~akw>`3Wc=6F9>TfZ^WdEt-(Qw+8#M}6_~!kiGV1&;wve-zG1!aSJ5>oD zS8FH~*G!vbFO2Yzx$Y7`xYlR_|J&;MKF-Gm0F67Snl}$$dGXTLnP2M9q`8C`9DAtH z%hj8wh(9AAKlm&*k_~?vgJnT>2oSZy((@dZYW@)D;nOxj2xziaBM_1g{HrwxUh_VS zc2%Z*G=qQ#W!>t;p0|1ckZDUs!L3GPc^7}l!JrBgA=d0lZ~w-Tj6+yUAMzc18;D6= z>n1+}TPjGq6#v$Y3>ReZ%4+t4X}uOKX^^!7P4|Y@wQHzlyeJ`Ev;Lj~lzcG+=jB9a zp(dO7?m0DwqQzgJkFMmv(%h?A7H$PY>nqgcLFm}V?G{Uv-2W|zU=daI1(QBh8s;j5 z80E2-J;t${g#OeNAOq`qY&w2eFsO0fq*@!>l?T%tmUbIb%J<9X&T zeh_4@>nly1=#D0W=Bj&gaA^|+w+HS*^KF!lr`)1W^s&74K!LT;h-?u?;_U$1q+GNX zNBDR;y$;A%@9{Ej7pqe~Qf_jK{Ip2>)yxPUdei0Vga@lWqCNks{)Bno0Cx+C-b7gN zN{hwXRyZrOD0qQou1R^*;Qd2%Ejw=%7IQl}m|dJo%t~eGO2V`T&!K)~Q@$$`)6y)$ z@kzP{PmAS@2*$YSPRpnH$D2-Mb1da>`U>$%)`gKz5)yGI5X&A-H;aZj-5K}|EU|^K JUYa2pnZaB1jr9Nk literal 0 HcmV?d00001 diff --git a/src/fenrir/1ChangeTTY.wav b/src/fenrir/1ChangeTTY.wav new file mode 100644 index 0000000000000000000000000000000000000000..124e213c2f3781f5fd1a3eaaf1f3739172688d45 GIT binary patch literal 28880 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
Ex-5Df2|B%P$8HI35G`^mU$(PoniHh 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 literal 0 HcmV?d00001 diff --git a/src/fenrir/__init__.py b/src/fenrir/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/src/fenrir/braille/__init__.py b/src/fenrir/braille/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/src/fenrir/braille/braille.py b/src/fenrir/braille/braille.py new file mode 100644 index 00000000..aff4f599 --- /dev/null +++ b/src/fenrir/braille/braille.py @@ -0,0 +1,15 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class braille(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass diff --git a/src/fenrir/commands/__init__.py b/src/fenrir/commands/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/src/fenrir/commands/command_template.py b/src/fenrir/commands/command_template.py new file mode 100644 index 00000000..25b6b1a8 --- /dev/null +++ b/src/fenrir/commands/command_template.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): + pass + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/__init__.py b/src/fenrir/commands/commands/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/src/fenrir/commands/commands/add_word_to_spell_check.py b/src/fenrir/commands/commands/add_word_to_spell_check.py new file mode 100644 index 00000000..ce334347 --- /dev/null +++ b/src/fenrir/commands/commands/add_word_to_spell_check.py @@ -0,0 +1,55 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +from utils import word_utils +initialized = False +try: + import enchant + initialized = True +except: + pass + +class command(): + def __init__(self): + self.language = '' + self.spellChecker = None + def initialize(self, environment): + self.env = environment + self.updateSpellLanguage() + def shutdown(self): + pass + def getDescription(self): + 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) + return + if self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage') != self.language: + try: + self.updateSpellLanguage() + except: + return + + cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() + + # get the word + newContent = self.env['screenData']['newContentText'].split('\n')[cursorPos['y']] + x, y, currWord = word_utils.getCurrentWord(cursorPos['x'], 0, newContent) + + if currWord != '': + if self.spellChecker.is_added(currWord): + self.env['runtime']['outputManager'].presentText(currWord + ' is already in dict',soundIcon='Cancel', interrupt=True) + else: + self.spellChecker.add(currWord) + self.env['runtime']['outputManager'].presentText(currWord + ' added',soundIcon='Accept', 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 new file mode 100644 index 00000000..d7426c43 --- /dev/null +++ b/src/fenrir/commands/commands/bookmark_1.py @@ -0,0 +1,48 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +from utils import mark_utils +from utils import line_utils + +class command(): + def __init__(self): + self.ID = '1' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'read Bookmark ' + 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) + return + if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]: + self.env['runtime']['outputManager'].presentText("Bookmark for application " + currApp + " not set", 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) + return + + # set marks + marked = '' + 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']) + else: + x, y, marked = \ + line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screenData']['newContentText']) + if marked.isspace(): + self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(marked, interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/bookmark_10.py b/src/fenrir/commands/commands/bookmark_10.py new file mode 100644 index 00000000..a975772b --- /dev/null +++ b/src/fenrir/commands/commands/bookmark_10.py @@ -0,0 +1,48 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +from utils import mark_utils +from utils import line_utils + +class command(): + def __init__(self): + self.ID = '10' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'read Bookmark ' + 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) + return + if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]: + self.env['runtime']['outputManager'].presentText("Bookmark for application " + currApp + " not set", 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) + return + + # set marks + marked = '' + 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']) + else: + x, y, marked = \ + line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screenData']['newContentText']) + if marked.isspace(): + self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(marked, interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/bookmark_2.py b/src/fenrir/commands/commands/bookmark_2.py new file mode 100644 index 00000000..5eb9a660 --- /dev/null +++ b/src/fenrir/commands/commands/bookmark_2.py @@ -0,0 +1,48 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +from utils import mark_utils +from utils import line_utils + +class command(): + def __init__(self): + self.ID = '2' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'read Bookmark ' + 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) + return + if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]: + self.env['runtime']['outputManager'].presentText("Bookmark for application " + currApp + " not set", 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) + return + + # set marks + marked = '' + 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']) + else: + x, y, marked = \ + line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screenData']['newContentText']) + if marked.isspace(): + self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(marked, interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/bookmark_3.py b/src/fenrir/commands/commands/bookmark_3.py new file mode 100644 index 00000000..95c521d7 --- /dev/null +++ b/src/fenrir/commands/commands/bookmark_3.py @@ -0,0 +1,48 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +from utils import mark_utils +from utils import line_utils + +class command(): + def __init__(self): + self.ID = '3' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'read Bookmark ' + 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) + return + if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]: + self.env['runtime']['outputManager'].presentText("Bookmark for application " + currApp + " not set", 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) + return + + # set marks + marked = '' + 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']) + else: + x, y, marked = \ + line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screenData']['newContentText']) + if marked.isspace(): + self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(marked, interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/bookmark_4.py b/src/fenrir/commands/commands/bookmark_4.py new file mode 100644 index 00000000..7386f998 --- /dev/null +++ b/src/fenrir/commands/commands/bookmark_4.py @@ -0,0 +1,48 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +from utils import mark_utils +from utils import line_utils + +class command(): + def __init__(self): + self.ID = '4' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'read Bookmark ' + 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) + return + if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]: + self.env['runtime']['outputManager'].presentText("Bookmark for application " + currApp + " not set", 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) + return + + # set marks + marked = '' + 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']) + else: + x, y, marked = \ + line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screenData']['newContentText']) + if marked.isspace(): + self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(marked, interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/bookmark_5.py b/src/fenrir/commands/commands/bookmark_5.py new file mode 100644 index 00000000..9250b058 --- /dev/null +++ b/src/fenrir/commands/commands/bookmark_5.py @@ -0,0 +1,48 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +from utils import mark_utils +from utils import line_utils + +class command(): + def __init__(self): + self.ID = '5' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'read Bookmark ' + 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) + return + if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]: + self.env['runtime']['outputManager'].presentText("Bookmark for application " + currApp + " not set", 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) + return + + # set marks + marked = '' + 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']) + else: + x, y, marked = \ + line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screenData']['newContentText']) + if marked.isspace(): + self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(marked, interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/bookmark_6.py b/src/fenrir/commands/commands/bookmark_6.py new file mode 100644 index 00000000..0749587e --- /dev/null +++ b/src/fenrir/commands/commands/bookmark_6.py @@ -0,0 +1,48 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +from utils import mark_utils +from utils import line_utils + +class command(): + def __init__(self): + self.ID = '6' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'read Bookmark ' + 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) + return + if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]: + self.env['runtime']['outputManager'].presentText("Bookmark for application " + currApp + " not set", 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) + return + + # set marks + marked = '' + 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']) + else: + x, y, marked = \ + line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screenData']['newContentText']) + if marked.isspace(): + self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(marked, interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/bookmark_7.py b/src/fenrir/commands/commands/bookmark_7.py new file mode 100644 index 00000000..e680dbdf --- /dev/null +++ b/src/fenrir/commands/commands/bookmark_7.py @@ -0,0 +1,48 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +from utils import mark_utils +from utils import line_utils + +class command(): + def __init__(self): + self.ID = '7' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'read Bookmark ' + 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) + return + if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]: + self.env['runtime']['outputManager'].presentText("Bookmark for application " + currApp + " not set", 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) + return + + # set marks + marked = '' + 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']) + else: + x, y, marked = \ + line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screenData']['newContentText']) + if marked.isspace(): + self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(marked, interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/bookmark_8.py b/src/fenrir/commands/commands/bookmark_8.py new file mode 100644 index 00000000..d540c758 --- /dev/null +++ b/src/fenrir/commands/commands/bookmark_8.py @@ -0,0 +1,48 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +from utils import mark_utils +from utils import line_utils + +class command(): + def __init__(self): + self.ID = '8' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'read Bookmark ' + 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) + return + if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]: + self.env['runtime']['outputManager'].presentText("Bookmark for application " + currApp + " not set", 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) + return + + # set marks + marked = '' + 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']) + else: + x, y, marked = \ + line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screenData']['newContentText']) + if marked.isspace(): + self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(marked, interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/bookmark_9.py b/src/fenrir/commands/commands/bookmark_9.py new file mode 100644 index 00000000..a6f53387 --- /dev/null +++ b/src/fenrir/commands/commands/bookmark_9.py @@ -0,0 +1,48 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +from utils import mark_utils +from utils import line_utils + +class command(): + def __init__(self): + self.ID = '9' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'read Bookmark ' + 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) + return + if not self.env['commandBuffer']['bookMarks'][self.ID][currApp]: + self.env['runtime']['outputManager'].presentText("Bookmark for application " + currApp + " not set", 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) + return + + # set marks + marked = '' + 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']) + else: + x, y, marked = \ + line_utils.getCurrentLine(startMark['x'], startMark['y'], self.env['screenData']['newContentText']) + if marked.isspace(): + self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(marked, interrupt=True) + + 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 new file mode 100644 index 00000000..686b7ff0 --- /dev/null +++ b/src/fenrir/commands/commands/clear_bookmark_1.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + self.ID = '1' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'remove Bookmark ' + 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) + + 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 new file mode 100644 index 00000000..335a73b9 --- /dev/null +++ b/src/fenrir/commands/commands/clear_bookmark_10.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + self.ID = '10' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'remove Bookmark ' + 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) + + 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 new file mode 100644 index 00000000..3f6f7139 --- /dev/null +++ b/src/fenrir/commands/commands/clear_bookmark_2.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + self.ID = '2' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'remove Bookmark ' + 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) + + 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 new file mode 100644 index 00000000..22471fa8 --- /dev/null +++ b/src/fenrir/commands/commands/clear_bookmark_3.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + self.ID = '3' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'remove Bookmark ' + 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) + + 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 new file mode 100644 index 00000000..3d440a3b --- /dev/null +++ b/src/fenrir/commands/commands/clear_bookmark_4.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + self.ID = '4' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'remove Bookmark ' + 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) + + 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 new file mode 100644 index 00000000..17d275bd --- /dev/null +++ b/src/fenrir/commands/commands/clear_bookmark_5.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + self.ID = '5' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'remove Bookmark ' + 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) + + 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 new file mode 100644 index 00000000..d7906f01 --- /dev/null +++ b/src/fenrir/commands/commands/clear_bookmark_6.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + self.ID = '6' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'remove Bookmark ' + 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) + + 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 new file mode 100644 index 00000000..3a46a111 --- /dev/null +++ b/src/fenrir/commands/commands/clear_bookmark_7.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + self.ID = '7' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'remove Bookmark ' + 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) + + 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 new file mode 100644 index 00000000..f9ce2a31 --- /dev/null +++ b/src/fenrir/commands/commands/clear_bookmark_8.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + self.ID = '8' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'remove Bookmark ' + 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) + + 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 new file mode 100644 index 00000000..79e47f39 --- /dev/null +++ b/src/fenrir/commands/commands/clear_bookmark_9.py @@ -0,0 +1,27 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + self.ID = '9' + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'remove Bookmark ' + 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) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/clear_clipboard.py b/src/fenrir/commands/commands/clear_clipboard.py new file mode 100644 index 00000000..8e82bfb0 --- /dev/null +++ b/src/fenrir/commands/commands/clear_clipboard.py @@ -0,0 +1,25 @@ +#!/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 '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) + 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 new file mode 100644 index 00000000..81d1707c --- /dev/null +++ b/src/fenrir/commands/commands/clear_window_application.py @@ -0,0 +1,27 @@ +#!/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 '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) + else: + 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 new file mode 100644 index 00000000..730082fc --- /dev/null +++ b/src/fenrir/commands/commands/copy_marked_to_clipboard.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 mark_utils + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'copies marked text to the currently selected clipboard' + + def run(self): + if not (self.env['commandBuffer']['Marks']['1'] and \ + self.env['commandBuffer']['Marks']['2']): + self.env['runtime']['outputManager'].presentText("two marks needed", 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']) + + self.env['commandBuffer']['clipboard'] = [marked] + self.env['commandBuffer']['clipboard'][:self.env['runtime']['settingsManager'].getSettingAsInt('general', 'numberOfClipboards') -1] + self.env['commandBuffer']['currClipboard'] = 0 + # reset marks + self.env['commandBuffer']['Marks']['1'] = None + self.env['commandBuffer']['Marks']['2'] = None + + if marked.isspace(): + self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(marked, interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/curr_char_phonetic.py b/src/fenrir/commands/commands/curr_char_phonetic.py new file mode 100644 index 00000000..8408b41e --- /dev/null +++ b/src/fenrir/commands/commands/curr_char_phonetic.py @@ -0,0 +1,33 @@ +#!/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 'phonetically presents the current character' + + def run(self): + cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() + + x, y, currChar = \ + char_utils.getCurrentChar(cursorPos['x'], cursorPos['y'], self.env['screenData']['newContentText']) + + if currChar.isspace(): + self.env['runtime']['outputManager'].presentText("blank" ,interrupt=True) + else: + currChar = char_utils.getPhonetic(currChar) + self.env['runtime']['outputManager'].presentText(currChar ,interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/curr_clipboard.py b/src/fenrir/commands/commands/curr_clipboard.py new file mode 100644 index 00000000..d47caec0 --- /dev/null +++ b/src/fenrir/commands/commands/curr_clipboard.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 '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) + return + self.env['runtime']['outputManager'].presentText(self.env['commandBuffer']['clipboard'][self.env['commandBuffer']['currClipboard']], interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/curr_screen.py b/src/fenrir/commands/commands/curr_screen.py new file mode 100644 index 00000000..8a1d42b0 --- /dev/null +++ b/src/fenrir/commands/commands/curr_screen.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 '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) + else: + self.env['runtime']['outputManager'].presentText(self.env['screenData']['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 new file mode 100644 index 00000000..7b33dff7 --- /dev/null +++ b/src/fenrir/commands/commands/curr_screen_after_cursor.py @@ -0,0 +1,32 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +from utils import mark_utils + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + 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']) + + if textAfterCursor.isspace(): + self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(textAfterCursor, interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/curr_screen_before_cursor.py b/src/fenrir/commands/commands/curr_screen_before_cursor.py new file mode 100644 index 00000000..e9367411 --- /dev/null +++ b/src/fenrir/commands/commands/curr_screen_before_cursor.py @@ -0,0 +1,36 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +from utils import mark_utils + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + 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() + else: + cursorPos = self.env['screenData']['newCursor'].copy() + + textBeforeCursor = mark_utils.getTextBeforeMark(cursorPos, self.env['screenData']['newContentText']) + + if textBeforeCursor.isspace(): + self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(textBeforeCursor, interrupt=True) + + def setCallback(self, callback): + pass + diff --git a/src/fenrir/commands/commands/curr_word_phonetic.py b/src/fenrir/commands/commands/curr_word_phonetic.py new file mode 100644 index 00000000..737e70c5 --- /dev/null +++ b/src/fenrir/commands/commands/curr_word_phonetic.py @@ -0,0 +1,36 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +from utils import word_utils +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 'phonetically spells the current word' + + def run(self): + cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() + x, y, currWord = \ + word_utils.getCurrentWord(cursorPos['x'], cursorPos['y'], self.env['screenData']['newContentText']) + + if currWord.isspace(): + self.env['runtime']['outputManager'].presentText("blank", interrupt=True) + else: + firstSequence = True + for c in currWord: + currChar = char_utils.getPhonetic(c) + self.env['runtime']['outputManager'].presentText(currChar, interrupt=firstSequence) + firstSequence = False + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/cursor_position.py b/src/fenrir/commands/commands/cursor_position.py new file mode 100644 index 00000000..9acc912d --- /dev/null +++ b/src/fenrir/commands/commands/cursor_position.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 '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) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/date.py b/src/fenrir/commands/commands/date.py new file mode 100644 index 00000000..cbf3a380 --- /dev/null +++ b/src/fenrir/commands/commands/date.py @@ -0,0 +1,30 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +import datetime + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'presents the date' + + def run(self): + dateFormat = self.env['runtime']['settingsManager'].getSetting('general', 'dateFormat') + + # get the time formatted + dateString = datetime.datetime.strftime(datetime.datetime.now(), dateFormat) + + # present the time via speak and braile, there is no soundicon, interrupt the current speech + self.env['runtime']['outputManager'].presentText(dateString , soundIcon='', 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 new file mode 100644 index 00000000..1cf1a640 --- /dev/null +++ b/src/fenrir/commands/commands/dec_sound_volume.py @@ -0,0 +1,33 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +import math + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'decrease sound volume' + + def run(self): + + value = self.env['runtime']['settingsManager'].getSettingAsFloat('sound', 'volume') + + value = round((math.ceil(10 * value) / 10) - 0.1, 2) + if value < 0.1: + 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) + + 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 new file mode 100644 index 00000000..fa818db1 --- /dev/null +++ b/src/fenrir/commands/commands/dec_speech_pitch.py @@ -0,0 +1,30 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +import math + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'decreases the pitch of the speech' + + def run(self): + value = self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'pitch') + value = round((math.ceil(10 * value) / 10) - 0.1, 2) + 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) + + 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 new file mode 100644 index 00000000..244ba9b9 --- /dev/null +++ b/src/fenrir/commands/commands/dec_speech_rate.py @@ -0,0 +1,30 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +import math + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'decreases the rate of the speech' + + def run(self): + value = self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'rate') + value = round((math.ceil(10 * value) / 10) - 0.1, 2) + if value < 0.0: + 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) + + 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 new file mode 100644 index 00000000..6ad5ba02 --- /dev/null +++ b/src/fenrir/commands/commands/dec_speech_volume.py @@ -0,0 +1,31 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +import math + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'decreases the volume of the speech' + + def run(self): + value = self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'volume') + value = round((math.ceil(10 * value) / 10) - 0.1, 2) + if value < 0.1: + 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) + + def setCallback(self, callback): + pass + diff --git a/src/fenrir/commands/commands/exit_review.py b/src/fenrir/commands/commands/exit_review.py new file mode 100644 index 00000000..6e9c72c5 --- /dev/null +++ b/src/fenrir/commands/commands/exit_review.py @@ -0,0 +1,28 @@ +#!/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']['cursorManager'].isReviewMode(): + 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) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/first_clipboard.py b/src/fenrir/commands/commands/first_clipboard.py new file mode 100644 index 00000000..c6cee34b --- /dev/null +++ b/src/fenrir/commands/commands/first_clipboard.py @@ -0,0 +1,27 @@ +#!/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 'selects the first clipboard' + + def run(self): + if len(self.env['commandBuffer']['clipboard']) == 0: + 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) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/forward_keypress.py b/src/fenrir/commands/commands/forward_keypress.py new file mode 100644 index 00000000..6aed1d65 --- /dev/null +++ b/src/fenrir/commands/commands/forward_keypress.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 '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) + + 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 new file mode 100644 index 00000000..f3c31558 --- /dev/null +++ b/src/fenrir/commands/commands/inc_sound_volume.py @@ -0,0 +1,32 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +import math + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'adjusts the volume for in coming sounds' + + def run(self): + + value = self.env['runtime']['settingsManager'].getSettingAsFloat('sound', 'volume') + + value = round((math.ceil(10 * value) / 10) + 0.1, 2) + if value > 1.0: + 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) + + 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 new file mode 100644 index 00000000..3d99df97 --- /dev/null +++ b/src/fenrir/commands/commands/inc_speech_pitch.py @@ -0,0 +1,30 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +import math + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'increases the pitch of the speech' + + def run(self): + value = self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'pitch') + value = round((math.ceil(10 * value) / 10) + 0.1, 2) + if value > 1.0: + 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) + + 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 new file mode 100644 index 00000000..3f20ae6b --- /dev/null +++ b/src/fenrir/commands/commands/inc_speech_rate.py @@ -0,0 +1,30 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +import math + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'increase the speech rate' + + def run(self): + value = self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'rate') + value = round((math.ceil(10 * value) / 10) + 0.1, 2) + if value > 1.0: + 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) + + 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 new file mode 100644 index 00000000..1ea41d32 --- /dev/null +++ b/src/fenrir/commands/commands/inc_speech_volume.py @@ -0,0 +1,30 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +import math + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'increase the speech volume' + + def run(self): + value = self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'volume') + value = round((math.ceil(10 * value) / 10) + 0.1, 2) + if value > 1.0: + 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) + + 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 new file mode 100644 index 00000000..4cfe3bdf --- /dev/null +++ b/src/fenrir/commands/commands/indent_curr_line.py @@ -0,0 +1,36 @@ +#!/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 '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() + else: + cursorPos = self.env['screenData']['newCursor'].copy() + x, y, currLine = \ + line_utils.getCurrentLine(cursorPos['x'], cursorPos['y'], self.env['screenData']['newContentText']) + + if currLine.isspace(): + 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) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/last_clipboard.py b/src/fenrir/commands/commands/last_clipboard.py new file mode 100644 index 00000000..cf08b299 --- /dev/null +++ b/src/fenrir/commands/commands/last_clipboard.py @@ -0,0 +1,27 @@ +#!/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 'selects the last clipboard' + + def run(self): + if len(self.env['commandBuffer']['clipboard']) == 0: + 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) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/last_incoming.py b/src/fenrir/commands/commands/last_incoming.py new file mode 100644 index 00000000..84b2f46a --- /dev/null +++ b/src/fenrir/commands/commands/last_incoming.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 'displays the last received text' + + def run(self): + self.env['runtime']['outputManager'].presentText(self.env['screenData']['newDelta'], interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/linux_paste_clipboard.py b/src/fenrir/commands/commands/linux_paste_clipboard.py new file mode 100644 index 00000000..88003398 --- /dev/null +++ b/src/fenrir/commands/commands/linux_paste_clipboard.py @@ -0,0 +1,33 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +import fcntl +import termios +import time, sys + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + 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) + return + with open("/dev/tty" + self.env['screenData']['newTTY'], 'w') as fd: + for c in self.env['commandBuffer']['clipboard'][currClipboard]: + fcntl.ioctl(fd, termios.TIOCSTI, c) + time.sleep(0.02) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/marked_text.py b/src/fenrir/commands/commands/marked_text.py new file mode 100644 index 00000000..7e7bc323 --- /dev/null +++ b/src/fenrir/commands/commands/marked_text.py @@ -0,0 +1,38 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +from utils import mark_utils + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + 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) + 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']) + + if marked.isspace(): + self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(marked, interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/next_clipboard.py b/src/fenrir/commands/commands/next_clipboard.py new file mode 100644 index 00000000..457bd9b6 --- /dev/null +++ b/src/fenrir/commands/commands/next_clipboard.py @@ -0,0 +1,32 @@ +#!/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 'selects the next clipboard' + + def run(self): + if len(self.env['commandBuffer']['clipboard']) == 0: + 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(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) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/present_first_line.py b/src/fenrir/commands/commands/present_first_line.py new file mode 100644 index 00000000..40954173 --- /dev/null +++ b/src/fenrir/commands/commands/present_first_line.py @@ -0,0 +1,30 @@ +#!/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 'present first line' + + def run(self): + x, y, firstLine = \ + line_utils.getCurrentLine(0, 0, self.env['screenData']['newContentText']) + + if firstLine.isspace(): + self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(firstLine, interrupt=True) + def setCallback(self, callback): + pass + diff --git a/src/fenrir/commands/commands/present_last_line.py b/src/fenrir/commands/commands/present_last_line.py new file mode 100644 index 00000000..f53af172 --- /dev/null +++ b/src/fenrir/commands/commands/present_last_line.py @@ -0,0 +1,30 @@ +#!/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 'current line' + + def run(self): + x, y, lastLine = \ + line_utils.getCurrentLine(0, self.env['screenData']['lines'] -1, self.env['screenData']['newContentText']) + + if lastLine.isspace(): + self.env['runtime']['outputManager'].presentText("blank", soundIcon='EmptyLine', interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(lastLine, interrupt=True) + def setCallback(self, callback): + pass + diff --git a/src/fenrir/commands/commands/prev_clipboard.py b/src/fenrir/commands/commands/prev_clipboard.py new file mode 100644 index 00000000..8659d662 --- /dev/null +++ b/src/fenrir/commands/commands/prev_clipboard.py @@ -0,0 +1,32 @@ +#!/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 'selects the previous clipboard' + + def run(self): + if len(self.env['commandBuffer']['clipboard']) == 0: + 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(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) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/quit_fenrir.py b/src/fenrir/commands/commands/quit_fenrir.py new file mode 100644 index 00000000..0be6540c --- /dev/null +++ b/src/fenrir/commands/commands/quit_fenrir.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 'exits Fenrir' + + def run(self): + self.env['generalInformation']['running'] = False + + def setCallback(self, callback): + pass + diff --git a/src/fenrir/commands/commands/remove_marks.py b/src/fenrir/commands/commands/remove_marks.py new file mode 100644 index 00000000..a180d853 --- /dev/null +++ b/src/fenrir/commands/commands/remove_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 'removes marks from selected text' + + def run(self): + self.env['runtime']['cursorManager'].clearMarks() + 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 new file mode 100644 index 00000000..6758ef26 --- /dev/null +++ b/src/fenrir/commands/commands/remove_word_from_spell_check.py @@ -0,0 +1,55 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +from utils import word_utils +initialized = False +try: + import enchant + initialized = True +except: + pass + +class command(): + def __init__(self): + self.language = '' + self.spellChecker = None + def initialize(self, environment): + self.env = environment + self.updateSpellLanguage() + def shutdown(self): + pass + def getDescription(self): + 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) + return + if self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage') != self.language: + try: + self.updateSpellLanguage() + except: + return + + cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() + + # get the word + newContent = self.env['screenData']['newContentText'].split('\n')[cursorPos['y']] + x, y, currWord = word_utils.getCurrentWord(cursorPos['x'], 0, newContent) + + 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) + else: + self.spellChecker.remove(currWord) + self.env['runtime']['outputManager'].presentText(currWord + ' removed',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 new file mode 100644 index 00000000..acc05f88 --- /dev/null +++ b/src/fenrir/commands/commands/review_bottom.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 '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) + + 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 new file mode 100644 index 00000000..993f5929 --- /dev/null +++ b/src/fenrir/commands/commands/review_curr_char.py @@ -0,0 +1,32 @@ +#!/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 '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']) + + if currChar.isspace(): + self.env['runtime']['outputManager'].presentText("blank" ,interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(currChar ,interrupt=True, ignorePunctuation=True, announceCapital=True) + + 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 new file mode 100644 index 00000000..6d8c9c19 --- /dev/null +++ b/src/fenrir/commands/commands/review_curr_line.py @@ -0,0 +1,32 @@ +#!/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 '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']) + + 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/commands/review_curr_word.py b/src/fenrir/commands/commands/review_curr_word.py new file mode 100644 index 00000000..0d657a6b --- /dev/null +++ b/src/fenrir/commands/commands/review_curr_word.py @@ -0,0 +1,32 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +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 'current word.' + + def run(self): + self.env['runtime']['cursorManager'].enterReviewModeCurrTextCursor() + + self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], currWord = \ + word_utils.getCurrentWord(self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], self.env['screenData']['newContentText']) + + if currWord.isspace(): + self.env['runtime']['outputManager'].presentText("blank", interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(currWord, interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/review_down.py b/src/fenrir/commands/commands/review_down.py new file mode 100644 index 00000000..bea47c06 --- /dev/null +++ b/src/fenrir/commands/commands/review_down.py @@ -0,0 +1,30 @@ +#!/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 'set review cursor to end of current line and display the content' + + def run(self): + cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() + self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], downChar = \ + char_utils.getDownChar(self.env['screenData']['newCursorReview']['x'],self.env['screenData']['newCursorReview']['y'], self.env['screenData']['newContentText']) + if downChar.isspace(): + self.env['runtime']['outputManager'].presentText("line is empty" ,interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(downChar ,interrupt=True, ignorePunctuation=True, announceCapital=True) + + 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 new file mode 100644 index 00000000..e69c0a37 --- /dev/null +++ b/src/fenrir/commands/commands/review_line_begin.py @@ -0,0 +1,33 @@ +#!/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 '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']) + + if currChar.isspace(): + self.env['runtime']['outputManager'].presentText("blank" ,interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(currChar ,interrupt=True, ignorePunctuation=True, announceCapital=True) + 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 new file mode 100644 index 00000000..9bb30561 --- /dev/null +++ b/src/fenrir/commands/commands/review_line_end.py @@ -0,0 +1,33 @@ +#!/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 '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']) + + if currChar.isspace(): + self.env['runtime']['outputManager'].presentText("space" ,interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(currChar ,interrupt=True, ignorePunctuation=True, announceCapital=True) + self.env['runtime']['outputManager'].presentText("end of line", 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 new file mode 100644 index 00000000..bb405abd --- /dev/null +++ b/src/fenrir/commands/commands/review_line_last_char.py @@ -0,0 +1,33 @@ +#!/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 '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']) + + if lastChar.isspace(): + self.env['runtime']['outputManager'].presentText("line is empty" ,interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(lastChar ,interrupt=True, ignorePunctuation=True, announceCapital=True) + 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 new file mode 100644 index 00000000..aa74a972 --- /dev/null +++ b/src/fenrir/commands/commands/review_next_char.py @@ -0,0 +1,34 @@ +#!/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 'moves review to the next 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['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], currChar = \ + char_utils.getNextChar(self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], self.env['screenData']['newContentText']) + + if currChar.isspace(): + self.env['runtime']['outputManager'].presentText("space", interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(currChar, interrupt=True, ignorePunctuation=True, announceCapital=True) + + 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 new file mode 100644 index 00000000..94966046 --- /dev/null +++ b/src/fenrir/commands/commands/review_next_line.py @@ -0,0 +1,34 @@ +#!/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 '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['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], currLine = \ + line_utils.getNextLine(self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['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/commands/review_next_word.py b/src/fenrir/commands/commands/review_next_word.py new file mode 100644 index 00000000..c41c6f5d --- /dev/null +++ b/src/fenrir/commands/commands/review_next_word.py @@ -0,0 +1,34 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +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 '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['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], currWord = \ + word_utils.getNextWord(self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], self.env['screenData']['newContentText']) + + if currWord.isspace(): + self.env['runtime']['outputManager'].presentText("blank", interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(currWord, interrupt=True) + + 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 new file mode 100644 index 00000000..6cfb8705 --- /dev/null +++ b/src/fenrir/commands/commands/review_prev_char.py @@ -0,0 +1,34 @@ +#!/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 '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['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], currChar = \ + char_utils.getPrevChar(self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], self.env['screenData']['newContentText']) + + if currChar.isspace(): + self.env['runtime']['outputManager'].presentText("space", interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(currChar, interrupt=True, ignorePunctuation=True, announceCapital=True) + + 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 new file mode 100644 index 00000000..16d1f135 --- /dev/null +++ b/src/fenrir/commands/commands/review_prev_line.py @@ -0,0 +1,32 @@ +#!/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 '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'], currLine = \ + line_utils.getPrevLine(self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['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/commands/review_prev_word.py b/src/fenrir/commands/commands/review_prev_word.py new file mode 100644 index 00000000..2085492b --- /dev/null +++ b/src/fenrir/commands/commands/review_prev_word.py @@ -0,0 +1,32 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +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 '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'], currWord = \ + word_utils.getPrevWord(self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], self.env['screenData']['newContentText']) + + if currWord.isspace(): + self.env['runtime']['outputManager'].presentText("blank", interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(currWord, interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/review_top.py b/src/fenrir/commands/commands/review_top.py new file mode 100644 index 00000000..b48f7308 --- /dev/null +++ b/src/fenrir/commands/commands/review_top.py @@ -0,0 +1,25 @@ +#!/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 '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) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/review_up.py b/src/fenrir/commands/commands/review_up.py new file mode 100644 index 00000000..9637f9e2 --- /dev/null +++ b/src/fenrir/commands/commands/review_up.py @@ -0,0 +1,30 @@ +#!/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 'set review cursor to end of current line and display the content' + + def run(self): + cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() + self.env['screenData']['newCursorReview']['x'], self.env['screenData']['newCursorReview']['y'], upChar = \ + char_utils.getUpChar(self.env['screenData']['newCursorReview']['x'],self.env['screenData']['newCursorReview']['y'], self.env['screenData']['newContentText']) + if upChar.isspace(): + self.env['runtime']['outputManager'].presentText("line is empty" ,interrupt=True) + else: + self.env['runtime']['outputManager'].presentText(upChar ,interrupt=True, ignorePunctuation=True, announceCapital=True) + + 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 new file mode 100644 index 00000000..a5582b5c --- /dev/null +++ b/src/fenrir/commands/commands/set_bookmark_1.py @@ -0,0 +1,36 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + self.ID = '1' + def initialize(self, environment): + self.env = environment + self.env['commandBuffer']['bookMarks'][self.ID] = {} + def shutdown(self): + pass + def getDescription(self): + return 'set Bookmark ' + self.ID + + def run(self): + if not self.env['commandBuffer']['Marks']['1']: + self.env['runtime']['outputManager'].presentText("No Mark found", interrupt=True) + return + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {} + + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'] = self.env['commandBuffer']['Marks']['1'].copy() + if self.env['commandBuffer']['Marks']['2']: + 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['commandBuffer']['Marks']['1'] = None + self.env['commandBuffer']['Marks']['2'] = None + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/set_bookmark_10.py b/src/fenrir/commands/commands/set_bookmark_10.py new file mode 100644 index 00000000..1e51729a --- /dev/null +++ b/src/fenrir/commands/commands/set_bookmark_10.py @@ -0,0 +1,36 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + self.ID = '10' + def initialize(self, environment): + self.env = environment + self.env['commandBuffer']['bookMarks'][self.ID] = {} + def shutdown(self): + pass + def getDescription(self): + return 'set Bookmark ' + self.ID + + def run(self): + if not self.env['commandBuffer']['Marks']['1']: + self.env['runtime']['outputManager'].presentText("No Mark found", interrupt=True) + return + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {} + + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'] = self.env['commandBuffer']['Marks']['1'].copy() + if self.env['commandBuffer']['Marks']['2']: + 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['commandBuffer']['Marks']['1'] = None + self.env['commandBuffer']['Marks']['2'] = None + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/set_bookmark_2.py b/src/fenrir/commands/commands/set_bookmark_2.py new file mode 100644 index 00000000..8087700e --- /dev/null +++ b/src/fenrir/commands/commands/set_bookmark_2.py @@ -0,0 +1,36 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + self.ID = '2' + def initialize(self, environment): + self.env = environment + self.env['commandBuffer']['bookMarks'][self.ID] = {} + def shutdown(self): + pass + def getDescription(self): + return 'set Bookmark ' + self.ID + + def run(self): + if not self.env['commandBuffer']['Marks']['1']: + self.env['runtime']['outputManager'].presentText("No Mark found", interrupt=True) + return + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {} + + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'] = self.env['commandBuffer']['Marks']['1'].copy() + if self.env['commandBuffer']['Marks']['2']: + 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['commandBuffer']['Marks']['1'] = None + self.env['commandBuffer']['Marks']['2'] = None + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/set_bookmark_3.py b/src/fenrir/commands/commands/set_bookmark_3.py new file mode 100644 index 00000000..ee00d310 --- /dev/null +++ b/src/fenrir/commands/commands/set_bookmark_3.py @@ -0,0 +1,36 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + self.ID = '3' + def initialize(self, environment): + self.env = environment + self.env['commandBuffer']['bookMarks'][self.ID] = {} + def shutdown(self): + pass + def getDescription(self): + return 'set Bookmark ' + self.ID + + def run(self): + if not self.env['commandBuffer']['Marks']['1']: + self.env['runtime']['outputManager'].presentText("No Mark found", interrupt=True) + return + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {} + + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'] = self.env['commandBuffer']['Marks']['1'].copy() + if self.env['commandBuffer']['Marks']['2']: + 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['commandBuffer']['Marks']['1'] = None + self.env['commandBuffer']['Marks']['2'] = None + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/set_bookmark_4.py b/src/fenrir/commands/commands/set_bookmark_4.py new file mode 100644 index 00000000..b983b418 --- /dev/null +++ b/src/fenrir/commands/commands/set_bookmark_4.py @@ -0,0 +1,36 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + self.ID = '4' + def initialize(self, environment): + self.env = environment + self.env['commandBuffer']['bookMarks'][self.ID] = {} + def shutdown(self): + pass + def getDescription(self): + return 'set Bookmark ' + self.ID + + def run(self): + if not self.env['commandBuffer']['Marks']['1']: + self.env['runtime']['outputManager'].presentText("No Mark found", interrupt=True) + return + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {} + + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'] = self.env['commandBuffer']['Marks']['1'].copy() + if self.env['commandBuffer']['Marks']['2']: + 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['commandBuffer']['Marks']['1'] = None + self.env['commandBuffer']['Marks']['2'] = None + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/set_bookmark_5.py b/src/fenrir/commands/commands/set_bookmark_5.py new file mode 100644 index 00000000..10dbb868 --- /dev/null +++ b/src/fenrir/commands/commands/set_bookmark_5.py @@ -0,0 +1,36 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + self.ID = '5' + def initialize(self, environment): + self.env = environment + self.env['commandBuffer']['bookMarks'][self.ID] = {} + def shutdown(self): + pass + def getDescription(self): + return 'set Bookmark ' + self.ID + + def run(self): + if not self.env['commandBuffer']['Marks']['1']: + self.env['runtime']['outputManager'].presentText("No Mark found", interrupt=True) + return + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {} + + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'] = self.env['commandBuffer']['Marks']['1'].copy() + if self.env['commandBuffer']['Marks']['2']: + 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['commandBuffer']['Marks']['1'] = None + self.env['commandBuffer']['Marks']['2'] = None + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/set_bookmark_6.py b/src/fenrir/commands/commands/set_bookmark_6.py new file mode 100644 index 00000000..43979791 --- /dev/null +++ b/src/fenrir/commands/commands/set_bookmark_6.py @@ -0,0 +1,36 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + self.ID = '6' + def initialize(self, environment): + self.env = environment + self.env['commandBuffer']['bookMarks'][self.ID] = {} + def shutdown(self): + pass + def getDescription(self): + return 'set Bookmark ' + self.ID + + def run(self): + if not self.env['commandBuffer']['Marks']['1']: + self.env['runtime']['outputManager'].presentText("No Mark found", interrupt=True) + return + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {} + + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'] = self.env['commandBuffer']['Marks']['1'].copy() + if self.env['commandBuffer']['Marks']['2']: + 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['commandBuffer']['Marks']['1'] = None + self.env['commandBuffer']['Marks']['2'] = None + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/set_bookmark_7.py b/src/fenrir/commands/commands/set_bookmark_7.py new file mode 100644 index 00000000..6fbbcbbc --- /dev/null +++ b/src/fenrir/commands/commands/set_bookmark_7.py @@ -0,0 +1,36 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + self.ID = '7' + def initialize(self, environment): + self.env = environment + self.env['commandBuffer']['bookMarks'][self.ID] = {} + def shutdown(self): + pass + def getDescription(self): + return 'set Bookmark ' + self.ID + + def run(self): + if not self.env['commandBuffer']['Marks']['1']: + self.env['runtime']['outputManager'].presentText("No Mark found", interrupt=True) + return + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {} + + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'] = self.env['commandBuffer']['Marks']['1'].copy() + if self.env['commandBuffer']['Marks']['2']: + 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['commandBuffer']['Marks']['1'] = None + self.env['commandBuffer']['Marks']['2'] = None + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/set_bookmark_8.py b/src/fenrir/commands/commands/set_bookmark_8.py new file mode 100644 index 00000000..dd87c7f4 --- /dev/null +++ b/src/fenrir/commands/commands/set_bookmark_8.py @@ -0,0 +1,36 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + self.ID = '8' + def initialize(self, environment): + self.env = environment + self.env['commandBuffer']['bookMarks'][self.ID] = {} + def shutdown(self): + pass + def getDescription(self): + return 'set Bookmark ' + self.ID + + def run(self): + if not self.env['commandBuffer']['Marks']['1']: + self.env['runtime']['outputManager'].presentText("No Mark found", interrupt=True) + return + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {} + + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'] = self.env['commandBuffer']['Marks']['1'].copy() + if self.env['commandBuffer']['Marks']['2']: + 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['commandBuffer']['Marks']['1'] = None + self.env['commandBuffer']['Marks']['2'] = None + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/set_bookmark_9.py b/src/fenrir/commands/commands/set_bookmark_9.py new file mode 100644 index 00000000..5136e375 --- /dev/null +++ b/src/fenrir/commands/commands/set_bookmark_9.py @@ -0,0 +1,36 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class command(): + def __init__(self): + self.ID = '9' + def initialize(self, environment): + self.env = environment + self.env['commandBuffer']['bookMarks'][self.ID] = {} + def shutdown(self): + pass + def getDescription(self): + return 'set Bookmark ' + self.ID + + def run(self): + if not self.env['commandBuffer']['Marks']['1']: + self.env['runtime']['outputManager'].presentText("No Mark found", interrupt=True) + return + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + self.env['commandBuffer']['bookMarks'][self.ID][currApp] = {} + + self.env['commandBuffer']['bookMarks'][self.ID][currApp]['1'] = self.env['commandBuffer']['Marks']['1'].copy() + if self.env['commandBuffer']['Marks']['2']: + 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['commandBuffer']['Marks']['1'] = None + self.env['commandBuffer']['Marks']['2'] = None + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/set_mark.py b/src/fenrir/commands/commands/set_mark.py new file mode 100644 index 00000000..fd25ba99 --- /dev/null +++ b/src/fenrir/commands/commands/set_mark.py @@ -0,0 +1,28 @@ +#!/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 '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) + return + + self.env['runtime']['cursorManager'].setMark() + self.env['runtime']['outputManager'].presentText('set mark', 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 new file mode 100644 index 00000000..61940b31 --- /dev/null +++ b/src/fenrir/commands/commands/set_window_application.py @@ -0,0 +1,28 @@ +#!/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 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']['cursorManager'].clearMarks() + else: + self.env['runtime']['outputManager'].presentText("Set window beginn 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 new file mode 100644 index 00000000..f9060aee --- /dev/null +++ b/src/fenrir/commands/commands/shut_up.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 'interrupts the current presentation' + def run(self): + if len(self.env['input']['prevDeepestInput']) > len(self.env['input']['currInput']): + return + self.env['runtime']['outputManager'].interruptOutput() + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/spell_check.py b/src/fenrir/commands/commands/spell_check.py new file mode 100644 index 00000000..363b8624 --- /dev/null +++ b/src/fenrir/commands/commands/spell_check.py @@ -0,0 +1,53 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +from utils import word_utils +initialized = False +try: + import enchant + initialized = True +except: + pass + +class command(): + def __init__(self): + self.language = '' + self.spellChecker = None + def initialize(self, environment): + self.env = environment + self.updateSpellLanguage() + def shutdown(self): + pass + def getDescription(self): + return 'checks the spelling of the current word' + 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) + return + if self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage') != self.language: + try: + self.updateSpellLanguage() + except: + return + + cursorPos = self.env['runtime']['cursorManager'].getReviewOrTextCursor() + + # get the word + newContent = self.env['screenData']['newContentText'].split('\n')[cursorPos['y']] + x, y, currWord = 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) + elif not ignore: + self.env['runtime']['outputManager'].presentText('correct',soundIcon='', interrupt=True) + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/time.py b/src/fenrir/commands/commands/time.py new file mode 100644 index 00000000..f34e9c04 --- /dev/null +++ b/src/fenrir/commands/commands/time.py @@ -0,0 +1,30 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +import datetime + +class command(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getDescription(self): + return 'presents the time' + + def run(self): + timeFormat = self.env['runtime']['settingsManager'].getSetting('general', 'timeFormat') + + # get the time formatted + timeString = datetime.datetime.strftime(datetime.datetime.now(), timeFormat) + + # present the time via speak and braile, there is no soundicon, interrupt the current speech + self.env['runtime']['outputManager'].presentText(timeString , soundIcon='', interrupt=True) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/toggle_auto_read.py b/src/fenrir/commands/commands/toggle_auto_read.py new file mode 100644 index 00000000..3090e2b2 --- /dev/null +++ b/src/fenrir/commands/commands/toggle_auto_read.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 '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) + else: + 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 new file mode 100644 index 00000000..3e6028c3 --- /dev/null +++ b/src/fenrir/commands/commands/toggle_auto_spell_check.py @@ -0,0 +1,27 @@ +#!/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 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) + else: + self.env['runtime']['outputManager'].presentText("auto spellcheck 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 new file mode 100644 index 00000000..9aed3436 --- /dev/null +++ b/src/fenrir/commands/commands/toggle_braille.py @@ -0,0 +1,27 @@ +#!/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 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']['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) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/toggle_output.py b/src/fenrir/commands/commands/toggle_output.py new file mode 100644 index 00000000..95708651 --- /dev/null +++ b/src/fenrir/commands/commands/toggle_output.py @@ -0,0 +1,34 @@ +#!/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 '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']['settingsManager'].setSetting('speech', 'enabled','False') + self.env['runtime']['settingsManager'].setSetting('sound', 'enabled','False') + self.env['runtime']['settingsManager'].setSetting('braille', 'enabled','False') + else: + 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) + + 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 new file mode 100644 index 00000000..ab43a10b --- /dev/null +++ b/src/fenrir/commands/commands/toggle_punctuation_level.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 '' + + def run(self): + self.env['runtime']['punctuationManager'].cyclePunctuation() + self.env['runtime']['outputManager'].presentText(self.env['runtime']['settingsManager'].getSetting('general', 'punctuationLevel'), 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 new file mode 100644 index 00000000..bc7c5a8a --- /dev/null +++ b/src/fenrir/commands/commands/toggle_sound.py @@ -0,0 +1,27 @@ +#!/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 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']['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) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/commands/toggle_speech.py b/src/fenrir/commands/commands/toggle_speech.py new file mode 100644 index 00000000..971c957e --- /dev/null +++ b/src/fenrir/commands/commands/toggle_speech.py @@ -0,0 +1,27 @@ +#!/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 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']['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) + + 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 new file mode 100644 index 00000000..e5ad15c8 --- /dev/null +++ b/src/fenrir/commands/commands/toggle_tutorial_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): + self.env['generalInformation']['tutorialMode'] = False + return 'You are leving 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 + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/onApplicationChange/test.py b/src/fenrir/commands/onApplicationChange/test.py new file mode 100644 index 00000000..ca4d74b6 --- /dev/null +++ b/src/fenrir/commands/onApplicationChange/test.py @@ -0,0 +1,25 @@ +#!/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/onInput/10000-shut_up.py b/src/fenrir/commands/onInput/10000-shut_up.py new file mode 100644 index 00000000..09c47165 --- /dev/null +++ b/src/fenrir/commands/onInput/10000-shut_up.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 '' + + def run(self): + if self.env['runtime']['inputManager'].noKeyPressed(): + return + if len(self.env['input']['prevDeepestInput']) > len(self.env['input']['currInput']): + return + if not self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'interruptOnKeyPress'): + return + if self.env['screenData']['newTTY'] != self.env['screenData']['oldTTY']: + return + self.env['runtime']['outputManager'].interruptOutput() + + 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 new file mode 100644 index 00000000..bb7bc291 --- /dev/null +++ b/src/fenrir/commands/onInput/45000-present_char_if_cursor_change_horizontal.py @@ -0,0 +1,38 @@ +#!/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['screenData']['newTTY'] != self.env['screenData']['oldTTY']: + 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['screenData']['newDelta'] != '': + return + if self.env['screenData']['newNegativeDelta'] != '': + return + # is it a horizontal change? + if self.env['screenData']['newCursor']['y'] != self.env['screenData']['oldCursor']['y'] or\ + self.env['screenData']['newCursor']['x'] == self.env['screenData']['oldCursor']['x']: + return + currChar = self.env['screenData']['newContentText'].split('\n')[self.env['screenData']['newCursor']['y']][self.env['screenData']['newCursor']['x']] + 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 new file mode 100644 index 00000000..528b6530 --- /dev/null +++ b/src/fenrir/commands/onInput/50000-char_echo.py @@ -0,0 +1,37 @@ +#!/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 + if self.env['runtime']['inputManager'].noKeyPressed(): + return + # is there any change? + if self.env['screenData']['newDelta'] == '': + 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 + self.env['runtime']['outputManager'].presentText(self.env['screenData']['newDelta'], 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 new file mode 100644 index 00000000..da0800f7 --- /dev/null +++ b/src/fenrir/commands/onInput/55000-present_line_if_cursor_change_vertical.py @@ -0,0 +1,38 @@ +#!/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']['newTTY'] != self.env['screenData']['oldTTY']: + return + if self.env['screenData']['newDelta'] != self.env['screenData']['oldDelta']: + return + if self.env['screenData']['newCursor']['y'] == self.env['screenData']['oldCursor']['y']: + return + if self.env['runtime']['inputManager'].noKeyPressed(): + return + currLine = self.env['screenData']['newContentText'].split('\n')[self.env['screenData']['newCursor']['y']] + 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/60000-word_echo.py b/src/fenrir/commands/onInput/60000-word_echo.py new file mode 100644 index 00000000..7474e410 --- /dev/null +++ b/src/fenrir/commands/onInput/60000-word_echo.py @@ -0,0 +1,56 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +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 'No Description found' + + def run(self): + if not self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'wordEcho'): + return + + # just when cursor move worddetection is needed + if self.env['screenData']['newCursor']['x'] == self.env['screenData']['oldCursor']['x']: + return + if self.env['runtime']['inputManager'].noKeyPressed(): + return + # for now no new line + if self.env['screenData']['newCursor']['y'] != self.env['screenData']['oldCursor']['y']: + return + if len(self.env['screenData']['newDelta']) > 1: + return + + # first place could not be the end of a word + if self.env['screenData']['newCursor']['x'] == 0: + return + + # get the word + newContent = self.env['screenData']['newContentText'].split('\n')[self.env['screenData']['newCursor']['y']] + x, y, currWord = word_utils.getCurrentWord(self.env['screenData']['newCursor']['x'], 0, newContent) + # was this a typed word? + if self.env['screenData']['newDelta'] != '': + if not(newContent[self.env['screenData']['oldCursor']['x']].strip(" \t\n") == '' and x != self.env['screenData']['oldCursor']['x']): + return + else: + # or just arrow arround? + if not(newContent[self.env['screenData']['newCursor']['x']].strip(" \t\n") == '' and x != self.env['screenData']['newCursor']['x']): + 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 new file mode 100644 index 00000000..087c37fd --- /dev/null +++ b/src/fenrir/commands/onInput/62000-spell_check.py @@ -0,0 +1,122 @@ +#!/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 + +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 self.env['runtime']['settingsManager'].getSettingAsBool('general', 'autoSpellCheck'): + return + if self.env['runtime']['inputManager'].noKeyPressed(): + return + if not initialized: + return + if self.env['runtime']['settingsManager'].getSetting('general', 'spellCheckLanguage') != self.language: + try: + self.updateSpellLanguage() + except: + return + + # just when cursor move worddetection is needed + if self.env['screenData']['newCursor']['x'] == self.env['screenData']['oldCursor']['x']: + return + + # for now no new line + if self.env['screenData']['newCursor']['y'] != self.env['screenData']['oldCursor']['y']: + return + if len(self.env['screenData']['newDelta']) > 1: + return + if self.env['screenData']['newNegativeDelta'] != '': + return + # first place could not be the end of a word + if self.env['screenData']['newCursor']['x'] == 0: + return + + # get the word + newContent = self.env['screenData']['newContentText'].split('\n')[self.env['screenData']['newCursor']['y']] + x, y, currWord = word_utils.getCurrentWord(self.env['screenData']['newCursor']['x'], 0, newContent) + # was this a typed word? + if self.env['screenData']['newDelta'] != '': + if not(newContent[self.env['screenData']['oldCursor']['x']].strip(" \t\n") == '' and x != self.env['screenData']['oldCursor']['x']): + return + else: + # or just arrow arround? + if not(newContent[self.env['screenData']['newCursor']['x']].isspace() and x != self.env['screenData']['newCursor']['x']): + return + + # ignore empty + if currWord[0] =='': + 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 new file mode 100644 index 00000000..4b20a094 --- /dev/null +++ b/src/fenrir/commands/onInput/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['screenData']['newCursor']['x'] >= self.env['screenData']['oldCursor']['x']: + return + + # More than just a deletion happend + if self.env['screenData']['newDelta'].strip() != '': + if self.env['screenData']['newDelta'] != self.env['screenData']['oldDelta']: + return + if self.env['runtime']['inputManager'].noKeyPressed(): + return + # No deletion + if self.env['screenData']['newNegativeDelta'] == '': + return + # too much for a single backspace... + if len(self.env['screenData']['newNegativeDelta']) >= 5: + return + + self.env['runtime']['outputManager'].presentText(self.env['screenData']['newNegativeDelta'], interrupt=True, ignorePunctuation=True, announceCapital=True) + + def setCallback(self, callback): + pass + diff --git a/src/fenrir/commands/onInput/80000-capslock.py b/src/fenrir/commands/onInput/80000-capslock.py new file mode 100644 index 00000000..411df45d --- /dev/null +++ b/src/fenrir/commands/onInput/80000-capslock.py @@ -0,0 +1,27 @@ +#!/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 self.env['input']['oldCapsLock'] == self.env['input']['newCapsLock']: + return + if self.env['input']['newCapsLock']: + self.env['runtime']['outputManager'].presentText("Capslock on", interrupt=False) + else: + self.env['runtime']['outputManager'].presentText("Capslock off", interrupt=False) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/onInput/80300-scrolllock.py b/src/fenrir/commands/onInput/80300-scrolllock.py new file mode 100644 index 00000000..0e6ec67c --- /dev/null +++ b/src/fenrir/commands/onInput/80300-scrolllock.py @@ -0,0 +1,27 @@ +#!/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 self.env['input']['oldScrollLock'] == self.env['input']['newScrollLock']: + return + if self.env['input']['newScrollLock']: + self.env['runtime']['outputManager'].presentText("Scrolllock on", interrupt=False) + else: + self.env['runtime']['outputManager'].presentText("Scrolllock off", interrupt=False) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/onInput/80500-numlock.py b/src/fenrir/commands/onInput/80500-numlock.py new file mode 100644 index 00000000..a2ebbc54 --- /dev/null +++ b/src/fenrir/commands/onInput/80500-numlock.py @@ -0,0 +1,27 @@ +#!/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 self.env['input']['oldNumLock'] == self.env['input']['newNumLock']: + return + if self.env['input']['newNumLock']: + self.env['runtime']['outputManager'].presentText("Numlock on", interrupt=False) + else: + self.env['runtime']['outputManager'].presentText("Numlock off", interrupt=False) + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/onInput/__init__.py b/src/fenrir/commands/onInput/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/src/fenrir/commands/onScreenChanged/10000-shut_up.py b/src/fenrir/commands/onScreenChanged/10000-shut_up.py new file mode 100644 index 00000000..6e18eb70 --- /dev/null +++ b/src/fenrir/commands/onScreenChanged/10000-shut_up.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 '' + + def run(self): + + self.env['runtime']['outputManager'].interruptOutput() + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/onScreenChanged/80000-screen_change_announcement.py b/src/fenrir/commands/onScreenChanged/80000-screen_change_announcement.py new file mode 100644 index 00000000..39b473bd --- /dev/null +++ b/src/fenrir/commands/onScreenChanged/80000-screen_change_announcement.py @@ -0,0 +1,25 @@ +#!/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']['outputManager'].presentText("screen " + str(self.env['screenData']['newTTY']),soundIcon='ChangeTTY', interrupt=True) + self.env['runtime']['outputManager'].presentText(self.env['screenData']['newContentText'], interrupt=False) + + 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 new file mode 100644 index 00000000..ff7cab4b --- /dev/null +++ b/src/fenrir/commands/onScreenChanged/85000-screen_chnage_reset_marks.py @@ -0,0 +1,25 @@ +#!/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['commandBuffer']['Marks']['1'] = None + self.env['commandBuffer']['Marks']['2'] = None + + def setCallback(self, callback): + pass + diff --git a/src/fenrir/commands/onScreenChanged/85000-screen_chnage_reset_review.py b/src/fenrir/commands/onScreenChanged/85000-screen_chnage_reset_review.py new file mode 100644 index 00000000..b63b0d5a --- /dev/null +++ b/src/fenrir/commands/onScreenChanged/85000-screen_chnage_reset_review.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'].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 new file mode 100644 index 00000000..b0b6147a --- /dev/null +++ b/src/fenrir/commands/onScreenChanged/89000-screen_chnage_leve_review_mode.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 'No Description found' + + def run(self): + self.env['runtime']['cursorManager'].clearMarks() + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/onScreenChanged/__init__.py b/src/fenrir/commands/onScreenChanged/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/src/fenrir/commands/onScreenUpdate/70000-incoming.py b/src/fenrir/commands/onScreenUpdate/70000-incoming.py new file mode 100644 index 00000000..317b9444 --- /dev/null +++ b/src/fenrir/commands/onScreenUpdate/70000-incoming.py @@ -0,0 +1,35 @@ +#!/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('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']) <= 5: + return + + self.env['runtime']['outputManager'].presentText(self.env['screenData']['newDelta'], interrupt=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 new file mode 100644 index 00000000..3ec3f43b --- /dev/null +++ b/src/fenrir/commands/onScreenUpdate/75000-incoming_promote.py @@ -0,0 +1,39 @@ +#!/bin/python +import time +# -*- 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('promote', 'enabled'): + 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']: + self.env['runtime']['outputManager'].playSoundIcon('PromotedText') + self.env['input']['lastInputTime'] = time.time() + return + + def setCallback(self, callback): + pass + diff --git a/src/fenrir/commands/onScreenUpdate/__init__.py b/src/fenrir/commands/onScreenUpdate/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/src/fenrir/commands/onSwitchApplicationProfile/__init__.py b/src/fenrir/commands/onSwitchApplicationProfile/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/fenrir/commands/onSwitchApplicationProfile/agetty.py b/src/fenrir/commands/onSwitchApplicationProfile/agetty.py new file mode 100644 index 00000000..dbd5250d --- /dev/null +++ b/src/fenrir/commands/onSwitchApplicationProfile/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['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 new file mode 100644 index 00000000..d82b6e9d --- /dev/null +++ b/src/fenrir/commands/onSwitchApplicationProfile/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['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 new file mode 100644 index 00000000..40255936 --- /dev/null +++ b/src/fenrir/commands/onSwitchApplicationProfile/default.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('default') + print('load new',self.env['screenData']['newApplication']) + print('--------------') + + def unload(self): + print('--------------') + print('default') + print('unload old',self.env['screenData']['oldApplication']) + print('--------------') + + def setCallback(self, callback): + pass diff --git a/src/fenrir/commands/onSwitchApplicationProfile/vim.py b/src/fenrir/commands/onSwitchApplicationProfile/vim.py new file mode 100644 index 00000000..74ae0c40 --- /dev/null +++ b/src/fenrir/commands/onSwitchApplicationProfile/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['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/commands/switchTrigger_template.py b/src/fenrir/commands/switchTrigger_template.py new file mode 100644 index 00000000..8efbea56 --- /dev/null +++ b/src/fenrir/commands/switchTrigger_template.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 'No description found' + def unload(self): + pass + def load(self): + pass + def setCallback(self, callback): + pass diff --git a/src/fenrir/core/__init__.py b/src/fenrir/core/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/src/fenrir/core/applicationManager.py b/src/fenrir/core/applicationManager.py new file mode 100644 index 00000000..8f127b88 --- /dev/null +++ b/src/fenrir/core/applicationManager.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 applicationManager(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def getCurrentApplication(self): + currApp = self.env['screenData']['newApplication'].upper() + if not currApp: + currApp == 'DEFAULT' + if currApp == '': + currApp == 'DEFAULT' + return currApp + def getPrevApplication(self): + prevApp = self.env['screenData']['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'] diff --git a/src/fenrir/core/commandManager.py b/src/fenrir/core/commandManager.py new file mode 100644 index 00000000..423e79ed --- /dev/null +++ b/src/fenrir/core/commandManager.py @@ -0,0 +1,127 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +import importlib.util +import glob, os, time +from core import debug + +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') + + 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') + + def loadCommands(self, section='commands'): + commandFolder = "commands/" + section +"/" + commandList = glob.glob(commandFolder+'*') + for command in commandList: + try: + fileName, fileExtension = os.path.splitext(command) + fileName = fileName.split('/')[-1] + if fileName in ['__init__','__pycache__']: + continue + 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) + self.env['commands'][section][fileName.upper()] = command_mod.command() + self.env['commands'][section][fileName.upper()].initialize(self.env) + self.env['runtime']['debug'].writeDebugOut("Load command:" + section + "." + fileName.upper() ,debug.debugLevel.INFO) + + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("Loading command:" + command ,debug.debugLevel.ERROR) + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + continue + + def shutdownCommands(self, section): + for command in sorted(self.env['commands'][section]): + try: + self.env['commands'][section][command].shutdown() + del self.env['commands'][section][command] + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("Shutdown command:" + section + "." + command ,debug.debugLevel.ERROR) + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + continue + + def executeSwitchTrigger(self, trigger, unLoadScript, loadScript): + if self.env['runtime']['screenManager'].isSuspendingScreen(): + return + #unload + oldScript = unLoadScript + if self.commandExists(oldScript, trigger): + try: + self.env['runtime']['debug'].writeDebugOut("Executing switchtrigger.unload:" + trigger + "." + oldScript ,debug.debugLevel.INFO) + self.env['commands'][trigger][oldScript].unload() + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("Executing trigger:" + trigger + "." + oldScript ,debug.debugLevel.ERROR) + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + #load + newScript = loadScript + if self.commandExists(newScript, trigger): + try: + self.env['runtime']['debug'].writeDebugOut("Executing switchtrigger.load:" + trigger + "." + newScript ,debug.debugLevel.INFO) + self.env['commands'][trigger][newScript].load() + except Exception as e: + 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 + for command in sorted(self.env['commands'][trigger]): + if self.commandExists(command, trigger): + try: + 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) + + def executeCommand(self, command, section = 'commands'): + if self.env['runtime']['screenManager'].isSuspendingScreen(): + return + if self.commandExists(command, section): + try: + if self.env['generalInformation']['tutorialMode']: + self.env['runtime']['debug'].writeDebugOut("Tutorial for command:" + section + "." + command ,debug.debugLevel.INFO) + description = self.env['commands'][section][command].getDescription() + 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.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 commandExists(self, command, section = 'commands'): + return( command in self.env['commands'][section]) diff --git a/src/fenrir/core/commands.py b/src/fenrir/core/commands.py new file mode 100644 index 00000000..3e8ead6a --- /dev/null +++ b/src/fenrir/core/commands.py @@ -0,0 +1,45 @@ +#!/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 = { +'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':{ + }, +} diff --git a/src/fenrir/core/cursorManager.py b/src/fenrir/core/cursorManager.py new file mode 100644 index 00000000..30ccb21c --- /dev/null +++ b/src/fenrir/core/cursorManager.py @@ -0,0 +1,87 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +class cursorManager(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def clearMarks(self): + self.env['commandBuffer']['Marks']['1'] = None + self.env['commandBuffer']['Marks']['2'] = None + def isMarkSet(self): + return self.env['commandBuffer']['Marks']['1'] != None + def isSingleMark(self): + return self.env['commandBuffer']['Marks']['1'] != None and \ + self.env['commandBuffer']['Marks']['2'] == None + def isMultibleMark(self): + return self.env['commandBuffer']['Marks']['1'] != None and \ + self.env['commandBuffer']['Marks']['2'] != None + def setMark(self): + if not self.env['commandBuffer']['Marks']['1']: + self.env['commandBuffer']['Marks']['1'] = self.env['screenData']['newCursorReview'].copy() + else: + self.env['commandBuffer']['Marks']['2'] = self.env['screenData']['newCursorReview'].copy() + def getReviewOrTextCursor(self): + if self.env['screenData']['newCursorReview']: + return self.env['screenData']['newCursorReview'].copy() + else: + return self.env['screenData']['newCursor'].copy() + def clearReviewCursor(self): + if not self.isReviewMode(): + return + self.env['screenData']['oldCursorReview'] = None + self.env['screenData']['newCursorReview'] = None + + def isReviewMode(self): + return self.env['screenData']['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() + 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 + def isApplicationWindowSet(self): + try: + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + if self.env['commandBuffer']['windowArea'][currApp]['1'] != None: + return True + except: + pass + return False + def setWindowForApplication(self): + if not self.env['commandBuffer']['Marks']['1']: + return False + if not self.env['commandBuffer']['Marks']['2']: + return False + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + self.env['commandBuffer']['windowArea'][currApp] = {} + + if self.env['commandBuffer']['Marks']['1']['x'] * self.env['commandBuffer']['Marks']['1']['y'] <= \ + self.env['commandBuffer']['Marks']['2']['x'] * self.env['commandBuffer']['Marks']['2']['y']: + self.env['commandBuffer']['windowArea'][currApp]['1'] = self.env['commandBuffer']['Marks']['1'].copy() + self.env['commandBuffer']['windowArea'][currApp]['2'] = self.env['commandBuffer']['Marks']['2'].copy() + else: + self.env['commandBuffer']['windowArea'][currApp]['1'] = self.env['commandBuffer']['Marks']['2'].copy() + self.env['commandBuffer']['windowArea'][currApp]['2'] = self.env['commandBuffer']['Marks']['1'].copy() + return True + def clearWindowForApplication(self): + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + try: + del self.env['commandBuffer']['windowArea'][currApp] + except: + return False + return True diff --git a/src/fenrir/core/debug.py b/src/fenrir/core/debug.py new file mode 100644 index 00000000..9b64b035 --- /dev/null +++ b/src/fenrir/core/debug.py @@ -0,0 +1,67 @@ +#!/usr/bin/python +# Debugger module for the Fenrir screen reader. + +from enum import Enum +from datetime import datetime + +class debugLevel(Enum): + DEACTIVE = 0 + ERROR = 1 + WARNING = 2 + INFO = 3 + def __int__(self): + 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): + if self.env['runtime']['settingsManager'].getSettingAsInt('general','debugLevel') < int(level): + if self._fileOpened: + self.closeDebugFile() + return + else: + if not self._fileOpened: + self.openDebugFile() + msg = str(level) +' ' + str(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f') +) + ': ' + 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/environment.py b/src/fenrir/core/environment.py new file mode 100644 index 00000000..ba768a91 --- /dev/null +++ b/src/fenrir/core/environment.py @@ -0,0 +1,26 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# 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 + +environment = { +'screenData': screenData.screenData, +'runtime': runtime.runtime, +'generalInformation': generalInformation.generalInformation, +'settings': settings.settings, +'commands': commands.commands, +'commandInfo': commands.commandInfo, +'commandBuffer': commands.commandBuffer, +'input': inputEvent.input, +'soundIcons': {}, +'bindings': {}, +} diff --git a/src/fenrir/core/generalInformation.py b/src/fenrir/core/generalInformation.py new file mode 100644 index 00000000..2a0c6013 --- /dev/null +++ b/src/fenrir/core/generalInformation.py @@ -0,0 +1,12 @@ +#!/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/inputEvent.py b/src/fenrir/core/inputEvent.py new file mode 100644 index 00000000..583aeab5 --- /dev/null +++ b/src/fenrir/core/inputEvent.py @@ -0,0 +1,32 @@ +#!/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': ['KEY_KP0'], +'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, +} diff --git a/src/fenrir/core/inputManager.py b/src/fenrir/core/inputManager.py new file mode 100644 index 00000000..ed3d4445 --- /dev/null +++ b/src/fenrir/core/inputManager.py @@ -0,0 +1,156 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +import time +from core import debug +from core import inputEvent + +class inputManager(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + self.env['runtime']['settingsManager'].loadDriver(\ + self.env['runtime']['settingsManager'].getSetting('keyboard', 'driver'), 'inputDriver') + # init LEDs with current state + self.env['input']['newNumLock'] = self.env['runtime']['inputDriver'].getNumlock() + self.env['input']['oldNumLock'] = self.env['input']['newNumLock'] + self.env['input']['newCapsLock'] = self.env['runtime']['inputDriver'].getCapslock() + self.env['input']['oldCapsLock'] = self.env['input']['newCapsLock'] + self.env['input']['newScrollLock'] = self.env['runtime']['inputDriver'].getScrollLock() + self.env['input']['oldScrollLock'] = self.env['input']['newScrollLock'] + self.grabDevices() + + def shutdown(self): + self.env['runtime']['inputManager'].releaseDevices() + self.env['runtime']['settingsManager'].shutdownDriver('inputDriver') + + def getInputEvent(self): + eventReceived = False + mEvent = self.env['runtime']['inputDriver'].getInputEvent() + if mEvent: + mEvent['EventName'] = self.convertEventName(mEvent['EventName']) + eventReceived = True + if mEvent['EventState'] == 0: + if mEvent['EventName'] in self.env['input']['currInput']: + 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'] = [] + self.env['input']['shortcutRepeat'] = 1 + 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']: + self.env['input']['shortcutRepeat'] += 1 + + elif mEvent['EventState'] == 2: + pass + else: + pass + self.env['input']['oldNumLock'] = self.env['input']['newNumLock'] + self.env['input']['newNumLock'] = self.env['runtime']['inputDriver'].getNumlock() + self.env['input']['oldCapsLock'] = self.env['input']['newCapsLock'] + self.env['input']['newCapsLock'] = self.env['runtime']['inputDriver'].getCapslock() + self.env['input']['oldScrollLock'] = self.env['input']['newScrollLock'] + self.env['input']['newScrollLock'] = self.env['runtime']['inputDriver'].getScrollLock() + self.env['input']['lastInputTime'] = time.time() + return eventReceived + + def grabDevices(self): + if self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'grabDevices'): + self.env['runtime']['inputDriver'].grabDevices() + + def releaseDevices(self): + try: + self.env['runtime']['inputDriver'].releaseDevices() + except: + pass + + def convertEventName(self, eventName): + if not eventName: + return '' + if eventName == '': + return '' + eventName = eventName.upper() + if eventName == 'KEY_LEFTCTRL': + eventName = 'KEY_CTRL' + elif eventName == 'KEY_RIGHTCTRL': + eventName = 'KEY_CTRL' + elif eventName == 'KEY_LEFTSHIFT': + eventName = 'KEY_SHIFT' + elif eventName == 'KEY_RIGHTSHIFT': + eventName = 'KEY_SHIFT' + elif eventName == 'KEY_LEFTALT': + eventName = 'KEY_ALT' + elif eventName == 'KEY_RIGHTALT': + eventName = 'KEY_ALT' + elif eventName == 'KEY_LEFTMETA': + eventName = 'KEY_META' + elif eventName == 'KEY_RIGHTMETA': + eventName = 'KEY_META' + if self.isFenrirKey(eventName): + eventName = 'KEY_FENRIR' + 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 writeEventBuffer(self): + try: + if self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'grabDevices'): + self.env['runtime']['inputDriver'].writeEventBuffer() + time.sleep(0.005) + self.clearEventBuffer() + 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']['currInput'] + + def noKeyPressed(self): + return self.env['input']['currInput'] == [] + + def getPrevDeepestInput(self): + shortcut = [] + shortcut.append(self.env['input']['shortcutRepeat']) + shortcut.append(self.env['input']['prevDeepestInput']) + + def getPrevShortcut(self): + shortcut = [] + shortcut.append(self.env['input']['shortcutRepeat']) + shortcut.append(self.env['input']['prevInput']) + return str(shortcut) + + def getCurrShortcut(self): + shortcut = [] + shortcut.append(self.env['input']['shortcutRepeat']) + shortcut.append(self.env['input']['currInput']) + return str(shortcut) + + def isFenrirKey(self, eventName): + return eventName in self.env['input']['fenrirKey'] + + def getCommandForShortcut(self, shortcut): + if not self.shortcutExists(shortcut): + return '' + return self.env['bindings'][shortcut] + + def shortcutExists(self, shortcut): + return(shortcut in self.env['bindings']) diff --git a/src/fenrir/core/outputManager.py b/src/fenrir/core/outputManager.py new file mode 100644 index 00000000..d9544005 --- /dev/null +++ b/src/fenrir/core/outputManager.py @@ -0,0 +1,123 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +import string + +class outputManager(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + self.env['runtime']['settingsManager'].loadDriver(\ + self.env['runtime']['settingsManager'].getSetting('speech', 'driver'), 'speechDriver') + self.env['runtime']['settingsManager'].loadDriver(\ + self.env['runtime']['settingsManager'].getSetting('sound', 'driver'), 'soundDriver') + + def shutdown(self): + self.env['runtime']['settingsManager'].shutdownDriver('soundDriver') + self.env['runtime']['settingsManager'].shutdownDriver('speechDriver') + + def presentText(self, text, interrupt=True, soundIcon = '', ignorePunctuation=False, announceCapital=False): + self.env['runtime']['debug'].writeDebugOut("presentText:\nsoundIcon:'"+soundIcon+"'\nText:\n" + text ,debug.debugLevel.INFO) + if self.playSoundIcon(soundIcon, interrupt): + self.env['runtime']['debug'].writeDebugOut("soundIcon found" ,debug.debugLevel.INFO) + return + toAnnounceCapital = announceCapital and len(text.strip(' \n\t')) == 1 and text.strip(' \n\t').isupper() + if toAnnounceCapital: + if self.playSoundIcon('capital', False): + toAnnounceCapital = False + + self.speakText(text, interrupt, ignorePunctuation,toAnnounceCapital) + self.brailleText(text, interrupt) + + def speakText(self, text, interrupt=True, ignorePunctuation=False, announceCapital=False): + if not self.env['runtime']['settingsManager'].getSettingAsBool('speech', 'enabled'): + self.env['runtime']['debug'].writeDebugOut("Speech disabled in outputManager.speakText",debug.debugLevel.INFO) + return + if self.env['runtime']['speechDriver'] == None: + self.env['runtime']['debug'].writeDebugOut("No speechDriver in outputManager.speakText",debug.debugLevel.ERROR) + return + if interrupt: + self.interruptOutput() + try: + self.env['runtime']['speechDriver'].setLanguage(self.env['runtime']['settingsManager'].getSetting('speech', 'language')) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("setting speech language in outputManager.speakText",debug.debugLevel.ERROR) + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + + try: + self.env['runtime']['speechDriver'].setVoice(self.env['runtime']['settingsManager'].getSetting('speech', 'voice')) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("Error while setting speech voice in outputManager.speakText",debug.debugLevel.ERROR) + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + + try: + if announceCapital: + self.env['runtime']['speechDriver'].setPitch(self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'capitalPitch')) + else: + self.env['runtime']['speechDriver'].setPitch(self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'pitch')) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("setting speech pitch in outputManager.speakText",debug.debugLevel.ERROR) + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + + try: + self.env['runtime']['speechDriver'].setRate(self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'rate')) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("setting speech rate in outputManager.speakText",debug.debugLevel.ERROR) + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + + try: + self.env['runtime']['speechDriver'].setModule(self.env['runtime']['settingsManager'].getSetting('speech', 'module')) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("setting speech module in outputManager.speakText",debug.debugLevel.ERROR) + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + + try: + self.env['runtime']['speechDriver'].setVolume(self.env['runtime']['settingsManager'].getSettingAsFloat('speech', 'volume')) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("setting speech volume in outputManager.speakText ",debug.debugLevel.ERROR) + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + + try: + text = self.env['runtime']['punctuationManager'].proceedPunctuation(text,ignorePunctuation) + self.env['runtime']['speechDriver'].speak(text) + self.env['runtime']['debug'].writeDebugOut("Speak: "+ text,debug.debugLevel.INFO) + except Exception as e: + 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): + if not self.env['runtime']['settingsManager'].getSettingAsBool('braille', 'enabled'): + return + if self.env['runtime']['brailleDriver'] == None: + return + print('braille:'+text) + + def interruptOutput(self): + self.env['runtime']['speechDriver'].cancel() + self.env['runtime']['debug'].writeDebugOut("Interrupt speech",debug.debugLevel.INFO) + + + def playSoundIcon(self, soundIcon = '', interrupt=True): + if soundIcon == '': + return False + soundIcon = soundIcon.upper() + if not self.env['runtime']['settingsManager'].getSettingAsBool('sound', 'enabled'): + self.env['runtime']['debug'].writeDebugOut("Sound disabled in outputManager.speakText",debug.debugLevel.INFO) + return False + + if self.env['runtime']['soundDriver'] == None: + self.env['runtime']['debug'].writeDebugOut("No speechDriver in outputManager.speakText",debug.debugLevel.ERROR) + return False + try: + self.env['runtime']['soundDriver'].setVolume(self.env['runtime']['settingsManager'].getSettingAsFloat('sound', 'volume')) + self.env['runtime']['soundDriver'].playSoundFile(self.env['soundIcons'][soundIcon], interrupt) + return True + except Exception as e: + self.env['runtime']['debug'].writeDebugOut("\"playSoundIcon\" in outputManager.speakText ",debug.debugLevel.ERROR) + self.env['runtime']['debug'].writeDebugOut(str(e),debug.debugLevel.ERROR) + return False diff --git a/src/fenrir/core/punctuationManager.py b/src/fenrir/core/punctuationManager.py new file mode 100644 index 00000000..2755b516 --- /dev/null +++ b/src/fenrir/core/punctuationManager.py @@ -0,0 +1,110 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +import string +from core import debug + +class punctuationManager(): + def __init__(self): + pass + def initialize(self, environment): + self.env = environment + self.allPunctNone = dict.fromkeys(map(ord, string.punctuation), ' ') + # replace with space: + # dot, comma, grave, apostrophe + for char in [ord('.'),ord(','),ord('`'),ord("'")]: + self.allPunctNone[char] = None + self.punctuation = { + 'levels':{ + 'none': '', + 'some': '#-$~+*-/\\@', + 'most': '.,:-$~+*-/\\@!#%^&*()[]}{<>;', + 'all': string.punctuation, + }, + 'punctuationDict':{ + '&':'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':{ + ':)':'smiley', + ';)':'winking face', + 'XD':'loool', + ':@':'angry face', + ':D':'lought' + } + } + def shutdown(self): + pass + def removeUnused(self, text): + return text.translate(self.allPunctNone) + + def useCustomDict(self, text, customDict): + resultText = str(text) + if customDict: + for key,item in customDict.items(): + resultText = resultText.replace(str(key),str(item)) + return resultText + def usePunctuationDict(self, text, punctuationDict, punctuation): + resultText = str(text) + + if punctuationDict and punctuation and punctuation != '': + for key,item in punctuationDict.items(): + if key in punctuation: + resultText = resultText.replace(str(key),' ' +str(item) +' ') + return resultText + + def proceedPunctuation(self, text, ignorePunctuation=False): + resultText = self.useCustomDict(text, self.punctuation['customDict']) + currPunctLevel = '' + if not ignorePunctuation and self.env['runtime']['settingsManager'].getSetting('general', 'punctuationLevel').lower() in self.punctuation['levels']: + currPunctLevel = self.punctuation['levels'][self.env['runtime']['settingsManager'].getSetting('general', 'punctuationLevel').lower()] + else: + currPunctLevel = string.punctuation + resultText = self.usePunctuationDict(resultText, self.punctuation['punctuationDict'], currPunctLevel) + resultText = self.removeUnused(resultText) + return resultText + + def cyclePunctuation(self): + punctList = list(self.punctuation['levels'].keys()) + try: + currIndex = punctList.index(self.env['runtime']['settingsManager'].getSetting('general', 'punctuationLevel').lower()) # curr punctuation + except: + return + currIndex += 1 + if currIndex >= len(punctList): + currIndex = 0 + currLevel = punctList[currIndex] + self.env['runtime']['settingsManager'].setSetting('general', currLevel.lower()) diff --git a/src/fenrir/core/runtime.py b/src/fenrir/core/runtime.py new file mode 100644 index 00000000..ad192bf6 --- /dev/null +++ b/src/fenrir/core/runtime.py @@ -0,0 +1,20 @@ +#!/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/screenData.py b/src/fenrir/core/screenData.py new file mode 100644 index 00000000..28c43bda --- /dev/null +++ b/src/fenrir/core/screenData.py @@ -0,0 +1,32 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +import time + +screenData = { +'columns': 0, +'lines': 0, +'oldDelta': '', +'oldNegativeDelta': '', +'oldCursorReview':None, +'oldCursor':{'x':0,'y':0}, +'oldContentBytes': b'', +'oldContentText': '', +'oldContentAttrib': b'', +'oldApplication': '', +'oldTTY':'-1', +'newDelta': '', +'newNegativeDelta': '', +'newCursorReview':None, +'newCursor':{'x':0,'y':0}, +'newContentBytes': b'', +'newContentText': '', +'newContentAttrib': b'', +'newTTY':'0', +'newApplication': '', +'lastScreenUpdate': time.time() +} diff --git a/src/fenrir/core/screenManager.py b/src/fenrir/core/screenManager.py new file mode 100644 index 00000000..406f5ec4 --- /dev/null +++ b/src/fenrir/core/screenManager.py @@ -0,0 +1,51 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +import time + +class screenManager(): + def __init__(self): + self.autoIgnoreScreens = [] + + def initialize(self, environment): + self.env = environment + self.env['runtime']['settingsManager'].loadDriver(\ + self.env['runtime']['settingsManager'].getSetting('screen', 'driver'), 'screenDriver') + if self.env['runtime']['settingsManager'].getSettingAsBool('screen', 'autodetectSuspendingScreen'): + self.autoIgnoreScreens = self.env['runtime']['screenDriver'].getIgnoreScreens() + + def shutdown(self): + self.env['runtime']['settingsManager'].shutdownDriver('screenDriver') + + def update(self, trigger='onUpdate'): + self.env['runtime']['screenDriver'].getCurrScreen() + self.env['screenData']['oldApplication'] = self.env['screenData']['newApplication'] + if not self.isSuspendingScreen(): + 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() + + def isSuspendingScreen(self): + return ((self.env['screenData']['newTTY'] in \ + self.env['runtime']['settingsManager'].getSetting('screen', 'suspendingScreen').split(',')) or + (self.env['screenData']['newTTY'] in self.autoIgnoreScreens)) + + def isScreenChange(self): + return self.env['screenData']['newTTY'] != self.env['screenData']['oldTTY'] + + def getWindowAreaInText(self, text): + if not self.env['runtime']['cursorManager'].isApplicationWindowSet(): + return text + windowText = '' + windowList = text.split('\n') + currApp = self.env['runtime']['applicationManager'].getCurrentApplication() + windowList = windowList[self.env['commandBuffer']['windowArea'][currApp]['1']['y']:self.env['commandBuffer']['windowArea'][currApp]['2']['y'] + 1] + for line in windowList: + windowText += line[self.env['commandBuffer']['windowArea'][currApp]['1']['x']:self.env['commandBuffer']['windowArea'][currApp]['2']['x'] + 1] + '\n' + return windowText + diff --git a/src/fenrir/core/settings.py b/src/fenrir/core/settings.py new file mode 100644 index 00000000..7e97843f --- /dev/null +++ b/src/fenrir/core/settings.py @@ -0,0 +1,68 @@ +#!/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': '', + 'voice': 'de', + 'language': 'de', + 'autoReadIncoming': True, +}, +'braille':{ + 'enabled': False, + 'layout': 'en', +}, +'screen':{ + 'driver': 'linux', + 'encoding': 'cp850', + 'screenUpdateDelay': 0.4, + 'suspendingScreen': '', + 'autodetectSuspendingScreen': False, +}, +'general':{ + 'debugLevel': debug.debugLevel.DEACTIVE, + 'punctuationLevel': 1, + 'numberOfClipboards': 10, + 'fenrirKeys': ['KEY_KP0'], + 'timeFormat': '%I:%M%P', + 'dateFormat': '%A, %B %d, %Y', + 'autoSpellCheck': False, + 'spellCheckLanguage': 'en_US', +}, +'promote':{ + 'enabled': True, + 'inactiveTimeoutSec': 120, + 'list': '', +}, +'keyboard':{ + 'driver': 'evdev', + 'device': 'all', + 'grabDevices': True, + 'ignoreShortcuts': False, + 'keyboardLayout': "desktop", + 'charEcho': False, + 'charDeleteEcho': True, + 'wordEcho': True, + 'interruptOnKeyPress': True, + 'doubleTapDelay': 0.2, +} +} diff --git a/src/fenrir/core/settingsManager.py b/src/fenrir/core/settingsManager.py new file mode 100644 index 00000000..1d404aef --- /dev/null +++ b/src/fenrir/core/settingsManager.py @@ -0,0 +1,214 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +import importlib.util +import os +from configparser import ConfigParser +from core import inputManager +from core import outputManager +from core import commandManager +from core import screenManager +from core import punctuationManager +from core import cursorManager +from core import applicationManager +from core import environment +from core.settings import settings +from core import debug + +class settingsManager(): + def __init__(self): + self.settings = settings + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + def loadShortcuts(self, kbConfigPath='../../config/keyboard/desktop.conf'): + kbConfig = open(kbConfigPath,"r") + while(True): + line = kbConfig.readline() + if not line: + break + line = line.replace('\n','') + if line.replace(" ","").startswith("#"): + continue + if line.count("=") != 1: + continue + sepLine = line.split('=') + commandName = sepLine[1].upper() + sepLine[0] = sepLine[0].replace(" ","") + sepLine[0] = sepLine[0].replace("'","") + sepLine[0] = sepLine[0].replace('"',"") + keys = sepLine[0].split(',') + shortcutKeys = [] + shortcutRepeat = 1 + shortcut = [] + for key in keys: + try: + shortcutRepeat = int(key) + except: + shortcutKeys.append(key.upper()) + shortcut.append(shortcutRepeat) + shortcut.append(sorted(shortcutKeys)) + self.env['runtime']['debug'].writeDebugOut("Shortcut: "+ str(shortcut) + ' command:' +commandName ,debug.debugLevel.INFO) + self.env['bindings'][str(shortcut)] = commandName + kbConfig.close() + + def loadSoundIcons(self, soundIconPath): + siConfig = open(soundIconPath + '/soundicons.conf',"r") + while(True): + line = siConfig.readline() + if not line: + break + line = line.replace('\n','') + if line.replace(" ","").startswith("#"): + continue + if line.count("=") != 1: + continue + Values = line.split('=') + soundIcon = Values[0].upper() + Values[1] = Values[1].replace("'","") + Values[1] = Values[1].replace('"',"") + soundIconFile = '' + if os.path.exists(Values[1]): + soundIconFile = Values[1] + else: + if not soundIconPath.endswith("/"): + soundIconPath += '/' + if os.path.exists(soundIconPath + Values[1]): + soundIconFile = soundIconPath + Values[1] + self.env['soundIcons'][soundIcon] = soundIconFile + siConfig.close() + + def loadSettings(self, settingConfigPath): + if not os.path.exists(settingConfigPath): + return False + self.env['settings'] = ConfigParser() + self.env['settings'].read(settingConfigPath) + return True + + def setSetting(self, section, setting, value): + self.env['settings'].set(section, setting, value) + + def getSetting(self, section, setting): + value = '' + try: + value = self.env['settings'].get(section, setting) + except: + value = str(self.settings[section][setting]) + return value + + def getSettingAsInt(self, section, setting): + value = 0 + try: + value = self.env['settings'].getint(section, setting) + except: + value = self.settings[section][setting] + return value + + def getSettingAsFloat(self, section, setting): + value = 0.0 + try: + value = self.env['settings'].getfloat(section, setting) + except: + value = self.settings[section][setting] + return value + + def getSettingAsBool(self, section, setting): + value = False + try: + value = self.env['settings'].getboolean(section, setting) + except: + value = self.settings[section][setting] + return value + + def loadDriver(self, driverName, driverType): + if self.env['runtime'][driverType] != None: + print('shutdown %s',driverType) + self.env['runtime'][driverType].shutdown(self.env) + spec = importlib.util.spec_from_file_location(driverName, driverType + '/' + driverName + '.py') + driver_mod = importlib.util.module_from_spec(spec) + spec.loader.exec_module(driver_mod) + self.env['runtime'][driverType] = driver_mod.driver() + self.env['runtime'][driverType].initialize(self.env) + + def shutdownDriver(self, driverType): + if self.env['runtime'][driverType] == None: + return + self.env['runtime'][driverType].shutdown() + del self.env['runtime'][driverType] + + def setFenrirKeys(self, keys): + keys = keys.upper() + keyList = keys.split(',') + for key in keyList: + if not key in self.env['input']['fenrirKey']: + self.env['input']['fenrirKey'].append(key) + + def keyIDasString(self, key): + try: + KeyID = self.getCodeForKeyID(key) + return str(KeyID) + except: + return '' + + def initFenrirConfig(self, environment = environment.environment, settingsRoot = '/etc/fenrir/', settingsFile='settings.conf'): + environment['runtime']['debug'] = debug.debug() + environment['runtime']['debug'].initialize(environment) + if not os.path.exists(settingsRoot): + if os.path.exists('../../config/'): + settingsRoot = '../../config/' + else: + return None + + environment['runtime']['settingsManager'] = self + environment['runtime']['settingsManager'].initialize(environment) + + validConfig = environment['runtime']['settingsManager'].loadSettings(settingsRoot + '/settings/' + settingsFile) + if not validConfig: + return None + self.setFenrirKeys(self.getSetting('general','fenrirKeys')) + 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')) + environment['runtime']['settingsManager'].loadShortcuts(self.getSetting('keyboard','keyboardLayout')) + if os.path.exists(settingsRoot + 'keyboard/' + self.getSetting('keyboard','keyboardLayout') + '.conf'): + self.setSetting('keyboard', 'keyboardLayout', settingsRoot + 'keyboard/' + self.getSetting('keyboard','keyboardLayout') + '.conf') + environment['runtime']['settingsManager'].loadShortcuts(self.getSetting('keyboard','keyboardLayout')) + else: + environment['runtime']['settingsManager'].loadShortcuts(self.getSetting('keyboard','keyboardLayout')) + + if not os.path.exists(self.getSetting('sound','theme') + '/soundicons.conf'): + if os.path.exists(settingsRoot + 'sound/'+ self.getSetting('sound','theme')): + self.setSetting('sound', 'theme', settingsRoot + 'sound/'+ self.getSetting('sound','theme')) + if os.path.exists(self.getSetting('sound','theme') + '/soundicons.conf'): + environment['runtime']['settingsManager'].loadSoundIcons(self.getSetting('sound','theme')) + else: + environment['runtime']['settingsManager'].loadSoundIcons(self.getSetting('sound','theme')) + + environment['runtime']['inputManager'] = inputManager.inputManager() + environment['runtime']['inputManager'].initialize(environment) + environment['runtime']['outputManager'] = outputManager.outputManager() + environment['runtime']['outputManager'].initialize(environment) + environment['runtime']['commandManager'] = commandManager.commandManager() + environment['runtime']['commandManager'].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) + + if environment['runtime']['screenManager'] == None: + environment['runtime']['screenManager'] = screenManager.screenManager() + environment['runtime']['screenManager'].initialize(environment) + + environment['runtime']['debug'].writeDebugOut('\/-------environment-------\/',debug.debugLevel.ERROR) + environment['runtime']['debug'].writeDebugOut(str(environment),debug.debugLevel.ERROR) + environment['runtime']['debug'].writeDebugOut('\/-------settings.conf-------\/',debug.debugLevel.ERROR) + environment['runtime']['debug'].writeDebugOut(str(environment['settings']._sections +),debug.debugLevel.ERROR) + return environment + diff --git a/src/fenrir/fenrir.egg-info/PKG-INFO b/src/fenrir/fenrir.egg-info/PKG-INFO new file mode 100644 index 00000000..972b1420 --- /dev/null +++ b/src/fenrir/fenrir.egg-info/PKG-INFO @@ -0,0 +1,39 @@ +Metadata-Version: 1.0 +Name: fenrir +Version: 0.1 +Summary: An TTy Screen Reader For Linux. +Home-page: https://github.com/chrys87/fenrir/ +Author: Chrys and others +Author-email: chrys@web.de +License: UNKNOWN +Description: # fenrir (Alfa) + An TTY screenreader for Linux. + Its an early alpha version. You can test it. It is not recommended for production use. If you want to help just let me know. + + # requirements + - linux + - python3 + - python-espeak + - python-evdev + - 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 + + # optional + - sox [its used by default in the generic sound driver for playing sound-icons] + - speech-dispatcher, python3-speechd [to use the speech-dispatcher driver] + - brltty, python-brlapi [for using braille] # (not implemented yet) + - gstreamer [for soundicons via gstreamer] # not working yet + - python-pyenchant for spell check functionality + + # installation + Currently there is no setupscript (sorry). But you can just run as root or setup needed permission + cd src/fenrir-package/ + sudo ./fenrir.py + Settings are located in the config directory. + +Platform: UNKNOWN diff --git a/src/fenrir/fenrir.egg-info/SOURCES.txt b/src/fenrir/fenrir.egg-info/SOURCES.txt new file mode 100644 index 00000000..ff6855fd --- /dev/null +++ b/src/fenrir/fenrir.egg-info/SOURCES.txt @@ -0,0 +1,168 @@ +setup.py +src/fenrir-package/braille/__init__.py +src/fenrir-package/braille/braille.py +src/fenrir-package/commands/__init__.py +src/fenrir-package/commands/command_template.py +src/fenrir-package/commands/switchTrigger_template.py +src/fenrir-package/commands/commands/__init__.py +src/fenrir-package/commands/commands/add_word_to_spell_check.py +src/fenrir-package/commands/commands/bookmark_1.py +src/fenrir-package/commands/commands/bookmark_10.py +src/fenrir-package/commands/commands/bookmark_2.py +src/fenrir-package/commands/commands/bookmark_3.py +src/fenrir-package/commands/commands/bookmark_4.py +src/fenrir-package/commands/commands/bookmark_5.py +src/fenrir-package/commands/commands/bookmark_6.py +src/fenrir-package/commands/commands/bookmark_7.py +src/fenrir-package/commands/commands/bookmark_8.py +src/fenrir-package/commands/commands/bookmark_9.py +src/fenrir-package/commands/commands/clear_bookmark_1.py +src/fenrir-package/commands/commands/clear_bookmark_10.py +src/fenrir-package/commands/commands/clear_bookmark_2.py +src/fenrir-package/commands/commands/clear_bookmark_3.py +src/fenrir-package/commands/commands/clear_bookmark_4.py +src/fenrir-package/commands/commands/clear_bookmark_5.py +src/fenrir-package/commands/commands/clear_bookmark_6.py +src/fenrir-package/commands/commands/clear_bookmark_7.py +src/fenrir-package/commands/commands/clear_bookmark_8.py +src/fenrir-package/commands/commands/clear_bookmark_9.py +src/fenrir-package/commands/commands/clear_clipboard.py +src/fenrir-package/commands/commands/clear_window_application.py +src/fenrir-package/commands/commands/copy_marked_to_clipboard.py +src/fenrir-package/commands/commands/curr_char_phonetic.py +src/fenrir-package/commands/commands/curr_clipboard.py +src/fenrir-package/commands/commands/curr_screen.py +src/fenrir-package/commands/commands/curr_screen_after_cursor.py +src/fenrir-package/commands/commands/curr_screen_before_cursor.py +src/fenrir-package/commands/commands/curr_word_phonetic.py +src/fenrir-package/commands/commands/cursor_position.py +src/fenrir-package/commands/commands/date.py +src/fenrir-package/commands/commands/dec_sound_volume.py +src/fenrir-package/commands/commands/dec_speech_pitch.py +src/fenrir-package/commands/commands/dec_speech_rate.py +src/fenrir-package/commands/commands/dec_speech_volume.py +src/fenrir-package/commands/commands/exit_review.py +src/fenrir-package/commands/commands/first_clipboard.py +src/fenrir-package/commands/commands/forward_keypress.py +src/fenrir-package/commands/commands/inc_sound_volume.py +src/fenrir-package/commands/commands/inc_speech_pitch.py +src/fenrir-package/commands/commands/inc_speech_rate.py +src/fenrir-package/commands/commands/inc_speech_volume.py +src/fenrir-package/commands/commands/indent_curr_line.py +src/fenrir-package/commands/commands/last_clipboard.py +src/fenrir-package/commands/commands/last_incoming.py +src/fenrir-package/commands/commands/linux_paste_clipboard.py +src/fenrir-package/commands/commands/marked_text.py +src/fenrir-package/commands/commands/next_clipboard.py +src/fenrir-package/commands/commands/present_first_line.py +src/fenrir-package/commands/commands/present_last_line.py +src/fenrir-package/commands/commands/prev_clipboard.py +src/fenrir-package/commands/commands/quit_fenrir.py +src/fenrir-package/commands/commands/remove_marks.py +src/fenrir-package/commands/commands/remove_word_from_spell_check.py +src/fenrir-package/commands/commands/review_bottom.py +src/fenrir-package/commands/commands/review_curr_char.py +src/fenrir-package/commands/commands/review_curr_line.py +src/fenrir-package/commands/commands/review_curr_word.py +src/fenrir-package/commands/commands/review_down.py +src/fenrir-package/commands/commands/review_line_begin.py +src/fenrir-package/commands/commands/review_line_end.py +src/fenrir-package/commands/commands/review_line_last_char.py +src/fenrir-package/commands/commands/review_next_char.py +src/fenrir-package/commands/commands/review_next_line.py +src/fenrir-package/commands/commands/review_next_word.py +src/fenrir-package/commands/commands/review_prev_char.py +src/fenrir-package/commands/commands/review_prev_line.py +src/fenrir-package/commands/commands/review_prev_word.py +src/fenrir-package/commands/commands/review_top.py +src/fenrir-package/commands/commands/review_up.py +src/fenrir-package/commands/commands/set_bookmark_1.py +src/fenrir-package/commands/commands/set_bookmark_10.py +src/fenrir-package/commands/commands/set_bookmark_2.py +src/fenrir-package/commands/commands/set_bookmark_3.py +src/fenrir-package/commands/commands/set_bookmark_4.py +src/fenrir-package/commands/commands/set_bookmark_5.py +src/fenrir-package/commands/commands/set_bookmark_6.py +src/fenrir-package/commands/commands/set_bookmark_7.py +src/fenrir-package/commands/commands/set_bookmark_8.py +src/fenrir-package/commands/commands/set_bookmark_9.py +src/fenrir-package/commands/commands/set_mark.py +src/fenrir-package/commands/commands/set_window_application.py +src/fenrir-package/commands/commands/shut_up.py +src/fenrir-package/commands/commands/spell_check.py +src/fenrir-package/commands/commands/time.py +src/fenrir-package/commands/commands/toggle_auto_read.py +src/fenrir-package/commands/commands/toggle_auto_spell_check.py +src/fenrir-package/commands/commands/toggle_braille.py +src/fenrir-package/commands/commands/toggle_output.py +src/fenrir-package/commands/commands/toggle_punctuation_level.py +src/fenrir-package/commands/commands/toggle_sound.py +src/fenrir-package/commands/commands/toggle_speech.py +src/fenrir-package/commands/commands/toggle_tutorial_mode.py +src/fenrir-package/commands/onInput/10000-shut_up.py +src/fenrir-package/commands/onInput/45000-present_char_if_cursor_change_horizontal.py +src/fenrir-package/commands/onInput/50000-char_echo.py +src/fenrir-package/commands/onInput/55000-present_line_if_cursor_change_vertical.py +src/fenrir-package/commands/onInput/60000-word_echo.py +src/fenrir-package/commands/onInput/62000-spell_check.py +src/fenrir-package/commands/onInput/65000-char_delete_echo.py +src/fenrir-package/commands/onInput/80000-capslock.py +src/fenrir-package/commands/onInput/80300-scrolllock.py +src/fenrir-package/commands/onInput/80500-numlock.py +src/fenrir-package/commands/onInput/__init__.py +src/fenrir-package/commands/onScreenChanged/10000-shut_up.py +src/fenrir-package/commands/onScreenChanged/80000-screen_change_announcement.py +src/fenrir-package/commands/onScreenChanged/85000-screen_chnage_reset_marks.py +src/fenrir-package/commands/onScreenChanged/85000-screen_chnage_reset_review.py +src/fenrir-package/commands/onScreenChanged/89000-screen_chnage_leve_review_mode.py +src/fenrir-package/commands/onScreenChanged/__init__.py +src/fenrir-package/commands/onScreenUpdate/70000-incoming.py +src/fenrir-package/commands/onScreenUpdate/75000-incoming_promote.py +src/fenrir-package/commands/onScreenUpdate/__init__.py +src/fenrir-package/commands/onSwitchApplicationProfile/__init__.py +src/fenrir-package/commands/onSwitchApplicationProfile/agetty.py +src/fenrir-package/commands/onSwitchApplicationProfile/bash.py +src/fenrir-package/commands/onSwitchApplicationProfile/default.py +src/fenrir-package/commands/onSwitchApplicationProfile/vim.py +src/fenrir-package/core/__init__.py +src/fenrir-package/core/applicationManager.py +src/fenrir-package/core/commandManager.py +src/fenrir-package/core/commands.py +src/fenrir-package/core/cursorManager.py +src/fenrir-package/core/debug.py +src/fenrir-package/core/environment.py +src/fenrir-package/core/generalInformation.py +src/fenrir-package/core/inputEvent.py +src/fenrir-package/core/inputManager.py +src/fenrir-package/core/outputManager.py +src/fenrir-package/core/punctuationManager.py +src/fenrir-package/core/runtime.py +src/fenrir-package/core/screenData.py +src/fenrir-package/core/screenManager.py +src/fenrir-package/core/settings.py +src/fenrir-package/core/settingsManager.py +src/fenrir-package/fenrir.egg-info/PKG-INFO +src/fenrir-package/fenrir.egg-info/SOURCES.txt +src/fenrir-package/fenrir.egg-info/dependency_links.txt +src/fenrir-package/fenrir.egg-info/entry_points.txt +src/fenrir-package/fenrir.egg-info/not-zip-safe +src/fenrir-package/fenrir.egg-info/requires.txt +src/fenrir-package/fenrir.egg-info/top_level.txt +src/fenrir-package/inputDriver/__init__.py +src/fenrir-package/inputDriver/evdev.py +src/fenrir-package/screenDriver/__init__.py +src/fenrir-package/screenDriver/linux.py +src/fenrir-package/soundDriver/__init__.py +src/fenrir-package/soundDriver/generic.py +src/fenrir-package/soundDriver/gstreamer.py +src/fenrir-package/speechDriver/__init__.py +src/fenrir-package/speechDriver/espeak.py +src/fenrir-package/speechDriver/generic.py +src/fenrir-package/speechDriver/speechd.py +src/fenrir-package/utils/__init__.py +src/fenrir-package/utils/char_utils.py +src/fenrir-package/utils/fenrir-config.py +src/fenrir-package/utils/line_utils.py +src/fenrir-package/utils/mark_utils.py +src/fenrir-package/utils/review_utils.py +src/fenrir-package/utils/word_utils.py \ No newline at end of file diff --git a/src/fenrir/fenrir.egg-info/dependency_links.txt b/src/fenrir/fenrir.egg-info/dependency_links.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/src/fenrir/fenrir.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/src/fenrir/fenrir.egg-info/entry_points.txt b/src/fenrir/fenrir.egg-info/entry_points.txt new file mode 100644 index 00000000..3beb7040 --- /dev/null +++ b/src/fenrir/fenrir.egg-info/entry_points.txt @@ -0,0 +1,3 @@ +[console_scripts] +fenrir = fenrir:fenrir + diff --git a/src/fenrir/fenrir.egg-info/not-zip-safe b/src/fenrir/fenrir.egg-info/not-zip-safe new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/src/fenrir/fenrir.egg-info/not-zip-safe @@ -0,0 +1 @@ + diff --git a/src/fenrir/fenrir.egg-info/requires.txt b/src/fenrir/fenrir.egg-info/requires.txt new file mode 100644 index 00000000..96c1e4c9 --- /dev/null +++ b/src/fenrir/fenrir.egg-info/requires.txt @@ -0,0 +1,3 @@ +evdev +sox +python-espeak diff --git a/src/fenrir/fenrir.egg-info/top_level.txt b/src/fenrir/fenrir.egg-info/top_level.txt new file mode 100644 index 00000000..787d26cb --- /dev/null +++ b/src/fenrir/fenrir.egg-info/top_level.txt @@ -0,0 +1,8 @@ +braille +commands +core +inputDriver +screenDriver +soundDriver +speechDriver +utils diff --git a/src/fenrir/fenrir.py b/src/fenrir/fenrir.py new file mode 100755 index 00000000..606b66d7 --- /dev/null +++ b/src/fenrir/fenrir.py @@ -0,0 +1,132 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +import os, sys, signal, time + +if not os.getcwd() in sys.path: + sys.path.append(os.getcwd()) + +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['runtime']['inputManager'].isFenrirKeyPressed() 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(): + 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 != '' + 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 + +if __name__ == "__main__": + app = fenrir() + app.proceed() + del app diff --git a/src/fenrir/inputDriver/__init__.py b/src/fenrir/inputDriver/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/src/fenrir/inputDriver/evdev.py b/src/fenrir/inputDriver/evdev.py new file mode 100644 index 00000000..33976591 --- /dev/null +++ b/src/fenrir/inputDriver/evdev.py @@ -0,0 +1,156 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +import evdev +import time +from evdev import InputDevice, UInput +from select import select + +from core import inputEvent +from core import debug + +class driver(): + def __init__(self): + self.iDevices = {} + self.uDevices = {} + self.ledDevices = {} + + def initialize(self, environment): + self.env = environment + self.getInputDevices() + + def shutdown(self): + pass + def getInputEvent(self): + 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() + while(event): + if not event: + return None + self.env['input']['eventBuffer'].append( [self.iDevices[fd], self.uDevices[fd], event]) + if event.code != 0: + currMapEvent = self.env['runtime']['inputDriver'].mapEvent(event) + if not currMapEvent: + return currMapEvent + if currMapEvent['EventState'] in [0,1,2]: + return currMapEvent + event = self.iDevices[fd].read_one() + return None + + def writeEventBuffer(self): + for iDevice, uDevice, event in self.env['input']['eventBuffer']: + self.writeUInput(uDevice, event) + + def clearEventBuffer(self): + del self.env['input']['eventBuffer'][:] + + def writeUInput(self, uDevice, event): + uDevice.write_event(event) + uDevice.syn() + def getInputDevices(self): + # 3 pos absolute + # 2 pos relative + # 17 LEDs + # 1 Keys + # we try to filter out mices and other stuff here + self.iDevices = map(evdev.InputDevice, (evdev.list_devices())) + self.ledDevices = map(evdev.InputDevice, (evdev.list_devices())) + 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() == 'AUTO': + 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()} + self.ledDevices = {dev.fd: dev for dev in self.ledDevices if dev.name.upper() in self.env['runtime']['settingsManager'].getSetting('keyboard', 'device').upper()} + + def mapEvent(self, event): + 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 getNumlock(self): + if self.ledDevices == {}: + return True + if self.ledDevices == None: + return True + for fd, dev in self.ledDevices.items(): + return 0 in dev.leds() + return True + + def getCapslock(self): + if self.ledDevices == {}: + return False + if self.ledDevices == None: + return False + for fd, dev in self.ledDevices.items(): + return 1 in dev.leds() + return False + + def getScrollLock(self): + if self.ledDevices == {}: + return False + if self.ledDevices == None: + return False + for fd, dev in self.ledDevices.items(): + return 2 in dev.leds() + return False + + def grabDevices(self): + 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() + + def releaseDevices(self): + 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): + self.releaseDevices() + + diff --git a/src/fenrir/screenDriver/__init__.py b/src/fenrir/screenDriver/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/src/fenrir/screenDriver/linux.py b/src/fenrir/screenDriver/linux.py new file mode 100644 index 00000000..36b3a386 --- /dev/null +++ b/src/fenrir/screenDriver/linux.py @@ -0,0 +1,143 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +import difflib +import re +import subprocess +from core import debug + +class driver(): + def __init__(self): + self.vcsaDevicePath = '/dev/vcsa' + def initialize(self, environment): + self.env = environment + def shutdown(self): + 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): + 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 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: + print(e) + 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: + print(e) + return + return + + def getIgnoreScreens(self): + xlist = [] + try: + x = subprocess.Popen('ps a -o tty,comm | grep Xorg', shell=True, stdout=subprocess.PIPE).stdout.read().decode()[:-1].split('\n') + except Exception as e: + return xlist + for i in x: + if not "grep" in i and \ + not "ps" in i: + if (i[:3].lower() == 'tty'): + xlist.append(i[3]) + return xlist + + + 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']['oldContentTextAttrib'] = self.env['screenData']['newContentAttrib'] + self.env['screenData']['oldCursor']['x'] = self.env['screenData']['newCursor']['x'] + self.env['screenData']['oldCursor']['y'] = self.env['screenData']['newCursor']['y'] + self.env['screenData']['oldDelta'] = self.env['screenData']['newDelta'] + 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']['newContentAttrib'] = self.env['screenData']['newContentBytes'][5:][::2] + self.env['screenData']['newContentText'] = self.insert_newlines(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']['oldNegativeDelta'] = '' + # always clear current deltas + self.env['screenData']['newNegativeDelta'] = '' + self.env['screenData']['newDelta'] = '' + # 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'])) + 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) + else: + diff = difflib.ndiff( oldScreenText.split('\n'),\ + newScreenText.split('\n')) + + diffList = list(diff) + + 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] == '-') diff --git a/src/fenrir/sound.py b/src/fenrir/sound.py new file mode 100755 index 00000000..14e25704 --- /dev/null +++ b/src/fenrir/sound.py @@ -0,0 +1,9 @@ +#!/bin/python + +import time + +from sound.gstreamer import sound + +s = sound() +s.playSoundFile('/home/chrys/Projekte/fenrir/fenrir/src/fenrir-package/1ChangeTTY.opus') +time.sleep(10) diff --git a/src/fenrir/soundDriver/__init__.py b/src/fenrir/soundDriver/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/src/fenrir/soundDriver/generic.py b/src/fenrir/soundDriver/generic.py new file mode 100644 index 00000000..ebbe1dc7 --- /dev/null +++ b/src/fenrir/soundDriver/generic.py @@ -0,0 +1,55 @@ +#!/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 = '' + 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' + return + def shutdown(self): + self.cancel() + return + def playFrequence(self, frequence, duration, adjustVolume): + 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 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 self.soundType == '': + return + if self.soundType == 'file': + self.proc.kill() + if self.soundType == 'frequence': + self.proc.kill() + self.soundType = '' + def setCallback(self, callback): + pass + def setVolume(self, volume): + self.volume = volume diff --git a/src/fenrir/soundDriver/gstreamer.py b/src/fenrir/soundDriver/gstreamer.py new file mode 100644 index 00000000..5e232532 --- /dev/null +++ b/src/fenrir/soundDriver/gstreamer.py @@ -0,0 +1,109 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug +import gi +import time +from gi.repository import GLib + +try: + gi.require_version('Gst', '1.0') + from gi.repository import Gst +except: + _gstreamerAvailable = False +else: + _gstreamerAvailable, args = Gst.init_check(None) + +class driver: + def __init__(self): + self._initialized = False + self._source = None + self._sink = None + self.volume = 1 + if not _gstreamerAvailable: + return + def initialize(self, environment): + if self._initialized: + return + if not _gstreamerAvailable: + return + self.env = environment + 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._initialized = True + return + def shutdown(self): + global _gstreamerAvailable + if not _gstreamerAvailable: + return + self.cancel() + self._initialized = False + _gstreamerAvailable = False + + def _onPlayerMessage(self, bus, message): + 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() + print(error, info) + print('_onPlayerMessage') + def _onPipelineMessage(self, bus, message): + 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() + print(error, info) + print('_onPipelineMessage') + + def _onTimeout(self, element): + element.set_state(Gst.State.NULL) + return False + + def playSoundFile(self, fileName, interrupt=True): + if interrupt: + self.cancel() + self._player.set_property('uri', 'file://%s' % fileName) + self._player.set_state(Gst.State.PLAYING) + print('playSoundFile') + def playFrequence(self, frequence, duration, adjustVolume, interrupt=True): + 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 _gstreamerAvailable: + 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): + self.volume = volume + + + diff --git a/src/fenrir/speechDriver/Readme.md b/src/fenrir/speechDriver/Readme.md new file mode 100644 index 00000000..de077fd4 --- /dev/null +++ b/src/fenrir/speechDriver/Readme.md @@ -0,0 +1,3 @@ +espeak = espeak driver +speechd = speech-dispatcher driver +generic = generic driver via /bin/say diff --git a/src/fenrir/speechDriver/__init__.py b/src/fenrir/speechDriver/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/src/fenrir/speechDriver/espeak.py b/src/fenrir/speechDriver/espeak.py new file mode 100644 index 00000000..18e960c0 --- /dev/null +++ b/src/fenrir/speechDriver/espeak.py @@ -0,0 +1,74 @@ +#!/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 + try: + from espeak import espeak + self._es = espeak + self._isInitialized = True + except: + self._initialized = False + def initialize(self, environment): + self.env = environment + def shutdown(self): + pass + + def speak(self,text, queueable=True): + if not self._isInitialized: + return False + if not queueable: + 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 + return self._es.set_voice(voice) + + def setPitch(self, pitch): + if not self._isInitialized: + return False + + def setRate(self, rate): + if not self._isInitialized: + return False + return self._es.set_parameter(self._es.Parameter().Rate, int(rate*450 + 80)) + + return self._es.set_parameter(self._es.Parameter().Pitch, int(pitch * 99)) + def setModule(self, module): + if not self._isInitialized: + return False + + def setLanguage(self, language): + if not self._isInitialized: + 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/generic.py b/src/fenrir/speechDriver/generic.py new file mode 100644 index 00000000..1afb8717 --- /dev/null +++ b/src/fenrir/speechDriver/generic.py @@ -0,0 +1,66 @@ +#!/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 + + 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/speechd.py b/src/fenrir/speechDriver/speechd.py new file mode 100644 index 00000000..17e8c82a --- /dev/null +++ b/src/fenrir/speechDriver/speechd.py @@ -0,0 +1,102 @@ +#!/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 = '' + try: + import speechd + self._sd = speechd.SSIPClient('fenrir') + self._isInitialized = True + except: + self._initialized = False + def initialize(self, environment): + self.env = environment + 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: + return False + if queueable == False: self.cancel() + try: + self._sd.set_synthesis_voice(self._language) + except: + pass + 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/utils/__init__.py b/src/fenrir/utils/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/src/fenrir/utils/char_utils.py b/src/fenrir/utils/char_utils.py new file mode 100644 index 00000000..344df9ff --- /dev/null +++ b/src/fenrir/utils/char_utils.py @@ -0,0 +1,90 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +def getPrevChar(currX,currY, currText): + if currText == '': + return -1, -1, '' + wrappedLines = currText.split('\n') + x = currX + y = currY + if x - 1 < 0: + if y - 1 > 0: + y -= 1 + x = len(wrappedLines[y]) - 1 + else: + x -= 1 + currChar = wrappedLines[y][x] + return x, y, currChar + +def getCurrentChar(currX,currY, currText): + if currText == '': + return -1, -1, '' + wrappedLines = currText.split('\n') + currChar = wrappedLines[currY][currX] + return currX, currY, currChar + +def getUpChar(currX,currY, currText): + if currText == '': + return -1, -1, '' + wrappedLines = currText.split('\n') + currY -= 1 + if currY < 0: + currY = 0 + currChar = wrappedLines[currY][currX] + return currX, currY, currChar + +def getDownChar(currX,currY, currText): + if currText == '': + return -1, -1, '' + wrappedLines = currText.split('\n') + currY += 1 + if currY >= len(wrappedLines): + currY = len(wrappedLines) -1 + currChar = wrappedLines[currY][currX] + return currX, currY, currChar + +def getLastCharInLine(currY, currText): + if currText == '': + return -1, -1, '' + wrappedLines = currText.split('\n') + currX = len(wrappedLines[currY].rstrip())-1 + if currX < 0: + currX = 0 + currChar = wrappedLines[currY][currX] + return currX, currY, currChar + +def getNextChar(currX,currY, currText): + if currText == '': + return -1, -1, '' + wrappedLines = currText.split('\n') + x = currX + y = currY + if x + 1 == len(wrappedLines[y]): + if y + 1 < len(wrappedLines) - 1: + y += 1 + x = 0 + else: + x += 1 + currChar = wrappedLines[y][x] + return x, y, currChar + +def getPhonetic(currChar): + if len(currChar) != 1: + return currChar + phoneticsDict = { + "A":"alpha", "B":"bravo", "C":"charlie", "D":"delta", "E":"echo", + "F":"foxtrot", "G":"golf", "H":"hotel", "I":"india", "J":"juliet", + "K":"kilo", "L":"lima", "M":"mike", "N":"november", "O":"oscar", + "P":"papa", "Q":"quebec", "R":"romeo", "S":"sierra", "T":"tango", + "U":"uniform", "V":"victor", "W":"whisky", "X":"x ray", + "Y":"yankee", "Z":"zulu" + } + try: + return phoneticsDict[currChar.upper()] + except: + return currChar diff --git a/src/fenrir/utils/fenrir-config.py b/src/fenrir/utils/fenrir-config.py new file mode 100644 index 00000000..d512ba67 --- /dev/null +++ b/src/fenrir/utils/fenrir-config.py @@ -0,0 +1,23 @@ +#!/usr/bin/python + +import configparser +import os +import sys +from os import listdir +from os.path import isfile, join +from inspect import isfunction +from xdg import BaseDirectory + +# Get configuration directory +if len(sys.argv) > 1: + configPath = sys.argv[1] +elif os.geteuid() == 0: + # Save settings system wide + configPath = "/etc/fenrir.conf" +else: + # Use local settings + configPath = BaseDirectory.xdg_data_home + "/fenrir" + if not os.path.exists(configPath): os.makedirs(configPath) + configPath = configPath + "/fenrir.conf" + + diff --git a/src/fenrir/utils/line_utils.py b/src/fenrir/utils/line_utils.py new file mode 100644 index 00000000..2de24fad --- /dev/null +++ b/src/fenrir/utils/line_utils.py @@ -0,0 +1,41 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +def getPrevLine(currX,currY, currText): + if currText == '': + return -1, -1, '' + wrappedLines = currText.split('\n') + x = currX + y = currY + if y - 1 >= 0: + y -= 1 + x = 0 + currLine = wrappedLines[y] + return x, y, currLine + +def getCurrentLine(currX,currY, currText): + if currText == '': + return -1, -1, '' + wrappedLines = currText.split('\n') + x = currX + y = currY + x = 0 + currLine = wrappedLines[y] + return x, y, currLine + +def getNextLine(currX,currY, currText): + if currText == '': + return -1, -1, '' + wrappedLines = currText.split('\n') + x = currX + y = currY + if y + 1 < len(wrappedLines): + y += 1 + x = 0 + currLine = wrappedLines[y] + return x, y, currLine diff --git a/src/fenrir/utils/mark_utils.py b/src/fenrir/utils/mark_utils.py new file mode 100644 index 00000000..d52b53f1 --- /dev/null +++ b/src/fenrir/utils/mark_utils.py @@ -0,0 +1,60 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + +def getTextBetweenMarks(firstMark, secondMark, inText): + if inText == None: + return '' + if not isinstance(inText, list): + inText = inText.split('\n') + if len(inText) < 1: + return '' + if firstMark == None: + return '' + if secondMark == None: + return '' + if (firstMark['y'] + 1) * (firstMark['x'] + 1) <= (secondMark['y'] + 1) * (secondMark['x'] + 1): + startMark = firstMark.copy() + endMark = secondMark.copy() + else: + endMark = firstMark.copy() + startMark = secondMark.copy() + textPart = '' + if startMark['y'] == endMark['y']: + textPart += inText[startMark['y']][startMark['x']:endMark['x'] + 1] + else: + currY = startMark['y'] + while currY <= endMark['y']: + if currY < endMark['y']: + if currY == startMark['y']: + textPart += inText[currY][startMark['x']:] + else: + textPart += inText[currY] + if len(inText[currY].strip()) != 0: + if len(textPart) - len(textPart.rstrip()) > 0: + textPart = textPart[:len(textPart.rstrip())] + "\n" + else: + textPart += '\n' + else: + textPart += inText[currY][:endMark['x'] + 1] + currY += 1 + return textPart + +def getTextBeforeMark(mark, inText): + if inText == None: + return '' + if mark == None: + return '' + return getTextBetweenMarks({'x':0,'y':0}, mark, inText) + +def getTextAfterMark(mark, inText): + if inText == None: + return '' + if mark == None: + return '' + inText = inText.split('\n') + return getTextBetweenMarks(mark, {'x':len(inText[0])-1,'y':len(inText)-1}, inText) diff --git a/src/fenrir/utils/review_utils.py b/src/fenrir/utils/review_utils.py new file mode 100644 index 00000000..1bca1526 --- /dev/null +++ b/src/fenrir/utils/review_utils.py @@ -0,0 +1,8 @@ +#!/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. + +from core import debug + diff --git a/src/fenrir/utils/word_utils.py b/src/fenrir/utils/word_utils.py new file mode 100644 index 00000000..aa4d30d3 --- /dev/null +++ b/src/fenrir/utils/word_utils.py @@ -0,0 +1,112 @@ +#!/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