diff --git a/docs/changelog.rst b/docs/changelog.rst index 9e3fb9d2..64cc2ed0 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -88,6 +88,9 @@ v0.20.0 (UNRELEASED) - Sort local playlists by name. (Fixes: :issue:`1026`, PR: :issue:`1028`) +- Add :meth:`mopidy.local.Library.get_images` for looking up images + for local URIs. (Fixes: :issue:`1031`, PR: :issue:`1032`) + **File scanner** - Improve error logging for scan code (Fixes: :issue:`856`, PR: :issue:`874`) diff --git a/mopidy/local/__init__.py b/mopidy/local/__init__.py index 97ed4a09..eecaa4a2 100644 --- a/mopidy/local/__init__.py +++ b/mopidy/local/__init__.py @@ -4,7 +4,7 @@ import logging import os import mopidy -from mopidy import config, ext +from mopidy import config, ext, models logger = logging.getLogger(__name__) @@ -101,6 +101,27 @@ class Library(object): """ return set() + def get_images(self, uris): + """ + Lookup the images for the given URIs. + + The default implementation will simply call :meth:`lookup` and + try and use the album art for any tracks returned. Most local + libraries should replace this with something smarter or simply + return an empty dictionary. + + :param list uris: list of URIs to find images for + :rtype: {uri: tuple of :class:`mopidy.models.Image`} + """ + result = {} + for uri in uris: + image_uris = set() + for track in self.lookup(uri): + if track.album and track.album.images: + image_uris.update(track.album.images) + result[uri] = [models.Image(uri=u) for u in image_uris] + return result + def load(self): """ (Re)load any tracks stored in memory, if any, otherwise just return diff --git a/mopidy/local/library.py b/mopidy/local/library.py index 90a54770..77c122bd 100644 --- a/mopidy/local/library.py +++ b/mopidy/local/library.py @@ -28,6 +28,11 @@ class LocalLibraryProvider(backend.LibraryProvider): return set() return self._library.get_distinct(field, query) + def get_images(self, uris): + if not self._library: + return {} + return self._library.get_images(uris) + def refresh(self, uri=None): if not self._library: return 0 diff --git a/tests/local/test_library.py b/tests/local/test_library.py index 6cc1992e..13ad9405 100644 --- a/tests/local/test_library.py +++ b/tests/local/test_library.py @@ -11,7 +11,7 @@ import pykka from mopidy import core from mopidy.local import actor, json -from mopidy.models import Album, Artist, Track +from mopidy.models import Album, Artist, Image, Track from tests import path_to_data_dir @@ -580,3 +580,30 @@ class LocalLibraryProviderTest(unittest.TestCase): with self.assertRaises(LookupError): self.library.search(any=['']) + + def test_default_get_images_impl_no_images(self): + result = self.library.get_images([track.uri for track in self.tracks]) + self.assertEqual(result, {track.uri: tuple() for track in self.tracks}) + + @mock.patch.object(json.JsonLibrary, 'lookup') + def test_default_get_images_impl_album_images(self, mock_lookup): + library = actor.LocalBackend(config=self.config, audio=None).library + + image = Image(uri='imageuri') + album = Album(images=[image.uri]) + track = Track(uri='trackuri', album=album) + mock_lookup.return_value = [track] + + result = library.get_images([track.uri]) + self.assertEqual(result, {track.uri: [image]}) + + @mock.patch.object(json.JsonLibrary, 'get_images') + def test_local_library_get_images(self, mock_get_images): + library = actor.LocalBackend(config=self.config, audio=None).library + + image = Image(uri='imageuri') + track = Track(uri='trackuri') + mock_get_images.return_value = {track.uri: [image]} + + result = library.get_images([track.uri]) + self.assertEqual(result, {track.uri: [image]})