<commit_before>from __future__ import unicode_literals

import logging

import gobject

import pygst
pygst.require('0.10')
import gst  # noqa

import pykka

from mopidy.audio import playlists, utils
from mopidy.audio.constants import PlaybackState
from mopidy.audio.listener import AudioListener
from mopidy.utils import process


logger = logging.getLogger(__name__)

playlists.register_typefinders()
playlists.register_elements()

_GST_STATE_MAPPING = {
    gst.STATE_PLAYING: PlaybackState.PLAYING,
    gst.STATE_PAUSED: PlaybackState.PAUSED,
    gst.STATE_NULL: PlaybackState.STOPPED}

MB = 1 << 20

# GST_PLAY_FLAG_VIDEO (1<<0)
# GST_PLAY_FLAG_AUDIO (1<<1)
# GST_PLAY_FLAG_TEXT (1<<2)
# GST_PLAY_FLAG_VIS (1<<3)
# GST_PLAY_FLAG_SOFT_VOLUME (1<<4)
# GST_PLAY_FLAG_NATIVE_AUDIO (1<<5)
# GST_PLAY_FLAG_NATIVE_VIDEO (1<<6)
# GST_PLAY_FLAG_DOWNLOAD (1<<7)
# GST_PLAY_FLAG_BUFFERING (1<<8)
# GST_PLAY_FLAG_DEINTERLACE (1<<9)
# GST_PLAY_FLAG_SOFT_COLORBALANCE (1<<10)

# Default flags to use for playbin: AUDIO, SOFT_VOLUME, DOWNLOAD
PLAYBIN_FLAGS = (1 << 1) | (1 << 4) | (1 << 7)
PLAYBIN_VIS_FLAGS = PLAYBIN_FLAGS | (1 << 3)


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

    #: The GStreamer state mapped to :class:`mopidy.audio.PlaybackState`
    state = PlaybackState.STOPPED

    def __init__(self, config, mixer):
        super(Audio, self).__init__()

        self._config = config
        self._mixer = mixer
        self._target_state = gst.STATE_NULL
        self._buffering = False

        self._playbin = None
        self._signal_ids = {}  # {(element, event): signal_id}

        self._appsrc = None
        self._appsrc_caps = None
        self._appsrc_need_data_callback = None
        self._appsrc_enough_data_callback = None
        self._appsrc_seek_data_callback = None

    def on_start(self):
        try:
            self._setup_preferences()
            self._setup_playbin()
            self._setup_output()
            self._setup_mixer()
            self._setup_visualizer()
            self._setup_message_processor()
        except gobject.GError as ex:
            logger.exception(ex)
            process.exit_process()

    def on_stop(self):
        self._teardown_message_processor()
        self._teardown_mixer()
        self._teardown_playbin()

    def _connect(self, element, event, *args):
        """Helper to keep track of signal ids based on element+event"""
        self._signal_ids[(element, event)] = element.connect(event, *args)

    def _disconnect(self, element, event):
        """Helper to disconnect signals created with _connect helper."""
        signal_id = self._signal_ids.pop((element, event), None)
        if signal_id is not None:
            element.disconnect(signal_id)

    def _setup_preferences(self):
        registry = gst.registry_get_default()
        jacksink = registry.find_feature(
            'jackaudiosink', gst.TYPE_ELEMENT_FACTORY)
        if jacksink:
            jacksink.set_rank(gst.RANK_SECONDARY)

    def _setup_playbin(self):
        playbin = gst.element_factory_make('playbin2')
        playbin.set_property('flags', PLAYBIN_FLAGS)

        playbin.set_property('buffer-size', 2*1024*1024)
        playbin.set_property('buffer-duration', 2*gst.SECOND)

        self._connect(playbin, 'about-to-finish', self._on_about_to_finish)
        self._connect(playbin, 'notify::source', self._on_new_source)
        self._connect(playbin, 'source-setup', self._on_source_setup)

        self._playbin = playbin

    def _on_about_to_finish(self, element):
        source, self._appsrc = self._appsrc, None
        if source is None:
            return
        self._appsrc_caps = None

        self._disconnect(source, 'need-data')
        self._disconnect(source, 'enough-data')
        self._disconnect(source, 'seek-data')<commit_msg>audio: Link to context of why we demote jack sinks (cherry picked from commit <PASSWORD>)<commit_after>from __future__ import unicode_literals

import logging

import gobject

import pygst
pygst.require('0.10')
import gst  # noqa

import pykka

from mopidy.audio import playlists, utils
from mopidy.audio.constants import PlaybackState
from mopidy.audio.listener import AudioListener
from mopidy.utils import process


logger = logging.getLogger(__name__)

playlists.register_typefinders()
playlists.register_elements()

_GST_STATE_MAPPING = {
    gst.STATE_PLAYING: PlaybackState.PLAYING,
    gst.STATE_PAUSED: PlaybackState.PAUSED,
    gst.STATE_NULL: PlaybackState.STOPPED}

MB = 1 << 20

# GST_PLAY_FLAG_VIDEO (1<<0)
# GST_PLAY_FLAG_AUDIO (1<<1)
# GST_PLAY_FLAG_TEXT (1<<2)
# GST_PLAY_FLAG_VIS (1<<3)
# GST_PLAY_FLAG_SOFT_VOLUME (1<<4)
# GST_PLAY_FLAG_NATIVE_AUDIO (1<<5)
# GST_PLAY_FLAG_NATIVE_VIDEO (1<<6)
# GST_PLAY_FLAG_DOWNLOAD (1<<7)
# GST_PLAY_FLAG_BUFFERING (1<<8)
# GST_PLAY_FLAG_DEINTERLACE (1<<9)
# GST_PLAY_FLAG_SOFT_COLORBALANCE (1<<10)

# Default flags to use for playbin: AUDIO, SOFT_VOLUME, DOWNLOAD
PLAYBIN_FLAGS = (1 << 1) | (1 << 4) | (1 << 7)
PLAYBIN_VIS_FLAGS = PLAYBIN_FLAGS | (1 << 3)


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

    #: The GStreamer state mapped to :class:`mopidy.audio.PlaybackState`
    state = PlaybackState.STOPPED

    def __init__(self, config, mixer):
        super(Audio, self).__init__()

        self._config = config
        self._mixer = mixer
        self._target_state = gst.STATE_NULL
        self._buffering = False

        self._playbin = None
        self._signal_ids = {}  # {(element, event): signal_id}

        self._appsrc = None
        self._appsrc_caps = None
        self._appsrc_need_data_callback = None
        self._appsrc_enough_data_callback = None
        self._appsrc_seek_data_callback = None

    def on_start(self):
        try:
            self._setup_preferences()
            self._setup_playbin()
            self._setup_output()
            self._setup_mixer()
            self._setup_visualizer()
            self._setup_message_processor()
        except gobject.GError as ex:
            logger.exception(ex)
            process.exit_process()

    def on_stop(self):
        self._teardown_message_processor()
        self._teardown_mixer()
        self._teardown_playbin()

    def _connect(self, element, event, *args):
        """Helper to keep track of signal ids based on element+event"""
        self._signal_ids[(element, event)] = element.connect(event, *args)

    def _disconnect(self, element, event):
        """Helper to disconnect signals created with _connect helper."""
        signal_id = self._signal_ids.pop((element, event), None)
        if signal_id is not None:
            element.disconnect(signal_id)

    def _setup_preferences(self):
        # Fix for https://github.com/mopidy/mopidy/issues/604
        registry = gst.registry_get_default()
        jacksink = registry.find_feature(
            'jackaudiosink', gst.TYPE_ELEMENT_FACTORY)
        if jacksink:
            jacksink.set_rank(gst.RANK_SECONDARY)

    def _setup_playbin(self):
        playbin = gst.element_factory_make('playbin2')
        playbin.set_property('flags', PLAYBIN_FLAGS)

        playbin.set_property('buffer-size', 2*1024*1024)
        playbin.set_property('buffer-duration', 2*gst.SECOND)

        self._connect(playbin, 'about-to-finish', self._on_about_to_finish)
        self._connect(playbin, 'notify::source', self._on_new_source)
        self._connect(playbin, 'source-setup', self._on_source_setup)

        self._playbin = playbin

    def _on_about_to_finish(self, element):
        source, self._appsrc = self._appsrc, None
        if source is None:
            return
        self._appsrc_caps = None

        self._disconnect(source, 'need-data')
        self._disconnect(source, 'enough-data')
        self._disconnect(source, 'seek-data')
{'fraction_non_alphanumeric': 0.10456034265558076, 'fraction_numerical': 0.012471655328798186, 'mean_word_length': 3.1521966527196654, 'pattern_counts': {'":': 0, '<': 70, '<?xml version=': 0, '>': 6, 'https://': 1, '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': '76494', 'n_tokens_mistral': 2703, 'n_tokens_neox': 2591, 'n_words': 510}