<commit_before>import pygst
pygst.require('0.10')
import gst

import logging

from pykka.actor import ThreadingActor
from pykka.registry import ActorRegistry

from mopidy import settings
from mopidy.backends.base import Backend
from mopidy.outputs.base import BaseOutput

logger = logging.getLogger('mopidy.outputs.gstreamer')

class GStreamerOutput(ThreadingActor, BaseOutput):
    """
    Audio output through `GStreamer <http://gstreamer.freedesktop.org/>`_.

    **Settings:**

    - :attr:`mopidy.settings.GSTREAMER_AUDIO_SINK`

    """

    def __init__(self):
        self.gst_pipeline = None

    def post_start(self):
        self._setup_gstreamer()

    def _setup_gstreamer(self):
        """
        **Warning:** :class:`GStreamerOutput` requires
        :class:`mopidy.utils.process.GObjectEventThread` to be running. This is
        not enforced by :class:`GStreamerOutput` itself.
        """

        logger.debug(u'Setting up GStreamer pipeline')

        self.gst_pipeline = gst.parse_launch(' ! '.join([
            'audioconvert name=convert',
            'volume name=volume',
            settings.GSTREAMER_AUDIO_SINK,
        ]))

        pad = self.gst_pipeline.get_by_name('convert').get_pad('sink')

        if settings.BACKENDS[0] == 'mopidy.backends.local.LocalBackend':
            uri_bin = gst.element_factory_make('uridecodebin', 'uri')
            uri_bin.connect('pad-added', self._process_new_pad, pad)
            self.gst_pipeline.add(uri_bin)
        else:
            app_src = gst.element_factory_make('appsrc', 'appsrc')
            app_src_caps = gst.Caps("""
                audio/x-raw-int,
                endianness=(int)1234,
                channels=(int)2,
                width=(int)16,
                depth=(int)16,
                signed=(boolean)true,
                rate=(int)44100""")
            app_src.set_property('caps', app_src_caps)
            self.gst_pipeline.add(app_src)
            app_src.get_pad('src').link(pad)

        # Setup bus and message processor
        gst_bus = self.gst_pipeline.get_bus()
        gst_bus.add_signal_watch()
        gst_bus.connect('message', self._process_gstreamer_message)

    def _process_new_pad(self, source, pad, target_pad):
        pad.link(target_pad)

    def _process_gstreamer_message(self, bus, message):
        """Process messages from GStreamer."""
        if message.type == gst.MESSAGE_EOS:
            logger.debug(u'GStreamer signalled end-of-stream. '
                'Telling backend ...')
            self._get_backend().playback.on_end_of_track()
        elif message.type == gst.MESSAGE_ERROR:
            self.set_state('NULL')
            error, debug = message.parse_error()
            logger.error(u'%s %s', error, debug)
            # FIXME Should we send 'stop_playback' to the backend here? Can we
            # differentiate on how serious the error is?

    def _get_backend(self):
        backend_refs = ActorRegistry.get_by_class(Backend)
        assert len(backend_refs) == 1, 'Expected exactly one running backend.'
        return backend_refs[0].proxy()

    def play_uri(self, uri):
        """Play audio at URI"""
        self.set_state('READY')
        self.gst_pipeline.get_by_name('uri').set_property('uri', uri)
        return self.set_state('PLAYING')

    def deliver_data(self, capabilities, data):
        """Deliver audio data to be played"""
        app_src = self.gst_pipeline.get_by_name('appsrc')
        caps = gst.caps_from_string(caps_string)<commit_msg>Fix sound with Spotify backend (YAY :-) )<commit_after>import pygst
pygst.require('0.10')
import gst

import logging

from pykka.actor import ThreadingActor
from pykka.registry import ActorRegistry

from mopidy import settings
from mopidy.backends.base import Backend
from mopidy.outputs.base import BaseOutput

logger = logging.getLogger('mopidy.outputs.gstreamer')

class GStreamerOutput(ThreadingActor, BaseOutput):
    """
    Audio output through `GStreamer <http://gstreamer.freedesktop.org/>`_.

    **Settings:**

    - :attr:`mopidy.settings.GSTREAMER_AUDIO_SINK`

    """

    def __init__(self):
        self.gst_pipeline = None

    def post_start(self):
        self._setup_gstreamer()

    def _setup_gstreamer(self):
        """
        **Warning:** :class:`GStreamerOutput` requires
        :class:`mopidy.utils.process.GObjectEventThread` to be running. This is
        not enforced by :class:`GStreamerOutput` itself.
        """

        logger.debug(u'Setting up GStreamer pipeline')

        self.gst_pipeline = gst.parse_launch(' ! '.join([
            'audioconvert name=convert',
            'volume name=volume',
            settings.GSTREAMER_AUDIO_SINK,
        ]))

        pad = self.gst_pipeline.get_by_name('convert').get_pad('sink')

        if settings.BACKENDS[0] == 'mopidy.backends.local.LocalBackend':
            uri_bin = gst.element_factory_make('uridecodebin', 'uri')
            uri_bin.connect('pad-added', self._process_new_pad, pad)
            self.gst_pipeline.add(uri_bin)
        else:
            app_src = gst.element_factory_make('appsrc', 'appsrc')
            app_src_caps = gst.Caps("""
                audio/x-raw-int,
                endianness=(int)1234,
                channels=(int)2,
                width=(int)16,
                depth=(int)16,
                signed=(boolean)true,
                rate=(int)44100""")
            app_src.set_property('caps', app_src_caps)
            self.gst_pipeline.add(app_src)
            app_src.get_pad('src').link(pad)

        # Setup bus and message processor
        gst_bus = self.gst_pipeline.get_bus()
        gst_bus.add_signal_watch()
        gst_bus.connect('message', self._process_gstreamer_message)

    def _process_new_pad(self, source, pad, target_pad):
        pad.link(target_pad)

    def _process_gstreamer_message(self, bus, message):
        """Process messages from GStreamer."""
        if message.type == gst.MESSAGE_EOS:
            logger.debug(u'GStreamer signalled end-of-stream. '
                'Telling backend ...')
            self._get_backend().playback.on_end_of_track()
        elif message.type == gst.MESSAGE_ERROR:
            self.set_state('NULL')
            error, debug = message.parse_error()
            logger.error(u'%s %s', error, debug)
            # FIXME Should we send 'stop_playback' to the backend here? Can we
            # differentiate on how serious the error is?

    def _get_backend(self):
        backend_refs = ActorRegistry.get_by_class(Backend)
        assert len(backend_refs) == 1, 'Expected exactly one running backend.'
        return backend_refs[0].proxy()

    def play_uri(self, uri):
        """Play audio at URI"""
        self.set_state('READY')
        self.gst_pipeline.get_by_name('uri').set_property('uri', uri)
        return self.set_state('PLAYING')

    def deliver_data(self, caps_string, data):
        """Deliver audio data to be played"""
        app_src = self.gst_pipeline.get_by_name('appsrc')
        caps = gst.caps_from_string(caps_string)
{'fraction_non_alphanumeric': 0.11463794813660196, 'fraction_numerical': 0.005668130933824571, 'mean_word_length': 2.5592536560766517, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5295582', 'n_tokens_mistral': 2240, 'n_tokens_neox': 2171, 'n_words': 415}