diff --git a/mopidy/audio/actor.py b/mopidy/audio/actor.py index fb8a0306..029913ac 100644 --- a/mopidy/audio/actor.py +++ b/mopidy/audio/actor.py @@ -155,7 +155,7 @@ class _Outputs(gst.Bin): # the actual switch, i.e. about to switch can block for longer thanks # to this queue. # TODO: make the min-max values a setting? - # TODO: move out of this class? + # TODO: this does not belong in this class. queue = gst.element_factory_make('queue') queue.set_property('max-size-buffers', 0) queue.set_property('max-size-bytes', 0) @@ -168,9 +168,11 @@ class _Outputs(gst.Bin): ghost_pad = gst.GhostPad('sink', queue.get_pad('sink')) self.add_pad(ghost_pad) - # Add an always connected fakesink so the tee doesn't fail. - # XXX disabled for now as we get one stream changed per sink... - # self._add(gst.element_factory_make('fakesink')) + # Add an always connected fakesink which respects the clock so the tee + # doesn't fail even if we don't have any outputs. + fakesink = gst.element_factory_make('fakesink') + fakesink.set_property('sync', True) + self._add(fakesink) def add_output(self, description): # XXX This only works for pipelines not in use until #790 gets done. @@ -346,12 +348,18 @@ class Audio(pykka.ThreadingActor): setup_proxy(source, self._config['proxy']) def _setup_output(self): - self._outputs = _Outputs() + # We don't want to test outputs for regular testing, so just instal + # an unsynced fakesink when someone asks for a testouput. + if self._config['audio']['output'] == 'testoutput': + self._outputs = gst.element_factory_make('fakesink') + else: + self._outputs = _Outputs() + try: + self._outputs.add_output(self._config['audio']['output']) + except exceptions.AudioException: + process.exit_process() # TODO: move this up the chain + self._outputs.get_pad('sink').add_event_probe(self._on_pad_event) - try: - self._outputs.add_output(self._config['audio']['output']) - except exceptions.AudioException: - process.exit_process() # TODO: move this up the chain self._playbin.set_property('audio-sink', self._outputs) def _setup_mixer(self): @@ -396,7 +404,12 @@ class Audio(pykka.ThreadingActor): pos_ms = pos // gst.MSECOND logger.debug('Triggering: position_changed(position=%s)', pos_ms) AudioListener.send('position_changed', position=pos_ms) - + elif event.type == gst.EVENT_SINK_MESSAGE: + # Handle stream changed messages when they reach our output bin. + # If we listen for it on the bus we get one per tee branch. + msg = event.parse_sink_message() + if msg.structure.has_name('playbin2-stream-changed'): + self._on_stream_changed(msg.structure['uri']) return True # TODO: consider splitting this out while we are at it. @@ -414,9 +427,7 @@ class Audio(pykka.ThreadingActor): elif msg.type == gst.MESSAGE_ASYNC_DONE: gst_logger.debug('Got async-done message.') elif msg.type == gst.MESSAGE_ELEMENT: - if msg.structure.has_name('playbin2-stream-changed'): - self._on_stream_changed(msg.structure['uri']) - elif gst.pbutils.is_missing_plugin_message(msg): + if gst.pbutils.is_missing_plugin_message(msg): self._on_missing_plugin(msg) def _on_playbin_state_changed(self, old_state, new_state, pending_state): diff --git a/tests/audio/test_actor.py b/tests/audio/test_actor.py index 2426f54e..fc3321d2 100644 --- a/tests/audio/test_actor.py +++ b/tests/audio/test_actor.py @@ -21,11 +21,9 @@ from mopidy.utils.path import path_to_uri from tests import path_to_data_dir -""" -We want to make sure both our real audio class and the fake one behave -correctly. So each test is first run against the real class, then repeated -against our dummy. -""" +# We want to make sure both our real audio class and the fake one behave +# correctly. So each test is first run against the real class, then repeated +# against our dummy. class BaseTest(unittest.TestCase): @@ -34,7 +32,7 @@ class BaseTest(unittest.TestCase): 'mixer': 'fakemixer track_max_volume=65536', 'mixer_track': None, 'mixer_volume': None, - 'output': 'fakesink', + 'output': 'testoutput', 'visualizer': None, } } @@ -49,7 +47,7 @@ class BaseTest(unittest.TestCase): 'audio': { 'mixer': 'foomixer', 'mixer_volume': None, - 'output': 'fakesink', + 'output': 'testoutput', 'visualizer': None, }, 'proxy': {