X-Git-Url: https://git.kaliko.me/?a=blobdiff_plain;f=sima%2Flib%2Fwebserv.py;h=8201964bdf1da71dbb9fa33e16fa590c497bb0bc;hb=2f23824849643b60e24ca0f838efaad41d5e0727;hp=c8ab86ec5ba7378bb2a711c8d51c847e7e55dc2e;hpb=d0232dae194becb33696266083df400a54afbd27;p=mpd-sima.git diff --git a/sima/lib/webserv.py b/sima/lib/webserv.py index c8ab86e..8201964 100644 --- a/sima/lib/webserv.py +++ b/sima/lib/webserv.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2009-2020 kaliko +# Copyright (c) 2009-2021 kaliko # Copyright (c) 2019 sacha # # This file is part of sima @@ -35,6 +35,7 @@ from .plugin import AdvancedPlugin from .meta import Artist, MetaContainer from ..utils.utils import WSError, WSNotFound, WSTimeout + def cache(func): """Caching decorator""" def wrapper(*args, **kwargs): @@ -48,7 +49,7 @@ def cache(func): else: results = func(*args, **kwargs) cls.log.debug('caching request') - cls._cache.get('asearch').update({hashedlst:list(results)}) + cls._cache.get('asearch').update({hashedlst: list(results)}) random.shuffle(results) return results return wrapper @@ -57,13 +58,11 @@ def cache(func): class WebService(AdvancedPlugin): """similar artists webservice """ - # pylint: disable=bad-builtin def __init__(self, daemon): super().__init__(daemon) self.history = daemon.short_history ## - self.to_add = list() self._cache = None self._flush_cache() wrapper = {'track': self._track, @@ -82,8 +81,8 @@ class WebService(AdvancedPlugin): self.log.info('%s: Flushing cache!', name) else: self.log.info('%s: Initialising cache!', name) - self._cache = {'asearch': dict(), - 'tsearch': dict()} + self._cache = {'asearch': {}, + 'tsearch': {}} def _cleanup_cache(self): """Avoid bloated cache @@ -99,13 +98,12 @@ class WebService(AdvancedPlugin): Look in player library for availability of similar artists in similarities """ - dynamic = self.plugin_conf.getint('max_art') # pylint: disable=no-member + dynamic = self.plugin_conf.getint('max_art') if dynamic <= 0: dynamic = 100 - results = list() + results = [] similarities.reverse() - while (len(results) < dynamic - and len(similarities) > 0): + while (len(results) < dynamic+1 and similarities): art_pop = similarities.pop() res = self.player.search_artist(art_pop) if res: @@ -157,12 +155,12 @@ class WebService(AdvancedPlugin): else: history = self.player.queue + history history = deque(history) - last_trk = history.popleft() # remove - extra_arts = list() - ret_extra = list() + last_trk = history.popleft() # remove + extra_arts = [] + ret_extra = [] depth = 0 - while depth < self.plugin_conf.getint('depth'): # pylint: disable=no-member - if len(history) == 0: + while depth < self.plugin_conf.getint('depth'): + if not history: break trk = history.popleft() if (trk.Artist in extra_arts @@ -209,15 +207,13 @@ class WebService(AdvancedPlugin): self.log.debug('Got nothing similar from library!') ret_extra = None if len(self.history) >= 2: - if self.plugin_conf.getint('depth') > 1: # pylint: disable=no-member + if self.plugin_conf.getint('depth') > 1: ret_extra = self.get_recursive_similar_artist() if ret_extra: # get them reorg to pick up best element ret_extra = self.get_reorg_artists_list(ret_extra) # tries to pickup less artist from extra art - if len(ret) < 4: - ret_extra = MetaContainer(ret_extra) - else: + if len(ret) > 4: ret_extra = MetaContainer(ret_extra[:max(4, len(ret))//2]) if ret_extra: self.log.debug('extra found in library: %s', @@ -228,9 +224,11 @@ class WebService(AdvancedPlugin): return [] # In random play mode use complete playlist to filter if self.player.playmode.get('random'): - queued_artists = MetaContainer([trk.Artist for trk in self.player.playlist]) + queued_artists = MetaContainer([trk.Artist for trk + in self.player.playlist]) else: - queued_artists = MetaContainer([trk.Artist for trk in self.player.queue]) + queued_artists = MetaContainer([trk.Artist for trk + in self.player.queue]) self.log.trace('Already queued: %s', queued_artists) self.log.trace('Candidate: %s', ret) if ret & queued_artists: @@ -244,30 +242,25 @@ class WebService(AdvancedPlugin): # Move around similars items to get in unplayed|not recently played # artist first. self.log.info('Got %d artists in library', len(ret)) - candidates = self.get_reorg_artists_list(list(ret)) + candidates = self.get_reorg_artists_list(ret) if candidates: self.log.info(' / '.join(map(str, candidates))) return candidates - def _get_album_history(self, artist): - """Retrieve album history""" - albums_list = set() - for trk in self.get_history(artist=artist.name): - if not trk.album: - continue - albums_list.add(trk.album) - return albums_list - def find_album(self, artists): """Find albums to queue. """ - self.to_add = list() + to_add = [] nb_album_add = 0 - target_album_to_add = self.plugin_conf.getint('album_to_add') # pylint: disable=no-member + target_album_to_add = self.plugin_conf.getint('album_to_add') for artist in artists: - album = self.album_candidate(artist) + album = self.album_candidate(artist, unplayed=True) + if not album: + continue nb_album_add += 1 candidates = self.player.find_tracks(album) + if not candidates: + continue if self.plugin_conf.getboolean('shuffle_album'): random.shuffle(candidates) # this allows to select a maximum number of track from the album @@ -275,23 +268,24 @@ class WebService(AdvancedPlugin): nbtracks = self.plugin_conf.getint('track_to_add_from_album') if nbtracks > 0: candidates = candidates[0:nbtracks] - self.to_add.extend(candidates) + to_add.extend(candidates) if nb_album_add == target_album_to_add: - return True + return to_add + return to_add def find_top(self, artists): """ find top tracks for artists in artists list. """ - self.to_add = list() - nbtracks_target = self.plugin_conf.getint('track_to_add') # pylint: disable=no-member + to_add = [] + nbtracks_target = self.plugin_conf.getint('track_to_add') for artist in artists: - if len(self.to_add) == nbtracks_target: - return + if len(to_add) == nbtracks_target: + break self.log.info('Looking for a top track for %s', artist) titles = deque() try: - titles = [t for t in self.ws.get_toptrack(artist)] + titles = list(self.ws.get_toptrack(artist)) except WSError as err: self.log.warning('%s: %s', self.ws.name, err) continue @@ -299,64 +293,71 @@ class WebService(AdvancedPlugin): found = self.player.search_track(artist, trk.title) if found: random.shuffle(found) - top_trk = self.filter_track(found) + top_trk = self.filter_track(found, to_add) if top_trk: - self.to_add.append(top_trk) + to_add.append(top_trk) break + return to_add def _track(self): """Get some tracks for track queue mode + + :return: list of Tracks """ + to_add = [] artists = self.get_local_similar_artists() - nbtracks_target = self.plugin_conf.getint('track_to_add') # pylint: disable=no-member + nbtracks_target = self.plugin_conf.getint('track_to_add') for artist in artists: self.log.debug('Trying to find titles to add for "%r"', artist) found = self.player.find_tracks(artist) - random.shuffle(found) if not found: self.log.debug('Found nothing to queue for %s', artist) continue + random.shuffle(found) # find tracks not in history for artist - track_candidate = self.filter_track(found) + track_candidate = self.filter_track(found, to_add) if track_candidate: - self.to_add.append(track_candidate) - if len(self.to_add) == nbtracks_target: + to_add.append(track_candidate) + self.log.info('%s plugin chose: %s', + self.ws.name, track_candidate) + if len(to_add) == nbtracks_target: break - if not self.to_add: - self.log.debug('Found no tracks to queue!') - return None - for track in self.to_add: - self.log.info('%s candidates: %s', track, self.ws.name) + return to_add def _album(self): """Get albums for album queue mode + + :return: list of Tracks """ artists = self.get_local_similar_artists() - self.find_album(artists) + return self.find_album(artists) def _top(self): """Get some tracks for top track queue mode + + :return: list of Tracks """ artists = self.get_local_similar_artists() - self.find_top(artists) - for track in self.to_add: + chosen = self.find_top(artists) + for track in chosen: self.log.info('%s candidates: %s', self.ws.name, track) + return chosen def callback_need_track(self): self._cleanup_cache() - if len(self.player.playlist) == 0: + if not self.player.playlist: self.log.info('No last track, cannot queue') return None if not self.player.playlist[-1].artist: self.log.warning('No artist set for the last track in queue') self.log.debug(repr(self.player.current)) return None - self.queue_mode() - msg = ' '.join(['{0}: {1:>3d}'.format(k, v) for + candidates = self.queue_mode() + msg = ' '.join([f'{k}: {v:>3d}' for k, v in sorted(self.ws.stats.items())]) self.log.debug('http stats: ' + msg) - candidates = self.to_add - self.to_add = list() + if not candidates: + self.log.info('%s plugin found nothing to queue', self.ws.name) if self.plugin_conf.get('queue_mode') != 'album': random.shuffle(candidates) return candidates