diff --git a/docs/changelog.rst b/docs/changelog.rst index 4206d455..4f4e4a5d 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -132,6 +132,9 @@ v0.20.0 (UNRELEASED) - Add basic tests for the stream library provider. +- Add support for proxies when doing initial metadata lookup for stream. + (Fixes :issue:`390`) + **Mopidy.js client library** This version has been released to npm as Mopidy.js v0.5.0. diff --git a/mopidy/audio/actor.py b/mopidy/audio/actor.py index 133c8424..6ef48a6b 100644 --- a/mopidy/audio/actor.py +++ b/mopidy/audio/actor.py @@ -244,20 +244,6 @@ class SoftwareMixer(object): self._mixer.trigger_mute_changed(self._last_mute) -def setup_proxy(element, config): - # TODO: reuse in scanner code - if not config.get('hostname'): - return - - proxy = "%s://%s:%d" % (config.get('scheme', 'http'), - config.get('hostname'), - config.get('port', 80)) - - element.set_property('proxy', proxy) - element.set_property('proxy-id', config.get('username')) - element.set_property('proxy-pw', config.get('password')) - - class _Handler(object): def __init__(self, audio): self._audio = audio @@ -531,8 +517,7 @@ class Audio(pykka.ThreadingActor): else: self._appsrc.reset() - if hasattr(source.props, 'proxy'): - setup_proxy(source, self._config['proxy']) + utils.setup_proxy(source, self._config['proxy']) def set_uri(self, uri): """ diff --git a/mopidy/audio/scan.py b/mopidy/audio/scan.py index 931a2e3a..38b86437 100644 --- a/mopidy/audio/scan.py +++ b/mopidy/audio/scan.py @@ -16,10 +16,11 @@ class Scanner(object): Helper to get tags and other relevant info from URIs. :param timeout: timeout for scanning a URI in ms + :param proxy_config: dictionary containing proxy config strings. :type event: int """ - def __init__(self, timeout=1000): + def __init__(self, timeout=1000, proxy_config=None): self._timeout_ms = timeout sink = gst.element_factory_make('fakesink') @@ -29,9 +30,13 @@ class Scanner(object): def pad_added(src, pad): return pad.link(sink.get_pad('sink')) + def source_setup(element, source): + utils.setup_proxy(source, proxy_config or {}) + self._uribin = gst.element_factory_make('uridecodebin') self._uribin.set_property('caps', audio_caps) self._uribin.connect('pad-added', pad_added) + self._uribin.connect('source-setup', source_setup) self._pipe = gst.element_factory_make('pipeline') self._pipe.add(self._uribin) diff --git a/mopidy/audio/utils.py b/mopidy/audio/utils.py index 8581fd61..1a8bf6a7 100644 --- a/mopidy/audio/utils.py +++ b/mopidy/audio/utils.py @@ -82,7 +82,8 @@ def _artists(tags, artist_name, artist_id=None): def convert_tags_to_track(tags): """Convert our normalized tags to a track. - :param :class:`dict` tags: dictionary of tag keys with a list of values + :param tags: dictionary of tag keys with a list of values + :type tags: :class:`dict` :rtype: :class:`mopidy.models.Track` """ album_kwargs = {} @@ -130,6 +131,26 @@ def convert_tags_to_track(tags): return Track(**track_kwargs) +def setup_proxy(element, config): + """Configure a GStreamer element with proxy settings. + + :param element: element to setup proxy in. + :type element: :class:`gst.GstElement` + :param config: proxy settings to use. + :type config: :class:`dict` + """ + if not hasattr(element.props, 'proxy') or not config.get('hostname'): + return + + proxy = "%s://%s:%d" % (config.get('scheme', 'http'), + config.get('hostname'), + config.get('port', 80)) + + element.set_property('proxy', proxy) + element.set_property('proxy-id', config.get('username')) + element.set_property('proxy-pw', config.get('password')) + + def convert_taglist(taglist): """Convert a :class:`gst.Taglist` to plain Python types. @@ -147,7 +168,8 @@ def convert_taglist(taglist): .. _GstTagList: http://gstreamer.freedesktop.org/data/doc/gstreamer/\ 0.10.36/gstreamer/html/gstreamer-GstTagList.html - :param gst.Taglist taglist: A GStreamer taglist to be converted. + :param taglist: A GStreamer taglist to be converted. + :type taglist: :class:`gst.Taglist` :rtype: dictionary of tag keys with a list of values. """ result = {} diff --git a/mopidy/stream/actor.py b/mopidy/stream/actor.py index 9599d9d3..58fd966a 100644 --- a/mopidy/stream/actor.py +++ b/mopidy/stream/actor.py @@ -20,7 +20,8 @@ class StreamBackend(pykka.ThreadingActor, backend.Backend): self.library = StreamLibraryProvider( backend=self, timeout=config['stream']['timeout'], - blacklist=config['stream']['metadata_blacklist']) + blacklist=config['stream']['metadata_blacklist'], + proxy=config['proxy']) self.playback = backend.PlaybackProvider(audio=audio, backend=self) self.playlists = None @@ -29,9 +30,9 @@ class StreamBackend(pykka.ThreadingActor, backend.Backend): class StreamLibraryProvider(backend.LibraryProvider): - def __init__(self, backend, timeout, blacklist): + def __init__(self, backend, timeout, blacklist, proxy): super(StreamLibraryProvider, self).__init__(backend) - self._scanner = scan.Scanner(timeout=timeout) + self._scanner = scan.Scanner(timeout=timeout, proxy_config=proxy) self._blacklist_re = re.compile( r'^(%s)$' % '|'.join(fnmatch.translate(u) for u in blacklist)) diff --git a/tests/stream/test_library.py b/tests/stream/test_library.py index 7ed871cb..93292376 100644 --- a/tests/stream/test_library.py +++ b/tests/stream/test_library.py @@ -25,19 +25,19 @@ class LibraryProviderTest(unittest.TestCase): self.uri = path_to_uri(path_to_data_dir('song1.wav')) def test_lookup_ignores_unknown_scheme(self): - library = actor.StreamLibraryProvider(self.backend, 1000, []) + library = actor.StreamLibraryProvider(self.backend, 1000, [], {}) self.assertFalse(library.lookup('http://example.com')) def test_lookup_respects_blacklist(self): - library = actor.StreamLibraryProvider(self.backend, 100, [self.uri]) + library = actor.StreamLibraryProvider(self.backend, 10, [self.uri], {}) self.assertEqual([Track(uri=self.uri)], library.lookup(self.uri)) def test_lookup_respects_blacklist_globbing(self): blacklist = [path_to_uri(path_to_data_dir('')) + '*'] - library = actor.StreamLibraryProvider(self.backend, 100, blacklist) + library = actor.StreamLibraryProvider(self.backend, 100, blacklist, {}) self.assertEqual([Track(uri=self.uri)], library.lookup(self.uri)) def test_lookup_converts_uri_metadata_to_track(self): - library = actor.StreamLibraryProvider(self.backend, 100, []) + library = actor.StreamLibraryProvider(self.backend, 100, [], {}) self.assertEqual([Track(length=4406, uri=self.uri)], library.lookup(self.uri))