alvaBC6.py
5.64 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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#brailleDisplayDrivers/alvaBC6.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) 2009-2011 Optelec B.V. <http://www.optelec.com/>, James Teh <jamie@jantrid.net>
import braille
import queueHandler
from logHandler import log
from ctypes import *
from ctypes.wintypes import *
import time
import config
import inputCore
ALVA_RELEASE_MASK = 0x8000
ALVA_2ND_CR_MASK = 0x80
ALVA_KEYS = {
# Thumb keys (FRONT_GROUP)
0x71: ("t1", "t2", "t3", "t4", "t5",
# Only for BC680
"t1", "t2", "t3", "t4", "t5"),
# eTouch keys (ETOUCH_GROUP)
0x72: ("etouch1", "etouch2", "etouch3", "etouch4"),
# Smartpad keys (PDA_GROUP)
0x73: ("sp1", "sp2", "spLeft", "spEnter", "spUp", "spDown", "spRight", "sp3", "sp4",
# Only for BC680
"sp1", "sp2", "spLeft", "spEnter", "spUp", "spDown", "spRight", "sp3", "sp4")
}
ALVA_CR_GROUP = 0x74
ALVA_MODIFIER_GROUP = 0x75
ALVA_ASCII_GROUP = 0x76
ALVA_PKEYCALLBACK = CFUNCTYPE(BOOL, c_int, USHORT, c_void_p)
#Try to load alvaw32.dll
try:
AlvaLib=windll[r"brailleDisplayDrivers\alvaw32.dll"]
except:
AlvaLib=None
class BrailleDisplayDriver(braille.BrailleDisplayDriver):
name = "alvaBC6"
# Translators: The name of a braille display.
description = _("ALVA BC640/680 series")
@classmethod
def check(cls):
return bool(AlvaLib)
def __init__(self):
super(BrailleDisplayDriver,self).__init__()
log.debug("ALVA BC6xx Braille init")
_AlvaNumDevices=c_int(0)
AlvaLib.AlvaScanDevices(byref(_AlvaNumDevices))
if _AlvaNumDevices.value==0:
raise RuntimeError("No ALVA display found")
log.debug("%d devices found" %_AlvaNumDevices.value)
AlvaLib.AlvaOpen(0)
self._alva_NumCells = 0
self._keysDown = set()
self._ignoreKeyReleases = False
self._keyCallbackInst = ALVA_PKEYCALLBACK(self._keyCallback)
AlvaLib.AlvaSetKeyCallback(0, self._keyCallbackInst, None)
def terminate(self):
super(BrailleDisplayDriver, self).terminate()
AlvaLib.AlvaClose(1)
# Drop the ctypes function instance for the key callback,
# as it is holding a reference to an instance method, which causes a reference cycle.
self._keyCallbackInst = None
def _get_numCells(self):
if self._alva_NumCells==0:
NumCells = c_int(0)
AlvaLib.AlvaGetCells(0, byref(NumCells))
if NumCells.value==0:
raise RuntimeError("Cannot obtain number of cells")
self._alva_NumCells = NumCells.value
log.info("ALVA BC6xx has %d cells" %self._alva_NumCells)
return self._alva_NumCells
def display(self, cells):
cells="".join([chr(x) for x in cells])
AlvaLib.AlvaSendBraille(0, cells, 0, len(cells))
def _keyCallback(self, dev, key, userData):
group = (key >> 8) & 0x7F
number = key & 0xFF
if key & ALVA_RELEASE_MASK:
# Release.
if not self._ignoreKeyReleases and self._keysDown:
try:
inputCore.manager.executeGesture(InputGesture(self._keysDown))
except inputCore.NoInputGestureAction:
pass
# Any further releases are just the rest of the keys in the combination being released,
# so they should be ignored.
self._ignoreKeyReleases = True
self._keysDown.discard((group, number))
else:
# Press.
if group == ALVA_CR_GROUP:
# Execute routing keys when pressed instead of released.
try:
inputCore.manager.executeGesture(InputGesture(((group, number),)))
except inputCore.NoInputGestureAction:
pass
else:
self._keysDown.add((group, number))
# This begins a new key combination.
self._ignoreKeyReleases = False
return False
gestureMap = inputCore.GlobalGestureMap({
"globalCommands.GlobalCommands": {
"braille_scrollBack": ("br(alvaBC6):t1","br(alvaBC6):etouch1"),
"braille_previousLine": ("br(alvaBC6):t2",),
"braille_toFocus": ("br(alvaBC6):t3",),
"braille_nextLine": ("br(alvaBC6):t4",),
"braille_scrollForward": ("br(alvaBC6):t5","br(alvaBC6):etouch3"),
"braille_routeTo": ("br(alvaBC6):routing",),
"review_top": ("br(alvaBC6):t1+t2",),
"review_bottom": ("br(alvaBC6):t4+t5",),
"braille_toggleTether": ("br(alvaBC6):t1+t3",),
"braille_cycleCursorShape": ("br(alvaBC6):t1+t4",),
"braille_toggleShowCursor": ("br(alvaBC6):t2+t5",),
"title": ("br(alvaBC6):etouch2",),
"reportStatusLine": ("br(alvaBC6):etouch4",),
"kb:shift+tab": ("br(alvaBC6):sp1",),
"kb:alt": ("br(alvaBC6):sp2",),
"kb:escape": ("br(alvaBC6):sp3",),
"kb:tab": ("br(alvaBC6):sp4",),
"kb:upArrow": ("br(alvaBC6):spUp",),
"kb:downArrow": ("br(alvaBC6):spDown",),
"kb:leftArrow": ("br(alvaBC6):spLeft",),
"kb:rightArrow": ("br(alvaBC6):spRight",),
"kb:enter": ("br(alvaBC6):spEnter",),
"dateTime": ("br(alvaBC6):sp1+sp2",),
"showGui": ("br(alvaBC6):sp1+sp3",),
"kb:windows+d": ("br(alvaBC6):sp1+sp4",),
"kb:windows+b": ("br(alvaBC6):sp3+sp4",),
"kb:windows": ("br(alvaBC6):sp2+sp3",),
"kb:alt+tab": ("br(alvaBC6):sp2+sp4",),
"kb:control+home": ("br(alvaBC6):t3+spUp",),
"kb:control+end": ("br(alvaBC6):t3+spDown",),
"kb:home": ("br(alvaBC6):t3+spLeft",),
"kb:end": ("br(alvaBC6):t3+spRight",),
}
})
class InputGesture(braille.BrailleDisplayGesture):
source = BrailleDisplayDriver.name
def __init__(self, keys):
super(InputGesture, self).__init__()
self.keyCodes = set(keys)
self.keyNames = names = set()
for group, number in self.keyCodes:
if group == ALVA_CR_GROUP:
if number & ALVA_2ND_CR_MASK:
names.add("routing2")
self.routingIndex = number & ~ALVA_2ND_CR_MASK
else:
names.add("routing")
self.routingIndex = number
else:
try:
names.add(ALVA_KEYS[group][number])
except (KeyError, IndexError):
log.debugWarning("Unknown key with group %d and number %d" % (group, number))
self.id = "+".join(names)