diff --git a/mopidy/frontends/mpd/dispatcher.py b/mopidy/frontends/mpd/dispatcher.py index dc665abc..e39c140b 100644 --- a/mopidy/frontends/mpd/dispatcher.py +++ b/mopidy/frontends/mpd/dispatcher.py @@ -236,6 +236,9 @@ class MpdContext(object): #: The subsytems that we want to be notified about in idle mode. subscriptions = None + playlist_uri_from_name = None + playlist_name_from_uri = None + def __init__(self, dispatcher, session=None, config=None, core=None): self.dispatcher = dispatcher self.session = session @@ -243,3 +246,29 @@ class MpdContext(object): self.core = core self.events = set() self.subscriptions = set() + self.playlist_uri_from_name = {} + self.playlist_name_from_uri = {} + self.refresh_playlists_mapping() + + def create_unique_name(self, playlist_name): + name = playlist_name + i = 2 + while name in self.playlist_uri_from_name: + name = '%s [%d]' % (playlist_name, i) + i += 1 + return name + + def refresh_playlists_mapping(self): + """ + Maintain map between playlists and unique playlist names to be used by + MPD + """ + if self.core is not None: + self.playlist_uri_from_name.clear() + self.playlist_name_from_uri.clear() + for playlist in self.core.playlists.playlists.get(): + if not playlist.name: + continue + name = self.create_unique_name(playlist.name) + self.playlist_uri_from_name[name] = playlist.uri + self.playlist_name_from_uri[playlist.uri] = name diff --git a/mopidy/frontends/mpd/protocol/music_db.py b/mopidy/frontends/mpd/protocol/music_db.py index c457ee02..11def309 100644 --- a/mopidy/frontends/mpd/protocol/music_db.py +++ b/mopidy/frontends/mpd/protocol/music_db.py @@ -381,9 +381,12 @@ def searchaddpl(context, playlist_name, mpd_query): return results = context.core.library.search(**query).get() - playlists = context.core.playlists.filter(name=playlist_name).get() - if playlists: - playlist = playlists[0] + if len(context.playlist_uri_from_name) == 0: + context.refresh_playlists_mapping() + + if playlist_name in context.playlist_uri_from_name: + uri = context.playlist_uri_from_name[playlist_name] + playlist = context.core.playlists.lookup(uri).get() else: playlist = context.core.playlists.create(playlist_name).get() tracks = list(playlist.tracks) + _get_tracks(results) diff --git a/mopidy/frontends/mpd/protocol/stored_playlists.py b/mopidy/frontends/mpd/protocol/stored_playlists.py index b1fe87de..0c9bf050 100644 --- a/mopidy/frontends/mpd/protocol/stored_playlists.py +++ b/mopidy/frontends/mpd/protocol/stored_playlists.py @@ -80,7 +80,11 @@ def listplaylists(context): for playlist in context.core.playlists.playlists.get(): if not playlist.name: continue - result.append(('playlist', playlist.name)) + if playlist.uri not in context.playlist_name_from_uri: + # the maps are not synced, we refresh them + context.refresh_playlists_mapping() + name = context.playlist_name_from_uri[playlist.uri] + result.append(('playlist', name)) last_modified = ( playlist.last_modified or dt.datetime.utcnow()).isoformat() # Remove microseconds diff --git a/tests/frontends/mpd/protocol/stored_playlists_test.py b/tests/frontends/mpd/protocol/stored_playlists_test.py index 49da5d0b..d837b0fa 100644 --- a/tests/frontends/mpd/protocol/stored_playlists_test.py +++ b/tests/frontends/mpd/protocol/stored_playlists_test.py @@ -64,6 +64,16 @@ class PlaylistsHandlerTest(protocol.BaseTestCase): self.assertInResponse('Last-Modified: 2001-03-17T13:41:17Z') self.assertInResponse('OK') + def test_listplaylists_duplicate(self): + playlist1 = Playlist(name='a', uri='dummy:a1') + playlist2 = Playlist(name='a', uri='dummy:a2') + self.backend.playlists.playlists = [playlist1, playlist2] + + self.sendRequest('listplaylists') + self.assertInResponse('playlist: a') + self.assertInResponse('playlist: a [2]') + self.assertInResponse('OK') + def test_listplaylists_ignores_playlists_without_name(self): last_modified = datetime.datetime(2001, 3, 17, 13, 41, 17, 12345) self.backend.playlists.playlists = [