From 57c759773a8d8ede1911d9198b01c289d5936afb Mon Sep 17 00:00:00 2001 From: Daniel Pavel Date: Mon, 17 Jun 2013 08:51:55 +0200 Subject: [PATCH] attach configuration to device settings objects --- lib/logitech/unifying_receiver/settings.py | 25 ++++---- lib/logitech/unifying_receiver/status.py | 7 +-- lib/solaar/configuration.py | 66 +++------------------- lib/solaar/ui/config_panel.py | 4 +- 4 files changed, 28 insertions(+), 74 deletions(-) diff --git a/lib/logitech/unifying_receiver/settings.py b/lib/logitech/unifying_receiver/settings.py index fa9078e8..571f8e96 100644 --- a/lib/logitech/unifying_receiver/settings.py +++ b/lib/logitech/unifying_receiver/settings.py @@ -16,9 +16,8 @@ from .common import NamedInt as _NamedInt, NamedInts as _NamedInts KIND = _NamedInts(toggle=0x1, choice=0x02, range=0x12) class _Setting(object): - __slots__ = ['name', 'label', 'description', - 'kind', '_rw', '_validator', - '_device', '_value'] + __slots__ = ['name', 'label', 'description', 'kind', 'persister', + '_rw', '_validator', '_device', '_value'] def __init__(self, name, rw, validator, kind=None, label=None, description=None): assert name @@ -31,6 +30,7 @@ class _Setting(object): assert kind is None or kind & validator.kind != 0 self.kind = kind or validator.kind + self.persister = None def __call__(self, device): o = _copy(self) @@ -43,14 +43,17 @@ class _Setting(object): return self._validator.choices if self._validator.kind & KIND.choice else None def read(self, cached=True): + if cached and self._value is not None: + if self.persister and self.name not in self.persister: + self.persister[self.name] = self._value + return self._value + if self._device: - if self._value is None or not cached: - reply = self._rw.read(self._device) - # print ("read reply", repr(reply)) - if reply: - # print ("pre-read", self._value) - self._value = self._validator.validate_read(reply) - # print ("post-read", self._value) + reply = self._rw.read(self._device) + if reply: + self._value = self._validator.validate_read(reply) + if self.persister and self.name not in self.persister: + self.persister[self.name] = self._value return self._value def write(self, value): @@ -59,6 +62,8 @@ class _Setting(object): reply = self._rw.write(self._device, data_bytes) if reply: self._value = self._validator.validate_write(value, reply) + if self.persister and self._value is not None: + self.persister[self.name] = self._value return self._value def __str__(self): diff --git a/lib/logitech/unifying_receiver/status.py b/lib/logitech/unifying_receiver/status.py index 4f2f66fb..e640b112 100644 --- a/lib/logitech/unifying_receiver/status.py +++ b/lib/logitech/unifying_receiver/status.py @@ -218,9 +218,8 @@ class DeviceStatus(dict): # get cleared when the device is turned off (but not when the device # goes idle, and we can't tell the difference right now). d.enable_notifications() - d.settings, None if self.configuration: - self.configuration.apply_to(d) + self.configuration.attach_to(d) else: if was_active: battery = self.get(BATTERY_LEVEL) @@ -229,8 +228,6 @@ class DeviceStatus(dict): # to change much while the device is offline. if battery is not None: self[BATTERY_LEVEL] = battery - if self.configuration: - self.configuration.acquire_from(d) if self.updated == 0 and active: # if the device is active on the very first status notification, @@ -360,7 +357,7 @@ class DeviceStatus(dict): _log.warn("%s: connection notification with unknown protocol %02X: %s", self._device.number, n.address, n) # if the device just came online, read the battery charge - if self._active: # and BATTERY_LEVEL not in self: + if self._active and BATTERY_LEVEL not in self: self.read_battery() return True diff --git a/lib/solaar/configuration.py b/lib/solaar/configuration.py index 640cf17e..e08abe38 100644 --- a/lib/solaar/configuration.py +++ b/lib/solaar/configuration.py @@ -67,6 +67,7 @@ def all(): def _device_key(device): return '%s:%s' % (device.serial, device.kind) + def _device_entry(device): if not _configuration: _load() @@ -81,66 +82,17 @@ def _device_entry(device): return c -def set(key, value): - set(None, key, value) - - -def get(key, default_value=None): - return - - -def set_device(device, key, value): - _device_entry(device)[key] = value - - -def get_device(device, key, default_value=None): - return _device_entry(device).get(key, default_value) - - -def apply_to(device): +def attach_to(device): """Apply the last saved configuration to a device.""" if not _configuration: _load() - entry = _device_entry(device) - if _log.isEnabledFor(_DEBUG): - _log.debug("applying %s to %s", entry, device) - + persister = _device_entry(device) for s in device.settings: - value = s.read() - if s.name in entry: - if value is None: - del entry[s.name] - elif value != entry[s.name]: - s.write(entry[s.name]) + if s.persister is None: + s.persister = persister + assert s.persister == persister + if s.name in persister: + s.write(persister[s.name]) else: - entry[s.name] = value - - -def acquire_from(device): - """Read the values of all the settings a device has, and save them.""" - if not _configuration: - _load() - - entry = _device_entry(device) - for s in device.settings: - value = s.read() - if value is not None: - entry[s.name] = value - - if _log.isEnabledFor(_DEBUG): - _log.debug("acquired %s from %s", entry, device) - - save() - - -def forget(device): - if not _configuration: - _load() - - if _log.isEnabledFor(_DEBUG): - _log.debug("forgetting %s", device) - - device_key = _device_key(device) - if device_key in _configuration: - del _configuration[device_key] + persister[s.name] = s.read(cached=False) diff --git a/lib/solaar/ui/config_panel.py b/lib/solaar/ui/config_panel.py index 8663675c..d3950e68 100644 --- a/lib/solaar/ui/config_panel.py +++ b/lib/solaar/ui/config_panel.py @@ -186,11 +186,11 @@ def update(frame): if device.status: items = list(_add_settings(box, device)) assert len(device.settings) == len(items) - force_read = True + # force_read = True device_active = bool(device.status) # if the device just became active, re-read the settings - force_read |= device_active and not box.get_sensitive() + # force_read |= device_active and not box.get_sensitive() box.set_sensitive(device_active) if device_active: for sbox, s in zip(items, device.settings):