Tagguessing: SoK project proposal

vedant agarwala vedant.kota at gmail.com
Mon Sep 23 18:55:09 UTC 2013


Hello everyone,

Below is the outline for my "Improving and Modularizing tag guessing"
Season of KDE project:

Implementation Details:

Creating a generic framework for tag getters: I will replace the
existing musicbrainz directory by a taggetter directory. It will
contain Controller and Provider classes (similar to StatSyncing) under
the namespace TagGetter. The settings UI and related classes will also
be present in this directory. I will change the musicbrainzTagger() in
the TagDialog class to tagGetterController(). Once this is called, an
object of TagGetter::Controller will be created and process of tag
guessing will begin. The Controller will have a list (a QList of
ProviderPointers) of available Providers and it will create objects of
each of them. Each of those objects will implementing the abstract
base class Provider. As required, the Controller will be calling the
methods (and connecting signals to slots) of the Provider on the main
thread and via polymorphism appropriate methods of each Provider will
be called.

Each TagGetter::Provider will have its own directory under the
TagGetter directory. They will contain classes and one that will
implement the Provider class. Each provider will be running in
parallel. As the different Providers do their work, results and
progress of the work will available to the Controller via the signals
connected to the slots of the Controller. Establishing a connection to
the web service server, converting the music into data sendable over
the internet, fetching results and the error handling will all be part
of each Provider’s work. Separate threads won’t be required because
the network operations will be handled by Qt (QNetworkRequest and
QNetworkReply) and they are the most time consuming. If something else
takes time to run (like decoding the audio and creating the
fingerprint) then the provider will have to manage this on another
thread (probably by using the ThreadWeaver::Job). As part of the
contract of each provider, each of its methods must return quickly.
This is important because the Controller will guarantee calling these
methods on the main thread.

The Controller will provide the Providers with the TrackPtr and hence
with track data (name, album, artist, length, file location etc.). I
will write a TagGetterMeta class. Member variables of this class will
include a trackPtr (to store the track pointer of the track whose
metadata is being fetched) and metadata variables (name, artist,
album, etc.). After data has been fetched, Providers will fill the
metadata to the TagGetterMetra objects according to the trackPtr and
return this object via a signal to TagGetter::Controller. Providers
should not store this data but they should keep the data that
authenticates the provider (probably an API key that is received on
authentication) as long as the objects of themselves exist since many
lists of tracks can sent to be the Provider in quick succession. Each
Provider can store a small amount of data in the data using the
KGlobal::config(). A provider should add itself to the "plugins"
section in Amarok Settings so that it can be enabled/disabled by the
user. If badly required also provide some additional user changeable
settings, since its best to keep working of plugins as abstracted from
the user as possible.

Adapt MusicBrainz tag getter to implement the abstract Provider class:
I will rewrite MusicBrainz code according to the above framework. All
the existing classes will shifted to the new musicbrainz subdirectory
inside the taggetter directory. The MusicBrainzFinder will become
MusicIpProvider, implementing the abstract Provider class. Other code
will also be re-written. Currently, libofa is used to create the
MusicIP (PUID) that is sent to MusicBrainz. MusicBrainz is phasing out
PUIDs in favour of AcustIDs.

Hence, another Provider will be made (in the same directory). A
AcoustIdProvider will use Chromaprint to compute AcustIDs rather than
the MusicIP generated by libofa. Chromaprint will be used to generate
the AcoustID. Chromaprint uses the standard C library[*] so code can
easily be used withing existing classes. I will make libchromaprint a
part of the optional tag guessing package (alongwith libofa) and
update the cmakelists, making Chromaprint as a requirement for
MusicBrainz tag guessing. Hence, the AcoustIdProvider will be
available only if Chromaprint has been installed. Chromaprint will be
part of the optional package. A HAS_CHROMAPRINT macro will keep track
of this. The provider will be “available” only if the macro is
defined.

Creating Last.fm tag getter: Create the Last.fm tag getter. First, I
will add the tag based service and then, if schedule permits, I can
add the fingerprint based service. Hence, two LastFm Providers will be
created. Implementation will be very easy thanks to liblastfm- A Qt
C++ library for the Last.fm webservices. It is already used in Amarok.
Both the Providers will share the authentication data and reply so
that network requests aren’t needlessly duplicated. They will be in
the same directory but will have two available providers. The network
replies by Last.fm and parsing will be handled by liblastfm itself.
Now the similarities end. The network requests and replies will have
to handled differently by the different providers, since one will be
tag based and the other fingerprint based.

For the LastfmTagProvider, the track/artist name has to be sent to the
Last.fm webservice API. The webservice will then return the other
track metadata. For the LastFmFingerprintProvider we will first have
to generate a “fingerprint” of the track using the Last Fm
Fingerprinter. This audio fingerprint will then be sent to the Last fm
web service via a call to the track.getFingerprintMetadata. Then the
web service will return the track metadata along with a “confidence
rating” to specify how accurately the track has been identified.

Tentative Timeline:

September-

week 1: Add the features (like using AcoustID) to this MusicBrainz tag getter

week 2: Make the directories and write the abstract classes (with
documentation).

week 3: Re-write the MusicBrainz tag getter according to the framework
with better documentation

week 4: Polish, make cmakelists for, write make tests and compile the
written abstract classes.

October-

week 1: Compile and run the new MusicBrainz. Fix issues and repeat

week 2: (Holiday week)

week 3: Complete the MusicBrainz tag getter.

week 4: Write the Last.fm tag getter (as many features as time permits)

November-

week 1: Compile and run the new Last.fm. Fix issues and repeat

week 2: Finish writing and test the Last.fm tag getter

week 3: (College examinations)

week 4: (College examinations)

December-

week 1: Write make tests to make sure that new tag getters follow the
set framework

week 2: Improve documentation. Fix bugs that have been discovered over the weeks

week 3: Fix Bugs, streamline and optimize the code.

week 4: Do some code cleaning and fix bugs so that my project can be
pushed into the master branch.


More information about the Amarok-devel mailing list