Merge branch 'gstreamer', remote branch 'adamcik/gstreamer' into gstreamer

This commit is contained in:
Stein Magnus Jodal 2010-08-14 01:02:58 +02:00
commit f448771027
5 changed files with 45 additions and 47 deletions

View File

@ -22,7 +22,10 @@ def main():
get_or_create_folder('~/.mopidy/')
core_queue = multiprocessing.Queue()
get_class(settings.SERVER)(core_queue).start()
core = CoreProcess(core_queue)
output_class = get_class(settings.OUTPUT)
backend_class = get_class(settings.BACKENDS[0])
frontend_class = get_class(settings.FRONTEND)
core = CoreProcess(core_queue, output_class, backend_class, frontend_class)
core.start()
asyncore.loop()

View File

@ -39,6 +39,8 @@ class GStreamerProcess(BaseProcess):
http://jameswestby.net/weblog/tech/14-caution-python-multiprocessing-and-glib-dont-mix.html.
"""
pipeline_description = 'appsrc name=data ! volume name=volume ! autoaudiosink name=sink'
def __init__(self, core_queue, output_queue):
super(GStreamerProcess, self).__init__()
self.core_queue = core_queue
@ -65,8 +67,10 @@ class GStreamerProcess(BaseProcess):
messages_thread.daemon = True
messages_thread.start()
# A pipeline consisting of many elements
self.gst_pipeline = gst.Pipeline("pipeline")
self.gst_pipeline = gst.parse_launch(self.pipeline_description)
self.gst_data_src = self.gst_pipeline.get_by_name('data')
self.gst_volume = self.gst_pipeline.get_by_name('volume')
self.gst_sink = self.gst_pipeline.get_by_name('sink')
# Setup bus and message processor
self.gst_bus = self.gst_pipeline.get_bus()
@ -74,42 +78,6 @@ class GStreamerProcess(BaseProcess):
self.gst_bus_id = self.gst_bus.connect('message',
self.process_gst_message)
# Bin for playing audio URIs
#self.gst_uri_src = gst.element_factory_make('uridecodebin', 'uri_src')
#self.gst_pipeline.add(self.gst_uri_src)
# Bin for playing audio data
self.gst_data_src = gst.element_factory_make('appsrc', 'data_src')
self.gst_pipeline.add(self.gst_data_src)
# Volume filter
self.gst_volume = gst.element_factory_make('volume', 'volume')
self.gst_pipeline.add(self.gst_volume)
# Audio output sink
self.gst_sink = gst.element_factory_make('autoaudiosink', 'sink')
self.gst_pipeline.add(self.gst_sink)
# Add callback that will link uri_src output with volume filter input
# when the output pad is ready.
# See http://stackoverflow.com/questions/2993777 for details.
def on_new_decoded_pad(dbin, pad, is_last):
uri_src = pad.get_parent()
pipeline = uri_src.get_parent()
volume = pipeline.get_by_name('volume')
uri_src.link(volume)
logger.debug("Linked uri_src's new decoded pad to volume filter")
# FIXME uridecodebin got no new-decoded-pad signal, but it's
# subcomponent decodebin2 got that signal. Fixing this is postponed
# till after data_src is up and running perfectly
#self.gst_uri_src.connect('new-decoded-pad', on_new_decoded_pad)
# Link data source output with volume filter input
self.gst_data_src.link(self.gst_volume)
# Link volume filter output to audio sink input
self.gst_volume.link(self.gst_sink)
def process_mopidy_message(self, message):
"""Process messages from the rest of Mopidy."""
if message['command'] == 'play_uri':

View File

@ -28,16 +28,23 @@ class BaseProcess(multiprocessing.Process):
except SettingsError as e:
logger.error(e.message)
sys.exit(1)
except ImportError as e:
logger.error(e)
sys.exit(1)
def run_inside_try(self):
raise NotImplementedError
class CoreProcess(BaseProcess):
def __init__(self, core_queue):
def __init__(self, core_queue, output_class, backend_class,
frontend_class):
super(CoreProcess, self).__init__()
self.core_queue = core_queue
self.output_queue = None
self.output_class = output_class
self.backend_class = backend_class
self.frontend_class = frontend_class
self.output = None
self.backend = None
self.frontend = None
@ -50,11 +57,9 @@ class CoreProcess(BaseProcess):
def setup(self):
self.output_queue = multiprocessing.Queue()
self.output = get_class(settings.OUTPUT)(self.core_queue,
self.output_queue)
self.backend = get_class(settings.BACKENDS[0])(self.core_queue,
self.output_queue)
self.frontend = get_class(settings.FRONTEND)(self.backend)
self.output = self.output_class(self.core_queue, self.output_queue)
self.backend = self.backend_class(self.core_queue, self.output_queue)
self.frontend = self.frontend_class(self.backend)
def process_message(self, message):
if message.get('to') == 'output':

View File

@ -24,8 +24,11 @@ def get_class(name):
module_name = name[:name.rindex('.')]
class_name = name[name.rindex('.') + 1:]
logger.debug('Loading: %s', name)
module = import_module(module_name)
class_object = getattr(module, class_name)
try:
module = import_module(module_name)
class_object = getattr(module, class_name)
except (ImportError, AttributeError):
raise ImportError("Couldn't load: %s" % name)
return class_object
def get_or_create_folder(folder):

View File

@ -11,6 +11,25 @@ from mopidy.models import Track, Artist, Album
from tests import SkipTest, data_folder
class GetClassTest(unittest.TestCase):
def test_loading_module_that_does_not_exist(self):
test = lambda: get_class('foo.bar.Baz')
self.assertRaises(ImportError, test)
def test_loading_class_that_does_not_exist(self):
test = lambda: get_class('unittest.FooBarBaz')
self.assertRaises(ImportError, test)
def test_import_error_message_contains_complete_class_path(self):
try:
get_class('foo.bar.Baz')
except ImportError as e:
self.assert_('foo.bar.Baz' in str(e))
def test_loading_existing_class(self):
cls = get_class('unittest.TestCase')
self.assertEqual(cls.__name__, 'TestCase')
class GetOrCreateFolderTest(unittest.TestCase):
def setUp(self):
self.parent = tempfile.mkdtemp()