small updates to the app
This commit is contained in:
parent
9b2c1bdef6
commit
9111afcd6b
|
@ -4,6 +4,7 @@
|
|||
|
||||
from gi.repository import Gtk
|
||||
|
||||
from logitech.devices import constants as C
|
||||
|
||||
_ICON_OK = 'Solaar'
|
||||
_ICON_FAIL = _ICON_OK + '-fail'
|
||||
|
@ -36,9 +37,9 @@ def create(title, click_action=None):
|
|||
return icon
|
||||
|
||||
|
||||
def update(icon, rstatus, tooltip):
|
||||
def update(icon, receiver, tooltip):
|
||||
icon.set_tooltip_markup(tooltip)
|
||||
if rstatus.code < 0:
|
||||
if receiver.code < C.STATUS.CONNECTED:
|
||||
icon.set_from_icon_name(_ICON_FAIL)
|
||||
else:
|
||||
icon.set_from_icon_name(_ICON_OK)
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
from gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
|
||||
from logitech.devices import constants as C
|
||||
|
||||
|
||||
_DEVICE_ICON_SIZE = Gtk.IconSize.DIALOG
|
||||
_STATUS_ICON_SIZE = Gtk.IconSize.DIALOG
|
||||
|
@ -16,7 +18,7 @@ def _update_receiver_box(box, receiver):
|
|||
icon, vbox = box.get_children()
|
||||
label, buttons_box = vbox.get_children()
|
||||
label.set_text(receiver.text or '')
|
||||
buttons_box.set_visible(receiver.code >= 0)
|
||||
buttons_box.set_visible(receiver.code >= C.STATUS.CONNECTED)
|
||||
|
||||
|
||||
def _update_device_box(frame, devstatus):
|
||||
|
@ -30,7 +32,7 @@ def _update_device_box(frame, devstatus):
|
|||
icon.set_name(devstatus.name)
|
||||
icon.set_from_icon_name(devstatus.name, _DEVICE_ICON_SIZE)
|
||||
|
||||
if devstatus.code < 0:
|
||||
if devstatus.code < C.STATUS.CONNECTED:
|
||||
expander.set_sensitive(False)
|
||||
expander.set_expanded(False)
|
||||
expander.set_label('<big><b>%s</b></big>\n%s' % (devstatus.name, devstatus.text))
|
||||
|
@ -41,7 +43,7 @@ def _update_device_box(frame, devstatus):
|
|||
texts = []
|
||||
|
||||
light_icon = ebox.get_children()[-2]
|
||||
light_level = getattr(devstatus, 'light_level', None)
|
||||
light_level = getattr(devstatus, C.PROPS.LIGHT_LEVEL, None)
|
||||
light_icon.set_visible(light_level is not None)
|
||||
if light_level is not None:
|
||||
texts.append('Light: %d lux' % light_level)
|
||||
|
@ -50,7 +52,7 @@ def _update_device_box(frame, devstatus):
|
|||
light_icon.set_tooltip_text(texts[-1])
|
||||
|
||||
battery_icon = ebox.get_children()[-1]
|
||||
battery_level = getattr(devstatus, 'battery_level', None)
|
||||
battery_level = getattr(devstatus, C.PROPS.BATTERY_LEVEL, None)
|
||||
battery_icon.set_sensitive(battery_level is not None)
|
||||
if battery_level is None:
|
||||
battery_icon.set_from_icon_name('battery_unknown', _STATUS_ICON_SIZE)
|
||||
|
@ -61,7 +63,7 @@ def _update_device_box(frame, devstatus):
|
|||
battery_icon.set_from_icon_name(icon_name, _STATUS_ICON_SIZE)
|
||||
battery_icon.set_tooltip_text(texts[-1])
|
||||
|
||||
battery_status = getattr(devstatus, 'battery_status', None)
|
||||
battery_status = getattr(devstatus, C.PROPS.BATTERY_STATUS, None)
|
||||
if battery_status is not None:
|
||||
texts.append(battery_status)
|
||||
battery_icon.set_tooltip_text(battery_icon.get_tooltip_text() + '\n' + battery_status)
|
||||
|
@ -163,16 +165,7 @@ def _device_box():
|
|||
|
||||
|
||||
def create(title, rstatus, show=True, close_to_tray=False):
|
||||
vbox = Gtk.VBox(homogeneous=False, spacing=4)
|
||||
vbox.set_border_width(4)
|
||||
|
||||
vbox.add(_receiver_box(rstatus))
|
||||
for i in range(1, 1 + _MAX_DEVICES):
|
||||
vbox.add(_device_box())
|
||||
vbox.set_visible(True)
|
||||
|
||||
window = Gtk.Window()
|
||||
window.add(vbox)
|
||||
|
||||
Gtk.Window.set_default_icon_name('mouse')
|
||||
window.set_icon_name(title)
|
||||
|
@ -181,6 +174,8 @@ def create(title, rstatus, show=True, close_to_tray=False):
|
|||
window.set_keep_above(True)
|
||||
window.set_deletable(False)
|
||||
window.set_resizable(False)
|
||||
window.set_size_request(200, 50)
|
||||
window.set_default_size(200, 50)
|
||||
|
||||
window.set_position(Gtk.WindowPosition.MOUSE)
|
||||
window.set_type_hint(Gdk.WindowTypeHint.UTILITY)
|
||||
|
@ -190,6 +185,15 @@ def create(title, rstatus, show=True, close_to_tray=False):
|
|||
# window.set_wmclass(title, 'status-window')
|
||||
# window.set_role('status-window')
|
||||
|
||||
vbox = Gtk.VBox(homogeneous=False, spacing=4)
|
||||
vbox.set_border_width(4)
|
||||
|
||||
vbox.add(_receiver_box(rstatus))
|
||||
for i in range(1, 1 + _MAX_DEVICES):
|
||||
vbox.add(_device_box())
|
||||
vbox.set_visible(True)
|
||||
window.add(vbox)
|
||||
|
||||
if close_to_tray:
|
||||
def _state_event(window, event):
|
||||
if event.new_window_state & Gdk.WindowState.ICONIFIED:
|
||||
|
|
|
@ -10,23 +10,23 @@ from binascii import hexlify as _hexlify
|
|||
from logitech.unifying_receiver import api
|
||||
from logitech.unifying_receiver.listener import EventsListener
|
||||
from logitech import devices
|
||||
from logitech.devices import constants as C
|
||||
|
||||
|
||||
_STATUS_TIMEOUT = 31 # seconds
|
||||
_THREAD_SLEEP = 2 # seconds
|
||||
|
||||
|
||||
_UNIFYING_RECEIVER = 'Unifying Receiver'
|
||||
_NO_RECEIVER = 'Receiver not found.'
|
||||
_INITIALIZING = 'Initializing...'
|
||||
_SCANNING = 'Scanning...'
|
||||
_NO_DEVICES = 'No devices found.'
|
||||
_OKAY = 'Status okay.'
|
||||
_OKAY = 'Status ok.'
|
||||
|
||||
|
||||
class _DevStatus(api.AttachedDeviceInfo):
|
||||
timestamp = time.time()
|
||||
code = devices.STATUS.UNKNOWN
|
||||
code = C.STATUS.UNKNOWN
|
||||
text = _INITIALIZING
|
||||
refresh = None
|
||||
|
||||
|
@ -55,28 +55,30 @@ class WatcherThread(threading.Thread):
|
|||
|
||||
while self.active:
|
||||
if self.listener is None:
|
||||
self._device_status_changed(self.rstatus, (devices.STATUS.UNKNOWN, _INITIALIZING))
|
||||
self._device_status_changed(self.rstatus, (C.STATUS.UNKNOWN, _INITIALIZING))
|
||||
self._update_status_text()
|
||||
|
||||
receiver = api.open()
|
||||
if receiver:
|
||||
self._device_status_changed(self.rstatus, (-10, _SCANNING))
|
||||
self._device_status_changed(self.rstatus, (C.STATUS.BOOTING, _SCANNING))
|
||||
self._update_status_text()
|
||||
|
||||
for devinfo in api.list_devices(receiver):
|
||||
self._new_device(devinfo)
|
||||
logging.debug("initial scan finished: %s", self.devices)
|
||||
if self.devices:
|
||||
self._device_status_changed(self.rstatus, (devices.STATUS.CONNECTED, _OKAY))
|
||||
self._device_status_changed(self.rstatus, (C.STATUS.CONNECTED, _OKAY))
|
||||
else:
|
||||
self._device_status_changed(self.rstatus, (devices.STATUS.CONNECTED, _NO_DEVICES))
|
||||
self._device_status_changed(self.rstatus, (C.STATUS.CONNECTED, _NO_DEVICES))
|
||||
self._update_status_text()
|
||||
|
||||
self.listener = EventsListener(receiver, self._events_callback)
|
||||
self.listener.start()
|
||||
else:
|
||||
self._device_status_changed(self.rstatus, (devices.STATUS.UNAVAILABLE, _NO_RECEIVER))
|
||||
self._device_status_changed(self.rstatus, (C.STATUS.UNAVAILABLE, _NO_RECEIVER))
|
||||
elif not self.listener.active:
|
||||
self.listener = None
|
||||
self._device_status_changed(self.rstatus, (devices.STATUS.UNAVAILABLE, _NO_RECEIVER))
|
||||
self._device_status_changed(self.rstatus, (C.STATUS.UNAVAILABLE, _NO_RECEIVER))
|
||||
self.devices.clear()
|
||||
|
||||
if self.active:
|
||||
|
@ -134,15 +136,14 @@ class WatcherThread(threading.Thread):
|
|||
if not self.active:
|
||||
return None
|
||||
|
||||
logging.debug("new devstatus from %s", dev)
|
||||
if type(dev) == int:
|
||||
dev = self.listener.request(api.get_device_info, dev)
|
||||
logging.debug("new devstatus from %s", dev)
|
||||
if dev:
|
||||
devstatus = _DevStatus(*dev)
|
||||
devstatus.refresh = self._request_status
|
||||
self.devices[dev.number] = devstatus
|
||||
self._device_status_changed(devstatus, devices.STATUS.CONNECTED)
|
||||
self._device_status_changed(devstatus, C.STATUS.CONNECTED)
|
||||
logging.debug("new devstatus %s", devstatus)
|
||||
return devstatus
|
||||
|
||||
def _events_callback(self, code, devnumber, data):
|
||||
|
@ -154,7 +155,7 @@ class WatcherThread(threading.Thread):
|
|||
devstatus = self.devices[devnumber]
|
||||
if code == 0x10 and data[:1] == b'\x8F':
|
||||
updated = True
|
||||
self._device_status_changed(devstatus, devices.STATUS.UNAVAILABLE)
|
||||
self._device_status_changed(devstatus, C.STATUS.UNAVAILABLE)
|
||||
elif code == 0x11:
|
||||
status = devices.process_event(devstatus, self.listener, data)
|
||||
updated |= self._device_status_changed(devstatus, status)
|
||||
|
@ -178,8 +179,8 @@ class WatcherThread(threading.Thread):
|
|||
|
||||
if type(status) == int:
|
||||
status_code = status
|
||||
if status_code in devices.STATUS_NAME:
|
||||
status_text = devices.STATUS_NAME[status_code]
|
||||
if status_code in C.STATUS_NAME:
|
||||
status_text = C.STATUS_NAME[status_code]
|
||||
else:
|
||||
status_code = status[0]
|
||||
if isinstance(status[1], str):
|
||||
|
@ -192,15 +193,16 @@ class WatcherThread(threading.Thread):
|
|||
else:
|
||||
setattr(devstatus, key, value)
|
||||
else:
|
||||
status_code = devices.STATUS.UNKNOWN
|
||||
status_code = C.STATUS.UNKNOWN
|
||||
status_text = ''
|
||||
|
||||
if not (status_code == 0 and old_status_code > 0):
|
||||
if not (status_code == C.STATUS.CONNECTED and old_status_code > C.STATUS.CONNECTED):
|
||||
# if this is not just a ping for a device with an already known status
|
||||
devstatus.code = status_code
|
||||
devstatus.text = status_text
|
||||
logging.debug("%s: device '%s' status update %s => %s: %s", time.asctime(), devstatus.name, old_status_code, status_code, status_text)
|
||||
|
||||
if status_code <= 0 or old_status_code <= 0 or status_code < old_status_code:
|
||||
if status_code < C.STATUS.CONNECTED or old_status_code < C.STATUS.CONNECTED or status_code < old_status_code:
|
||||
self._notify(devstatus.code, devstatus.name, devstatus.text)
|
||||
|
||||
return True
|
||||
|
@ -214,7 +216,7 @@ class WatcherThread(threading.Thread):
|
|||
|
||||
if self.devices:
|
||||
lines = []
|
||||
if self.rstatus.code < 0:
|
||||
if self.rstatus.code < C.STATUS.CONNECTED:
|
||||
lines += (self.rstatus.text, '')
|
||||
|
||||
devstatuses = [self.devices[d] for d in range(1, 1 + api.C.MAX_ATTACHED_DEVICES) if d in self.devices]
|
||||
|
@ -224,7 +226,7 @@ class WatcherThread(threading.Thread):
|
|||
lines.append('<b>' + devstatus.name + '</b>')
|
||||
lines.append(' ' + devstatus.text)
|
||||
else:
|
||||
lines.append('<b>' + devstatus.name + '</b>: ' + devstatus.text)
|
||||
lines.append('<b>' + devstatus.name + '</b> ' + devstatus.text)
|
||||
else:
|
||||
lines.append('<b>' + devstatus.name + '</b>')
|
||||
lines.append('')
|
||||
|
|
|
@ -2,16 +2,17 @@
|
|||
#
|
||||
#
|
||||
|
||||
import logging
|
||||
|
||||
from . import k750
|
||||
from .constants import *
|
||||
from . import constants as C
|
||||
|
||||
from ..unifying_receiver import api as _api
|
||||
from ..unifying_receiver.common import FallbackDict as _FDict
|
||||
|
||||
|
||||
def ping(devinfo, listener):
|
||||
reply = listener.request(_api.ping, devinfo.number)
|
||||
return STATUS.CONNECTED if reply else STATUS.UNAVAILABLE
|
||||
return C.STATUS.CONNECTED if reply else C.STATUS.UNAVAILABLE
|
||||
|
||||
|
||||
def default_request_status(devinfo, listener):
|
||||
|
@ -19,43 +20,54 @@ def default_request_status(devinfo, listener):
|
|||
reply = listener.request(_api.get_device_battery_level, devinfo.number, features_array=devinfo.features)
|
||||
if reply:
|
||||
discharge, dischargeNext, status = reply
|
||||
return STATUS.CONNECTED, {PROPS.BATTERY_LEVEL: discharge}
|
||||
return C.STATUS.CONNECTED, {C.PROPS.BATTERY_LEVEL: discharge}
|
||||
|
||||
|
||||
def default_process_event(devinfo, listener, data):
|
||||
feature_index = ord(data[0:1])
|
||||
feature = devinfo.features[feature_index]
|
||||
feature_function = ord(data[1:2]) & 0xF0
|
||||
|
||||
if feature == _api.C.FEATURE.BATTERY:
|
||||
if ord(data[1:2]) & 0xF0 == 0:
|
||||
if feature_function == 0:
|
||||
discharge = ord(data[2:3])
|
||||
status = _api.C.BATTERY_STATUS[ord(data[3:4])]
|
||||
return STATUS.CONNECTED, {BATTERY_LEVEL: discharge, BATTERY_STATUS: status}
|
||||
return C.STATUS.CONNECTED, {C.PROPS.BATTERY_LEVEL: discharge, C.PROPS.BATTERY_STATUS: status}
|
||||
# ?
|
||||
elif feature == _api.C.FEATURE.REPROGRAMMABLE_KEYS:
|
||||
if ord(data[1:2]) & 0xF0 == 0:
|
||||
print 'reprogrammable key', repr(data)
|
||||
if feature_function == 0:
|
||||
logging.debug('reprogrammable key: %s', repr(data))
|
||||
# TODO
|
||||
pass
|
||||
# ?
|
||||
elif feature == _api.C.FEATURE.WIRELESS:
|
||||
if ord(data[1:2]) & 0xF0 == 0:
|
||||
if feature_function == 0:
|
||||
logging.debug("wireless status: %s", repr(data))
|
||||
# TODO
|
||||
pass
|
||||
# ?
|
||||
|
||||
|
||||
_REQUEST_STATUS_FUNCTIONS = _FDict()
|
||||
_REQUEST_STATUS_FUNCTIONS[k750.NAME] = k750.request_status
|
||||
_REQUEST_STATUS_FUNCTIONS = {
|
||||
k750.NAME: k750.request_status
|
||||
}
|
||||
|
||||
def request_status(devinfo, listener):
|
||||
if listener:
|
||||
return _REQUEST_STATUS_FUNCTIONS[devinfo.name](devinfo, listener) or default_request_status(devinfo, listener) or ping(devinfo, listener)
|
||||
if devinfo.name in _REQUEST_STATUS_FUNCTIONS:
|
||||
return _REQUEST_STATUS_FUNCTIONS[devinfo.name](devinfo, listener)
|
||||
return default_request_status(devinfo, listener) or ping(devinfo, listener)
|
||||
|
||||
|
||||
_PROCESS_EVENT_FUNCTIONS = _FDict()
|
||||
_PROCESS_EVENT_FUNCTIONS[k750.NAME] = k750.process_event
|
||||
_PROCESS_EVENT_FUNCTIONS = {
|
||||
k750.NAME: k750.process_event
|
||||
}
|
||||
|
||||
def process_event(devinfo, listener, data):
|
||||
if listener:
|
||||
return default_process_event(devinfo, listener, data) or _PROCESS_EVENT_FUNCTIONS[devinfo.name](devinfo, listener, data)
|
||||
default_result = default_process_event(devinfo, listener, data)
|
||||
if default_result is not None:
|
||||
return default_result
|
||||
|
||||
if devinfo.name in _PROCESS_EVENT_FUNCTIONS:
|
||||
return _PROCESS_EVENT_FUNCTIONS[devinfo.name](devinfo, listener, data)
|
||||
|
|
|
@ -6,11 +6,13 @@ STATUS = type('STATUS', (),
|
|||
dict(
|
||||
UNKNOWN=-9999,
|
||||
UNAVAILABLE=-1,
|
||||
CONNECTED=0,
|
||||
BOOTING=0,
|
||||
CONNECTED=1,
|
||||
))
|
||||
|
||||
STATUS_NAME = {
|
||||
STATUS.UNAVAILABLE: 'inactive',
|
||||
STATUS.BOOTING: 'initializing',
|
||||
STATUS.CONNECTED: 'connected',
|
||||
}
|
||||
|
||||
|
|
|
@ -189,7 +189,7 @@ def read(handle, timeout=DEFAULT_TIMEOUT):
|
|||
devnumber = ord(data[1:2])
|
||||
return code, devnumber, data[2:]
|
||||
|
||||
_l.log(_LOG_LEVEL, "(%d,*) => r[]", handle)
|
||||
# _l.log(_LOG_LEVEL, "(%d,*) => r[]", handle)
|
||||
|
||||
|
||||
def request(handle, devnumber, feature_index_function, params=b'', features_array=None):
|
||||
|
|
Loading…
Reference in New Issue