optionally listen for upower suspend/resume events to stop/start all receiver listeners
This commit is contained in:
parent
51e2d965cf
commit
d5374b9f51
|
|
@ -120,13 +120,13 @@ def monitor_glib(callback, *device_filters):
|
||||||
c = _Context()
|
c = _Context()
|
||||||
|
|
||||||
# already existing devices
|
# already existing devices
|
||||||
for device in c.list_devices(subsystem='hidraw'):
|
# for device in c.list_devices(subsystem='hidraw'):
|
||||||
# print (device, dict(device), dict(device.attributes))
|
# # print (device, dict(device), dict(device.attributes))
|
||||||
for filter in device_filters:
|
# for filter in device_filters:
|
||||||
d_info = _match('add', device, *filter)
|
# d_info = _match('add', device, *filter)
|
||||||
if d_info:
|
# if d_info:
|
||||||
GLib.idle_add(callback, 'add', d_info)
|
# GLib.idle_add(callback, 'add', d_info)
|
||||||
break
|
# break
|
||||||
|
|
||||||
m = _Monitor.from_netlink(c)
|
m = _Monitor.from_netlink(c)
|
||||||
m.filter_by(subsystem='hidraw')
|
m.filter_by(subsystem='hidraw')
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,9 @@ def _run(args):
|
||||||
ui.init()
|
ui.init()
|
||||||
|
|
||||||
import solaar.listener as listener
|
import solaar.listener as listener
|
||||||
listener.start_scanner(ui.status_changed, ui.error_dialog)
|
listener.setup_scanner(ui.status_changed, ui.error_dialog)
|
||||||
|
|
||||||
|
listener.start_all()
|
||||||
|
|
||||||
# main UI event loop
|
# main UI event loop
|
||||||
ui.run_loop()
|
ui.run_loop()
|
||||||
|
|
|
||||||
|
|
@ -201,11 +201,11 @@ class ReceiverListener(_listener.EventsListener):
|
||||||
_all_listeners = {}
|
_all_listeners = {}
|
||||||
|
|
||||||
|
|
||||||
def start(device_info, status_changed_callback):
|
def _start(device_info):
|
||||||
assert status_changed_callback
|
assert _status_callback
|
||||||
receiver = Receiver.open(device_info)
|
receiver = Receiver.open(device_info)
|
||||||
if receiver:
|
if receiver:
|
||||||
rl = ReceiverListener(receiver, status_changed_callback)
|
rl = ReceiverListener(receiver, _status_callback)
|
||||||
rl.start()
|
rl.start()
|
||||||
_all_listeners[device_info.path] = rl
|
_all_listeners[device_info.path] = rl
|
||||||
return rl
|
return rl
|
||||||
|
|
@ -213,12 +213,21 @@ def start(device_info, status_changed_callback):
|
||||||
_log.warn("failed to open %s", device_info)
|
_log.warn("failed to open %s", device_info)
|
||||||
|
|
||||||
|
|
||||||
|
def start_all():
|
||||||
|
# just in case this it called twice in a row...
|
||||||
|
stop_all()
|
||||||
|
|
||||||
|
_log.info("starting receiver listening threads")
|
||||||
|
for device_info in _base.receivers():
|
||||||
|
_process_receiver_event('add', device_info)
|
||||||
|
|
||||||
|
|
||||||
def stop_all():
|
def stop_all():
|
||||||
listeners = list(_all_listeners.values())
|
listeners = list(_all_listeners.values())
|
||||||
_all_listeners.clear()
|
_all_listeners.clear()
|
||||||
|
|
||||||
if listeners:
|
if listeners:
|
||||||
_log.info("stopping %s", listeners)
|
_log.info("stopping receiver listening threads %s", listeners)
|
||||||
|
|
||||||
for l in listeners:
|
for l in listeners:
|
||||||
l.stop()
|
l.stop()
|
||||||
|
|
@ -230,10 +239,16 @@ def stop_all():
|
||||||
l.join()
|
l.join()
|
||||||
|
|
||||||
|
|
||||||
|
# stop/start all receiver threads on suspend/resume events, if possible
|
||||||
|
from . import upower
|
||||||
|
upower.watch(start_all, stop_all)
|
||||||
|
|
||||||
|
|
||||||
|
from logitech.unifying_receiver import base as _base
|
||||||
_status_callback = None
|
_status_callback = None
|
||||||
_error_callback = None
|
_error_callback = None
|
||||||
|
|
||||||
def start_scanner(status_changed_callback, error_callback):
|
def setup_scanner(status_changed_callback, error_callback):
|
||||||
global _status_callback, _error_callback
|
global _status_callback, _error_callback
|
||||||
if _status_callback:
|
if _status_callback:
|
||||||
raise Exception("scanner was already set-up")
|
raise Exception("scanner was already set-up")
|
||||||
|
|
@ -241,7 +256,6 @@ def start_scanner(status_changed_callback, error_callback):
|
||||||
_status_callback = status_changed_callback
|
_status_callback = status_changed_callback
|
||||||
_error_callback = error_callback
|
_error_callback = error_callback
|
||||||
|
|
||||||
from logitech.unifying_receiver import base as _base
|
|
||||||
_base.notify_on_receivers_glib(_process_receiver_event)
|
_base.notify_on_receivers_glib(_process_receiver_event)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -249,6 +263,7 @@ def start_scanner(status_changed_callback, error_callback):
|
||||||
def _process_receiver_event(action, device_info):
|
def _process_receiver_event(action, device_info):
|
||||||
assert action is not None
|
assert action is not None
|
||||||
assert device_info is not None
|
assert device_info is not None
|
||||||
|
assert _error_callback
|
||||||
|
|
||||||
_log.info("receiver event %s %s", action, device_info)
|
_log.info("receiver event %s %s", action, device_info)
|
||||||
|
|
||||||
|
|
@ -261,7 +276,7 @@ def _process_receiver_event(action, device_info):
|
||||||
if action == 'add':
|
if action == 'add':
|
||||||
# a new receiver device was detected
|
# a new receiver device was detected
|
||||||
try:
|
try:
|
||||||
start(device_info, _status_callback)
|
_start(device_info)
|
||||||
except OSError:
|
except OSError:
|
||||||
# permission error, ignore this path for now
|
# permission error, ignore this path for now
|
||||||
_error_callback('permissions', device_info.path)
|
_error_callback('permissions', device_info.path)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
|
from logging import getLogger
|
||||||
|
_log = getLogger(__name__)
|
||||||
|
del getLogger
|
||||||
|
|
||||||
|
#
|
||||||
|
# As suggested here: http://stackoverflow.com/a/13548984
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
_suspend_callback = None
|
||||||
|
def _suspend():
|
||||||
|
if _suspend_callback:
|
||||||
|
_log.info("received suspend event from UPower")
|
||||||
|
_suspend_callback()
|
||||||
|
|
||||||
|
|
||||||
|
_resume_callback = None
|
||||||
|
def _resume():
|
||||||
|
if _resume_callback:
|
||||||
|
_log.info("received resume event from UPower")
|
||||||
|
_resume_callback()
|
||||||
|
|
||||||
|
|
||||||
|
def watch(on_resume_callback, on_suspend_callback):
|
||||||
|
"""Register callback for suspend/resume events.
|
||||||
|
They are called only if the system DBus is running, and the UPower daemon is available."""
|
||||||
|
global _resume_callback, _suspend_callback
|
||||||
|
_suspend_callback = on_suspend_callback
|
||||||
|
_resume_callback = on_resume_callback
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
import dbus # for dbus communication (obviously)
|
||||||
|
|
||||||
|
_UPOWER_BUS = 'org.freedesktop.UPower'
|
||||||
|
_UPOWER_INTERFACE = 'org.freedesktop.UPower'
|
||||||
|
|
||||||
|
# integration into the main GLib loop
|
||||||
|
from dbus.mainloop.glib import DBusGMainLoop
|
||||||
|
DBusGMainLoop(set_as_default=True)
|
||||||
|
|
||||||
|
bus = dbus.SystemBus()
|
||||||
|
assert bus
|
||||||
|
|
||||||
|
bus.add_signal_receiver(_suspend, signal_name='Sleeping',
|
||||||
|
dbus_interface=_UPOWER_INTERFACE, bus_name=_UPOWER_BUS)
|
||||||
|
|
||||||
|
bus.add_signal_receiver(_resume, signal_name='Resuming',
|
||||||
|
dbus_interface=_UPOWER_INTERFACE, bus_name=_UPOWER_BUS)
|
||||||
|
|
||||||
|
_log.info("connected to system dbus, watching for suspend/resume events")
|
||||||
|
|
||||||
|
except:
|
||||||
|
# Either:
|
||||||
|
# - the dbus library is not available
|
||||||
|
# - the system dbus is not running
|
||||||
|
_log.warn("failed to register suspend/resume callbacks")
|
||||||
|
pass
|
||||||
Loading…
Reference in New Issue