device: add callback to call when changing a setting
This commit is contained in:
parent
476f41f8ae
commit
ed248c62b9
|
@ -63,7 +63,8 @@ class Device:
|
||||||
short=None,
|
short=None,
|
||||||
long=None,
|
long=None,
|
||||||
product_id=None,
|
product_id=None,
|
||||||
bus_id=None
|
bus_id=None,
|
||||||
|
setting_callback=None
|
||||||
):
|
):
|
||||||
assert receiver or handle
|
assert receiver or handle
|
||||||
Device.instances.append(self)
|
Device.instances.append(self)
|
||||||
|
@ -76,6 +77,7 @@ class Device:
|
||||||
self.hidpp_short = short
|
self.hidpp_short = short
|
||||||
self.hidpp_long = long
|
self.hidpp_long = long
|
||||||
self.bluetooth = bus_id == 0x0005 # Bluetooth connections need long messages
|
self.bluetooth = bus_id == 0x0005 # Bluetooth connections need long messages
|
||||||
|
self.setting_callback = setting_callback
|
||||||
|
|
||||||
if receiver:
|
if receiver:
|
||||||
assert number > 0 and number <= 15 # some receivers have devices past their max # of devices
|
assert number > 0 and number <= 15 # some receivers have devices past their max # of devices
|
||||||
|
@ -526,7 +528,7 @@ class Device:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def open(self, device_info):
|
def open(self, device_info, setting_callback=None):
|
||||||
"""Opens a Logitech Device found attached to the machine, by Linux device path.
|
"""Opens a Logitech Device found attached to the machine, by Linux device path.
|
||||||
:returns: An open file handle for the found receiver, or ``None``.
|
:returns: An open file handle for the found receiver, or ``None``.
|
||||||
"""
|
"""
|
||||||
|
@ -541,7 +543,8 @@ class Device:
|
||||||
short=device_info.hidpp_short,
|
short=device_info.hidpp_short,
|
||||||
long=device_info.hidpp_long,
|
long=device_info.hidpp_long,
|
||||||
product_id=device_info.product_id,
|
product_id=device_info.product_id,
|
||||||
bus_id=device_info.bus_id
|
bus_id=device_info.bus_id,
|
||||||
|
setting_callback=setting_callback
|
||||||
)
|
)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
logger.exception('open %s', device_info)
|
logger.exception('open %s', device_info)
|
||||||
|
|
|
@ -1285,9 +1285,6 @@ class Set(Action):
|
||||||
return 'Set: ' + ' '.join([str(a) for a in self.args])
|
return 'Set: ' + ' '.join([str(a) for a in self.args])
|
||||||
|
|
||||||
def evaluate(self, feature, notification, device, status, last_result):
|
def evaluate(self, feature, notification, device, status, last_result):
|
||||||
# importing here to avoid circular imports
|
|
||||||
from solaar.ui.config_panel import change_setting as _change_setting
|
|
||||||
|
|
||||||
if len(self.args) < 3:
|
if len(self.args) < 3:
|
||||||
return None
|
return None
|
||||||
if logger.isEnabledFor(logging.INFO):
|
if logger.isEnabledFor(logging.INFO):
|
||||||
|
@ -1304,7 +1301,9 @@ class Set(Action):
|
||||||
if args is None:
|
if args is None:
|
||||||
logger.warning('Set Action: invalid args %s for setting %s of %s', self.args[2:], self.args[1], self.args[0])
|
logger.warning('Set Action: invalid args %s for setting %s of %s', self.args[2:], self.args[1], self.args[0])
|
||||||
return None
|
return None
|
||||||
_change_setting(dev, setting, args)
|
setting.write(*args)
|
||||||
|
if device.setting_callback:
|
||||||
|
device.setting_callback(device, type(setting), args)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def data(self):
|
def data(self):
|
||||||
|
|
|
@ -22,8 +22,6 @@ import threading as _threading
|
||||||
|
|
||||||
from struct import unpack as _unpack
|
from struct import unpack as _unpack
|
||||||
|
|
||||||
from solaar.ui.config_panel import record_setting
|
|
||||||
|
|
||||||
from . import diversion as _diversion
|
from . import diversion as _diversion
|
||||||
from . import hidpp10 as _hidpp10
|
from . import hidpp10 as _hidpp10
|
||||||
from . import hidpp20 as _hidpp20
|
from . import hidpp20 as _hidpp20
|
||||||
|
@ -413,7 +411,8 @@ def _process_feature_notification(device, status, n, feature):
|
||||||
elif feature == _F.BACKLIGHT2:
|
elif feature == _F.BACKLIGHT2:
|
||||||
if (n.address == 0x00):
|
if (n.address == 0x00):
|
||||||
level = _unpack('!B', n.data[1:2])[0]
|
level = _unpack('!B', n.data[1:2])[0]
|
||||||
record_setting(device, _st.Backlight2Level, [level])
|
if device.setting_callback:
|
||||||
|
device.setting_callback(device, _st.Backlight2Level, [level])
|
||||||
|
|
||||||
elif feature == _F.REPROG_CONTROLS_V4:
|
elif feature == _F.REPROG_CONTROLS_V4:
|
||||||
if n.address == 0x00:
|
if n.address == 0x00:
|
||||||
|
@ -442,7 +441,8 @@ def _process_feature_notification(device, status, n, feature):
|
||||||
if logger.isEnabledFor(logging.INFO):
|
if logger.isEnabledFor(logging.INFO):
|
||||||
logger.info('%s: WHEEL: ratchet: %d', device, ratchet)
|
logger.info('%s: WHEEL: ratchet: %d', device, ratchet)
|
||||||
if ratchet < 2: # don't process messages with unusual ratchet values
|
if ratchet < 2: # don't process messages with unusual ratchet values
|
||||||
record_setting(device, _st.ScrollRatchet, [2 if ratchet else 1])
|
if device.setting_callback:
|
||||||
|
device.setting_callback(device, _st.ScrollRatchet, [2 if ratchet else 1])
|
||||||
else:
|
else:
|
||||||
if logger.isEnabledFor(logging.INFO):
|
if logger.isEnabledFor(logging.INFO):
|
||||||
logger.info('%s: unknown WHEEL %s', device, n)
|
logger.info('%s: unknown WHEEL %s', device, n)
|
||||||
|
@ -459,9 +459,11 @@ def _process_feature_notification(device, status, n, feature):
|
||||||
elif (n.address == 0x10):
|
elif (n.address == 0x10):
|
||||||
resolution_index = _unpack('!B', n.data[:1])[0]
|
resolution_index = _unpack('!B', n.data[:1])[0]
|
||||||
profile_sector = _unpack('!H', device.feature_request(_F.ONBOARD_PROFILES, 0x40)[:2])[0]
|
profile_sector = _unpack('!H', device.feature_request(_F.ONBOARD_PROFILES, 0x40)[:2])[0]
|
||||||
for profile in device.profiles.profiles.values() if device.profiles else []:
|
if device.setting_callback:
|
||||||
if profile.sector == profile_sector:
|
for profile in device.profiles.profiles.values() if device.profiles else []:
|
||||||
record_setting(device, _st.AdjustableDpi, [profile.resolutions[resolution_index]])
|
if profile.sector == profile_sector:
|
||||||
|
device.setting_callback(device, _st.AdjustableDpi, [profile.resolutions[resolution_index]])
|
||||||
|
break
|
||||||
|
|
||||||
_diversion.process_notification(device, status, n, feature)
|
_diversion.process_notification(device, status, n, feature)
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -47,12 +47,13 @@ class Receiver:
|
||||||
number = 0xFF
|
number = 0xFF
|
||||||
kind = None
|
kind = None
|
||||||
|
|
||||||
def __init__(self, handle, path, product_id):
|
def __init__(self, handle, path, product_id, setting_callback=None):
|
||||||
assert handle
|
assert handle
|
||||||
self.isDevice = False # some devices act as receiver so we need a property to distinguish them
|
self.isDevice = False # some devices act as receiver so we need a property to distinguish them
|
||||||
self.handle = handle
|
self.handle = handle
|
||||||
self.path = path
|
self.path = path
|
||||||
self.product_id = product_id
|
self.product_id = product_id
|
||||||
|
self.setting_callback = setting_callback
|
||||||
product_info = _product_information(self.product_id)
|
product_info = _product_information(self.product_id)
|
||||||
if not product_info:
|
if not product_info:
|
||||||
logger.warning('Unknown receiver type: %s', self.product_id)
|
logger.warning('Unknown receiver type: %s', self.product_id)
|
||||||
|
@ -237,7 +238,7 @@ class Receiver:
|
||||||
assert notification is None or notification.sub_id == 0x41
|
assert notification is None or notification.sub_id == 0x41
|
||||||
|
|
||||||
try:
|
try:
|
||||||
dev = Device(self, number, notification)
|
dev = Device(self, number, notification, setting_callback=self.setting_callback)
|
||||||
if logger.isEnabledFor(logging.INFO):
|
if logger.isEnabledFor(logging.INFO):
|
||||||
logger.info('%s: found new device %d (%s)', self, number, dev.wpid)
|
logger.info('%s: found new device %d (%s)', self, number, dev.wpid)
|
||||||
self._devices[number] = dev
|
self._devices[number] = dev
|
||||||
|
@ -382,7 +383,7 @@ class Receiver:
|
||||||
__bool__ = __nonzero__ = lambda self: self.handle is not None
|
__bool__ = __nonzero__ = lambda self: self.handle is not None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def open(self, device_info):
|
def open(self, device_info, setting_callback=None):
|
||||||
"""Opens a Logitech Receiver found attached to the machine, by Linux device path.
|
"""Opens a Logitech Receiver found attached to the machine, by Linux device path.
|
||||||
|
|
||||||
:returns: An open file handle for the found receiver, or ``None``.
|
:returns: An open file handle for the found receiver, or ``None``.
|
||||||
|
@ -390,7 +391,7 @@ class Receiver:
|
||||||
try:
|
try:
|
||||||
handle = _base.open_path(device_info.path)
|
handle = _base.open_path(device_info.path)
|
||||||
if handle:
|
if handle:
|
||||||
return Receiver(handle, device_info.path, device_info.product_id)
|
return Receiver(handle, device_info.path, device_info.product_id, setting_callback)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
logger.exception('open %s', device_info)
|
logger.exception('open %s', device_info)
|
||||||
if e.errno == _errno.EACCES:
|
if e.errno == _errno.EACCES:
|
||||||
|
|
|
@ -1447,10 +1447,10 @@ class ActionSettingRW:
|
||||||
self.active = True
|
self.active = True
|
||||||
if divertSetting:
|
if divertSetting:
|
||||||
divertSetting.write_key_value(int(self.key.key), 1)
|
divertSetting.write_key_value(int(self.key.key), 1)
|
||||||
|
if self.device.setting_callback:
|
||||||
|
self.device.setting_callback(device, type(divertSetting), [self.key.key, 1])
|
||||||
device.add_notification_handler(self.name, handler)
|
device.add_notification_handler(self.name, handler)
|
||||||
from solaar.ui import status_changed as _status_changed
|
|
||||||
self.activate_action()
|
self.activate_action()
|
||||||
_status_changed(device, refresh=True) # update main window
|
|
||||||
else:
|
else:
|
||||||
logger.error('cannot enable %s on %s for key %s', self.name, device, key)
|
logger.error('cannot enable %s on %s for key %s', self.name, device, key)
|
||||||
else: # Disable
|
else: # Disable
|
||||||
|
@ -1458,8 +1458,8 @@ class ActionSettingRW:
|
||||||
self.active = False
|
self.active = False
|
||||||
if divertSetting:
|
if divertSetting:
|
||||||
divertSetting.write_key_value(int(self.key.key), 0)
|
divertSetting.write_key_value(int(self.key.key), 0)
|
||||||
from solaar.ui import status_changed as _status_changed
|
if self.device.setting_callback:
|
||||||
_status_changed(device, refresh=True) # update main window
|
self.device.setting_callback(device, type(divertSetting), [self.key.key, 0])
|
||||||
try:
|
try:
|
||||||
device.remove_notification_handler(self.name)
|
device.remove_notification_handler(self.name)
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|
|
@ -479,14 +479,14 @@ class ThumbInvert(_Setting):
|
||||||
|
|
||||||
# change UI to show result of onboard profile change
|
# change UI to show result of onboard profile change
|
||||||
def profile_change(device, profile_sector):
|
def profile_change(device, profile_sector):
|
||||||
from solaar.ui.config_panel import record_setting # prevent circular import
|
if device.setting_callback:
|
||||||
record_setting(device, OnboardProfiles, [profile_sector])
|
device.setting_callback(device, OnboardProfiles, [profile_sector])
|
||||||
for profile in device.profiles.profiles.values() if device.profiles else []:
|
for profile in device.profiles.profiles.values() if device.profiles else []:
|
||||||
if profile.sector == profile_sector:
|
if profile.sector == profile_sector:
|
||||||
resolution_index = profile.resolution_default_index
|
resolution_index = profile.resolution_default_index
|
||||||
record_setting(device, AdjustableDpi, [profile.resolutions[resolution_index]])
|
device.setting_callback(device, AdjustableDpi, [profile.resolutions[resolution_index]])
|
||||||
record_setting(device, ReportRate, [profile.report_rate])
|
device.setting_callback(device, ReportRate, [profile.report_rate])
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
||||||
class OnboardProfiles(_Setting):
|
class OnboardProfiles(_Setting):
|
||||||
|
@ -772,8 +772,8 @@ class DpiSlidingXY(_RawXYProcessing):
|
||||||
def setNewDpi(self, newDpiIdx):
|
def setNewDpi(self, newDpiIdx):
|
||||||
newDpi = self.dpiChoices[newDpiIdx]
|
newDpi = self.dpiChoices[newDpiIdx]
|
||||||
self.dpiSetting.write(newDpi)
|
self.dpiSetting.write(newDpi)
|
||||||
from solaar.ui import status_changed as _status_changed
|
if self.device.setting_callback:
|
||||||
_status_changed(self.device, refresh=True) # update main window
|
self.device.setting_callback(self.device, type(self.dpiSetting), [newDpi])
|
||||||
|
|
||||||
def displayNewDpi(self, newDpiIdx):
|
def displayNewDpi(self, newDpiIdx):
|
||||||
from solaar.ui import notify as _notify # import here to avoid circular import when running `solaar show`,
|
from solaar.ui import notify as _notify # import here to avoid circular import when running `solaar show`,
|
||||||
|
@ -1024,10 +1024,10 @@ class SpeedChange(_Setting):
|
||||||
if newSpeed is not None:
|
if newSpeed is not None:
|
||||||
if speed_setting:
|
if speed_setting:
|
||||||
speed_setting.write(newSpeed)
|
speed_setting.write(newSpeed)
|
||||||
|
if self.device.setting_callback:
|
||||||
|
self.device.setting_callback(self.device, type(speed_setting), [newSpeed])
|
||||||
else:
|
else:
|
||||||
logger.error('cannot save sensitivity setting on %s', self.device)
|
logger.error('cannot save sensitivity setting on %s', self.device)
|
||||||
from solaar.ui import status_changed as _status_changed
|
|
||||||
_status_changed(self.device, refresh=True) # update main window
|
|
||||||
if self.device.persister:
|
if self.device.persister:
|
||||||
self.device.persister['_speed-change'] = currentSpeed
|
self.device.persister['_speed-change'] = currentSpeed
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue