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 display_songs(filenames, path=None, enable_pager=False): lines = [] if path is None: c_w, t_w = columns_width(columns) header = '' for i, column in enumerate(columns): header += colorize(column.title().ljust(c_w[column]), colors[i % len(colors)], True) if enable_pager: lines.append(header) lines.append('-' * t_w) else: print(header) print('—' * t_w) current_song = mpd.get_current_song() for song in filenames: if path is None: bold = True if song == current_song else False row = '' for i, column in enumerate(columns): if column == 'filename': tag = song else: tag = mpd.get_tag(song, column, empty='<empty>') if column == 'time': m, s = divmod(int(tag), 60) tag = '{}:{:02}'.format(m, s) if len(tag) > c_w[column] - 1: tag = tag[:c_w[column] - 2] + '…' row += colorize(tag.ljust(c_w[column]), colors[i % len(colors)], bold) if enable_pager: lines.append(row) else: print(row) else: if enable_pager: lines.append(os.path.join(path, song)) else: print(os.path.join(path, song)) if enable_pager: pager_p = subprocess.Popen(shlex.split(pager), stdin=subprocess.PIPE) pager_p.stdin.write(bytes('\n'.join(lines), 'utf-8')) pager_p.stdin.close() pager_p.communicate()
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)