Rip out rest of code that supported simulatnous outputs
This commit is contained in:
parent
f912164d39
commit
b2ccdec960
@ -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)
|
||||
|
||||
@ -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.
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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?
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
#:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user