2012-01-06 22:27:02 +01:00
|
|
|
#include "blobversion.h"
|
2011-04-29 21:44:51 +02:00
|
|
|
#include "config.h"
|
2011-07-15 15:27:50 +02:00
|
|
|
#include "internetmodel.h"
|
2012-10-31 06:53:09 +01:00
|
|
|
#include "searchboxwidget.h"
|
2011-04-25 21:16:26 +02:00
|
|
|
#include "spotifyserver.h"
|
|
|
|
#include "spotifyservice.h"
|
2012-02-12 14:41:50 +01:00
|
|
|
#include "core/application.h"
|
2011-04-27 18:38:28 +02:00
|
|
|
#include "core/database.h"
|
2011-04-26 15:42:58 +02:00
|
|
|
#include "core/logging.h"
|
2012-06-28 23:57:51 +02:00
|
|
|
#include "core/mergedproxymodel.h"
|
2011-04-28 17:10:28 +02:00
|
|
|
#include "core/player.h"
|
2011-04-26 15:42:58 +02:00
|
|
|
#include "core/taskmanager.h"
|
2011-11-28 14:51:35 +01:00
|
|
|
#include "core/timeconstants.h"
|
2011-04-29 21:44:51 +02:00
|
|
|
#include "core/utilities.h"
|
2011-09-24 15:44:23 +02:00
|
|
|
#include "globalsearch/globalsearch.h"
|
|
|
|
#include "globalsearch/spotifysearchprovider.h"
|
2011-04-28 19:50:45 +02:00
|
|
|
#include "playlist/playlist.h"
|
2011-04-28 22:48:53 +02:00
|
|
|
#include "playlist/playlistcontainer.h"
|
2011-04-28 19:50:45 +02:00
|
|
|
#include "playlist/playlistmanager.h"
|
2011-04-26 15:42:58 +02:00
|
|
|
#include "ui/iconloader.h"
|
2012-06-28 23:57:51 +02:00
|
|
|
#include "widgets/didyoumean.h"
|
2011-04-25 21:16:26 +02:00
|
|
|
|
|
|
|
#include <QCoreApplication>
|
2011-04-29 21:44:51 +02:00
|
|
|
#include <QFile>
|
|
|
|
#include <QFileInfo>
|
2011-04-27 18:38:28 +02:00
|
|
|
#include <QMenu>
|
2011-04-29 21:44:51 +02:00
|
|
|
#include <QMessageBox>
|
2012-01-04 12:50:19 +01:00
|
|
|
#include <QMimeData>
|
2011-04-25 21:16:26 +02:00
|
|
|
#include <QProcess>
|
2011-04-26 15:42:58 +02:00
|
|
|
#include <QSettings>
|
2011-05-25 16:22:49 +02:00
|
|
|
#include <QVariant>
|
|
|
|
|
2013-09-17 17:09:56 +02:00
|
|
|
#ifdef HAVE_SPOTIFY_DOWNLOADER
|
|
|
|
#include "spotifyblobdownloader.h"
|
|
|
|
#endif
|
2012-09-03 17:35:43 +02:00
|
|
|
|
2011-05-25 16:22:49 +02:00
|
|
|
Q_DECLARE_METATYPE(QStandardItem*);
|
2011-04-25 21:16:26 +02:00
|
|
|
|
|
|
|
const char* SpotifyService::kServiceName = "Spotify";
|
|
|
|
const char* SpotifyService::kSettingsGroup = "Spotify";
|
2011-04-29 21:44:51 +02:00
|
|
|
const char* SpotifyService::kBlobDownloadUrl = "http://spotify.clementine-player.org/";
|
2011-04-28 19:50:45 +02:00
|
|
|
const int SpotifyService::kSearchDelayMsec = 400;
|
2011-04-25 21:16:26 +02:00
|
|
|
|
2012-02-12 14:41:50 +01:00
|
|
|
SpotifyService::SpotifyService(Application* app, InternetModel* parent)
|
|
|
|
: InternetService(kServiceName, app, parent, parent),
|
2011-04-25 21:16:26 +02:00
|
|
|
server_(NULL),
|
2011-04-26 15:42:58 +02:00
|
|
|
blob_process_(NULL),
|
|
|
|
root_(NULL),
|
2011-04-30 14:31:20 +02:00
|
|
|
search_(NULL),
|
2011-04-26 15:42:58 +02:00
|
|
|
starred_(NULL),
|
|
|
|
inbox_(NULL),
|
2012-06-12 15:53:23 +02:00
|
|
|
toplist_(NULL),
|
2011-04-27 18:38:28 +02:00
|
|
|
login_task_id_(0),
|
|
|
|
context_menu_(NULL),
|
2012-06-28 23:57:51 +02:00
|
|
|
search_box_(new SearchBoxWidget(this)),
|
2011-08-27 23:01:28 +02:00
|
|
|
search_delay_(new QTimer(this)),
|
2011-11-27 18:29:33 +01:00
|
|
|
login_state_(LoginState_OtherError),
|
2012-01-08 00:26:27 +01:00
|
|
|
bitrate_(pb::spotify::Bitrate320k),
|
2011-11-27 18:29:33 +01:00
|
|
|
volume_normalisation_(false)
|
|
|
|
{
|
2011-04-29 21:44:51 +02:00
|
|
|
// 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.
|
2011-04-30 14:31:20 +02:00
|
|
|
#ifdef Q_OS_MAC
|
|
|
|
system_blob_path_ = QCoreApplication::applicationDirPath() +
|
|
|
|
"/../PlugIns/clementine-spotifyblob";
|
|
|
|
#else
|
2011-04-30 20:22:14 +02:00
|
|
|
system_blob_path_ = QCoreApplication::applicationDirPath() +
|
|
|
|
"/clementine-spotifyblob" CMAKE_EXECUTABLE_SUFFIX;
|
2011-04-30 14:31:20 +02:00
|
|
|
#endif
|
2011-04-29 21:44:51 +02:00
|
|
|
|
|
|
|
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";
|
|
|
|
|
2011-04-30 14:31:20 +02:00
|
|
|
qLog(Debug) << "Spotify system blob path:" << system_blob_path_;
|
2011-04-29 21:44:51 +02:00
|
|
|
qLog(Debug) << "Spotify local blob path:" << local_blob_path_;
|
2011-04-27 18:38:28 +02:00
|
|
|
|
2012-02-13 21:44:04 +01:00
|
|
|
app_->global_search()->AddProvider(new SpotifySearchProvider(app_, this));
|
2011-09-24 15:44:23 +02:00
|
|
|
|
2011-04-28 19:50:45 +02:00
|
|
|
search_delay_->setInterval(kSearchDelayMsec);
|
|
|
|
search_delay_->setSingleShot(true);
|
|
|
|
connect(search_delay_, SIGNAL(timeout()), SLOT(DoSearch()));
|
2012-06-28 23:57:51 +02:00
|
|
|
connect(search_box_, SIGNAL(TextChanged(QString)), SLOT(Search(QString)));
|
2011-04-25 21:16:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
SpotifyService::~SpotifyService() {
|
2011-04-30 14:31:20 +02:00
|
|
|
if (blob_process_ && blob_process_->state() == QProcess::Running) {
|
|
|
|
qLog(Info) << "Terminating blob process...";
|
|
|
|
blob_process_->terminate();
|
|
|
|
blob_process_->waitForFinished(1000);
|
|
|
|
}
|
2011-04-25 21:16:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QStandardItem* SpotifyService::CreateRootItem() {
|
2011-11-05 17:08:56 +01:00
|
|
|
root_ = new QStandardItem(QIcon(":icons/22x22/spotify.png"), kServiceName);
|
2011-07-15 15:27:50 +02:00
|
|
|
root_->setData(true, InternetModel::Role_CanLazyLoad);
|
2011-04-26 15:42:58 +02:00
|
|
|
return root_;
|
2011-04-25 21:16:26 +02:00
|
|
|
}
|
|
|
|
|
2011-04-26 15:42:58 +02:00
|
|
|
void SpotifyService::LazyPopulate(QStandardItem* item) {
|
2011-07-15 15:27:50 +02:00
|
|
|
switch (item->data(InternetModel::Role_Type).toInt()) {
|
|
|
|
case InternetModel::Type_Service:
|
2011-04-26 15:42:58 +02:00
|
|
|
EnsureServerCreated();
|
|
|
|
break;
|
|
|
|
|
2011-04-27 18:38:28 +02:00
|
|
|
case Type_SearchResults:
|
|
|
|
break;
|
|
|
|
|
2011-04-26 19:06:36 +02:00
|
|
|
case Type_InboxPlaylist:
|
|
|
|
EnsureServerCreated();
|
|
|
|
server_->LoadInbox();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Type_StarredPlaylist:
|
|
|
|
EnsureServerCreated();
|
|
|
|
server_->LoadStarred();
|
|
|
|
break;
|
|
|
|
|
2011-11-01 11:52:22 +01:00
|
|
|
case InternetModel::Type_UserPlaylist:
|
2011-04-26 19:06:36 +02:00
|
|
|
EnsureServerCreated();
|
|
|
|
server_->LoadUserPlaylist(item->data(Role_UserPlaylistIndex).toInt());
|
|
|
|
break;
|
|
|
|
|
2012-06-12 15:53:23 +02:00
|
|
|
case Type_Toplist:
|
|
|
|
EnsureServerCreated();
|
|
|
|
server_->LoadToplist();
|
|
|
|
break;
|
|
|
|
|
2011-04-26 15:42:58 +02:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-04-25 21:16:26 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpotifyService::Login(const QString& username, const QString& password) {
|
2011-08-27 23:01:28 +02:00
|
|
|
Logout();
|
2011-04-26 15:42:58 +02:00
|
|
|
EnsureServerCreated(username, password);
|
|
|
|
}
|
|
|
|
|
2011-08-27 23:01:28 +02:00
|
|
|
void SpotifyService::LoginCompleted(bool success, const QString& error,
|
2012-01-08 00:26:27 +01:00
|
|
|
pb::spotify::LoginResponse_Error error_code) {
|
2011-04-26 15:42:58 +02:00
|
|
|
if (login_task_id_) {
|
2012-02-12 14:41:50 +01:00
|
|
|
app_->task_manager()->SetTaskFinished(login_task_id_);
|
2011-04-26 15:42:58 +02:00
|
|
|
login_task_id_ = 0;
|
|
|
|
}
|
|
|
|
|
2011-04-30 14:31:20 +02:00
|
|
|
if (!success) {
|
2011-11-28 13:32:45 +01:00
|
|
|
bool show_error_dialog = true;
|
|
|
|
QString error_copy(error);
|
2011-08-27 23:01:28 +02:00
|
|
|
|
|
|
|
switch (error_code) {
|
2012-01-08 00:26:27 +01:00
|
|
|
case pb::spotify::LoginResponse_Error_BadUsernameOrPassword:
|
2011-08-27 23:01:28 +02:00
|
|
|
login_state_ = LoginState_BadCredentials;
|
|
|
|
break;
|
|
|
|
|
2012-01-08 00:26:27 +01:00
|
|
|
case pb::spotify::LoginResponse_Error_UserBanned:
|
2011-08-27 23:01:28 +02:00
|
|
|
login_state_ = LoginState_Banned;
|
|
|
|
break;
|
|
|
|
|
2012-01-08 00:26:27 +01:00
|
|
|
case pb::spotify::LoginResponse_Error_UserNeedsPremium:
|
2011-08-27 23:01:28 +02:00
|
|
|
login_state_ = LoginState_NoPremium;
|
|
|
|
break;
|
|
|
|
|
2012-01-08 00:26:27 +01:00
|
|
|
case pb::spotify::LoginResponse_Error_ReloginFailed:
|
2011-11-28 13:32:45 +01:00
|
|
|
if (login_state_ == LoginState_LoggedIn) {
|
|
|
|
// This is the first time the relogin has failed - show a message this
|
|
|
|
// time only.
|
|
|
|
error_copy = tr("You have been logged out of Spotify, please re-enter your password in the Settings dialog.");
|
|
|
|
} else {
|
|
|
|
show_error_dialog = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
login_state_ = LoginState_ReloginFailed;
|
|
|
|
break;
|
|
|
|
|
2011-08-27 23:01:28 +02:00
|
|
|
default:
|
|
|
|
login_state_ = LoginState_OtherError;
|
2011-11-28 13:32:45 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (show_error_dialog) {
|
|
|
|
QMessageBox::warning(NULL, tr("Spotify login error"), error_copy, QMessageBox::Close);
|
2011-08-27 23:01:28 +02:00
|
|
|
}
|
2011-11-28 13:32:45 +01:00
|
|
|
} else {
|
|
|
|
login_state_ = LoginState_LoggedIn;
|
2011-04-30 14:31:20 +02:00
|
|
|
}
|
|
|
|
|
2011-08-27 23:01:28 +02:00
|
|
|
QSettings s;
|
|
|
|
s.beginGroup(kSettingsGroup);
|
|
|
|
s.setValue("login_state", login_state_);
|
|
|
|
|
2011-04-26 15:42:58 +02:00
|
|
|
emit LoginFinished(success);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpotifyService::BlobProcessError(QProcess::ProcessError error) {
|
|
|
|
qLog(Error) << "Spotify blob process failed:" << error;
|
2011-04-29 21:44:51 +02:00
|
|
|
blob_process_->deleteLater();
|
|
|
|
blob_process_ = NULL;
|
2011-04-29 23:49:48 +02:00
|
|
|
|
|
|
|
if (login_task_id_) {
|
2012-02-12 14:41:50 +01:00
|
|
|
app_->task_manager()->SetTaskFinished(login_task_id_);
|
2011-04-29 23:49:48 +02:00
|
|
|
}
|
2011-04-26 15:42:58 +02:00
|
|
|
}
|
|
|
|
|
2011-08-27 23:01:28 +02:00
|
|
|
void SpotifyService::ReloadSettings() {
|
|
|
|
QSettings s;
|
|
|
|
s.beginGroup(kSettingsGroup);
|
|
|
|
|
|
|
|
login_state_ = LoginState(s.value("login_state", LoginState_OtherError).toInt());
|
2012-01-08 00:26:27 +01:00
|
|
|
bitrate_ = static_cast<pb::spotify::Bitrate>(
|
|
|
|
s.value("bitrate", pb::spotify::Bitrate320k).toInt());
|
2011-11-27 18:29:33 +01:00
|
|
|
volume_normalisation_ = s.value("volume_normalisation", false).toBool();
|
|
|
|
|
|
|
|
if (server_ && blob_process_) {
|
|
|
|
server_->SetPlaybackSettings(bitrate_, volume_normalisation_);
|
|
|
|
}
|
2011-08-27 23:01:28 +02:00
|
|
|
}
|
|
|
|
|
2011-04-26 15:42:58 +02:00
|
|
|
void SpotifyService::EnsureServerCreated(const QString& username,
|
|
|
|
const QString& password) {
|
2011-04-29 21:44:51 +02:00
|
|
|
if (server_ && blob_process_) {
|
2011-04-26 15:42:58 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-04-29 21:44:51 +02:00
|
|
|
delete server_;
|
2011-04-25 21:16:26 +02:00
|
|
|
server_ = new SpotifyServer(this);
|
|
|
|
|
2012-01-08 00:26:27 +01:00
|
|
|
connect(server_, SIGNAL(LoginCompleted(bool,QString,pb::spotify::LoginResponse_Error)),
|
|
|
|
SLOT(LoginCompleted(bool,QString,pb::spotify::LoginResponse_Error)));
|
|
|
|
connect(server_, SIGNAL(PlaylistsUpdated(pb::spotify::Playlists)),
|
|
|
|
SLOT(PlaylistsUpdated(pb::spotify::Playlists)));
|
|
|
|
connect(server_, SIGNAL(InboxLoaded(pb::spotify::LoadPlaylistResponse)),
|
|
|
|
SLOT(InboxLoaded(pb::spotify::LoadPlaylistResponse)));
|
|
|
|
connect(server_, SIGNAL(StarredLoaded(pb::spotify::LoadPlaylistResponse)),
|
|
|
|
SLOT(StarredLoaded(pb::spotify::LoadPlaylistResponse)));
|
|
|
|
connect(server_, SIGNAL(UserPlaylistLoaded(pb::spotify::LoadPlaylistResponse)),
|
|
|
|
SLOT(UserPlaylistLoaded(pb::spotify::LoadPlaylistResponse)));
|
2011-04-27 18:38:28 +02:00
|
|
|
connect(server_, SIGNAL(PlaybackError(QString)),
|
|
|
|
SIGNAL(StreamError(QString)));
|
2012-01-08 00:26:27 +01:00
|
|
|
connect(server_, SIGNAL(SearchResults(pb::spotify::SearchResponse)),
|
|
|
|
SLOT(SearchResults(pb::spotify::SearchResponse)));
|
2011-04-29 15:41:42 +02:00
|
|
|
connect(server_, SIGNAL(ImageLoaded(QString,QImage)),
|
2011-11-29 11:20:23 +01:00
|
|
|
SIGNAL(ImageLoaded(QString,QImage)));
|
2012-01-08 00:26:27 +01:00
|
|
|
connect(server_, SIGNAL(SyncPlaylistProgress(pb::spotify::SyncPlaylistProgress)),
|
|
|
|
SLOT(SyncPlaylistProgress(pb::spotify::SyncPlaylistProgress)));
|
2012-06-12 15:53:23 +02:00
|
|
|
connect(server_, SIGNAL(ToplistBrowseResults(pb::spotify::BrowseToplistResponse)),
|
|
|
|
SLOT(ToplistLoaded(pb::spotify::BrowseToplistResponse)));
|
2011-04-25 21:16:26 +02:00
|
|
|
|
|
|
|
server_->Init();
|
|
|
|
|
2012-02-12 14:41:50 +01:00
|
|
|
login_task_id_ = app_->task_manager()->StartTask(tr("Connecting to Spotify"));
|
2011-04-25 21:16:26 +02:00
|
|
|
|
2011-11-27 18:29:33 +01:00
|
|
|
QString login_username = username;
|
|
|
|
QString login_password = password;
|
|
|
|
|
2011-04-26 15:42:58 +02:00
|
|
|
if (username.isEmpty()) {
|
|
|
|
QSettings s;
|
|
|
|
s.beginGroup(kSettingsGroup);
|
2011-04-25 21:16:26 +02:00
|
|
|
|
2011-11-27 18:29:33 +01:00
|
|
|
login_username = s.value("username").toString();
|
|
|
|
login_password = QString();
|
2011-04-26 15:42:58 +02:00
|
|
|
}
|
2011-04-29 21:44:51 +02:00
|
|
|
|
2011-11-27 18:29:33 +01:00
|
|
|
server_->Login(login_username, login_password, bitrate_, volume_normalisation_);
|
|
|
|
|
2011-04-29 21:44:51 +02:00
|
|
|
StartBlobProcess();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpotifyService::StartBlobProcess() {
|
|
|
|
// Try to find an executable to run
|
|
|
|
QString blob_path;
|
|
|
|
QProcessEnvironment env(QProcessEnvironment::systemEnvironment());
|
|
|
|
|
|
|
|
// Look in the system search path first
|
2011-04-30 14:31:20 +02:00
|
|
|
if (QFile::exists(system_blob_path_)) {
|
|
|
|
blob_path = system_blob_path_;
|
2011-04-29 21:44:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Next look in the local path
|
|
|
|
if (blob_path.isEmpty()) {
|
|
|
|
if (QFile::exists(local_blob_path_)) {
|
|
|
|
blob_path = local_blob_path_;
|
2011-04-30 14:31:20 +02:00
|
|
|
env.insert("LD_LIBRARY_PATH", QFileInfo(local_blob_path_).path());
|
2011-04-29 21:44:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (blob_path.isEmpty()) {
|
|
|
|
// If the blob still wasn't found then we'll prompt the user to download one
|
|
|
|
if (login_task_id_) {
|
2012-02-12 14:41:50 +01:00
|
|
|
app_->task_manager()->SetTaskFinished(login_task_id_);
|
2011-04-29 21:44:51 +02:00
|
|
|
}
|
|
|
|
|
2013-09-17 17:09:56 +02:00
|
|
|
#ifdef HAVE_SPOTIFY_DOWNLOADER
|
|
|
|
if (SpotifyBlobDownloader::Prompt()) {
|
|
|
|
InstallBlob();
|
|
|
|
}
|
|
|
|
#endif
|
2011-04-29 21:44:51 +02:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
delete blob_process_;
|
|
|
|
blob_process_ = new QProcess(this);
|
|
|
|
blob_process_->setProcessChannelMode(QProcess::ForwardedChannels);
|
2011-04-29 23:49:48 +02:00
|
|
|
blob_process_->setProcessEnvironment(env);
|
2011-04-29 21:44:51 +02:00
|
|
|
|
|
|
|
connect(blob_process_,
|
|
|
|
SIGNAL(error(QProcess::ProcessError)),
|
|
|
|
SLOT(BlobProcessError(QProcess::ProcessError)));
|
|
|
|
|
|
|
|
qLog(Info) << "Starting" << blob_path;
|
|
|
|
blob_process_->start(
|
|
|
|
blob_path, QStringList() << QString::number(server_->server_port()));
|
|
|
|
}
|
|
|
|
|
2011-04-30 14:31:20 +02:00
|
|
|
bool SpotifyService::IsBlobInstalled() const {
|
|
|
|
return QFile::exists(system_blob_path_) ||
|
|
|
|
QFile::exists(local_blob_path_);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpotifyService::InstallBlob() {
|
2013-09-17 17:09:56 +02:00
|
|
|
#ifdef HAVE_SPOTIFY_DOWNLOADER
|
2011-04-30 14:31:20 +02:00
|
|
|
// 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();
|
2013-09-17 17:09:56 +02:00
|
|
|
#endif // HAVE_SPOTIFY_DOWNLOADER
|
2011-04-30 14:31:20 +02:00
|
|
|
}
|
|
|
|
|
2011-04-29 21:44:51 +02:00
|
|
|
void SpotifyService::BlobDownloadFinished() {
|
|
|
|
EnsureServerCreated();
|
2011-04-25 21:16:26 +02:00
|
|
|
}
|
|
|
|
|
2012-01-08 00:26:27 +01:00
|
|
|
void SpotifyService::PlaylistsUpdated(const pb::spotify::Playlists& response) {
|
2011-04-26 15:42:58 +02:00
|
|
|
if (login_task_id_) {
|
2012-02-12 14:41:50 +01:00
|
|
|
app_->task_manager()->SetTaskFinished(login_task_id_);
|
2011-04-26 15:42:58 +02:00
|
|
|
login_task_id_ = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create starred and inbox playlists if they're not here already
|
2011-04-29 13:24:58 +02:00
|
|
|
if (!search_) {
|
|
|
|
search_ = new QStandardItem(IconLoader::Load("edit-find"),
|
2012-06-28 23:57:51 +02:00
|
|
|
tr("Search results"));
|
|
|
|
search_->setToolTip(tr("Start typing something on the search box above to "
|
|
|
|
"fill this search results list"));
|
2011-07-15 15:27:50 +02:00
|
|
|
search_->setData(Type_SearchResults, InternetModel::Role_Type);
|
2012-07-29 01:35:05 +02:00
|
|
|
search_->setData(InternetModel::PlayBehaviour_MultipleItems,
|
2011-07-15 15:27:50 +02:00
|
|
|
InternetModel::Role_PlayBehaviour);
|
2011-04-27 18:38:28 +02:00
|
|
|
|
2011-04-26 15:42:58 +02:00
|
|
|
starred_ = new QStandardItem(QIcon(":/star-on.png"), tr("Starred"));
|
2011-07-15 15:27:50 +02:00
|
|
|
starred_->setData(Type_StarredPlaylist, InternetModel::Role_Type);
|
|
|
|
starred_->setData(true, InternetModel::Role_CanLazyLoad);
|
2012-07-29 01:35:05 +02:00
|
|
|
starred_->setData(InternetModel::PlayBehaviour_MultipleItems,
|
|
|
|
InternetModel::Role_PlayBehaviour);
|
2011-04-26 15:42:58 +02:00
|
|
|
|
|
|
|
inbox_ = new QStandardItem(IconLoader::Load("mail-message"), tr("Inbox"));
|
2011-07-15 15:27:50 +02:00
|
|
|
inbox_->setData(Type_InboxPlaylist, InternetModel::Role_Type);
|
|
|
|
inbox_->setData(true, InternetModel::Role_CanLazyLoad);
|
2012-07-29 01:35:05 +02:00
|
|
|
inbox_->setData(InternetModel::PlayBehaviour_MultipleItems,
|
|
|
|
InternetModel::Role_PlayBehaviour);
|
2011-04-26 15:42:58 +02:00
|
|
|
|
2012-06-12 15:53:23 +02:00
|
|
|
toplist_ = new QStandardItem(QIcon(), tr("Top tracks"));
|
|
|
|
toplist_->setData(Type_Toplist, InternetModel::Role_Type);
|
|
|
|
toplist_->setData(true, InternetModel::Role_CanLazyLoad);
|
2012-07-29 01:35:05 +02:00
|
|
|
toplist_->setData(InternetModel::PlayBehaviour_MultipleItems,
|
|
|
|
InternetModel::Role_PlayBehaviour);
|
2012-06-12 15:53:23 +02:00
|
|
|
|
2011-04-29 13:24:58 +02:00
|
|
|
root_->appendRow(search_);
|
2012-06-12 15:53:23 +02:00
|
|
|
root_->appendRow(toplist_);
|
2011-04-26 15:42:58 +02:00
|
|
|
root_->appendRow(starred_);
|
|
|
|
root_->appendRow(inbox_);
|
|
|
|
}
|
|
|
|
|
2011-04-27 18:38:28 +02:00
|
|
|
// Don't do anything if the playlists haven't changed since last time.
|
|
|
|
if (!DoPlaylistsDiffer(response)) {
|
|
|
|
qLog(Debug) << "Playlists haven't changed - not updating";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-04-26 15:42:58 +02:00
|
|
|
// Remove and recreate the other playlists
|
2011-04-27 18:38:28 +02:00
|
|
|
foreach (QStandardItem* item, playlists_) {
|
|
|
|
item->parent()->removeRow(item->row());
|
|
|
|
}
|
2011-04-26 15:42:58 +02:00
|
|
|
playlists_.clear();
|
|
|
|
|
|
|
|
for (int i=0 ; i<response.playlist_size() ; ++i) {
|
2012-01-08 00:26:27 +01:00
|
|
|
const pb::spotify::Playlists::Playlist& msg = response.playlist(i);
|
2011-04-26 15:42:58 +02:00
|
|
|
|
|
|
|
QStandardItem* item = new QStandardItem(QStringFromStdString(msg.name()));
|
2011-11-01 11:52:22 +01:00
|
|
|
item->setData(InternetModel::Type_UserPlaylist, InternetModel::Role_Type);
|
2011-07-15 15:27:50 +02:00
|
|
|
item->setData(true, InternetModel::Role_CanLazyLoad);
|
2011-04-26 19:06:36 +02:00
|
|
|
item->setData(msg.index(), Role_UserPlaylistIndex);
|
2012-07-29 01:35:05 +02:00
|
|
|
item->setData(InternetModel::PlayBehaviour_MultipleItems, InternetModel::Role_PlayBehaviour);
|
2011-04-26 15:42:58 +02:00
|
|
|
|
|
|
|
root_->appendRow(item);
|
2011-04-26 19:06:36 +02:00
|
|
|
playlists_ << item;
|
2011-11-01 11:52:22 +01:00
|
|
|
|
|
|
|
// Preload the playlist items so that drag & drop works immediately.
|
|
|
|
LazyPopulate(item);
|
2011-04-26 19:06:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-08 00:26:27 +01:00
|
|
|
bool SpotifyService::DoPlaylistsDiffer(const pb::spotify::Playlists& response) const {
|
2011-04-27 18:38:28 +02:00
|
|
|
if (playlists_.count() != response.playlist_size()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i=0 ; i<response.playlist_size() ; ++i) {
|
2012-01-08 00:26:27 +01:00
|
|
|
const pb::spotify::Playlists::Playlist& msg = response.playlist(i);
|
2011-04-27 18:38:28 +02:00
|
|
|
const QStandardItem* item = PlaylistBySpotifyIndex(msg.index());
|
|
|
|
|
|
|
|
if (!item) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (QStringFromStdString(msg.name()) != item->text()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-01-08 00:26:27 +01:00
|
|
|
void SpotifyService::InboxLoaded(const pb::spotify::LoadPlaylistResponse& response) {
|
2012-07-12 16:35:09 +02:00
|
|
|
if (inbox_) {
|
|
|
|
FillPlaylist(inbox_, response);
|
|
|
|
}
|
2011-04-26 19:06:36 +02:00
|
|
|
}
|
|
|
|
|
2012-01-08 00:26:27 +01:00
|
|
|
void SpotifyService::StarredLoaded(const pb::spotify::LoadPlaylistResponse& response) {
|
2012-07-12 16:35:09 +02:00
|
|
|
if (starred_) {
|
|
|
|
FillPlaylist(starred_, response);
|
|
|
|
}
|
2011-04-26 19:06:36 +02:00
|
|
|
}
|
|
|
|
|
2012-06-12 15:53:23 +02:00
|
|
|
void SpotifyService::ToplistLoaded(const pb::spotify::BrowseToplistResponse& response) {
|
2012-07-12 16:35:09 +02:00
|
|
|
if (toplist_) {
|
|
|
|
FillPlaylist(toplist_, response.track());
|
|
|
|
}
|
2012-06-12 15:53:23 +02:00
|
|
|
}
|
|
|
|
|
2011-04-27 18:38:28 +02:00
|
|
|
QStandardItem* SpotifyService::PlaylistBySpotifyIndex(int index) const {
|
2011-04-26 19:06:36 +02:00
|
|
|
foreach (QStandardItem* item, playlists_) {
|
2011-04-27 18:38:28 +02:00
|
|
|
if (item->data(Role_UserPlaylistIndex).toInt() == index) {
|
|
|
|
return item;
|
2011-04-26 19:06:36 +02:00
|
|
|
}
|
|
|
|
}
|
2011-04-27 18:38:28 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-01-08 00:26:27 +01:00
|
|
|
void SpotifyService::UserPlaylistLoaded(const pb::spotify::LoadPlaylistResponse& response) {
|
2011-04-27 18:38:28 +02:00
|
|
|
// Find a playlist with this index
|
|
|
|
QStandardItem* item = PlaylistBySpotifyIndex(response.request().user_playlist_index());
|
|
|
|
if (item) {
|
|
|
|
FillPlaylist(item, response);
|
|
|
|
}
|
2011-04-26 19:06:36 +02:00
|
|
|
}
|
|
|
|
|
2012-06-12 15:53:23 +02:00
|
|
|
void SpotifyService::FillPlaylist(
|
|
|
|
QStandardItem* item,
|
|
|
|
const google::protobuf::RepeatedPtrField<pb::spotify::Track>& tracks) {
|
2011-04-26 19:06:36 +02:00
|
|
|
if (item->hasChildren())
|
|
|
|
item->removeRows(0, item->rowCount());
|
|
|
|
|
2012-06-12 15:53:23 +02:00
|
|
|
for (int i=0 ; i < tracks.size() ; ++i) {
|
2011-04-26 19:06:36 +02:00
|
|
|
Song song;
|
2012-06-12 15:53:23 +02:00
|
|
|
SongFromProtobuf(tracks.Get(i), &song);
|
2011-04-26 19:06:36 +02:00
|
|
|
|
2012-06-27 21:19:30 +02:00
|
|
|
QStandardItem* child = CreateSongItem(song);
|
2011-04-26 19:06:36 +02:00
|
|
|
|
|
|
|
item->appendRow(child);
|
2011-04-26 15:42:58 +02:00
|
|
|
}
|
2011-04-25 21:16:26 +02:00
|
|
|
}
|
2011-04-26 19:06:36 +02:00
|
|
|
|
2012-06-12 15:53:23 +02:00
|
|
|
void SpotifyService::FillPlaylist(QStandardItem* item, const pb::spotify::LoadPlaylistResponse& response) {
|
|
|
|
qLog(Debug) << "Filling playlist:" << item->text();
|
|
|
|
FillPlaylist(item, response.track());
|
|
|
|
}
|
|
|
|
|
2012-01-08 00:26:27 +01:00
|
|
|
void SpotifyService::SongFromProtobuf(const pb::spotify::Track& track, Song* song) {
|
2011-04-26 19:06:36 +02:00
|
|
|
song->set_rating(track.starred() ? 1.0 : 0.0);
|
|
|
|
song->set_title(QStringFromStdString(track.title()));
|
|
|
|
song->set_album(QStringFromStdString(track.album()));
|
|
|
|
song->set_length_nanosec(track.duration_msec() * kNsecPerMsec);
|
|
|
|
song->set_score(track.popularity());
|
|
|
|
song->set_disc(track.disc());
|
|
|
|
song->set_track(track.track());
|
|
|
|
song->set_year(track.year());
|
2011-04-28 14:27:53 +02:00
|
|
|
song->set_url(QUrl(QStringFromStdString(track.uri())));
|
2011-04-29 15:41:42 +02:00
|
|
|
song->set_art_automatic("spotify://image/" + QStringFromStdString(track.album_art_id()));
|
2011-04-26 19:06:36 +02:00
|
|
|
|
|
|
|
QStringList artists;
|
|
|
|
for (int i=0 ; i<track.artist_size() ; ++i) {
|
|
|
|
artists << QStringFromStdString(track.artist(i));
|
|
|
|
}
|
|
|
|
|
|
|
|
song->set_artist(artists.join(", "));
|
|
|
|
|
|
|
|
song->set_filetype(Song::Type_Stream);
|
|
|
|
song->set_valid(true);
|
2011-04-27 18:38:28 +02:00
|
|
|
song->set_directory_id(0);
|
|
|
|
song->set_mtime(0);
|
|
|
|
song->set_ctime(0);
|
|
|
|
song->set_filesize(0);
|
2011-04-26 19:06:36 +02:00
|
|
|
}
|
2011-04-26 20:39:38 +02:00
|
|
|
|
|
|
|
PlaylistItem::Options SpotifyService::playlistitem_options() const {
|
2011-11-28 19:19:11 +01:00
|
|
|
return PlaylistItem::PauseDisabled | PlaylistItem::SeekDisabled;
|
2011-04-26 20:39:38 +02:00
|
|
|
}
|
2011-04-27 18:38:28 +02:00
|
|
|
|
2012-06-28 23:57:51 +02:00
|
|
|
QWidget* SpotifyService::HeaderWidget() const {
|
2012-07-21 20:15:36 +02:00
|
|
|
if (IsLoggedIn())
|
|
|
|
return search_box_;
|
|
|
|
return NULL;
|
2012-06-28 23:57:51 +02:00
|
|
|
}
|
|
|
|
|
2011-04-27 18:38:28 +02:00
|
|
|
void SpotifyService::EnsureMenuCreated() {
|
|
|
|
if (context_menu_)
|
|
|
|
return;
|
|
|
|
|
|
|
|
context_menu_ = new QMenu;
|
2011-04-28 19:50:45 +02:00
|
|
|
context_menu_->addAction(IconLoader::Load("configure"), tr("Configure Spotify..."), this, SLOT(ShowConfig()));
|
2011-05-25 16:22:49 +02:00
|
|
|
|
|
|
|
playlist_context_menu_ = new QMenu;
|
2012-07-29 20:12:16 +02:00
|
|
|
playlist_context_menu_->addActions(GetPlaylistActions());
|
|
|
|
playlist_context_menu_->addSeparator();
|
2011-05-25 16:22:49 +02:00
|
|
|
playlist_sync_action_ = playlist_context_menu_->addAction(
|
|
|
|
IconLoader::Load("view-refresh"),
|
|
|
|
tr("Make playlist available offline"),
|
|
|
|
this,
|
|
|
|
SLOT(SyncPlaylist()));
|
2012-07-29 20:12:16 +02:00
|
|
|
playlist_context_menu_->addSeparator();
|
|
|
|
playlist_context_menu_->addAction(IconLoader::Load("configure"),
|
|
|
|
tr("Configure Spotify..."),
|
|
|
|
this, SLOT(ShowConfig()));
|
2011-05-25 16:22:49 +02:00
|
|
|
}
|
|
|
|
|
2012-06-28 23:57:51 +02:00
|
|
|
void SpotifyService::ClearSearchResults() {
|
|
|
|
if (search_)
|
|
|
|
search_->removeRows(0, search_->rowCount());
|
|
|
|
}
|
|
|
|
|
2011-05-25 16:22:49 +02:00
|
|
|
void SpotifyService::SyncPlaylist() {
|
|
|
|
QStandardItem* item = playlist_sync_action_->data().value<QStandardItem*>();
|
|
|
|
Q_ASSERT(item);
|
|
|
|
|
2011-11-01 11:52:22 +01:00
|
|
|
switch (item->data(InternetModel::Role_Type).toInt()) {
|
|
|
|
case InternetModel::Type_UserPlaylist: {
|
2011-05-25 16:22:49 +02:00
|
|
|
int index = item->data(Role_UserPlaylistIndex).toInt();
|
|
|
|
server_->SyncUserPlaylist(index);
|
|
|
|
playlist_sync_ids_[index] =
|
2012-02-12 14:41:50 +01:00
|
|
|
app_->task_manager()->StartTask(tr("Syncing Spotify playlist"));
|
2011-05-25 16:22:49 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Type_InboxPlaylist:
|
|
|
|
server_->SyncInbox();
|
2012-02-12 14:41:50 +01:00
|
|
|
inbox_sync_id_ = app_->task_manager()->StartTask(tr("Syncing Spotify inbox"));
|
2011-05-25 16:22:49 +02:00
|
|
|
break;
|
|
|
|
case Type_StarredPlaylist:
|
|
|
|
server_->SyncStarred();
|
2012-02-12 14:41:50 +01:00
|
|
|
starred_sync_id_ = app_->task_manager()->StartTask(tr("Syncing Spotify starred tracks"));
|
2011-05-25 16:22:49 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2011-04-27 18:38:28 +02:00
|
|
|
}
|
|
|
|
|
2012-06-28 23:57:51 +02:00
|
|
|
void SpotifyService::Search(const QString& text, bool now) {
|
2011-04-28 19:50:45 +02:00
|
|
|
EnsureServerCreated();
|
|
|
|
|
|
|
|
pending_search_ = text;
|
2012-06-28 23:57:51 +02:00
|
|
|
|
|
|
|
// If there is no text (e.g. user cleared search box), we don't need to do a
|
|
|
|
// real query that will return nothing: we can clear the playlist now
|
|
|
|
if (text.isEmpty()) {
|
|
|
|
search_delay_->stop();
|
|
|
|
ClearSearchResults();
|
|
|
|
return;
|
|
|
|
}
|
2011-04-28 22:48:53 +02:00
|
|
|
|
|
|
|
if (now) {
|
|
|
|
search_delay_->stop();
|
|
|
|
DoSearch();
|
|
|
|
} else {
|
|
|
|
search_delay_->start();
|
|
|
|
}
|
2011-04-27 18:38:28 +02:00
|
|
|
}
|
|
|
|
|
2011-04-28 19:50:45 +02:00
|
|
|
void SpotifyService::DoSearch() {
|
|
|
|
if (!pending_search_.isEmpty()) {
|
|
|
|
server_->Search(pending_search_, 200);
|
2011-04-27 18:38:28 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-08 00:26:27 +01:00
|
|
|
void SpotifyService::SearchResults(const pb::spotify::SearchResponse& response) {
|
2011-04-27 18:38:28 +02:00
|
|
|
if (QStringFromStdString(response.request().query()) != pending_search_) {
|
|
|
|
qLog(Debug) << "Old search result for"
|
|
|
|
<< QStringFromStdString(response.request().query())
|
|
|
|
<< "expecting" << pending_search_;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
pending_search_.clear();
|
|
|
|
|
|
|
|
SongList songs;
|
|
|
|
for (int i=0 ; i<response.result_size() ; ++i) {
|
|
|
|
Song song;
|
|
|
|
SongFromProtobuf(response.result(i), &song);
|
|
|
|
songs << song;
|
|
|
|
}
|
|
|
|
|
|
|
|
qLog(Debug) << "Got" << songs.count() << "results";
|
|
|
|
|
2012-06-28 23:57:51 +02:00
|
|
|
ClearSearchResults();
|
|
|
|
|
|
|
|
// Fill results list
|
|
|
|
foreach(const Song& song, songs) {
|
|
|
|
QStandardItem* child = CreateSongItem(song);
|
|
|
|
search_->appendRow(child);
|
|
|
|
}
|
2011-04-28 22:48:53 +02:00
|
|
|
|
2012-06-28 23:57:51 +02:00
|
|
|
const QString did_you_mean_suggestion = QStringFromStdString(response.did_you_mean());
|
|
|
|
qLog(Debug) << "Did you mean suggestion: " << did_you_mean_suggestion;
|
|
|
|
if (!did_you_mean_suggestion.isEmpty()) {
|
|
|
|
search_box_->did_you_mean()->Show(did_you_mean_suggestion);
|
2012-07-01 23:55:54 +02:00
|
|
|
} else {
|
|
|
|
// In case something else was previously displayed
|
|
|
|
search_box_->did_you_mean()->hide();
|
2011-04-28 22:48:53 +02:00
|
|
|
}
|
2012-06-28 23:57:51 +02:00
|
|
|
|
|
|
|
QModelIndex index = model()->merged_model()->mapFromSource(search_->index());
|
|
|
|
ScrollToIndex(index);
|
2011-04-27 18:38:28 +02:00
|
|
|
}
|
2011-04-28 17:10:28 +02:00
|
|
|
|
|
|
|
SpotifyServer* SpotifyService::server() const {
|
2011-09-25 20:24:44 +02:00
|
|
|
SpotifyService* nonconst_this = const_cast<SpotifyService*>(this);
|
|
|
|
|
|
|
|
if (QThread::currentThread() != thread()) {
|
|
|
|
metaObject()->invokeMethod(nonconst_this, "EnsureServerCreated",
|
|
|
|
Qt::BlockingQueuedConnection);
|
|
|
|
} else {
|
|
|
|
nonconst_this->EnsureServerCreated();
|
|
|
|
}
|
|
|
|
|
2011-04-28 17:10:28 +02:00
|
|
|
return server_;
|
|
|
|
}
|
2011-04-28 19:50:45 +02:00
|
|
|
|
2012-03-11 15:44:43 +01:00
|
|
|
void SpotifyService::ShowContextMenu(const QPoint& global_pos) {
|
2011-04-28 19:50:45 +02:00
|
|
|
EnsureMenuCreated();
|
2012-03-11 15:44:43 +01:00
|
|
|
QStandardItem* item = model()->itemFromIndex(model()->current_index());
|
2011-05-25 16:22:49 +02:00
|
|
|
if (item) {
|
2011-11-01 11:52:22 +01:00
|
|
|
int type = item->data(InternetModel::Role_Type).toInt();
|
2011-05-25 16:22:49 +02:00
|
|
|
if (type == Type_InboxPlaylist ||
|
|
|
|
type == Type_StarredPlaylist ||
|
2011-11-01 11:52:22 +01:00
|
|
|
type == InternetModel::Type_UserPlaylist) {
|
2011-05-25 16:22:49 +02:00
|
|
|
playlist_sync_action_->setData(qVariantFromValue(item));
|
|
|
|
playlist_context_menu_->popup(global_pos);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-28 19:50:45 +02:00
|
|
|
context_menu_->popup(global_pos);
|
|
|
|
}
|
|
|
|
|
2011-04-29 13:24:58 +02:00
|
|
|
void SpotifyService::ItemDoubleClicked(QStandardItem* item) {
|
|
|
|
}
|
2011-04-29 15:41:42 +02:00
|
|
|
|
2012-01-04 12:50:19 +01:00
|
|
|
void SpotifyService::DropMimeData(const QMimeData* data, const QModelIndex& index) {
|
|
|
|
qLog(Debug) << Q_FUNC_INFO << data->urls();
|
|
|
|
}
|
|
|
|
|
2011-11-29 11:20:23 +01:00
|
|
|
void SpotifyService::LoadImage(const QString& id) {
|
2011-04-29 15:41:42 +02:00
|
|
|
EnsureServerCreated();
|
2011-11-29 11:20:23 +01:00
|
|
|
server_->LoadImage(id);
|
2011-04-29 15:41:42 +02:00
|
|
|
}
|
2011-04-29 20:56:17 +02:00
|
|
|
|
2011-05-25 16:22:49 +02:00
|
|
|
void SpotifyService::SyncPlaylistProgress(
|
2012-01-08 00:26:27 +01:00
|
|
|
const pb::spotify::SyncPlaylistProgress& progress) {
|
2011-05-25 16:22:49 +02:00
|
|
|
qLog(Debug) << "Sync progress:" << progress.sync_progress();
|
|
|
|
int task_id = -1;
|
|
|
|
switch (progress.request().type()) {
|
2012-01-08 00:26:27 +01:00
|
|
|
case pb::spotify::Inbox:
|
2011-05-25 16:22:49 +02:00
|
|
|
task_id = inbox_sync_id_;
|
|
|
|
break;
|
2012-01-08 00:26:27 +01:00
|
|
|
case pb::spotify::Starred:
|
2011-05-25 16:22:49 +02:00
|
|
|
task_id = starred_sync_id_;
|
|
|
|
break;
|
2012-01-08 00:26:27 +01:00
|
|
|
case pb::spotify::UserPlaylist: {
|
2011-06-20 17:08:06 +02:00
|
|
|
QMap<int, int>::const_iterator it = playlist_sync_ids_.constFind(
|
2011-05-25 16:22:49 +02:00
|
|
|
progress.request().user_playlist_index());
|
2011-06-20 17:08:06 +02:00
|
|
|
if (it != playlist_sync_ids_.constEnd()) {
|
2011-05-25 16:22:49 +02:00
|
|
|
task_id = it.value();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (task_id == -1) {
|
|
|
|
qLog(Warning) << "Received sync progress for unknown playlist";
|
|
|
|
return;
|
|
|
|
}
|
2012-02-12 14:41:50 +01:00
|
|
|
app_->task_manager()->SetTaskProgress(task_id, progress.sync_progress(), 100);
|
2011-05-25 16:22:49 +02:00
|
|
|
if (progress.sync_progress() == 100) {
|
2012-02-12 14:41:50 +01:00
|
|
|
app_->task_manager()->SetTaskFinished(task_id);
|
2012-01-08 00:26:27 +01:00
|
|
|
if (progress.request().type() == pb::spotify::UserPlaylist) {
|
2011-05-25 16:22:49 +02:00
|
|
|
playlist_sync_ids_.remove(task_id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-29 20:56:17 +02:00
|
|
|
void SpotifyService::ShowConfig() {
|
2012-12-05 10:36:22 +01:00
|
|
|
app_->OpenSettingsDialogAtPage(SettingsDialog::Page_Spotify);
|
2011-04-29 20:56:17 +02:00
|
|
|
}
|
2011-08-27 23:01:28 +02:00
|
|
|
|
|
|
|
void SpotifyService::Logout() {
|
|
|
|
delete server_;
|
|
|
|
delete blob_process_;
|
|
|
|
server_ = NULL;
|
|
|
|
blob_process_ = NULL;
|
|
|
|
|
|
|
|
login_state_ = LoginState_OtherError;
|
2011-10-30 19:52:54 +01:00
|
|
|
|
|
|
|
QSettings s;
|
|
|
|
s.beginGroup(kSettingsGroup);
|
|
|
|
s.setValue("login_state", login_state_);
|
2011-08-27 23:01:28 +02:00
|
|
|
}
|