Move lyrics providers to own thread

This commit is contained in:
Jonas Kvinge 2024-08-24 20:07:36 +02:00
parent 77e934beab
commit 2c0ad2fc88
26 changed files with 182 additions and 92 deletions

View File

@ -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;
}),

View File

@ -17,7 +17,8 @@
*
*/
#include <QObject>
#include <QApplication>
#include <QThread>
#include <QString>
#include <QUrl>
#include <QRegularExpression>
@ -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();

View File

@ -19,7 +19,8 @@
#include "config.h"
#include <QObject>
#include <QApplication>
#include <QThread>
#include <QByteArray>
#include <QVariant>
#include <QString>
@ -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;

View File

@ -41,12 +41,12 @@ class ChartLyricsProvider : public LyricsProvider {
explicit ChartLyricsProvider(SharedPtr<NetworkAccessManager> 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);

View File

@ -17,7 +17,8 @@
*
*/
#include <QObject>
#include <QApplication>
#include <QThread>
#include <QString>
#include <QUrl>
#include <QRegularExpression>
@ -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,}"));

View File

@ -22,7 +22,8 @@
#include <utility>
#include <memory>
#include <QObject>
#include <QApplication>
#include <QThread>
#include <QList>
#include <QByteArray>
#include <QVariant>
@ -42,6 +43,7 @@
#include <QJsonValue>
#include <QJsonParseError>
#include <QMessageBox>
#include <QMutexLocker>
#include "core/logging.h"
#include "core/shared_ptr.h"
@ -70,7 +72,7 @@ GeniusLyricsProvider::GeniusLyricsProvider(SharedPtr<NetworkAccessManager> 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<GeniusLyricsSearchContext>();
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);

View File

@ -32,6 +32,7 @@
#include <QUrl>
#include <QSslError>
#include <QJsonArray>
#include <QMutex>
#include "core/shared_ptr.h"
#include "jsonlyricsprovider.h"
@ -49,12 +50,12 @@ class GeniusLyricsProvider : public JsonLyricsProvider {
explicit GeniusLyricsProvider(SharedPtr<NetworkAccessManager> 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<GeniusLyricsSearchContext>;
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<int, SharedPtr<GeniusLyricsSearchContext>> requests_search_;

View File

@ -19,7 +19,8 @@
#include "config.h"
#include <QObject>
#include <QApplication>
#include <QThread>
#include <QByteArray>
#include <QVariant>
#include <QString>
@ -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;

View File

@ -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<NetworkAccessManager> 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:

View File

@ -19,7 +19,6 @@
#include "config.h"
#include <QObject>
#include <QByteArray>
#include <QString>
#include <QNetworkRequest>

View File

@ -17,7 +17,8 @@
*
*/
#include <QObject>
#include <QApplication>
#include <QThread>
#include <QString>
#include <QUrl>
#include <QRegularExpression>
@ -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,}"));

View File

@ -19,7 +19,8 @@
#include "config.h"
#include <QObject>
#include <QApplication>
#include <QThread>
#include <QByteArray>
#include <QVariant>
#include <QString>
@ -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;

View File

@ -42,13 +42,11 @@ class LoloLyricsProvider : public LyricsProvider {
explicit LoloLyricsProvider(SharedPtr<NetworkAccessManager> 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:

View File

@ -19,6 +19,8 @@
#include "config.h"
#include <QApplication>
#include <QThread>
#include <QByteArray>
#include <QVariant>
#include <QString>
@ -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);

View File

@ -42,14 +42,12 @@ class LyricFindLyricsProvider : public JsonLyricsProvider {
explicit LyricFindLyricsProvider(SharedPtr<NetworkAccessManager> 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);

View File

@ -22,7 +22,6 @@
#include <chrono>
#include <QtGlobal>
#include <QObject>
#include <QTimer>
#include <QString>

View File

@ -22,7 +22,6 @@
#include <algorithm>
#include <utility>
#include <QObject>
#include <QTimer>
#include <QList>
@ -54,7 +53,7 @@ void LyricsFetcherSearch::TerminateSearch() {
const QList<int> 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<LyricsProviders> 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);
}

View File

@ -19,7 +19,6 @@
#include "config.h"
#include <QObject>
#include <QString>
#include "core/shared_ptr.h"
@ -28,3 +27,11 @@
LyricsProvider::LyricsProvider(const QString &name, const bool enabled, const bool authentication_required, SharedPtr<NetworkAccessManager> 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;
}

View File

@ -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();

View File

@ -20,8 +20,8 @@
#include "config.h"
#include <utility>
#include <memory>
#include <QObject>
#include <QMutex>
#include <QList>
#include <QMap>
@ -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<NetworkAccessManager>()) {
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());

View File

@ -29,7 +29,11 @@
#include <QMap>
#include <QString>
#include <QAtomicInt>
#include <QThread>
#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<NetworkAccessManager> 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<NetworkAccessManager> network_;
QMap<LyricsProvider*, QString> lyrics_providers_;
QList<LyricsProvider*> ordered_providers_;
QMutex mutex_;

View File

@ -22,7 +22,8 @@
#include <utility>
#include <memory>
#include <QObject>
#include <QApplication>
#include <QThread>
#include <QByteArray>
#include <QVariant>
#include <QString>
@ -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<LyricsSearchContext>();
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);

View File

@ -45,9 +45,6 @@ class MusixmatchLyricsProvider : public JsonLyricsProvider, public MusixmatchPro
explicit MusixmatchLyricsProvider(SharedPtr<NetworkAccessManager> 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);

View File

@ -19,7 +19,8 @@
#include "config.h"
#include <QObject>
#include <QApplication>
#include <QThread>
#include <QVariant>
#include <QString>
#include <QUrl>
@ -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;

View File

@ -42,12 +42,12 @@ class OVHLyricsProvider : public JsonLyricsProvider {
explicit OVHLyricsProvider(SharedPtr<NetworkAccessManager> 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);

View File

@ -17,7 +17,8 @@
*
*/
#include <QObject>
#include <QApplication>
#include <QThread>
#include <QString>
#include <QUrl>
#include <QRegularExpression>
@ -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+"));