# standard library import
from difflib import get_close_matches
+from itertools import dropwhile
from select import select
# third parties components
# local import
from .lib.player import Player
from .lib.track import Track
+from .lib.meta import Album
from .lib.simastr import SimaStr
PlayerUnHandledError = MPDError # pylint: disable=C0103
+def blacklist(artist=False, album=False, track=False):
+ #pylint: disable=C0111,W0212
+ field = (artist, album, track)
+ def decorated(func):
+ def wrapper(*args, **kwargs):
+ cls = args[0]
+ boolgen = (bl for bl in field)
+ bl_fun = (cls.database.get_bl_artist,
+ cls.database.get_bl_album,
+ cls.database.get_bl_track,)
+ #bl_getter = next(fn for fn, bl in zip(bl_fun, boolgen) if bl is True)
+ bl_getter = next(dropwhile(lambda _: not next(boolgen), bl_fun))
+ #cls.log.debug('using {0} as bl filter'.format(bl_getter.__name__))
+ results = func(*args, **kwargs)
+ for elem in results:
+ if bl_getter(elem, add_not=True):
+ cls.log.info('Blacklisted: {0}'.format(elem))
+ results.remove(elem)
+ return results
+ return wrapper
+ return decorated
+
class PlayerClient(Player):
- """MPC Client
+ """MPD Client
From python-musicpd:
_fetch_nothing …
_fetch_item single str
_fetch_songs list of dict, especially tracks
_fetch_plugins,
TODO: handle exception in command not going through _client_wrapper() (ie.
- find_aa, remove…)
+ remove…)
"""
+ database = None # sima database (history, blaclist)
+
def __init__(self, host="localhost", port="6600", password=None):
super().__init__()
self._comm = self._args = None
wrapper = self._execute
return lambda *args: wrapper(command, args)
- def __del__(self):
- """Avoid hanging sockets"""
- self.disconnect()
-
def _execute(self, command, args):
self._write_command(command, args)
return self._client_wrapper()
return self.find('artist', artist, 'title', title)
return self.find('artist', artist)
+ @blacklist(artist=True)
def fuzzy_find_artist(self, art):
"""
Controls presence of artist in music library.
return alb_art_search
return self.find('artist', artist, 'album', album)
+ @blacklist(album=True)
def find_albums(self, artist):
"""
- Fetch all albums for "AlbumArtist" == artist
+ Fetch all albums for "AlbumArtist" == artist
Filter albums returned for "artist" == artist since MPD returns any
album containing at least a single track for artist
"""
- albums = set()
- albums.update(self.list('album', 'albumartist', artist))
+ albums = []
+ kwalbart = {'albumartist':artist, 'artist':artist}
+ for album in self.list('album', 'albumartist', artist):
+ if album not in albums:
+ albums.append(Album(name=album, **kwalbart))
for album in self.list('album', 'artist', artist):
arts = set([trk.artist for trk in self.find('album', album)])
- if len(arts) < 2:
- albums.add(album)
- else:
+ if len(arts) < 2: # TODO: better heuristic, use a ratio instead
+ if album not in albums:
+ albums.append(Album(name=album, albumartist=artist))
+ elif (album and album not in albums):
self.log.debug('"{0}" probably not an album of "{1}"'.format(
- album, artist) + '({0})'.format('/'.join(arts)))
+ album, artist) + '({0})'.format('/'.join(arts)))
return albums
def monitor(self):
def disconnect(self):
# Try to tell MPD we're closing the connection first
try:
+ self._client.noidle()
self._client.close()
# If that fails, don't worry, just ignore it and disconnect
except (MPDError, IOError):