diff --git a/src/scrobbler/audioscrobbler.cpp b/src/scrobbler/audioscrobbler.cpp index 1d772f658..1022c6497 100644 --- a/src/scrobbler/audioscrobbler.cpp +++ b/src/scrobbler/audioscrobbler.cpp @@ -195,7 +195,7 @@ void AudioScrobbler::Submit() { for (ScrobblerService *service : scrobbler_services_->List()) { if (!service->IsEnabled() || !service->IsAuthenticated() || service->IsSubmitted()) continue; - service->DoSubmit(); + service->StartSubmit(); } } diff --git a/src/scrobbler/listenbrainzscrobbler.cpp b/src/scrobbler/listenbrainzscrobbler.cpp index d94bd326d..3e5d2532f 100644 --- a/src/scrobbler/listenbrainzscrobbler.cpp +++ b/src/scrobbler/listenbrainzscrobbler.cpp @@ -19,6 +19,8 @@ #include "config.h" +#include + #include #include #include @@ -73,7 +75,8 @@ ListenBrainzScrobbler::ListenBrainzScrobbler(Application *app, QObject *parent) login_time_(0), submitted_(false), scrobbled_(false), - timestamp_(0) { + timestamp_(0), + submit_error_(false) { refresh_login_timer_.setSingleShot(true); QObject::connect(&refresh_login_timer_, &QTimer::timeout, this, &ListenBrainzScrobbler::RequestNewAccessToken); @@ -339,7 +342,7 @@ void ListenBrainzScrobbler::AuthenticateReplyFinished(QNetworkReply *reply) { qLog(Debug) << "ListenBrainz: Authentication was successful, login expires in" << expires_in_; - DoSubmit(); + StartSubmit(); } @@ -509,25 +512,22 @@ void ListenBrainzScrobbler::Scrobble(const Song &song) { if (app_->scrobbler()->IsOffline() || !IsAuthenticated()) return; - if (!submitted_) { - submitted_ = true; - if (app_->scrobbler()->SubmitDelay() <= 0) { - Submit(); - } - else if (!timer_submit_.isActive()) { - timer_submit_.setInterval(static_cast(app_->scrobbler()->SubmitDelay() * kMsecPerSec)); - timer_submit_.start(); - } - } + StartSubmit(); } -void ListenBrainzScrobbler::DoSubmit() { +void ListenBrainzScrobbler::StartSubmit(const bool initial) { if (!submitted_ && cache_->Count() > 0) { - submitted_ = true; - if (!timer_submit_.isActive()) { - timer_submit_.setInterval(static_cast(app_->scrobbler()->SubmitDelay() * kMsecPerSec)); + if (initial && app_->scrobbler()->SubmitDelay() <= 0 && !submit_error_) { + if (timer_submit_.isActive()) { + timer_submit_.stop(); + } + Submit(); + } + else if (!timer_submit_.isActive()) { + int submit_delay = static_cast(std::max(app_->scrobbler()->SubmitDelay(), submit_error_ ? 30 : 5) * kMsecPerSec); + timer_submit_.setInterval(submit_delay); timer_submit_.start(); } } @@ -538,8 +538,6 @@ void ListenBrainzScrobbler::Submit() { qLog(Debug) << "ListenBrainz: Submitting scrobbles."; - submitted_ = false; - if (!IsEnabled() || !IsAuthenticated() || app_->scrobbler()->IsOffline()) return; QJsonArray array; @@ -573,6 +571,8 @@ void ListenBrainzScrobbler::Submit() { if (i <= 0) return; + submitted_ = true; + QJsonObject object; object.insert("listen_type", "import"); object.insert("payload", array); @@ -591,17 +591,21 @@ void ListenBrainzScrobbler::ScrobbleRequestFinished(QNetworkReply *reply, const QObject::disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); + submitted_ = false; + QByteArray data = GetReplyData(reply); if (data.isEmpty()) { cache_->ClearSent(list); - DoSubmit(); + submit_error_ = true; + StartSubmit(); return; } QJsonObject json_obj = ExtractJsonObj(data); if (json_obj.isEmpty()) { cache_->ClearSent(list); - DoSubmit(); + submit_error_ = true; + StartSubmit(); return; } @@ -609,7 +613,8 @@ void ListenBrainzScrobbler::ScrobbleRequestFinished(QNetworkReply *reply, const QString error_desc = json_obj["error_description"].toString(); Error(error_desc); cache_->ClearSent(list); - DoSubmit(); + submit_error_ = true; + StartSubmit(); return; } @@ -619,7 +624,8 @@ void ListenBrainzScrobbler::ScrobbleRequestFinished(QNetworkReply *reply, const } cache_->Flush(list); - DoSubmit(); + submit_error_ = false; + StartSubmit(); } diff --git a/src/scrobbler/listenbrainzscrobbler.h b/src/scrobbler/listenbrainzscrobbler.h index 0c745088b..16a1a59d2 100644 --- a/src/scrobbler/listenbrainzscrobbler.h +++ b/src/scrobbler/listenbrainzscrobbler.h @@ -89,7 +89,7 @@ class ListenBrainzScrobbler : public ScrobblerService { void AuthError(const QString &error); void Error(const QString &error, const QVariant &debug = QVariant()) override; void RequestAccessToken(const QUrl &redirect_url = QUrl(), const QString &code = QString()); - void DoSubmit() override; + void StartSubmit(const bool initial = false) override; void CheckScrobblePrevSong(); static const char *kOAuthAuthorizeUrl; @@ -118,6 +118,7 @@ class ListenBrainzScrobbler : public ScrobblerService { quint64 timestamp_; QTimer refresh_login_timer_; QTimer timer_submit_; + bool submit_error_; QList replies_; diff --git a/src/scrobbler/scrobblerservice.h b/src/scrobbler/scrobblerservice.h index 8f86c4ae4..62404ba69 100644 --- a/src/scrobbler/scrobblerservice.h +++ b/src/scrobbler/scrobblerservice.h @@ -52,7 +52,7 @@ class ScrobblerService : public QObject { virtual void Love() {} virtual void Error(const QString &error, const QVariant &debug = QVariant()) = 0; - virtual void DoSubmit() = 0; + virtual void StartSubmit(const bool initial = false) = 0; virtual void Submitted() = 0; virtual bool IsSubmitted() const { return false; } diff --git a/src/scrobbler/scrobblingapi20.cpp b/src/scrobbler/scrobblingapi20.cpp index f189a612e..2366f8397 100644 --- a/src/scrobbler/scrobblingapi20.cpp +++ b/src/scrobbler/scrobblingapi20.cpp @@ -79,7 +79,8 @@ ScrobblingAPI20::ScrobblingAPI20(const QString &name, const QString &settings_gr subscriber_(false), submitted_(false), scrobbled_(false), - timestamp_(0) { + timestamp_(0), + submit_error_(false) { timer_submit_.setSingleShot(true); QObject::connect(&timer_submit_, &QTimer::timeout, this, &ScrobblingAPI20::Submit); @@ -345,7 +346,7 @@ void ScrobblingAPI20::AuthenticateReplyFinished(QNetworkReply *reply) { emit AuthenticationComplete(true); - DoSubmit(); + StartSubmit(); } @@ -536,25 +537,22 @@ void ScrobblingAPI20::Scrobble(const Song &song) { return; } - if (!submitted_) { - submitted_ = true; - if (!batch_ || app_->scrobbler()->SubmitDelay() <= 0) { - Submit(); - } - else if (!timer_submit_.isActive()) { - timer_submit_.setInterval(static_cast(app_->scrobbler()->SubmitDelay() * kMsecPerSec)); - timer_submit_.start(); - } - } + StartSubmit(true); } -void ScrobblingAPI20::DoSubmit() { +void ScrobblingAPI20::StartSubmit(const bool initial) { if (!submitted_ && cache()->Count() > 0) { - submitted_ = true; - if (!timer_submit_.isActive()) { - timer_submit_.setInterval(static_cast(app_->scrobbler()->SubmitDelay() * kMsecPerSec)); + if (initial && (!batch_ || app_->scrobbler()->SubmitDelay() <= 0) && !submit_error_) { + if (timer_submit_.isActive()) { + timer_submit_.stop(); + } + Submit(); + } + else if (!timer_submit_.isActive()) { + int submit_delay = static_cast(std::max(app_->scrobbler()->SubmitDelay(), submit_error_ ? 30 : 5) * kMsecPerSec); + timer_submit_.setInterval(submit_delay); timer_submit_.start(); } } @@ -563,8 +561,6 @@ void ScrobblingAPI20::DoSubmit() { void ScrobblingAPI20::Submit() { - submitted_ = false; - if (!IsEnabled() || !IsAuthenticated() || app_->scrobbler()->IsOffline()) return; qLog(Debug) << name_ << "Submitting scrobbles."; @@ -601,6 +597,8 @@ void ScrobblingAPI20::Submit() { if (!batch_ || i <= 0) return; + submitted_ = true; + QNetworkReply *reply = CreateRequest(params); QObject::connect(reply, &QNetworkReply::finished, this, [this, reply, list]() { ScrobbleRequestFinished(reply, list); }); @@ -613,17 +611,21 @@ void ScrobblingAPI20::ScrobbleRequestFinished(QNetworkReply *reply, const QList< QObject::disconnect(reply, nullptr, this, nullptr); reply->deleteLater(); + submitted_ = false; + QByteArray data = GetReplyData(reply); if (data.isEmpty()) { cache()->ClearSent(list); - DoSubmit(); + submit_error_ = true; + StartSubmit(); return; } QJsonObject json_obj = ExtractJsonObj(data); if (json_obj.isEmpty()) { cache()->ClearSent(list); - DoSubmit(); + submit_error_ = true; + StartSubmit(); return; } @@ -633,52 +635,53 @@ void ScrobblingAPI20::ScrobbleRequestFinished(QNetworkReply *reply, const QList< QString error_reason = QString("%1 (%2)").arg(error_message).arg(error_code); Error(error_reason); cache()->ClearSent(list); - DoSubmit(); - return; - } - - if (!json_obj.contains("scrobbles")) { - Error("Json reply from server is missing scrobbles.", json_obj); - cache()->ClearSent(list); - DoSubmit(); + submit_error_ = true; + StartSubmit(); return; } cache()->Flush(list); + submit_error_ = false; + + if (!json_obj.contains("scrobbles")) { + Error("Json reply from server is missing scrobbles.", json_obj); + StartSubmit(); + return; + } QJsonValue value_scrobbles = json_obj["scrobbles"]; if (!value_scrobbles.isObject()) { Error("Json scrobbles is not an object.", json_obj); - DoSubmit(); + StartSubmit(); return; } json_obj = value_scrobbles.toObject(); if (json_obj.isEmpty()) { Error("Json scrobbles object is empty.", value_scrobbles); - DoSubmit(); + StartSubmit(); return; } if (!json_obj.contains("@attr") || !json_obj.contains("scrobble")) { Error("Json scrobbles object is missing values.", json_obj); - DoSubmit(); + StartSubmit(); return; } QJsonValue value_attr = json_obj["@attr"]; if (!value_attr.isObject()) { Error("Json scrobbles attr is not an object.", value_attr); - DoSubmit(); + StartSubmit(); return; } QJsonObject obj_attr = value_attr.toObject(); if (obj_attr.isEmpty()) { Error("Json scrobbles attr is empty.", value_attr); - DoSubmit(); + StartSubmit(); return; } if (!obj_attr.contains("accepted") || !obj_attr.contains("ignored")) { Error("Json scrobbles attr is missing values.", obj_attr); - DoSubmit(); + StartSubmit(); return; } int accepted = obj_attr["accepted"].toInt(); @@ -693,7 +696,7 @@ void ScrobblingAPI20::ScrobbleRequestFinished(QNetworkReply *reply, const QList< QJsonObject obj_scrobble = value_scrobble.toObject(); if (obj_scrobble.isEmpty()) { Error("Json scrobbles scrobble object is empty.", obj_scrobble); - DoSubmit(); + StartSubmit(); return; } array_scrobble.append(obj_scrobble); @@ -702,13 +705,13 @@ void ScrobblingAPI20::ScrobbleRequestFinished(QNetworkReply *reply, const QList< array_scrobble = value_scrobble.toArray(); if (array_scrobble.isEmpty()) { Error("Json scrobbles scrobble array is empty.", value_scrobble); - DoSubmit(); + StartSubmit(); return; } } else { Error("Json scrobbles scrobble is not an object or array.", value_scrobble); - DoSubmit(); + StartSubmit(); return; } @@ -774,7 +777,7 @@ void ScrobblingAPI20::ScrobbleRequestFinished(QNetworkReply *reply, const QList< } - DoSubmit(); + StartSubmit(); } diff --git a/src/scrobbler/scrobblingapi20.h b/src/scrobbler/scrobblingapi20.h index 6499ae683..84f40e530 100644 --- a/src/scrobbler/scrobblingapi20.h +++ b/src/scrobbler/scrobblingapi20.h @@ -130,7 +130,7 @@ class ScrobblingAPI20 : public ScrobblerService { void SendSingleScrobble(ScrobblerCacheItemPtr item); void Error(const QString &error, const QVariant &debug = QVariant()) override; static QString ErrorString(const ScrobbleErrorCode error); - void DoSubmit() override; + void StartSubmit(const bool initial = false) override; void CheckScrobblePrevSong(); QString name_; @@ -154,6 +154,7 @@ class ScrobblingAPI20 : public ScrobblerService { Song song_playing_; bool scrobbled_; quint64 timestamp_; + bool submit_error_; QTimer timer_submit_; diff --git a/src/scrobbler/subsonicscrobbler.h b/src/scrobbler/subsonicscrobbler.h index 56e5ee703..6c819393b 100644 --- a/src/scrobbler/subsonicscrobbler.h +++ b/src/scrobbler/subsonicscrobbler.h @@ -54,7 +54,7 @@ class SubsonicScrobbler : public ScrobblerService { void Scrobble(const Song &song) override; void Error(const QString &error, const QVariant &debug = QVariant()) override; - void DoSubmit() override {} + void StartSubmit(const bool initial = false) override { Q_UNUSED(initial) } void Submitted() override { submitted_ = true; } bool IsSubmitted() const override { return submitted_; }