From 8c82f4773ffd48eec76a19bd78d76cb0e9f27a2d Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Wed, 2 Sep 2015 00:24:02 +0200 Subject: [PATCH] gst1: Update imports to use PyGI --- mopidy/__main__.py | 8 +- mopidy/audio/actor.py | 161 +++++++++++----------- mopidy/audio/scan.py | 69 +++++----- mopidy/audio/utils.py | 64 ++++----- mopidy/commands.py | 8 +- mopidy/internal/deps.py | 17 ++- mopidy/internal/network.py | 28 ++-- mopidy/internal/playlists.py | 4 - tests/audio/test_actor.py | 42 +++--- tests/audio/test_scan.py | 8 +- tests/internal/network/test_connection.py | 96 ++++++------- tests/internal/network/test_server.py | 12 +- tests/internal/test_deps.py | 17 ++- tests/internal/test_path.py | 4 +- 14 files changed, 263 insertions(+), 275 deletions(-) diff --git a/mopidy/__main__.py b/mopidy/__main__.py index fbc750af..c1cf42f9 100644 --- a/mopidy/__main__.py +++ b/mopidy/__main__.py @@ -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 diff --git a/mopidy/audio/actor.py b/mopidy/audio/actor.py index 9645c4af..3595092e 100644 --- a/mopidy/audio/actor.py +++ b/mopidy/audio/actor.py @@ -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) diff --git a/mopidy/audio/scan.py b/mopidy/audio/scan.py index fd5d2d49..ba6adaf0 100644 --- a/mopidy/audio/scan.py +++ b/mopidy/audio/scan.py @@ -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) diff --git a/mopidy/audio/utils.py b/mopidy/audio/utils.py index bc527df7..aa0b1d63 100644 --- a/mopidy/audio/utils.py +++ b/mopidy/audio/utils.py @@ -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)): diff --git a/mopidy/commands.py b/mopidy/commands.py index 4890c722..872d5773 100644 --- a/mopidy/commands.py +++ b/mopidy/commands.py @@ -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'] diff --git a/mopidy/internal/deps.py b/mopidy/internal/deps.py index 1f363657..3744db87 100644 --- a/mopidy/internal/deps.py +++ b/mopidy/internal/deps.py @@ -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] diff --git a/mopidy/internal/network.py b/mopidy/internal/network.py index 4b8b35fe..c956d795 100644 --- a/mopidy/internal/network.py +++ b/mopidy/internal/network.py @@ -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 diff --git a/mopidy/internal/playlists.py b/mopidy/internal/playlists.py index f8e654af..e80588c9 100644 --- a/mopidy/internal/playlists.py +++ b/mopidy/internal/playlists.py @@ -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 diff --git a/tests/audio/test_actor.py b/tests/audio/test_actor.py index 0cfbdaf3..e1841561 100644 --- a/tests/audio/test_actor.py +++ b/tests/audio/test_actor.py @@ -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) diff --git a/tests/audio/test_scan.py b/tests/audio/test_scan.py index 8c2b9af3..08def2af 100644 --- a/tests/audio/test_scan.py +++ b/tests/audio/test_scan.py @@ -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 diff --git a/tests/internal/network/test_connection.py b/tests/internal/network/test_connection.py index 8ae7d15c..291bbc46 100644 --- a/tests/internal/network/test_connection.py +++ b/tests/internal/network/test_connection.py @@ -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) diff --git a/tests/internal/network/test_server.py b/tests/internal/network/test_server.py index af8effd2..1df25dbc 100644 --- a/tests/internal/network/test_server.py +++ b/tests/internal/network/test_server.py @@ -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( diff --git a/tests/internal/test_deps.py b/tests/internal/test_deps.py index 27e6f629..ea102b47 100644 --- a/tests/internal/test_deps.py +++ b/tests/internal/test_deps.py @@ -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') diff --git a/tests/internal/test_path.py b/tests/internal/test_path.py index 8aa8f7c1..751e7c6e 100644 --- a/tests/internal/test_path.py +++ b/tests/internal/test_path.py @@ -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):