def p_expression_filter(p): 'expression : FILTER' exact = True if p[1][0].isupper() else False alias = (p[1][0] if p[1][1] in '"\'' else p[1][0:2]).lower() name = filters_alias.get(alias, '') pattern = p[1][2:-1] if p[1][1] in '"\'' else p[1][3:-1] if not name: warning('Filter [{}] does not exist'.format(alias)) sys.exit(0) if name == 'lastfm_a': p[0] = OrderedSet() if exact: artists = lastfm.find_artists(pattern) else: artists = lastfm.search_artists(pattern) for artist in artists: p[0] |= mpd.find('artist', artist) elif name == 'lastfm_b': p[0] = OrderedSet() if exact: albums = lastfm.find_albums(pattern) else: albums = lastfm.search_albums(pattern) for album, artist in albums: matched_songs = mpd.find_multiple(albumartist=artist, album=album) if not matched_songs: matched_songs = mpd.find_multiple(artist=artist, album=album) p[0] |= matched_songs p[0] = mpd.set_sort(p[0]) elif exact: p[0] = OrderedSet(mpd.find(name, pattern)) else: p[0] = OrderedSet(mpd.search(name, pattern))
def p_expression_collection(p): 'expression : COLLECTION' p[0] = OrderedSet() if p[1] in collectionsmanager.c: collection = collectionsmanager.c[p[1]] if 'expression' in collection: p[0] |= parser.parse(collection['expression'], lexer=lex.lex(debug=0, reflags=re.UNICODE|re.IGNORECASE)) if 'songs' in collection: p[0] |= OrderedSet(collection['songs']) if enable_command and 'command' in collection: try: output = subprocess.check_output(collection['command'], shell=True) p[0] |= OrderedSet(format_mpc_output(output.decode())) except subprocess.CalledProcessError: warning('Error while executing `command` in collection [{}]'. format(p[1])) sys.exit(0) if 'sort' in collection: p[0] = mpd.set_sort(p[0]) elif p[1] == 'all': p[0] = OrderedSet(mpd.get_all_songs()) elif p[1] == 'c': p[0] = OrderedSet(mpd.get_playlist_songs()) elif p[1] == 'C': c_song = mpd.get_current_song() if c_song is not None: p[0] = OrderedSet([c_song]) elif p[1] == 'A': c_song = mpd.get_current_song() if c_song is not None: p[0] = OrderedSet(mpd.find('artist', mpd.get_tag(c_song, 'artist'))) elif p[1] == 'B': c_song = mpd.get_current_song() if c_song is not None: p[0] = OrderedSet(mpd.find_multiple( albumartist=mpd.get_tag(c_song, 'albumartist'), album=mpd.get_tag(c_song, 'album'))) if not p[0]: p[0] = OrderedSet(mpd.find_multiple( artist=mpd.get_tag(c_song, 'artist'), album=mpd.get_tag(c_song, 'album'))) else: warning('Collection [{}] does not exist'.format(p[1])) sys.exit(0)
def p_expression_collection(p): 'expression : COLLECTION' if p[1] in collections: collection = collections[p[1]] p[0] = OrderedSet() if 'expression' in collection: p[0] |= p.parser.parse(collection['expression'], lexer=lex.lex(debug=0, reflags=re.UNICODE)) if 'songs' in collection: p[0] |= OrderedSet(collection['songs']) if enable_command and 'command' in collection: try: output = check_output(collection['command'], shell=True) p[0] |= OrderedSet(format_mpc_output(output.decode())) except CalledProcessError: warning('Error while executing `command` in collection [%s]' % p[1]) sys.exit(0) if 'sort' in collection: p[0] = mpd.set_sort(p[0]) elif p[1] == 'all': p[0] = OrderedSet(mpd.get_all_songs()) elif p[1] == 'c': p[0] = OrderedSet(mpd.get_playlist_songs()) elif p[1] == 'C': p[0] = OrderedSet([mpd.get_current_song()]) elif p[1] == 'A': c_song = mpd.get_current_song() p[0] = OrderedSet(mpd.find('artist', mpd.get_tag(c_song, 'artist'))) elif p[1] == 'B': c_song = mpd.get_current_song() p[0] = OrderedSet(mpd.find_multiple( artist=mpd.get_tag(c_song, 'artist'), album=mpd.get_tag(c_song, 'album'))) else: warning('Collection [%s] doesn\'t exist' % p[1]) sys.exit(0)
def p_expression_modifier(p): 'expression : expression MODIFIER' modifier = (p[2][1:]).lstrip() # Sorting modifier if modifier == 's': p[0] = mpd.set_sort(p[1]) # N-random songs modifier elif re.match(r'^r[0-9]+$', modifier): try: p[0] = OrderedSet(random.sample(p[1], int(modifier[1:]))) except ValueError: p[0] = p[1] # N-random artists modifier elif re.match(r'^ra[0-9]+$', modifier): artists = OrderedSet() for song in p[1]: artists.add(mpd.get_tag(song, 'artist')) try: r_artists = OrderedSet(random.sample(artists, int(modifier[2:]))) except ValueError: p[0] = p[1] else: songs = [] for artist in r_artists: songs.extend(mpd.find('artist', artist)) p[0] = OrderedSet([song for song in p[1] if song in songs]) # N-random albums modifier elif re.match(r'^rb[0-9]+$', modifier): albums = OrderedSet() for song in p[1]: albums.add(mpd.get_tags(song, ('album', 'artist'))) try: r_albums = OrderedSet(random.sample(albums, int(modifier[2:]))) except ValueError: p[0] = p[1] else: songs = [] for album, artist in r_albums: songs.extend(mpd.find_multiple(album=album, artist=artist)) p[0] = OrderedSet([song for song in p[1] if song in songs]) # N-minutes-long modifier elif re.match(r'^d[0-9]+$', modifier): total_duration = int(modifier[1:]) * 60 d = 0 p[0] = OrderedSet() p[1] = list(p[1]) random.shuffle(p[1]) for song in p[1]: if d < total_duration: p[0].add(song) d += int(mpd.get_tag(song, 'time')) else: break # N-similar artists modifier elif re.match(r'^i?sa[0-9]+$', modifier): include = True if modifier[0] == 'i' else False limit = int((modifier[3:] if include else modifier[2:])) w_tags = defaultdict(int) for song in p[1]: tags = lastfm.get_artist_tags(mpd.get_tag(song, 'artist')) for tag in tags: w_tags[tag] += tags[tag] if not w_tags: p[0] = p[1] if include else OrderedSet() else: songs = [] similar_artists = lastfm.get_similar_artists(w_tags) for artist, score in similar_artists: if not limit: break matched_songs = mpd.find('artist', artist) if not include: matched_songs = OrderedSet(matched_songs) - p[1] if matched_songs: songs.extend(matched_songs) limit -= 1 p[0] = OrderedSet(songs) # N-similar albums modifier elif re.match(r'^i?sb[0-9]+$', modifier): include = True if modifier[0] == 'i' else False limit = int((modifier[3:] if include else modifier[2:])) w_tags = defaultdict(int) for song in p[1]: tags = lastfm.get_album_tags(mpd.get_tag(song, 'album'), mpd.get_tag(song, 'artist')) for tag in tags: w_tags[tag] += tags[tag] if not w_tags: p[0] = p[1] if include else OrderedSet() else: songs = [] for (album, artist), score in lastfm.get_similar_albums(w_tags): if not limit: break matched_songs = mpd.find_multiple(album=album, artist=artist) if not include: matched_songs = OrderedSet(matched_songs) - p[1] if matched_songs: songs.extend(matched_songs) limit -= 1 p[0] = OrderedSet(songs) else: warning('Modifier [%s] doesn\'t exist' % modifier) sys.exit(0)
def p_expression_modifier(p): 'expression : expression MODIFIER' modifier = (p[2][1:]).lstrip() # Sorting modifier if modifier == 's': p[0] = mpd.set_sort(p[1]) # N-random songs modifier elif re.match(r'^r[0-9]+$', modifier): p[1] = exclude_songs(p[1]) try: p[0] = OrderedSet(random.sample(p[1], int(modifier[1:]))) except ValueError: p[0] = p[1] # N-random artists modifier elif re.match(r'^ra[0-9]+$', modifier): p[1] = exclude_songs(p[1]) artists = OrderedSet() for song in p[1]: artists.add(mpd.get_tag(song, 'artist')) try: r_artists = OrderedSet(random.sample(artists, int(modifier[2:]))) except ValueError: p[0] = p[1] else: songs = [] for artist in r_artists: songs.extend(mpd.find('artist', artist)) p[0] = OrderedSet([song for song in p[1] if song in songs]) # N-random albums modifier elif re.match(r'^rb[0-9]+$', modifier): p[1] = exclude_songs(p[1]) albums = OrderedSet() for song in p[1]: albums.add(mpd.get_tags(song, ('album', 'albumartist'))) try: r_albums = OrderedSet(random.sample(albums, int(modifier[2:]))) except ValueError: p[0] = p[1] else: songs = [] for album, artist in r_albums: matched_songs = mpd.find_multiple(album=album, albumartist=artist) if not matched_songs: matched_songs = mpd.find_multiple(album=album, artist=artist) songs.extend(matched_songs) p[0] = OrderedSet([song for song in p[1] if song in songs]) # N-minutes-long modifier elif re.match(r'^d[0-9]+$', modifier): p[1] = exclude_songs(p[1]) total_duration = int(modifier[1:]) * 60 d = 0 p[0] = OrderedSet() p[1] = list(p[1]) random.shuffle(p[1]) for song in p[1]: if d < total_duration: p[0].add(song) d += int(mpd.get_tag(song, 'time')) else: break # N-similar artists modifier elif re.match(r'^i?sa[0-9]+$', modifier): include = True if modifier[0] == 'i' else False limit = int(modifier[3:] if include else modifier[2:]) w_tags = collections.defaultdict(int) for song in p[1]: tags = lastfm.get_artist_tags(mpd.get_tag(song, 'artist')) for tag, w in tags.items(): w_tags[tag] += w if not w_tags: p[0] = p[1] if include else OrderedSet() else: songs = [] for artist, _ in lastfm.get_similar_artists(w_tags): if not limit: break matched_songs = mpd.find('artist', artist) if not include: matched_songs = OrderedSet(matched_songs) - p[1] if matched_songs: songs.extend(matched_songs) limit -= 1 p[0] = OrderedSet(songs) # N-similar albums modifier elif re.match(r'^i?sb[0-9]+$', modifier): include = True if modifier[0] == 'i' else False limit = int(modifier[3:] if include else modifier[2:]) w_tags = collections.defaultdict(int) for song in p[1]: tags = lastfm.get_album_tags(mpd.get_tag(song, 'album'), mpd.get_tag(song, 'albumartist')) for tag, w in tags.items(): w_tags[tag] += w if not w_tags: p[0] = p[1] if include else OrderedSet() else: songs = [] for (album, artist), score in lastfm.get_similar_albums(w_tags): if not limit: break matched_songs = mpd.find_multiple(album=album, albumartist=artist) if not matched_songs: matched_songs = mpd.find_multiple(album=album, artist=artist) if not include: matched_songs = OrderedSet(matched_songs) - p[1] if matched_songs: songs.extend(matched_songs) limit -= 1 p[0] = OrderedSet(songs) # N-top tracks modifier elif re.match(r'^p[0-9]+$', modifier): p[0] = OrderedSet() artists = OrderedSet(mpd.get_tag(song, 'artist') for song in p[1]) for artist in artists: limit = int(modifier[1:]) for track in lastfm.get_artist_top_tracks(artist): if not limit: break matched_songs = mpd.search_multiple(artist=artist, title=track) if len(matched_songs) > 1: matched_songs = mpd.find_multiple(artist=artist, title=track) \ or matched_songs if matched_songs: p[0].add(matched_songs[0]) limit -= 1 else: warning('Modifier [{}] does not exist'.format(modifier)) sys.exit(0)