Add some spotify branding, display spotify login errors, add a button to the config dialog to download the blob, only make the config dialog try to login when it needs to, fix a bug where the Starred and Inbox items would sometimes not get created.

This commit is contained in:
David Sansome 2011-04-30 12:31:20 +00:00
parent 1c0a0f17dd
commit 70e6018b1e
12 changed files with 213 additions and 45 deletions

View File

@ -318,5 +318,6 @@
<file>icons/32x32/edit-find.png</file>
<file>icons/48x48/edit-find.png</file>
<file>schema/schema-33.sql</file>
<file>spotify-core-logo-128x128.png</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

@ -44,6 +44,14 @@ SpotifyBlobDownloader::~SpotifyBlobDownloader() {
delete progress_;
}
bool SpotifyBlobDownloader::Prompt() {
QMessageBox::StandardButton ret = QMessageBox::question(NULL,
tr("Spotify plugin not installed"),
tr("An additional plugin is required to use Spotify in Clementine. Would you like to download and install it now?"),
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
return ret == QMessageBox::Yes;
}
void SpotifyBlobDownloader::Start() {
qDeleteAll(replies_);
replies_.clear();

View File

@ -32,6 +32,8 @@ public:
QObject* parent = 0);
~SpotifyBlobDownloader();
static bool Prompt();
void Start();
signals:

View File

@ -33,20 +33,55 @@ SpotifyConfig::SpotifyConfig(QWidget *parent)
network_(new NetworkAccessManager(this)),
ui_(new Ui_SpotifyConfig),
service_(RadioModel::Service<SpotifyService>()),
needs_validation_(true)
validated_(false)
{
ui_->setupUi(this);
ui_->busy->hide();
QFont bold_font(font());
bold_font.setBold(true);
ui_->blob_status->setFont(bold_font);
connect(ui_->download_blob, SIGNAL(clicked()), SLOT(DownloadBlob()));
connect(service_, SIGNAL(LoginFinished(bool)), SLOT(LoginFinished(bool)));
connect(service_, SIGNAL(BlobStateChanged()), SLOT(BlobStateChanged()));
BlobStateChanged();
}
SpotifyConfig::~SpotifyConfig() {
delete ui_;
}
void SpotifyConfig::BlobStateChanged() {
const bool installed = service_->IsBlobInstalled();
ui_->account_group->setEnabled(installed);
ui_->blob_status->setText(installed ? tr("Installed") : tr("Not installed"));
#ifdef Q_OS_LINUX
ui_->download_blob->setEnabled(!installed);
#else
ui_->download_blob->setEnabled(false);
#endif
}
void SpotifyConfig::DownloadBlob() {
service_->InstallBlob();
}
bool SpotifyConfig::NeedsValidation() const {
// FIXME
return needs_validation_;
if (!service_->IsBlobInstalled()) {
return false;
}
if (ui_->username->text() == original_username_ &&
ui_->password->text() == original_password_) {
return false;
}
return !validated_;
}
void SpotifyConfig::Validate() {
@ -58,8 +93,12 @@ void SpotifyConfig::Load() {
QSettings s;
s.beginGroup(SpotifyService::kSettingsGroup);
ui_->username->setText(s.value("username").toString());
ui_->password->setText(s.value("password").toString());
original_username_ = s.value("username").toString();
original_password_ = s.value("password").toString();
ui_->username->setText(original_username_);
ui_->password->setText(original_password_);
validated_ = false;
}
void SpotifyConfig::Save() {
@ -73,8 +112,7 @@ void SpotifyConfig::Save() {
}
void SpotifyConfig::LoginFinished(bool success) {
qDebug() << Q_FUNC_INFO << success;
needs_validation_ = !success;
validated_ = success;
ui_->busy->hide();
emit ValidationComplete(success);
}

View File

@ -44,6 +44,9 @@ public slots:
void Load();
void Save();
void BlobStateChanged();
void DownloadBlob();
private slots:
void LoginFinished(bool success);
@ -52,7 +55,9 @@ private:
Ui_SpotifyConfig* ui_;
SpotifyService* service_;
bool needs_validation_;
bool validated_;
QString original_username_;
QString original_password_;
};
#endif // SPOTIFYCONFIG_H

View File

@ -6,16 +6,16 @@
<rect>
<x>0</x>
<y>0</y>
<width>448</width>
<height>310</height>
<width>484</width>
<height>384</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="groupBox">
<widget class="QGroupBox" name="account_group">
<property name="title">
<string>Account details</string>
</property>
@ -69,6 +69,56 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Spotify plugin</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>For licensing reasons Spotify support is in a separate plugin.</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Plugin status:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="blob_status"/>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="download_blob">
<property name="text">
<string>Download...</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
@ -82,6 +132,45 @@
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_3">
<property name="minimumSize">
<size>
<width>64</width>
<height>64</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>64</width>
<height>64</height>
</size>
</property>
<property name="pixmap">
<pixmap resource="../../data/data.qrc">:/spotify-core-logo-128x128.png</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QWidget" name="busy" native="true">
<layout class="QHBoxLayout" name="horizontalLayout">
@ -120,6 +209,8 @@
<header>widgets/busyindicator.h</header>
</customwidget>
</customwidgets>
<resources/>
<resources>
<include location="../../data/data.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -90,9 +90,7 @@ void SpotifyServer::HandleMessage(const protobuf::SpotifyMessage& message) {
const protobuf::LoginResponse& response = message.login_response();
logged_in_ = response.success();
if (!response.success()) {
qLog(Info) << QStringFromStdString(response.error());
} else {
if (response.success()) {
// Send any messages that were queued before the client logged in
foreach (const protobuf::SpotifyMessage& message, queued_messages_) {
SendMessage(message);
@ -100,7 +98,7 @@ void SpotifyServer::HandleMessage(const protobuf::SpotifyMessage& message) {
queued_messages_.clear();
}
emit LoginCompleted(response.success());
emit LoginCompleted(response.success(), QStringFromStdString(response.error()));
} else if (message.has_playlists_updated()) {
emit PlaylistsUpdated(message.playlists_updated());
} else if (message.has_load_playlist_response()) {

View File

@ -47,7 +47,7 @@ public:
int server_port() const;
signals:
void LoginCompleted(bool success);
void LoginCompleted(bool success, const QString& error);
void PlaylistsUpdated(const protobuf::Playlists& playlists);
void StarredLoaded(const protobuf::LoadPlaylistResponse& response);

View File

@ -37,6 +37,7 @@ SpotifyService::SpotifyService(RadioModel* parent)
url_handler_(new SpotifyUrlHandler(this, this)),
blob_process_(NULL),
root_(NULL),
search_(NULL),
starred_(NULL),
inbox_(NULL),
login_task_id_(0),
@ -46,14 +47,19 @@ SpotifyService::SpotifyService(RadioModel* parent)
// Build the search path for the binary blob.
// Look for one distributed alongside clementine first, then check in the
// user's home directory for any that have been downloaded.
blob_path_ << QCoreApplication::applicationFilePath() + "-spotifyblob" CMAKE_EXECUTABLE_SUFFIX
<< QCoreApplication::applicationDirPath() + "/../PlugIns/clementine-spotifyblob" CMAKE_EXECUTABLE_SUFFIX;
#ifdef Q_OS_MAC
system_blob_path_ = QCoreApplication::applicationDirPath() +
"/../PlugIns/clementine-spotifyblob";
#else
system_blob_path_ = QCoreApplication::applicationFilePath() +
"-spotifyblob" CMAKE_EXECUTABLE_SUFFIX;
#endif
local_blob_version_ = QString("version%1-%2bit").arg(SPOTIFY_BLOB_VERSION).arg(sizeof(void*) * 8);
local_blob_path_ = Utilities::GetConfigPath(Utilities::Path_LocalSpotifyBlob) +
"/" + local_blob_version_ + "/blob";
qLog(Debug) << "Spotify blob search path:" << blob_path_;
qLog(Debug) << "Spotify system blob path:" << system_blob_path_;
qLog(Debug) << "Spotify local blob path:" << local_blob_path_;
model()->player()->RegisterUrlHandler(url_handler_);
@ -66,6 +72,11 @@ SpotifyService::SpotifyService(RadioModel* parent)
}
SpotifyService::~SpotifyService() {
if (blob_process_ && blob_process_->state() == QProcess::Running) {
qLog(Info) << "Terminating blob process...";
blob_process_->terminate();
blob_process_->waitForFinished(1000);
}
}
QStandardItem* SpotifyService::CreateRootItem() {
@ -118,12 +129,16 @@ void SpotifyService::Login(const QString& username, const QString& password) {
EnsureServerCreated(username, password);
}
void SpotifyService::LoginCompleted(bool success) {
void SpotifyService::LoginCompleted(bool success, const QString& error) {
if (login_task_id_) {
model()->task_manager()->SetTaskFinished(login_task_id_);
login_task_id_ = 0;
}
if (!success) {
QMessageBox::warning(NULL, tr("Spotify login error"), error, QMessageBox::Close);
}
emit LoginFinished(success);
}
@ -132,8 +147,6 @@ void SpotifyService::BlobProcessError(QProcess::ProcessError error) {
blob_process_->deleteLater();
blob_process_ = NULL;
emit StreamError("The Spotify process failed");
if (login_task_id_) {
model()->task_manager()->SetTaskFinished(login_task_id_);
}
@ -148,7 +161,7 @@ void SpotifyService::EnsureServerCreated(const QString& username,
delete server_;
server_ = new SpotifyServer(this);
connect(server_, SIGNAL(LoginCompleted(bool)), SLOT(LoginCompleted(bool)));
connect(server_, SIGNAL(LoginCompleted(bool,QString)), SLOT(LoginCompleted(bool,QString)));
connect(server_, SIGNAL(PlaylistsUpdated(protobuf::Playlists)),
SLOT(PlaylistsUpdated(protobuf::Playlists)));
connect(server_, SIGNAL(InboxLoaded(protobuf::LoadPlaylistResponse)),
@ -186,19 +199,15 @@ void SpotifyService::StartBlobProcess() {
QProcessEnvironment env(QProcessEnvironment::systemEnvironment());
// Look in the system search path first
foreach (const QString& path, blob_path_) {
if (QFile::exists(path)) {
blob_path = path;
break;
}
if (QFile::exists(system_blob_path_)) {
blob_path = system_blob_path_;
}
// Next look in the local path
const QString local_blob_dir = QFileInfo(local_blob_path_).path();
if (blob_path.isEmpty()) {
if (QFile::exists(local_blob_path_)) {
blob_path = local_blob_path_;
env.insert("LD_LIBRARY_PATH", local_blob_dir);
env.insert("LD_LIBRARY_PATH", QFileInfo(local_blob_path_).path());
}
}
@ -209,17 +218,8 @@ void SpotifyService::StartBlobProcess() {
}
#ifdef Q_OS_LINUX
QMessageBox::StandardButton ret = QMessageBox::question(NULL,
tr("Spotify plugin not installed"),
tr("An additional plugin is required to use Spotify in Clementine. Would you like to download and install it now?"),
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
if (ret == QMessageBox::Yes) {
// The downloader deletes itself when it finishes
SpotifyBlobDownloader* downloader = new SpotifyBlobDownloader(
local_blob_version_, local_blob_dir, this);
connect(downloader, SIGNAL(Finished()), SLOT(BlobDownloadFinished()));
downloader->Start();
if (SpotifyBlobDownloader::Prompt()) {
InstallBlob();
}
#endif
@ -240,6 +240,20 @@ void SpotifyService::StartBlobProcess() {
blob_path, QStringList() << QString::number(server_->server_port()));
}
bool SpotifyService::IsBlobInstalled() const {
return QFile::exists(system_blob_path_) ||
QFile::exists(local_blob_path_);
}
void SpotifyService::InstallBlob() {
// The downloader deletes itself when it finishes
SpotifyBlobDownloader* downloader = new SpotifyBlobDownloader(
local_blob_version_, QFileInfo(local_blob_path_).path(), this);
connect(downloader, SIGNAL(Finished()), SLOT(BlobDownloadFinished()));
connect(downloader, SIGNAL(Finished()), SIGNAL(BlobStateChanged()));
downloader->Start();
}
void SpotifyService::BlobDownloadFinished() {
EnsureServerCreated();
}

View File

@ -52,7 +52,11 @@ public:
SpotifyServer* server() const;
bool IsBlobInstalled() const;
void InstallBlob();
signals:
void BlobStateChanged();
void LoginFinished(bool success);
void ImageLoaded(const QUrl& url, const QImage& image);
@ -72,7 +76,7 @@ private:
private slots:
void BlobProcessError(QProcess::ProcessError error);
void LoginCompleted(bool success);
void LoginCompleted(bool success, const QString& error);
void PlaylistsUpdated(const protobuf::Playlists& response);
void InboxLoaded(const protobuf::LoadPlaylistResponse& response);
void StarredLoaded(const protobuf::LoadPlaylistResponse& response);
@ -90,9 +94,9 @@ private:
SpotifyServer* server_;
SpotifyUrlHandler* url_handler_;
QString system_blob_path_;
QString local_blob_version_;
QString local_blob_path_;
QStringList blob_path_;
QProcess* blob_process_;
QStandardItem* root_;

View File

@ -16,6 +16,7 @@
*/
#include "about.h"
#include "config.h"
#include "ui_about.h"
#include <QCoreApplication>
@ -77,6 +78,12 @@ QString About::MakeHtml() const {
ret += QString("<br /><a href=\"http://rainymood.com\">Rainy Mood</a>");
ret += QString("<br /><a href=\"http://www.smitelli.com/?page=blog&p=54\">Scott Smitelli</a></p>");
#ifdef HAVE_SPOTIFY
ret += "<p>This product uses SPOTIFY(R) CORE but is not endorsed, certified "
"or otherwise approved in any way by Spotify. Spotify is the "
"registered trade mark of the Spotify Group.</p>";
#endif // HAVE_SPOTIFY
return ret;
}