68 lines
2.8 KiB
Python
68 lines
2.8 KiB
Python
"""One thread owns the USB handle; the GTK main loop never waits for USB."""
|
|
import queue
|
|
import threading
|
|
from gi.repository import GLib
|
|
from .controller import Controller
|
|
from .transport import DeviceError, Hidraw, discover
|
|
|
|
|
|
class Worker(threading.Thread):
|
|
def __init__(self, callback, *, device_path=None, demo=False):
|
|
super().__init__(name='btd700-usb', daemon=True)
|
|
self.callback = callback
|
|
self.device_path = device_path
|
|
self.demo = demo
|
|
self.commands = queue.Queue()
|
|
self.stopping = threading.Event()
|
|
self.controller = None
|
|
self.transport = None
|
|
|
|
def submit(self, method, args, kwargs):
|
|
self.commands.put((method, args, kwargs))
|
|
|
|
def stop(self):
|
|
self.stopping.set()
|
|
self.commands.put(None)
|
|
|
|
def run(self):
|
|
try:
|
|
while not self.stopping.is_set():
|
|
try:
|
|
action = self.commands.get(timeout=2)
|
|
except queue.Empty:
|
|
action = None
|
|
if self.stopping.is_set():
|
|
break
|
|
error = ''
|
|
try:
|
|
if self.controller is None:
|
|
if self.demo:
|
|
from .demo import DemoTransport
|
|
self.transport = DemoTransport()
|
|
else:
|
|
devices = discover()
|
|
if self.device_path:
|
|
devices = [d for d in devices if d.path == self.device_path]
|
|
if not devices:
|
|
raise DeviceError('Kein BTD 700 gefunden. Bitte den Dongle einstecken.')
|
|
if len(devices) > 1:
|
|
raise DeviceError('Mehrere BTD 700 gefunden. Mit --device /dev/hidrawN auswählen.')
|
|
self.transport = Hidraw(devices[0])
|
|
self.controller = Controller(self.transport)
|
|
if action:
|
|
method, args, kwargs = action
|
|
try:
|
|
getattr(self.controller, method)(*args, **kwargs)
|
|
except (ValueError, DeviceError, TimeoutError) as exc:
|
|
error = str(exc)
|
|
status = self.controller.snapshot()
|
|
GLib.idle_add(self.callback, status, error, bool(action))
|
|
except Exception as exc:
|
|
if self.transport:
|
|
self.transport.close()
|
|
self.transport = self.controller = None
|
|
GLib.idle_add(self.callback, None, error or str(exc), bool(action))
|
|
finally:
|
|
if self.transport:
|
|
self.transport.close()
|