From 2bf84f77d9e4f838d7db96db7739a61255c3c82c Mon Sep 17 00:00:00 2001 From: Arnaud Bienner Date: Wed, 8 Aug 2012 23:23:49 +0200 Subject: [PATCH] Add soundcloud in the global search --- src/CMakeLists.txt | 2 + src/globalsearch/soundcloudsearchprovider.cpp | 95 +++++++++++++++++++ src/globalsearch/soundcloudsearchprovider.h | 53 +++++++++++ src/internet/soundcloudservice.cpp | 26 ++++- src/internet/soundcloudservice.h | 6 ++ 5 files changed, 179 insertions(+), 3 deletions(-) create mode 100644 src/globalsearch/soundcloudsearchprovider.cpp create mode 100644 src/globalsearch/soundcloudsearchprovider.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 21884edef..6be27725a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -152,6 +152,7 @@ set(SOURCES globalsearch/searchproviderstatuswidget.cpp globalsearch/simplesearchprovider.cpp globalsearch/somafmsearchprovider.cpp + globalsearch/soundcloudsearchprovider.cpp globalsearch/suggestionwidget.cpp globalsearch/urlsearchprovider.cpp @@ -425,6 +426,7 @@ set(HEADERS globalsearch/groovesharksearchprovider.h globalsearch/searchprovider.h globalsearch/simplesearchprovider.h + globalsearch/soundcloudsearchprovider.h globalsearch/suggestionwidget.h internet/digitallyimportedclient.h diff --git a/src/globalsearch/soundcloudsearchprovider.cpp b/src/globalsearch/soundcloudsearchprovider.cpp new file mode 100644 index 000000000..375bf8a92 --- /dev/null +++ b/src/globalsearch/soundcloudsearchprovider.cpp @@ -0,0 +1,95 @@ +/* This file is part of Clementine. + Copyright 2011, David Sansome + + Clementine is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Clementine is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Clementine. If not, see . +*/ + +#include "soundcloudsearchprovider.h" + +#include + +#include "core/application.h" +#include "core/logging.h" +#include "covers/albumcoverloader.h" +#include "internet/soundcloudservice.h" + +SoundCloudSearchProvider::SoundCloudSearchProvider(Application* app, QObject* parent) + : SearchProvider(app, parent), + service_(NULL) +{ +} + +void SoundCloudSearchProvider::Init(SoundCloudService* service) { + service_ = service; + SearchProvider::Init("SoundCloud", "soundcloud", + QIcon(":providers/soundcloud.png"), + WantsDelayedQueries | ArtIsProbablyRemote | CanShowConfig); + + connect(service_, SIGNAL(SimpleSearchResults(int, SongList)), + SLOT(SearchDone(int, SongList))); + connect(service_, SIGNAL(AlbumSearchResult(int, QList)), + SLOT(AlbumSearchResult(int, QList))); + connect(service_, SIGNAL(AlbumSongsLoaded(quint64, SongList)), + SLOT(AlbumSongsLoaded(quint64, SongList))); + + cover_loader_options_.desired_height_ = kArtHeight; + cover_loader_options_.pad_output_image_ = true; + cover_loader_options_.scale_output_image_ = true; + + connect(app_->album_cover_loader(), + SIGNAL(ImageLoaded(quint64, QImage)), + SLOT(AlbumArtLoaded(quint64, QImage))); +} + +void SoundCloudSearchProvider::SearchAsync(int id, const QString& query) { + const int service_id = service_->SimpleSearch(query); + pending_searches_[service_id] = PendingState(id, TokenizeQuery(query));; +} + +void SoundCloudSearchProvider::SearchDone(int id, const SongList& songs) { + // Map back to the original id. + const PendingState state = pending_searches_.take(id); + const int global_search_id = state.orig_id_; + + ResultList ret; + foreach (const Song& song, songs) { + Result result(this); + result.metadata_ = song; + + ret << result; + } + + emit ResultsAvailable(global_search_id, ret); + MaybeSearchFinished(global_search_id); +} + +void SoundCloudSearchProvider::MaybeSearchFinished(int id) { + if (pending_searches_.keys(PendingState(id, QStringList())).isEmpty()) { + emit SearchFinished(id); + } +} + +void SoundCloudSearchProvider::LoadArtAsync(int id, const Result& result) { + quint64 loader_id = app_->album_cover_loader()->LoadImageAsync( + cover_loader_options_, result.metadata_); + cover_loader_tasks_[loader_id] = id; +} + +void SoundCloudSearchProvider::AlbumArtLoaded(quint64 id, const QImage& image) { + if (!cover_loader_tasks_.contains(id)) { + return; + } + int original_id = cover_loader_tasks_.take(id); + emit ArtLoaded(original_id, image); +} diff --git a/src/globalsearch/soundcloudsearchprovider.h b/src/globalsearch/soundcloudsearchprovider.h new file mode 100644 index 000000000..7ef38a334 --- /dev/null +++ b/src/globalsearch/soundcloudsearchprovider.h @@ -0,0 +1,53 @@ +/* This file is part of Clementine. + Copyright 2012, David Sansome + + Clementine is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Clementine is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Clementine. If not, see . +*/ + +#ifndef SOUNDCLOUDSEARCHPROVIDER_H +#define SOUNDCLOUDSEARCHPROVIDER_H + +#include "searchprovider.h" +#include "covers/albumcoverloaderoptions.h" +#include "internet/soundcloudservice.h" + +class AlbumCoverLoader; + +class SoundCloudSearchProvider : public SearchProvider { + Q_OBJECT + + public: + explicit SoundCloudSearchProvider(Application* app, QObject* parent = 0); + void Init(SoundCloudService* service); + + // SearchProvider + void SearchAsync(int id, const QString& query); + void LoadArtAsync(int id, const Result& result); + InternetService* internet_service() { return service_; } + + private slots: + void AlbumArtLoaded(quint64 id, const QImage& image); + void SearchDone(int id, const SongList& songs); + + private: + void MaybeSearchFinished(int id); + + SoundCloudService* service_; + QMap pending_searches_; + + AlbumCoverLoaderOptions cover_loader_options_; + QMap cover_loader_tasks_; +}; + +#endif diff --git a/src/internet/soundcloudservice.cpp b/src/internet/soundcloudservice.cpp index 847162327..45a2aa7ec 100644 --- a/src/internet/soundcloudservice.cpp +++ b/src/internet/soundcloudservice.cpp @@ -38,6 +38,8 @@ #include "core/taskmanager.h" #include "core/timeconstants.h" #include "core/utilities.h" +#include "globalsearch/globalsearch.h" +#include "globalsearch/soundcloudsearchprovider.h" #include "ui/iconloader.h" const char* SoundCloudService::kApiClientId = "2add0f709fcfae1fd7a198ec7573d2d4"; @@ -67,6 +69,10 @@ SoundCloudService::SoundCloudService(Application* app, InternetModel *parent) search_delay_->setSingleShot(true); connect(search_delay_, SIGNAL(timeout()), SLOT(DoSearch())); + SoundCloudSearchProvider* search_provider = new SoundCloudSearchProvider(app_, this); + search_provider->Init(this); + app_->global_search()->AddProvider(search_provider); + connect(search_box_, SIGNAL(TextChanged(QString)), SLOT(Search(QString))); } @@ -133,12 +139,10 @@ void SoundCloudService::Search(const QString& text, bool now) { void SoundCloudService::DoSearch() { ClearSearchResults(); - qLog(Debug) << "Search"; - QList parameters; parameters << Param("q", pending_search_); QNetworkReply* reply = CreateRequest("tracks", parameters); - int id = next_pending_search_id_++; + const int id = next_pending_search_id_++; NewClosure(reply, SIGNAL(finished()), this, SLOT(SearchFinished(QNetworkReply*,int)), reply, id); @@ -162,6 +166,22 @@ void SoundCloudService::ClearSearchResults() { search_->removeRows(0, search_->rowCount()); } +int SoundCloudService::SimpleSearch(const QString& text) { + QList parameters; + parameters << Param("q", pending_search_); + QNetworkReply* reply = CreateRequest("tracks", parameters); + const int id = next_pending_search_id_++; + NewClosure(reply, SIGNAL(finished()), + this, SLOT(SimpleSearchFinished(QNetworkReply*,int)), + reply, id); + return id; +} + +void SoundCloudService::SimpleSearchFinished(QNetworkReply* reply, int id) { + SongList songs = ExtractSongs(ExtractResult(reply)); + emit SimpleSearchResults(id, songs); +} + QNetworkReply* SoundCloudService::CreateRequest( const QString& ressource_name, const QList& params) { diff --git a/src/internet/soundcloudservice.h b/src/internet/soundcloudservice.h index 10610f63c..23476e42e 100644 --- a/src/internet/soundcloudservice.h +++ b/src/internet/soundcloudservice.h @@ -42,13 +42,19 @@ class SoundCloudService : public InternetService { //void ShowContextMenu(const QPoint& global_pos); QWidget* HeaderWidget() const; + int SimpleSearch(const QString& query); + static const char* kServiceName; static const char* kSettingsGroup; + signals: + void SimpleSearchResults(int id, SongList songs); + private slots: void Search(const QString& text, bool now = false); void DoSearch(); void SearchFinished(QNetworkReply* reply, int task); + void SimpleSearchFinished(QNetworkReply* reply, int id); void Homepage();