Last.fm authentication
This commit is contained in:
parent
bd30d815d1
commit
4cbad8929d
@ -38,5 +38,6 @@
|
||||
<file>last.fm/neighbour_radio.png</file>
|
||||
<file>last.fm/personal_radio.png</file>
|
||||
<file>last.fm/recommended_radio.png</file>
|
||||
<file>spinner.gif</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
BIN
data/spinner.gif
Normal file
BIN
data/spinner.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 673 B |
22
src/busyindicator.cpp
Normal file
22
src/busyindicator.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
#include "busyindicator.h"
|
||||
|
||||
#include <QMovie>
|
||||
|
||||
BusyIndicator::BusyIndicator(QWidget* parent)
|
||||
: QLabel(parent),
|
||||
movie_(new QMovie(":spinner.gif"))
|
||||
{
|
||||
setMovie(movie_);
|
||||
}
|
||||
|
||||
BusyIndicator::~BusyIndicator() {
|
||||
delete movie_;
|
||||
}
|
||||
|
||||
void BusyIndicator::showEvent(QShowEvent*) {
|
||||
movie_->start();
|
||||
}
|
||||
|
||||
void BusyIndicator::hideEvent(QHideEvent*) {
|
||||
movie_->stop();
|
||||
}
|
23
src/busyindicator.h
Normal file
23
src/busyindicator.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef BUSYINDICATOR_H
|
||||
#define BUSYINDICATOR_H
|
||||
|
||||
#include <QLabel>
|
||||
|
||||
class QMovie;
|
||||
|
||||
class BusyIndicator : public QLabel {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
BusyIndicator(QWidget* parent = 0);
|
||||
~BusyIndicator();
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent* event);
|
||||
void hideEvent(QHideEvent* event);
|
||||
|
||||
private:
|
||||
QMovie* movie_;
|
||||
};
|
||||
|
||||
#endif // BUSYINDICATOR_H
|
43
src/lastfmconfig.cpp
Normal file
43
src/lastfmconfig.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
#include "lastfmconfig.h"
|
||||
#include "lastfmservice.h"
|
||||
|
||||
#include <lastfm/ws.h>
|
||||
|
||||
#include <QMessageBox>
|
||||
|
||||
LastFMConfig::LastFMConfig(LastFMService* service, QWidget *parent)
|
||||
: QDialog(parent),
|
||||
service_(service)
|
||||
{
|
||||
ui_.setupUi(this);
|
||||
|
||||
ui_.username->setText(lastfm::ws::Username);
|
||||
ui_.busy->hide();
|
||||
|
||||
connect(service_, SIGNAL(AuthenticationComplete(bool)), SLOT(AuthenticationComplete(bool)));
|
||||
}
|
||||
|
||||
void LastFMConfig::accept() {
|
||||
if (ui_.username->text().isEmpty() || ui_.password->text().isEmpty()) {
|
||||
QDialog::accept();
|
||||
return;
|
||||
}
|
||||
|
||||
ui_.busy->show();
|
||||
ui_.button_box->setEnabled(false);
|
||||
|
||||
service_->Authenticate(ui_.username->text(), ui_.password->text());
|
||||
}
|
||||
|
||||
void LastFMConfig::AuthenticationComplete(bool success) {
|
||||
ui_.busy->hide();
|
||||
ui_.button_box->setEnabled(true);
|
||||
|
||||
if (success) {
|
||||
ui_.username->setText(lastfm::ws::Username);
|
||||
ui_.password->clear();
|
||||
QDialog::accept();
|
||||
} else {
|
||||
QMessageBox::warning(this, "Authentication failed", "Your Last.fm credentials were incorrect");
|
||||
}
|
||||
}
|
26
src/lastfmconfig.h
Normal file
26
src/lastfmconfig.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef LASTFMCONFIG_H
|
||||
#define LASTFMCONFIG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include "ui_lastfmconfig.h"
|
||||
|
||||
class LastFMService;
|
||||
|
||||
class LastFMConfig : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
LastFMConfig(LastFMService* service, QWidget* parent = 0);
|
||||
|
||||
void accept();
|
||||
|
||||
private slots:
|
||||
void AuthenticationComplete(bool success);
|
||||
|
||||
private:
|
||||
Ui::LastFMConfig ui_;
|
||||
LastFMService* service_;
|
||||
};
|
||||
|
||||
#endif // LASTFMCONFIG_H
|
173
src/lastfmconfig.ui
Normal file
173
src/lastfmconfig.ui
Normal file
@ -0,0 +1,173 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>LastFMConfig</class>
|
||||
<widget class="QDialog" name="LastFMConfig">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>385</width>
|
||||
<height>255</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Last.fm</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Enter your Last.fm details below:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Last.fm username</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="username"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Last.fm password</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="password">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="scrobble">
|
||||
<property name="text">
|
||||
<string>Scrobble tracks that I listen to</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Note that you must be a <span style=" font-weight:600;">paid subscriber</span> to listen to Last.fm radio from within Tangerine.</p></body></html></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="busy" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Authenticating...</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="BusyIndicator" name="label_6">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="button_box">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>BusyIndicator</class>
|
||||
<extends>QLabel</extends>
|
||||
<header>busyindicator.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>button_box</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>LastFMConfig</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>button_box</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>LastFMConfig</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
@ -1,9 +1,31 @@
|
||||
#include "lastfmservice.h"
|
||||
#include "lastfmconfig.h"
|
||||
#include "radioitem.h"
|
||||
|
||||
#include <lastfm/ws.h>
|
||||
#include <lastfm/misc.h>
|
||||
#include <lastfm/XmlQuery>
|
||||
|
||||
#include <QSettings>
|
||||
|
||||
const char* LastFMService::kSettingsGroup = "Last.fm";
|
||||
|
||||
LastFMService::LastFMService(QObject* parent)
|
||||
: RadioService("Last.fm", parent)
|
||||
{
|
||||
lastfm::ws::ApiKey = "75d20fb472be99275392aefa2760ea09";
|
||||
lastfm::ws::SharedSecret = "d3072b60ae626be12be69448f5c46e70";
|
||||
|
||||
QSettings settings;
|
||||
settings.beginGroup(kSettingsGroup);
|
||||
lastfm::ws::Username = settings.value("user").toString();
|
||||
lastfm::ws::SessionKey = settings.value("session").toString();
|
||||
|
||||
config_ = new LastFMConfig(this);
|
||||
}
|
||||
|
||||
LastFMService::~LastFMService() {
|
||||
delete config_;
|
||||
}
|
||||
|
||||
RadioItem* LastFMService::CreateRootItem(RadioItem* parent) {
|
||||
@ -15,6 +37,7 @@ RadioItem* LastFMService::CreateRootItem(RadioItem* parent) {
|
||||
void LastFMService::LazyPopulate(RadioItem *item) {
|
||||
switch (item->type) {
|
||||
case RadioItem::Type_Service:
|
||||
// Create child items
|
||||
CreateStationItem(Type_MyRecommendations, "My Recommendations",
|
||||
":last.fm/recommended_radio.png", item);
|
||||
CreateStationItem(Type_MyRadio, "My Radio Station",
|
||||
@ -23,7 +46,16 @@ void LastFMService::LazyPopulate(RadioItem *item) {
|
||||
":last.fm/loved_radio.png", item);
|
||||
CreateStationItem(Type_MyNeighbourhood, "My Neighbourhood",
|
||||
":last.fm/neighbour_radio.png", item);
|
||||
|
||||
if (lastfm::ws::SessionKey.isEmpty())
|
||||
config_->show();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
item->lazy_loaded = true;
|
||||
}
|
||||
|
||||
RadioItem* LastFMService::CreateStationItem(ItemType type, const QString& name,
|
||||
@ -34,3 +66,41 @@ RadioItem* LastFMService::CreateStationItem(ItemType type, const QString& name,
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void LastFMService::Authenticate(const QString& username, const QString& password) {
|
||||
QMap<QString, QString> params;
|
||||
params["method"] = "auth.getMobileSession";
|
||||
params["username"] = username;
|
||||
params["authToken"] = lastfm::md5((username + lastfm::md5(password.toUtf8())).toUtf8());
|
||||
|
||||
QNetworkReply* reply = lastfm::ws::post(params);
|
||||
connect(reply, SIGNAL(finished()), SLOT(AuthenticateReplyFinished()));
|
||||
}
|
||||
|
||||
void LastFMService::AuthenticateReplyFinished() {
|
||||
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
|
||||
if (!reply) {
|
||||
emit AuthenticationComplete(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse the reply
|
||||
try {
|
||||
lastfm::XmlQuery const lfm = lastfm::ws::parse(reply);
|
||||
|
||||
lastfm::ws::Username = lfm["session"]["name"].text();
|
||||
lastfm::ws::SessionKey = lfm["session"]["key"].text();
|
||||
} catch (std::runtime_error& e) {
|
||||
qDebug() << e.what();
|
||||
emit AuthenticationComplete(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Save the session key
|
||||
QSettings settings;
|
||||
settings.beginGroup(kSettingsGroup);
|
||||
settings.setValue("username", lastfm::ws::Username);
|
||||
settings.setValue("session", lastfm::ws::SessionKey);
|
||||
|
||||
emit AuthenticationComplete(true);
|
||||
}
|
||||
|
@ -3,9 +3,16 @@
|
||||
|
||||
#include "radioservice.h"
|
||||
|
||||
class LastFMConfig;
|
||||
|
||||
class LastFMService : public RadioService {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
LastFMService(QObject* parent = 0);
|
||||
~LastFMService();
|
||||
|
||||
static const char* kSettingsGroup;
|
||||
|
||||
enum ItemType {
|
||||
Type_MyRecommendations = 1000,
|
||||
@ -17,9 +24,20 @@ class LastFMService : public RadioService {
|
||||
RadioItem* CreateRootItem(RadioItem* parent);
|
||||
void LazyPopulate(RadioItem *item);
|
||||
|
||||
void Authenticate(const QString& username, const QString& password);
|
||||
|
||||
signals:
|
||||
void AuthenticationComplete(bool success);
|
||||
|
||||
private slots:
|
||||
void AuthenticateReplyFinished();
|
||||
|
||||
private:
|
||||
RadioItem* CreateStationItem(ItemType type, const QString& name,
|
||||
const QString& icon, RadioItem* parent);
|
||||
|
||||
private:
|
||||
LastFMConfig* config_;
|
||||
};
|
||||
|
||||
#endif // LASTFMSERVICE_H
|
||||
|
@ -10,6 +10,7 @@ class RadioService : public QObject {
|
||||
|
||||
public:
|
||||
RadioService(const QString& name, QObject* parent = 0);
|
||||
virtual ~RadioService() {}
|
||||
|
||||
QString name() const { return name_; }
|
||||
|
||||
|
@ -72,7 +72,8 @@ QModelIndex SimpleTreeModel<T>::parent(const QModelIndex& index) const {
|
||||
template <typename T>
|
||||
int SimpleTreeModel<T>::rowCount(const QModelIndex & parent) const {
|
||||
T* item = IndexToItem(parent);
|
||||
const_cast<SimpleTreeModel<T>*>(this)->LazyPopulate(item); // Ahem
|
||||
if (!item->lazy_loaded)
|
||||
const_cast<SimpleTreeModel<T>*>(this)->LazyPopulate(item); // Ahem
|
||||
|
||||
return item->children.count();
|
||||
}
|
||||
|
14
src/src.pro
14
src/src.pro
@ -2,7 +2,7 @@
|
||||
# Project created by QtCreator 2009-12-15T18:38:35
|
||||
# -------------------------------------------------
|
||||
QT += sql \
|
||||
opengl
|
||||
network opengl xml
|
||||
TARGET = tangerine
|
||||
TEMPLATE = app
|
||||
SOURCES += main.cpp \
|
||||
@ -36,7 +36,9 @@ SOURCES += main.cpp \
|
||||
radioitem.cpp \
|
||||
radioservice.cpp \
|
||||
lastfmservice.cpp \
|
||||
radiomodel.cpp
|
||||
radiomodel.cpp \
|
||||
lastfmconfig.cpp \
|
||||
busyindicator.cpp
|
||||
HEADERS += mainwindow.h \
|
||||
player.h \
|
||||
library.h \
|
||||
@ -72,13 +74,17 @@ HEADERS += mainwindow.h \
|
||||
radioservice.h \
|
||||
lastfmservice.h \
|
||||
simpletreemodel.h \
|
||||
radiomodel.h
|
||||
radiomodel.h \
|
||||
lastfmconfig.h \
|
||||
busyindicator.h
|
||||
FORMS += mainwindow.ui \
|
||||
libraryconfig.ui \
|
||||
fileview.ui
|
||||
fileview.ui \
|
||||
lastfmconfig.ui
|
||||
RESOURCES += ../data/data.qrc
|
||||
OTHER_FILES += ../data/schema.sql \
|
||||
../data/mainwindow.css
|
||||
LIBS += -llastfm
|
||||
!win32 {
|
||||
QMAKE_CXXFLAGS += $$system(taglib-config --cflags)
|
||||
LIBS += $$system(taglib-config --libs)
|
||||
|
Loading…
x
Reference in New Issue
Block a user