optionally listen for upower suspend/resume events to stop/start all receiver listeners

This commit is contained in:
Daniel Pavel 2013-06-23 18:11:42 +02:00
parent 51e2d965cf
commit d5374b9f51
4 changed files with 96 additions and 15 deletions

View File

@ -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')

View File

@ -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()

View File

@ -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)

64
lib/solaar/upower.py Normal file
View File

@ -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