use specialized namedtuple for events

This commit is contained in:
Daniel Pavel 2012-10-12 18:17:46 +03:00
parent 5347f41d73
commit bca21a7220
4 changed files with 49 additions and 44 deletions

View File

@ -23,7 +23,7 @@ if __name__ == '__main__':
arg_parser = argparse.ArgumentParser(prog=APP_TITLE)
arg_parser.add_argument('-v', '--verbose', action='count', default=0,
help='increase the logger verbosity (may be repeated)')
arg_parser.add_argument('-s', '--systray', action='store_true',
arg_parser.add_argument('-S', '--no-systray', action='store_false', dest='systray',
help='embed the application into the systray')
arg_parser.add_argument('-N', '--no-notifications', action='store_false', dest='notifications',
help='disable desktop notifications (if systray is enabled)')
@ -67,5 +67,4 @@ if __name__ == '__main__':
Gtk.main()
watcher.stop()
if args.notifications:
ui.notify.set_active(False)
ui.notify.set_active(False)

View File

@ -132,7 +132,7 @@ class Watcher(Thread):
return None
if type(dev) == int:
# assert self.listener
assert self.listener
dev = self.listener.request(api.get_device_info, dev)
if dev:
@ -177,33 +177,33 @@ class Watcher(Thread):
devstatus.code = status_code
devstatus.text = status_text
_l.debug("%s update %s => %s: %s", devstatus, old_status_code, status_code, status_text)
_l.debug("%s update %s => %s: %s", devstatus, old_status_code, status_code, status_text)
if self.notify and (status_code <= C.STATUS.CONNECTED or status_code != old_status_code):
self.notify(devstatus.code, devstatus.name, devstatus.text)
return True
def _events_callback(self, code, devnumber, data):
# _l.debug("event %s", (code, devnumber, data))
def _events_callback(self, event):
# _l.debug("event %s", event)
updated = False
if devnumber in self.devices:
devstatus = self.devices[devnumber]
if code == 0x10 and data[:1] == b'\x8F':
if event.devnumber in self.devices:
devstatus = self.devices[event.devnumber]
if event.code == 0x10 and event.data[:1] == b'\x8F':
updated = True
self._device_status_changed(devstatus, C.STATUS.UNAVAILABLE)
elif code == 0x11:
status = devices.process_event(devstatus, data, self.listener)
elif event.code == 0x11:
status = devices.process_event(devstatus, event.data, self.listener)
updated |= self._device_status_changed(devstatus, status)
else:
_l.warn("unknown event code %02x", code)
elif devnumber:
self._new_device(devnumber)
_l.warn("unknown event %s", event)
elif event.devnumber:
self._new_device(event.devnumber)
updated = True
else:
_l.warn("don't know how to handle event %s", (code, devnumber, data))
_l.warn("don't know how to handle event %s", event)
if updated:
self._update_status_text()

View File

@ -2,6 +2,9 @@
# Some common functions and types.
#
from binascii import hexlify as _hexlify
class FallbackDict(dict):
def __init__(self, fallback_function=lambda x: None, *args, **kwargs):
super(FallbackDict, self).__init__(*args, **kwargs)
@ -46,4 +49,8 @@ ReprogrammableKeyInfo = namedtuple('ReprogrammableKeyInfo', [
'task_name',
'flags'])
class Packet(namedtuple('Packet', ['code', 'devnumber', 'data'])):
def __str__(self):
return 'Packet(0x%02x,%d,%s)' % (self.code, self.devnumber, _hexlify(self.data))
del namedtuple

View File

@ -4,10 +4,11 @@
from logging import getLogger as _Logger
from threading import (Thread, Event, Lock)
from time import sleep as _sleep
# from time import sleep as _sleep
from . import base as _base
from . import exceptions as E
from .common import Packet
# for both Python 2 and 3
try:
@ -21,16 +22,15 @@ _l = _Logger('lur.listener')
_READ_EVENT_TIMEOUT = int(_base.DEFAULT_TIMEOUT / 5) # ms
_IDLE_SLEEP = _base.DEFAULT_TIMEOUT / 5 # ms
def _callback_caller(listener, callback):
# _l.log(_LOG_LEVEL, "%s starting callback caller", listener)
while listener._active:
while listener._active or not listener.events.empty():
event = listener.events.get()
_l.log(_LOG_LEVEL, "%s delivering event %s", listener, event)
try:
callback.__call__(*event)
callback.__call__(event)
except:
_l.exception("callback for %s", event)
# _l.log(_LOG_LEVEL, "%s stopped callback caller", listener)
@ -55,11 +55,10 @@ class EventsListener(Thread):
self.task = None
self.task_processing = Lock()
self.task_reply = None
self.task_done = Event()
self.events = Queue(16)
self.events = Queue(32)
self.event_caller = Thread(group='Unifying Receiver', name='Callback-%x' % receiver, target=_callback_caller, args=(self, events_callback))
self.event_caller.daemon = True
@ -77,23 +76,22 @@ class EventsListener(Thread):
_base.unhandled_hook = self._unhandled
while self._active:
event = None
try:
event = _base.read(self.receiver, _READ_EVENT_TIMEOUT)
except E.NoReceiver:
_l.warn("%s receiver disconnected", self)
self.events.put(Packet(0xFF, 0xFF, None))
self._active = False
if self._active:
if event:
# _l.log(_LOG_LEVEL, "%s queueing event %s", self, event)
self.events.put(event)
if event:
_l.log(_LOG_LEVEL, "%s queueing event %s", self, event)
self.events.put(Packet(*event))
if self.task is None:
# _l.log(_LOG_LEVEL, "%s idle sleep", self)
_sleep(_IDLE_SLEEP / 1000.0)
else:
self.task_reply = self._make_request(*self.task)
self.task_done.set()
if self.task:
task, self.task = self.task, None
self.task_reply = self._make_request(*task)
self.task_done.set()
_base.close(self.receiver)
self.__str_cached = 'Events(%x)' % self.receiver
@ -102,9 +100,10 @@ class EventsListener(Thread):
def stop(self):
"""Tells the listener to stop as soon as possible."""
_l.log(_LOG_LEVEL, "%s stopping", self)
self._active = False
self.join()
if self._active:
_l.log(_LOG_LEVEL, "stopping %s", self)
self._active = False
self.join()
def request(self, api_function, *args, **kwargs):
"""Make an UR API request through this listener's receiver.
@ -114,14 +113,14 @@ class EventsListener(Thread):
"""
# _l.log(_LOG_LEVEL, "%s request '%s.%s' with %s, %s", self, api_function.__module__, api_function.__name__, args, kwargs)
self.task_processing.acquire()
self.task_done.clear()
self.task = (api_function, args, kwargs)
if not self._active:
return None
self.task_done.wait()
reply = self.task_reply
self.task = self.task_reply = None
self.task_processing.release()
with self.task_processing:
self.task_done.clear()
self.task = (api_function, args, kwargs)
self.task_done.wait()
reply, self.task_reply = self.task_reply, None
# _l.log(_LOG_LEVEL, "%s request '%s.%s' => %s", self, api_function.__module__, api_function.__name__, repr(reply))
if isinstance(reply, Exception):
@ -139,8 +138,8 @@ class EventsListener(Thread):
self.task_reply = e
def _unhandled(self, reply_code, devnumber, data):
event = (reply_code, devnumber, data)
_l.log(_LOG_LEVEL, "%s queueing unhandled event %s", self, event)
event = Packet(reply_code, devnumber, data)
# _l.log(_LOG_LEVEL, "%s queueing unhandled event %s", self, event)
self.events.put(event)
def __str__(self):