Add basics of last.fm suggester and library resolver.
This commit is contained in:
parent
a65dab7bad
commit
41e79bea0e
@ -185,6 +185,8 @@ set(SOURCES
|
|||||||
radio/somafmservice.cpp
|
radio/somafmservice.cpp
|
||||||
radio/somafmurlhandler.cpp
|
radio/somafmurlhandler.cpp
|
||||||
|
|
||||||
|
resolvers/libraryresolver.cpp
|
||||||
|
|
||||||
scripting/installscriptdialog.cpp
|
scripting/installscriptdialog.cpp
|
||||||
scripting/languageengine.cpp
|
scripting/languageengine.cpp
|
||||||
scripting/script.cpp
|
scripting/script.cpp
|
||||||
@ -222,6 +224,8 @@ set(SOURCES
|
|||||||
songinfo/ultimatelyricsprovider.cpp
|
songinfo/ultimatelyricsprovider.cpp
|
||||||
songinfo/ultimatelyricsreader.cpp
|
songinfo/ultimatelyricsreader.cpp
|
||||||
|
|
||||||
|
suggesters/lastfmsuggester.cpp
|
||||||
|
|
||||||
transcoder/transcodedialog.cpp
|
transcoder/transcodedialog.cpp
|
||||||
transcoder/transcoder.cpp
|
transcoder/transcoder.cpp
|
||||||
transcoder/transcoderoptionsaac.cpp
|
transcoder/transcoderoptionsaac.cpp
|
||||||
@ -397,6 +401,8 @@ set(HEADERS
|
|||||||
radio/somafmservice.h
|
radio/somafmservice.h
|
||||||
radio/somafmurlhandler.h
|
radio/somafmurlhandler.h
|
||||||
|
|
||||||
|
resolvers/libraryresolver.h
|
||||||
|
|
||||||
scripting/installscriptdialog.h
|
scripting/installscriptdialog.h
|
||||||
scripting/languageengine.h
|
scripting/languageengine.h
|
||||||
scripting/scriptdialog.h
|
scripting/scriptdialog.h
|
||||||
@ -428,6 +434,8 @@ set(HEADERS
|
|||||||
songinfo/ultimatelyricsprovider.h
|
songinfo/ultimatelyricsprovider.h
|
||||||
songinfo/ultimatelyricsreader.h
|
songinfo/ultimatelyricsreader.h
|
||||||
|
|
||||||
|
suggesters/lastfmsuggester.h
|
||||||
|
|
||||||
transcoder/transcodedialog.h
|
transcoder/transcodedialog.h
|
||||||
transcoder/transcoder.h
|
transcoder/transcoder.h
|
||||||
transcoder/transcoderoptionsdialog.h
|
transcoder/transcoderoptionsdialog.h
|
||||||
|
62
src/resolvers/libraryresolver.cpp
Normal file
62
src/resolvers/libraryresolver.cpp
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#include "libraryresolver.h"
|
||||||
|
|
||||||
|
#include <QtConcurrentRun>
|
||||||
|
|
||||||
|
#include <boost/scoped_ptr.hpp>
|
||||||
|
|
||||||
|
#include "core/boundfuturewatcher.h"
|
||||||
|
#include "core/song.h"
|
||||||
|
#include "library/librarybackend.h"
|
||||||
|
#include "library/libraryquery.h"
|
||||||
|
#include "library/sqlrow.h"
|
||||||
|
|
||||||
|
using boost::scoped_ptr;
|
||||||
|
|
||||||
|
LibraryResolver::LibraryResolver(LibraryBackendInterface* backend, QObject* parent)
|
||||||
|
: QObject(parent),
|
||||||
|
backend_(backend) {
|
||||||
|
}
|
||||||
|
|
||||||
|
int LibraryResolver::ResolveSong(const Song& song) {
|
||||||
|
LibraryQuery* query = new LibraryQuery;
|
||||||
|
query->AddWhere("artist", song.artist());
|
||||||
|
query->AddWhere("title", song.title());
|
||||||
|
|
||||||
|
QFuture<bool> future = QtConcurrent::run(
|
||||||
|
backend_, &LibraryBackendInterface::ExecQuery, query);
|
||||||
|
BoundFutureWatcher<bool, LibraryQuery*>* watcher =
|
||||||
|
new BoundFutureWatcher<bool, LibraryQuery*>(query);
|
||||||
|
watcher->setFuture(future);
|
||||||
|
connect(watcher, SIGNAL(finished()), SLOT(QueryFinished()));
|
||||||
|
|
||||||
|
int id = next_id_++;
|
||||||
|
queries_[query] = id;
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LibraryResolver::QueryFinished() {
|
||||||
|
BoundFutureWatcher<bool, LibraryQuery*>* watcher =
|
||||||
|
static_cast<BoundFutureWatcher<bool, LibraryQuery*>*>(sender());
|
||||||
|
scoped_ptr<LibraryQuery> query(watcher->data());
|
||||||
|
watcher->deleteLater();
|
||||||
|
|
||||||
|
QMap<LibraryQuery*, int>::iterator it = queries_.find(query.get());
|
||||||
|
if (it == queries_.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int id = it.value();
|
||||||
|
queries_.erase(it);
|
||||||
|
|
||||||
|
SongList songs;
|
||||||
|
if (watcher->result() && query->Next()) {
|
||||||
|
do {
|
||||||
|
Song song;
|
||||||
|
song.InitFromQuery(*query);
|
||||||
|
songs << song;
|
||||||
|
} while (query->Next());
|
||||||
|
}
|
||||||
|
|
||||||
|
emit ResolveFinished(id, songs);
|
||||||
|
}
|
32
src/resolvers/libraryresolver.h
Normal file
32
src/resolvers/libraryresolver.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#ifndef LIBRARYRESOLVER_H
|
||||||
|
#define LIBRARYRESOLVER_H
|
||||||
|
|
||||||
|
#include <QMap>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "core/song.h"
|
||||||
|
|
||||||
|
class QNetworkReply;
|
||||||
|
|
||||||
|
class LibraryBackendInterface;
|
||||||
|
class LibraryQuery;
|
||||||
|
|
||||||
|
class LibraryResolver : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
LibraryResolver(LibraryBackendInterface* backend, QObject* parent = 0);
|
||||||
|
int ResolveSong(const Song& song);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void ResolveFinished(int id, SongList songs);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void QueryFinished();
|
||||||
|
|
||||||
|
private:
|
||||||
|
LibraryBackendInterface* backend_;
|
||||||
|
QMap<LibraryQuery*, int> queries_;
|
||||||
|
int next_id_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LIBRARYRESOLVER_H
|
66
src/suggesters/lastfmsuggester.cpp
Normal file
66
src/suggesters/lastfmsuggester.cpp
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#include "lastfmsuggester.h"
|
||||||
|
|
||||||
|
#include <lastfm/XmlQuery>
|
||||||
|
|
||||||
|
#include "core/logging.h"
|
||||||
|
#include "core/timeconstants.h"
|
||||||
|
|
||||||
|
using lastfm::XmlQuery;
|
||||||
|
|
||||||
|
LastFMSuggester::LastFMSuggester(QObject* parent)
|
||||||
|
: QObject(parent),
|
||||||
|
next_id_(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
int LastFMSuggester::SuggestSongs(const Song& song) {
|
||||||
|
QMap<QString, QString> params;
|
||||||
|
params["method"] = "track.getsimilar";
|
||||||
|
params["track"] = song.title();
|
||||||
|
params["artist"] = song.artist();
|
||||||
|
params["limit"] = "25";
|
||||||
|
QNetworkReply* reply = lastfm::ws::get(params);
|
||||||
|
connect(reply, SIGNAL(finished()), SLOT(RequestFinished()));
|
||||||
|
|
||||||
|
int id = next_id_++;
|
||||||
|
replies_[reply] = id;
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LastFMSuggester::RequestFinished() {
|
||||||
|
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
|
||||||
|
Q_ASSERT(reply);
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
QMap<QNetworkReply*, int>::iterator it = replies_.find(reply);
|
||||||
|
if (it == replies_.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int id = it.value();
|
||||||
|
replies_.erase(it);
|
||||||
|
|
||||||
|
try {
|
||||||
|
lastfm::XmlQuery const lfm = lastfm::ws::parse(reply);
|
||||||
|
#ifdef Q_OS_WIN32
|
||||||
|
if (lastfm::ws::last_parse_error != lastfm::ws::NoError)
|
||||||
|
throw std::runtime_error("");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const QList<XmlQuery> tracks = lfm["similartracks"].children("track");
|
||||||
|
SongList songs;
|
||||||
|
foreach (const XmlQuery& q, tracks) {
|
||||||
|
Song song;
|
||||||
|
song.Init(
|
||||||
|
q["name"].text(),
|
||||||
|
q["artist"]["name"].text(),
|
||||||
|
QString::null,
|
||||||
|
QString(q["duration"].text()).toInt() * kNsecPerMsec);
|
||||||
|
songs << song;
|
||||||
|
}
|
||||||
|
qLog(Debug) << songs.length() << "suggested songs from Last.fm";
|
||||||
|
emit SuggestSongsFinished(id, songs);
|
||||||
|
} catch (std::runtime_error& e) {
|
||||||
|
qLog(Error) << e.what();
|
||||||
|
emit SuggestSongsFinished(id, SongList());
|
||||||
|
}
|
||||||
|
}
|
30
src/suggesters/lastfmsuggester.h
Normal file
30
src/suggesters/lastfmsuggester.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef LASTFMSUGGESTER_H
|
||||||
|
#define LASTFMSUGGESTER_H
|
||||||
|
|
||||||
|
#include <QMap>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include <lastfm/ws.h>
|
||||||
|
|
||||||
|
#include "core/song.h"
|
||||||
|
|
||||||
|
class LastFMSuggester : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
LastFMSuggester(QObject* parent = 0);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
int SuggestSongs(const Song& song);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void SuggestSongsFinished(int id, const SongList& songs);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void RequestFinished();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QMap<QNetworkReply*, int> replies_;
|
||||||
|
int next_id_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LASTFMSUGGESTER_H
|
Loading…
x
Reference in New Issue
Block a user