1
0
mirror of https://github.com/clementine-player/Clementine synced 2024-12-16 19:31:02 +01:00

Allow the artist and album to be specified separately when searching for album covers

This commit is contained in:
David Sansome 2011-06-22 19:07:15 +00:00
parent 2e9ec3e9d4
commit bac414a630
14 changed files with 67 additions and 45 deletions

View File

@ -39,8 +39,9 @@ class AmazonCoverProvider(clementine.CoverProvider):
self.network = clementine.NetworkAccessManager()
def StartSearch(self, query, id):
url = QUrl.fromEncoded(self.API_URL.format(self.PrepareAmazonRESTUrl(query)))
def StartSearch(self, artist, album, id):
query = self.PrepareAmazonRESTUrl(artist + " " + album)
url = QUrl.fromEncoded(self.API_URL.format(query))
LOGGER.debug("ID %d: Sending request to '%s'" % (id, url))
reply = self.network.get(QNetworkRequest(url))

View File

@ -25,8 +25,8 @@ class GoogleImagesCoverProvider(clementine.CoverProvider):
}
self.network = clementine.NetworkAccessManager()
def StartSearch(self, query, id):
url = self.GetQueryURL(query)
def StartSearch(self, artist, album, id):
url = self.GetQueryURL(artist + " " + album)
LOGGER.info("Id %d - sending request to '%s'" % (id, url))
reply = self.network.get(QNetworkRequest(url))
@ -34,12 +34,12 @@ class GoogleImagesCoverProvider(clementine.CoverProvider):
def QueryFinished():
LOGGER.debug("Id %d - finished" % id)
self.SearchFinished(id, self.ParseReply(query, reply))
self.SearchFinished(id, self.ParseReply(artist, album, reply))
reply.connect("finished()", QueryFinished)
return True
def ParseReply(self, query, reply):
def ParseReply(self, artist, album, reply):
results = json.loads(str(reply.readAll()))
parsed = []
@ -48,7 +48,9 @@ class GoogleImagesCoverProvider(clementine.CoverProvider):
LOGGER.warning("Error parsing reply: %s", results["responseDetails"])
return parsed
LOGGER.info("Parsing reply for query '%s'", query)
query = "%s - %s" % (artist, album)
LOGGER.info("Parsing reply for query '%s'" % query)
for result in results['responseData']['results']:
current = clementine.CoverSearchResult()

View File

@ -33,10 +33,11 @@ AlbumCoverFetcher::AlbumCoverFetcher(QObject* parent, QNetworkAccessManager* net
connect(request_starter_, SIGNAL(timeout()), SLOT(StartRequests()));
}
quint64 AlbumCoverFetcher::FetchAlbumCover(
const QString& artist_name, const QString& album_name) {
quint64 AlbumCoverFetcher::FetchAlbumCover(const QString& artist,
const QString& album) {
CoverSearchRequest request;
request.query = artist_name + " " + album_name;
request.artist = artist;
request.album = album;
request.search = false;
request.id = next_id_ ++;
@ -44,9 +45,11 @@ quint64 AlbumCoverFetcher::FetchAlbumCover(
return request.id;
}
quint64 AlbumCoverFetcher::SearchForCovers(const QString &query) {
quint64 AlbumCoverFetcher::SearchForCovers(const QString& artist,
const QString& album) {
CoverSearchRequest request;
request.query = query;
request.artist = artist;
request.album = album;
request.search = true;
request.id = next_id_ ++;
@ -81,8 +84,8 @@ void AlbumCoverFetcher::StartRequests() {
// search objects are this fetcher's children so worst case scenario - they get
// deleted with it
AlbumCoverFetcherSearch* search = new AlbumCoverFetcherSearch(request, network_,
this);
AlbumCoverFetcherSearch* search = new AlbumCoverFetcherSearch(
request, network_, this);
active_requests_.insert(request.id, search);
connect(search, SIGNAL(SearchFinished(quint64, CoverSearchResults)),

View File

@ -38,8 +38,11 @@ class AlbumCoverFetcherSearch;
struct CoverSearchRequest {
// an unique (for one AlbumCoverFetcher) request identifier
quint64 id;
// a search query
QString query;
QString artist;
QString album;
// is this only a search request or should we also fetch the first
// cover that's found?
bool search;
@ -77,7 +80,7 @@ class AlbumCoverFetcher : public QObject {
static const int kMaxConcurrentRequests;
quint64 SearchForCovers(const QString& query);
quint64 SearchForCovers(const QString& artist, const QString& album);
quint64 FetchAlbumCover(const QString& artist, const QString& album);
void Clear();

View File

@ -60,18 +60,19 @@ void AlbumCoverFetcherSearch::TerminateSearch() {
void AlbumCoverFetcherSearch::Start() {
CoverProviders* providers = &CoverProviders::instance();
// end this search before it even began if there are no providers...
foreach(CoverProvider* provider, providers->List()) {
connect(provider, SIGNAL(SearchFinished(int,QList<CoverSearchResult>)),
SLOT(ProviderSearchFinished(int,QList<CoverSearchResult>)));
const int id = providers->NextId();
const bool success = provider->StartSearch(request_.query, id);
const bool success = provider->StartSearch(
request_.artist, request_.album, id);
if (success) {
pending_requests_[id] = provider;
}
}
// end this search before it even began if there are no providers...
if(pending_requests_.isEmpty()) {
TerminateSearch();
}

View File

@ -40,7 +40,7 @@ public:
// Starts searching for covers matching the given query text. Returns true
// if the query has been started, or false if an error occurred. The provider
// should remember the ID and emit it along with the result when it finishes.
virtual bool StartSearch(const QString& query, int id) = 0;
virtual bool StartSearch(const QString& artist, const QString& album, int id) = 0;
virtual void CancelSearch(int id) {}

View File

@ -30,10 +30,10 @@ LastFmCoverProvider::LastFmCoverProvider(QObject* parent)
{
}
bool LastFmCoverProvider::StartSearch(const QString& query, int id) {
bool LastFmCoverProvider::StartSearch(const QString& artist, const QString& album, int id) {
QMap<QString, QString> params;
params["method"] = "album.search";
params["album"] = query;
params["album"] = album + " " + artist;
QNetworkReply* reply = lastfm::ws::post(params);
connect(reply, SIGNAL(finished()), SLOT(QueryFinished()));

View File

@ -33,7 +33,7 @@ class LastFmCoverProvider : public CoverProvider {
public:
LastFmCoverProvider(QObject* parent);
bool StartSearch(const QString& query, int id);
bool StartSearch(const QString& artist, const QString& album, int id);
private slots:
void QueryFinished();

View File

@ -79,16 +79,16 @@ if (_wrapper) {
}
CoverProvider::CancelSearch(id);
}
bool PythonQtShell_CoverProvider::StartSearch(const QString& query, int id)
bool PythonQtShell_CoverProvider::StartSearch(const QString& artist, const QString& album, int id)
{
if (_wrapper) {
PyObject* obj = PyObject_GetAttrString((PyObject*)_wrapper, "StartSearch");
PyErr_Clear();
if (obj && !PythonQtSlotFunction_Check(obj)) {
static const char* argumentList[] ={"bool" , "const QString&" , "int"};
static const PythonQtMethodInfo* methodInfo = PythonQtMethodInfo::getCachedMethodInfoFromArgumentList(3, argumentList);
static const char* argumentList[] ={"bool" , "const QString&" , "const QString&" , "int"};
static const PythonQtMethodInfo* methodInfo = PythonQtMethodInfo::getCachedMethodInfoFromArgumentList(4, argumentList);
bool returnValue = 0;
void* args[3] = {NULL, (void*)&query, (void*)&id};
void* args[4] = {NULL, (void*)&artist, (void*)&album, (void*)&id};
PyObject* result = PythonQtSignalTarget::call(obj, methodInfo, args, true);
if (result) {
args[0] = PythonQtConv::ConvertPythonToQt(methodInfo->parameters().at(0), result, false, NULL, &returnValue);

View File

@ -74,7 +74,7 @@ public:
PythonQtShell_CoverProvider(const QString& name, QObject* parent):CoverProvider(name, parent),_wrapper(NULL) {};
virtual void CancelSearch(int id);
virtual bool StartSearch(const QString& query, int id);
virtual bool StartSearch(const QString& artist, const QString& album, int id);
virtual void childEvent(QChildEvent* arg__1);
virtual void customEvent(QEvent* arg__1);
virtual bool event(QEvent* arg__1);

View File

@ -158,12 +158,7 @@ QString AlbumCoverChoiceController::LoadCoverFromURL(Song* song) {
QString AlbumCoverChoiceController::SearchForCover(Song* song) {
// Get something sensible to stick in the search box
QString query = song->artist();
if (!query.isEmpty())
query += " ";
query += song->album();
QImage image = cover_searcher_->Exec(query);
QImage image = cover_searcher_->Exec(song->artist(), song->album());
if(!image.isNull()) {
QString cover = SaveCoverInCache(song->artist(), song->album(), image);

View File

@ -115,11 +115,12 @@ void AlbumCoverSearcher::Init(AlbumCoverFetcher* fetcher) {
connect(fetcher_, SIGNAL(SearchFinished(quint64,CoverSearchResults)), SLOT(SearchFinished(quint64,CoverSearchResults)));
}
QImage AlbumCoverSearcher::Exec(const QString &query) {
ui_->query->setText(query);
ui_->query->setFocus();
QImage AlbumCoverSearcher::Exec(const QString& artist, const QString& album) {
ui_->artist->setText(artist);
ui_->album->setText(album);
ui_->artist->setFocus();
if(!query.isEmpty()) {
if(!artist.isEmpty() || !album.isEmpty()) {
Search();
}
@ -140,13 +141,14 @@ QImage AlbumCoverSearcher::Exec(const QString &query) {
void AlbumCoverSearcher::Search() {
ui_->busy->show();
ui_->search->setEnabled(false);
ui_->query->setEnabled(false);
ui_->artist->setEnabled(false);
ui_->album->setEnabled(false);
ui_->covers->setEnabled(false);
model_->clear();
cover_loading_tasks_.clear();
id_ = fetcher_->SearchForCovers(ui_->query->text());
id_ = fetcher_->SearchForCovers(ui_->artist->text(), ui_->album->text());
}
void AlbumCoverSearcher::SearchFinished(quint64 id, const CoverSearchResults& results) {
@ -154,7 +156,8 @@ void AlbumCoverSearcher::SearchFinished(quint64 id, const CoverSearchResults& re
return;
ui_->search->setEnabled(true);
ui_->query->setEnabled(true);
ui_->artist->setEnabled(true);
ui_->album->setEnabled(true);
ui_->covers->setEnabled(true);
id_ = 0;

View File

@ -67,7 +67,7 @@ public:
void Init(AlbumCoverFetcher* fetcher);
QImage Exec(const QString& query);
QImage Exec(const QString& artist, const QString& album);
protected:
void keyPressEvent(QKeyEvent *);

View File

@ -17,9 +17,22 @@
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="LineEdit" name="query">
<widget class="LineEdit" name="artist">
<property name="toolTip">
<string>Artist</string>
</property>
<property name="hint" stdset="0">
<string>Enter search terms here</string>
<string>Artist</string>
</property>
</widget>
</item>
<item>
<widget class="LineEdit" name="album">
<property name="toolTip">
<string>Album</string>
</property>
<property name="hint" stdset="0">
<string>Album</string>
</property>
</widget>
</item>
@ -99,7 +112,8 @@
</customwidget>
</customwidgets>
<tabstops>
<tabstop>query</tabstop>
<tabstop>artist</tabstop>
<tabstop>album</tabstop>
<tabstop>search</tabstop>
<tabstop>covers</tabstop>
<tabstop>buttonBox</tabstop>
@ -139,7 +153,7 @@
</hints>
</connection>
<connection>
<sender>query</sender>
<sender>artist</sender>
<signal>returnPressed()</signal>
<receiver>search</receiver>
<slot>click()</slot>