load the configuration when the device is detected
and apply it every time the device comes online
This commit is contained in:
parent
1d438f098f
commit
8d5718178f
|
@ -33,6 +33,7 @@ class _Setting(object):
|
|||
self.persister = None
|
||||
|
||||
def __call__(self, device):
|
||||
assert not hasattr(self, '_value')
|
||||
o = _copy(self)
|
||||
o._value = None
|
||||
o._device = device # _proxy(device)
|
||||
|
@ -43,12 +44,15 @@ class _Setting(object):
|
|||
return self._validator.choices if self._validator.kind & KIND.choice else None
|
||||
|
||||
def read(self, cached=True):
|
||||
if self._value is None and self.persister:
|
||||
self._value = self.persister.get(self.name)
|
||||
|
||||
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._device.online:
|
||||
reply = self._rw.read(self._device)
|
||||
if reply:
|
||||
self._value = self._validator.validate_read(reply)
|
||||
|
@ -66,6 +70,10 @@ class _Setting(object):
|
|||
self.persister[self.name] = self._value
|
||||
return self._value
|
||||
|
||||
def apply(self):
|
||||
if self._value is not None:
|
||||
self.write(self._value)
|
||||
|
||||
def __str__(self):
|
||||
if hasattr(self, '_value'):
|
||||
assert hasattr(self, '_device')
|
||||
|
@ -73,6 +81,9 @@ class _Setting(object):
|
|||
return '<Setting([%s:%s] %s)>' % (self._rw.kind, self._validator.kind, self.name)
|
||||
__unicode__ = __repr__ = __str__
|
||||
|
||||
#
|
||||
# read/write low-level operators
|
||||
#
|
||||
|
||||
class _RegisterRW(object):
|
||||
__slots__ = ['register']
|
||||
|
@ -111,6 +122,10 @@ class _FeatureRW(object):
|
|||
assert self.feature is not None
|
||||
return device.feature_request(self.feature, self.write_fnid, data_bytes)
|
||||
|
||||
#
|
||||
# value validators
|
||||
# handle the conversion from read bytes, to setting value, and back
|
||||
#
|
||||
|
||||
class _BooleanValidator(object):
|
||||
__slots__ = ['true_value', 'false_value', 'mask', 'write_returns_value']
|
||||
|
@ -118,6 +133,7 @@ class _BooleanValidator(object):
|
|||
kind = KIND.toggle
|
||||
default_true = 0x01
|
||||
default_false = 0x00
|
||||
# mask specifies all the affected bits in the value
|
||||
default_mask = 0xFF
|
||||
|
||||
def __init__(self, true_value=default_true, false_value=default_false, mask=default_mask, write_returns_value=False):
|
||||
|
@ -191,7 +207,7 @@ class _ChoicesValidator(object):
|
|||
return self.choices[value]
|
||||
|
||||
#
|
||||
#
|
||||
# pre-defined basic setting descriptors
|
||||
#
|
||||
|
||||
def register_toggle(name, register,
|
||||
|
|
|
@ -136,9 +136,6 @@ class DeviceStatus(dict):
|
|||
# timestamp of when this status object was last updated
|
||||
self.updated = 0
|
||||
|
||||
# optional object able to persist device settings
|
||||
self.configuration = None
|
||||
|
||||
def __str__(self):
|
||||
def _item(name, format):
|
||||
value = self.get(name)
|
||||
|
@ -242,8 +239,11 @@ 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).
|
||||
self[KEYS.NOTIFICATION_FLAGS] = d.enable_notifications()
|
||||
if self.configuration:
|
||||
self.configuration.attach_to(d)
|
||||
|
||||
# Devices lose configuration when they are turned off,
|
||||
# make sure they're up-to-date.
|
||||
for s in self._device.settings:
|
||||
s.apply()
|
||||
else:
|
||||
if was_active:
|
||||
battery = self.get(KEYS.BATTERY_LEVEL)
|
||||
|
|
|
@ -105,7 +105,3 @@ def attach_to(device):
|
|||
if s.persister is None:
|
||||
s.persister = persister
|
||||
assert s.persister == persister
|
||||
if s.name in persister:
|
||||
s.write(persister[s.name])
|
||||
else:
|
||||
persister[s.name] = s.read(cached=False)
|
||||
|
|
|
@ -171,8 +171,10 @@ class ReceiverListener(_listener.EventsListener):
|
|||
|
||||
if not already_known:
|
||||
_log.info("%s triggered new device %s (%s)", n, dev, dev.kind)
|
||||
# If there are saved configs, bring the device's settings up-to-date.
|
||||
# They will be applied when the device is marked as online.
|
||||
configuration.attach_to(dev)
|
||||
dev.status = _status.DeviceStatus(dev, self._status_changed)
|
||||
dev.status.configuration = configuration
|
||||
# the receiver changed status as well
|
||||
self._status_changed(self.receiver)
|
||||
|
||||
|
|
|
@ -9,7 +9,8 @@ from gi.repository import Gtk, GLib
|
|||
from logitech.unifying_receiver import settings as _settings
|
||||
|
||||
#
|
||||
#
|
||||
# a separate thread is used to read/write from the device
|
||||
# so as not to block the main (GUI) thread
|
||||
#
|
||||
|
||||
try:
|
||||
|
@ -29,15 +30,16 @@ def _process_apply_queue():
|
|||
while True:
|
||||
task = _apply_queue.get()
|
||||
assert isinstance(task, tuple)
|
||||
device_is_online = True
|
||||
# print ("task", *task)
|
||||
if task[0] == 'write':
|
||||
_, setting, value, sbox = task
|
||||
GLib.idle_add(_write_start, sbox, priority=0)
|
||||
value = setting.write(value)
|
||||
elif task[0] == 'read':
|
||||
_, setting, force_read, sbox = task
|
||||
_, setting, force_read, sbox, device_is_online = task
|
||||
value = setting.read(not force_read)
|
||||
GLib.idle_add(_update_setting_item, sbox, value, priority=99)
|
||||
GLib.idle_add(_update_setting_item, sbox, value, device_is_online, priority=99)
|
||||
|
||||
from threading import Thread as _Thread
|
||||
_queue_processor = _Thread(name='SettingsProcessor', target=_process_apply_queue)
|
||||
|
@ -190,10 +192,7 @@ def update(device, is_online=None):
|
|||
sbox = _items[k] = _create_sbox(s)
|
||||
_box.pack_start(sbox, False, False, 0)
|
||||
|
||||
if is_online:
|
||||
_apply_queue.put(('read', s, False, sbox))
|
||||
else:
|
||||
_update_setting_item(sbox, None, False)
|
||||
_apply_queue.put(('read', s, False, sbox, is_online))
|
||||
|
||||
_box.set_visible(True)
|
||||
|
||||
|
|
Loading…
Reference in New Issue