brltty.py
3.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#brailleDisplayDrivers/brltty.py
#A part of NonVisual Desktop Access (NVDA)
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.
#Copyright (C) 2008-2010 James Teh <jamie@jantrid.net>
import time
import wx
import braille
from logHandler import log
import inputCore
try:
import brlapi
BRLAPI_CMD_KEYS = dict((code, name[8:].lower())
for name, code in brlapi.__dict__.iteritems() if name.startswith("KEY_CMD_"))
except ImportError:
pass
KEY_CHECK_INTERVAL = 50
class BrailleDisplayDriver(braille.BrailleDisplayDriver):
"""brltty braille display driver.
"""
name = "brltty"
description = "brltty"
@classmethod
def check(cls):
try:
brlapi
return True
except NameError:
pass
return False
def __init__(self):
super(BrailleDisplayDriver, self).__init__()
self._con = brlapi.Connection()
self._con.enterTtyModeWithPath()
self._keyCheckTimer = wx.PyTimer(self._handleKeyPresses)
self._keyCheckTimer.Start(KEY_CHECK_INTERVAL)
# BRLTTY simulates key presses for braille typing keys, so let BRLTTY handle them.
# NVDA may eventually implement this itself, but there's no reason to deny BRLTTY users this functionality in the meantime.
self._con.ignoreKeys(brlapi.rangeType_type, (long(brlapi.KEY_TYPE_SYM),))
def terminate(self):
super(BrailleDisplayDriver, self).terminate()
# Exceptions might be raised if initialisation failed. Just ignore them.
try:
self._keyCheckTimer.Stop()
self._keyCheckTimer = None
except:
pass
try:
# Give BRLTTY a chance to write the last piece of data to the display.
time.sleep(0.05)
self._con.leaveTtyMode()
except:
pass
def _get_numCells(self):
return self._con.displaySize[0]
def display(self, cells):
cells = "".join(chr(cell) for cell in cells)
# HACK: Temporarily work around a bug which causes brltty to freeze if data is written while there are key presses waiting.
# Simply consume and act upon any waiting key presses.
self._handleKeyPresses()
self._con.writeDots(cells)
def _handleKeyPresses(self):
while True:
try:
key = self._con.readKey(False)
except:
log.error("Error reading key press from brlapi", exc_info=True)
return
if not key:
break
key = self._con.expandKeyCode(key)
self._onKeyPress(key)
def _onKeyPress(self, key):
keyType = key["type"]
command = key["command"]
argument = key["argument"]
if keyType == brlapi.KEY_TYPE_CMD:
try:
inputCore.manager.executeGesture(InputGesture(command, argument))
except inputCore.NoInputGestureAction:
pass
gestureMap = inputCore.GlobalGestureMap({
"globalCommands.GlobalCommands": {
"braille_scrollBack": ("br(brltty):fwinlt",),
"braille_scrollForward": ("br(brltty):fwinrt",),
"braille_previousLine": ("br(brltty):lnup",),
"braille_nextLine": ("br(brltty):lndn",),
"braille_routeTo": ("br(brltty):route",),
}
})
class InputGesture(braille.BrailleDisplayGesture):
source = BrailleDisplayDriver.name
def __init__(self, command, argument):
super(InputGesture, self).__init__()
self.id = BRLAPI_CMD_KEYS[command]
if command == brlapi.KEY_CMD_ROUTE:
self.routingIndex = argument