listeners: Make listeners async

- Add a common Listener base class
- Make send helper for sending out events with pykka
- Make send async helper for avoiding blocking events

This change ensures all the events now get sent out via the MainThread instead
of blocking the actors.
This commit is contained in:
Thomas Adamcik 2013-11-26 15:10:48 +01:00
parent c3d6234a5e
commit c128668621
4 changed files with 42 additions and 44 deletions

View File

@ -1,9 +1,9 @@
from __future__ import unicode_literals
import pykka
from mopidy import listener
class AudioListener(object):
class AudioListener(listener.Listener):
"""
Marker interface for recipients of events sent by the audio actor.
@ -17,25 +17,7 @@ class AudioListener(object):
@staticmethod
def send(event, **kwargs):
"""Helper to allow calling of audio listener events"""
listeners = pykka.ActorRegistry.get_by_class(AudioListener)
for listener in listeners:
listener.proxy().on_event(event, **kwargs)
def on_event(self, event, **kwargs):
"""
Called on all events.
*MAY* be implemented by actor. By default, this method forwards the
event to the specific event methods.
For a list of what event names to expect, see the names of the other
methods in :class:`AudioListener`.
:param event: the event name
:type event: string
:param kwargs: any other arguments to the specific event handlers
"""
getattr(self, event)(**kwargs)
listener.send_async(AudioListener, event, **kwargs)
def reached_end_of_stream(self):
"""

View File

@ -1,9 +1,9 @@
from __future__ import unicode_literals
import pykka
from mopidy import listener
class BackendListener(object):
class BackendListener(listener.Listener):
"""
Marker interface for recipients of events sent by the backend actors.
@ -19,22 +19,7 @@ class BackendListener(object):
@staticmethod
def send(event, **kwargs):
"""Helper to allow calling of backend listener events"""
listeners = pykka.ActorRegistry.get_by_class(BackendListener)
for listener in listeners:
listener.proxy().on_event(event, **kwargs)
def on_event(self, event, **kwargs):
"""
Called on all events.
*MAY* be implemented by actor. By default, this method forwards the
event to the specific event methods.
:param event: the event name
:type event: string
:param kwargs: any other arguments to the specific event handlers
"""
getattr(self, event)(**kwargs)
listener.send_async(BackendListener, event, **kwargs)
def playlists_loaded(self):
"""

View File

@ -1,9 +1,9 @@
from __future__ import unicode_literals
import pykka
from mopidy import listener
class CoreListener(object):
class CoreListener(listener.Listener):
"""
Marker interface for recipients of events sent by the core actor.
@ -17,9 +17,7 @@ class CoreListener(object):
@staticmethod
def send(event, **kwargs):
"""Helper to allow calling of core listener events"""
listeners = pykka.ActorRegistry.get_by_class(CoreListener)
for listener in listeners:
listener.proxy().on_event(event, **kwargs)
listener.send_async(CoreListener, event, **kwargs)
def on_event(self, event, **kwargs):
"""

33
mopidy/listener.py Normal file
View File

@ -0,0 +1,33 @@
from __future__ import unicode_literals
import gobject
import logging
import pykka
logger = logging.getLogger('mopidy.listener')
def send_async(cls, event, **kwargs):
gobject.idle_add(lambda: send(cls, event, **kwargs))
def send(cls, event, **kwargs):
listeners = pykka.ActorRegistry.get_by_class(cls)
logger.debug('Sending %s to %s: %s', event, cls.__name__, kwargs)
for listener in listeners:
listener.proxy().on_event(event, **kwargs)
class Listener(object):
def on_event(self, event, **kwargs):
"""
Called on all events.
*MAY* be implemented by actor. By default, this method forwards the
event to the specific event methods.
:param event: the event name
:type event: string
:param kwargs: any other arguments to the specific event handlers
"""
getattr(self, event)(**kwargs)