From 2c0ad2fc88bbfed6931391fc498020f1ccd78bcd Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Sat, 24 Aug 2024 20:07:36 +0200 Subject: [PATCH] Move lyrics providers to own thread --- src/core/application.cpp | 20 ++++----- src/lyrics/azlyricscomlyricsprovider.cpp | 5 ++- src/lyrics/chartlyricsprovider.cpp | 11 +++-- src/lyrics/chartlyricsprovider.h | 6 +-- src/lyrics/elyricsnetlyricsprovider.cpp | 5 ++- src/lyrics/geniuslyricsprovider.cpp | 52 +++++++++++++++++----- src/lyrics/geniuslyricsprovider.h | 13 ++++-- src/lyrics/htmllyricsprovider.cpp | 23 +++++++--- src/lyrics/htmllyricsprovider.h | 4 +- src/lyrics/jsonlyricsprovider.cpp | 1 - src/lyrics/letraslyricsprovider.cpp | 5 ++- src/lyrics/lololyricsprovider.cpp | 11 +++-- src/lyrics/lololyricsprovider.h | 4 +- src/lyrics/lyricfindlyricsprovider.cpp | 14 +++--- src/lyrics/lyricfindlyricsprovider.h | 6 +-- src/lyrics/lyricsfetcher.cpp | 1 - src/lyrics/lyricsfetchersearch.cpp | 5 +-- src/lyrics/lyricsprovider.cpp | 9 +++- src/lyrics/lyricsprovider.h | 7 ++- src/lyrics/lyricsproviders.cpp | 17 ++++++- src/lyrics/lyricsproviders.h | 9 ++++ src/lyrics/musixmatchlyricsprovider.cpp | 18 +++++--- src/lyrics/musixmatchlyricsprovider.h | 6 +-- src/lyrics/ovhlyricsprovider.cpp | 11 +++-- src/lyrics/ovhlyricsprovider.h | 6 +-- src/lyrics/songlyricscomlyricsprovider.cpp | 5 ++- 26 files changed, 182 insertions(+), 92 deletions(-) diff --git a/src/core/application.cpp b/src/core/application.cpp index 5bb5321b8..0c6d6c5b6 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -171,16 +171,16 @@ class ApplicationImpl { lyrics_providers_([app]() { LyricsProviders *lyrics_providers = new LyricsProviders(app); // Initialize the repository of lyrics providers. - lyrics_providers->AddProvider(new GeniusLyricsProvider(app->network())); - lyrics_providers->AddProvider(new OVHLyricsProvider(app->network())); - lyrics_providers->AddProvider(new LoloLyricsProvider(app->network())); - lyrics_providers->AddProvider(new MusixmatchLyricsProvider(app->network())); - lyrics_providers->AddProvider(new ChartLyricsProvider(app->network())); - lyrics_providers->AddProvider(new SongLyricsComLyricsProvider(app->network())); - lyrics_providers->AddProvider(new AzLyricsComLyricsProvider(app->network())); - lyrics_providers->AddProvider(new ElyricsNetLyricsProvider(app->network())); - lyrics_providers->AddProvider(new LetrasLyricsProvider(app->network())); - lyrics_providers->AddProvider(new LyricFindLyricsProvider(app->network())); + lyrics_providers->AddProvider(new GeniusLyricsProvider(lyrics_providers->network())); + lyrics_providers->AddProvider(new OVHLyricsProvider(lyrics_providers->network())); + lyrics_providers->AddProvider(new LoloLyricsProvider(lyrics_providers->network())); + lyrics_providers->AddProvider(new MusixmatchLyricsProvider(lyrics_providers->network())); + lyrics_providers->AddProvider(new ChartLyricsProvider(lyrics_providers->network())); + lyrics_providers->AddProvider(new SongLyricsComLyricsProvider(lyrics_providers->network())); + lyrics_providers->AddProvider(new AzLyricsComLyricsProvider(lyrics_providers->network())); + lyrics_providers->AddProvider(new ElyricsNetLyricsProvider(lyrics_providers->network())); + lyrics_providers->AddProvider(new LetrasLyricsProvider(lyrics_providers->network())); + lyrics_providers->AddProvider(new LyricFindLyricsProvider(lyrics_providers->network())); lyrics_providers->ReloadSettings(); return lyrics_providers; }), diff --git a/src/lyrics/azlyricscomlyricsprovider.cpp b/src/lyrics/azlyricscomlyricsprovider.cpp index 3a4a05536..c18b2680f 100644 --- a/src/lyrics/azlyricscomlyricsprovider.cpp +++ b/src/lyrics/azlyricscomlyricsprovider.cpp @@ -17,7 +17,8 @@ * */ -#include +#include +#include #include #include #include @@ -46,6 +47,8 @@ QUrl AzLyricsComLyricsProvider::Url(const LyricsSearchRequest &request) { QString AzLyricsComLyricsProvider::StringFixup(const QString &text) { + Q_ASSERT(QThread::currentThread() != qApp->thread()); + static const QRegularExpression regex_words_numbers_and_dash(QStringLiteral("[^\\w0-9\\-]")); return Utilities::Transliterate(text).remove(regex_words_numbers_and_dash).toLower(); diff --git a/src/lyrics/chartlyricsprovider.cpp b/src/lyrics/chartlyricsprovider.cpp index 09c31def8..6e5e64d1f 100644 --- a/src/lyrics/chartlyricsprovider.cpp +++ b/src/lyrics/chartlyricsprovider.cpp @@ -19,7 +19,8 @@ #include "config.h" -#include +#include +#include #include #include #include @@ -54,7 +55,9 @@ ChartLyricsProvider::~ChartLyricsProvider() { } -bool ChartLyricsProvider::StartSearch(const int id, const LyricsSearchRequest &request) { +void ChartLyricsProvider::StartSearch(const int id, const LyricsSearchRequest &request) { + + Q_ASSERT(QThread::currentThread() != qApp->thread()); QUrlQuery url_query; url_query.addQueryItem(QStringLiteral("artist"), QString::fromUtf8(QUrl::toPercentEncoding(request.artist))); @@ -68,12 +71,8 @@ bool ChartLyricsProvider::StartSearch(const int id, const LyricsSearchRequest &r replies_ << reply; QObject::connect(reply, &QNetworkReply::finished, this, [this, reply, id, request]() { HandleSearchReply(reply, id, request); }); - return true; - } -void ChartLyricsProvider::CancelSearch(const int) {} - void ChartLyricsProvider::HandleSearchReply(QNetworkReply *reply, const int id, const LyricsSearchRequest &request) { if (!replies_.contains(reply)) return; diff --git a/src/lyrics/chartlyricsprovider.h b/src/lyrics/chartlyricsprovider.h index 934416695..1df3564b0 100644 --- a/src/lyrics/chartlyricsprovider.h +++ b/src/lyrics/chartlyricsprovider.h @@ -41,12 +41,12 @@ class ChartLyricsProvider : public LyricsProvider { explicit ChartLyricsProvider(SharedPtr network, QObject *parent = nullptr); ~ChartLyricsProvider() override; - bool StartSearch(const int id, const LyricsSearchRequest &request) override; - void CancelSearch(int id) override; - private: void Error(const QString &error, const QVariant &debug = QVariant()) override; + protected Q_SLOTS: + void StartSearch(const int id, const LyricsSearchRequest &request) override; + private Q_SLOTS: void HandleSearchReply(QNetworkReply *reply, const int id, const LyricsSearchRequest &request); diff --git a/src/lyrics/elyricsnetlyricsprovider.cpp b/src/lyrics/elyricsnetlyricsprovider.cpp index 80b3ecc7e..70a4a9b08 100644 --- a/src/lyrics/elyricsnetlyricsprovider.cpp +++ b/src/lyrics/elyricsnetlyricsprovider.cpp @@ -17,7 +17,8 @@ * */ -#include +#include +#include #include #include #include @@ -46,6 +47,8 @@ QUrl ElyricsNetLyricsProvider::Url(const LyricsSearchRequest &request) { QString ElyricsNetLyricsProvider::StringFixup(const QString &text) { + Q_ASSERT(QThread::currentThread() != qApp->thread()); + static const QRegularExpression regex_illegal_characters(QStringLiteral("[^\\w0-9_,&\\-\\(\\) ]")); static const QRegularExpression regex_duplicate_whitespaces(QStringLiteral(" {2,}")); diff --git a/src/lyrics/geniuslyricsprovider.cpp b/src/lyrics/geniuslyricsprovider.cpp index c4e80bcb2..fbf1673f4 100644 --- a/src/lyrics/geniuslyricsprovider.cpp +++ b/src/lyrics/geniuslyricsprovider.cpp @@ -22,7 +22,8 @@ #include #include -#include +#include +#include #include #include #include @@ -42,6 +43,7 @@ #include #include #include +#include #include "core/logging.h" #include "core/shared_ptr.h" @@ -70,7 +72,7 @@ GeniusLyricsProvider::GeniusLyricsProvider(SharedPtr netwo Settings s; s.beginGroup(kSettingsGroup); if (s.contains("access_token")) { - access_token_ = s.value("access_token").toString(); + set_access_token(s.value("access_token").toString()); } s.endGroup(); @@ -87,6 +89,27 @@ GeniusLyricsProvider::~GeniusLyricsProvider() { } +QString GeniusLyricsProvider::access_token() const { + + QMutexLocker l(&mutex_access_token_); + return access_token_; + +} + +void GeniusLyricsProvider::clear_access_token() { + + QMutexLocker l(&mutex_access_token_); + access_token_.clear(); + +} + +void GeniusLyricsProvider::set_access_token(const QString &access_token) { + + QMutexLocker l(&mutex_access_token_); + access_token_ = access_token; + +} + void GeniusLyricsProvider::Authenticate() { QUrl redirect_url(QString::fromLatin1(kOAuthRedirectUrl)); @@ -277,11 +300,13 @@ void GeniusLyricsProvider::AccessTokenRequestFinished(QNetworkReply *reply) { return; } - access_token_ = json_obj[QLatin1String("access_token")].toString(); + const QString access_token = json_obj[QLatin1String("access_token")].toString(); + + set_access_token(access_token); Settings s; s.beginGroup(kSettingsGroup); - s.setValue("access_token", access_token_); + s.setValue("access_token", access_token); s.endGroup(); qLog(Debug) << "Genius: Authentication was successful."; @@ -291,15 +316,20 @@ void GeniusLyricsProvider::AccessTokenRequestFinished(QNetworkReply *reply) { } -bool GeniusLyricsProvider::StartSearch(const int id, const LyricsSearchRequest &request) { +void GeniusLyricsProvider::StartSearch(const int id, const LyricsSearchRequest &request) { - if (access_token_.isEmpty()) return false; + Q_ASSERT(QThread::currentThread() != qApp->thread()); GeniusLyricsSearchContextPtr search = make_shared(); search->id = id; search->request = request; requests_search_.insert(id, search); + if (access_token().isEmpty()) { + EndSearch(search); + return; + } + QUrlQuery url_query; url_query.addQueryItem(QStringLiteral("q"), QString::fromLatin1(QUrl::toPercentEncoding(QStringLiteral("%1 %2").arg(request.artist, request.title)))); @@ -307,19 +337,17 @@ bool GeniusLyricsProvider::StartSearch(const int id, const LyricsSearchRequest & url.setQuery(url_query); QNetworkRequest req(url); req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy); - req.setRawHeader("Authorization", "Bearer " + access_token_.toUtf8()); + req.setRawHeader("Authorization", "Bearer " + access_token().toUtf8()); QNetworkReply *reply = network_->get(req); replies_ << reply; QObject::connect(reply, &QNetworkReply::finished, this, [this, reply, id]() { HandleSearchReply(reply, id); }); - return true; - } -void GeniusLyricsProvider::CancelSearch(const int id) { Q_UNUSED(id); } - void GeniusLyricsProvider::HandleSearchReply(QNetworkReply *reply, const int id) { + Q_ASSERT(QThread::currentThread() != qApp->thread()); + if (!replies_.contains(reply)) return; replies_.removeAll(reply); QObject::disconnect(reply, nullptr, this, nullptr); @@ -439,6 +467,8 @@ void GeniusLyricsProvider::HandleSearchReply(QNetworkReply *reply, const int id) void GeniusLyricsProvider::HandleLyricReply(QNetworkReply *reply, const int search_id, const QUrl &url) { + Q_ASSERT(QThread::currentThread() != qApp->thread()); + if (!replies_.contains(reply)) return; replies_.removeAll(reply); QObject::disconnect(reply, nullptr, this, nullptr); diff --git a/src/lyrics/geniuslyricsprovider.h b/src/lyrics/geniuslyricsprovider.h index 4075fcaf8..56dcf9f92 100644 --- a/src/lyrics/geniuslyricsprovider.h +++ b/src/lyrics/geniuslyricsprovider.h @@ -32,6 +32,7 @@ #include #include #include +#include #include "core/shared_ptr.h" #include "jsonlyricsprovider.h" @@ -49,12 +50,12 @@ class GeniusLyricsProvider : public JsonLyricsProvider { explicit GeniusLyricsProvider(SharedPtr network, QObject *parent = nullptr); ~GeniusLyricsProvider() override; - bool IsAuthenticated() const override { return !access_token_.isEmpty(); } + bool IsAuthenticated() const override { return !access_token().isEmpty(); } void Authenticate() override; - void Deauthenticate() override { access_token_.clear(); } + void Deauthenticate() override { clear_access_token(); } - bool StartSearch(const int id, const LyricsSearchRequest &request) override; - void CancelSearch(const int id) override; + protected Q_SLOTS: + void StartSearch(const int id, const LyricsSearchRequest &request) override; private: struct GeniusLyricsLyricContext { @@ -74,6 +75,9 @@ class GeniusLyricsProvider : public JsonLyricsProvider { using GeniusLyricsSearchContextPtr = SharedPtr; private: + QString access_token() const; + void clear_access_token(); + void set_access_token(const QString &access_token); void RequestAccessToken(const QUrl &url, const QUrl &redirect_url); void AuthError(const QString &error = QString(), const QVariant &debug = QVariant()); void Error(const QString &error, const QVariant &debug = QVariant()) override; @@ -90,6 +94,7 @@ class GeniusLyricsProvider : public JsonLyricsProvider { LocalRedirectServer *server_; QString code_verifier_; QString code_challenge_; + mutable QMutex mutex_access_token_; QString access_token_; QStringList login_errors_; QMap> requests_search_; diff --git a/src/lyrics/htmllyricsprovider.cpp b/src/lyrics/htmllyricsprovider.cpp index 39afbd68f..c6f340d43 100644 --- a/src/lyrics/htmllyricsprovider.cpp +++ b/src/lyrics/htmllyricsprovider.cpp @@ -19,7 +19,8 @@ #include "config.h" -#include +#include +#include #include #include #include @@ -49,10 +50,20 @@ HtmlLyricsProvider::~HtmlLyricsProvider() { } -bool HtmlLyricsProvider::StartSearch(const int id, const LyricsSearchRequest &request) { +bool HtmlLyricsProvider::StartSearchAsync(const int id, const LyricsSearchRequest &request) { if (request.artist.isEmpty() || request.title.isEmpty()) return false; + QMetaObject::invokeMethod(this, "StartSearch", Qt::QueuedConnection, Q_ARG(int, id), Q_ARG(LyricsSearchRequest, request)); + + return true; + +} + +void HtmlLyricsProvider::StartSearch(const int id, const LyricsSearchRequest &request) { + + Q_ASSERT(QThread::currentThread() != qApp->thread()); + QUrl url(Url(request)); QNetworkRequest req(url); req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy); @@ -63,14 +74,12 @@ bool HtmlLyricsProvider::StartSearch(const int id, const LyricsSearchRequest &re qLog(Debug) << name_ << "Sending request for" << url; - return true; - } -void HtmlLyricsProvider::CancelSearch(const int id) { Q_UNUSED(id); } - void HtmlLyricsProvider::HandleLyricsReply(QNetworkReply *reply, const int id, const LyricsSearchRequest &request) { + Q_ASSERT(QThread::currentThread() != qApp->thread()); + if (!replies_.contains(reply)) return; replies_.removeAll(reply); QObject::disconnect(reply, nullptr, this, nullptr); @@ -116,6 +125,8 @@ void HtmlLyricsProvider::HandleLyricsReply(QNetworkReply *reply, const int id, c QString HtmlLyricsProvider::ParseLyricsFromHTML(const QString &content, const QRegularExpression &start_tag, const QRegularExpression &end_tag, const QRegularExpression &lyrics_start, const bool multiple) { + Q_ASSERT(QThread::currentThread() != qApp->thread()); + QString lyrics; qint64 start_idx = 0; diff --git a/src/lyrics/htmllyricsprovider.h b/src/lyrics/htmllyricsprovider.h index be8a1abb6..4f77df6bc 100644 --- a/src/lyrics/htmllyricsprovider.h +++ b/src/lyrics/htmllyricsprovider.h @@ -43,8 +43,7 @@ class HtmlLyricsProvider : public LyricsProvider { explicit HtmlLyricsProvider(const QString &name, const bool enabled, const QString &start_tag, const QString &end_tag, const QString &lyrics_start, const bool multiple, SharedPtr network, QObject *parent); ~HtmlLyricsProvider(); - virtual bool StartSearch(const int id, const LyricsSearchRequest &request) override; - virtual void CancelSearch(const int id) override; + virtual bool StartSearchAsync(const int id, const LyricsSearchRequest &request) override; static QString ParseLyricsFromHTML(const QString &content, const QRegularExpression &start_tag, const QRegularExpression &end_tag, const QRegularExpression &lyrics_start, const bool multiple); @@ -53,6 +52,7 @@ class HtmlLyricsProvider : public LyricsProvider { void Error(const QString &error, const QVariant &debug = QVariant()) override; protected Q_SLOTS: + virtual void StartSearch(const int id, const LyricsSearchRequest &request) override; virtual void HandleLyricsReply(QNetworkReply *reply, const int id, const LyricsSearchRequest &request); protected: diff --git a/src/lyrics/jsonlyricsprovider.cpp b/src/lyrics/jsonlyricsprovider.cpp index 53480484d..afd7f81ae 100644 --- a/src/lyrics/jsonlyricsprovider.cpp +++ b/src/lyrics/jsonlyricsprovider.cpp @@ -19,7 +19,6 @@ #include "config.h" -#include #include #include #include diff --git a/src/lyrics/letraslyricsprovider.cpp b/src/lyrics/letraslyricsprovider.cpp index 3eb79f423..88be00eee 100644 --- a/src/lyrics/letraslyricsprovider.cpp +++ b/src/lyrics/letraslyricsprovider.cpp @@ -17,7 +17,8 @@ * */ -#include +#include +#include #include #include #include @@ -47,6 +48,8 @@ QUrl LetrasLyricsProvider::Url(const LyricsSearchRequest &request) { QString LetrasLyricsProvider::StringFixup(const QString &text) { + Q_ASSERT(QThread::currentThread() != qApp->thread()); + static const QRegularExpression regex_illegal_characters(QStringLiteral("[^\\w0-9_,&\\-\\(\\) ]")); static const QRegularExpression regex_multiple_whitespaces(QStringLiteral(" {2,}")); diff --git a/src/lyrics/lololyricsprovider.cpp b/src/lyrics/lololyricsprovider.cpp index 522815b03..8658ac9e5 100644 --- a/src/lyrics/lololyricsprovider.cpp +++ b/src/lyrics/lololyricsprovider.cpp @@ -19,7 +19,8 @@ #include "config.h" -#include +#include +#include #include #include #include @@ -54,7 +55,9 @@ LoloLyricsProvider::~LoloLyricsProvider() { } -bool LoloLyricsProvider::StartSearch(const int id, const LyricsSearchRequest &request) { +void LoloLyricsProvider::StartSearch(const int id, const LyricsSearchRequest &request) { + + Q_ASSERT(QThread::currentThread() != qApp->thread()); QUrlQuery url_query; url_query.addQueryItem(QStringLiteral("artist"), QString::fromLatin1(QUrl::toPercentEncoding(request.artist))); @@ -68,12 +71,8 @@ bool LoloLyricsProvider::StartSearch(const int id, const LyricsSearchRequest &re replies_ << reply; QObject::connect(reply, &QNetworkReply::finished, this, [this, reply, id, request]() { HandleSearchReply(reply, id, request); }); - return true; - } -void LoloLyricsProvider::CancelSearch(const int id) { Q_UNUSED(id); } - void LoloLyricsProvider::HandleSearchReply(QNetworkReply *reply, const int id, const LyricsSearchRequest &request) { if (!replies_.contains(reply)) return; diff --git a/src/lyrics/lololyricsprovider.h b/src/lyrics/lololyricsprovider.h index a0d7b2e8f..fdbcd825f 100644 --- a/src/lyrics/lololyricsprovider.h +++ b/src/lyrics/lololyricsprovider.h @@ -42,13 +42,11 @@ class LoloLyricsProvider : public LyricsProvider { explicit LoloLyricsProvider(SharedPtr network, QObject *parent = nullptr); ~LoloLyricsProvider() override; - bool StartSearch(const int id, const LyricsSearchRequest &request) override; - void CancelSearch(const int id) override; - private: void Error(const QString &error, const QVariant &debug = QVariant()) override; private Q_SLOTS: + void StartSearch(const int id, const LyricsSearchRequest &request) override; void HandleSearchReply(QNetworkReply *reply, const int id, const LyricsSearchRequest &request); private: diff --git a/src/lyrics/lyricfindlyricsprovider.cpp b/src/lyrics/lyricfindlyricsprovider.cpp index b5b699c77..25f99cef2 100644 --- a/src/lyrics/lyricfindlyricsprovider.cpp +++ b/src/lyrics/lyricfindlyricsprovider.cpp @@ -19,6 +19,8 @@ #include "config.h" +#include +#include #include #include #include @@ -62,6 +64,8 @@ QUrl LyricFindLyricsProvider::Url(const LyricsSearchRequest &request) { QString LyricFindLyricsProvider::StringFixup(const QString &text) { + Q_ASSERT(QThread::currentThread() != qApp->thread()); + static const QRegularExpression regex_illegal_characters(QStringLiteral("[^\\w0-9_\\- ]")); static const QRegularExpression regex_multiple_whitespaces(QStringLiteral(" {2,}")); @@ -74,7 +78,9 @@ QString LyricFindLyricsProvider::StringFixup(const QString &text) { } -bool LyricFindLyricsProvider::StartSearch(const int id, const LyricsSearchRequest &request) { +void LyricFindLyricsProvider::StartSearch(const int id, const LyricsSearchRequest &request) { + + Q_ASSERT(QThread::currentThread() != qApp->thread()); const QUrl url = Url(request); QNetworkRequest req(url); @@ -86,14 +92,12 @@ bool LyricFindLyricsProvider::StartSearch(const int id, const LyricsSearchReques qLog(Debug) << "LyricFind: Sending request for" << url; - return true; - } -void LyricFindLyricsProvider::CancelSearch(const int id) { Q_UNUSED(id); } - void LyricFindLyricsProvider::HandleSearchReply(QNetworkReply *reply, const int id, const LyricsSearchRequest &request) { + Q_ASSERT(QThread::currentThread() != qApp->thread()); + if (!replies_.contains(reply)) return; replies_.removeAll(reply); QObject::disconnect(reply, nullptr, this, nullptr); diff --git a/src/lyrics/lyricfindlyricsprovider.h b/src/lyrics/lyricfindlyricsprovider.h index a597b3abc..c36a69d43 100644 --- a/src/lyrics/lyricfindlyricsprovider.h +++ b/src/lyrics/lyricfindlyricsprovider.h @@ -42,14 +42,12 @@ class LyricFindLyricsProvider : public JsonLyricsProvider { explicit LyricFindLyricsProvider(SharedPtr network, QObject *parent = nullptr); ~LyricFindLyricsProvider() override; - bool StartSearch(const int id, const LyricsSearchRequest &request) override; - void CancelSearch(const int id) override; - private: static QUrl Url(const LyricsSearchRequest &request); static QString StringFixup(const QString &text); - void Error(const QString &error, const QVariant &debug = QVariant()) override; + void StartSearch(const int id, const LyricsSearchRequest &request) override; void EndSearch(const int id, const LyricsSearchRequest &request, const LyricsSearchResults &lyrics = LyricsSearchResults()); + void Error(const QString &error, const QVariant &debug = QVariant()) override; private Q_SLOTS: void HandleSearchReply(QNetworkReply *reply, const int id, const LyricsSearchRequest &request); diff --git a/src/lyrics/lyricsfetcher.cpp b/src/lyrics/lyricsfetcher.cpp index 021e1b6cf..59e3227ce 100644 --- a/src/lyrics/lyricsfetcher.cpp +++ b/src/lyrics/lyricsfetcher.cpp @@ -22,7 +22,6 @@ #include #include -#include #include #include diff --git a/src/lyrics/lyricsfetchersearch.cpp b/src/lyrics/lyricsfetchersearch.cpp index 777db68e7..114b567b5 100644 --- a/src/lyrics/lyricsfetchersearch.cpp +++ b/src/lyrics/lyricsfetchersearch.cpp @@ -22,7 +22,6 @@ #include #include -#include #include #include @@ -54,7 +53,7 @@ void LyricsFetcherSearch::TerminateSearch() { const QList keys = pending_requests_.keys(); for (const int id : keys) { - pending_requests_.take(id)->CancelSearch(id); + pending_requests_.take(id)->CancelSearchAsync(id); } AllProvidersFinished(); @@ -75,7 +74,7 @@ void LyricsFetcherSearch::Start(SharedPtr lyrics_providers) { if (!provider->is_enabled() || !provider->IsAuthenticated()) continue; QObject::connect(provider, &LyricsProvider::SearchFinished, this, &LyricsFetcherSearch::ProviderSearchFinished); const int id = lyrics_providers->NextId(); - const bool success = provider->StartSearch(id, request_); + const bool success = provider->StartSearchAsync(id, request_); if (success) { pending_requests_.insert(id, provider); } diff --git a/src/lyrics/lyricsprovider.cpp b/src/lyrics/lyricsprovider.cpp index 30ab8f1d1..5403464d3 100644 --- a/src/lyrics/lyricsprovider.cpp +++ b/src/lyrics/lyricsprovider.cpp @@ -19,7 +19,6 @@ #include "config.h" -#include #include #include "core/shared_ptr.h" @@ -28,3 +27,11 @@ LyricsProvider::LyricsProvider(const QString &name, const bool enabled, const bool authentication_required, SharedPtr network, QObject *parent) : QObject(parent), network_(network), name_(name), enabled_(enabled), order_(0), authentication_required_(authentication_required) {} + +bool LyricsProvider::StartSearchAsync(const int id, const LyricsSearchRequest &request) { + + QMetaObject::invokeMethod(this, "StartSearch", Qt::QueuedConnection, Q_ARG(int, id), Q_ARG(LyricsSearchRequest, request)); + + return true; + +} diff --git a/src/lyrics/lyricsprovider.h b/src/lyrics/lyricsprovider.h index ba2666ee7..74e169508 100644 --- a/src/lyrics/lyricsprovider.h +++ b/src/lyrics/lyricsprovider.h @@ -47,8 +47,8 @@ class LyricsProvider : public QObject { void set_enabled(const bool enabled) { enabled_ = enabled; } void set_order(const int order) { order_ = order; } - virtual bool StartSearch(const int id, const LyricsSearchRequest &request) = 0; - virtual void CancelSearch(const int id) { Q_UNUSED(id); } + virtual bool StartSearchAsync(const int id, const LyricsSearchRequest &request); + virtual void CancelSearchAsync(const int id) { Q_UNUSED(id); } virtual bool AuthenticationRequired() const { return authentication_required_; } virtual void Authenticate() {} virtual bool IsAuthenticated() const { return !authentication_required_; } @@ -56,6 +56,9 @@ class LyricsProvider : public QObject { virtual void Error(const QString &error, const QVariant &debug = QVariant()) = 0; + protected Q_SLOTS: + virtual void StartSearch(const int id, const LyricsSearchRequest &request) = 0; + Q_SIGNALS: void AuthenticationComplete(const bool success, const QStringList &errors = QStringList()); void AuthenticationSuccess(); diff --git a/src/lyrics/lyricsproviders.cpp b/src/lyrics/lyricsproviders.cpp index f3504a498..13d3ec14a 100644 --- a/src/lyrics/lyricsproviders.cpp +++ b/src/lyrics/lyricsproviders.cpp @@ -20,8 +20,8 @@ #include "config.h" #include +#include -#include #include #include #include @@ -31,6 +31,7 @@ #include "core/logging.h" #include "core/settings.h" +#include "core/networkaccessmanager.h" #include "lyricsprovider.h" #include "lyricsproviders.h" @@ -39,7 +40,14 @@ int LyricsProviders::NextOrderId = 0; -LyricsProviders::LyricsProviders(QObject *parent) : QObject(parent) {} +using std::make_shared; + +LyricsProviders::LyricsProviders(QObject *parent) : QObject(parent), thread_(new QThread(this)), network_(make_shared()) { + + network_->moveToThread(thread_); + thread_->start(); + +} LyricsProviders::~LyricsProviders() { @@ -47,6 +55,9 @@ LyricsProviders::~LyricsProviders() { delete lyrics_providers_.firstKey(); } + thread_->quit(); + thread_->wait(1000); + } void LyricsProviders::ReloadSettings() { @@ -96,6 +107,8 @@ LyricsProvider *LyricsProviders::ProviderByName(const QString &name) const { void LyricsProviders::AddProvider(LyricsProvider *provider) { + provider->moveToThread(thread_); + { QMutexLocker locker(&mutex_); lyrics_providers_.insert(provider, provider->name()); diff --git a/src/lyrics/lyricsproviders.h b/src/lyrics/lyricsproviders.h index 2a09d21dc..27906523e 100644 --- a/src/lyrics/lyricsproviders.h +++ b/src/lyrics/lyricsproviders.h @@ -29,7 +29,11 @@ #include #include #include +#include +#include "core/shared_ptr.h" + +class NetworkAccessManager; class LyricsProvider; class LyricsProviders : public QObject { @@ -39,6 +43,8 @@ class LyricsProviders : public QObject { explicit LyricsProviders(QObject *parent = nullptr); ~LyricsProviders() override; + SharedPtr network() const { return network_; } + void ReloadSettings(); LyricsProvider *ProviderByName(const QString &name) const; @@ -56,6 +62,9 @@ class LyricsProviders : public QObject { static int NextOrderId; + QThread *thread_; + SharedPtr network_; + QMap lyrics_providers_; QList ordered_providers_; QMutex mutex_; diff --git a/src/lyrics/musixmatchlyricsprovider.cpp b/src/lyrics/musixmatchlyricsprovider.cpp index 69c153cbc..af97aebe5 100644 --- a/src/lyrics/musixmatchlyricsprovider.cpp +++ b/src/lyrics/musixmatchlyricsprovider.cpp @@ -22,7 +22,8 @@ #include #include -#include +#include +#include #include #include #include @@ -59,7 +60,9 @@ MusixmatchLyricsProvider::~MusixmatchLyricsProvider() { } -bool MusixmatchLyricsProvider::StartSearch(const int id, const LyricsSearchRequest &request) { +void MusixmatchLyricsProvider::StartSearch(const int id, const LyricsSearchRequest &request) { + + Q_ASSERT(QThread::currentThread() != qApp->thread()); LyricsSearchContextPtr search = make_shared(); search->id = id; @@ -67,15 +70,14 @@ bool MusixmatchLyricsProvider::StartSearch(const int id, const LyricsSearchReque requests_search_.append(search); if (use_api_) { - return SendSearchRequest(search); + SendSearchRequest(search); + return; } - return CreateLyricsRequest(search); + CreateLyricsRequest(search); } -void MusixmatchLyricsProvider::CancelSearch(const int id) { Q_UNUSED(id); } - bool MusixmatchLyricsProvider::SendSearchRequest(LyricsSearchContextPtr search) { QUrlQuery url_query; @@ -100,6 +102,8 @@ bool MusixmatchLyricsProvider::SendSearchRequest(LyricsSearchContextPtr search) void MusixmatchLyricsProvider::HandleSearchReply(QNetworkReply *reply, LyricsSearchContextPtr search) { + Q_ASSERT(QThread::currentThread() != qApp->thread()); + if (!replies_.contains(reply)) return; replies_.removeAll(reply); QObject::disconnect(reply, nullptr, this, nullptr); @@ -274,6 +278,8 @@ bool MusixmatchLyricsProvider::SendLyricsRequest(LyricsSearchContextPtr search, void MusixmatchLyricsProvider::HandleLyricsReply(QNetworkReply *reply, LyricsSearchContextPtr search, const QUrl &url) { + Q_ASSERT(QThread::currentThread() != qApp->thread()); + if (!replies_.contains(reply)) return; replies_.removeAll(reply); QObject::disconnect(reply, nullptr, this, nullptr); diff --git a/src/lyrics/musixmatchlyricsprovider.h b/src/lyrics/musixmatchlyricsprovider.h index 4f26520b3..f3c03711e 100644 --- a/src/lyrics/musixmatchlyricsprovider.h +++ b/src/lyrics/musixmatchlyricsprovider.h @@ -45,9 +45,6 @@ class MusixmatchLyricsProvider : public JsonLyricsProvider, public MusixmatchPro explicit MusixmatchLyricsProvider(SharedPtr network, QObject *parent = nullptr); ~MusixmatchLyricsProvider() override; - bool StartSearch(const int id, const LyricsSearchRequest &request) override; - void CancelSearch(const int id) override; - private: struct LyricsSearchContext { explicit LyricsSearchContext() : id(-1) {} @@ -66,6 +63,9 @@ class MusixmatchLyricsProvider : public JsonLyricsProvider, public MusixmatchPro void EndSearch(LyricsSearchContextPtr search, const QUrl &url = QUrl()); void Error(const QString &error, const QVariant &debug = QVariant()) override; + protected Q_SLOTS: + void StartSearch(const int id, const LyricsSearchRequest &request) override; + private Q_SLOTS: void HandleSearchReply(QNetworkReply *reply, MusixmatchLyricsProvider::LyricsSearchContextPtr search); void HandleLyricsReply(QNetworkReply *reply, MusixmatchLyricsProvider::LyricsSearchContextPtr search, const QUrl &url); diff --git a/src/lyrics/ovhlyricsprovider.cpp b/src/lyrics/ovhlyricsprovider.cpp index ac90d6ce0..6d5cbf242 100644 --- a/src/lyrics/ovhlyricsprovider.cpp +++ b/src/lyrics/ovhlyricsprovider.cpp @@ -19,7 +19,8 @@ #include "config.h" -#include +#include +#include #include #include #include @@ -53,7 +54,9 @@ OVHLyricsProvider::~OVHLyricsProvider() { } -bool OVHLyricsProvider::StartSearch(const int id, const LyricsSearchRequest &request) { +void OVHLyricsProvider::StartSearch(const int id, const LyricsSearchRequest &request) { + + Q_ASSERT(QThread::currentThread() != qApp->thread()); QUrl url(QString::fromLatin1(kUrlSearch) + QString::fromLatin1(QUrl::toPercentEncoding(request.artist)) + QLatin1Char('/') + QString::fromLatin1(QUrl::toPercentEncoding(request.title))); QNetworkRequest req(url); @@ -62,12 +65,8 @@ bool OVHLyricsProvider::StartSearch(const int id, const LyricsSearchRequest &req replies_ << reply; QObject::connect(reply, &QNetworkReply::finished, this, [this, reply, id, request]() { HandleSearchReply(reply, id, request); }); - return true; - } -void OVHLyricsProvider::CancelSearch(const int id) { Q_UNUSED(id); } - void OVHLyricsProvider::HandleSearchReply(QNetworkReply *reply, const int id, const LyricsSearchRequest &request) { if (!replies_.contains(reply)) return; diff --git a/src/lyrics/ovhlyricsprovider.h b/src/lyrics/ovhlyricsprovider.h index 3bbce06c8..6dea61cbc 100644 --- a/src/lyrics/ovhlyricsprovider.h +++ b/src/lyrics/ovhlyricsprovider.h @@ -42,12 +42,12 @@ class OVHLyricsProvider : public JsonLyricsProvider { explicit OVHLyricsProvider(SharedPtr network, QObject *parent = nullptr); ~OVHLyricsProvider() override; - bool StartSearch(const int id, const LyricsSearchRequest &request) override; - void CancelSearch(const int id) override; - private: void Error(const QString &error, const QVariant &debug = QVariant()) override; + protected Q_SLOTS: + void StartSearch(const int id, const LyricsSearchRequest &request) override; + private Q_SLOTS: void HandleSearchReply(QNetworkReply *reply, const int id, const LyricsSearchRequest &request); diff --git a/src/lyrics/songlyricscomlyricsprovider.cpp b/src/lyrics/songlyricscomlyricsprovider.cpp index e6d5bb78a..9c7c1a75e 100644 --- a/src/lyrics/songlyricscomlyricsprovider.cpp +++ b/src/lyrics/songlyricscomlyricsprovider.cpp @@ -17,7 +17,8 @@ * */ -#include +#include +#include #include #include #include @@ -45,6 +46,8 @@ QUrl SongLyricsComLyricsProvider::Url(const LyricsSearchRequest &request) { QString SongLyricsComLyricsProvider::StringFixup(QString text) { + Q_ASSERT(QThread::currentThread() != qApp->thread()); + static const QRegularExpression regex_illegal_characters(QStringLiteral("[^\\w0-9\\- ]")); static const QRegularExpression regex_multiple_whitespaces(QStringLiteral(" {2,}")); static const QRegularExpression regex_multiple_dashes(QStringLiteral("(-)\\1+"));