Extract GStreamerMessagesThread as a generic GObjectEventThread

This commit is contained in:
Stein Magnus Jodal 2010-10-31 00:48:10 +02:00
parent f9e49fc5eb
commit 39be6d2033
3 changed files with 35 additions and 19 deletions

View File

@ -7,7 +7,7 @@ from mopidy import get_version, settings, OptionalDependencyError
from mopidy.utils import get_class
from mopidy.utils.log import setup_logging
from mopidy.utils.path import get_or_create_folder, get_or_create_file
from mopidy.utils.process import BaseThread
from mopidy.utils.process import BaseThread, GObjectEventThread
from mopidy.utils.settings import list_settings_optparse_callback
logger = logging.getLogger('mopidy.core')
@ -47,6 +47,7 @@ class CoreProcess(BaseThread):
def setup(self):
self.setup_logging()
self.setup_settings()
self.gobject_loop = self.setup_gobject_loop(self.core_queue)
self.output = self.setup_output(self.core_queue)
self.backend = self.setup_backend(self.core_queue, self.output)
self.frontends = self.setup_frontends(self.core_queue, self.backend)
@ -61,6 +62,11 @@ class CoreProcess(BaseThread):
get_or_create_file('~/.mopidy/settings.py')
settings.validate()
def setup_gobject_loop(self, core_queue):
gobject_loop = GObjectEventThread(core_queue)
gobject_loop.start()
return gobject_loop
def setup_output(self, core_queue):
output = get_class(settings.OUTPUT)(core_queue)
output.start()

View File

@ -1,6 +1,3 @@
import gobject
gobject.threads_init()
import pygst
pygst.require('0.10')
import gst
@ -28,20 +25,14 @@ class GStreamerOutput(BaseOutput):
def __init__(self, *args, **kwargs):
super(GStreamerOutput, self).__init__(*args, **kwargs)
# Start a helper thread that can run the gobject.MainLoop
self.messages_thread = GStreamerMessagesThread(self.core_queue)
# Start a helper thread that can process the output_queue
self.output_queue = multiprocessing.Queue()
self.player_thread = GStreamerPlayerThread(self.core_queue,
self.output_queue)
def start(self):
self.messages_thread.start()
self.player_thread.start()
def destroy(self):
self.messages_thread.destroy()
self.player_thread.destroy()
def process_message(self, message):
@ -91,21 +82,15 @@ class GStreamerOutput(BaseOutput):
return self._send_recv({'command': 'set_volume', 'volume': volume})
class GStreamerMessagesThread(BaseThread):
def __init__(self, core_queue):
super(GStreamerMessagesThread, self).__init__(core_queue)
self.name = u'GStreamerMessagesThread'
def run_inside_try(self):
gobject.MainLoop().run()
class GStreamerPlayerThread(BaseThread):
"""
A process for all work related to GStreamer.
The main loop processes events from both Mopidy and GStreamer.
This thread requires :class:`mopidy.utils.process.GObjectEventThread` to be
running too. This is not enforced in any way by the code.
Make sure this subprocess is started by the MainThread in the top-most
parent process, and not some other thread. If not, we can get into the
problems described at

View File

@ -4,6 +4,9 @@ import multiprocessing.dummy
from multiprocessing.reduction import reduce_connection
import pickle
import gobject
gobject.threads_init()
from mopidy import SettingsError
logger = logging.getLogger('mopidy.utils.process')
@ -84,3 +87,25 @@ class BaseThread(multiprocessing.dummy.Process):
self.core_queue.put({'to': 'core', 'command': 'exit',
'status': status, 'reason': reason})
self.destroy()
class GObjectEventThread(BaseThread):
"""
A GObject event loop which is shared by all Mopidy components that uses
libraries that need a GObject event loop, like GStreamer and D-Bus.
Should be started by Mopidy's core and used by
:mod:`mopidy.output.gstreamer`, :mod:`mopidy.frontend.mpris`, etc.
"""
def __init__(self, core_queue):
super(GObjectEventThread, self).__init__(core_queue)
self.name = u'GObjectEventThread'
self.loop = None
def run_inside_try(self):
self.loop = gobject.MainLoop().run()
def destroy(self):
self.loop.quit()
super(GObjectEventThread, self).destroy()