add unicode sending to the protocol

This commit is contained in:
Charlotte 🦝 Delenk 2022-10-05 13:07:29 +01:00
parent f11d7586a9
commit 1326e78b59
Signed by: darkkirb
GPG key ID: AB2BD8DAF2E37122
2 changed files with 45 additions and 7 deletions

View file

@ -10,6 +10,7 @@ The order of the buttons (from left to right) is the same as in `KEYS_LAYOUT`.
Most buttons have the same names as in GeminiPR, except for the extra buttons
which are called X1-X26.
'''
from plover.engine import StenoEngine
from plover.machine.base import ThreadedStenotypeBase
from plover import log
@ -18,6 +19,7 @@ import hid
import platform
import threading
import time
from typing import Optional
# This is a hack to not open the hid device in exclusive mode on
# darwin, if the version of hidapi installed is current enough
@ -27,7 +29,7 @@ if platform.system() == "Darwin":
hid.hidapi.hid_darwin_set_open_exclusive.argtypes = (ctypes.c_int, )
hid.hidapi.hid_darwin_set_open_exclusive.restype = None
hid.hidapi.hid_darwin_set_open_exclusive(0)
except AttributeError as e:
except AttributeError:
log.error("hidapi < 0.12 in use, plover-hid will not work correctly")
USAGE_PAGE: int = 0xFF60
@ -40,12 +42,35 @@ N_LEVERS: int = 80
SIMPLE_REPORT_TYPE: int = 0x62
SIMPLE_REPORT_LEN: int = 32
class InvalidReport(Exception):
pass
STENO_KEY_CHART = tuple(f"X{i}" for i in range(1, N_LEVERS + 1))
print('steno key chart', len(STENO_KEY_CHART))
class UnicodeSender:
def __init__(self, engine: StenoEngine):
self._engine = engine
def start(self):
global unicode_sender
unicode_sender = self
def stop(self):
global unicode_sender
unicode_sender = None
def send_string(self, string: str):
self._engine.keyboard_emulation.send_string(string)
unicode_sender: Optional[UnicodeSender] = None
class HidMachine(ThreadedStenotypeBase):
KEYS_LAYOUT: str = '''
X1 X2 X3 X4 X5 X6 X7 X8 X9 X10
@ -57,17 +82,26 @@ class HidMachine(ThreadedStenotypeBase):
X61 X62 X63 X64 X65 X66 X67 X68 X69 X70
X71 X72 X73 X74 X75 X76 X77 X78 X79 X80
'''
def __init__(self, params):
super().__init__()
self._params = params
self._hid = None
def _parse(self, report):
def _parse(self, report: bytes) -> Optional[BitString]:
if len(report) != SIMPLE_REPORT_LEN:
raise InvalidReport()
if report[:3] != b"STN":
if report[:3] == b"STN":
return BitString(bytes=report[3:13])
elif report[:3] == b"UNI":
try:
s = report[3:].decode("UTF-8").strip('\0')
if unicode_sender is not None:
unicode_sender.send_string(s)
except UnicodeDecodeError:
raise InvalidReport()
else:
raise InvalidReport()
return BitString(bytes=report[3:13])
def _ping_thread(self):
while not self.finished.wait(0):
@ -89,6 +123,8 @@ class HidMachine(ThreadedStenotypeBase):
continue
try:
report = self._parse(report)
if report is None:
continue
except InvalidReport:
continue
keystate |= report
@ -109,14 +145,15 @@ class HidMachine(ThreadedStenotypeBase):
devices = [
device["path"]
for device in hid.enumerate()
if device["usage_page"] == USAGE_PAGE and device["usage"] == USAGE
if device["usage_page"] == USAGE_PAGE
and device["usage"] == USAGE
]
if not devices:
self._error()
return
# FIXME: if multiple compatible devices are found we should either
# let the end user configure which one they want, or support reading
# from all connected plover hid devices at the same time.
# let the end user configure which one they want, or support
# reading from all connected plover hid devices at the same time.
self._hid = hid.Device(path=devices[0])
except hid.HIDException:
self._error()

View file

@ -16,3 +16,4 @@ py_modules =
[options.entry_points]
plover.machine =
Plover HID = plover_machine_hid:HidMachine
plover.extension = plover_machine_hid:UnicodeSender