]> kaliko git repositories - mpd-sima.git/blobdiff - sima/client.py
Attempt to fix AttributeError issue
[mpd-sima.git] / sima / client.py
index 2893d9b52cf52bb5a53266ec2bdedc7f0e05ebcd..06ba8961e8a6bcb305fbafd3912986bcd366efaa 100644 (file)
@@ -36,6 +36,7 @@ except ImportError as err:
     sexit(1)
 
 # local import
     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
 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
 
 
 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
 
 class PlayerClient(Player):
     """MPD Client
@@ -121,11 +144,12 @@ class PlayerClient(Player):
         return ans
 
     def __skipped_track(self, old_curr):
         return ans
 
     def __skipped_track(self, old_curr):
+        curr = self.current
         if (self.state == 'stop'
             or not hasattr(old_curr, 'id')
         if (self.state == 'stop'
             or not hasattr(old_curr, 'id')
-            or not hasattr(self.current, 'id')):
+            or not hasattr(curr, 'id')):
             return False
             return False
-        return self.current.id != old_curr.id  # pylint: disable=no-member
+        return curr.id != old_curr.id  # pylint: disable=no-member
 
     def _flush_cache(self):
         """
 
     def _flush_cache(self):
         """
@@ -137,8 +161,10 @@ class PlayerClient(Player):
             self.log.info('Player: Initialising cache!')
         self._cache = {
                 'artists': None,
             self.log.info('Player: Initialising cache!')
         self._cache = {
                 'artists': None,
+                'nombid_artists': None,
                 }
         self._cache['artists'] = frozenset(self._client.list('artist'))
                 }
         self._cache['artists'] = frozenset(self._client.list('artist'))
+        self._cache['nombid_artists'] = frozenset(self._client.list('artist', 'musicbrainz_artistid', ''))
 
     @blacklist(track=True)
     def find_track(self, artist, title=None):
 
     @blacklist(track=True)
     def find_track(self, artist, title=None):
@@ -156,6 +182,67 @@ class PlayerClient(Player):
                                         'title', title))
         return list(tracks)
 
                                         '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=<UUID4>) # 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._client.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)
     def fuzzy_find_track(self, artist, title):
         # Retrieve all tracks from artist
         all_tracks = self.find_track(artist, title)
@@ -196,8 +283,9 @@ class PlayerClient(Player):
                album containing at least a single track for artist
         """
         albums = []
                album containing at least a single track for artist
         """
         albums = []
-        for name in artist.aliases:
-            self.log.debug('Searching album for {}'.format(name))
+        for name in artist.names:
+            if len(artist.names) > 1:
+                self.log.debug('Searching album for aliase: "{}"'.format(name))
             kwalbart = {'albumartist':name, 'artist':name}
             for album in self.list('album', 'albumartist', artist):
                 if album and album not in albums:
             kwalbart = {'albumartist':name, 'artist':name}
             for album in self.list('album', 'albumartist', artist):
                 if album and album not in albums:
@@ -210,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:
                 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)))
                 elif album and album not in albums:
                     self.log.debug('"{0}" probably not an album of "{1}"'.format(
                                    album, artist) + '({0})'.format('/'.join(arts)))