* Use Chromaprinter instead of OFA fingerprinter.

* Send fingerprint to Acoustid instead of MusicDNS.
* Retrieve MBID instead of PUID and send to Musicbrainz.
This commit is contained in:
John Maguire 2012-01-06 16:31:29 +00:00
parent 423295b01e
commit db83c411c2
6 changed files with 52 additions and 40 deletions

View File

@ -142,8 +142,6 @@ QString Chromaprinter::CreateFingerprint() {
qLog(Debug) << "Decode time:" << decode_time << "Codegen time:" << codegen_time; qLog(Debug) << "Decode time:" << decode_time << "Codegen time:" << codegen_time;
qLog(Debug) << "Chromaprint:" << fingerprint;
// Cleanup // Cleanup
gst_bus_set_sync_handler(gst_pipeline_get_bus(GST_PIPELINE(pipeline_)), NULL, NULL); gst_bus_set_sync_handler(gst_pipeline_get_bus(GST_PIPELINE(pipeline_)), NULL, NULL);
g_source_remove(bus_callback_id); g_source_remove(bus_callback_id);

View File

@ -35,14 +35,14 @@ MusicBrainzClient::MusicBrainzClient(QObject* parent)
{ {
} }
void MusicBrainzClient::Start(int id, const QString& puid) { void MusicBrainzClient::Start(int id, const QString& mbid) {
typedef QPair<QString, QString> Param; typedef QPair<QString, QString> Param;
QList<Param> parameters; QList<Param> parameters;
parameters << Param("type", "xml") parameters << Param("type", "xml")
<< Param("puid", puid); << Param("inc", "artist+releases");
QUrl url(kTrackUrl); QUrl url(kTrackUrl + mbid);
url.setQueryItems(parameters); url.setQueryItems(parameters);
QNetworkRequest req(url); QNetworkRequest req(url);

View File

@ -30,8 +30,8 @@ class QNetworkReply;
class MusicBrainzClient : public QObject { class MusicBrainzClient : public QObject {
Q_OBJECT Q_OBJECT
// Gets metadata for a particular PUID. // Gets metadata for a particular MBID.
// A PUID is created from a fingerprint using MusicDnsClient. // An MBID is created from a fingerprint using MusicDnsClient.
// You can create one MusicBrainzClient and make multiple requests using it. // You can create one MusicBrainzClient and make multiple requests using it.
// IDs are provided by the caller when a request is started and included in // IDs are provided by the caller when a request is started and included in
// the Finished signal - they have no meaning to MusicBrainzClient. // the Finished signal - they have no meaning to MusicBrainzClient.
@ -52,8 +52,8 @@ public:
// Starts a request and returns immediately. Finished() will be emitted // Starts a request and returns immediately. Finished() will be emitted
// later with the same ID. // later with the same ID.
void Start(int id, const QString& puid); void Start(int id, const QString& mbid);
void StartDiscIdRequest(const QString& puid); void StartDiscIdRequest(const QString& discid);
// Cancels the request with the given ID. Finished() will never be emitted // Cancels the request with the given ID. Finished() will never be emitted
// for that ID. Does nothing if there is no request with the given ID. // for that ID. Does nothing if there is no request with the given ID.

View File

@ -16,15 +16,18 @@
*/ */
#include "musicdnsclient.h" #include "musicdnsclient.h"
#include "core/network.h"
#include <QCoreApplication> #include <QCoreApplication>
#include <QNetworkReply> #include <QNetworkReply>
#include <QXmlStreamReader>
#include <QtDebug>
const char* MusicDnsClient::kClientId = "c44f70e49000dd7c0d1388bff2bf4152"; #include <qjson/parser.h>
const char* MusicDnsClient::kUrl = "http://ofa.musicdns.org/ofa/1/track";
#include "core/logging.h"
#include "core/network.h"
#include "core/timeconstants.h"
const char* MusicDnsClient::kClientId = "qsZGpeLx";
const char* MusicDnsClient::kUrl = "http://api.acoustid.org/v2/lookup";
const int MusicDnsClient::kDefaultTimeout = 5000; // msec const int MusicDnsClient::kDefaultTimeout = 5000; // msec
MusicDnsClient::MusicDnsClient(QObject* parent) MusicDnsClient::MusicDnsClient(QObject* parent)
@ -42,20 +45,11 @@ void MusicDnsClient::Start(int id, const QString& fingerprint, int duration_msec
typedef QPair<QString, QString> Param; typedef QPair<QString, QString> Param;
QList<Param> parameters; QList<Param> parameters;
parameters << Param("alb", "unknown") parameters << Param("format", "json")
<< Param("art", "unknown") << Param("client", kClientId)
<< Param("brt", "0") << Param("duration", QString::number(duration_msec / kMsecPerSec))
<< Param("cid", kClientId) << Param("meta", "recordingids")
<< Param("cvr", QString("%1 %2").arg(QCoreApplication::applicationName(), << Param("fingerprint", fingerprint);
QCoreApplication::applicationVersion()))
<< Param("dur", QString::number(duration_msec))
<< Param("fmt", "unknown")
<< Param("fpt", fingerprint)
<< Param("gnr", "unknown")
<< Param("rmd", "1")
<< Param("tnm", "0")
<< Param("ttl", "unknown")
<< Param("yrr", "0");
QUrl url(kUrl); QUrl url(kUrl);
url.setQueryItems(parameters); url.setQueryItems(parameters);
@ -95,12 +89,31 @@ void MusicDnsClient::RequestFinished() {
return; return;
} }
QXmlStreamReader reader(reply); QJson::Parser parser;
while (!reader.atEnd()) { bool ok = false;
if (reader.readNext() == QXmlStreamReader::StartElement && reader.name() == "puid") { QVariantMap result = parser.parse(reply, &ok).toMap();
QString puid = reader.attributes().value("id").toString(); if (!ok) {
emit Finished(id, puid); emit Finished(id, QString());
return; return;
}
QString status = result["status"].toString();
if (status != "ok") {
emit Finished(id, QString());
return;
}
QVariantList results = result["results"].toList();
foreach (const QVariant& v, results) {
QVariantMap r = v.toMap();
if (r.contains("recordings")) {
QVariantList recordings = r["recordings"].toList();
foreach (const QVariant& recording, recordings) {
QVariantMap o = recording.toMap();
if (o.contains("id")) {
emit Finished(id, o["id"].toString());
return;
}
}
} }
} }

View File

@ -29,9 +29,9 @@ class QNetworkReply;
class MusicDnsClient : public QObject { class MusicDnsClient : public QObject {
Q_OBJECT Q_OBJECT
// Gets a PUID from an OFA fingerprint. // Gets a MBID from a Chromaprint fingerprint.
// A fingerprint identifies one particular encoding of a song and is created // A fingerprint identifies one particular encoding of a song and is created
// by Fingerprinter. A PUID identifies the actual song and can be passed to // by Fingerprinter. An MBID identifies the actual song and can be passed to
// Musicbrainz to get metadata. // Musicbrainz to get metadata.
// You can create one MusicDnsClient and make multiple requests using it. // You can create one MusicDnsClient and make multiple requests using it.
// IDs are provided by the caller when a request is started and included in // IDs are provided by the caller when a request is started and included in
@ -56,7 +56,7 @@ public:
void CancelAll(); void CancelAll();
signals: signals:
void Finished(int id, const QString& puid); void Finished(int id, const QString& mbid);
private slots: private slots:
void RequestFinished(); void RequestFinished();

View File

@ -15,10 +15,11 @@
along with Clementine. If not, see <http://www.gnu.org/licenses/>. along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "fingerprinter.h" #include "tagfetcher.h"
#include "chromaprinter.h"
#include "musicbrainzclient.h" #include "musicbrainzclient.h"
#include "musicdnsclient.h" #include "musicdnsclient.h"
#include "tagfetcher.h"
#include "core/timeconstants.h" #include "core/timeconstants.h"
#include <QFuture> #include <QFuture>
@ -37,7 +38,7 @@ TagFetcher::TagFetcher(QObject* parent)
} }
QString TagFetcher::GetFingerprint(const Song& song) { QString TagFetcher::GetFingerprint(const Song& song) {
return Fingerprinter(song.url().toLocalFile()).CreateFingerprint(); return Chromaprinter(song.url().toLocalFile()).CreateFingerprint();
} }
void TagFetcher::StartFetch(const SongList& songs) { void TagFetcher::StartFetch(const SongList& songs) {