gst1: Update imports to use PyGI

This commit is contained in:
Stein Magnus Jodal 2015-09-02 00:24:02 +02:00
parent d046974aaf
commit 8c82f4773f
14 changed files with 263 additions and 275 deletions

View File

@ -7,12 +7,12 @@ import sys
import textwrap
try:
import gobject # noqa
from gi.repository import GObject, Gst
except ImportError:
print(textwrap.dedent("""
ERROR: The gobject Python package was not found.
ERROR: The GObject and Gst Python packages were not found.
Mopidy requires GStreamer (and GObject) to work. These are C libraries
Mopidy requires GStreamer and GObject to work. These are C libraries
with a number of dependencies themselves, and cannot be installed with
the regular Python tools like pip.
@ -21,7 +21,7 @@ except ImportError:
"""))
raise
gobject.threads_init()
GObject.threads_init()
try:
# Make GObject's mainloop the event loop for python-dbus

View File

@ -4,12 +4,9 @@ import logging
import os
import threading
import gobject
import pygst
pygst.require('0.10')
import gst # noqa
import gst.pbutils # noqa
import gi
gi.require_version('Gst', '1.0')
from gi.repository import GObject, Gst
import pykka
@ -28,9 +25,9 @@ logger = logging.getLogger(__name__)
gst_logger = logging.getLogger('mopidy.audio.gst')
_GST_STATE_MAPPING = {
gst.STATE_PLAYING: PlaybackState.PLAYING,
gst.STATE_PAUSED: PlaybackState.PAUSED,
gst.STATE_NULL: PlaybackState.STOPPED}
Gst.STATE_PLAYING: PlaybackState.PLAYING,
Gst.STATE_PAUSED: PlaybackState.PAUSED,
Gst.STATE_NULL: PlaybackState.STOPPED}
class _Signals(object):
@ -118,9 +115,9 @@ class _Appsrc(object):
if buffer_ is None:
gst_logger.debug('Sending appsrc end-of-stream event.')
return self._source.emit('end-of-stream') == gst.FLOW_OK
return self._source.emit('end-of-stream') == Gst.FLOW_OK
else:
return self._source.emit('push-buffer', buffer_) == gst.FLOW_OK
return self._source.emit('push-buffer', buffer_) == Gst.FLOW_OK
def _on_signal(self, element, clocktime, func):
# This shim is used to ensure we always return true, and also handles
@ -133,29 +130,29 @@ class _Appsrc(object):
# TODO: expose this as a property on audio when #790 gets further along.
class _Outputs(gst.Bin):
class _Outputs(Gst.Bin):
def __init__(self):
gst.Bin.__init__(self, 'outputs')
Gst.Bin.__init__(self, 'outputs')
self._tee = gst.element_factory_make('tee')
self._tee = Gst.element_factory_make('tee')
self.add(self._tee)
ghost_pad = gst.GhostPad('sink', self._tee.get_pad('sink'))
ghost_pad = Gst.GhostPad('sink', self._tee.get_pad('sink'))
self.add_pad(ghost_pad)
# 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 = 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.
try:
output = gst.parse_bin_from_description(
output = Gst.parse_bin_from_description(
description, ghost_unconnected_pads=True)
except gobject.GError as ex:
except GObject.GError as ex:
logger.error(
'Failed to create audio output "%s": %s', description, ex)
raise exceptions.AudioException(bytes(ex))
@ -164,7 +161,7 @@ class _Outputs(gst.Bin):
logger.info('Audio output set to "%s"', description)
def _add(self, element):
queue = gst.element_factory_make('queue')
queue = Gst.element_factory_make('queue')
self.add(element)
self.add(queue)
queue.link(element)
@ -234,28 +231,28 @@ class _Handler(object):
self._event_handler_id = None
def on_message(self, bus, msg):
if msg.type == gst.MESSAGE_STATE_CHANGED and msg.src == self._element:
if msg.type == Gst.MESSAGE_STATE_CHANGED and msg.src == self._element:
self.on_playbin_state_changed(*msg.parse_state_changed())
elif msg.type == gst.MESSAGE_BUFFERING:
elif msg.type == Gst.MESSAGE_BUFFERING:
self.on_buffering(msg.parse_buffering(), msg.structure)
elif msg.type == gst.MESSAGE_EOS:
elif msg.type == Gst.MESSAGE_EOS:
self.on_end_of_stream()
elif msg.type == gst.MESSAGE_ERROR:
elif msg.type == Gst.MESSAGE_ERROR:
self.on_error(*msg.parse_error())
elif msg.type == gst.MESSAGE_WARNING:
elif msg.type == Gst.MESSAGE_WARNING:
self.on_warning(*msg.parse_warning())
elif msg.type == gst.MESSAGE_ASYNC_DONE:
elif msg.type == Gst.MESSAGE_ASYNC_DONE:
self.on_async_done()
elif msg.type == gst.MESSAGE_TAG:
elif msg.type == Gst.MESSAGE_TAG:
self.on_tag(msg.parse_tag())
elif msg.type == gst.MESSAGE_ELEMENT:
if gst.pbutils.is_missing_plugin_message(msg):
elif msg.type == Gst.MESSAGE_ELEMENT:
if Gst.pbutils.is_missing_plugin_message(msg):
self.on_missing_plugin(msg)
def on_event(self, pad, event):
if event.type == gst.EVENT_NEWSEGMENT:
if event.type == Gst.EVENT_NEWSEGMENT:
self.on_new_segment(*event.parse_new_segment())
elif event.type == gst.EVENT_SINK_MESSAGE:
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()
@ -268,17 +265,17 @@ class _Handler(object):
old_state.value_name, new_state.value_name,
pending_state.value_name)
if new_state == gst.STATE_READY and pending_state == gst.STATE_NULL:
if new_state == Gst.STATE_READY and pending_state == Gst.STATE_NULL:
# XXX: We're not called on the last state change when going down to
# NULL, so we rewrite the second to last call to get the expected
# behavior.
new_state = gst.STATE_NULL
pending_state = gst.STATE_VOID_PENDING
new_state = Gst.STATE_NULL
pending_state = Gst.STATE_VOID_PENDING
if pending_state != gst.STATE_VOID_PENDING:
if pending_state != Gst.STATE_VOID_PENDING:
return # Ignore intermediate state changes
if new_state == gst.STATE_READY:
if new_state == Gst.STATE_READY:
return # Ignore READY state as it's GStreamer specific
new_state = _GST_STATE_MAPPING[new_state]
@ -297,23 +294,23 @@ class _Handler(object):
AudioListener.send('stream_changed', uri=None)
if 'GST_DEBUG_DUMP_DOT_DIR' in os.environ:
gst.DEBUG_BIN_TO_DOT_FILE(
self._audio._playbin, gst.DEBUG_GRAPH_SHOW_ALL, 'mopidy')
Gst.DEBUG_BIN_TO_DOT_FILE(
self._audio._playbin, Gst.DEBUG_GRAPH_SHOW_ALL, 'mopidy')
def on_buffering(self, percent, structure=None):
if structure and structure.has_field('buffering-mode'):
if structure['buffering-mode'] == gst.BUFFERING_LIVE:
if structure['buffering-mode'] == Gst.BUFFERING_LIVE:
return # Live sources stall in paused.
level = logging.getLevelName('TRACE')
if percent < 10 and not self._audio._buffering:
self._audio._playbin.set_state(gst.STATE_PAUSED)
self._audio._playbin.set_state(Gst.STATE_PAUSED)
self._audio._buffering = True
level = logging.DEBUG
if percent == 100:
self._audio._buffering = False
if self._audio._target_state == gst.STATE_PLAYING:
self._audio._playbin.set_state(gst.STATE_PLAYING)
if self._audio._target_state == Gst.STATE_PLAYING:
self._audio._playbin.set_state(Gst.STATE_PLAYING)
level = logging.DEBUG
gst_logger.log(level, 'Got buffering message: percent=%d%%', percent)
@ -346,12 +343,12 @@ class _Handler(object):
AudioListener.send('tags_changed', tags=tags.keys())
def on_missing_plugin(self, msg):
desc = gst.pbutils.missing_plugin_message_get_description(msg)
debug = gst.pbutils.missing_plugin_message_get_installer_detail(msg)
desc = Gst.pbutils.missing_plugin_message_get_description(msg)
debug = Gst.pbutils.missing_plugin_message_get_installer_detail(msg)
gst_logger.debug('Got missing-plugin message: description:%s', desc)
logger.warning('Could not find a %s to handle media.', desc)
if gst.pbutils.install_plugins_supported():
if Gst.pbutils.install_plugins_supported():
logger.info('You might be able to fix this by running: '
'gst-installer "%s"', debug)
# TODO: store the missing plugins installer info in a file so we can
@ -362,7 +359,7 @@ class _Handler(object):
gst_logger.debug('Got new-segment event: update=%s rate=%s format=%s '
'start=%s stop=%s position=%s', update, rate,
format_.value_name, start, stop, position)
position_ms = position // gst.MSECOND
position_ms = position // Gst.MSECOND
logger.debug('Audio event: position_changed(position=%s)', position_ms)
AudioListener.send('position_changed', position=position_ms)
@ -389,7 +386,7 @@ class Audio(pykka.ThreadingActor):
super(Audio, self).__init__()
self._config = config
self._target_state = gst.STATE_NULL
self._target_state = Gst.STATE_NULL
self._buffering = False
self._tags = {}
@ -411,7 +408,7 @@ class Audio(pykka.ThreadingActor):
self._setup_playbin()
self._setup_outputs()
self._setup_audio_sink()
except gobject.GError as ex:
except GObject.GError as ex:
logger.exception(ex)
process.exit_process()
@ -422,19 +419,19 @@ class Audio(pykka.ThreadingActor):
def _setup_preferences(self):
# TODO: move out of audio actor?
# Fix for https://github.com/mopidy/mopidy/issues/604
registry = gst.registry_get_default()
registry = Gst.registry_get_default()
jacksink = registry.find_feature(
'jackaudiosink', gst.TYPE_ELEMENT_FACTORY)
'jackaudiosink', Gst.TYPE_ELEMENT_FACTORY)
if jacksink:
jacksink.set_rank(gst.RANK_SECONDARY)
jacksink.set_rank(Gst.RANK_SECONDARY)
def _setup_playbin(self):
playbin = gst.element_factory_make('playbin2')
playbin = Gst.element_factory_make('playbin2')
playbin.set_property('flags', 2) # GST_PLAY_FLAG_AUDIO
# TODO: turn into config values...
playbin.set_property('buffer-size', 5 << 20) # 5MB
playbin.set_property('buffer-duration', 5 * gst.SECOND)
playbin.set_property('buffer-duration', 5 * Gst.SECOND)
self._signals.connect(playbin, 'source-setup', self._on_source_setup)
self._signals.connect(playbin, 'about-to-finish',
@ -448,13 +445,13 @@ class Audio(pykka.ThreadingActor):
self._handler.teardown_event_handling()
self._signals.disconnect(self._playbin, 'about-to-finish')
self._signals.disconnect(self._playbin, 'source-setup')
self._playbin.set_state(gst.STATE_NULL)
self._playbin.set_state(Gst.STATE_NULL)
def _setup_outputs(self):
# We don't want to use outputs for regular testing, so just install
# an unsynced fakesink when someone asks for a 'testoutput'.
if self._config['audio']['output'] == 'testoutput':
self._outputs = gst.element_factory_make('fakesink')
self._outputs = Gst.element_factory_make('fakesink')
else:
self._outputs = _Outputs()
try:
@ -465,23 +462,23 @@ class Audio(pykka.ThreadingActor):
self._handler.setup_event_handling(self._outputs.get_pad('sink'))
def _setup_audio_sink(self):
audio_sink = gst.Bin('audio-sink')
audio_sink = Gst.Bin('audio-sink')
# Queue element to buy us time between the about to finish event and
# the actual switch, i.e. about to switch can block for longer thanks
# to this queue.
# TODO: make the min-max values a setting?
queue = gst.element_factory_make('queue')
queue = Gst.element_factory_make('queue')
queue.set_property('max-size-buffers', 0)
queue.set_property('max-size-bytes', 0)
queue.set_property('max-size-time', 3 * gst.SECOND)
queue.set_property('min-threshold-time', 1 * gst.SECOND)
queue.set_property('max-size-time', 3 * Gst.SECOND)
queue.set_property('min-threshold-time', 1 * Gst.SECOND)
audio_sink.add(queue)
audio_sink.add(self._outputs)
if self.mixer:
volume = gst.element_factory_make('volume')
volume = Gst.element_factory_make('volume')
audio_sink.add(volume)
queue.link(volume)
volume.link(self._outputs)
@ -489,7 +486,7 @@ class Audio(pykka.ThreadingActor):
else:
queue.link(self._outputs)
ghost_pad = gst.GhostPad('sink', queue.get_pad('sink'))
ghost_pad = Gst.GhostPad('sink', queue.get_pad('sink'))
audio_sink.add_pad(ghost_pad)
self._playbin.set_property('audio-sink', audio_sink)
@ -561,7 +558,7 @@ class Audio(pykka.ThreadingActor):
:type seek_data: callable which takes time position in ms
"""
self._appsrc.prepare(
gst.Caps(bytes(caps)), need_data, enough_data, seek_data)
Gst.Caps(bytes(caps)), need_data, enough_data, seek_data)
self._playbin.set_property('uri', 'appsrc://')
def emit_data(self, buffer_):
@ -577,7 +574,7 @@ class Audio(pykka.ThreadingActor):
Returns :class:`True` if data was delivered.
:param buffer_: buffer to pass to appsrc
:type buffer_: :class:`gst.Buffer` or :class:`None`
:type buffer_: :class:`Gst.Buffer` or :class:`None`
:rtype: boolean
"""
return self._appsrc.push(buffer_)
@ -616,9 +613,9 @@ class Audio(pykka.ThreadingActor):
:rtype: int
"""
try:
gst_position = self._playbin.query_position(gst.FORMAT_TIME)[0]
gst_position = self._playbin.query_position(Gst.FORMAT_TIME)[0]
return utils.clocktime_to_millisecond(gst_position)
except gst.QueryError:
except Gst.QueryError:
# TODO: take state into account for this and possibly also return
# None as the unknown value instead of zero?
logger.debug('Position query failed')
@ -635,7 +632,7 @@ class Audio(pykka.ThreadingActor):
# TODO: double check seek flags in use.
gst_position = utils.millisecond_to_clocktime(position)
result = self._playbin.seek_simple(
gst.Format(gst.FORMAT_TIME), gst.SEEK_FLAG_FLUSH, gst_position)
Gst.Format(Gst.FORMAT_TIME), Gst.SEEK_FLAG_FLUSH, gst_position)
gst_logger.debug('Sent flushing seek: position=%s', gst_position)
return result
@ -645,7 +642,7 @@ class Audio(pykka.ThreadingActor):
:rtype: :class:`True` if successfull, else :class:`False`
"""
return self._set_state(gst.STATE_PLAYING)
return self._set_state(Gst.STATE_PLAYING)
def pause_playback(self):
"""
@ -653,7 +650,7 @@ class Audio(pykka.ThreadingActor):
:rtype: :class:`True` if successfull, else :class:`False`
"""
return self._set_state(gst.STATE_PAUSED)
return self._set_state(Gst.STATE_PAUSED)
def prepare_change(self):
"""
@ -664,7 +661,7 @@ class Audio(pykka.ThreadingActor):
is that GStreamer will reset all its state when it changes to
:attr:`gst.STATE_READY`.
"""
return self._set_state(gst.STATE_READY)
return self._set_state(Gst.STATE_READY)
def stop_playback(self):
"""
@ -673,7 +670,7 @@ class Audio(pykka.ThreadingActor):
:rtype: :class:`True` if successfull, else :class:`False`
"""
self._buffering = False
return self._set_state(gst.STATE_NULL)
return self._set_state(Gst.STATE_NULL)
def wait_for_state_change(self):
"""Block until any pending state changes are complete.
@ -689,7 +686,7 @@ class Audio(pykka.ThreadingActor):
"""
def sync_handler(bus, message):
self._handler.on_message(bus, message)
return gst.BUS_DROP
return Gst.BUS_DROP
bus = self._playbin.get_bus()
bus.set_sync_handler(sync_handler)
@ -710,9 +707,9 @@ class Audio(pykka.ThreadingActor):
"READY" -> "NULL"
"READY" -> "PAUSED"
:param state: State to set playbin to. One of: `gst.STATE_NULL`,
`gst.STATE_READY`, `gst.STATE_PAUSED` and `gst.STATE_PLAYING`.
:type state: :class:`gst.State`
:param state: State to set playbin to. One of: `Gst.STATE_NULL`,
`Gst.STATE_READY`, `Gst.STATE_PAUSED` and `Gst.STATE_PLAYING`.
:type state: :class:`Gst.State`
:rtype: :class:`True` if successfull, else :class:`False`
"""
self._target_state = state
@ -720,7 +717,7 @@ class Audio(pykka.ThreadingActor):
gst_logger.debug('State change to %s: result=%s', state.value_name,
result.value_name)
if result == gst.STATE_CHANGE_FAILURE:
if result == Gst.STATE_CHANGE_FAILURE:
logger.warning(
'Setting GStreamer state to %s failed', state.value_name)
return False
@ -740,25 +737,25 @@ class Audio(pykka.ThreadingActor):
:param track: the current track
:type track: :class:`mopidy.models.Track`
"""
taglist = gst.TagList()
taglist = Gst.TagList()
artists = [a for a in (track.artists or []) if a.name]
# Default to blank data to trick shoutcast into clearing any previous
# values it might have.
taglist[gst.TAG_ARTIST] = ' '
taglist[gst.TAG_TITLE] = ' '
taglist[gst.TAG_ALBUM] = ' '
taglist[Gst.TAG_ARTIST] = ' '
taglist[Gst.TAG_TITLE] = ' '
taglist[Gst.TAG_ALBUM] = ' '
if artists:
taglist[gst.TAG_ARTIST] = ', '.join([a.name for a in artists])
taglist[Gst.TAG_ARTIST] = ', '.join([a.name for a in artists])
if track.name:
taglist[gst.TAG_TITLE] = track.name
taglist[Gst.TAG_TITLE] = track.name
if track.album and track.album.name:
taglist[gst.TAG_ALBUM] = track.album.name
taglist[Gst.TAG_ALBUM] = track.album.name
event = gst.event_new_tag(taglist)
event = Gst.event_new_tag(taglist)
# TODO: check if we get this back on our own bus?
self._playbin.send_event(event)
gst_logger.debug('Sent tag event: track=%s', track.uri)

View File

@ -3,10 +3,9 @@ from __future__ import (
import collections
import pygst
pygst.require('0.10')
import gst # noqa
import gst.pbutils # noqa
import gi
gi.require_version('Gst', '1.0')
from gi.repository import GObject, Gst, GstPbutils
from mopidy import exceptions
from mopidy.audio import utils
@ -15,7 +14,7 @@ from mopidy.internal import encoding
_Result = collections.namedtuple(
'Result', ('uri', 'tags', 'duration', 'seekable', 'mime', 'playable'))
_RAW_AUDIO = gst.Caps(b'audio/x-raw-int; audio/x-raw-float')
_RAW_AUDIO = Gst.Caps(b'audio/x-raw-int; audio/x-raw-float')
# TODO: replace with a scan(uri, timeout=1000, proxy_config=None)?
@ -59,7 +58,7 @@ class Scanner(object):
duration = _query_duration(pipeline)
seekable = _query_seekable(pipeline)
finally:
pipeline.set_state(gst.STATE_NULL)
pipeline.set_state(Gst.STATE_NULL)
del pipeline
return _Result(uri, tags, duration, seekable, mime, have_audio)
@ -68,17 +67,17 @@ class Scanner(object):
# Turns out it's _much_ faster to just create a new pipeline for every as
# decodebins and other elements don't seem to take well to being reused.
def _setup_pipeline(uri, proxy_config=None):
src = gst.element_make_from_uri(gst.URI_SRC, uri)
src = Gst.element_make_from_uri(Gst.URI_SRC, uri)
if not src:
raise exceptions.ScannerError('GStreamer can not open: %s' % uri)
typefind = gst.element_factory_make('typefind')
decodebin = gst.element_factory_make('decodebin2')
typefind = Gst.element_factory_make('typefind')
decodebin = Gst.element_factory_make('decodebin2')
pipeline = gst.element_factory_make('pipeline')
pipeline = Gst.element_factory_make('pipeline')
for e in (src, typefind, decodebin):
pipeline.add(e)
gst.element_link_many(src, typefind, decodebin)
Gst.element_link_many(src, typefind, decodebin)
if proxy_config:
utils.setup_proxy(src, proxy_config)
@ -91,13 +90,13 @@ def _setup_pipeline(uri, proxy_config=None):
def _have_type(element, probability, caps, decodebin):
decodebin.set_property('sink-caps', caps)
struct = gst.Structure('have-type')
struct = Gst.Structure('have-type')
struct['caps'] = caps.get_structure(0)
element.get_bus().post(gst.message_new_application(element, struct))
element.get_bus().post(Gst.message_new_application(element, struct))
def _pad_added(element, pad, pipeline):
sink = gst.element_factory_make('fakesink')
sink = Gst.element_factory_make('fakesink')
sink.set_property('sync', False)
pipeline.add(sink)
@ -105,29 +104,29 @@ def _pad_added(element, pad, pipeline):
pad.link(sink.get_pad('sink'))
if pad.get_caps().is_subset(_RAW_AUDIO):
struct = gst.Structure('have-audio')
element.get_bus().post(gst.message_new_application(element, struct))
struct = Gst.Structure('have-audio')
element.get_bus().post(Gst.message_new_application(element, struct))
def _start_pipeline(pipeline):
if pipeline.set_state(gst.STATE_PAUSED) == gst.STATE_CHANGE_NO_PREROLL:
pipeline.set_state(gst.STATE_PLAYING)
if pipeline.set_state(Gst.STATE_PAUSED) == Gst.STATE_CHANGE_NO_PREROLL:
pipeline.set_state(Gst.STATE_PLAYING)
def _query_duration(pipeline):
try:
duration = pipeline.query_duration(gst.FORMAT_TIME, None)[0]
except gst.QueryError:
duration = pipeline.query_duration(Gst.FORMAT_TIME, None)[0]
except Gst.QueryError:
return None
if duration < 0:
return None
else:
return duration // gst.MSECOND
return duration // Gst.MSECOND
def _query_seekable(pipeline):
query = gst.query_new_seeking(gst.FORMAT_TIME)
query = Gst.query_new_seeking(Gst.FORMAT_TIME)
pipeline.query(query)
return query.parse_seeking()[1]
@ -135,15 +134,15 @@ def _query_seekable(pipeline):
def _process(pipeline, timeout_ms):
clock = pipeline.get_clock()
bus = pipeline.get_bus()
timeout = timeout_ms * gst.MSECOND
timeout = timeout_ms * Gst.MSECOND
tags = {}
mime = None
have_audio = False
missing_message = None
types = (
gst.MESSAGE_ELEMENT | gst.MESSAGE_APPLICATION | gst.MESSAGE_ERROR |
gst.MESSAGE_EOS | gst.MESSAGE_ASYNC_DONE | gst.MESSAGE_TAG)
Gst.MESSAGE_ELEMENT | Gst.MESSAGE_APPLICATION | Gst.MESSAGE_ERROR |
Gst.MESSAGE_EOS | Gst.MESSAGE_ASYNC_DONE | Gst.MESSAGE_TAG)
previous = clock.get_time()
while timeout > 0:
@ -151,29 +150,29 @@ def _process(pipeline, timeout_ms):
if message is None:
break
elif message.type == gst.MESSAGE_ELEMENT:
if gst.pbutils.is_missing_plugin_message(message):
elif message.type == Gst.MESSAGE_ELEMENT:
if GstPbutils.is_missing_plugin_message(message):
missing_message = message
elif message.type == gst.MESSAGE_APPLICATION:
elif message.type == Gst.MESSAGE_APPLICATION:
if message.structure.get_name() == 'have-type':
mime = message.structure['caps'].get_name()
if mime.startswith('text/') or mime == 'application/xml':
return tags, mime, have_audio
elif message.structure.get_name() == 'have-audio':
have_audio = True
elif message.type == gst.MESSAGE_ERROR:
elif message.type == Gst.MESSAGE_ERROR:
error = encoding.locale_decode(message.parse_error()[0])
if missing_message and not mime:
caps = missing_message.structure['detail']
mime = caps.get_structure(0).get_name()
return tags, mime, have_audio
raise exceptions.ScannerError(error)
elif message.type == gst.MESSAGE_EOS:
elif message.type == Gst.MESSAGE_EOS:
return tags, mime, have_audio
elif message.type == gst.MESSAGE_ASYNC_DONE:
elif message.type == Gst.MESSAGE_ASYNC_DONE:
if message.src == pipeline:
return tags, mime, have_audio
elif message.type == gst.MESSAGE_TAG:
elif message.type == Gst.MESSAGE_TAG:
taglist = message.parse_tag()
# Note that this will only keep the last tag.
tags.update(utils.convert_taglist(taglist))
@ -189,15 +188,13 @@ if __name__ == '__main__':
import os
import sys
import gobject
from mopidy.internal import path
gobject.threads_init()
GObject.threads_init()
scanner = Scanner(5000)
for uri in sys.argv[1:]:
if not gst.uri_is_valid(uri):
if not Gst.uri_is_valid(uri):
uri = path.path_to_uri(os.path.abspath(uri))
try:
result = scanner.scan(uri)

View File

@ -4,9 +4,9 @@ import datetime
import logging
import numbers
import pygst
pygst.require('0.10')
import gst # noqa
import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst
from mopidy import compat, httpclient
from mopidy.models import Album, Artist, Track
@ -17,7 +17,7 @@ logger = logging.getLogger(__name__)
def calculate_duration(num_samples, sample_rate):
"""Determine duration of samples using GStreamer helper for precise
math."""
return gst.util_uint64_scale(num_samples, gst.SECOND, sample_rate)
return Gst.util_uint64_scale(num_samples, Gst.SECOND, sample_rate)
def create_buffer(data, capabilites=None, timestamp=None, duration=None):
@ -25,10 +25,10 @@ def create_buffer(data, capabilites=None, timestamp=None, duration=None):
Mainly intended to keep gst imports out of non-audio modules.
"""
buffer_ = gst.Buffer(data)
buffer_ = Gst.Buffer(data)
if capabilites:
if isinstance(capabilites, compat.string_types):
capabilites = gst.caps_from_string(capabilites)
capabilites = Gst.caps_from_string(capabilites)
buffer_.set_caps(capabilites)
if timestamp:
buffer_.timestamp = timestamp
@ -39,12 +39,12 @@ def create_buffer(data, capabilites=None, timestamp=None, duration=None):
def millisecond_to_clocktime(value):
"""Convert a millisecond time to internal GStreamer time."""
return value * gst.MSECOND
return value * Gst.MSECOND
def clocktime_to_millisecond(value):
"""Convert an internal GStreamer time to millisecond time."""
return value // gst.MSECOND
return value // Gst.MSECOND
def supported_uri_schemes(uri_schemes):
@ -55,9 +55,9 @@ def supported_uri_schemes(uri_schemes):
:rtype: set of URI schemes we can support via this GStreamer install.
"""
supported_schemes = set()
registry = gst.registry_get_default()
registry = Gst.registry_get_default()
for factory in registry.get_feature_list(gst.TYPE_ELEMENT_FACTORY):
for factory in registry.get_feature_list(Gst.TYPE_ELEMENT_FACTORY):
for uri in factory.get_uri_protocols():
if uri in uri_schemes:
supported_schemes.add(uri)
@ -95,37 +95,37 @@ def convert_tags_to_track(tags):
album_kwargs = {}
track_kwargs = {}
track_kwargs['composers'] = _artists(tags, gst.TAG_COMPOSER)
track_kwargs['performers'] = _artists(tags, gst.TAG_PERFORMER)
track_kwargs['artists'] = _artists(tags, gst.TAG_ARTIST,
track_kwargs['composers'] = _artists(tags, Gst.TAG_COMPOSER)
track_kwargs['performers'] = _artists(tags, Gst.TAG_PERFORMER)
track_kwargs['artists'] = _artists(tags, Gst.TAG_ARTIST,
'musicbrainz-artistid',
'musicbrainz-sortname')
album_kwargs['artists'] = _artists(
tags, gst.TAG_ALBUM_ARTIST, 'musicbrainz-albumartistid')
tags, Gst.TAG_ALBUM_ARTIST, 'musicbrainz-albumartistid')
track_kwargs['genre'] = '; '.join(tags.get(gst.TAG_GENRE, []))
track_kwargs['name'] = '; '.join(tags.get(gst.TAG_TITLE, []))
track_kwargs['genre'] = '; '.join(tags.get(Gst.TAG_GENRE, []))
track_kwargs['name'] = '; '.join(tags.get(Gst.TAG_TITLE, []))
if not track_kwargs['name']:
track_kwargs['name'] = '; '.join(tags.get(gst.TAG_ORGANIZATION, []))
track_kwargs['name'] = '; '.join(tags.get(Gst.TAG_ORGANIZATION, []))
track_kwargs['comment'] = '; '.join(tags.get('comment', []))
if not track_kwargs['comment']:
track_kwargs['comment'] = '; '.join(tags.get(gst.TAG_LOCATION, []))
track_kwargs['comment'] = '; '.join(tags.get(Gst.TAG_LOCATION, []))
if not track_kwargs['comment']:
track_kwargs['comment'] = '; '.join(tags.get(gst.TAG_COPYRIGHT, []))
track_kwargs['comment'] = '; '.join(tags.get(Gst.TAG_COPYRIGHT, []))
track_kwargs['track_no'] = tags.get(gst.TAG_TRACK_NUMBER, [None])[0]
track_kwargs['disc_no'] = tags.get(gst.TAG_ALBUM_VOLUME_NUMBER, [None])[0]
track_kwargs['bitrate'] = tags.get(gst.TAG_BITRATE, [None])[0]
track_kwargs['track_no'] = tags.get(Gst.TAG_TRACK_NUMBER, [None])[0]
track_kwargs['disc_no'] = tags.get(Gst.TAG_ALBUM_VOLUME_NUMBER, [None])[0]
track_kwargs['bitrate'] = tags.get(Gst.TAG_BITRATE, [None])[0]
track_kwargs['musicbrainz_id'] = tags.get('musicbrainz-trackid', [None])[0]
album_kwargs['name'] = tags.get(gst.TAG_ALBUM, [None])[0]
album_kwargs['num_tracks'] = tags.get(gst.TAG_TRACK_COUNT, [None])[0]
album_kwargs['num_discs'] = tags.get(gst.TAG_ALBUM_VOLUME_COUNT, [None])[0]
album_kwargs['name'] = tags.get(Gst.TAG_ALBUM, [None])[0]
album_kwargs['num_tracks'] = tags.get(Gst.TAG_TRACK_COUNT, [None])[0]
album_kwargs['num_discs'] = tags.get(Gst.TAG_ALBUM_VOLUME_COUNT, [None])[0]
album_kwargs['musicbrainz_id'] = tags.get('musicbrainz-albumid', [None])[0]
if tags.get(gst.TAG_DATE) and tags.get(gst.TAG_DATE)[0]:
track_kwargs['date'] = tags[gst.TAG_DATE][0].isoformat()
if tags.get(Gst.TAG_DATE) and tags.get(Gst.TAG_DATE)[0]:
track_kwargs['date'] = tags[Gst.TAG_DATE][0].isoformat()
# Clear out any empty values we found
track_kwargs = {k: v for k, v in track_kwargs.items() if v}
@ -142,7 +142,7 @@ def setup_proxy(element, config):
"""Configure a GStreamer element with proxy settings.
:param element: element to setup proxy in.
:type element: :class:`gst.GstElement`
:type element: :class:`Gst.GstElement`
:param config: proxy settings to use.
:type config: :class:`dict`
"""
@ -155,7 +155,7 @@ def setup_proxy(element, config):
def convert_taglist(taglist):
"""Convert a :class:`gst.Taglist` to plain Python types.
"""Convert a :class:`Gst.Taglist` to plain Python types.
Knows how to convert:
@ -172,7 +172,7 @@ def convert_taglist(taglist):
0.10.36/gstreamer/html/gstreamer-GstTagList.html
:param taglist: A GStreamer taglist to be converted.
:type taglist: :class:`gst.Taglist`
:type taglist: :class:`Gst.Taglist`
:rtype: dictionary of tag keys with a list of values.
"""
result = {}
@ -187,13 +187,13 @@ def convert_taglist(taglist):
values = [values]
for value in values:
if isinstance(value, gst.Date):
if isinstance(value, Gst.Date):
try:
date = datetime.date(value.year, value.month, value.day)
result[key].append(date)
except ValueError:
logger.debug('Ignoring invalid date: %r = %r', key, value)
elif isinstance(value, gst.Buffer):
elif isinstance(value, Gst.Buffer):
result[key].append(bytes(value))
elif isinstance(
value, (compat.string_types, bool, numbers.Number)):

View File

@ -7,9 +7,7 @@ import logging
import os
import sys
import glib
import gobject
from gi.repository import GLib, GObject
import pykka
@ -21,7 +19,7 @@ from mopidy.internal import deps, process, timer, versioning
logger = logging.getLogger(__name__)
_default_config = []
for base in glib.get_system_config_dirs() + (glib.get_user_config_dir(),):
for base in GLib.get_system_config_dirs() + (GLib.get_user_config_dir(),):
_default_config.append(os.path.join(base, b'mopidy', b'mopidy.conf'))
DEFAULT_CONFIG = b':'.join(_default_config)
@ -286,7 +284,7 @@ class RootCommand(Command):
help='`section/key=value` values to override config options')
def run(self, args, config):
loop = gobject.MainLoop()
loop = GObject.MainLoop()
mixer_class = self.get_mixer_class(config, args.registry['mixer'])
backend_classes = args.registry['backend']

View File

@ -5,11 +5,11 @@ import os
import platform
import sys
import pkg_resources
import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst
import pygst
pygst.require('0.10')
import gst # noqa
import pkg_resources
from mopidy.internal import formatting
@ -110,8 +110,7 @@ def pkg_info(project_name=None, include_extras=False):
def gstreamer_info():
other = []
other.append('Python wrapper: gst-python %s' % (
'.'.join(map(str, gst.get_pygst_version()))))
other.append('Python wrapper: python-gi %s' % gi.__version__)
found_elements = []
missing_elements = []
@ -135,8 +134,8 @@ def gstreamer_info():
return {
'name': 'GStreamer',
'version': '.'.join(map(str, gst.get_gst_version())),
'path': os.path.dirname(gst.__file__),
'version': '.'.join(map(str, Gst.version())),
'path': os.path.dirname(gi.__file__),
'other': '\n'.join(other),
}
@ -187,6 +186,6 @@ def _gstreamer_check_elements():
]
known_elements = [
factory.get_name() for factory in
gst.registry_get_default().get_feature_list(gst.TYPE_ELEMENT_FACTORY)]
Gst.registry_get_default().get_feature_list(Gst.TYPE_ELEMENT_FACTORY)]
return [
(element, element in known_elements) for element in elements_to_check]

View File

@ -7,7 +7,7 @@ import socket
import sys
import threading
import gobject
from gi.repository import GObject
import pykka
@ -67,7 +67,7 @@ def format_hostname(hostname):
class Server(object):
"""Setup listener and register it with gobject's event loop."""
"""Setup listener and register it with GObject's event loop."""
def __init__(self, host, port, protocol, protocol_kwargs=None,
max_connections=5, timeout=30):
@ -87,7 +87,7 @@ class Server(object):
return sock
def register_server_socket(self, fileno):
gobject.io_add_watch(fileno, gobject.IO_IN, self.handle_connection)
GObject.io_add_watch(fileno, GObject.IO_IN, self.handle_connection)
def handle_connection(self, fd, flags):
try:
@ -132,7 +132,7 @@ class Server(object):
class Connection(object):
# NOTE: the callback code is _not_ run in the actor's thread, but in the
# same one as the event loop. If code in the callbacks blocks, the rest of
# gobject code will likely be blocked as well...
# GObject code will likely be blocked as well...
#
# Also note that source_remove() return values are ignored on purpose, a
# false return value would only tell us that what we thought was registered
@ -211,14 +211,14 @@ class Connection(object):
return
self.disable_timeout()
self.timeout_id = gobject.timeout_add_seconds(
self.timeout_id = GObject.timeout_add_seconds(
self.timeout, self.timeout_callback)
def disable_timeout(self):
"""Deactivate timeout mechanism."""
if self.timeout_id is None:
return
gobject.source_remove(self.timeout_id)
GObject.source_remove(self.timeout_id)
self.timeout_id = None
def enable_recv(self):
@ -226,9 +226,9 @@ class Connection(object):
return
try:
self.recv_id = gobject.io_add_watch(
self.recv_id = GObject.io_add_watch(
self.sock.fileno(),
gobject.IO_IN | gobject.IO_ERR | gobject.IO_HUP,
GObject.IO_IN | GObject.IO_ERR | GObject.IO_HUP,
self.recv_callback)
except socket.error as e:
self.stop('Problem with connection: %s' % e)
@ -236,7 +236,7 @@ class Connection(object):
def disable_recv(self):
if self.recv_id is None:
return
gobject.source_remove(self.recv_id)
GObject.source_remove(self.recv_id)
self.recv_id = None
def enable_send(self):
@ -244,9 +244,9 @@ class Connection(object):
return
try:
self.send_id = gobject.io_add_watch(
self.send_id = GObject.io_add_watch(
self.sock.fileno(),
gobject.IO_OUT | gobject.IO_ERR | gobject.IO_HUP,
GObject.IO_OUT | GObject.IO_ERR | GObject.IO_HUP,
self.send_callback)
except socket.error as e:
self.stop('Problem with connection: %s' % e)
@ -255,11 +255,11 @@ class Connection(object):
if self.send_id is None:
return
gobject.source_remove(self.send_id)
GObject.source_remove(self.send_id)
self.send_id = None
def recv_callback(self, fd, flags):
if flags & (gobject.IO_ERR | gobject.IO_HUP):
if flags & (GObject.IO_ERR | GObject.IO_HUP):
self.stop('Bad client flags: %s' % flags)
return True
@ -283,7 +283,7 @@ class Connection(object):
return True
def send_callback(self, fd, flags):
if flags & (gobject.IO_ERR | gobject.IO_HUP):
if flags & (GObject.IO_ERR | GObject.IO_HUP):
self.stop('Bad client flags: %s' % flags)
return True

View File

@ -2,10 +2,6 @@ from __future__ import absolute_import, unicode_literals
import io
import pygst
pygst.require('0.10')
import gst # noqa
from mopidy.compat import configparser
from mopidy.internal import validation

View File

@ -3,15 +3,13 @@ from __future__ import absolute_import, unicode_literals
import threading
import unittest
import gobject
gobject.threads_init()
import gi
gi.require_version('Gst', '1.0')
from gi.repository import GObject, Gst
GObject.threads_init()
import mock
import pygst
pygst.require('0.10')
import gst # noqa
import pykka
from mopidy import audio
@ -520,17 +518,17 @@ class AudioStateTest(unittest.TestCase):
def test_state_does_not_change_when_in_gst_ready_state(self):
self.audio._handler.on_playbin_state_changed(
gst.STATE_NULL, gst.STATE_READY, gst.STATE_VOID_PENDING)
Gst.STATE_NULL, Gst.STATE_READY, Gst.STATE_VOID_PENDING)
self.assertEqual(audio.PlaybackState.STOPPED, self.audio.state)
def test_state_changes_from_stopped_to_playing_on_play(self):
self.audio._handler.on_playbin_state_changed(
gst.STATE_NULL, gst.STATE_READY, gst.STATE_PLAYING)
Gst.STATE_NULL, Gst.STATE_READY, Gst.STATE_PLAYING)
self.audio._handler.on_playbin_state_changed(
gst.STATE_READY, gst.STATE_PAUSED, gst.STATE_PLAYING)
Gst.STATE_READY, Gst.STATE_PAUSED, Gst.STATE_PLAYING)
self.audio._handler.on_playbin_state_changed(
gst.STATE_PAUSED, gst.STATE_PLAYING, gst.STATE_VOID_PENDING)
Gst.STATE_PAUSED, Gst.STATE_PLAYING, Gst.STATE_VOID_PENDING)
self.assertEqual(audio.PlaybackState.PLAYING, self.audio.state)
@ -538,7 +536,7 @@ class AudioStateTest(unittest.TestCase):
self.audio.state = audio.PlaybackState.PLAYING
self.audio._handler.on_playbin_state_changed(
gst.STATE_PLAYING, gst.STATE_PAUSED, gst.STATE_VOID_PENDING)
Gst.STATE_PLAYING, Gst.STATE_PAUSED, Gst.STATE_VOID_PENDING)
self.assertEqual(audio.PlaybackState.PAUSED, self.audio.state)
@ -546,12 +544,12 @@ class AudioStateTest(unittest.TestCase):
self.audio.state = audio.PlaybackState.PLAYING
self.audio._handler.on_playbin_state_changed(
gst.STATE_PLAYING, gst.STATE_PAUSED, gst.STATE_NULL)
Gst.STATE_PLAYING, Gst.STATE_PAUSED, Gst.STATE_NULL)
self.audio._handler.on_playbin_state_changed(
gst.STATE_PAUSED, gst.STATE_READY, gst.STATE_NULL)
Gst.STATE_PAUSED, Gst.STATE_READY, Gst.STATE_NULL)
# We never get the following call, so the logic must work without it
# self.audio._handler.on_playbin_state_changed(
# gst.STATE_READY, gst.STATE_NULL, gst.STATE_VOID_PENDING)
# Gst.STATE_READY, Gst.STATE_NULL, Gst.STATE_VOID_PENDING)
self.assertEqual(audio.PlaybackState.STOPPED, self.audio.state)
@ -565,17 +563,17 @@ class AudioBufferingTest(unittest.TestCase):
def test_pause_when_buffer_empty(self):
playbin = self.audio._playbin
self.audio.start_playback()
playbin.set_state.assert_called_with(gst.STATE_PLAYING)
playbin.set_state.assert_called_with(Gst.STATE_PLAYING)
playbin.set_state.reset_mock()
self.audio._handler.on_buffering(0)
playbin.set_state.assert_called_with(gst.STATE_PAUSED)
playbin.set_state.assert_called_with(Gst.STATE_PAUSED)
self.assertTrue(self.audio._buffering)
def test_stay_paused_when_buffering_finished(self):
playbin = self.audio._playbin
self.audio.pause_playback()
playbin.set_state.assert_called_with(gst.STATE_PAUSED)
playbin.set_state.assert_called_with(Gst.STATE_PAUSED)
playbin.set_state.reset_mock()
self.audio._handler.on_buffering(100)
@ -585,11 +583,11 @@ class AudioBufferingTest(unittest.TestCase):
def test_change_to_paused_while_buffering(self):
playbin = self.audio._playbin
self.audio.start_playback()
playbin.set_state.assert_called_with(gst.STATE_PLAYING)
playbin.set_state.assert_called_with(Gst.STATE_PLAYING)
playbin.set_state.reset_mock()
self.audio._handler.on_buffering(0)
playbin.set_state.assert_called_with(gst.STATE_PAUSED)
playbin.set_state.assert_called_with(Gst.STATE_PAUSED)
self.audio.pause_playback()
playbin.set_state.reset_mock()
@ -600,13 +598,13 @@ class AudioBufferingTest(unittest.TestCase):
def test_change_to_stopped_while_buffering(self):
playbin = self.audio._playbin
self.audio.start_playback()
playbin.set_state.assert_called_with(gst.STATE_PLAYING)
playbin.set_state.assert_called_with(Gst.STATE_PLAYING)
playbin.set_state.reset_mock()
self.audio._handler.on_buffering(0)
playbin.set_state.assert_called_with(gst.STATE_PAUSED)
playbin.set_state.assert_called_with(Gst.STATE_PAUSED)
playbin.set_state.reset_mock()
self.audio.stop_playback()
playbin.set_state.assert_called_with(gst.STATE_NULL)
playbin.set_state.assert_called_with(Gst.STATE_NULL)
self.assertFalse(self.audio._buffering)

View File

@ -3,8 +3,12 @@ from __future__ import absolute_import, unicode_literals
import os
import unittest
import gobject
gobject.threads_init()
import gi
gi.require_version('Gst', '1.0')
from gi.repository import GObject, Gst
GObject.threads_init()
Gst.init(None)
from mopidy import exceptions
from mopidy.audio import scan

View File

@ -5,7 +5,7 @@ import logging
import socket
import unittest
import gobject
from gi.repository import GObject
from mock import Mock, call, patch, sentinel
@ -162,27 +162,27 @@ class ConnectionTest(unittest.TestCase):
network.Connection.stop(self.mock, sentinel.reason)
network.logger.log(any_int, any_unicode)
@patch.object(gobject, 'io_add_watch', new=Mock())
@patch.object(GObject, 'io_add_watch', new=Mock())
def test_enable_recv_registers_with_gobject(self):
self.mock.recv_id = None
self.mock.sock = Mock(spec=socket.SocketType)
self.mock.sock.fileno.return_value = sentinel.fileno
gobject.io_add_watch.return_value = sentinel.tag
GObject.io_add_watch.return_value = sentinel.tag
network.Connection.enable_recv(self.mock)
gobject.io_add_watch.assert_called_once_with(
GObject.io_add_watch.assert_called_once_with(
sentinel.fileno,
gobject.IO_IN | gobject.IO_ERR | gobject.IO_HUP,
GObject.IO_IN | GObject.IO_ERR | GObject.IO_HUP,
self.mock.recv_callback)
self.assertEqual(sentinel.tag, self.mock.recv_id)
@patch.object(gobject, 'io_add_watch', new=Mock())
@patch.object(GObject, 'io_add_watch', new=Mock())
def test_enable_recv_already_registered(self):
self.mock.sock = Mock(spec=socket.SocketType)
self.mock.recv_id = sentinel.tag
network.Connection.enable_recv(self.mock)
self.assertEqual(0, gobject.io_add_watch.call_count)
self.assertEqual(0, GObject.io_add_watch.call_count)
def test_enable_recv_does_not_change_tag(self):
self.mock.recv_id = sentinel.tag
@ -191,20 +191,20 @@ class ConnectionTest(unittest.TestCase):
network.Connection.enable_recv(self.mock)
self.assertEqual(sentinel.tag, self.mock.recv_id)
@patch.object(gobject, 'source_remove', new=Mock())
@patch.object(GObject, 'source_remove', new=Mock())
def test_disable_recv_deregisters(self):
self.mock.recv_id = sentinel.tag
network.Connection.disable_recv(self.mock)
gobject.source_remove.assert_called_once_with(sentinel.tag)
GObject.source_remove.assert_called_once_with(sentinel.tag)
self.assertEqual(None, self.mock.recv_id)
@patch.object(gobject, 'source_remove', new=Mock())
@patch.object(GObject, 'source_remove', new=Mock())
def test_disable_recv_already_deregistered(self):
self.mock.recv_id = None
network.Connection.disable_recv(self.mock)
self.assertEqual(0, gobject.source_remove.call_count)
self.assertEqual(0, GObject.source_remove.call_count)
self.assertEqual(None, self.mock.recv_id)
def test_enable_recv_on_closed_socket(self):
@ -216,27 +216,27 @@ class ConnectionTest(unittest.TestCase):
self.mock.stop.assert_called_once_with(any_unicode)
self.assertEqual(None, self.mock.recv_id)
@patch.object(gobject, 'io_add_watch', new=Mock())
@patch.object(GObject, 'io_add_watch', new=Mock())
def test_enable_send_registers_with_gobject(self):
self.mock.send_id = None
self.mock.sock = Mock(spec=socket.SocketType)
self.mock.sock.fileno.return_value = sentinel.fileno
gobject.io_add_watch.return_value = sentinel.tag
GObject.io_add_watch.return_value = sentinel.tag
network.Connection.enable_send(self.mock)
gobject.io_add_watch.assert_called_once_with(
GObject.io_add_watch.assert_called_once_with(
sentinel.fileno,
gobject.IO_OUT | gobject.IO_ERR | gobject.IO_HUP,
GObject.IO_OUT | GObject.IO_ERR | GObject.IO_HUP,
self.mock.send_callback)
self.assertEqual(sentinel.tag, self.mock.send_id)
@patch.object(gobject, 'io_add_watch', new=Mock())
@patch.object(GObject, 'io_add_watch', new=Mock())
def test_enable_send_already_registered(self):
self.mock.sock = Mock(spec=socket.SocketType)
self.mock.send_id = sentinel.tag
network.Connection.enable_send(self.mock)
self.assertEqual(0, gobject.io_add_watch.call_count)
self.assertEqual(0, GObject.io_add_watch.call_count)
def test_enable_send_does_not_change_tag(self):
self.mock.send_id = sentinel.tag
@ -245,20 +245,20 @@ class ConnectionTest(unittest.TestCase):
network.Connection.enable_send(self.mock)
self.assertEqual(sentinel.tag, self.mock.send_id)
@patch.object(gobject, 'source_remove', new=Mock())
@patch.object(GObject, 'source_remove', new=Mock())
def test_disable_send_deregisters(self):
self.mock.send_id = sentinel.tag
network.Connection.disable_send(self.mock)
gobject.source_remove.assert_called_once_with(sentinel.tag)
GObject.source_remove.assert_called_once_with(sentinel.tag)
self.assertEqual(None, self.mock.send_id)
@patch.object(gobject, 'source_remove', new=Mock())
@patch.object(GObject, 'source_remove', new=Mock())
def test_disable_send_already_deregistered(self):
self.mock.send_id = None
network.Connection.disable_send(self.mock)
self.assertEqual(0, gobject.source_remove.call_count)
self.assertEqual(0, GObject.source_remove.call_count)
self.assertEqual(None, self.mock.send_id)
def test_enable_send_on_closed_socket(self):
@ -269,36 +269,36 @@ class ConnectionTest(unittest.TestCase):
network.Connection.enable_send(self.mock)
self.assertEqual(None, self.mock.send_id)
@patch.object(gobject, 'timeout_add_seconds', new=Mock())
@patch.object(GObject, 'timeout_add_seconds', new=Mock())
def test_enable_timeout_clears_existing_timeouts(self):
self.mock.timeout = 10
network.Connection.enable_timeout(self.mock)
self.mock.disable_timeout.assert_called_once_with()
@patch.object(gobject, 'timeout_add_seconds', new=Mock())
@patch.object(GObject, 'timeout_add_seconds', new=Mock())
def test_enable_timeout_add_gobject_timeout(self):
self.mock.timeout = 10
gobject.timeout_add_seconds.return_value = sentinel.tag
GObject.timeout_add_seconds.return_value = sentinel.tag
network.Connection.enable_timeout(self.mock)
gobject.timeout_add_seconds.assert_called_once_with(
GObject.timeout_add_seconds.assert_called_once_with(
10, self.mock.timeout_callback)
self.assertEqual(sentinel.tag, self.mock.timeout_id)
@patch.object(gobject, 'timeout_add_seconds', new=Mock())
@patch.object(GObject, 'timeout_add_seconds', new=Mock())
def test_enable_timeout_does_not_add_timeout(self):
self.mock.timeout = 0
network.Connection.enable_timeout(self.mock)
self.assertEqual(0, gobject.timeout_add_seconds.call_count)
self.assertEqual(0, GObject.timeout_add_seconds.call_count)
self.mock.timeout = -1
network.Connection.enable_timeout(self.mock)
self.assertEqual(0, gobject.timeout_add_seconds.call_count)
self.assertEqual(0, GObject.timeout_add_seconds.call_count)
self.mock.timeout = None
network.Connection.enable_timeout(self.mock)
self.assertEqual(0, gobject.timeout_add_seconds.call_count)
self.assertEqual(0, GObject.timeout_add_seconds.call_count)
def test_enable_timeout_does_not_call_disable_for_invalid_timeout(self):
self.mock.timeout = 0
@ -313,20 +313,20 @@ class ConnectionTest(unittest.TestCase):
network.Connection.enable_timeout(self.mock)
self.assertEqual(0, self.mock.disable_timeout.call_count)
@patch.object(gobject, 'source_remove', new=Mock())
@patch.object(GObject, 'source_remove', new=Mock())
def test_disable_timeout_deregisters(self):
self.mock.timeout_id = sentinel.tag
network.Connection.disable_timeout(self.mock)
gobject.source_remove.assert_called_once_with(sentinel.tag)
GObject.source_remove.assert_called_once_with(sentinel.tag)
self.assertEqual(None, self.mock.timeout_id)
@patch.object(gobject, 'source_remove', new=Mock())
@patch.object(GObject, 'source_remove', new=Mock())
def test_disable_timeout_already_deregistered(self):
self.mock.timeout_id = None
network.Connection.disable_timeout(self.mock)
self.assertEqual(0, gobject.source_remove.call_count)
self.assertEqual(0, GObject.source_remove.call_count)
self.assertEqual(None, self.mock.timeout_id)
def test_queue_send_acquires_and_releases_lock(self):
@ -372,7 +372,7 @@ class ConnectionTest(unittest.TestCase):
self.mock.actor_ref = Mock()
self.assertTrue(network.Connection.recv_callback(
self.mock, sentinel.fd, gobject.IO_IN | gobject.IO_ERR))
self.mock, sentinel.fd, GObject.IO_IN | GObject.IO_ERR))
self.mock.stop.assert_called_once_with(any_unicode)
def test_recv_callback_respects_io_hup(self):
@ -380,7 +380,7 @@ class ConnectionTest(unittest.TestCase):
self.mock.actor_ref = Mock()
self.assertTrue(network.Connection.recv_callback(
self.mock, sentinel.fd, gobject.IO_IN | gobject.IO_HUP))
self.mock, sentinel.fd, GObject.IO_IN | GObject.IO_HUP))
self.mock.stop.assert_called_once_with(any_unicode)
def test_recv_callback_respects_io_hup_and_io_err(self):
@ -389,7 +389,7 @@ class ConnectionTest(unittest.TestCase):
self.assertTrue(network.Connection.recv_callback(
self.mock, sentinel.fd,
gobject.IO_IN | gobject.IO_HUP | gobject.IO_ERR))
GObject.IO_IN | GObject.IO_HUP | GObject.IO_ERR))
self.mock.stop.assert_called_once_with(any_unicode)
def test_recv_callback_sends_data_to_actor(self):
@ -398,7 +398,7 @@ class ConnectionTest(unittest.TestCase):
self.mock.actor_ref = Mock()
self.assertTrue(network.Connection.recv_callback(
self.mock, sentinel.fd, gobject.IO_IN))
self.mock, sentinel.fd, GObject.IO_IN))
self.mock.actor_ref.tell.assert_called_once_with(
{'received': 'data'})
@ -409,7 +409,7 @@ class ConnectionTest(unittest.TestCase):
self.mock.actor_ref.tell.side_effect = pykka.ActorDeadError()
self.assertTrue(network.Connection.recv_callback(
self.mock, sentinel.fd, gobject.IO_IN))
self.mock, sentinel.fd, GObject.IO_IN))
self.mock.stop.assert_called_once_with(any_unicode)
def test_recv_callback_gets_no_data(self):
@ -418,7 +418,7 @@ class ConnectionTest(unittest.TestCase):
self.mock.actor_ref = Mock()
self.assertTrue(network.Connection.recv_callback(
self.mock, sentinel.fd, gobject.IO_IN))
self.mock, sentinel.fd, GObject.IO_IN))
self.assertEqual(self.mock.mock_calls, [
call.sock.recv(any_int),
call.disable_recv(),
@ -431,7 +431,7 @@ class ConnectionTest(unittest.TestCase):
for error in (errno.EWOULDBLOCK, errno.EINTR):
self.mock.sock.recv.side_effect = socket.error(error, '')
self.assertTrue(network.Connection.recv_callback(
self.mock, sentinel.fd, gobject.IO_IN))
self.mock, sentinel.fd, GObject.IO_IN))
self.assertEqual(0, self.mock.stop.call_count)
def test_recv_callback_unrecoverable_error(self):
@ -439,7 +439,7 @@ class ConnectionTest(unittest.TestCase):
self.mock.sock.recv.side_effect = socket.error
self.assertTrue(network.Connection.recv_callback(
self.mock, sentinel.fd, gobject.IO_IN))
self.mock, sentinel.fd, GObject.IO_IN))
self.mock.stop.assert_called_once_with(any_unicode)
def test_send_callback_respects_io_err(self):
@ -450,7 +450,7 @@ class ConnectionTest(unittest.TestCase):
self.mock.send_buffer = ''
self.assertTrue(network.Connection.send_callback(
self.mock, sentinel.fd, gobject.IO_IN | gobject.IO_ERR))
self.mock, sentinel.fd, GObject.IO_IN | GObject.IO_ERR))
self.mock.stop.assert_called_once_with(any_unicode)
def test_send_callback_respects_io_hup(self):
@ -461,7 +461,7 @@ class ConnectionTest(unittest.TestCase):
self.mock.send_buffer = ''
self.assertTrue(network.Connection.send_callback(
self.mock, sentinel.fd, gobject.IO_IN | gobject.IO_HUP))
self.mock, sentinel.fd, GObject.IO_IN | GObject.IO_HUP))
self.mock.stop.assert_called_once_with(any_unicode)
def test_send_callback_respects_io_hup_and_io_err(self):
@ -473,7 +473,7 @@ class ConnectionTest(unittest.TestCase):
self.assertTrue(network.Connection.send_callback(
self.mock, sentinel.fd,
gobject.IO_IN | gobject.IO_HUP | gobject.IO_ERR))
GObject.IO_IN | GObject.IO_HUP | GObject.IO_ERR))
self.mock.stop.assert_called_once_with(any_unicode)
def test_send_callback_acquires_and_releases_lock(self):
@ -484,7 +484,7 @@ class ConnectionTest(unittest.TestCase):
self.mock.sock.send.return_value = 0
self.assertTrue(network.Connection.send_callback(
self.mock, sentinel.fd, gobject.IO_IN))
self.mock, sentinel.fd, GObject.IO_IN))
self.mock.send_lock.acquire.assert_called_once_with(False)
self.mock.send_lock.release.assert_called_once_with()
@ -496,7 +496,7 @@ class ConnectionTest(unittest.TestCase):
self.mock.sock.send.return_value = 0
self.assertTrue(network.Connection.send_callback(
self.mock, sentinel.fd, gobject.IO_IN))
self.mock, sentinel.fd, GObject.IO_IN))
self.mock.send_lock.acquire.assert_called_once_with(False)
self.assertEqual(0, self.mock.sock.send.call_count)
@ -507,7 +507,7 @@ class ConnectionTest(unittest.TestCase):
self.mock.send.return_value = ''
self.assertTrue(network.Connection.send_callback(
self.mock, sentinel.fd, gobject.IO_IN))
self.mock, sentinel.fd, GObject.IO_IN))
self.mock.disable_send.assert_called_once_with()
self.mock.send.assert_called_once_with('data')
self.assertEqual('', self.mock.send_buffer)
@ -519,7 +519,7 @@ class ConnectionTest(unittest.TestCase):
self.mock.send.return_value = 'ta'
self.assertTrue(network.Connection.send_callback(
self.mock, sentinel.fd, gobject.IO_IN))
self.mock, sentinel.fd, GObject.IO_IN))
self.mock.send.assert_called_once_with('data')
self.assertEqual('ta', self.mock.send_buffer)

View File

@ -4,7 +4,7 @@ import errno
import socket
import unittest
import gobject
from gi.repository import GObject
from mock import Mock, patch, sentinel
@ -91,11 +91,11 @@ class ServerTest(unittest.TestCase):
network.Server.create_server_socket(
self.mock, sentinel.host, sentinel.port)
@patch.object(gobject, 'io_add_watch', new=Mock())
@patch.object(GObject, 'io_add_watch', new=Mock())
def test_register_server_socket_sets_up_io_watch(self):
network.Server.register_server_socket(self.mock, sentinel.fileno)
gobject.io_add_watch.assert_called_once_with(
sentinel.fileno, gobject.IO_IN, self.mock.handle_connection)
GObject.io_add_watch.assert_called_once_with(
sentinel.fileno, GObject.IO_IN, self.mock.handle_connection)
def test_handle_connection(self):
self.mock.accept_connection.return_value = (
@ -103,7 +103,7 @@ class ServerTest(unittest.TestCase):
self.mock.maximum_connections_exceeded.return_value = False
self.assertTrue(network.Server.handle_connection(
self.mock, sentinel.fileno, gobject.IO_IN))
self.mock, sentinel.fileno, GObject.IO_IN))
self.mock.accept_connection.assert_called_once_with()
self.mock.maximum_connections_exceeded.assert_called_once_with()
self.mock.init_connection.assert_called_once_with(
@ -116,7 +116,7 @@ class ServerTest(unittest.TestCase):
self.mock.maximum_connections_exceeded.return_value = True
self.assertTrue(network.Server.handle_connection(
self.mock, sentinel.fileno, gobject.IO_IN))
self.mock, sentinel.fileno, GObject.IO_IN))
self.mock.accept_connection.assert_called_once_with()
self.mock.maximum_connections_exceeded.assert_called_once_with()
self.mock.reject_connection.assert_called_once_with(

View File

@ -4,14 +4,14 @@ import platform
import sys
import unittest
import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst
import mock
import pkg_resources
import pygst
pygst.require('0.10')
import gst # noqa
from mopidy.internal import deps
@ -74,12 +74,11 @@ class DepsTest(unittest.TestCase):
self.assertEqual('GStreamer', result['name'])
self.assertEqual(
'.'.join(map(str, gst.get_gst_version())), result['version'])
self.assertIn('gst', result['path'])
'.'.join(map(str, Gst.version())), result['version'])
self.assertIn('gi', result['path'])
self.assertNotIn('__init__.py', result['path'])
self.assertIn('Python wrapper: gst-python', result['other'])
self.assertIn(
'.'.join(map(str, gst.get_pygst_version())), result['other'])
self.assertIn('Python wrapper: python-gi', result['other'])
self.assertIn(gi.__version__, result['other'])
self.assertIn('Relevant elements:', result['other'])
@mock.patch('pkg_resources.get_distribution')

View File

@ -7,7 +7,7 @@ import shutil
import tempfile
import unittest
import glib
from gi.repository import GLib
from mopidy import compat, exceptions
from mopidy.internal import path
@ -215,7 +215,7 @@ class ExpandPathTest(unittest.TestCase):
def test_xdg_subsititution(self):
self.assertEqual(
glib.get_user_data_dir() + b'/foo',
GLib.get_user_data_dir() + b'/foo',
path.expand_path(b'$XDG_DATA_DIR/foo'))
def test_xdg_subsititution_unknown(self):