diff options
| author | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2013-01-21 18:54:29 +0000 |
|---|---|---|
| committer | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2013-01-21 18:54:29 +0000 |
| commit | d370ae8951e89fc41260636fb5e2993858945c7c (patch) | |
| tree | 3f9fc46783ba8ed9731edd71c0a068ff9e91b57e | |
| parent | 016961e11e1414c02e5b52d5ffd8b7a6a2b91c74 (diff) | |
| download | qmmp-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
| -rw-r--r-- | src/plugins/General/scrobbler/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/plugins/General/scrobbler/scrobbler.cpp | 10 | ||||
| -rw-r--r-- | src/plugins/General/scrobbler/scrobbler.h | 1 | ||||
| -rw-r--r-- | src/plugins/General/scrobbler/scrobbler.pro | 2 | ||||
| -rw-r--r-- | src/plugins/General/scrobbler/scrobbler2.cpp | 110 | ||||
| -rw-r--r-- | src/plugins/General/scrobbler/scrobbler2.h | 13 |
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 |
