From b2ccdec9603a26e5efeb557db69d8aab23aa2e29 Mon Sep 17 00:00:00 2001 From: Thomas Adamcik Date: Sun, 17 Jul 2011 04:14:21 +0200 Subject: [PATCH] Rip out rest of code that supported simulatnous outputs --- docs/changes.rst | 9 +++- docs/installation/gstreamer.rst | 4 +- docs/settings.rst | 2 +- mopidy/gstreamer.py | 96 ++------------------------------- mopidy/outputs/__init__.py | 29 +--------- mopidy/outputs/shoutcast.py | 16 ------ mopidy/settings.py | 8 +-- 7 files changed, 19 insertions(+), 145 deletions(-) diff --git a/docs/changes.rst b/docs/changes.rst index 5506bfb0..b0d320eb 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -17,10 +17,17 @@ v0.6.0 (in development) - Replace :attr:`mopidy.backends.base.Backend.uri_handlers` with :attr:`mopidy.backends.base.Backend.uri_schemes`, which just takes the part up to the colon of an URI, and not any prefix. + - Add Listener API, :mod:`mopidy.listeners`, to be implemented by actors wanting to receive events from the backend. This is a formalization of the ad hoc events the Last.fm scrobbler has already been using for some time. -- Fix metadata update in Shoutcast streaming (Fixes: :issue:`122`) + +- Fix metadata update in Shoutcast streaming (Fixes: :issue:`122`) + +- Multiple simultaneously playing outputs was considered more trouble than what + it is worth maintnance wise. Thus, this feature has been axed for now. + Switching outputs is still posible, but only one can be active at a time, and + it is still the case that switching during playback does not funtion. v0.5.0 (2011-06-15) diff --git a/docs/installation/gstreamer.rst b/docs/installation/gstreamer.rst index 08e16378..8f2ea07e 100644 --- a/docs/installation/gstreamer.rst +++ b/docs/installation/gstreamer.rst @@ -73,8 +73,8 @@ Using a custom audio sink ========================= If you for some reason want to use some other GStreamer audio sink than -``autoaudiosink``, you can add ``mopidy.outputs.custom.CustomOutput`` to the -:attr:`mopidy.settings.OUTPUTS` setting, and set the +``autoaudiosink``, you can set :attr:`mopidy.settings.OUTPUTS` to +``mopidy.outputs.custom.CustomOutput``, and set the :attr:`mopidy.settings.CUSTOM_OUTPUT` setting to a partial GStreamer pipeline description describing the GStreamer sink you want to use. diff --git a/docs/settings.rst b/docs/settings.rst index 68adfd55..d3c9015e 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -131,7 +131,7 @@ server simultaneously. To use the SHOUTcast output, do the following: #. Install, configure and start the Icecast server. It can be found in the ``icecast2`` package in Debian/Ubuntu. -#. Add ``mopidy.outputs.shoutcast.ShoutcastOutput`` output to the +#. Set ``mopidy.outputs.shoutcast.ShoutcastOutput`` as the first output in the :attr:`mopidy.settings.OUTPUTS` setting. #. Check the default values for the following settings, and alter them to match diff --git a/mopidy/gstreamer.py b/mopidy/gstreamer.py index 1de6e000..b43089e0 100644 --- a/mopidy/gstreamer.py +++ b/mopidy/gstreamer.py @@ -29,7 +29,7 @@ class GStreamer(ThreadingActor): **Settings:** - - :attr:`mopidy.settings.OUTPUTS` + - :attr:`mopidy.settings.OUTPUT` """ @@ -66,9 +66,9 @@ class GStreamer(ThreadingActor): self._pipeline.get_by_name('convert').get_pad('sink')) def _setup_outputs(self): - for output in settings.OUTPUTS: - self._outputs.append(get_class(output)(self)) - self._outputs[0].connect() + for klass in settings.OUTPUTS: + self._outputs.append(get_class(klass)()) + self.connect_output(self._outputs[0].bin) def _setup_message_processor(self): bus = self._pipeline.get_bus() @@ -87,10 +87,6 @@ class GStreamer(ThreadingActor): pad.link(target_pad) def _on_message(self, bus, message): - if message.src in self._handlers: - if self._handlers[message.src](message): - return # Message was handeled by output - if message.type == gst.MESSAGE_EOS: logger.debug(u'GStreamer signalled end-of-stream. ' 'Telling backend ...') @@ -305,86 +301,4 @@ class GStreamer(ThreadingActor): gst.element_link_many(self._volume, output) logger.debug('Output set to %s', output.get_name()) - def list_outputs(self): - """ - Get list with the name of all active outputs. - - :rtype: list of strings - """ - return [output.get_name() for output in self._outputs] - - def remove_output(self, output): - """ - Remove output from our pipeline. - - :param output: output to remove from the pipeline - :type output: :class:`gst.Bin` - """ - peersrc = output.get_pad('sink').get_peer() - handler = peersrc.add_event_probe(self._handle_event_probe) - - struct = gst.Structure('mopidy-unlink') - struct.set_value('handler', handler) - - event = gst.event_new_custom(gst.EVENT_CUSTOM_DOWNSTREAM, struct) - self._volume.send_event(event) - - def _handle_event_probe(self, srcpad, event): - if event.type == gst.EVENT_CUSTOM_DOWNSTREAM and event.has_name('mopidy-unlink'): - data = self._get_structure_data(event.get_structure()) - - output = srcpad.get_peer().get_parent() - - srcpad.unlink(srcpad.get_peer()) - srcpad.remove_event_probe(data['handler']) - - output.set_state(gst.STATE_NULL) - self._pipeline.remove(output) - - logger.warning('Removed %s', output.get_name()) - return False - return True - - def _get_structure_data(self, struct): - # Ugly hack to get around missing get_value in pygst bindings :/ - data = {} - def get_data(key, value): - data[key] = value - struct.foreach(get_data) - return data - - def connect_message_handler(self, element, handler): - """ - Attach custom message handler for given element. - - Hook to allow outputs (or other code) to register custom message - handlers for all messages coming from the element in question. - - In the case of outputs, :meth:`mopidy.outputs.BaseOutput.on_connect` - should be used to attach such handlers and care should be taken to - remove them in :meth:`mopidy.outputs.BaseOutput.on_remove` using - :meth:`remove_message_handler`. - - The handler callback will only be given the message in question, and - is free to ignore the message. However, if the handler wants to prevent - the default handling of the message it should return :class:`True` - indicating that the message has been handled. - - Note that there can only be one handler per element. - - :param element: element to watch messages from - :type element: :class:`gst.Element` - :param handler: callable that takes :class:`gst.Message` and returns - :class:`True` if the message has been handeled - :type handler: callable - """ - self._handlers[element] = handler - - def remove_message_handler(self, element): - """ - Remove custom message handler. - - :param element: element to remove message handling from. - :type element: :class:`gst.Element` - """ - self._handlers.pop(element, None) + # FIXME re-add disconnect / swap output code? diff --git a/mopidy/outputs/__init__.py b/mopidy/outputs/__init__.py index d94c0727..21179f94 100644 --- a/mopidy/outputs/__init__.py +++ b/mopidy/outputs/__init__.py @@ -13,8 +13,7 @@ class BaseOutput(object): MESSAGE_ERROR = gst.MESSAGE_ERROR MESSAGE_WARNING = gst.MESSAGE_WARNING - def __init__(self, gstreamer): - self.gstreamer = gstreamer + def __init__(self): self.bin = self._build_bin() self.bin.set_name(self.get_name()) @@ -25,32 +24,6 @@ class BaseOutput(object): logger.debug('Creating new output: %s', description) return gst.parse_bin_from_description(description, True) - def connect(self): - """Attach output to GStreamer pipeline.""" - self.gstreamer.connect_output(self.bin) - self.on_connect() - - def on_connect(self): - """ - Called after output has been connected to GStreamer pipeline. - - *MAY be implemented by subclass.* - """ - pass - - def remove(self): - """Remove output from GStreamer pipeline.""" - self.gstreamer.remove_output(self.bin) - self.on_remove() - - def on_remove(self): - """ - Called after output has been removed from GStreamer pipeline. - - *MAY be implemented by subclass.* - """ - pass - def get_name(self): """ Get name of the output. Defaults to the output's class name. diff --git a/mopidy/outputs/shoutcast.py b/mopidy/outputs/shoutcast.py index ffe09aae..0279ae2d 100644 --- a/mopidy/outputs/shoutcast.py +++ b/mopidy/outputs/shoutcast.py @@ -40,19 +40,3 @@ class ShoutcastOutput(BaseOutput): u'username': settings.SHOUTCAST_OUTPUT_USERNAME, u'password': settings.SHOUTCAST_OUTPUT_PASSWORD, }) - - def on_connect(self): - self.gstreamer.connect_message_handler( - self.bin.get_by_name('shoutcast'), self.message_handler) - - def on_remove(self): - self.gstreamer.remove_message_handler( - self.bin.get_by_name('shoutcast')) - - def message_handler(self, message): - if message.type != self.MESSAGE_ERROR: - return False - error, debug = message.parse_error() - logger.warning('%s (%s)', error, debug) - self.remove() - return True diff --git a/mopidy/settings.py b/mopidy/settings.py index f3e012ed..392c9ad7 100644 --- a/mopidy/settings.py +++ b/mopidy/settings.py @@ -173,12 +173,8 @@ MPD_SERVER_PASSWORD = None #: #: Default:: #: -#: OUTPUTS = ( -#: u'mopidy.outputs.local.LocalOutput', -#: ) -OUTPUTS = ( - u'mopidy.outputs.local.LocalOutput', -) +#: OUTPUTS = (u'mopidy.outputs.local.LocalOutput',) +OUTPUTS = (u'mopidy.outputs.local.LocalOutput',) #: Hostname of the SHOUTcast server which Mopidy should stream audio to. #: