Make scrobbler handle streams

This commit is contained in:
Jonas Kvinge
2020-04-25 00:07:42 +02:00
parent 5ba00b61be
commit 4abc650edf
12 changed files with 94 additions and 28 deletions

View File

@@ -55,6 +55,10 @@ AudioScrobbler::AudioScrobbler(Application *app, QObject *parent) :
ReloadSettings();
for (ScrobblerService *service : scrobbler_services_->List()) {
connect(service, SIGNAL(ErrorMessage(QString)), SLOT(ErrorReceived(QString)));
}
}
AudioScrobbler::~AudioScrobbler() {}
@@ -116,53 +120,61 @@ void AudioScrobbler::ShowConfig() {
}
void AudioScrobbler::UpdateNowPlaying(const Song &song) {
qLog(Debug) << "Sending now playing for song" << song.artist() << song.album() << song.title();
for (ScrobblerService *service : scrobbler_services_->List()) {
if (!service->IsEnabled()) continue;
service->UpdateNowPlaying(song);
}
}
void AudioScrobbler::ClearPlaying() {
for (ScrobblerService *service : scrobbler_services_->List()) {
if (!service->IsEnabled()) continue;
service->ClearPlaying();
}
}
void AudioScrobbler::Scrobble(const Song &song, const int scrobble_point) {
qLog(Debug) << "Scrobbling song" << song.artist() << song.album() << song.title() << "at" << scrobble_point;
for (ScrobblerService *service : scrobbler_services_->List()) {
if (!service->IsEnabled()) continue;
service->Scrobble(song);
}
}
void AudioScrobbler::Love() {
for (ScrobblerService *service : scrobbler_services_->List()) {
if (!service->IsEnabled() || !service->IsAuthenticated()) continue;
service->Love();
}
}
void AudioScrobbler::Submit() {
for (ScrobblerService *service : scrobbler_services_->List()) {
if (!service->IsEnabled() || !service->IsAuthenticated() || service->IsSubmitted()) continue;
service->DoSubmit();
}
}
void AudioScrobbler::WriteCache() {
for (ScrobblerService *service : scrobbler_services_->List()) {
if (!service->IsEnabled()) continue;
service->WriteCache();
}
}
void AudioScrobbler::ConnectError() {
for (ScrobblerService *service : scrobbler_services_->List()) {
connect(service, SIGNAL(ErrorMessage(QString)), SLOT(ErrorReceived(QString)));
}
}
void AudioScrobbler::ErrorReceived(QString error) {

View File

@@ -51,7 +51,6 @@ class AudioScrobbler : public QObject {
void ClearPlaying();
void Scrobble(const Song &song, const int scrobble_point);
void ShowConfig();
void ConnectError();
ScrobblerService *ServiceByName(const QString &name) const { return scrobbler_services_->ServiceByName(name); }

View File

@@ -70,6 +70,7 @@ ListenBrainzScrobbler::ListenBrainzScrobbler(Application *app, QObject *parent)
enabled_(false),
expires_in_(-1),
submitted_(false),
scrobbled_(false),
timestamp_(0) {
ReloadSettings();
@@ -345,7 +346,10 @@ QByteArray ListenBrainzScrobbler::GetReplyData(QNetworkReply *reply) {
void ListenBrainzScrobbler::UpdateNowPlaying(const Song &song) {
CheckScrobblePrevSong();
song_playing_ = song;
scrobbled_ = false;
timestamp_ = QDateTime::currentDateTime().toTime_t();
if (!song.is_metadata_good() || !IsAuthenticated() || app_->scrobbler()->IsOffline()) return;
@@ -418,13 +422,20 @@ void ListenBrainzScrobbler::UpdateNowPlayingRequestFinished(QNetworkReply *reply
}
void ListenBrainzScrobbler::ClearPlaying() {
CheckScrobblePrevSong();
song_playing_ = Song();
scrobbled_ = false;
timestamp_ = 0;
}
void ListenBrainzScrobbler::Scrobble(const Song &song) {
if (song.id() != song_playing_.id() || song.url() != song_playing_.url() || !song.is_metadata_good()) return;
scrobbled_ = true;
cache_->Add(song, timestamp_);
if (app_->scrobbler()->IsOffline()) return;
@@ -552,3 +563,12 @@ void ListenBrainzScrobbler::Error(const QString &error, const QVariant &debug) {
}
void ListenBrainzScrobbler::CheckScrobblePrevSong() {
quint64 duration = QDateTime::currentDateTime().toTime_t() - timestamp_;
if (!scrobbled_ && song_playing_.is_metadata_good() && song_playing_.source() == Song::Source_Stream && duration > 30) {
Scrobble(song_playing_);
}
}

View File

@@ -88,6 +88,7 @@ class ListenBrainzScrobbler : public ScrobblerService {
void AuthError(const QString &error);
void Error(const QString &error, const QVariant &debug = QVariant());
void DoSubmit();
void CheckScrobblePrevSong();
static const char *kAuthUrl;
static const char *kAuthTokenUrl;
@@ -110,6 +111,7 @@ class ListenBrainzScrobbler : public ScrobblerService {
QString refresh_token_;
bool submitted_;
Song song_playing_;
bool scrobbled_;
quint64 timestamp_;
};

View File

@@ -77,6 +77,7 @@ ScrobblingAPI20::ScrobblingAPI20(const QString &name, const QString &settings_gr
enabled_(false),
subscriber_(false),
submitted_(false),
scrobbled_(false),
timestamp_(0) {}
ScrobblingAPI20::~ScrobblingAPI20() {}
@@ -422,8 +423,11 @@ QByteArray ScrobblingAPI20::GetReplyData(QNetworkReply *reply) {
void ScrobblingAPI20::UpdateNowPlaying(const Song &song) {
CheckScrobblePrevSong();
song_playing_ = song;
timestamp_ = QDateTime::currentDateTime().toTime_t();
scrobbled_ = false;
if (!IsAuthenticated() || !song.is_metadata_good() || app_->scrobbler()->IsOffline()) return;
@@ -477,13 +481,21 @@ void ScrobblingAPI20::UpdateNowPlayingRequestFinished(QNetworkReply *reply) {
}
void ScrobblingAPI20::ClearPlaying() {
CheckScrobblePrevSong();
song_playing_ = Song();
scrobbled_ = false;
timestamp_ = 0;
}
void ScrobblingAPI20::Scrobble(const Song &song) {
if (song.id() != song_playing_.id() || song.url() != song_playing_.url() || !song.is_metadata_good()) return;
scrobbled_ = true;
cache()->Add(song, timestamp_);
if (app_->scrobbler()->IsOffline()) return;
@@ -595,15 +607,15 @@ void ScrobblingAPI20::ScrobbleRequestFinished(QNetworkReply *reply, QList<quint6
cache()->Flush(list);
QJsonValue json_scrobbles = json_obj["scrobbles"];
if (!json_scrobbles.isObject()) {
QJsonValue value_scrobbles = json_obj["scrobbles"];
if (!value_scrobbles.isObject()) {
Error("Json scrobbles is not an object.", json_obj);
DoSubmit();
return;
}
json_obj = json_scrobbles.toObject();
json_obj = value_scrobbles.toObject();
if (json_obj.isEmpty()) {
Error("Json scrobbles object is empty.", json_scrobbles);
Error("Json scrobbles object is empty.", value_scrobbles);
DoSubmit();
return;
}
@@ -775,14 +787,14 @@ void ScrobblingAPI20::SingleScrobbleRequestFinished(QNetworkReply *reply, quint6
cache()->Remove(timestamp);
item = nullptr;
QJsonValue json_scrobbles = json_obj["scrobbles"];
if (!json_scrobbles.isObject()) {
QJsonValue value_scrobbles = json_obj["scrobbles"];
if (!value_scrobbles.isObject()) {
Error("Json scrobbles is not an object.", json_obj);
return;
}
json_obj = json_scrobbles.toObject();
json_obj = value_scrobbles.toObject();
if (json_obj.isEmpty()) {
Error("Json scrobbles object is empty.", json_scrobbles);
Error("Json scrobbles object is empty.", value_scrobbles);
return;
}
if (!json_obj.contains("@attr") || !json_obj.contains("scrobble")) {
@@ -980,3 +992,13 @@ QString ScrobblingAPI20::ErrorString(const ScrobbleErrorCode error) const {
}
}
void ScrobblingAPI20::CheckScrobblePrevSong() {
quint64 time = QDateTime::currentDateTime().toTime_t() - timestamp_;
if (!scrobbled_ && song_playing_.is_metadata_good() && song_playing_.source() == Song::Source_Stream && time > 30) {
Scrobble(song_playing_);
}
}

View File

@@ -133,6 +133,7 @@ class ScrobblingAPI20 : public ScrobblerService {
void Error(const QString &error, const QVariant &debug = QVariant());
QString ErrorString(const ScrobbleErrorCode error) const;
void DoSubmit();
void CheckScrobblePrevSong();
QString name_;
QString settings_group_;
@@ -153,6 +154,7 @@ class ScrobblingAPI20 : public ScrobblerService {
bool submitted_;
Song song_playing_;
bool scrobbled_;
quint64 timestamp_;
};