Modified:
/trunk/README.txt
/trunk/autoqueue.py
/trunk/mirage.py
/trunk/mirage_miximize.py
/trunk/mirage_songs.py
/trunk/quodlibet_autoqueue.py
/trunk/rhythmbox_autoqueue.py
/trunk/test_mirage.py
=======================================
--- /trunk/README.txt Tue Jan 20 07:39:33 2009
+++ /trunk/README.txt Wed Sep 16 05:33:17 2009
@@ -57,13 +57,6 @@
seconds. For instance 4440 will get you a queue of 74 minutes, which
is a common size for blank audio CDs. Default: 0
-- relax: Filter to relax the block track rules: use any search
- expression you can use in the quod libet search to allow some songs
- to break the rules. For instance I use: '(#(added < 30
- days),grouping=favorites)', so that my favorites, and anything I
- added in the last month can be played more often than the block
- track variable indicates. Default: ''
-
- restrict: Filter to restrict which tracks autoqueue finds. For
instance, you could use 'genre=reggae', to find only songs with the
genre reggae or '&(#(date > 1979), #(date < 1990))' to find only
=======================================
--- /trunk/autoqueue.py Fri May 29 01:49:11 2009
+++ /trunk/autoqueue.py Wed Sep 16 05:33:17 2009
@@ -187,6 +187,7 @@
self.running = False
self.verbose = False
self.weed = False
+ self.lastfm = True
self.now = datetime.now()
self.song = None
self._blocked_artists = deque([])
@@ -340,7 +341,7 @@
if self.running:
return
self.song = song
- if MIRAGE and self.by_mirage:
+ if MIRAGE:
fid = "analyze_track" + str(int(time()))
self.player_execute_async(self.analyze_track, song, funcid=fid)
if self.desired_queue_length == 0 or self.queue_needs_songs():
@@ -581,11 +582,14 @@
@Throttle(WAIT_BETWEEN_REQUESTS)
def last_fm_request(self, url):
+ if not self.lastfm:
+ return None
try:
stream = urllib.urlopen(url)
xmldoc = minidom.parse(stream).documentElement
return xmldoc
except:
+ self.lastfm = False
return None
def get_artist(self, artist_name, with_connection=None):
@@ -672,22 +676,25 @@
track = self.get_track(artist_name, title)
track_id, artist_id = track[0], track[1]
db = Db(self.get_db_path())
- if db.get_track(track_id):
+ if db.has_scores(track_id):
return
- self.log("no mirage data found for %s, analyzing track" % filename)
+ yield
+ scms = db.get_track(track_id)
+ if not scms:
+ self.log("no mirage data found for %s, analyzing track" %
filename)
+ try:
+ scms = self.mir.analyze(filename)
+ except MatrixDimensionMismatchException:
+ return
+ db.add_track(track_id, scms)
exclude_ids = self.get_artist_tracks(artist_id)
- try:
- scms = self.mir.analyze(filename)
- except MatrixDimensionMismatchException:
- return
- for dummy in db.add_and_compare(
- track_id, scms, exclude_ids=exclude_ids):
+ for dummy in db.add_neighbours(track_id, scms,
exclude_ids=exclude_ids):
yield
return
def get_ordered_mirage_tracks(self, song):
"""get similar tracks from mirage acoustic analysis"""
- maximum = 20000
+ maximum = 100
scale_to = 10000
artist_name = song.get_artist()
title = song.get_title()
@@ -698,12 +705,12 @@
track = self.get_track(artist_name, title)
track_id, artist_id, updated = track[0], track[1], track[3]
db = Db(self.get_db_path())
- for match, mtrack_id in db.get_neighbours(track_id):
+ for i, match, mtrack_id in db.get_neighbours(track_id):
result = self.get_artist_and_title(mtrack_id)
if not result:
continue
track_artist, track_title = result
- yield(scale(match, maximum, scale_to),
+ yield(scale(i, maximum, scale_to),
{'mirage_distance': match,
'artist': track_artist,
'title': track_title})
=======================================
--- /trunk/mirage.py Tue Apr 28 02:30:33 2009
+++ /trunk/mirage.py Wed Sep 16 05:33:17 2009
@@ -409,6 +409,14 @@
self.close_database_connection(connection)
return None
+ def has_scores(self, trackid, no=10):
+ connection = self.get_database_connection()
+ cursor = connection.execute(
+ "SELECT COUNT(*) FROM distance WHERE track_1 = ?", (trackid,))
+ l = cursor.fetchone()[0]
+ self.close_database_connection(connection)
+ return l >= no
+
def get_tracks(self, exclude_ids=None):
if not exclude_ids:
exclude_ids = []
@@ -433,53 +441,41 @@
connection.commit()
self.close_database_connection(connection)
- def add_and_compare(self, trackid, scms, cutoff=7500,
exclude_ids=None):
- min_add = 5
+ def add_neighbours(self, trackid, scms, exclude_ids=None):
+ connection = self.get_database_connection()
+ connection.commit()
+ connection.execute("DELETE FROM distance WHERE track_1 = ?",
(trackid,))
+ self.close_database_connection(connection)
+ yield
+ min_add = 10
if not exclude_ids:
exclude_ids = []
- self.add_track(trackid, scms)
c = ScmsConfiguration(20)
- add = []
- best_of_the_rest = []
+ best = []
for buf, otherid in self.get_tracks(
exclude_ids=exclude_ids):
if trackid == otherid:
continue
other = instance_from_picklestring(buf)
dist = int(distance(scms, other, c) * 1000)
- if dist < cutoff:
- add.append((trackid, otherid, dist))
- else:
- if len(add) > min_add - 1:
+ if len(best) > min_add - 1:
+ if dist > best[-1][0]:
continue
- if len(best_of_the_rest) > min_add - 1:
- if dist > best_of_the_rest[-1][0]:
- continue
- best_of_the_rest.append((dist, trackid, otherid))
- best_of_the_rest.sort()
- while len(best_of_the_rest) > min_add:
- best_of_the_rest.pop()
+ best.append((dist, trackid, otherid))
+ best.sort()
+ while len(best) > min_add:
+ best.pop()
yield
added = 0
- if add:
+ if best:
connection = self.get_database_connection()
- while add:
+ while best:
added += 1
connection.execute(
- "INSERT INTO distance (track_1, track_2, distance) "
- "VALUES (?, ?, ?)", add.pop())
+ "INSERT INTO distance (distance, track_1, track_2) "
+ "VALUES (?, ?, ?)", best.pop())
connection.commit()
self.close_database_connection(connection)
- connection = self.get_database_connection()
- while best_of_the_rest and added < min_add:
- dist, trackid, otherid = best_of_the_rest.pop(0)
- connection.execute(
- "INSERT INTO distance (track_1, track_2, distance) "
- "VALUES (?, ?, ?)",
- (trackid, otherid, dist))
- added += 1
- connection.commit()
- self.close_database_connection(connection)
print "added %d connections" % added
def compare(self, id1, id2):
@@ -492,16 +488,12 @@
connection = self.get_database_connection()
neighbours1 = [row for row in connection.execute(
"SELECT distance, track_2 FROM distance WHERE track_1 = ? "
- "ORDER BY distance ASC LIMIT 100",
- (trackid,))]
- neighbours2 = [row for row in connection.execute(
- "SELECT distance, track_1 FROM distance WHERE track_2 = ? "
- "ORDER BY distance ASC LIMIT 100",
+ "ORDER BY distance ASC",
(trackid,))]
self.close_database_connection(connection)
- neighbours1.extend(neighbours2)
- neighbours1.sort()
- return neighbours1
+ return [
+ (i, distance, track) for (i, (distance, track)) in
+ enumerate(neighbours1)]
class Mfcc(object):
@@ -535,7 +527,10 @@
t = DbgTimer()
t.start()
mel = Matrix(self.filterweights.rows, m.columns)
- mel.d = mel.d + dot(self.filterweights.d, m.d)
+ try:
+ mel.d = mel.d + dot(self.filterweights.d, m.d)
+ except ValueError:
+ raise MfccFailedException
mel.d = vf(mel.d)
try:
=======================================
--- /trunk/mirage_miximize.py Tue Mar 24 17:08:41 2009
+++ /trunk/mirage_miximize.py Wed Sep 16 05:33:17 2009
@@ -57,14 +57,17 @@
filename = song("~filename")
track = self.get_track(artist_name, title)
track_id, artist_id = track[0], track[1]
- if db.get_track(track_id):
+ if db.has_scores(track_id):
continue
+ scms = db.get_track(track_id)
+ if not scms:
+ try:
+ scms = self.mir.analyze(filename)
+ except:
+ return
+ db.add_track(track_id, scms)
exclude_ids = self.get_artist_tracks(artist_id)
- try:
- scms = self.mir.analyze(filename)
- except:
- return
- for dummy in db.add_and_compare(
+ for dummy in db.add_neighbours(
track_id, scms, exclude_ids=exclude_ids):
yield
yield
=======================================
--- /trunk/mirage_songs.py Tue Mar 24 17:08:41 2009
+++ /trunk/mirage_songs.py Wed Sep 16 05:33:17 2009
@@ -44,14 +44,17 @@
filename = song("~filename")
track = self.get_track(artist_name, title)
track_id, artist_id = track[0], track[1]
- if db.get_track(track_id):
+ if db.has_scores(track_id):
continue
+ scms = db.get_track(track_id)
+ if not scms:
+ try:
+ scms = self.mir.analyze(filename)
+ except:
+ return
+ db.add_track(track_id, scms)
exclude_ids = self.get_artist_tracks(artist_id)
- try:
- scms = self.mir.analyze(filename)
- except:
- return
- for dummy in db.add_and_compare(
+ for dummy in db.add_neighbours(
track_id, scms, exclude_ids=exclude_ids):
yield
yield
=======================================
--- /trunk/quodlibet_autoqueue.py Tue Jun 2 07:46:13 2009
+++ /trunk/quodlibet_autoqueue.py Wed Sep 16 05:33:17 2009
@@ -7,11 +7,9 @@
published by the Free Software Foundation"""
import const, gtk
-from datetime import datetime
from plugins.events import EventPlugin
from widgets import main
from parse import Query
-from qltk import Frame
from library import library
from quodlibet.util import copool
import config
=======================================
--- /trunk/rhythmbox_autoqueue.py Sun Feb 8 06:28:43 2009
+++ /trunk/rhythmbox_autoqueue.py Wed Sep 16 05:33:17 2009
@@ -22,14 +22,14 @@
from autoqueue import AutoQueueBase, SongBase
-GCONFPATH = '/apps/rhythmbox/plugins/lastfm_queue/'
+GCONFPATH = '/apps/rhythmbox/plugins/autoqueue/'
class Song(SongBase):
"""A wrapper object around rhythmbox song objects."""
def __init__(self, song, db):
self.song = song
self.db = db
-
+
def get_artist(self):
"""return lowercase UNICODE name of artist"""
return unicode(
@@ -53,6 +53,7 @@
return urllib.unquote(location[7:])
return None
+
class AutoQueuePlugin(rb.Plugin, AutoQueueBase):
def __init__(self):
rb.Plugin.__init__(self)
@@ -62,14 +63,14 @@
self.gconfclient = gconf.client_get_default()
self.verbose = False
self.by_mirage = False
-
+
def activate(self, shell):
self.shell = shell
self.rdb = shell.get_property('db')
sp = shell.get_player ()
self.pec_id = sp.connect(
'playing-song-changed', self.playing_entry_changed)
-
+
def deactivate(self, shell):
self.rdb = None
self.shell = None
@@ -85,7 +86,7 @@
def playing_entry_changed(self, sp, entry):
if entry:
self.on_song_started(Song(entry, self.rdb))
-
+
def player_get_userdir(self):
"""get the application user directory to store files"""
folder = os.path.join(
@@ -93,7 +94,7 @@
if not os.path.isdir(folder):
os.mkdir(folder)
return folder
-
+
def player_construct_track_search(self, artist, title, restrictions):
"""construct a search that looks for songs with this artist
and title"""
@@ -103,7 +104,7 @@
if restrictions:
result += restrictions
return result
-
+
def player_construct_tag_search(self, tags, exclude_artists,
restrictions):
"""construct a search that looks for songs with these
tags"""
@@ -116,7 +117,7 @@
if restrictions:
result += restrictions
return result
-
+
def player_construct_restrictions(
self, track_block_time, relaxors, restrictors):
"""contstruct a search to further modify the searches"""
=======================================
--- /trunk/test_mirage.py Wed Mar 11 01:57:22 2009
+++ /trunk/test_mirage.py Wed Sep 16 05:33:17 2009
@@ -108,10 +108,11 @@
c = ScmsConfiguration(20)
assert_equals(124, int(distance(scms3_db, scms4_db, c)))
- def test_add_and_compare(self):
+ def test_add_neighbours(self):
testdb = Db(":memory:")
for i, testscms in enumerate(scmses):
- for dummy in testdb.add_and_compare(i, testscms):
+ testdb.add_track(i, testscms)
+ for dummy in testdb.add_neighbours(i, testscms):
pass
connection = testdb.get_database_connection()
distances = [