small clean-ups in device status handling
This commit is contained in:
parent
c22fe6320d
commit
b39016df7c
|
@ -16,24 +16,23 @@ from logitech.unifying_receiver import (Receiver,
|
|||
#
|
||||
#
|
||||
|
||||
class _DUMMY_RECEIVER(object):
|
||||
__slots__ = []
|
||||
name = Receiver.name
|
||||
kind = None
|
||||
max_devices = Receiver.max_devices
|
||||
status = 'Receiver not found.'
|
||||
__bool__ = __nonzero__ = lambda self: False
|
||||
__unicode__ = __str__ = __repr__ = lambda self: 'DUMMY'
|
||||
DUMMY = _DUMMY_RECEIVER()
|
||||
|
||||
from collections import namedtuple
|
||||
_GHOST_DEVICE = namedtuple('_GHOST_DEVICE', ['number', 'name', 'kind', 'status'])
|
||||
_GHOST_DEVICE = namedtuple('_GHOST_DEVICE', ['number', 'name', 'kind', 'status', 'max_devices'])
|
||||
_GHOST_DEVICE.__bool__ = lambda self: False
|
||||
_GHOST_DEVICE.__nonzero__ = _GHOST_DEVICE.__bool__
|
||||
del namedtuple
|
||||
|
||||
def _ghost(device):
|
||||
return _GHOST_DEVICE(number=device.number, name=device.name, kind=device.kind, status=None, max_devices=None)
|
||||
|
||||
DUMMY = _GHOST_DEVICE(Receiver.number, Receiver.name, None, 'Receiver not found.', Receiver.max_devices)
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
# how often to poll devices that haven't updated their statuses on their own
|
||||
# (through notifications)
|
||||
_POLL_TICK = 60 # seconds
|
||||
|
||||
|
||||
|
@ -46,6 +45,11 @@ class ReceiverListener(_listener.EventsListener):
|
|||
self._last_tick = 0
|
||||
|
||||
self.status_changed_callback = status_changed_callback
|
||||
|
||||
# make it a bit similar with the regular devices
|
||||
receiver.kind = None
|
||||
# replace the
|
||||
receiver.handle = _listener.ThreadedHandle(receiver.handle, receiver.path)
|
||||
receiver.status = _status.ReceiverStatus(receiver, self._status_changed)
|
||||
|
||||
def has_started(self):
|
||||
|
@ -100,9 +104,12 @@ class ReceiverListener(_listener.EventsListener):
|
|||
if device.status is None:
|
||||
# device was unpaired, and since the object is weakref'ed
|
||||
# it won't be valid for much longer
|
||||
device = _GHOST_DEVICE(number=device.number, name=device.name, kind=device.kind, status=None)
|
||||
device = _ghost(device)
|
||||
|
||||
self.status_changed_callback(r, device, alert, reason)
|
||||
|
||||
if device.status is None:
|
||||
# the receiver changed status as well
|
||||
self.status_changed_callback(r)
|
||||
|
||||
def _notifications_handler(self, n):
|
||||
|
@ -117,21 +124,25 @@ class ReceiverListener(_listener.EventsListener):
|
|||
already_known = n.devnumber in self.receiver
|
||||
dev = self.receiver[n.devnumber]
|
||||
|
||||
if dev and not already_known:
|
||||
if not dev:
|
||||
_log.warn("received %s for invalid device %d: %s", n, n.devnumber, repr(dev))
|
||||
return
|
||||
|
||||
if not already_known:
|
||||
# read these as soon as possible, they will be used everywhere
|
||||
dev.protocol, dev.codename
|
||||
dev.status = _status.DeviceStatus(dev, self._status_changed)
|
||||
# the receiver changed status as well
|
||||
self._status_changed(self.receiver)
|
||||
|
||||
if dev and dev.status is not None:
|
||||
# status may be None if the device has just been unpaired
|
||||
if dev.status is not None:
|
||||
dev.status.process_notification(n)
|
||||
if self.receiver.status.lock_open and not already_known:
|
||||
# this should be the first notification after a device was paired
|
||||
assert n.sub_id == 0x41 and n.address == 0x04
|
||||
_log.info("pairing detected new device")
|
||||
self.receiver.status.new_device = dev
|
||||
else:
|
||||
_log.warn("received notification %s for invalid device %d: %s", n, n.devnumber, dev)
|
||||
|
||||
def __str__(self):
|
||||
return '<ReceiverListener(%s,%s)>' % (self.receiver.path, self.receiver.handle)
|
||||
|
@ -141,8 +152,6 @@ class ReceiverListener(_listener.EventsListener):
|
|||
def open(self, status_changed_callback=None):
|
||||
receiver = Receiver.open()
|
||||
if receiver:
|
||||
receiver.handle = _listener.ThreadedHandle(receiver.handle, receiver.path)
|
||||
receiver.kind = None
|
||||
rl = ReceiverListener(receiver, status_changed_callback)
|
||||
rl.start()
|
||||
return rl
|
||||
|
|
|
@ -183,6 +183,7 @@ def update(frame):
|
|||
return
|
||||
|
||||
device_active = bool(device.status)
|
||||
# if the device just became active, re-read the settings
|
||||
force_read |= device_active and not box.get_sensitive()
|
||||
box.set_sensitive(device_active)
|
||||
if device_active:
|
||||
|
|
|
@ -424,10 +424,10 @@ def update(window, receiver, device=None):
|
|||
frames = list(vbox.get_children())
|
||||
assert len(frames) == 1 + receiver.max_devices, frames
|
||||
|
||||
if device:
|
||||
_update_device_box(frames[device.number], None if device.status is None else device)
|
||||
else:
|
||||
if device is None:
|
||||
_update_receiver_box(frames[0], receiver)
|
||||
if not receiver:
|
||||
for frame in frames[1:]:
|
||||
_update_device_box(frame, None)
|
||||
else:
|
||||
_update_device_box(frames[device.number], None if device.status is None else device)
|
||||
|
|
|
@ -78,7 +78,7 @@ def _icon_with_battery(level, active):
|
|||
|
||||
def update(icon, receiver, device=None):
|
||||
# print ("icon update", receiver, receiver.status, len(receiver), device)
|
||||
if device:
|
||||
if device is not None:
|
||||
icon._devices[device.number] = None if device.status is None else device
|
||||
if not receiver:
|
||||
icon._devices[:] = _NO_DEVICES
|
||||
|
|
|
@ -148,11 +148,11 @@ class EventsListener(_threading.Thread):
|
|||
|
||||
if n:
|
||||
# if _log.isEnabledFor(_DEBUG):
|
||||
# _log.debug("processing notification %s", n)
|
||||
# _log.debug("processing %s", n)
|
||||
try:
|
||||
self._notifications_callback(n)
|
||||
except:
|
||||
_log.exception("processing notification %s", n)
|
||||
_log.exception("processing %s", n)
|
||||
elif self.tick_period:
|
||||
idle_reads += 1
|
||||
if idle_reads % _IDLE_READS == 0:
|
||||
|
@ -189,7 +189,7 @@ class EventsListener(_threading.Thread):
|
|||
# i.e. triggered by a callback handling a previous notification.
|
||||
if self._active and _threading.current_thread() == self:
|
||||
if _log.isEnabledFor(_DEBUG):
|
||||
_log.debug("queueing unhandled notification %s", n)
|
||||
_log.debug("queueing unhandled %s", n)
|
||||
self._queued_notifications.put(n)
|
||||
|
||||
def __bool__(self):
|
||||
|
|
|
@ -176,26 +176,14 @@ class PairedDevice(object):
|
|||
return self.number
|
||||
__int__ = __index__
|
||||
|
||||
def __lt__(self, other):
|
||||
return self.number < other.number
|
||||
|
||||
def __le__(self, other):
|
||||
return self.number <= other.number
|
||||
|
||||
def __gt__(self, other):
|
||||
return self.number > other.number
|
||||
|
||||
def __ge__(self, other):
|
||||
return self.number >= other.number
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.receiver == other.receiver and self.number == other.number
|
||||
return self.serial == other.serial
|
||||
|
||||
def __ne__(self, other):
|
||||
return self.receiver != other.receiver or self.number != other.number
|
||||
return self.serial != other.serial
|
||||
|
||||
def __hash__(self):
|
||||
return self.number
|
||||
return self.serial.__hash__()
|
||||
|
||||
def __str__(self):
|
||||
return '<PairedDevice(%d,%s)>' % (self.number, self.codename or '?')
|
||||
|
@ -210,6 +198,7 @@ class Receiver(object):
|
|||
|
||||
The paired devices are available through the sequence interface.
|
||||
"""
|
||||
number = 0xFF
|
||||
name = 'Unifying Receiver'
|
||||
kind = None
|
||||
max_devices = MAX_PAIRED_DEVICES
|
||||
|
@ -220,7 +209,6 @@ class Receiver(object):
|
|||
assert path
|
||||
self.path = path
|
||||
|
||||
self.number = 0xFF
|
||||
self._serial = None
|
||||
self._firmware = None
|
||||
self._devices = {}
|
||||
|
|
|
@ -186,11 +186,7 @@ class DeviceStatus(dict):
|
|||
if n.sub_id >= 0x40:
|
||||
return self._process_hidpp10_notification(n)
|
||||
|
||||
# if n.sub_id >= len(self._device.features):
|
||||
# _log.warn("%s: notification from invalid feature index %02X", self._device, n.sub_id)
|
||||
# return False
|
||||
|
||||
# assuming 0x00 to 0x3F are device feature (HID++ 2.0) notifications
|
||||
# assuming 0x00 to 0x3F are feature (HID++ 2.0) notifications
|
||||
try:
|
||||
feature = self._device.features[n.sub_id]
|
||||
except IndexError:
|
||||
|
|
Loading…
Reference in New Issue