def run(self): self._reset_state() while not self.finished.isSet(): try: response = self._machine.read(self._file_offset) except IOError as e: log.warning(u'Stenograph machine disconnected, reconnecting…') log.debug('Stenograph exception: %s', str(e)) self._reset_state() if self._reconnect(): log.warning('Stenograph reconnected.') self._ready() except EOFError: # File ended -- will resume normal operation after new file self._reset_state() else: if response is None: continue if not self._read_exactly_8 and len(response) == 8: self._read_exactly_8 = True content = len(response) > 0 self._file_offset += len(response) if not self._realtime and not content: self._realtime = True elif self._realtime and content and self._read_exactly_8: chords = Stenograph.process_steno_packet(response) for keys in chords: if keys: self._on_stroke(keys) self._machine.disconnect()
def _send_receive(self, request): """Send a StenoPacket and return the response or raise exceptions.""" log.debug('Requesting from Stenograph: %s', request) response = self._machine.send_receive(request) log.debug('Response from Stenograph: %s', response) if response is None: """No response implies device connection issue.""" raise IOError() elif response.packet_id == StenoPacket.ID_ERROR: """Writer may reply with an error packet""" error_number = response.p1 if error_number == 3: raise UnableToPerformRequestException() elif error_number == 7: raise FileNotAvailableException() elif error_number == 8: raise NoRealtimeFileException() elif error_number == 9: raise FinishedReadingClosedFileException() else: """Writer has returned a packet""" if (response.packet_id != request.packet_id or response.sequence_number != request.sequence_number): raise ProtocolViolationException() return response
def start_loading(self, filename): op = self.dictionaries.get(filename) if op is not None: return self.dictionaries[filename] log.debug("loading dictionary: %s", filename) op = DictionaryLoadingOperation(filename) self.dictionaries[filename] = op return op
def start_loading(self, filename): op = self.dictionaries.get(filename) if op is not None: return self.dictionaries[filename] log.debug('loading dictionary: %s', filename) op = DictionaryLoadingOperation(filename) self.dictionaries[filename] = op return op
def _open_device_by_class_interface_and_instance(class_guid): device_info = SetupDiGetClassDevs(class_guid.bytes, 0, 0, 0x12) if device_info == INVALID_HANDLE_VALUE: log.debug('dev info is invalid handle') return INVALID_HANDLE_VALUE usb_device = StenographMachine._open_device_instance( device_info, class_guid) return usb_device
def load(self): timestamp = None try: timestamp = resource_timestamp(self.filename) self.result = load_dictionary(self.filename) except Exception as e: log.debug('loading dictionary %s failed', self.filename, exc_info=True) self.result = DictionaryLoaderException(self.filename, e) self.result.timestamp = timestamp
def set_is_running(self, value): if value != self.is_running: log.debug('%s output', 'enabling' if value else 'disabling') self.is_running = value if self.is_running: self.translator.set_state(self.running_state) self.formatter.set_output(self.full_output) else: self.translator.clear_state() self.formatter.set_output(self.command_only_output) if self.machine is not None: self.machine.set_suppression(self.is_running) for callback in self.subscribers: callback(None)
def run(self): class ReadState(object): def __init__(self): self.realtime = False # Not realtime until we get a 0-length response self.realtime_file_open = False # We are reading from a file self.offset = 0 # File offset to read from def reset(self): self.__init__() state = ReadState() while not self.finished.isSet(): try: if not state.realtime_file_open: # Open realtime file self._send_receive(StenoPacket.make_open_request()) state.realtime_file_open = True response = self._send_receive( StenoPacket.make_read_request(file_offset=state.offset)) except IOError as e: log.warning(u'Stenograph writer disconnected, reconnecting…') log.debug('Stenograph exception: %s', e) # User could start a new file while disconnected. state.reset() if self._reconnect(): log.warning('Stenograph writer reconnected.') self._ready() except NoRealtimeFileException: # User hasn't started writing, just keep opening the realtime file state.reset() except FinishedReadingClosedFileException: # File closed! Open the realtime file. state.reset() else: if response.data_length: state.offset += response.data_length elif not state.realtime: state.realtime = True if response.data_length and state.realtime: for stroke in response.strokes(): self._on_stroke(stroke) self._machine.disconnect()
def run(self): settings = self.serial_port.getSettingsDict() settings['timeout'] = 0.01 self.serial_port.applySettingsDict(settings) for command in REALTIME_COMMANDS: log.debug('Palantype: sending %s', str(command)) self.serial_port.write(bytearray(command)) sleep(0.5) self._ready() while not self.finished.isSet(): if not self.serial_port.inWaiting(): self.serial_port.write(REQUEST_READ) # Request a read 5 times a second sleep(0.2) raw = self.serial_port.read(5) if raw is None: continue log.debug('Palantype: read %s', raw) try: # Look for start of chord stroke_beginning = raw.index(1) except ValueError: pass else: # Trim anything else raw = raw[stroke_beginning:] if len(raw) < 5: # Read more if it's an incomplete chord raw += self.serial_port.read(5 - len(raw)) if len(raw) == 5: keys = self._parse_packet(raw) steno_keys = self.keymap.keys_to_actions(keys) if steno_keys: self._notify(steno_keys) if self.serial_port: self.serial_port.write(END)
def set_machine(self, machine_class, machine_options=None, machine_mappings=None, reset_machine=False): if (not reset_machine and self.machine_class == machine_class and self.machine_options == machine_options and self.machine_mappings == machine_mappings): return if self.machine is not None: log.debug('stopping machine: %s', self.machine_class.__name__) self.machine.remove_state_callback(self._machine_state_callback) self.machine.remove_stroke_callback( self._translator_machine_callback) self.machine.remove_stroke_callback(log.stroke) self.machine.stop_capture() self.machine_class = None self.machine_options = None self.machine_mappings = None self.machine = None if machine_class is not None: log.debug('starting machine: %s', machine_class.__name__) machine = machine_class(machine_options) if machine_mappings is not None: machine.set_mappings(machine_mappings) machine.add_state_callback(self._machine_state_callback) machine.add_stroke_callback(log.stroke) machine.add_stroke_callback(self._translator_machine_callback) self.machine = machine self.machine_class = machine_class self.machine_options = machine_options self.machine_mappings = machine_mappings self.machine.start_capture() is_running = self.is_running else: is_running = False self.set_is_running(is_running)
def _open_device_instance(device_info, guid): dev_interface_data = DeviceInterfaceData() dev_interface_data.cbSize = sizeof(dev_interface_data) status = SetupDiEnumDeviceInterfaces(device_info, None, guid.bytes, 0, byref(dev_interface_data)) if status == 0: log.debug('status is zero') return INVALID_HANDLE_VALUE request_length = DWORD(0) # Call with None to see how big a buffer we need for detail data. SetupDiGetInterfaceDeviceDetail(device_info, byref(dev_interface_data), None, 0, pointer(request_length), None) err = GetLastError() if err != ERROR_INSUFFICIENT_BUFFER: log.debug('last error not insufficient buffer') return INVALID_HANDLE_VALUE characters = request_length.value class DeviceDetailData(Structure): _fields_ = [('cbSize', DWORD), ('DevicePath', c_char * characters)] dev_detail_data = DeviceDetailData() dev_detail_data.cbSize = 5 # Now put the actual detail data into the buffer status = SetupDiGetInterfaceDeviceDetail(device_info, byref(dev_interface_data), byref(dev_detail_data), characters, pointer(request_length), None) if not status: log.debug('not status') return INVALID_HANDLE_VALUE log.debug('okay, creating file') return CreateFile(dev_detail_data.DevicePath, 0xC0000000, 0x3, 0, 0x3, 0x80, 0)