aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/General/scrobbler
diff options
context:
space:
mode:
authortrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2013-01-21 18:54:29 +0000
committertrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2013-01-21 18:54:29 +0000
commitd370ae8951e89fc41260636fb5e2993858945c7c (patch)
tree3f9fc46783ba8ed9731edd71c0a068ff9e91b57e /src/plugins/General/scrobbler
parent016961e11e1414c02e5b52d5ffd8b7a6a2b91c74 (diff)
downloadqmmp-d370ae8951e89fc41260636fb5e2993858945c7c.tar.gz
qmmp-d370ae8951e89fc41260636fb5e2993858945c7c.tar.bz2
qmmp-d370ae8951e89fc41260636fb5e2993858945c7c.zip
improved scrobbler plugin, removed QtXML dependence
git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@3182 90c681e8-e032-0410-971d-27865f9a5e38
Diffstat (limited to 'src/plugins/General/scrobbler')
-rw-r--r--src/plugins/General/scrobbler/CMakeLists.txt1
-rw-r--r--src/plugins/General/scrobbler/scrobbler.cpp10
-rw-r--r--src/plugins/General/scrobbler/scrobbler.h1
-rw-r--r--src/plugins/General/scrobbler/scrobbler.pro2
-rw-r--r--src/plugins/General/scrobbler/scrobbler2.cpp110
-rw-r--r--src/plugins/General/scrobbler/scrobbler2.h13
6 files changed, 93 insertions, 44 deletions
diff --git a/src/plugins/General/scrobbler/CMakeLists.txt b/src/plugins/General/scrobbler/CMakeLists.txt
index 6364b9685..f548508cd 100644
--- a/src/plugins/General/scrobbler/CMakeLists.txt
+++ b/src/plugins/General/scrobbler/CMakeLists.txt
@@ -4,7 +4,6 @@ cmake_minimum_required(VERSION 2.4.7)
SET(QT_USE_QTNETWORK TRUE)
-SET(QT_USE_QTXML TRUE)
INCLUDE(FindQt4)
include(${QT_USE_FILE})
diff --git a/src/plugins/General/scrobbler/scrobbler.cpp b/src/plugins/General/scrobbler/scrobbler.cpp
index b49008c8a..9cb824d81 100644
--- a/src/plugins/General/scrobbler/scrobbler.cpp
+++ b/src/plugins/General/scrobbler/scrobbler.cpp
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2008-2012 by Ilya Kotov *
+ * Copyright (C) 2008-2013 by Ilya Kotov *
* forkotov02@hotmail.ru *
* *
* This program is free software; you can redistribute it and/or modify *
@@ -37,7 +37,7 @@
#define PROTOCOL_VER "1.2.1"
#define CLIENT_ID "qmm"
-#define CLIENT_VER "0.5"
+#define CLIENT_VER "0.7"
Scrobbler::Scrobbler(const QString &url,
@@ -49,7 +49,6 @@ Scrobbler::Scrobbler(const QString &url,
m_failure_count = 0;
m_handshake_count = 0;
m_http = new QNetworkAccessManager(this);
- m_state = Qmmp::Stopped;
m_login = login;
m_passw = passw;
m_server = url;
@@ -110,6 +109,7 @@ Scrobbler::Scrobbler(const QString &url,
}
file.close();
}
+ m_start_ts = QDateTime::currentDateTime().toTime_t();
if (!m_disabled)
handshake();
}
@@ -123,7 +123,6 @@ Scrobbler::~Scrobbler()
void Scrobbler::setState(Qmmp::State state)
{
- m_state = state;
switch ((uint) state)
{
case Qmmp::Playing:
@@ -157,7 +156,7 @@ void Scrobbler::setState(Qmmp::State state)
void Scrobbler::updateMetaData()
{
QMap <Qmmp::MetaData, QString> metadata = m_core->metaData();
- if (m_state == Qmmp::Playing
+ if (m_core->state() == Qmmp::Playing
&& !metadata.value(Qmmp::TITLE).isEmpty() //skip empty tags
&& !metadata.value(Qmmp::ARTIST).isEmpty()
&& m_core->totalTime() //skip stream
@@ -194,6 +193,7 @@ void Scrobbler::processResponse(QNetworkReply *reply)
if (reply == m_handshakeReply)
{
+ m_handshakeReply = 0;
m_submitUrl.clear();
m_session.clear();
m_nowPlayingUrl.clear();
diff --git a/src/plugins/General/scrobbler/scrobbler.h b/src/plugins/General/scrobbler/scrobbler.h
index 3dd9cbd0a..0baaeed1b 100644
--- a/src/plugins/General/scrobbler/scrobbler.h
+++ b/src/plugins/General/scrobbler/scrobbler.h
@@ -92,7 +92,6 @@ private:
uint m_start_ts;
SongInfo m_song;
QNetworkAccessManager *m_http;
- Qmmp::State m_state;
SoundCore *m_core;
QString m_login;
QString m_passw;
diff --git a/src/plugins/General/scrobbler/scrobbler.pro b/src/plugins/General/scrobbler/scrobbler.pro
index 97d5219ec..6b8eba577 100644
--- a/src/plugins/General/scrobbler/scrobbler.pro
+++ b/src/plugins/General/scrobbler/scrobbler.pro
@@ -38,7 +38,7 @@ SOURCES += scrobblerfactory.cpp \
settingsdialog.cpp \
scrobblerhandler.cpp \
scrobbler2.cpp
-QT += network xml
+QT += network
INCLUDEPATH += ../../../
unix:LIBS += -lqmmpui \
-lqmmp
diff --git a/src/plugins/General/scrobbler/scrobbler2.cpp b/src/plugins/General/scrobbler/scrobbler2.cpp
index 7509fe8de..278bc8e19 100644
--- a/src/plugins/General/scrobbler/scrobbler2.cpp
+++ b/src/plugins/General/scrobbler/scrobbler2.cpp
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2010 by Ilya Kotov *
+ * Copyright (C) 2010-2013 by Ilya Kotov *
* forkotov02@hotmail.ru *
* *
* This program is free software; you can redistribute it and/or modify *
@@ -24,12 +24,12 @@
#include <QNetworkReply>
#include <QByteArray>
#include <QCryptographicHash>
+#include <QXmlStreamReader>
#include <QUrl>
#include <QTime>
#include <QTimer>
#include <QDateTime>
#include <QDir>
-#include <QDomDocument>
#include <QDesktopServices>
#include <QSettings>
#include <qmmp/soundcore.h>
@@ -105,6 +105,15 @@ Scrobbler2::Scrobbler2(const QString &url, const QString &name, QObject *parent)
}
if(m_session.isEmpty())
getToken();
+ else
+ {
+ submit();
+ if(m_core->state() == Qmmp::Playing)
+ {
+ setState(Qmmp::Playing);
+ updateMetaData();
+ }
+ }
}
@@ -161,37 +170,68 @@ void Scrobbler2::updateMetaData()
void Scrobbler2::processResponse(QNetworkReply *reply)
{
- QString data = QString::fromUtf8(reply->readAll());
if (reply->error() != QNetworkReply::NoError)
{
qWarning("Scrobbler2[%s]: http error: %s", qPrintable(m_name), qPrintable(reply->errorString()));
}
- QDomDocument document;
- document.setContent(data);
- QDomElement root = document.documentElement();
+
+ ScrobblerResponse response;
+ QStringList tags;
+ QXmlStreamReader reader(reply);
+ while(!reader.atEnd())
+ {
+ reader.readNext();
+ if(reader.isStartElement())
+ {
+ tags << reader.name().toString();
+ if(tags.last() == "lfm")
+ response.status = reader.attributes().value("status").toString();
+ else if(tags.last() == "error")
+ response.code = reader.attributes().value("code").toString();
+ }
+ else if(reader.isCharacters() && !reader.isWhitespace())
+ {
+ if(tags.last() == "token")
+ response.token = reader.text().toString();
+ else if(tags.last() == "error")
+ response.error = reader.text().toString();
+ if(tags.count() >= 2 && tags.at(tags.count() - 2) == "session")
+ {
+ if(tags.last() == "key")
+ response.key = reader.text().toString();
+ else if(tags.last() == "name")
+ response.name = reader.text().toString();
+ else if(tags.last() == "subscriber")
+ response.subscriber = reader.text().toString();
+ }
+ }
+ else if(reader.isEndElement())
+ {
+ tags.takeLast();
+ }
+ }
+
QString error_code;
- QString status = root.attribute("status");
- if(status != "ok" && !status.isEmpty())
+ if(response.status != "ok" && !response.status.isEmpty())
{
- QDomElement error = root.firstChildElement("error");
- if(!error.isNull())
+ if(!response.error.isEmpty())
{
- qWarning("Scrobbler2[%s]: status=%s, %s-%s", qPrintable(m_name), qPrintable(status),
- qPrintable(error.attribute("code")), qPrintable(error.text()));
- error_code = error.attribute("code");
+ qWarning("Scrobbler2[%s]: status=%s, %s-%s",
+ qPrintable(m_name),
+ qPrintable(response.status),
+ qPrintable(response.code), qPrintable(response.error));
+ error_code = response.code;
}
else
qWarning("Scrobbler2[%s]: invalid content", qPrintable(m_name));
}
- data = data.trimmed();
-
if (reply == m_getTokenReply)
{
m_getTokenReply = 0;
- if(status == "ok")
+ if(response.status == "ok")
{
- m_token = root.firstChildElement("token").text();
+ m_token = response.token;
qDebug("Scrobbler2[%s]: token: %s", qPrintable(m_name), qPrintable(m_token));
QDesktopServices::openUrl("http://www.last.fm/api/auth/?api_key="API_KEY"&token="+m_token);
QTimer::singleShot(120000, this, SLOT(getSession())); //2 minutes
@@ -212,17 +252,15 @@ void Scrobbler2::processResponse(QNetworkReply *reply)
{
m_getSessionReply = 0;
m_session.clear();
- if(status == "ok")
+ if(response.status == "ok")
{
- QDomElement session = root.firstChildElement("session");
- m_session = session.firstChildElement("key").text();
- QString name = session.firstChildElement("name").text();
- QString subscriber = session.firstChildElement("subscriber").text();
- qDebug("Scrobbler2[%s]: name: %s", qPrintable(m_name),qPrintable(name));
+ m_session = response.key;
+ qDebug("Scrobbler2[%s]: name: %s", qPrintable(m_name),qPrintable(response.name));
qDebug("Scrobbler2[%s]: key: %s", qPrintable(m_name), qPrintable(m_session));
- qDebug("Scrobbler2[%s]: subscriber: %s",qPrintable(m_name), qPrintable(subscriber));
+ qDebug("Scrobbler2[%s]: subscriber: %s",qPrintable(m_name), qPrintable(response.subscriber));
QSettings settings(Qmmp::configFile(), QSettings::IniFormat);
settings.setValue("Scrobbler/lastfm_session", m_session);
+ submit();
}
else if(error_code == "4" || error_code == "15") //invalid token
{
@@ -252,7 +290,7 @@ void Scrobbler2::processResponse(QNetworkReply *reply)
else if (reply == m_submitReply)
{
m_submitReply = 0;
- if (status == "ok")
+ if (response.status == "ok")
{
qDebug("Scrobbler2[%s]: submited %d song(s)",qPrintable(m_name), m_submitedSongs);
while (m_submitedSongs)
@@ -264,7 +302,7 @@ void Scrobbler2::processResponse(QNetworkReply *reply)
{
submit();
}
- else
+ else
{
syncCache(); // update the cache file to reflect the empty cache
updateMetaData();
@@ -289,7 +327,7 @@ void Scrobbler2::processResponse(QNetworkReply *reply)
else if (reply == m_notificationReply)
{
m_notificationReply = 0;
- if(status == "ok")
+ if(response.status == "ok")
{
qDebug("Scrobbler2[%s]: Now-Playing notification done", qPrintable(m_name));
}
@@ -365,9 +403,10 @@ void Scrobbler2::getSession()
void Scrobbler2::submit()
{
- qDebug("Scrobbler2[%s]: submit request", qPrintable(m_name));
- if (m_songCache.isEmpty() || m_session.isEmpty())
+ if (m_songCache.isEmpty() || m_session.isEmpty() || m_submitReply)
return;
+
+ qDebug("Scrobbler2[%s]: submit request", qPrintable(m_name));
m_submitedSongs = qMin(m_songCache.size(),25);
QMap <QString, QString> params;
@@ -377,19 +416,18 @@ void Scrobbler2::submit()
params.insert(QString("track[%1]").arg(i),info.metaData(Qmmp::TITLE));
params.insert(QString("timestamp[%1]").arg(i),QString("%1").arg(info.timeStamp()));
params.insert(QString("artist[%1]").arg(i),info.metaData(Qmmp::ARTIST));
- if(!info.metaData(Qmmp::ALBUM).isEmpty())
- params.insert(QString("album[%1]").arg(i),info.metaData(Qmmp::ALBUM));
- if(!info.metaData(Qmmp::TRACK).isEmpty())
- params.insert(QString("trackNumber[%1]").arg(i),info.metaData(Qmmp::TRACK));
+ params.insert(QString("album[%1]").arg(i),info.metaData(Qmmp::ALBUM));
+ params.insert(QString("trackNumber[%1]").arg(i),info.metaData(Qmmp::TRACK));
params.insert(QString("duration[%1]").arg(i),QString("%1").arg(info.length()));
}
params.insert("api_key", API_KEY);
params.insert("method", "track.scrobble");
params.insert("sk", m_session);
- foreach (QString key, params) //removes empty keys
+ QStringList keys = params.keys();
+ foreach (QString key, keys) //removes empty keys
{
- if(params.value(key).isEmpty())
+ if(params.value(key).isEmpty() || params.value(key) == "0")
params.remove(key);
}
@@ -405,7 +443,7 @@ void Scrobbler2::submit()
}
data.append(SECRET);
body.addQueryItem("api_sig", QCryptographicHash::hash(data, QCryptographicHash::Md5).toHex());
- QByteArray bodyData = body.toEncoded().remove(0,1);
+ QByteArray bodyData = body.toEncoded().remove(0,1);
bodyData.replace("+", QUrl::toPercentEncoding("+"));
QNetworkRequest request(url);
diff --git a/src/plugins/General/scrobbler/scrobbler2.h b/src/plugins/General/scrobbler/scrobbler2.h
index 58306109c..d0a1e4f11 100644
--- a/src/plugins/General/scrobbler/scrobbler2.h
+++ b/src/plugins/General/scrobbler/scrobbler2.h
@@ -32,7 +32,20 @@ class SoundCore;
/**
@author Ilya Kotov <forkotov02@hotmail.ru>
*/
+struct ScrobblerResponse
+{
+ QString status;
+ QString token;
+ QString code;
+ QString error;
+ QString key;
+ QString name;
+ QString subscriber;
+};
+/**
+ @author Ilya Kotov <forkotov02@hotmail.ru>
+*/
class Scrobbler2 : public QObject
{
Q_OBJECT