From 05d7e21348c192ba72e4cfe2e722d6a0f54ab326 Mon Sep 17 00:00:00 2001 From: trialuser02 Date: Thu, 25 Dec 2008 17:47:04 +0000 Subject: scrobbler plugin: now-playing notification support, new api support git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@707 90c681e8-e032-0410-971d-27865f9a5e38 --- src/plugins/General/CMakeLists.txt | 2 +- src/plugins/General/General.pro | 2 +- src/plugins/General/scrobbler/CMakeLists.txt | 10 +- src/plugins/General/scrobbler/scrobbler.cpp | 168 +++++++++++++++++---- src/plugins/General/scrobbler/scrobbler.h | 46 +++++- src/plugins/General/scrobbler/scrobbler.pro | 2 +- src/plugins/General/scrobbler/scrobblerfactory.cpp | 2 +- src/plugins/General/scrobbler/scrobblerfactory.h | 3 +- src/plugins/General/scrobbler/settingsdialog.cpp | 11 +- src/plugins/General/scrobbler/settingsdialog.h | 4 +- src/plugins/General/scrobbler/settingsdialog.ui | 53 ++++--- .../scrobbler/translations/scrobbler_plugin_cs.ts | 10 -- .../scrobbler/translations/scrobbler_plugin_de.ts | 11 -- .../scrobbler/translations/scrobbler_plugin_ru.ts | 11 -- .../translations/scrobbler_plugin_uk_UA.ts | 11 -- .../translations/scrobbler_plugin_zh_CN.ts | 10 -- .../translations/scrobbler_plugin_zh_TW.ts | 10 -- 17 files changed, 226 insertions(+), 140 deletions(-) (limited to 'src') diff --git a/src/plugins/General/CMakeLists.txt b/src/plugins/General/CMakeLists.txt index d596e06ef..e78c28075 100644 --- a/src/plugins/General/CMakeLists.txt +++ b/src/plugins/General/CMakeLists.txt @@ -8,7 +8,7 @@ add_subdirectory(mpris) ENDIF(USE_DBUS) IF(USE_SCROBBLER) -#add_subdirectory(scrobbler) +add_subdirectory(scrobbler) ENDIF(USE_SCROBBLER) IF(USE_STATICON) diff --git a/src/plugins/General/General.pro b/src/plugins/General/General.pro index 8ba55358b..61fcd2967 100644 --- a/src/plugins/General/General.pro +++ b/src/plugins/General/General.pro @@ -1,5 +1,5 @@ SUBDIRS += statusicon \ - #scrobbler \ + scrobbler \ mpris \ notifier TEMPLATE = subdirs diff --git a/src/plugins/General/scrobbler/CMakeLists.txt b/src/plugins/General/scrobbler/CMakeLists.txt index 5aa0cc773..19b06d585 100644 --- a/src/plugins/General/scrobbler/CMakeLists.txt +++ b/src/plugins/General/scrobbler/CMakeLists.txt @@ -20,17 +20,13 @@ ADD_DEFINITIONS(-DQT_NO_DEBUG) ADD_DEFINITIONS(-DQT_SHARED) ADD_DEFINITIONS(-DQT_THREAD) - include_directories(${CMAKE_CURRENT_BINARY_DIR}) -SET(QT_INCLUDES - ${QT_INCLUDES} - ${CMAKE_CURRENT_SOURCE_DIR}/../../../ -) - # libqmmpui include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../) link_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../qmmpui) +#libqmmp +link_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../qmmp) SET(libscrobbler_SRCS settingsdialog.cpp @@ -65,5 +61,5 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) ADD_LIBRARY(scrobbler SHARED ${libscrobbler_SRCS} ${libscrobbler_MOC_SRCS} ${libscrobbler_UIS_H} ${libscrobbler_RCC_SRCS}) add_dependencies(scrobbler qmmpui) -target_link_libraries(scrobbler ${QT_LIBRARIES} -lqmmpui) +target_link_libraries(scrobbler ${QT_LIBRARIES} -lqmmpui -lqmmp) install(TARGETS scrobbler DESTINATION ${LIB_DIR}/qmmp/General) diff --git a/src/plugins/General/scrobbler/scrobbler.cpp b/src/plugins/General/scrobbler/scrobbler.cpp index 7236bef88..af0ecd40b 100644 --- a/src/plugins/General/scrobbler/scrobbler.cpp +++ b/src/plugins/General/scrobbler/scrobbler.cpp @@ -26,21 +26,23 @@ #include #include #include +#include #include "scrobbler.h" #define SCROBBLER_HS_URL "post.audioscrobbler.com" #define PROTOCOL_VER "1.2" #define CLIENT_ID "qmm" -#define CLIENT_VER "0.1" +#define CLIENT_VER "0.2" + Scrobbler::Scrobbler(QObject *parent) : General(parent) { m_http = new QHttp(this); m_http->setHost(SCROBBLER_HS_URL, 80); - m_state = General::Stopped; - QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + m_state = Qmmp::Stopped; + QSettings settings(Qmmp::configFile(), QSettings::IniFormat); settings.beginGroup("Scrobbler"); m_login = settings.value("login").toString(); m_passw = settings.value("password").toString(); @@ -64,10 +66,16 @@ Scrobbler::Scrobbler(QObject *parent) connect(m_http, SIGNAL(requestFinished (int, bool)), SLOT(processResponse(int, bool))); connect(m_http, SIGNAL(readyRead (const QHttpResponseHeader&)), SLOT(readResponse(const QHttpResponseHeader&))); + + m_core = SoundCore::instance(); + connect (m_core, SIGNAL(metaDataChanged()), SLOT(updateMetaData())); + connect (m_core, SIGNAL(stateChanged (Qmmp::State)), SLOT(setState(Qmmp::State))); + m_time = new QTime(); m_submitedSongs = 0; m_handshakeid = 0; m_submitid = 0; + m_notificationid = 0; if (!m_disabled) handshake(); } @@ -78,14 +86,14 @@ Scrobbler::~Scrobbler() delete m_time; } -void Scrobbler::setState(const uint &state) +void Scrobbler::setState(Qmmp::State state) { m_state = state; if (m_disabled) return; switch ((uint) state) { - case General::Playing: + case Qmmp::Playing: { m_start_ts = time(NULL); m_time->restart(); @@ -93,13 +101,13 @@ void Scrobbler::setState(const uint &state) handshake(); break; } - case General::Paused: + case Qmmp::Paused: { break; } - case General::Stopped: + case Qmmp::Stopped: { - if (!m_song.isEmpty() + if (!m_song.metaData().isEmpty() && ((m_time->elapsed ()/1000 > 240) || (m_time->elapsed ()/1000 > int(m_song.length()/2))) && (m_time->elapsed ()/1000 > 60)) @@ -124,20 +132,24 @@ void Scrobbler::setState(const uint &state) } } -void Scrobbler::setSongInfo(const SongInfo &song) +void Scrobbler::updateMetaData() { - if (m_state == General::Playing - && !song.title().isEmpty() //skip empty tags - && !song.artist().isEmpty() - && !song.isStream() //skip stream - && !song.artist().contains("&") //skip tags with special symbols - && !song.title().contains("&") - && !song.album().contains("&") - && !song.artist().contains("=") - && !song.title().contains("=") - && !song.album().contains("=")) + QMap metadata = m_core->metaData(); + if (m_state == Qmmp::Playing + && !metadata.value(Qmmp::TITLE).isEmpty() //skip empty tags + && !metadata.value(Qmmp::ARTIST).isEmpty() + && m_core->length() //skip stream + && !metadata.value(Qmmp::ARTIST).contains("&") //skip tags with special symbols + && !metadata.value(Qmmp::TITLE).contains("&") + && !metadata.value(Qmmp::ALBUM).contains("&") + && !metadata.value(Qmmp::ARTIST).contains("=") + && !metadata.value(Qmmp::TITLE).contains("=") + && !metadata.value(Qmmp::ALBUM).contains("=")) { - m_song = song; + m_song = SongInfo(metadata, m_core->length()); + + if (isReady() && m_notificationid == 0) + sendNotification(m_song); } } @@ -173,7 +185,9 @@ void Scrobbler::processResponse(int id, bool error) qDebug("Scrobbler: Now-Playing URL: %s",qPrintable(strlist[2])); qDebug("Scrobbler: Submission URL: %s",qPrintable(strlist[3])); m_submitUrl = strlist[3]; + m_nowPlayingUrl = strlist[2]; m_session = strlist[1]; + updateMetaData(); //send now-playing notification for already playing song return; } } @@ -194,6 +208,17 @@ void Scrobbler::processResponse(int id, bool error) m_songCache.removeFirst (); } } + else if (id == m_notificationid) + { + m_notificationid = 0; + if (!strlist[0].contains("OK")) + { + qWarning("Scrobbler: notification error: %s", qPrintable(strlist[0])); + //TODO badsession handling + return; + } + qDebug("Scrobbler: Now-Playing notification done"); + } m_array.clear(); } @@ -242,31 +267,122 @@ void Scrobbler::submit() { SongInfo info = m_songCache[i]; body += QString("&a[%9]=%1&t[%9]=%2&i[%9]=%3&o[%9]=%4&r[%9]=%5&l[%9]=%6&b[%9]=%7&n[%9]=%8&m[%9]=") - .arg(info.artist()) - .arg(info.title()) + .arg(info.metaData(Qmmp::ARTIST)) + .arg(info.metaData(Qmmp::TITLE)) .arg( m_timeStamps[i]) .arg("P") .arg("") .arg(info.length()) - .arg(info.album()) - .arg(info.track()) + .arg(info.metaData(Qmmp::ALBUM)) + .arg(info.metaData(Qmmp::TRACK)) .arg(i); } QUrl url(m_submitUrl); m_http->setHost(url.host(), url.port()); QHttpRequestHeader header("POST", url.path()); header.setContentType("application/x-www-form-urlencoded"); - header.setValue("User-Agent","iScrobbler/1.5.1qmmp-plugins/0.2"); + header.setValue("User-Agent","iScrobbler/1.5.1qmmp-plugins/" + Qmmp::strVersion()); header.setValue("Host",url.host()); header.setValue("Accept", "*/*"); header.setContentLength(QUrl::toPercentEncoding(body,":/[]&=").size()); qDebug("Scrobbler: submit request header"); - qDebug(qPrintable(header.toString())); + qDebug(qPrintable(header.toString().trimmed())); qDebug("*****************************"); m_submitid = m_http->request(header, QUrl::toPercentEncoding(body,":/[]&=")); } +void Scrobbler::sendNotification(const SongInfo &info) +{ + qDebug("Scrobbler::sendNotification()"); + QString body = QString("s=%1").arg(m_session); + body += QString("&a=%1&t=%2&b=%3&l=%4&n=%5&m=") + .arg(info.metaData(Qmmp::ARTIST)) + .arg(info.metaData(Qmmp::TITLE)) + .arg(info.metaData(Qmmp::ALBUM)) + .arg(info.length()) + .arg(info.metaData(Qmmp::TRACK)); + QUrl url(m_nowPlayingUrl); + m_http->setHost(url.host(), url.port()); + QHttpRequestHeader header("POST", url.path()); + header.setContentType("application/x-www-form-urlencoded"); + header.setValue("User-Agent","iScrobbler/1.5.1qmmp-plugins/" + Qmmp::strVersion()); + header.setValue("Host",url.host()); + header.setValue("Accept", "*/*"); + header.setContentLength(QUrl::toPercentEncoding(body,":/[]&=").size()); + qDebug("Scrobbler: Now-Playing notification request header"); + qDebug(qPrintable(header.toString().trimmed())); + qDebug("*****************************"); + m_notificationid = m_http->request(header, QUrl::toPercentEncoding(body,":/[]&=")); +} + bool Scrobbler::isReady() { return !m_submitUrl.isEmpty() && !m_session.isEmpty(); } + +SongInfo::SongInfo() +{ + m_length = 0; +} + +SongInfo::SongInfo(const QMap metadata, qint64 length) +{ + m_metadata = metadata; + m_length = length; +} + +SongInfo::SongInfo(const SongInfo &other) +{ + m_metadata = other.metaData(); + m_length = other.length(); +} + +SongInfo::~SongInfo() +{} + +void SongInfo::operator=(const SongInfo &info) +{ + m_metadata = info.metaData(); + m_length = info.length(); +} + +bool SongInfo::operator==(const SongInfo &info) +{ + return (m_metadata == info.metaData()) && (m_length == info.length()); +} + +bool SongInfo::operator!=(const SongInfo &info) +{ + return !operator==(info); +} + +void SongInfo::setMetaData(const QMap metadata) +{ + m_metadata = metadata; +} + +void SongInfo::setLength(qint64 l) +{ + m_length = l; +} + +const QMap SongInfo::metaData() const +{ + return m_metadata; +} + +const QString SongInfo::metaData(Qmmp::MetaData key) const +{ + return m_metadata.value(key); +} + +qint64 SongInfo::length () const +{ + return m_length; +} + +void SongInfo::clear() +{ + m_metadata.clear(); + m_length = 0; +} diff --git a/src/plugins/General/scrobbler/scrobbler.h b/src/plugins/General/scrobbler/scrobbler.h index 3f1294131..dd058263d 100644 --- a/src/plugins/General/scrobbler/scrobbler.h +++ b/src/plugins/General/scrobbler/scrobbler.h @@ -21,44 +21,73 @@ #define SCROBBLER_H #include +#include #include +#include #include class QHttp; class QTime; - - +class SoundCore; /** - @author Ilya Kotov + @author Ilya Kotov */ +class SongInfo +{ +public: + SongInfo(); + SongInfo(const QMap metadata, qint64 length); + SongInfo(const SongInfo &other); + + ~SongInfo(); + + void operator=(const SongInfo &info); + bool operator==(const SongInfo &info); + bool operator!=(const SongInfo &info); + + void setMetaData(const QMap metadata); + void setLength(qint64 l); + const QMap metaData() const; + const QString metaData(Qmmp::MetaData) const; + qint64 length () const; + void clear(); + +private: + QMap m_metadata; + qint64 m_length; + +}; + class Scrobbler : public General { -Q_OBJECT + Q_OBJECT public: Scrobbler(QObject *parent = 0); ~Scrobbler(); - void setState(const uint& state); - void setSongInfo(const SongInfo &song); - private slots: + void setState(Qmmp::State state); + void updateMetaData(); void processResponse(int, bool); void readResponse(const QHttpResponseHeader&); private: void handshake(); void submit(); + void sendNotification(const SongInfo &info); bool isReady(); time_t m_start_ts; SongInfo m_song; QHttp *m_http; - uint m_state; + Qmmp::State m_state; + SoundCore *m_core; QString m_login; QString m_passw; QString m_submitUrl; + QString m_nowPlayingUrl; QString m_session; QList m_timeStamps; QList m_songCache; @@ -66,6 +95,7 @@ private: int m_submitedSongs; int m_handshakeid; int m_submitid; + int m_notificationid; QByteArray m_array; bool m_disabled; diff --git a/src/plugins/General/scrobbler/scrobbler.pro b/src/plugins/General/scrobbler/scrobbler.pro index f5df78011..118b03c84 100644 --- a/src/plugins/General/scrobbler/scrobbler.pro +++ b/src/plugins/General/scrobbler/scrobbler.pro @@ -40,7 +40,7 @@ QT += network INCLUDEPATH += ../../../ -LIBS += -lqmmpui +LIBS += -lqmmpui -lqmmp FORMS += settingsdialog.ui diff --git a/src/plugins/General/scrobbler/scrobblerfactory.cpp b/src/plugins/General/scrobbler/scrobblerfactory.cpp index 21a3b522b..2f36f971a 100644 --- a/src/plugins/General/scrobbler/scrobblerfactory.cpp +++ b/src/plugins/General/scrobbler/scrobblerfactory.cpp @@ -34,7 +34,7 @@ const GeneralProperties ScrobblerFactory::properties() const return properties; } -General *ScrobblerFactory::create(Control*, QObject *parent) +General *ScrobblerFactory::create(QObject *parent) { return new Scrobbler(parent); } diff --git a/src/plugins/General/scrobbler/scrobblerfactory.h b/src/plugins/General/scrobbler/scrobblerfactory.h index d883da917..a0bd0a626 100644 --- a/src/plugins/General/scrobbler/scrobblerfactory.h +++ b/src/plugins/General/scrobbler/scrobblerfactory.h @@ -27,7 +27,6 @@ #include #include -#include #include class ScrobblerFactory : public QObject, public GeneralFactory @@ -36,7 +35,7 @@ Q_OBJECT Q_INTERFACES(GeneralFactory); public: const GeneralProperties properties() const; - General *create(Control*, QObject *parent); + General *create(QObject *parent); QDialog *createConfigDialog(QWidget *parent); void showAbout(QWidget *parent); QTranslator *createTranslator(QObject *parent); diff --git a/src/plugins/General/scrobbler/settingsdialog.cpp b/src/plugins/General/scrobbler/settingsdialog.cpp index 9280550f1..346e53631 100644 --- a/src/plugins/General/scrobbler/settingsdialog.cpp +++ b/src/plugins/General/scrobbler/settingsdialog.cpp @@ -19,7 +19,7 @@ ***************************************************************************/ #include -#include +#include #include "settingsdialog.h" @@ -27,24 +27,23 @@ SettingsDialog::SettingsDialog(QWidget *parent) : QDialog(parent) { ui.setupUi(this); - QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + QSettings settings(Qmmp::configFile() + "/.qmmp/qmmprc", QSettings::IniFormat); settings.beginGroup("Scrobbler"); ui.userLineEdit->setText(settings.value("login").toString()); ui.passwordLineEdit->setText(settings.value("password").toString()); settings.endGroup(); - connect(ui.okButton, SIGNAL(clicked()), SLOT(writeSettings())); } SettingsDialog::~SettingsDialog() {} -void SettingsDialog::writeSettings() +void SettingsDialog::accept() { - QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + QSettings settings(Qmmp::configFile() + "/.qmmp/qmmprc", QSettings::IniFormat); settings.beginGroup("Scrobbler"); settings.setValue("login",ui.userLineEdit->text()); settings.setValue("password",ui.passwordLineEdit->text()); settings.endGroup(); - accept(); + QDialog::accept(); } diff --git a/src/plugins/General/scrobbler/settingsdialog.h b/src/plugins/General/scrobbler/settingsdialog.h index 0d5b21d52..81494dfb5 100644 --- a/src/plugins/General/scrobbler/settingsdialog.h +++ b/src/plugins/General/scrobbler/settingsdialog.h @@ -37,8 +37,8 @@ public: ~SettingsDialog(); -private slots: - void writeSettings(); +public slots: + virtual void accept(); private: Ui::SettingsDialog ui; diff --git a/src/plugins/General/scrobbler/settingsdialog.ui b/src/plugins/General/scrobbler/settingsdialog.ui index 37ccc4157..90d2fa481 100644 --- a/src/plugins/General/scrobbler/settingsdialog.ui +++ b/src/plugins/General/scrobbler/settingsdialog.ui @@ -6,13 +6,13 @@ 0 0 250 - 123 + 101 Scrobbler Plugin Settings - + @@ -38,31 +38,24 @@ - + Qt::Horizontal - + - 61 - 20 + 136 + 18 - - - OK - - - - - - - Cancel + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok @@ -73,18 +66,34 @@ - cancelButton - clicked() + buttonBox + accepted() + SettingsDialog + accept() + + + 156 + 77 + + + 16 + 69 + + + + + buttonBox + rejected() SettingsDialog reject() - 204 - 90 + 216 + 81 - 26 - 102 + 75 + 81 diff --git a/src/plugins/General/scrobbler/translations/scrobbler_plugin_cs.ts b/src/plugins/General/scrobbler/translations/scrobbler_plugin_cs.ts index 11213151e..225c2503e 100644 --- a/src/plugins/General/scrobbler/translations/scrobbler_plugin_cs.ts +++ b/src/plugins/General/scrobbler/translations/scrobbler_plugin_cs.ts @@ -25,16 +25,6 @@ SettingsDialog - - - OK - OK - - - - Cancel - Zrušit - Scrobbler Plugin Settings diff --git a/src/plugins/General/scrobbler/translations/scrobbler_plugin_de.ts b/src/plugins/General/scrobbler/translations/scrobbler_plugin_de.ts index dd3c5bae7..dd979238f 100644 --- a/src/plugins/General/scrobbler/translations/scrobbler_plugin_de.ts +++ b/src/plugins/General/scrobbler/translations/scrobbler_plugin_de.ts @@ -1,6 +1,5 @@ - ScrobblerFactory @@ -41,15 +40,5 @@ Password: Passwort: - - - OK - OK - - - - Cancel - Abbrechen - diff --git a/src/plugins/General/scrobbler/translations/scrobbler_plugin_ru.ts b/src/plugins/General/scrobbler/translations/scrobbler_plugin_ru.ts index af8bdd115..fdd6c84b6 100644 --- a/src/plugins/General/scrobbler/translations/scrobbler_plugin_ru.ts +++ b/src/plugins/General/scrobbler/translations/scrobbler_plugin_ru.ts @@ -1,6 +1,5 @@ - ScrobblerFactory @@ -41,15 +40,5 @@ Password: Пароль: - - - OK - - - - - Cancel - Отмена - diff --git a/src/plugins/General/scrobbler/translations/scrobbler_plugin_uk_UA.ts b/src/plugins/General/scrobbler/translations/scrobbler_plugin_uk_UA.ts index 868a710ab..0b3d70ff4 100644 --- a/src/plugins/General/scrobbler/translations/scrobbler_plugin_uk_UA.ts +++ b/src/plugins/General/scrobbler/translations/scrobbler_plugin_uk_UA.ts @@ -1,6 +1,5 @@ - ScrobblerFactory @@ -41,15 +40,5 @@ Password: Пароль: - - - OK - Застосувати - - - - Cancel - Відміна - diff --git a/src/plugins/General/scrobbler/translations/scrobbler_plugin_zh_CN.ts b/src/plugins/General/scrobbler/translations/scrobbler_plugin_zh_CN.ts index db60bc97d..cac4dd97c 100644 --- a/src/plugins/General/scrobbler/translations/scrobbler_plugin_zh_CN.ts +++ b/src/plugins/General/scrobbler/translations/scrobbler_plugin_zh_CN.ts @@ -40,15 +40,5 @@ Password: 密码: - - - OK - 确定 - - - - Cancel - 取消 - diff --git a/src/plugins/General/scrobbler/translations/scrobbler_plugin_zh_TW.ts b/src/plugins/General/scrobbler/translations/scrobbler_plugin_zh_TW.ts index 6c42fd1ef..43fb8ccc3 100644 --- a/src/plugins/General/scrobbler/translations/scrobbler_plugin_zh_TW.ts +++ b/src/plugins/General/scrobbler/translations/scrobbler_plugin_zh_TW.ts @@ -40,15 +40,5 @@ Password: 密碼: - - - OK - 確定 - - - - Cancel - 取消 - -- cgit v1.2.3-13-gbd6f