X-Git-Url: http://git.kaliko.me/?a=blobdiff_plain;f=sima%2Fclient.py;h=e171c0b1d6c1934d728470e649b06c104e486992;hb=73405cb1d2bbeac4bdd956b9746a1e8a3b7355d7;hp=f3d1614ad6b6672093024feca685604c262d9fba;hpb=d6dadb1d86ae2e9082d45f1f5fda2f8152ae2f8a;p=mpd-sima.git diff --git a/sima/client.py b/sima/client.py index f3d1614..e171c0b 100644 --- a/sima/client.py +++ b/sima/client.py @@ -36,6 +36,7 @@ except ImportError as err: sexit(1) # local import +from .lib.simastr import SimaStr from .lib.player import Player, blacklist from .lib.track import Track from .lib.meta import Album, Artist @@ -50,6 +51,28 @@ class PlayerCommandError(PlayerError): PlayerUnHandledError = MPDError # pylint: disable=C0103 +def bl_artist(func): + def wrapper(*args, **kwargs): + cls = args[0] + if not args[0].database: + return func(*args, **kwargs) + result = func(*args, **kwargs) + if not result: + return + names = list() + for art in result.names: + if cls.database.get_bl_artist(art, add_not=True): + cls.log.debug('Blacklisted "{0}"'.format(art)) + continue + names.append(art) + if not names: + return + resp = Artist(name=names.pop(), mbid=result.mbid) + for name in names: + resp.add_alias(name) + return resp + return wrapper + class PlayerClient(Player): """MPD Client @@ -136,9 +159,12 @@ class PlayerClient(Player): else: self.log.info('Player: Initialising cache!') self._cache = { - 'artists': None, + 'artists': frozenset(), + 'nombid_artists': frozenset(), } - self._cache['artists'] = frozenset(self._client.list('artist')) + self._cache['artists'] = frozenset(self._execute('list', ['artist'])) + if Artist.use_mbid: + self._cache['nombid_artists'] = frozenset(self._execute('list', ['artist', 'musicbrainz_artistid', ''])) @blacklist(track=True) def find_track(self, artist, title=None): @@ -156,6 +182,67 @@ class PlayerClient(Player): 'title', title)) return list(tracks) + @bl_artist + def search_artist(self, artist): + """ + Search artists based on a fuzzy search in the media library + >>> art = Artist(name='the beatles', mbid=) # mbid optional + >>> bea = player.search_artist(art) + >>> print(bea.names) + >>> ['The Beatles', 'Beatles', 'the beatles'] + + Returns an Artist object + """ + found = False + if artist.mbid: + # look for exact search w/ musicbrainz_artistid + exact_m = self._execute('list', ['artist', 'musicbrainz_artistid', artist.mbid]) + if exact_m: + [artist.add_alias(name) for name in exact_m] + found = True + else: + artist = Artist(name=artist.name) + # then complete with fuzzy search on artist with no musicbrainz_artistid + if artist.mbid: + # we already performed a lookup on artists with mbid set + # search through remaining artists + artists = self._cache.get('nombid_artists', []) + else: + artists = self._cache.get('artists', []) + match = get_close_matches(artist.name, artists, 50, 0.73) + if not match and not found: + return + if len(match) > 1: + self.log.debug('found close match for "%s": %s' % + (artist, '/'.join(match))) + # Does not perform fuzzy matching on short and single word strings + # Only lowercased comparison + if ' ' not in artist.name and len(artist.name) < 8: + for fuzz_art in match: + # Regular lowered string comparison + if artist.name.lower() == fuzz_art.lower(): + artist.add_alias(fuzz_art) + return artist + fzartist = SimaStr(artist.name) + for fuzz_art in match: + # Regular lowered string comparison + if artist.name.lower() == fuzz_art.lower(): + found = True + artist.add_alias(fuzz_art) + if artist.name != fuzz_art: + self.log.debug('"%s" matches "%s".' % (fuzz_art, artist)) + continue + # SimaStr string __eq__ (not regular string comparison here) + if fzartist == fuzz_art: + found = True + artist.add_alias(fuzz_art) + self.log.info('"%s" quite probably matches "%s" (SimaStr)' % + (fuzz_art, artist)) + if found: + if artist.aliases: + self.log.debug('Found: {}'.format('/'.join(list(artist.names)[:4]))) + return artist + def fuzzy_find_track(self, artist, title): # Retrieve all tracks from artist all_tracks = self.find_track(artist, title) @@ -211,7 +298,7 @@ class PlayerClient(Player): arts = set([trk.artist for trk in album_trks]) if len(set(arts)) < 2: # TODO: better heuristic, use a ratio instead if album not in albums: - albums.append(Album(name=album, albumartist=artist)) + albums.append(Album(name=album, **kwalbart)) elif album and album not in albums: self.log.debug('"{0}" probably not an album of "{1}"'.format( album, artist) + '({0})'.format('/'.join(arts))) @@ -245,7 +332,7 @@ class PlayerClient(Player): def add(self, track): """Overriding MPD's add method to accept add signature with a Track object""" - self._client.add(track.file) + self._execute('add', [track.file]) @property def artists(self):