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()
|
||||
|
||||
# already existing devices
|
||||
for device in c.list_devices(subsystem='hidraw'):
|
||||
# print (device, dict(device), dict(device.attributes))
|
||||
for filter in device_filters:
|
||||
d_info = _match('add', device, *filter)
|
||||
if d_info:
|
||||
GLib.idle_add(callback, 'add', d_info)
|
||||
break
|
||||
# for device in c.list_devices(subsystem='hidraw'):
|
||||
# # print (device, dict(device), dict(device.attributes))
|
||||
# for filter in device_filters:
|
||||
# d_info = _match('add', device, *filter)
|
||||
# if d_info:
|
||||
# GLib.idle_add(callback, 'add', d_info)
|
||||
# break
|
||||
|
||||
m = _Monitor.from_netlink(c)
|
||||
m.filter_by(subsystem='hidraw')
|
||||
|
|
|
@ -44,7 +44,9 @@ def _run(args):
|
|||
ui.init()
|
||||
|
||||
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
|
||||
ui.run_loop()
|
||||
|
|
|
@ -201,11 +201,11 @@ class ReceiverListener(_listener.EventsListener):
|
|||
_all_listeners = {}
|
||||
|
||||
|
||||
def start(device_info, status_changed_callback):
|
||||
assert status_changed_callback
|
||||
def _start(device_info):
|
||||
assert _status_callback
|
||||
receiver = Receiver.open(device_info)
|
||||
if receiver:
|
||||
rl = ReceiverListener(receiver, status_changed_callback)
|
||||
rl = ReceiverListener(receiver, _status_callback)
|
||||
rl.start()
|
||||
_all_listeners[device_info.path] = rl
|
||||
return rl
|
||||
|
@ -213,12 +213,21 @@ def start(device_info, status_changed_callback):
|
|||
_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():
|
||||
listeners = list(_all_listeners.values())
|
||||
_all_listeners.clear()
|
||||
|
||||
if listeners:
|
||||
_log.info("stopping %s", listeners)
|
||||
_log.info("stopping receiver listening threads %s", listeners)
|
||||
|
||||
for l in listeners:
|
||||
l.stop()
|
||||
|
@ -230,10 +239,16 @@ def stop_all():
|
|||
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
|
||||
_error_callback = None
|
||||
|
||||
def start_scanner(status_changed_callback, error_callback):
|
||||
def setup_scanner(status_changed_callback, error_callback):
|
||||
global _status_callback, _error_callback
|
||||
if _status_callback:
|
||||
raise Exception("scanner was already set-up")
|
||||
|
@ -241,7 +256,6 @@ def start_scanner(status_changed_callback, error_callback):
|
|||
_status_callback = status_changed_callback
|
||||
_error_callback = error_callback
|
||||
|
||||
from logitech.unifying_receiver import base as _base
|
||||
_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):
|
||||
assert action is not None
|
||||
assert device_info is not None
|
||||
assert _error_callback
|
||||
|
||||
_log.info("receiver event %s %s", action, device_info)
|
||||
|
||||
|
@ -261,7 +276,7 @@ def _process_receiver_event(action, device_info):
|
|||
if action == 'add':
|
||||
# a new receiver device was detected
|
||||
try:
|
||||
start(device_info, _status_callback)
|
||||
_start(device_info)
|
||||
except OSError:
|
||||
# permission error, ignore this path for now
|
||||
_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