Permalink
Browse files

Re-organise the code somewhat.

  • Loading branch information...
1 parent 77fcefb commit 0e4c3523214a84d1d9a975d764556b2a76d3ff63 Albin Stjerna committed Feb 23, 2013
Showing with 185 additions and 0 deletions.
  1. +29 −0 bin/fred.py
  2. +46 −0 bin/plc.py
  3. +40 −0 bin/pldc.py
  4. +70 −0 bin/search.py
View
@@ -0,0 +1,29 @@
+#!/usr/bin/python
+# -*- mode: Python; encoding: utf-8; indent-tabs-mode: nil; tab-width: 2 -*-
+
+# Fred: a xapian-backed music search utility.
+import sys
+import os
+import time
+from db import xapian_music as db
+
+CURRENT_DIR = os.path.dirname(__file__)
+DBPATH = os.path.join(CURRENT_DIR, "music.db")
+#MUSIC_DIR = os.path.join(CURRENT_DIR, "test/music_dir")
+MUSIC_DIR = "/var/storage/Musik/"
+
+def main(args):
+ start_time = time.time()
+
+ db.index(datapath = MUSIC_DIR, dbpath = DBPATH)
+
+ #db.tag(dbpath=DBPATH, querystring=" ".join(args[1:]), tags=["inbox", "fisk"])
+
+ matches = db.search(dbpath=DBPATH, querystring=" ".join(args[1:]))
+ for match in matches:
+ print u"{tracknumber} {artist} – »{title}« from {album} {year} ({length} s). Last modified {mtime}. Tagged {tags}.".format(**match['data'])
+ print "N: Found %i tracks in in %f ms.\n" % (len(matches), (time.time() - start_time)*1000)
+
+
+if __name__ == "__main__":
+ main(sys.argv)
View
@@ -0,0 +1,46 @@
+#!/usr/bin/env python
+# -*- mode: Python; encoding: utf-8; indent-tabs-mode: nil; tab-width: 2 -*-
+# This is a reference playlist compiler.
+import time
+import os
+import sys
+from playlist import transport as ts
+from playlist import m3u
+from playlist.match import match_transport
+from db import rhythmbox as rb
+from db import dirtree
+
+RB_DB = os.path.expanduser('~/.local/share/rhythmbox/rhythmdb.xml')
+CURRENT_DIR = os.path.dirname(__file__)
+
+if len(sys.argv) > 1 and not len(sys.argv) > 2:
+ playlist = ts.load(sys.argv[1])
+else:
+ sys.stderr.write("Usage: plc <playlist file> <optional output file>. "
+ "If no output file is given, print to stdout.\n")
+ sys.exit()
+
+start_time = time.time()
+
+songs = match_transport(playlist, rb.get_songs(RB_DB))
+
+for i, song in enumerate(songs):
+ if song == None:
+ sys.stderr.write("E: couldn't find %d: %s by %s.\n" %
+ ((i+1), playlist["playlist"][i]["title"],
+ playlist["playlist"][i]["artist"]))
+
+m3u_list = m3u.M3UList(songs, name=playlist['description'],
+ comments=[playlist['comment']])
+
+target = sys.stdout
+
+if len(sys.argv) > 2:
+ target = sys.argv[2]
+
+m3u.write(m3u_list, target)
+
+sys.stderr.write("N: Finished matching in %f seconds.\n" %
+ (time.time() - start_time))
+
+
View
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+# -*- mode: Python; encoding: utf-8; indent-tabs-mode: nil; tab-width: 2 -*-
+# This is a reference playlist decompiler.
+import os
+import sys
+from playlist import transport as ts
+from playlist import m3u
+from db import dirtree as dt
+
+def main(args):
+ if len(args) != 2:
+ sys.stderr.write("Usage: pldc <playlist file>.\n")
+ sys.exit()
+
+ playlist = m3u.parse(args[1])
+
+ def mangle_song(s):
+ ("Read the metadata from the song in path s, "
+ "and mangle it to a valid line for the songs "
+ "part of a transport playlist.")
+
+ md = dt.read_metadata_from_file(s)
+ return ts.make_song(artist=md['artist'][0],
+ length=md.info.length,
+ title=md['title'][0],
+ album=md.get("album", None)[0])
+
+
+ songs = map(mangle_song, playlist)
+
+ # fixme: these and other options should be provided at command line:
+ transport = ts.make_playlist(songs,
+ "http://test.example.com/pls",
+ "description")
+ ts.write(transport, sys.stdout)
+
+
+
+if __name__ == "__main__":
+ main(sys.argv)
View
@@ -0,0 +1,70 @@
+#!/usr/bin/python
+# -*- mode: Python; encoding: utf-8; indent-tabs-mode: nil; tab-width: 2 -*-
+
+import xapian
+from db.dirtree import get_songs
+
+def index(datapath, dbpath):
+ # Create or open the database we're going to be writing to.
+ db = xapian.WritableDatabase(dbpath, xapian.DB_CREATE_OR_OPEN)
+
+ # Set up a TermGenerator that we'll use in indexing.
+ termgenerator = xapian.TermGenerator()
+ termgenerator.set_stemmer(xapian.Stem("en"))
+
+ for song in get_songs(datapath):
+ # We make a document and tell the term generator to use this.
+ doc = xapian.Document()
+ termgenerator.set_document(doc)
+
+ # Index each field with a suitable prefix.
+ # Prefixes from http://xapian.org/docs/omega/termprefixes.html
+ termgenerator.index_text(song['title'], 1, 'S')
+ termgenerator.index_text(song['artist'], 1, 'A')
+# termgenerator.index_text(description, 1, 'XD')
+
+ # Index fields without prefixes for general search.
+ termgenerator.index_text(song['title'])
+ termgenerator.increase_termpos()
+ termgenerator.index_text(song['artist'])
+
+ # Store all the fields for display purposes.
+ doc.set_data(unicode(song['mdata']))
+
+ # use doc.add_term(str.join(K, "my tag"), 0) to add tags the way notmuch does
+
+ # We use the identifier to ensure each object ends up in the
+ # database only once no matter how many times we run the
+ # indexer.
+ idterm = u"Q" + song['path']
+ doc.add_boolean_term(idterm)
+ db.replace_document(idterm, doc)
+
+def search(dbpath, querystring):
+ # offset - defines starting point within result set
+ # pagesize - defines number of records to retrieve
+
+ # Open the database we're going to search.
+ db = xapian.Database(dbpath)
+
+ # Set up a QueryParser with a stemmer and suitable prefixes
+ queryparser = xapian.QueryParser()
+ queryparser.set_stemmer(xapian.Stem("en"))
+ queryparser.set_stemming_strategy(queryparser.STEM_SOME)
+ queryparser.add_prefix("title", "S")
+ queryparser.add_prefix("artist", "A")
+
+ # And parse the query
+ query = queryparser.parse_query(querystring)
+
+ # Use an Enquire object on the database to run the query
+ enquire = xapian.Enquire(db)
+ enquire.set_query(query)
+
+ # And print out something about each match
+ matches = []
+ for match in enquire.get_mset(0, db.get_doccount()):
+ matches.append({docid: match.docid})
+
+
+ return matches

0 comments on commit 0e4c352

Please sign in to comment.