From 7d10b76169f2e3f2b16b9159633c0eefa43a2050 Mon Sep 17 00:00:00 2001 From: "adrian.sampson" Date: Sun, 5 Apr 2009 20:27:53 +0000 Subject: [PATCH] added list and count --HG-- extra : convert_revision : svn%3A41726ec3-264d-0410-9c23-a9f1637257cc/trunk%40184 --- beets/library.py | 11 +++++++ beets/player/bpd.py | 78 +++++++++++++++++++++++++++++++++------------ bts | 2 +- 3 files changed, 70 insertions(+), 21 deletions(-) diff --git a/beets/library.py b/beets/library.py index c6b9a2bba..1590da35e 100644 --- a/beets/library.py +++ b/beets/library.py @@ -373,6 +373,17 @@ class Query(object): clause, subvals = self.clause() return ('SELECT ' + columns + ' FROM items WHERE ' + clause, subvals) + def count(self, library): + """Returns `(num, length)` where `num` is the number of items in + the library matching this query and `length` is their total + length in seconds. + """ + clause, subvals = self.clause() + statement = 'SELECT COUNT(id), SUM(length) FROM items WHERE ' + clause + c = library.conn.cursor() + result = c.execute(statement, subvals).fetchone() + return (result[0], result[1]) + def execute(self, library): """Runs the query in the specified library, returning a ResultIterator. diff --git a/beets/player/bpd.py b/beets/player/bpd.py index 164e87ae1..2af1e4e2e 100755 --- a/beets/player/bpd.py +++ b/beets/player/bpd.py @@ -858,31 +858,32 @@ class Server(BaseServer): def cmd_stats(self, conn): - # The first three items need to be done more efficiently. The - # last three need to be implemented. + # The first two items need to be done more efficiently. + songs, totaltime = beets.library.TrueQuery().count(self.lib) conn.send('artists: ' + str(len(self.lib.artists())), 'albums: ' + str(len(self.lib.albums())), - 'songs: ' + str(len(list(self.lib.items()))), + 'songs: ' + str(songs), 'uptime: ' + str(int(time.time() - self.startup_time)), - 'playtime: ' + '0', - 'db_playtime: ' + '0', - 'db_update: ' + str(int(self.startup_time)), + 'playtime: ' + '0', #fixme + 'db_playtime: ' + str(int(totaltime)), + 'db_update: ' + str(int(self.startup_time)), #fixme ) # Searching. tagtype_map = { - 'Artist': 'artist', - 'Album': 'album', - 'Title': 'title', - 'Track': 'track', + 'artist': 'artist', + 'album': 'album', + 'title': 'title', + 'track': 'track', # Name? - 'Genre': 'genre', - 'Date': 'year', - 'Composer': 'composer', + 'genre': 'genre', + 'date': 'year', + 'composer': 'composer', # Performer? - 'Disc': 'disc', + 'disc': 'disc', + 'filename': 'path', # Suspect. } def cmd_tagtypes(self, conn): @@ -892,22 +893,59 @@ class Server(BaseServer): for tag in self.tagtype_map: conn.send('tagtype: ' + tag) - def cmd_search(self, conn, key, value): + def _tagtype_to_key(self, tag): + """Uses `tagtype_map` to look up the beets column name for an + MPD tagtype (or throw an appropriate exception). + """ + try: + return self.tagtype_map[tag.lower()] + except KeyError: + raise BPDError(ERROR_UNKNOWN, 'no such tagtype') + + def cmd_search(self, conn, tag, value): """Perform a substring match in a specific column.""" - if key == 'filename': - key = 'path' + key = self._tagtype_to_key(tag) query = beets.library.SubstringQuery(key, value) for item in self.lib.get(query): conn.send(*self._item_info(item)) - def cmd_find(self, conn, key, value): + def cmd_find(self, conn, tag, value): """Perform an exact match in a specific column.""" - if key == 'filename': - key = 'path' + key = self._tagtype_to_key(tag) query = beets.library.MatchQuery(key, value) for item in self.lib.get(query): conn.send(*self._item_info(item)) + def cmd_list(self, conn, show_tag, match_tag=None, match_term=None): + """List distinct metadata values for show_tag, possibly + filtered by matching match_tag to match_term. + """ + show_key = self._tagtype_to_key(show_tag) + if match_tag and match_term: + match_key = self._tagtype_to_key(match_tag) + query = beets.library.MatchQuery(match_key, match_term) + else: + query = beets.library.TrueQuery() + + clause, subvals = query.clause() + statement = 'SELECT DISTINCT ' + show_key + \ + ' FROM items WHERE ' + clause + c = self.lib.conn.cursor() + c.execute(statement, subvals) + + for row in c: + conn.send(show_tag + ': ' + row[0]) + + def cmd_count(self, conn, tag, value): + """Returns the number and total time of songs matching the + tag/value query. + """ + key = self._tagtype_to_key(tag) + query = beets.library.MatchQuery(key, value) + songs, playtime = query.count(self.lib) + conn.send('songs: ' + str(songs), + 'playtime: ' + str(int(playtime))) + # "Outputs." Just a dummy implementation because we don't control # any outputs. diff --git a/bts b/bts index 9b1f496ed..e988cbaaa 100755 --- a/bts +++ b/bts @@ -82,7 +82,7 @@ def bpd(lib, config, opts): if __name__ == "__main__": # parse options usage = """usage: %prog [options] command -command is one of: add, remove, update, write, list, help""" +command is one of: add, remove, update, write, list, bpd, help""" op = OptionParser(usage=usage) op.add_option('-l', '--library', dest='libpath', metavar='PATH', default=None,