diff --git a/src/covermanager/albumcoverfetchersearch.cpp b/src/covermanager/albumcoverfetchersearch.cpp index 30bba4a47..0382bc5e6 100644 --- a/src/covermanager/albumcoverfetchersearch.cpp +++ b/src/covermanager/albumcoverfetchersearch.cpp @@ -211,7 +211,7 @@ void AlbumCoverFetcherSearch::FetchMoreImages() { void AlbumCoverFetcherSearch::ProviderCoverFetchFinished(QNetworkReply *reply) { - disconnect(reply, &QNetworkReply::finished, this, nullptr); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); if (!pending_image_loads_.contains(reply)) return; diff --git a/src/covermanager/deezercoverprovider.cpp b/src/covermanager/deezercoverprovider.cpp index d712ce7e4..fe2d1ad15 100644 --- a/src/covermanager/deezercoverprovider.cpp +++ b/src/covermanager/deezercoverprovider.cpp @@ -53,6 +53,17 @@ const int DeezerCoverProvider::kLimit = 10; DeezerCoverProvider::DeezerCoverProvider(Application *app, QObject *parent): JsonCoverProvider("Deezer", true, false, 2.0, true, true, app, parent), network_(new NetworkAccessManager(this)) {} +DeezerCoverProvider::~DeezerCoverProvider() { + + while (!replies_.isEmpty()) { + QNetworkReply *reply = replies_.takeFirst(); + disconnect(reply, nullptr, this, nullptr); + reply->abort(); + reply->deleteLater(); + } + +} + bool DeezerCoverProvider::StartSearch(const QString &artist, const QString &album, const QString &title, const int id) { typedef QPair Param; @@ -83,6 +94,7 @@ bool DeezerCoverProvider::StartSearch(const QString &artist, const QString &albu QNetworkRequest req(url); req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); QNetworkReply *reply = network_->get(req); + replies_ << reply; connect(reply, &QNetworkReply::finished, [=] { HandleSearchReply(reply, id); }); return true; @@ -174,6 +186,9 @@ QJsonValue DeezerCoverProvider::ExtractData(const QByteArray &data) { void DeezerCoverProvider::HandleSearchReply(QNetworkReply *reply, const int id) { + if (!replies_.contains(reply)) return; + replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); CoverSearchResults results; diff --git a/src/covermanager/deezercoverprovider.h b/src/covermanager/deezercoverprovider.h index 5af5f929a..2a386dd7e 100644 --- a/src/covermanager/deezercoverprovider.h +++ b/src/covermanager/deezercoverprovider.h @@ -23,6 +23,7 @@ #include "config.h" #include +#include #include #include #include @@ -40,6 +41,8 @@ class DeezerCoverProvider : public JsonCoverProvider { public: explicit DeezerCoverProvider(Application *app, QObject *parent = nullptr); + ~DeezerCoverProvider(); + bool StartSearch(const QString &artist, const QString &album, const QString &title, const int id); void CancelSearch(const int id); @@ -56,6 +59,7 @@ class DeezerCoverProvider : public JsonCoverProvider { static const int kLimit; QNetworkAccessManager *network_; + QList replies_; }; diff --git a/src/covermanager/discogscoverprovider.cpp b/src/covermanager/discogscoverprovider.cpp index f9e7b58d1..edcb42fe8 100644 --- a/src/covermanager/discogscoverprovider.cpp +++ b/src/covermanager/discogscoverprovider.cpp @@ -61,7 +61,16 @@ const char *DiscogsCoverProvider::kSecretKeyB64 = "ZkFIcmlaSER4aHhRSlF2U3d0bm5ZV DiscogsCoverProvider::DiscogsCoverProvider(Application *app, QObject *parent) : JsonCoverProvider("Discogs", false, false, 0.0, false, false, app, parent), network_(new NetworkAccessManager(this)) {} DiscogsCoverProvider::~DiscogsCoverProvider() { + + while (!replies_.isEmpty()) { + QNetworkReply *reply = replies_.takeFirst(); + disconnect(reply, nullptr, this, nullptr); + reply->abort(); + reply->deleteLater(); + } + requests_search_.clear(); + } bool DiscogsCoverProvider::StartSearch(const QString &artist, const QString &album, const QString &title, const int id) { @@ -124,6 +133,7 @@ QNetworkReply *DiscogsCoverProvider::CreateRequest(QUrl url, const ParamList &pa QNetworkRequest req(url); req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); QNetworkReply *reply = network_->get(req); + replies_ << reply; return reply; @@ -173,6 +183,9 @@ QByteArray DiscogsCoverProvider::GetReplyData(QNetworkReply *reply) { void DiscogsCoverProvider::HandleSearchReply(QNetworkReply *reply, const int id) { + if (!replies_.contains(reply)) return; + replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); if (!requests_search_.contains(id)) { @@ -258,6 +271,9 @@ void DiscogsCoverProvider::StartRelease(std::shared_ptrdeleteLater(); if (!requests_search_.contains(search_id)) { diff --git a/src/covermanager/discogscoverprovider.h b/src/covermanager/discogscoverprovider.h index 5ab6e3cd7..933e1366f 100644 --- a/src/covermanager/discogscoverprovider.h +++ b/src/covermanager/discogscoverprovider.h @@ -28,6 +28,8 @@ #include #include +#include +#include #include #include #include @@ -88,6 +90,7 @@ class DiscogsCoverProvider : public JsonCoverProvider { QNetworkAccessManager *network_; QMap> requests_search_; + QList replies_; }; diff --git a/src/covermanager/lastfmcoverprovider.cpp b/src/covermanager/lastfmcoverprovider.cpp index c249f8e64..9492a47f7 100644 --- a/src/covermanager/lastfmcoverprovider.cpp +++ b/src/covermanager/lastfmcoverprovider.cpp @@ -55,6 +55,17 @@ const char *LastFmCoverProvider::kSecret = "80fd738f49596e9709b1bf9319c444a8"; LastFmCoverProvider::LastFmCoverProvider(Application *app, QObject *parent) : JsonCoverProvider("Last.fm", true, false, 1.0, true, false, app, parent), network_(new NetworkAccessManager(this)) {} +LastFmCoverProvider::~LastFmCoverProvider() { + + while (!replies_.isEmpty()) { + QNetworkReply *reply = replies_.takeFirst(); + disconnect(reply, nullptr, this, nullptr); + reply->abort(); + reply->deleteLater(); + } + +} + bool LastFmCoverProvider::StartSearch(const QString &artist, const QString &album, const QString &title, const int id) { typedef QPair Param; @@ -100,6 +111,7 @@ bool LastFmCoverProvider::StartSearch(const QString &artist, const QString &albu req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); QNetworkReply *reply = network_->post(req, url_query.toString(QUrl::FullyEncoded).toUtf8()); + replies_ << reply; connect(reply, &QNetworkReply::finished, [=] { QueryFinished(reply, id, type); }); return true; @@ -108,6 +120,9 @@ bool LastFmCoverProvider::StartSearch(const QString &artist, const QString &albu void LastFmCoverProvider::QueryFinished(QNetworkReply *reply, const int id, const QString &type) { + if (!replies_.contains(reply)) return; + replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); CoverSearchResults results; @@ -305,7 +320,7 @@ QByteArray LastFmCoverProvider::GetReplyData(QNetworkReply *reply) { void LastFmCoverProvider::Error(const QString &error, const QVariant &debug) { - qLog(Error) << "LastFm:" << error; + qLog(Error) << "Last.fm:" << error; if (debug.isValid()) qLog(Debug) << debug; } diff --git a/src/covermanager/lastfmcoverprovider.h b/src/covermanager/lastfmcoverprovider.h index 4581c6e87..60ceff3a1 100644 --- a/src/covermanager/lastfmcoverprovider.h +++ b/src/covermanager/lastfmcoverprovider.h @@ -23,6 +23,7 @@ #include "config.h" #include +#include #include #include #include @@ -39,6 +40,8 @@ class LastFmCoverProvider : public JsonCoverProvider { public: explicit LastFmCoverProvider(Application *app, QObject *parent = nullptr); + ~LastFmCoverProvider(); + bool StartSearch(const QString &artist, const QString &album, const QString &title, const int id); private slots: @@ -63,6 +66,7 @@ class LastFmCoverProvider : public JsonCoverProvider { static const char *kSecret; QNetworkAccessManager *network_; + QList replies_; }; diff --git a/src/covermanager/musicbrainzcoverprovider.cpp b/src/covermanager/musicbrainzcoverprovider.cpp index 9b83d61bd..cc501b725 100644 --- a/src/covermanager/musicbrainzcoverprovider.cpp +++ b/src/covermanager/musicbrainzcoverprovider.cpp @@ -50,6 +50,17 @@ const int MusicbrainzCoverProvider::kLimit = 8; MusicbrainzCoverProvider::MusicbrainzCoverProvider(Application *app, QObject *parent): JsonCoverProvider("MusicBrainz", true, false, 1.5, true, false, app, parent), network_(new NetworkAccessManager(this)) {} +MusicbrainzCoverProvider::~MusicbrainzCoverProvider() { + + while (!replies_.isEmpty()) { + QNetworkReply *reply = replies_.takeFirst(); + disconnect(reply, nullptr, this, nullptr); + reply->abort(); + reply->deleteLater(); + } + +} + bool MusicbrainzCoverProvider::StartSearch(const QString &artist, const QString &album, const QString &title, const int id) { Q_UNUSED(title); @@ -66,6 +77,7 @@ bool MusicbrainzCoverProvider::StartSearch(const QString &artist, const QString QNetworkRequest req(url); req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); QNetworkReply *reply = network_->get(req); + replies_ << reply; connect(reply, &QNetworkReply::finished, [=] { HandleSearchReply(reply, id); }); return true; @@ -74,6 +86,9 @@ bool MusicbrainzCoverProvider::StartSearch(const QString &artist, const QString void MusicbrainzCoverProvider::HandleSearchReply(QNetworkReply *reply, const int search_id) { + if (!replies_.contains(reply)) return; + replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); CoverSearchResults results; diff --git a/src/covermanager/musicbrainzcoverprovider.h b/src/covermanager/musicbrainzcoverprovider.h index 4d76c9afd..1bf8fb3f5 100644 --- a/src/covermanager/musicbrainzcoverprovider.h +++ b/src/covermanager/musicbrainzcoverprovider.h @@ -23,6 +23,7 @@ #include "config.h" #include +#include #include #include #include @@ -38,6 +39,7 @@ class MusicbrainzCoverProvider : public JsonCoverProvider { Q_OBJECT public: explicit MusicbrainzCoverProvider(Application *app, QObject *parent = nullptr); + ~MusicbrainzCoverProvider(); bool StartSearch(const QString &artist, const QString &album, const QString &title, const int id); @@ -54,6 +56,7 @@ class MusicbrainzCoverProvider : public JsonCoverProvider { static const int kLimit; QNetworkAccessManager *network_; + QList replies_; }; diff --git a/src/covermanager/musixmatchcoverprovider.cpp b/src/covermanager/musixmatchcoverprovider.cpp index 7a8a7a6f9..3fe857f84 100644 --- a/src/covermanager/musixmatchcoverprovider.cpp +++ b/src/covermanager/musixmatchcoverprovider.cpp @@ -42,6 +42,17 @@ MusixmatchCoverProvider::MusixmatchCoverProvider(Application *app, QObject *parent): JsonCoverProvider("Musixmatch", true, false, 1.0, true, false, app, parent), network_(new NetworkAccessManager(this)) {} +MusixmatchCoverProvider::~MusixmatchCoverProvider() { + + while (!replies_.isEmpty()) { + QNetworkReply *reply = replies_.takeFirst(); + disconnect(reply, nullptr, this, nullptr); + reply->abort(); + reply->deleteLater(); + } + +} + bool MusixmatchCoverProvider::StartSearch(const QString &artist, const QString &album, const QString &title, const int id) { Q_UNUSED(title); @@ -69,6 +80,7 @@ bool MusixmatchCoverProvider::StartSearch(const QString &artist, const QString & QNetworkRequest req(url); req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); QNetworkReply *reply = network_->get(req); + replies_ << reply; connect(reply, &QNetworkReply::finished, [=] { HandleSearchReply(reply, id, artist, album); }); //qLog(Debug) << "Musixmatch: Sending request for" << artist_stripped << album_stripped << url; @@ -81,6 +93,9 @@ void MusixmatchCoverProvider::CancelSearch(const int id) { Q_UNUSED(id); } void MusixmatchCoverProvider::HandleSearchReply(QNetworkReply *reply, const int id, const QString &artist, const QString &album) { + if (!replies_.contains(reply)) return; + replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); CoverSearchResults results; diff --git a/src/covermanager/musixmatchcoverprovider.h b/src/covermanager/musixmatchcoverprovider.h index ab0321896..8c39cd4bc 100644 --- a/src/covermanager/musixmatchcoverprovider.h +++ b/src/covermanager/musixmatchcoverprovider.h @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -37,6 +38,7 @@ class MusixmatchCoverProvider : public JsonCoverProvider { public: explicit MusixmatchCoverProvider(Application *app, QObject *parent = nullptr); + ~MusixmatchCoverProvider(); bool StartSearch(const QString &artist, const QString &album, const QString &title, const int id); void CancelSearch(const int id); @@ -49,6 +51,7 @@ class MusixmatchCoverProvider : public JsonCoverProvider { private: QNetworkAccessManager *network_; + QList replies_; }; diff --git a/src/covermanager/qobuzcoverprovider.cpp b/src/covermanager/qobuzcoverprovider.cpp index 91786352e..3b5bc9449 100644 --- a/src/covermanager/qobuzcoverprovider.cpp +++ b/src/covermanager/qobuzcoverprovider.cpp @@ -53,6 +53,17 @@ const int QobuzCoverProvider::kLimit = 10; QobuzCoverProvider::QobuzCoverProvider(Application *app, QObject *parent) : JsonCoverProvider("Qobuz", true, false, 2.0, true, true, app, parent), network_(new NetworkAccessManager(this)) {} +QobuzCoverProvider::~QobuzCoverProvider() { + + while (!replies_.isEmpty()) { + QNetworkReply *reply = replies_.takeFirst(); + disconnect(reply, nullptr, this, nullptr); + reply->abort(); + reply->deleteLater(); + } + +} + bool QobuzCoverProvider::StartSearch(const QString &artist, const QString &album, const QString &title, const int id) { typedef QPair Param; @@ -88,6 +99,7 @@ bool QobuzCoverProvider::StartSearch(const QString &artist, const QString &album req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); req.setRawHeader("X-App-Id", kAppID); QNetworkReply *reply = network_->get(req); + replies_ << reply; connect(reply, &QNetworkReply::finished, [=] { HandleSearchReply(reply, id); }); return true; @@ -142,6 +154,9 @@ QByteArray QobuzCoverProvider::GetReplyData(QNetworkReply *reply) { void QobuzCoverProvider::HandleSearchReply(QNetworkReply *reply, const int id) { + if (!replies_.contains(reply)) return; + replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); CoverSearchResults results; diff --git a/src/covermanager/qobuzcoverprovider.h b/src/covermanager/qobuzcoverprovider.h index e6f8325b3..8232be563 100644 --- a/src/covermanager/qobuzcoverprovider.h +++ b/src/covermanager/qobuzcoverprovider.h @@ -23,6 +23,7 @@ #include "config.h" #include +#include #include #include #include @@ -39,6 +40,8 @@ class QobuzCoverProvider : public JsonCoverProvider { public: explicit QobuzCoverProvider(Application *app, QObject *parent = nullptr); + ~QobuzCoverProvider(); + bool StartSearch(const QString &artist, const QString &album, const QString &title, const int id); void CancelSearch(const int id); @@ -55,6 +58,7 @@ class QobuzCoverProvider : public JsonCoverProvider { static const int kLimit; QNetworkAccessManager *network_; + QList replies_; }; diff --git a/src/covermanager/spotifycoverprovider.cpp b/src/covermanager/spotifycoverprovider.cpp index 9f5ff8fb0..cc01479c0 100644 --- a/src/covermanager/spotifycoverprovider.cpp +++ b/src/covermanager/spotifycoverprovider.cpp @@ -85,6 +85,17 @@ SpotifyCoverProvider::SpotifyCoverProvider(Application *app, QObject *parent) : } +SpotifyCoverProvider::~SpotifyCoverProvider() { + + while (!replies_.isEmpty()) { + QNetworkReply *reply = replies_.takeFirst(); + disconnect(reply, nullptr, this, nullptr); + reply->abort(); + reply->deleteLater(); + } + +} + void SpotifyCoverProvider::Authenticate() { QUrl redirect_url(kOAuthRedirectUrl); @@ -230,6 +241,7 @@ void SpotifyCoverProvider::RequestAccessToken(const QString code, const QUrl red QByteArray query = url_query.toString(QUrl::FullyEncoded).toUtf8(); QNetworkReply *reply = network_->post(req, query); + replies_ << reply; connect(reply, SIGNAL(sslErrors(QList)), this, SLOT(HandleLoginSSLErrors(QList))); connect(reply, &QNetworkReply::finished, [=] { AccessTokenRequestFinished(reply); }); @@ -245,6 +257,9 @@ void SpotifyCoverProvider::HandleLoginSSLErrors(QList ssl_errors) { void SpotifyCoverProvider::AccessTokenRequestFinished(QNetworkReply *reply) { + if (!replies_.contains(reply)) return; + replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); if (reply->error() != QNetworkReply::NoError || reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() != 200) { @@ -372,6 +387,7 @@ bool SpotifyCoverProvider::StartSearch(const QString &artist, const QString &alb req.setRawHeader("Authorization", "Bearer " + access_token_.toUtf8()); QNetworkReply *reply = network_->get(req); + replies_ << reply; connect(reply, &QNetworkReply::finished, [=] { HandleSearchReply(reply, id, extract); }); return true; @@ -429,6 +445,9 @@ QByteArray SpotifyCoverProvider::GetReplyData(QNetworkReply *reply) { void SpotifyCoverProvider::HandleSearchReply(QNetworkReply *reply, const int id, const QString &extract) { + if (!replies_.contains(reply)) return; + replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); QByteArray data = GetReplyData(reply); diff --git a/src/covermanager/spotifycoverprovider.h b/src/covermanager/spotifycoverprovider.h index 98afb0b9a..5f818076d 100644 --- a/src/covermanager/spotifycoverprovider.h +++ b/src/covermanager/spotifycoverprovider.h @@ -46,6 +46,8 @@ class SpotifyCoverProvider : public JsonCoverProvider { public: explicit SpotifyCoverProvider(Application *app, QObject *parent = nullptr); + ~SpotifyCoverProvider(); + bool StartSearch(const QString &artist, const QString &album, const QString &title, const int id); void CancelSearch(const int id); @@ -88,6 +90,7 @@ class SpotifyCoverProvider : public JsonCoverProvider { quint64 expires_in_; quint64 login_time_; QTimer refresh_login_timer_; + QList replies_; }; diff --git a/src/covermanager/tidalcoverprovider.cpp b/src/covermanager/tidalcoverprovider.cpp index 8eb436f4b..278f21029 100644 --- a/src/covermanager/tidalcoverprovider.cpp +++ b/src/covermanager/tidalcoverprovider.cpp @@ -59,6 +59,17 @@ TidalCoverProvider::TidalCoverProvider(Application *app, QObject *parent) : } +TidalCoverProvider::~TidalCoverProvider() { + + while (!replies_.isEmpty()) { + QNetworkReply *reply = replies_.takeFirst(); + disconnect(reply, nullptr, this, nullptr); + reply->abort(); + reply->deleteLater(); + } + +} + bool TidalCoverProvider::StartSearch(const QString &artist, const QString &album, const QString &title, const int id) { typedef QPair Param; @@ -95,6 +106,7 @@ bool TidalCoverProvider::StartSearch(const QString &artist, const QString &album if (!service_->session_id().isEmpty()) req.setRawHeader("X-Tidal-SessionId", service_->session_id().toUtf8()); QNetworkReply *reply = network_->get(req); + replies_ << reply; connect(reply, &QNetworkReply::finished, [=] { HandleSearchReply(reply, id); }); return true; @@ -154,6 +166,9 @@ QByteArray TidalCoverProvider::GetReplyData(QNetworkReply *reply) { void TidalCoverProvider::HandleSearchReply(QNetworkReply *reply, const int id) { + if (!replies_.contains(reply)) return; + replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); CoverSearchResults results; diff --git a/src/covermanager/tidalcoverprovider.h b/src/covermanager/tidalcoverprovider.h index bc8297cd5..bc960c303 100644 --- a/src/covermanager/tidalcoverprovider.h +++ b/src/covermanager/tidalcoverprovider.h @@ -44,6 +44,8 @@ class TidalCoverProvider : public JsonCoverProvider { public: explicit TidalCoverProvider(Application *app, QObject *parent = nullptr); + ~TidalCoverProvider(); + bool StartSearch(const QString &artist, const QString &album, const QString &title, const int id); void CancelSearch(const int id); @@ -64,6 +66,7 @@ class TidalCoverProvider : public JsonCoverProvider { TidalService *service_; QNetworkAccessManager *network_; + QList replies_; }; diff --git a/src/lyrics/auddlyricsprovider.cpp b/src/lyrics/auddlyricsprovider.cpp index 97687dd40..cfabe2e26 100644 --- a/src/lyrics/auddlyricsprovider.cpp +++ b/src/lyrics/auddlyricsprovider.cpp @@ -48,6 +48,17 @@ const int AuddLyricsProvider::kMaxLength = 6000; AuddLyricsProvider::AuddLyricsProvider(QObject *parent) : JsonLyricsProvider("AudD", true, false, parent), network_(new NetworkAccessManager(this)) {} +AuddLyricsProvider::~AuddLyricsProvider() { + + while (!replies_.isEmpty()) { + QNetworkReply *reply = replies_.takeFirst(); + disconnect(reply, nullptr, this, nullptr); + reply->abort(); + reply->deleteLater(); + } + +} + bool AuddLyricsProvider::StartSearch(const QString &artist, const QString &album, const QString &title, const quint64 id) { Q_UNUSED(album); @@ -65,6 +76,7 @@ bool AuddLyricsProvider::StartSearch(const QString &artist, const QString &album QNetworkRequest req(url); req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); QNetworkReply *reply = network_->get(req); + replies_ << reply; connect(reply, &QNetworkReply::finished, [=] { HandleSearchReply(reply, id, artist, title); }); //qLog(Debug) << "AudDLyrics: Sending request for" << url; @@ -77,6 +89,9 @@ void AuddLyricsProvider::CancelSearch(const quint64 id) { Q_UNUSED(id); } void AuddLyricsProvider::HandleSearchReply(QNetworkReply *reply, const quint64 id, const QString &artist, const QString &title) { + if (!replies_.contains(reply)) return; + replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); QJsonArray json_result = ExtractResult(reply, artist, title); diff --git a/src/lyrics/auddlyricsprovider.h b/src/lyrics/auddlyricsprovider.h index 39c484718..3b933f717 100644 --- a/src/lyrics/auddlyricsprovider.h +++ b/src/lyrics/auddlyricsprovider.h @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -39,10 +40,15 @@ class AuddLyricsProvider : public JsonLyricsProvider { public: explicit AuddLyricsProvider(QObject *parent = nullptr); + ~AuddLyricsProvider(); bool StartSearch(const QString &artist, const QString &album, const QString &title, quint64 id); void CancelSearch(const quint64 id); + private: + void Error(const QString &error, const QVariant &debug = QVariant()); + QJsonArray ExtractResult(QNetworkReply *reply, const QString &artist, const QString &title); + private slots: void HandleSearchReply(QNetworkReply *reply, const quint64 id, const QString &artist, const QString &title); @@ -51,9 +57,7 @@ class AuddLyricsProvider : public JsonLyricsProvider { static const char *kAPITokenB64; static const int kMaxLength; QNetworkAccessManager *network_; - void Error(const QString &error, const QVariant &debug = QVariant()); - - QJsonArray ExtractResult(QNetworkReply *reply, const QString &artist, const QString &title); + QList replies_; }; diff --git a/src/lyrics/chartlyricsprovider.cpp b/src/lyrics/chartlyricsprovider.cpp index d5101614d..c9974fd21 100644 --- a/src/lyrics/chartlyricsprovider.cpp +++ b/src/lyrics/chartlyricsprovider.cpp @@ -32,7 +32,6 @@ #include #include -#include "core/closure.h" #include "core/logging.h" #include "core/network.h" #include "core/utilities.h" @@ -44,6 +43,17 @@ const char *ChartLyricsProvider::kUrlSearch = "http://api.chartlyrics.com/apiv1. ChartLyricsProvider::ChartLyricsProvider(QObject *parent) : LyricsProvider("ChartLyrics", false, false, parent), network_(new NetworkAccessManager(this)) {} +ChartLyricsProvider::~ChartLyricsProvider() { + + while (!replies_.isEmpty()) { + QNetworkReply *reply = replies_.takeFirst(); + disconnect(reply, nullptr, this, nullptr); + reply->abort(); + reply->deleteLater(); + } + +} + bool ChartLyricsProvider::StartSearch(const QString &artist, const QString&, const QString &title, const quint64 id) { const ParamList params = ParamList() << Param("artist", artist) @@ -57,7 +67,8 @@ bool ChartLyricsProvider::StartSearch(const QString &artist, const QString&, con QUrl url(kUrlSearch); url.setQuery(url_query); QNetworkReply *reply = network_->get(QNetworkRequest(url)); - NewClosure(reply, SIGNAL(finished()), this, SLOT(HandleSearchReply(QNetworkReply*, const quint64, const QString&, const QString&)), reply, id, artist, title); + replies_ << reply; + connect(reply, &QNetworkReply::finished, [=] { HandleSearchReply(reply, id, artist, title); }); //qLog(Debug) << "ChartLyrics: Sending request for" << url; @@ -69,6 +80,9 @@ void ChartLyricsProvider::CancelSearch(const quint64) {} void ChartLyricsProvider::HandleSearchReply(QNetworkReply *reply, const quint64 id, const QString &artist, const QString &title) { + if (!replies_.contains(reply)) return; + replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); if (reply->error() != QNetworkReply::NoError) { diff --git a/src/lyrics/chartlyricsprovider.h b/src/lyrics/chartlyricsprovider.h index cfa4e3033..12e377740 100644 --- a/src/lyrics/chartlyricsprovider.h +++ b/src/lyrics/chartlyricsprovider.h @@ -23,19 +23,22 @@ #include "config.h" #include +#include #include #include -#include -#include #include "lyricsprovider.h" #include "lyricsfetcher.h" +class QNetworkAccessManager; +class QNetworkReply; + class ChartLyricsProvider : public LyricsProvider { Q_OBJECT public: explicit ChartLyricsProvider(QObject *parent = nullptr); + ~ChartLyricsProvider(); bool StartSearch(const QString &artist, const QString &album, const QString &title, const quint64 id); void CancelSearch(quint64 id); @@ -50,6 +53,7 @@ class ChartLyricsProvider : public LyricsProvider { static const char *kUrlSearch; QNetworkAccessManager *network_; + QList replies_; }; diff --git a/src/lyrics/geniuslyricsprovider.cpp b/src/lyrics/geniuslyricsprovider.cpp index 91f745f4f..063ff62ca 100644 --- a/src/lyrics/geniuslyricsprovider.cpp +++ b/src/lyrics/geniuslyricsprovider.cpp @@ -73,6 +73,17 @@ GeniusLyricsProvider::GeniusLyricsProvider(QObject *parent) : JsonLyricsProvider } +GeniusLyricsProvider::~GeniusLyricsProvider() { + + while (!replies_.isEmpty()) { + QNetworkReply *reply = replies_.takeFirst(); + disconnect(reply, nullptr, this, nullptr); + reply->abort(); + reply->deleteLater(); + } + +} + void GeniusLyricsProvider::Authenticate() { QUrl redirect_url(kOAuthRedirectUrl); @@ -182,6 +193,7 @@ void GeniusLyricsProvider::RequestAccessToken(const QUrl &url, const QUrl &redir QByteArray query = new_url_query.toString(QUrl::FullyEncoded).toUtf8(); QNetworkReply *reply = network_->post(req, query); + replies_ << reply; connect(reply, SIGNAL(sslErrors(QList)), this, SLOT(HandleLoginSSLErrors(QList))); connect(reply, &QNetworkReply::finished, [=] { AccessTokenRequestFinished(reply); }); @@ -204,6 +216,9 @@ void GeniusLyricsProvider::HandleLoginSSLErrors(QList ssl_errors) { void GeniusLyricsProvider::AccessTokenRequestFinished(QNetworkReply *reply) { + if (!replies_.contains(reply)) return; + replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); if (reply->error() != QNetworkReply::NoError || reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() != 200) { @@ -309,6 +324,7 @@ bool GeniusLyricsProvider::StartSearch(const QString &artist, const QString &alb req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); req.setRawHeader("Authorization", "Bearer " + access_token_.toUtf8()); QNetworkReply *reply = network_->get(req); + replies_ << reply; connect(reply, &QNetworkReply::finished, [=] { HandleSearchReply(reply, id); }); //qLog(Debug) << "GeniusLyrics: Sending request for" << url; @@ -321,6 +337,9 @@ void GeniusLyricsProvider::CancelSearch(const quint64 id) { Q_UNUSED(id); } void GeniusLyricsProvider::HandleSearchReply(QNetworkReply *reply, const quint64 id) { + if (!replies_.contains(reply)) return; + replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); if (!requests_search_.contains(id)) return; @@ -422,6 +441,7 @@ void GeniusLyricsProvider::HandleSearchReply(QNetworkReply *reply, const quint64 QNetworkRequest req(url); req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); QNetworkReply *new_reply = network_->get(req); + replies_ << new_reply; connect(new_reply, &QNetworkReply::finished, [=] { HandleLyricReply(new_reply, search->id, url); }); } @@ -432,6 +452,9 @@ void GeniusLyricsProvider::HandleSearchReply(QNetworkReply *reply, const quint64 void GeniusLyricsProvider::HandleLyricReply(QNetworkReply *reply, const int search_id, const QUrl &url) { + if (!replies_.contains(reply)) return; + replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); if (!requests_search_.contains(search_id)) return; diff --git a/src/lyrics/geniuslyricsprovider.h b/src/lyrics/geniuslyricsprovider.h index 121e1dc33..d0e79abe5 100644 --- a/src/lyrics/geniuslyricsprovider.h +++ b/src/lyrics/geniuslyricsprovider.h @@ -48,6 +48,7 @@ class GeniusLyricsProvider : public JsonLyricsProvider { public: explicit GeniusLyricsProvider(QObject *parent = nullptr); + ~GeniusLyricsProvider(); bool IsAuthenticated() { return !access_token_.isEmpty(); } void Authenticate(); @@ -102,6 +103,7 @@ class GeniusLyricsProvider : public JsonLyricsProvider { QString access_token_; QStringList login_errors_; QMap> requests_search_; + QList replies_; }; diff --git a/src/lyrics/jsonlyricsprovider.h b/src/lyrics/jsonlyricsprovider.h index c2e708865..f2cbeef80 100644 --- a/src/lyrics/jsonlyricsprovider.h +++ b/src/lyrics/jsonlyricsprovider.h @@ -24,6 +24,7 @@ #include #include +#include #include #include #include diff --git a/src/lyrics/lololyricsprovider.cpp b/src/lyrics/lololyricsprovider.cpp index 3186cd271..4ae91f8f4 100644 --- a/src/lyrics/lololyricsprovider.cpp +++ b/src/lyrics/lololyricsprovider.cpp @@ -43,6 +43,17 @@ const char *LoloLyricsProvider::kUrlSearch = "http://api.lololyrics.com/0.5/getL LoloLyricsProvider::LoloLyricsProvider(QObject *parent) : LyricsProvider("LoloLyrics", true, false, parent), network_(new NetworkAccessManager(this)) {} +LoloLyricsProvider::~LoloLyricsProvider() { + + while (!replies_.isEmpty()) { + QNetworkReply *reply = replies_.takeFirst(); + disconnect(reply, nullptr, this, nullptr); + reply->abort(); + reply->deleteLater(); + } + +} + bool LoloLyricsProvider::StartSearch(const QString &artist, const QString &album, const QString &title, const quint64 id) { Q_UNUSED(album); @@ -60,6 +71,7 @@ bool LoloLyricsProvider::StartSearch(const QString &artist, const QString &album QNetworkRequest req(url); req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); QNetworkReply *reply = network_->get(req); + replies_ << reply; connect(reply, &QNetworkReply::finished, [=] { HandleSearchReply(reply, id, artist, title); }); //qLog(Debug) << "LoloLyrics: Sending request for" << url; @@ -72,6 +84,9 @@ void LoloLyricsProvider::CancelSearch(const quint64 id) { Q_UNUSED(id); } void LoloLyricsProvider::HandleSearchReply(QNetworkReply *reply, const quint64 id, const QString &artist, const QString &title) { + if (!replies_.contains(reply)) return; + replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); QString failure_reason; diff --git a/src/lyrics/lololyricsprovider.h b/src/lyrics/lololyricsprovider.h index 3da7f9925..f00b80c23 100644 --- a/src/lyrics/lololyricsprovider.h +++ b/src/lyrics/lololyricsprovider.h @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -37,17 +38,21 @@ class LoloLyricsProvider : public LyricsProvider { public: explicit LoloLyricsProvider(QObject *parent = nullptr); + ~LoloLyricsProvider(); bool StartSearch(const QString &artist, const QString &album, const QString &title, const quint64 id); void CancelSearch(const quint64 id); + private: + void Error(const QString &error, const QVariant &debug = QVariant()); + private slots: void HandleSearchReply(QNetworkReply *reply, const quint64 id, const QString &artist, const QString &title); private: static const char *kUrlSearch; QNetworkAccessManager *network_; - void Error(const QString &error, const QVariant &debug = QVariant()); + QList replies_; }; diff --git a/src/lyrics/musixmatchlyricsprovider.cpp b/src/lyrics/musixmatchlyricsprovider.cpp index b198b36b3..5779905ae 100644 --- a/src/lyrics/musixmatchlyricsprovider.cpp +++ b/src/lyrics/musixmatchlyricsprovider.cpp @@ -41,6 +41,17 @@ MusixmatchLyricsProvider::MusixmatchLyricsProvider(QObject *parent) : JsonLyricsProvider("Musixmatch", true, false, parent), network_(new NetworkAccessManager(this)) {} +MusixmatchLyricsProvider::~MusixmatchLyricsProvider() { + + while (!replies_.isEmpty()) { + QNetworkReply *reply = replies_.takeFirst(); + disconnect(reply, nullptr, this, nullptr); + reply->abort(); + reply->deleteLater(); + } + +} + bool MusixmatchLyricsProvider::StartSearch(const QString &artist, const QString &album, const QString &title, const quint64 id) { QString artist_stripped = artist; @@ -66,6 +77,7 @@ bool MusixmatchLyricsProvider::StartSearch(const QString &artist, const QString QNetworkRequest req(url); req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); QNetworkReply *reply = network_->get(req); + replies_ << reply; connect(reply, &QNetworkReply::finished, [=] { HandleSearchReply(reply, id, artist, album, title); }); qLog(Debug) << "MusixmatchLyrics: Sending request for" << artist_stripped << title_stripped << url; @@ -80,6 +92,9 @@ void MusixmatchLyricsProvider::HandleSearchReply(QNetworkReply *reply, const qui Q_UNUSED(album); + if (!replies_.contains(reply)) return; + replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); LyricsSearchResults results; diff --git a/src/lyrics/musixmatchlyricsprovider.h b/src/lyrics/musixmatchlyricsprovider.h index a17764648..d83dda373 100644 --- a/src/lyrics/musixmatchlyricsprovider.h +++ b/src/lyrics/musixmatchlyricsprovider.h @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -38,6 +39,7 @@ class MusixmatchLyricsProvider : public JsonLyricsProvider { public: explicit MusixmatchLyricsProvider(QObject *parent = nullptr); + ~MusixmatchLyricsProvider(); bool StartSearch(const QString &artist, const QString &album, const QString &title, const quint64 id); void CancelSearch(const quint64 id); @@ -50,6 +52,7 @@ class MusixmatchLyricsProvider : public JsonLyricsProvider { private: QNetworkAccessManager *network_; + QList replies_; }; diff --git a/src/lyrics/ovhlyricsprovider.cpp b/src/lyrics/ovhlyricsprovider.cpp index c219338c3..0ac7f5916 100644 --- a/src/lyrics/ovhlyricsprovider.cpp +++ b/src/lyrics/ovhlyricsprovider.cpp @@ -40,6 +40,17 @@ const char *OVHLyricsProvider::kUrlSearch = "https://api.lyrics.ovh/v1/"; OVHLyricsProvider::OVHLyricsProvider(QObject *parent) : JsonLyricsProvider("Lyrics.ovh", true, false, parent), network_(new NetworkAccessManager(this)) {} +OVHLyricsProvider::~OVHLyricsProvider() { + + while (!replies_.isEmpty()) { + QNetworkReply *reply = replies_.takeFirst(); + disconnect(reply, nullptr, this, nullptr); + reply->abort(); + reply->deleteLater(); + } + +} + bool OVHLyricsProvider::StartSearch(const QString &artist, const QString &album, const QString &title, const quint64 id) { Q_UNUSED(album); @@ -48,6 +59,7 @@ bool OVHLyricsProvider::StartSearch(const QString &artist, const QString &album, QNetworkRequest req(url); req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); QNetworkReply *reply = network_->get(req); + replies_ << reply; connect(reply, &QNetworkReply::finished, [=] { HandleSearchReply(reply, id, artist, title); }); //qLog(Debug) << "OVHLyrics: Sending request for" << url; @@ -60,6 +72,9 @@ void OVHLyricsProvider::CancelSearch(const quint64 id) { Q_UNUSED(id); } void OVHLyricsProvider::HandleSearchReply(QNetworkReply *reply, const quint64 id, const QString &artist, const QString &title) { + if (!replies_.contains(reply)) return; + replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); QJsonObject json_obj = ExtractJsonObj(reply); diff --git a/src/lyrics/ovhlyricsprovider.h b/src/lyrics/ovhlyricsprovider.h index 716b0fbfd..96cdc9fe6 100644 --- a/src/lyrics/ovhlyricsprovider.h +++ b/src/lyrics/ovhlyricsprovider.h @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -37,17 +38,21 @@ class OVHLyricsProvider : public JsonLyricsProvider { public: explicit OVHLyricsProvider(QObject *parent = nullptr); + ~OVHLyricsProvider(); bool StartSearch(const QString &artist, const QString &album, const QString &title, const quint64 id); void CancelSearch(const quint64 id); + private: + void Error(const QString &error, const QVariant &debug = QVariant()); + private slots: void HandleSearchReply(QNetworkReply *reply, const quint64 id, const QString &artist, const QString &title); private: static const char *kUrlSearch; QNetworkAccessManager *network_; - void Error(const QString &error, const QVariant &debug = QVariant()); + QList replies_; }; diff --git a/src/musicbrainz/acoustidclient.cpp b/src/musicbrainz/acoustidclient.cpp index eb5045e8a..f94984fe2 100644 --- a/src/musicbrainz/acoustidclient.cpp +++ b/src/musicbrainz/acoustidclient.cpp @@ -57,6 +57,12 @@ AcoustidClient::AcoustidClient(QObject *parent) network_(new NetworkAccessManager(this)), timeouts_(new NetworkTimeouts(kDefaultTimeout, this)) {} +AcoustidClient::~AcoustidClient() { + + CancelAll(); + +} + void AcoustidClient::SetTimeout(const int msec) { timeouts_->SetTimeout(msec); } void AcoustidClient::Start(const int id, const QString &fingerprint, int duration_msec) { @@ -82,10 +88,13 @@ void AcoustidClient::Start(const int id, const QString &fingerprint, int duratio requests_[id] = reply; timeouts_->AddReply(reply); + } void AcoustidClient::Cancel(const int id) { + if (requests_.contains(id)) delete requests_.take(id); + } void AcoustidClient::CancelAll() { @@ -113,6 +122,7 @@ struct IdSource { void AcoustidClient::RequestFinished(QNetworkReply *reply, const int request_id) { + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); requests_.remove(request_id); diff --git a/src/musicbrainz/acoustidclient.h b/src/musicbrainz/acoustidclient.h index 6a6496f4e..473203046 100644 --- a/src/musicbrainz/acoustidclient.h +++ b/src/musicbrainz/acoustidclient.h @@ -43,6 +43,7 @@ class AcoustidClient : public QObject { public: explicit AcoustidClient(QObject *parent = nullptr); + ~AcoustidClient(); // Network requests will be aborted after this interval. void SetTimeout(const int msec); @@ -70,6 +71,7 @@ class AcoustidClient : public QObject { QNetworkAccessManager *network_; NetworkTimeouts *timeouts_; QMap requests_; + }; #endif // ACOUSTIDCLIENT_H diff --git a/src/musicbrainz/musicbrainzclient.cpp b/src/musicbrainz/musicbrainzclient.cpp index 01e0ab0cd..b7fa3a824 100644 --- a/src/musicbrainz/musicbrainzclient.cpp +++ b/src/musicbrainz/musicbrainzclient.cpp @@ -69,6 +69,12 @@ MusicBrainzClient::MusicBrainzClient(QObject *parent, QNetworkAccessManager *net } +MusicBrainzClient::~MusicBrainzClient() { + + CancelAll(); + +} + QByteArray MusicBrainzClient::GetReplyData(QNetworkReply *reply, QString &error) { QByteArray data; @@ -114,7 +120,7 @@ void MusicBrainzClient::Cancel(int id) { while (!requests_.isEmpty() && requests_.contains(id)) { QNetworkReply *reply = requests_.take(id); - disconnect(reply, 0, this, 0); + disconnect(reply, nullptr, this, nullptr); if (reply->isRunning()) reply->abort(); reply->deleteLater(); } @@ -187,6 +193,7 @@ void MusicBrainzClient::FlushRequests() { void MusicBrainzClient::RequestFinished(QNetworkReply *reply, const int id, const int request_number) { + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); const int nb_removed = requests_.remove(id, reply); @@ -232,6 +239,7 @@ void MusicBrainzClient::RequestFinished(QNetworkReply *reply, const int id, cons void MusicBrainzClient::DiscIdRequestFinished(const QString &discid, QNetworkReply *reply) { + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); ResultList ret; diff --git a/src/musicbrainz/musicbrainzclient.h b/src/musicbrainz/musicbrainzclient.h index f0dcb5694..25efa3e42 100644 --- a/src/musicbrainz/musicbrainzclient.h +++ b/src/musicbrainz/musicbrainzclient.h @@ -51,6 +51,7 @@ class MusicBrainzClient : public QObject { // The second argument allows for specifying a custom network access manager. // It is used in tests. The ownership of network is not transferred. explicit MusicBrainzClient(QObject *parent = nullptr, QNetworkAccessManager *network = nullptr); + ~MusicBrainzClient(); struct Result { Result() : duration_msec_(0), track_(0), year_(-1) {} diff --git a/src/scrobbler/listenbrainzscrobbler.cpp b/src/scrobbler/listenbrainzscrobbler.cpp index 437aa5284..94b765468 100644 --- a/src/scrobbler/listenbrainzscrobbler.cpp +++ b/src/scrobbler/listenbrainzscrobbler.cpp @@ -83,7 +83,22 @@ ListenBrainzScrobbler::ListenBrainzScrobbler(Application *app, QObject *parent) } -ListenBrainzScrobbler::~ListenBrainzScrobbler() {} +ListenBrainzScrobbler::~ListenBrainzScrobbler() { + + while (!replies_.isEmpty()) { + QNetworkReply *reply = replies_.takeFirst(); + disconnect(reply, nullptr, this, nullptr); + reply->abort(); + reply->deleteLater(); + } + + if (server_) { + disconnect(server_, nullptr, this, nullptr); + if (server_->isListening()) server_->close(); + server_->deleteLater(); + } + +} void ListenBrainzScrobbler::ReloadSettings() { @@ -231,12 +246,16 @@ void ListenBrainzScrobbler::RequestAccessToken(const QUrl &redirect_url, const Q req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); QByteArray query = url_query.toString(QUrl::FullyEncoded).toUtf8(); QNetworkReply *reply = network_->post(req, query); + replies_ << reply; connect(reply, &QNetworkReply::finished, [=] { AuthenticateReplyFinished(reply); }); } void ListenBrainzScrobbler::AuthenticateReplyFinished(QNetworkReply *reply) { + if (!replies_.contains(reply)) return; + replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); QByteArray data; @@ -330,6 +349,7 @@ QNetworkReply *ListenBrainzScrobbler::CreateRequest(const QUrl &url, const QJson req.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); req.setRawHeader("Authorization", QString("Token %1").arg(user_token_).toUtf8()); QNetworkReply *reply = network_->post(req, json_doc.toJson()); + replies_ << reply; //qLog(Debug) << "ListenBrainz: Sending request" << json_doc.toJson(); @@ -433,6 +453,9 @@ void ListenBrainzScrobbler::UpdateNowPlaying(const Song &song) { void ListenBrainzScrobbler::UpdateNowPlayingRequestFinished(QNetworkReply *reply) { + if (!replies_.contains(reply)) return; + replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); QByteArray data = GetReplyData(reply); @@ -555,6 +578,9 @@ void ListenBrainzScrobbler::Submit() { void ListenBrainzScrobbler::ScrobbleRequestFinished(QNetworkReply *reply, QList list) { + if (!replies_.contains(reply)) return; + replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); QByteArray data = GetReplyData(reply); diff --git a/src/scrobbler/listenbrainzscrobbler.h b/src/scrobbler/listenbrainzscrobbler.h index 7c9fd7998..85534f50c 100644 --- a/src/scrobbler/listenbrainzscrobbler.h +++ b/src/scrobbler/listenbrainzscrobbler.h @@ -117,6 +117,8 @@ class ListenBrainzScrobbler : public ScrobblerService { quint64 timestamp_; QTimer refresh_login_timer_; + QList replies_; + }; #endif // LISTENBRAINZSCROBBLER_H diff --git a/src/scrobbler/scrobblingapi20.cpp b/src/scrobbler/scrobblingapi20.cpp index c86516432..20944ada5 100644 --- a/src/scrobbler/scrobblingapi20.cpp +++ b/src/scrobbler/scrobblingapi20.cpp @@ -80,7 +80,22 @@ ScrobblingAPI20::ScrobblingAPI20(const QString &name, const QString &settings_gr scrobbled_(false), timestamp_(0) {} -ScrobblingAPI20::~ScrobblingAPI20() {} +ScrobblingAPI20::~ScrobblingAPI20() { + + while (!replies_.isEmpty()) { + QNetworkReply *reply = replies_.takeFirst(); + disconnect(reply, nullptr, this, nullptr); + reply->abort(); + reply->deleteLater(); + } + + if (server_) { + disconnect(server_, nullptr, this, nullptr); + if (server_->isListening()) server_->close(); + server_->deleteLater(); + } + +} void ScrobblingAPI20::ReloadSettings() { @@ -232,12 +247,16 @@ void ScrobblingAPI20::RequestSession(const QString &token) { QNetworkRequest req(session_url); req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); QNetworkReply *reply = network()->get(req); + replies_ << reply; connect(reply, &QNetworkReply::finished, [=] { AuthenticateReplyFinished(reply); }); } void ScrobblingAPI20::AuthenticateReplyFinished(QNetworkReply *reply) { + if (!replies_.contains(reply)) return; + replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); QByteArray data; @@ -362,6 +381,7 @@ QNetworkReply *ScrobblingAPI20::CreateRequest(const ParamList &request_params) { req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); QByteArray query = url_query.toString(QUrl::FullyEncoded).toUtf8(); QNetworkReply *reply = network()->post(req, query); + replies_ << reply; //qLog(Debug) << name_ << "Sending request" << query; @@ -454,6 +474,9 @@ void ScrobblingAPI20::UpdateNowPlaying(const Song &song) { void ScrobblingAPI20::UpdateNowPlayingRequestFinished(QNetworkReply *reply) { + if (!replies_.contains(reply)) return; + replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); QByteArray data = GetReplyData(reply); @@ -573,6 +596,9 @@ void ScrobblingAPI20::Submit() { void ScrobblingAPI20::ScrobbleRequestFinished(QNetworkReply *reply, QList list) { + if (!replies_.contains(reply)) return; + replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); QByteArray data = GetReplyData(reply); @@ -750,6 +776,9 @@ void ScrobblingAPI20::SendSingleScrobble(ScrobblerCacheItemPtr item) { void ScrobblingAPI20::SingleScrobbleRequestFinished(QNetworkReply *reply, quint64 timestamp) { + if (!replies_.contains(reply)) return; + replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); ScrobblerCacheItemPtr item = cache()->Get(timestamp); @@ -898,6 +927,9 @@ void ScrobblingAPI20::Love() { void ScrobblingAPI20::LoveRequestFinished(QNetworkReply *reply) { + if (!replies_.contains(reply)) return; + replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); QByteArray data = GetReplyData(reply); diff --git a/src/scrobbler/scrobblingapi20.h b/src/scrobbler/scrobblingapi20.h index 3950ff991..936e70b53 100644 --- a/src/scrobbler/scrobblingapi20.h +++ b/src/scrobbler/scrobblingapi20.h @@ -157,6 +157,8 @@ class ScrobblingAPI20 : public ScrobblerService { bool scrobbled_; quint64 timestamp_; + QList replies_; + }; #endif // SCROBBLINGAPI20_H diff --git a/src/subsonic/subsonicrequest.cpp b/src/subsonic/subsonicrequest.cpp index cf0263e7d..f2a3f2357 100644 --- a/src/subsonic/subsonicrequest.cpp +++ b/src/subsonic/subsonicrequest.cpp @@ -164,6 +164,7 @@ void SubsonicRequest::AlbumsReplyReceived(QNetworkReply *reply, const int offset if (!replies_.contains(reply)) return; replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); --albums_requests_active_; diff --git a/src/subsonic/subsonicservice.cpp b/src/subsonic/subsonicservice.cpp index ecf525986..75a50a765 100644 --- a/src/subsonic/subsonicservice.cpp +++ b/src/subsonic/subsonicservice.cpp @@ -98,7 +98,16 @@ SubsonicService::SubsonicService(Application *app, QObject *parent) } SubsonicService::~SubsonicService() { + + while (!replies_.isEmpty()) { + QNetworkReply *reply = replies_.takeFirst(); + disconnect(reply, nullptr, this, nullptr); + if (reply->isRunning()) reply->abort(); + reply->deleteLater(); + } + collection_backend_->deleteLater(); + } void SubsonicService::Exit() { @@ -177,6 +186,7 @@ void SubsonicService::SendPing(QUrl url, const QString &username, const QString errors_.clear(); QNetworkReply *reply = network_->get(req); + replies_ << reply; connect(reply, SIGNAL(sslErrors(QList)), this, SLOT(HandlePingSSLErrors(QList))); connect(reply, &QNetworkReply::finished, [=] { HandlePingReply(reply, url, username, password); }); @@ -196,6 +206,9 @@ void SubsonicService::HandlePingReply(QNetworkReply *reply, const QUrl &url, con Q_UNUSED(url); + if (!replies_.contains(reply)) return; + replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); if (reply->error() != QNetworkReply::NoError || reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() != 200) { @@ -359,8 +372,8 @@ void SubsonicService::CheckConfiguration() { void SubsonicService::ResetSongsRequest() { if (songs_request_.get()) { - disconnect(songs_request_.get(), 0, this, 0); - disconnect(this, 0, songs_request_.get(), 0); + disconnect(songs_request_.get(), nullptr, this, nullptr); + disconnect(this, nullptr, songs_request_.get(), nullptr); songs_request_.reset(); } diff --git a/src/subsonic/subsonicservice.h b/src/subsonic/subsonicservice.h index 69be2cd43..5fb3a93d9 100644 --- a/src/subsonic/subsonicservice.h +++ b/src/subsonic/subsonicservice.h @@ -126,6 +126,8 @@ class SubsonicService : public InternetService { QStringList errors_; int ping_redirects_; + QList replies_; + }; #endif // SUBSONICSERVICE_H diff --git a/src/tidal/tidalfavoriterequest.cpp b/src/tidal/tidalfavoriterequest.cpp index 4e1c5203f..53d89c4fb 100644 --- a/src/tidal/tidalfavoriterequest.cpp +++ b/src/tidal/tidalfavoriterequest.cpp @@ -51,7 +51,7 @@ TidalFavoriteRequest::~TidalFavoriteRequest() { while (!replies_.isEmpty()) { QNetworkReply *reply = replies_.takeFirst(); - disconnect(reply, 0, this, 0); + disconnect(reply, nullptr, this, nullptr); reply->abort(); reply->deleteLater(); } @@ -152,6 +152,7 @@ void TidalFavoriteRequest::AddFavoritesReply(QNetworkReply *reply, const Favorit if (replies_.contains(reply)) { replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); } else { @@ -254,6 +255,7 @@ void TidalFavoriteRequest::RemoveFavoritesReply(QNetworkReply *reply, const Favo if (replies_.contains(reply)) { replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); } else { diff --git a/src/tidal/tidalrequest.cpp b/src/tidal/tidalrequest.cpp index 991c646a4..a7cb94240 100644 --- a/src/tidal/tidalrequest.cpp +++ b/src/tidal/tidalrequest.cpp @@ -84,14 +84,14 @@ TidalRequest::~TidalRequest() { while (!replies_.isEmpty()) { QNetworkReply *reply = replies_.takeFirst(); - disconnect(reply, 0, this, 0); + disconnect(reply, nullptr, this, nullptr); if (reply->isRunning()) reply->abort(); reply->deleteLater(); } while (!album_cover_replies_.isEmpty()) { QNetworkReply *reply = album_cover_replies_.takeFirst(); - disconnect(reply, 0, this, 0); + disconnect(reply, nullptr, this, nullptr); if (reply->isRunning()) reply->abort(); reply->deleteLater(); } @@ -330,6 +330,7 @@ void TidalRequest::ArtistsReplyReceived(QNetworkReply *reply, const int limit_re if (!replies_.contains(reply)) return; replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); QByteArray data = GetReplyData(reply, (offset_requested == 0)); @@ -521,6 +522,7 @@ void TidalRequest::AlbumsReceived(QNetworkReply *reply, const QString &artist_id if (!replies_.contains(reply)) return; replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); QByteArray data = GetReplyData(reply, auto_login); @@ -787,6 +789,7 @@ void TidalRequest::SongsReceived(QNetworkReply *reply, const QString &artist_id, if (!replies_.contains(reply)) return; replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); QByteArray data = GetReplyData(reply, auto_login); @@ -1127,6 +1130,7 @@ void TidalRequest::AlbumCoverReceived(QNetworkReply *reply, const QString &album if (album_cover_replies_.contains(reply)) { album_cover_replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); } else { diff --git a/src/tidal/tidalservice.cpp b/src/tidal/tidalservice.cpp index abcf64a43..5a0aaa35a 100644 --- a/src/tidal/tidalservice.cpp +++ b/src/tidal/tidalservice.cpp @@ -179,9 +179,16 @@ TidalService::TidalService(Application *app, QObject *parent) TidalService::~TidalService() { + while (!replies_.isEmpty()) { + QNetworkReply *reply = replies_.takeFirst(); + disconnect(reply, nullptr, this, nullptr); + reply->abort(); + reply->deleteLater(); + } + while (!stream_url_requests_.isEmpty()) { TidalStreamURLRequest *stream_url_req = stream_url_requests_.takeFirst(); - disconnect(stream_url_req, 0, this, 0); + disconnect(stream_url_req, nullptr, this, nullptr); stream_url_req->deleteLater(); } @@ -208,7 +215,7 @@ void TidalService::Exit() { void TidalService::ExitReceived() { QObject *obj = static_cast(sender()); - disconnect(obj, 0, this, 0); + disconnect(obj, nullptr, this, nullptr); qLog(Debug) << obj << "successfully exited."; wait_for_exit_.removeAll(obj); if (wait_for_exit_.isEmpty()) emit ExitFinished(); @@ -338,6 +345,7 @@ void TidalService::AuthorisationUrlReceived(const QUrl &url) { login_errors_.clear(); QNetworkReply *reply = network_->post(request, query); + replies_ << reply; connect(reply, SIGNAL(sslErrors(QList)), this, SLOT(HandleLoginSSLErrors(QList))); connect(reply, &QNetworkReply::finished, [=] { AccessTokenRequestFinished(reply); }); @@ -360,6 +368,9 @@ void TidalService::HandleLoginSSLErrors(QList ssl_errors) { void TidalService::AccessTokenRequestFinished(QNetworkReply *reply) { + if (!replies_.contains(reply)) return; + replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); login_sent_ = false; @@ -503,6 +514,7 @@ void TidalService::SendLogin(const QString &api_token, const QString &username, QNetworkReply *reply = network_->post(req, query); connect(reply, SIGNAL(sslErrors(QList)), this, SLOT(HandleLoginSSLErrors(QList))); connect(reply, &QNetworkReply::finished, [=] { HandleAuthReply(reply); }); + replies_ << reply; //qLog(Debug) << "Tidal: Sending request" << url << query; @@ -510,6 +522,9 @@ void TidalService::SendLogin(const QString &api_token, const QString &username, void TidalService::HandleAuthReply(QNetworkReply *reply) { + if (!replies_.contains(reply)) return; + replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); login_sent_ = false; @@ -657,8 +672,8 @@ void TidalService::TryLogin() { void TidalService::ResetArtistsRequest() { if (artists_request_.get()) { - disconnect(artists_request_.get(), 0, this, 0); - disconnect(this, 0, artists_request_.get(), 0); + disconnect(artists_request_.get(), nullptr, this, nullptr); + disconnect(this, nullptr, artists_request_.get(), nullptr); artists_request_.reset(); } @@ -716,8 +731,8 @@ void TidalService::ArtistsUpdateProgressReceived(const int id, const int progres void TidalService::ResetAlbumsRequest() { if (albums_request_.get()) { - disconnect(albums_request_.get(), 0, this, 0); - disconnect(this, 0, albums_request_.get(), 0); + disconnect(albums_request_.get(), nullptr, this, nullptr); + disconnect(this, nullptr, albums_request_.get(), nullptr); albums_request_.reset(); } @@ -773,8 +788,8 @@ void TidalService::AlbumsUpdateProgressReceived(const int id, const int progress void TidalService::ResetSongsRequest() { if (songs_request_.get()) { - disconnect(songs_request_.get(), 0, this, 0); - disconnect(this, 0, songs_request_.get(), 0); + disconnect(songs_request_.get(), nullptr, this, nullptr); + disconnect(this, nullptr, songs_request_.get(), nullptr); songs_request_.reset(); } diff --git a/src/tidal/tidalservice.h b/src/tidal/tidalservice.h index 30b0f07ae..753d41122 100644 --- a/src/tidal/tidalservice.h +++ b/src/tidal/tidalservice.h @@ -247,6 +247,7 @@ class TidalService : public InternetService { QStringList login_errors_; QList wait_for_exit_; + QList replies_; }; diff --git a/src/tidal/tidalstreamurlrequest.cpp b/src/tidal/tidalstreamurlrequest.cpp index 45cbca5df..cd0299518 100644 --- a/src/tidal/tidalstreamurlrequest.cpp +++ b/src/tidal/tidalstreamurlrequest.cpp @@ -57,7 +57,7 @@ TidalStreamURLRequest::TidalStreamURLRequest(TidalService *service, NetworkAcces TidalStreamURLRequest::~TidalStreamURLRequest() { if (reply_) { - disconnect(reply_, 0, this, 0); + disconnect(reply_, nullptr, this, nullptr); if (reply_->isRunning()) reply_->abort(); reply_->deleteLater(); } @@ -114,7 +114,7 @@ void TidalStreamURLRequest::GetStreamURL() { ++tries_; if (reply_) { - disconnect(reply_, 0, this, 0); + disconnect(reply_, nullptr, this, nullptr); if (reply_->isRunning()) reply_->abort(); reply_->deleteLater(); } @@ -149,7 +149,7 @@ void TidalStreamURLRequest::GetStreamURL() { void TidalStreamURLRequest::StreamURLReceived() { if (!reply_) return; - disconnect(reply_, 0, this, 0); + disconnect(reply_, nullptr, this, nullptr); reply_->deleteLater(); QByteArray data = GetReplyData(reply_, true);