[GSoC Update] Playdar Wrap-up

Andy Coder andrew.coder at gmail.com
Sun Aug 15 06:18:31 CEST 2010


The big problem that got resolved since the last update is the
possibility that, when a track being searched for isn't in the
collection, the MemoryQueryMaker will read from the collection before
any new results are added, so the track won't be found until the next
query.  This isn't a problem in cases where the query is run again
when a collection emits updated(), but in context applets, (Similar
Artists, in particular), this isn't the case, and we miss out on music
that's actually available.

After having trouble running an existing MemoryQueryMaker a second
time, (filters and matchers get lost on the first run), I devised a
solution that appears to work, and seems pretty fast.
PlaydarQueryMaker now calls setAutoDelete( true ) on its
MemoryQueryMaker, regardless of what's been set for the
PlaydarQueryMaker itself, and, if the MemoryQueryMaker has finished,
and new tracks have shown up since it ended, we create a new
MemoryQueryMaker, invoke each query setup function that was called
originally, and run the query, emitting queryDone() after it comes
back.  If nothing changed, we skip it.

The part of this that Leo felt should be reviewed by folks is how I
handle calling the setup functions.  I've made several new classes,
(defined in playdarcollection/support/QMFunctionTypes.h), which
correspond to QueryMaker:: member functions that return a QueryMaker*
and take 0-4 arguments, ( a class for each arity, argument types are
template parameters ).  Each defines a type called FunPtr, and takes a
FunPtr and the arguments we'd like the function invoked with later.
These are used whenever a QueryMaker* returning member of
PlaydarQueryMaker is called, when we append the function and its
parameters to a list.  They all share the CurriedQMFunction base
class, and define QueryMaker* operator()( QueryMaker *qm ), so when we
need to run the functions on a new QueryMaker, we iterate over the
list, applying each object to the new QueryMaker,   the result being
that the object calls its function with the stored parameters,
providing qm as the this pointer.  The practical result of this is
that the new QueryMaker is set up exactly how the old one was, but
will be run on the updated collection.

The syntax of the whole thing is a bit odd, but it's conceptually
simple, (store a list of member functions with arguments, that can
later be invoked on any suitable object, sort of like making new
static members on-the-fly), and faster than other options that don't
involve changing the way that MemoryQueryMaker works, so I like it.
Still, if anyone's got an option that they think is more reasonable,
I'd be happy to hear it.

Also, the Similar Artists applet now has a button that appears
alongside the show in sources and last.fm buttons to add the top track
of an artist to the playlist.  Since the Artist widget has been
changed to use CollectionManager::instance()->queryMaker() instead of
CollectionManager::instance()->primaryCollection()->queryMaker(), (as
has the CurrentEngine), this can resolve the track using Playdar, if
it's available.

Folks can see this in action by looking at the Flickr set in my blog
post about it [0], or getting the playdar_collection branch from my
gitorious clone[1].

 - Andy Coder

[0]: http://andy-coder.blogspot.com/2010/08/gsoc-wrap-up-using-playdar-in-amarok.html
[1]: git://gitorious.org/~andycoder/amarok/andycoders-amarok-clone.git


More information about the Amarok-devel mailing list